DefenderWeapon and SidearmWeapon

This commit is contained in:
2016-03-01 22:37:19 +01:00
parent afd0e69a8a
commit 13546aa3fc
14 changed files with 340 additions and 65 deletions
@@ -1,7 +1,6 @@
#include "WeaponBehaviour.h" #include "WeaponBehaviour.h"
#include "Collision/Collision.h" #include "Collision/Collision.h"
#include "Core/EPlayerDamage.h" #include "Core/EPlayerDamage.h"
#include "Rendering/ESetCamera.h"
class DefenderWeaponBehaviour : public WeaponBehaviour<DefenderWeaponBehaviour> class DefenderWeaponBehaviour : public WeaponBehaviour<DefenderWeaponBehaviour>
{ {
@@ -10,29 +9,24 @@ public:
: System(systemParams) : System(systemParams)
, WeaponBehaviour(systemParams, "DefenderWeapon", renderer, collisionOctree) , WeaponBehaviour(systemParams, "DefenderWeapon", renderer, collisionOctree)
, m_RandomEngine(m_RandomDevice()) , m_RandomEngine(m_RandomDevice())
{ { }
EVENT_SUBSCRIBE_MEMBER(m_ESetCamera, &DefenderWeaponBehaviour::OnSetCamera);
}
void UpdateComponent(EntityWrapper& entity, ComponentWrapper& cWeapon, double dt) override; void UpdateComponent(EntityWrapper& entity, ComponentWrapper& cWeapon, double dt) override;
void UpdateWeapon(ComponentWrapper cWeapon, WeaponInfo& wi, double dt) override; void UpdateWeapon(ComponentWrapper cWeapon, WeaponInfo& wi, double dt) override;
void OnPrimaryFire(ComponentWrapper cWeapon, WeaponInfo& wi) override; void OnPrimaryFire(ComponentWrapper cWeapon, WeaponInfo& wi) override;
void OnCeasePrimaryFire(ComponentWrapper cWeapon, WeaponInfo& wi) override; void OnCeasePrimaryFire(ComponentWrapper cWeapon, WeaponInfo& wi) override;
void OnReload(ComponentWrapper cWeapon, WeaponInfo& wi) override;
bool OnInputCommand(ComponentWrapper cWeapon, WeaponInfo& wi, const Events::InputCommand& e) override; bool OnInputCommand(ComponentWrapper cWeapon, WeaponInfo& wi, const Events::InputCommand& e) override;
private: private:
std::random_device m_RandomDevice; std::random_device m_RandomDevice;
std::mt19937 m_RandomEngine; std::mt19937 m_RandomEngine;
EntityWrapper m_CurrentCamera;
EventRelay<DefenderWeaponBehaviour, Events::SetCamera> m_ESetCamera;
bool OnSetCamera(const Events::SetCamera& e);
// Weapon functions // Weapon functions
void fireShell(ComponentWrapper cWeapon, WeaponInfo& wi); void fireShell(ComponentWrapper cWeapon, WeaponInfo& wi);
void dealDamage(ComponentWrapper cWeapon, WeaponInfo& wi, glm::vec3 direction, double damage); void dealDamage(ComponentWrapper cWeapon, WeaponInfo& wi, glm::vec3 direction, double damage);
bool canFire(ComponentWrapper cWeapon, WeaponInfo& wi);
// Utility // Utility
float traceRayDistance(glm::vec3 origin, glm::vec3 direction);
Camera cameraFromEntity(EntityWrapper camera); Camera cameraFromEntity(EntityWrapper camera);
}; };
@@ -15,12 +15,12 @@ public:
void UpdateWeapon(ComponentWrapper cWeapon, WeaponInfo& wi, double dt) override; void UpdateWeapon(ComponentWrapper cWeapon, WeaponInfo& wi, double dt) override;
void OnPrimaryFire(ComponentWrapper cWeapon, WeaponInfo& wi) override; void OnPrimaryFire(ComponentWrapper cWeapon, WeaponInfo& wi) override;
void OnCeasePrimaryFire(ComponentWrapper cWeapon, WeaponInfo& wi) override; void OnCeasePrimaryFire(ComponentWrapper cWeapon, WeaponInfo& wi) override;
void OnEquip(ComponentWrapper cWeapon, WeaponInfo& wi) override;
void OnHolster(ComponentWrapper cWeapon, WeaponInfo& wi) override; void OnHolster(ComponentWrapper cWeapon, WeaponInfo& wi) override;
private: private:
std::random_device m_RandomDevice; std::random_device m_RandomDevice;
std::mt19937 m_RandomEngine; std::mt19937 m_RandomEngine;
EntityWrapper m_CurrentCamera;
// Weapon functions // Weapon functions
void fireBullet(ComponentWrapper cWeapon, WeaponInfo& wi); void fireBullet(ComponentWrapper cWeapon, WeaponInfo& wi);
@@ -28,5 +28,6 @@ private:
// Utility // Utility
bool canFire(ComponentWrapper cWeapon); bool canFire(ComponentWrapper cWeapon);
bool playerInFirstPerson(EntityWrapper player);
//float traceRayDistance(glm::vec3 origin, glm::vec3 direction); //float traceRayDistance(glm::vec3 origin, glm::vec3 direction);
}; };
+51 -6
View File
@@ -7,6 +7,7 @@
#include "Collision/EntityAABB.h" #include "Collision/EntityAABB.h"
#include "Input/EInputCommand.h" #include "Input/EInputCommand.h"
#include "Systems/SpawnerSystem.h" #include "Systems/SpawnerSystem.h"
#include "Rendering/ESetCamera.h"
template <typename ETYPE> template <typename ETYPE>
class WeaponBehaviour : public PureSystem class WeaponBehaviour : public PureSystem
@@ -21,6 +22,7 @@ public:
, m_CollisionOctree(collisionOctree) , m_CollisionOctree(collisionOctree)
{ {
EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &WeaponBehaviour::_OnInputCommand) EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &WeaponBehaviour::_OnInputCommand)
EVENT_SUBSCRIBE_MEMBER(m_ESetCamera, &WeaponBehaviour::_OnSetCamera)
} }
virtual ~WeaponBehaviour() = default; virtual ~WeaponBehaviour() = default;
@@ -44,6 +46,7 @@ protected:
}; };
IRenderer* m_Renderer; IRenderer* m_Renderer;
EntityWrapper m_CurrentCamera;
Octree<EntityAABB>* m_CollisionOctree; Octree<EntityAABB>* m_CollisionOctree;
std::unordered_map<EntityWrapper, WeaponInfo> m_ActiveWeapons; std::unordered_map<EntityWrapper, WeaponInfo> m_ActiveWeapons;
@@ -51,10 +54,49 @@ protected:
virtual void OnPrimaryFire(ComponentWrapper cWeapon, WeaponInfo& wi) { } virtual void OnPrimaryFire(ComponentWrapper cWeapon, WeaponInfo& wi) { }
virtual void OnCeasePrimaryFire(ComponentWrapper cWeapon, WeaponInfo& wi) { } virtual void OnCeasePrimaryFire(ComponentWrapper cWeapon, WeaponInfo& wi) { }
virtual void OnReload(ComponentWrapper cWeapon, WeaponInfo& wi) { } virtual void OnReload(ComponentWrapper cWeapon, WeaponInfo& wi) { }
virtual void OnEquip(ComponentWrapper cWeapon, WeaponInfo& wi) { }
virtual void OnHolster(ComponentWrapper cWeapon, WeaponInfo& wi) { } virtual void OnHolster(ComponentWrapper cWeapon, WeaponInfo& wi) { }
virtual bool OnInputCommand(ComponentWrapper cWeapon, WeaponInfo& wi, const Events::InputCommand& e) { return false; } virtual bool OnInputCommand(ComponentWrapper cWeapon, WeaponInfo& wi, const Events::InputCommand& e) { return false; }
bool isPlayerInFirstPerson(EntityWrapper player)
{
if (!m_CurrentCamera.Valid()) {
return false;
} else {
return m_CurrentCamera == player || m_CurrentCamera.IsChildOf(player);
}
}
// Returns wi.FirstPersonEntity or wi.ThirdPersonEntity depending on
// if the player is in first person mode or not.
EntityWrapper getRelevantWeaponModelEntity(WeaponInfo& wi)
{
if (isPlayerInFirstPerson(wi.Player)) {
return wi.FirstPersonEntity;
} else {
return wi.ThirdPersonEntity;
}
}
float 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;
}
}
private: private:
EventRelay<ETYPE, Events::SetCamera> m_ESetCamera;
bool _OnSetCamera(const Events::SetCamera& e)
{
m_CurrentCamera = e.CameraEntity;
return true;
}
EventRelay<ETYPE, Events::InputCommand> m_EInputCommand; EventRelay<ETYPE, Events::InputCommand> m_EInputCommand;
bool _OnInputCommand(const Events::InputCommand& e) bool _OnInputCommand(const Events::InputCommand& e)
{ {
@@ -78,7 +120,7 @@ private:
if (e.Command == "SelectWeapon") { if (e.Command == "SelectWeapon") {
if (e.Value > 0) { if (e.Value > 0) {
if (static_cast<ComponentInfo::EnumType>(e.Value) == static_cast<ComponentInfo::EnumType>((*cWeapon)["Slot"])) { if (static_cast<ComponentInfo::EnumType>(e.Value) == static_cast<ComponentInfo::EnumType>((*cWeapon)["Slot"])) {
selectWeapon(player); selectWeapon(*cWeapon, player);
} else { } else {
holsterWeapon(*cWeapon, player); holsterWeapon(*cWeapon, player);
} }
@@ -132,7 +174,7 @@ private:
return activeWeapon; return activeWeapon;
} }
void selectWeapon(EntityWrapper player) void selectWeapon(ComponentWrapper cWeapon, EntityWrapper player)
{ {
// Don't reselect weapon if it's already active // Don't reselect weapon if it's already active
if (getActiveWeapon(player)) { if (getActiveWeapon(player)) {
@@ -170,10 +212,13 @@ private:
thirdPersonWeapon = SpawnerSystem::Spawn(thirdPersonAttachment, thirdPersonAttachment); thirdPersonWeapon = SpawnerSystem::Spawn(thirdPersonAttachment, thirdPersonAttachment);
} }
m_ActiveWeapons[player].Player = player; WeaponInfo& wi = m_ActiveWeapons[player];
m_ActiveWeapons[player].WeaponEntity = player; wi.Player = player;
m_ActiveWeapons[player].FirstPersonEntity = firstPersonWeapon; wi.WeaponEntity = player;
m_ActiveWeapons[player].ThirdPersonEntity = thirdPersonWeapon; wi.FirstPersonEntity = firstPersonWeapon;
wi.ThirdPersonEntity = thirdPersonWeapon;
OnEquip(cWeapon, wi);
} }
void holsterWeapon(ComponentWrapper cWeapon, EntityWrapper player) void holsterWeapon(ComponentWrapper cWeapon, EntityWrapper player)
@@ -11,6 +11,8 @@
<ViewPunch>0.01</ViewPunch> <ViewPunch>0.01</ViewPunch>
<ReloadTime>0.5</ReloadTime> <ReloadTime>0.5</ReloadTime>
<Slot><Primary/></Slot> <Slot><Primary/></Slot>
<IsFiring>false</IsFiring> <TriggerHeld>false</TriggerHeld>
<TimeSinceLastFire>0</TimeSinceLastFire> <FireCooldown>0</FireCooldown>
<IsReloading>false</IsReloading>
<ReloadTimer>0</ReloadTimer>
</DefenderWeapon> </DefenderWeapon>
@@ -48,8 +48,10 @@
<xs:annotation><xs:documentation>Time it takes to load ONE SHELL into the weapon in seconds</xs:documentation></xs:annotation> <xs:annotation><xs:documentation>Time it takes to load ONE SHELL into the weapon in seconds</xs:documentation></xs:annotation>
</xs:element> </xs:element>
<xs:element name="Slot" type="WeaponSlotEnum" minOccurs="0"/> <xs:element name="Slot" type="WeaponSlotEnum" minOccurs="0"/>
<xs:element name="IsFiring" type="t:bool" minOccurs="0"/> <xs:element name="TriggerHeld" type="t:bool" minOccurs="0"/>
<xs:element name="TimeSinceLastFire" type="t:double" minOccurs="0"/> <xs:element name="FireCooldown" type="t:double" minOccurs="0"/>
<xs:element name="IsReloading" type="t:bool" minOccurs="0"/>
<xs:element name="ReloadTimer" type="t:double" minOccurs="0"/>
</xs:all> </xs:all>
</xs:complexType> </xs:complexType>
</xs:element> </xs:element>
@@ -3,9 +3,11 @@
<MagazineAmmo>16</MagazineAmmo> <MagazineAmmo>16</MagazineAmmo>
<MagazineSize>16</MagazineSize> <MagazineSize>16</MagazineSize>
<BaseDamage>20</BaseDamage> <BaseDamage>20</BaseDamage>
<RPM>120</RPM> <RPM>500</RPM>
<Automatic>false</Automatic>
<ViewPunch>0.01</ViewPunch> <ViewPunch>0.01</ViewPunch>
<ReloadTime>0.5</ReloadTime> <ReloadTime>0.5</ReloadTime>
<EquipTime>0.5</EquipTime>
<Slot><Secondary/></Slot> <Slot><Secondary/></Slot>
<TriggerHeld>false</TriggerHeld> <TriggerHeld>false</TriggerHeld>
<FireCooldown>0</FireCooldown> <FireCooldown>0</FireCooldown>
@@ -23,7 +23,7 @@
<xs:annotation><xs:documentation>Ammo currently loaded into the magazine</xs:documentation></xs:annotation> <xs:annotation><xs:documentation>Ammo currently loaded into the magazine</xs:documentation></xs:annotation>
</xs:element> </xs:element>
<xs:element name="MagazineSize" type="t:int" minOccurs="0"> <xs:element name="MagazineSize" type="t:int" minOccurs="0">
<xs:annotation><xs:documentation>Max number of rounds in a magazine</xs:documentation></xs:annotation> <xs:annotation><xs:documentation>Max number of rounds in a magazine</xs:documentation></xs:annotation>
</xs:element> </xs:element>
<xs:element name="BaseDamage" type="t:double" minOccurs="0"> <xs:element name="BaseDamage" type="t:double" minOccurs="0">
<xs:annotation><xs:documentation>Damage dealt if all shotgun pellets hit</xs:documentation></xs:annotation> <xs:annotation><xs:documentation>Damage dealt if all shotgun pellets hit</xs:documentation></xs:annotation>
@@ -31,12 +31,16 @@
<xs:element name="RPM" type="t:double" minOccurs="0"> <xs:element name="RPM" type="t:double" minOccurs="0">
<xs:annotation><xs:documentation>Rate of fire in rounds per minute</xs:documentation></xs:annotation> <xs:annotation><xs:documentation>Rate of fire in rounds per minute</xs:documentation></xs:annotation>
</xs:element> </xs:element>
<xs:element name="Automatic" type="t:bool" minOccurs="0"/>
<xs:element name="ViewPunch" type="t:float" minOccurs="0"> <xs:element name="ViewPunch" type="t:float" minOccurs="0">
<xs:annotation><xs:documentation>View punch in radians for each shell fired</xs:documentation></xs:annotation> <xs:annotation><xs:documentation>View punch in radians for each shell fired</xs:documentation></xs:annotation>
</xs:element> </xs:element>
<xs:element name="ReloadTime" type="t:double" minOccurs="0"> <xs:element name="ReloadTime" type="t:double" minOccurs="0">
<xs:annotation><xs:documentation>Time it takes to load ONE SHELL into the weapon in seconds</xs:documentation></xs:annotation> <xs:annotation><xs:documentation>Time it takes to load ONE SHELL into the weapon in seconds</xs:documentation></xs:annotation>
</xs:element> </xs:element>
<xs:element name="EquipTime" type="t:double" minOccurs="0">
<xs:annotation><xs:documentation>Time it takes from selecting the weapon until it's ready to fire</xs:documentation></xs:annotation>
</xs:element>
<xs:element name="Slot" type="WeaponSlotEnum" minOccurs="0"/> <xs:element name="Slot" type="WeaponSlotEnum" minOccurs="0"/>
<xs:element name="TriggerHeld" type="t:bool" minOccurs="0"/> <xs:element name="TriggerHeld" type="t:bool" minOccurs="0"/>
<xs:element name="FireCooldown" type="t:double" minOccurs="0"/> <xs:element name="FireCooldown" type="t:double" minOccurs="0"/>
+7 -7
View File
@@ -8,7 +8,7 @@
</c:AABB> </c:AABB>
<c:Collidable/> <c:Collidable/>
<c:DefenderWeapon> <c:DefenderWeapon>
<TimeSinceLastFire>52.867678870419283</TimeSinceLastFire> <TimeSinceLastFire>102.85760837900634</TimeSinceLastFire>
</c:DefenderWeapon> </c:DefenderWeapon>
<c:DoubleJump/> <c:DoubleJump/>
<c:SidearmWeapon/> <c:SidearmWeapon/>
@@ -454,7 +454,7 @@
<Components> <Components>
<c:Animation> <c:Animation>
<AnimationName1>Idle</AnimationName1> <AnimationName1>Idle</AnimationName1>
<Time1>0.022133545026491674</Time1> <Time1>1.8348644854054612</Time1>
<Speed1>1</Speed1> <Speed1>1</Speed1>
<AnimationName2></AnimationName2> <AnimationName2></AnimationName2>
<AnimationName3></AnimationName3> <AnimationName3></AnimationName3>
@@ -478,8 +478,8 @@
<EntityFile>Schema/Entities/DefenderWeaponView.xml</EntityFile> <EntityFile>Schema/Entities/DefenderWeaponView.xml</EntityFile>
</c:Spawner> </c:Spawner>
<c:Transform> <c:Transform>
<Position X="0.120430708" Y="-0.228458226" Z="-0.181454539"/> <Position X="0.120430619" Y="-0.229639441" Z="-0.181454554"/>
<Orientation X="0.0104047246" Y="-0.00268179877" Z="0.0428441055"/> <Orientation X="0.0104045719" Y="-0.00268170005" Z="0.0428441055"/>
</c:Transform> </c:Transform>
</Components> </Components>
<Children/> <Children/>
@@ -497,8 +497,8 @@
<EntityFile>Schema/Entities/SidearmWeaponView.xml</EntityFile> <EntityFile>Schema/Entities/SidearmWeaponView.xml</EntityFile>
</c:Spawner> </c:Spawner>
<c:Transform> <c:Transform>
<Position X="0.120430708" Y="-0.228458226" Z="-0.181454539"/> <Position X="0.120430619" Y="-0.229639441" Z="-0.181454554"/>
<Orientation X="0.0104047246" Y="-0.00268179877" Z="0.0428441055"/> <Orientation X="0.0104045719" Y="-0.00268170005" Z="0.0428441055"/>
</c:Transform> </c:Transform>
</Components> </Components>
<Children/> <Children/>
@@ -528,7 +528,7 @@
<Components> <Components>
<c:Animation> <c:Animation>
<AnimationName1>Idle</AnimationName1> <AnimationName1>Idle</AnimationName1>
<Time1>0.13373697879978863</Time1> <Time1>0.013134522267137072</Time1>
<Speed1>1</Speed1> <Speed1>1</Speed1>
<AnimationName2></AnimationName2> <AnimationName2></AnimationName2>
<AnimationName3></AnimationName3> <AnimationName3></AnimationName3>
+18
View File
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<Entity xmlns:c="components" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../Types/Entity.xsd">
<Components>
<c:Sprite>
<DiffuseTexture>Textures/Effects/Ray.png</DiffuseTexture>
<GlowMap></GlowMap>
<Color A="1" B="0" G="0" R="1"/>
</c:Sprite>
<c:Transform>
<Position X="0" Y="0.690654039" Z="2.69841838"/>
<Scale X="2" Y="0.0260000005" Z="1"/>
</c:Transform>
</Components>
<Children/>
</Entity>
+43
View File
@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<Entity xmlns:c="components" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../Types/Entity.xsd">
<Components>
<c:Transform>
<Scale X="0" Y="1" Z="1"/>
</c:Transform>
</Components>
<Children>
<Entity>
<Components>
<c:Sprite>
<DiffuseTexture>Textures/Effects/Ray.png</DiffuseTexture>
<GlowMap></GlowMap>
<Color A="1" B="0" G="0" R="1"/>
</c:Sprite>
<c:Transform>
<Position X="0" Y="0" Z="-50"/>
<Scale X="100" Y="0.0260000005" Z="0"/>
<Orientation X="0" Y="-1.57099998" Z="0"/>
</c:Transform>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:Sprite>
<DiffuseTexture>Textures/Effects/Ray.png</DiffuseTexture>
<GlowMap></GlowMap>
<Color A="1" B="0" G="0" R="1"/>
</c:Sprite>
<c:Transform>
<Position X="0" Y="0" Z="-50"/>
<Scale X="100" Y="0.0260000005" Z="0"/>
<Orientation X="0" Y="-1.57099998" Z="3.1400001"/>
</c:Transform>
</Components>
<Children/>
</Entity>
</Children>
</Entity>
@@ -14,7 +14,7 @@
<Entity name="WeaponMuzzle"> <Entity name="WeaponMuzzle">
<Components> <Components>
<c:Spawner> <c:Spawner>
<EntityFile>Schema/Entities/RayBlue.xml</EntityFile> <EntityFile>Schema/Entities/Ray2Red.xml</EntityFile>
</c:Spawner> </c:Spawner>
<c:Transform> <c:Transform>
<Position X="0" Y="0.105000004" Z="-0.256000012"/> <Position X="0" Y="0.105000004" Z="-0.256000012"/>
@@ -22,6 +22,67 @@
</Components> </Components>
<Children/> <Children/>
</Entity> </Entity>
<Entity name="AmmunitionHUD">
<Components>
<c:AmmunitionHUD/>
<c:Transform>
<Position X="-0.0300000012" Y="0.077000007" Z="-0.063000001"/>
<Scale X="0.400000006" Y="0.400000006" Z="0.400000006"/>
</c:Transform>
</Components>
<Children>
<Entity name="AmmunitionHUDBackground">
<Components>
<c:Sprite>
<DiffuseTexture>Textures/Core/UnitHexagon.png</DiffuseTexture>
<GlowMap></GlowMap>
<Color A="0.588235319" B="0" G="0" R="0"/>
</c:Sprite>
<c:Transform>
<Position X="0" Y="0" Z="-0.00300000003"/>
<Scale X="0.119999997" Y="0.119999997" Z="0.119999997"/>
</c:Transform>
</Components>
<Children/>
</Entity>
<Entity name="AmmunitionText">
<Components>
<c:Transform/>
</Components>
<Children>
<Entity name="MagazineAmmo">
<Components>
<c:Text>
<Content>16</Content>
<Resource>Fonts/DroidSans.ttf,64</Resource>
<Color A="1" B="3.92156863" G="1.17647064" R="0"/>
</c:Text>
<c:Transform>
<Position X="0" Y="-0.00600000005" Z="0"/>
<Scale X="0.0599999987" Y="0.0599999987" Z="0.0599999987"/>
</c:Transform>
</Components>
<Children/>
</Entity>
<Entity name="Infinity!">
<Components>
<c:Text>
<Content>8</Content>
<Resource>Fonts/DroidSans.ttf,64</Resource>
<Color A="1" B="3.92156863" G="1.17647064" R="0"/>
</c:Text>
<c:Transform>
<Position X="0.0150000006" Y="-0.029000001" Z="0"/>
<Scale X="0.0399999991" Y="0.0399999991" Z="0.0399999991"/>
<Orientation X="0" Y="0" Z="1.5710001"/>
</c:Transform>
</Components>
<Children/>
</Entity>
</Children>
</Entity>
</Children>
</Entity>
</Children> </Children>
</Entity> </Entity>
+45 -7
View File
@@ -390,14 +390,52 @@ bool EditorGUI::drawComponentField_Vector(ComponentWrapper &c, const ComponentIn
// Limit scale values to a minimum of 0 // Limit scale values to a minimum of 0
return ImGui::DragFloat3("", glm::value_ptr(val), 0.1f, 0.f, std::numeric_limits<float>::max()); return ImGui::DragFloat3("", glm::value_ptr(val), 0.1f, 0.f, std::numeric_limits<float>::max());
} else if (field.Name == "Orientation") { } else if (field.Name == "Orientation") {
// Make orentations have a period of 2*Pi //glm::vec3 tempVal = val;
glm::vec3 tempVal = glm::fmod(val, glm::vec3(glm::two_pi<float>())); glm::vec3 originalVal = val;
if (ImGui::SliderFloat3("", glm::value_ptr(tempVal), 0.f, glm::two_pi<float>())) {
val = tempVal; ImVec2 cursorPos = ImGui::GetCursorScreenPos();
return true; glm::tvec3<bool> isSnapping(false, false, false);
} else { bool changed = ImGui::DragFloat3("", glm::value_ptr(val), 0.066666f);
return false; if (changed) {
// Make orentations have a period of 2*Pi
val = glm::fmod(val, glm::vec3(glm::two_pi<float>()));
for (int i = 0; i < 3; i++) {
if (val[i] < 0) {
val[i] += glm::two_pi<float>();
}
}
} }
// Snap to angle
//float snapRange = glm::pi<float>() / 15.f;
//float snapAngle = glm::quarter_pi<float>();
//glm::vec3 snap = glm::fmod(val, glm::vec3(snapAngle));
//for (int i = 0; i < 3; i++) {
// isSnapping[i] = glm::abs(snap[i] - (snapRange / 2.f)) < snapRange;
//}
//if (changed && ImGui::IsMouseDown(0)) {
// glm::vec3 change = val - originalVal;
// for (int i = 0; i < 3; i++) {
// if (isSnapping[i] && glm::abs(change[i]) < snapRange) {
// val[i] -= snap[i] - snapRange;
// }
// }
//}
// Draw snapping outline
float width = ImGui::CalcItemWidth() / 3.f;;
float spacing = GImGui->Style.ItemInnerSpacing.x;
for (int i = 0; i < 3; i++) {
if (isSnapping[i]) {
ImVec2 pos = cursorPos + ImVec2(i * (width + spacing), 0.f);
ImRect bb(pos - ImVec2(1, 1), pos + ImVec2(width, 17));
auto window = ImGui::GetCurrentWindow();
const ImU32 col = window->Color(ImGuiCol_HeaderActive);
window->DrawList->AddRect(bb.Min, bb.Max, col, 3.f);
}
}
return changed;
} else { } else {
return ImGui::DragFloat3("", glm::value_ptr(val), 0.1f, std::numeric_limits<float>::lowest(), std::numeric_limits<float>::max()); return ImGui::DragFloat3("", glm::value_ptr(val), 0.1f, std::numeric_limits<float>::lowest(), std::numeric_limits<float>::max());
} }
@@ -2,33 +2,73 @@
void DefenderWeaponBehaviour::UpdateComponent(EntityWrapper& entity, ComponentWrapper& cWeapon, double dt) void DefenderWeaponBehaviour::UpdateComponent(EntityWrapper& entity, ComponentWrapper& cWeapon, double dt)
{ {
(double&)cWeapon["TimeSinceLastFire"] += dt; double& fireCooldown = cWeapon["FireCooldown"];
fireCooldown = glm::max(0.0, fireCooldown - dt);
WeaponBehaviour::UpdateComponent(entity, cWeapon, dt); WeaponBehaviour::UpdateComponent(entity, cWeapon, dt);
} }
void DefenderWeaponBehaviour::UpdateWeapon(ComponentWrapper cWeapon, WeaponInfo& wi, double dt) void DefenderWeaponBehaviour::UpdateWeapon(ComponentWrapper cWeapon, WeaponInfo& wi, double dt)
{ {
bool isFiring = cWeapon["IsFiring"]; double& reloadTimer = cWeapon["ReloadTimer"];
bool cooldownPassed = (double)cWeapon["TimeSinceLastFire"] >= (60.0 / (double)cWeapon["RPM"]); reloadTimer = glm::max(0.0, reloadTimer - dt);
bool isNotShielding = wi.Player.ChildrenWithComponent("Shield").size() == 0;
if (isFiring && cooldownPassed && isNotShielding) { double reloadTime = cWeapon["ReloadTime"];
bool& isReloading = cWeapon["IsReloading"];
if (isReloading && reloadTimer <= 0.0) {
int& magAmmo = cWeapon["MagazineAmmo"];
int& magSize = cWeapon["MagazineSize"];
int& ammo = cWeapon["Ammo"];
if (magAmmo < magSize && ammo > 0) {
ammo -= 1;
magAmmo += 1;
reloadTimer = reloadTime;
} else {
isReloading = false;
}
}
if (canFire(cWeapon, wi)) {
fireShell(cWeapon, wi); fireShell(cWeapon, wi);
} }
} }
void DefenderWeaponBehaviour::OnPrimaryFire(ComponentWrapper cWeapon, WeaponInfo& wi) void DefenderWeaponBehaviour::OnPrimaryFire(ComponentWrapper cWeapon, WeaponInfo& wi)
{ {
cWeapon["IsFiring"] = true; cWeapon["TriggerHeld"] = true;
bool cooldownPassed = (double)cWeapon["TimeSinceLastFire"] >= (60.0 / (double)cWeapon["RPM"]); if (canFire(cWeapon, wi)) {
bool isNotShielding = wi.Player.ChildrenWithComponent("Shield").size() == 0;
if (cooldownPassed && isNotShielding) {
fireShell(cWeapon, wi); fireShell(cWeapon, wi);
} }
} }
void DefenderWeaponBehaviour::OnCeasePrimaryFire(ComponentWrapper cWeapon, WeaponInfo& wi) void DefenderWeaponBehaviour::OnCeasePrimaryFire(ComponentWrapper cWeapon, WeaponInfo& wi)
{ {
cWeapon["IsFiring"] = false; cWeapon["TriggerHeld"] = false;
}
void DefenderWeaponBehaviour::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;
} }
bool DefenderWeaponBehaviour::OnInputCommand(ComponentWrapper cWeapon, WeaponInfo& wi, const Events::InputCommand& e) bool DefenderWeaponBehaviour::OnInputCommand(ComponentWrapper cWeapon, WeaponInfo& wi, const Events::InputCommand& e)
@@ -47,15 +87,23 @@ bool DefenderWeaponBehaviour::OnInputCommand(ComponentWrapper cWeapon, WeaponInf
return false; return false;
} }
bool DefenderWeaponBehaviour::OnSetCamera(const Events::SetCamera& e)
{
m_CurrentCamera = e.CameraEntity;
return true;
}
void DefenderWeaponBehaviour::fireShell(ComponentWrapper cWeapon, WeaponInfo& wi) void DefenderWeaponBehaviour::fireShell(ComponentWrapper cWeapon, WeaponInfo& wi)
{ {
cWeapon["TimeSinceLastFire"] = 0.0; cWeapon["FireCooldown"] = 60.0 / (double)cWeapon["RPM"];
// Stop reloading
bool& isReloading = cWeapon["IsReloading"];
isReloading = false;
// Ammo
int& magAmmo = cWeapon["MagazineAmmo"];
if (magAmmo <= 0) {
OnReload(cWeapon, wi);
return;
} else {
magAmmo -= 1;
}
int numPellets = cWeapon["NumPellets"]; int numPellets = cWeapon["NumPellets"];
float spreadAngle = cWeapon["SpreadAngle"]; float spreadAngle = cWeapon["SpreadAngle"];
std::uniform_real_distribution<float> randomSpreadAngle(-spreadAngle, spreadAngle); std::uniform_real_distribution<float> randomSpreadAngle(-spreadAngle, spreadAngle);
@@ -92,7 +140,6 @@ void DefenderWeaponBehaviour::fireShell(ComponentWrapper cWeapon, WeaponInfo& wi
dealDamage(cWeapon, wi, direction, pelletDamage); dealDamage(cWeapon, wi, direction, pelletDamage);
} }
} }
} }
void DefenderWeaponBehaviour::dealDamage(ComponentWrapper cWeapon, WeaponInfo& wi, glm::vec3 direction, double damage) void DefenderWeaponBehaviour::dealDamage(ComponentWrapper cWeapon, WeaponInfo& wi, glm::vec3 direction, double damage)
@@ -154,16 +201,13 @@ void DefenderWeaponBehaviour::dealDamage(ComponentWrapper cWeapon, WeaponInfo& w
LOG_DEBUG("Damage: %f", damage); LOG_DEBUG("Damage: %f", damage);
} }
float DefenderWeaponBehaviour::traceRayDistance(glm::vec3 origin, glm::vec3 direction) bool DefenderWeaponBehaviour::canFire(ComponentWrapper cWeapon, WeaponInfo& wi)
{ {
float distance; bool triggerHeld = cWeapon["TriggerHeld"];
glm::vec3 pos; bool cooldownPassed = (double)cWeapon["FireCooldown"] <= 0.0;
auto entity = Collision::EntityFirstHitByRay(Ray(origin, direction), m_CollisionOctree, distance, pos); bool isNotShielding = wi.Player.ChildrenWithComponent("Shield").size() == 0;
if (entity) { // TODO: Ammo checks
return distance; return triggerHeld && cooldownPassed && isNotShielding;
} else {
return 100.f;
}
} }
Camera DefenderWeaponBehaviour::cameraFromEntity(EntityWrapper camera) Camera DefenderWeaponBehaviour::cameraFromEntity(EntityWrapper camera)
@@ -14,7 +14,7 @@ void SidearmWeaponBehaviour::UpdateComponent(EntityWrapper& entity, ComponentWra
void SidearmWeaponBehaviour::UpdateWeapon(ComponentWrapper cWeapon, WeaponInfo& wi, double dt) void SidearmWeaponBehaviour::UpdateWeapon(ComponentWrapper cWeapon, WeaponInfo& wi, double dt)
{ {
if (canFire(cWeapon)) { if ((bool)cWeapon["Automatic"] && canFire(cWeapon)) {
fireBullet(cWeapon, wi); fireBullet(cWeapon, wi);
} }
} }
@@ -32,6 +32,11 @@ void SidearmWeaponBehaviour::OnCeasePrimaryFire(ComponentWrapper cWeapon, Weapon
cWeapon["TriggerHeld"] = false; cWeapon["TriggerHeld"] = false;
} }
void SidearmWeaponBehaviour::OnEquip(ComponentWrapper cWeapon, WeaponInfo& wi)
{
cWeapon["FireCooldown"] = (double)cWeapon["EquipTime"];
}
void SidearmWeaponBehaviour::OnHolster(ComponentWrapper cWeapon, WeaponInfo& wi) void SidearmWeaponBehaviour::OnHolster(ComponentWrapper cWeapon, WeaponInfo& wi)
{ {
// Make sure the trigger is released if weapon is holstered while firing // Make sure the trigger is released if weapon is holstered while firing
@@ -46,7 +51,23 @@ void SidearmWeaponBehaviour::OnHolster(ComponentWrapper cWeapon, WeaponInfo& wi)
void SidearmWeaponBehaviour::fireBullet(ComponentWrapper cWeapon, WeaponInfo& wi) 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);
if (!weaponModelEntity.Valid()) {
return;
}
// Tracer
EntityWrapper tracerSpawner = weaponModelEntity.FirstChildByName("WeaponMuzzle");
if (tracerSpawner.Valid()) {
glm::vec3 origin = Transform::AbsolutePosition(tracerSpawner);
glm::vec3 direction = Transform::AbsoluteOrientation(tracerSpawner) * glm::vec3(0, 0, -1);
float distance = traceRayDistance(origin, direction);
EntityWrapper ray = SpawnerSystem::Spawn(tracerSpawner);
((glm::vec3&)ray["Transform"]["Scale"]).z = (distance / 100.f);
}
} }
bool SidearmWeaponBehaviour::canFire(ComponentWrapper cWeapon) bool SidearmWeaponBehaviour::canFire(ComponentWrapper cWeapon)