Merge branch 'master' into HUD-Timers
# Conflicts: # resources/Schema/Entities/QualityAssurance.xml # src/Game/Game.cpp
This commit is contained in:
+18
-5
@@ -10,7 +10,9 @@
|
||||
#include "Systems/SpawnerSystem.h"
|
||||
#include "Systems/PlayerSpawnSystem.h"
|
||||
#include "Systems/PlayerDeathSystem.h"
|
||||
#include "Core/EntityFileWriter.h"
|
||||
#include "Systems/FloatingEffectSystem.h"
|
||||
#include "Core/EntityFile.h"
|
||||
#include "Core/EntityXMLFileWriter.h"
|
||||
#include "Game/Systems/CapturePointSystem.h"
|
||||
#include "Game/Systems/CapturePointHUDSystem.h"
|
||||
#include "Game/Systems/PickupSpawnSystem.h"
|
||||
@@ -26,7 +28,9 @@
|
||||
#include "Network/MultiplayerSnapshotFilter.h"
|
||||
#include "Game/Systems/AmmunitionHUDSystem.h"
|
||||
#include "Game/Systems/AbilityCooldownHUDSystem.h"
|
||||
#include "Game/Systems/CapturePointArrowHUDSystem.h"
|
||||
#include "Game/Systems/KillFeedSystem.h"
|
||||
#include "Game/Systems/BoostSystem.h"
|
||||
#include "GUI/ButtonSystem.h"
|
||||
#include "GUI/MainMenuSystem.h"
|
||||
|
||||
@@ -43,6 +47,7 @@ Game::Game(int argc, char* argv[])
|
||||
ResourceManager::RegisterType<PNG>("Png");
|
||||
ResourceManager::RegisterType<ShaderProgram>("ShaderProgram");
|
||||
ResourceManager::RegisterType<EntityFile>("EntityFile");
|
||||
ResourceManager::RegisterType<EntityXMLFile>("EntityXMLFile");
|
||||
ResourceManager::RegisterType<Font>("FontFile");
|
||||
|
||||
m_Config = ResourceManager::Load<ConfigFile>("Config.ini");
|
||||
@@ -79,10 +84,7 @@ Game::Game(int argc, char* argv[])
|
||||
std::string mapToLoad = m_Config->Get<std::string>("Debug.LoadMap", "");
|
||||
if (!mapToLoad.empty()) {
|
||||
auto file = ResourceManager::Load<EntityFile>(mapToLoad);
|
||||
EntityFilePreprocessor fpp(file);
|
||||
fpp.RegisterComponents(m_World);
|
||||
EntityFileParser fp(file);
|
||||
fp.MergeEntities(m_World);
|
||||
file->MergeInto(m_World);
|
||||
}
|
||||
|
||||
// Create the sound manager
|
||||
@@ -119,6 +121,7 @@ Game::Game(int argc, char* argv[])
|
||||
++updateOrderLevel;
|
||||
m_SystemPipeline->AddSystem<SoundSystem>(updateOrderLevel);
|
||||
m_SystemPipeline->AddSystem<RaptorCopterSystem>(updateOrderLevel);
|
||||
m_SystemPipeline->AddSystem<FloatingEffectSystem>(updateOrderLevel);
|
||||
m_SystemPipeline->AddSystem<ExplosionEffectSystem>(updateOrderLevel);
|
||||
m_SystemPipeline->AddSystem<HealthSystem>(updateOrderLevel);
|
||||
m_SystemPipeline->AddSystem<PlayerMovementSystem>(updateOrderLevel);
|
||||
@@ -133,7 +136,17 @@ Game::Game(int argc, char* argv[])
|
||||
m_SystemPipeline->AddSystem<DamageIndicatorSystem>(updateOrderLevel);
|
||||
m_SystemPipeline->AddSystem<AmmunitionHUDSystem>(updateOrderLevel);
|
||||
m_SystemPipeline->AddSystem<AbilityCooldownHUDSystem>(updateOrderLevel);
|
||||
m_SystemPipeline->AddSystem<CapturePointArrowHUDSystem>(updateOrderLevel);
|
||||
m_SystemPipeline->AddSystem<KillFeedSystem>(updateOrderLevel);
|
||||
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);
|
||||
m_SystemPipeline->AddSystem<AmmunitionHUDSystem>(updateOrderLevel);
|
||||
m_SystemPipeline->AddSystem<KillFeedSystem>(updateOrderLevel);
|
||||
m_SystemPipeline->AddSystem<BoostSystem>(updateOrderLevel);
|
||||
m_SystemPipeline->AddSystem<ButtonSystem>(updateOrderLevel, m_Renderer);
|
||||
m_SystemPipeline->AddSystem<MainMenuSystem>(updateOrderLevel, m_Renderer);
|
||||
// Populate Octree with collidables
|
||||
|
||||
@@ -5,6 +5,7 @@ AmmoPickupSystem::AmmoPickupSystem(SystemParams params)
|
||||
{
|
||||
if (IsServer) {
|
||||
EVENT_SUBSCRIBE_MEMBER(m_ETriggerTouch, &AmmoPickupSystem::OnTriggerTouch);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_ETriggerLeave, &AmmoPickupSystem::OnTriggerLeave);
|
||||
}
|
||||
if (IsClient) {
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EAmmoPickup, &AmmoPickupSystem::OnAmmoPickup);
|
||||
@@ -14,43 +15,50 @@ AmmoPickupSystem::AmmoPickupSystem(SystemParams params)
|
||||
void AmmoPickupSystem::Update(double dt)
|
||||
{
|
||||
if (IsServer) {
|
||||
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 it = m_ETriggerTouchVector.begin();
|
||||
while (it != m_ETriggerTouchVector.end()) {
|
||||
auto& somePickup = *it;
|
||||
somePickup.DecreaseThisRespawnTimer -= dt;
|
||||
if (somePickup.DecreaseThisRespawnTimer < 0.0) {
|
||||
auto entityFile = ResourceManager::Load<EntityFile>("Schema/Entities/AmmoPickup.xml");
|
||||
EntityFileParser parser(entityFile);
|
||||
EntityID ammoPickupID = parser.MergeEntities(m_World);
|
||||
EntityWrapper ammoPickup = entityFile->MergeInto(m_World);
|
||||
|
||||
//let the world know a pickup has spawned (graphics effects, etc)
|
||||
//let the world know a pickup has spawned
|
||||
Events::PickupSpawned ePickupSpawned;
|
||||
ePickupSpawned.Pickup = EntityWrapper(m_World, ammoPickupID);
|
||||
ePickupSpawned.Pickup = ammoPickup;
|
||||
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;
|
||||
m_World->SetParent(newAmmoPickupEntity.ID, ammoPickupPosition.parentID);
|
||||
//copy values from the old entity to the new entity
|
||||
auto& newAmmoPickupEntity = ammoPickup;
|
||||
newAmmoPickupEntity["Transform"]["Position"] = somePickup.Pos;
|
||||
newAmmoPickupEntity["AmmoPickup"]["AmmoGain"] = somePickup.AmmoGain;
|
||||
newAmmoPickupEntity["AmmoPickup"]["RespawnTimer"] = somePickup.RespawnTimer;
|
||||
m_World->SetParent(newAmmoPickupEntity.ID, somePickup.parentID);
|
||||
|
||||
//erase the current element (AmmoPickupPosition)
|
||||
m_ETriggerTouchVector.erase(it);
|
||||
//erase the current element (somePickup)
|
||||
it = m_ETriggerTouchVector.erase(it);
|
||||
}
|
||||
else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
//still touching m_PickupAtMaximum?
|
||||
for (auto& it = m_PickupAtMaximum.begin(); it != m_PickupAtMaximum.end(); ++it) {
|
||||
if (!it->player.Valid()) {
|
||||
m_PickupAtMaximum.erase(it);
|
||||
break;
|
||||
}
|
||||
if ((int)it->player["AssaultWeapon"]["Ammo"] < (int)it->player["AssaultWeapon"]["MaxAmmo"]) {
|
||||
DoPickup(it->player, it->trigger);
|
||||
m_PickupAtMaximum.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool AmmoPickupSystem::OnTriggerTouch(Events::TriggerTouch& e)
|
||||
{
|
||||
/*if (e.Entity != LocalPlayer) {
|
||||
return false;
|
||||
}*/
|
||||
|
||||
if (!e.Entity.Valid()) {
|
||||
return false;
|
||||
}
|
||||
@@ -61,30 +69,13 @@ bool AmmoPickupSystem::OnTriggerTouch(Events::TriggerTouch& e)
|
||||
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) {
|
||||
//if at maxammo, save the trigger-touch to a vector since standing inside it will not re-trigger the trigger
|
||||
if ((int)e.Entity["AssaultWeapon"]["Ammo"] >= (int)e.Entity["AssaultWeapon"]["MaxAmmo"]) {
|
||||
m_PickupAtMaximum.push_back({ e.Entity, e.Trigger });
|
||||
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({ e.Trigger["Transform"]["Position"], e.Trigger["AmmoPickup"]["AmmoGain"],
|
||||
e.Trigger["AmmoPickup"]["RespawnTimer"], e.Trigger["AmmoPickup"]["RespawnTimer"], m_World->GetParent(e.Trigger.ID) });
|
||||
|
||||
//delete the ammopickup
|
||||
m_World->DeleteEntity(e.Trigger.ID);
|
||||
DoPickup(e.Entity, e.Trigger);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -107,3 +98,39 @@ bool AmmoPickupSystem::OnAmmoPickup(Events::AmmoPickup & e)
|
||||
currentAmmo = std::min(currentAmmo + e.AmmoGain, maxWeaponAmmo);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AmmoPickupSystem::OnTriggerLeave(Events::TriggerLeave& e) {
|
||||
if (!e.Trigger.HasComponent("AmmoPickup")) {
|
||||
return false;
|
||||
}
|
||||
//triggerleave erases possible m_PickupAtMaximum
|
||||
for (auto& it = m_PickupAtMaximum.begin(); it != m_PickupAtMaximum.end(); ++it) {
|
||||
if (it->trigger.ID == e.Trigger.ID && it->player.ID == e.Entity.ID) {
|
||||
m_PickupAtMaximum.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void AmmoPickupSystem::DoPickup(EntityWrapper &player, EntityWrapper &trigger) {
|
||||
int maxWeaponAmmo = (int)player["AssaultWeapon"]["MaxAmmo"];
|
||||
int& currentAmmo = (int)player["AssaultWeapon"]["Ammo"];
|
||||
int ammoGiven = 0.01*(double)trigger["AmmoPickup"]["AmmoGain"] * maxWeaponAmmo;
|
||||
|
||||
Events::AmmoPickup ePlayerAmmoPickup;
|
||||
ePlayerAmmoPickup.AmmoGain = ammoGiven;
|
||||
ePlayerAmmoPickup.Player = player;
|
||||
m_EventBroker->Publish(ePlayerAmmoPickup);
|
||||
|
||||
//immediately give the player the ammo (on server)
|
||||
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)trigger["Transform"]["Position"], trigger["AmmoPickup"]["AmmoGain"],
|
||||
trigger["AmmoPickup"]["RespawnTimer"], trigger["AmmoPickup"]["RespawnTimer"], m_World->GetParent(trigger.ID) });
|
||||
|
||||
//delete the ammopickup
|
||||
m_World->DeleteEntity(trigger.ID);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
#include "Systems/BoostSystem.h"
|
||||
|
||||
BoostSystem::BoostSystem(SystemParams params)
|
||||
: System(params)
|
||||
{
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EPlayerDamage, &BoostSystem::OnPlayerDamage);
|
||||
}
|
||||
|
||||
bool BoostSystem::OnPlayerDamage(Events::PlayerDamage& e)
|
||||
{
|
||||
if (e.Victim.ID == e.Inflictor.ID) {
|
||||
return false;
|
||||
}
|
||||
if (!e.Victim.Valid() && e.Victim != LocalPlayer && !e.Victim.IsChildOf(LocalPlayer)) {
|
||||
return false;
|
||||
}
|
||||
if (!e.Inflictor.Valid() || !e.Victim.Valid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//if its not friendly fire, return
|
||||
if ((int)m_World->GetComponent(e.Inflictor.ID, "Team")["Team"] != (int)m_World->GetComponent(e.Victim.ID, "Team")["Team"]) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//determine the inflictors class
|
||||
auto className = DetermineClass(e.Inflictor);
|
||||
if (className == "") {
|
||||
return false;
|
||||
}
|
||||
|
||||
//get the XML file, example: "Schema/Entities/BoostclassName.xml"
|
||||
std::string classXML = "Schema/Entities/" + className + ".xml";
|
||||
|
||||
//check if player already has a child with the component, if so delete that child
|
||||
auto playerBoostAssaultEntity = e.Victim.FirstChildByName(className);
|
||||
if (playerBoostAssaultEntity.Valid()) {
|
||||
m_World->DeleteEntity(playerBoostAssaultEntity.ID);
|
||||
}
|
||||
//load boost XML file, set it entity parented with the victim player
|
||||
auto entityFile = ResourceManager::Load<EntityFile>(classXML);
|
||||
EntityWrapper boostAssaultEntity = entityFile->MergeInto(m_World);
|
||||
m_World->SetName(boostAssaultEntity.ID, className);
|
||||
m_World->SetParent(boostAssaultEntity.ID, e.Victim.ID);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string BoostSystem::DetermineClass(EntityWrapper inflictorPlayer)
|
||||
{
|
||||
//determine the class based on what component the inflictor-player has
|
||||
if (m_World->HasComponent(inflictorPlayer.ID, "DashAbility")) {
|
||||
return "BoostAssault";
|
||||
}
|
||||
if (m_World->HasComponent(inflictorPlayer.ID, "ShieldAbility")) {
|
||||
return "BoostDefender";
|
||||
}
|
||||
if (m_World->HasComponent(inflictorPlayer.ID, "SprintAbility")) {
|
||||
return "BoostSniper";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
#include "Systems/CapturePointArrowHUDSystem.h"
|
||||
|
||||
CapturePointArrowHUDSystem::CapturePointArrowHUDSystem(SystemParams params)
|
||||
: System(params)
|
||||
, ImpureSystem()
|
||||
{
|
||||
EVENT_SUBSCRIBE_MEMBER(m_ECapturedEvent, &CapturePointArrowHUDSystem::OnCapturePointCaptured);
|
||||
}
|
||||
|
||||
|
||||
void CapturePointArrowHUDSystem::Update(double dt)
|
||||
{
|
||||
bool loadCheck = true;
|
||||
int redTeamEnum;
|
||||
int blueTeamEnum;
|
||||
int spectatorTeamEnum;
|
||||
|
||||
//Get list for all CapturePointArrowHUDComponents
|
||||
auto arrowHUDs = m_World->GetComponents("CapturePointArrowHUD");
|
||||
auto capturePoints = m_World->GetComponents("CapturePoint");
|
||||
if(arrowHUDs == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
for(auto& cArrowHUD : *arrowHUDs) {
|
||||
//Get what team the current arrow corresponds to
|
||||
EntityWrapper arrowEntity = EntityWrapper(m_World, cArrowHUD.EntityID);
|
||||
if (!arrowEntity.Valid()) {
|
||||
continue;
|
||||
}
|
||||
if(!arrowEntity.HasComponent("Team")) {
|
||||
continue;
|
||||
}
|
||||
auto cTeam = arrowEntity["Team"];
|
||||
int currentTeam = (int)cTeam["Team"];
|
||||
|
||||
if (loadCheck) {
|
||||
redTeamEnum = (int)cTeam["Team"].Enum("Red");
|
||||
blueTeamEnum = (int)cTeam["Team"].Enum("Blue");
|
||||
spectatorTeamEnum = (int)cTeam["Team"].Enum("Spectator");
|
||||
loadCheck = false;
|
||||
|
||||
|
||||
if (!m_InitialtargetsSet) {
|
||||
std::unordered_map<int, glm::vec3> blueTargets, redTargets;
|
||||
EntityWrapper homeBlue, homeRed;
|
||||
int lastCP = -INFINITY;
|
||||
int firstCP = INFINITY;
|
||||
|
||||
for (auto& cCP : *capturePoints) {
|
||||
auto homePointTeam = (int)cCP["HomePointForTeam"];
|
||||
EntityWrapper capturePointEntity = EntityWrapper(m_World, cCP.EntityID);
|
||||
int capturePointID = (int)capturePointEntity["CapturePoint"]["CapturePointNumber"];
|
||||
|
||||
if(capturePointID < firstCP) {
|
||||
firstCP = capturePointID;
|
||||
}
|
||||
|
||||
if(capturePointID > lastCP) {
|
||||
lastCP = capturePointID;
|
||||
}
|
||||
|
||||
if (!capturePointEntity.HasComponent("Team")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int currentOwner = (int)capturePointEntity["Team"]["Team"];
|
||||
|
||||
if(currentOwner != redTeamEnum) {
|
||||
//This capturePoint is not owned by the red team and is therefor an eligible target for red team
|
||||
glm::vec3 targetPos = Transform::AbsolutePosition(capturePointEntity);
|
||||
redTargets.insert(std::pair<int, glm::vec3>(capturePointID, targetPos));
|
||||
}
|
||||
if(currentOwner != blueTeamEnum) {
|
||||
//This capturePoint is not owned by the blue team and is therefor an eligible target for blue team
|
||||
glm::vec3 targetPos = Transform::AbsolutePosition(capturePointEntity);
|
||||
blueTargets.insert(std::pair<int, glm::vec3>(capturePointID, targetPos));
|
||||
}
|
||||
|
||||
if(homePointTeam == blueTeamEnum) {
|
||||
//CP is the home point for blue team.
|
||||
homeBlue = capturePointEntity;
|
||||
} else if (homePointTeam == redTeamEnum) {
|
||||
//CP is the home point for red team.
|
||||
homeRed = capturePointEntity;
|
||||
}
|
||||
}
|
||||
|
||||
if(!homeRed.Valid() || !homeBlue.Valid()) {
|
||||
//One or both teams have no home point, cant continue
|
||||
return;
|
||||
}
|
||||
|
||||
std::unordered_map<int, glm::vec3>::const_iterator got;
|
||||
//Find next target for red team.
|
||||
if((int)homeRed["CapturePoint"]["CapturePointNumber"] == lastCP) {
|
||||
//Red home base is the last capture point, count back from lastCP and find next target
|
||||
for (int i = lastCP; i >= firstCP; i--) {
|
||||
got = redTargets.find(i);
|
||||
if(got == redTargets.end()) {
|
||||
continue;
|
||||
} else {
|
||||
m_RedTeamCurrentTarget = got->second;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if ((int)homeRed["CapturePoint"]["CapturePointNumber"] == firstCP) {
|
||||
//Red home is the first capture point, count forward from firstCP and find next target.
|
||||
for (int i = firstCP; i <= lastCP; i++) {
|
||||
got = redTargets.find(i);
|
||||
if(got == redTargets.end()) {
|
||||
//Target was not found, try the next one after that.
|
||||
continue;
|
||||
} else {
|
||||
m_RedTeamCurrentTarget = got->second;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Find next target for blue team
|
||||
if ((int)homeBlue["CapturePoint"]["CapturePointNumber"] == lastCP) {
|
||||
//Red home base is the last capture point, count back from lastCP and find next target
|
||||
for (int i = lastCP; i >= firstCP; i--) {
|
||||
got = blueTargets.find(i);
|
||||
if (got == blueTargets.end()) {
|
||||
continue;
|
||||
} else {
|
||||
m_BlueTeamCurrentTarget = got->second;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if ((int)homeBlue["CapturePoint"]["CapturePointNumber"] == firstCP) {
|
||||
//Red home is the first capture point, count forward from firstCP and find next target.
|
||||
for (int i = firstCP; i <= lastCP; i++) {
|
||||
got = blueTargets.find(i);
|
||||
if (got == blueTargets.end()) {
|
||||
//Target was not found, try the next one after that.
|
||||
continue;
|
||||
} else {
|
||||
m_BlueTeamCurrentTarget = got->second;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//if red team, get red team next point, otherwise blue team next point.
|
||||
//Untill this is awailable we will just use the hardcoded value in the component.
|
||||
//This will also give us a position, so we wont need to loop through all capturePoints.
|
||||
glm::vec3 pos;
|
||||
if(currentTeam == redTeamEnum) {
|
||||
pos = m_RedTeamCurrentTarget;
|
||||
} else if (currentTeam == blueTeamEnum) {
|
||||
pos = m_BlueTeamCurrentTarget;
|
||||
}
|
||||
|
||||
glm::vec3& arrowOri = arrowEntity["Transform"]["Orientation"];
|
||||
glm::vec3 lookVector = glm::normalize(Transform::AbsolutePosition(arrowEntity) - pos); //Maybe should be player instead
|
||||
float pitch = std::asin(-lookVector.y);
|
||||
float yaw = std::atan2(lookVector.x, lookVector.z);
|
||||
arrowOri.x = pitch;
|
||||
arrowOri.y = yaw;
|
||||
arrowOri.z = 0.f;
|
||||
EntityWrapper parent = arrowEntity.Parent();
|
||||
if (parent.Valid()) {
|
||||
arrowOri -= Transform::AbsoluteOrientationEuler(parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CapturePointArrowHUDSystem::OnCapturePointCaptured(Events::Captured& e)
|
||||
{
|
||||
if(!e.BlueTeamNextCapturePoint.Valid() || !e.RedTeamNextCapturePoint.Valid()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
m_RedTeamCurrentTarget = Transform::AbsolutePosition(e.RedTeamNextCapturePoint);
|
||||
m_BlueTeamCurrentTarget = Transform::AbsolutePosition(e.BlueTeamNextCapturePoint);
|
||||
|
||||
m_InitialtargetsSet = true;
|
||||
return 0;
|
||||
}
|
||||
@@ -103,9 +103,8 @@ void CapturePointSystem::UpdateComponent(EntityWrapper& capturePointEntity, Comp
|
||||
}
|
||||
}
|
||||
if (m_RecentlyCapturedNeedNextCapturePointNow) {
|
||||
m_CapturedEvent.NextCapturePoint = m_CapturedEvent.TeamNumberThatCapturedCapturePoint == blueTeam ?
|
||||
m_CapturePointNumberToEntityMap[nextPossibleCapturePoint["Blue"]] :
|
||||
m_CapturePointNumberToEntityMap[nextPossibleCapturePoint["Red"]];
|
||||
m_CapturedEvent.BlueTeamNextCapturePoint = m_CapturePointNumberToEntityMap[nextPossibleCapturePoint["Blue"]];
|
||||
m_CapturedEvent.RedTeamNextCapturePoint = m_CapturePointNumberToEntityMap[nextPossibleCapturePoint["Red"]];
|
||||
m_EventBroker->Publish(m_CapturedEvent);
|
||||
m_RecentlyCapturedNeedNextCapturePointNow = false;
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ DamageIndicatorSystem::DamageIndicatorSystem(SystemParams params)
|
||||
|
||||
//load texture to cache
|
||||
auto texture = CommonFunctions::LoadTexture("Textures/DamageIndicator.png", false);
|
||||
auto entityFile = ResourceManager::Load<EntityFile>("Schema/Entities/DamageIndicator.xml");
|
||||
auto entityFile = ResourceManager::Load<EntityXMLFile>("Schema/Entities/DamageIndicator.xml");
|
||||
}
|
||||
|
||||
void DamageIndicatorSystem::Update(double dt) {
|
||||
@@ -50,15 +50,13 @@ bool DamageIndicatorSystem::OnPlayerDamage(Events::PlayerDamage& e)
|
||||
|
||||
//load & set the "2d" sprite
|
||||
auto entityFile = ResourceManager::Load<EntityFile>("Schema/Entities/DamageIndicator.xml");
|
||||
EntityFileParser parser(entityFile);
|
||||
EntityID spriteID = parser.MergeEntities(m_World);
|
||||
m_World->SetParent(spriteID, m_CurrentCamera);
|
||||
auto spriteWrapper = EntityWrapper(m_World, spriteID);
|
||||
EntityWrapper sprite = entityFile->MergeInto(m_World);
|
||||
m_World->SetParent(sprite.ID, m_CurrentCamera);
|
||||
//simply set the rotation z-wise to the angleBetweenVectors
|
||||
spriteWrapper["Transform"]["Orientation"] = glm::vec3(0, 0, angleBetweenVectors);
|
||||
sprite["Transform"]["Orientation"] = glm::vec3(0, 0, angleBetweenVectors);
|
||||
|
||||
if (!IsServer) {
|
||||
updateDamageIndicatorVector.emplace_back(spriteWrapper, inflictorPos);
|
||||
updateDamageIndicatorVector.emplace_back(sprite, inflictorPos);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -127,8 +125,8 @@ glm::vec3 DamageIndicatorSystem::DamageIndicatorTest(EntityWrapper player) {
|
||||
auto inflictorPos = glm::vec3(currentPos.x + testVar*6.0f, currentPos.y, currentPos.z + testVar2*6.0f);
|
||||
|
||||
//load the explosioneffect XML
|
||||
auto deathEffect = ResourceManager::Load<EntityFile>("Schema/Entities/PlayerDeathExplosionWithCamera.xml");
|
||||
EntityFileParser parser(deathEffect);
|
||||
auto deathEffect = ResourceManager::Load<EntityXMLFile>("Schema/Entities/PlayerDeathExplosionWithCamera.xml");
|
||||
EntityXMLFileParser parser(deathEffect);
|
||||
EntityID deathEffectID = parser.MergeEntities(m_World);
|
||||
EntityWrapper deathEffectEW = EntityWrapper(m_World, deathEffectID);
|
||||
|
||||
|
||||
@@ -30,6 +30,11 @@ bool HealthSystem::OnPlayerDamaged(Events::PlayerDamage& e)
|
||||
|
||||
ComponentWrapper cHealth = e.Victim["Health"];
|
||||
double& health = cHealth["Health"];
|
||||
//if player has the boost from a defender, subtract the damage taken by StrengthOfEffect amount
|
||||
auto playerBoostDefenderEntity = e.Victim.FirstChildByName("BoostDefender");
|
||||
if (playerBoostDefenderEntity.Valid()) {
|
||||
e.Damage -= (double)playerBoostDefenderEntity["BoostDefender"]["StrengthOfEffect"];
|
||||
}
|
||||
health -= e.Damage;
|
||||
|
||||
return true;
|
||||
|
||||
@@ -5,66 +5,97 @@ PickupSpawnSystem::PickupSpawnSystem(SystemParams params)
|
||||
{
|
||||
if (IsServer) {
|
||||
EVENT_SUBSCRIBE_MEMBER(m_ETriggerTouch, &PickupSpawnSystem::OnTriggerTouch);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_ETriggerLeave, &PickupSpawnSystem::OnTriggerLeave);
|
||||
}
|
||||
}
|
||||
|
||||
void PickupSpawnSystem::Update(double dt)
|
||||
{
|
||||
if (IsServer) {
|
||||
for (auto it = m_ETriggerTouchVector.begin(); it != m_ETriggerTouchVector.end(); ++it) {
|
||||
auto& healthPickupPosition = *it;
|
||||
//set the double timer value (value 3)
|
||||
healthPickupPosition.DecreaseThisRespawnTimer -= dt;
|
||||
if (healthPickupPosition.DecreaseThisRespawnTimer < 0) {
|
||||
//spawn and delete the vector item
|
||||
auto it = m_ETriggerTouchVector.begin();
|
||||
while (it != m_ETriggerTouchVector.end()) {
|
||||
auto& somePickup = *it;
|
||||
somePickup.DecreaseThisRespawnTimer -= dt;
|
||||
if (somePickup.DecreaseThisRespawnTimer < 0.0) {
|
||||
//spawn the new healthPickup
|
||||
auto entityFile = ResourceManager::Load<EntityFile>("Schema/Entities/HealthPickup.xml");
|
||||
EntityFileParser parser(entityFile);
|
||||
EntityID healthPickupID = parser.MergeEntities(m_World);
|
||||
EntityWrapper healthPickup = entityFile->MergeInto(m_World);
|
||||
|
||||
//let the world know a pickup has spawned (graphics effects, etc)
|
||||
Events::PickupSpawned ePickupSpawned;
|
||||
ePickupSpawned.Pickup = EntityWrapper(m_World, healthPickupID);
|
||||
ePickupSpawned.Pickup = healthPickup;
|
||||
m_EventBroker->Publish(ePickupSpawned);
|
||||
|
||||
//set values from the old entity to the new entity
|
||||
auto& newHealthPickupEntity = EntityWrapper(m_World, healthPickupID);
|
||||
newHealthPickupEntity["Transform"]["Position"] = healthPickupPosition.Pos;
|
||||
newHealthPickupEntity["HealthPickup"]["HealthGain"] = healthPickupPosition.HealthGain;
|
||||
newHealthPickupEntity["HealthPickup"]["RespawnTimer"] = healthPickupPosition.RespawnTimer;
|
||||
m_World->SetParent(newHealthPickupEntity.ID, healthPickupPosition.parentID);
|
||||
//copy values from the old entity to the new entity
|
||||
auto& newHealthPickupEntity = healthPickup;
|
||||
newHealthPickupEntity["Transform"]["Position"] = somePickup.Pos;
|
||||
newHealthPickupEntity["HealthPickup"]["HealthGain"] = somePickup.HealthGain;
|
||||
newHealthPickupEntity["HealthPickup"]["RespawnTimer"] = somePickup.RespawnTimer;
|
||||
m_World->SetParent(newHealthPickupEntity.ID, somePickup.parentID);
|
||||
|
||||
//erase the current element (healthPickupPosition)
|
||||
m_ETriggerTouchVector.erase(it);
|
||||
//erase the current element (somePickup)
|
||||
it = m_ETriggerTouchVector.erase(it);
|
||||
} else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
//still touching PickupAtMaximum?
|
||||
for (auto& it = m_PickupAtMaximum.begin(); it != m_PickupAtMaximum.end(); ++it) {
|
||||
if (!it->player.Valid()) {
|
||||
m_PickupAtMaximum.erase(it);
|
||||
break;
|
||||
}
|
||||
if ((double)it->player["Health"]["Health"] < (double)it->player["Health"]["MaxHealth"]) {
|
||||
DoPickup(it->player, it->trigger);
|
||||
m_PickupAtMaximum.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool PickupSpawnSystem::OnTriggerTouch(Events::TriggerTouch& e)
|
||||
{
|
||||
if (!e.Trigger.HasComponent("HealthPickup")) {
|
||||
return false;
|
||||
}
|
||||
double healthGiven = 0.01*(double)e.Trigger["HealthPickup"]["HealthGain"] * (double)e.Entity["Health"]["MaxHealth"];
|
||||
//cant pick up healthpacks if you are already at MaxHealth
|
||||
//if at maxhealth, save the trigger-touch to a vector since standing inside it will not re-trigger the trigger
|
||||
if ((double)e.Entity["Health"]["Health"] >= (double)e.Entity["Health"]["MaxHealth"]) {
|
||||
m_PickupAtMaximum.push_back({ e.Entity, e.Trigger });
|
||||
return false;
|
||||
}
|
||||
|
||||
//personEntered = e.Entity, thingEntered = e.Trigger
|
||||
DoPickup(e.Entity, e.Trigger);
|
||||
return true;
|
||||
}
|
||||
bool PickupSpawnSystem::OnTriggerLeave(Events::TriggerLeave& e)
|
||||
{
|
||||
if (!e.Trigger.HasComponent("HealthPickup")) {
|
||||
return false;
|
||||
}
|
||||
//triggerleave erases possible m_PickupAtMaximum
|
||||
for (auto& it = m_PickupAtMaximum.begin(); it != m_PickupAtMaximum.end(); ++it) {
|
||||
if (it->trigger.ID == e.Trigger.ID && it->player.ID == e.Entity.ID) {
|
||||
m_PickupAtMaximum.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
void PickupSpawnSystem::DoPickup(EntityWrapper &player, EntityWrapper &trigger)
|
||||
{
|
||||
double healthGiven = 0.01*(double)trigger["HealthPickup"]["HealthGain"] * (double)player["Health"]["MaxHealth"];
|
||||
|
||||
//only the server will increase the players hp and set it in the next delta
|
||||
Events::PlayerHealthPickup ePlayerHealthPickup;
|
||||
ePlayerHealthPickup.HealthAmount = healthGiven;
|
||||
ePlayerHealthPickup.Player = e.Entity;
|
||||
ePlayerHealthPickup.Player = player;
|
||||
m_EventBroker->Publish(ePlayerHealthPickup);
|
||||
|
||||
//copy position, healthgain, 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 healthPickup
|
||||
m_ETriggerTouchVector.push_back({ (glm::vec3)e.Trigger["Transform"]["Position"], e.Trigger["HealthPickup"]["HealthGain"],
|
||||
e.Trigger["HealthPickup"]["RespawnTimer"], e.Trigger["HealthPickup"]["RespawnTimer"], m_World->GetParent(e.Trigger.ID) });
|
||||
m_ETriggerTouchVector.push_back({ (glm::vec3)trigger["Transform"]["Position"], trigger["HealthPickup"]["HealthGain"],
|
||||
trigger["HealthPickup"]["RespawnTimer"], trigger["HealthPickup"]["RespawnTimer"], m_World->GetParent(trigger.ID) });
|
||||
|
||||
//delete the healthpickup
|
||||
m_World->DeleteEntity(e.Trigger.ID);
|
||||
return true;
|
||||
m_World->DeleteEntity(trigger.ID);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ PlayerDeathSystem::PlayerDeathSystem(SystemParams params)
|
||||
: System(params)
|
||||
{
|
||||
EVENT_SUBSCRIBE_MEMBER(m_OnPlayerDeath, &PlayerDeathSystem::OnPlayerDeath);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EEntityDeleted, &PlayerDeathSystem::OnEntityDeleted);
|
||||
}
|
||||
|
||||
void PlayerDeathSystem::Update(double dt)
|
||||
@@ -27,10 +28,8 @@ bool PlayerDeathSystem::OnPlayerDeath(Events::PlayerDeath& e)
|
||||
void PlayerDeathSystem::createDeathEffect(EntityWrapper player)
|
||||
{
|
||||
//load the explosioneffect XML
|
||||
auto deathEffect = ResourceManager::Load<EntityFile>("Schema/Entities/PlayerDeathExplosionWithCamera.xml");
|
||||
EntityFileParser parser(deathEffect);
|
||||
EntityID deathEffectID = parser.MergeEntities(m_World);
|
||||
EntityWrapper deathEffectEW = EntityWrapper(m_World, deathEffectID);
|
||||
auto entityFile = ResourceManager::Load<EntityFile>("Schema/Entities/PlayerDeathExplosionWithCamera.xml");
|
||||
EntityWrapper deathEffectEW = entityFile->MergeInto(m_World);
|
||||
|
||||
//components that we need from player
|
||||
auto playerModel = player.FirstChildByName("PlayerModel");
|
||||
@@ -59,9 +58,28 @@ void PlayerDeathSystem::createDeathEffect(EntityWrapper player)
|
||||
|
||||
//camera (with lifetime) behind the player
|
||||
if (player == LocalPlayer) {
|
||||
m_LocalPlayerDeathEffect = deathEffectEW;
|
||||
auto cam = deathEffectEW.FirstChildByName("Camera");
|
||||
Events::SetCamera eSetCamera;
|
||||
eSetCamera.CameraEntity = cam;
|
||||
m_EventBroker->Publish(eSetCamera);
|
||||
}
|
||||
}
|
||||
|
||||
bool PlayerDeathSystem::OnEntityDeleted(Events::EntityDeleted& e)
|
||||
{
|
||||
// We only care about when the local players death effect is removed.
|
||||
if (m_LocalPlayerDeathEffect.ID != e.DeletedEntity) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Look for the spectator camera entity in the level.
|
||||
EntityWrapper spectatorCam = m_World->GetFirstEntityByName("SpectatorCamera");
|
||||
if (!spectatorCam.Valid() || !spectatorCam.HasComponent("Camera") || LocalPlayer.Valid()) {
|
||||
return false;
|
||||
}
|
||||
Events::SetCamera eSetCamera;
|
||||
eSetCamera.CameraEntity = spectatorCam;
|
||||
m_EventBroker->Publish(eSetCamera);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ PlayerMovementSystem::PlayerMovementSystem(SystemParams params)
|
||||
{
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EPlayerSpawned, &PlayerMovementSystem::OnPlayerSpawned);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EDoubleJump, &PlayerMovementSystem::OnDoubleJump);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EDashAbility, &PlayerMovementSystem::OnDashAbility);
|
||||
}
|
||||
|
||||
PlayerMovementSystem::~PlayerMovementSystem()
|
||||
@@ -61,12 +62,18 @@ void PlayerMovementSystem::updateMovementControllers(double dt)
|
||||
float playerMovementSpeed = player["Player"]["MovementSpeed"];
|
||||
float playerCrouchSpeed = player["Player"]["CrouchSpeed"];
|
||||
glm::vec3& wishDirection = player["Player"]["CurrentWishDirection"];
|
||||
auto playerBoostAssaultEntity = player.FirstChildByName("BoostAssault");
|
||||
if (playerBoostAssaultEntity.Valid()) {
|
||||
playerMovementSpeed *= (double)playerBoostAssaultEntity["BoostAssault"]["StrengthOfEffect"];
|
||||
playerCrouchSpeed *= (double)playerBoostAssaultEntity["BoostAssault"]["StrengthOfEffect"];
|
||||
}
|
||||
|
||||
|
||||
if (player.HasComponent("Physics")) {
|
||||
ComponentWrapper cPhysics = player["Physics"];
|
||||
//Assault Dash Check
|
||||
if (player.HasComponent("DashAbility")) {
|
||||
controller->AssaultDashCheck(dt, ((glm::vec3)cPhysics["Velocity"]).y != 0.0f, player["DashAbility"]["CoolDownMaxTimer"], player["DashAbility"]["CoolDownTimer"]);
|
||||
controller->AssaultDashCheck(dt, ((glm::vec3)cPhysics["Velocity"]).y != 0.0f, player["DashAbility"]["CoolDownMaxTimer"], player["DashAbility"]["CoolDownTimer"], player.ID);
|
||||
}
|
||||
wishDirection = controller->Movement() * glm::inverse(glm::quat(ori));
|
||||
//this makes sure you can only dash in the 4 directions: forw,backw,left,right
|
||||
@@ -112,6 +119,10 @@ void PlayerMovementSystem::updateMovementControllers(double dt)
|
||||
//if doubleTapped do Assault Dash - but only boost maximum 50.0f
|
||||
float doubleTapDashBoost = controller->AssaultDashDoubleTapped() ? 40.0f : 1.0f;
|
||||
accelerationSpeed = glm::min(doubleTapDashBoost*glm::min(accelerationSpeed, addSpeed), 50.0f);
|
||||
//if player has Boost from an Assault class, accelerate the player faster
|
||||
if (playerBoostAssaultEntity.Valid()) {
|
||||
accelerationSpeed *= (double)playerBoostAssaultEntity["BoostAssault"]["StrengthOfEffect"];
|
||||
}
|
||||
velocity += accelerationSpeed * wishDirection;
|
||||
ImGui::Text("velocity: (%f, %f, %f) |%f|", velocity.x, velocity.y, velocity.z, glm::length(velocity));
|
||||
}
|
||||
@@ -303,11 +314,11 @@ bool PlayerMovementSystem::OnPlayerSpawned(Events::PlayerSpawned& e)
|
||||
bool PlayerMovementSystem::OnDoubleJump(Events::DoubleJump & e)
|
||||
{
|
||||
// If entity does not exist, exit
|
||||
if (!EntityWrapper(m_World, e.entityID).Valid()) {
|
||||
if (!EntityWrapper(m_World, e.entityID).Valid()) {
|
||||
return false;
|
||||
}
|
||||
// If entity IsLocalPlayer, exit
|
||||
if (e.entityID == m_LocalPlayer.ID) {
|
||||
if (e.entityID == m_LocalPlayer.ID) {
|
||||
return false;
|
||||
}
|
||||
spawnHexagon(EntityWrapper(m_World, e.entityID));
|
||||
@@ -315,11 +326,33 @@ bool PlayerMovementSystem::OnDoubleJump(Events::DoubleJump & e)
|
||||
}
|
||||
|
||||
void PlayerMovementSystem::spawnHexagon(EntityWrapper target)
|
||||
{
|
||||
{
|
||||
//put a hexagon at the entitys... feet?
|
||||
auto hexagonEffect = ResourceManager::Load<EntityFile>("Schema/Entities/DoubleJumpHexagon.xml");
|
||||
EntityFileParser parser(hexagonEffect);
|
||||
EntityID hexagonEffectID = parser.MergeEntities(m_World);
|
||||
EntityWrapper hexagonEW = EntityWrapper(m_World, hexagonEffectID);
|
||||
auto entityFile = ResourceManager::Load<EntityFile>("Schema/Entities/DoubleJumpHexagon.xml");
|
||||
EntityWrapper hexagonEW = entityFile->MergeInto(m_World);
|
||||
hexagonEW["Transform"]["Position"] = (glm::vec3)target["Transform"]["Position"];
|
||||
}
|
||||
}
|
||||
|
||||
bool PlayerMovementSystem::OnDashAbility(Events::DashAbility & e)
|
||||
{
|
||||
EntityWrapper player(m_World, e.Player);
|
||||
if (!player.Valid() || !IsClient || player.ID == LocalPlayer.ID) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto entityFile = ResourceManager::Load<EntityFile>("Schema/Entities/DashEffect.xml");
|
||||
EntityWrapper dashEffect = entityFile->MergeInto(m_World);
|
||||
auto playerModel = player.FirstChildByName("PlayerModel");
|
||||
auto playerEntityModel = playerModel["Model"];
|
||||
auto playerEntityAnimation = playerModel["Animation"];
|
||||
playerEntityModel.Copy(dashEffect["Model"]);
|
||||
playerEntityAnimation.Copy(dashEffect["Animation"]);
|
||||
dashEffect["ExplosionEffect"]["EndColor"] = (glm::vec4)playerEntityModel["Color"];
|
||||
((glm::vec4&)dashEffect["ExplosionEffect"]["EndColor"]).w = 0.f;
|
||||
dashEffect["Animation"]["Speed1"] = 0.0;
|
||||
dashEffect["Animation"]["Speed2"] = 0.0;
|
||||
dashEffect["Animation"]["Speed3"] = 0.0;
|
||||
dashEffect["Transform"]["Position"] = (glm::vec3)player["Transform"]["Position"];
|
||||
dashEffect["Transform"]["Orientation"] = (glm::vec3)player["Transform"]["Orientation"];
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ PlayerSpawnSystem::PlayerSpawnSystem(SystemParams params)
|
||||
ConfigFile* config = ResourceManager::Load<ConfigFile>("Config.ini");
|
||||
m_NetworkEnabled = config->Get("Networking.StartNetwork", false);
|
||||
m_ForcedRespawnTime = config->Get("Debug.RespawnTime", -1.0f);
|
||||
m_DbgConfigForceRespawn = m_ForcedRespawnTime > 0;
|
||||
m_DbgConfigForceRespawn = m_ForcedRespawnTime > 0 && IsServer;
|
||||
}
|
||||
|
||||
void PlayerSpawnSystem::Update(double dt)
|
||||
@@ -26,7 +26,21 @@ void PlayerSpawnSystem::Update(double dt)
|
||||
// Increase timer.
|
||||
double& timer = (double&)modeComponent["RespawnTime"];
|
||||
timer += dt;
|
||||
double maxRespawnTime = m_DbgConfigForceRespawn ? m_ForcedRespawnTime : (double)modeComponent["MaxRespawnTime"];
|
||||
if (m_DbgConfigForceRespawn) {
|
||||
(double&)modeComponent["MaxRespawnTime"] = m_ForcedRespawnTime;
|
||||
}
|
||||
double maxRespawnTime = (double)modeComponent["MaxRespawnTime"];
|
||||
EntityWrapper spectatorCam = m_World->GetFirstEntityByName("SpectatorCamera");
|
||||
if (spectatorCam.Valid()) {
|
||||
EntityWrapper HUD = spectatorCam.FirstChildByName("SpectatorHUD");
|
||||
if (HUD.Valid()) {
|
||||
EntityWrapper respawnTimer = spectatorCam.FirstChildByName("RespawnTimer");
|
||||
if (respawnTimer.Valid()) {
|
||||
//Update respawn time in the HUD element.
|
||||
respawnTimer["Text"]["Content"] = std::to_string(1 + (int)(maxRespawnTime - timer));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (timer < maxRespawnTime) {
|
||||
return;
|
||||
}
|
||||
@@ -54,7 +68,14 @@ void PlayerSpawnSystem::Update(double dt)
|
||||
|
||||
// If the spawner has a team affiliation, check it
|
||||
if (spawner.HasComponent("Team")) {
|
||||
if ((int)spawner["Team"]["Team"] != req.Team) {
|
||||
auto cSpawnerTeam = spawner["Team"];
|
||||
if ((int)cSpawnerTeam["Team"] != req.Team) {
|
||||
// Increase num spawned players if someone picks spectator, since it is valid to pick spectator
|
||||
// but don't spawn anything, goto next spawnrequest.
|
||||
if (req.Team == (int)cSpawnerTeam["Team"].Enum("Spectator")) {
|
||||
++numSpawnedPlayers;
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -75,9 +96,9 @@ void PlayerSpawnSystem::Update(double dt)
|
||||
}
|
||||
}
|
||||
if (numSpawnedPlayers != (int)m_SpawnRequests.size()) {
|
||||
LOG_DEBUG("%i players were supposed to be spawned, but %i was spawned.", (int)m_SpawnRequests.size(), numSpawnedPlayers);
|
||||
LOG_DEBUG("%i players were supposed to be spawned or set as spectator, but only %i was handled.", (int)m_SpawnRequests.size(), numSpawnedPlayers);
|
||||
} else {
|
||||
LOG_DEBUG("%i players were spawned.", numSpawnedPlayers);
|
||||
LOG_DEBUG("%i players were spawned or set as spectator.", numSpawnedPlayers);
|
||||
}
|
||||
m_SpawnRequests.clear();
|
||||
}
|
||||
@@ -88,24 +109,29 @@ bool PlayerSpawnSystem::OnInputCommand(Events::InputCommand& e)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (e.Value == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// A dead client should be able to swap to the spectator camera.
|
||||
if (IsClient && !LocalPlayer.Valid()) {
|
||||
// Set the spectator camera as active, if it exists.
|
||||
// Find the camera.
|
||||
EntityWrapper spectatorCam = m_World->GetFirstEntityByName("SpectatorCamera");
|
||||
if (spectatorCam.Valid() && spectatorCam.HasComponent("Camera")) {
|
||||
Events::SetCamera eSetCamera;
|
||||
eSetCamera.CameraEntity = spectatorCam;
|
||||
m_EventBroker->Publish(eSetCamera);
|
||||
}
|
||||
}
|
||||
|
||||
// Team picks should be processed ONLY server-side!
|
||||
// Don't make a spawn request if we're the client.
|
||||
if (!IsServer && m_NetworkEnabled) {
|
||||
return false;
|
||||
}
|
||||
|
||||
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.
|
||||
// Check if the player already requested spawn.
|
||||
auto iter = m_SpawnRequests.begin();
|
||||
for (; iter != m_SpawnRequests.end(); ++iter) {
|
||||
if (iter->PlayerID == e.PlayerID) {
|
||||
@@ -114,11 +140,11 @@ bool PlayerSpawnSystem::OnInputCommand(Events::InputCommand& e)
|
||||
}
|
||||
|
||||
if (iter != m_SpawnRequests.end()) {
|
||||
//If player is in queue to spawn, then change their team affiliation in the request.
|
||||
// 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.
|
||||
// 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;
|
||||
|
||||
@@ -17,15 +17,17 @@ EntityWrapper SpawnerSystem::Spawn(EntityWrapper spawner, EntityWrapper parent /
|
||||
|
||||
// Load the entity file and parse it
|
||||
const std::string& entityFilePath = spawner["Spawner"]["EntityFile"];
|
||||
auto entityFile = ResourceManager::Load<EntityFile>(entityFilePath);
|
||||
if (entityFile == nullptr) {
|
||||
EntityWrapper spawnedEntity;
|
||||
try {
|
||||
auto entityFile = ResourceManager::Load<EntityFile>(entityFilePath);
|
||||
spawnedEntity = entityFile->MergeInto(world);
|
||||
world->SetParent(spawnedEntity.ID, parent.ID);
|
||||
} catch (const Resource::FailedLoadingException& e) {
|
||||
return EntityWrapper::Invalid;
|
||||
}
|
||||
EntityFileParser parser(entityFile);
|
||||
EntityWrapper spawnedEntity(world, parser.MergeEntities(world, parent.ID));
|
||||
|
||||
//If the spawned entity is collideable, then we must not spawn it where it collides with something that
|
||||
//has a dontCollideComponent attached.
|
||||
// If the spawned entity is collidable, then we must not spawn it where it collides with something that
|
||||
// has a dontCollideComponent attached.
|
||||
bool spawnOnCollidable = dontCollideComponent.empty() || !spawnedEntity.HasComponent("Collidable");
|
||||
if (!spawnOnCollidable) {
|
||||
boost::optional<EntityAABB> optBox = Collision::EntityAbsoluteAABB(spawnedEntity);
|
||||
|
||||
@@ -366,9 +366,10 @@ bool AssaultWeaponBehaviour::shoot(double damage)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for friendly fire
|
||||
|
||||
// If friendly fire - reduce damage to 0 (needed to make Boosts, Ammosharing work)
|
||||
if ((ComponentInfo::EnumType)victim["Team"]["Team"] == (ComponentInfo::EnumType)m_Player["Team"]["Team"]) {
|
||||
return false;
|
||||
damage = 0;
|
||||
}
|
||||
|
||||
// Deal damage!
|
||||
|
||||
Reference in New Issue
Block a user