This commit is contained in:
2016-02-10 01:16:38 +01:00
parent 5cea3bed3a
commit d931660c56
13 changed files with 181 additions and 100 deletions
+1 -1
View File
@@ -29,7 +29,7 @@ struct EntityWrapper
EntityWrapper FirstChildByName(const std::string& name);
EntityWrapper FirstParentWithComponent(const std::string& componentType);
bool IsChildOf(EntityWrapper potentialParent);
bool Valid();
bool Valid() const;
ComponentWrapper operator[](const char* componentName);
bool operator==(const EntityWrapper& e) const;
+2 -1
View File
@@ -5,6 +5,7 @@
#include <functional>
#include <list>
#include <tuple>
#include <set>
#include "../Common.h"
#include "Event.h"
@@ -107,7 +108,7 @@ private:
typedef std::unordered_map<ContextTypeName_t, EventRelays_t> ContextRelays_t;
ContextRelays_t m_ContextRelays;
std::vector<BaseEventRelay*> m_RelaysToSubscribe;
std::vector<std::tuple<EventID, ContextTypeName_t, EventTypeName_t>> m_RelaysToUnsubscribe;
std::unordered_map<BaseEventRelay*, std::tuple<EventID, ContextTypeName_t, EventTypeName_t>> m_RelaysToUnsubscribe;
typedef std::list<std::pair<EventTypeName_t, std::shared_ptr<Event>>> EventQueue_t;
std::shared_ptr<EventQueue_t> m_EventQueueRead;
+1 -3
View File
@@ -5,9 +5,7 @@
#include "../Common.h"
#include "AABB.h"
//Fwd declarations.
class Ray;
#include "Ray.h"
namespace OctSpace
{
+1 -1
View File
@@ -68,7 +68,7 @@ protected:
const std::string m_ComponentType;
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& cComponent, double dt) = 0;
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& cPlayer, double dt) = 0;
};
class ImpureSystem : public virtual System
+116 -13
View File
@@ -13,17 +13,23 @@
#include "Input/EInputCommand.h"
#include "Core/EntityFile.h"
#include "Core/EntityFileParser.h"
#include "Core/Octree.h"
#include "Collision/EntityAABB.h"
class WeaponBehaviour;
class WeaponSystem : public PureSystem, ImpureSystem
{
public:
WeaponSystem(SystemParams params, IRenderer* renderer);
WeaponSystem(SystemParams params, IRenderer* renderer, Octree<EntityAABB>* collisionOctree);
virtual void Update(double dt) override;
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& cComponent, double dt) override;
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& cPlayer, double dt) override;
private:
SystemParams m_SystemParams;
IRenderer* m_Renderer;
Octree<EntityAABB>* m_CollisionOctree;
std::unordered_map<EntityWrapper, std::shared_ptr<WeaponBehaviour>> m_ActiveWeapons;
@@ -38,12 +44,18 @@ private:
void selectWeapon(EntityWrapper player, ComponentInfo::EnumType slot);
};
class WeaponBehaviour
class WeaponBehaviour : protected System
{
public:
WeaponBehaviour(EntityWrapper weaponEntity)
: m_Entity(weaponEntity)
WeaponBehaviour(SystemParams systemParams, Octree<EntityAABB>* collisionOctree, EntityWrapper weaponEntity)
: System(systemParams)
, m_CollisionOctree(collisionOctree)
, m_Entity(weaponEntity)
{ }
virtual ~WeaponBehaviour() = default;
WeaponBehaviour(const WeaponBehaviour&) = delete;
WeaponBehaviour& operator=(const WeaponBehaviour &) = delete;
virtual void Fire() = 0;
virtual void CeaseFire() { }
@@ -51,15 +63,19 @@ public:
virtual void Update(double dt) { }
protected:
Octree<EntityAABB>* m_CollisionOctree;
EntityWrapper m_Entity;
};
class AssaultWeaponBehaviour : public WeaponBehaviour
{
public:
AssaultWeaponBehaviour(EntityWrapper weaponEntity)
: WeaponBehaviour(weaponEntity)
{ }
AssaultWeaponBehaviour(SystemParams systemParams, Octree<EntityAABB>* collisionOctree, EntityWrapper weaponEntity)
: WeaponBehaviour(systemParams, collisionOctree, weaponEntity)
{
m_RayRed = ResourceManager::Load<EntityFile>("Schema/Entities/RayRed.xml");
m_RayBlue = ResourceManager::Load<EntityFile>("Schema/Entities/RayBlue.xml");
}
virtual void Fire() override
{
@@ -73,6 +89,25 @@ public:
m_Firing = false;
}
virtual void Reload() override
{
ComponentWrapper& cAssaultWeapon = m_Entity["AssaultWeapon"];
int& magAmmo = cAssaultWeapon["MagazineAmmo"];
int magSize = cAssaultWeapon["MagazineSize"];
int& ammo = cAssaultWeapon["Ammo"];
// Don't reload if we're already fully loaded
if (magAmmo == magSize) {
return;
}
// Throw away rounds in magazine to incentivise ammo sharing
int toLoad = glm::min(magSize, ammo);
magAmmo = toLoad;
ammo -= toLoad;
}
virtual void Update(double dt) override
{
if (!m_Firing) {
@@ -82,7 +117,7 @@ public:
m_TimeSinceLastFire += dt;
ComponentWrapper& cAssaultWeapon = m_Entity["AssaultWeapon"];
if (m_TimeSinceLastFire > (double)cAssaultWeapon["RPM"] / 60.0) {
if (m_TimeSinceLastFire >= 1.0 / ((double)cAssaultWeapon["RPM"] / 60.0)) {
fireRound();
}
}
@@ -90,7 +125,8 @@ public:
private:
bool m_Firing = false;
double m_TimeSinceLastFire = 0.0;
ComponentWrapper m_Component;
EntityFile* m_RayRed = nullptr;
EntityFile* m_RayBlue = nullptr;
void fireRound()
{
@@ -99,18 +135,85 @@ private:
int& magAmmo = cAssaultWeapon["MagazineAmmo"];
int ammo = cAssaultWeapon["Ammo"];
// Reload if our magazine is empty and we have ammo to fill it with
if (magAmmo <= 0 && ammo > 0) {
CeaseFire();
// Reload if our magazine is empty
if (magAmmo <= 0) {
Reload();
return;
}
// Fire
magAmmo -= 1;
spawnTracer();
m_TimeSinceLastFire = 0.0;
}
void spawnTracer()
{
ComponentWrapper cTeam = m_Entity["Team"];
ComponentInfo::EnumType team = cTeam["Team"];
// Select the right color of effect
EntityFile* rayFile = nullptr;
if (team == cTeam["Team"].Enum("Red")) {
rayFile = m_RayRed;
}
if (team == cTeam["Team"].Enum("Blue")) {
rayFile = m_RayBlue;
}
if (rayFile == nullptr) {
return;
}
// Create the entity
EntityFileParser parser(rayFile);
EntityID rayID = parser.MergeEntities(m_World);
EntityWrapper ray(m_World, rayID);
// Figure out where to put it
EntityWrapper attachment;
if (m_Entity == LocalPlayer || true) {
// Spawn the effect from the weapon view model for the local player
attachment = m_Entity.FirstChildByName("WeaponMuzzle");
}
// TODO: Spawn the effect from the weapon world model once it exists
glm::mat4 transformation = Transform::AbsoluteTransformation(attachment);
glm::vec3 _scale;
glm::vec3 translation;
glm::quat _orientation;
glm::vec3 _skew;
glm::vec4 _perspective;
glm::decompose(transformation, _scale, _orientation, translation, _skew, _perspective);
// Matrix to euler angles
glm::vec3 euler;
euler.y = glm::asin(-transformation[0][2]);
if (cos(euler.y) != 0) {
euler.x = atan2(transformation[1][2], transformation[2][2]);
euler.z = atan2(transformation[0][1], transformation[0][0]);
} else {
euler.x = atan2(-transformation[2][0], transformation[1][1]);
euler.z = 0;
}
// TODO: Spread?
(glm::vec3&)ray["Transform"]["Position"] = translation;
(glm::vec3&)ray["Transform"]["Orientation"] = euler;
glm::vec3& scale = ray["Transform"]["Scale"];
scale.z = traceRayDistance(translation, glm::quat(euler) * glm::vec3(0.f, 0.f, -1.f));
}
float traceRayDistance(glm::vec3 origin, glm::vec3 direction)
{
OctSpace::Output result;
if (m_CollisionOctree->RayCollides(Ray(origin, direction), result)) {
return result.CollideDistance;
} else {
return 0.f;
}
}
};
#endif