From bb76c9d248bb94d503e5331c25bcf55d567f2a01 Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Thu, 25 Feb 2016 16:24:38 +0100 Subject: [PATCH] WIP multi-weapon behaviours --- include/Engine/Core/EntityWrapper.h | 4 + include/Engine/Core/System.h | 2 +- .../Systems/Weapon/AssaultWeaponBehaviour.h | 30 +-- .../Systems/Weapon/DefenderWeaponBehaviour.h | 38 +++ include/Game/Systems/Weapon/WeaponBehaviour.h | 173 +++++++++++- resources/Schema/Components.xsd | 2 + resources/Schema/Components/AssaultWeapon.xml | 1 + resources/Schema/Components/AssaultWeapon.xsd | 2 + .../Schema/Components/DefenderWeapon.xml | 16 ++ .../Schema/Components/DefenderWeapon.xsd | 44 +++ resources/Schema/Components/Player.xml | 1 + resources/Schema/Components/Player.xsd | 1 + resources/Schema/Components/Weapon.xml | 3 - resources/Schema/Components/Weapon.xsd | 17 -- .../Schema/Components/WeaponAttachment.xml | 5 + .../Schema/Components/WeaponAttachment.xsd | 28 ++ .../Schema/Entities/AssaultWeaponView.xml | 99 +++++++ .../Schema/Entities/AssaultWeaponWorld.xml | 40 +++ resources/Schema/Entities/DefenderShield.xml | 40 +++ .../Schema/Entities/DefenderWeaponView.xml | 99 +++++++ .../Schema/Entities/DefenderWeaponViewRed.xml | 99 +++++++ .../Schema/Entities/DefenderWeaponWorld.xml | 41 +++ .../Entities/DefenderWeaponWorldRed.xml | 41 +++ resources/Schema/Entities/MovementTest.xml | 253 +----------------- resources/Schema/Entities/Player.xml | 204 +++++--------- resources/Schema/Entities/PlayerRed.xml | 209 ++++++--------- resources/Schema/Types/Entity.xsd | 2 + resources/Schema/Types/WeaponSlotEnum.xsd | 16 ++ src/Engine/Core/EntityWrapper.cpp | 43 +++ src/Engine/Core/Util/Logging.cpp | 4 +- src/Game/Game.cpp | 8 +- .../Network/MultiplayerSnapshotFilter.cpp | 1 + src/Game/Systems/DamageIndicatorSystem.cpp | 2 +- ...aviour.cpp => AssaultWeaponBehaviour.cpp_} | 52 ++-- .../Weapon/DefenderWeaponBehaviour.cpp | 188 +++++++++++++ .../{WeaponSystem.cpp => WeaponSystem.cpp_} | 56 +++- 36 files changed, 1251 insertions(+), 613 deletions(-) create mode 100644 include/Game/Systems/Weapon/DefenderWeaponBehaviour.h create mode 100755 resources/Schema/Components/DefenderWeapon.xml create mode 100755 resources/Schema/Components/DefenderWeapon.xsd delete mode 100644 resources/Schema/Components/Weapon.xml delete mode 100644 resources/Schema/Components/Weapon.xsd create mode 100644 resources/Schema/Components/WeaponAttachment.xml create mode 100644 resources/Schema/Components/WeaponAttachment.xsd create mode 100755 resources/Schema/Entities/AssaultWeaponView.xml create mode 100755 resources/Schema/Entities/AssaultWeaponWorld.xml create mode 100755 resources/Schema/Entities/DefenderShield.xml create mode 100755 resources/Schema/Entities/DefenderWeaponView.xml create mode 100755 resources/Schema/Entities/DefenderWeaponViewRed.xml create mode 100755 resources/Schema/Entities/DefenderWeaponWorld.xml create mode 100755 resources/Schema/Entities/DefenderWeaponWorldRed.xml mode change 100644 => 100755 resources/Schema/Entities/PlayerRed.xml create mode 100644 resources/Schema/Types/WeaponSlotEnum.xsd rename src/Game/Systems/Weapon/{AssaultWeaponBehaviour.cpp => AssaultWeaponBehaviour.cpp_} (87%) create mode 100644 src/Game/Systems/Weapon/DefenderWeaponBehaviour.cpp rename src/Game/Systems/Weapon/{WeaponSystem.cpp => WeaponSystem.cpp_} (56%) diff --git a/include/Engine/Core/EntityWrapper.h b/include/Engine/Core/EntityWrapper.h index 4643e28b..8ece8e59 100644 --- a/include/Engine/Core/EntityWrapper.h +++ b/include/Engine/Core/EntityWrapper.h @@ -30,10 +30,13 @@ struct EntityWrapper EntityWrapper FirstChildByName(const std::string& name); EntityWrapper FirstParentWithComponent(const std::string& componentType); EntityWrapper Clone(EntityWrapper parent = EntityWrapper::Invalid); + std::vector ChildrenWithComponent(const std::string& componentType); + void DeleteChildren(); bool IsChildOf(EntityWrapper potentialParent); bool Valid() const; ComponentWrapper operator[](const char* componentName); + ComponentWrapper operator[](const std::string& componentName); bool operator==(const EntityWrapper& e) const; bool operator!=(const EntityWrapper& e) const; explicit operator EntityID() const; @@ -41,6 +44,7 @@ struct EntityWrapper private: EntityWrapper firstChildByNameRecursive(const std::string& name, EntityID parent); EntityWrapper cloneRecursive(EntityWrapper entity, EntityWrapper parent); + void childrenWithComponentRecursive(const std::string& componentType, EntityWrapper& entity, std::vector& childrenWithComponent); }; namespace std diff --git a/include/Engine/Core/System.h b/include/Engine/Core/System.h index 1a387855..23d5f9a5 100644 --- a/include/Engine/Core/System.h +++ b/include/Engine/Core/System.h @@ -68,7 +68,7 @@ protected: const std::string m_ComponentType; - virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& cPlayer, double dt) = 0; + virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) = 0; }; class ImpureSystem : public virtual System diff --git a/include/Game/Systems/Weapon/AssaultWeaponBehaviour.h b/include/Game/Systems/Weapon/AssaultWeaponBehaviour.h index 7bd9c175..993dd060 100644 --- a/include/Game/Systems/Weapon/AssaultWeaponBehaviour.h +++ b/include/Game/Systems/Weapon/AssaultWeaponBehaviour.h @@ -1,37 +1,33 @@ +#ifndef AssaultWeaponBehaviour_h__ +#define AssaultWeaponBehaviour_h__ + #include "Sound/EPlaySoundOnEntity.h" #include "Collision/Collision.h" -#include "Rendering/AnimationSystem.h" #include "Core/ConfigFile.h" #include "WeaponBehaviour.h" #include "../SpawnerSystem.h" #include "Core/EPlayerDamage.h" #include "Core/EShoot.h" - -class AssaultWeaponBehaviour : public WeaponBehaviour +class AssaultWeaponBehaviour : public WeaponBehaviour { public: - AssaultWeaponBehaviour(SystemParams systemParams, IRenderer* renderer, Octree* collisionOctree, EntityWrapper weaponEntity); - - virtual void Fire() override; - virtual void CeaseFire() override; - virtual void Reload() override; + AssaultWeaponBehaviour(SystemParams systemParams, IRenderer* renderer, Octree* collisionOctree) + : WeaponBehaviour(systemParams, "AssaultWeapon", renderer, collisionOctree) + { } - virtual void Update(double dt) override; +protected: + virtual void OnPrimaryFire(WeaponInfo& wi) override; + virtual void OnCeasePrimaryFire(WeaponInfo& wi) override; + virtual void OnReload(WeaponInfo& wi) override; private: - EntityWrapper m_FirstPersonModel; - EntityWrapper m_ThirdPersonModel; // State bool m_Firing = false; bool m_Reloading = false; double m_ReloadTimer = 0.0; - EntityWrapper m_FirstPersonReloadImpersonator; - EntityWrapper m_ThirdPersonReloadImpersonator; double m_TimeSinceLastFire = 0.0; - - EventRelay m_EAnimationComplete; - bool OnAnimationComplete(Events::AnimationComplete& e); + EntityWrapper m_FirstPersonReloadImpostor; bool hasAmmo(); void fireRound(); @@ -47,3 +43,5 @@ private: bool shoot(double damage); void showHitMarker(); }; + +#endif \ No newline at end of file diff --git a/include/Game/Systems/Weapon/DefenderWeaponBehaviour.h b/include/Game/Systems/Weapon/DefenderWeaponBehaviour.h new file mode 100644 index 00000000..5ca13d3e --- /dev/null +++ b/include/Game/Systems/Weapon/DefenderWeaponBehaviour.h @@ -0,0 +1,38 @@ +#include "WeaponBehaviour.h" +#include "Collision/Collision.h" +#include "Core/EPlayerDamage.h" +#include "Rendering/ESetCamera.h" + +class DefenderWeaponBehaviour : public WeaponBehaviour +{ +public: + DefenderWeaponBehaviour(SystemParams systemParams, IRenderer* renderer, Octree* collisionOctree) + : System(systemParams) + , WeaponBehaviour(systemParams, "DefenderWeapon", renderer, collisionOctree) + , m_RandomEngine(m_RandomDevice()) + { + EVENT_SUBSCRIBE_MEMBER(m_ESetCamera, &DefenderWeaponBehaviour::OnSetCamera); + } + + void UpdateComponent(EntityWrapper& entity, ComponentWrapper& cWeapon, double dt) override; + void UpdateWeapon(WeaponInfo& wi, double dt) override; + void OnPrimaryFire(WeaponInfo& wi) override; + void OnCeasePrimaryFire(WeaponInfo& wi) override; + bool OnInputCommand(WeaponInfo& wi, const Events::InputCommand& e) override; + +private: + std::random_device m_RandomDevice; + std::mt19937 m_RandomEngine; + EntityWrapper m_CurrentCamera; + + EventRelay m_ESetCamera; + bool OnSetCamera(const Events::SetCamera& e); + + // Weapon functions + void fireShell(WeaponInfo& wi); + void dealDamage(WeaponInfo& wi, glm::vec3 direction, double damage); + + // Utility + float traceRayDistance(glm::vec3 origin, glm::vec3 direction); + Camera cameraFromEntity(EntityWrapper camera); +}; \ No newline at end of file diff --git a/include/Game/Systems/Weapon/WeaponBehaviour.h b/include/Game/Systems/Weapon/WeaponBehaviour.h index 7a0b4626..f23269df 100644 --- a/include/Game/Systems/Weapon/WeaponBehaviour.h +++ b/include/Game/Systems/Weapon/WeaponBehaviour.h @@ -5,30 +5,177 @@ #include "Rendering/IRenderer.h" #include "Core/Octree.h" #include "Collision/EntityAABB.h" +#include "Input/EInputCommand.h" +#include "Systems/SpawnerSystem.h" -class WeaponBehaviour : public System +template +class WeaponBehaviour : public PureSystem { + friend class WeaponSystem; + public: - WeaponBehaviour(SystemParams systemParams, IRenderer* renderer, Octree* collisionOctree, EntityWrapper player) - : System(systemParams) + WeaponBehaviour(SystemParams params, std::string componentType, IRenderer* renderer, Octree* collisionOctree) + : System(params) + , PureSystem(componentType) , m_Renderer(renderer) , m_CollisionOctree(collisionOctree) - , m_Player(player) - { } + { + EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &WeaponBehaviour::_OnInputCommand) + } virtual ~WeaponBehaviour() = default; - WeaponBehaviour(const WeaponBehaviour&) = delete; - WeaponBehaviour& operator=(const WeaponBehaviour &) = delete; - - virtual void Fire() = 0; - virtual void CeaseFire() { } - virtual void Reload() { } - virtual void Update(double dt) { } + virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) override + { + auto weapon = getActiveWeapon(entity); + if (!weapon) { + return; + } else { + UpdateWeapon(*weapon, dt); + } + } protected: + struct WeaponInfo + { + std::string WeaponComponent; + EntityWrapper Player; + EntityWrapper WeaponEntity; + EntityWrapper FirstPersonEntity; + EntityWrapper ThirdPersonEntity; + ComponentWrapper GetComponent() { return WeaponEntity[WeaponComponent]; } + }; + IRenderer* m_Renderer; Octree* m_CollisionOctree; - EntityWrapper m_Player; + std::unordered_map m_ActiveWeapons; + + virtual void UpdateWeapon(WeaponInfo& wi, double dt) { } + virtual void OnPrimaryFire(WeaponInfo& wi) { } + virtual void OnCeasePrimaryFire(WeaponInfo& wi) { } + virtual void OnReload(WeaponInfo& wi) { } + virtual bool OnInputCommand(WeaponInfo& wi, const Events::InputCommand& e) { return false; } + +private: + EventRelay m_EInputCommand; + bool _OnInputCommand(const Events::InputCommand& e) + { + EntityWrapper player = e.Player; + if (e.PlayerID == -1) { + player = LocalPlayer; + } + + // Make sure the player is alive + if (!player.Valid()) { + return false; + } + + // Make sure the player has this weapon + auto weapon = getWeaponComponent(player); + if (!weapon) { + return false; + } + + // Weapon selection + if (e.Command == "SelectWeapon") { + if (static_cast(e.Value) == static_cast((*weapon)["Slot"])) { + selectWeapon(player); + } + } + + // Only handle weapon actions if the weapon is active + auto activeWeapon = getActiveWeapon(player); + if (!activeWeapon) { + return false; + } + + // Fire + if (e.Command == "PrimaryFire") { + if (e.Value > 0) { + OnPrimaryFire(*activeWeapon); + } else { + OnCeasePrimaryFire(*activeWeapon); + } + } + + // Reload + if (e.Command == "Reload" && e.Value != 0) { + OnReload(*activeWeapon); + } + + return OnInputCommand(*activeWeapon, e); + } + + boost::optional getWeaponComponent(EntityWrapper player) + { + if (!player.HasComponent(m_ComponentType)) { + return boost::none; + } + + return player[m_ComponentType]; + } + + boost::optional getActiveWeapon(EntityWrapper player) + { + auto it = m_ActiveWeapons.find(player); + if (it == m_ActiveWeapons.end()) { + return boost::none; + } + WeaponInfo& activeWeapon = it->second; + + if (!activeWeapon.FirstPersonEntity.Valid() && !activeWeapon.ThirdPersonEntity.Valid()) { + return boost::none; + } + + return activeWeapon; + } + + void selectWeapon(EntityWrapper player) + { + // Find the weapon attachments matching the weapon type + std::vector weaponAttachments = player.ChildrenWithComponent("WeaponAttachment"); + EntityWrapper firstPersonAttachment; + EntityWrapper thirdPersonAttachment; + for (auto& attachment : weaponAttachments) { + ComponentWrapper cWeaponAttachment = attachment["WeaponAttachment"]; + if ((std::string&)cWeaponAttachment["Weapon"] == m_ComponentType) { + ComponentWrapper::SubscriptProxy person = cWeaponAttachment["Person"]; + if ((ComponentInfo::EnumType)person == person.Enum("FirstPerson")) { + firstPersonAttachment = attachment; + } else if ((ComponentInfo::EnumType)person == person.Enum("ThirdPerson")) { + thirdPersonAttachment = attachment; + } + } + } + + if (!firstPersonAttachment.Valid() && !thirdPersonAttachment.Valid()) { + LOG_WARNING("No weapon attachment found for %s of player #%i", m_ComponentType.c_str(), player.ID); + return; + } + + // Purge other weapon entities + for (auto& attachment : weaponAttachments) { + //if (attachment == firstPersonAttachment || attachment == thirdPersonAttachment) { + // continue; + //} + attachment.DeleteChildren(); + } + + // Spawn the weapon(s) + EntityWrapper firstPersonWeapon; + EntityWrapper thirdPersonWeapon; + if (firstPersonAttachment.Valid()) { + firstPersonWeapon = SpawnerSystem::Spawn(firstPersonAttachment, firstPersonAttachment); + } + if (thirdPersonAttachment.Valid()) { + thirdPersonWeapon = SpawnerSystem::Spawn(thirdPersonAttachment, thirdPersonAttachment); + } + + m_ActiveWeapons[player].WeaponComponent = m_ComponentType; + m_ActiveWeapons[player].Player = player; + m_ActiveWeapons[player].WeaponEntity = player; + m_ActiveWeapons[player].FirstPersonEntity = firstPersonWeapon; + m_ActiveWeapons[player].ThirdPersonEntity = thirdPersonWeapon; + } }; #endif diff --git a/resources/Schema/Components.xsd b/resources/Schema/Components.xsd index 42abed82..cad50c7e 100644 --- a/resources/Schema/Components.xsd +++ b/resources/Schema/Components.xsd @@ -46,4 +46,6 @@ + + \ No newline at end of file diff --git a/resources/Schema/Components/AssaultWeapon.xml b/resources/Schema/Components/AssaultWeapon.xml index 6c645624..c835217b 100755 --- a/resources/Schema/Components/AssaultWeapon.xml +++ b/resources/Schema/Components/AssaultWeapon.xml @@ -8,4 +8,5 @@ 120 0.01 2 + \ No newline at end of file diff --git a/resources/Schema/Components/AssaultWeapon.xsd b/resources/Schema/Components/AssaultWeapon.xsd index 95df64b7..7e9854a2 100755 --- a/resources/Schema/Components/AssaultWeapon.xsd +++ b/resources/Schema/Components/AssaultWeapon.xsd @@ -2,6 +2,7 @@ + @@ -28,6 +29,7 @@ Time it takes to reload the weapon in seconds + diff --git a/resources/Schema/Components/DefenderWeapon.xml b/resources/Schema/Components/DefenderWeapon.xml new file mode 100755 index 00000000..998f3bde --- /dev/null +++ b/resources/Schema/Components/DefenderWeapon.xml @@ -0,0 +1,16 @@ + + + 8 + 8 + 64 + 64 + 90 + 0.174533 + 10 + 120 + 0.01 + 0.5 + + false + 0 + \ No newline at end of file diff --git a/resources/Schema/Components/DefenderWeapon.xsd b/resources/Schema/Components/DefenderWeapon.xsd new file mode 100755 index 00000000..3fe5a64a --- /dev/null +++ b/resources/Schema/Components/DefenderWeapon.xsd @@ -0,0 +1,44 @@ + + + + + + + + + + + Ammo currently loaded into the magazine + + + Max number of rounds in a magazine + + + Current ammo carried + + + Maximum ammo able to be carried + + + Damage dealt if all shotgun pellets hit + + + Spread angle in radians + + + + Rate of fire in rounds per minute + + + View punch in radians for each shell fired + + + Time it takes to load ONE SHELL into the weapon in seconds + + + + + + + + diff --git a/resources/Schema/Components/Player.xml b/resources/Schema/Components/Player.xml index 00cff257..1aaeff25 100644 --- a/resources/Schema/Components/Player.xml +++ b/resources/Schema/Components/Player.xml @@ -3,4 +3,5 @@ 3 1.5 + \ No newline at end of file diff --git a/resources/Schema/Components/Player.xsd b/resources/Schema/Components/Player.xsd index 1b33d222..ebaed462 100644 --- a/resources/Schema/Components/Player.xsd +++ b/resources/Schema/Components/Player.xsd @@ -12,6 +12,7 @@ + diff --git a/resources/Schema/Components/Weapon.xml b/resources/Schema/Components/Weapon.xml deleted file mode 100644 index 38c6fce9..00000000 --- a/resources/Schema/Components/Weapon.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/resources/Schema/Components/Weapon.xsd b/resources/Schema/Components/Weapon.xsd deleted file mode 100644 index 8bddd8a9..00000000 --- a/resources/Schema/Components/Weapon.xsd +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/resources/Schema/Components/WeaponAttachment.xml b/resources/Schema/Components/WeaponAttachment.xml new file mode 100644 index 00000000..8867b2b7 --- /dev/null +++ b/resources/Schema/Components/WeaponAttachment.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/resources/Schema/Components/WeaponAttachment.xsd b/resources/Schema/Components/WeaponAttachment.xsd new file mode 100644 index 00000000..3b1291ae --- /dev/null +++ b/resources/Schema/Components/WeaponAttachment.xsd @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + Combine with a spawner to define a weapon attachment point + + + + The weapon component type this attachment refers to + + + + + + \ No newline at end of file diff --git a/resources/Schema/Entities/AssaultWeaponView.xml b/resources/Schema/Entities/AssaultWeaponView.xml new file mode 100755 index 00000000..4b985fbb --- /dev/null +++ b/resources/Schema/Entities/AssaultWeaponView.xml @@ -0,0 +1,99 @@ + + + + + + R_Arm_Weapon_Joint + + + Models/Weapons/Blue/AssaultWeaponBlue.mesh + + + + + + + + + + + + Schema/Entities/RayBlue.xml + + + + + + + + + + + Schema/Entities/ReloadEffectView.xml + + + + + + + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + + + + + + + + 32 + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + 360 + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/AssaultWeaponWorld.xml b/resources/Schema/Entities/AssaultWeaponWorld.xml new file mode 100755 index 00000000..6fcb97b3 --- /dev/null +++ b/resources/Schema/Entities/AssaultWeaponWorld.xml @@ -0,0 +1,40 @@ + + + + + + R_Arm_Weapon_Joint + + + Models/Weapons/Blue/AssaultWeaponBlue.mesh + + + + + + + + + + + + Schema/Entities/RayBlue.xml + + + + + + + + + + + Schema/Entities/ReloadEffectWorld.xml + + + + + + + + diff --git a/resources/Schema/Entities/DefenderShield.xml b/resources/Schema/Entities/DefenderShield.xml new file mode 100755 index 00000000..da760e72 --- /dev/null +++ b/resources/Schema/Entities/DefenderShield.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + Models/Core/UnitPlane.mesh + + + + + + + + + + + + + + Models/Core/UnitHexagon.mesh + + true + + + + + + + + + + + + diff --git a/resources/Schema/Entities/DefenderWeaponView.xml b/resources/Schema/Entities/DefenderWeaponView.xml new file mode 100755 index 00000000..f6b6e89d --- /dev/null +++ b/resources/Schema/Entities/DefenderWeaponView.xml @@ -0,0 +1,99 @@ + + + + + + R_Arm_Weapon_Joint + + + + Models/Weapons/Blue/DefenderGunBlue.mesh + + + + + + + + + + + Schema/Entities/RayBlue.xml + + + + + + + + + + + Schema/Entities/ReloadEffectView.xml + + + + + + + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + + + + + + + + 32 + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + 360 + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/DefenderWeaponViewRed.xml b/resources/Schema/Entities/DefenderWeaponViewRed.xml new file mode 100755 index 00000000..b5b1c322 --- /dev/null +++ b/resources/Schema/Entities/DefenderWeaponViewRed.xml @@ -0,0 +1,99 @@ + + + + + + R_Arm_Weapon_Joint + + + + Models/Weapons/Red/DefenderGunRed.mesh + + + + + + + + + + + Schema/Entities/RayRed.xml + + + + + + + + + + + Schema/Entities/ReloadEffectView.xml + + + + + + + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + + + + + + + + 32 + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + 360 + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/DefenderWeaponWorld.xml b/resources/Schema/Entities/DefenderWeaponWorld.xml new file mode 100755 index 00000000..826301b4 --- /dev/null +++ b/resources/Schema/Entities/DefenderWeaponWorld.xml @@ -0,0 +1,41 @@ + + + + + + R_Arm_Weapon_Joint + + + + Models/Weapons/Blue/DefenderGunBlue.mesh + + + + + + + + + + + + Schema/Entities/RayBlue.xml + + + + + + + + + + + Schema/Entities/ReloadEffectWorld.xml + + + + + + + + diff --git a/resources/Schema/Entities/DefenderWeaponWorldRed.xml b/resources/Schema/Entities/DefenderWeaponWorldRed.xml new file mode 100755 index 00000000..7f697304 --- /dev/null +++ b/resources/Schema/Entities/DefenderWeaponWorldRed.xml @@ -0,0 +1,41 @@ + + + + + + R_Arm_Weapon_Joint + + + + Models/Weapons/Red/DefenderGunRed.mesh + + + + + + + + + + + + Schema/Entities/RayRed.xml + + + + + + + + + + + Schema/Entities/ReloadEffectWorld.xml + + + + + + + + diff --git a/resources/Schema/Entities/MovementTest.xml b/resources/Schema/Entities/MovementTest.xml index 84aaa03a..41474568 100644 --- a/resources/Schema/Entities/MovementTest.xml +++ b/resources/Schema/Entities/MovementTest.xml @@ -10,7 +10,7 @@ - Schema/Entities/Player.xml + Schema/Entities/PlayerRed.xml @@ -118,257 +118,6 @@ - - - - - - - - 600 - - - - - - - - - 5 - - - - - - - - - - - - - - - - - - - - - - - Fonts/DroidSans.ttf,100 - - - - - - - - - - - - - - Models/Widgets/Camera.mesh - false - - - - - - - - - - - - - - - - - - - 1 - - - - - Models/Core/UnitHexagon.mesh - - - - - - - - - - - - - - Textures/Weapons/Crosshair/SmallThickHoleDot.png - false - - - - - - - - - - - - - - Idle - 1.9569972344146196 - 1 - - - Models/Characters/Assault/FirstPerson.mesh - true - - - - - - - - R_Arm_Weapon_Joint - - - Models/Weapons/Blue/AssaultWeaponBlue.mesh - true - - - - - - - - - - - Schema/Entities/RayBlue.xml - - - - - - - - - - - - - Schema/Entities/WeaponReloadEffect.xml - - - - - - - - - - - - - - Models/Widgets/Camera.mesh - false - - - - - - - - - - - - Idle - 1.8055945618467364 - 1 - - - AimRifle - - - - - Models/Characters/Assault/AssaultAnimations.mesh - - - - - - - - - R_Arm_Weapon_Joint - - - Models/Weapons/Blue/AssaultWeaponBlue.mesh - false - - - - - - - - - - - Schema/Entities/RayBlue.xml - - - - - - - - - - - - - - - Models/Core/UnitCube.mesh - - false - - - - - - - - - - - - Models/Core/UnitCube.mesh - - false - - - - - - - - - diff --git a/resources/Schema/Entities/Player.xml b/resources/Schema/Entities/Player.xml index 4f012955..7976fe2b 100644 --- a/resources/Schema/Entities/Player.xml +++ b/resources/Schema/Entities/Player.xml @@ -7,23 +7,30 @@ - 600 + + + - + + 1.6944730461160304 + 5 + - + + + @@ -303,7 +310,8 @@ - + + @@ -363,7 +371,7 @@ Idle - 0.97725610639912475 + 0.67172915251515519 1 @@ -375,100 +383,29 @@ - + - - R_Arm_Weapon_Joint - - - Models/Weapons/Blue/AssaultWeaponBlue.mesh - - - - - + + Schema/Entities/DefenderWeaponView.xml + + + + DefenderWeapon + - - - - - Schema/Entities/RayBlue.xml - - - - - - - - - - - Schema/Entities/ReloadEffectView.xml - - - - - - - - - - - - - - - - - - Textures/Core/UnitHexagon.png - - - - - - - - - - - - - - - - - - - 32 - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - 360 - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - - - + + + + + + Schema/Entities/AssaultWeaponView.xml + + + + AssaultWeapon + + + @@ -492,7 +429,6 @@ Idle - 0.87583812735846323 1 @@ -501,6 +437,7 @@ AimRifle + Models/Characters/Assault/AssaultAnimations.mesh @@ -509,41 +446,35 @@ - + - - R_Arm_Weapon_Joint - - - Models/Weapons/Blue/AssaultWeaponBlue.mesh - - - - - + + Schema/Entities/DefenderWeaponWorld.xml + + + + DefenderWeapon + + + + - - - - - Schema/Entities/RayBlue.xml - - - - - - - - - - - Schema/Entities/ReloadEffectWorld.xml - - - - - - + + + + + + Schema/Entities/AssaultWeaponWorld.xml + + + + AssaultWeapon + + + + + + @@ -609,6 +540,17 @@ + + + + Schema/Entities/DefenderShield.xml + + + + + + + diff --git a/resources/Schema/Entities/PlayerRed.xml b/resources/Schema/Entities/PlayerRed.xml old mode 100644 new mode 100755 index d56fa3c1..69116f21 --- a/resources/Schema/Entities/PlayerRed.xml +++ b/resources/Schema/Entities/PlayerRed.xml @@ -7,23 +7,30 @@ - 600 + + + - + + 1.6944730461160304 + 5 + - + + + @@ -364,7 +371,7 @@ Idle - 1.2667383999985162 + 0.67172915251515519 1 @@ -376,100 +383,29 @@ - + - - R_Arm_Weapon_Joint - - - Models/Weapons/Red/AssaultWeaponRed.mesh - - - - - + + Schema/Entities/DefenderWeaponViewRed.xml + + + + DefenderWeapon + - - - - - Schema/Entities/RayRed.xml - - - - - - - - - - - Schema/Entities/ReloadEffectViewRed.xml - - - - - - - - - - - - - - - - - - Textures/Core/UnitHexagon.png - - - - - - - - - - - - - - - - - - - 32 - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - 360 - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - - - + + + + + + Schema/Entities/AssaultWeaponView.xml + + + + AssaultWeapon + + + @@ -493,7 +429,6 @@ Idle - 0.26532318661337229 1 @@ -502,6 +437,7 @@ AimRifle + Models/Characters/Assault/AssaultAnimations.mesh @@ -510,41 +446,35 @@ - + - - R_Arm_Weapon_Joint - - - Models/Weapons/Red/AssaultWeaponRed.mesh - - - - - + + Schema/Entities/DefenderWeaponWorldRed.xml + + + + DefenderWeapon + + + + - - - - - Schema/Entities/RayRed.xml - - - - - - - - - - - Schema/Entities/ReloadEffectWorldRed.xml - - - - - - + + + + + + Schema/Entities/AssaultWeaponWorld.xml + + + + AssaultWeapon + + + + + + @@ -583,20 +513,20 @@ - + - + Textures/Icons/Arrow.png false - + @@ -604,12 +534,23 @@ true - + + + + + Schema/Entities/DefenderShield.xml + + + + + + + diff --git a/resources/Schema/Types/Entity.xsd b/resources/Schema/Types/Entity.xsd index a9c5f641..0965ef89 100644 --- a/resources/Schema/Types/Entity.xsd +++ b/resources/Schema/Types/Entity.xsd @@ -50,6 +50,8 @@ + + diff --git a/resources/Schema/Types/WeaponSlotEnum.xsd b/resources/Schema/Types/WeaponSlotEnum.xsd new file mode 100644 index 00000000..6713ca9d --- /dev/null +++ b/resources/Schema/Types/WeaponSlotEnum.xsd @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Engine/Core/EntityWrapper.cpp b/src/Engine/Core/EntityWrapper.cpp index ace1f4a7..b3bef55a 100644 --- a/src/Engine/Core/EntityWrapper.cpp +++ b/src/Engine/Core/EntityWrapper.cpp @@ -62,6 +62,29 @@ EntityWrapper EntityWrapper::Clone(EntityWrapper parent /*= Invalid*/) return clone; } +std::vector EntityWrapper::ChildrenWithComponent(const std::string& componentType) +{ + std::vector childrenWithComponent; + childrenWithComponentRecursive(componentType, *this, childrenWithComponent); + return childrenWithComponent; +} + +void EntityWrapper::DeleteChildren() +{ + auto itPair = this->World->GetDirectChildren(this->ID); + if (itPair.first == itPair.second) { + return; + } + + std::vector entitiesToDelete; + for (auto it = itPair.first; it != itPair.second; it++) { + entitiesToDelete.push_back(it->second); + } + for (auto& e : entitiesToDelete) { + this->World->DeleteEntity(e); + } +} + bool EntityWrapper::IsChildOf(EntityWrapper potentialParent) { EntityWrapper entity = *this; @@ -101,6 +124,11 @@ ComponentWrapper EntityWrapper::operator[](const char* componentName) } } +ComponentWrapper EntityWrapper::operator[](const std::string& componentName) +{ + return this->operator[](componentName.c_str()); +} + bool EntityWrapper::operator==(const EntityWrapper& e) const { return (this->ID == e.ID) && (this->World == e.World); @@ -166,3 +194,18 @@ EntityWrapper EntityWrapper::cloneRecursive(EntityWrapper entity, EntityWrapper return clone; } +void EntityWrapper::childrenWithComponentRecursive(const std::string& componentType, EntityWrapper& entity, std::vector& childrenWithComponent) +{ + auto itPair = this->World->GetDirectChildren(entity.ID); + if (itPair.first == itPair.second) { + return; + } + + for (auto it = itPair.first; it != itPair.second; ++it) { + EntityWrapper child = EntityWrapper(entity.World, it->second); + if (child.HasComponent(componentType)) { + childrenWithComponent.push_back(child); + } + childrenWithComponentRecursive(componentType, child, childrenWithComponent); + } +} diff --git a/src/Engine/Core/Util/Logging.cpp b/src/Engine/Core/Util/Logging.cpp index 63a6f380..c7612fd8 100644 --- a/src/Engine/Core/Util/Logging.cpp +++ b/src/Engine/Core/Util/Logging.cpp @@ -33,8 +33,8 @@ void _LOG(_LOG_LEVEL logLevel, const char* file, const char* func, unsigned int va_end(args); if (logLevel == LOG_LEVEL_ERROR) { - std::cerr << file << ":" << line << " " << func << std::endl; - std::cerr << _LOG_LEVEL_PREFIX[logLevel] << message << std::endl; + //std::cerr << file << ":" << line << " " << func << std::endl; + //std::cerr << _LOG_LEVEL_PREFIX[logLevel] << message << std::endl; } else { std::cout << _LOG_LEVEL_PREFIX[logLevel] << message << std::endl; } diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index 24b7cd1e..5388fd04 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -16,7 +16,7 @@ #include "Game/Systems/PickupSpawnSystem.h" #include "Game/Systems/AmmoPickupSystem.h" #include "Game/Systems/DamageIndicatorSystem.h" -#include "Game/Systems/Weapon/WeaponSystem.h" +#include "Game/Systems/Weapon/DefenderWeaponBehaviour.h" #include "Rendering/AnimationSystem.h" #include "Game/Systems/HealthHUDSystem.h" #include "Rendering/BoneAttachmentSystem.h" @@ -98,6 +98,10 @@ Game::Game(int argc, char* argv[]) m_NetworkClient->Connect(m_NetworkAddress, m_NetworkPort); m_Renderer->SetWindowTitle(m_Renderer->WindowTitle() + " CLIENT"); } + } else { + // If network is disabled, pretend we're a server + m_IsClient = true; + m_IsServer = true; } // Create Octrees @@ -120,7 +124,7 @@ Game::Game(int argc, char* argv[]) m_SystemPipeline->AddSystem(updateOrderLevel); m_SystemPipeline->AddSystem(updateOrderLevel); m_SystemPipeline->AddSystem(updateOrderLevel); - m_SystemPipeline->AddSystem(updateOrderLevel, m_Renderer, m_OctreeCollision); + m_SystemPipeline->AddSystem(updateOrderLevel, m_Renderer, m_OctreeCollision); m_SystemPipeline->AddSystem(updateOrderLevel); m_SystemPipeline->AddSystem(updateOrderLevel); m_SystemPipeline->AddSystem(updateOrderLevel); diff --git a/src/Game/Network/MultiplayerSnapshotFilter.cpp b/src/Game/Network/MultiplayerSnapshotFilter.cpp index 69b7f282..295cdd7a 100644 --- a/src/Game/Network/MultiplayerSnapshotFilter.cpp +++ b/src/Game/Network/MultiplayerSnapshotFilter.cpp @@ -13,6 +13,7 @@ bool MultiplayerSnapshotFilter::FilterComponent(EntityWrapper entity, SharedComp component.Info.Name == "Transform" || component.Info.Name == "Physics" || component.Info.Name == "AssaultWeapon" + || component.Info.Name == "DefenderWeapon" || component.Info.Name == "Animation" || component.Info.Name == "AnimationOffset" || entity.Name() == "PlayerName" diff --git a/src/Game/Systems/DamageIndicatorSystem.cpp b/src/Game/Systems/DamageIndicatorSystem.cpp index 92fbe607..ca26052d 100644 --- a/src/Game/Systems/DamageIndicatorSystem.cpp +++ b/src/Game/Systems/DamageIndicatorSystem.cpp @@ -13,7 +13,7 @@ DamageIndicatorSystem::DamageIndicatorSystem(SystemParams params) } void DamageIndicatorSystem::Update(double dt) { - if (!IsServer) { + if (!IsServer && LocalPlayer.Valid()) { for (auto& iter = updateDamageIndicatorVector.begin(); iter != updateDamageIndicatorVector.end(); iter++) { if (!iter->spriteEntity.Valid()) { updateDamageIndicatorVector.erase(iter); diff --git a/src/Game/Systems/Weapon/AssaultWeaponBehaviour.cpp b/src/Game/Systems/Weapon/AssaultWeaponBehaviour.cpp_ similarity index 87% rename from src/Game/Systems/Weapon/AssaultWeaponBehaviour.cpp rename to src/Game/Systems/Weapon/AssaultWeaponBehaviour.cpp_ index 84d3ccd4..c3b3385f 100644 --- a/src/Game/Systems/Weapon/AssaultWeaponBehaviour.cpp +++ b/src/Game/Systems/Weapon/AssaultWeaponBehaviour.cpp_ @@ -1,13 +1,5 @@ #include "Systems/Weapon/AssaultWeaponBehaviour.h" -AssaultWeaponBehaviour::AssaultWeaponBehaviour(SystemParams systemParams, IRenderer* renderer, Octree* collisionOctree, EntityWrapper player) - : WeaponBehaviour(systemParams, renderer, collisionOctree, player) -{ - m_FirstPersonModel = m_Player.FirstChildByName("Hands"); - m_ThirdPersonModel = m_Player.FirstChildByName("PlayerModel"); - EVENT_SUBSCRIBE_MEMBER(m_EAnimationComplete, &AssaultWeaponBehaviour::OnAnimationComplete); -} - void AssaultWeaponBehaviour::Fire() { m_TimeSinceLastFire = 0.0; @@ -36,7 +28,7 @@ void AssaultWeaponBehaviour::Reload() return; } - // Don't reload if we're completly out of ammo + // Don't reload if we're completely out of ammo if (ammo == 0) { playEmptySound(); m_TimeSinceLastFire = -0.0f; // HACK: To make empty sound play with interval @@ -56,14 +48,14 @@ void AssaultWeaponBehaviour::Update(double dt) { if (m_Reloading) { m_ReloadTimer -= dt; - // Re-enable glow on reload impersonator half-way through the animation + // Re-enable glow on reload impostor half-way through the animation if (IsClient) { if (m_ReloadTimer <= (double)m_Player["AssaultWeapon"]["ReloadTime"] / 2.0) { - if (m_FirstPersonReloadImpersonator.Valid()) { - m_FirstPersonReloadImpersonator["Model"]["GlowMap"] = true; + if (m_FirstPersonReloadImpostor.Valid()) { + m_FirstPersonReloadImpostor["Model"]["GlowMap"] = true; } - if (m_ThirdPersonReloadImpersonator.Valid()) { - m_ThirdPersonReloadImpersonator["Model"]["GlowMap"] = true; + if (m_ThirdPersonReloadImpostor.Valid()) { + m_ThirdPersonReloadImpostor["Model"]["GlowMap"] = true; } } } @@ -96,21 +88,6 @@ void AssaultWeaponBehaviour::Update(double dt) } } -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"]; @@ -177,7 +154,6 @@ void AssaultWeaponBehaviour::spawnTracer() 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); @@ -215,6 +191,12 @@ void AssaultWeaponBehaviour::playEmptySound() void AssaultWeaponBehaviour::viewPunch() { + // Since we send absolute client orientations to server, running this server side would + // cause aim desync. + if (!IsClient) { + return; + } + EntityWrapper playerCamera = m_Player.FirstChildByName("Camera"); if (!playerCamera.Valid()) { return; @@ -323,8 +305,8 @@ void AssaultWeaponBehaviour::playReloadAnimation() EntityWrapper firstPersonWeaponModel = m_Player.FirstChildByName("WeaponModel"); EntityWrapper reloadSpawner = m_Player.FirstChildByName("FirstPersonReloadSpawner"); if (IsClient) { - m_FirstPersonReloadImpersonator = SpawnerSystem::Spawn(reloadSpawner, reloadSpawner); - firstPersonWeaponModel["Model"].Copy(m_FirstPersonReloadImpersonator["Model"]); + m_FirstPersonReloadImpostor = SpawnerSystem::Spawn(reloadSpawner, reloadSpawner); + firstPersonWeaponModel["Model"].Copy(m_FirstPersonReloadImpostor["Model"]); } firstPersonWeaponModel["Model"]["Visible"] = false; } @@ -332,8 +314,8 @@ void AssaultWeaponBehaviour::playReloadAnimation() EntityWrapper thirdPersonWeaponModel = m_Player.FirstChildByName("ThirdPersonWeaponModel"); EntityWrapper reloadSpawner = m_Player.FirstChildByName("ThirdPersonReloadSpawner"); if (IsClient) { - m_ThirdPersonReloadImpersonator = SpawnerSystem::Spawn(reloadSpawner, reloadSpawner); - thirdPersonWeaponModel["Model"].Copy(m_ThirdPersonReloadImpersonator["Model"]); + m_ThirdPersonReloadImpostor = SpawnerSystem::Spawn(reloadSpawner, reloadSpawner); + thirdPersonWeaponModel["Model"].Copy(m_ThirdPersonReloadImpostor["Model"]); } thirdPersonWeaponModel["Model"]["Visible"] = false; } @@ -371,7 +353,7 @@ bool AssaultWeaponBehaviour::shoot(double damage) return false; } - // Don't let us shoot ourselves in the foot + // Don't let us shoot ourselves in the foot somehow if (victim == LocalPlayer) { return false; } diff --git a/src/Game/Systems/Weapon/DefenderWeaponBehaviour.cpp b/src/Game/Systems/Weapon/DefenderWeaponBehaviour.cpp new file mode 100644 index 00000000..028bd10c --- /dev/null +++ b/src/Game/Systems/Weapon/DefenderWeaponBehaviour.cpp @@ -0,0 +1,188 @@ +#include "Systems/Weapon/DefenderWeaponBehaviour.h" + +void DefenderWeaponBehaviour::UpdateComponent(EntityWrapper& entity, ComponentWrapper& cWeapon, double dt) +{ + (double&)cWeapon["TimeSinceLastFire"] += dt; + WeaponBehaviour::UpdateComponent(entity, cWeapon, dt); +} + +void DefenderWeaponBehaviour::UpdateWeapon(WeaponInfo& wi, double dt) +{ + ComponentWrapper cWeapon = wi.GetComponent(); + + bool isFiring = cWeapon["IsFiring"]; + bool cooldownPassed = (double)cWeapon["TimeSinceLastFire"] >= (60.0 / (double)cWeapon["RPM"]); + bool isNotShielding = wi.Player.ChildrenWithComponent("Shield").size() == 0; + if (isFiring && cooldownPassed && isNotShielding) { + fireShell(wi); + } +} + +void DefenderWeaponBehaviour::OnPrimaryFire(WeaponInfo& wi) +{ + ComponentWrapper cWeapon = wi.GetComponent(); + cWeapon["IsFiring"] = true; + bool cooldownPassed = (double)cWeapon["TimeSinceLastFire"] >= (60.0 / (double)cWeapon["RPM"]); + bool isNotShielding = wi.Player.ChildrenWithComponent("Shield").size() == 0; + if (cooldownPassed && isNotShielding) { + fireShell(wi); + } +} + +void DefenderWeaponBehaviour::OnCeasePrimaryFire(WeaponInfo& wi) +{ + ComponentWrapper cWeapon = wi.GetComponent(); + cWeapon["IsFiring"] = false; +} + +bool DefenderWeaponBehaviour::OnInputCommand(WeaponInfo& wi, const Events::InputCommand& e) +{ + if (e.Command == "SpecialAbility" && IsServer) { + EntityWrapper attachment = wi.Player.FirstChildByName("ShieldAttachment"); + if (attachment.Valid()) { + if (e.Value > 0) { + SpawnerSystem::Spawn(attachment, attachment); + } else { + attachment.DeleteChildren(); + } + } + } + + return false; +} + +bool DefenderWeaponBehaviour::OnSetCamera(const Events::SetCamera& e) +{ + m_CurrentCamera = e.CameraEntity; + return true; +} + +void DefenderWeaponBehaviour::fireShell(WeaponInfo& wi) +{ + ComponentWrapper cWeapon = wi.GetComponent(); + + cWeapon["TimeSinceLastFire"] = 0.0; + int numPellets = cWeapon["NumPellets"]; + float spreadAngle = cWeapon["SpreadAngle"]; + std::uniform_real_distribution randomSpreadAngle(-spreadAngle, spreadAngle); + + // Calculate pellet angles + // HACK: Random for now? + // TODO: Make distribution even for each quadrant + std::vector pelletAngles; + for (int i = 0; i < numPellets; i++) { + pelletAngles.push_back(glm::vec2(randomSpreadAngle(m_RandomEngine), randomSpreadAngle(m_RandomEngine))); + LOG_DEBUG("%f %f", pelletAngles[i].x, pelletAngles[i].y); + } + + double pelletDamage = (double)cWeapon["BaseDamage"] / numPellets; + + // Tracers + EntityWrapper weaponModelEntity; + if (wi.Player == LocalPlayer) { + weaponModelEntity = wi.FirstPersonEntity; + } else { + weaponModelEntity = wi.ThirdPersonEntity; + } + if (weaponModelEntity.Valid()) { + EntityWrapper spawner = weaponModelEntity.FirstChildByName("WeaponMuzzle"); + for (auto& angles : pelletAngles) { + glm::vec3 direction = Transform::AbsoluteOrientation(spawner) * glm::quat(glm::vec3(angles, 0.f)) * glm::vec3(0, 0, -1); + float distance = traceRayDistance(Transform::AbsolutePosition(spawner), direction); + EntityWrapper ray = SpawnerSystem::Spawn(spawner); + ((glm::vec3&)ray["Transform"]["Scale"]).z = (distance / 100.f); + glm::vec3& orientation = ray["Transform"]["Orientation"]; + orientation.x += angles.x; + orientation.y += angles.y; + glm::vec3 trajectory = direction * distance; + dealDamage(wi, direction, pelletDamage); + } + } + +} + +void DefenderWeaponBehaviour::dealDamage(WeaponInfo& wi, glm::vec3 direction, double damage) +{ + // Only deal damage client side + if (!IsClient) { + return; + } + + // Only handle shooting for the local player + if (wi.Player != LocalPlayer) { + return; + } + + // Make sure the player isn't shooting from the grave + if (!wi.Player.Valid()) { + return; + } + + glm::vec3 maxRange = direction * 2.f; + EntityWrapper camera = wi.Player.FirstChildByName("Camera"); + glm::vec3 cameraPosition = Transform::AbsolutePosition(camera); + if (!camera.Valid()) { + return; + } + Rectangle screenResolution = m_Renderer->GetViewportSize(); + glm::vec2 centerScreen = glm::vec2(screenResolution.Width / 2, screenResolution.Height / 2); + glm::vec2 screenCoords = cameraFromEntity(m_CurrentCamera).WorldToScreen(cameraPosition + maxRange, m_Renderer->GetViewportSize()); + PickData pickData = m_Renderer->Pick(centerScreen + screenCoords); + EntityWrapper victim(m_World, pickData.Entity); + if (!victim.Valid()) { + return; + } + + // Don't let us shoot ourselves in the foot somehow + if (victim == LocalPlayer) { + return; + } + + // Only care about players being hit + if (!victim.HasComponent("Player")) { + victim = victim.FirstParentWithComponent("Player"); + } + if (!victim.Valid()) { + return; + } + + // Check for friendly fire + if ((ComponentInfo::EnumType)victim["Team"]["Team"] == (ComponentInfo::EnumType)wi.Player["Team"]["Team"]) { + return; + } + + // Deal damage! + Events::PlayerDamage ePlayerDamage; + ePlayerDamage.Inflictor = wi.Player; + ePlayerDamage.Victim = victim; + ePlayerDamage.Damage = damage; + m_EventBroker->Publish(ePlayerDamage); + LOG_DEBUG("Damage: %f", damage); +} + +float DefenderWeaponBehaviour::traceRayDistance(glm::vec3 origin, glm::vec3 direction) +{ + float distance; + glm::vec3 pos; + auto entity = Collision::EntityFirstHitByRay(Ray(origin, direction), m_CollisionOctree, distance, pos); + if (entity) { + return distance; + } else { + return 100.f; + } +} + +Camera DefenderWeaponBehaviour::cameraFromEntity(EntityWrapper camera) +{ + ComponentWrapper cTransform = camera["Transform"]; + ComponentWrapper cCamera = camera["Camera"]; + Camera cam( + (float)m_Renderer->Resolution().Width / m_Renderer->Resolution().Height, + (double)cCamera["FOV"], + (double)cCamera["NearClip"], + (double)cCamera["FarClip"] + ); + cam.SetPosition(cTransform["Position"]); + cam.SetOrientation(glm::quat((const glm::vec3&)cTransform["Orientation"])); + return cam; +} diff --git a/src/Game/Systems/Weapon/WeaponSystem.cpp b/src/Game/Systems/Weapon/WeaponSystem.cpp_ similarity index 56% rename from src/Game/Systems/Weapon/WeaponSystem.cpp rename to src/Game/Systems/Weapon/WeaponSystem.cpp_ index 3a49ae90..d33c5098 100644 --- a/src/Game/Systems/Weapon/WeaponSystem.cpp +++ b/src/Game/Systems/Weapon/WeaponSystem.cpp_ @@ -13,7 +13,7 @@ WeaponSystem::WeaponSystem(SystemParams params, IRenderer* renderer, Octree weaponAttachments = player.ChildrenWithComponent("WeaponAttachment"); + + // Find the weapon attachments matching the slot selected + EntityWrapper firstPersonAttachment; + EntityWrapper thirdPersonAttachment; + for (auto& attachment : weaponAttachments) { + ComponentWrapper cWeaponAttachment = attachment["WeaponAttachment"]; + if ((ComponentInfo::EnumType)cWeaponAttachment["Slot"] == slot) { + ComponentWrapper::SubscriptProxy person = cWeaponAttachment["Person"]; + if (person == person.Enum("FirstPerson")) { + firstPersonAttachment = attachment; + } else if (person == person.Enum("ThirdPerson")) { + thirdPersonAttachment = attachment; + } + } + } + + if (firstPersonAttachment.Valid() && thirdPersonAttachment.Valid()) { + LOG_WARNING("No weapon attachment found for slot %i of player #%i", slot, player.ID); + return; + } + + // TODO: Delete old weapons + + // Spawn the weapon(s) + EntityWrapper firstPersonWeapon; + EntityWrapper thirdPersonWeapon; + if (firstPersonAttachment.Valid()) { + firstPersonWeapon = SpawnerSystem::Spawn(firstPersonAttachment, firstPersonAttachment); + } + if (thirdPersonAttachment.Valid()) { + firstPersonWeapon = SpawnerSystem::Spawn(thirdPersonAttachment, thirdPersonAttachment); + } + + // Create the correct behaviour + if (firstPersonWeapon.Valid()) { + if (firstPersonWeapon.HasComponent("AssaultWeapon") { + + } + } + // Primary if (slot == 1) { // TODO: if class... - if (m_ActiveWeapons.count(player) == 0) { - m_ActiveWeapons.insert(std::make_pair(player, std::make_shared(m_SystemParams, m_Renderer, m_CollisionOctree, player))); - } else { - //m_ActiveWeapons.erase(player); - } + nextBehaviour = std::make_shared(m_SystemParams, m_Renderer, m_CollisionOctree, player); } // Secondary if (slot == 2) { //m_ActiveWeapons[player] = std::make_shared(); } + + if (nextBehaviour != nullptr) { + // TODO: Destroy previous behaviour and make new + if (m_ActiveWeapons.count(player) == 0) { + m_ActiveWeapons[player] = nextBehaviour; + } + } } bool WeaponSystem::OnPlayerSpawned(Events::PlayerSpawned& e)