Merge remote-tracking branch 'origin/master' into Dirtybit

# Conflicts:
#	src/Engine/Collision/CollisionSystem.cpp
#	src/Engine/Core/Transform.cpp
#	src/Engine/Editor/EditorSystem.cpp
#	src/Engine/Rendering/AnimationSystem.cpp
#	src/Engine/Rendering/BoneAttachmentSystem.cpp
#	src/Game/Systems/CapturePointSystem.cpp
#	src/Game/Systems/ExplosionEffectSystem.cpp
#	src/Game/Systems/PlayerMovementSystem.cpp
This commit is contained in:
2016-03-12 03:37:29 +01:00
220 changed files with 61854 additions and 9148 deletions
+10 -2
View File
@@ -35,8 +35,12 @@
#include "Game/Systems/BoostSystem.h"
#include "Game/Systems/BoostIconsHUDSystem.h"
#include "Game/Systems/ScoreScreenSystem.h"
#include "Game/Systems/SpectatorCameraSystem.h"
#include "GUI/ButtonSystem.h"
#include "GUI/MainMenuSystem.h"
#include "Game/Systems/MainMenuSystem.h"
#include "Game/Systems/ServerListSystem.h"
#include "Game/Systems/StartSystem.h"
#include "Rendering/TextureSprite.h"
Game::Game(int argc, char* argv[])
@@ -48,6 +52,7 @@ Game::Game(int argc, char* argv[])
ResourceManager::RegisterType<Model>("Model");
ResourceManager::RegisterType<RawModel>("RawModel");
ResourceManager::RegisterType<Texture>("Texture");
ResourceManager::RegisterType<TextureSprite>("TextureSprite");
ResourceManager::RegisterType<PNG>("Png");
ResourceManager::RegisterType<ShaderProgram>("ShaderProgram");
ResourceManager::RegisterType<EntityFile>("EntityFile");
@@ -149,6 +154,9 @@ Game::Game(int argc, char* argv[])
m_SystemPipeline->AddSystem<MainMenuSystem>(updateOrderLevel, m_Renderer);
m_SystemPipeline->AddSystem<BoostIconsHUDSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<ScoreScreenSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<SpectatorCameraSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<ServerListSystem>(updateOrderLevel, m_Renderer);
m_SystemPipeline->AddSystem<StartSystem>(updateOrderLevel);
// Populate Octree with collidables
++updateOrderLevel;
m_SystemPipeline->AddSystem<FillOctreeSystem>(updateOrderLevel, m_OctreeCollision, "Collidable");
@@ -211,7 +219,7 @@ void Game::Tick()
PerformanceTimer::StartTimerAndStopPrevious("InputProxy");
m_InputProxy->Update(dt);
m_EventBroker->Swap();
m_InputProxy->Process();
m_InputProxy->Process(ImGui::GetIO().WantCaptureKeyboard || ImGui::GetIO().WantCaptureMouse);
m_EventBroker->Swap();
PerformanceTimer::StartTimerAndStopPrevious("SoundManager");
@@ -15,7 +15,9 @@ bool MultiplayerSnapshotFilter::FilterComponent(EntityWrapper entity, SharedComp
|| component.Info.Name == "AssaultWeapon"
|| component.Info.Name == "DefenderWeapon"
|| component.Info.Name == "Animation"
|| component.Info.Name == "AnimationOffset"
|| component.Info.Name == "Blend"
|| component.Info.Name == "BlendAdditive"
|| component.Info.Name == "BlendOverride"
|| entity.Name() == "PlayerName"
) {
return false;
+61 -13
View File
@@ -37,8 +37,7 @@ void AmmoPickupSystem::Update(double dt)
//erase the current element (somePickup)
it = m_ETriggerTouchVector.erase(it);
}
else {
} else {
it++;
}
}
@@ -48,7 +47,7 @@ void AmmoPickupSystem::Update(double dt)
m_PickupAtMaximum.erase(it);
break;
}
if ((int)it->player["AssaultWeapon"]["Ammo"] < (int)it->player["AssaultWeapon"]["MaxAmmo"]) {
if (!DoesPlayerHaveMaxAmmo(it->player)) {
DoPickup(it->player, it->trigger);
m_PickupAtMaximum.erase(it);
break;
@@ -56,6 +55,58 @@ void AmmoPickupSystem::Update(double dt)
}
}
}
bool AmmoPickupSystem::DoesPlayerHaveMaxAmmo(EntityWrapper &player) {
PlayerClass playerClass = DetermineClass(player);
if (playerClass == PlayerClass::Defender) {
return !((int)player["DefenderWeapon"]["Ammo"] < (int)player["DefenderWeapon"]["MaxAmmo"]);
} else if (playerClass == PlayerClass::Sniper) {
return !((int)player["SniperWeapon"]["Ammo"] < (int)player["SniperWeapon"]["MaxAmmo"]);
} else if (playerClass == PlayerClass::Assault) {
return !((int)player["AssaultWeapon"]["Ammo"] < (int)player["AssaultWeapon"]["MaxAmmo"]);
} else {
return false;
}
}
void AmmoPickupSystem::SetPlayerAmmo(EntityWrapper &player, int ammoGain) {
int maxWeaponAmmo = GetPlayerMaxAmmo(player);
PlayerClass playerClass = DetermineClass(player);
if (playerClass == PlayerClass::Defender) {
(Field<int>)player["DefenderWeapon"]["Ammo"] = std::min((int)player["DefenderWeapon"]["Ammo"] + ammoGain, maxWeaponAmmo);
} else if (playerClass == PlayerClass::Sniper) {
(Field<int>)player["SniperWeapon"]["Ammo"] = std::min((int)player["SniperWeapon"]["Ammo"] + ammoGain, maxWeaponAmmo);
} else if (playerClass == PlayerClass::Assault) {
(Field<int>)player["AssaultWeapon"]["Ammo"] = std::min((int)player["AssaultWeapon"]["Ammo"] + ammoGain, maxWeaponAmmo);
} else {
//unknown class - ignore
}
}
int AmmoPickupSystem::GetPlayerMaxAmmo(EntityWrapper &player) {
PlayerClass playerClass = DetermineClass(player);
if (playerClass == PlayerClass::Defender) {
return (int)player["DefenderWeapon"]["MaxAmmo"];
} else if (playerClass == PlayerClass::Sniper) {
return (int)player["SniperWeapon"]["MaxAmmo"];
} else if (playerClass == PlayerClass::Assault) {
return (int)player["AssaultWeapon"]["MaxAmmo"];
} else {
return -1;
}
}
AmmoPickupSystem::PlayerClass AmmoPickupSystem::DetermineClass(EntityWrapper &player)
{
//determine the class based on what component the inflictor-player has
if (m_World->HasComponent(player.ID, "DashAbility")) {
return PlayerClass::Assault;
}
if (m_World->HasComponent(player.ID, "ShieldAbility")) {
return PlayerClass::Defender;
}
if (m_World->HasComponent(player.ID, "SprintAbility")) {
return PlayerClass::Sniper;
}
return PlayerClass::None;
}
bool AmmoPickupSystem::OnTriggerTouch(Events::TriggerTouch& e)
{
@@ -63,7 +114,7 @@ bool AmmoPickupSystem::OnTriggerTouch(Events::TriggerTouch& e)
return false;
}
//TODO: add other weapontypes
if (!e.Entity.HasComponent("AssaultWeapon")) {
if (DetermineClass(e.Entity) == PlayerClass::None) {
return false;
}
if (!e.Trigger.HasComponent("AmmoPickup")) {
@@ -71,7 +122,7 @@ bool AmmoPickupSystem::OnTriggerTouch(Events::TriggerTouch& e)
}
//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"]) {
if (DoesPlayerHaveMaxAmmo(e.Entity)) {
m_PickupAtMaximum.push_back({ e.Entity, e.Trigger });
return false;
}
@@ -85,19 +136,16 @@ bool AmmoPickupSystem::OnAmmoPickup(Events::AmmoPickup & e)
return false;
}
//TODO: add other weapontypes
if (!e.Player.HasComponent("AssaultWeapon")) {
if (DetermineClass(e.Player) == PlayerClass::None) {
return false;
}
int maxWeaponAmmo = (int)e.Player["AssaultWeapon"]["MaxAmmo"];
int& currentAmmo = (int)e.Player["AssaultWeapon"]["Ammo"];
//cant pick up ammopacks if you are already at MaxAmmo
if (currentAmmo >= maxWeaponAmmo) {
if (DoesPlayerHaveMaxAmmo(e.Player)) {
return false;
}
SetPlayerAmmo(e.Player, e.AmmoGain);
currentAmmo = std::min(currentAmmo + e.AmmoGain, maxWeaponAmmo);
return false;
return true;
}
bool AmmoPickupSystem::OnTriggerLeave(Events::TriggerLeave& e) {
@@ -119,7 +167,7 @@ void AmmoPickupSystem::DoPickup(EntityWrapper &player, EntityWrapper &trigger) {
if (!trigger.Valid()) {
return;
}
int maxWeaponAmmo = (int)player["AssaultWeapon"]["MaxAmmo"];
int maxWeaponAmmo = GetPlayerMaxAmmo(player);
int ammoGiven = 0.01*(double)trigger["AmmoPickup"]["AmmoGain"] * maxWeaponAmmo;
Events::AmmoPickup ePlayerAmmoPickup;
+17 -4
View File
@@ -108,10 +108,10 @@ void CapturePointSystem::UpdateComponent(EntityWrapper& capturePointEntity, Comp
//change what model is displaying (change all in case 2 capturepoints has been captured on the same frame)
for (int i = 0; i < m_NumberOfCapturePoints; i++) {
auto owner = (int)m_CapturePointNumberToEntityMap[i]["Team"]["Team"];
if (m_CapturePointNumberToEntityMap[i].FirstChildByName("Red").ID != EntityID_Invalid) {
m_CapturePointNumberToEntityMap[i].FirstChildByName("Red")["Model"]["Visible"] = owner == redTeam ? true : false;
m_CapturePointNumberToEntityMap[i].FirstChildByName("Blue")["Model"]["Visible"] = owner == blueTeam ? true : false;
m_CapturePointNumberToEntityMap[i].FirstChildByName("Spectator")["Model"]["Visible"] = owner == spectatorTeam ? true : false;
if (m_CapturePointNumberToEntityMap[i].FirstChildByName("Red").Valid()) {
ChangeCapturePointModelsVisibility(m_CapturePointNumberToEntityMap[i].FirstChildByName("Red"), owner == redTeam);
ChangeCapturePointModelsVisibility(m_CapturePointNumberToEntityMap[i].FirstChildByName("Blue"), owner == blueTeam);
ChangeCapturePointModelsVisibility(m_CapturePointNumberToEntityMap[i].FirstChildByName("Spectator"), owner == spectatorTeam);
}
}
//save the next cap points and publish the captured event
@@ -232,6 +232,19 @@ void CapturePointSystem::UpdateComponent(EntityWrapper& capturePointEntity, Comp
}
void CapturePointSystem::ChangeCapturePointModelsVisibility(EntityWrapper &capturePointModels, bool isOwner) {
(Field<bool>)capturePointModels["Model"]["Visible"] = isOwner;
for (auto& capModel : capturePointModels.ChildrenWithComponent("Transform"))
{
if (capModel.HasComponent("Model")) {
(Field<bool>)capModel["Model"]["Visible"] = isOwner;
}
if (capModel.HasComponent("PointLight")) {
(Field<bool>)capModel["PointLight"]["Visible"] = isOwner;
}
}
}
bool CapturePointSystem::OnTriggerTouch(const Events::TriggerTouch& e)
{
//personEntered = e.Entity, thingEntered = e.Trigger
+11 -5
View File
@@ -8,12 +8,13 @@ DamageIndicatorSystem::DamageIndicatorSystem(SystemParams params)
EVENT_SUBSCRIBE_MEMBER(m_ESetCamera, &DamageIndicatorSystem::OnSetCamera);
//load texture to cache
auto texture = CommonFunctions::LoadTexture("Textures/DamageIndicator.png", false);
auto texture = CommonFunctions::TryLoadResource<Texture, false>("Textures/DamageIndicator.png");
auto entityFile = ResourceManager::Load<EntityXMLFile>("Schema/Entities/DamageIndicator.xml");
m_NetworkEnabled = ResourceManager::Load<ConfigFile>("Config.ini")->Get("Networking.StartNetwork", false);
}
void DamageIndicatorSystem::Update(double dt) {
if (!IsServer && LocalPlayer.Valid()) {
if ((!IsServer || !m_NetworkEnabled) && LocalPlayer.Valid()) {
for (auto& iter = updateDamageIndicatorVector.begin(); iter != updateDamageIndicatorVector.end(); iter++) {
if (!iter->spriteEntity.Valid()) {
updateDamageIndicatorVector.erase(iter);
@@ -40,10 +41,15 @@ bool DamageIndicatorSystem::OnPlayerDamage(Events::PlayerDamage& e)
return false;
}
//friendly fire - return
if (e.Damage < 0.1f) {
return false;
}
glm::vec3 inflictorPos = e.Inflictor["Transform"]["Position"];
//if testing
#ifdef INDICATOR_TEST
inflictorPos = DamageIndicatorTest(e.Victim);
inflictorPos = DamageIndicatorTest(e.Victim);
#endif
float angleBetweenVectors = CalculateAngle(e.Victim, inflictorPos);
@@ -55,7 +61,7 @@ bool DamageIndicatorSystem::OnPlayerDamage(Events::PlayerDamage& e)
//simply set the rotation z-wise to the angleBetweenVectors
sprite["Transform"]["Orientation"] = glm::vec3(0, 0, angleBetweenVectors);
if (!IsServer) {
if (!IsServer || !m_NetworkEnabled) {
updateDamageIndicatorVector.emplace_back(sprite, inflictorPos);
}
@@ -122,7 +128,7 @@ glm::vec3 DamageIndicatorSystem::DamageIndicatorTest(EntityWrapper player) {
}
m_TestVar++;
auto inflictorPos = glm::vec3(currentPos.x + testVar*6.0f, currentPos.y, currentPos.z + testVar2*6.0f);
auto inflictorPos = glm::vec3(currentPos.x + testVar*6.0f, currentPos.y, currentPos.z + testVar2*6.0f);
//load the explosioneffect XML
auto deathEffect = ResourceManager::Load<EntityXMLFile>("Schema/Entities/PlayerDeathExplosionWithCamera.xml");
+10 -7
View File
@@ -2,14 +2,17 @@
void ExplosionEffectSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt)
{
Field<double> timeSinceDeath = component["TimeSinceDeath"];
if (timeSinceDeath > (double)component["ExplosionDuration"]) {
timeSinceDeath = 0.f;
Field<double> delay = component["Delay"];
if (delay > 0) {
delay = std::max(0.0, delay - dt);
}
timeSinceDeath += dt;
//if ((bool)Component["Gravity"] == true) {
// (bool)Component["ExponentialAccelaration"] = false;
//}
if (delay <= 0) {
Field<double> timeSinceDeath = component["TimeSinceDeath"];
timeSinceDeath += (Field<double>)component["Speed"] * dt;
if (timeSinceDeath < 0 || timeSinceDeath > (const double&)component["ExplosionDuration"]) {
timeSinceDeath = 0.0;
}
}
}
+103
View File
@@ -0,0 +1,103 @@
#include "../Game/Systems/MainMenuSystem.h"
MainMenuSystem::MainMenuSystem(SystemParams params, IRenderer* renderer)
: System(params)
, ImpureSystem()
, m_Renderer(renderer)
{
EVENT_SUBSCRIBE_MEMBER(m_EPressed, &MainMenuSystem::OnButtonPress);
EVENT_SUBSCRIBE_MEMBER(m_EReleased, &MainMenuSystem::OnButtonRelease);
EVENT_SUBSCRIBE_MEMBER(m_EClicked, &MainMenuSystem::OnButtonClick);
EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &MainMenuSystem::OnInputCommand);
}
void MainMenuSystem::Update(double dt)
{
}
void MainMenuSystem::OpenSubMenu(const Events::InputCommand& e)
{
auto menus = m_World->GetComponents("Menu");
if (menus == nullptr) {
return;
}
if (m_OpenSubMenu == EntityWrapper::Invalid) {
//No submenu is open, open one.
for (auto& menu : *menus) {
EntityWrapper menuEntity = EntityWrapper(m_World, menu.EntityID);
auto serverListSpawner = menuEntity.FirstChildByName(e.Command + "Spawner");
if (!serverListSpawner.HasComponent("Spawner")) {
return;
}
m_OpenSubMenu = SpawnerSystem::Spawn(serverListSpawner, serverListSpawner);
Events::SearchForServers event;
m_EventBroker->Publish(event);
break;
}
} else if (m_OpenSubMenu.Name().compare(e.Command) != 0) {
//Menu is open, but not the right one, delete the old one and open a new one.
m_World->DeleteEntity(m_OpenSubMenu.ID);
m_OpenSubMenu = EntityWrapper::Invalid;
for (auto& menu : *menus) {
EntityWrapper menuEntity = EntityWrapper(m_World, menu.EntityID);
auto serverListSpawner = menuEntity.FirstChildByName(e.Command + "Spawner");
if (!serverListSpawner.HasComponent("Spawner")) {
return;
}
m_OpenSubMenu = SpawnerSystem::Spawn(serverListSpawner, serverListSpawner);
Events::SearchForServers event;
m_EventBroker->Publish(event);
break;
}
} else {
//Serverlist submenu is open, close it.
m_World->DeleteEntity(m_OpenSubMenu.ID);
m_OpenSubMenu = EntityWrapper::Invalid;
}
}
bool MainMenuSystem::OnButtonClick(const Events::ButtonClicked& e)
{
EntityWrapper entity = e.Entity;
if (entity.Name() == "ServerIdentityConnect") {
EntityWrapper serverIdentityEntity = entity.FirstParentWithComponent("ServerIdentity");
if(serverIdentityEntity.Valid()) {
Events::ConnectRequest event;
event.IP = (std::string)serverIdentityEntity["ServerIdentity"]["IP"];
event.Port = (int)serverIdentityEntity["ServerIdentity"]["Port"];
printf("\n ----Request Server Connect----\nIP: %s\nPort: %i\n ------------------------------", event.IP, event.Port);
m_EventBroker->Publish(event);
}
} else if (entity.HasComponent("ConfigBtnResolution")) {
m_Renderer->SetResolution(Rectangle((int)entity["ConfigBtnResolution"]["Width"], (int)entity["ConfigBtnResolution"]["Height"]));
}
return true;
}
bool MainMenuSystem::OnButtonRelease(const Events::ButtonReleased& e)
{
return true;
}
bool MainMenuSystem::OnButtonPress(const Events::ButtonPressed& e)
{
return true;
}
bool MainMenuSystem::OnInputCommand(const Events::InputCommand& e)
{
if(e.Command == "Play" && e.Value == 1) {
OpenSubMenu(e);
} else if (e.Command == "RefreshServerList" && e.Value == 1){
Events::SearchForServers event;
m_EventBroker->Publish(event);
} else if (e.Command == "Options" && e.Value == 1) {
OpenSubMenu(e);
}
return true;
}
+30 -7
View File
@@ -1,10 +1,12 @@
#include "Systems/PlayerDeathSystem.h"
#include "Core/ELockMouse.h"
PlayerDeathSystem::PlayerDeathSystem(SystemParams params)
: System(params)
{
EVENT_SUBSCRIBE_MEMBER(m_OnPlayerDeath, &PlayerDeathSystem::OnPlayerDeath);
EVENT_SUBSCRIBE_MEMBER(m_EEntityDeleted, &PlayerDeathSystem::OnEntityDeleted);
EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &PlayerDeathSystem::OnInputCommand);
}
void PlayerDeathSystem::Update(double dt)
@@ -33,10 +35,10 @@ void PlayerDeathSystem::createDeathEffect(EntityWrapper player)
//components that we need from player
auto playerModel = player.FirstChildByName("PlayerModel");
if (!playerModel.Valid()) {
return;
}
if (!playerModel.HasComponent("Model") || !playerModel.HasComponent("Animation")) {
if (player == LocalPlayer) {
setSpectatorCamera();
}
return;
}
auto playerEntityModel = playerModel["Model"];
@@ -68,14 +70,35 @@ bool PlayerDeathSystem::OnEntityDeleted(Events::EntityDeleted& e)
if (m_LocalPlayerDeathEffect.ID != e.DeletedEntity) {
return false;
}
// If the player hasn't spawned already, activate the spectator camera.
if (!LocalPlayer.Valid()) {
setSpectatorCamera();
}
return true;
}
void PlayerDeathSystem::setSpectatorCamera()
{
// 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;
if (!spectatorCam.HasComponent("Camera")) {
return;
}
Events::SetCamera eSetCamera;
eSetCamera.CameraEntity = spectatorCam;
m_EventBroker->Publish(eSetCamera);
return true;
Events::UnlockMouse unlock;
m_EventBroker->Publish(unlock);
}
bool PlayerDeathSystem::OnInputCommand(Events::InputCommand& e)
{
if (e.Value == 0 || e.Command != "SwapToTeamPick" && e.Command != "SwapToClassPick") {
return false;
}
// Ensure that we don't set spectator camera if the player deliberately changes to class/team pick.
m_LocalPlayerDeathEffect = EntityWrapper::Invalid;
return true;
}
+51 -48
View File
@@ -81,27 +81,18 @@ void PlayerMovementSystem::updateMovementControllers(double dt)
cameraOrientation.x(cameraOrientation.x() + controller->Rotation().x);
// Limit camera pitch so we don't break our necks
cameraOrientation.x(glm::clamp(cameraOrientation.x(), -glm::half_pi<float>(), glm::half_pi<float>()));
// Set third person model aim pitch
EntityWrapper playerModel = player.FirstChildByName("PlayerModel");
//Third-person aim
if (playerModel.Valid()) {
EntityWrapper aimPrimaryEntity = playerModel.FirstChildByName("AimPrimary");
EntityWrapper aimPrimaryEntity = playerModel.FirstChildByName("Aim");
if(aimPrimaryEntity.Valid()){
if(aimPrimaryEntity.HasComponent("Animation")) {
float pitch = cameraOrientation.x() + 0.2f;
double time = (pitch + glm::half_pi<float>()) / glm::pi<float>();
float pitch = cameraOrientation.x();
double time = ((pitch + glm::half_pi<float>()) / glm::pi<float>());
(Field<double>)aimPrimaryEntity["Animation"]["Time"] = time;
}
}
EntityWrapper aimSecondaryEntity = playerModel.FirstChildByName("AimSecondary");
if (aimSecondaryEntity.Valid()) {
if (aimSecondaryEntity.HasComponent("Animation")) {
float pitch = cameraOrientation.x() + 0.2f;
double time = (pitch + glm::half_pi<float>()) / glm::pi<float>();
(Field<double>)aimSecondaryEntity["Animation"]["Time"] = time;
}
}
}
}
@@ -214,7 +205,7 @@ void PlayerMovementSystem::updateMovementControllers(double dt)
{
Events::AutoAnimationBlend aeb;
aeb.Duration = 0.25;
aeb.NodeName = "StandCrouchBlend";
aeb.NodeName = "MovementBlend";
aeb.RootNode = playerModel;
aeb.Start = true;
aeb.Restart = false;
@@ -245,11 +236,11 @@ void PlayerMovementSystem::updateMovementControllers(double dt)
{
Events::AutoAnimationBlend aeb;
aeb.Duration = 0.25;
aeb.NodeName = "StandCrouchBlend";
aeb.NodeName = "MovementBlend";
aeb.RootNode = playerModel;
aeb.Start = true;
aeb.Restart = false;
aeb.AnimationEntity = playerModel.FirstChildByName("Jump");
aeb.AnimationEntity = playerModel.FirstChildByName("BlendTreeLower").FirstChildByName("Jump");
m_EventBroker->Publish(aeb);
}
}
@@ -274,6 +265,12 @@ void PlayerMovementSystem::updateMovementControllers(double dt)
size = glm::vec3(1.f, 1.f, 1.f);
} else {
size = glm::vec3(1.f, 1.6f, 1.f);
if (controller->CrouchingLastFrame() && isOnGround) {
// The collision should resolve this anyway, but
// this is more reliable, since the box gets larger.
Field<glm::vec3> pos = cTransform["Position"];
pos.y(pos.y() + 0.3f);
}
}
}
@@ -378,12 +375,12 @@ void PlayerMovementSystem::spawnHexagon(EntityWrapper target)
bool PlayerMovementSystem::OnDashAbility(Events::DashAbility & e)
{
EntityWrapper player(m_World, e.Player);
if (!player.Valid() || !IsClient){// || player.ID == LocalPlayer.ID) {
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 entityFile = ResourceManager::Load<EntityFile>("Schema/Entities/DashEffect.xml");
// EntityWrapper dashEffect = entityFile->MergeInto(m_World);
EntityWrapper playerModel = player.FirstChildByName("PlayerModel");
for (auto& kv : m_PlayerInputControllers) {
@@ -401,7 +398,7 @@ bool PlayerMovementSystem::OnDashAbility(Events::DashAbility & e)
if (controller->Movement().x > 0) {
{
Events::AutoAnimationBlend aeb;
aeb.Duration = 0.3;
aeb.Duration = 0.1;
aeb.NodeName = "DashRight";
aeb.RootNode = playerModel;
aeb.Restart = true;
@@ -410,19 +407,18 @@ bool PlayerMovementSystem::OnDashAbility(Events::DashAbility & e)
}
{
Events::AutoAnimationBlend aeb;
aeb.Duration = 0.3;
aeb.NodeName = "StandCrouchBlend";
aeb.Duration = 0.2;
aeb.NodeName = "MovementBlend";
aeb.RootNode = playerModel;
aeb.Delay = -0.3;
aeb.Start = true;
aeb.Restart = false;
aeb.AnimationEntity = playerModel.FirstChildByName("DashForward");
aeb.AnimationEntity = playerModel.FirstChildByName("DashRight");
m_EventBroker->Publish(aeb);
}
} else {
{
Events::AutoAnimationBlend aeb;
aeb.Duration = 0.3;
aeb.Duration = 0.1;
aeb.NodeName = "DashLeft";
aeb.RootNode = playerModel;
aeb.Restart = true;
@@ -431,13 +427,12 @@ bool PlayerMovementSystem::OnDashAbility(Events::DashAbility & e)
}
{
Events::AutoAnimationBlend aeb;
aeb.Duration = 0.3;
aeb.NodeName = "StandCrouchBlend";
aeb.Duration = 0.2;
aeb.NodeName = "MovementBlend";
aeb.RootNode = playerModel;
aeb.Delay = -0.3;
aeb.Start = true;
aeb.Restart = false;
aeb.AnimationEntity = playerModel.FirstChildByName("DashForward");
aeb.AnimationEntity = playerModel.FirstChildByName("DashLeft");
m_EventBroker->Publish(aeb);
}
}
@@ -445,7 +440,7 @@ bool PlayerMovementSystem::OnDashAbility(Events::DashAbility & e)
if (controller->Movement().z < 0) {
{
Events::AutoAnimationBlend aeb;
aeb.Duration = 0.3;
aeb.Duration = 0.1;
aeb.NodeName = "DashForward";
aeb.RootNode = playerModel;
aeb.Restart = true;
@@ -454,10 +449,9 @@ bool PlayerMovementSystem::OnDashAbility(Events::DashAbility & e)
}
{
Events::AutoAnimationBlend aeb;
aeb.Duration = 0.3;
aeb.NodeName = "StandCrouchBlend";
aeb.Duration = 0.2;
aeb.NodeName = "MovementBlend";
aeb.RootNode = playerModel;
aeb.Delay = -0.3;
aeb.Start = true;
aeb.Restart = false;
aeb.AnimationEntity = playerModel.FirstChildByName("DashForward");
@@ -466,7 +460,7 @@ bool PlayerMovementSystem::OnDashAbility(Events::DashAbility & e)
} else {
{
Events::AutoAnimationBlend aeb;
aeb.Duration = 0.3;
aeb.Duration = 0.1;
aeb.NodeName = "DashBackward";
aeb.RootNode = playerModel;
aeb.Restart = true;
@@ -475,32 +469,41 @@ bool PlayerMovementSystem::OnDashAbility(Events::DashAbility & e)
}
{
Events::AutoAnimationBlend aeb;
aeb.Duration = 0.3;
aeb.NodeName = "StandCrouchBlend";
aeb.Duration = 0.2;
aeb.NodeName = "MovementBlend";
aeb.RootNode = playerModel;
aeb.Delay = -0.3;
aeb.Start = true;
aeb.Restart = false;
aeb.AnimationEntity = playerModel.FirstChildByName("DashForward");
aeb.AnimationEntity = playerModel.FirstChildByName("DashBackward");
m_EventBroker->Publish(aeb);
}
}
}
}
}
}
/*
auto playerEntityAnimation = playerModel["Animation"];
playerEntityModel.Copy(dashEffect["Model"]);
playerEntityAnimation.Copy(dashEffect["Animation"]);
dashEffect["ExplosionEffect"]["EndColor"] = (glm::vec4)playerEntityModel["Color"];
((Field<glm::vec4>)dashEffect["ExplosionEffect"]["EndColor"]).w = 0.f;
*/
EntityWrapper dashEffectModel;
dashEffectModel = playerModel.Clone();
player["Transform"].Copy(dashEffectModel["Transform"]);
dashEffectModel.AttachComponent("ExplosionEffect");
dashEffectModel["ExplosionEffect"]["EndColor"] = (glm::vec4)playerModel["Model"]["Color"];
((Field<glm::vec4>)dashEffectModel["ExplosionEffect"]["EndColor"]).w = 0.f;
(Field<double>)dashEffectModel["ExplosionEffect"]["ExplosionDuration"] = dashEffect["Lifetime"]["Lifetime"];
(Field<glm::vec3>)dashEffectModel["ExplosionEffect"]["ExplosionOrigin"] = glm::vec3(0, 1, 0) + (0.2f * controller->Movement());
auto animationChildren = dashEffectModel.ChildrenWithComponent("Animation");
for (auto animationEntity : animationChildren) {
(Field<bool>)animationEntity["Animation"]["Play"] = false;
}
*/
}
}
}
return true;
}
+61 -52
View File
@@ -1,4 +1,5 @@
#include "Systems/PlayerSpawnSystem.h"
#include "Core/ELockMouse.h"
PlayerSpawnSystem::PlayerSpawnSystem(SystemParams params)
: System(params)
@@ -59,7 +60,15 @@ void PlayerSpawnSystem::Update(double dt)
}
int numSpawnedPlayers = 0;
for (auto& req : m_SpawnRequests) {
int playersSpectating = 0;
const int numRequestsToHandle = (int)m_SpawnRequests.size();
for (auto it = m_SpawnRequests.begin(); it != m_SpawnRequests.end(); ++it) {
// It is valid if they didn't pick class yet
// but don't spawn anything, goto next spawnrequest.
if (it->Class == PlayerClass::None) {
++playersSpectating;
continue;
}
for (auto& cPlayerSpawn : *playerSpawns) {
EntityWrapper spawner(m_World, cPlayerSpawn.EntityID);
if (!spawner.HasComponent("Spawner")) {
@@ -69,43 +78,49 @@ void PlayerSpawnSystem::Update(double dt)
// If the spawner has a team affiliation, check it
if (spawner.HasComponent("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;
if ((int)cSpawnerTeam["Team"] != it->Team) {
// If they somehow has a valid class as spectator, don't spawn them.
if (it->Team == cSpawnerTeam["Team"].Enum("Spectator")) {
++playersSpectating;
break;
}
continue;
}
}
// TODO: Choose a different spawner depending on class picked?
// Spawn the player!
EntityWrapper player = SpawnerSystem::Spawn(spawner, EntityWrapper::Invalid, "Player");
// Set the player team affiliation
player["Team"]["Team"] = req.Team;
player["Team"]["Team"] = it->Team;
// Publish a PlayerSpawned event
Events::PlayerSpawned e;
e.PlayerID = req.PlayerID;
e.PlayerID = it->PlayerID;
e.Player = player;
e.Spawner = spawner;
m_EventBroker->Publish(e);
++numSpawnedPlayers;
it = m_SpawnRequests.erase(it);
break;
}
if (it == m_SpawnRequests.end()) {
break;
}
}
if (numSpawnedPlayers != (int)m_SpawnRequests.size()) {
LOG_DEBUG("%i players were supposed to be spawned or set as spectator, but only %i was handled.", (int)m_SpawnRequests.size(), numSpawnedPlayers);
if (numSpawnedPlayers != numRequestsToHandle - playersSpectating) {
LOG_DEBUG("%i players were supposed to be spawned, but only %i was successfully.", numRequestsToHandle - playersSpectating, numSpawnedPlayers);
} else {
LOG_DEBUG("%i players were spawned or set as spectator.", numSpawnedPlayers);
std::string dbg = numSpawnedPlayers != 0 ? std::to_string(numSpawnedPlayers) + " players were spawned. " : "";
dbg += playersSpectating != 0 ? std::to_string(playersSpectating) + " players are spectating/picking class. " : "";
LOG_DEBUG(dbg.c_str());
}
m_SpawnRequests.clear();
}
bool PlayerSpawnSystem::OnInputCommand(Events::InputCommand& e)
{
if (e.Command != "PickTeam" && e.Command != "SwapToClassPick") {
if (e.Command != "PickTeam" && e.Command != "PickClass" && e.Command != "SwapToTeamPick" && e.Command != "SwapToClassPick") {
return false;
}
@@ -113,19 +128,6 @@ bool PlayerSpawnSystem::OnInputCommand(Events::InputCommand& e)
return false;
}
// A dead client should be able to swap to the overwatch camera.
if (IsClient && !LocalPlayer.Valid()) {
// Set the camera as active, if it exists.
// Find the respawn camera or class pick camera.
std::string camName = e.Command == "SwapToClassPick" ? "PickClassCamera" : "SpectatorCamera";
EntityWrapper spectatorCam = m_World->GetFirstEntityByName(camName);
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) {
@@ -136,27 +138,38 @@ bool PlayerSpawnSystem::OnInputCommand(Events::InputCommand& e)
auto iter = m_SpawnRequests.begin();
for (; iter != m_SpawnRequests.end(); ++iter) {
if (iter->PlayerID == e.PlayerID) {
// If player wants to switch class, remove their spawn request.
if (e.Command == "SwapToClassPick") {
m_SpawnRequests.erase(iter);
// If player wants to switch team or class , remove their selected class so they don't spawn.
if (e.Command == "SwapToTeamPick" || e.Command == "SwapToClassPick") {
iter->Class = PlayerClass::None;
return true;
}
break;
}
}
if (e.Command == "SwapToClassPick") {
return true;
}
//If we get here we got a PickTeam or PickClass, so add or alter a spawn request.
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;
// If player is in queue to spawn, then change their team affiliation or class in the request.
if (e.Command == "PickTeam") {
iter->Team = (ComponentInfo::EnumType)e.Value;
} else {
iter->Class = static_cast<PlayerClass>((int)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;
if (e.Command == "PickTeam") {
req.Team = (ComponentInfo::EnumType)e.Value;
req.Class = PlayerClass::None;
} else {
// Should never get here, since you should have picked a team before you ever get a chance to pick class.
LOG_WARNING("Sequence error: Should not be able to pick class before team");
req.Team = 1; // TODO: 1 Signifies spectator, should probably have real enum here later.
req.Class = static_cast<PlayerClass>((int)e.Value);
}
m_SpawnRequests.push_back(req);
} else {
return false;
@@ -191,18 +204,8 @@ bool PlayerSpawnSystem::OnPlayerSpawned(Events::PlayerSpawned& e)
Events::SetCamera e;
e.CameraEntity = cameraEntity;
m_EventBroker->Publish(e);
}
// HACK: Set the player model color to team color
EntityWrapper playerModel = e.Player.FirstChildByName("PlayerModel");
if (playerModel.Valid() && e.Player.HasComponent("Team")) {
ComponentWrapper cTeam = e.Player["Team"];
ComponentWrapper cModel = playerModel["Model"];
if ((ComponentInfo::EnumType)cTeam["Team"] == cTeam["Team"].Enum("Red")) {
cModel["Color"] = glm::vec3(1.f, 0.f, 0.f);
} else if ((ComponentInfo::EnumType)cTeam["Team"] == cTeam["Team"].Enum("Blue")) {
cModel["Color"] = glm::vec3(0.f, 0.25f, 1.f);
}
Events::LockMouse lock;
m_EventBroker->Publish(lock);
}
return true;
@@ -210,7 +213,7 @@ bool PlayerSpawnSystem::OnPlayerSpawned(Events::PlayerSpawned& e)
bool PlayerSpawnSystem::OnPlayerDeath(Events::PlayerDeath& e)
{
//Only spawn request if network is disabled or we are server.
// Only spawn request if network is disabled or we are server.
if (!IsServer && m_NetworkEnabled) {
return false;
}
@@ -218,10 +221,6 @@ bool PlayerSpawnSystem::OnPlayerDeath(Events::PlayerDeath& e)
return false;
}
ComponentWrapper cTeam = e.Player["Team"];
//A spectator can't die anyway
if ((ComponentInfo::EnumType)cTeam["Team"] == cTeam["Team"].Enum("Spectator")) {
return false;
}
if (m_PlayerIDs.count(e.Player.ID) == 0) {
return false;
@@ -230,6 +229,16 @@ bool PlayerSpawnSystem::OnPlayerDeath(Events::PlayerDeath& e)
SpawnRequest req;
req.PlayerID = m_PlayerIDs.at(e.Player.ID);
req.Team = cTeam["Team"];
// TODO: Something better than temp class state code, if we ever add class enums in .xml
if (e.Player.HasComponent("DashAbility")) {
req.Class = PlayerClass::Assault;
} else if (e.Player.HasComponent("SprintAbility")) {
req.Class = PlayerClass::Sniper;
} else if (e.Player.HasComponent("ShieldAbility")) {
req.Class = PlayerClass::Defender;
} else {
req.Class = PlayerClass::None;
}
m_SpawnRequests.push_back(req);
return true;
+53
View File
@@ -0,0 +1,53 @@
#include "../Game/Systems/ServerListSystem.h"
ServerListSystem::ServerListSystem(SystemParams params, IRenderer* renderer)
: System(params)
, PureSystem("ServerList")
, m_Renderer(renderer)
{
EVENT_SUBSCRIBE_MEMBER(m_EServerListRecieved, &ServerListSystem::OnServerListRecieved);
}
void ServerListSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& cServerList, double dt)
{
}
void ServerListSystem::RefreshList()
{
Events::SearchForServers event;
m_EventBroker->Publish(event);
}
bool ServerListSystem::OnServerListRecieved(const Events::DisplayServerlist& e)
{
if (e.Serverlist.size() == 0) {
return 1;
}
auto serverLists = m_World->GetComponents("ServerList");
if (serverLists == nullptr)
return 1;
for (auto& cServerList : *serverLists) {
EntityWrapper serverListEntity = EntityWrapper(m_World, cServerList.EntityID);
EntityWrapper identitySpawner = serverListEntity.FirstChildByName("ServerIdentitySpawner");
identitySpawner.DeleteChildren();
(Field<int>)cServerList["TotalIdentities"] = (int)e.Serverlist.size();
for (int i = 0; i < e.Serverlist.size(); i++) {
//Create Identities for each server and place them on the right position.
EntityWrapper newIdentity = SpawnerSystem::Spawn(identitySpawner, identitySpawner);
EntityWrapper serverIdentityEntity = newIdentity.FirstChildByName("ServerIdentity");
glm::vec3 offset = (glm::vec3)serverListEntity["ServerList"]["Offset"];
(Field<glm::vec3>)serverIdentityEntity["Transform"]["Position"] = offset * (float)i;
auto& cIdentity = serverIdentityEntity["ServerIdentity"];
(Field<std::string>)cIdentity["IP"] = e.Serverlist[i].Address;
(Field<std::string>)cIdentity["ServerName"] = e.Serverlist[i].Name;
(Field<int>)cIdentity["Port"] = e.Serverlist[i].Port;
(Field<int>)cIdentity["PlayersConnected"] = e.Serverlist[i].PlayersConnected;
}
}
return 1;
}
+104
View File
@@ -0,0 +1,104 @@
#include "Systems/SpectatorCameraSystem.h"
#include "Rendering/ESetCamera.h"
#include "Core/ELockMouse.h"
SpectatorCameraSystem::SpectatorCameraSystem(SystemParams params)
: System(params)
, m_CamSetToTeamPick(false)
, m_PickedTeam(-1)
{
EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &SpectatorCameraSystem::OnInputCommand);
EVENT_SUBSCRIBE_MEMBER(m_EDisconnect, &SpectatorCameraSystem::OnDisconnect);
}
void SpectatorCameraSystem::Update(double dt)
{
if (!m_CamSetToTeamPick && IsClient) {
// Find the class pick camera and set them to it, since they need to pick a team before they can leave the screen.
EntityWrapper spectatorCam = m_World->GetFirstEntityByName("PickTeamCamera");
if (spectatorCam.HasComponent("Camera")) {
m_CamSetToTeamPick = true;
Events::SetCamera eSetCamera;
eSetCamera.CameraEntity = spectatorCam;
m_EventBroker->Publish(eSetCamera);
Events::UnlockMouse unlock;
m_EventBroker->Publish(unlock);
}
}
}
bool SpectatorCameraSystem::OnInputCommand(const Events::InputCommand& e)
{
// Only the client should do this, and only if player is not spawned.
if (!IsClient || LocalPlayer.Valid()) {
return false;
}
bool swapToClass = e.Command == "PickTeam" || e.Command == "SwapToClassPick";
if (e.Value == 0 || !swapToClass && e.Command != "SwapToTeamPick" && e.Command != "PickClass") {
return false;
}
if (e.Command == "PickTeam") {
m_PickedTeam = e.Value;
}
// If a team has not been picked, they may not exit the pick team screen.
if (m_PickedTeam == -1) {
return false;
}
// A dead client should be able to swap to and between the overwatch cameras.
std::string camName;
// TODO: 1 Signifies spectator, should probably have real enum here later.
// Spectators should never end up at the class select, instead put them at the SpectatorCamera.
if (swapToClass && m_PickedTeam != 1) {
camName = "PickClassCamera";
} else if (e.Command == "SwapToTeamPick") {
camName = "PickTeamCamera";
} else {
camName = "SpectatorCamera";
}
EntityWrapper spectatorCam = m_World->GetFirstEntityByName(camName);
// Set the camera as active, if it exists.
if (spectatorCam.HasComponent("Camera")) {
// Set the class pick button visible if a blue or red team is picked, else invisible.
EntityWrapper HUD;
if (camName == "SpectatorCamera") {
HUD = spectatorCam.FirstChildByName("SpectatorHUD");
} else if (camName == "PickTeamCamera") {
HUD = spectatorCam.FirstChildByName("PickTeamHUD");
}
// If we are at the class pick already, or if HUD is invalid for any other reason, do nothing.
if (HUD.Valid()) {
EntityWrapper toClassButton = spectatorCam.FirstChildByName("ToClassPick");
if (toClassButton.Valid()) {
// Set ClassButton as invisible if spectator, else visible.
bool visible = m_PickedTeam != 1; // TODO: 1 Signifies spectator.
toClassButton["Sprite"]["Visible"] = visible;
for (auto& child : toClassButton.ChildrenWithComponent("Text")) {
child["Text"]["Visible"] = visible;
}
}
}
Events::SetCamera eSetCamera;
eSetCamera.CameraEntity = spectatorCam;
m_EventBroker->Publish(eSetCamera);
Events::UnlockMouse unlock;
m_EventBroker->Publish(unlock);
}
return true;
}
bool SpectatorCameraSystem::OnDisconnect(const Events::PlayerDisconnected& e)
{
// If local player gets disconnected, they should be set to
// the spectator camera next time a map loads that has one.
if (e.Entity == LocalPlayer.ID) {
m_CamSetToTeamPick = false;
// They will also be set to menu, so unlock mouse just in case they were in game with locked mouse.
Events::UnlockMouse unlock;
m_EventBroker->Publish(unlock);
}
return true;
}
+33
View File
@@ -0,0 +1,33 @@
#include "../Game/Systems/StartSystem.h"
StartSystem::StartSystem(SystemParams params)
: System(params)
, ImpureSystem()
{
EVENT_SUBSCRIBE_MEMBER(m_ECameraActivated, &StartSystem::OnCameraActivated);
}
void StartSystem::Update(double dt)
{
auto cameras = m_World->GetComponents("Camera");
if(cameras == nullptr) {
return;
}
for(auto& cCamera: *cameras) {
EntityWrapper cameraEntity = EntityWrapper(m_World, cCamera.EntityID);
if(cameraEntity == m_ActiveCamera){
return;
}
if(cameraEntity.Name() == "Overview_Camera_Start_Menu") {
Events::SetCamera event;
event.CameraEntity = cameraEntity;
m_EventBroker->Publish(event);
}
}
}
bool StartSystem::OnCameraActivated(const Events::SetCamera& e)
{
m_ActiveCamera = e.CameraEntity;
return 1;
}
+10 -6
View File
@@ -7,17 +7,21 @@ void TextFieldReader::UpdateComponent(EntityWrapper& entity, ComponentWrapper& c
}
// Find the entity to read from
const std::string& parentEntityName = cAmmunitionHUD["ParentEntityName"];
const std::string& entityName = cAmmunitionHUD["ParentEntityName"];
const std::string& componentType = cAmmunitionHUD["ComponentType"];
EntityWrapper readEntity = entity;
if (!parentEntityName.empty()) {
readEntity = entity.FirstParentByName(parentEntityName);
if (!readEntity.Valid()) {
return;
if (entityName.empty()) {
if (!readEntity.HasComponent(componentType)) {
readEntity = readEntity.FirstParentWithComponent(componentType);
}
} else {
readEntity = entity.FirstParentByName(entityName);
}
if (!readEntity.Valid()) {
return;
}
// Find the component to read from
const std::string& componentType = cAmmunitionHUD["ComponentType"];
if (componentType.empty() || !readEntity.HasComponent(componentType)) {
return;
}
@@ -40,12 +40,16 @@ void AssaultWeaponBehaviour::UpdateWeapon(ComponentWrapper cWeapon, WeaponInfo&
magAmmo = glm::min(*magSize, *ammo);
isReloading = false;
if (wi.FirstPersonEntity.Valid()) {
wi.FirstPersonEntity["Model"]["Visible"] = true;
wi.FirstPersonEntity.FirstChildByName("ViewModel")["Model"]["Visible"] = true;
}
if (wi.ThirdPersonEntity.Valid()) {
wi.ThirdPersonEntity["Model"]["Visible"] = true;
}
}
double reloadTime = cWeapon["ReloadTime"];
if (isReloading && reloadTimer <= reloadTime / 2) {
}
// Restore view angle
if (IsClient) {
@@ -68,7 +72,7 @@ void AssaultWeaponBehaviour::UpdateWeapon(ComponentWrapper cWeapon, WeaponInfo&
const float& movementSpeed = cPlayer["MovementSpeed"];
float speed = glm::length((const glm::vec3&)cPhysics["Velocity"]);
float animationWeight = glm::min(speed, movementSpeed) / movementSpeed;
EntityWrapper rootNode = wi.FirstPersonEntity.FirstParentWithComponent("Model");
EntityWrapper rootNode = wi.FirstPersonEntity;
if (rootNode.Valid()) {
EntityWrapper blend = rootNode.FirstChildByName("MovementBlend");
if (blend.Valid()) {
@@ -121,19 +125,35 @@ void AssaultWeaponBehaviour::OnReload(ComponentWrapper cWeapon, WeaponInfo& wi)
reloadTimer = reloadTime;
// Play animation
playAnimationAndReturn(wi.FirstPersonEntity, "BlendTreeAssaultWeapon", "Reload");
if (IsClient) {
// Spawn explosion effect
EntityWrapper reloadEffectSpawner = wi.FirstPersonEntity.FirstChildByName("FirstPersonReloadSpawner");
if (reloadEffectSpawner.Valid()) {
SpawnerSystem::Spawn(reloadEffectSpawner, reloadEffectSpawner);
playAnimationAndReturn(wi.FirstPersonEntity, "ActionBlend", "Reload");
// Third person anim
Events::AutoAnimationBlend b1;
b1.RootNode = wi.ThirdPersonPlayerModel;
b1.NodeName = "Reload";
b1.Restart = true;
b1.Start = true;
m_EventBroker->Publish(b1);
// Spawn explosion effect
if (wi.FirstPersonEntity.Valid()) {
if (IsClient) {
EntityWrapper reloadEffectSpawner = wi.FirstPersonEntity.FirstChildByName("ReloadSpawner");
if (reloadEffectSpawner.Valid()) {
reloadEffectSpawner.DeleteChildren();
SpawnerSystem::Spawn(reloadEffectSpawner, reloadEffectSpawner);
}
}
if (wi.FirstPersonEntity.Valid()) {
wi.FirstPersonEntity["Model"]["Visible"] = false;
}
if (wi.ThirdPersonEntity.Valid()) {
wi.ThirdPersonEntity["Model"]["Visible"] = false;
wi.FirstPersonEntity.FirstChildByName("ViewModel")["Model"]["Visible"] = false;
}
if (wi.ThirdPersonEntity.Valid()) {
if (IsServer) {
EntityWrapper reloadEffectSpawner = wi.ThirdPersonEntity.FirstChildByName("ReloadSpawner");
if (reloadEffectSpawner.Valid()) {
reloadEffectSpawner.DeleteChildren();
SpawnerSystem::Spawn(reloadEffectSpawner, reloadEffectSpawner);
}
}
wi.ThirdPersonEntity["Model"]["Visible"] = false;
}
// Sound
@@ -190,7 +210,7 @@ void AssaultWeaponBehaviour::fireBullet(ComponentWrapper cWeapon, WeaponInfo& wi
}
// Get weapon model based on current person
EntityWrapper weaponModelEntity = getRelevantWeaponModelEntity(wi);
EntityWrapper weaponModelEntity = getRelevantWeaponEntity(wi);
if (!weaponModelEntity.Valid()) {
return;
}
@@ -221,7 +241,15 @@ void AssaultWeaponBehaviour::fireBullet(ComponentWrapper cWeapon, WeaponInfo& wi
}
// Play animation
playAnimationAndReturn(wi.FirstPersonEntity, "BlendTreeAssaultWeapon", "Fire");
playAnimationAndReturn(wi.FirstPersonEntity, "ActionBlend", "Fire");
// Third person anim
Events::AutoAnimationBlend b1;
b1.RootNode = wi.ThirdPersonPlayerModel;
b1.NodeName = "Fire";
b1.Restart = true;
b1.Start = true;
m_EventBroker->Publish(b1);
// Sound
Events::PlaySoundOnEntity e;
@@ -36,7 +36,7 @@ void DefenderWeaponBehaviour::UpdateWeapon(ComponentWrapper cWeapon, WeaponInfo&
m_EventBroker->Publish(e);
} else {
isReloading = false;
playAnimationAndReturn(wi.FirstPersonEntity, "FinalBlend", "Idle");
playAnimationAndReturn(wi.FirstPersonEntity, "FinalBlend", "ReloadEnd");
}
}
@@ -99,7 +99,21 @@ void DefenderWeaponBehaviour::OnReload(ComponentWrapper cWeapon, WeaponInfo& wi)
reloadTimer = reloadTime;
// Play animation
playAnimationAndReturn(wi.FirstPersonEntity, "FinalBlend", "Reload");
if (wi.FirstPersonEntity.Valid()) {
Events::AutoAnimationBlend eBlendStart;
eBlendStart.RootNode = wi.FirstPersonEntity;
eBlendStart.NodeName = "ReloadStart";
eBlendStart.Restart = true;
eBlendStart.Start = true;
m_EventBroker->Publish(eBlendStart);
Events::AutoAnimationBlend eBlendLoop;
eBlendLoop.RootNode = wi.FirstPersonEntity;
eBlendLoop.NodeName = "ReloadLoop";
eBlendLoop.Restart = true;
eBlendLoop.Start = true;
eBlendLoop.AnimationEntity = wi.FirstPersonEntity.FirstChildByName("ReloadStart");
m_EventBroker->Publish(eBlendLoop);
}
}
void DefenderWeaponBehaviour::OnHolster(ComponentWrapper cWeapon, WeaponInfo& wi)
@@ -114,17 +128,18 @@ void DefenderWeaponBehaviour::OnHolster(ComponentWrapper cWeapon, WeaponInfo& wi
bool DefenderWeaponBehaviour::OnInputCommand(ComponentWrapper cWeapon, WeaponInfo& wi, const Events::InputCommand& e)
{
if (e.Command == "SpecialAbility" && IsServer) {
if (e.Command == "SpecialAbility") {
EntityWrapper attachment = wi.Player.FirstChildByName("ShieldAttachment");
if (attachment.Valid()) {
if (e.Value > 0) {
SpawnerSystem::Spawn(attachment, attachment);
if (IsServer) {
SpawnerSystem::Spawn(attachment, attachment);
}
EntityWrapper root = wi.FirstPersonEntity.FirstParentWithComponent("Model");
if (root.Valid()) {
EntityWrapper subTree = root.FirstChildByName("FinalBlend");
if (subTree.Valid()) {
EntityWrapper animationNode = subTree.FirstChildByName("Shield");
if (IsClient) {
EntityWrapper root = wi.FirstPersonEntity;
if (root.Valid()) {
EntityWrapper animationNode = root.FirstChildByName("Shield");
if (animationNode.Valid()) {
Events::AutoAnimationBlend eFireBlend;
eFireBlend.RootNode = root;
@@ -138,11 +153,10 @@ bool DefenderWeaponBehaviour::OnInputCommand(ComponentWrapper cWeapon, WeaponInf
} else {
attachment.DeleteChildren();
EntityWrapper root = wi.FirstPersonEntity.FirstParentWithComponent("Model");
if (root.Valid()) {
EntityWrapper subTree = root.FirstChildByName("FinalBlend");
if (subTree.Valid()) {
EntityWrapper animationNode = subTree.FirstChildByName("ActionBlend");
if (IsClient) {
EntityWrapper root = wi.FirstPersonEntity;
if (root.Valid()) {
EntityWrapper animationNode = root.FirstChildByName("ActionBlend");
if (animationNode.Valid()) {
Events::AutoAnimationBlend eFireBlend;
eFireBlend.RootNode = root;
@@ -232,7 +246,7 @@ void DefenderWeaponBehaviour::fireShell(ComponentWrapper cWeapon, WeaponInfo& wi
}
// Play animation
playAnimationAndReturn(wi.FirstPersonEntity, "BlendTreeDefenderWeapon", "Fire");
playAnimationAndReturn(wi.FirstPersonEntity, "FinalBlend", "Fire");
// Sound
Events::PlaySoundOnEntity e;
@@ -52,7 +52,7 @@ void SidearmWeaponBehaviour::fireBullet(ComponentWrapper cWeapon, WeaponInfo& wi
cWeapon["FireCooldown"] = 60.0 / (double)cWeapon["RPM"];
// Get weapon model based on current person
EntityWrapper weaponModelEntity = getRelevantWeaponModelEntity(wi);
EntityWrapper weaponModelEntity = getRelevantWeaponEntity(wi);
if (!weaponModelEntity.Valid()) {
return;
}