diff --git a/include/Game/Systems/Weapon/AssaultWeaponBehaviour.h b/include/Game/Systems/Weapon/AssaultWeaponBehaviour.h index 993dd060..7244d443 100644 --- a/include/Game/Systems/Weapon/AssaultWeaponBehaviour.h +++ b/include/Game/Systems/Weapon/AssaultWeaponBehaviour.h @@ -1,47 +1,40 @@ #ifndef AssaultWeaponBehaviour_h__ #define AssaultWeaponBehaviour_h__ -#include "Sound/EPlaySoundOnEntity.h" -#include "Collision/Collision.h" -#include "Core/ConfigFile.h" #include "WeaponBehaviour.h" -#include "../SpawnerSystem.h" +#include "Collision/Collision.h" #include "Core/EPlayerDamage.h" -#include "Core/EShoot.h" +#include "Sound/EPlaySoundOnEntity.h" class AssaultWeaponBehaviour : public WeaponBehaviour { public: AssaultWeaponBehaviour(SystemParams systemParams, IRenderer* renderer, Octree* collisionOctree) - : WeaponBehaviour(systemParams, "AssaultWeapon", renderer, collisionOctree) + : System(systemParams) + , WeaponBehaviour(systemParams, "AssaultWeapon", renderer, collisionOctree) + , m_RandomEngine(m_RandomDevice()) { } -protected: - virtual void OnPrimaryFire(WeaponInfo& wi) override; - virtual void OnCeasePrimaryFire(WeaponInfo& wi) override; - virtual void OnReload(WeaponInfo& wi) override; + void UpdateComponent(EntityWrapper& entity, ComponentWrapper& cWeapon, double dt) override; + void UpdateWeapon(ComponentWrapper cWeapon, WeaponInfo& wi, double dt) override; + void OnPrimaryFire(ComponentWrapper cWeapon, WeaponInfo& wi) override; + void OnCeasePrimaryFire(ComponentWrapper cWeapon, WeaponInfo& wi) override; + void OnReload(ComponentWrapper cWeapon, WeaponInfo& wi) override; + void OnHolster(ComponentWrapper cWeapon, WeaponInfo& wi) override; + //bool OnInputCommand(ComponentWrapper cWeapon, WeaponInfo& wi, const Events::InputCommand& e) override; private: - // State - bool m_Firing = false; - bool m_Reloading = false; - double m_ReloadTimer = 0.0; - double m_TimeSinceLastFire = 0.0; - EntityWrapper m_FirstPersonReloadImpostor; + std::random_device m_RandomDevice; + std::mt19937 m_RandomEngine; - bool hasAmmo(); - void fireRound(); - void spawnTracer(); - float traceRayDistance(glm::vec3 origin, glm::vec3 direction); - void playFireSound(); - void playEmptySound(); - void viewPunch(); - void finishReload(); - void playShootAnimation(); - void playIdleAnimation(); - void playReloadAnimation(); - bool shoot(double damage); - void showHitMarker(); + // Weapon functions + void fireBullet(ComponentWrapper cWeapon, WeaponInfo& wi); + //void dealDamage(ComponentWrapper cWeapon, WeaponInfo& wi, glm::vec3 direction, double damage); + bool canFire(ComponentWrapper cWeapon, WeaponInfo& wi); + bool dealDamage(ComponentWrapper cWeapon, WeaponInfo& wi); + + // Utility + //Camera cameraFromEntity(EntityWrapper camera); }; #endif \ No newline at end of file diff --git a/include/Game/Systems/Weapon/DefenderWeaponBehaviour.h b/include/Game/Systems/Weapon/DefenderWeaponBehaviour.h index 77d579f8..9e7d4991 100644 --- a/include/Game/Systems/Weapon/DefenderWeaponBehaviour.h +++ b/include/Game/Systems/Weapon/DefenderWeaponBehaviour.h @@ -1,3 +1,6 @@ +#ifndef DefenderWeaponBehaviour_h__ +#define DefenderWeaponBehaviour_h__ + #include "WeaponBehaviour.h" #include "Collision/Collision.h" #include "Core/EPlayerDamage.h" @@ -31,4 +34,6 @@ private: // Utility Camera cameraFromEntity(EntityWrapper camera); -}; \ No newline at end of file +}; + +#endif \ No newline at end of file diff --git a/include/Game/Systems/Weapon/SidearmWeaponBehaviour.h b/include/Game/Systems/Weapon/SidearmWeaponBehaviour.h index d221b8bb..10e6105a 100644 --- a/include/Game/Systems/Weapon/SidearmWeaponBehaviour.h +++ b/include/Game/Systems/Weapon/SidearmWeaponBehaviour.h @@ -1,3 +1,6 @@ +#ifndef SidearmWeaponBehaviour_h__ +#define SidearmWeaponBehaviour_h__ + #include "WeaponBehaviour.h" #include "Collision/Collision.h" #include "Core/EPlayerDamage.h" @@ -30,4 +33,6 @@ private: bool canFire(ComponentWrapper cWeapon); bool playerInFirstPerson(EntityWrapper player); //float traceRayDistance(glm::vec3 origin, glm::vec3 direction); -}; \ No newline at end of file +}; + +#endif \ No newline at end of file diff --git a/resources/Schema/Components/AssaultWeapon.xml b/resources/Schema/Components/AssaultWeapon.xml index c835217b..ba74fbb7 100755 --- a/resources/Schema/Components/AssaultWeapon.xml +++ b/resources/Schema/Components/AssaultWeapon.xml @@ -1,12 +1,21 @@ + 32 32 - 360 - 360 - 5 - 120 - 0.01 + 320 + 320 + 15 + 0.174533 + 0.10 + 420 + 0.03 + 0.18 2 - + 0.5 + false + 0 + false + 0 + 0 \ No newline at end of file diff --git a/resources/Schema/Components/AssaultWeapon.xsd b/resources/Schema/Components/AssaultWeapon.xsd index 7e9854a2..a1e745de 100755 --- a/resources/Schema/Components/AssaultWeapon.xsd +++ b/resources/Schema/Components/AssaultWeapon.xsd @@ -7,6 +7,7 @@ + Ammo currently loaded into the magazine @@ -20,16 +21,32 @@ Maximum ammo able to be carried + + Spread angle in radians + + + Maximum vertical aim travel angle in radians + Rate of fire in rounds per minute - View punch in radians for each bullet fired + View punch in radians for each shell fired + + + The speed in radians per second the view returns to its original position after being punched - Time it takes to reload the weapon in seconds + Time it takes to load ONE SHELL into the weapon in seconds - + + Time it takes from selecting the weapon until it's ready to fire + + + + + + diff --git a/resources/Schema/Components/DefenderWeapon.xml b/resources/Schema/Components/DefenderWeapon.xml index 68b87759..b01955bc 100755 --- a/resources/Schema/Components/DefenderWeapon.xml +++ b/resources/Schema/Components/DefenderWeapon.xml @@ -1,5 +1,6 @@ + 8 8 64 @@ -12,7 +13,6 @@ 0.03 0.2 0.5 - false 0 false diff --git a/resources/Schema/Components/DefenderWeapon.xsd b/resources/Schema/Components/DefenderWeapon.xsd index d2b503f8..53200952 100755 --- a/resources/Schema/Components/DefenderWeapon.xsd +++ b/resources/Schema/Components/DefenderWeapon.xsd @@ -19,6 +19,7 @@ + Ammo currently loaded into the magazine @@ -53,7 +54,6 @@ Time it takes to load ONE SHELL into the weapon in seconds - diff --git a/resources/Schema/Components/SidearmWeapon.xml b/resources/Schema/Components/SidearmWeapon.xml index 1d503ecc..bc90c067 100644 --- a/resources/Schema/Components/SidearmWeapon.xml +++ b/resources/Schema/Components/SidearmWeapon.xml @@ -1,5 +1,6 @@ + 16 16 20 @@ -8,7 +9,6 @@ 0.01 0.5 0.5 - false 0 false diff --git a/resources/Schema/Components/SidearmWeapon.xsd b/resources/Schema/Components/SidearmWeapon.xsd index bafb9de2..514bf354 100644 --- a/resources/Schema/Components/SidearmWeapon.xsd +++ b/resources/Schema/Components/SidearmWeapon.xsd @@ -19,6 +19,7 @@ + Ammo currently loaded into the magazine @@ -41,7 +42,6 @@ Time it takes from selecting the weapon until it's ready to fire - diff --git a/resources/Schema/Entities/AssaultWeaponView.xml b/resources/Schema/Entities/AssaultWeaponView.xml index 4b985fbb..b5c87674 100755 --- a/resources/Schema/Entities/AssaultWeaponView.xml +++ b/resources/Schema/Entities/AssaultWeaponView.xml @@ -1,17 +1,11 @@ - + - - R_Arm_Weapon_Joint - Models/Weapons/Blue/AssaultWeaponBlue.mesh - - - - + @@ -21,7 +15,8 @@ Schema/Entities/RayBlue.xml - + + @@ -37,9 +32,8 @@ - - + @@ -70,6 +64,11 @@ Fonts/DroidSans.ttf,64 + + Player + AssaultWeapon + MagazineAmmo + @@ -79,10 +78,15 @@ - 360 + 320 Fonts/DroidSans.ttf,64 + + Player + AssaultWeapon + Ammo + diff --git a/resources/Schema/Entities/AssaultWeaponWorld.xml b/resources/Schema/Entities/AssaultWeaponWorld.xml index 6fcb97b3..9f33c8f2 100755 --- a/resources/Schema/Entities/AssaultWeaponWorld.xml +++ b/resources/Schema/Entities/AssaultWeaponWorld.xml @@ -1,17 +1,11 @@ - + - - R_Arm_Weapon_Joint - Models/Weapons/Blue/AssaultWeaponBlue.mesh - - - - + diff --git a/resources/Schema/Entities/Player.xml b/resources/Schema/Entities/Player.xml index 1ee9d5d3..affe9f79 100644 --- a/resources/Schema/Entities/Player.xml +++ b/resources/Schema/Entities/Player.xml @@ -6,10 +6,14 @@ + + + + + - + - @@ -470,10 +474,10 @@ R_Arm_Weapon_Joint - DefenderWeapon + AssaultWeapon - Schema/Entities/DefenderWeaponView.xml + Schema/Entities/AssaultWeaponView.xml @@ -545,13 +549,13 @@ - DefenderWeapon + AssaultWeapon - Schema/Entities/DefenderWeaponWorld.xml + Schema/Entities/AssaultWeaponWorld.xml diff --git a/resources/Schema/Entities/PlayerAssaultFallbackBlue.xml b/resources/Schema/Entities/PlayerAssaultFallbackBlue.xml new file mode 100644 index 00000000..bb6367f8 --- /dev/null +++ b/resources/Schema/Entities/PlayerAssaultFallbackBlue.xml @@ -0,0 +1,695 @@ + + + + + + + + + + + + + + + + + + 5 + + + + + + + + + + + + + + + + + 0.10000000149011612 + 300 + + + + + + + + + + Models/Widgets/Camera.mesh + false + + + + + + + + + + + + + + + + + + + Textures/Weapons/Crosshair/SmallThickHoleDot.png + + false + + + + + + + + + + + + Schema/Entities/HitMarker.xml + + + + + + + + + + + + + + 1 + + + + + Textures/HealthHUD3.png + + + + + + + + + + + + + + + + + + + + + + + Textures/Core/White.png + + false + + + + + + + + + + + + + + + + Textures/Core/White.png + + false + + + + + + + + + + + + + + + + Textures/Core/White.png + + false + + + + + + + + + + + + + + + + + 1 + + + + 100/100 + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + 2 + + + + + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + 3 + + + + + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + 4 + + + 1 + + + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + 1 + + + + + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + + 1 + + + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + + + + + + + + + + + + + + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + Models/Widgets/Arrows/Arrow5.mesh + + + + + + + + + + + + + + + + + + + + Idle + 1.8348644854054612 + 1 + + + + + Models/Characters/Assault/Test/FirstPerson.mesh + + + + + + + + + R_Arm_Weapon_Joint + + + AssaultWeapon + + + Schema/Entities/AssaultWeaponView.xml + + + + + + + + + + + + R_Arm_Weapon_Joint + + + SidearmWeapon + + + Schema/Entities/SidearmWeaponView.xml + + + + + + + + + + + + + + + + 0.10000000149011612 + 300 + + + Models/Widgets/Camera.mesh + false + + + + + + + + + + + + IdleF + 1 + + + + + AimRifle + + + + + + Models/Characters/Assault/AssaultBlue.mesh + + + + + + + + + R_Arm_Weapon_Joint + + + AssaultWeapon + + + + + + Schema/Entities/AssaultWeaponWorld.xml + + + + + + + + + + + Models/Weapons/Blue/AssaultWeaponBlue.mesh + + + + + + + + Schema/Entities/RayBlue.xml + + + + + + + + + + + Schema/Entities/ReloadEffectWorld.xml + + + + + + + + + + + + + R_Arm_Weapon_Joint + + + SidearmWeapon + + + + + + Schema/Entities/SidearmWeaponWorld.xml + + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + false + + + + + + + + + + + + Models/Core/UnitCube.mesh + + false + + + + + + + + + + + Insert name here + Fonts/DroidSans.ttf,100 + + + + + + + + + + + + + + Textures/Icons/Arrow.png + + false + + + + + 50 + true + + + + + + + + + + + + Schema/Entities/DefenderShield.xml + + + + + + + + + + diff --git a/resources/Schema/Entities/Ray2Red b/resources/Schema/Entities/Ray2Red deleted file mode 100644 index 813443b2..00000000 --- a/resources/Schema/Entities/Ray2Red +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - Textures/Effects/Ray.png - - - - - - - - - - - - diff --git a/resources/Schema/Entities/Ray2Red.xml b/resources/Schema/Entities/Ray2Red.xml deleted file mode 100644 index 6c7c3248..00000000 --- a/resources/Schema/Entities/Ray2Red.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - Textures/Effects/Ray.png - - - - - - - - - - - - - - - Textures/Effects/Ray.png - - - - - - - - - - - - - - diff --git a/resources/Schema/Entities/RayBlue b/resources/Schema/Entities/RayBlue deleted file mode 100644 index d34e185e..00000000 --- a/resources/Schema/Entities/RayBlue +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - Models/Core/UnitCylinder.mesh - - - - - - - - - - - diff --git a/resources/Schema/Entities/RayBlue.xml b/resources/Schema/Entities/RayBlue.xml index 022d7769..0ad0ddf0 100644 --- a/resources/Schema/Entities/RayBlue.xml +++ b/resources/Schema/Entities/RayBlue.xml @@ -1,20 +1,46 @@ - + - 0.25 + 0.10000000149011612 - - Models/Effects/CylinderShot.mesh - - true - - + - + + + + + Textures/Effects/Ray.png + + + + + + + + + + + + + + + Textures/Effects/Ray.png + + + + + + + + + + + + diff --git a/resources/Schema/Entities/RayRed b/resources/Schema/Entities/RayRed deleted file mode 100644 index d34e185e..00000000 --- a/resources/Schema/Entities/RayRed +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - Models/Core/UnitCylinder.mesh - - - - - - - - - - - diff --git a/resources/Schema/Entities/RayRed.xml b/resources/Schema/Entities/RayRed.xml deleted file mode 100644 index 0a20f148..00000000 --- a/resources/Schema/Entities/RayRed.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - 0.25 - - - Models/Effects/CylinderShot.mesh - - true - - - - - - - - - diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index 10107ab1..9ebb28eb 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -18,6 +18,7 @@ #include "Game/Systems/PickupSpawnSystem.h" #include "Game/Systems/AmmoPickupSystem.h" #include "Game/Systems/DamageIndicatorSystem.h" +#include "Game/Systems/Weapon/AssaultWeaponBehaviour.h" #include "Game/Systems/Weapon/DefenderWeaponBehaviour.h" #include "Game/Systems/Weapon/SidearmWeaponBehaviour.h" #include "Rendering/AnimationSystem.h" @@ -128,6 +129,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_Renderer, m_OctreeCollision); m_SystemPipeline->AddSystem(updateOrderLevel); diff --git a/src/Game/Systems/Weapon/AssaultWeaponBehaviour.cpp b/src/Game/Systems/Weapon/AssaultWeaponBehaviour.cpp new file mode 100644 index 00000000..c982637b --- /dev/null +++ b/src/Game/Systems/Weapon/AssaultWeaponBehaviour.cpp @@ -0,0 +1,228 @@ +#include "Systems/Weapon/AssaultWeaponBehaviour.h" + +void AssaultWeaponBehaviour::UpdateComponent(EntityWrapper& entity, ComponentWrapper& cWeapon, double dt) +{ + double& fireCooldown = cWeapon["FireCooldown"]; + fireCooldown = glm::max(0.0, fireCooldown - dt); + + WeaponBehaviour::UpdateComponent(entity, cWeapon, dt); +} + +void AssaultWeaponBehaviour::UpdateWeapon(ComponentWrapper cWeapon, WeaponInfo& wi, double dt) +{ + // Decrement reload timer + double& reloadTimer = cWeapon["ReloadTimer"]; + reloadTimer = glm::max(0.0, reloadTimer - dt); + + // Start reloading automatically if at 0 mag ammo + int& magAmmo = cWeapon["MagazineAmmo"]; + if (m_ConfigAutoReload && magAmmo <= 0) { + OnReload(cWeapon, wi); + } + + // Handle reloading + bool& isReloading = cWeapon["IsReloading"]; + if (isReloading && reloadTimer <= 0.0) { + int& magSize = cWeapon["MagazineSize"]; + int& ammo = cWeapon["Ammo"]; + + ammo = glm::max(0, ammo - (magSize - magAmmo)); + magAmmo = glm::min(magSize, ammo); + isReloading = false; + } + + // Restore view angle + if (IsClient) { + float& currentTravel = cWeapon["CurrentTravel"]; + float& returnSpeed = cWeapon["ViewReturnSpeed"]; + if (currentTravel > 0) { + float change = returnSpeed * dt; + currentTravel = glm::max(0.f, currentTravel - change); + EntityWrapper camera = wi.Player.FirstChildByName("Camera"); + if (camera.Valid()) { + glm::vec3& cameraOrientation = camera["Transform"]["Orientation"]; + cameraOrientation.x -= change; + } + } + } + + // Fire if we're able to fire + if (canFire(cWeapon, wi)) { + fireBullet(cWeapon, wi); + } +} + +void AssaultWeaponBehaviour::OnPrimaryFire(ComponentWrapper cWeapon, WeaponInfo& wi) +{ + cWeapon["TriggerHeld"] = true; + if (canFire(cWeapon, wi)) { + fireBullet(cWeapon, wi); + } +} + +void AssaultWeaponBehaviour::OnCeasePrimaryFire(ComponentWrapper cWeapon, WeaponInfo& wi) +{ + cWeapon["TriggerHeld"] = false; +} + +void AssaultWeaponBehaviour::OnReload(ComponentWrapper cWeapon, WeaponInfo& wi) +{ + bool& isReloading = cWeapon["IsReloading"]; + if (isReloading) { + return; + } + + int& magAmmo = cWeapon["MagazineAmmo"]; + int& magSize = cWeapon["MagazineSize"]; + if (magAmmo >= magSize) { + return; + } + int& ammo = cWeapon["Ammo"]; + if (ammo <= 0) { + return; + } + + double reloadTime = cWeapon["ReloadTime"]; + double& reloadTimer = cWeapon["ReloadTimer"]; + + // Start reload + isReloading = true; + reloadTimer = reloadTime; +} + +void AssaultWeaponBehaviour::OnHolster(ComponentWrapper cWeapon, WeaponInfo& wi) +{ + // Make sure the trigger is released if weapon is holstered while firing + cWeapon["TriggerHeld"] = false; + + // Cancel any reload + cWeapon["IsReloading"] = false; + cWeapon["ReloadTimer"] = 0.0; +} + +void AssaultWeaponBehaviour::fireBullet(ComponentWrapper cWeapon, WeaponInfo& wi) +{ + cWeapon["FireCooldown"] = 60.0 / (double)cWeapon["RPM"]; + + // Ammo + int& magAmmo = cWeapon["MagazineAmmo"]; + if (magAmmo <= 0) { + return; + } else { + magAmmo -= 1; + } + + // View punch + if (IsClient) { + EntityWrapper camera = wi.Player.FirstChildByName("Camera"); + if (camera.Valid()) { + glm::vec3& cameraOrientation = camera["Transform"]["Orientation"]; + float viewPunch = cWeapon["ViewPunch"]; + float maxTravelAngle = cWeapon["MaxTravelAngle"]; + float& currentTravel = cWeapon["CurrentTravel"]; + if (currentTravel < maxTravelAngle) { + float change = viewPunch; + if (currentTravel + change > maxTravelAngle) { + change = maxTravelAngle - currentTravel; + } + cameraOrientation.x += change; + currentTravel += change; + } + } + } + + // Get weapon model based on current person + EntityWrapper weaponModelEntity = getRelevantWeaponModelEntity(wi); + if (!weaponModelEntity.Valid()) { + return; + } + + // Tracer + EntityWrapper tracerSpawner = weaponModelEntity.FirstChildByName("WeaponMuzzle"); + if (tracerSpawner.Valid()) { + glm::vec3 origin = Transform::AbsolutePosition(tracerSpawner); + glm::vec3 direction = glm::quat(Transform::AbsoluteOrientationEuler(tracerSpawner)) * glm::vec3(0, 0, -1); + float distance = traceRayDistance(origin, direction); + EntityWrapper ray = SpawnerSystem::Spawn(tracerSpawner); + if (ray.Valid()) { + ((glm::vec3&)ray["Transform"]["Scale"]).z = distance; + } + } + + // Deal damage + if (dealDamage(cWeapon, wi)) { + // Show hit marker + EntityWrapper hitMarkerSpawner = wi.Player.FirstChildByName("HitMarkerSpawner"); + if (hitMarkerSpawner.Valid()) { + SpawnerSystem::Spawn(hitMarkerSpawner, hitMarkerSpawner); + Events::PlaySoundOnEntity e; + e.EmitterID = wi.Player.ID; + e.FilePath = "Audio/weapon/hitclick.wav"; + m_EventBroker->Publish(e); + } + } +} + +bool AssaultWeaponBehaviour::canFire(ComponentWrapper cWeapon, WeaponInfo& wi) +{ + bool triggerHeld = cWeapon["TriggerHeld"]; + bool cooldownPassed = (double)cWeapon["FireCooldown"] <= 0.0; + bool isReloading = cWeapon["IsReloading"]; + return triggerHeld && cooldownPassed; +} + +bool AssaultWeaponBehaviour::dealDamage(ComponentWrapper cWeapon, WeaponInfo& wi) +{ + // Only deal damage client side + if (!IsClient) { + return false; + } + + // Only handle damage for the local player + if (wi.Player != LocalPlayer) { + return false; + } + + // Make sure the player isn't shooting from the grave + if (!wi.Player.Valid()) { + return false; + } + + // 3D-pick middle of screen + Rectangle viewport = m_Renderer->GetViewportSize(); + glm::vec2 centerScreen(viewport.Width / 2, viewport.Height / 2); + // TODO: Some horizontal spread + PickData pickData = m_Renderer->Pick(centerScreen); + EntityWrapper victim(m_World, pickData.Entity); + if (!victim.Valid()) { + return false; + } + + // Don't let us somehow shoot ourselves in the foot + if (victim == LocalPlayer) { + return false; + } + + // Only care about players being hit + if (!victim.HasComponent("Player")) { + victim = victim.FirstParentWithComponent("Player"); + } + if (!victim.Valid()) { + return false; + } + + double damage = cWeapon["BaseDamage"]; + // If friendly fire, reduce damage to 0 (needed to make Boosts, Ammosharing work) + if ((ComponentInfo::EnumType)victim["Team"]["Team"] == (ComponentInfo::EnumType)wi.Player["Team"]["Team"]) { + damage = 0; + } + + // Deal damage! + Events::PlayerDamage ePlayerDamage; + ePlayerDamage.Inflictor = wi.Player; + ePlayerDamage.Victim = victim; + ePlayerDamage.Damage = damage; + m_EventBroker->Publish(ePlayerDamage); + + return damage > 0; +}