diff --git a/rwengine/src/data/WeaponData.hpp b/rwengine/src/data/WeaponData.hpp index edee94eb..f00a3fbe 100644 --- a/rwengine/src/data/WeaponData.hpp +++ b/rwengine/src/data/WeaponData.hpp @@ -34,49 +34,4 @@ struct WeaponData { std::uint32_t inventorySlot; }; -/** - * @brief simple object for performing weapon checks against the world - * - * @todo RADIUS hitscans - */ -struct WeaponScan { - enum ScanType { - /** Instant-hit ray weapons */ - HITSCAN, - /** Area of effect attack */ - RADIUS, - }; - - const ScanType type; - - float damage; - - glm::vec3 center{}; - float radius; - - glm::vec3 end{}; - - WeaponData* weapon; - - // Constructor for a RADIUS hitscan - WeaponScan(float damage, const glm::vec3& center, float radius, - WeaponData* weapon = nullptr) - : type(RADIUS) - , damage(damage) - , center(center) - , radius(radius) - , weapon(weapon) { - } - - // Constructor for a ray hitscan - WeaponScan(float damage, const glm::vec3& start, const glm::vec3& end, - WeaponData* weapon = nullptr) - : type(HITSCAN) - , damage(damage) - , center(start) - , end(end) - , weapon(weapon) { - } -}; - #endif diff --git a/rwengine/src/engine/GameWorld.cpp b/rwengine/src/engine/GameWorld.cpp index 41bfd7b3..2a2a5134 100644 --- a/rwengine/src/engine/GameWorld.cpp +++ b/rwengine/src/engine/GameWorld.cpp @@ -25,7 +25,8 @@ #include "data/CutsceneData.hpp" #include "data/InstanceData.hpp" -#include "data/WeaponData.hpp" + +#include "items/Weapon.hpp" #include "loaders/LoaderCutsceneDAT.hpp" #include "loaders/LoaderIFP.hpp" diff --git a/rwengine/src/items/Weapon.cpp b/rwengine/src/items/Weapon.cpp index 0dded254..de9b383a 100644 --- a/rwengine/src/items/Weapon.cpp +++ b/rwengine/src/items/Weapon.cpp @@ -9,6 +9,10 @@ #include "objects/CharacterObject.hpp" #include "objects/ProjectileObject.hpp" +bool WeaponScan::doesDamage(GameObject* target) const { + return target != source; +} + void Weapon::fireHitscan(WeaponData* weapon, CharacterObject* owner) { auto handFrame = owner->getClump()->findFrame("srhand"); glm::mat4 handMatrix = handFrame->getWorldTransform(); diff --git a/rwengine/src/items/Weapon.hpp b/rwengine/src/items/Weapon.hpp index 72e4ac46..14c1e8aa 100644 --- a/rwengine/src/items/Weapon.hpp +++ b/rwengine/src/items/Weapon.hpp @@ -1,9 +1,59 @@ #ifndef _RWENGINE_WEAPON_HPP_ #define _RWENGINE_WEAPON_HPP_ +#include class CharacterObject; +class GameObject; struct WeaponData; +/** + * @brief simple object for performing weapon checks against the world + */ +struct WeaponScan { + enum ScanType { + /** Instant-hit ray weapons */ + HITSCAN, + /** Area of effect attack */ + RADIUS, + }; + + const ScanType type; + + float damage; + + glm::vec3 center{}; + float radius; + + glm::vec3 end{}; + + WeaponData* weapon; + GameObject* source; + + // Constructor for a RADIUS hitscan + WeaponScan(float damage, const glm::vec3& center, float radius, + WeaponData* weapon = nullptr, GameObject* source = nullptr) + : type(RADIUS) + , damage(damage) + , center(center) + , radius(radius) + , weapon(weapon) + , source(source) { + } + + // Constructor for a ray hitscan + WeaponScan(float damage, const glm::vec3& start, const glm::vec3& end, + WeaponData* weapon = nullptr, GameObject* source = nullptr) + : type(HITSCAN) + , damage(damage) + , center(start) + , end(end) + , weapon(weapon) + , source(source) { + } + + bool doesDamage(GameObject* target) const; +}; + namespace Weapon { void fireProjectile(WeaponData* weapon, CharacterObject* character, float force); void fireHitscan(WeaponData *weapon, CharacterObject* character); diff --git a/tests/test_Weapon.cpp b/tests/test_Weapon.cpp index ccacda4d..8edbeb5a 100644 --- a/tests/test_Weapon.cpp +++ b/tests/test_Weapon.cpp @@ -1,13 +1,37 @@ #include #include +#include #include #include #include "test_Globals.hpp" BOOST_AUTO_TEST_SUITE(WeaponTests) +BOOST_AUTO_TEST_CASE(radius_ctor_creates_radius_scan) { + WeaponScan scan{10.f, {1.f, 1.f, 1.f}, 5.f}; + BOOST_CHECK_EQUAL(scan.type, WeaponScan::RADIUS); +} + +BOOST_AUTO_TEST_CASE(hitscan_ctor_creates_radius_scan) { + WeaponScan scan{10.f, {1.f, 1.f, 1.f}, {0.f, 0.f, 0.f}}; + BOOST_CHECK_EQUAL(scan.type, WeaponScan::HITSCAN); +} + +struct WeaponScanFixture { + GameObject* source = reinterpret_cast(0x0000BEEF); + WeaponScan scan{10.f, {1.f, 1.f, 1.f}, {0.f, 0.f, 0.f}, nullptr, source}; +}; + +BOOST_FIXTURE_TEST_CASE(weapon_scan_doesnt_injur_source, WeaponScanFixture) { + BOOST_CHECK(!scan.doesDamage(reinterpret_cast(0x0000BEEF))); +} + +BOOST_FIXTURE_TEST_CASE(weapon_scan_does_injur_others, WeaponScanFixture) { + BOOST_CHECK(scan.doesDamage(reinterpret_cast(0xDEADBEEF))); +} + #if RW_TEST_WITH_DATA -BOOST_AUTO_TEST_CASE(TestWeaponScan) { +BOOST_AUTO_TEST_CASE(TestDoWeaponScan) { { // Test RADIUS scan auto character = Global::get().e->createPedestrian(1, {0.f, 0.f, 0.f});