diff --git a/assets b/assets index d97e6ce5..504752c9 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit d97e6ce5b99b9f8a2d5fe6dbfa1dbd11444f62ae +Subproject commit 504752c94966c432513cac35acf906f8c9a3f965 diff --git a/include/Engine/Collision/Collision.h b/include/Engine/Collision/Collision.h index 9e1a81db..5431df4d 100644 --- a/include/Engine/Collision/Collision.h +++ b/include/Engine/Collision/Collision.h @@ -12,7 +12,7 @@ #include "../Core/AABB.h" #include "Rendering/RawModelCustom.h" //#include "Rendering/RawModelAssimp.h" -#include "../Core/Transform.h" +#include "../Core/TransformSystem.h" #include "../Core/Entity.h" #include "../Core/EntityWrapper.h" #include "EntityAABB.h" @@ -84,6 +84,18 @@ bool AABBvsTriangles(const AABB& box, const std::vector& modelIndices, const glm::mat4& modelMatrix); +enum Output +{ + OutContained, + OutSeparated, + OutIntersecting +}; +//Detects intersection and containment. +Output AABBvsTrianglesWContainment(const AABB& box, + const RawModel::Vertex* modelVertices, + const std::vector& modelIndices, + const glm::mat4& modelMatrix); + //Return true if the boxes are intersecting. bool AABBVsAABB(const AABB& a, const AABB& b); //Return true if the boxes are intersecting. diff --git a/include/Engine/Core/ComponentInfo.h b/include/Engine/Core/ComponentInfo.h index 137a44d8..e3b77d1d 100644 --- a/include/Engine/Core/ComponentInfo.h +++ b/include/Engine/Core/ComponentInfo.h @@ -2,6 +2,7 @@ #define ComponentInfo_h__ #include "../Common.h" +#include "Entity.h" #include struct ComponentInfo @@ -21,6 +22,7 @@ struct ComponentInfo { std::string Name; std::string Type; + unsigned char Index; unsigned int Offset; unsigned int Stride; }; @@ -32,6 +34,16 @@ struct ComponentInfo unsigned int Stride = 0; boost::shared_array Defaults = nullptr; std::shared_ptr Meta = nullptr; + + std::size_t GetHeaderSize() const + { + std::size_t size = 0; + + // A component block starts with an entity ID + size += sizeof(EntityID); + + return size; + } }; template<> diff --git a/include/Engine/Core/ComponentPool.h b/include/Engine/Core/ComponentPool.h index aedfd06b..44709c60 100644 --- a/include/Engine/Core/ComponentPool.h +++ b/include/Engine/Core/ComponentPool.h @@ -5,16 +5,15 @@ #include "MemoryPool.h" #include "ComponentInfo.h" #include "ComponentWrapper.h" +#include "DirtySet.h" + +class ComponentPool; class ComponentPoolForwardIterator : public std::iterator { public: - ComponentPoolForwardIterator(const ComponentInfo& componentInfo, const MemoryPool::iterator begin, const MemoryPool::iterator end) - : m_ComponentInfo(componentInfo) - , m_MemoryPoolIterator(begin) - , m_MemoryPoolEnd(end) - { } + ComponentPoolForwardIterator(ComponentPool* pool, const MemoryPool::iterator begin, const MemoryPool::iterator end); ComponentPoolForwardIterator(const ComponentPoolForwardIterator& other) = default; ComponentPoolForwardIterator(ComponentPoolForwardIterator&& other) = default; @@ -27,6 +26,7 @@ public: ComponentWrapper operator*() const; private: + ComponentPool* m_ComponentPool; const ComponentInfo& m_ComponentInfo; MemoryPool::iterator m_MemoryPoolIterator; const MemoryPool::iterator m_MemoryPoolEnd; @@ -34,6 +34,7 @@ private: class ComponentPool { + friend class ComponentPoolForwardIterator; public: typedef ComponentPoolForwardIterator iterator; typedef ptrdiff_t difference_type; @@ -42,9 +43,10 @@ public: typedef ComponentWrapper* pointer; typedef ComponentWrapper& reference; - ComponentPool(const ::ComponentInfo& ci) + ComponentPool(const ::ComponentInfo& ci, World* world) : m_ComponentInfo(ci) - , m_Pool(ci.Meta->Allocation, sizeof(EntityID) + ci.Stride) + , m_Pool(ci.Meta->Allocation, ci.GetHeaderSize() + ci.Stride) + , m_World(world) { } ~ComponentPool(); ComponentPool(const ComponentPool& other); @@ -61,8 +63,8 @@ public: // Delete a component and free its memory void Delete(ComponentWrapper& wrapper); - iterator begin() const; - iterator end() const; + iterator begin(); + iterator end(); size_t size() const; //Dumps information about what the pool memory looks like right now @@ -80,6 +82,8 @@ private: ::ComponentInfo m_ComponentInfo; MemoryPool m_Pool; std::unordered_map m_EntityToComponent; + DirtySet m_DirtySet; + World* m_World; }; #endif \ No newline at end of file diff --git a/include/Engine/Core/ComponentWrapper.h b/include/Engine/Core/ComponentWrapper.h index 7897e874..f291b751 100644 --- a/include/Engine/Core/ComponentWrapper.h +++ b/include/Engine/Core/ComponentWrapper.h @@ -4,46 +4,32 @@ #include #include #include "../Common.h" +#include "../GLM.h" #include "Entity.h" #include "ComponentInfo.h" +#include "DirtySet.h" #include "Util/Any.h" -template -struct ComponentField { }; - -template -struct ComponentField::value>::type> -{ - static T& Get(const ComponentInfo::Field_t& info, char* data) { return *reinterpret_cast(data); } - static void Set(const ComponentInfo::Field_t& info, char* data, const T& value) { Get(data) = value; } -}; - -template <> -struct ComponentField -{ - static std::string& Get(const ComponentInfo::Field_t& info, char* data) { return **reinterpret_cast(data); } - static void Set(const ComponentInfo::Field_t& info, char* data, const std::string& value) { Get(info, data) = value; } -}; +class World; struct ComponentWrapper { - ComponentWrapper(const ComponentInfo& componentInfo, char* data) - : Info(componentInfo) - , EntityID(*reinterpret_cast<::EntityID*>(data)) - , Data(data + sizeof(::EntityID)) - { } + ComponentWrapper(const ComponentInfo& componentInfo, char* data, ::DirtyBitField* dirtyBitField, World* world); + World* m_World; const ComponentInfo& Info; const ::EntityID EntityID; char* Data; + ::DirtyBitField* DirtyBitField = nullptr; - ComponentInfo::EnumType Enum(const char* fieldName, const char* enumKey) - { - return Info.Meta->FieldEnumDefinitions.at(fieldName).at(enumKey); - } + ComponentInfo::EnumType Enum(const char* fieldName, const char* enumKey); + + bool Dirty(DirtySetType type, const std::string& fieldName); + void SetDirty(DirtySetType type, const std::string& fieldName, bool dirty = true); + void SetAllDirty(const std::string& fieldName, bool dirty = true); template - T& Field(std::string name) + T& Field(const std::string& name) { const ComponentInfo::Field_t& field = Info.Fields.at(name); if (sizeof(T) > field.Stride) { @@ -55,13 +41,15 @@ struct ComponentWrapper } template - void SetField(std::string name, const T value) { Field(name) = value; } - //template - //void SetField(std::string name, T& value) { Field(name) = value; } + void SetField(const std::string& name, const T& value) + { + Field(name) = value; + SetAllDirty(name); + } // Specialization for string literals template - void SetField(std::string name, const char(&value)[N]) { Field(name) = std::string(value); } + void SetField(const std::string& name, const char(&value)[N]) { SetField(name, std::string(value)); } void Copy(ComponentWrapper& destination) { @@ -95,40 +83,163 @@ struct ComponentWrapper struct SubscriptProxy { friend struct ComponentWrapper; - private: - SubscriptProxy(ComponentWrapper* component, std::string propertyName) + + public: + SubscriptProxy(ComponentWrapper* component, std::string fieldName) : m_Component(component) - , m_PropertyName(propertyName) + , m_FieldName(fieldName) { } ComponentWrapper* m_Component; - std::string m_PropertyName; + std::string m_FieldName; public: // Return the integer value of an enum type key for this field - ComponentInfo::EnumType Enum(const char* enumKey) { return m_Component->Enum(m_PropertyName.c_str(), enumKey); } + ComponentInfo::EnumType Enum(const char* enumKey) { return m_Component->Enum(m_FieldName.c_str(), enumKey); } + bool Dirty(DirtySetType type) { return m_Component->Dirty(type, m_FieldName); } + void SetDirty(DirtySetType type, bool dirty = true) { m_Component->SetDirty(type, m_FieldName, dirty); } + void SetAllDirty(bool dirty = true) { m_Component->SetAllDirty(m_FieldName, dirty); } - template - operator T&() { return m_Component->Field(m_PropertyName); } + operator const double&() { return m_Component->Field(m_FieldName); } + operator const float&() { return m_Component->Field(m_FieldName); } + operator const int&() { return m_Component->Field(m_FieldName); } + operator const glm::vec3&() { return m_Component->Field(m_FieldName); } + operator const glm::vec4&() { return m_Component->Field(m_FieldName); } + operator const glm::quat&() { return m_Component->Field(m_FieldName); } + operator const bool&() { return m_Component->Field(m_FieldName); } + operator const std::string&() { return m_Component->Field(m_FieldName); } + // Don't allow non-const references + // If this wasn't deleted, the above overloads would still get called for some reason... + template < + typename T, + typename = typename std::enable_if::value>::type + > + //operator T&() = delete; + operator T&() { static_assert(constexpr(false), "https://github.com/teamfisk/TacticalZ/pull/212"); } + + // Value assignment template - void operator=(const T val) { m_Component->SetField(m_PropertyName, val); } - // TODO: Pass by reference and rvalue (universal reference?) - //template - //void operator=(T& val) { m_Component->SetField(m_PropertyName, val); } + void operator=(const T& val) { m_Component->SetField(m_FieldName, val); } // Specialization for string literals template - void operator=(const char(&val)[N]) { m_Component->SetField(m_PropertyName, val); } + void operator=(const char(&val)[N]) { m_Component->SetField(m_FieldName, val); } }; - SubscriptProxy operator[](std::string propertyName) { return SubscriptProxy(this, propertyName); } + SubscriptProxy operator[](const std::string& propertyName) { return SubscriptProxy(this, propertyName); } }; +struct FIELDLOL { }; // lol + +template +struct FieldBase : FIELDLOL +{ + FieldBase(ComponentWrapper::SubscriptProxy& Proxy) + : Proxy(Proxy) + , Data(Proxy.m_Component->Field(Proxy.m_FieldName)) + { } + + void SetAllDirty() { Proxy.SetAllDirty(); } + + FieldBase& operator=(const FieldBase& rhs) { Data = rhs.Data; SetAllDirty(); return *this; } + FieldBase& operator=(const T& rhs) { Data = rhs; SetAllDirty(); return *this; } + + template FieldBase& operator+=(const T2& rhs) { Data += rhs; SetAllDirty(); return *this; } + template FieldBase& operator-=(const T2& rhs) { Data -= rhs; SetAllDirty(); return *this; } + template FieldBase& operator*=(const T2& rhs) { Data *= rhs; SetAllDirty(); return *this; } + template FieldBase& operator/=(const T2& rhs) { Data /= rhs; SetAllDirty(); return *this; } + template FieldBase& operator%=(const T2& rhs) { Data %= rhs; SetAllDirty(); return *this; } + template FieldBase& operator&=(const T2& rhs) { Data &= rhs; SetAllDirty(); return *this; } + template FieldBase& operator|=(const T2& rhs) { Data |= rhs; SetAllDirty(); return *this; } + template FieldBase& operator^=(const T2& rhs) { Data ^= rhs; SetAllDirty(); return *this; } + template FieldBase& operator<<=(const T2& rhs) { Data <<= rhs; SetAllDirty(); return *this; } + template FieldBase& operator>>=(const T2& rhs) { Data >>= rhs; SetAllDirty(); return *this; } + + T operator+() const { return +Data; } + T operator-() const { return -Data; } + T operator~() const { return ~Data; } + + FieldBase& operator++() { Data++; SetAllDirty(); return *this; } + T operator++(int) { T tmp = Data; operator++(); return tmp; } + FieldBase& operator--() { Data--; SetAllDirty(); return *this; } + T operator--(int) { T tmp = Data; operator--(); return tmp; } + + operator const T&() const { return Data; } + const T& operator*() const { return operator const T&(); } + +protected: + ComponentWrapper::SubscriptProxy Proxy; + T& Data; +}; + +template +struct Field : FieldBase +{ + using FieldBase::FieldBase; + using FieldBase::operator=; +}; + +template <> +struct Field : FieldBase +{ + using FieldBase::FieldBase; + using FieldBase::operator=; + + glm::vec3::value_type x() const { return Data.x; } + void x(glm::vec3::value_type val) { Data.x = val; SetAllDirty(); } + glm::vec3::value_type y() const { return Data.y; } + void y(glm::vec3::value_type val) { Data.y = val; SetAllDirty(); } + glm::vec3::value_type z() const { return Data.z; } + void z(glm::vec3::value_type val) { Data.z = val; SetAllDirty(); } + + template friend glm::vec3 operator+(const Field& lhs, const T& rhs) { return static_cast(lhs) + glm::vec3(rhs); } + template friend glm::vec3 operator-(const Field& lhs, const T& rhs) { return static_cast(lhs) - glm::vec3(rhs); } + template friend glm::vec3 operator*(const Field& lhs, const T& rhs) { return static_cast(lhs) * glm::vec3(rhs); } + template friend glm::vec3 operator/(const Field& lhs, const T& rhs) { return static_cast(lhs) / glm::vec3(rhs); } + template friend glm::vec3 operator+(const T& lhs, const Field& rhs) { return glm::vec3(lhs) + static_cast(rhs); } + template friend glm::vec3 operator-(const T& lhs, const Field& rhs) { return glm::vec3(lhs) - static_cast(rhs); } + template friend glm::vec3 operator*(const T& lhs, const Field& rhs) { return glm::vec3(lhs) * static_cast(rhs); } + template friend glm::vec3 operator/(const T& lhs, const Field& rhs) { return glm::vec3(lhs) / static_cast(rhs); } + + friend glm::vec3& operator+=(glm::vec3& lhs, const Field& rhs) { lhs += *rhs; return lhs; } +}; + +template <> +struct Field : FieldBase +{ + //Field(glm::vec4& Data) + // : FieldBase(Data) + //{ } + using FieldBase::FieldBase; + using FieldBase::operator=; + + glm::vec4::value_type x() const { return Data.x; } + void x(glm::vec4::value_type val) { Data.x = val; SetAllDirty(); } + glm::vec4::value_type y() const { return Data.y; } + void y(glm::vec4::value_type val) { Data.y = val; SetAllDirty(); } + glm::vec4::value_type z() const { return Data.z; } + void z(glm::vec4::value_type val) { Data.z = val; SetAllDirty(); } + glm::vec4::value_type w() const { return Data.w; } + void w(glm::vec4::value_type val) { Data.w = val; SetAllDirty(); } + + template friend glm::vec4 operator+(const Field& lhs, const T& rhs) { return static_cast(lhs) + glm::vec4(rhs); } + template friend glm::vec4 operator-(const Field& lhs, const T& rhs) { return static_cast(lhs) - glm::vec4(rhs); } + template friend glm::vec4 operator*(const Field& lhs, const T& rhs) { return static_cast(lhs) * glm::vec4(rhs); } + template friend glm::vec4 operator/(const Field& lhs, const T& rhs) { return static_cast(lhs) / glm::vec4(rhs); } + template friend glm::vec4 operator+(const T& lhs, const Field& rhs) { return glm::vec4(lhs) + static_cast(rhs); } + template friend glm::vec4 operator-(const T& lhs, const Field& rhs) { return glm::vec4(lhs) - static_cast(rhs); } + template friend glm::vec4 operator*(const T& lhs, const Field& rhs) { return glm::vec4(lhs) * static_cast(rhs); } + template friend glm::vec4 operator/(const T& lhs, const Field& rhs) { return glm::vec4(lhs) / static_cast(rhs); } + + friend glm::vec4& operator+=(glm::vec4& lhs, const Field& rhs) { lhs += *rhs; return lhs; } +}; + + // A component wrapper that "owns" its data through a shared pointer struct SharedComponentWrapper : ComponentWrapper { SharedComponentWrapper(const ComponentInfo& componentInfo, boost::shared_array data) - : ComponentWrapper(componentInfo, data.get()) + : ComponentWrapper(componentInfo, data.get(), nullptr, nullptr) , m_DataReference(data) { } diff --git a/include/Engine/Core/DirtySet.h b/include/Engine/Core/DirtySet.h new file mode 100644 index 00000000..53885a7a --- /dev/null +++ b/include/Engine/Core/DirtySet.h @@ -0,0 +1,16 @@ +#ifndef DirtySet_h__ +#define DirtySet_h__ + +#include +#include "ComponentInfo.h" + +enum class DirtySetType +{ + Transform, + Network +}; + +typedef std::unordered_map> DirtyBitField; +typedef std::unordered_map DirtySet; + +#endif \ No newline at end of file diff --git a/include/Engine/Core/ECaptured.h b/include/Engine/Core/ECaptured.h index 047c5d7d..e0de0f31 100644 --- a/include/Engine/Core/ECaptured.h +++ b/include/Engine/Core/ECaptured.h @@ -1,5 +1,5 @@ -#ifndef ECaptured_h__ -#define ECaptured_h__ +#ifndef Events_Captured_h__ +#define Events_Captured_h__ #include "EventBroker.h" #include "../Core/Entity.h" diff --git a/include/Engine/Core/EEntityDeleted.h b/include/Engine/Core/EEntityDeleted.h index 80e20e17..b826e011 100644 --- a/include/Engine/Core/EEntityDeleted.h +++ b/include/Engine/Core/EEntityDeleted.h @@ -2,14 +2,14 @@ #define EEntityDeleted_h__ #include "Event.h" -#include "Entity.h" +#include "EntityWrapper.h" namespace Events { struct EntityDeleted : Event { - EntityID DeletedEntity; + EntityWrapper DeletedEntity; // True if the entity deletion was triggered because the entity's parent was deleted before it bool Cascaded; }; diff --git a/include/Engine/Core/EntityWrapper.h b/include/Engine/Core/EntityWrapper.h index 305fc21f..01f3f22e 100644 --- a/include/Engine/Core/EntityWrapper.h +++ b/include/Engine/Core/EntityWrapper.h @@ -45,8 +45,9 @@ 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); + static void fillRelationships(std::unordered_multimap& relationMap, EntityWrapper entity); + static void recreateRelationships(const std::unordered_multimap& relationMap, EntityWrapper templateEntity, EntityWrapper parent = EntityWrapper::Invalid); }; namespace std diff --git a/include/Engine/Core/ResourceManager.h b/include/Engine/Core/ResourceManager.h index b994b5cf..cf569260 100644 --- a/include/Engine/Core/ResourceManager.h +++ b/include/Engine/Core/ResourceManager.h @@ -19,6 +19,7 @@ class Resource protected: Resource() { } + virtual ~Resource() = default; public: //Should be thrown in a Resource's constructor if it cannot complete because another resource is still loading. diff --git a/include/Engine/Core/SystemPipeline.h b/include/Engine/Core/SystemPipeline.h index c4801fde..df6adc9f 100644 --- a/include/Engine/Core/SystemPipeline.h +++ b/include/Engine/Core/SystemPipeline.h @@ -81,7 +81,7 @@ public: for (auto& pair : group.PureSystems) { const std::string& componentName = pair.first; auto& systems = pair.second; - const ComponentPool* pool = m_World->GetComponents(componentName); + ComponentPool* pool = m_World->GetComponents(componentName); if (pool == nullptr) { continue; } diff --git a/include/Engine/Core/Transform.h b/include/Engine/Core/Transform.h deleted file mode 100644 index bd381e8b..00000000 --- a/include/Engine/Core/Transform.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef Transform_h__ -#define Transform_h__ - -#include "../GLM.h" -#include "World.h" -#include "EntityWrapper.h" - -namespace Transform -{ - -glm::mat4 AbsoluteTransformation(EntityWrapper entity); -glm::vec3 AbsolutePosition(EntityWrapper entity); -glm::vec3 AbsolutePosition(World* world, EntityID entity); -glm::vec3 AbsoluteOrientationEuler(EntityWrapper entity); -glm::quat AbsoluteOrientation(EntityWrapper entity); -glm::quat AbsoluteOrientation(World* world, EntityID entity); -glm::vec3 AbsoluteScale(EntityWrapper entity); -glm::vec3 AbsoluteScale(World* world, EntityID entity); -glm::mat4 ModelMatrix(EntityWrapper entity); -glm::mat4 ModelMatrix(EntityID entity, World* world); -glm::vec3 TransformPoint(const glm::vec3& point, const glm::mat4& matrix); - -} - -#endif \ No newline at end of file diff --git a/include/Engine/Core/TransformSystem.h b/include/Engine/Core/TransformSystem.h new file mode 100644 index 00000000..37ada400 --- /dev/null +++ b/include/Engine/Core/TransformSystem.h @@ -0,0 +1,39 @@ +#ifndef Transform_h__ +#define Transform_h__ + +#include "../GLM.h" +#include "System.h" +#include "EEntityDeleted.h" + +class TransformSystem : public System +{ +public: + TransformSystem(SystemParams params); + + //glm::mat4 AbsoluteTransformation(EntityWrapper entity); + static glm::vec3 AbsolutePosition(EntityWrapper entity); + static glm::vec3 AbsolutePosition(World* world, EntityID entity); + static glm::vec3 AbsoluteOrientationEuler(EntityWrapper entity); + static glm::quat AbsoluteOrientation(EntityWrapper entity); + static glm::quat AbsoluteOrientation(World* world, EntityID entity); + static glm::vec3 AbsoluteScale(EntityWrapper entity); + static glm::vec3 AbsoluteScale(World* world, EntityID entity); + static glm::mat4 ModelMatrix(EntityWrapper entity); + static glm::mat4 ModelMatrix(EntityID entity, World* world); + static glm::vec3 TransformPoint(const glm::vec3& point, const glm::mat4& matrix); + + static int RecalculatedPositions; + static int RecalculatedOrientations; + static int RecalculatedScales; + +private: + static std::unordered_map PositionCache; + static std::unordered_map OrientationCache; + static std::unordered_map ScaleCache; + static std::unordered_map MatrixCache; + + EventRelay m_EEntityDeleted; + bool OnEntityDeleted(const Events::EntityDeleted& e); +}; + +#endif \ No newline at end of file diff --git a/include/Engine/Core/World.h b/include/Engine/Core/World.h index 9ae38021..dd7f2887 100644 --- a/include/Engine/Core/World.h +++ b/include/Engine/Core/World.h @@ -35,7 +35,7 @@ public: // Delete a component off an entity void DeleteComponent(EntityID entity, const std::string& componentType); // Get all components of the specified type - const ComponentPool* GetComponents(const std::string& componentType); + ComponentPool* GetComponents(const std::string& componentType); // Get entity parent EntityID GetParent(EntityID entity); // Change the parent of an entity diff --git a/include/Engine/Editor/EditorSystem.h b/include/Engine/Editor/EditorSystem.h index 655ac9b9..7fe8ce6f 100644 --- a/include/Engine/Editor/EditorSystem.h +++ b/include/Engine/Editor/EditorSystem.h @@ -47,6 +47,7 @@ private: // Utility functions EntityWrapper importEntity(EntityWrapper parent, boost::filesystem::path filePath); void setWidgetMode(EditorGUI::WidgetMode mode); + bool isAnyParentMissingTransform(EntityID entityID); // GUI callbacks void OnEntitySelected(EntityWrapper entity); diff --git a/include/Engine/Input/FirstPersonInputController.h b/include/Engine/Input/FirstPersonInputController.h index 68c8a430..c159e113 100644 --- a/include/Engine/Input/FirstPersonInputController.h +++ b/include/Engine/Input/FirstPersonInputController.h @@ -19,6 +19,7 @@ public: virtual const glm::vec3 Rotation() const { return m_Rotation; } virtual bool Jumping() const { return m_Jumping; } virtual bool Crouching() const { return m_Crouching; } + virtual bool CrouchingLastFrame() const { return m_CrouchingLastFrame; } virtual bool DoubleJumping() const { return m_DoubleJumping; } virtual void SetDoubleJumping(bool isDoubleJumping) { m_DoubleJumping = isDoubleJumping; @@ -29,7 +30,7 @@ public: virtual bool OnCommand(const Events::InputCommand& e) override; virtual void Reset(); - void AssaultDashCheck(double dt, bool isJumping, double assaultDashCoolDownMaxTimer, double& assaultDashCoolDownTimer, EntityID playerID); + void AssaultDashCheck(double dt, bool isJumping, double assaultDashCoolDownMaxTimer, Field assaultDashCoolDownTimer, EntityID playerID); virtual bool AssaultDashDoubleTapped() const { return m_AssaultDashDoubleTapped; } virtual bool PlayerIsDashing() const { return m_PlayerIsDashing; } bool SpecialAbilityKeyDown() const { return m_SpecialAbilityKeyDown; } @@ -44,6 +45,7 @@ protected: bool m_Jumping = false; bool m_DoubleJumping = false; bool m_Crouching = false; + bool m_CrouchingLastFrame = false; //assault dash membervariables - needed to calculate the doubletap- and dashlogic double m_AssaultDashDoubleTapDeltaTime = 0.0; //i will let m_AssaultDashDoubleTapSensitivityTimer stay hardcoded, its not really a gamevariable (more an inputvariable), @@ -82,6 +84,7 @@ void FirstPersonInputController::Reset() { m_Rotation = glm::vec3(0.f, 0.f, 0.f); m_Jumping = false; + m_CrouchingLastFrame = m_Crouching; } template @@ -354,7 +357,7 @@ bool FirstPersonInputController::OnLockMouse(const Events::LockMou } template -void FirstPersonInputController::AssaultDashCheck(double dt, bool isJumping, double assaultDashCoolDownMaxTimer, double& assaultDashCoolDownTimer, EntityID playerID) { +void FirstPersonInputController::AssaultDashCheck(double dt, bool isJumping, double assaultDashCoolDownMaxTimer, Field assaultDashCoolDownTimer, EntityID playerID) { m_AssaultDashDoubleTapDeltaTime += dt; assaultDashCoolDownTimer -= dt; //cooldown = assaultDashCoolDownMaxTimer sec, pretend the dash lasts 0.25 sec (for friction to do its work) diff --git a/include/Engine/Network/Client.h b/include/Engine/Network/Client.h index 3033542d..29e9ac9a 100644 --- a/include/Engine/Network/Client.h +++ b/include/Engine/Network/Client.h @@ -32,6 +32,9 @@ #include "../Game/Events/EDashAbility.h" #include "Network/EDisplayServerlist.h" #include "Network/EConnectRequest.h" +#include "Network/EPlayerDisconnected.h" +#include "Game/Events/EReset.h" + class Client : public Network { public: @@ -40,9 +43,9 @@ public: ~Client(); void Connect(std::string address, int port); - void Update() override; + void Update(double dt) override; private: - //UDPClient m_Unreliable; + UDPClient m_Unreliable; TCPClient m_Reliable; std::vector m_PlayerSpawnEvents; void parseSpawnEvents(); @@ -74,14 +77,14 @@ private: // Network logic PlayerDefinition m_PlayerDefinitions[8]; SnapshotDefinitions m_NextSnapshot; - double m_DurationOfPingTime; - std::clock_t m_StartPingTime; - std::clock_t m_TimeSinceSentInputs; - unsigned int m_SendInputIntervalMs; + double m_DurationOfPingTime = 0; + double m_StartPingTime = 0; + double m_TimeSinceSentInputs = 0; + double m_SendInputInterval = 0.033; std::vector m_InputCommandBuffer; // Private member functions - size_t receive(char* data); + size_t receive(char* data); void disconnect(); void parseMessageType(Packet& packet); void updateFields(Packet& packet, const ComponentInfo& componentInfo, const EntityID& entityID); @@ -100,6 +103,7 @@ private: void parseDoubleJump(Packet& packet); void parseDashEffect(Packet& packet); void parseAmmoPickup(Packet& packet); + void parseRemoveWorld(Packet& packet); void InterpolateFields(Packet& packet, const ComponentInfo & componentInfo, const EntityID & entityID, const std::string & componentType); void parseSnapshot(Packet& packet); void identifyPacketLoss(); @@ -109,7 +113,6 @@ private: void sendLocalPlayerTransform(); void becomePlayer(); void displayServerlist(); - void removeWorld(); void createMainMenu(); // Mapping Logic // Returns if local EntityID exist in map @@ -138,8 +141,8 @@ private: UDPClient m_ServerlistRequest; std::vector m_Serverlist; bool m_SearchingForServers = false; - std::clock_t m_StartSearchTime; - double m_SearchingTime = 2000; // Config I guess + double m_TimeSearched = 0; + double m_SearchingTime = 0.2; // Config I guess }; #endif diff --git a/include/Engine/Network/MessageType.h b/include/Engine/Network/MessageType.h index c34f584e..11fb85be 100644 --- a/include/Engine/Network/MessageType.h +++ b/include/Engine/Network/MessageType.h @@ -23,6 +23,7 @@ enum class MessageType OnDashEffect, ServerlistRequest, AmmoPickup, + RemoveWorld, Invalid }; diff --git a/include/Engine/Network/Network.h b/include/Engine/Network/Network.h index b4de053e..b6c47f71 100644 --- a/include/Engine/Network/Network.h +++ b/include/Engine/Network/Network.h @@ -22,7 +22,7 @@ public: Network(World* world, EventBroker* eventBroker); virtual ~Network() { }; - virtual void Update() = 0; + virtual void Update(double dt) = 0; protected: World* m_World; @@ -39,6 +39,8 @@ protected: void logReceivedData(int bytesReceived); void saveToFile(); void updateNetworkData(); + void popNetworkSegmentOfHeader(Packet& packet); + void removeWorld(); }; #endif \ No newline at end of file diff --git a/include/Engine/Network/Packet.h b/include/Engine/Network/Packet.h index e7444d9d..bac7fd69 100644 --- a/include/Engine/Network/Packet.h +++ b/include/Engine/Network/Packet.h @@ -16,7 +16,9 @@ public: Packet(char* data, const size_t sizeOfPacket); Packet(MessageType type); ~Packet(); - void Init(MessageType type, unsigned int& packetID); + void Init(MessageType type, unsigned int& packetID, + int groupIndex, int groupSize, + int packetGroup); // Add primitive types like int, float, char... template @@ -25,7 +27,8 @@ public: // Check if we are trying to add more than the package can fit. if (m_MaxPacketSize < m_Offset + sizeof(T)) { if (m_MaxPacketSize >= 32000) { - LOG_WARNING("Package::WritePrimitive(): New size is huge %i bytes\n", m_MaxPacketSize*2); + // This will spam couse 8 players are over 100 000 bytes + //LOG_WARNING("Package::WritePrimitive(): New size is huge %i bytes\n", m_MaxPacketSize*2); } resizeData(); } @@ -57,13 +60,19 @@ public: void UpdateSize(); char* ReadData(int SizeOfData); void ChangePacketID(unsigned int& packetID); + void ChangeGroupIndex(int groupIndex); + void ChangeGroupSize(int groupSize); + void ChangeGroup(int group); size_t Size() { return m_Offset; }; char* Data() { return m_Data; }; MessageType GetMessageType(); + size_t Group(); size_t DataReadSize() { return m_ReturnDataOffset; } size_t MaxSize() { return m_MaxPacketSize; } size_t HeaderSize() { return m_HeaderSize; } - + size_t GroupIndex(); + size_t GroupSize(); + size_t PacketID(); private: char* m_Data; size_t m_ReturnDataOffset = 0; @@ -72,6 +81,13 @@ private: size_t m_HeaderSize = 0; void resizeData(); void resizeData(int size); + + size_t packetSizeOffset = 0; + size_t groupOffset = 0; + size_t groupIndexOffset = 0; + size_t groupSizeOffset = 0; + size_t messageTypeOffset = 0; + size_t packetIDOffset = 0; }; #endif \ No newline at end of file diff --git a/include/Engine/Network/PlayerDefinition.h b/include/Engine/Network/PlayerDefinition.h index afd5d889..6ccd1034 100644 --- a/include/Engine/Network/PlayerDefinition.h +++ b/include/Engine/Network/PlayerDefinition.h @@ -14,6 +14,7 @@ struct PlayerDefinition { unsigned short TCPPort; // use for tcp connections boost::shared_ptr TCPSocket; + int PacketGroup = 1; }; #endif diff --git a/include/Engine/Network/Server.h b/include/Engine/Network/Server.h index f96a4a7d..67859143 100644 --- a/include/Engine/Network/Server.h +++ b/include/Engine/Network/Server.h @@ -11,6 +11,7 @@ #include "Network/MessageType.h" #include "Network/PlayerDefinition.h" #include "Core/World.h" +#include "Core/EntityFile.h" #include "Core/EventBroker.h" #include "../Network/Network.h" #include "Input/EInputCommand.h" @@ -24,6 +25,8 @@ #include "Core/EPlayerDeath.h" #include "Network/EPlayerConnected.h" #include "Network/EKillDeath.h" +#include "Core/EWin.h" +#include "Game/Events/EReset.h" class Server : public Network { @@ -31,16 +34,17 @@ public: Server(World* world, EventBroker* eventBroker, int port); ~Server(); - void Update() override; + void Update(double dt) override; private: // Network channels TCPServer m_Reliable; - //UDPServer m_Unreliable; + UDPServer m_Unreliable; UDPServer m_ServerlistRequest; // dont forget to set these in the childrens receive logic boost::asio::ip::address m_Address; int m_Port = 27666; + bool m_GameIsOver = false; // Sending messages to client logic std::map m_ConnectedPlayers; std::vector m_PlayersToDisconnect; @@ -48,14 +52,14 @@ private: char readBuffer[BUFFERSIZE] = { 0 }; size_t bytesRead = 0; // time for previouse message - std::clock_t previousePingMessage = std::clock(); - std::clock_t previousSnapshotMessage = std::clock(); - std::clock_t timOutTimer = std::clock(); + double previousPingMessage = 0; + double previousSnapshotMessage = 0; + double timeOutTimer = 0; - // How often we send messages (milliseconds) - float pingIntervalMs; - float snapshotInterval; - int checkTimeOutInterval = 100; + // How often we send messages (seconds) + double pingInterval = 1; + double snapshotInterval = 0.05; + double checkTimeOutInterval = 0.1; int m_NextPlayerID = 0; std::vector m_InputCommandsToBroadcast; //Timers @@ -71,6 +75,7 @@ private: void reliableBroadcast(Packet& packet); void unreliableBroadcast(Packet& packet); void sendSnapshot(); + void createWorldSnapshot(Packet& packet); void addPlayersToPacket(Packet& packet, EntityID entityID); void addChildrenToPacket(Packet& packet, EntityID entityID); void addInputCommandsToPacket(Packet& packet); @@ -83,6 +88,7 @@ private: void kick(PlayerID player); PlayerID getPlayerIDFromEndpoint(); PlayerID getPlayerIDFromEntityID(EntityID entityID); + void resetMap(); void parsePlayerTransform(Packet& packet); void parseOnInputCommand(Packet& packet); void parseClientPing(); @@ -110,6 +116,8 @@ private: bool OnAmmoPickup(const Events::AmmoPickup& e); EventRelay m_EPlayerDeath; bool OnPlayerDeath(const Events::PlayerDeath& e); + EventRelay m_EWin; + bool OnWin(const Events::Win& e); }; #endif diff --git a/include/Engine/Network/UDPClient.h b/include/Engine/Network/UDPClient.h index 0550b152..174a0c78 100644 --- a/include/Engine/Network/UDPClient.h +++ b/include/Engine/Network/UDPClient.h @@ -1,5 +1,7 @@ #ifndef UDPClient_h__ #define UDPClient_h__ +#include +#include #include #include "Network/NetworkClient.h" @@ -13,16 +15,27 @@ public: bool Connect(std::string playerName, std::string address, int port); void Disconnect(); void Receive(Packet& packet); - void Send(Packet & packet); + void ReceivePackets(); + void Send(Packet& packet); void Broadcast(Packet& packet, int port); bool IsSocketAvailable(); + // Returns false if no packets are available + bool GetNextPacket(Packet& packet); private: + typedef std::map>>> PacketMap; // Assio UDP logic boost::asio::io_service m_IOService; boost::asio::ip::udp::endpoint m_ReceiverEndpoint; boost::shared_ptr m_Socket; + int m_LastReceivedSnapshotGroup = 0; int readBuffer(); + void readPartOfPacket(); PacketID m_SendPacketID = 0; + //map:(packetGroup, vector:(pair:(groupIndex, packetData))) + PacketMap m_PacketSegmentMap; + bool hasReceivedPacket(int packetGroup, int groupIndex); + // 2^19 + const int m_SizeOfSocketBuffer = 524288; }; #endif \ No newline at end of file diff --git a/include/Engine/Network/UDPServer.h b/include/Engine/Network/UDPServer.h index 54f4e327..19b5531c 100644 --- a/include/Engine/Network/UDPServer.h +++ b/include/Engine/Network/UDPServer.h @@ -3,6 +3,7 @@ #include "NetworkServer.h" #include +#define MAXPACKETSIZE 64000 class UDPServer : public NetworkServer { @@ -13,6 +14,7 @@ public: void AcceptNewConnections(int& nextPlayerID, std::map& connectedPlayers); void Receive(Packet & packet, PlayerDefinition & playerDefinition); void Send(Packet & packet, PlayerDefinition & playerDefinition); + void SendToConnectedPlayers(Packet & packet, std::map& playersTosendTo); void Send(Packet & packet); void Send(Packet & packet, boost::asio::ip::udp::endpoint endpoint); void Broadcast(Packet & packet, int port); diff --git a/include/Engine/Rendering/CubeMapPass.h b/include/Engine/Rendering/CubeMapPass.h index 02e8e7ba..54bea377 100644 --- a/include/Engine/Rendering/CubeMapPass.h +++ b/include/Engine/Rendering/CubeMapPass.h @@ -3,6 +3,7 @@ #include "IRenderer.h" #include "ShaderProgram.h" +#include "PNG.h" class CubeMapPass { @@ -21,7 +22,7 @@ private: IRenderer* m_Renderer; std::string m_PreviusCubeMapTexture; - std::vector m_CubeMapTextures; + std::vector m_CubeMapTextures; }; #endif \ No newline at end of file diff --git a/include/Engine/Rendering/DirectionalLightJob.h b/include/Engine/Rendering/DirectionalLightJob.h index 5f104ca5..d79eddb0 100644 --- a/include/Engine/Rendering/DirectionalLightJob.h +++ b/include/Engine/Rendering/DirectionalLightJob.h @@ -7,7 +7,7 @@ #include "../GLM.h" #include "../Core/ComponentWrapper.h" #include "RenderJob.h" -#include "../Core/Transform.h" +#include "../Core/TransformSystem.h" #include "../Core/World.h" struct DirectionalLightJob : RenderJob @@ -16,7 +16,7 @@ struct DirectionalLightJob : RenderJob : RenderJob() { - Direction = glm::vec4(0,0,-1,0) * glm::inverse(Transform::AbsoluteOrientation(m_World, transformComponent.EntityID)); + Direction = glm::vec4(0,0,-1,0) * glm::inverse(TransformSystem::AbsoluteOrientation(m_World, transformComponent.EntityID)); //Direction = glm::vec4((glm::vec3)directionalLightComponent["Direction"], 0.f); Color = (glm::vec4)directionalLightComponent["Color"]; Intensity = (double)directionalLightComponent["Intensity"]; diff --git a/include/Engine/Rendering/ExplosionEffectJob.h b/include/Engine/Rendering/ExplosionEffectJob.h index a86b59af..d43c8476 100644 --- a/include/Engine/Rendering/ExplosionEffectJob.h +++ b/include/Engine/Rendering/ExplosionEffectJob.h @@ -18,15 +18,17 @@ struct ExplosionEffectJob : ModelJob ExplosionEffectJob(ComponentWrapper explosionEffectComponent, ::Model* model, Camera* camera, glm::mat4 matrix, ::RawModel::MaterialProperties matGroup, ComponentWrapper modelComponent, ::World* world, glm::vec4 fillColor, float fillPercentage, bool isShielded, bool shadow) : ModelJob(model, camera, matrix, matGroup, modelComponent, world, fillColor, fillPercentage, isShielded, shadow) { - ExplosionOrigin = (glm::vec3)explosionEffectComponent["ExplosionOrigin"]; - TimeSinceDeath = (double)explosionEffectComponent["TimeSinceDeath"]; - ExplosionDuration = (double)explosionEffectComponent["ExplosionDuration"]; - EndColor = (glm::vec4)explosionEffectComponent["EndColor"]; - Randomness = (bool)explosionEffectComponent["Randomness"]; - RandomnessScalar = (double)explosionEffectComponent["RandomnessScalar"]; - Velocity = (glm::vec2)explosionEffectComponent["Velocity"]; - ColorByDistance = (bool)explosionEffectComponent["ColorByDistance"]; - ExponentialAccelaration = (bool)explosionEffectComponent["ExponentialAccelaration"]; + ExplosionOrigin = (Field)explosionEffectComponent["ExplosionOrigin"]; + TimeSinceDeath = (Field)explosionEffectComponent["TimeSinceDeath"]; + ExplosionDuration = (Field)explosionEffectComponent["ExplosionDuration"]; + EndColor = (Field)explosionEffectComponent["EndColor"]; + Randomness = (Field)explosionEffectComponent["Randomness"]; + RandomnessScalar = (Field)explosionEffectComponent["RandomnessScalar"]; + Velocity = (Field)explosionEffectComponent["Velocity"]; + ColorByDistance = (Field)explosionEffectComponent["ColorByDistance"]; + ExponentialAccelaration = (Field)explosionEffectComponent["ExponentialAccelaration"]; + Reverse = (Field)explosionEffectComponent["Reverse"];Reverse = (bool)explosionEffectComponent["Reverse"]; + ColorDistanceScalar = (Field)explosionEffectComponent["ColorDistanceScalar"];ColorDistanceScalar = (double)explosionEffectComponent["ColorDistanceScalar"]; }; glm::vec3 ExplosionOrigin; @@ -38,12 +40,14 @@ struct ExplosionEffectJob : ModelJob glm::vec4 EndColor; bool Randomness = false; - float RandomnessScalar = 1.f; + double RandomnessScalar = 1.f; glm::vec2 Velocity; bool ColorByDistance = false; //bool ReverseAnimation = false; //bool Wireframe = false; bool ExponentialAccelaration = false; + bool Reverse = false; + double ColorDistanceScalar = 1.f; std::array RandomNumbers = { 0.3257552917701f, diff --git a/include/Engine/Rendering/Image.h b/include/Engine/Rendering/Image.h index 19ef43c1..102521ed 100644 --- a/include/Engine/Rendering/Image.h +++ b/include/Engine/Rendering/Image.h @@ -3,6 +3,8 @@ struct Image { + virtual ~Image() = default; + enum class ImageFormat { Unknown, diff --git a/include/Engine/Rendering/ModelJob.h b/include/Engine/Rendering/ModelJob.h index dc4c8cb5..0bb3d1c8 100644 --- a/include/Engine/Rendering/ModelJob.h +++ b/include/Engine/Rendering/ModelJob.h @@ -12,7 +12,7 @@ #include "../Core/ResourceManager.h" #include "Camera.h" #include "../Core/World.h" -#include "../Core/Transform.h" +#include "../Core/TransformSystem.h" #include "Skeleton.h" #include "ShaderProgram.h" #include "BlendTree.h" @@ -26,24 +26,13 @@ struct ModelJob : RenderJob ModelID = model->ResourceID; Type = matProp.type; ::RawModel::MaterialBasic* matGroup = matProp.material; + ShaderID = matProp.ShaderID; switch(matProp.type){ case ::RawModel::MaterialType::Basic: - if (Model->IsSkinned()) { - ShaderID = ResourceManager::Load("#ForwardPlusSkinnedProgram")->ResourceID; - } - else { - ShaderID = ResourceManager::Load("#ForwardPlusProgram")->ResourceID; - } TextureID = 0; break; case ::RawModel::MaterialType::SingleTextures: { - if (Model->IsSkinned()) { - ShaderID = ResourceManager::Load("#ForwardPlusSkinnedProgram")->ResourceID; - } - else { - ShaderID = ResourceManager::Load("#ForwardPlusProgram")->ResourceID; - } ::RawModel::MaterialSingleTextures* singleTextures = static_cast<::RawModel::MaterialSingleTextures*>(matProp.material); TextureID = (singleTextures->ColorMap.Texture) ? singleTextures->ColorMap.Texture->ResourceID : 0; if (modelComponent["DiffuseTexture"]) { @@ -65,12 +54,6 @@ struct ModelJob : RenderJob break; case ::RawModel::MaterialType::SplatMapping: { - if (Model->IsSkinned()) { - ShaderID = ResourceManager::Load("#ForwardPlusSplatMapSkinnedProgram")->ResourceID; - } - else { - ShaderID = ResourceManager::Load("#ForwardPlusSplatMapProgram")->ResourceID; - } ::RawModel::MaterialSplatMapping* SplatTextures = static_cast<::RawModel::MaterialSplatMapping*>(matProp.material); SplatMap = &SplatTextures->SplatMap; diff --git a/include/Engine/Rendering/PointLightJob.h b/include/Engine/Rendering/PointLightJob.h index 4c0a3875..80c8232c 100644 --- a/include/Engine/Rendering/PointLightJob.h +++ b/include/Engine/Rendering/PointLightJob.h @@ -7,7 +7,7 @@ #include "../GLM.h" #include "../Core/ComponentWrapper.h" #include "RenderJob.h" -#include "../Core/Transform.h" +#include "../Core/TransformSystem.h" #include "../Core/World.h" struct PointLightJob : RenderJob @@ -16,7 +16,7 @@ struct PointLightJob : RenderJob : RenderJob() { Position = glm::vec4((glm::vec3)transformComponent["Position"], 1.0f); - Position = glm::vec4(Transform::AbsolutePosition(m_World, transformComponent.EntityID), 1.f); + Position = glm::vec4(TransformSystem::AbsolutePosition(m_World, transformComponent.EntityID), 1.f); Color = (glm::vec4)pointLightComponent["Color"]; Radius = (double)pointLightComponent["Radius"]; Intensity = (double)pointLightComponent["Intensity"]; diff --git a/include/Engine/Rendering/RawModelCustom.h b/include/Engine/Rendering/RawModelCustom.h index ebf8da2b..f9fd18ef 100644 --- a/include/Engine/Rendering/RawModelCustom.h +++ b/include/Engine/Rendering/RawModelCustom.h @@ -18,6 +18,7 @@ #include "../Core/ResourceManager.h" #include "Texture.h" #include "Skeleton.h" +#include "ShaderProgram.h" #include "boost\endian\buffers.hpp" @@ -87,6 +88,7 @@ public: struct MaterialProperties { MaterialType type; MaterialBasic* material; + unsigned int ShaderID = 0; }; const Vertex* Vertices() const { diff --git a/include/Engine/Rendering/RenderSystem.h b/include/Engine/Rendering/RenderSystem.h index fbcf7ec3..74fa6cad 100644 --- a/include/Engine/Rendering/RenderSystem.h +++ b/include/Engine/Rendering/RenderSystem.h @@ -14,7 +14,7 @@ #include "ModelJob.h" #include "Renderer.h" #include "PointLightJob.h" -#include "../Core/Transform.h" +#include "../Core/TransformSystem.h" #include "../Core/EPlayerSpawned.h" #include "../Core/Octree.h" #include "../Collision/EntityAABB.h" diff --git a/include/Engine/Rendering/Renderer.h b/include/Engine/Rendering/Renderer.h index c36ba59a..51cf62e7 100644 --- a/include/Engine/Rendering/Renderer.h +++ b/include/Engine/Rendering/Renderer.h @@ -22,7 +22,7 @@ #include "../Core/EventBroker.h" #include "ImGuiRenderPass.h" #include "Camera.h" -#include "../Core/Transform.h" +#include "../Core/TransformSystem.h" #include "imgui/imgui.h" #include "TextPass.h" #include "Util/CommonFunctions.h" diff --git a/include/Engine/Rendering/SpriteJob.h b/include/Engine/Rendering/SpriteJob.h index 1410a682..b0c16bd4 100644 --- a/include/Engine/Rendering/SpriteJob.h +++ b/include/Engine/Rendering/SpriteJob.h @@ -13,7 +13,7 @@ #include "../Core/ResourceManager.h" #include "Camera.h" #include "../Core/World.h" -#include "../Core/Transform.h" +#include "../Core/TransformSystem.h" #include "Skeleton.h" struct SpriteJob : RenderJob @@ -37,7 +37,7 @@ struct SpriteJob : RenderJob BlurBackground = (bool)cSprite["BlurBackground"]; Entity = cSprite.EntityID; - Position = Transform::AbsolutePosition(world, cSprite.EntityID); + Position = TransformSystem::AbsolutePosition(world, cSprite.EntityID); Depth = 0; if (depthSorted) { glm::vec3 viewpos = glm::vec3(camera->ViewMatrix() * glm::vec4(Position, 1)); @@ -50,7 +50,7 @@ struct SpriteJob : RenderJob FillColor = fillColor; FillPercentage = fillPercentage; - glm::vec3 scale = Transform::AbsoluteScale(world, cSprite.EntityID); + glm::vec3 scale = TransformSystem::AbsoluteScale(world, cSprite.EntityID); if((bool)cSprite["KeepRatio"] == true) { if(scale.y >= scale.x) { diff --git a/include/Engine/Rendering/TextJob.h b/include/Engine/Rendering/TextJob.h index a11761d2..e80359be 100644 --- a/include/Engine/Rendering/TextJob.h +++ b/include/Engine/Rendering/TextJob.h @@ -17,8 +17,8 @@ struct TextJob : RenderJob : RenderJob() { Matrix = matrix; - Color = (glm::vec4)textComponent["Color"]; - Content = (std::string)textComponent["Content"]; + Color = (const glm::vec4&)textComponent["Color"]; + Content = (const std::string&)textComponent["Content"]; Resource = font; if ((int)textComponent["Alignment"] == textComponent["Alignment"].Enum("Left")) { diff --git a/include/Engine/Rendering/TextPass.h b/include/Engine/Rendering/TextPass.h index 8fbb3df0..bb11e5b7 100644 --- a/include/Engine/Rendering/TextPass.h +++ b/include/Engine/Rendering/TextPass.h @@ -23,6 +23,7 @@ public: private: void renderText(std::string text, Font* font, TextJob::AlignmentEnum alignment, glm::vec4 color, glm::mat4 modelMatrix, glm::mat4 projectionMatrix, glm::mat4 viewMatrix); + std::string parseColors(std::string text, std::map& colorChanges, glm::vec4 originalColor); Font* font; GLuint VAO, VBO; diff --git a/include/Engine/Rendering/TextureSprite.h b/include/Engine/Rendering/TextureSprite.h index f8527664..84998a7b 100644 --- a/include/Engine/Rendering/TextureSprite.h +++ b/include/Engine/Rendering/TextureSprite.h @@ -14,8 +14,6 @@ protected: TextureSprite(std::string path); public: - ~TextureSprite(); - void Bind(GLenum textureUnit = GL_TEXTURE0); GLuint m_Texture = 0; diff --git a/include/Engine/Sound/EChangeBGM.h b/include/Engine/Sound/EChangeBGM.h new file mode 100644 index 00000000..e60c58fc --- /dev/null +++ b/include/Engine/Sound/EChangeBGM.h @@ -0,0 +1,16 @@ +#ifndef Events_ChangeBGM_h__ +#define Events_ChangeBGM_h__ + +#include +#include "../Engine/Core/EventBroker.h" + +namespace Events +{ + +struct ChangeBGM : Event +{ + std::string FilePath = ""; +}; + +} +#endif // Events_ChangeBGM_h__ diff --git a/include/Engine/Sound/EPlayAnnouncerVoice.h b/include/Engine/Sound/EPlayAnnouncerVoice.h new file mode 100644 index 00000000..18d1a953 --- /dev/null +++ b/include/Engine/Sound/EPlayAnnouncerVoice.h @@ -0,0 +1,17 @@ +#ifndef Events_PlayAnnouncerVoice_h__ +#define Events_PlayAnnouncerVoice_h__ + +#include +#include "../Engine/Core/EventBroker.h" + +namespace Events +{ + +struct PlayAnonuncerVoice : public Event +{ + std::string FilePath = ""; +}; + +} + +#endif diff --git a/include/Engine/Sound/EPlaySoundOnEntity.h b/include/Engine/Sound/EPlaySoundOnEntity.h index 39dea432..12be68b9 100644 --- a/include/Engine/Sound/EPlaySoundOnEntity.h +++ b/include/Engine/Sound/EPlaySoundOnEntity.h @@ -12,7 +12,8 @@ namespace Events // Sound behavior is thereby specified in the SoundEmitter component. struct PlaySoundOnEntity : public Event { - EntityID EmitterID = 0; + EntityWrapper Emitter = EntityWrapper::Invalid; + float Gain = 1.f; std::string FilePath = ""; }; diff --git a/include/Engine/Sound/ESetAnnouncerGain.h b/include/Engine/Sound/ESetAnnouncerGain.h new file mode 100644 index 00000000..2149be80 --- /dev/null +++ b/include/Engine/Sound/ESetAnnouncerGain.h @@ -0,0 +1,16 @@ +#ifndef Events_SetAnnouncerGain_h__ +#define Events_SetAnnouncerGain_h__ + +#include "../Engine/Core/EventBroker.h" + +namespace Events +{ + +struct SetAnnouncerGain : public Event +{ + float Gain = 1; +}; + +} + +#endif // diff --git a/include/Engine/Sound/SoundManager.h b/include/Engine/Sound/SoundManager.h index 5b027c62..819f74b5 100644 --- a/include/Engine/Sound/SoundManager.h +++ b/include/Engine/Sound/SoundManager.h @@ -9,32 +9,35 @@ #include "OpenAL/al.h" #include "OpenAL/alc.h" -#include "imgui/imgui.h" - -#include "Core/World.h" -#include "Core/EventBroker.h" +#include "../Engine/Core/World.h" +#include "../Engine/Core/EventBroker.h" #include "../Engine/Core/ResourceManager.h" #include "../Engine/Core/ConfigFile.h" -#include "Core/Transform.h" // Absolute transform -#include "Sound/Sound.h" +#include "../Engine/Core/TransformSystem.h" +#include "../Engine/Sound/Sound.h" #include "../Engine/Sound/EPlayQueueOnEntity.h" -#include "Sound/EPlaySoundOnEntity.h" -#include "Sound/EPlaySoundOnPosition.h" -#include "Sound/EPlayBackgroundMusic.h" -#include "Sound/EPauseSound.h" -#include "Sound/EContinueSound.h" -#include "Sound/EStopSound.h" -#include "Sound/ESetBGMGain.h" -#include "Sound/ESetSFXGain.h" -#include "Core/EPause.h" -#include "Core/EComponentAttached.h" +#include "../Engine/Sound/EPlaySoundOnEntity.h" +#include "../Engine/Sound/EPlaySoundOnPosition.h" +#include "../Engine/Sound/EPlayBackgroundMusic.h" +#include "../Engine/Sound/EPlayAnnouncerVoice.h" +#include "../Engine/Sound/EPauseSound.h" +#include "../Engine/Sound/EContinueSound.h" +#include "../Engine/Sound/EStopSound.h" +#include "../Engine/Sound/ESetBGMGain.h" +#include "../Engine/Sound/ESetSFXGain.h" +#include "../Engine/Sound/ESetAnnouncerGain.h" +#include "../Engine/Sound/EChangeBGM.h" +#include "../Engine/Core/EPause.h" +#include "../Engine/Core/EComponentAttached.h" #include "../Core/EPlayerSpawned.h" + typedef std::pair> QueuedBuffers; enum class SoundType { SFX, - BGM + BGM, + Announcer }; struct Source @@ -43,6 +46,7 @@ struct Source Sound* SoundResource = nullptr; ALuint ALsource; SoundType Type; + float Duration; }; class SoundManager @@ -74,14 +78,20 @@ private: ALenum getSourceState(ALuint source); void setGain(Source* source, float gain); void setSoundProperties(Source* source, ComponentWrapper* soundComponent); + float getDurationSeconds(Source* source); + float getTimeOffsetSeconds(Source* source); // Specific logic void playSound(Source* source); - // Need to be the same format (sample rate etc) + // Needs to be the same format (sample rate etc) void playQueue(QueuedBuffers qb); void stopSound(Source* source); Source* createSource(std::string filePath); std::unordered_map m_Sources; + void matchBGMLoop(); + Source* m_CurrentBGM = nullptr; + Source* m_CurrentBGMCombo = nullptr; + bool m_DrumLoopHasBeenStarted = false; // Logic World* m_World = nullptr; @@ -93,6 +103,7 @@ private: float m_BGMVolumeChannel = 1.0f; float m_SFXVolumeChannel = 1.0f; + float m_AnnouncerVolumeChannel = 1.0f; EntityWrapper m_LocalPlayer = EntityWrapper(); // Events @@ -102,6 +113,8 @@ private: bool OnPlaySoundOnPosition(const Events::PlaySoundOnPosition &e); EventRelay m_EPlayBackgroundMusic; bool OnPlayBackgroundMusic(const Events::PlayBackgroundMusic &e); + EventRelay m_EPlayAnnouncerVoice; + bool OnPlayAnnouncerVoice(const Events::PlayAnonuncerVoice& e); EventRelay m_EPauseSound; bool OnPauseSound(const Events::PauseSound &e); EventRelay m_EStopSound; @@ -112,6 +125,8 @@ private: bool OnSetBGMGain(const Events::SetBGMGain &e); EventRelay m_ESetSFXGain; bool OnSetSFXGain(const Events::SetSFXGain &e); + EventRelay m_ESetAnnouncerGain; + bool OnSetAnnouncerGain(const Events::SetAnnouncerGain& e); EventRelay m_EComponentAttached; bool OnComponentAttached(const Events::ComponentAttached &e); EventRelay m_EPause; @@ -122,6 +137,8 @@ private: bool OnPlayerSpawned(const Events::PlayerSpawned &e); EventRelay m_EPlayQueueOnEntity; bool OnPlayQueueOnEntity(const Events::PlayQueueOnEntity &e); + EventRelay m_EChangeBGM; + bool OnChangeBGM(const Events::ChangeBGM &e); }; diff --git a/include/Game/Events/EReset.h b/include/Game/Events/EReset.h new file mode 100644 index 00000000..70fea123 --- /dev/null +++ b/include/Game/Events/EReset.h @@ -0,0 +1,16 @@ +#ifndef Events_Reset_h__ +#define Events_Reset_h__ + +#include "Core/EventBroker.h" +#include "Core/EntityWrapper.h" + +namespace Events +{ + +struct Reset : Event +{ +}; + +} + +#endif \ No newline at end of file diff --git a/include/Game/Systems/AmmoPickupSystem.h b/include/Game/Systems/AmmoPickupSystem.h index 1e61dd32..2276f071 100644 --- a/include/Game/Systems/AmmoPickupSystem.h +++ b/include/Game/Systems/AmmoPickupSystem.h @@ -2,7 +2,7 @@ #define AmmoPickupSystem_h__ #include "Core/System.h" -#include "Core/Transform.h" +#include "Core/TransformSystem.h" #include "Core/ResourceManager.h" #include "Core/EntityFile.h" #include "Core/EPickupSpawned.h" diff --git a/include/Game/Systems/CapturePointArrowHUDSystem.h b/include/Game/Systems/CapturePointArrowHUDSystem.h index 26462879..9f71e290 100644 --- a/include/Game/Systems/CapturePointArrowHUDSystem.h +++ b/include/Game/Systems/CapturePointArrowHUDSystem.h @@ -7,7 +7,7 @@ #include "Common.h" #include "Core/System.h" -#include "Core/Transform.h" +#include "Core/TransformSystem.h" #include "Core/ECaptured.h" diff --git a/include/Game/Systems/CapturePointSystem.h b/include/Game/Systems/CapturePointSystem.h index 3cf72e15..0cba5401 100644 --- a/include/Game/Systems/CapturePointSystem.h +++ b/include/Game/Systems/CapturePointSystem.h @@ -9,6 +9,7 @@ #include "Engine/Collision/ETrigger.h" #include "Core/ECaptured.h" #include "Core/EWin.h" +#include "Game/Events/EReset.h" #include #include @@ -23,6 +24,7 @@ public: virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& capturePoint, double dt) override; private: + void Init(); //methods which will take care of specific events EventRelay m_ETriggerTouch; bool CapturePointSystem::OnTriggerTouch(const Events::TriggerTouch& e); @@ -30,6 +32,9 @@ private: bool CapturePointSystem::OnTriggerLeave(const Events::TriggerLeave& e); EventRelay m_ECaptured; bool CapturePointSystem::OnCaptured(const Events::Captured& e); + EventRelay m_EReset; + bool CapturePointSystem::OnReset(const Events::Reset& e); + void ChangeCapturePointModelsVisibility(EntityWrapper &capturePointModels, bool isOwner); bool m_WinnerWasFound = false; //need to track these variables for the captureSystem to work as per design! diff --git a/include/Game/Systems/DamageIndicatorSystem.h b/include/Game/Systems/DamageIndicatorSystem.h index f3a95817..9caf4463 100644 --- a/include/Game/Systems/DamageIndicatorSystem.h +++ b/include/Game/Systems/DamageIndicatorSystem.h @@ -2,7 +2,7 @@ #define DamageIndicatorSystem_h__ #include "Core/System.h" -#include "Core/Transform.h" +#include "Core/TransformSystem.h" #include "Core/ResourceManager.h" #include "Core/EntityFile.h" #include "Core/EPlayerDamage.h" diff --git a/include/Game/Systems/ExplosionEffectSystem.h b/include/Game/Systems/ExplosionEffectSystem.h index 24eee955..d2eafa15 100644 --- a/include/Game/Systems/ExplosionEffectSystem.h +++ b/include/Game/Systems/ExplosionEffectSystem.h @@ -3,6 +3,7 @@ #include "Common.h" #include "Core/System.h" +#include "Engine/GLM.h" class ExplosionEffectSystem : public PureSystem { diff --git a/include/Game/Systems/FloatingEffectSystem.h b/include/Game/Systems/FloatingEffectSystem.h index 56931001..942c75d0 100644 --- a/include/Game/Systems/FloatingEffectSystem.h +++ b/include/Game/Systems/FloatingEffectSystem.h @@ -12,8 +12,8 @@ public: virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) override { ComponentWrapper& transform = m_World->GetComponent(component.EntityID, "Transform"); - (double&)component["Time"] += dt; - (glm::vec3&)transform["Position"] = (float)(double)component["Amplitude"] * glm::sin((glm::two_pi() / (float)(double)component["Period"]) * (float)(double)component["Time"]) * (glm::vec3)component["Axis"]; + (Field)component["Time"] += dt; + (Field)transform["Position"] = (float)(double)component["Amplitude"] * glm::sin((glm::two_pi() / (float)(double)component["Period"]) * (float)(double)component["Time"]) * (glm::vec3)component["Axis"]; } }; \ No newline at end of file diff --git a/include/Game/Systems/MainMenuSystem.h b/include/Game/Systems/MainMenuSystem.h index ddefcbf4..2e85df97 100644 --- a/include/Game/Systems/MainMenuSystem.h +++ b/include/Game/Systems/MainMenuSystem.h @@ -7,7 +7,6 @@ #include "Core/Event.h" #include "Systems/SpawnerSystem.h" - #include "GUI/EButtonClicked.h" #include "GUI/EButtonPressed.h" #include "GUI/EButtonReleased.h" @@ -24,6 +23,8 @@ public: private: IRenderer* m_Renderer; + void OpenSubMenu(const Events::InputCommand& e); + void OpenDropDown(const Events::InputCommand& e); EventRelay m_EClicked; bool OnButtonClick(const Events::ButtonClicked& e); @@ -36,6 +37,7 @@ private: std::string m_CurrentCommand = ""; EntityWrapper m_OpenSubMenu = EntityWrapper::Invalid; + EntityWrapper m_DropDown = EntityWrapper::Invalid; }; diff --git a/include/Game/Systems/PickupSpawnSystem.h b/include/Game/Systems/PickupSpawnSystem.h index b72b8b25..de1fa024 100644 --- a/include/Game/Systems/PickupSpawnSystem.h +++ b/include/Game/Systems/PickupSpawnSystem.h @@ -2,7 +2,7 @@ #define PickupSpawnSystem_h__ #include "Core/System.h" -#include "Core/Transform.h" +#include "Core/TransformSystem.h" #include "Core/ResourceManager.h" #include "Core/EntityFile.h" #include "Core/EPickupSpawned.h" diff --git a/include/Game/Systems/PlayerMovementSystem.h b/include/Game/Systems/PlayerMovementSystem.h index 6ad52a95..feb1951e 100644 --- a/include/Game/Systems/PlayerMovementSystem.h +++ b/include/Game/Systems/PlayerMovementSystem.h @@ -33,7 +33,7 @@ private: // Used to track afterimages for sprint effect. float m_SprintEffectTimer; // The logic for making the sound play when player is moving - void playerStep(double dt); + void playerStep(double dt, EntityWrapper player); // Spawn a hexagon at origin of an Entity void spawnHexagon(EntityWrapper target); diff --git a/include/Game/Systems/RaptorCopterSystem.h b/include/Game/Systems/RaptorCopterSystem.h index b3589dcd..7bc28422 100644 --- a/include/Game/Systems/RaptorCopterSystem.h +++ b/include/Game/Systems/RaptorCopterSystem.h @@ -1,6 +1,25 @@ #include "Common.h" #include "Core/System.h" + + + //struct FSubscriptProxy + // { + // friend struct ComponentWrapper; + // FSubscriptProxy(ComponentWrapper* component, std::string fieldName) + // : m_Component(component) + // , m_FieldName(fieldName) + // { } + + // ComponentWrapper* m_Component; + // std::string m_FieldName; + + // public: + // template + // operator Field() { return Field(m_Component->Field(m_FieldName)); } + + // }; + class RaptorCopterSystem : public PureSystem { public: @@ -9,9 +28,11 @@ public: , PureSystem("RaptorCopter") { } - virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) override + virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& cRaptorCopter, double dt) override { - ComponentWrapper& transform = m_World->GetComponent(component.EntityID, "Transform"); - (glm::vec3&)transform["Orientation"] += (float)(double)component["Speed"] * (float)dt * (glm::vec3)component["Axis"]; + ComponentWrapper& cTransform = entity["Transform"]; + //FSubscriptProxy subOri(&cTransform, "Orientation"); + //Field orientation = subOri; + (Field)cTransform["Orientation"] += (float)(const double&)cRaptorCopter["Speed"] * (float)dt * (glm::vec3)cRaptorCopter["Axis"]; } }; \ No newline at end of file diff --git a/include/Game/Systems/ScoreScreenSystem.h b/include/Game/Systems/ScoreScreenSystem.h index 2559bfb3..6b2bb113 100644 --- a/include/Game/Systems/ScoreScreenSystem.h +++ b/include/Game/Systems/ScoreScreenSystem.h @@ -8,6 +8,8 @@ #include "Core/EPlayerSpawned.h" #include "Network/EPlayerConnected.h" #include "Network/EPlayerDisconnected.h" +#include "Game/Events/EReset.h" +#include "Engine/Input/EInputCommand.h" #include "GLM.h" class ScoreScreenSystem : public PureSystem @@ -25,6 +27,10 @@ public: bool OnPlayerConnected(const Events::PlayerConnected& e); EventRelay m_EPlayerDisconnected; bool OnPlayerDisconnected(const Events::PlayerDisconnected& e); + EventRelay m_EReset; + bool OnReset(const Events::Reset& e); + EventRelay m_EInputCommand; + bool OnInputCommand(const Events::InputCommand& e); private: struct PlayerData { diff --git a/include/Game/Systems/SoundSystem.h b/include/Game/Systems/SoundSystem.h index 962eb085..4852f01a 100644 --- a/include/Game/Systems/SoundSystem.h +++ b/include/Game/Systems/SoundSystem.h @@ -2,6 +2,7 @@ #define Systems_SoundSystem_h__ #include +#include #include "../Engine/Core/System.h" #include "../Engine/Core/ResourceManager.h" @@ -20,9 +21,10 @@ #include "../Engine/Collision/ETrigger.h" #include "../Engine/Sound/EPlaySoundOnEntity.h" #include "../Engine/Sound/EPlayBackgroundMusic.h" +#include "../Engine/Sound/EPlayAnnouncerVoice.h" #include "../Game/Events/EDoubleJump.h" #include "../Game/Events/EDashAbility.h" - +#include "../Engine/Sound/EChangeBGM.h" class SoundSystem : public PureSystem, ImpureSystem { @@ -33,14 +35,10 @@ public: private: std::string m_Announcer = ""; // Logic for playing a sound when a player jumps - void playerJumps(); - - // Temporary solution for play test. - bool m_DrumsIsPlaying = false; - double m_DrumTimer = 0.0; - bool drumTimer(double dt); + void playerJumps(EntityWrapper player); - std::default_random_engine generator; + std::default_random_engine m_RandomGenerator; + std::uniform_int_distribution m_RandIntDistribution; EventRelay m_EPlayerSpawned; bool OnPlayerSpawned(const Events::PlayerSpawned &e); @@ -48,10 +46,6 @@ private: bool OnInputCommand(const Events::InputCommand &e); EventRelay m_EDoubleJump; bool OnDoubleJump(const Events::DoubleJump &e); - EventRelay m_EDashAbility; - bool OnDashAbility(const Events::DashAbility &e); - EventRelay m_ETriggerTouch; - bool OnTriggerTouch(const Events::TriggerTouch &e); EventRelay m_ECaptured; bool OnCaptured(const Events::Captured &e); EventRelay m_EPlayerDamage; diff --git a/include/Game/Systems/SpawnerSystem.h b/include/Game/Systems/SpawnerSystem.h index f36f7259..c5b5b7b8 100644 --- a/include/Game/Systems/SpawnerSystem.h +++ b/include/Game/Systems/SpawnerSystem.h @@ -6,7 +6,7 @@ #include "GLM.h" #include "Core/System.h" #include "Events/ESpawnerSpawn.h" -#include "Core/Transform.h" +#include "Core/TransformSystem.h" #include "Core/EntityFile.h" class SpawnerSystem : public System diff --git a/include/Game/Systems/SpectatorCameraSystem.h b/include/Game/Systems/SpectatorCameraSystem.h index 5a00279b..6ba7294d 100644 --- a/include/Game/Systems/SpectatorCameraSystem.h +++ b/include/Game/Systems/SpectatorCameraSystem.h @@ -3,6 +3,8 @@ #include "Core/System.h" #include "Input/EInputCommand.h" +#include "Network/EPlayerDisconnected.h" +#include "Game/Events/EReset.h" class SpectatorCameraSystem : public ImpureSystem { @@ -14,9 +16,14 @@ public: private: int m_PickedTeam; bool m_CamSetToTeamPick; + void reset(); EventRelay m_EInputCommand; bool OnInputCommand(const Events::InputCommand& e); + EventRelay m_EDisconnect; + bool OnDisconnect(const Events::PlayerDisconnected& e); + EventRelay m_EReset; + bool OnReset(const Events::Reset& e); }; #endif \ No newline at end of file diff --git a/include/Game/Systems/Weapon/DefenderWeaponBehaviour.h b/include/Game/Systems/Weapon/DefenderWeaponBehaviour.h index 51f9c2cd..0035d5eb 100644 --- a/include/Game/Systems/Weapon/DefenderWeaponBehaviour.h +++ b/include/Game/Systems/Weapon/DefenderWeaponBehaviour.h @@ -5,6 +5,7 @@ #include "Collision/Collision.h" #include "Core/EPlayerDamage.h" #include "Sound/EPlaySoundOnEntity.h" +#include "Sound/EPlaySoundOnEntity.h" #include class DefenderWeaponBehaviour : public WeaponBehaviour diff --git a/include/Game/Systems/Weapon/WeaponBehaviour.h b/include/Game/Systems/Weapon/WeaponBehaviour.h index 6d13e741..bafc907e 100644 --- a/include/Game/Systems/Weapon/WeaponBehaviour.h +++ b/include/Game/Systems/Weapon/WeaponBehaviour.h @@ -270,7 +270,8 @@ private: EntityWrapper thirdPersonAttachment; for (auto& attachment : weaponAttachments) { ComponentWrapper cWeaponAttachment = attachment["WeaponAttachment"]; - if ((std::string&)cWeaponAttachment["Weapon"] == m_ComponentType) { + Field weaponType = cWeaponAttachment["Weapon"]; + if (*weaponType == m_ComponentType) { ComponentWrapper::SubscriptProxy person = cWeaponAttachment["Person"]; if ((ComponentInfo::EnumType)person == person.Enum("FirstPerson")) { firstPersonAttachment = attachment; diff --git a/resources/DefaultConfig.ini b/resources/DefaultConfig.ini index 5daddb56..be4b7324 100644 --- a/resources/DefaultConfig.ini +++ b/resources/DefaultConfig.ini @@ -39,6 +39,7 @@ ResourceLoading=true [Sound] BGMVolume=1.0 SFXVolume=1.0 +AnnouncerVolume=1.0 Announcer=female [SSAO] diff --git a/resources/DefaultInput.ini b/resources/DefaultInput.ini index 18fb943f..840e5cd0 100644 --- a/resources/DefaultInput.ini +++ b/resources/DefaultInput.ini @@ -29,4 +29,6 @@ K=TakeDamage,1500 F2=PerformanceTimingResetAllTimers F3=PerformanceTimingCreateExcelData Comma=SwapToClassPick -Period=SwapToTeamPick \ No newline at end of file +Period=SwapToTeamPick +Enter=PickClass,1 +F5=DisconnectFromServer \ No newline at end of file diff --git a/resources/Schema/Components.xsd b/resources/Schema/Components.xsd index aa303da9..9e252c27 100644 --- a/resources/Schema/Components.xsd +++ b/resources/Schema/Components.xsd @@ -68,6 +68,8 @@ + + \ No newline at end of file diff --git a/resources/Schema/Components/CapturePointGameMode.xml b/resources/Schema/Components/CapturePointGameMode.xml index 3104e71f..f8e04eaf 100644 --- a/resources/Schema/Components/CapturePointGameMode.xml +++ b/resources/Schema/Components/CapturePointGameMode.xml @@ -2,4 +2,5 @@ 0.0 8.0 + 10.0 \ No newline at end of file diff --git a/resources/Schema/Components/CapturePointGameMode.xsd b/resources/Schema/Components/CapturePointGameMode.xsd index 8b81d67a..791b75b1 100644 --- a/resources/Schema/Components/CapturePointGameMode.xsd +++ b/resources/Schema/Components/CapturePointGameMode.xsd @@ -12,6 +12,9 @@ Players will be spawned when RespawnTime reaches this. + + The map will be reset when time reaches 0. + diff --git a/resources/Schema/Components/ConfigBtnFloat.xml b/resources/Schema/Components/ConfigBtnFloat.xml new file mode 100644 index 00000000..f9d4478e --- /dev/null +++ b/resources/Schema/Components/ConfigBtnFloat.xml @@ -0,0 +1,6 @@ + + +
+ + +
\ No newline at end of file diff --git a/resources/Schema/Components/ConfigBtnFloat.xsd b/resources/Schema/Components/ConfigBtnFloat.xsd new file mode 100644 index 00000000..69b36bd2 --- /dev/null +++ b/resources/Schema/Components/ConfigBtnFloat.xsd @@ -0,0 +1,22 @@ + + + + + + + Used with a Button component, this button will change a variable in the config file. + + + + The header of the section in config. + + + The name of the field to be changed in the config. + + + The value to give the field. + + + + + \ No newline at end of file diff --git a/resources/Schema/Components/ConfigBtnResolution.xml b/resources/Schema/Components/ConfigBtnResolution.xml new file mode 100644 index 00000000..9a586518 --- /dev/null +++ b/resources/Schema/Components/ConfigBtnResolution.xml @@ -0,0 +1,6 @@ + + +
+ + +
\ No newline at end of file diff --git a/resources/Schema/Components/ConfigBtnResolution.xsd b/resources/Schema/Components/ConfigBtnResolution.xsd new file mode 100644 index 00000000..d5d6b723 --- /dev/null +++ b/resources/Schema/Components/ConfigBtnResolution.xsd @@ -0,0 +1,17 @@ + + + + + Used with a Button component, this button will change a variable in the config file. + + + + Value of the resolution width. + + + Value of the resolution height. + + + + + \ No newline at end of file diff --git a/resources/Schema/Components/ExplosionEffect.xml b/resources/Schema/Components/ExplosionEffect.xml index 0b4a44c4..80022738 100644 --- a/resources/Schema/Components/ExplosionEffect.xml +++ b/resources/Schema/Components/ExplosionEffect.xml @@ -1,19 +1,21 @@ - 0 - 2 + 0.0 + 2.0 1 0 - 0 - 1 + false + 1.0 - 0 - + false - 0 + false + false + false + 1.0 \ No newline at end of file diff --git a/resources/Schema/Components/ExplosionEffect.xsd b/resources/Schema/Components/ExplosionEffect.xsd index bd29b2ed..f0edcc8e 100644 --- a/resources/Schema/Components/ExplosionEffect.xsd +++ b/resources/Schema/Components/ExplosionEffect.xsd @@ -44,15 +44,21 @@ Change the color by its moved distance instead of by its time - Linear/Exponential accelaration + + Pulsate the effect + + + Reverse the effect + + + Scale the distance of the color change + diff --git a/resources/Schema/Components/SoundEmitter.xml b/resources/Schema/Components/SoundEmitter.xml index e0a38d2f..f74183c2 100644 --- a/resources/Schema/Components/SoundEmitter.xml +++ b/resources/Schema/Components/SoundEmitter.xml @@ -4,7 +4,7 @@ 1.0 1.0 false - 20.0 - 1.0 + 220.0 + 10 1.0 \ No newline at end of file diff --git a/resources/Schema/Components/Sprite.xml b/resources/Schema/Components/Sprite.xml index a1963ff8..9ba27381 100644 --- a/resources/Schema/Components/Sprite.xml +++ b/resources/Schema/Components/Sprite.xml @@ -9,6 +9,6 @@ false false false - false + true false diff --git a/resources/Schema/Entities/AmmoPickup.xml b/resources/Schema/Entities/AmmoPickup.xml index ee3704f1..a8415489 100644 --- a/resources/Schema/Entities/AmmoPickup.xml +++ b/resources/Schema/Entities/AmmoPickup.xml @@ -2,21 +2,26 @@ - - - Models/Props/PickUps/AmmoPickUp.mesh - + 8 + + Models/Props/PickUps/AmmoPickUp.mesh + + + + + 1.5 + 3 + - + + - - diff --git a/resources/Schema/Entities/CP_Rocky.xml b/resources/Schema/Entities/CP_Rocky.xml deleted file mode 100644 index d034be78..00000000 --- a/resources/Schema/Entities/CP_Rocky.xml +++ /dev/null @@ -1,5317 +0,0 @@ - - - - - - - - - - - - - - - - - - Models/Props/GroundTest.mesh - - - - - - - - - - Models/Props/Highground5.mesh - - - - - - - - - - Models/Props/Highground6.mesh - - - - - - - - - - - Models/Props/Highground7.mesh - - - - - - - - - - - - Models/Props/Walls/SciFiWallTop.mesh - - - - - - - - - Models/Props/Walls/SciFiWallSmall1.mesh - - - - - - - - - - Models/Props/Walls/SciFiWallBig.mesh - true - - - - - - - - - - Models/Props/Walls/SciFiWallBig.mesh - - - - - - - - - - - - Models/Props/Walls/SciFiWallMedium.mesh - - - - - - - - - - Models/Props/Walls/SciFiWallSmall2.mesh - - - - - - - - - - Models/Props/Walls/SciFiWallMedium.mesh - - - - - - - - - - - - Models/Props/Walls/SciFiWallSmall3.mesh - - - - - - - - - - Models/Props/Walls/SciFiWallSmall4.mesh - - - - - - - - - Schema/Entities/ScoreBoard_Main.xml - - - - - - - - - - - - - - - - Models/Core/UnitCube.mesh - - - - - - - - - - - - - - - - - - - - - - - - Models/Core/UnitCube.mesh - - - - - - - - - - - Schema/Entities/ScoreBoard_Blue.xml - - - - - - - - - - - - - - - Models/Core/UnitCube.mesh - - - - - - - - - - - - - - - - - - - - - - - - - - - - ID - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - - - - Name - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - - - - KD - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - - - - Kills - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - - - - Deaths - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - - - - - - - - - - Schema/Entities/ScoreBoard_Red.xml - - - - - - - - - - - - - - - Models/Core/UnitCube.mesh - - - - - - - - - - - - - - - - - - - - - - - - - - - - ID - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - - - - Name - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - - - - KD - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - - - - Kills - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - - - - Deaths - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - - - - - - - - - - - - - - Schema/Entities/ScoreBoard_Main.xml - - - - - - - - - - - - - - - - Models/Core/UnitCube.mesh - - - - - - - - - - - - - - - - - - - - - - - - Models/Core/UnitCube.mesh - - - - - - - - - - - Schema/Entities/ScoreBoard_Red.xml - - - - - - - - - - - - - - - Models/Core/UnitCube.mesh - - - - - - - - - - - - - - - - - - - - - - - - - - - - ID - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - - - - Name - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - - - - KD - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - - - - Kills - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - - - - Deaths - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - - - - - - - - - - Schema/Entities/ScoreBoard_Blue.xml - - - - - - - - - - - - - - - Models/Core/UnitCube.mesh - - - - - - - - - - - - - - - - - - - - - - - - - - - - ID - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - - - - Name - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - - - - KD - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - - - - Kills - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - - - - Deaths - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - - - - - - - - - - - - - - - - - Models/Props/Highground1.mesh - - - - - - - - - - Models/Props/Highground2.mesh - - - - - - - - - - - Models/Props/Highground3.mesh - - - - - - - - - - - Models/Props/Highground4.mesh - - - - - - - - - - - Models/Props/Highground8.mesh - - - - - - - - - - - - - Models/Props/Highground9.mesh - - - - - - - - - - - - - Models/Props/Highground10.mesh - - - - - - - - - - - - - Models/Props/Highground6.mesh - - - - - - - - - - - - - Models/Props/Highground1.mesh - - - - - - - - - - - - Models/Props/Highground2.mesh - - - - - - - - - - - - - Models/Props/Highground3.mesh - - - - - - - - - - - - - Models/Props/Highground4.mesh - - - - - - - - - - - - - Models/Props/Highground5.mesh - - - - - - - - - - - - - - - - - - - - - - Models/Props/Pillars/SciFiPillar2Blue.mesh - - - - - - - - - - - - - - 6 - Models/Props/Pillars/SciFiPillar1Blue.mesh - - - - - - - - - - - - - 6 - Models/Props/Pillars/SciFiPillar1Red.mesh - - - - - - - - - - - - - 4 - Models/Props/Pillars/SciFiPillar2Red.mesh - - - - - - - - - - - - - 6 - Models/Props/Pillars/SciFiPillar3Blue.mesh - - - - - - - - - - - - - - 6 - Models/Props/Pillars/SciFiPillar1Blue.mesh - - - - - - - - - - - - - - 4 - Models/Props/Pillars/SciFiPillar1Red.mesh - - - - - - - - - - - - - - 4 - Models/Props/Pillars/SciFiPillar3Red.mesh - - - - - - - - - - - - - - Models/Props/Pillars/SciFiPillar2Blue.mesh - - - - - - - - - - - - - 6 - Models/Props/Pillars/SciFiPillar2Red.mesh - - - - - - - - - - - - - 6 - Models/Props/Pillars/SciFiPillar2Blue.mesh - - - - - - - - - - - - - - 6 - Models/Props/Pillars/SciFiPillar2Blue.mesh - - - - - - - - - - - - - - 6 - Models/Props/Pillars/SciFiPillar2Blue.mesh - - - - - - - - - - - - - 4 - Models/Props/Pillars/SciFiPillar2Red.mesh - - - - - - - - - - - - - - 6 - Models/Props/Pillars/SciFiPillar2Red.mesh - - - - - - - - - - - - - 6 - Models/Props/Pillars/SciFiPillar2Red.mesh - - - - - - - - - - - - - - 6 - Models/Props/Pillars/SciFiPillar2Red.mesh - - - - - - - - - - - - - - - - - - - - - - - - - 5 - Models/Props/Stones/ShinyStoneCrystalRed.mesh - - - - - - - - - - - - - - 6 - Models/Props/Stones/ShinyStoneCrystalRed.mesh - - - - - - - - - - - - - 2 - - - - - - - - - - - - - - 6 - Models/Props/Stones/ShinyStoneCrystalRed.mesh - - - - - - - - - - - - - - 6 - Models/Props/Stones/ShinyStoneCrystalRed.mesh - - - - - - - - - - - - - - 6 - Models/Props/Stones/ShinyStoneCrystalRed.mesh - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2 - - - - - - - - - - - - - - 6 - Models/Props/Stones/ShinyStoneCrystalRed.mesh - - - - - - - - - - - - - - 6 - Models/Props/Stones/ShinyStoneCrystalRed.mesh - - - - - - - - - - - - - 4 - Models/Props/Stones/ShinyStoneCrystalRed.mesh - - - - - - - - - - - - - - 2 - 1 - - - - - - - - - - - - 2 - - - - - - - - - - - - 3 - - - - - - - - - - - - - - - - - - - - Models/Props/PickUps/PickUpHolder.mesh - - - - - - - - - - - - 2 - - - - - - - - - - - - - - 8 - - - - Models/Props/PickUps/HealthPickUp.mesh - - - - - - - - - - - - - - - - - Models/Props/PickUps/PickUpHolder.mesh - - - - - - - - - - - - 2 - - - - - - - - - - - - - - 8 - - - - Models/Props/PickUps/HealthPickUp.mesh - - - - - - - - - - - - - - - - - Models/Props/PickUps/PickUpHolder.mesh - - - - - - - - - - - - 2 - - - - - - - - - - - - - - 8 - - - - Models/Props/PickUps/AmmoPickUp.mesh - - - - - - - - - - - - - - - - - Models/Props/PickUps/PickUpHolder.mesh - - - - - - - - - - - - 2 - - - - - - - - - - - - - - 8 - - - - Models/Props/PickUps/AmmoPickUp.mesh - - - - - - - - - - - - - - - - - Models/Props/PickUps/PickUpHolder.mesh - - - - - - - - - - - - 2 - - - - - - - - - - - - - - 8 - - - - Models/Props/PickUps/HealthPickUp.mesh - - - - - - - - - - - - - - - - - Models/Props/PickUps/PickUpHolder.mesh - - - - - - - - - - - - 2 - - - - - - - - - - - - - - 8 - - - - Models/Props/PickUps/HealthPickUp.mesh - - - - - - - - - - - - - - - - - Models/Props/PickUps/PickUpHolder.mesh - - - - - - - - - - - - 2 - - - - - - - - - - - - - - 8 - - - - Models/Props/PickUps/AmmoPickUp.mesh - - - - - - - - - - - - - - - - - - - - - - - - - Models/Props/Stones/BigStone.mesh - - - - - - - - - - - - Models/Props/Stones/MediumStone2.mesh - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - - - Models/Props/Stones/BigStone.mesh - - - - - - - - - - - - - - Models/Props/Stones/BigStone.mesh - - - - - - - - - - - - - Models/Props/Stones/MediumStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/MediumStone2.mesh - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - - - Models/Props/Stones/MediumStone2.mesh - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - - - Models/Props/Stones/MediumStone1.mesh - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - - - Models/Props/Stones/BigStone.mesh - - - - - - - - - - - - - Models/Props/Stones/BigStone.mesh - - - - - - - - - - - - - Models/Props/Stones/MediumStone2.mesh - - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/BigStone.mesh - - - - - - - - - - - - - Models/Props/Stones/MediumStone1.mesh - - - - - - - - - - - - - Models/Props/Stones/BigStone.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - - - Models/Props/Stones/MediumStone2.mesh - - - - - - - - - - - - - - Models/Props/Stones/MediumStone1.mesh - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/BigStone.mesh - - - - - - - - - - - - - Models/Props/Stones/MediumStone2.mesh - - - - - - - - - - - - - - Models/Props/Stones/BigStone.mesh - - - - - - - - - - - - - Models/Props/Stones/BigStone.mesh - - - - - - - - - - - - - Models/Props/Stones/MediumStone1.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - - - - - - - - - - - Models/Props/Bridges/SciFiBridge1Red.mesh - - - - - - - - - - - - Models/Props/Bridges/SciFiBridgeDefense.mesh - - - - - - - - - - - - Models/Props/Bridges/SciFiBridgeDefense.mesh - - - - - - - - - - - Models/Props/Bridges/SciFiBridgeDefense.mesh - - - - - - - - - - - Models/Props/Bridges/SciFiBridgeDefense.mesh - - - - - - - - - - - - - - - - - - Models/Props/Bridges/SciFiBridgeDefense.mesh - - - - - - - - - - - - Models/Props/Bridges/SciFiBridgeDefense.mesh - - - - - - - - - - - Models/Props/Bridges/SciFiBridgeDefense.mesh - - - - - - - - - - - Models/Props/Bridges/SciFiBridgeDefense.mesh - - - - - - - - - - - - - - - - - - - - Models/Props/Bridges/SciFiBridge1Red.mesh - - - - - - - - - - - - Models/Props/Pillars/SciFiBridgePillar1.mesh - - - - - - - - - - - - - - - Models/Props/Pillars/SciFiBridgePillar1.mesh - - - - - - - - - - - - - - Models/Props/Bridges/SciFiBridge1Red.mesh - - - - - - - - - - - - - - - - - - - - - Models/Props/SciFiHolder1.mesh - - - - - - - - - - - - - Models/Props/SciFiHolder1.mesh - - - - - - - - - - - - - - - - - - - - Models/Props/Flora/SpecialRoot.mesh - - - - - - - - - - - - - - - - - - - - Models/Props/Walls/BigWallRed.mesh - - - - - - - - - - - - Models/Props/Walls/BigWallRed.mesh - - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - - Models/Props/Walls/MediumWall2.mesh - - - - - - - - - - - - - Models/Props/Walls/MediumWall2.mesh - - - - - - - - - - - - - Models/Props/Walls/MediumWall2.mesh - - - - - - - - - - - - - Models/Props/Walls/MediumWall2.mesh - - - - - - - - - - - - - Models/Props/Walls/MediumWall1.mesh - - - - - - - - - - - - Models/Props/Walls/MediumWall1.mesh - - - - - - - - - - - - Models/Props/Walls/BigWallRed.mesh - - - - - - - - - - - - Models/Props/Walls/BigWallRed.mesh - - - - - - - - - - - - - - Models/Props/Walls/BigWallBlue.mesh - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - - Models/Core/UnitPlane.mesh - - true - - - - - - - - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - - - - - - - - - - - - 6 - Models/Props/Pillars/SciFiPillar1Red.mesh - - - - - - - - - - - - - - Models/Props/Pillars/StonePillar.mesh - - - - - - - - - - - - - - Models/Props/Pillars/StonePillar.mesh - - - - - - - - - - - - - - Models/Props/Pillars/StonePillar.mesh - - - - - - - - - - - - - - - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - - - - - - - - - - - - - - - Models/Props/PickUps/PickUpHolder.mesh - - - - - - - - - - - - 2 - - - - - - - - - - - - - - 8 - - - - Models/Props/PickUps/HealthPickUp.mesh - - - - - - - - - - - - - - - - - Models/Props/PickUps/PickUpHolder.mesh - - - - - - - - - - - - 2 - - - - - - - - - - - - - - 8 - - - - Models/Props/PickUps/AmmoPickUp.mesh - - - - - - - - - - - - - - - - - - - - - - - - - Models/Props/Stones/BigStone.mesh - - - - - - - - - - - - - Models/Props/Stones/BigStone.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/BigStone.mesh - - - - - - - - - - - - Models/Props/Stones/MediumStone2.mesh - - - - - - - - - - - - - - - - - - - - - - 6 - Models/Props/Stones/ShinyStoneCrystalRed.mesh - - - - - - - - - - - - - - 6 - Models/Props/Stones/ShinyStoneCrystalBlue.mesh - - - - - - - - - - - - - - - - - - - - - Models/Props/Walls/SmallWall2.mesh - - - - - - - - - - - - - Models/Props/Walls/SmallWall2.mesh - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - - Models/Props/Walls/MediumWall1.mesh - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - - - - - - - - - Models/Props/Bridges/SciFiBridge1Blue.mesh - - - - - - - - - - - - Models/Props/Bridges/SciFiBridgeDefense.mesh - - - - - - - - - - - - Models/Props/Bridges/SciFiBridgeDefense.mesh - - - - - - - - - - - Models/Props/Bridges/SciFiBridgeDefense.mesh - - - - - - - - - - - Models/Props/Bridges/SciFiBridgeDefense.mesh - - - - - - - - - - - - - - - - - - Models/Props/Bridges/SciFiBridgeDefense.mesh - - - - - - - - - - - - Models/Props/Bridges/SciFiBridgeDefense.mesh - - - - - - - - - - - Models/Props/Bridges/SciFiBridgeDefense.mesh - - - - - - - - - - - Models/Props/Bridges/SciFiBridgeDefense.mesh - - - - - - - - - - - - - - - - - - - - Models/Props/Pillars/SciFiBridgePillar1.mesh - - - - - - - - - - - - - - Models/Props/Bridges/SciFiBridge1Blue.mesh - - - - - - - - - - - - Models/Props/Pillars/SciFiBridgePillar1.mesh - - - - - - - - - - - - - - - Models/Props/Bridges/SciFiBridge1Blue.mesh - - - - - - - - - - - - - - - - - - - - - Models/Props/SciFiHolder1.mesh - - - - - - - - - - - - - Models/Props/SciFiHolder1.mesh - - - - - - - - - - - - - - Models/Core/UnitPlane.mesh - - true - - - - - - - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - Models/Props/Walls/MediumWall1.mesh - - - - - - - - - - - - Models/Props/Walls/MediumWall2.mesh - - - - - - - - - - - - - Models/Props/Walls/BigWallBlue.mesh - - - - - - - - - - - - Models/Props/Walls/BigWallBlue.mesh - - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - - Models/Props/Walls/MediumWall1.mesh - - - - - - - - - - - - Models/Props/Walls/BigWallRed.mesh - - - - - - - - - - - - Models/Props/Walls/BigWallRed.mesh - - - - - - - - - - - - - - Models/Props/Walls/MediumWall2.mesh - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - Models/Props/Walls/MediumWall2.mesh - - - - - - - - - - - - - Models/Props/Walls/MediumWall2.mesh - - - - - - - - - - - - - Models/Props/Walls/BigWallRed.mesh - - - - - - - - - - - - - - - - - - - - Models/Props/Flora/SpecialRoot.mesh - - - - - - - - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - Models/Props/Stones/MediumStone1.mesh - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - - - - Models/Props/Stones/BigStone.mesh - - - - - - - - - - - - Models/Props/Stones/MediumStone1.mesh - - - - - - - - - - - - - Models/Props/Stones/MediumStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/MediumStone1.mesh - - - - - - - - - - - - - Models/Props/Stones/BigStone.mesh - - - - - - - - - - - - - Models/Props/Stones/MediumStone2.mesh - - - - - - - - - - - - - - Models/Props/Stones/BigStone.mesh - - - - - - - - - - - - - - Models/Props/Stones/MediumStone1.mesh - - - - - - - - - - - - Models/Props/Stones/BigStone.mesh - - - - - - - - - - - - - Models/Props/Stones/MediumStone2.mesh - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - - - Models/Props/Stones/BigStone.mesh - - - - - - - - - - - - - Models/Props/Stones/BigStone.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/MediumStone2.mesh - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - - - Models/Props/Stones/MediumStone2.mesh - - - - - - - - - - - - - - Models/Props/Stones/BigStone.mesh - - - - - - - - - - - - - Models/Props/Stones/BigStone.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/BigStone.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - - - Models/Props/Stones/MediumStone2.mesh - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - - - Models/Props/Stones/BigStone.mesh - - - - - - - - - - - - - Models/Props/Stones/MediumStone2.mesh - - - - - - - - - - - - - - - - - - - - - 6 - Models/Props/Stones/ShinyStoneCrystalBlue.mesh - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2 - - - - - - - - - - - - - - 6 - Models/Props/Stones/ShinyStoneCrystalBlue.mesh - - - - - - - - - - - - - - 6 - Models/Props/Stones/ShinyStoneCrystalBlue.mesh - - - - - - - - - - - - - 2 - - - - - - - - - - - - - - 6 - Models/Props/Stones/ShinyStoneCrystalBlue.mesh - - - - - - - - - - - - - - 6 - Models/Props/Stones/ShinyStoneCrystalBlue.mesh - - - - - - - - - - - - - - 6 - Models/Props/Stones/ShinyStoneCrystalBlue.mesh - - - - - - - - - - - - - 4 - Models/Props/Stones/ShinyStoneCrystalBlue.mesh - - - - - - - - - - - - - - 3 - - - - - - - - - - - - 2 - 1 - - - - - - - - - - - - 2 - - - - - - - - - - - - - - 5 - Models/Props/Stones/ShinyStoneCrystalBlue.mesh - - - - - - - - - - - - - - - - - - - - Models/Props/PickUps/PickUpHolder.mesh - - - - - - - - - - - - 2 - - - - - - - - - - - - - - 8 - - - - Models/Props/PickUps/HealthPickUp.mesh - - - - - - - - - - - - - - - - - Models/Props/PickUps/PickUpHolder.mesh - - - - - - - - - - - - 2 - - - - - - - - - - - - - - 8 - - - - Models/Props/PickUps/HealthPickUp.mesh - - - - - - - - - - - - - - - - - Models/Props/PickUps/PickUpHolder.mesh - - - - - - - - - - - - 2 - - - - - - - - - - - - - - 8 - - - - Models/Props/PickUps/HealthPickUp.mesh - - - - - - - - - - - - - - - - - Models/Props/PickUps/PickUpHolder.mesh - - - - - - - - - - - - 2 - - - - - - - - - - - - - - 8 - - - - Models/Props/PickUps/AmmoPickUp.mesh - - - - - - - - - - - - - - - - - Models/Props/PickUps/PickUpHolder.mesh - - - - - - - - - - - - 2 - - - - - - - - - - - - - - 8 - - - - Models/Props/PickUps/AmmoPickUp.mesh - - - - - - - - - - - - - - - - - Models/Props/PickUps/PickUpHolder.mesh - - - - - - - - - - - - 2 - - - - - - - - - - - - - - 8 - - - - Models/Props/PickUps/HealthPickUp.mesh - - - - - - - - - - - - - - - - - Models/Props/PickUps/PickUpHolder.mesh - - - - - - - - - - - - 2 - - - - - - - - - - - - - - 8 - - - - Models/Props/PickUps/AmmoPickUp.mesh - - - - - - - - - - - - - - - - - - - - - - - - - Models/Props/Pillars/StonePillar.mesh - - - - - - - - - - - - - - Models/Props/Pillars/StonePillar.mesh - - - - - - - - - - - - - - 6 - Models/Props/Pillars/SciFiPillar1Blue.mesh - - - - - - - - - - - - - - Models/Props/Pillars/StonePillar.mesh - - - - - - - - - - - - - - - - - - Schema/Entities/Player.xml - - - - - - - - - - - - - - - - Models/Characters/Assault/AssaultTPose.mesh - false - - - - - - - - - - - - Models/Characters/Assault/AssaultTPose.mesh - false - - - - - - - - - - - - Models/Characters/Assault/AssaultTPose.mesh - false - - - - - - - - - - - - Models/Characters/Assault/AssaultTPose.mesh - false - - - - - - - - - - - - - - Schema/Entities/PlayerRed.xml - - - - - - - - - - - - - - - - Models/Characters/Assault/AssaultTPose.mesh - false - - - - - - - - - - - - Models/Characters/Assault/AssaultTPose.mesh - false - - - - - - - - - - - - Models/Characters/Assault/AssaultTPose.mesh - false - - - - - - - - - - - - Models/Characters/Assault/AssaultTPose.mesh - false - - - - - - - - - - - - - - - - - - - 10 - - - - - - - - - - - 0.40000000596046448 - - - - - - - - - - - 10 - - - - - - - - - - - 10 - - - - - - - - - - - - 10 - - - - - - - - - - - 1 - - - - - - - - - 10 - - - - - - - - - - - - - - - - - - - Models/Props/CapturePoint/CapturePointNeutral.mesh - - - - - - - - - - 1 - - - - Models/Core/UnitCylinder.mesh - - true - - - - - - - - - - - - - - - - Models/Props/CapturePoint/CapturePointBlue.mesh - - - - - - - - - - -15 - - - - 4 - - - - Models/Core/UnitCylinder.mesh - - true - - - - - - - - - - - - - - - - - - - - Models/Props/CapturePoint/CapturePointNeutral.mesh - - - - - - - - - - 2 - - - - Models/Core/UnitCylinder.mesh - - true - - - - - - - - - - - - - - - - Models/Props/CapturePoint/CapturePointRed.mesh - - - - - - - - - - 15 - - - - - - - Models/Core/UnitCylinder.mesh - - true - - - - - - - - - - - - - - - - - - - - Models/Props/CapturePoint/CapturePointNeutral.mesh - - - - - - - - - - 3 - - - - Models/Core/UnitCylinder.mesh - - true - - - - - - - - - - - - - - - - diff --git a/resources/Schema/Entities/CP_Rocky2.xml b/resources/Schema/Entities/CP_Rocky2.xml index 469966e6..69b0e51e 100644 --- a/resources/Schema/Entities/CP_Rocky2.xml +++ b/resources/Schema/Entities/CP_Rocky2.xml @@ -2,6 +2,9 @@ + + 7.2538959303540196 + @@ -24,18 +27,44 @@ - 2 Models/Props/Walls/SciFiWallTop.mesh + false + + + + + 2 + Models/Props/Walls/SciFiWallSmall2.mesh + + + + + 2 Models/Props/Walls/SciFiWallBig.mesh + false + + + + + + + + + + + + 2 + Models/Props/Walls/SciFiWallBig.mesh + false @@ -47,6 +76,7 @@ 2 Models/Props/Walls/SciFiWallMedium.mesh + false @@ -63,36 +93,13 @@ - - - - - 2 - Models/Props/Walls/SciFiWallSmall2.mesh - - - - - - - - - - 2 - Models/Props/Walls/SciFiWallBig.mesh - - - - - - - 2 Models/Props/Walls/SciFiWallMedium.mesh + false @@ -106,6 +113,7 @@ 2 Models/Props/Walls/SciFiWallSmall3.mesh + false @@ -149,7 +157,6 @@ Models/Highgrounds/Highground3.mesh - @@ -278,7 +285,6 @@ Models/Highgrounds/Highground12.mesh - @@ -684,57 +690,6 @@ - - - - - Models/Highgrounds/Hg18.mesh - - - - - - - - - - - - - Models/Highgrounds/Hg20.mesh - - - - - - - - - - - - - Models/Highgrounds/Hg6.mesh - - - - - - - - - - - - - Models/Highgrounds/Hg8.mesh - - - - - - - @@ -797,6 +752,57 @@ + + + + + Models/Highgrounds/Hg18.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg20.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg6.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg8.mesh + + + + + + + @@ -852,6 +858,7 @@ + 1.5 Models/Props/Pillars/SciFiPillar2Red.mesh @@ -880,6 +887,7 @@ + 1.5 Models/Props/Pillars/SciFiPillar2Red.mesh @@ -907,6 +915,7 @@ + 2 Models/Props/Walls/BigWallRed.mesh @@ -1169,6 +1178,7 @@ + 2 Models/Props/Pillars/SciFiPillar2Blue.mesh @@ -1416,7 +1426,7 @@ Models/Highgrounds/Hg2.mesh - + @@ -1441,6 +1451,7 @@ + 1.5 Models/Props/Bridges/Bridge1_SciFi_Blue.mesh @@ -1453,10 +1464,10 @@ - Models/Props/Bridges/SciFiBridgeDefense.mesh + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh - + @@ -1465,7 +1476,7 @@ - Models/Props/Bridges/SciFiBridgeDefense.mesh + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh @@ -1476,10 +1487,10 @@ - Models/Props/Bridges/SciFiBridgeDefense.mesh + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh - + @@ -1487,10 +1498,10 @@ - Models/Props/Bridges/SciFiBridgeDefense.mesh + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh - + @@ -1505,10 +1516,10 @@ - Models/Props/Bridges/SciFiBridgeDefense.mesh + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh - + @@ -1517,7 +1528,7 @@ - Models/Props/Bridges/SciFiBridgeDefense.mesh + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh @@ -1528,7 +1539,7 @@ - Models/Props/Bridges/SciFiBridgeDefense.mesh + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh @@ -1539,7 +1550,7 @@ - Models/Props/Bridges/SciFiBridgeDefense.mesh + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh @@ -1559,6 +1570,7 @@ + 1.5 Models/Props/Bridges/Bridge1_SciFi_Blue.mesh @@ -1571,6 +1583,7 @@ + 1.5 Models/Props/Bridges/Bridge1_SciFi_Blue.mesh @@ -1583,6 +1596,7 @@ + 1.5 Models/Props/Bridges/SciFi_Bridge_Support_Top_Blue.mesh @@ -1607,11 +1621,11 @@ 12 - + - + @@ -1619,6 +1633,7 @@ + 1.5 Models/Props/Bridges/SciFi_Bridge_Support_Middle_Blue.mesh @@ -1637,6 +1652,7 @@ + 1.5 Models/Props/Bridges/SciFi_Bridge_Support_Top_Blue.mesh @@ -1661,11 +1677,11 @@ 12 - + - + @@ -1673,6 +1689,7 @@ + 1.5 Models/Props/Bridges/SciFi_Bridge_Support_Middle_Blue.mesh @@ -1691,11 +1708,12 @@ + 1.5 Models/Props/Bridges/Bridge1_SciFi_Blue.mesh - - + + @@ -1705,6 +1723,7 @@ + 1.5 Models/Props/Bridges/SciFi_Bridge_Support_Top_Blue.mesh @@ -1730,11 +1749,11 @@ 12 - + - + @@ -1742,6 +1761,7 @@ + 1.5 Models/Props/Bridges/SciFi_Bridge_Support_Middle_Blue.mesh @@ -1769,7 +1789,7 @@ - + @@ -1796,8 +1816,8 @@ Models/Props/Walls/SpecialWall1.mesh - - + + @@ -1950,6 +1970,7 @@ + 2.5 Models/Props/Pillars/SciFiPillar2Blue.mesh @@ -1964,6 +1985,7 @@ + 2.5 Models/Props/Pillars/SciFiPillar2Blue.mesh @@ -2017,7 +2039,7 @@ - 6 + 2.5 Models/Props/Pillars/SciFiPillar1Blue.mesh @@ -2039,10 +2061,11 @@ - Models/Props/Walls/SmallWall3.mesh + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh - + @@ -2052,10 +2075,11 @@ - Models/Props/Walls/SmallWall3.mesh + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh - + @@ -2066,7 +2090,8 @@ - Models/Props/Walls/MediumWall3.mesh + 2 + Models/Props/Walls/Medium_Wall_SciFi_Blue.mesh @@ -2079,10 +2104,11 @@ - Models/Props/Walls/SmallWall3.mesh + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh - + @@ -2093,10 +2119,11 @@ - Models/Props/Walls/SmallWall3.mesh + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh - + @@ -2107,10 +2134,11 @@ - Models/Props/Walls/SmallWall3.mesh + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh - + @@ -2121,10 +2149,11 @@ - Models/Props/Walls/SmallWall3.mesh + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh - + @@ -2134,10 +2163,10 @@ - Models/Props/Walls/SmallWall3.mesh + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh - + @@ -2148,10 +2177,11 @@ - Models/Props/Walls/SmallWall3.mesh + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh - + @@ -2162,6 +2192,7 @@ + 2 Models/Props/Walls/BigWallBlue.mesh @@ -2176,10 +2207,10 @@ - Models/Props/Walls/SmallWall3.mesh + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh - + @@ -2190,10 +2221,11 @@ - Models/Props/Walls/SmallWall3.mesh + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh - + @@ -2203,6 +2235,7 @@ + 2 Models/Props/Walls/BigWallBlue.mesh @@ -2216,10 +2249,11 @@ - Models/Props/Walls/SmallWall3.mesh + 2 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh - + @@ -2229,6 +2263,7 @@ + 2 Models/Props/Walls/BigWallBlue.mesh @@ -2242,6 +2277,7 @@ + 2 Models/Props/Walls/BigWallBlue.mesh @@ -2253,6 +2289,7 @@ + 2 Models/Props/Walls/BigWallBlue.mesh @@ -2268,10 +2305,10 @@ - Models/Props/Walls/SmallWall3.mesh + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh - + @@ -2282,7 +2319,8 @@ - Models/Props/Walls/MediumWall3.mesh + 2 + Models/Props/Walls/Medium_Wall_SciFi_Blue.mesh @@ -2295,10 +2333,11 @@ - Models/Props/Walls/SmallWall3.mesh + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh - + @@ -2309,10 +2348,11 @@ - Models/Props/Walls/SmallWall3.mesh + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh - + @@ -2322,10 +2362,11 @@ - Models/Props/Walls/MediumWall3.mesh + 2 + Models/Props/Walls/Medium_Wall_SciFi_Blue.mesh - + @@ -2335,10 +2376,11 @@ - Models/Props/Walls/MediumWall3.mesh + 2 + Models/Props/Walls/Medium_Wall_SciFi_Blue.mesh - + @@ -2348,10 +2390,11 @@ - Models/Props/Walls/MediumWall3.mesh + 2 + Models/Props/Walls/Medium_Wall_SciFi_Blue.mesh - + @@ -2361,7 +2404,8 @@ - Models/Props/Walls/MediumWall3.mesh + 2 + Models/Props/Walls/Medium_Wall_SciFi_Blue.mesh @@ -2374,7 +2418,8 @@ - Models/Props/Walls/MediumWall3.mesh + 2 + Models/Props/Walls/Medium_Wall_SciFi_Blue.mesh @@ -2387,6 +2432,7 @@ + 2 Models/Props/Walls/BigWallBlue.mesh @@ -2400,10 +2446,11 @@ - Models/Props/Walls/SmallWall3.mesh + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh - + @@ -2414,10 +2461,11 @@ - Models/Props/Walls/SmallWall3.mesh + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh - + @@ -2434,8 +2482,8 @@ true - - + + @@ -2450,10 +2498,10 @@ - Models/Props/SciFiHolder1.mesh + Models/Props/Bridge_Holder_Blue.mesh - + @@ -2476,10 +2524,10 @@ - Models/Props/SciFiHolder1.mesh + Models/Props/Bridge_Holder_Blue.mesh - + @@ -2489,10 +2537,10 @@ - Models/Props/SciFiHolder1.mesh + Models/Props/Bridge_Holder_Blue.mesh - + @@ -2509,7 +2557,7 @@ - 15 + 4 Models/Props/Stones/ShinyStoneCrystalBlue.mesh @@ -2524,7 +2572,7 @@ - 15 + 3 Models/Props/Stones/ShinyStoneCrystalBlue.mesh @@ -2539,12 +2587,11 @@ - 15 + 3 Models/Props/Stones/ShinyStoneCrystalBlue.mesh - - + @@ -2593,7 +2640,7 @@ - 15 + 3 Models/Props/Stones/ShinyStoneCrystalBlue.mesh @@ -2608,7 +2655,7 @@ - 15 + 3 Models/Props/Stones/ShinyStoneCrystalBlue.mesh @@ -2623,7 +2670,7 @@ - 15 + 3 Models/Props/Stones/ShinyStoneCrystalBlue.mesh @@ -2653,12 +2700,12 @@ - 15 + 3 Models/Props/Stones/ShinyStoneCrystalBlue.mesh - + @@ -2681,12 +2728,12 @@ - 15 + 3 Models/Props/Stones/ShinyStoneCrystalBlue.mesh - - + + @@ -2696,11 +2743,11 @@ - 15 + 3 Models/Props/Stones/ShinyStoneCrystalBlue.mesh - + @@ -2711,7 +2758,7 @@ - 15 + 3 Models/Props/Stones/ShinyStoneCrystalBlue.mesh @@ -2761,7 +2808,7 @@ - 15 + 3 Models/Props/Stones/ShinyStoneCrystalBlue.mesh @@ -2779,154 +2826,6 @@ - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - @@ -2940,461 +2839,6 @@ - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - - Models/Props/Stones/BigStone.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/mediumStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/MediumStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - Models/Props/Stones/BigStone.mesh - - - - - - - - - - - - - - Models/Props/Stones/MediumStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - - Models/Props/Stones/BigStone.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - - Models/Props/Stones/BigStone.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - - Models/Props/Stones/MediumStone2.mesh - - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - - Models/Props/Stones/MediumStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/MediumStone2.mesh - - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - Models/Props/Stones/BigStone.mesh - - - - - - - - - - - - - Models/Props/Stones/MediumStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/MediumStone2.mesh - - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - @@ -3416,9 +2860,21 @@ Models/Props/Stones/SmallStone1.mesh - - - + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + @@ -3430,63 +2886,8 @@ Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - Models/Props/Stones/MediumStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - + + @@ -3498,8 +2899,73 @@ Models/Props/Stones/SmallStone1.mesh - - + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + @@ -3518,6 +2984,359 @@ + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + @@ -3552,8 +3371,168 @@ Models/Props/Stones/SmallStone2.mesh - - + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/mediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + @@ -3588,11 +3567,11 @@ - Models/Props/Stones/SmallStone1.mesh + Models/Props/Stones/SmallStone2.mesh - - + + @@ -3605,8 +3584,22 @@ Models/Props/Stones/SmallStone1.mesh - - + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + @@ -3619,9 +3612,8 @@ Models/Props/Stones/SmallStone2.mesh - - - + + @@ -3633,8 +3625,63 @@ Models/Props/Stones/BigStone.mesh - - + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + @@ -3646,19 +3693,6 @@ - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - @@ -3685,6 +3719,19 @@ + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + @@ -3715,10 +3762,11 @@ Models/Props/PickUps/PickUpHolder.mesh + false - - + + @@ -3727,11 +3775,11 @@ 2 - + - + @@ -3746,9 +3794,175 @@ Models/Props/PickUps/HealthPickUp.mesh + + + 1.5 + 3 + - - + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + 1.5 + 3 + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + + + 1.5 + 3 + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + 1.5 + 3 + + + + @@ -3775,11 +3989,11 @@ 2 - + - + @@ -3794,57 +4008,14 @@ Models/Props/PickUps/HealthPickUp.mesh + + + 1.5 + 3 + - - - - - - - - - - - - - - - - Models/Props/PickUps/PickUpHolder.mesh - - - - - - - - - - - - 2 - - - - - - - - - - - - - 8 - - - - Models/Props/PickUps/HealthPickUp.mesh - - - - - + + @@ -3859,6 +4030,7 @@ Models/Props/PickUps/PickUpHolder.mesh + false @@ -3871,11 +4043,11 @@ 2 - + - + @@ -3890,153 +4062,14 @@ Models/Props/PickUps/AmmoPickUp.mesh + + + 1.5 + 3 + - - - - - - - - - - - - - - - - Models/Props/PickUps/PickUpHolder.mesh - - - - - - - - - - - - 2 - - - - - - - - - - - - - 8 - - - - Models/Props/PickUps/AmmoPickUp.mesh - - - - - - - - - - - - - - - - - - - Models/Props/PickUps/PickUpHolder.mesh - - - - - - - - - - - - 2 - - - - - - - - - - - - - 8 - - - - Models/Props/PickUps/HealthPickUp.mesh - - - - - - - - - - - - - - - - - - - Models/Props/PickUps/PickUpHolder.mesh - - - - - - - - - - - - 2 - - - - - - - - - - - - - 8 - - - - Models/Props/PickUps/AmmoPickUp.mesh - - - - - + + @@ -4063,7 +4096,7 @@ - 6 + 2 Models/Props/Pillars/SciFiPillar2Red.mesh @@ -4077,21 +4110,7 @@ - Models/Props/Pillars/SciFiPillar2Blue.mesh - - - - - - - - - - - - - - 6 + 2 Models/Props/Pillars/SciFiPillar2Red.mesh @@ -4106,22 +4125,7 @@ - 4 - Models/Props/Pillars/SciFiPillar2Red.mesh - - - - - - - - - - - - - - 6 + 2 Models/Props/Pillars/SciFiPillar1Red.mesh @@ -4135,7 +4139,36 @@ - 6 + 2 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + 2 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + 2 Models/Props/Pillars/SciFiPillar2Red.mesh @@ -4150,35 +4183,7 @@ - 6 - Models/Props/Pillars/SciFiPillar2Red.mesh - - - - - - - - - - - - - 6 - Models/Props/Pillars/SciFiPillar2Red.mesh - - - - - - - - - - - - - 4 + 2 Models/Props/Pillars/SciFiPillar3Red.mesh @@ -4207,7 +4212,21 @@ - 4 + 2 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + 2 Models/Props/Pillars/SciFiPillar1Red.mesh @@ -4222,22 +4241,7 @@ - 6 - Models/Props/Pillars/SciFiPillar2Red.mesh - - - - - - - - - - - - - - 4 + 2 Models/Props/Pillars/SciFiPillar3Red.mesh @@ -4252,13 +4256,12 @@ - 4 + 2 Models/Props/Pillars/SciFiPillar2Red.mesh - - - + + @@ -4267,12 +4270,13 @@ - 6 + 2 Models/Props/Pillars/SciFiPillar2Red.mesh - - + + + @@ -4288,11 +4292,13 @@ - Models/Props/Bridges/SciFiBridgeDefense.mesh + 3 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh - - + + + @@ -4301,7 +4307,48 @@ - 15 + Models/Props/Pillars/SciFiPillar1Blue.mesh + + + + + + + + + + + + + + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + 3 Models/Props/Stones/ShinyStoneCrystalBlue.mesh @@ -4315,22 +4362,61 @@ - 15 + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + 3 Models/Props/Stones/ShinyStoneCrystalBlue.mesh - - + + + + + + + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + true + + + + + + + + @@ -4373,32 +4459,18 @@ - - - - Models/Props/Flora/HangingBush4.mesh - true - - - - - - - - - 10 + 9 Models/Props/Stones/ShinyStoneCrystalBlue.mesh - - - + + @@ -4407,12 +4479,11 @@ - 15 - Models/Props/Stones/ShinyStoneCrystalBlue.mesh + Models/Props/Stones/AssaultHolder.mesh - - + + @@ -4421,21 +4492,7 @@ - Models/Props/Pillars/SciFiPillar1Blue.mesh - - - - - - - - - - - - - - 15 + 3 Models/Props/Stones/ShinyStoneCrystalBlue.mesh @@ -4463,7 +4520,35 @@ - 15 + 3 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh + + + + + + + + + + + + + 3 Models/Props/Stones/ShinyStoneCrystalBlue.mesh @@ -4478,53 +4563,10 @@ - Models/Props/Stones/AssaultHolder.mesh + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh - - - - - - - - - - - - 15 - Models/Props/Stones/ShinyStoneCrystalBlue.mesh - - - - - - - - - - - - - - 15 - Models/Props/Stones/ShinyStoneCrystalBlue.mesh - - - - - - - - - - - - - Models/Props/Bridges/SciFiBridgeDefense.mesh - - - + @@ -4534,11 +4576,12 @@ - Models/Props/Bridges/SciFiBridgeDefense.mesh + 3 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh - - + + @@ -4547,10 +4590,10 @@ - Models/Props/Bridges/SciFiBridgeDefense.mesh + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh - + @@ -4560,49 +4603,10 @@ - Models/Props/Bridges/SciFiBridgeDefense.mesh + Models/Props/Bridge_Holder_Blue.mesh - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - - Models/Props/SciFiHolder1.mesh - - - + @@ -4612,10 +4616,10 @@ - Models/Props/Bridges/SciFiBridgeDefense.mesh + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh - + @@ -4628,11 +4632,160 @@ + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + + 2 + Models/Props/Pillars/SciFiPillar1Red.mesh + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.mesh + + + + + + + + + @@ -4641,7 +4794,7 @@ - + @@ -4668,22 +4821,8 @@ Models/Props/Walls/SpecialWall1.mesh - - - - - - - - - - - - Models/Props/Walls/SpecialWall1.mesh - - - - + + @@ -4691,21 +4830,6 @@ - - - - Models/Core/UnitPlane.mesh - - true - - - - - - - - - @@ -4715,124 +4839,7 @@ - Models/Props/Bridges/Bridge1_SciFi_Red.mesh - - - - - - - - - - - - Models/Props/Bridges/SciFiBridgeDefense.mesh - - - - - - - - - - - - Models/Props/Bridges/SciFiBridgeDefense.mesh - - - - - - - - - - - Models/Props/Bridges/SciFiBridgeDefense.mesh - - - - - - - - - - - Models/Props/Bridges/SciFiBridgeDefense.mesh - - - - - - - - - - - - - - - - - - Models/Props/Bridges/SciFiBridgeDefense.mesh - - - - - - - - - - - - Models/Props/Bridges/SciFiBridgeDefense.mesh - - - - - - - - - - - Models/Props/Bridges/SciFiBridgeDefense.mesh - - - - - - - - - - - Models/Props/Bridges/SciFiBridgeDefense.mesh - - - - - - - - - - - - - - - - - - - + 1.5 Models/Props/Bridges/Bridge1_SciFi_Red.mesh @@ -4845,11 +4852,11 @@ - Models/Props/Bridges/SciFiBridgeDefense.mesh + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh - - + + @@ -4858,10 +4865,23 @@ - Models/Props/Bridges/SciFiBridgeDefense.mesh + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh - + + + + + + + + + + + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + @@ -4879,32 +4899,6 @@ - - - - 12 - - - - - - - - - - - - - Models/Props/Bridges/SciFi_Bridge_Support_Middle_Red.mesh - - - - - - - - - @@ -4917,12 +4911,79 @@ + + + + 12 + + + + + + + + + + + + + 1.5 + Models/Props/Bridges/SciFi_Bridge_Support_Middle_Red.mesh + + + + + + + + + + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + + + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + + + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + + + 1.5 Models/Props/Bridges/Bridge1_SciFi_Red.mesh @@ -4943,27 +5004,15 @@ - - - - - Models/Props/Bridges/SciFi_Bridge_Support_Bot_Red.mesh - - - - - - - 12 - + - + @@ -4971,6 +5020,7 @@ + 1.5 Models/Props/Bridges/SciFi_Bridge_Support_Middle_Red.mesh @@ -4981,62 +5031,22 @@ + + + + + Models/Props/Bridges/SciFi_Bridge_Support_Bot_Red.mesh + + + + + + + - - - - - Models/Props/Bridges/SciFiBridgeDefense.mesh - - - - - - - - - - - - - Models/Props/Bridges/SciFiBridgeDefense.mesh - - - - - - - - - - - - - Models/Props/Bridges/SciFiBridgeDefense.mesh - - - - - - - - - - - - - Models/Props/Bridges/SciFiBridgeDefense.mesh - - - - - - - - @@ -5052,27 +5062,15 @@ - - - - - Models/Props/Bridges/SciFi_Bridge_Support_Bot_Red.mesh - - - - - - - 12 - + - + @@ -5090,12 +5088,144 @@ + + + + + Models/Props/Bridges/SciFi_Bridge_Support_Bot_Red.mesh + + + + + + + + 1.5 + Models/Props/Bridges/Bridge1_SciFi_Red.mesh + + + + + + + + + + + + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + + + + + + + + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + + + + + + + + + + 1.5 Models/Props/Bridges/Bridge1_SciFi_Red.mesh @@ -5108,6 +5238,1784 @@ + + + + + + + + + + 3 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 3 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 3 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 2 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 2 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 2 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 2 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + 2 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 2 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 2 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + 2 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 3 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 3 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 3 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Core/UnitPlane.mesh + + true + + + + + + + + + + + + + + + + + + + Models/Props/Bridge_Holder_Red.mesh + + + + + + + + + + + + + Models/Props/Bridge_Holder_Red.mesh + + + + + + + + + + + + + Models/Props/Bridge_Holder_Red.mesh + + + + + + + + + + + + + Models/Props/Bridge_Holder_Red.mesh + + + + + + + + + + + + + Models/Props/SciFiHolder1.mesh + + + + + + + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/mediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/mediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + + Models/Props/Stones/mediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/mediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/mediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/mediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/mediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + 1.5 + 3 + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + 1.5 + 3 + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + + + 1.5 + 3 + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + 1.5 + 3 + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + 1.5 + 3 + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + 1.5 + 3 + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + 1.5 + 3 + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + + + 1.5 + 3 + + + + + + + + + + + + + + + + @@ -5147,8 +7055,9 @@ Models/Props/Stones/AssaultHolder.mesh - - + + + @@ -5167,6 +7076,19 @@ + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + @@ -5187,9 +7109,57 @@ Models/Props/Stones/AssaultHolder.mesh - - - + + + + + + + + + + + + + + + + + + 2 + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + 2 + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + + + 2 + Models/Props/Walls/BigWallRed.mesh + + + + @@ -5198,459 +7168,400 @@ - Models/Props/Stones/AssaultHolder.mesh + 2 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh - - + + + - - - - - - - + - Models/Props/PickUps/PickUpHolder.mesh + Models/Props/Walls/Small_Wall_SciFi_Red.mesh - - - + + + - - - - - 2 - - - - - - - - - - - - - 8 - - - - Models/Props/PickUps/HealthPickUp.mesh - - - - - - - - - - - - - - + + - Models/Props/PickUps/PickUpHolder.mesh + 2 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh - - - + + + - - - - - 2 - - - - - - - - - - - - - 8 - - - - Models/Props/PickUps/HealthPickUp.mesh - - - - - - - - - - - - - - + + - Models/Props/PickUps/PickUpHolder.mesh + Models/Props/Walls/MediumWall3.mesh - - - + + - - - - - 2 - - - - - - - - - - - - - 8 - - - - Models/Props/PickUps/HealthPickUp.mesh - - - - - 1.5 - 1 - 0.30000001192092896 - - - - - - - - - - - - - + + - Models/Props/PickUps/PickUpHolder.mesh + 2 + Models/Props/Walls/BigWallRed.mesh - - - + + - - - - - 2 - - - - - - - - - - - - - 8 - - - - Models/Props/PickUps/AmmoPickUp.mesh - - - - - - - - - - - - - - + + - Models/Props/PickUps/PickUpHolder.mesh + Models/Props/Walls/Medium_Wall_SciFi_Red.mesh - - - + + - - - - - 2 - - - - - - - - - - - - - 8 - - - - Models/Props/PickUps/AmmoPickUp.mesh - - - - - - - - - - - - - - + + - Models/Props/PickUps/PickUpHolder.mesh + 2 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh - - - + + - - - - - 2 - - - - - - - - - - - - - 8 - - - - Models/Props/PickUps/AmmoPickUp.mesh - - - - - - - - - - - - - - + + - Models/Props/PickUps/PickUpHolder.mesh + 2 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh - - - + + + - - - - - 2 - - - - - - - - - - - - - 8 - - - - Models/Props/PickUps/HealthPickUp.mesh - - - - - - - - - - - - - - + + - Models/Props/PickUps/PickUpHolder.mesh + Models/Props/Walls/Small_Wall_SciFi_Red.mesh - - - + + - - - - - 2 - - - - - - - - - - - - - 8 - - - - Models/Props/PickUps/HealthPickUp.mesh - - - - - - - - - - - - - - + + - Models/Props/PickUps/PickUpHolder.mesh + 2 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh - - - + + + - - - - - 2 - - - - - - - - - - - - - 8 - - - - Models/Props/PickUps/HealthPickUp.mesh - - - - - - - - - - - - - - + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Medium_Wall_SciFi_Red.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Medium_Wall_SciFi_Red.mesh + + + + + + + + + + + + + Models/Props/Walls/Medium_Wall_SciFi_Red.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + Models/Props/Walls/Medium_Wall_SciFi_Red.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Medium_Wall_SciFi_Red.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh + + + + + + + @@ -5659,6 +7570,20 @@ + + + + + Models/Props/Flora/Root.mesh + + + + + + + + + @@ -5687,20 +7612,6 @@ - - - - - Models/Props/Flora/Root.mesh - - - - - - - - - @@ -5717,6 +7628,13 @@ + + + + + + + @@ -5726,25 +7644,12 @@ - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - + 2 Models/Props/Walls/BigWallRed.mesh - - + + @@ -5753,11 +7658,12 @@ - Models/Props/Walls/SmallWall3.mesh + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh - - + + @@ -5767,11 +7673,12 @@ - Models/Props/Walls/SmallWall3.mesh + 2 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh - - + + @@ -5781,199 +7688,12 @@ - Models/Props/Walls/MediumWall3.mesh - - - - - - - - - - - - - Models/Props/Walls/MediumWall3.mesh - - - - - - - - - - - - - Models/Props/Walls/MediumWall3.mesh - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - - Models/Props/Walls/MediumWall3.mesh - - - - - - - - - - - - - Models/Props/Walls/MediumWall3.mesh - - - - - - - - - - - - + 2 Models/Props/Walls/BigWallRed.mesh - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - + + @@ -5982,11 +7702,12 @@ + 2 Models/Props/Walls/BigWallBlue.mesh - - + + @@ -5995,25 +7716,12 @@ - Models/Props/Walls/SmallWall3.mesh + 2 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - + + @@ -6023,740 +7731,12 @@ - Models/Props/Walls/BigWallRed.mesh + 2 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh - - - - - - - - - - - Models/Props/Walls/MediumWall3.mesh - - - - - - - - - - - - - Models/Props/Walls/BigWallRed.mesh - - - - - - - - - - - Models/Props/Walls/BigWallRed.mesh - - - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - - Models/Props/Walls/MediumWall3.mesh - - - - - - - - - - - - - Models/Props/Walls/BigWallRed.mesh - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - - - - - - - - - Models/Props/SciFiHolder1.mesh - - - - - - - - - - - - - Models/Props/SciFiHolder1.mesh - - - - - - - - - - - - - Models/Props/SciFiHolder1.mesh - - - - - - - - - - - - - Models/Props/SciFiHolder1.mesh - - - - - - - - - - - - - Models/Props/SciFiHolder1.mesh - - - - - - - - - - - - - - - - - - - - Models/Props/Pillars/StonePillar.mesh - - - - - - - - - - - - - - - - - - - Models/Props/Stones/MediumStone2.mesh - - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - Models/Props/Stones/BigStone.mesh - - - - - - - - - - - - - Models/Props/Stones/MediumStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/BigStone.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - - Models/Props/Stones/mediumStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - - Models/Props/Stones/BigStone.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - - Models/Props/Stones/MediumStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - - Models/Props/Stones/MediumStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/BigStone.mesh - - - - - - - - - - - - - Models/Props/Stones/MediumStone2.mesh - - - - - - - - - - - - - - Models/Props/Stones/mediumStone2.mesh - - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - Models/Props/Stones/MediumStone2.mesh - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - - - Models/Props/Stones/mediumStone2.mesh - - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/MediumStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - - Models/Props/Stones/MediumStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/mediumStone2.mesh - - - - + + @@ -6766,158 +7746,12 @@ - Models/Props/Stones/SmallStone2.mesh + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh - - - - - - - - - - - Models/Props/Stones/MediumStone2.mesh - - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - - Models/Props/Stones/BigStone.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/mediumStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/BigStone.mesh - - - - - - - - - - - - Models/Props/Stones/mediumStone2.mesh - - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - + + @@ -6927,11 +7761,12 @@ - Models/Props/Stones/SmallStone1.mesh + 2 + Models/Props/Walls/Medium_Wall_SciFi_Blue.mesh - - + + @@ -6940,405 +7775,12 @@ - Models/Props/Stones/SmallStone2.mesh + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - - Models/Props/Stones/BigStone.mesh - - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - - Models/Props/Stones/BigStone.mesh - - - - - - - - - - - - - Models/Props/Stones/BigStone.mesh - - - - - - - - - - - - - - Models/Props/Stones/MediumStone2.mesh - - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - - Models/Props/Stones/mediumStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - - - - - - - - - 7 - Models/Props/Stones/ShinyStoneCrystalRed.mesh - - - - - - - - - - - - - - 7 - Models/Props/Stones/ShinyStoneCrystalRed.mesh - - - - - - - - - - - - - 7 - Models/Props/Stones/ShinyStoneCrystalRed.mesh - - - - + + @@ -7348,494 +7790,18 @@ - 7 - Models/Props/Stones/ShinyStoneCrystalRed.mesh + 2 + Models/Props/Walls/BigWallBlue.mesh - - - - - - - - - - - - 7 - Models/Props/Stones/ShinyStoneCrystalRed.mesh - - - - - - - - - - - - - - 7 - Models/Props/Stones/ShinyStoneCrystalRed.mesh - - - - - - - - - - - - - - 7 - Models/Props/Stones/ShinyStoneCrystalRed.mesh - - - - - - - - - - - - - - 7 - Models/Props/Stones/ShinyStoneCrystalRed.mesh - - - - - - - - - - - - - - 6 - Models/Props/Stones/ShinyStoneCrystalRed.mesh - - - - - - - - - - - - - - 7 - Models/Props/Stones/ShinyStoneCrystalRed.mesh - - - - - - - - - - - - - 7 - Models/Props/Stones/ShinyStoneCrystalRed.mesh - - - - - - - - - - - - - - 7 - Models/Props/Stones/ShinyStoneCrystalRed.mesh - - - - - - - - - - - - - - 6 - Models/Props/Stones/ShinyStoneCrystalRed.mesh - - - - - - - - - - - - - - 7 - Models/Props/Stones/ShinyStoneCrystalRed.mesh - - - - - - - - - - - - - - 7 - Models/Props/Stones/ShinyStoneCrystalRed.mesh - - - - - + + - - - - - - - - - - Models/Props/Pillars/StonePillar.mesh - - - - - - - - - - - - - - Models/Props/Pillars/StonePillar.mesh - - - - - - - - - - - - Models/Props/Pillars/StonePillar.mesh - - - - - - - - - - - - - - Models/Props/Pillars/SciFiPillar2Red.mesh - - - - - - - - - - - - - Models/Props/Pillars/SciFiPillar2Red.mesh - - - - - - - - - - - - - - 6 - Models/Props/Pillars/SciFiPillar1Red.mesh - - - - - - - - - - - - - - - - - - - - - - - - - - - - 4 - Models/Props/Pillars/SciFiPillar3Blue.mesh - - - - - - - - - - - - - - 4 - Models/Props/Pillars/SciFiPillar2Blue.mesh - - - - - - - - - - - - - - 6 - Models/Props/Pillars/SciFiPillar2Blue.mesh - - - - - - - - - - - - - 6 - Models/Props/Pillars/SciFiPillar2Blue.mesh - - - - - - - - - - - - - - Models/Props/Pillars/SciFiPillar2Blue.mesh - - - - - - - - - - - - - - 6 - Models/Props/Pillars/SciFiPillar2Blue.mesh - - - - - - - - - - - - - 6 - Models/Props/Pillars/SciFiPillar1Blue.mesh - - - - - - - - - - - - - 4 - Models/Props/Pillars/SciFiPillar3Blue.mesh - - - - - - - - - - - - - - 4 - Models/Props/Pillars/SciFiPillar2Red.mesh - - - - - - - - - - - - - - 6 - Models/Props/Pillars/SciFiPillar2Blue.mesh - - - - - - - - - - - - - Models/Props/Pillars/SciFiPillar2Blue.mesh - - - - - - - - - - - - - - 6 - Models/Props/Pillars/SciFiPillar2Blue.mesh - - - - - - - - - - - - - 6 - Models/Props/Pillars/SciFiPillar2Blue.mesh - - - - - - - - - - - - - - 6 - Models/Props/Pillars/SciFiPillar2Blue.mesh - - - - - - - - - - - - - - - - @@ -7848,9 +7814,8 @@ Models/Props/Stones/AssaultHolder.mesh - - - + + @@ -7862,8 +7827,73 @@ Models/Props/Stones/AssaultHolder.mesh - - + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + @@ -7889,8 +7919,9 @@ Models/Props/Stones/AssaultHolder.mesh - - + + + @@ -7916,9 +7947,21 @@ Models/Props/Stones/AssaultHolder.mesh - - - + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + @@ -7944,8 +7987,9 @@ Models/Props/Stones/AssaultHolder.mesh - - + + + @@ -7957,47 +8001,9 @@ Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - + + + @@ -8022,311 +8028,12 @@ Models/Props/Stones/AssaultHolder.mesh - - + + - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - - - - - - - - - - Models/Props/Walls/BigWallRed.mesh - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - - Models/Props/Walls/BigWallBlue.mesh - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - - Models/Props/Walls/MediumWall3.mesh - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - - Models/Props/Walls/BigWallRed.mesh - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - - Models/Props/Walls/BigWallBlue.mesh - - - - - - - - - - - - - Models/Props/Walls/smallWall3.mesh - - - - - - - - - - - - - - - - - - - - Models/Props/PickUps/PickUpHolder.mesh - - - - - - - - - - - - 2 - - - - - - - - - - - - - 8 - - - - Models/Props/PickUps/HealthPickUp.mesh - - - - - - - - - - - - - - - - - - - Models/Props/PickUps/PickUpHolder.mesh - - - - - - - - - - - - 2 - - - - - - - - - - - - - 8 - - - - Models/Props/PickUps/AmmoPickUp.mesh - - - - - - - - - - - - - - - @@ -8334,6 +8041,47 @@ + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + @@ -8354,13 +8102,240 @@ Models/Props/Stones/SmallStone2.mesh - - + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Stones/mediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + @@ -8375,32 +8350,6 @@ - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - @@ -8414,179 +8363,6 @@ - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - Models/Props/Pillars/StonePillar.mesh - - - - - - - - - - - - - Models/Props/Stones/BigStone.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - - Models/Props/Stones/MediumStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/MediumStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - - Models/Props/Stones/MediumStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/MediumStone2.mesh - - - - - - - - - - - - - - Models/Props/Stones/mediumStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - @@ -8605,25 +8381,11 @@ - Models/Props/Stones/MediumStone2.mesh + Models/Props/Stones/BigStone.mesh - - - - - - - - - - - - Models/Props/Stones/MediumStone2.mesh - - - - + + @@ -8635,26 +8397,127 @@ Models/Props/Stones/SmallStone2.mesh - - + + + + + + + + + - - Models/Props/Stones/SmallStone2.mesh + Models/Props/PickUps/PickUpHolder.mesh + false - - - + + + - + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + + + 1.5 + 3 + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + 1.5 + 3 + + + + + + + + + + + + + @@ -8667,11 +8530,11 @@ - 6 + 2 Models/Props/Stones/ShinyStoneCrystalRed.mesh - + @@ -8682,7 +8545,7 @@ - 15 + 3 Models/Props/Stones/ShinyStoneCrystalRed.mesh @@ -8697,6 +8560,193 @@ + + + + + + + + + + + + + + + 2 + Models/Props/Pillars/SciFiPillar1Blue.mesh + + + + + + + + + + + + + 2.5 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar3Blue.mesh + + + + + + + + + + + + + + 2.5 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + 2.5 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + 2.5 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + 2.5 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + 2.5 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar3Blue.mesh + + + + + + + + + + + + + + 2.5 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + @@ -8708,7 +8758,7 @@ - Schema/Entities/Player.xml + Schema/Entities/PlayerAssaultBlue.xml @@ -8723,7 +8773,7 @@ false - + @@ -8736,7 +8786,7 @@ false - + @@ -8762,1541 +8812,13 @@ false - + - - - - - - - - - - - - - - 4 - - - - - - - - - - - 4 - - - - - - - - - - - 5 - - - - - - - - - - - 4 - - - - - - - - - - - 4 - - - - - - - - - - - 4 - - - - - - - - - - - 4 - - - - - - - - - - - 4 - - - - - - - - - - - 4 - - - - - - - - - - - 4 - - - - - - - - - - - 4 - - - - - - - - - - - 4 - 2 - - - - - - - - - - - 4 - - - - - - - - - - - 4 - - - - - - - - - - - 4 - 1 - - - - - - - - - - - 4 - - - - - - - - - - - - - 10 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 - 2 - 0.5 - - - - - - - - - - - - 5 - 2 - 0.5 - - - - - - - - - - - - - - - - - - - - - 5 - 2 - 0.5 - - - - - - - - - - - - 5 - 2 - 0.5 - - - - - - - - - - - - - - - - - - - - - 5 - 2 - 0.5 - - - - - - - - - - - - 5 - 2 - 0.5 - - - - - - - - - - - - - - - - - - - - - 5 - 2 - 0.5 - - - - - - - - - - - - 5 - 2 - 0.5 - - - - - - - - - - - - - - - - - - - - - 5 - 2 - 0.5 - - - - - - - - - - - - 5 - 2 - 0.5 - - - - - - - - - - - - - - - - - - - - - 5 - 2 - 0.5 - - - - - - - - - - - - 5 - 2 - 0.5 - - - - - - - - - - - - - - - - - - - - - 5 - 2 - 0.5 - - - - - - - - - - - - 5 - 2 - 0.5 - - - - - - - - - - - - - - - - - - - - - 5 - 2 - 0.5 - - - - - - - - - - - - 5 - 2 - 0.5 - - - - - - - - - - - - - - - - - - - - - 5 - 2 - 0.5 - - - - - - - - - - - - 5 - 2 - 0.5 - - - - - - - - - - - - - - - - - - - - - 5 - 2 - 0.5 - - - - - - - - - - - - 5 - 2 - 0.5 - - - - - - - - - - - - - - - - - - - - - 5 - 2 - 0.5 - - - - - - - - - - - - 5 - 2 - 0.5 - - - - - - - - - - - - - - - - - - - - - 5 - 2 - 0.5 - - - - - - - - - - - - 5 - 2 - 0.5 - - - - - - - - - - - - - - - - - - - - - 5 - 2 - 0.5 - - - - - - - - - - - - 5 - 2 - 0.5 - - - - - - - - - - - - - - - - - - - - - 5 - 2 - 0.5 - - - - - - - - - - - - 5 - 2 - 0.5 - - - - - - - - - - - - - - - - - - - - - 5 - 2 - 0.5 - - - - - - - - - - - - 5 - 2 - 0.5 - - - - - - - - - - - - - - - - - - - - - 5 - 2 - 0.5 - - - - - - - - - - - - 5 - 2 - 0.5 - - - - - - - - - - - - - - - - - - - - - 5 - 2 - 0.5 - - - - - - - - - - - - 5 - 2 - 0.5 - - - - - - - - - - - - - - - - 15 - 1 - - - - - - - - - - - - - - - - - 10 - 1 - - - - - - - - - - - - 10 - 1 - - - - - - - - - - - - 10 - 1 - - - - - - - - - - - - - - - - 10 - - - - - - - - - - - - 10 - - - - - - - - - - - - 0.80000001192092896 - 1.2000000476837158 - - - - - - - - - 10 - - - - - - - - - - - 0.60000002384185791 - false - - - - - - - - - - - 10 - - - - - - - - - - - - - - - - - - - - - - 10 - 1 - - - - - - - - - - - - 10 - 1 - - - - - - - - - - - - 10 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - 5 - 2 - 0.5 - - - - - - - - - - - - 3 - 2 - 0.5 - - - - - - - - - - - - - - - - - - - - - 5 - 2 - 0.5 - - - - - - - - - - - - 5 - 2 - 0.5 - - - - - - - - - - - - - - - - - - - - - 5 - 2 - 0.5 - - - - - - - - - - - - 5 - 2 - 0.5 - - - - - - - - - - - - - - - - - - - - - 5 - 1 - 0.5 - - - - - - - - - - - - 5 - 1 - 0.5 - - - - - - - - - - - - - - - - - - - - - 5 - 2 - 0.5 - - - - - - - - - - - - 5 - 2 - 0.5 - - - - - - - - - - - - - - - - - - - - - 5 - 1 - 0.5 - - - - - - - - - - - - 5 - 2 - 0.5 - - - - - - - - - - - - - - - - - - - - - 5 - 2 - 0.5 - - - - - - - - - - - - 5 - 2 - 0.5 - - - - - - - - - - - - - - - - - - - - - 5 - 1 - 0.5 - - - - - - - - - - - - 5 - 1 - 0.5 - - - - - - - - - - - - - - - - - - - - - 5 - 2 - 0.5 - - - - - - - - - - - - 5 - 2 - 0.5 - - - - - - - - - - - - - - - - - - - - - 5 - 1 - 0.5 - - - - - - - - - - - - 5 - 1 - 0.5 - - - - - - - - - - - - - - - - - - - - - 5 - 2 - 0.5 - - - - - - - - - - - - 5 - 2 - 0.5 - - - - - - - - - - - - - - - - - - - - - 5 - 1 - 0.5 - - - - - - - - - - - - 5 - 1 - 0.5 - - - - - - - - - - - - - - - - - - - - - 5 - 1 - 0.5 - - - - - - - - - - - - 5 - 1 - 0.5 - - - - - - - - - - - - - - - - 15 - 1 - - - - - - - - - - - @@ -10334,7 +8856,7 @@ false - + @@ -10360,13 +8882,328 @@ false - + + + + + + + + + + + + + + + + + + + Models/Core/UnitCube.mesh + false + + + + + + + + + + + + + + + + + + + + + + + + Models/Core/UnitCube.mesh + false + + + + + + + + + + + Schema/Entities/ScoreBoard_Red.xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Kills + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Deaths + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + KD + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + ID + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + false + + + + + + + + + + + + + + + + Schema/Entities/ScoreBoard_Blue.xml + + + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + Kills + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + KD + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Deaths + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + ID + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Name + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + + + @@ -10375,7 +9212,7 @@ - + @@ -10387,138 +9224,36 @@ - + - + + 0.20000000298023224 + 300 + - + - + - - - - - false - Models/Core/UnitQuad.mesh - - Textures/Icons/Classes/Sniper-01.png - - - PickClass - 3 - - - - - - - - - - - Sniper - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - - - - - false - Models/Core/UnitQuad.mesh - - Textures/Icons/Classes/Defender-01.png - - - PickClass - 2 - - - - - - - - - - - Defender - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - + - Pick Class + 1 Fonts/DroidSans.ttf,64 - + - - - - - false - Models/Core/UnitQuad.mesh - - Textures/Icons/Classes/Assault-01.png - - - PickClass - 1 - - - - - - - - - - - Assault - Fonts/DroidSans.ttf,64 - - - - - - - - - - - @@ -10539,19 +9274,6 @@ - - - - Change - Fonts/DroidSans.ttf,64 - - - - - - - - @@ -10565,25 +9287,21 @@ + + + + Change + Fonts/DroidSans.ttf,64 + + + + + + + + - - - - - - - - - - - - - - - - - @@ -10668,44 +9386,6 @@ - - - - false - Models/Core/UnitQuad.mesh - - Textures/Core/UnitHexagon.png - - - - - - - - - - - - - - 3 - - - false - Models/Core/UnitQuad.mesh - - Textures/Core/UnitHexagon_Rotated.png - - - - - - - - - - - @@ -10782,67 +9462,43 @@ - - - - - - 7 - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - - - false - Models/Core/UnitQuad.mesh - - Textures/Core/UnitHexagon.png - - - - SwapToTeamPick - 1 - - - - - - - - + - - Change - Fonts/DroidSans.ttf,64 - + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + - - + - - - - - - Team - Fonts/DroidSans.ttf,64 - - - - - - - + + + + + + + + 3 + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + @@ -10898,9 +9554,199 @@ + + + + 0.20000000298023224 + 300 + + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Icons/Classes/Assault-01.png + + + PickClass + 1 + + + + + + + + + + + Assault + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Icons/Classes/Sniper-01.png + + + PickClass + 3 + + + + + + + + + + + Sniper + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + SwapToTeamPick + 1 + + + + + + + + + + + Team + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + Change + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Icons/Classes/Defender-01.png + + + PickClass + 2 + + + + + + + + + + + Defender + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Pick Class + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + - + + 0.20000000298023224 + 300 + @@ -10911,6 +9757,41 @@ + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + PickTeam + 3 + + + + + + + + + + + Blue + Fonts/DroidSans.ttf,64 + + + + + + + + + + @@ -10946,20 +9827,6 @@ - - - - Pick Team - Fonts/DroidSans.ttf,64 - - - - - - - - - @@ -11011,6 +9878,20 @@ + + + + Pick Team + Fonts/DroidSans.ttf,64 + + + + + + + + + @@ -11046,41 +9927,6 @@ - - - - - false - Models/Core/UnitQuad.mesh - - Textures/Core/UnitHexagon.png - - - - PickTeam - 3 - - - - - - - - - - - Blue - Fonts/DroidSans.ttf,64 - - - - - - - - - - @@ -11089,419 +9935,2137 @@ - + - + - - Schema/Entities/ScoreBoard_Main.xml - - - - - + - + + + + 4 + + + + + + + + + + + 4 + + + + + + + + + + + 4 + + + + + + + + + + + 5 + + + + + + + + + + + 4 + + + + + + + + + + + 4 + 1 + + + + + + + + + + + 4 + + + + + + + + + + + 4 + + + + + + + + + + + 4 + + + + + + + + + + + 4 + + + + + + + + + + + 4 + + + + + + + + + + + 4 + 2 + + + + + + + + + + + 4 + + + + + + + + + + + 4 + + + + + + + + + + + 4 + + + + + + + + + + + 4 + + + + + + + + + + + + + + + - + - - Models/Core/UnitCube.mesh - - - - - - - - - - - - - - - - - - - - - - - Models/Core/UnitCube.mesh - - - - - - - - - - - Schema/Entities/ScoreBoard_Red.xml - - - + - + - + + + 5 + 1 + 0.5 + + + + - - - - - Models/Core/UnitCube.mesh - - - - - - - - - - - - - - - - - - - - - - - - - - - - ID - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - - - - Name - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - - - - KD - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - - - - Kills - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - - - - Deaths - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - - - + + + + + + + 5 + 1 + 0.5 + + + + + + - + - - Schema/Entities/ScoreBoard_Blue.xml - - + - + - + + + 5 + 2 + 0.5 + + + + - - - - - Models/Core/UnitCube.mesh - - - - - - - - - - - - - - - - - - - - - - - - - - - - ID - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - - - - Name - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - - - - KD - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - - - - Kills - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - - - - Deaths - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - - - + + + + + + + 5 + 2 + 0.5 + + + + + + - + + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + + + + + + + + + + 2 + 1 + 0.5 + + + + + + + + + + + + 3 + 1 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + + + + + + + + + + 3 + 1 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + + + + + 15 + 1 + + + + + + + + + + + + + + + + + 10 + 1 + + + + + + + + + + + + 10 + 1 + + + + + + + + + + + + 10 + 1 + + + + + + + + + + + + + + + - - Schema/Entities/EndScreen.xml - - + - + - + - - - + + + 6 + 1 + 0.5 + + + + + + + + + + + + - + + + + 5 + 1 + 0.5 + - + - - - - - Models/Core/UnitQuad.mesh - - Textures/Core/White.png - true - - false - - - - - - - - - - - Models/Core/UnitQuad.mesh - - Textures/Core/White.png - true - - - - - - - - - - - - Blue team win! - Fonts/DroidSans.ttf,64 - false - - - - - - - - - - - - Red team win! - Fonts/DroidSans.ttf,64 - - - - - - - - - + + + + + + + 6 + 1 + 0.5 + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + + + + + + + + 6 + 1 + 0.5 + + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + 10 + + + + + + + + + + + 10 + + + + + + + + + + + 0.40000000596046448 + + + + + + + + + + + + + + + + + + + + + + 10 + 1 + + + + + + + + + + + + 10 + 1 + + + + + + + + + + + + 10 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + + + + + 15 + 1 + + + + + + + + + + + + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 6 + 2 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 6 + 2 + 0.5 + + + + + + + + + + + + + + + + + + 1 + 1.2000000476837158 + + + + + + + + + + 10 + + + + + + + + + + + 10 + + + + + + + + + + + 10 + + + + + + + @@ -11509,183 +12073,4767 @@ - + - + + 1 + + - Models/Props/CapturePoint/CapturePointRed.mesh + Models/Props/CapturePoint/CapturePointCylinder.mesh + + false + true + - + + - + - - 15 - - - - - - - - - + - Models/Core/UnitCylinder.mesh - - true + Models/Props/CapturePoint/CapturePointRed.mesh + false - - - - - - + - + + + + + + + + + + + + 0.5 + + + + 20 + + + 3 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer2.mesh + + false + false + + + + + + + + + + + 0.30000001192092896 + + + + 30 + + + 3.5 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer1.mesh + + false + false + + + + + + + + + + + 0.10000000149011612 + + + + 10 + + + 0.5 + + + + + + + + + + + 1 + + + + + + + + + + + + 4.5 + 0.5 + false + + + + + + + + + + + + 4.5 + 0.5 + false + + + + + + + + + + + + 4.5 + 0.5 + false + + + + + + + + + + + + 4.5 + 0.5 + false + + + + + + + + + + + + + Models/Props/CapturePoint/CenterCrystal.mesh + + false + false + + + + + + + + + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + false + true + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + false + true + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + false + true + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + false + true + + + + + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointNeutral.mesh + + + + + + + + + + + + + + + 0.5 + + + + 20 + + + 3 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer2.mesh + false + + + + + + + + + + + 0.10000000149011612 + + + + 10 + + + 0.5 + + + + + + + + + + + 1 + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + + + Models/Props/CapturePoint/CenterCrystal.mesh + false + true + + + + + + + + + + + + + 0.30000001192092896 + + + + 30 + + + 3.5 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer1.mesh + false + + + + + + + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + true + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + true + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + true + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + true + + + + + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointBlue.mesh + false + + + + + + + + + + + + + + + 0.5 + + + + 20 + + + 3 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer2.mesh + + false + false + + + + + + + + + + + 0.30000001192092896 + + + + 30 + + + 3.5 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer1.mesh + + false + false + + + + + + + + + + + 0.10000000149011612 + + + + 10 + + + 0.5 + + + + + + + + + + + 1 + + + + + + + + + + + + 4.5 + 0.5 + false + + + + + + + + + + + + 4.5 + 0.5 + false + + + + + + + + + + + + 4.5 + 0.5 + false + + + + + + + + + + + + 4.5 + 0.5 + false + + + + + + + + + + + + + Models/Props/CapturePoint/CenterCrystal.mesh + + false + false + + + + + + + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + false + true + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + false + true + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + false + true + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + false + true + + + + + + + + + + + + + - + - + + 15 + + + + + + + + + - Models/Props/CapturePoint/CapturePointNeutral.mesh + Models/Props/CapturePoint/CapturePointCylinder.mesh + + false + true + - + + - + - - 1 - - + - Models/Core/UnitCylinder.mesh - - true + Models/Props/CapturePoint/CapturePointNeutral.mesh + false - - - - - - + - + + + + + + + + + + + + 0.5 + + + + 20 + + + 3 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer2.mesh + false + false + + + + + + + + + + + 0.10000000149011612 + + + + 10 + + + 0.5 + + + + + + + + + + + Models/Props/CapturePoint/CenterCrystal.mesh + false + false + + + + + + + + + + + 1 + + + + + + + + + + + 4.5 + 0.5 + false + + + + + + + + + + + 4.5 + 0.5 + false + + + + + + + + + + + 4.5 + 0.5 + false + + + + + + + + + + + 4.5 + 0.5 + false + + + + + + + + + + + + + + + 0.30000001192092896 + + + + 30 + + + 3.5 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer1.mesh + false + false + + + + + + + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + false + true + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + false + true + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + false + true + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + false + true + + + + + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointBlue.mesh + false + + + + + + + + + + + + + + + 0.5 + + + + 20 + + + 3 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer2.mesh + + false + false + true + + + + + + + + + + + 0.30000001192092896 + + + + 30 + + + 3.5 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer1.mesh + + false + false + + + + + + + + + + + 0.10000000149011612 + + + + 10 + + + 0.5 + + + + + + + + + + + Models/Props/CapturePoint/CenterCrystal.mesh + + false + false + + + + + + + + + 1 + + + + + + + + + + + + 4.5 + 0.5 + false + + + + + + + + + + + + 4.5 + 0.5 + false + + + + + + + + + + + + 4.5 + 0.5 + false + + + + + + + + + + + + 4.5 + 0.5 + false + + + + + + + + + + + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + false + true + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + false + true + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + false + true + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + false + true + + + + + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointRed.mesh + + + + + + + + + + + + + + + 0.5 + + + + 20 + + + 3 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer2.mesh + + false + + + + + + + + + + + 0.10000000149011612 + + + + 10 + + + 0.5 + + + + + + + + + + + 1 + + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + + + Models/Props/CapturePoint/CenterCrystal.mesh + + false + + + + + + + + + + + + + 0.30000001192092896 + + + + 30 + + + 3.5 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer1.mesh + + false + + + + + + + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + true + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + true + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + true + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + true + + + + + + + + + + + + + - + - + + 2 + + - Models/Props/CapturePoint/CapturePointNeutral.mesh + Models/Props/CapturePoint/CapturePointCylinder.mesh + + false + true + - + + - + - - 3 - - + - Models/Core/UnitCylinder.mesh - - true + Models/Props/CapturePoint/CapturePointBlue.mesh + false - - - - - - + - + + + + + + + + + + + + 0.10000000149011612 + + + + 10 + + + 0.5 + + + + + + + + + + + Models/Props/CapturePoint/CenterCrystal.mesh + + false + false + + + + + + + + + 1 + + + + + + + + + + + + 4.5 + 0.5 + false + + + + + + + + + + + + 4.5 + 0.5 + false + + + + + + + + + + + + 4.5 + 0.5 + false + + + + + + + + + + + + 4.5 + 0.5 + false + + + + + + + + + + + + + + + 0.5 + + + + 20 + + + 3 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer2.mesh + + false + false + + + + + + + + + + + 0.30000001192092896 + + + + 30 + + + 3.5 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer1.mesh + + false + false + + + + + + + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + false + true + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + false + true + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + false + true + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + false + true + + + + + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointNeutral.mesh + + + + + + + + + + + + + + + 0.30000001192092896 + + + + 30 + + + 3.5 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer1.mesh + false + + + + + + + + + + + 0.5 + + + + 20 + + + 3 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer2.mesh + false + + + + + + + + + + + 0.10000000149011612 + + + + 10 + + + 0.5 + + + + + + + + + + + 1 + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + + + Models/Props/CapturePoint/CenterCrystal.mesh + false + + + + + + + + + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + true + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + true + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + true + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + true + + + + + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointRed.mesh + false + + + + + + + + + + + + + + + 0.30000001192092896 + + + + 30 + + + 3.5 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer1.mesh + + false + false + + + + + + + + + + + 0.10000000149011612 + + + + 10 + + + 0.5 + + + + + + + + + + + Models/Props/CapturePoint/CenterCrystal.mesh + + false + false + + + + + + + + + + + 1 + + + + + + + + + + + + 4.5 + 0.5 + false + + + + + + + + + + + + 4.5 + 0.5 + false + + + + + + + + + + + + 4.5 + 0.5 + false + + + + + + + + + + + + 4.5 + 0.5 + false + + + + + + + + + + + + + + + 0.5 + + + + 20 + + + 3 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer2.mesh + + false + false + + + + + + + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + false + true + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + false + true + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + false + true + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + false + true + + + + + + + + + + + + + - + - + + 3 + + - Models/Props/CapturePoint/CapturePointNeutral.mesh + Models/Props/CapturePoint/CapturePointCylinder.mesh + + false + true + - + + - + - - 2 - - + - Models/Core/UnitCylinder.mesh - - true + Models/Props/CapturePoint/CapturePointBlue.mesh + false - - - - - - + - + + + + + + + + + + + + 0.30000001192092896 + + + + 30 + + + 3.5 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer1.mesh + + false + false + + + + + + + + + + + 0.5 + + + + 20 + + + 3 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer2.mesh + + false + false + + + + + + + + + + + 0.10000000149011612 + + + + 10 + + + 0.5 + + + + + + + + + + + Models/Props/CapturePoint/CenterCrystal.mesh + + false + false + + + + + + + + + 1 + + + + + + + + + + + + 4.5 + 0.5 + false + + + + + + + + + + + + 4.5 + 0.5 + false + + + + + + + + + + + + 4.5 + 0.5 + false + + + + + + + + + + + + 4.5 + 0.5 + false + + + + + + + + + + + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + false + true + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + false + true + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + false + true + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + false + true + + + + + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointNeutral.mesh + + + + + + + + + + + + + + + 0.10000000149011612 + + + + 10 + + + 0.5 + + + + + + + + + + + 1 + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + + + Models/Props/CapturePoint/CenterCrystal.mesh + false + + + + + + + + + + + + + 0.30000001192092896 + + + + 30 + + + 3.5 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer1.mesh + false + + + + + + + + + + + 0.5 + + + + 20 + + + 3 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer2.mesh + false + + + + + + + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + true + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + true + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + true + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + true + + + + + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointRed.mesh + false + + + + + + + + + + + + + + + 0.5 + + + + 20 + + + 3 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer2.mesh + + false + false + + + + + + + + + + + 0.10000000149011612 + + + + 10 + + + 0.5 + + + + + + + + + + + 1 + + + + + + + + + + + + 4.5 + 0.5 + false + + + + + + + + + + + + 4.5 + 0.5 + false + + + + + + + + + + + + 4.5 + 0.5 + false + + + + + + + + + + + + 4.5 + 0.5 + false + + + + + + + + + + + + + Models/Props/CapturePoint/CenterCrystal.mesh + + false + false + + + + + + + + + + + + + 0.30000001192092896 + + + + 30 + + + 3.5 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer1.mesh + + false + false + + + + + + + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + false + true + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + false + true + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + false + true + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + false + true + + + + + + + + + + + + + - + - + + -15 + + + + 4 + + + + + + - Models/Props/CapturePoint/CapturePointBlue.mesh + Models/Props/CapturePoint/CapturePointCylinder.mesh + + false + true + - + + - + - - -15 - - - - 4 - - - - - - + - Models/Core/UnitCylinder.mesh - - true + Models/Props/CapturePoint/CapturePointBlue.mesh - - - - - - + - + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + true + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + true + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + true + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + true + + + + + + + + + + + + + + + + + + + + + + + 0.10000000149011612 + + + + 10 + + + 0.5 + + + + + + + + + + + Models/Props/CapturePoint/CenterCrystal.mesh + + false + + + + + + + + + 1 + + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + + + + + 0.30000001192092896 + + + + 30 + + + 3.5 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer1.mesh + + false + + + + + + + + + + + 0.5 + + + + 20 + + + 3 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer2.mesh + + false + + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointRed.mesh + false + + + + + + + + + + + + + + + 0.30000001192092896 + + + + 30 + + + 3.5 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer1.mesh + + false + false + + + + + + + + + + + 0.5 + + + + 20 + + + 3 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer2.mesh + + false + false + + + + + + + + + + + 0.10000000149011612 + + + + 10 + + + 0.5 + + + + + + + + + + + Models/Props/CapturePoint/CenterCrystal.mesh + + false + false + + + + + + + + + + + 1 + + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + false + true + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + false + true + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + false + true + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + false + true + + + + + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointNeutral.mesh + false + + + + + + + + + + + + + + + 0.30000001192092896 + + + + 30 + + + 3.5 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer1.mesh + false + false + + + + + + + + + + + 0.5 + + + + 20 + + + 3 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer2.mesh + false + false + + + + + + + + + + + 0.10000000149011612 + + + + 10 + + + 0.5 + + + + + + + + + + + Models/Props/CapturePoint/CenterCrystal.mesh + false + false + + + + + + + + + + + 1 + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + false + true + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + false + true + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + false + true + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + false + true + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/CapturePointBorderBlue.xml b/resources/Schema/Entities/CapturePointBorderBlue.xml new file mode 100644 index 00000000..9ce9f0cf --- /dev/null +++ b/resources/Schema/Entities/CapturePointBorderBlue.xml @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + true + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + true + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + true + + + + + + + + + + + + + + 6 + + 0.10000000149011612 + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + true + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/CapturePointBorderRed.xml b/resources/Schema/Entities/CapturePointBorderRed.xml new file mode 100644 index 00000000..ebcbbef6 --- /dev/null +++ b/resources/Schema/Entities/CapturePointBorderRed.xml @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + true + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + true + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + true + + + + + + + + + + + + + + 6 + + 0.10000000149011612 + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + true + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/CapturePointBorderSpectator.xml b/resources/Schema/Entities/CapturePointBorderSpectator.xml new file mode 100644 index 00000000..c8211e32 --- /dev/null +++ b/resources/Schema/Entities/CapturePointBorderSpectator.xml @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + true + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + true + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + true + + + + + + + + + + + + + + 6 + + 0.10000000149011612 + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + true + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/FloatingCrystal.xml b/resources/Schema/Entities/FloatingCrystal.xml new file mode 100644 index 00000000..8e1ad5ab --- /dev/null +++ b/resources/Schema/Entities/FloatingCrystal.xml @@ -0,0 +1,169 @@ + + + + + + + + + + + + 0.30000001192092896 + + + + 30 + + + 3.5 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer1.mesh + + false + + + + + + + + + + + 0.5 + + + + 20 + + + 3 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer2.mesh + + false + + + + + + + + + + + 0.10000000149011612 + + + + 10 + + + 0.5 + + + + + + + + + + + Models/Props/CapturePoint/CenterCrystal.mesh + + false + + + + + + + + + 1 + + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/FloatingCrystalBlue.xml b/resources/Schema/Entities/FloatingCrystalBlue.xml new file mode 100644 index 00000000..0b5771cd --- /dev/null +++ b/resources/Schema/Entities/FloatingCrystalBlue.xml @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + 0.30000001192092896 + + + + 30 + + + 3.5 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer1.mesh + + false + true + + + + + + + + + + + 0.5 + + + + 20 + + + 3 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer2.mesh + + false + true + + + + + + + + + + + 0.10000000149011612 + + + + 10 + + + 0.5 + + + + + + + + + + + Models/Props/CapturePoint/CenterCrystal.mesh + + false + true + + + + + + + + + 1 + + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/FloatingCrystalRed.xml b/resources/Schema/Entities/FloatingCrystalRed.xml new file mode 100644 index 00000000..0ca14a15 --- /dev/null +++ b/resources/Schema/Entities/FloatingCrystalRed.xml @@ -0,0 +1,173 @@ + + + + + + + + + + + + + + 0.30000001192092896 + + + + 30 + + + 3.5 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer1.mesh + + false + + + + + + + + + + + 0.5 + + + + 20 + + + 3 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer2.mesh + + false + + + + + + + + + + + 0.10000000149011612 + + + + 10 + + + 0.5 + + + + + + + + + + + Models/Props/CapturePoint/CenterCrystal.mesh + + false + + + + + + + + + + + 1 + + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/FloatingCrystalWhite.xml b/resources/Schema/Entities/FloatingCrystalWhite.xml new file mode 100644 index 00000000..d1ccd894 --- /dev/null +++ b/resources/Schema/Entities/FloatingCrystalWhite.xml @@ -0,0 +1,167 @@ + + + + + + + + + + + + + + 0.30000001192092896 + + + + 30 + + + 3.5 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer1.mesh + false + + + + + + + + + + + 0.5 + + + + 20 + + + 3 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer2.mesh + false + + + + + + + + + + + 0.10000000149011612 + + + + 10 + + + 0.5 + + + + + + + + + + + Models/Props/CapturePoint/CenterCrystal.mesh + false + true + + + + + + + + + + + 1 + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/FloatingCrystal_Blue.xml b/resources/Schema/Entities/FloatingCrystal_Blue.xml new file mode 100644 index 00000000..636a54bc --- /dev/null +++ b/resources/Schema/Entities/FloatingCrystal_Blue.xml @@ -0,0 +1,171 @@ + + + + + + + + + + + + + + 0.20000000298023224 + + + + 10 + + + 0.5 + + + + + + + + + + + Models/Props/CapturePoint/CenterCrystalBlue.mesh + + false + + + + + + + + + 1 + + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + + + + + 0.5 + + + + 30 + + + 3.5 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer1Blue.mesh + + false + + + + + + + + + + + 0.5 + + + + 20 + + + 3 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer2Blue.mesh + + false + + + + + + + + + + diff --git a/resources/Schema/Entities/HealthPickup.xml b/resources/Schema/Entities/HealthPickup.xml index 6474426f..af9530aa 100644 --- a/resources/Schema/Entities/HealthPickup.xml +++ b/resources/Schema/Entities/HealthPickup.xml @@ -2,21 +2,26 @@ - - - Models/Props/PickUps/HealthPickUp.mesh - + 8 + + Models/Props/PickUps/HealthPickUp.mesh + + + + + 1.5 + 3 + - + + - - diff --git a/resources/Schema/Entities/MuzzleFlashGay.xml b/resources/Schema/Entities/MuzzleFlashGay.xml new file mode 100644 index 00000000..62b1c2dc --- /dev/null +++ b/resources/Schema/Entities/MuzzleFlashGay.xml @@ -0,0 +1,102 @@ + + + + + + 0.039999999105930328 + + + + + + + + + Models/Effects/MuzzleFlash/Rainbow/PlaneRight.mesh + false + true + + + + + + + + + Models/Effects/MuzzleFlash/Rainbow/Cone1Outside.mesh + false + true + + + + + + + + + Models/Effects/MuzzleFlash/Rainbow/Cone1Inside.mesh + false + true + + + + + + + + + Models/Effects/MuzzleFlash/Rainbow/Cone2Outside.mesh + false + true + + + + + + + + + Models/Effects/MuzzleFlash/Rainbow/Cone2Inside.mesh + false + true + + + + + + + + + Models/Effects/MuzzleFlash/Rainbow/PlaneUp.mesh + false + true + + + + + + + + + Models/Effects/MuzzleFlash/Rainbow/PlaneDown.mesh + false + true + + + + + + + + + Models/Effects/MuzzleFlash/Rainbow/PlaneLeft.mesh + false + true + + + + + + + + diff --git a/resources/Schema/Entities/CP_RockHard.xml b/resources/Schema/Entities/NewMap2version6NEW.xml similarity index 72% rename from resources/Schema/Entities/CP_RockHard.xml rename to resources/Schema/Entities/NewMap2version6NEW.xml index 9f11d052..5544ba82 100644 --- a/resources/Schema/Entities/CP_RockHard.xml +++ b/resources/Schema/Entities/NewMap2version6NEW.xml @@ -2,10 +2,6 @@ - - 0.58443805362486501 - 3 - @@ -21,7 +17,6 @@ 2 Models/Props/GroundTest.mesh - @@ -29,6 +24,7 @@ + 2 Models/Props/Walls/SciFiWallTop.mesh @@ -38,6 +34,42 @@ + 2 + Models/Props/Walls/SciFiWallBig.mesh + + + + + + + + + + + + 2 + Models/Props/Walls/SciFiWallBig.mesh + + + + + + + + + + 2 + Models/Props/Walls/SciFiWallMedium.mesh + + + + + + + + + + 2 Models/Props/Walls/SciFiWallSmall1.mesh @@ -48,6 +80,7 @@ + 2 Models/Props/Walls/SciFiWallSmall2.mesh @@ -58,39 +91,7 @@ - Models/Props/Walls/SciFiWallBig.mesh - - - - - - - - - - - - Models/Props/Walls/SciFiWallBig.mesh - true - - - - - - - - - - Models/Props/Walls/SciFiWallMedium.mesh - - - - - - - - - + 2 Models/Props/Walls/SciFiWallMedium.mesh @@ -103,6 +104,7 @@ + 2 Models/Props/Walls/SciFiWallSmall3.mesh @@ -113,6 +115,7 @@ + 2 Models/Props/Walls/SciFiWallSmall4.mesh @@ -125,7 +128,7 @@ - Models/Props/Highground1.mesh + Models/Highgrounds/Highground1.mesh @@ -135,8 +138,7 @@ - Models/Props/Highground2.mesh - + Models/Highgrounds/Highground2.mesh @@ -146,7 +148,7 @@ - Models/Props/Highground3.mesh + Models/Highgrounds/Highground3.mesh @@ -158,10 +160,9 @@ Models/Highgrounds/Highground24.mesh - - + @@ -236,7 +237,7 @@ Models/Highgrounds/Hg10.mesh - + @@ -250,7 +251,7 @@ Models/Highgrounds/Hg19.mesh - + @@ -612,33 +613,7 @@ - Models/Props/Highground1.mesh - - - - - - - - - - - - Models/Props/Highground2.mesh - - - - - - - - - - - - - Models/Props/Highground3.mesh - + Models/Highgrounds/Highground3.mesh @@ -660,6 +635,7 @@ + Models/Highgrounds/Highground2.mesh @@ -703,11 +679,36 @@ Models/Highgrounds/Highground5.mesh - + + + + + + Models/Highgrounds/Hg10.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg4.mesh + + + + + + + @@ -778,7 +779,8 @@ Models/Highgrounds/Hg6.mesh - + + @@ -795,30 +797,6 @@ - - - - - Models/Highgrounds/Hg10.mesh - - - - - - - - - - - - Models/Highgrounds/Hg4.mesh - - - - - - - @@ -826,7 +804,7 @@ Models/Highgrounds/Hg16.mesh - + @@ -877,7 +855,7 @@ Models/Props/Pillars/SciFiPillar2Red.mesh - + @@ -919,7 +897,7 @@ Models/Highgrounds/Hg10.mesh - + @@ -932,7 +910,7 @@ Models/Props/Walls/BigWallRed.mesh - + @@ -1088,7 +1066,7 @@ Models/Props/Pillars/SciFiPillar2Red.mesh - + @@ -1168,8 +1146,8 @@ Models/Props/Stones/AssaultHolder.mesh - - + + @@ -1181,8 +1159,8 @@ Models/Props/Stones/AssaultHolder.mesh - - + + @@ -1359,7 +1337,7 @@ Models/Highgrounds/Hg28.mesh - + @@ -1419,518 +1397,42 @@ - - - - - - - - Models/Props/Stones/ShinyStoneCrystalBlue.mesh + Models/Highgrounds/Hg1.mesh - - - + + - - - - - - - Models/Props/Bridges/SciFiBridgeDefense.mesh - - - - - - - - - - - - - Models/Props/Stones/ShinyStoneCrystalBlue.mesh - - - - - - - - - - - - - Models/Props/Stones/ShinyStoneCrystalBlue.mesh - - - - - - - - - - - - - - Models/Props/Bridges/SciFiBridgeDefense.mesh - - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - - - Models/Props/Bridges/SciFiBridgeDefense.mesh - - - - - - - - - - - - - Models/Props/Stones/ShinyStoneCrystalBlue.mesh - - - - - - - - - - - - - Models/Props/Stones/ShinyStoneCrystalBlue.mesh - - - - - - - - - - - - - - Models/Props/Stones/ShinyStoneCrystalBlue.mesh - - - - - - - - - - - - - 6 - Models/Props/Stones/ShinyStoneCrystalBlue.mesh - - - - - - - - - - - - - - Models/Props/SciFiHolder1.mesh - - - - - - - - - - - - - Models/Props/Pillars/SciFiPillar1Blue.mesh - - - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - - Models/Props/Bridges/SciFiBridgeDefense.mesh - - - - - - - - - - - - - Models/Props/Bridges/SciFiBridgeDefense.mesh - - - - - - - - - - - - - Models/Props/Bridges/SciFiBridgeDefense.mesh - - - - - - - - - - - - - 6 - Models/Props/Stones/ShinyStoneCrystalBlue.mesh - - - - - - - - + + + + + + Models/Highgrounds/Hg2.mesh + + + + + + + + - + - - - - + + + - - - - - 6 - Models/Props/Pillars/SciFiPillar1Red.mesh - - - - - - - - - - - - - 4 - Models/Props/Pillars/SciFiPillar2Red.mesh - - - - - - - - - - - - - - 4 - Models/Props/Pillars/SciFiPillar1Red.mesh - - - - - - - - - - - - - - 4 - Models/Props/Pillars/SciFiPillar3Red.mesh - - - - - - - - - - - - - - 6 - Models/Props/Pillars/SciFiPillar2Red.mesh - - - - - - - - - - - - - Models/Props/Pillars/SciFiPillar2Blue.mesh - - - - - - - - - - - - - - 4 - Models/Props/Pillars/SciFiPillar2Red.mesh - - - - - - - - - - - - - - 6 - Models/Props/Pillars/SciFiPillar2Red.mesh - - - - - - - - - - - - - 6 - Models/Props/Pillars/SciFiPillar2Red.mesh - - - - - - - - - - - - - - 6 - Models/Props/Pillars/SciFiPillar2Red.mesh - - - - - - - - - - - - - Models/Props/Pillars/SciFiPillar2Red.mesh - - - - - - - - - - - - - - 6 - Models/Props/Pillars/SciFiPillar2Red.mesh - - - - - - - - - - - - - 6 - Models/Props/Pillars/SciFiPillar2Red.mesh - - - - - - - - - - - - - - 6 - Models/Props/Pillars/SciFiPillar2Red.mesh - - - - - - - - - - - - - - 4 - Models/Props/Pillars/SciFiPillar3Red.mesh - - - - - - - - - - - - - - - - - + @@ -1939,11 +1441,262 @@ - Models/Props/SciFiHolder1.mesh + Models/Props/Bridges/Bridge1_SciFi_Blue.mesh - - + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + + + + + + + + + + Models/Props/Bridges/Bridge1_SciFi_Blue.mesh + + + + + + + + + + + + Models/Props/Bridges/Bridge1_SciFi_Blue.mesh + + + + + + + + + + + + Models/Props/Bridges/SciFi_Bridge_Support_Top_Blue.mesh + + + + + + + + + + + + Models/Props/Bridges/SciFi_Bridge_Support_Bot_Blue.mesh + + + + + + + + + + + 12 + + + + + + + + + + + + + Models/Props/Bridges/SciFi_Bridge_Support_Middle_Blue.mesh + + + + + + + + + + + + + + + + + + Models/Props/Bridges/SciFi_Bridge_Support_Top_Blue.mesh + + + + + + + + + + + + Models/Props/Bridges/SciFi_Bridge_Support_Bot_Blue.mesh + + + + + + + + + + + 12 + + + + + + + + + + + + + Models/Props/Bridges/SciFi_Bridge_Support_Middle_Blue.mesh + + + + + + + + + + + + + + + + + + Models/Props/Bridges/Bridge1_SciFi_Blue.mesh + + + + + @@ -1952,11 +1705,72 @@ - Models/Props/SciFiHolder1.mesh + Models/Props/Bridges/SciFi_Bridge_Support_Top_Blue.mesh - - + + + + + + + + + + + Models/Props/Bridges/SciFi_Bridge_Support_Bot_Blue.mesh + + + + + + + + + + + 12 + + + + + + + + + + + + + Models/Props/Bridges/SciFi_Bridge_Support_Middle_Blue.mesh + + + + + + + + + + + + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.mesh + + + + + @@ -1965,15 +1779,673 @@ - Models/Props/SciFiHolder1.mesh + Models/Props/Walls/SpecialWall1.mesh - - + + + + + + + + Models/Props/Walls/SpecialWall1.mesh + + + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.mesh + + + + + + + + + + + + + + + + + + + + + Models/Props/Flora/Root.mesh + + + + + + + + + + + + + + Models/Props/Flora/Root.mesh + + + + + + + + + + + + + Models/Props/Flora/Root.mesh + + + + + + + + + + + + + + Models/Props/Flora/Root.mesh + + + + + + + + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar1Blue.mesh + + + + + + + + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/MediumWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/MediumWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/MediumWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/MediumWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/MediumWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/MediumWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/MediumWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + + Models/Core/UnitPlane.mesh + + true + + + + + + + + + + + + + + @@ -2000,23 +2472,15 @@ - - - - - - - - Models/Props/Flora/SpecialRoot.mesh + Models/Props/SciFiHolder1.mesh - - - + + @@ -2025,39 +2489,11 @@ - Models/Props/Flora/SpecialRoot.mesh + Models/Props/SciFiHolder1.mesh - - - - - - - - - - - - Models/Props/Flora/SpecialRoot.mesh - - - - - - - - - - - - - - Models/Props/Flora/SpecialRoot.mesh - - - - + + @@ -2073,231 +2509,8 @@ - 6 - Models/Props/Stones/ShinyStoneCrystalRed.mesh - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2 - - - - - - - - - - - - - - 5 - Models/Props/Stones/ShinyStoneCrystalRed.mesh - - - - - - - - - - - - - - 6 - Models/Props/Stones/ShinyStoneCrystalRed.mesh - - - - - - - - - - - - - - 6 - Models/Props/Stones/ShinyStoneCrystalRed.mesh - - - - - - - - - - - - - 2 - - - - - - - - - - - - - - 6 - Models/Props/Stones/ShinyStoneCrystalRed.mesh - - - - - - - - - - - - - - 4 - Models/Props/Stones/ShinyStoneCrystalRed.mesh - - - - - - - - - - - - - - 2 - - - - - - - - - - - - 3 - - - - - - - - - - - - 2 - 1 - - - - - - - - - - - - - - 6 - Models/Props/Stones/ShinyStoneCrystalRed.mesh - - - - - - - - - - - - - - 6 - Models/Props/Stones/ShinyStoneCrystalRed.mesh - - - - - - - - - - - - - - 4 - Models/Props/Stones/ShinyStoneCrystalRed.mesh - - - - - - - - - - - - - - - 6 - Models/Props/Stones/ShinyStoneCrystalRed.mesh + 15 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh @@ -2311,7 +2524,121 @@ - 6 + 15 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 15 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 2 + + + + + + + + + + + + 2 + 1 + + + + + + + + + + + + 3 + + + + + + + + + + + + + + 15 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 15 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 15 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 15 Models/Props/Stones/ShinyStoneCrystalRed.mesh @@ -2326,12 +2653,41 @@ - 6 - Models/Props/Stones/ShinyStoneCrystalRed.mesh + 15 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh - - + + + + + + + + + + + 2 + + + + + + + + + + + + + + 15 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + @@ -2340,27 +2696,12 @@ - 6 - Models/Props/Stones/ShinyStoneCrystalRed.mesh + 15 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh - - - - - - - - - - - - 6 - Models/Props/Stones/ShinyStoneCrystalRed.mesh - - - - + + @@ -2370,11 +2711,63 @@ - Models/Props/Stones/ShinyStoneCrystalRed.mesh + 15 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh - - + + + + + + + + + + + 2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 15 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + @@ -2386,6 +2779,19 @@ + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + @@ -2404,11 +2810,38 @@ - Models/Props/Stones/mediumStone2.mesh + Models/Props/Stones/SmallStone2.mesh - - + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + @@ -2420,26 +2853,12 @@ Models/Props/Stones/SmallStone1.mesh - - + + + - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - + @@ -2448,103 +2867,49 @@ Models/Props/Stones/SmallStone1.mesh - + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - - Models/Props/Stones/MediumStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/BigStone.mesh - - - - - - - - - - - - - - Models/Props/Stones/mediumStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/BigStone.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - @@ -2576,33 +2941,6 @@ - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - @@ -2623,8 +2961,8 @@ Models/Props/Stones/SmallStone1.mesh - - + + @@ -2633,38 +2971,11 @@ - Models/Props/Stones/SmallStone1.mesh + Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - + + @@ -2683,193 +2994,6 @@ - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - Models/Props/Stones/MediumStone2.mesh - - - - - - - - - - - - - - Models/Props/Stones/BigStone.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/BigStone.mesh - - - - - - - - - - - - Models/Props/Stones/BigStone.mesh - - - - - - - - - - - - - Models/Props/Stones/MediumStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/MediumStone2.mesh - - - - - - - - - - - - - - Models/Props/Stones/mediumStone2.mesh - - - - - - - - - - - - - - Models/Props/Stones/mediumStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/mediumStone2.mesh - - - - - - - - - - - - - - Models/Props/Stones/mediumStone2.mesh - - - - - - - - - @@ -2884,20 +3008,6 @@ - - - - - Models/Props/Stones/MediumStone2.mesh - - - - - - - - - @@ -2905,9 +3015,8 @@ Models/Props/Stones/BigStone.mesh - - - + + @@ -2919,9 +3028,8 @@ Models/Props/Stones/SmallStone1.mesh - - - + + @@ -2933,87 +3041,8 @@ Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - Models/Props/Stones/BigStone.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - - Models/Props/Stones/BigStone.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - Models/Props/Stones/MediumStone2.mesh - - - - + + @@ -3036,11 +3065,11 @@ - Models/Props/Stones/MediumStone2.mesh + Models/Props/Stones/SmallStone2.mesh - - + + @@ -3066,9 +3095,47 @@ Models/Props/Stones/SmallStone2.mesh - - - + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + @@ -3087,33 +3154,6 @@ - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - Models/Props/Stones/mediumStone2.mesh - - - - - - - - - @@ -3121,8 +3161,7 @@ Models/Props/Stones/SmallStone2.mesh - - + @@ -3134,9 +3173,8 @@ Models/Props/Stones/SmallStone1.mesh - - - + + @@ -3148,36 +3186,9 @@ Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - + + + @@ -3195,20 +3206,6 @@ - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - @@ -3240,11 +3237,12 @@ - Models/Props/Stones/MediumStone2.mesh + Models/Props/Stones/SmallStone1.mesh - - + + + @@ -3256,9 +3254,23 @@ Models/Props/Stones/SmallStone2.mesh - - - + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + @@ -3270,9 +3282,73 @@ Models/Props/Stones/MediumStone2.mesh - - - + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + @@ -3298,9 +3374,9 @@ Models/Props/Stones/SmallStone2.mesh - - - + + + @@ -3309,11 +3385,11 @@ - Models/Props/Stones/SmallStone2.mesh + Models/Props/Stones/SmallStone1.mesh - - + + @@ -3322,12 +3398,11 @@ - Models/Props/Stones/SmallStone2.mesh + Models/Props/Stones/SmallStone1.mesh - - - + + @@ -3336,11 +3411,66 @@ - Models/Props/Stones/SmallStone2.mesh + Models/Props/Stones/SmallStone1.mesh - - + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + @@ -3365,8 +3495,9 @@ Models/Props/Stones/SmallStone1.mesh - - + + + @@ -3378,8 +3509,8 @@ Models/Props/Stones/BigStone.mesh - - + + @@ -3391,15 +3522,172 @@ Models/Props/Stones/SmallStone2.mesh - - + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/mediumStone2.mesh + + + + - + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + @@ -3423,48 +3711,6 @@ - - - - Models/Props/PickUps/PickUpHolder.mesh - - - - - - - - - - - - - - - - - - - - - 8 - - - - Models/Props/PickUps/HealthPickUp.mesh - - - - - - - - - - - - - @@ -3479,8 +3725,13 @@ + + 2 + + + - + @@ -3495,135 +3746,10 @@ Models/Props/PickUps/HealthPickUp.mesh + - - - - - - - - - - - - - - Models/Props/PickUps/PickUpHolder.mesh - - - - - - - - - - - - - - - - - - - - - 8 - - - - Models/Props/PickUps/AmmoPickUp.mesh - - - - - - - - - - - - - - - - - Models/Props/PickUps/PickUpHolder.mesh - - - - - - - - - - - - - - - - - - - - - 8 - - - - Models/Props/PickUps/HealthPickUp.mesh - - - - - - - - - - - - - - - - - Models/Props/PickUps/PickUpHolder.mesh - - - - - - - - - - - - - - - - - - - - - 8 - - - - Models/Props/PickUps/AmmoPickUp.mesh - - - - + @@ -3647,8 +3773,13 @@ + + 2 + + + - + @@ -3663,93 +3794,10 @@ Models/Props/PickUps/HealthPickUp.mesh + - - - - - - - - - - - - - - Models/Props/PickUps/PickUpHolder.mesh - - - - - - - - - - - - - - - - - - - - - 8 - - - - Models/Props/PickUps/HealthPickUp.mesh - - - - - - - - - - - - - - - - - Models/Props/PickUps/PickUpHolder.mesh - - - - - - - - - - - - - - - - - - - - - 8 - - - - Models/Props/PickUps/AmmoPickUp.mesh - - - - + @@ -3773,8 +3821,13 @@ + + 2 + + + - + @@ -3789,9 +3842,202 @@ Models/Props/PickUps/HealthPickUp.mesh + - + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + 2 + + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + 2 + + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + 2 + + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + 2 + + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + + + @@ -3803,7 +4049,358 @@ - + + + + + + + + + + + + 15 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + true + false + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + true + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + true + + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + 15 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + 10 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + 15 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar1Blue.mesh + + + + + + + + + + + + + + 15 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 15 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + + + Models/Props/SciFiHolder1.mesh + + + + + + + + + + + + + 15 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + + + 15 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + + + + @@ -3812,11 +4409,11 @@ - Models/Props/Pillars/SciFiPillar2Red.mesh + Models/Props/Walls/MediumWall3.mesh - - + + @@ -3825,11 +4422,211 @@ - Models/Props/Pillars/StonePillar.mesh + Models/Props/Walls/SmallWall3.mesh - - + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/MediumWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + Models/Props/Walls/MediumWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/MediumWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + @@ -3839,10 +4636,12 @@ - Models/Props/Pillars/StonePillar.mesh + Models/Props/Walls/SmallWall3.mesh - + + + @@ -3851,12 +4650,37 @@ - Models/Props/Pillars/StonePillar.mesh + Models/Props/Walls/BigWallRed.mesh - - - + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + + + Models/Props/Walls/MediumWall3.mesh + + + + @@ -3865,30 +4689,1085 @@ - 6 - Models/Props/Pillars/SciFiPillar1Red.mesh + Models/Props/Walls/MediumWall3.mesh - - + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/MediumWall3.mesh + + + + + + + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + + + + + + + Models/Props/Bridges/Bridge1_SciFi_Red.mesh + + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + + + Models/Props/Bridges/SciFi_Bridge_Support_Top_Red.mesh + + + + + + + + + + + 12 + + + + + + + + + + + + + Models/Props/Bridges/SciFi_Bridge_Support_Middle_Red.mesh + + + + + + + + + + + + + + Models/Props/Bridges/SciFi_Bridge_Support_Bot_Red.mesh + + + + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + + + Models/Props/Bridges/Bridge1_SciFi_Red.mesh + + + + + + + + + + + + Models/Props/Bridges/SciFi_Bridge_Support_Top_Red.mesh + + + + + + + + + + + 12 + + + + + + + + + + + + + Models/Props/Bridges/SciFi_Bridge_Support_Middle_Red.mesh + + + + + + + + + + + + + + Models/Props/Bridges/SciFi_Bridge_Support_Bot_Red.mesh + + + + + + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + + + + + Models/Props/Bridges/SciFi_Bridge_Support_Top_Red.mesh + + + + + + + + + + + + 12 + + + + + + + + + + + + + Models/Props/Bridges/SciFi_Bridge_Support_Middle_Red.mesh + + + + + + + + + + + + + + Models/Props/Bridges/SciFi_Bridge_Support_Bot_Red.mesh + + + + + + + + + + + + + + Models/Props/Bridges/Bridge1_SciFi_Red.mesh + + + + + + + + + + + + + + Models/Props/Bridges/Bridge1_SciFi_Red.mesh + + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + - + + + + + 2 + + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + + + + + + + + + - - Models/Props/Pillars/SciFiPillar2Red.mesh + Models/Props/PickUps/PickUpHolder.mesh - - - + + + - + + + + + 2 + + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + 2 + + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + 1.5 + 1 + 0.30000001192092896 + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + 2 + + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + 2 + + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + 2 + + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + 2 + + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + 2 + + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + 2 + + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + + + + + + + + + @@ -3955,7 +5834,7 @@ - + @@ -3964,424 +5843,11 @@ - Models/Props/Bridges/SciFiBridge1Red.mesh + Models/Props/Flora/Root.mesh - - - - - - - - - - Models/Props/Bridges/SciFiBridgeDefense.mesh - - - - - - - - - - - - Models/Props/Bridges/SciFiBridgeDefense.mesh - - - - - - - - - - - Models/Props/Bridges/SciFiBridgeDefense.mesh - - - - - - - - - - - Models/Props/Bridges/SciFiBridgeDefense.mesh - - - - - - - - - - - - - - - - - - Models/Props/Bridges/SciFiBridgeDefense.mesh - - - - - - - - - - - - Models/Props/Bridges/SciFiBridgeDefense.mesh - - - - - - - - - - - Models/Props/Bridges/SciFiBridgeDefense.mesh - - - - - - - - - - - Models/Props/Bridges/SciFiBridgeDefense.mesh - - - - - - - - - - - - - - - - - - - - Models/Props/Bridges/SciFiBridge1Red.mesh - - - - - - - - - - - - Models/Props/Bridges/SciFiBridgeDefense.mesh - - - - - - - - - - - - - Models/Props/Bridges/SciFiBridgeDefense.mesh - - - - - - - - - - - - - Models/Props/Bridges/SciFiBridgeDefense.mesh - - - - - - - - - - - - - Models/Props/Bridges/SciFiBridge1Red.mesh - - - - - - - - - - - - Models/Props/Pillars/SciFiBridgePillar1.mesh - - - - - - - - - - - - - - - Models/Props/Bridges/SciFiBridgeDefense.mesh - - - - - - - - - - - - - Models/Props/Bridges/SciFiBridgeDefense.mesh - - - - - - - - - - - - - Models/Props/Pillars/SciFiBridgePillar1.mesh - - - - - - - - - - - - - Models/Props/Bridges/SciFiBridgeDefense.mesh - - - - - - - - - - - - - - - Models/Props/Pillars/SciFiBridgePillar1.mesh - - - - - - - - - - - - - - Models/Props/Bridges/SciFiBridge1Red.mesh - - - - - - - - - - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - Models/Props/Walls/MediumWall3.mesh - - - - - - - - - - - - - Models/Props/Walls/BigWallRed.mesh - - - - + + @@ -4391,11 +5857,12 @@ - Models/Props/Walls/BigWallRed.mesh + Models/Props/Flora/Root.mesh - - + + + @@ -4404,11 +5871,12 @@ - Models/Props/Walls/MediumWall3.mesh + Models/Props/Flora/Root.mesh - - + + + @@ -4417,366 +5885,12 @@ - Models/Props/Walls/MediumWall3.mesh + Models/Props/Flora/Root.mesh - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - - Models/Props/Walls/MediumWall3.mesh - - - - - - - - - - - - - Models/Props/Walls/BigWallRed.mesh - - - - - - - - - - - Models/Props/Walls/BigWallRed.mesh - - - - - - - - - - - - - - - Models/Props/Walls/BigWallRed.mesh - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - - Models/Props/Walls/MediumWall3.mesh - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - Models/Props/Walls/BigWallBlue.mesh - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - Models/Props/Walls/BigWallRed.mesh - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - - Models/Props/Walls/MediumWall3.mesh - - - - - - - - - - - - - Models/Props/Walls/MediumWall3.mesh - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - + + + @@ -4798,14 +5912,7 @@ - - - - - - - - + @@ -4814,13 +5921,11 @@ - 6 - Models/Props/Stones/ShinyStoneCrystalRed.mesh + Models/Props/SciFiHolder1.mesh - - - + + @@ -4829,454 +5934,61 @@ - 6 - Models/Props/Stones/ShinyStoneCrystalRed.mesh + Models/Props/SciFiHolder1.mesh - - - + + + + + + + + + + + Models/Props/SciFiHolder1.mesh + + + + + + + + + + + + + Models/Props/SciFiHolder1.mesh + + + + + + + + + + + + + Models/Props/SciFiHolder1.mesh + + + + - + - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - - Models/Props/Walls/BigWallBlue.mesh - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - - Models/Props/Walls/BigWallRed.mesh - - - - - - - - - - - - - Models/Props/Walls/BigWallBlue.mesh - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - - Models/Props/Walls/MediumWall3.mesh - - - - - - - - - - - - - Models/Props/Walls/BigWallRed.mesh - - - - - - - - - - - - - Models/Props/Walls/smallWall3.mesh - - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - - - - - - - - - Models/Props/Stones/BigStone.mesh - - - - - - - - - - - - - Models/Props/Stones/MediumStone2.mesh - - - - - - - - @@ -5284,666 +5996,7 @@ Models/Props/Pillars/StonePillar.mesh - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - - Models/Props/Stones/MediumStone2.mesh - - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - - Models/Props/Stones/MediumStone2.mesh - - - - - - - - - - - - - - Models/Props/Stones/MediumStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - - Models/Props/Stones/MediumStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/BigStone.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - Models/Props/Stones/MediumStone2.mesh - - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - Models/Props/Stones/mediumStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - - Models/Props/Stones/MediumStone2.mesh - - - - - - - - - - - - - - - - - - - Models/Props/PickUps/PickUpHolder.mesh - - - - - - - - - - - - - - - - - - - - - 8 - - - - Models/Props/PickUps/AmmoPickUp.mesh - - - - - - - - - - - - - - - - - Models/Props/PickUps/PickUpHolder.mesh - - - - - - - - - - - - - - - - - - - - - 8 - - - - Models/Props/PickUps/HealthPickUp.mesh - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 6 - Models/Props/Stones/ShinyStoneCrystalBlue.mesh - - - - - - - - - - - - - - 6 - Models/Props/Stones/ShinyStoneCrystalBlue.mesh - - - - - - - - - - - - - - - - - - - - - - - - 2 - - - - - - - - - - - - - - - - - - - - - - - - - 4 - Models/Props/Stones/ShinyStoneCrystalBlue.mesh - - - - - - - - - - - - - - - 6 - Models/Props/Stones/ShinyStoneCrystalBlue.mesh - - - - - - - - - - - - - 2 - - - - - - - - - - - - - - 6 - Models/Props/Stones/ShinyStoneCrystalBlue.mesh - - - - - - - - - - - - - - 6 - Models/Props/Stones/ShinyStoneCrystalRed.mesh - - - - - - - - - - - - - - 4 - Models/Props/Stones/ShinyStoneCrystalBlue.mesh - - - - - - - - - - - - - - 2 - 1 - - - - - - - - - - - - 2 - - - - - - - - - - - - 3 - - - - - - - - - - - - - - 6 - Models/Props/Stones/ShinyStoneCrystalBlue.mesh - - - - - - - - - - - - - - 5 - Models/Props/Stones/ShinyStoneCrystalBlue.mesh - - - - - - - - - - - - - - 6 - Models/Props/Stones/ShinyStoneCrystalBlue.mesh - - - - - - - - - - - - - - 6 - Models/Props/Stones/ShinyStoneCrystalBlue.mesh - - - - - - - - - - - - - - 6 - Models/Props/Stones/ShinyStoneCrystalBlue.mesh - - - - - + @@ -5959,12 +6012,10 @@ - Models/Props/Stones/SmallStone2.mesh + Models/Props/Stones/BigStone.mesh - - - + @@ -5976,167 +6027,7 @@ Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - - Models/Props/Stones/MediumStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/MediumStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/mediumStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - + @@ -6147,363 +6038,29 @@ - Models/Props/Stones/MediumStone2.mesh + Models/Props/Stones/SmallStone2.mesh - - + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + - - - - - Models/Props/Stones/BigStone.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - - Models/Props/Stones/BigStone.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/MediumStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - - Models/Props/Stones/MediumStone2.mesh - - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - Models/Props/Stones/MediumStone2.mesh - - - - - - - - - - - - - - Models/Props/Stones/BigStone.mesh - - - - - - - - - - - - - Models/Props/Stones/MediumStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - - Models/Props/Stones/BigStone.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone1.mesh - - - - - - - - - @@ -6525,8 +6082,197 @@ Models/Props/Stones/SmallStone1.mesh - - + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + @@ -6566,9 +6312,34 @@ Models/Props/Stones/SmallStone2.mesh - - - + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + @@ -6580,8 +6351,64 @@ Models/Props/Stones/SmallStone1.mesh - - + + + + + + + + + + + + Models/Props/Stones/mediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/mediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + @@ -6599,6 +6426,34 @@ + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + @@ -6606,9 +6461,142 @@ Models/Props/Stones/SmallStone1.mesh - - - + + + + + + + + + + + + Models/Props/Stones/mediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + @@ -6634,35 +6622,9 @@ Models/Props/Stones/BigStone.mesh - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - + + + @@ -6674,9 +6636,9 @@ Models/Props/Stones/SmallStone1.mesh - - - + + + @@ -6685,11 +6647,12 @@ - Models/Props/Stones/SmallStone1.mesh + Models/Props/Stones/MediumStone2.mesh - - + + + @@ -6698,37 +6661,11 @@ - Models/Props/Stones/SmallStone2.mesh + Models/Props/Stones/mediumStone2.mesh - - - - - - - - - - - Models/Props/Stones/BigStone.mesh - - - - - - - - - - - - - Models/Props/Stones/SmallStone2.mesh - - - - + + @@ -6753,13 +6690,309 @@ Models/Props/Stones/SmallStone1.mesh - - + + + + + + + + + + + Models/Props/Stones/mediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/mediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + + + Models/Props/Stones/mediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + @@ -6780,8 +7013,254 @@ Models/Props/Stones/BigStone.mesh - - + + + + + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + + + + + + + 7 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 7 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 7 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 7 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + 7 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 7 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 7 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 7 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 7 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 7 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 7 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + @@ -6791,12 +7270,13 @@ - Models/Props/Stones/SmallStone1.mesh + 7 + Models/Props/Stones/ShinyStoneCrystalRed.mesh - - - + + + @@ -6805,376 +7285,12 @@ - Models/Props/Stones/SmallStone2.mesh + 7 + Models/Props/Stones/ShinyStoneCrystalRed.mesh - - - - - - - - - - - - - - - - - - Models/Props/PickUps/PickUpHolder.mesh - - - - - - - - - - - - - - - - - - - - - 8 - - - - Models/Props/PickUps/AmmoPickUp.mesh - - - - - - - - - - - - - - - - - Models/Props/PickUps/PickUpHolder.mesh - - - - - - - - - - - - - - - - - - - - - 8 - - - - Models/Props/PickUps/HealthPickUp.mesh - - - - - - - - - - - - - - - - - Models/Props/PickUps/PickUpHolder.mesh - - - - - - - - - - - - - - - - - - - - - 8 - - - - Models/Props/PickUps/AmmoPickUp.mesh - - - - - - - - - - - - - - - - - Models/Props/PickUps/PickUpHolder.mesh - - - - - - - - - - - - - - - - - - - - - 8 - - - - Models/Props/PickUps/AmmoPickUp.mesh - - - - - - - - - - - - - - - - - Models/Props/PickUps/PickUpHolder.mesh - - - - - - - - - - - - - - - - - - - - - 8 - - - - Models/Props/PickUps/HealthPickUp.mesh - - - - - - - - - - - - - - - - - Models/Props/PickUps/PickUpHolder.mesh - - - - - - - - - - - - - - - - - - - - - 8 - - - - Models/Props/PickUps/HealthPickUp.mesh - - - - - - - - - - - - - - - - - Models/Props/PickUps/PickUpHolder.mesh - - - - - - - - - - - - - - - - - - - - - 8 - - - - Models/Props/PickUps/HealthPickUp.mesh - - - - - - - - - - - - - - - - - - - - - - - - - Models/Props/Walls/SpecialWall1.mesh - - - - - - - - - - - - - - Models/Props/Walls/SpecialWall1.mesh - - - - - - - - - - - - - - Models/Props/Walls/SpecialWall1.mesh - - - - - - - - - - - - - - Models/Props/Walls/SpecialWall1.mesh - - - - - + + @@ -7193,41 +7309,25 @@ Models/Props/Pillars/StonePillar.mesh - + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + - - - - - Models/Props/Pillars/SciFiPillar2Blue.mesh - - - - - - - - - - - - - 6 - Models/Props/Pillars/SciFiPillar1Blue.mesh - - - - - - - - - @@ -7246,10 +7346,11 @@ - Models/Props/Pillars/StonePillar.mesh + Models/Props/Pillars/SciFiPillar2Red.mesh - + + @@ -7258,7 +7359,7 @@ - Models/Props/Pillars/SciFiPillar2Blue.mesh + Models/Props/Pillars/SciFiPillar2Red.mesh @@ -7268,866 +7369,17 @@ - - - - - - - - Models/Props/Bridges/SciFiBridge1Blue.mesh + 6 + Models/Props/Pillars/SciFiPillar1Red.mesh - - - - - - - - - - Models/Props/Bridges/SciFiBridge1Blue.mesh - - - - - - - - - - - - Models/Props/Pillars/SciFiBridgePillar1.mesh - - - - - - - - - - - - - - - Models/Props/Pillars/SciFiBridgePillar1.mesh - - - - - - - - - - - - - - - Models/Props/Pillars/SciFiBridgePillar1.mesh - - - - - - - - - - - - - - Models/Props/Bridges/SciFiBridge1Blue.mesh - - - - - - - - - - - - - - Models/Props/Bridges/SciFiBridge1Blue.mesh - - - - - - - - - - - - Models/Props/Bridges/SciFiBridgeDefense.mesh - - - - - - - - - - - - Models/Props/Bridges/SciFiBridgeDefense.mesh - - - - - - - - - - - Models/Props/Bridges/SciFiBridgeDefense.mesh - - - - - - - - - - - Models/Props/Bridges/SciFiBridgeDefense.mesh - - - - - - - - - - - - - - - - - - Models/Props/Bridges/SciFiBridgeDefense.mesh - - - - - - - - - - - - Models/Props/Bridges/SciFiBridgeDefense.mesh - - - - - - - - - - - Models/Props/Bridges/SciFiBridgeDefense.mesh - - - - - - - - - - - Models/Props/Bridges/SciFiBridgeDefense.mesh - - - - - - - - - - - - - - - - - - - - - - - - - - - Models/Props/SciFiHolder1.mesh - - - - - - - - - - - - - Models/Props/SciFiHolder1.mesh - - - - - - - - - - - - - Models/Props/SciFiHolder1.mesh - - - - - - - - - - - - - Models/Props/SciFiHolder1.mesh - - - - - - - - - - - - - - - - - - - - Models/Props/Flora/SpecialRoot.mesh - - - - - - - - - - - - - Models/Props/Flora/SpecialRoot.mesh - - - - - - - - - - - - - - Models/Props/Flora/SpecialRoot.mesh - - - - - - - - - - - - - - Models/Props/Flora/SpecialRoot.mesh - - - - - - - - - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - Models/Props/Walls/BigWallBlue.mesh - - - - - - - - - - - - - - Models/Props/Walls/BigWallBlue.mesh - - - - - - - - - - - Models/Props/Walls/BigWallBlue.mesh - - - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - Models/Props/Walls/BigWallBlue.mesh - - - - - - - - - - - - - Models/Props/Walls/MediumWall3.mesh - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - - Models/Props/Walls/MediumWall3.mesh - - - - - - - - - - - - - Models/Props/Walls/BigWallBlue.mesh - - - - - - - - - - - - - Models/Props/Walls/MediumWall3.mesh - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - - Models/Props/Walls/BigWallBlue.mesh - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - - Models/Props/Walls/MediumWall3.mesh - - - - - - - - - - - - - Models/Props/Walls/MediumWall3.mesh - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - - Models/Props/Walls/MediumWall3.mesh - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - Models/Props/Walls/SmallWall3.mesh - - - - - - - - - - - - - Models/Props/Walls/MediumWall3.mesh - - - - - - - - - - - - - - Models/Core/UnitPlane.mesh - - true - - - - - - - - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - - Models/Props/Stones/AssaultHolder.mesh - - - - - - - - - - - - - - - - - - - - Models/Props/Pillars/StonePillar.mesh - - - + + + @@ -8136,14 +7388,12 @@ - + - - - + @@ -8151,7 +7401,50 @@ 6 - Models/Props/Pillars/SciFiPillar1Blue.mesh + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar1Red.mesh @@ -8160,6 +7453,35 @@ + + + + + 4 + Models/Props/Pillars/SciFiPillar3Red.mesh + + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + @@ -8179,7 +7501,7 @@ 4 - Models/Props/Pillars/SciFiPillar3Blue.mesh + Models/Props/Pillars/SciFiPillar3Red.mesh @@ -8189,6 +7511,136 @@ + + + + + 4 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + 4 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + 4 + Models/Props/Pillars/SciFiPillar1Red.mesh + + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + + + + + + + + + + + + 4 + Models/Props/Pillars/SciFiPillar3Blue.mesh + + + + + + + + + @@ -8203,6 +7655,106 @@ + + + + + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar1Blue.mesh + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + 4 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + @@ -8222,12 +7774,12 @@ 4 - Models/Props/Pillars/SciFiPillar2Red.mesh + Models/Props/Pillars/SciFiPillar3Blue.mesh - - - + + + @@ -8262,48 +7814,6 @@ - - - - - 6 - Models/Props/Pillars/SciFiPillar2Blue.mesh - - - - - - - - - - - - - Models/Props/Pillars/SciFiPillar2Blue.mesh - - - - - - - - - - - - - - 6 - Models/Props/Pillars/SciFiPillar2Blue.mesh - - - - - - - - @@ -8319,305 +7829,2188 @@ - - - - - 6 - Models/Props/Pillars/SciFiPillar2Blue.mesh - - - - - - - - - - - - - - 4 - Models/Props/Pillars/SciFiPillar3Blue.mesh - - - - - - - - - - - - - - - - - + - - - - - - - - Schema/Entities/PlayerAssaultFallbackBlue.xml - - - - - - - - - - - Models/Characters/Assault/Test/AssaultTPose.mesh - - - - - - - - - - Models/Characters/Assault/Test/AssaultTPose.mesh - - - - - - - - - - - - Models/Characters/Assault/Test/AssaultTPose.mesh - - - - - - - - - - - - Models/Characters/Assault/Test/AssaultTPose.mesh - - - - - - - - - - - - Models/Characters/Assault/Test/AssaultTPose.mesh - - - - - - - - - - - - Models/Characters/Assault/Test/AssaultTPose.mesh - - - - - - - - - - - - - - - - - - - Schema/Entities/PlayerAssaultFallbackRed.xml - - - - - - - - - - - Models/Characters/Assault/Test/AssaultTPose.mesh - - - - - - - - - - - - Models/Characters/Assault/Test/AssaultTPose.mesh - - - - - - - - - - - - Models/Characters/Assault/Test/AssaultTPose.mesh - - - - - - - - - - - - Models/Characters/Assault/Test/AssaultTPose.mesh - - - - - - - - - - - - Models/Characters/Assault/Test/AssaultTPose.mesh - - - - - - - - - - - - Models/Characters/Assault/Test/AssaultTPose.mesh - - - - - - - - - - - - - - - - - - - 10 - - - - - - - - - - - 10 - - - - - - - - - - - - 10 - - - - - - - - - - - 0.40000000596046448 - - - - - - - - - - - 10 - - - - - - - - - - - 0.69999998807907104 - 1.6000000238418579 - - + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + 2 + + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + 2 + + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + + + + + + + + + + + + + + + + + + + + + + Models/Props/Walls/MediumWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + Models/Props/Walls/smallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/mediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 15 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + - + + + + + + + + - - 10 - - + + - + + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + Schema/Entities/ScoreBoard_Red.xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Kills + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + ID + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Deaths + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Name + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + KD + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + + + + + + + + + + + Schema/Entities/ScoreBoard_Blue.xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Kills + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + ID + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Name + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + KD + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Deaths + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + Schema/Entities/ScoreBoard_Blue.xml + + + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + + + + + + + + + + + + + + + KD + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + ID + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Name + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Kills + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Deaths + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + + + Schema/Entities/ScoreBoard_Red.xml + + + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + ID + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + KD + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Kills + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Deaths + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + + + + + + + 0.049999997019767761 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Textures/Icons/Classes/Assault-01.png + + false + + + PickClass + 1 + + + + + + + + + + + Assault + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + Textures/Icons/Classes/Sniper-01.png + + false + + + PickClass + 3 + + + + + + + + + + + Sniper + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + false + + + + SwapToTeamPick + 1 + + + + + + + + + + + Team + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + Change + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Textures/Icons/Classes/Defender-01.png + + false + + + PickClass + 2 + + + + + + + + + + + Defender + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Pick Class + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Pick Team + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + false + + + + PickTeam + 1 + + + + + + + + + + + Spectator + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + false + + + + PickTeam + 3 + + + + + + + + + + + Blue + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + false + + + + PickTeam + 2 + + + + + + + + + + + Red + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + false + + false + + + SwapToClassPick + 1 + + + + + + + + + + + Class + Fonts/DroidSans.ttf,64 + false + + + + + + + + + + + + Change + Fonts/DroidSans.ttf,64 + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + false + + + + SwapToTeamPick + 1 + + + + + + + + + + + Team + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + Change + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + false + + + + + + + + + + + + + + 2 + + + Textures/Core/UnitHexagon_Rotated.png + + false + + + + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + false + + + + + + + + + + + + + + 1 + + + Textures/Core/UnitHexagon_Rotated.png + + false + + + + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + false + + + + + + + + + + + 1 + + + + 4 + + + Textures/Core/UnitHexagon_Rotated.png + + false + + + + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + false + + + + + + + + + + + 1 + + + + + Textures/Core/UnitHexagon_Rotated.png + + false + + + + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + false + + + + + + + + + + + + + + 3 + + + Textures/Core/UnitHexagon_Rotated.png + + false + + + + + + + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + false + + + + SwapToClassPick + 1 + + + + + + + + + + + Class + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + Change + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + 7 + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + @@ -8626,110 +10019,6 @@ - - - - - Models/Props/CapturePoint/CapturePointNeutral.mesh - - - - - - - - - - 3 - - - - - Models/Core/UnitCylinder.mesh - - true - - - - - - - - - - - - - - - Models/Props/CapturePoint/CapturePointNeutral.mesh - - - - - - - - - - 1 - - - - - Models/Core/UnitCylinder.mesh - - true - - - - - - - - - - - - - - - Models/Props/CapturePoint/CapturePointBlue.mesh - - - - - - - - - - -15 - - - - 4 - - - - - - - - - Models/Core/UnitCylinder.mesh - - true - - - - - - - - - - @@ -8753,6 +10042,7 @@ true + @@ -8792,6 +10082,7 @@ true + @@ -8801,231 +10092,823 @@ - - - - - - 0.049999997019767761 - - - - - - - - - + + + + Models/Props/CapturePoint/CapturePointNeutral.mesh + - - + - + + + + 1 + + + + + Models/Core/UnitCylinder.mesh + + true + + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointNeutral.mesh + + + + + + + + + + 3 + + + + + Models/Core/UnitCylinder.mesh + + true + + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointBlue.mesh + + + + + + + + + + -15 + + + + 4 + + + + + + + + + Models/Core/UnitCylinder.mesh + + true + + + + + + + + + + + + + + + + + + + + + + + Schema/Entities/PlayerRed.xml + + + + + + + + + + + Models/Characters/Assault/AssaultTPose.mesh + false + + + + + + + + + + + + Models/Characters/Assault/AssaultTPose.mesh + false + + + + + + + + + + + + Models/Characters/Assault/AssaultTPose.mesh + false + + + + + + + + + + + + Models/Characters/Assault/AssaultTPose.mesh + false + + + + + + + + + + + + + + + + + + + + - - + - + - + + + + 5 + 2 + 0.5 + - - + - - - - - Textures/Core/UnitHexagon.png - - - - - - - - - - - - - - - 2 - - - Textures/Core/UnitHexagon_Rotated.png - - - - - - - - - - - - - - - - Textures/Core/UnitHexagon.png - - - - - - - - - - - - - - - 1 - - - Textures/Core/UnitHexagon_Rotated.png - - - - - - - - - - - - - - - - Textures/Core/UnitHexagon.png - - - - - - - - - - - - - - - 3 - - - Textures/Core/UnitHexagon_Rotated.png - - - - - - - - - - - - - - - - Textures/Core/UnitHexagon.png - - - - - - - - - - - - 1 - - - - - Textures/Core/UnitHexagon_Rotated.png - - - - - - - - - - - - - - - - Textures/Core/UnitHexagon.png - - - - - - - - - - - - 1 - - - - 4 - - - Textures/Core/UnitHexagon_Rotated.png - - - - - - - - - - - - - + - + - - 3 - Fonts/DroidSans.ttf,64 - - + + + 5 + 2 + 0.5 + - - + + + + + + + + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + @@ -9034,79 +10917,956 @@ - + + + + + 15 + 1 + + + + + + + + - - + + + + 10 + 1 + - + - - - - - - Textures/Core/UnitHexagon.png - - - - PickClass - 2 - - - - - - - - - - - - - Textures/Core/UnitRaptor.png - - - - PickClass - 1 - - - - - - - - - - - - - Textures/Test/aM4ME4GR.png - - - - PickClass - 3 - - - - - - - - - + + + + + + + 10 + 1 + + + + + + + + + + + + 10 + 1 + + + + + + + + + + 10 + + + + + + + + + + + + + + + + 4 + 2 + + + + + + + + + + + 4 + + + + + + + + + + + 4 + + + + + + + + + + + 4 + + + + + + + + + + + 4 + + + + + + + + + + + 5 + + + + + + + + + + + 4 + + + + + + + + + + + 4 + + + + + + + + + + + 4 + + + + + + + + + + + 4 + 1 + + + + + + + + + + + 4 + + + + + + + + + + + 4 + + + + + + + + + + + 4 + + + + + + + + + + + 4 + + + + + + + + + + + 4 + + + + + + + + + + + 4 + + + + + + + + + + + + + 0.60000002384185791 + false + + + + + + + + + + + + 10 + + + + + + + + + + + + 10 + + + + + + + + + + + + 0.80000001192092896 + 1.2000000476837158 + + + + + + + + + 10 + + + + + + + + + + + 10 + + + + + + + + + + + + + + + + + + + + + + 10 + 1 + + + + + + + + + + + + 10 + 1 + + + + + + + + + + + + 10 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + + + + + + + + + + 3 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + + + + + 15 + 1 + + + + + + + + + + + + + + + + + + + + + Schema/Entities/Player.xml + + + + + + + + + + + Models/Characters/Assault/AssaultTPose.mesh + false + + + + + + + + + + + + Models/Characters/Assault/AssaultTPose.mesh + false + + + + + + + + + + + + Models/Characters/Assault/AssaultTPose.mesh + false + + + + + + + + + + + + Models/Characters/Assault/AssaultTPose.mesh + false + + + + + + + diff --git a/resources/Schema/Entities/OptionMenu.xml b/resources/Schema/Entities/OptionMenu.xml new file mode 100644 index 00000000..b7be623d --- /dev/null +++ b/resources/Schema/Entities/OptionMenu.xml @@ -0,0 +1,141 @@ + + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Core/White.png + true + + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Core/White.png + false + + + + + + + + + + + + Options + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Core/White.png + + + + Resolution + 1 + + + + + + + + + + + + + + + + Resolution + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + + Schema/Entities/Resolution_Options.xml + + + + + + + + + + diff --git a/resources/Schema/Entities/Resolution_Options b/resources/Schema/Entities/Resolution_Options new file mode 100644 index 00000000..293bee0a --- /dev/null +++ b/resources/Schema/Entities/Resolution_Options @@ -0,0 +1,128 @@ + + + + + + + + + + + + + 1920 + 1080 + + + Models/Core/UnitQuad.mesh + + Textures/Core/White.png + true + + + + + + + + + + + + 1920x1080 + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + 1366 + 768 + + + Models/Core/UnitQuad.mesh + + Textures/Core/White.png + true + + + + + + + + + + + + 1366x768 + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + 1280 + 720 + + + Models/Core/UnitQuad.mesh + + Textures/Core/White.png + true + + + + + + + + + + + + 1280x720 + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/Resolution_Options.xml b/resources/Schema/Entities/Resolution_Options.xml new file mode 100644 index 00000000..3aaa32e5 --- /dev/null +++ b/resources/Schema/Entities/Resolution_Options.xml @@ -0,0 +1,149 @@ + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/White.png + + + + + + + + + + + + + + 1920 + 1080 + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/White.png + true + + + + + + + + + + + + 1920x1080 + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + 1366 + 768 + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/White.png + true + + + + + + + + + + + + 1366x768 + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + 1280 + 720 + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/White.png + true + + + + + + + + + + + + 1280x720 + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/ServerIdentity.xml b/resources/Schema/Entities/ServerIdentity.xml index 3c47e045..1a24fb8a 100644 --- a/resources/Schema/Entities/ServerIdentity.xml +++ b/resources/Schema/Entities/ServerIdentity.xml @@ -17,7 +17,6 @@ 123.123.123.123 Fonts/DroidSans.ttf,64 - @@ -28,7 +27,7 @@ IP - + @@ -39,7 +38,6 @@ 65999 Fonts/DroidSans.ttf,64 - @@ -50,7 +48,7 @@ Port - + @@ -61,7 +59,6 @@ UnkownServer Fonts/DroidSans.ttf,64 - @@ -72,7 +69,7 @@ ServerName - + @@ -82,7 +79,6 @@ 0 Fonts/DroidSans.ttf,64 - @@ -93,7 +89,7 @@ PlayersConnected - + @@ -102,14 +98,15 @@ + false + Models/Core/UnitQuad.mesh + Textures/Core/White.png true - - false - + - + @@ -117,6 +114,75 @@ + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + + + + + + + + + diff --git a/resources/Schema/Entities/ServerList.xml b/resources/Schema/Entities/ServerList.xml index f9a601f5..aa8f787b 100644 --- a/resources/Schema/Entities/ServerList.xml +++ b/resources/Schema/Entities/ServerList.xml @@ -1,5 +1,5 @@ - + @@ -12,7 +12,7 @@ - + @@ -30,27 +30,14 @@ - - - - Textures/Core/White.png - true - - - - - - - - - + Models/Core/UnitQuad.mesh + Textures/Core/White.png true - @@ -66,8 +53,9 @@ - Textures/Icons/rotate.png + Models/Core/UnitQuad.mesh + Textures/Icons/rotate.png @@ -79,6 +67,135 @@ + + + + + + + + + Servers + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Core/White.png + false + + + + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Core/White.png + true + + + + + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + + + + + + + + + + + diff --git a/resources/Schema/Entities/StartMenu.xml b/resources/Schema/Entities/StartMenu.xml index 2ad8f377..86ee626e 100644 --- a/resources/Schema/Entities/StartMenu.xml +++ b/resources/Schema/Entities/StartMenu.xml @@ -22,7 +22,7 @@ - 7.0999304984909202 + 0.53338721940212963 @@ -2828,7 +2828,7 @@ - + @@ -2870,7 +2870,7 @@ - + @@ -2912,7 +2912,7 @@ - + @@ -2954,7 +2954,7 @@ - + @@ -2996,7 +2996,7 @@ - + @@ -3038,7 +3038,7 @@ - + @@ -3080,7 +3080,7 @@ - + @@ -3122,7 +3122,7 @@ - + @@ -3164,7 +3164,7 @@ - + @@ -5261,7 +5261,7 @@ - + @@ -5303,7 +5303,7 @@ - + @@ -6869,7 +6869,7 @@ - + @@ -6911,7 +6911,7 @@ - + @@ -6953,7 +6953,7 @@ - + @@ -6995,7 +6995,7 @@ - + @@ -7037,7 +7037,7 @@ - + @@ -7079,7 +7079,7 @@ - + @@ -7121,7 +7121,7 @@ - + @@ -8796,7 +8796,7 @@ - + @@ -8808,7 +8808,7 @@ - + @@ -8858,10 +8858,11 @@ + false + Models/Core/UnitQuad.mesh + Textures/Core/White.png true - - false @@ -8874,6 +8875,44 @@ + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + + + + + + + + + + @@ -8890,40 +8929,6 @@ - - - - - - - - - Textures/HUD/ButtonCorner_16.png - - - - - - - - - - - - - Textures/HUD/ButtonCorner_16.png - - - - - - - - - - - - @@ -8937,10 +8942,11 @@ + false + Models/Core/UnitQuad.mesh + Textures/Core/White.png true - - false @@ -8973,8 +8979,10 @@ - Textures/HUD/ButtonCorner_16.png + Models/Core/UnitQuad.mesh + Textures/HUD/ButtonCorner_16.png + false @@ -8986,8 +8994,10 @@ - Textures/HUD/ButtonCorner_16.png + Models/Core/UnitQuad.mesh + Textures/HUD/ButtonCorner_16.png + false @@ -9008,16 +9018,59 @@ + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + Textures/Core/White.png true - - false + + Options + 1 + @@ -9027,7 +9080,7 @@ - Option + Options Fonts/DroidSans.ttf,64 @@ -9040,40 +9093,6 @@ - - - - - - - - - Textures/HUD/ButtonCorner_16.png - - - - - - - - - - - - - Textures/HUD/ButtonCorner_16.png - - - - - - - - - - - - @@ -9087,10 +9106,11 @@ + false + Models/Core/UnitQuad.mesh + Textures/Core/White.png true - - false @@ -9123,8 +9143,10 @@ - Textures/HUD/ButtonCorner_16.png + Models/Core/UnitQuad.mesh + Textures/HUD/ButtonCorner_16.png + false @@ -9136,8 +9158,10 @@ - Textures/HUD/ButtonCorner_16.png + Models/Core/UnitQuad.mesh + Textures/HUD/ButtonCorner_16.png + false @@ -9169,6 +9193,15 @@ + + + + Schema/Entities/OptionMenu.xml + + + + + diff --git a/resources/Schema/Entities/aim_rays_with_capturep.xml b/resources/Schema/Entities/aim_rays_with_capturep.xml index 6aa3246a..60030ba5 100644 --- a/resources/Schema/Entities/aim_rays_with_capturep.xml +++ b/resources/Schema/Entities/aim_rays_with_capturep.xml @@ -13,6 +13,7 @@ models/core/unitcube.mesh + false @@ -28,6 +29,7 @@ models/core/unitcube.mesh + false @@ -52,6 +54,7 @@ models/core/unitcube.mesh + false @@ -67,6 +70,7 @@ models/core/unitcube.mesh + false @@ -82,6 +86,7 @@ models/core/unitcube.mesh + false @@ -99,7 +104,7 @@ - Schema/Entities/Player.xml + Schema/Entities/PlayerRed.xml @@ -198,6 +203,7 @@ models/core/unitcube.mesh + false @@ -210,7 +216,7 @@ - + @@ -225,6 +231,11 @@ + + + + false + @@ -239,7 +250,24 @@ - + + + + + + + + + + + + + + + + + + @@ -250,7 +278,25 @@ - + + + + + + + + + + + + + + + + + + + @@ -261,7 +307,43 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -272,11 +354,11 @@ - + - -15 + 12 @@ -302,7 +384,38 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/Schema/Types/Entity.xsd b/resources/Schema/Types/Entity.xsd index 9da41687..c0bc884d 100644 --- a/resources/Schema/Types/Entity.xsd +++ b/resources/Schema/Types/Entity.xsd @@ -73,6 +73,8 @@ + + diff --git a/resources/Shaders/ExplosionEffect.geom.glsl b/resources/Shaders/ExplosionEffect.geom.glsl index 19944cac..420bbaae 100644 --- a/resources/Shaders/ExplosionEffect.geom.glsl +++ b/resources/Shaders/ExplosionEffect.geom.glsl @@ -15,6 +15,11 @@ uniform float RandomnessScalar; uniform vec2 Velocity; uniform bool ColorByDistance; uniform bool ExponentialAccelaration; +uniform bool Reverse; +uniform float ColorDistanceScalar; +//uniform bool Gravity; +//uniform bool Rotation; +//uniform bool MaxRadius; in VertexData{ vec3 Position; @@ -41,169 +46,136 @@ out VertexData{ layout(triangles) in; layout(triangle_strip, max_vertices = 3) out; +float EqualTo(float x, float y) { + return 1.0 - abs(sign(x - y)); +} + +float NotEqualTo(float x, float y) { + return abs(sign(x - y)); +} + +float GreaterThan(float x, float y) { + return max(sign(x - y), 0.0); +} + +float LessThan(float x, float y) { + return max(sign(y - x), 0.0); +} + +float GreaterEqualTo(float x, float y) { + return 1.0 - LessThan(x, y); +} + +float LessEqualTo(float x, float y) { + return 1.0 - GreaterThan(x, y); +} + // returns a "random" number based on input parameter float GetRandomNumber(int polygon_index) { - int randomIndex = int(mod(polygon_index, 50)); - - return RandomNumbers[randomIndex]; + return RandomNumbers[int(mod(polygon_index, 50))]; } -float randomNumber = 0.0; -float randomDistance = 0.0; - -void main() +vec3 CalcCenterOfTriangle(vec3 vertex0, vec3 vertex1, vec3 vertex2) { // calculate middle of vectors - vec3 v1 = Input[1].Position - Input[0].Position; - vec3 v2 = Input[2].Position - Input[0].Position; - vec3 v3 = Input[2].Position - (v1 / 2); - vec3 v4 = Input[1].Position - (v2 / 2); + vec3 dir1 = normalize(vertex1 - vertex0); + vec3 dir2 = normalize(vertex2 - vertex0); - // calculate intersection - - // normalize direction - vec3 dir1 = normalize(v1); - vec3 dir2 = normalize(v2); - - vec3 vecA = Input[2].Position - Input[1].Position; //o2 - o1 + vec3 vecA = vertex2 - vertex1; //o2 - o1 vec3 vecB = cross(dir1, dir2); mat3 matrisA = mat3(vecA, dir2, vecB); float lengthA = length(vecB); lengthA = lengthA * lengthA; - + float s = determinant(matrisA) / lengthA; // center position of triangle - vec3 centerOfTriangle = Input[1].Position + (s * dir1); - + return vertex1 + (s * dir1); +} + +void PassThingsThrough(int index) +{ + // pass through vertex data + Output.Normal = Input[index].Normal; + Output.Position = Input[index].Position; + Output.TextureCoordinate = Input[index].TextureCoordinate; + Output.Tangent = Input[index].Tangent; + Output.BiTangent = Input[index].BiTangent; + Output.ExplosionColor = EndColor; +} + +void main() +{ + vec3 centerOfTriangle = CalcCenterOfTriangle(Input[0].Position, Input[1].Position, Input[2].Position); + // center position of triangle to origin vector vec3 origin2TriangleCenterVector = centerOfTriangle - ExplosionOrigin; vec3 normalizedOrigin2TriangleCenterVector = normalize(origin2TriangleCenterVector); + // distance between origin and the center of the current triangle + float origin2TriangleCenterDistance = length(origin2TriangleCenterVector); + // time percentage until end of explosion (0.0-1.0) float timePercetage = TimeSinceDeath / ExplosionDuration; - // get a random number if randomness is enabled, otherwise the random number will be zero and won't affect the other algorithms - if (Randomness == true) - { - randomDistance = GetRandomNumber(gl_PrimitiveIDIn) * RandomnessScalar; - } + // get a random number if randomness is enabled, otherwise the random distance will be zero and won't affect the other algorithms + float randomDistance = float(Randomness) * GetRandomNumber(gl_PrimitiveIDIn) * RandomnessScalar; vec2 randomVelocity = Velocity * (randomDistance + 1.0); // accelaration to use on current frame. is a interpolation between start and end value float currentVelocity = mix(randomVelocity.x, randomVelocity.y, timePercetage); - if (ExponentialAccelaration == true) - { - currentVelocity = pow(currentVelocity, 2) / 2.0; - } + // if the accelaration should be exponential + currentVelocity = currentVelocity * max(currentVelocity * float(ExponentialAccelaration), 1.0); - // distance between origin and the center of the current triangle - float origin2TriangleCenterDistance = length(origin2TriangleCenterVector); + // the distance the blast has moved since the beginning, i.e. its radius + float blastWave = TimeSinceDeath * currentVelocity; // the distance from origin to the triangle center with eventual randomness added - float fullDistanceWithRandomness = origin2TriangleCenterDistance + randomDistance; - - // vector from the triangle center to the explosion's shockwave - vec3 triangleCenter2ExplosionRadius = (normalizedOrigin2TriangleCenterVector * (TimeSinceDeath * currentVelocity)) - (normalizedOrigin2TriangleCenterVector * fullDistanceWithRandomness); + float origin2TriangleCenterDistanceWithRandomness = origin2TriangleCenterDistance + randomDistance; - // if the triangle is inside the blast radius... - if (fullDistanceWithRandomness <= (TimeSinceDeath * currentVelocity)) + vec3 triangleCenter2ExplosionRadius = (normalizedOrigin2TriangleCenterVector * blastWave) - (normalizedOrigin2TriangleCenterVector * origin2TriangleCenterDistanceWithRandomness); + + // if the triangle is inside the blast's radius... + float isInsideBlastRadius = LessEqualTo(origin2TriangleCenterDistanceWithRandomness, blastWave); + + // calculate the max distance (s) the triangle will move + float accelaration = (randomVelocity.y - randomVelocity.x) / ExplosionDuration; + float maxDistance = (randomVelocity.x * ExplosionDuration) + (0.5 * accelaration * ExplosionDuration * ExplosionDuration); + + // if explosion color should be affected by distance instead of time... + if (ColorByDistance == true) { - float maxRadius = max(TimeSinceDeath * currentVelocity, (ExplosionDuration * currentVelocity)); - - float a = (randomVelocity.y - randomVelocity.x) / ExplosionDuration; - //float t = sqrt((2 * origin2TriangleCenterDistance) / a); - - // if explosion color should be affected by distance instead of time... - if (ColorByDistance == true) - { - // calculate the max distance (s) the triangle will move - float s = (randomVelocity.x * ExplosionDuration) + (0.5 * a * pow(ExplosionDuration, 2)); - float te = (length(triangleCenter2ExplosionRadius) / s); - - Output.ExplosionColor = EndColor; - Output.ExplosionPercentageElapsed = te; - - } - else - { - Output.ExplosionColor = EndColor; - Output.ExplosionPercentageElapsed = timePercetage; - - } - - // for every vertex on the triangle... - for (int i = 0; i < gl_in.length(); i++) - { - // move the triangle to the blast radius - vec3 ExplodedPosition = Input[i].Position + triangleCenter2ExplosionRadius; - - // pass through vertex data - Output.Normal = Input[i].Normal; - Output.Position = Input[i].Position; - Output.TextureCoordinate = Input[i].TextureCoordinate; - Output.Tangent = Input[i].Tangent; - Output.BiTangent = Input[i].BiTangent; - for (int j = 0; j < MAX_SPLITS; j++) - { - Output.PositionLightSpace[j] = Input[i].PositionLightSpace[j]; - } - - // convert to model space for the gravity to always be in -y - vec4 ExplodedPositionInModelSpace = M * vec4(ExplodedPosition, 1.0); - - // if there is gravity, apply it - //if (Gravity == true) - //{ - // // ---DO THIS----> //ExplodedPositionInModelSpace.y = ExplodedPositionInModelSpace.y - TimeSinceHit; - // - // ExplodedPositionInModelSpace.y = ExplodedPositionInModelSpace.y - pow(TimeSinceDeath, 2); - //} - - // convert to screen space - gl_Position = P*V * ExplodedPositionInModelSpace; - EmitVertex(); - } + Output.ExplosionPercentageElapsed = (length(triangleCenter2ExplosionRadius) / maxDistance) * isInsideBlastRadius * ColorDistanceScalar; } else { - // if explosion color should be affected by distance instead of time... - if (ColorByDistance == true) - { - Output.ExplosionColor = EndColor; - Output.ExplosionPercentageElapsed = 0.0; - } - else - { - Output.ExplosionColor = EndColor; - Output.ExplosionPercentageElapsed = timePercetage; + Output.ExplosionPercentageElapsed = timePercetage; + } + + vec3 ExplodedPosition; + for (int i = 0; i < gl_in.length(); i++) + { + // move the triangle to the blast radius + ExplodedPosition = Input[i].Position + (triangleCenter2ExplosionRadius * isInsideBlastRadius); - } - - // for every vertex on the triangle... - for(int i = 0; i < gl_in.length(); i++) - { - // pass through vertex data - Output.Normal = Input[i].Normal; - Output.Position = Input[i].Position; - Output.TextureCoordinate = Input[i].TextureCoordinate; - Output.Tangent = Input[i].Tangent; - Output.BiTangent = Input[i].BiTangent; + // pass through vertex data + PassThingsThrough(i); for (int j = 0; j < MAX_SPLITS; j++) { Output.PositionLightSpace[j] = Input[i].PositionLightSpace[j]; } - - // no change in position, pass through vertex - gl_Position = gl_in[i].gl_Position; - EmitVertex(); - } + for (int j = 0; j < MAX_SPLITS; j++) + { + Output.PositionLightSpace[j] = Input[i].PositionLightSpace[j]; + } + + // convert to window space + gl_Position = P * V * M * vec4(ExplodedPosition, 1.0); + EmitVertex(); } - - //EndPrimitive(); -} +} \ No newline at end of file diff --git a/src/Engine/Collision/Collision.cpp b/src/Engine/Collision/Collision.cpp index 68d99d92..dc04e8cf 100644 --- a/src/Engine/Collision/Collision.cpp +++ b/src/Engine/Collision/Collision.cpp @@ -151,9 +151,9 @@ bool RayVsModel(const Ray& ray, const glm::mat4& modelMatrix) { for (int i = 0; i < modelIndices.size();) { - glm::vec3 v0 = Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix); - glm::vec3 v1 = Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix); - glm::vec3 v2 = Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix); + glm::vec3 v0 = TransformSystem::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix); + glm::vec3 v1 = TransformSystem::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix); + glm::vec3 v2 = TransformSystem::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix); if (RayVsTriangle(ray, v0, v1, v2)) { return true; } @@ -204,9 +204,9 @@ bool RayVsModel(const Ray& ray, outDistance = INFINITY; bool hit = false; for (int i = 0; i < modelIndices.size();) { - glm::vec3 v0 = Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix); - glm::vec3 v1 = Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix); - glm::vec3 v2 = Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix); + glm::vec3 v0 = TransformSystem::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix); + glm::vec3 v1 = TransformSystem::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix); + glm::vec3 v2 = TransformSystem::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix); float dist = outDistance; float u; float v; @@ -360,7 +360,14 @@ constexpr bool FaceIsGround(float faceNormalY) //An array containing 3 int pairs { 0, 2 }, { 0, 1 }, { 1, 2 } constexpr std::array, 3> dimensionPairs({ std::pair(0, 2), std::pair(0, 1), std::pair(1, 2) }); -bool AABBvsTriangle(const AABB& box, +enum class BoxTriRes +{ + Front, + Behind, + Intersect +}; + +BoxTriRes AABBvsTriangle(const AABB& box, const std::array& triPos, const glm::vec3& originalBoxVelocity, float verticalStepHeight, @@ -374,7 +381,7 @@ bool AABBvsTriangle(const AABB& box, //Less checks, and we should be able to walk out from models if we are trapped inside. glm::vec3 triNormal = glm::cross(triPos[1] - triPos[0], triPos[2] - triPos[0]); if (!vectorHasLength(triNormal) || (glm::dot(triNormal, originalBoxVelocity) > 0)) { - return false; + return BoxTriRes::Behind; } triNormal = glm::normalize(triNormal); @@ -409,6 +416,9 @@ bool AABBvsTriangle(const AABB& box, const glm::vec3& min = box.MinCorner(); const glm::vec3& max = box.MaxCorner(); + // If there is no intersection, whether the box center is in front of or behind the triangle. + BoxTriRes noIntersection = glm::dot(triNormal, origin - triPos[0]) > 0 ? BoxTriRes::Front : BoxTriRes::Behind; + //For each projection in xy-, xz-, and yx-planes. for (std::pair dim : dimensionPairs) { //2D Triangle. @@ -426,7 +436,7 @@ bool AABBvsTriangle(const AABB& box, bool pushedFromTriangleLine; //if projections don't overlap, return false. if (!rectangleVsTriangle(boxMin, boxMax, t2D, resolutionVector, resolutionDist, pushedFromTriangleLine)) { - return false; + return noIntersection; } else if (resolveCollision) { //Overwrite the smallest resolution if this is smaller. if (resolutionDist < resolveShortest.DistanceSq) { @@ -462,14 +472,15 @@ bool AABBvsTriangle(const AABB& box, float t = glm::dot(triNormal, triPos[0] - origin) / glm::dot(triNormal, diagonal); //If intersection point between plane and diagonal is within the box. if (glm::abs(t) > 1) { - return false; + return noIntersection; } if (!resolveCollision) { - return true; + return BoxTriRes::Intersect; } glm::vec3 cornerResolution = (1+t) * diagonal; + cornerResolution = glm::dot(cornerResolution, triNormal) * triNormal; //Overwrite the smallest resolution if cornerResolution is smaller. float lenSq = glm::length2(cornerResolution); if (lenSq < resolveShortest.DistanceSq) { @@ -498,7 +509,7 @@ bool AABBvsTriangle(const AABB& box, case ResolveDimZ: //If we get here, the resolution is along one coordinate axis. //set velocity to 0 in y if it is along y-axis. - return true; + return BoxTriRes::Intersect; case Line: projNorm = glm::normalize(outResolution); break; @@ -533,10 +544,10 @@ bool AABBvsTriangle(const AABB& box, boxVelocity = boxVelocity - glm::dot(boxVelocity, projNorm) * projNorm; } } - return true; + return BoxTriRes::Intersect; } -bool AABBvsTriangles(const AABB& box, +Output AABBvsTriangles(const AABB& box, const RawModel::Vertex* modelVertices, const std::vector& modelIndices, const glm::mat4& modelMatrix, @@ -546,34 +557,41 @@ bool AABBvsTriangles(const AABB& box, glm::vec3& outResolutionVector, bool resolveCollision) { - bool hit = false; - + bool intersect = false; + Output out = Output::OutContained; bool everHitTheGround = false; AABB newBox = box; outResolutionVector = glm::vec3(0.f); glm::vec3 originalBoxVelocity(boxVelocity); for (int i = 0; i < modelIndices.size(); ) { std::array triVertices = { - Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix), - Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix), - Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix) + TransformSystem::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix), + TransformSystem::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix), + TransformSystem::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix) }; glm::vec3 outVec; bool collideWithGround = isOnGround; - if (AABBvsTriangle(newBox, triVertices, originalBoxVelocity, verticalStepHeight, collideWithGround, boxVelocity, outVec, resolveCollision)) { - hit = true; + switch (AABBvsTriangle(newBox, triVertices, originalBoxVelocity, verticalStepHeight, collideWithGround, boxVelocity, outVec, resolveCollision)) { + case Collision::BoxTriRes::Front: + out = Output::OutSeparated; + break; + case Collision::BoxTriRes::Intersect: + intersect = true; outResolutionVector += outVec; newBox = AABB::FromOriginSize(newBox.Origin() + outVec, newBox.Size()); if (collideWithGround) { everHitTheGround = isOnGround = true; } + break; + default: + break; } } if (!everHitTheGround) { isOnGround = false; } - return hit; + return intersect ? Output::OutIntersecting : out; } bool AABBvsTriangles(const AABB& box, @@ -593,13 +611,31 @@ bool AABBvsTriangles(const AABB& box, verticalStepHeight, isOnGround, outResolutionVector, - true); + true) == Output::OutIntersecting; } bool AABBvsTriangles(const AABB& box, const RawModel::Vertex* modelVertices, const std::vector& modelIndices, const glm::mat4& modelMatrix) +{ + glm::vec3 vel, outres; + bool g; + return AABBvsTriangles(box, + modelVertices, + modelIndices, + modelMatrix, + vel, + 0.f, + g, + outres, + false) == Output::OutIntersecting; +} + +Output AABBvsTrianglesWContainment(const AABB& box, + const RawModel::Vertex* modelVertices, + const std::vector& modelIndices, + const glm::mat4& modelMatrix) { glm::vec3 vel, outres; bool g; @@ -619,9 +655,9 @@ boost::optional EntityAbsoluteAABB(EntityWrapper& entity, bool takeM AABB modelSpaceBox; if (entity.HasComponent("AABB") && !takeModelBox) { ComponentWrapper& cAABB = entity["AABB"]; - modelSpaceBox = EntityAABB::FromOriginSize((glm::vec3)cAABB["Origin"], (glm::vec3)cAABB["Size"]); + modelSpaceBox = EntityAABB::FromOriginSize((const glm::vec3&)cAABB["Origin"], (const glm::vec3&)cAABB["Size"]); } else if (entity.HasComponent("Model")) { - std::string res = entity["Model"]["Resource"]; + const std::string& res = entity["Model"]["Resource"]; if (res.empty()) { return boost::none; } @@ -638,7 +674,7 @@ boost::optional EntityAbsoluteAABB(EntityWrapper& entity, bool takeM return boost::none; } - glm::mat4 modelMat = Transform::AbsoluteTransformation(entity); + glm::mat4 modelMat = TransformSystem::ModelMatrix(entity); glm::vec3 mini(INFINITY); glm::vec3 maxi(-INFINITY); glm::vec3 maxCorner = modelSpaceBox.MaxCorner(); @@ -649,7 +685,7 @@ boost::optional EntityAbsoluteAABB(EntityWrapper& entity, bool takeM corner.x = bits.test(0) ? maxCorner.x : minCorner.x; corner.y = bits.test(1) ? maxCorner.y : minCorner.y; corner.z = bits.test(2) ? maxCorner.z : minCorner.z; - corner = Transform::TransformPoint(corner, modelMat); + corner = TransformSystem::TransformPoint(corner, modelMat); mini = glm::min(mini, corner); maxi = glm::max(maxi, corner); } @@ -667,7 +703,7 @@ boost::optional AbsoluteAABBExplosionEffect(EntityWrapper& entity) if (!modelBox) { return boost::none; } - bool isRandom = (bool)entity["ExplosionEffect"]["Randomness"]; + Field isRandom = entity["ExplosionEffect"]["Randomness"]; float random = isRandom ? (float)(double)entity["ExplosionEffect"]["RandomnessScalar"] : 0; glm::vec3 origin = (glm::vec3)entity["ExplosionEffect"]["ExplosionOrigin"]; glm::vec3 randomVel = (glm::vec3)entity["ExplosionEffect"]["Velocity"]; @@ -705,7 +741,7 @@ boost::optional EntityFirstHitByRay(const Ray& ray, std::vectorVertices(), model->m_RawModel->m_Indices, Transform::ModelMatrix(entityBox.Entity), outDistance, u, v)) { + if (RayVsModel(ray, model->Vertices(), model->m_RawModel->m_Indices, TransformSystem::ModelMatrix(entityBox.Entity), outDistance, u, v)) { outIntersectPos = ray.Origin() + outDistance * ray.Direction(); return entityBox; } diff --git a/src/Engine/Collision/CollisionSystem.cpp b/src/Engine/Collision/CollisionSystem.cpp index 53cabfac..433af482 100644 --- a/src/Engine/Collision/CollisionSystem.cpp +++ b/src/Engine/Collision/CollisionSystem.cpp @@ -37,6 +37,10 @@ void CollisionSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& c bool hit; float dist; if (boxB.Entity.HasComponent("Model")) { + if (!((bool)boxB.Entity["Model"]["Visible"])) { + // Don't collide against invisible models. + continue; + } RawModel* model; std::string res = (std::string)boxB.Entity["Model"]["Resource"]; try { @@ -45,7 +49,7 @@ void CollisionSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& c continue; } float u, v; - hit = Collision::RayVsModel(ray, model->Vertices(), model->m_Indices, Transform::ModelMatrix(boxB.Entity), dist, u, v); + hit = Collision::RayVsModel(ray, model->Vertices(), model->m_Indices, TransformSystem::ModelMatrix(boxB.Entity), dist, u, v); } else { hit = Collision::RayVsAABB(ray, boxB, dist); } @@ -54,12 +58,12 @@ void CollisionSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& c //TODO: Perhaps this should be done slightly more properly. glm::vec3 newOriginPos = ray.Origin() + (dist - 0.707107f*diameter) * ray.Direction(); glm::vec3 resolve = newOriginPos - boxA.Origin(); - (glm::vec3&)cTransform["Position"] += resolve; + (Field)cTransform["Position"] += resolve; boxA = *Collision::EntityAbsoluteAABB(entity); if (resolve.y > 0) { everHitTheGround = true; - (bool)cPhysics["IsOnGround"] = true; - ((glm::vec3&)cPhysics["Velocity"]).y = 0.f; + cPhysics["IsOnGround"] = true; + ((Field)cPhysics["Velocity"]).y(0.f); } break; } @@ -77,7 +81,11 @@ void CollisionSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& c } if (boxB.Entity.HasComponent("Model") && Collision::AABBVsAABB(boxA, boxB)) { - //Here we know boxB is a entity with Collideable, AABB, and Model. + // Here we know boxB is a entity with Collideable, AABB, and Model. + if (!((const bool&)boxB.Entity["Model"]["Visible"])) { + // Don't collide against invisible models. + continue; + } RawModel* model; try { model = ResourceManager::Load(boxB.Entity["Model"]["Resource"]); @@ -85,15 +93,14 @@ void CollisionSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& c continue; } - glm::mat4 modelMatrix = Transform::ModelMatrix(boxB.Entity); + glm::mat4 modelMatrix = TransformSystem::ModelMatrix(boxB.Entity); glm::vec3 inOutVelocity = (glm::vec3)cPhysics["Velocity"]; - bool notMovingxz = glm::all(glm::lessThan(glm::abs(glm::vec2(inOutVelocity.x, inOutVelocity.z)), glm::vec2(0.01f))) && prevPosIt != m_PrevPositions.end(); bool isOnGround = (bool)cPhysics["IsOnGround"]; float verticalStepHeight = (float)(double)cPhysics["VerticalStepHeight"]; if (Collision::AABBvsTriangles(boxA, model->Vertices(), model->m_Indices, modelMatrix, inOutVelocity, verticalStepHeight, isOnGround, resolutionVector)) { //Move the position to previous position if it is not moving in the xz-plane, else resolve with the resolution vector. - (glm::vec3&)cTransform["Position"] += notMovingxz ? prevPosIt->second - boxA.Origin() : resolutionVector; + (Field)cTransform["Position"] += resolutionVector; boxA = *Collision::EntityAbsoluteAABB(entity); cPhysics["Velocity"] = inOutVelocity; if (isOnGround) { @@ -103,12 +110,12 @@ void CollisionSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& c } } else if (Collision::AABBVsAABB(boxA, boxB, resolutionVector)) { //Enter here if boxB has no Model. - (glm::vec3&)cTransform["Position"] += resolutionVector; + (Field)cTransform["Position"] += resolutionVector; boxA = *Collision::EntityAbsoluteAABB(entity); if (resolutionVector.y > 0) { everHitTheGround = true; (bool)cPhysics["IsOnGround"] = true; - ((glm::vec3&)cPhysics["Velocity"]).y = 0.f; + ((Field)cPhysics["Velocity"]).y(0.f); } } } diff --git a/src/Engine/Collision/TriggerSystem.cpp b/src/Engine/Collision/TriggerSystem.cpp index 21a47721..c9bc18dc 100644 --- a/src/Engine/Collision/TriggerSystem.cpp +++ b/src/Engine/Collision/TriggerSystem.cpp @@ -10,6 +10,16 @@ void TriggerSystem::UpdateComponent(EntityWrapper& triggerEntity, ComponentWrapp return; } + RawModel* triggerModel = nullptr; + glm::mat4 triggerModelMat; + if (triggerEntity.HasComponent("Model")) { + try { + triggerModel = ResourceManager::Load(triggerEntity["Model"]["Resource"]); + triggerModelMat = TransformSystem::ModelMatrix(triggerEntity); + } catch (const std::exception&) { + } + } + m_OctreeOut.clear(); m_Octree->ObjectsInSameRegion(*triggerBox, m_OctreeOut); @@ -22,7 +32,17 @@ void TriggerSystem::UpdateComponent(EntityWrapper& triggerEntity, ComponentWrapp if (colliderFitsInTrigger) { completelyInsideBox = AABB::FromOriginSize((*triggerBox).Origin(), (*triggerBox).Size() - 2.0f * colliderBox.Size()); } - if (colliderFitsInTrigger && Collision::AABBVsAABB(completelyInsideBox, colliderBox)) { + + // We know the entity is inside the trigger box, but perhaps not the model yet. + Collision::Output out = triggerModel == nullptr + ? Collision::Output::OutContained + : Collision::AABBvsTrianglesWContainment( + colliderBox, + triggerModel->Vertices(), + triggerModel->m_Indices, + triggerModelMat); + + if (colliderFitsInTrigger && Collision::AABBVsAABB(completelyInsideBox, colliderBox) && out == Collision::Output::OutContained) { // Entity is completely inside the trigger. // If it was only touching before, it is erased. m_EntitiesTouchingTrigger[triggerEntity].erase(colliderEntity); @@ -32,7 +52,8 @@ void TriggerSystem::UpdateComponent(EntityWrapper& triggerEntity, ComponentWrapp completeSet.insert(colliderEntity); publish(colliderEntity, triggerEntity); } - } else { + continue; + } else if (out != Collision::Output::OutSeparated) { // Entity is only touching the trigger. auto& touchSet = m_EntitiesTouchingTrigger[triggerEntity]; auto& completeSet = m_EntitiesCompletelyInTrigger[triggerEntity]; @@ -47,17 +68,17 @@ void TriggerSystem::UpdateComponent(EntityWrapper& triggerEntity, ComponentWrapp touchSet.insert(colliderEntity); } // Else, it was touching the trigger last frame too and nothing is done. - } - } else { - // Entity is not touching the trigger, - // Throw event if it was previously. - if (throwLeaveIfWasInTrigger(m_EntitiesTouchingTrigger[triggerEntity], colliderEntity, triggerEntity)) { continue; } - // This only occurs if the entity was completely inside the trigger one frame, - // then completely outside the trigger, e.g. when dying and respawning. - throwLeaveIfWasInTrigger(m_EntitiesCompletelyInTrigger[triggerEntity], colliderEntity, triggerEntity); } + // Only get here if entity is not touching the trigger, + // throw event if it was touching previously. + if (throwLeaveIfWasInTrigger(m_EntitiesTouchingTrigger[triggerEntity], colliderEntity, triggerEntity)) { + continue; + } + // This only occurs if the entity was completely inside the trigger one frame, + // then completely outside the trigger, e.g. when dying and respawning. + throwLeaveIfWasInTrigger(m_EntitiesCompletelyInTrigger[triggerEntity], colliderEntity, triggerEntity); } } diff --git a/src/Engine/Core/ComponentPool.cpp b/src/Engine/Core/ComponentPool.cpp index 059b2e38..49b06fb1 100644 --- a/src/Engine/Core/ComponentPool.cpp +++ b/src/Engine/Core/ComponentPool.cpp @@ -1,9 +1,17 @@ #include "Core/ComponentPool.h" +ComponentPoolForwardIterator::ComponentPoolForwardIterator(ComponentPool* pool, const MemoryPool::iterator begin, const MemoryPool::iterator end) + : m_ComponentPool(pool) + , m_ComponentInfo(pool->m_ComponentInfo) + , m_MemoryPoolIterator(begin) + , m_MemoryPoolEnd(end) +{ } + ComponentWrapper ComponentPoolForwardIterator::operator*() const { char* data = &(*m_MemoryPoolIterator); - ComponentWrapper wrapper(m_ComponentInfo, data); + EntityID entity = *reinterpret_cast(data); + ComponentWrapper wrapper(m_ComponentInfo, data, &m_ComponentPool->m_DirtySet[entity], m_ComponentPool->m_World); return wrapper; } @@ -44,7 +52,7 @@ ComponentPool::ComponentPool(const ComponentPool& other) // Duplicate strings for (auto& name : m_ComponentInfo.StringFields) { for (auto& c : *this) { - std::string& val = c[name]; + Field val = c[name]; ComponentWrapper::SolidifyStrings(c); } } @@ -71,7 +79,7 @@ ComponentWrapper ComponentPool::Allocate(EntityID entity) memcpy(data, &entity, sizeof(EntityID)); m_EntityToComponent[entity] = data; - ComponentWrapper component(m_ComponentInfo, data); + ComponentWrapper component(m_ComponentInfo, data, &m_DirtySet[entity], m_World); // Copy defaults memcpy(component.Data, m_ComponentInfo.Defaults.get(), m_ComponentInfo.Stride); @@ -82,7 +90,9 @@ ComponentWrapper ComponentPool::Allocate(EntityID entity) ComponentWrapper ComponentPool::GetByEntity(EntityID ent) { - return ComponentWrapper(m_ComponentInfo, m_EntityToComponent.at(ent)); + auto data = m_EntityToComponent.at(ent); + auto bitField = &m_DirtySet[ent]; + return ComponentWrapper(m_ComponentInfo, data, bitField, m_World); } bool ComponentPool::KnowsEntity(EntityID ent) @@ -95,16 +105,17 @@ void ComponentPool::Delete(ComponentWrapper& wrapper) ComponentWrapper::Destroy(wrapper.Info, wrapper.Data); m_EntityToComponent.erase(wrapper.EntityID); m_Pool.Free(wrapper.Data - sizeof(EntityID)); + m_DirtySet.erase(wrapper.EntityID); } -ComponentPool::iterator ComponentPool::begin() const +ComponentPool::iterator ComponentPool::begin() { - return iterator(m_ComponentInfo, m_Pool.begin(), m_Pool.end()); + return iterator(this, m_Pool.begin(), m_Pool.end()); } -ComponentPool::iterator ComponentPool::end() const +ComponentPool::iterator ComponentPool::end() { - return iterator(m_ComponentInfo, m_Pool.end(), m_Pool.end()); + return iterator(this, m_Pool.end(), m_Pool.end()); } size_t ComponentPool::size() const diff --git a/src/Engine/Core/ComponentWrapper.cpp b/src/Engine/Core/ComponentWrapper.cpp new file mode 100644 index 00000000..e4d7cde4 --- /dev/null +++ b/src/Engine/Core/ComponentWrapper.cpp @@ -0,0 +1,59 @@ +#include "Core/World.h" +#include "Core/ComponentWrapper.h" + +ComponentWrapper::ComponentWrapper(const ComponentInfo& componentInfo, char* data, ::DirtyBitField* dirtyBitField, World* world) + : Info(componentInfo) + , EntityID(*reinterpret_cast<::EntityID*>(data)) + , Data(data + componentInfo.GetHeaderSize()) + , DirtyBitField(dirtyBitField) + , m_World(world) +{} + +ComponentInfo::EnumType ComponentWrapper::Enum(const char* fieldName, const char* enumKey) +{ + return Info.Meta->FieldEnumDefinitions.at(fieldName).at(enumKey); +} + +bool ComponentWrapper::Dirty(DirtySetType type, const std::string& fieldName) +{ + if (DirtyBitField == nullptr) { + return true; + } else { + auto& field = Info.Fields.at(fieldName); + return DirtyBitField->operator[](type).count(field.Index) == 1; + } +} + +void ComponentWrapper::SetDirty(DirtySetType type, const std::string& fieldName, bool dirty /* = true */) +{ + if (DirtyBitField == nullptr) { + return; + } + + auto& field = Info.Fields.at(fieldName); + if (dirty) { + DirtyBitField->operator[](type).insert(field.Index); + // Because parents affects children when altered, we also need to flag all children as dirty. + if (type == DirtySetType::Transform && m_World != nullptr) { + auto children = m_World->GetDirectChildren(EntityID); + for (auto kv = children.first; kv != children.second; ++kv) { + const auto& child = kv->second; + if (m_World->HasComponent(child, Info.Name)) { + m_World->GetComponent(child, Info.Name).SetDirty(DirtySetType::Transform, fieldName, true); + if (fieldName == "Orientation" || fieldName == "Scale") { + m_World->GetComponent(child, Info.Name).SetDirty(DirtySetType::Transform, "Position", true); + } + } + } + } + } else { + DirtyBitField->operator[](type).erase(field.Index); + } +} + +void ComponentWrapper::SetAllDirty(const std::string& fieldName, bool dirty /* = true */) +{ + for (auto& kv : *DirtyBitField) { + SetDirty(kv.first, fieldName); + } +} \ No newline at end of file diff --git a/src/Engine/Core/EntityWrapper.cpp b/src/Engine/Core/EntityWrapper.cpp index 83a31fa7..ba6cafe0 100644 --- a/src/Engine/Core/EntityWrapper.cpp +++ b/src/Engine/Core/EntityWrapper.cpp @@ -106,8 +106,30 @@ EntityWrapper EntityWrapper::Clone(EntityWrapper parent /*= Invalid*/) return EntityWrapper::Invalid; } - EntityWrapper clone = cloneRecursive(*this, EntityWrapper::Invalid); - this->World->SetParent(clone.ID, parent.ID); + // Create a relationship map of children of this entity + std::unordered_multimap relationships; + fillRelationships(relationships, *this); + + ::World* targetWorld = this->World; + if (parent.Valid()) { + targetWorld = parent.World; + } + + // Create root entity + EntityWrapper clone(targetWorld, targetWorld->CreateEntity(parent.ID)); + // Copy name + clone.World->SetName(clone.ID, this->Name()); + // Clone components + for (auto& kv : this->World->GetComponentPools()) { + if (kv.second->KnowsEntity(this->ID)) { + ComponentWrapper c1 = kv.second->GetByEntity(this->ID); + ComponentWrapper c2 = clone.World->AttachComponent(clone.ID, kv.first); + c1.Copy(c2); + } + } + // Recreate entity tree + recreateRelationships(relationships, *this, clone); + return clone; } @@ -219,30 +241,6 @@ EntityWrapper EntityWrapper::firstChildByNameRecursive(const std::string& name, return EntityWrapper::Invalid; } -EntityWrapper EntityWrapper::cloneRecursive(EntityWrapper entity, EntityWrapper parent) -{ - EntityWrapper clone = EntityWrapper(entity.World, entity.World->CreateEntity(parent.ID)); - entity.World->SetName(clone.ID, entity.Name()); - - // Clone components - for (auto& kv : entity.World->GetComponentPools()) { - if (kv.second->KnowsEntity(entity.ID)) { - ComponentWrapper c1 = kv.second->GetByEntity(entity.ID); - ComponentWrapper c2 = entity.World->AttachComponent(clone.ID, kv.first); - c1.Copy(c2); - } - } - - // Clone children - auto children = entity.World->GetDirectChildren(entity.ID); - for (auto it = children.first; it != children.second; ++it) { - EntityWrapper child(entity.World, it->second); - cloneRecursive(child, clone); - } - - return clone; -} - void EntityWrapper::childrenWithComponentRecursive(const std::string& componentType, EntityWrapper& entity, std::vector& childrenWithComponent) { auto itPair = this->World->GetDirectChildren(entity.ID); @@ -258,3 +256,35 @@ void EntityWrapper::childrenWithComponentRecursive(const std::string& componentT childrenWithComponentRecursive(componentType, child, childrenWithComponent); } } + +void EntityWrapper::fillRelationships(std::unordered_multimap& relationMap, EntityWrapper entity) +{ + auto children = entity.World->GetDirectChildren(entity.ID); + for (auto it = children.first; it != children.second; ++it) { + EntityWrapper child(entity.World, it->second); + relationMap.insert(std::make_pair(entity, child)); + fillRelationships(relationMap, child); + } +} + +void EntityWrapper::recreateRelationships(const std::unordered_multimap& relationMap, EntityWrapper templateEntity, EntityWrapper parent /*= EntityWrapper::Invalid*/) +{ + // Recursively create children + auto children = relationMap.equal_range(templateEntity); + for (auto it = children.first; it != children.second; ++it) { + EntityWrapper child = it->second; + // Create clone entity + EntityWrapper clone(parent.World, parent.World->CreateEntity(parent.ID)); + // Copy name + clone.World->SetName(clone.ID, child.Name()); + // Clone components + for (auto& kv : child.World->GetComponentPools()) { + if (kv.second->KnowsEntity(child.ID)) { + ComponentWrapper c1 = kv.second->GetByEntity(child.ID); + ComponentWrapper c2 = clone.World->AttachComponent(clone.ID, kv.first); + c1.Copy(c2); + } + } + recreateRelationships(relationMap, child, clone); + } +} diff --git a/src/Engine/Core/EntityXMLFilePreprocessor.cpp b/src/Engine/Core/EntityXMLFilePreprocessor.cpp index 9695509d..132d962a 100644 --- a/src/Engine/Core/EntityXMLFilePreprocessor.cpp +++ b/src/Engine/Core/EntityXMLFilePreprocessor.cpp @@ -125,6 +125,7 @@ void EntityXMLFilePreprocessor::parseComponentInfo() auto modelGroup = modelGroupParticle->getModelGroupTerm(); // getParticles(); for (unsigned int i = 0; i < particles->size(); ++i) { @@ -182,12 +183,14 @@ void EntityXMLFilePreprocessor::parseComponentInfo() auto& field = compInfo.Fields[name]; field.Name = name; field.Type = effectiveType; + field.Index = fieldIndex; field.Offset = fieldOffset; field.Stride = stride; compInfo.FieldsInOrder.push_back(name); if (field.Type == "string") { compInfo.StringFields.push_back(name); } + fieldIndex += 1; fieldOffset += stride; } diff --git a/src/Engine/Core/Transform.cpp b/src/Engine/Core/Transform.cpp index e5cff11c..43b5109d 100644 --- a/src/Engine/Core/Transform.cpp +++ b/src/Engine/Core/Transform.cpp @@ -1,103 +1,162 @@ -#include "Core/Transform.h" +#include "Core/TransformSystem.h" -glm::mat4 Transform::AbsoluteTransformation(EntityWrapper entity) +std::unordered_map TransformSystem::PositionCache; +std::unordered_map TransformSystem::OrientationCache; +std::unordered_map TransformSystem::ScaleCache; +std::unordered_map TransformSystem::MatrixCache; + +int TransformSystem::RecalculatedPositions = 0; +int TransformSystem::RecalculatedOrientations = 0; +int TransformSystem::RecalculatedScales = 0; + +TransformSystem::TransformSystem(SystemParams params) + : System(params) { - glm::mat4 t = glm::mat4(1.f); + EVENT_SUBSCRIBE_MEMBER(m_EEntityDeleted, &TransformSystem::OnEntityDeleted); +} - while (entity.Valid()) { - t = glm::translate((glm::vec3&)entity["Transform"]["Position"]) * glm::toMat4(glm::quat((glm::vec3&)entity["Transform"]["Orientation"])) * glm::scale((glm::vec3&)entity["Transform"]["Scale"]) * t; - entity = entity.Parent(); +bool TransformSystem::OnEntityDeleted(const Events::EntityDeleted& e) +{ + // Clean up deleted entity + PositionCache.erase(e.DeletedEntity); + OrientationCache.erase(e.DeletedEntity); + ScaleCache.erase(e.DeletedEntity); + MatrixCache.erase(e.DeletedEntity); + return true; +} + +//glm::mat4 Transform::AbsoluteTransformation(EntityWrapper entity) +//{ +// glm::mat4 t = glm::mat4(1.f); +// +// while (entity.Valid()) { +// t = glm::translate((const glm::vec3&)entity["Transform"]["Position"]) * glm::toMat4(glm::quat((const glm::vec3&)entity["Transform"]["Orientation"])) * glm::scale((const glm::vec3&)entity["Transform"]["Scale"]) * t; +// entity = entity.Parent(); +// } +// +// return t; +//} + +glm::vec3 TransformSystem::AbsolutePosition(World* world, EntityID entity) +{ + return TransformSystem::AbsolutePosition(EntityWrapper(world, entity)); +} + +glm::vec3 TransformSystem::AbsolutePosition(EntityWrapper entity) +{ + if (!entity.Valid()) { + return glm::vec3(); } - return t; -} - -glm::vec3 Transform::AbsolutePosition(EntityWrapper entity) -{ - return AbsolutePosition(entity.World, entity.ID); -} - -glm::vec3 Transform::AbsolutePosition(World* world, EntityID entity) -{ - glm::vec3 position; - - while (entity != EntityID_Invalid) { - ComponentWrapper transform = world->GetComponent(entity, "Transform"); - EntityID parent = world->GetParent(entity); - position += Transform::AbsoluteScale(world, parent) * (Transform::AbsoluteOrientation(world, parent) * (glm::vec3)transform["Position"]); - entity = parent; + auto cacheIt = PositionCache.find(entity); + ComponentWrapper cTransform = entity["Transform"]; + ComponentWrapper::SubscriptProxy cTransformPosition = cTransform["Position"]; + if (cacheIt != PositionCache.end() && !cTransformPosition.Dirty(DirtySetType::Transform)) { + return cacheIt->second; + } else { + EntityWrapper parent = entity.Parent(); + // Calculate position + glm::vec3 position = AbsolutePosition(parent) + TransformSystem::AbsoluteOrientation(parent) * (TransformSystem::AbsoluteScale(parent) * (const glm::vec3&)cTransformPosition); + // Cache it + PositionCache[entity] = position; + RecalculatedPositions++; + // Unset dirty flag + cTransformPosition.SetDirty(DirtySetType::Transform, false); + return position; } - - return position; } -glm::vec3 Transform::AbsoluteOrientationEuler(EntityWrapper entity) +glm::vec3 TransformSystem::AbsoluteOrientationEuler(EntityWrapper entity) { glm::vec3 orientation; while (entity.Valid()) { ComponentWrapper transform = entity["Transform"]; - orientation += (glm::vec3)transform["Orientation"]; + orientation += (Field)transform["Orientation"]; entity = entity.Parent(); } return orientation; } -glm::quat Transform::AbsoluteOrientation(EntityWrapper entity) +glm::quat TransformSystem::AbsoluteOrientation(World* world, EntityID entity) { - return AbsoluteOrientation(entity.World, entity.ID); + return TransformSystem::AbsoluteOrientation(EntityWrapper(world, entity)); } -glm::quat Transform::AbsoluteOrientation(World* world, EntityID entity) +glm::quat TransformSystem::AbsoluteOrientation(EntityWrapper entity) { - glm::quat orientation; - - while (entity != EntityID_Invalid) { - ComponentWrapper transform = world->GetComponent(entity, "Transform"); - orientation = glm::quat((glm::vec3)transform["Orientation"]) * orientation; - entity = world->GetParent(entity); + if (!entity.Valid()) { + return glm::quat(); } - return orientation; + auto cacheIt = OrientationCache.find(entity); + ComponentWrapper cTransform = entity["Transform"]; + ComponentWrapper::SubscriptProxy cTransformOrientation = cTransform["Orientation"]; + if (cacheIt != OrientationCache.end() && !cTransformOrientation.Dirty(DirtySetType::Transform)) { + return cacheIt->second; + } else { + EntityWrapper parent = entity.Parent(); + // Calculate orientation + glm::quat orientation = AbsoluteOrientation(parent) * glm::quat((const glm::vec3&)cTransformOrientation); + // Cache it + OrientationCache[entity] = orientation; + RecalculatedOrientations++; + // Unset dirty flag + cTransformOrientation.SetDirty(DirtySetType::Transform, false); + return orientation; + } } -glm::vec3 Transform::AbsoluteScale(EntityWrapper entity) +glm::vec3 TransformSystem::AbsoluteScale(World* world, EntityID entity) { - return AbsoluteScale(entity.World, entity.ID); + return TransformSystem::AbsoluteScale(EntityWrapper(world, entity)); } -glm::vec3 Transform::AbsoluteScale(World* world, EntityID entity) +glm::vec3 TransformSystem::AbsoluteScale(EntityWrapper entity) { - glm::vec3 scale(1.f); - - while (entity != EntityID_Invalid) { - ComponentWrapper transform = world->GetComponent(entity, "Transform"); - scale *= (glm::vec3)transform["Scale"]; - entity = world->GetParent(entity); + if (!entity.Valid()) { + return glm::vec3(1.f); } - return scale; + auto cacheIt = ScaleCache.find(entity); + ComponentWrapper cTransform = entity["Transform"]; + ComponentWrapper::SubscriptProxy cTransformScale = cTransform["Scale"]; + if (cacheIt != ScaleCache.end() && !cTransformScale.Dirty(DirtySetType::Transform)) { + return cacheIt->second; + } else { + EntityWrapper parent = entity.Parent(); + // Calculate scale + glm::vec3 scale = AbsoluteScale(parent) * (const glm::vec3&)cTransformScale; + // Cache it + ScaleCache[entity] = scale; + RecalculatedPositions++; + // Unset dirty flag + cTransformScale.SetDirty(DirtySetType::Transform, false); + return scale; + } } -glm::mat4 Transform::ModelMatrix(EntityWrapper entity) +glm::mat4 TransformSystem::ModelMatrix(EntityID entityID, World* world) { - return ModelMatrix(entity.ID, entity.World); + return ModelMatrix(EntityWrapper(world, entityID)); } -glm::mat4 Transform::ModelMatrix(EntityID entity, World* world) +glm::mat4 TransformSystem::ModelMatrix(EntityWrapper entity) { - return AbsoluteTransformation(EntityWrapper(world, entity)); - - //glm::vec3 position = Transform::AbsolutePosition(world, entity); - //glm::quat orientation = Transform::AbsoluteOrientation(world, entity); - //glm::vec3 scale = Transform::AbsoluteScale(world, entity); - - //glm::mat4 modelMatrix = glm::translate(glm::mat4(), position) * glm::toMat4(orientation) * glm::scale(scale); - //return modelMatrix; + auto cacheIt = MatrixCache.find(entity); + ComponentWrapper cTransform = entity["Transform"]; + bool isDirty = cTransform["Position"].Dirty(DirtySetType::Transform) || cTransform["Orientation"].Dirty(DirtySetType::Transform) || cTransform["Scale"].Dirty(DirtySetType::Transform); + if (cacheIt != MatrixCache.end() && !isDirty) { + return cacheIt->second; + } else { + glm::mat4 matrix = glm::translate(AbsolutePosition(entity)) * glm::toMat4(AbsoluteOrientation(entity)) * glm::scale(AbsoluteScale(entity)); + MatrixCache[entity] = matrix; + return matrix; + } } -glm::vec3 Transform::TransformPoint(const glm::vec3& point, const glm::mat4& matrix) +glm::vec3 TransformSystem::TransformPoint(const glm::vec3& point, const glm::mat4& matrix) { return glm::vec3(matrix * glm::vec4(point.x, point.y, point.z, 1)); } \ No newline at end of file diff --git a/src/Engine/Core/TransformSystem.cpp b/src/Engine/Core/TransformSystem.cpp new file mode 100644 index 00000000..7fc3a585 --- /dev/null +++ b/src/Engine/Core/TransformSystem.cpp @@ -0,0 +1,162 @@ +#include "Core/TransformSystem.h" + +std::unordered_map TransformSystem::PositionCache; +std::unordered_map TransformSystem::OrientationCache; +std::unordered_map TransformSystem::ScaleCache; +std::unordered_map TransformSystem::MatrixCache; + +int TransformSystem::RecalculatedPositions = 0; +int TransformSystem::RecalculatedOrientations = 0; +int TransformSystem::RecalculatedScales = 0; + +TransformSystem::TransformSystem(SystemParams params) + : System(params) +{ + EVENT_SUBSCRIBE_MEMBER(m_EEntityDeleted, &TransformSystem::OnEntityDeleted); +} + +bool TransformSystem::OnEntityDeleted(const Events::EntityDeleted& e) +{ + // Clean up deleted entity + PositionCache.erase(e.DeletedEntity); + OrientationCache.erase(e.DeletedEntity); + ScaleCache.erase(e.DeletedEntity); + MatrixCache.erase(e.DeletedEntity); + return true; +} + +//glm::mat4 Transform::AbsoluteTransformation(EntityWrapper entity) +//{ +// glm::mat4 t = glm::mat4(1.f); +// +// while (entity.Valid()) { +// t = glm::translate((const glm::vec3&)entity["Transform"]["Position"]) * glm::toMat4(glm::quat((const glm::vec3&)entity["Transform"]["Orientation"])) * glm::scale((const glm::vec3&)entity["Transform"]["Scale"]) * t; +// entity = entity.Parent(); +// } +// +// return t; +//} + +glm::vec3 TransformSystem::AbsolutePosition(World* world, EntityID entity) +{ + return TransformSystem::AbsolutePosition(EntityWrapper(world, entity)); +} + +glm::vec3 TransformSystem::AbsolutePosition(EntityWrapper entity) +{ + if (!entity.Valid()) { + return glm::vec3(); + } + + auto cacheIt = PositionCache.find(entity); + ComponentWrapper cTransform = entity["Transform"]; + ComponentWrapper::SubscriptProxy cTransformPosition = cTransform["Position"]; + if (cacheIt != PositionCache.end() && !cTransformPosition.Dirty(DirtySetType::Transform)) { + return cacheIt->second; + } else { + EntityWrapper parent = entity.Parent(); + // Calculate position + glm::vec3 position = AbsolutePosition(parent) + TransformSystem::AbsoluteOrientation(parent) * (TransformSystem::AbsoluteScale(parent) * (const glm::vec3&)cTransformPosition); + // Cache it + PositionCache[entity] = position; + RecalculatedPositions++; + // Unset dirty flag + cTransformPosition.SetDirty(DirtySetType::Transform, false); + return position; + } +} + +glm::vec3 TransformSystem::AbsoluteOrientationEuler(EntityWrapper entity) +{ + glm::vec3 orientation; + + while (entity.Valid()) { + ComponentWrapper transform = entity["Transform"]; + orientation += (Field)transform["Orientation"]; + entity = entity.Parent(); + } + + return orientation; +} + +glm::quat TransformSystem::AbsoluteOrientation(World* world, EntityID entity) +{ + return TransformSystem::AbsoluteOrientation(EntityWrapper(world, entity)); +} + +glm::quat TransformSystem::AbsoluteOrientation(EntityWrapper entity) +{ + if (!entity.Valid()) { + return glm::quat(); + } + + auto cacheIt = OrientationCache.find(entity); + ComponentWrapper cTransform = entity["Transform"]; + ComponentWrapper::SubscriptProxy cTransformOrientation = cTransform["Orientation"]; + if (cacheIt != OrientationCache.end() && !cTransformOrientation.Dirty(DirtySetType::Transform)) { + return cacheIt->second; + } else { + EntityWrapper parent = entity.Parent(); + // Calculate orientation + glm::quat orientation = AbsoluteOrientation(parent) * glm::quat((const glm::vec3&)cTransformOrientation); + // Cache it + OrientationCache[entity] = orientation; + RecalculatedOrientations++; + // Unset dirty flag + cTransformOrientation.SetDirty(DirtySetType::Transform, false); + return orientation; + } +} + +glm::vec3 TransformSystem::AbsoluteScale(World* world, EntityID entity) +{ + return TransformSystem::AbsoluteScale(EntityWrapper(world, entity)); +} + +glm::vec3 TransformSystem::AbsoluteScale(EntityWrapper entity) +{ + if (!entity.Valid()) { + return glm::vec3(1.f); + } + + auto cacheIt = ScaleCache.find(entity); + ComponentWrapper cTransform = entity["Transform"]; + ComponentWrapper::SubscriptProxy cTransformScale = cTransform["Scale"]; + if (cacheIt != ScaleCache.end() && !cTransformScale.Dirty(DirtySetType::Transform)) { + return cacheIt->second; + } else { + EntityWrapper parent = entity.Parent(); + // Calculate scale + glm::vec3 scale = AbsoluteScale(parent) * (const glm::vec3&)cTransformScale; + // Cache it + ScaleCache[entity] = scale; + RecalculatedPositions++; + // Unset dirty flag + cTransformScale.SetDirty(DirtySetType::Transform, false); + return scale; + } +} + +glm::mat4 TransformSystem::ModelMatrix(EntityID entityID, World* world) +{ + return ModelMatrix(EntityWrapper(world, entityID)); +} + +glm::mat4 TransformSystem::ModelMatrix(EntityWrapper entity) +{ + //auto cacheIt = MatrixCache.find(entity); + //ComponentWrapper cTransform = entity["Transform"]; + //bool isDirty = cTransform["Position"].Dirty(DirtySetType::Transform) || cTransform["Orientation"].Dirty(DirtySetType::Transform) || cTransform["Scale"].Dirty(DirtySetType::Transform); + //if (cacheIt != MatrixCache.end() && !isDirty && false) { + // return cacheIt->second; + //} else { + glm::mat4 matrix = glm::translate(AbsolutePosition(entity)) * glm::toMat4(AbsoluteOrientation(entity)) * glm::scale(AbsoluteScale(entity)); + // MatrixCache[entity] = matrix; + return matrix; + //} +} + +glm::vec3 TransformSystem::TransformPoint(const glm::vec3& point, const glm::mat4& matrix) +{ + return glm::vec3(matrix * glm::vec4(point.x, point.y, point.z, 1)); +} \ No newline at end of file diff --git a/src/Engine/Core/UniformScaleSystem.cpp b/src/Engine/Core/UniformScaleSystem.cpp index d5ac878a..2d50ccca 100644 --- a/src/Engine/Core/UniformScaleSystem.cpp +++ b/src/Engine/Core/UniformScaleSystem.cpp @@ -13,8 +13,8 @@ void UniformScaleSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper return; } - float distance = glm::length((glm::vec3)entity["Transform"]["Position"] - (glm::vec3&)m_Camera["Transform"]["Position"]); - entity["Transform"]["Scale"] = (glm::vec3&)cUniformScale["Scale"] * distance; + float distance = glm::length((glm::vec3)entity["Transform"]["Position"] - (const glm::vec3&)m_Camera["Transform"]["Position"]); + entity["Transform"]["Scale"] = (const glm::vec3&)cUniformScale["Scale"] * distance; } bool UniformScaleSystem::OnSetCamera(const Events::SetCamera& e) diff --git a/src/Engine/Core/World.cpp b/src/Engine/Core/World.cpp index 0952a53b..baf39fc8 100644 --- a/src/Engine/Core/World.cpp +++ b/src/Engine/Core/World.cpp @@ -48,7 +48,7 @@ bool World::ValidEntity(EntityID entity) const void World::RegisterComponent(const ComponentInfo& ci) { if (m_ComponentPools.find(ci.Name) == m_ComponentPools.end()) { - m_ComponentPools[ci.Name] = new ComponentPool(ci); + m_ComponentPools[ci.Name] = new ComponentPool(ci, this); } } @@ -95,7 +95,7 @@ void World::DeleteComponent(EntityID entity, const std::string& componentType) } } -const ComponentPool* World::GetComponents(const std::string& componentType) +ComponentPool* World::GetComponents(const std::string& componentType) { auto it = m_ComponentPools.find(componentType); return (it != m_ComponentPools.end()) ? it->second : nullptr; @@ -223,7 +223,7 @@ void World::deleteEntityRecursive(EntityID entity, bool cascaded /*= false*/) if (m_EventBroker != nullptr) { Events::EntityDeleted e; - e.DeletedEntity = entity; + e.DeletedEntity = EntityWrapper(this, entity); e.Cascaded = cascaded; m_EventBroker->Publish(e); } diff --git a/src/Engine/Editor/EditorGUI.cpp b/src/Engine/Editor/EditorGUI.cpp index 7435bca8..ef9b4408 100644 --- a/src/Engine/Editor/EditorGUI.cpp +++ b/src/Engine/Editor/EditorGUI.cpp @@ -381,6 +381,10 @@ bool EditorGUI::drawComponentField(ComponentWrapper& c, const ComponentInfo::Fie ImGui::TextDisabled(field.Type.c_str()); } + if (dirty) { + c[field.Name].SetAllDirty(); + } + ImGui::PopID(); return dirty; diff --git a/src/Engine/Editor/EditorRenderSystem.cpp b/src/Engine/Editor/EditorRenderSystem.cpp index f31b63cf..f365579c 100644 --- a/src/Engine/Editor/EditorRenderSystem.cpp +++ b/src/Engine/Editor/EditorRenderSystem.cpp @@ -52,7 +52,7 @@ void EditorRenderSystem::Update(double dt) } EntityWrapper entity(m_World, cModel.EntityID); - glm::mat4 modelMatrix = Transform::ModelMatrix(entity.ID, entity.World); + glm::mat4 modelMatrix = TransformSystem::ModelMatrix(entity.ID, entity.World); for (auto matGroup : model->MaterialGroups()) { std::shared_ptr modelJob = std::make_shared(model, scene.Camera, modelMatrix, matGroup, cModel, entity.World, glm::vec4(0), 0.f, false, false); if (cModel["Transparent"]) { diff --git a/src/Engine/Editor/EditorSystem.cpp b/src/Engine/Editor/EditorSystem.cpp index 5e0d02fd..e3b47036 100644 --- a/src/Engine/Editor/EditorSystem.cpp +++ b/src/Engine/Editor/EditorSystem.cpp @@ -4,7 +4,7 @@ #include "Editor/EditorWidgetSystem.h" #include "Core/EntityFile.h" -EditorSystem::EditorSystem(SystemParams params, IRenderer* renderer, RenderFrame* renderFrame) +EditorSystem::EditorSystem(SystemParams params, IRenderer* renderer, RenderFrame* renderFrame) : System(params) , m_Renderer(renderer) , m_RenderFrame(renderFrame) @@ -14,7 +14,7 @@ EditorSystem::EditorSystem(SystemParams params, IRenderer* renderer, RenderFrame m_EditorWorldSystemPipeline->AddSystem(0); m_EditorWorldSystemPipeline->AddSystem(0, m_Renderer); m_EditorWorldSystemPipeline->AddSystem(1, m_Renderer, m_RenderFrame); - + m_EditorCamera = importEntity(EntityWrapper(m_EditorWorld, EntityID_Invalid), "Schema/Entities/Empty.xml"); m_ActualCamera = m_EditorCamera; m_EditorWorld->AttachComponent(m_EditorCamera.ID, "Transform"); @@ -47,6 +47,7 @@ EditorSystem::EditorSystem(SystemParams params, IRenderer* renderer, RenderFrame Enable(); } else { Disable(); + m_EventBroker->Publish(Events::UnlockMouse()); } } @@ -71,21 +72,23 @@ void EditorSystem::Update(double dt) m_EditorStats->Draw(actualDelta); if (m_CurrentSelection.Valid() && m_Widget.Valid()) { - (glm::vec3&)m_Widget["Transform"]["Position"] = Transform::AbsolutePosition(m_CurrentSelection); + if (isAnyParentMissingTransform(m_CurrentSelection.ID)) { + return; + } + (Field)m_Widget["Transform"]["Position"] = TransformSystem::AbsolutePosition(m_CurrentSelection); if (m_WidgetSpace == EditorGUI::WidgetSpace::Local) { - (glm::vec3&)m_Widget["Transform"]["Orientation"] = Transform::AbsoluteOrientationEuler(m_CurrentSelection); + m_Widget["Transform"]["Orientation"] = TransformSystem::AbsoluteOrientationEuler(m_CurrentSelection); } else { - (glm::vec3&)m_Widget["Transform"]["Orientation"] = glm::vec3(0, 0, 0); + m_Widget["Transform"]["Orientation"] = glm::vec3(0, 0, 0); } } - m_EditorWorldSystemPipeline->Update(actualDelta); ComponentWrapper& cameraTransform = m_EditorCamera["Transform"]; - glm::vec3& ori = cameraTransform["Orientation"]; - ori.x = m_EditorCameraInputController->Rotation().x; - ori.y = m_EditorCameraInputController->Rotation().y; - glm::vec3& pos = cameraTransform["Position"]; + Field ori = cameraTransform["Orientation"]; + ori.x(m_EditorCameraInputController->Rotation().x); + ori.y(m_EditorCameraInputController->Rotation().y); + Field pos = cameraTransform["Position"]; pos += m_EditorCameraInputController->Movement() * glm::inverse(glm::quat(ori)) * (float)actualDelta; } } @@ -101,7 +104,7 @@ void EditorSystem::Enable() eSetCamera.CameraEntity = m_EditorCamera; m_EventBroker->Publish(eSetCamera); if (m_ActualCamera.Valid()) { - (glm::vec3&)m_EditorCamera["Transform"]["Position"] = Transform::AbsolutePosition(m_ActualCamera); + (Field)m_EditorCamera["Transform"]["Position"] = TransformSystem::AbsolutePosition(m_ActualCamera); } // Pause the world we're editing @@ -202,24 +205,27 @@ bool EditorSystem::OnMousePress(const Events::MousePress& e) bool EditorSystem::OnWidgetDelta(const Events::WidgetDelta& e) { if (m_CurrentSelection.Valid()) { + if (isAnyParentMissingTransform(m_CurrentSelection.ID)) { + return false; + } if (m_WidgetSpace == EditorGUI::WidgetSpace::Global) { glm::quat parentOrientation; glm::vec3 parentScale(1.f); EntityWrapper parent = m_CurrentSelection.Parent(); if (parent.Valid()) { - parentOrientation = glm::inverse(Transform::AbsoluteOrientation(parent)); - parentScale = Transform::AbsoluteScale(parent); + parentOrientation = glm::inverse(TransformSystem::AbsoluteOrientation(parent)); + parentScale = TransformSystem::AbsoluteScale(parent); } - (glm::vec3&)m_CurrentSelection["Transform"]["Position"] += parentOrientation * e.Translation / parentScale; + (Field)m_CurrentSelection["Transform"]["Position"] += parentOrientation * e.Translation / parentScale; } else if (m_WidgetSpace == EditorGUI::WidgetSpace::Local) { glm::vec3 parentScale(1.f); EntityWrapper parent = m_CurrentSelection.Parent(); if (parent.Valid()) { - parentScale = Transform::AbsoluteScale(parent); + parentScale = TransformSystem::AbsoluteScale(parent); } glm::quat selectionOri = glm::quat((glm::vec3)m_CurrentSelection["Transform"]["Orientation"]); glm::vec3 localTranslation = selectionOri * e.Translation / parentScale; - (glm::vec3&)m_CurrentSelection["Transform"]["Position"] += localTranslation; + (Field)m_CurrentSelection["Transform"]["Position"] += localTranslation; } m_EditorGUI->SetDirty(m_CurrentSelection); } @@ -306,5 +312,17 @@ void EditorSystem::setWidgetMode(EditorGUI::WidgetMode mode) break; } - m_Widget["Transform"]["Position"] = Transform::AbsolutePosition(m_CurrentSelection.World, m_CurrentSelection.ID); + m_Widget["Transform"]["Position"] = TransformSystem::AbsolutePosition(m_CurrentSelection.World, m_CurrentSelection.ID); +} + +bool EditorSystem::isAnyParentMissingTransform(EntityID entityID) +{ + EntityWrapper entity(m_World, entityID); + while (entity.Parent().Valid()) { + if (!entity.HasComponent("Transform")) { + return true; + } + entity = entity.Parent(); + } + return false; } diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index b4eafbcb..705872fa 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -1,4 +1,5 @@ #include "Network/Client.h" + using namespace boost::asio::ip; Client::Client(World* world, EventBroker* eventBroker) @@ -11,7 +12,7 @@ Client::Client(World* world, EventBroker* eventBroker) auto config = ResourceManager::Load("Config.ini"); m_PlayerName = config->Get("Networking.Name", "Raptorcopter"); - m_SendInputIntervalMs = config->Get("Networking.SendInputIntervalMs", 33); + m_SendInputInterval = config->Get("Networking.SendInputIntervalMs", 33) / 1000.0; LOG_INFO("Client initialized"); m_ServerlistRequest.Connect(m_PlayerName, "192.168.1.255", 32554); @@ -47,19 +48,22 @@ void Client::Connect(std::string address, int port) } } -void Client::Update() +void Client::Update(double dt) { m_EventBroker->Process(); - //while (m_Unreliable.IsSocketAvailable()) { - // // Packet will get real data in receive - // Packet packet(MessageType::Invalid); - // m_Unreliable.Receive(packet); - // if (packet.GetMessageType() == MessageType::Connect) { - // parseUDPConnect(packet); - // } else { - // parseMessageType(packet); - // } - //} + while (m_Unreliable.IsSocketAvailable()) { + m_Unreliable.ReceivePackets(); + } + // Packet will get real data in GetNextPacket() + Packet parsedPacket(MessageType::Invalid); + while (m_Unreliable.GetNextPacket(parsedPacket)) { + if (parsedPacket.GetMessageType() == MessageType::Connect) { + parseUDPConnect(parsedPacket); + } else { + parseMessageType(parsedPacket); + } + } + while (m_Reliable.IsSocketAvailable()) { // Packet will get real data in receive Packet packet(MessageType::Invalid); @@ -81,7 +85,9 @@ void Client::Update() } if (m_SearchingForServers) { - if (m_SearchingTime < (1000* (std::clock() - m_StartSearchTime) / (double)CLOCKS_PER_SEC)) { + m_TimeSearched += dt; + if (m_SearchingTime < m_TimeSearched) { + m_TimeSearched = 0; m_SearchingForServers = false; //displayServerlist(); Events::DisplayServerlist e; @@ -92,9 +98,10 @@ void Client::Update() if (m_IsConnected) { // Don't send 1 input in 1 packet, bunch em up. - if (m_SendInputIntervalMs < (1000 * (std::clock() - m_TimeSinceSentInputs) / (double)CLOCKS_PER_SEC)) { + m_TimeSinceSentInputs += dt; + if (m_SendInputInterval < m_TimeSinceSentInputs) { sendInputCommands(); - m_TimeSinceSentInputs = std::clock(); + m_TimeSinceSentInputs = 0; } // HACK: Send absolute player positions for now to avoid desync until we have reliable messages sendLocalPlayerTransform(); @@ -106,8 +113,9 @@ void Client::Update() void Client::parseMessageType(Packet& packet) { - // Pop packetSize - packet.ReadPrimitive(); + // Pop packetSize, sequenceNumber and packetsInSequence. + popNetworkSegmentOfHeader(packet); + int messageType = packet.ReadPrimitive(); if (messageType == -1) return; @@ -154,6 +162,9 @@ void Client::parseMessageType(Packet& packet) case MessageType::AmmoPickup: parseAmmoPickup(packet); break; + case MessageType::RemoveWorld: + parseRemoveWorld(packet); + break; default: break; } @@ -162,26 +173,29 @@ void Client::parseMessageType(Packet& packet) void Client::parseUDPConnect(Packet& packet) { // Map ServerEntityID and your PlayerID + // TODO: If this is not received send a new connect message. LOG_INFO("I be connected PogChamp"); } void Client::parseTCPConnect(Packet& packet) { LOG_INFO("Received TCP connect from server"); - // Pop size of message int - packet.ReadPrimitive(); + // Pop packetSize, group, groupIndex and groupSize. + popNetworkSegmentOfHeader(packet); + int messageType = packet.ReadPrimitive(); // Read packet ID m_PreviousPacketID = m_PacketID; // Set previous packet id m_PacketID = packet.ReadPrimitive(); //Read new packet id // parse player id and other stuff m_PlayerID = packet.ReadPrimitive(); - m_PlayerID = packet.ReadPrimitive(); LOG_INFO("A Player connected"); + // TODO: If this is not received send a new connect message. Packet UnreliablePacket(MessageType::Connect, m_SendPacketID); // Add player id and other stuff packet.WritePrimitive(m_PlayerID); - // m_Unreliable.Send(packet); + m_Unreliable.Send(packet); + // LOG_INFO("Sent UDP Connect Server"); } @@ -208,10 +222,11 @@ void Client::parsePing() void Client::parseServerlist(Packet& packet) { - // Pop size, message type, and ID - packet.ReadPrimitive(); + // Pop packetSize, group, groupIndex and groupSize. + popNetworkSegmentOfHeader(packet); packet.ReadPrimitive(); packet.ReadPrimitive(); + std::string address = packet.ReadString(); int port = packet.ReadPrimitive(); std::string serverName = packet.ReadString(); @@ -224,7 +239,7 @@ void Client::parseServerlist(Packet& packet) void Client::parseKick() { LOG_WARNING("You have been kicked from the server."); - m_IsConnected = false; + disconnect(); } void Client::parseSpawnEvents() @@ -327,6 +342,13 @@ void Client::parseAmmoPickup(Packet & packet) m_EventBroker->Publish(e); } +void Client::parseRemoveWorld(Packet & packet) +{ + removeWorld(); + Events::Reset e; + m_EventBroker->Publish(e); +} + void Client::updateFields(Packet& packet, const ComponentInfo& componentInfo, const EntityID& entityID) { for (auto field : componentInfo.FieldsInOrder) { @@ -463,7 +485,12 @@ void Client::disconnect() m_PacketID = 0; Packet packet(MessageType::Disconnect, m_SendPacketID); m_Reliable.Send(packet); + m_Unreliable.Disconnect(); m_Reliable.Disconnect(); + Events::PlayerDisconnected e; + e.Entity = m_LocalPlayer.ID; + e.PlayerID = -1; + m_EventBroker->Publish(e); createMainMenu(); } @@ -475,8 +502,8 @@ bool Client::OnInputCommand(const Events::InputCommand & e) if (e.Command == "ConnectToServer") { // Connect for now if (e.Value > 0) { - //m_Reliable.Connect(m_PlayerName, m_Address, m_Port); - // m_Unreliable.Connect(m_PlayerName, m_Address, m_Port); + m_Reliable.Connect(m_PlayerName, m_Address, m_Port); + m_Unreliable.Connect(m_PlayerName, m_Address, m_Port); } //LOG_DEBUG("Client::OnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID); return true; @@ -553,6 +580,7 @@ bool Client::OnConnectRequest(const Events::ConnectRequest& e) { removeWorld(); if (m_Reliable.Connect(m_PlayerName, e.IP, e.Port)) { + m_Unreliable.Connect(m_PlayerName, e.IP, e.Port); // The client sent a successful connect message return true; @@ -568,7 +596,7 @@ bool Client::OnConnectRequest(const Events::ConnectRequest& e) bool Client::OnSearchForServers(const Events::SearchForServers& e) { m_SearchingForServers = true; - m_StartSearchTime = std::clock(); + m_TimeSearched = 0; m_Serverlist.clear(); Packet packet(MessageType::ServerlistRequest); m_ServerlistRequest.Broadcast(packet, 13); // TODO: Config @@ -612,8 +640,8 @@ void Client::sendLocalPlayerTransform() Packet packet(MessageType::PlayerTransform, m_SendPacketID); ComponentWrapper cTransform = m_LocalPlayer["Transform"]; - glm::vec3& position = cTransform["Position"]; - glm::vec3& orientation = cTransform["Orientation"]; + const glm::vec3& position = cTransform["Position"]; + const glm::vec3& orientation = cTransform["Orientation"]; packet.WritePrimitive(position.x); packet.WritePrimitive(position.y); packet.WritePrimitive(position.z); @@ -629,7 +657,7 @@ void Client::sendLocalPlayerTransform() packet.WritePrimitive((int)cAssaultWeapon["Ammo"]); } - m_Reliable.Send(packet); + m_Unreliable.Send(packet); } void Client::identifyPacketLoss() @@ -691,20 +719,6 @@ void Client::displayServerlist() } } - -void Client::removeWorld() -{ - std::vector childrenToBeDeleted; - auto rootEntites = m_World->GetDirectChildren(EntityID_Invalid); - for (auto it = rootEntites.first; it != rootEntites.second; it++) { - childrenToBeDeleted.push_back(it->second); - } - for (int i = 0; i < childrenToBeDeleted.size(); ++i) { - m_World->DeleteEntity(childrenToBeDeleted[i]); - } -} - - void Client::createMainMenu() { auto entityFile = ResourceManager::Load("Schema/Entities/StartMenu.xml"); diff --git a/src/Engine/Network/Network.cpp b/src/Engine/Network/Network.cpp index 6ce9ef82..b69fba09 100644 --- a/src/Engine/Network/Network.cpp +++ b/src/Engine/Network/Network.cpp @@ -9,7 +9,7 @@ Network::Network(World* world, EventBroker* eventBroker) m_TimeoutMs = config->Get("Networking.TimeoutMs", 20000); } -void Network::Update() +void Network::Update(double dt) { updateNetworkData(); } @@ -83,3 +83,24 @@ void Network::updateNetworkData() m_NetworkData.DataReceivedThisInterval = 0; } } + +void Network::popNetworkSegmentOfHeader(Packet & packet) +{ + // Pop packetSize, group, groupIndex and groupSize. + packet.ReadPrimitive(); + packet.ReadPrimitive(); + packet.ReadPrimitive(); + packet.ReadPrimitive(); +} + +void Network::removeWorld() +{ + std::vector childrenToBeDeleted; + auto rootEntites = m_World->GetDirectChildren(EntityID_Invalid); + for (auto it = rootEntites.first; it != rootEntites.second; it++) { + childrenToBeDeleted.push_back(it->second); + } + for (int i = 0; i < childrenToBeDeleted.size(); ++i) { + m_World->DeleteEntity(childrenToBeDeleted[i]); + } +} \ No newline at end of file diff --git a/src/Engine/Network/Packet.cpp b/src/Engine/Network/Packet.cpp index 6a4d0098..83fbf34b 100644 --- a/src/Engine/Network/Packet.cpp +++ b/src/Engine/Network/Packet.cpp @@ -3,16 +3,22 @@ Packet::Packet(MessageType type, unsigned int& packetID) { m_Data = new char[m_MaxPacketSize]; - Init(type, packetID); + Init(type, packetID, 1, 1, -1); } // Create message Packet::Packet(char* data, const size_t sizeOfPacket) { + // Create message header + // allocate memory for size of packet, sequenceNumber and totalPacketesInSequence + m_ReturnDataOffset = 0; + m_Offset = 0; // Resize message m_MaxPacketSize = sizeOfPacket; // Copy data newly allocated memory m_Data = new char[sizeOfPacket]; + unsigned int dummy = 0; + Init(MessageType::Invalid, dummy, 0, 0, 0); memcpy(m_Data, data, sizeOfPacket); m_Offset = sizeOfPacket; } @@ -21,7 +27,7 @@ Packet::Packet(MessageType type) { m_Data = new char[m_MaxPacketSize]; unsigned int dummy = 0; - Init(type, dummy); + Init(type, dummy, 1, 1, -1); } Packet::~Packet() @@ -29,16 +35,30 @@ Packet::~Packet() delete[] m_Data; } -void Packet::Init(MessageType type, unsigned int & packetID) +void Packet::Init(MessageType type, unsigned int & packetID, + int groupIndex, int groupSize, int group) { m_ReturnDataOffset = 0; m_Offset = 0; // Create message header - // allocate memory for size of packet(only used in tcp) + // allocate memory for size of packet, sequenceNumber and totalPacketesInSequence + packetSizeOffset = m_Offset; WritePrimitive(0); + // packetGroup is the group the packet is in + groupOffset = m_Offset; + WritePrimitive(group); + // What index the packet has in the packetGroup + groupIndexOffset = m_Offset; + WritePrimitive(groupIndex); + // The total amount of packets in a packetGroup + groupSizeOffset = m_Offset; + WritePrimitive(groupSize); // Add message type int messageType = static_cast(type); + messageTypeOffset = m_Offset; WritePrimitive(messageType); + // Packet ID + packetIDOffset = m_Offset; WritePrimitive(packetID); packetID++; m_HeaderSize = m_Offset; @@ -50,7 +70,7 @@ void Packet::WriteString(const std::string& str) size_t sizeOfString = str.size() + 1; if (m_Offset + sizeOfString > m_MaxPacketSize) { if (m_MaxPacketSize >= 32000) { - LOG_WARNING("Package::WriteString(): New size is huge %i bytes\n", m_MaxPacketSize*2); + //LOG_WARNING("Package::WriteString(): New size is huge %i bytes\n", m_MaxPacketSize*2); } resizeData(); } @@ -65,7 +85,7 @@ void Packet::WriteData(char * data, int sizeOfData) if (m_Offset + sizeOfData > m_MaxPacketSize) { if (m_MaxPacketSize >= 32000) { - LOG_WARNING("Package::WriteData(): New size is huge %i bytes\n", m_MaxPacketSize*2); + //LOG_WARNING("Package::WriteData(): New size is huge %i bytes\n", m_MaxPacketSize*2); } while (m_Offset + sizeOfData > m_MaxPacketSize) { resizeData(); @@ -104,8 +124,7 @@ void Packet::ReconstructFromData(char * data, size_t sizeOfData) void Packet::UpdateSize() { - int whatisoffset = m_Offset; - memcpy(m_Data, &m_Offset, sizeof(int)); + memcpy(m_Data + packetSizeOffset, &m_Offset, sizeof(int)); } char * Packet::ReadData(int sizeOfData) @@ -123,14 +142,47 @@ void Packet::ChangePacketID(unsigned int & packetID) { packetID = packetID + 1; // Overwrite old PacketID - memcpy(m_Data + 2*sizeof(int), &packetID, sizeof(int)); + memcpy(m_Data + packetIDOffset, &packetID, sizeof(int)); +} + +void Packet::ChangeGroupIndex(int groupIndex) +{ + memcpy(m_Data + groupIndexOffset, &groupIndex, sizeof(int)); +} + +void Packet::ChangeGroupSize(int groupSize) +{ + memcpy(m_Data + groupSizeOffset, &groupSize, sizeof(int)); +} + +void Packet::ChangeGroup(int group) +{ + memcpy(m_Data + groupOffset, &group, sizeof(int)); } MessageType Packet::GetMessageType() { - MessageType messagType; - memcpy(&messagType, m_Data + sizeof(int), sizeof(int)); - return messagType; + return *reinterpret_cast(m_Data + messageTypeOffset); +} + +size_t Packet::Group() +{ + return *reinterpret_cast(m_Data + groupOffset); +} + +size_t Packet::GroupIndex() +{ + return *reinterpret_cast(m_Data + groupIndexOffset); +} + +size_t Packet::GroupSize() +{ + return *reinterpret_cast(m_Data + groupSizeOffset); +} + +size_t Packet::PacketID() +{ + return *reinterpret_cast(m_Data + packetIDOffset); } void Packet::resizeData() diff --git a/src/Engine/Network/Server.cpp b/src/Engine/Network/Server.cpp index 0dd761a0..dc40ea3f 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -5,8 +5,8 @@ Server::Server(World* world, EventBroker* eventBroker, int port) , m_ServerlistRequest(13) { ConfigFile* config = ResourceManager::Load("Config.ini"); - snapshotInterval = 1000 * config->Get("Networking.SnapshotInterval", 0.05f); - pingIntervalMs = config->Get("Networking.PingIntervalMs", 1000); + snapshotInterval = config->Get("Networking.SnapshotInterval", 0.05); + pingInterval = config->Get("Networking.PingIntervalMs", 1000) / 1000.0; m_ServerName = config->Get("Networking.Name", "Unnamed"); // Subscribe to events @@ -17,6 +17,7 @@ Server::Server(World* world, EventBroker* eventBroker, int port) EVENT_SUBSCRIBE_MEMBER(m_EPlayerDamage, &Server::OnPlayerDamage); EVENT_SUBSCRIBE_MEMBER(m_EAmmoPickup, &Server::OnAmmoPickup); EVENT_SUBSCRIBE_MEMBER(m_EPlayerDeath, &Server::OnPlayerDeath); + EVENT_SUBSCRIBE_MEMBER(m_EWin, &Server::OnWin); // BindWW if (port == 0) { port = config->Get("Networking.Port", 27666); @@ -30,7 +31,7 @@ Server::~Server() } -void Server::Update() +void Server::Update(double dt) { m_Reliable.AcceptNewConnections(m_NextPlayerID, m_ConnectedPlayers); @@ -49,19 +50,19 @@ void Server::Update() } } - //PlayerDefinition pd; - //while (m_Unreliable.IsSocketAvailable()) { - // // Packet will get real data in receive - // Packet packet(MessageType::Invalid); - // m_Unreliable.Receive(packet, pd); - // m_Address = pd.Endpoint.address(); - // m_Port = pd.Endpoint.port(); - // if (packet.GetMessageType() == MessageType::Connect) { - // parseUDPConnect(packet); - // } else { - // parseMessageType(packet); - // } - //} + PlayerDefinition pd; + while (m_Unreliable.IsSocketAvailable()) { + // Packet will get real data in receive + Packet packet(MessageType::Invalid); + m_Unreliable.Receive(packet, pd); + m_Address = pd.Endpoint.address(); + m_Port = pd.Endpoint.port(); + if (packet.GetMessageType() == MessageType::Connect) { + parseUDPConnect(packet); + } else { + parseMessageType(packet); + } + } while (m_ServerlistRequest.IsSocketAvailable()) { Packet packet(MessageType::Invalid); @@ -69,9 +70,11 @@ void Server::Update() localArea.Endpoint = boost::asio::ip::udp::endpoint(); m_ServerlistRequest.Receive(packet, localArea); if (packet.GetMessageType() == MessageType::ServerlistRequest) { - packet.ReadPrimitive(); // Pop size - packet.ReadPrimitive(); // Pop MsgType - packet.ReadPrimitive(); // Pop packet ID + // Pop header + popNetworkSegmentOfHeader(packet); + packet.ReadPrimitive(); + packet.ReadPrimitive(); + int port = packet.ReadPrimitive(); std::string address = localArea.Endpoint.address().to_string(); parseServerlistRequest(boost::asio::ip::udp::endpoint(boost::asio::ip::address().from_string(address), port)); @@ -84,34 +87,52 @@ void Server::Update() } m_PlayersToDisconnect.clear(); - std::clock_t currentTime = std::clock(); // Send snapshot - if (snapshotInterval < (1000 * (currentTime - previousSnapshotMessage) / (double)CLOCKS_PER_SEC)) { + previousSnapshotMessage += dt; + if (snapshotInterval < previousSnapshotMessage) { sendSnapshot(); - previousSnapshotMessage = currentTime; + previousSnapshotMessage = 0; } // Send pings each - if (pingIntervalMs < (1000 * (currentTime - previousePingMessage) / (double)CLOCKS_PER_SEC)) { + previousPingMessage += dt; + if (pingInterval < previousPingMessage) { sendPing(); - previousePingMessage = currentTime; + previousPingMessage = 0; } // Time out logic - if (checkTimeOutInterval < (1000 * (currentTime - timOutTimer) / (double)CLOCKS_PER_SEC)) { + timeOutTimer += dt; + if (checkTimeOutInterval < timeOutTimer) { checkForTimeOuts(); - timOutTimer = currentTime; + timeOutTimer = 0; } m_EventBroker->Process(); if (isReadingData) { - Network::Update(); + Network::Update(dt); + } + + if (m_GameIsOver) { + auto pool = m_World->GetComponents("CapturePointGameMode"); + if (pool != nullptr && pool->size() > 0) { + // Take the first CapturePointGameMode component found. + ComponentWrapper& modeComponent = *pool->begin(); + // Decrease timer. + Field timer = modeComponent["ResetCountdown"]; + timer -= dt; + if (timer < 0) { + resetMap(); + } + } else { + resetMap(); + } } } void Server::parseMessageType(Packet& packet) { - // Pop packetSize which is used by TCP Client to + // Pop packetSize, sequenceNumber and packetsInSequence. // create a packet of the correct size - packet.ReadPrimitive(); + popNetworkSegmentOfHeader(packet); int messageType = packet.ReadPrimitive(); // Read what type off message was sent from server // Read packet ID @@ -162,10 +183,7 @@ void Server::reliableBroadcast(Packet& packet) void Server::unreliableBroadcast(Packet& packet) { - for (auto& kv : m_ConnectedPlayers) { - packet.ChangePacketID(kv.second.PacketID); - // m_Unreliable.Send(packet, kv.second); - } + m_Unreliable.SendToConnectedPlayers(packet, m_ConnectedPlayers); } // Send snapshot fields @@ -174,7 +192,14 @@ void Server::sendSnapshot() Packet packet(MessageType::Snapshot); addInputCommandsToPacket(packet); addPlayersToPacket(packet, EntityID_Invalid); - reliableBroadcast(packet); + unreliableBroadcast(packet); +} + +// Send snapshot fields +void Server::createWorldSnapshot(Packet& packet) +{ + addInputCommandsToPacket(packet); + addChildrenToPacket(packet, EntityID_Invalid); } void Server::addInputCommandsToPacket(Packet& packet) @@ -224,7 +249,7 @@ void Server::addPlayersToPacket(Packet & packet, EntityID entityID) for (auto& componentField : componentWrapper.Info.FieldsInOrder) { ComponentInfo::Field_t fieldInfo = componentWrapper.Info.Fields.at(componentField); if (fieldInfo.Type == "string") { - std::string& value = componentWrapper[componentField]; + const std::string& value = componentWrapper[componentField]; packet.WriteString(value); } else { packet.WriteData(componentWrapper.Data + fieldInfo.Offset, fieldInfo.Stride); @@ -268,7 +293,7 @@ void Server::addChildrenToPacket(Packet & packet, EntityID entityID) for (auto& componentField : componentWrapper.Info.FieldsInOrder) { ComponentInfo::Field_t fieldInfo = componentWrapper.Info.Fields.at(componentField); if (fieldInfo.Type == "string") { - std::string& value = componentWrapper[componentField]; + const std::string& value = componentWrapper[componentField]; packet.WriteString(value); } else { packet.WriteData(componentWrapper.Data + fieldInfo.Offset, fieldInfo.Stride); @@ -299,8 +324,6 @@ void Server::sendPing() reliableBroadcast(packet); } - - void Server::checkForTimeOuts() { double startPing = 1000 * m_StartPingTime @@ -317,38 +340,35 @@ void Server::checkForTimeOuts() } } } - for (size_t i = 0; i < playersToRemove.size(); i++) { + for (int i = playersToRemove.size() - 1; i >= 0; i--) { disconnect(playersToRemove.at(i)); } } -//void Server::parseUDPConnect(Packet & packet) -//{ -// // Pop size of message int -// packet.ReadPrimitive(); -// int messageType = packet.ReadPrimitive(); -// // Read packet ID -// m_PreviousPacketID = m_PacketID; // Set previous packet id -// m_PacketID = packet.ReadPrimitive(); //Read new packet id -// // parse player id and other stuff -// PlayerID playerID = packet.ReadPrimitive(); -// if (!EntityWrapper(m_World, playerID).Valid()) { -// -// } -// // Do something here? -// boost::asio::ip::udp::endpoint endpoint(m_Address, m_Port); -// m_ConnectedPlayers.at(playerID).Endpoint = endpoint; -// LOG_INFO("parseUDPConnect: Spectator \"%s\" connected on IP: %s", m_ConnectedPlayers.at(playerID).Name.c_str(), m_ConnectedPlayers.at(playerID).Endpoint.address().to_string().c_str()); -// // Send a message to the player that connected -// Packet connnectPacket(MessageType::Connect, m_ConnectedPlayers.at(playerID).PacketID); -// m_Unreliable.Send(connnectPacket); -// LOG_INFO("UDP Connect sent to client"); -//} +void Server::parseUDPConnect(Packet & packet) +{ + //Pop packetSize, sequenceNumber and packetsInSequence. + popNetworkSegmentOfHeader(packet); + int messageType = packet.ReadPrimitive(); + // Read packet ID + m_PreviousPacketID = m_PacketID; // Set previous packet id + m_PacketID = packet.ReadPrimitive(); //Read new packet id + // parse player id and other stuff + PlayerID playerID = packet.ReadPrimitive(); + boost::asio::ip::udp::endpoint endpoint(m_Address, m_Port); + m_ConnectedPlayers.at(playerID).Endpoint = endpoint; + LOG_INFO("parseUDPConnect: Spectator \"%s\" connected on IP: %s", m_ConnectedPlayers.at(playerID).Name.c_str(), m_ConnectedPlayers.at(playerID).Endpoint.address().to_string().c_str()); + // Send a message to the player that connected + Packet connnectPacket(MessageType::Connect, m_ConnectedPlayers.at(playerID).PacketID); + m_Unreliable.Send(connnectPacket); + LOG_INFO("UDP Connect sent to client"); +} void Server::parseTCPConnect(Packet & packet) { - // Pop size of message int - packet.ReadPrimitive(); + // Pop packetSize, sequenceNumber and packetsInSequence. + popNetworkSegmentOfHeader(packet); + int messageType = packet.ReadPrimitive(); // Read packet ID m_PreviousPacketID = m_PacketID; // Set previous packet id @@ -356,9 +376,9 @@ void Server::parseTCPConnect(Packet & packet) LOG_INFO("Parsing connections"); // Check if player is already connected - // Ska vara till lagd i TCPServer receive PlayerID playerID = getPlayerIDFromEndpoint(); if (playerID == -1) { + LOG_INFO("Server::parseTCPConnect: Not connected"); return; } // Create a new player @@ -381,11 +401,10 @@ void Server::parseTCPConnect(Packet & packet) Packet connnectPacket(MessageType::Connect, m_ConnectedPlayers.at(playerID).PacketID); // Write playerID to packet connnectPacket.WritePrimitive(playerID); - m_Reliable.Send(connnectPacket); + m_Reliable.Send(connnectPacket, m_ConnectedPlayers.at(playerID)); Packet firstSnapshot(MessageType::Snapshot); - addInputCommandsToPacket(firstSnapshot); - addChildrenToPacket(firstSnapshot, EntityID_Invalid); + createWorldSnapshot(firstSnapshot); m_Reliable.Send(firstSnapshot); // Send notification that a player has connected @@ -494,7 +513,7 @@ bool Server::OnEntityDeleted(const Events::EntityDeleted & e) { if (!e.Cascaded) { Packet packet = Packet(MessageType::EntityDeleted); - packet.WritePrimitive(e.DeletedEntity); + packet.WritePrimitive(e.DeletedEntity.ID); reliableBroadcast(packet); } return false; @@ -547,6 +566,13 @@ bool Server::OnPlayerDeath(const Events::PlayerDeath& e) return false; } +bool Server::OnWin(const Events::Win & e) +{ + // Postpone the gameover reset + m_GameIsOver = true; + return true; +} + void Server::parseClientPing() { LOG_INFO("%i: Parsing ping", m_PacketID); @@ -669,3 +695,19 @@ PlayerID Server::getPlayerIDFromEntityID(EntityID entityID) } return -1; } + +void Server::resetMap() +{ + m_GameIsOver = false; + Events::Reset reset; + m_EventBroker->Publish(reset); + Packet removeMap(MessageType::RemoveWorld); + reliableBroadcast(removeMap); + removeWorld(); + // Hardcoded for now. + auto entityFile = ResourceManager::Load("Schema/Entities/CP_Rocky2.xml"); + entityFile->MergeInto(m_World); + Packet newWorld(MessageType::Snapshot); + createWorldSnapshot(newWorld); + reliableBroadcast(newWorld); +} \ No newline at end of file diff --git a/src/Engine/Network/TCPClient.cpp b/src/Engine/Network/TCPClient.cpp index df9c159a..28da80ce 100644 --- a/src/Engine/Network/TCPClient.cpp +++ b/src/Engine/Network/TCPClient.cpp @@ -3,25 +3,14 @@ using namespace boost::asio::ip; TCPClient::TCPClient() -{ -} +{ } TCPClient::~TCPClient() -{ -} +{ } bool TCPClient::Connect(std::string playerName, std::string address, int port) { - if (m_Socket) { - if (m_IsConnected) { - Packet packet(MessageType::Connect, m_SendPacketID); - packet.WriteString(playerName); - Send(packet); - LOG_INFO("Connect message sent again!"); - } - return true; - } - else if (!m_IsConnected) { + if (!m_Socket) { boost::system::error_code error = boost::asio::error::host_not_found; m_Endpoint = tcp::endpoint(boost::asio::ip::address::from_string(address), port); m_Socket = std::unique_ptr(new tcp::socket(m_IOService)); @@ -36,9 +25,7 @@ bool TCPClient::Connect(std::string playerName, std::string address, int port) Send(packet); LOG_INFO("Connect message sent!"); return true; - } - // If error - else { + } else { // If error m_Socket->close(); m_Socket = nullptr; return false; @@ -47,14 +34,10 @@ bool TCPClient::Connect(std::string playerName, std::string address, int port) } void TCPClient::Disconnect() -{ - if (!m_IsConnected) { - return; - } +{ m_Socket->shutdown(boost::asio::ip::tcp::socket::shutdown_both); m_Socket->close(); m_Socket = nullptr; - m_IsConnected = false; } void TCPClient::Receive(Packet& packet) @@ -66,7 +49,7 @@ void TCPClient::Receive(Packet& packet) } size_t TCPClient::readBuffer() -{ +{ if (!m_Socket) { return 0; } @@ -92,7 +75,7 @@ size_t TCPClient::readBuffer() while (sizeOfPacket > bytesReceived) { // Read the rest of the message bytesReceived += m_Socket->read_some(boost - ::asio::buffer((void*)(m_ReadBuffer), sizeOfPacket - bytesReceived), + ::asio::buffer((void*)(m_ReadBuffer + bytesReceived), sizeOfPacket - bytesReceived), error); if (error) { //LOG_ERROR("receive: %s", error.message().c_str()); diff --git a/src/Engine/Network/TCPServer.cpp b/src/Engine/Network/TCPServer.cpp index ff35aa91..eddd679c 100644 --- a/src/Engine/Network/TCPServer.cpp +++ b/src/Engine/Network/TCPServer.cpp @@ -48,6 +48,7 @@ void TCPServer::Send(Packet & packet, PlayerDefinition & playerDefinition) { packet.UpdateSize(); try { + // Crashed once TCPSocket was NULL int bytesSent = playerDefinition.TCPSocket->send( boost::asio::buffer(packet.Data(), packet.Size()), 0); diff --git a/src/Engine/Network/UDPClient.cpp b/src/Engine/Network/UDPClient.cpp index 15682000..872d567c 100644 --- a/src/Engine/Network/UDPClient.cpp +++ b/src/Engine/Network/UDPClient.cpp @@ -1,14 +1,13 @@ #include "Network/UDPClient.h" +#include "boost/asio/basic_datagram_socket.hpp" using namespace boost::asio::ip; UDPClient::UDPClient() -{ -} +{ } UDPClient::~UDPClient() -{ -} +{ } bool UDPClient::Connect(std::string playerName, std::string address, int port) { @@ -18,22 +17,35 @@ bool UDPClient::Connect(std::string playerName, std::string address, int port) m_ReceiverEndpoint = udp::endpoint(boost::asio::ip::address().from_string(address), port); m_Socket = boost::shared_ptr(new boost::asio::ip::udp::socket(m_IOService)); m_Socket->open(boost::asio::ip::udp::v4()); + boost::asio::socket_base::receive_buffer_size option(m_SizeOfSocketBuffer); + m_Socket->set_option(option); return true; } void UDPClient::Disconnect() { + m_Socket->shutdown(boost::asio::ip::tcp::socket::shutdown_both); + m_Socket->close(); + m_Socket = nullptr; + m_LastReceivedSnapshotGroup = 0; + m_PacketSegmentMap.clear(); + PacketID m_SendPacketID = 0; } void UDPClient::Receive(Packet& packet) { int bytesRead = readBuffer(); - if (bytesRead > 0) { + if (bytesRead > 0) { packet.ReconstructFromData(m_ReadBuffer, bytesRead); } } +void UDPClient::ReceivePackets() +{ + readPartOfPacket(); +} + int UDPClient::readBuffer() { if (!m_Socket) { @@ -41,9 +53,9 @@ int UDPClient::readBuffer() } boost::system::error_code error; // Read size of packet - m_Socket->receive(boost + m_Socket->receive(boost ::asio::buffer((void*)m_ReadBuffer, sizeof(int)), - boost::asio::ip::udp::socket::message_peek, error); + boost::asio::ip::udp::socket::message_peek, error); int sizeOfPacket = 0; memcpy(&sizeOfPacket, m_ReadBuffer, sizeof(int)); if (sizeOfPacket > m_Socket->available()) { @@ -72,6 +84,72 @@ int UDPClient::readBuffer() return bytesReceived; } +void UDPClient::readPartOfPacket() +{ + if (!m_Socket) { + return; + } + boost::system::error_code error; + // Peek header + m_Socket->receive(boost + ::asio::buffer((void*)m_ReadBuffer, 5 * sizeof(int)), + boost::asio::ip::udp::socket::message_peek, error); + + int sizeOfPacket = 0; + memcpy(&sizeOfPacket, m_ReadBuffer, sizeof(int)); + if (sizeOfPacket == 0) { + return; + } + int packetGroup = *reinterpret_cast(m_ReadBuffer + sizeof(int)); + int packetGroupIndex = *reinterpret_cast(m_ReadBuffer + 2 * sizeof(int)); + int packetGroupSize = *reinterpret_cast(m_ReadBuffer + 3 * sizeof(int)); + //LOG_INFO("Packet group: %i. Group index: %i. Group size: %i. Packet size: %i.", packetGroup, packetGroupIndex, packetGroupSize, sizeOfPacket); + if (sizeOfPacket > m_Socket->available()) { + LOG_WARNING("UDPClient::readBuffer(): We haven't got the whole packet yet."); + // return; + } + // if the buffer is to small increase the size of it + boost::shared_ptr packetData(new char[sizeOfPacket]); + + // Read the message + size_t bytesReceived = m_Socket->receive_from(boost + ::asio::buffer((void*)(packetData.get()), + sizeOfPacket), + m_ReceiverEndpoint, 0, error); + if (error) { + LOG_ERROR("UDPClient::readPartOfPacket: %s", error.message().c_str()); + } + // Might want to do this earlier when i figure out a good way to + // remove data from network buffer. + if (hasReceivedPacket(packetGroup, packetGroupIndex)) { + return; + } + // If group exists + PacketMap::iterator it; + it = m_PacketSegmentMap.find(packetGroup); + if (it != m_PacketSegmentMap.end()) { + it->second.push_back(std::make_pair(packetGroupIndex, std::move(packetData))); + } else { // Create group and add element + m_PacketSegmentMap[packetGroup].push_back(std::make_pair(packetGroupIndex, std::move(packetData))); + } + return; +} + +bool UDPClient::hasReceivedPacket(int packetGroup, int groupIndex) +{ + PacketMap::iterator it; + it = m_PacketSegmentMap.find(packetGroup); + if (it != m_PacketSegmentMap.end()) { + const std::vector>>& loopPacketGroup = it->second; + for (size_t i = 0; i < loopPacketGroup.size(); i++) { + if (loopPacketGroup.at(i).first == groupIndex) { + return true; + } + } + } + return false; +} + void UDPClient::Send(Packet& packet) { packet.UpdateSize(); @@ -79,7 +157,7 @@ void UDPClient::Send(Packet& packet) packet.Data(), packet.Size()), m_ReceiverEndpoint, 0); -} +} void UDPClient::Broadcast(Packet& packet, int port) { @@ -95,8 +173,55 @@ void UDPClient::Broadcast(Packet& packet, int port) bool UDPClient::IsSocketAvailable() { - if (!m_Socket) { + if (!m_Socket) { return false; } return m_Socket->available(); -} \ No newline at end of file +} + +bool UDPClient::GetNextPacket(Packet & packet) +{ + // A duplicate packet should not be present in the vector! + // Soo we will assume that this is true and only look if size + // of vector is correct. + PacketMap::iterator it = m_PacketSegmentMap.begin(); + while (it != m_PacketSegmentMap.end()) { + // pair(Group index, packetData) + std::vector>>& currentVector = it->second; + Packet headerInfoPacket(currentVector.at(0).second.get(), packet.HeaderSize()); + int groupSize = headerInfoPacket.GroupSize(); + //LOG_INFO("UDPClient::GetNextPacket: Packet group : %i.Group index : %i.Group size : %i. lastReceivedSnapshotGroup: %i. MessageType(Ples 4): %i", headerInfoPacket.Group(), headerInfoPacket.GroupIndex(), groupSize, lastReceivedSnapshotGroup, headerInfoPacket.GetMessageType()); + //LOG_INFO("UDPClient::GetNextPacket: Packet group : %i.lastReceivedSnapshotGroup: %i. MessageType(Ples 4): %i", headerInfoPacket.Group(), lastReceivedSnapshotGroup, headerInfoPacket.GetMessageType()); + int mapSize = m_PacketSegmentMap.size(); + if (mapSize > 5) { + it = m_PacketSegmentMap.erase(it); + LOG_INFO("The map is increasing in size, size is %i", mapSize); + continue; + } + if (headerInfoPacket.GetMessageType() == MessageType::Snapshot && m_LastReceivedSnapshotGroup > headerInfoPacket.Group()) { + it = m_PacketSegmentMap.erase(it); + continue; + //LOG_INFO("Deleted old entry"); + } + if (currentVector.size() == groupSize) { + std::sort(currentVector.begin(), currentVector.end()); + // Add the first packet in vector + packet.ReconstructFromData(currentVector.at(0).second.get(), packet.HeaderSize()); + // Add the rest of the packets. + int sizeOfData = 0; + for (auto& packetSegment : currentVector) { + memcpy(&sizeOfData, packetSegment.second.get(), sizeof(int)); + packet.WriteData(packetSegment.second.get() + packet.HeaderSize(), sizeOfData - packet.HeaderSize()); + } + if (headerInfoPacket.GetMessageType() == MessageType::Snapshot) { + m_LastReceivedSnapshotGroup = packet.Group(); + } + // No need to get next it as we are returning. + m_PacketSegmentMap.erase(it); + return true; + } else { + ++it; + } + } + return false; +} diff --git a/src/Engine/Network/UDPServer.cpp b/src/Engine/Network/UDPServer.cpp index bfa27d69..e67a66c4 100644 --- a/src/Engine/Network/UDPServer.cpp +++ b/src/Engine/Network/UDPServer.cpp @@ -12,34 +12,110 @@ UDPServer::UDPServer(int port) UDPServer::~UDPServer() { } - -void UDPServer::Send(Packet& packet, PlayerDefinition & playerDefinition) +// TODO: Fix correct groups +void UDPServer::Send(Packet& packet, PlayerDefinition& playerDefinition) { packet.UpdateSize(); try { - int bytesSent = m_Socket->send_to( - boost::asio::buffer(packet.Data(), packet.Size()), - playerDefinition.Endpoint, - 0); - LOG_INFO("Size of packet is %i", bytesSent); + // Remove header from packet. + packet.ReadData(packet.HeaderSize()); + int totalBytesSent = 0; + int groupIndex = 1; + int groupSize = std::ceil((float)packet.Size() / MAXPACKETSIZE); + int packetDataSent = 0; + int packetDataSize = packet.Size() - packet.HeaderSize(); + + while (packetDataSize > packetDataSent) { + Packet splitPacket(packet.GetMessageType(), playerDefinition.PacketID); + splitPacket.ChangeGroupIndex(groupIndex); + splitPacket.ChangeGroupSize(groupSize); + splitPacket.ChangeGroup(playerDefinition.PacketGroup); + int amountToSend = packetDataSize - packetDataSent; + if (amountToSend > MAXPACKETSIZE) { + amountToSend = MAXPACKETSIZE; + } + splitPacket.WriteData(packet.ReadData(amountToSend), amountToSend); + splitPacket.UpdateSize(); + // Remove header size from bytes sent soo that we only + // count data in the packet + int bytesSent = 0; + bytesSent = m_Socket->send_to( + boost::asio::buffer(splitPacket.Data(), splitPacket.Size()), + playerDefinition.Endpoint, + 0); + packetDataSent += bytesSent - splitPacket.HeaderSize(); + totalBytesSent += bytesSent; + //LOG_INFO("bytesSent size %i, groupIndex: %i. Number of packets: %i", bytesSent, sequenceNumber, totalMessages); + ++groupIndex; + } + playerDefinition.PacketGroup++; } catch (const boost::system::system_error& e) { LOG_INFO(e.what()); // TODO: Clean up invalid endpoints out of m_ConnectedPlayers later playerDefinition.Endpoint = boost::asio::ip::udp::endpoint(); } - } + +void UDPServer::SendToConnectedPlayers(Packet& packet, std::map& playersTosendTo) +{ + packet.UpdateSize(); + // Remove header from packet. + packet.ReadData(packet.HeaderSize()); + int totalBytesSent = 0; + int groupIndex = 1; + int groupSize = std::ceil((float)packet.Size() / MAXPACKETSIZE); + int packetDataSent = 0; + int packetDataSize = packet.Size() - packet.HeaderSize(); + + while (packetDataSize > packetDataSent) { + Packet splitPacket(packet.GetMessageType()); + splitPacket.ChangeGroupIndex(groupIndex); + splitPacket.ChangeGroupSize(groupSize); + int amountToSend = packetDataSize - packetDataSent; + if (amountToSend > MAXPACKETSIZE) { + amountToSend = MAXPACKETSIZE; + } + splitPacket.WriteData(packet.ReadData(amountToSend), amountToSend); + splitPacket.UpdateSize(); + // Remove header size from bytes sent soo that we only + // count data in the packet + int bytesSent = 0; + for (auto& kv : playersTosendTo) { + try { + splitPacket.ChangeGroup(kv.second.PacketGroup); + bytesSent = m_Socket->send_to( + boost::asio::buffer(splitPacket.Data(), splitPacket.Size()), + kv.second.Endpoint, + 0); + // LOG_INFO("bytesSent: %i", bytesSent); + } catch (const boost::system::system_error& e) { + LOG_INFO("UDPServer::SendToConnectedPlayers: Disconnected client. %s", e.what()); + // TODO: Clean up invalid endpoints out of m_ConnectedPlayers later + kv.second.Endpoint = boost::asio::ip::udp::endpoint(); + } + } + packetDataSent += splitPacket.Size() - splitPacket.HeaderSize(); + totalBytesSent += splitPacket.Size(); + + //LOG_INFO("bytesSent size %i, groupIndex: %i. Number of packets: %i", bytesSent, sequenceNumber, totalMessages); + ++groupIndex; + } + for (auto& kv : playersTosendTo) { + kv.second.PacketGroup++; + } +} + // Send back to endpoint of received packet void UDPServer::Send(Packet & packet) { packet.UpdateSize(); - size_t bytesSent = m_Socket->send_to( + size_t bytesSent = m_Socket->send_to( boost::asio::buffer( packet.Data(), packet.Size()), m_ReceiverEndpoint, 0); - LOG_INFO("Size of packet is %i", bytesSent); + //LOG_INFO("Size of packet is %i", bytesSent); } // Broadcasting respond specific logic @@ -52,7 +128,7 @@ void UDPServer::Send(Packet & packet, boost::asio::ip::udp::endpoint endpoint) packet.Size()), endpoint, 0); - LOG_INFO("Size of packet is %i", bytesSent); + //LOG_INFO("Size of packet is %i", bytesSent); } // Broadcasting @@ -64,7 +140,7 @@ void UDPServer::Broadcast(Packet & packet, int port) boost::asio::buffer( packet.Data(), packet.Size()), - boost::asio::ip::udp::endpoint(boost::asio::ip::address_v4().broadcast(),port), + boost::asio::ip::udp::endpoint(boost::asio::ip::address_v4().broadcast(), port), 0); m_Socket->set_option(boost::asio::socket_base::broadcast(false)); } @@ -91,7 +167,7 @@ int UDPServer::readBuffer() int addasdasd = m_Socket->available(); boost::system::error_code error; // Read size of packet - m_Socket->receive_from(boost + m_Socket->receive_from(boost ::asio::buffer((void*)m_ReadBuffer, sizeof(int)), m_ReceiverEndpoint, boost::asio::ip::udp::socket::message_peek, error); unsigned int sizeOfPacket = 0; @@ -114,13 +190,13 @@ int UDPServer::readBuffer() ::asio::buffer((void*)(m_ReadBuffer), sizeOfPacket), m_ReceiverEndpoint, 0, error); - if (error) { - //LOG_ERROR("receive: %s", error.message().c_str()); - } - if (sizeOfPacket > 1000000) - LOG_WARNING("The packets received are bigger than 1MB"); + if (error) { + //LOG_ERROR("receive: %s", error.message().c_str()); + } + if (sizeOfPacket > 1000000) + LOG_WARNING("The packets received are bigger than 1MB"); - return bytesReceived; + return bytesReceived; } void UDPServer::AcceptNewConnections(int& nextPlayerID, std::map& connectedPlayers) diff --git a/src/Engine/Rendering/AnimationSystem.cpp b/src/Engine/Rendering/AnimationSystem.cpp index 3895dc4a..895cbc28 100644 --- a/src/Engine/Rendering/AnimationSystem.cpp +++ b/src/Engine/Rendering/AnimationSystem.cpp @@ -73,7 +73,8 @@ void AnimationSystem::UpdateAnimations(double dt) Model* model; try { - model = ResourceManager::Load<::Model, true>(modelEntity["Model"]["Resource"]); + Field res = modelEntity["Model"]["Resource"]; + model = ResourceManager::Load<::Model, true>(res); } catch (const std::exception&) { continue; } @@ -89,23 +90,23 @@ void AnimationSystem::UpdateAnimations(double dt) continue; } - double animationSpeed = (double)animationC["Speed"]; + double animationSpeed = (const double&)animationC["Speed"]; - if((bool)animationC["Reverse"]) { + if((const bool&)animationC["Reverse"]) { animationSpeed *= -1; } - if ((bool)animationC["Play"]) { + if ((const bool&)animationC["Play"]) { - double nextTime = (double)animationC["Time"] + animationSpeed * dt; - if (!(bool)animationC["Loop"]) { + double nextTime = (Field)animationC["Time"] + animationSpeed * dt; + if (!(Field)animationC["Loop"]) { if (nextTime > animation->Duration) { nextTime = animation->Duration; - (bool&)animationC["Play"] = false; + (Field)animationC["Play"] = false; } else if (nextTime < 0) { nextTime = 0; - (bool&)animationC["Play"] = false; + (Field)animationC["Play"] = false; } } else { if (nextTime > animation->Duration) { @@ -119,7 +120,7 @@ void AnimationSystem::UpdateAnimations(double dt) } } } - (double&)animationC["Time"] = nextTime; + (Field)animationC["Time"] = nextTime; } } } @@ -219,15 +220,15 @@ bool AnimationSystem::OnAutoAnimationBlend(Events::AutoAnimationBlend& e) if (entity.Valid()) { if (entity.HasComponent("Animation")) { const Skeleton::Animation* animation = skeleton->GetAnimation(entity["Animation"]["AnimationName"]); - (bool&)entity["Animation"]["Reverse"] = e.Reverse; + (Field)entity["Animation"]["Reverse"] = e.Reverse; if (e.Restart) { if (animation != nullptr) { if (e.Restart) { if (e.Reverse) { - (double&)entity["Animation"]["Time"] = animation->Duration; + (Field)entity["Animation"]["Time"] = animation->Duration; } else { - (double&)entity["Animation"]["Time"] = 0.0; + (Field)entity["Animation"]["Time"] = 0.0; } } } @@ -266,15 +267,15 @@ bool AnimationSystem::OnAutoAnimationBlend(Events::AutoAnimationBlend& e) if (entity.Valid()) { if (entity.HasComponent("Animation")) { const Skeleton::Animation* animation = skeleton->GetAnimation(entity["Animation"]["AnimationName"]); - (bool&)entity["Animation"]["Reverse"] = e.Reverse; + entity["Animation"]["Reverse"] = e.Reverse; if (e.Restart) { if (animation != nullptr) { if (e.Restart) { if (e.Reverse) { - (double&)entity["Animation"]["Time"] = animation->Duration; + entity["Animation"]["Time"] = animation->Duration; } else { - (double&)entity["Animation"]["Time"] = 0.0; + entity["Animation"]["Time"] = 0.0; } } } @@ -289,7 +290,7 @@ bool AnimationSystem::OnAutoAnimationBlend(Events::AutoAnimationBlend& e) bool AnimationSystem::OnEntityDeleted(Events::EntityDeleted& e) { - EntityWrapper entity = EntityWrapper(m_World, e.DeletedEntity); + EntityWrapper entity = e.DeletedEntity; if (entity.HasComponent("Model")) { Model* model; diff --git a/src/Engine/Rendering/BlendTree.cpp b/src/Engine/Rendering/BlendTree.cpp index ca22cd74..f1ca25c7 100644 --- a/src/Engine/Rendering/BlendTree.cpp +++ b/src/Engine/Rendering/BlendTree.cpp @@ -13,7 +13,7 @@ BlendTree::BlendTree(EntityWrapper ModelEntity, Skeleton* skeleton) m_Root = new Node(); m_Root->Entity = ModelEntity; m_Root->Name = ModelEntity.Name(); - m_Root->Pose = m_Skeleton->GetFrameBones(animation, (double)ModelEntity["Animation"]["Time"], (bool)ModelEntity["Animation"]["Additive"]); + m_Root->Pose = m_Skeleton->GetFrameBones(animation, (const double&)ModelEntity["Animation"]["Time"], (const bool&)ModelEntity["Animation"]["Additive"]); m_Root->Parent = nullptr; m_Root->Type = NodeType::Animation; @@ -23,9 +23,9 @@ BlendTree::BlendTree(EntityWrapper ModelEntity, Skeleton* skeleton) m_Root->Name = ModelEntity.Name(); m_Root->Parent = nullptr; m_Root->Type = NodeType::Blend; - m_Root->Weight = (double)ModelEntity["Blend"]["Weight"]; - m_Root->SubTreeRoot = (bool)ModelEntity["Blend"]["SubTreeRoot"]; - (double&)ModelEntity["Blend"]["Weight"] = glm::clamp((double)ModelEntity["Blend"]["Weight"], 0.0, 1.0); + m_Root->Weight = (const double&)ModelEntity["Blend"]["Weight"]; + m_Root->SubTreeRoot = (const bool&)ModelEntity["Blend"]["SubTreeRoot"]; + ModelEntity["Blend"]["Weight"] = glm::clamp((const double&)ModelEntity["Blend"]["Weight"], 0.0, 1.0); m_Root->Child[0] = FillTreeByName(m_Root, (std::string)ModelEntity["Blend"]["Pose1"], ModelEntity); m_Root->Child[1] = FillTreeByName(m_Root, (std::string)ModelEntity["Blend"]["Pose2"], ModelEntity); @@ -117,7 +117,7 @@ BlendTree::Node* BlendTree::FillTreeByName(Node* parentNode, std::string name, E Node* node = new Node(); node->Entity = childEntity; node->Name = childEntity.Name(); - node->Pose = m_Skeleton->GetFrameBones(animation, (double)childEntity["Animation"]["Time"], (bool)childEntity["Animation"]["Additive"]); + node->Pose = m_Skeleton->GetFrameBones(animation, (const double&)childEntity["Animation"]["Time"], (const bool&)childEntity["Animation"]["Additive"]); node->Parent = parentNode; node->Type = NodeType::Animation; return node; @@ -128,9 +128,9 @@ BlendTree::Node* BlendTree::FillTreeByName(Node* parentNode, std::string name, E node->Name = childEntity.Name(); node->Parent = parentNode; node->Type = NodeType::Blend; - (double&)childEntity["Blend"]["Weight"] = glm::clamp((double)childEntity["Blend"]["Weight"], 0.0, 1.0); - node->Weight = (double)childEntity["Blend"]["Weight"]; - node->SubTreeRoot = (bool)childEntity["Blend"]["SubTreeRoot"]; + childEntity["Blend"]["Weight"] = glm::clamp((const double&)childEntity["Blend"]["Weight"], 0.0, 1.0); + node->Weight = (const double&)childEntity["Blend"]["Weight"]; + node->SubTreeRoot = (const bool&)childEntity["Blend"]["SubTreeRoot"]; //if (node->Weight < 1.f && node->Weight > 0.f) { node->Child[0] = FillTreeByName(node, (std::string)childEntity["Blend"]["Pose1"], childEntity); node->Child[1] = FillTreeByName(node, (std::string)childEntity["Blend"]["Pose2"], childEntity); @@ -210,7 +210,7 @@ BlendTree::AutoBlendInfo BlendTree::AutoBlendStep(AutoBlendInfo blendInfo) if (entity.Valid()) { if (entity.HasComponent("Blend")) { - (double&)entity["Blend"]["Weight"] = blendInfo.Weight; + entity["Blend"]["Weight"] = blendInfo.Weight; } } } @@ -225,7 +225,7 @@ BlendTree::AutoBlendInfo BlendTree::AutoBlendStep(AutoBlendInfo blendInfo) if (entity.Valid()) { if (entity.HasComponent("Animation")) { - (bool&)entity["Animation"]["Play"] = true; + entity["Animation"]["Play"] = true; } } } @@ -259,7 +259,7 @@ BlendTree::AutoBlendInfo BlendTree::AutoBlendStep(AutoBlendInfo blendInfo) } double weight = ((goalWeight - startWeight) * blendInfo.progress) + startWeight; - (double&)currentNode->Entity["Blend"]["Weight"] = weight; + currentNode->Entity["Blend"]["Weight"] = weight; currentNode->Weight = weight; lastNode = currentNode; @@ -322,7 +322,7 @@ BlendTree::AutoBlendInfo BlendTree::AutoBlendStep(AutoBlendInfo blendInfo) } double weight = ((goalWeight - startWeight) * blendInfo.progress) + startWeight; - (double&)currentNode->Entity["Blend"]["Weight"] = weight; + currentNode->Entity["Blend"]["Weight"] = weight; currentNode->Weight = weight; lastNode = currentNode; diff --git a/src/Engine/Rendering/BlurHUD.cpp b/src/Engine/Rendering/BlurHUD.cpp index d9af3085..58a61fd4 100644 --- a/src/Engine/Rendering/BlurHUD.cpp +++ b/src/Engine/Rendering/BlurHUD.cpp @@ -119,6 +119,21 @@ GLuint BlurHUD::Draw(GLuint texture, RenderScene& scene) { GLERROR("DrawBloomPass::Draw: Pre"); + bool shouldRun = false; + for (auto& job : scene.Jobs.SpriteJob) { + auto spriteJob = std::dynamic_pointer_cast(job); + if (!spriteJob) { + continue; + } + if (!spriteJob->BlurBackground) { + continue; + } + shouldRun = true; + break; + } + if(!shouldRun) { + return m_BlackTexture->m_Texture; + } FillStencil(scene); RenderState state; @@ -142,9 +157,15 @@ GLuint BlurHUD::Draw(GLuint texture, RenderScene& scene) glViewport(0, 0, m_Renderer->GetViewportSize().Width/m_BlurQuality, m_Renderer->GetViewportSize().Height/m_BlurQuality); glScissor(0, 0, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); + m_GaussianProgram_vert->Bind(); + glUniform1i(glGetUniformLocation(shaderHandle_vert, "Lod"), 0); m_GaussianProgram_horiz->Bind(); + glUniform1i(glGetUniformLocation(shaderHandle_horiz, "Lod"), 0); + + glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texture); + glBindVertexArray(m_ScreenQuad->VAO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ScreenQuad->ElementBuffer); glDrawElementsBaseVertex(GL_TRIANGLES, m_ScreenQuad->MaterialGroups()[0].material->EndIndex - m_ScreenQuad->MaterialGroups()[0].material->StartIndex +1 @@ -158,8 +179,6 @@ GLuint BlurHUD::Draw(GLuint texture, RenderScene& scene) glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, m_GaussianTexture_horiz); - glBindVertexArray(m_ScreenQuad->VAO); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ScreenQuad->ElementBuffer); glDrawElementsBaseVertex(GL_TRIANGLES, m_ScreenQuad->MaterialGroups()[0].material->EndIndex - m_ScreenQuad->MaterialGroups()[0].material->StartIndex +1 , GL_UNSIGNED_INT, 0, m_ScreenQuad->MaterialGroups()[0].material->StartIndex); //horizontal pass @@ -170,8 +189,6 @@ GLuint BlurHUD::Draw(GLuint texture, RenderScene& scene) glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, m_GaussianTexture_vert); - glBindVertexArray(m_ScreenQuad->VAO); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ScreenQuad->ElementBuffer); glDrawElementsBaseVertex(GL_TRIANGLES, m_ScreenQuad->MaterialGroups()[0].material->EndIndex - m_ScreenQuad->MaterialGroups()[0].material->StartIndex +1 , GL_UNSIGNED_INT, 0, m_ScreenQuad->MaterialGroups()[0].material->StartIndex); m_GaussianFrameBuffer_horiz.Unbind(); @@ -184,8 +201,7 @@ GLuint BlurHUD::Draw(GLuint texture, RenderScene& scene) glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, m_GaussianTexture_horiz); - glBindVertexArray(m_ScreenQuad->VAO); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ScreenQuad->ElementBuffer); + glDrawElementsBaseVertex(GL_TRIANGLES, m_ScreenQuad->MaterialGroups()[0].material->EndIndex - m_ScreenQuad->MaterialGroups()[0].material->StartIndex +1 , GL_UNSIGNED_INT, 0, m_ScreenQuad->MaterialGroups()[0].material->StartIndex); @@ -200,10 +216,7 @@ GLuint BlurHUD::Draw(GLuint texture, RenderScene& scene) void BlurHUD::OnWindowResize() { - CommonFunctions::GenerateTexture(&m_GaussianTexture_vert, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewportSize().Width/m_BlurQuality, m_Renderer->GetViewportSize().Height/m_BlurQuality), GL_RGB16F, GL_RGB, GL_FLOAT); - m_GaussianFrameBuffer_vert.Generate(); - CommonFunctions::GenerateTexture(&m_GaussianTexture_horiz, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewportSize().Width/m_BlurQuality, m_Renderer->GetViewportSize().Height/m_BlurQuality), GL_RGB16F, GL_RGB, GL_FLOAT); - m_GaussianFrameBuffer_horiz.Generate(); + InitializeBuffers(); } void BlurHUD::FillStencil(RenderScene& scene) @@ -226,9 +239,8 @@ void BlurHUD::FillStencil(RenderScene& scene) m_FillDepthStencilProgram->Bind(); GLuint shaderHandle = m_FillDepthStencilProgram->GetHandle(); + glm::mat4 VP = scene.Camera->ProjectionMatrix() * scene.Camera->ViewMatrix(); - glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); - glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); for (auto& job : scene.Jobs.SpriteJob) { auto spriteJob = std::dynamic_pointer_cast(job); @@ -238,7 +250,10 @@ void BlurHUD::FillStencil(RenderScene& scene) if (!spriteJob->BlurBackground) { continue; } - glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(spriteJob->Matrix)); + + glm::mat4 MVP = VP * spriteJob->Matrix; + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "PVM"), 1, GL_FALSE, glm::value_ptr(MVP)); + glBindVertexArray(spriteJob->Model->VAO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, spriteJob->Model->ElementBuffer); @@ -254,7 +269,8 @@ void BlurHUD::FillStencil(RenderScene& scene) if(!spriteJob->BlurBackground) { continue; } - glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(spriteJob->Matrix)); + glm::mat4 MVP = VP * spriteJob->Matrix; + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "PVM"), 1, GL_FALSE, glm::value_ptr(MVP)); glBindVertexArray(spriteJob->Model->VAO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, spriteJob->Model->ElementBuffer); diff --git a/src/Engine/Rendering/BoneAttachmentSystem.cpp b/src/Engine/Rendering/BoneAttachmentSystem.cpp index c1cdf0f2..440bb65c 100644 --- a/src/Engine/Rendering/BoneAttachmentSystem.cpp +++ b/src/Engine/Rendering/BoneAttachmentSystem.cpp @@ -55,13 +55,13 @@ void BoneAttachmentSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapp glm::vec3 angles = glm::eulerAngles(rotation); if ((bool)entity["BoneAttachment"]["InheritPosition"]) { - (glm::vec3&)entity["Transform"]["Position"] = translation + (glm::vec3)entity["BoneAttachment"]["PositionOffset"]; + entity["Transform"]["Position"] = translation + (glm::vec3)entity["BoneAttachment"]["PositionOffset"]; } if ((bool)entity["BoneAttachment"]["InheritOrientation"]) { - (glm::vec3&)entity["Transform"]["Orientation"] = angles; + entity["Transform"]["Orientation"] = angles; } if ((bool)entity["BoneAttachment"]["InheritScale"]) { - (glm::vec3&)entity["Transform"]["Scale"] = scale * (glm::vec3)entity["BoneAttachment"]["ScaleOffset"]; + entity["Transform"]["Scale"] = scale * (glm::vec3)entity["BoneAttachment"]["ScaleOffset"]; } } diff --git a/src/Engine/Rendering/CubeMapPass.cpp b/src/Engine/Rendering/CubeMapPass.cpp index e2a55b74..8d133579 100644 --- a/src/Engine/Rendering/CubeMapPass.cpp +++ b/src/Engine/Rendering/CubeMapPass.cpp @@ -6,18 +6,16 @@ CubeMapPass::CubeMapPass(IRenderer* renderer) LoadTextures("Nevada"); } -void CubeMapPass::LoadTextures(std::string input) +void CubeMapPass::LoadTextures(std::string cubemapName) { - if (m_PreviusCubeMapTexture != input) { + if (m_PreviusCubeMapTexture != cubemapName) { m_CubeMapTextures.clear(); for (int i = 0; i < 6; i++) { - std::string str; - str = "Textures/Test/CubeMap/" + input + "/CubeMapTest0" + std::to_string(i) + ".png"; - Texture* img = ResourceManager::Load(str); - m_CubeMapTextures.push_back(img); + std::string path = "Textures/Test/CubeMap/" + cubemapName + "/CubeMapTest0" + std::to_string(i) + ".png"; + m_CubeMapTextures.push_back(path); } GenerateCubeMapTexture(); - m_PreviusCubeMapTexture = input; + m_PreviusCubeMapTexture = cubemapName; } } @@ -29,7 +27,9 @@ void CubeMapPass::GenerateCubeMapTexture() glBindTexture(GL_TEXTURE_CUBE_MAP, m_CubeMapTexture); for (int i = 0; i < 6; i++) { - glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA32F, m_CubeMapTextures[0]->Width, m_CubeMapTextures[0]->Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_CubeMapTextures[i]->Data); + PNG* img = ResourceManager::Load(m_CubeMapTextures[i]); + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA32F, img->Width, img->Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, img->Data); + ResourceManager::Release("PNG", m_CubeMapTextures[i]); } glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); diff --git a/src/Engine/Rendering/DrawBloomPass.cpp b/src/Engine/Rendering/DrawBloomPass.cpp index f70f25c1..e0c6af66 100644 --- a/src/Engine/Rendering/DrawBloomPass.cpp +++ b/src/Engine/Rendering/DrawBloomPass.cpp @@ -151,18 +151,7 @@ void DrawBloomPass::OnWindowResize() if (m_Quality == 0) { return; } - CommonFunctions::GenerateMipMapTexture( - &m_GaussianTexture_vert, GL_CLAMP_TO_BORDER, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height) - , GL_RGB, GL_FLOAT, m_BloomLod); - CommonFunctions::GenerateMipMapTexture( - &m_GaussianTexture_horiz, GL_CLAMP_TO_BORDER, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height) - , GL_RGB, GL_FLOAT, m_BloomLod); - for (int i = 0; i < m_BloomLod; i++) { - m_GaussianFrameBuffer_vert[i].Generate(); - m_GaussianFrameBuffer_horiz[i].Generate(); - - } - + InitializeBuffers(); } void DrawBloomPass::GaussianLodPass(GLuint mipMap, GLuint texture) diff --git a/src/Engine/Rendering/DrawFinalPass.cpp b/src/Engine/Rendering/DrawFinalPass.cpp index a538f818..df1b931c 100644 --- a/src/Engine/Rendering/DrawFinalPass.cpp +++ b/src/Engine/Rendering/DrawFinalPass.cpp @@ -1333,7 +1333,12 @@ void DrawFinalPass::BindExplosionUniforms(GLuint shaderHandle, std::shared_ptrExplosionOrigin)); GLERROR("Bind 6 uniform"); - glUniform1f(glGetUniformLocation(shaderHandle, "TimeSinceDeath"), job->TimeSinceDeath); + if (job->Reverse == false) { + glUniform1f(glGetUniformLocation(shaderHandle, "TimeSinceDeath"), job->TimeSinceDeath); + } + else { + glUniform1f(glGetUniformLocation(shaderHandle, "TimeSinceDeath"), (job->ExplosionDuration - job->TimeSinceDeath)); + } GLERROR("Bind 7 uniform"); glUniform1f(glGetUniformLocation(shaderHandle, "ExplosionDuration"), job->ExplosionDuration); GLERROR("Bind 8 uniform"); @@ -1351,6 +1356,10 @@ void DrawFinalPass::BindExplosionUniforms(GLuint shaderHandle, std::shared_ptrExponentialAccelaration); GLERROR("Bind 15 uniform"); + glUniform1i(glGetUniformLocation(shaderHandle, "Reverse"), job->Reverse); + GLERROR("Bind 15-2 uniform"); + glUniform1f(glGetUniformLocation(shaderHandle, "ColorDistanceScalar"), job->ColorDistanceScalar); + GLERROR("Bind 15-3 uniform"); glUniform4fv(glGetUniformLocation(shaderHandle, "Color"), 1, glm::value_ptr(job->Color)); GLERROR("Bind 16 uniform"); diff --git a/src/Engine/Rendering/DrawFinalPassState.cpp b/src/Engine/Rendering/DrawFinalPassState.cpp index 5c238985..811d9d84 100644 --- a/src/Engine/Rendering/DrawFinalPassState.cpp +++ b/src/Engine/Rendering/DrawFinalPassState.cpp @@ -10,6 +10,8 @@ DrawFinalPassState::DrawFinalPassState(GLuint frameBuffer) Enable(GL_DEPTH_TEST); DepthMask(GL_TRUE); Enable(GL_CULL_FACE); + Enable(GL_ALPHA_TEST); + AlphaFunc(GL_GEQUAL, 0.05f); // Enable(GL_STENCIL_TEST); // StencilFunc(GL_NOTEQUAL, 1, 0xFF); // StencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); diff --git a/src/Engine/Rendering/RawModelCustom.cpp b/src/Engine/Rendering/RawModelCustom.cpp index dd6a96de..94a824f0 100644 --- a/src/Engine/Rendering/RawModelCustom.cpp +++ b/src/Engine/Rendering/RawModelCustom.cpp @@ -148,14 +148,29 @@ void RawModelCustom::ReadMaterialSingle(std::size_t& offset, char* fileData, con case MaterialType::Basic: newMaterialProperty.material = new MaterialBasic(); ReadMaterialBasic(newMaterialProperty.material, offset, fileData, fileByteSize); + if(hasSkin){ + newMaterialProperty.ShaderID = ResourceManager::Load("#ForwardPlusSkinnedProgram")->ResourceID; + } else { + newMaterialProperty.ShaderID = ResourceManager::Load("#ForwardPlusProgram")->ResourceID; + } break; case MaterialType::SplatMapping: newMaterialProperty.material = new MaterialSplatMapping(); ReadMaterialSplatMapping(static_cast(newMaterialProperty.material), offset, fileData, fileByteSize); + if (hasSkin){ + newMaterialProperty.ShaderID = ResourceManager::Load("#ForwardPlusSplatMapSkinnedProgram")->ResourceID; + } else { + newMaterialProperty.ShaderID = ResourceManager::Load("#ForwardPlusSplatMapProgram")->ResourceID; + } break; case MaterialType::SingleTextures: newMaterialProperty.material = new MaterialSingleTextures(); ReadMaterialSingleTexture(static_cast(newMaterialProperty.material), offset, fileData, fileByteSize); + if (hasSkin){ + newMaterialProperty.ShaderID = ResourceManager::Load("#ForwardPlusSkinnedProgram")->ResourceID; + } else { + newMaterialProperty.ShaderID = ResourceManager::Load("#ForwardPlusProgram")->ResourceID; + } break; default: throw Resource::FailedLoadingException("Material contains an unknown MaterialType"); diff --git a/src/Engine/Rendering/RenderSystem.cpp b/src/Engine/Rendering/RenderSystem.cpp index fee539d4..0bc0eb93 100644 --- a/src/Engine/Rendering/RenderSystem.cpp +++ b/src/Engine/Rendering/RenderSystem.cpp @@ -71,7 +71,7 @@ void RenderSystem::fillSprites(std::list>& jobs, Worl float minScale = (float)(double)indicator["MinScale"]; bool hasTeam = indicator["VisibleForSingleTeamOnly"]; isIndicator = true; - glm::vec3 pos = Transform::AbsolutePosition(entity); + glm::vec3 pos = TransformSystem::AbsolutePosition(entity); EntityWrapper entityTeam; @@ -138,7 +138,7 @@ void RenderSystem::fillSprites(std::list>& jobs, Worl modelMatrix[3][2] = pos.z; modelMatrix[3][3] = 1.0f; - glm::mat4 tranformationMatrix = modelMatrix * glm::scale(Transform::AbsoluteScale(entity)); + glm::mat4 tranformationMatrix = modelMatrix * glm::scale(TransformSystem::AbsoluteScale(entity)); glm::vec4 tmp = tranformationMatrix * glm::vec4(glm::vec3(0.5, 0.5, 0), 1.0f); glm::vec2 projectedTopRight = m_Camera->WorldToScreen(glm::vec3(tmp), m_Renderer->GetViewportSize()); tmp = tranformationMatrix * glm::vec4(glm::vec3(-0.5, -0.5, 0), 1.0f); @@ -151,7 +151,7 @@ void RenderSystem::fillSprites(std::list>& jobs, Worl modelMatrix = tranformationMatrix; } else { - modelMatrix = Transform::ModelMatrix(entity.ID, world); + modelMatrix = TransformSystem::ModelMatrix(entity.ID, world); } @@ -184,7 +184,7 @@ bool RenderSystem::isEntityVisible(EntityWrapper& entity) } // Hide things parented to local player if they have the HiddenFromLocalPlayer component - bool outOfBodyExperience = ResourceManager::Load("Config.ini")->Get("Debug.OutOfBodyExperience", false); + bool outOfBodyExperience = false; // ResourceManager::Load("Config.ini")->Get("Debug.OutOfBodyExperience", false); if ( (entity.HasComponent("HiddenForLocalPlayer") || entity.FirstParentWithComponent("HiddenForLocalPlayer").Valid()) && (entity == m_LocalPlayer || entity.IsChildOf(m_LocalPlayer)) @@ -250,7 +250,7 @@ void RenderSystem::fillModels(RenderScene::Queues &Jobs) bool isShielded = m_World->HasComponent(cModel.EntityID, "Shielded") || m_World->HasComponent(cModel.EntityID, "Player"); - glm::mat4 modelMatrix = Transform::ModelMatrix(cModel.EntityID, m_World); + glm::mat4 modelMatrix = TransformSystem::ModelMatrix(cModel.EntityID, m_World); //Loop through all materialgroups of a model for (auto matGroup : model->MaterialGroups()) { //If the model has an explosioneffect component, we will add an explosioneffectjob @@ -422,7 +422,7 @@ void RenderSystem::fillText(std::list>& jobs, World* } } - glm::mat4 modelMatrix = Transform::ModelMatrix(textComponent.EntityID, world); + glm::mat4 modelMatrix = TransformSystem::ModelMatrix(textComponent.EntityID, world); std::shared_ptr textJob = std::shared_ptr(new TextJob(modelMatrix, font, textComponent)); jobs.push_back(textJob); @@ -440,8 +440,8 @@ void RenderSystem::Update(double dt) // Update the current camera used for rendering if (m_CurrentCamera.Valid()) { - m_Camera->SetPosition(Transform::AbsolutePosition(m_CurrentCamera)); - m_Camera->SetOrientation(Transform::AbsoluteOrientation(m_CurrentCamera)); + m_Camera->SetPosition(TransformSystem::AbsolutePosition(m_CurrentCamera)); + m_Camera->SetOrientation(TransformSystem::AbsoluteOrientation(m_CurrentCamera)); } RenderScene scene; diff --git a/src/Engine/Rendering/Renderer.cpp b/src/Engine/Rendering/Renderer.cpp index eecb5a7a..63d7dfaf 100644 --- a/src/Engine/Rendering/Renderer.cpp +++ b/src/Engine/Rendering/Renderer.cpp @@ -140,6 +140,7 @@ void Renderer::updateFramebufferSize() m_LightCullingPass->OnWindowResize(); m_DrawBloomPass->OnWindowResize(); m_SSAOPass->OnWindowResize(); + m_BlurHUDPass->OnWindowResize(); e.NewResolution = m_ViewportSize; m_EventBroker->Publish(e); diff --git a/src/Engine/Rendering/TextPass.cpp b/src/Engine/Rendering/TextPass.cpp index 9583fcfd..cb21e01d 100644 --- a/src/Engine/Rendering/TextPass.cpp +++ b/src/Engine/Rendering/TextPass.cpp @@ -7,23 +7,23 @@ TextPass::TextPass() void TextPass::Initialize() { - glGenVertexArrays(1, &VAO); - glGenBuffers(1, &VBO); - glBindVertexArray(VAO); - glBindBuffer(GL_ARRAY_BUFFER, VBO); - glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 6 * 4, NULL, GL_DYNAMIC_DRAW); - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), 0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindVertexArray(0); + glGenVertexArrays(1, &VAO); + glGenBuffers(1, &VBO); + glBindVertexArray(VAO); + glBindBuffer(GL_ARRAY_BUFFER, VBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 6 * 4, NULL, GL_DYNAMIC_DRAW); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), 0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); - m_TextProgram = ResourceManager::Load("#TextProgram"); - m_TextProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/Text.vert.glsl"))); - m_TextProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/Text.frag.glsl"))); - m_TextProgram->Compile(); - m_TextProgram->BindFragDataLocation(0, "sceneColor"); - m_TextProgram->BindFragDataLocation(1, "bloomColor"); - m_TextProgram->Link(); + m_TextProgram = ResourceManager::Load("#TextProgram"); + m_TextProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/Text.vert.glsl"))); + m_TextProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/Text.frag.glsl"))); + m_TextProgram->Compile(); + m_TextProgram->BindFragDataLocation(0, "sceneColor"); + m_TextProgram->BindFragDataLocation(1, "bloomColor"); + m_TextProgram->Link(); } void TextPass::Update() @@ -33,81 +33,180 @@ void TextPass::Update() void TextPass::Draw(RenderScene& scene, FrameBuffer& frameBuffer) { - GLERROR("Derp1"); - TextPassState* state = new TextPassState(frameBuffer.GetHandle()); - for (auto &job : scene.Jobs.Text) { - auto textJob = std::dynamic_pointer_cast(job); - if (textJob) { + GLERROR("Derp1"); + TextPassState* state = new TextPassState(frameBuffer.GetHandle()); + for (auto &job : scene.Jobs.Text) { + auto textJob = std::dynamic_pointer_cast(job); + if (textJob) { - renderText(textJob->Content, textJob->Resource, textJob->Alignment, textJob->Color, textJob->Matrix, scene.Camera->ProjectionMatrix(), scene.Camera->ViewMatrix()); - } - } - GLERROR("Derp2"); - delete state; + renderText(textJob->Content, textJob->Resource, textJob->Alignment, textJob->Color, textJob->Matrix, scene.Camera->ProjectionMatrix(), scene.Camera->ViewMatrix()); + } + } + GLERROR("Derp2"); + delete state; +} + +std::string TextPass::parseColors(std::string text, std::map& colorChanges, glm::vec4 originalColor) +{ + std::string parsedString = text; + glm::vec4 newColor = originalColor; + bool colorChange = false; + + for (std::string::const_iterator c = parsedString.begin(); c != parsedString.end(); c++) { + if (*c == char(92)) { // Backlash + if ((c + 1) != parsedString.end()) { + if (*(c + 1) == char('C')) { // C for Color + if ((c + 7) != parsedString.end()) { + bool hasCorrectFormat = true; + + for (std::string::const_iterator colorC = c + 2; colorC != c + 8; colorC++) { + if (*colorC < '0' || *colorC > 'F') { + hasCorrectFormat = false; + break; + } + } + + if (hasCorrectFormat == true) { + colorChange = true; + + std::array hexToInt = { + std::stoi(std::string(c + 2, c + 4), 0, 16), + std::stoi(std::string(c + 4, c + 6), 0, 16), + std::stoi(std::string(c + 6, c + 8), 0, 16) + }; + + newColor = glm::vec4( + float(hexToInt[0]) / 255.f, + float(hexToInt[1]) / 255.f, + float(hexToInt[2]) / 255.f, + newColor.a); + + parsedString.erase(c, (c + 8)); + } + } + } + + if (*(c + 1) == char('A')) { // A for Alpha + if ((c + 3) != parsedString.end()) { + bool hasCorrectFormat = true; + + for (std::string::const_iterator colorC = c + 2; colorC != c + 4; colorC++) { + if (*colorC < '0' || *colorC > 'F') { + hasCorrectFormat = false; + break; + } + } + + if (hasCorrectFormat == true) { + colorChange = true; + + int hexToInt = std::stoi(std::string(c + 2, c + 4), 0, 16); + + newColor = glm::vec4( + newColor.r, + newColor.g, + newColor.b, + float(hexToInt) / 255.f); + + parsedString.erase(c, (c + 4)); + } + } + } + + if ((*(c + 1) >= '1' && *(c + 1) <= '9') || *(c + 1) == 'B' || *(c + 1) == 'E' || *(c + 1) == 'F') { // Icons + if (*(c + 1) >= '1' && *(c + 1) <= '9') { + parsedString.replace(c, (c + 2), 1, (*(c + 1) - 48)); + } + else { + parsedString.replace(c, (c + 2), 1, (*(c + 1) - 55)); + } + } + + if (colorChange) { + colorChanges[c - parsedString.begin()] = newColor; + } + } + } + } + + + + return parsedString; } void TextPass::renderText(std::string text, Font* font, TextJob::AlignmentEnum alignment, glm::vec4 color, glm::mat4 modelMatrix, glm::mat4 projectionMatrix, glm::mat4 viewMatrix) { - GLfloat penX = 0; - GLfloat penY = 0; - GLfloat scale = 1.0/font->FontSize; + GLfloat penX = 0; + GLfloat penY = 0; + GLfloat scale = 1.0 / font->FontSize; - GLfloat stringWidth = 0.f; + GLfloat stringWidth = 0.f; - for (std::string::const_iterator c = text.begin(); c != text.end(); c++) { - Font::Character ch = font->m_Characters[*c]; - stringWidth += (ch.Advance >> 6) * scale; - } + std::map colorChanges; + std::string parsedText = parseColors(text, colorChanges, color); - if(alignment == TextJob::AlignmentEnum::Center) { - penX = -stringWidth/2.f; - } else if (alignment == TextJob::AlignmentEnum::Right) { - penX = -stringWidth; - } else { - penX = 0; - } - - + for (std::string::const_iterator c = parsedText.begin(); c != parsedText.end(); c++) { + Font::Character ch = font->m_Characters[*c]; + stringWidth += (ch.Advance >> 6) * scale; + } - m_TextProgram->Bind(); - glUniform4fv(glGetUniformLocation(m_TextProgram->GetHandle(), "textColor"), 1, glm::value_ptr(color)); - glUniformMatrix4fv(glGetUniformLocation(m_TextProgram->GetHandle(), "M"), 1, GL_FALSE, glm::value_ptr(modelMatrix)); - glUniformMatrix4fv(glGetUniformLocation(m_TextProgram->GetHandle(), "V"), 1, GL_FALSE, glm::value_ptr(viewMatrix)); - glUniformMatrix4fv(glGetUniformLocation(m_TextProgram->GetHandle(), "P"), 1, GL_FALSE, glm::value_ptr(projectionMatrix)); - glActiveTexture(GL_TEXTURE0); - glBindVertexArray(VAO); + if (alignment == TextJob::AlignmentEnum::Center) { + penX = -stringWidth / 2.f; + } + else if (alignment == TextJob::AlignmentEnum::Right) { + penX = -stringWidth; + } + else { + penX = 0; + } - for (std::string::const_iterator c = text.begin(); c != text.end(); c++) { - Font::Character ch = font->m_Characters[*c]; - GLfloat xpos = penX + ch.Bearing.x * scale; - GLfloat ypos = penY - (ch.Size.y - ch.Bearing.y) * scale; + m_TextProgram->Bind(); + glUniform4fv(glGetUniformLocation(m_TextProgram->GetHandle(), "textColor"), 1, glm::value_ptr(color)); + glUniformMatrix4fv(glGetUniformLocation(m_TextProgram->GetHandle(), "M"), 1, GL_FALSE, glm::value_ptr(modelMatrix)); + glUniformMatrix4fv(glGetUniformLocation(m_TextProgram->GetHandle(), "V"), 1, GL_FALSE, glm::value_ptr(viewMatrix)); + glUniformMatrix4fv(glGetUniformLocation(m_TextProgram->GetHandle(), "P"), 1, GL_FALSE, glm::value_ptr(projectionMatrix)); + glActiveTexture(GL_TEXTURE0); + glBindVertexArray(VAO); - GLfloat w = ch.Size.x * scale; - GLfloat h = ch.Size.y * scale; - GLfloat vertices[6][4] = { - { xpos, ypos + h, 0.0, 0.0 }, - { xpos, ypos, 0.0, 1.0 }, - { xpos + w, ypos, 1.0, 1.0 }, + for (std::string::const_iterator c = parsedText.begin(); c != parsedText.end(); c++) { - { xpos, ypos + h, 0.0, 0.0 }, - { xpos + w, ypos, 1.0, 1.0 }, - { xpos + w, ypos + h, 1.0, 0.0 } - }; + auto it = colorChanges.find(c - parsedText.begin()); + if (it != colorChanges.end()) { + glUniform4fv(glGetUniformLocation(m_TextProgram->GetHandle(), "textColor"), 1, glm::value_ptr(it->second)); + } - glBindTexture(GL_TEXTURE_2D, ch.TextureID); + Font::Character ch = font->m_Characters[*c]; - glBindBuffer(GL_ARRAY_BUFFER, VBO); - glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glDrawArrays(GL_TRIANGLES, 0, 6); - penX += (ch.Advance >> 6) * scale; // Bitshift by 6 to get value in pixels (2^6 = 64) - } - glBindVertexArray(0); - glBindTexture(GL_TEXTURE_2D, 0); + GLfloat xpos = penX + ch.Bearing.x * scale; + GLfloat ypos = penY - (ch.Size.y - ch.Bearing.y) * scale; - GLERROR("Text rendering Error"); + GLfloat w = ch.Size.x * scale; + GLfloat h = ch.Size.y * scale; + + GLfloat vertices[6][4] = { + { xpos, ypos + h, 0.0, 0.0 }, + { xpos, ypos, 0.0, 1.0 }, + { xpos + w, ypos, 1.0, 1.0 }, + + { xpos, ypos + h, 0.0, 0.0 }, + { xpos + w, ypos, 1.0, 1.0 }, + { xpos + w, ypos + h, 1.0, 0.0 } + }; + + glBindTexture(GL_TEXTURE_2D, ch.TextureID); + + glBindBuffer(GL_ARRAY_BUFFER, VBO); + glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glDrawArrays(GL_TRIANGLES, 0, 6); + penX += (ch.Advance >> 6) * scale; // Bitshift by 6 to get value in pixels (2^6 = 64) + } + glBindVertexArray(0); + glBindTexture(GL_TEXTURE_2D, 0); + + GLERROR("Text rendering Error"); } diff --git a/src/Engine/Rendering/Texture.cpp b/src/Engine/Rendering/Texture.cpp index fdf387c2..5ad1cf39 100644 --- a/src/Engine/Rendering/Texture.cpp +++ b/src/Engine/Rendering/Texture.cpp @@ -19,7 +19,6 @@ Texture::Texture(std::string path) } // Construct the OpenGL texture - glGenTextures(1, &m_Texture); glBindTexture(GL_TEXTURE_2D, m_Texture); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); @@ -30,6 +29,8 @@ Texture::Texture(std::string path) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); GLERROR("Texture load"); + + ResourceManager::Release("PNG", path); } Texture::~Texture() diff --git a/src/Engine/Sound/SoundManager.cpp b/src/Engine/Sound/SoundManager.cpp index 8e103d5c..8267d9ff 100644 --- a/src/Engine/Sound/SoundManager.cpp +++ b/src/Engine/Sound/SoundManager.cpp @@ -7,6 +7,7 @@ SoundManager::SoundManager(World* world, EventBroker* eventBroker) m_World = world; m_BGMVolumeChannel = config->Get("Sound.BGMVolume", 1.f); m_SFXVolumeChannel = config->Get("Sound.SFXVolume", 1.f); + m_AnnouncerVolumeChannel = config->Get("Sound.AnnouncerVolume", 1.f); initOpenAL(); alSpeedOfSound(340.29f); @@ -16,16 +17,23 @@ SoundManager::SoundManager(World* world, EventBroker* eventBroker) EVENT_SUBSCRIBE_MEMBER(m_EPlaySoundOnEntity, &SoundManager::OnPlaySoundOnEntity); EVENT_SUBSCRIBE_MEMBER(m_EPlaySoundOnPosition, &SoundManager::OnPlaySoundOnPosition); EVENT_SUBSCRIBE_MEMBER(m_EPlayBackgroundMusic, &SoundManager::OnPlayBackgroundMusic); + EVENT_SUBSCRIBE_MEMBER(m_EPlayAnnouncerVoice, &SoundManager::OnPlayAnnouncerVoice); EVENT_SUBSCRIBE_MEMBER(m_EStopSound, &SoundManager::OnStopSound); EVENT_SUBSCRIBE_MEMBER(m_EPauseSound, &SoundManager::OnPauseSound); EVENT_SUBSCRIBE_MEMBER(m_EContinueSound, &SoundManager::OnContinueSound); EVENT_SUBSCRIBE_MEMBER(m_ESetBGMGain, &SoundManager::OnSetBGMGain); EVENT_SUBSCRIBE_MEMBER(m_ESetSFXGain, &SoundManager::OnSetSFXGain); + EVENT_SUBSCRIBE_MEMBER(m_ESetAnnouncerGain, &SoundManager::OnSetAnnouncerGain); EVENT_SUBSCRIBE_MEMBER(m_EPause, &SoundManager::OnPause); EVENT_SUBSCRIBE_MEMBER(m_EResume, &SoundManager::OnResume); EVENT_SUBSCRIBE_MEMBER(m_EComponentAttached, &SoundManager::OnComponentAttached); EVENT_SUBSCRIBE_MEMBER(m_EPlayerSpawned, &SoundManager::OnPlayerSpawned); EVENT_SUBSCRIBE_MEMBER(m_EPlayQueueOnEntity, &SoundManager::OnPlayQueueOnEntity); + EVENT_SUBSCRIBE_MEMBER(m_EChangeBGM, &SoundManager::OnChangeBGM); + + Events::ChangeBGM e; + e.FilePath = "Audio/bgm/MenuMusic.wav"; + m_EventBroker->Publish(e); } SoundManager::~SoundManager() @@ -56,13 +64,11 @@ void SoundManager::stopEmitters() void SoundManager::Update(double dt) { m_EventBroker->Process(); - deleteInactiveEmitters(); // can be optimized with "EEntityDeleted" + deleteInactiveEmitters(); updateEmitters(dt); updateListener(dt); - - // Editor debug info - ImGui::SliderFloat("BGM", &m_BGMVolumeChannel, 0.0f, 1.0f, "%.3f", 1.0f); - ImGui::SliderFloat("SFX", &m_SFXVolumeChannel, 0.0f, 1.0f, "%.3f", 1.0f); + if (m_DrumLoopHasBeenStarted) + matchBGMLoop(); } void SoundManager::deleteInactiveEmitters() @@ -113,18 +119,18 @@ void SoundManager::updateEmitters(double dt) if (!m_World->ValidEntity(m_World->GetParent(it->first))) { return; } - glm::vec3 nextPos = Transform::AbsolutePosition(m_World, it->first); + glm::vec3 nextPos = TransformSystem::AbsolutePosition(m_World, it->first); // Calculate velocity glm::vec3 velocity = glm::vec3(nextPos - previousPos) / (float)dt; setSourcePos(it->second->ALsource, nextPos); - setSourceVel(it->second->ALsource, velocity); + //setSourceVel(it->second->ALsource, glm::vec3(0)); auto emitter = m_World->GetComponent(it->first, "SoundEmitter"); setSoundProperties(it->second, &emitter); // Path changed - if (it->second->SoundResource->Path() != (std::string)emitter["FilePath"]) { - it->second->SoundResource = ResourceManager::Load((std::string)emitter["FilePath"]); + if (it->second->SoundResource->Path() != (const std::string&)emitter["FilePath"]) { + it->second->SoundResource = ResourceManager::Load((const std::string&)emitter["FilePath"]); if (it->second->SoundResource->Buffer() != 0) { playSound(it->second); } @@ -147,11 +153,11 @@ void SoundManager::updateListener(double dt) if (listener.IsChildOf(m_LocalPlayer) || listener == m_LocalPlayer) { glm::vec3 previousPos; alGetListener3f(AL_POSITION, &previousPos.x, &previousPos.y, &previousPos.z); // Get previous pos - glm::vec3 nextPos = Transform::AbsolutePosition(listener); // Get next (current) pos + glm::vec3 nextPos = TransformSystem::AbsolutePosition(listener); // Get next (current) pos glm::vec3 velocity = glm::vec3(nextPos - previousPos) / (float)dt; // Calculate velocity setListenerPos(nextPos); setListenerVel(velocity); - setListenerOri(glm::eulerAngles(Transform::AbsoluteOrientation(listener))); + setListenerOri(glm::eulerAngles(TransformSystem::AbsoluteOrientation(listener))); break; } } @@ -166,9 +172,34 @@ Source* SoundManager::createSource(std::string filePath) Source* source = new Source(); source->ALsource = alSource; source->SoundResource = ResourceManager::Load(filePath); + source->Duration = getDurationSeconds(source); return source; } +void SoundManager::matchBGMLoop() +{ + if (m_CurrentBGMCombo == nullptr) + return; + auto cCapturePoints = m_World->GetComponents("CapturePoint"); + for (auto it = cCapturePoints->begin(); it != cCapturePoints->end(); it++) { + float timeCaptured = (float)(double)(*it)["CaptureTimer"]; + float maxTimer = (float)(double)(*it)["CapturePointMaxTimer"]; + int capturePointIndex = (int)(*it)["CapturePointNumber"]; + + if (capturePointIndex == 0) { // Home for red team + if (timeCaptured < 0 && glm::abs(timeCaptured) < maxTimer) { + float gain = glm::abs(timeCaptured) / maxTimer; + setGain(m_CurrentBGMCombo, gain); + } + } else if (capturePointIndex == 4) { // Home for blue team + if (timeCaptured > 0 && timeCaptured < maxTimer) { + float gain = timeCaptured / maxTimer; + setGain(m_CurrentBGMCombo, gain); + } + } + } +} + void SoundManager::playSound(Source* source) { alSourcei(source->ALsource, AL_BUFFER, source->SoundResource->Buffer()); @@ -192,10 +223,12 @@ bool SoundManager::OnPlaySoundOnEntity(const Events::PlaySoundOnEntity & e) { Source* source = createSource(e.FilePath); source->Type = SoundType::SFX; - EntityID child = m_World->CreateEntity(e.EmitterID); + EntityID child = m_World->CreateEntity(e.Emitter.ID); m_World->AttachComponent(child, "Transform"); - m_World->AttachComponent(child, "SoundEmitter"); + auto cEmitter = m_World->AttachComponent(child, "SoundEmitter"); + (double&)(float)cEmitter["Gain"] = e.Gain; m_Sources[child] = source; + setGain(source, cEmitter["Gain"]); playSound(source); return false; } @@ -205,14 +238,14 @@ bool SoundManager::OnPlaySoundOnPosition(const Events::PlaySoundOnPosition & e) Source* source = createSource(e.FilePath); auto emitterID = m_World->CreateEntity(); auto transform = m_World->AttachComponent(emitterID, "Transform"); - (glm::vec3&)transform["Position"] = e.Position; + transform["Position"] = e.Position; auto emitter = m_World->AttachComponent(emitterID, "SoundEmitter"); - (float&)(double)emitter["Gain"] = e.Gain; - (float&)(double)emitter["Pitch"] = e.Pitch; - (bool&)emitter["Loop"] = e.Loop; - (float&)(double)emitter["MaxDistance"] = e.MaxDistance; - (float&)(double)emitter["RollOffFactor"] = e.RollOffFactor; - (float&)(double)emitter["ReferenceDistance"] = e.ReferenceDistance; + emitter["Gain"] = e.Gain; + emitter["Pitch"] = e.Pitch; + emitter["Loop"] = e.Loop; + emitter["MaxDistance"] = e.MaxDistance; + emitter["RollOffFactor"] = e.RollOffFactor; + emitter["ReferenceDistance"] = e.ReferenceDistance; source->Type = SoundType::SFX; m_Sources[emitterID] = source; playSound(source); @@ -242,12 +275,12 @@ bool SoundManager::OnPlayBackgroundMusic(const Events::PlayBackgroundMusic & e) auto listenerComponents = m_World->GetComponents("Listener"); for (auto it = listenerComponents->begin(); it != listenerComponents->end(); it++) { if ((*it).EntityID != m_LocalPlayer.ID) { - break; + continue; } auto emitterChild = m_World->CreateEntity((*it).EntityID); auto emitter = m_World->AttachComponent(emitterChild, "SoundEmitter"); - (bool&)emitter["Loop"] = true; - (std::string&)emitter["FilePath"] = e.FilePath; + emitter["Loop"] = true; + emitter["FilePath"] = e.FilePath; m_World->AttachComponent(emitterChild, "Transform"); Source* source = createSource(e.FilePath); source->Type = SoundType::BGM; @@ -258,6 +291,28 @@ bool SoundManager::OnPlayBackgroundMusic(const Events::PlayBackgroundMusic & e) return true; } + +bool SoundManager::OnPlayAnnouncerVoice(const Events::PlayAnonuncerVoice& e) +{ + auto listenerComponents = m_World->GetComponents("Listener"); + for (auto it = listenerComponents->begin(); it != listenerComponents->end(); it++) { + if ((*it).EntityID != m_LocalPlayer.ID) { + continue; + } + auto emitterChild = m_World->CreateEntity((*it).EntityID); + auto emitter = m_World->AttachComponent(emitterChild, "SoundEmitter"); + emitter["Loop"] = false; + emitter["FilePath"] = e.FilePath; + m_World->AttachComponent(emitterChild, "Transform"); + Source* source = createSource(e.FilePath); + source->Type = SoundType::Announcer; + setSoundProperties(source, &emitter); + m_Sources[emitterChild] = source; + playSound(source); + } + return true; +} + bool SoundManager::OnSetBGMGain(const Events::SetBGMGain & e) { m_BGMVolumeChannel = e.Gain; @@ -270,6 +325,13 @@ bool SoundManager::OnSetSFXGain(const Events::SetSFXGain & e) return true; } + +bool SoundManager::OnSetAnnouncerGain(const Events::SetAnnouncerGain& e) +{ + m_AnnouncerVolumeChannel = e.Gain; + return true; +} + bool SoundManager::OnComponentAttached(const Events::ComponentAttached & e) { if (e.Component.Info.Name == "SoundEmitter") { @@ -301,12 +363,20 @@ bool SoundManager::OnPlayerSpawned(const Events::PlayerSpawned &e) { if (e.PlayerID == -1) { // Local player m_LocalPlayer = e.Player; + if (m_DrumLoopHasBeenStarted) { + return true; + } + m_CurrentBGMCombo = createSource("Audio/BGM/Layer2.wav"); + m_CurrentBGMCombo->Type = SoundType::BGM; + alSourcei(m_CurrentBGMCombo->ALsource, AL_LOOPING, 1); + setGain(m_CurrentBGMCombo, 0); + playSound(m_CurrentBGMCombo); + m_DrumLoopHasBeenStarted = true; return true; } return false; } - bool SoundManager::OnPlayQueueOnEntity(const Events::PlayQueueOnEntity &e) { Source* source = createSource(*e.FilePaths.begin()); @@ -321,6 +391,18 @@ bool SoundManager::OnPlayQueueOnEntity(const Events::PlayQueueOnEntity &e) return true; } +bool SoundManager::OnChangeBGM(const Events::ChangeBGM &e) +{ + if (m_CurrentBGM != nullptr) { + stopSound(m_CurrentBGM); + } + m_CurrentBGM = createSource(e.FilePath); + m_CurrentBGM->Type = SoundType::BGM; + alSourcei(m_CurrentBGM->ALsource, AL_LOOPING, 1); + playSound(m_CurrentBGM); + return true; +} + ALenum SoundManager::getSourceState(ALuint source) { ALenum state; @@ -335,15 +417,49 @@ void SoundManager::setGain(Source * source, float gain) void SoundManager::setSoundProperties(Source* source, ComponentWrapper* soundComponent) { - float gain = (source->Type == SoundType::SFX) ? m_SFXVolumeChannel : m_BGMVolumeChannel; + float gain; + switch (source->Type) { + case SoundType::SFX: + gain = m_SFXVolumeChannel; + break; + case SoundType::BGM: + gain = m_BGMVolumeChannel; + break; + case SoundType::Announcer: + gain = m_AnnouncerVolumeChannel; + break; + default: + gain = 1.f; + break; + } alSourcef(source->ALsource, AL_GAIN, (float)(double)(*soundComponent)["Gain"] * gain); alSourcef(source->ALsource, AL_PITCH, (float)(double)(*soundComponent)["Pitch"]); - alSourcei(source->ALsource, AL_LOOPING, (int)(bool)(*soundComponent)["Loop"]); // YOLO + alSourcei(source->ALsource, AL_LOOPING, (int)(bool)(*soundComponent)["Loop"]); alSourcef(source->ALsource, AL_MAX_DISTANCE, (float)(double)(*soundComponent)["MaxDistance"]); alSourcef(source->ALsource, AL_ROLLOFF_FACTOR, (float)(double)(*soundComponent)["RollOffFactor"]); alSourcef(source->ALsource, AL_REFERENCE_DISTANCE, (float)(double)(*soundComponent)["ReferenceDistance"]); } +float SoundManager::getDurationSeconds(Source* source) +{ + ALuint buffer = source->SoundResource->Buffer(); + ALint sizeBytes, channels, bits, frequenzy; + alGetBufferi(buffer, AL_SIZE, &sizeBytes); + alGetBufferi(buffer, AL_CHANNELS, &channels); + alGetBufferi(buffer, AL_BITS, &bits); + alGetBufferi(buffer, AL_FREQUENCY, &frequenzy); + float sampleLength = (float)sizeBytes * 8 / (channels * bits); + return (sampleLength / frequenzy); +} + + +float SoundManager::getTimeOffsetSeconds(Source* source) +{ + float time; + alGetSourcef(source->ALsource, AL_SEC_OFFSET, &time); + return time; +} + void SoundManager::initOpenAL() { // Initialize OpenAL diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index a9d3f2d5..875e00ef 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -55,7 +55,7 @@ Game::Game(int argc, char* argv[]) ResourceManager::RegisterType("RawModel"); ResourceManager::RegisterType("Texture"); ResourceManager::RegisterType("TextureSprite"); - ResourceManager::RegisterType("Png"); + ResourceManager::RegisterType("PNG"); ResourceManager::RegisterType("ShaderProgram"); ResourceManager::RegisterType("EntityFile"); ResourceManager::RegisterType("EntityXMLFile"); @@ -129,6 +129,7 @@ Game::Game(int argc, char* argv[]) // All systems with orderlevel 0 will be updated first. unsigned int updateOrderLevel = 0; m_SystemPipeline->AddSystem(updateOrderLevel); + m_SystemPipeline->AddSystem(updateOrderLevel); ++updateOrderLevel; m_SystemPipeline->AddSystem(updateOrderLevel); m_SystemPipeline->AddSystem(updateOrderLevel); @@ -227,16 +228,18 @@ void Game::Tick() m_EventBroker->Swap(); PerformanceTimer::StartTimerAndStopPrevious("SoundManager"); - m_SoundManager->Update(dt); + if (m_IsClient) { + m_SoundManager->Update(dt); + } // Update network PerformanceTimer::StartTimerAndStopPrevious("Network"); m_EventBroker->Process(); if (m_NetworkClient != nullptr) { - m_NetworkClient->Update(); + m_NetworkClient->Update(dt); } if (m_NetworkServer != nullptr) { - m_NetworkServer->Update(); + m_NetworkServer->Update(dt); } //m_SoundManager->Update(dt); @@ -252,6 +255,13 @@ void Game::Tick() m_RenderFrame->Clear(); m_EventBroker->Swap(); m_EventBroker->Clear(); + + //LOG_DEBUG("Recalculated positions: %i", TransformSystem::RecalculatedPositions); + //LOG_DEBUG("Recalculated orientations: %i", TransformSystem::RecalculatedOrientations); + //LOG_DEBUG("Recalculated scales: %i", TransformSystem::RecalculatedScales); + TransformSystem::RecalculatedPositions = 0; + TransformSystem::RecalculatedOrientations = 0; + TransformSystem::RecalculatedScales = 0; } int Game::parseArgs(int argc, char* argv[]) diff --git a/src/Game/Systems/AmmoPickupSystem.cpp b/src/Game/Systems/AmmoPickupSystem.cpp index ea4561c6..34749d4e 100644 --- a/src/Game/Systems/AmmoPickupSystem.cpp +++ b/src/Game/Systems/AmmoPickupSystem.cpp @@ -72,11 +72,11 @@ void AmmoPickupSystem::SetPlayerAmmo(EntityWrapper &player, int ammoGain) { PlayerClass playerClass = DetermineClass(player); if (playerClass == PlayerClass::Defender) { - (int&)player["DefenderWeapon"]["Ammo"] = std::min((int)player["DefenderWeapon"]["Ammo"] + ammoGain, maxWeaponAmmo); + (Field)player["DefenderWeapon"]["Ammo"] = std::min((int)player["DefenderWeapon"]["Ammo"] + ammoGain, maxWeaponAmmo); } else if (playerClass == PlayerClass::Sniper) { - (int&)player["SniperWeapon"]["Ammo"] = std::min((int)player["SniperWeapon"]["Ammo"] + ammoGain, maxWeaponAmmo); + (Field)player["SniperWeapon"]["Ammo"] = std::min((int)player["SniperWeapon"]["Ammo"] + ammoGain, maxWeaponAmmo); } else if (playerClass == PlayerClass::Assault) { - (int&)player["AssaultWeapon"]["Ammo"] = std::min((int)player["AssaultWeapon"]["Ammo"] + ammoGain, maxWeaponAmmo); + (Field)player["AssaultWeapon"]["Ammo"] = std::min((int)player["AssaultWeapon"]["Ammo"] + ammoGain, maxWeaponAmmo); } else { //unknown class - ignore } diff --git a/src/Game/Systems/CapturePointArrowHUDSystem.cpp b/src/Game/Systems/CapturePointArrowHUDSystem.cpp index 9e327a43..e0b0297c 100644 --- a/src/Game/Systems/CapturePointArrowHUDSystem.cpp +++ b/src/Game/Systems/CapturePointArrowHUDSystem.cpp @@ -68,12 +68,12 @@ void CapturePointArrowHUDSystem::Update(double dt) if(currentOwner != redTeamEnum) { //This capturePoint is not owned by the red team and is therefor an eligible target for red team - glm::vec3 targetPos = Transform::AbsolutePosition(capturePointEntity); + glm::vec3 targetPos = TransformSystem::AbsolutePosition(capturePointEntity); redTargets.insert(std::pair(capturePointID, targetPos)); } if(currentOwner != blueTeamEnum) { //This capturePoint is not owned by the blue team and is therefor an eligible target for blue team - glm::vec3 targetPos = Transform::AbsolutePosition(capturePointEntity); + glm::vec3 targetPos = TransformSystem::AbsolutePosition(capturePointEntity); blueTargets.insert(std::pair(capturePointID, targetPos)); } @@ -155,16 +155,16 @@ void CapturePointArrowHUDSystem::Update(double dt) pos = m_BlueTeamCurrentTarget; } - glm::vec3& arrowOri = arrowEntity["Transform"]["Orientation"]; - glm::vec3 lookVector = glm::normalize(Transform::AbsolutePosition(arrowEntity) - pos); //Maybe should be player instead + Field arrowOri = arrowEntity["Transform"]["Orientation"]; + glm::vec3 lookVector = glm::normalize(TransformSystem::AbsolutePosition(arrowEntity) - pos); //Maybe should be player instead float pitch = std::asin(-lookVector.y); float yaw = std::atan2(lookVector.x, lookVector.z); - arrowOri.x = pitch; - arrowOri.y = yaw; - arrowOri.z = 0.f; + arrowOri.x(pitch); + arrowOri.y(yaw); + arrowOri.z(0.f); EntityWrapper parent = arrowEntity.Parent(); if (parent.Valid()) { - arrowOri -= Transform::AbsoluteOrientationEuler(parent); + arrowOri -= TransformSystem::AbsoluteOrientationEuler(parent); } } } @@ -175,8 +175,8 @@ bool CapturePointArrowHUDSystem::OnCapturePointCaptured(Events::Captured& e) return 0; } - m_RedTeamCurrentTarget = Transform::AbsolutePosition(e.RedTeamNextCapturePoint); - m_BlueTeamCurrentTarget = Transform::AbsolutePosition(e.BlueTeamNextCapturePoint); + m_RedTeamCurrentTarget = TransformSystem::AbsolutePosition(e.RedTeamNextCapturePoint); + m_BlueTeamCurrentTarget = TransformSystem::AbsolutePosition(e.BlueTeamNextCapturePoint); m_InitialtargetsSet = true; return 0; diff --git a/src/Game/Systems/CapturePointHUDSystem.cpp b/src/Game/Systems/CapturePointHUDSystem.cpp index b7376249..1c0b1f8e 100644 --- a/src/Game/Systems/CapturePointHUDSystem.cpp +++ b/src/Game/Systems/CapturePointHUDSystem.cpp @@ -49,7 +49,8 @@ void CapturePointHUDSystem::Update(double dt) double currentCaptureTime = (double)entityCP["CapturePoint"]["CaptureTimer"]; double progress = glm::abs(currentCaptureTime)/15.0; int currentCapturingTeam = currentCaptureTime > 0 ? redTeam : currentCaptureTime < 0 ? blueTeam : spectatorTeam; - ((glm::vec3&)entityHUD["Transform"]["Orientation"]).z = currentCapturingTeam == redTeam ? glm::half_pi()+glm::pi() : glm::half_pi(); + Field orientation = entityHUD["Transform"]["Orientation"]; + orientation.z(currentCapturingTeam == redTeam ? glm::half_pi()+glm::pi() : glm::half_pi()); glm::vec4 fillColor = currentCapturingTeam == redTeam ? glm::vec4(1, 0.f, 0, 0.7f) : glm::vec4(0, 0.2f, 1, 0.7f); entityHUD["Fill"]["Color"] = fillColor; entityHUD["Fill"]["Percentage"] = progress; diff --git a/src/Game/Systems/CapturePointSystem.cpp b/src/Game/Systems/CapturePointSystem.cpp index 4647d1b7..6739b814 100644 --- a/src/Game/Systems/CapturePointSystem.cpp +++ b/src/Game/Systems/CapturePointSystem.cpp @@ -10,8 +10,26 @@ CapturePointSystem::CapturePointSystem(SystemParams params) EVENT_SUBSCRIBE_MEMBER(m_ETriggerTouch, &CapturePointSystem::OnTriggerTouch); EVENT_SUBSCRIBE_MEMBER(m_ETriggerLeave, &CapturePointSystem::OnTriggerLeave); EVENT_SUBSCRIBE_MEMBER(m_ECaptured, &CapturePointSystem::OnCaptured); + EVENT_SUBSCRIBE_MEMBER(m_EReset, &CapturePointSystem::OnReset); + Init(); } +} +void CapturePointSystem::Init() +{ + m_WinnerWasFound = false; + //need to track these variables for the captureSystem to work as per design! + m_RedTeamNextPossibleCapturePoint = m_NotACapturePoint; + m_BlueTeamNextPossibleCapturePoint = m_NotACapturePoint; + m_RedTeamHomeCapturePoint = m_NotACapturePoint; + m_BlueTeamHomeCapturePoint = m_NotACapturePoint; + m_NumberOfCapturePoints = 0; + m_ResetTimers = false; + m_RecentlyCapturedNeedNextCapturePointNow = false; + m_CapturePointNumberToEntityMap.clear(); + //vectors which will keep track of enter/leave changes + m_ETriggerTouchVector.clear(); + m_ETriggerLeaveVector.clear(); } //here all capturepoints will update their component @@ -24,6 +42,9 @@ void CapturePointSystem::UpdateComponent(EntityWrapper& capturePointEntity, Comp if (m_WinnerWasFound) { return; } + if (!capturePointEntity.Valid()) { + return; + } const int capturePointNumber = cCapturePoint["CapturePointNumber"]; const bool hasTeamComponent = capturePointEntity.HasComponent("Team"); @@ -60,7 +81,7 @@ void CapturePointSystem::UpdateComponent(EntityWrapper& capturePointEntity, Comp } //if we havent received all capturepoints yet, just return - if (m_NumberOfCapturePoints == 0 || m_NumberOfCapturePoints != m_CapturePointNumberToEntityMap.size()) { + if (m_NumberOfCapturePoints == 0 || m_NumberOfCapturePoints > m_CapturePointNumberToEntityMap.size()) { m_CapturePointNumberToEntityMap.insert(std::make_pair(capturePointNumber, capturePointEntity)); return; } @@ -108,10 +129,10 @@ void CapturePointSystem::UpdateComponent(EntityWrapper& capturePointEntity, Comp //change what model is displaying (change all in case 2 capturepoints has been captured on the same frame) for (int i = 0; i < m_NumberOfCapturePoints; i++) { auto owner = (int)m_CapturePointNumberToEntityMap[i]["Team"]["Team"]; - if (m_CapturePointNumberToEntityMap[i].FirstChildByName("Red").ID != EntityID_Invalid) { - (bool&)m_CapturePointNumberToEntityMap[i].FirstChildByName("Red")["Model"]["Visible"] = owner == redTeam ? true : false; - (bool&)m_CapturePointNumberToEntityMap[i].FirstChildByName("Blue")["Model"]["Visible"] = owner == blueTeam ? true : false; - (bool&)m_CapturePointNumberToEntityMap[i].FirstChildByName("Spectator")["Model"]["Visible"] = owner == spectatorTeam ? true : false; + if (m_CapturePointNumberToEntityMap[i].FirstChildByName("Red").Valid()) { + ChangeCapturePointModelsVisibility(m_CapturePointNumberToEntityMap[i].FirstChildByName("Red"), owner == redTeam); + ChangeCapturePointModelsVisibility(m_CapturePointNumberToEntityMap[i].FirstChildByName("Blue"), owner == blueTeam); + ChangeCapturePointModelsVisibility(m_CapturePointNumberToEntityMap[i].FirstChildByName("Spectator"), owner == spectatorTeam); } } //save the next cap points and publish the captured event @@ -232,6 +253,19 @@ void CapturePointSystem::UpdateComponent(EntityWrapper& capturePointEntity, Comp } +void CapturePointSystem::ChangeCapturePointModelsVisibility(EntityWrapper &capturePointModels, bool isOwner) +{ + (Field)capturePointModels["Model"]["Visible"] = isOwner; + for (auto& capModel : capturePointModels.ChildrenWithComponent("Transform")) { + if (capModel.HasComponent("Model")) { + (Field)capModel["Model"]["Visible"] = isOwner; + } + if (capModel.HasComponent("PointLight")) { + (Field)capModel["PointLight"]["Visible"] = isOwner; + } + } +} + bool CapturePointSystem::OnTriggerTouch(const Events::TriggerTouch& e) { //personEntered = e.Entity, thingEntered = e.Trigger @@ -256,3 +290,9 @@ bool CapturePointSystem::OnCaptured(const Events::Captured& e) m_ResetTimers = true; return true; } + +bool CapturePointSystem::OnReset(const Events::Reset& e) +{ + Init(); + return true; +} \ No newline at end of file diff --git a/src/Game/Systems/DamageIndicatorSystem.cpp b/src/Game/Systems/DamageIndicatorSystem.cpp index c4de21ff..8783816f 100644 --- a/src/Game/Systems/DamageIndicatorSystem.cpp +++ b/src/Game/Systems/DamageIndicatorSystem.cpp @@ -87,7 +87,7 @@ float DamageIndicatorSystem::CalculateAngle(EntityWrapper player, glm::vec3 enem auto enemyPlayerVector = glm::normalize(playerPosition - enemyPosition); //get the rotationvector relative to the z-axis - auto rotationVectorVec3 = glm::vec3(glm::toMat4(Transform::AbsoluteOrientation(player))*glm::vec4(0, 0, 1, 0)); + auto rotationVectorVec3 = glm::vec3(glm::toMat4(TransformSystem::AbsoluteOrientation(player))*glm::vec4(0, 0, 1, 0)); //rotate the direction-vector 90 degrees to get the players side-vector auto playerSideVector = glm::vec3(glm::rotateY(rotationVectorVec3, 1.57f)); diff --git a/src/Game/Systems/ExplosionEffectSystem.cpp b/src/Game/Systems/ExplosionEffectSystem.cpp index 71de192a..f3d43cb4 100644 --- a/src/Game/Systems/ExplosionEffectSystem.cpp +++ b/src/Game/Systems/ExplosionEffectSystem.cpp @@ -2,17 +2,20 @@ void ExplosionEffectSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) { - double& delay = (double)component["Delay"]; + Field delay = component["Delay"]; if (delay > 0) { delay = std::max(0.0, delay - dt); } - if (delay <= 0) { - double& timeSinceDeath = component["TimeSinceDeath"]; - timeSinceDeath += (double)component["Speed"] * dt; - if (timeSinceDeath < 0 || timeSinceDeath > (double)component["ExplosionDuration"]) { - timeSinceDeath = 0.0; - } - } + if (delay <= 0) { + Field timeSinceDeath = component["TimeSinceDeath"]; + timeSinceDeath += (Field)component["Speed"] * dt; + if (timeSinceDeath < 0) { + timeSinceDeath = 0.0; + } + else if (timeSinceDeath >(const double&)component["ExplosionDuration"]) { + timeSinceDeath = (const double&)component["ExplosionDuration"]; + } + } } diff --git a/src/Game/Systems/HealthHUDSystem.cpp b/src/Game/Systems/HealthHUDSystem.cpp index 74258d6e..cd8a428f 100644 --- a/src/Game/Systems/HealthHUDSystem.cpp +++ b/src/Game/Systems/HealthHUDSystem.cpp @@ -22,19 +22,23 @@ void HealthHUDSystem::Update(double dt) if (entityIDParent.HasComponent("Health")) { if (entity.HasComponent("Text")) { + Field health = entityIDParent["Health"]["Health"]; + Field maxHealth = entityIDParent["Health"]["Health"]; std::string s = ""; - s = s + std::to_string((int)(double)entityIDParent["Health"]["Health"]); + s = s + std::to_string((int)health); s = s + "/"; - s = s + std::to_string((int)(double)entityIDParent["Health"]["MaxHealth"]); - float healthPercentage = (double)entityIDParent["Health"]["Health"]/(double)entityIDParent["Health"]["MaxHealth"]; - //(glm::vec4&)entity["Text"]["Color"] = glm::vec4(1.0 - healthPercentage, 0.f, healthPercentage, glm::vec4(entity["Text"]["Color"]).a); + s = s + std::to_string((int)maxHealth); + float healthPercentage = health/maxHealth; + //(Field)entity["Text"]["Color"] = glm::vec4(1.0 - healthPercentage, 0.f, healthPercentage, glm::vec4(entity["Text"]["Color"]).a); entity["Text"]["Content"] = s; } if(entity.HasComponent("Fill")) { - float healthPercentage = (double)entityIDParent["Health"]["Health"]/(double)entityIDParent["Health"]["MaxHealth"]; - (glm::vec4&)entity["Fill"]["Color"] = glm::vec4(1.0 - healthPercentage, 0.f, healthPercentage, glm::vec4(entity["Fill"]["Color"]).a); - (double&)entity["Fill"]["Percentage"] = healthPercentage; + Field health = entityIDParent["Health"]["Health"]; + Field maxHealth = entityIDParent["Health"]["Health"]; + float healthPercentage = health/maxHealth; + entity["Fill"]["Color"] = glm::vec4(1.0 - healthPercentage, 0.f, healthPercentage, glm::vec4(entity["Fill"]["Color"]).a); + entity["Fill"]["Percentage"] = (double)healthPercentage; } } diff --git a/src/Game/Systems/HealthSystem.cpp b/src/Game/Systems/HealthSystem.cpp index 9fa570c2..c19d1b65 100644 --- a/src/Game/Systems/HealthSystem.cpp +++ b/src/Game/Systems/HealthSystem.cpp @@ -21,7 +21,7 @@ bool HealthSystem::OnPlayerDamaged(Events::PlayerDamage& e) } ComponentWrapper cHealth = e.Victim["Health"]; - double& health = cHealth["Health"]; + Field health = cHealth["Health"]; //if player has the boost from a defender, subtract the damage taken by StrengthOfEffect amount auto playerBoostDefenderEntity = e.Victim.FirstChildByName("BoostDefender"); if (playerBoostDefenderEntity.Valid()) { @@ -56,9 +56,9 @@ bool HealthSystem::OnInputCommand(Events::InputCommand& e) bool HealthSystem::OnPlayerHealthPickup(Events::PlayerHealthPickup& e) { ComponentWrapper cHealth = e.Player["Health"]; - double& health = cHealth["Health"]; + Field health = cHealth["Health"]; health += e.HealthAmount; - health = std::min(health, (double)cHealth["MaxHealth"]); + health = std::min((double)health, (double)cHealth["MaxHealth"]); return true; } diff --git a/src/Game/Systems/InterpolationSystem.cpp b/src/Game/Systems/InterpolationSystem.cpp index 430c01c1..f545a0ae 100644 --- a/src/Game/Systems/InterpolationSystem.cpp +++ b/src/Game/Systems/InterpolationSystem.cpp @@ -17,7 +17,7 @@ void InterpolationSystem::Update(double dt) continue; } auto& iPosition = kv.second; - glm::vec3& position = iPosition.Component[iPosition.Field]; + Field> position = iPosition.Component[iPosition.Field]; iPosition.Alpha += dt; float alpha = glm::min(iPosition.Alpha / m_SnapshotInterval, 1.0); @@ -31,7 +31,7 @@ void InterpolationSystem::Update(double dt) continue; } auto& iOrientation = kv.second; - glm::vec3& orientation = iOrientation.Component[iOrientation.Field]; + Field orientation = iOrientation.Component[iOrientation.Field]; iOrientation.Alpha += dt / m_SnapshotInterval; iOrientation.Alpha = glm::min(iOrientation.Alpha, 1.0); @@ -45,7 +45,7 @@ void InterpolationSystem::Update(double dt) continue; } auto& iVelocity = kv.second; - glm::vec3& position = iVelocity.Component[iVelocity.Field]; + Field position = iVelocity.Component[iVelocity.Field]; iVelocity.Alpha += dt; float alpha = glm::min(iVelocity.Alpha / m_SnapshotInterval, 1.0); @@ -72,8 +72,8 @@ bool InterpolationSystem::OnInterpolate(Events::Interpolate& e) Interpolation iOrientation( cTransform, "Orientation", - glm::quat((glm::vec3&)cTransform["Orientation"]), - glm::quat((glm::vec3&)e.Component["Orientation"]) + glm::quat((Field)cTransform["Orientation"]), + glm::quat((Field)e.Component["Orientation"]) ); m_InterpolateOrientation.erase(e.Entity); m_InterpolateOrientation.insert(std::make_pair(e.Entity, iOrientation)); diff --git a/src/Game/Systems/KillFeedSystem.cpp b/src/Game/Systems/KillFeedSystem.cpp index 8a16d708..eb3e916e 100644 --- a/src/Game/Systems/KillFeedSystem.cpp +++ b/src/Game/Systems/KillFeedSystem.cpp @@ -13,7 +13,7 @@ void KillFeedSystem::Update(double dt) for (int i = 1; i <= 3; i++) { EntityWrapper child = entity.FirstChildByName("KillFeed" + std::to_string(i)); if (child.HasComponent("Text")) { - (std::string&)child["Text"]["Content"] = ""; + (Field)child["Text"]["Content"] = ""; } } @@ -27,14 +27,14 @@ void KillFeedSystem::Update(double dt) EntityWrapper child = entity.FirstChildByName("KillFeed" + std::to_string(feedIndex)); if (child.HasComponent("Text")) { - (std::string&)child["Text"]["Content"] = (*it).Content; - (glm::vec4&)child["Text"]["Color"] = (*it).Color; + (Field)child["Text"]["Content"] = (*it).Content; + (Field)child["Text"]["Color"] = (*it).Color; (*it).TimeToLive -= dt; if ((*it).TimeToLive <= 0.f) { - (std::string&)child["Text"]["Content"] = ""; - (glm::vec4&)child["Text"]["Color"] = (*it).Color; + (Field)child["Text"]["Content"] = ""; + (Field)child["Text"]["Color"] = (*it).Color; remove = true; } } diff --git a/src/Game/Systems/LifetimeSystem.cpp b/src/Game/Systems/LifetimeSystem.cpp index db19e88a..d5ceebd8 100644 --- a/src/Game/Systems/LifetimeSystem.cpp +++ b/src/Game/Systems/LifetimeSystem.cpp @@ -18,7 +18,7 @@ void LifetimeSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& cL return; } - double& lifetime = cLifetime["Lifetime"]; + Field lifetime = cLifetime["Lifetime"]; lifetime -= dt; if (lifetime <= 0.0) { diff --git a/src/Game/Systems/MainMenuSystem.cpp b/src/Game/Systems/MainMenuSystem.cpp index 848070b4..fa7c0479 100644 --- a/src/Game/Systems/MainMenuSystem.cpp +++ b/src/Game/Systems/MainMenuSystem.cpp @@ -16,10 +16,87 @@ void MainMenuSystem::Update(double dt) } +void MainMenuSystem::OpenSubMenu(const Events::InputCommand& e) +{ + auto menus = m_World->GetComponents("Menu"); + if (menus == nullptr) { + return; + } + + if (m_OpenSubMenu == EntityWrapper::Invalid) { + //No submenu is open, open one. + for (auto& menu : *menus) { + EntityWrapper menuEntity = EntityWrapper(m_World, menu.EntityID); + auto spawner = menuEntity.FirstChildByName(e.Command + "Spawner"); + if (!spawner.HasComponent("Spawner")) { + return; + } + m_OpenSubMenu = SpawnerSystem::Spawn(spawner, spawner); + if (e.Command == "Play") { + Events::SearchForServers event; + m_EventBroker->Publish(event); + } + break; + } + + } else if (m_OpenSubMenu.Name().compare(e.Command) != 0) { + //Menu is open, but not the right one, delete the old one and open a new one. + m_World->DeleteEntity(m_OpenSubMenu.ID); + m_OpenSubMenu = EntityWrapper::Invalid; + m_World->DeleteEntity(m_DropDown.ID); + m_DropDown = EntityWrapper::Invalid; + + for (auto& menu : *menus) { + EntityWrapper menuEntity = EntityWrapper(m_World, menu.EntityID); + auto Spawner = menuEntity.FirstChildByName(e.Command + "Spawner"); + if (!Spawner.HasComponent("Spawner")) { + return; + } + m_OpenSubMenu = SpawnerSystem::Spawn(Spawner, Spawner); + if(e.Command == "Play") { + Events::SearchForServers event; + m_EventBroker->Publish(event); + } + break; + } + } else { + //wanted submenu is open, close it. + m_World->DeleteEntity(m_OpenSubMenu.ID); + m_OpenSubMenu = EntityWrapper::Invalid; + m_World->DeleteEntity(m_DropDown.ID); + m_DropDown = EntityWrapper::Invalid; + } +} + + +void MainMenuSystem::OpenDropDown(const Events::InputCommand& e) +{ + auto menus = m_World->GetComponents("Menu"); + if (menus == nullptr) { + return; + } + + if (m_DropDown == EntityWrapper::Invalid) { + //No submenu is open, open one. + for (auto& menu : *menus) { + EntityWrapper menuEntity = EntityWrapper(m_World, menu.EntityID); + auto spawner = menuEntity.FirstChildByName(e.Command + "Spawner"); + if (!spawner.HasComponent("Spawner")) { + return; + } + m_DropDown = SpawnerSystem::Spawn(spawner, spawner); + break; + } + } else { + m_World->DeleteEntity(m_DropDown.ID); + m_DropDown = EntityWrapper::Invalid; + } +} + bool MainMenuSystem::OnButtonClick(const Events::ButtonClicked& e) { - if (e.EntityName == "ServerIdentityConnect") { - EntityWrapper entity = e.Entity; + EntityWrapper entity = e.Entity; + if (entity.Name() == "ServerIdentityConnect") { EntityWrapper serverIdentityEntity = entity.FirstParentWithComponent("ServerIdentity"); if(serverIdentityEntity.Valid()) { Events::ConnectRequest event; @@ -28,6 +105,11 @@ bool MainMenuSystem::OnButtonClick(const Events::ButtonClicked& e) printf("\n ----Request Server Connect----\nIP: %s\nPort: %i\n ------------------------------", event.IP, event.Port); m_EventBroker->Publish(event); } + } else if (entity.HasComponent("ConfigBtnResolution")) { + + m_Renderer->SetResolution(Rectangle((int)entity["ConfigBtnResolution"]["Width"], (int)entity["ConfigBtnResolution"]["Height"])); + m_World->DeleteEntity(m_DropDown.ID); + m_DropDown = EntityWrapper::Invalid; } return true; } @@ -45,49 +127,14 @@ bool MainMenuSystem::OnButtonPress(const Events::ButtonPressed& e) bool MainMenuSystem::OnInputCommand(const Events::InputCommand& e) { if(e.Command == "Play" && e.Value == 1) { - auto menus = m_World->GetComponents("Menu"); - if (menus == nullptr) { - return 0; - } - - if (m_OpenSubMenu == EntityWrapper::Invalid) { - //No submenu is open, open one. - for (auto& menu : *menus) { - EntityWrapper menuEntity = EntityWrapper(m_World, menu.EntityID); - auto serverListSpawner = menuEntity.FirstChildByName(e.Command + "Spawner"); - if (!serverListSpawner.HasComponent("Spawner")) { - return 0; - } - m_OpenSubMenu = SpawnerSystem::Spawn(serverListSpawner, serverListSpawner); - Events::SearchForServers event; - m_EventBroker->Publish(event); - break; - } - - } else if(!m_OpenSubMenu.HasComponent("ServerList")) { - //Menu is open, but not the right one, delete the old one and open a new one. - m_World->DeleteEntity(m_OpenSubMenu.ID); - m_OpenSubMenu = EntityWrapper::Invalid; - - for (auto& menu : *menus) { - EntityWrapper menuEntity = EntityWrapper(m_World, menu.EntityID); - auto serverListSpawner = menuEntity.FirstChildByName(e.Command + "Spawner"); - if (!serverListSpawner.HasComponent("Spawner")) { - return 0; - } - m_OpenSubMenu = SpawnerSystem::Spawn(serverListSpawner, serverListSpawner); - Events::SearchForServers event; - m_EventBroker->Publish(event); - break; - } - } else { - //Serverlist submenu is open, close it. - m_World->DeleteEntity(m_OpenSubMenu.ID); - m_OpenSubMenu = EntityWrapper::Invalid; - } + OpenSubMenu(e); } else if (e.Command == "RefreshServerList" && e.Value == 1){ Events::SearchForServers event; m_EventBroker->Publish(event); + } else if (e.Command == "Options" && e.Value == 1) { + OpenSubMenu(e); + } else if (e.Command == "Resolution" && e.Value == 1) { + OpenDropDown(e); } return true; } \ No newline at end of file diff --git a/src/Game/Systems/PlayerDeathSystem.cpp b/src/Game/Systems/PlayerDeathSystem.cpp index 9f2900fa..61abde31 100644 --- a/src/Game/Systems/PlayerDeathSystem.cpp +++ b/src/Game/Systems/PlayerDeathSystem.cpp @@ -67,7 +67,7 @@ void PlayerDeathSystem::createDeathEffect(EntityWrapper player) bool PlayerDeathSystem::OnEntityDeleted(Events::EntityDeleted& e) { // We only care about when the local players death effect is removed. - if (m_LocalPlayerDeathEffect.ID != e.DeletedEntity) { + if (m_LocalPlayerDeathEffect != e.DeletedEntity) { return false; } diff --git a/src/Game/Systems/PlayerMovementSystem.cpp b/src/Game/Systems/PlayerMovementSystem.cpp index 51d7bcef..09da8d41 100644 --- a/src/Game/Systems/PlayerMovementSystem.cpp +++ b/src/Game/Systems/PlayerMovementSystem.cpp @@ -31,7 +31,7 @@ void PlayerMovementSystem::Update(double dt) return; } m_SprintEffectTimer = 0.f; - const ComponentPool* pool = m_World->GetComponents("SprintAbility"); + auto pool = m_World->GetComponents("SprintAbility"); if (pool == nullptr) { return; } @@ -56,7 +56,7 @@ void PlayerMovementSystem::Update(double dt) playerEntityModel.Copy(sprintEffect["Model"]); playerEntityAnimation.Copy(sprintEffect["Animation"]); sprintEffect["ExplosionEffect"]["EndColor"] = (glm::vec4)playerEntityModel["Color"]; - ((glm::vec4&)sprintEffect["ExplosionEffect"]["EndColor"]).w = 0.f; + ((Field)sprintEffect["ExplosionEffect"]["EndColor"]).w(0.f); sprintEffect["Animation"]["Speed1"] = 0.0; sprintEffect["Animation"]["Speed2"] = 0.0; sprintEffect["Animation"]["Speed3"] = 0.0; @@ -79,10 +79,10 @@ void PlayerMovementSystem::updateMovementControllers(double dt) // Aim pitch EntityWrapper cameraEntity = player.FirstChildByName("Camera"); if (cameraEntity.Valid()) { - glm::vec3& cameraOrientation = cameraEntity["Transform"]["Orientation"]; - cameraOrientation.x += controller->Rotation().x; + Field cameraOrientation = cameraEntity["Transform"]["Orientation"]; + cameraOrientation.x(cameraOrientation.x() + controller->Rotation().x); // Limit camera pitch so we don't break our necks - cameraOrientation.x = glm::clamp(cameraOrientation.x, -glm::half_pi(), glm::half_pi()); + cameraOrientation.x(glm::clamp(cameraOrientation.x(), -glm::half_pi(), glm::half_pi())); float pitch = cameraOrientation.x; double time = ((pitch + glm::half_pi()) / glm::pi()); @@ -97,12 +97,12 @@ void PlayerMovementSystem::updateMovementControllers(double dt) } ComponentWrapper& cTransform = player["Transform"]; - glm::vec3& ori = cTransform["Orientation"]; - ori.y += controller->Rotation().y; + Field ori = cTransform["Orientation"]; + ori.y(ori.y() + controller->Rotation().y); float playerMovementSpeed = player["Player"]["MovementSpeed"]; float playerCrouchSpeed = player["Player"]["CrouchSpeed"]; - glm::vec3& wishDirection = player["Player"]["CurrentWishDirection"]; + Field wishDirection = player["Player"]["CurrentWishDirection"]; auto playerBoostAssaultEntity = player.FirstChildByName("BoostAssault"); if (playerBoostAssaultEntity.Valid()) { playerMovementSpeed *= (double)playerBoostAssaultEntity["BoostAssault"]["StrengthOfEffect"]; @@ -122,7 +122,8 @@ void PlayerMovementSystem::updateMovementControllers(double dt) ComponentWrapper cPhysics = player["Physics"]; //Assault Dash Check if (player.HasComponent("DashAbility")) { - controller->AssaultDashCheck(dt, ((glm::vec3)cPhysics["Velocity"]).y != 0.0f, player["DashAbility"]["CoolDownMaxTimer"], player["DashAbility"]["CoolDownTimer"], player.ID); + Field coolDownTimer = player["DashAbility"]["CoolDownTimer"]; + controller->AssaultDashCheck(dt, ((glm::vec3)cPhysics["Velocity"]).y != 0.0f, player["DashAbility"]["CoolDownMaxTimer"], coolDownTimer, player.ID); } wishDirection = controller->Movement() * glm::inverse(glm::quat(ori)); //this makes sure you can only dash in the 4 directions: forw,backw,left,right @@ -136,21 +137,21 @@ void PlayerMovementSystem::updateMovementControllers(double dt) wishSpeed = playerMovementSpeed; } if (player.ID == m_LocalPlayer.ID) { - if (glm::length(wishDirection) == 0) { + if (glm::length((glm::vec3)wishDirection) == 0) { // If no key is pressed, reset the distance moved since last step. m_DistanceMoved = 0; } } - glm::vec3& velocity = cPhysics["Velocity"]; + Field velocity = cPhysics["Velocity"]; bool isOnGround = (bool)cPhysics["IsOnGround"]; //ImGui::Text(isOnGround ? "On ground" : "In air"); //ImGui::Text("velocity: (%f, %f, %f) |%f|", velocity.x, velocity.y, velocity.z, glm::length(velocity)); glm::vec3 groundVelocity(0.f, 0.f, 0.f); - groundVelocity.x = velocity.x; - groundVelocity.z = velocity.z; + groundVelocity.x = velocity.x(); + groundVelocity.z = velocity.z(); //ImGui::Text("groundVelocity: (%f, %f, %f) |%f|", groundVelocity.x, groundVelocity.y, groundVelocity.z, glm::length(groundVelocity)); //ImGui::Text("wishDirection: (%f, %f, %f) |%f|", wishDirection.x, wishDirection.y, wishDirection.z, glm::length(wishDirection)); - float currentSpeedProj = glm::dot(groundVelocity, wishDirection); + float currentSpeedProj = glm::dot(groundVelocity, (glm::vec3)wishDirection); float addSpeed = wishSpeed - currentSpeedProj; //ImGui::Text("currentSpeedProj: %f", currentSpeedProj); //ImGui::Text("wishSpeed: %f", wishSpeed); @@ -175,8 +176,8 @@ void PlayerMovementSystem::updateMovementControllers(double dt) if (sniperSprinting) { accelerationSpeed *= (double)player["SprintAbility"]["StrengthOfEffect"]; } - velocity += accelerationSpeed * wishDirection; - ImGui::Text("velocity: (%f, %f, %f) |%f|", velocity.x, velocity.y, velocity.z, glm::length(velocity)); + velocity += accelerationSpeed * (glm::vec3)wishDirection; + ImGui::Text("velocity: (%f, %f, %f) |%f|", velocity.x(), velocity.y(), velocity.z(), glm::length((glm::vec3)velocity)); } if (isOnGround) { @@ -186,7 +187,7 @@ void PlayerMovementSystem::updateMovementControllers(double dt) if (controller->Jumping() && !controller->Crouching()) { if (isOnGround) { (bool)cPhysics["IsOnGround"] = false; - velocity.y = player["Player"]["JumpSpeed"]; + velocity.y(player["Player"]["JumpSpeed"]); if (player.Valid()) { @@ -218,7 +219,7 @@ void PlayerMovementSystem::updateMovementControllers(double dt) } else if (player.HasComponent("DoubleJump") && !controller->DoubleJumping()) { //Enter here if player can double jump and is doing so. (bool)cPhysics["IsOnGround"] = false; - velocity.y = player["DoubleJump"]["DoubleJumpSpeed"]; + velocity.y(player["DoubleJump"]["DoubleJumpSpeed"]); if (player.Valid()) { EntityWrapper playerModel = player.FirstChildByName("PlayerModel"); @@ -259,20 +260,25 @@ void PlayerMovementSystem::updateMovementControllers(double dt) } if (player.HasComponent("AABB")) { - glm::vec3& size = player["AABB"]["Size"]; + Field size = player["AABB"]["Size"]; if (controller->Crouching()) { size = glm::vec3(1.f, 1.f, 1.f); } else { size = glm::vec3(1.f, 1.6f, 1.f); + if (controller->CrouchingLastFrame() && isOnGround) { + // The collision should resolve this anyway, but + // this is more reliable, since the box gets larger. + Field pos = cTransform["Position"]; + pos.y(pos.y() + 0.3f); + } } } // TODO: Animations } - + playerStep(dt, player); controller->Reset(); } - playerStep(dt); } @@ -281,11 +287,11 @@ void PlayerMovementSystem::updateVelocity(EntityWrapper player, double dt) // Only apply velocity to local player ComponentWrapper& cTransform = player["Transform"]; ComponentWrapper& cPhysics = player["Physics"]; - glm::vec3& velocity = cPhysics["Velocity"]; + Field velocity = cPhysics["Velocity"]; bool isOnGround = (bool)cPhysics["IsOnGround"]; // Ground friction - float speed = glm::length(velocity); + float speed = glm::length((glm::vec3)velocity); static float groundFriction = 7.f; ImGui::InputFloat("groundFriction", &groundFriction); static float airFriction = 2.f; @@ -295,16 +301,16 @@ void PlayerMovementSystem::updateVelocity(EntityWrapper player, double dt) if (speed > 0) { float drop = speed * friction * (float)dt; float multiplier = glm::max(speed - drop, 0.f) / speed; - velocity.x *= multiplier; - velocity.z *= multiplier; + velocity.x(velocity.x() * multiplier); + velocity.z(velocity.z() * multiplier); } // Gravity if (cPhysics["Gravity"]) { - velocity.y -= 9.82f * (float)dt; + velocity.y(velocity.y() - (9.82f * (float)dt)); } - glm::vec3& position = cTransform["Position"]; + Field position = cTransform["Position"]; position += velocity * (float)dt; } @@ -327,12 +333,12 @@ void PlayerMovementSystem::setAim(EntityWrapper root, std::string weaponNodeName } } -void PlayerMovementSystem::playerStep(double dt) +void PlayerMovementSystem::playerStep(double dt, EntityWrapper player) { - if (!m_LocalPlayer.Valid()) { + // Position of the local player, used see how far a player has moved. + if(!IsClient) { return; } - // Position of the local player, used see how far a player has moved. glm::vec3 pos = (glm::vec3)m_World->GetComponent(m_LocalPlayer.ID, "Transform")["Position"]; // Used to see if a player is airborne. bool grounded = (bool)m_World->GetComponent(m_LocalPlayer.ID, "Physics")["IsOnGround"]; @@ -343,8 +349,8 @@ void PlayerMovementSystem::playerStep(double dt) // Player moved a step's distance // Create footstep sound Events::PlaySoundOnEntity e; - e.EmitterID = m_LocalPlayer.ID; - e.FilePath = m_LeftFoot ? "Audio/footstep/footstep2.wav" : "Audio/footstep/footstep3.wav"; + e.Emitter = m_LocalPlayer; + e.FilePath = m_LeftFoot ? "Audio/Footstep/Footstep2.wav" : "Audio/Footstep/Footstep3.wav"; m_LeftFoot = !m_LeftFoot; m_EventBroker->Publish(e); m_DistanceMoved = 0.f; @@ -500,9 +506,9 @@ bool PlayerMovementSystem::OnDashAbility(Events::DashAbility & e) dashEffectModel.AttachComponent("ExplosionEffect"); dashEffectModel["ExplosionEffect"]["EndColor"] = (glm::vec4)playerModel["Model"]["Color"]; - ((glm::vec4&)dashEffectModel["ExplosionEffect"]["EndColor"]).w = 0.f; - (double&)dashEffectModel["ExplosionEffect"]["ExplosionDuration"] = dashEffect["Lifetime"]["Lifetime"]; - (glm::vec3&)dashEffectModel["ExplosionEffect"]["ExplosionOrigin"] = glm::vec3(0, 1, 0) + (0.2f * controller->Movement()); + ((Field)dashEffectModel["ExplosionEffect"]["EndColor"]).w = 0.f; + (Field)dashEffectModel["ExplosionEffect"]["ExplosionDuration"] = dashEffect["Lifetime"]["Lifetime"]; + (Field)dashEffectModel["ExplosionEffect"]["ExplosionOrigin"] = glm::vec3(0, 1, 0) + (0.2f * controller->Movement()); @@ -510,7 +516,7 @@ bool PlayerMovementSystem::OnDashAbility(Events::DashAbility & e) auto animationChildren = dashEffectModel.ChildrenWithComponent("Animation"); for (auto animationEntity : animationChildren) { - (bool&)animationEntity["Animation"]["Play"] = false; + (Field)animationEntity["Animation"]["Play"] = false; } */ } diff --git a/src/Game/Systems/PlayerSpawnSystem.cpp b/src/Game/Systems/PlayerSpawnSystem.cpp index 03e3adb4..ac33edb7 100644 --- a/src/Game/Systems/PlayerSpawnSystem.cpp +++ b/src/Game/Systems/PlayerSpawnSystem.cpp @@ -25,10 +25,10 @@ void PlayerSpawnSystem::Update(double dt) // Take the first CapturePointGameMode component found. ComponentWrapper& modeComponent = *pool->begin(); // Increase timer. - double& timer = (double&)modeComponent["RespawnTime"]; + Field timer = modeComponent["RespawnTime"]; timer += dt; if (m_DbgConfigForceRespawn) { - (double&)modeComponent["MaxRespawnTime"] = m_ForcedRespawnTime; + (Field)modeComponent["MaxRespawnTime"] = m_ForcedRespawnTime; } double maxRespawnTime = (double)modeComponent["MaxRespawnTime"]; EntityWrapper spectatorCam = m_World->GetFirstEntityByName("SpectatorCamera"); diff --git a/src/Game/Systems/ScoreScreenSystem.cpp b/src/Game/Systems/ScoreScreenSystem.cpp index 94674432..02518b8c 100644 --- a/src/Game/Systems/ScoreScreenSystem.cpp +++ b/src/Game/Systems/ScoreScreenSystem.cpp @@ -9,6 +9,8 @@ ScoreScreenSystem::ScoreScreenSystem(SystemParams params) EVENT_SUBSCRIBE_MEMBER(m_EPlayerSpawned, &ScoreScreenSystem::OnPlayerSpawn); EVENT_SUBSCRIBE_MEMBER(m_EPlayerConnected, &ScoreScreenSystem::OnPlayerConnected); EVENT_SUBSCRIBE_MEMBER(m_EPlayerDisconnected, &ScoreScreenSystem::OnPlayerDisconnected); + EVENT_SUBSCRIBE_MEMBER(m_EReset, &ScoreScreenSystem::OnReset); + EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &ScoreScreenSystem::OnInputCommand); } void ScoreScreenSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& scoreScreen, double dt) @@ -40,13 +42,13 @@ void ScoreScreenSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& if (it->first == ID) { if (it->second.Team != currentTeam) { m_World->DeleteEntity(child.ID); - (int&)entity["ScoreScreen"]["TotalIdentities"] -= 1; + (Field)entity["ScoreScreen"]["TotalIdentities"] -= 1; break; } for (auto it2 = m_DisconnectedIdentities.begin(); it2 != m_DisconnectedIdentities.end(); ++it2) { if (ID == *it2) { m_World->DeleteEntity(child.ID); - (int&)entity["ScoreScreen"]["TotalIdentities"] -= 1; + (Field)entity["ScoreScreen"]["TotalIdentities"] -= 1; it2 = m_DisconnectedIdentities.erase(it2); it = m_PlayerIdentities.erase(it); @@ -59,17 +61,17 @@ void ScoreScreenSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& break; } //Update Deaths for child - (int&)child["ScoreIdentity"]["Kills"] = it->second.Kills; + (Field)child["ScoreIdentity"]["Kills"] = it->second.Kills; //Update Kills for child - (int&)child["ScoreIdentity"]["Deaths"] = it->second.Deaths; + (Field)child["ScoreIdentity"]["Deaths"] = it->second.Deaths; //KD is not updated at the moment. if (it->second.Deaths != 0) { - (double&)child["ScoreIdentity"]["KD"] = it->second.Kills/it->second.Deaths; + (Field)child["ScoreIdentity"]["KD"] = it->second.Kills/it->second.Deaths; } //Update position for child glm::vec3 offset = (glm::vec3)entity["ScoreScreen"]["Offset"]; - (glm::vec3&) child["Transform"]["Position"] = offset * position; + (Field) child["Transform"]["Position"] = offset * position; position += 1.f; break; @@ -90,16 +92,16 @@ void ScoreScreenSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& EntityWrapper scoreIdentity = entityFile->MergeInto(m_World); glm::vec3 offset = (glm::vec3)entity["ScoreScreen"]["Offset"]; int newPosition = (int)entity["ScoreScreen"]["TotalIdentities"]; - (glm::vec3&) scoreIdentity["Transform"]["Position"] = offset * (float)newPosition; + (Field) scoreIdentity["Transform"]["Position"] = offset * (float)newPosition; auto cScoreIdentity = scoreIdentity["ScoreIdentity"]; auto data = it->second; - (std::string&)cScoreIdentity["Name"] = data.Name; - (int&)cScoreIdentity["ID"] = data.ID; + (Field)cScoreIdentity["Name"] = data.Name; + (Field)cScoreIdentity["ID"] = data.ID; m_World->SetParent(scoreIdentity.ID, entity.ID); - (int&)entity["ScoreScreen"]["TotalIdentities"] += 1; + (Field)entity["ScoreScreen"]["TotalIdentities"] += 1; } } @@ -156,3 +158,25 @@ bool ScoreScreenSystem::OnPlayerDisconnected(const Events::PlayerDisconnected& e m_DisconnectedIdentities.push_back(e.PlayerID); return 0; } + +bool ScoreScreenSystem::OnReset(const Events::Reset & e) +{ + for (auto& it : m_PlayerIdentities) { + it.second.Deaths = 0; + it.second.Kills = 0; + it.second.Team = 1; + it.second.Player = EntityWrapper::Invalid; + } + return true; +} + +bool ScoreScreenSystem::OnInputCommand(const Events::InputCommand & e) +{ + if (e.Command != "PickTeam" || e.PlayerID == -1 || e.Value == 0) { + return false; + } + + m_PlayerIdentities.at(e.PlayerID).Team = e.Value; + + return true; +} diff --git a/src/Game/Systems/ServerListSystem.cpp b/src/Game/Systems/ServerListSystem.cpp index ad575e3f..2db23c1a 100644 --- a/src/Game/Systems/ServerListSystem.cpp +++ b/src/Game/Systems/ServerListSystem.cpp @@ -33,20 +33,20 @@ bool ServerListSystem::OnServerListRecieved(const Events::DisplayServerlist& e) EntityWrapper identitySpawner = serverListEntity.FirstChildByName("ServerIdentitySpawner"); identitySpawner.DeleteChildren(); - (int&)cServerList["TotalIdentities"] = (int)e.Serverlist.size(); + (Field)cServerList["TotalIdentities"] = (int)e.Serverlist.size(); for (int i = 0; i < e.Serverlist.size(); i++) { //Create Identities for each server and place them on the right position. EntityWrapper newIdentity = SpawnerSystem::Spawn(identitySpawner, identitySpawner); EntityWrapper serverIdentityEntity = newIdentity.FirstChildByName("ServerIdentity"); glm::vec3 offset = (glm::vec3)serverListEntity["ServerList"]["Offset"]; - (glm::vec3&)serverIdentityEntity["Transform"]["Position"] = offset * (float)i; + (Field)serverIdentityEntity["Transform"]["Position"] = offset * (float)i; auto& cIdentity = serverIdentityEntity["ServerIdentity"]; - (std::string&)cIdentity["IP"] = e.Serverlist[i].Address; - (std::string&)cIdentity["ServerName"] = e.Serverlist[i].Name; - (int&)cIdentity["Port"] = e.Serverlist[i].Port; - (int&)cIdentity["PlayersConnected"] = e.Serverlist[i].PlayersConnected; + (Field)cIdentity["IP"] = e.Serverlist[i].Address; + (Field)cIdentity["ServerName"] = e.Serverlist[i].Name; + (Field)cIdentity["Port"] = e.Serverlist[i].Port; + (Field)cIdentity["PlayersConnected"] = e.Serverlist[i].PlayersConnected; } } return 1; diff --git a/src/Game/Systems/SoundSystem.cpp b/src/Game/Systems/SoundSystem.cpp index be9c8aaf..4ee7090b 100644 --- a/src/Game/Systems/SoundSystem.cpp +++ b/src/Game/Systems/SoundSystem.cpp @@ -6,45 +6,33 @@ SoundSystem::SoundSystem(SystemParams params) { ConfigFile* config = ResourceManager::Load("Config.ini"); m_Announcer = ResourceManager::Load("Config.ini")->Get("Sound.Announcer", "female"); - if (IsClient) { - EVENT_SUBSCRIBE_MEMBER(m_EPlayerSpawned, &SoundSystem::OnPlayerSpawned); - EVENT_SUBSCRIBE_MEMBER(m_InputCommand, &SoundSystem::OnInputCommand); - EVENT_SUBSCRIBE_MEMBER(m_EDoubleJump, &SoundSystem::OnDoubleJump); - EVENT_SUBSCRIBE_MEMBER(m_EDashAbility, &SoundSystem::OnDashAbility); - EVENT_SUBSCRIBE_MEMBER(m_EPlayerDamage, &SoundSystem::OnPlayerDamage); - EVENT_SUBSCRIBE_MEMBER(m_ECaptured, &SoundSystem::OnCaptured); - EVENT_SUBSCRIBE_MEMBER(m_ETriggerTouch, &SoundSystem::OnTriggerTouch); - EVENT_SUBSCRIBE_MEMBER(m_EPlayerDeath, &SoundSystem::OnPlayerDeath); - } + unsigned seed = std::chrono::system_clock::now().time_since_epoch().count(); + m_RandomGenerator = std::default_random_engine(seed); + m_RandIntDistribution = std::uniform_int_distribution(1, 12); + EVENT_SUBSCRIBE_MEMBER(m_EPlayerSpawned, &SoundSystem::OnPlayerSpawned); + EVENT_SUBSCRIBE_MEMBER(m_InputCommand, &SoundSystem::OnInputCommand); + EVENT_SUBSCRIBE_MEMBER(m_EDoubleJump, &SoundSystem::OnDoubleJump); + EVENT_SUBSCRIBE_MEMBER(m_EPlayerDamage, &SoundSystem::OnPlayerDamage); + EVENT_SUBSCRIBE_MEMBER(m_ECaptured, &SoundSystem::OnCaptured); + EVENT_SUBSCRIBE_MEMBER(m_EPlayerDeath, &SoundSystem::OnPlayerDeath); } void SoundSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& cComponent, double dt) { } void SoundSystem::Update(double dt) -{ - if (!IsClient) { - return; - } - - // Temp for play test. - if (m_DrumsIsPlaying) { - m_DrumsIsPlaying = !drumTimer(dt); - } -} +{ } bool SoundSystem::OnPlayerSpawned(const Events::PlayerSpawned &e) { if (e.PlayerID == -1) { // Local player m_World->AttachComponent(e.Player.ID, "Listener"); - Events::PlaySoundOnEntity go; - go.EmitterID = LocalPlayer.ID; - go.FilePath = "Audio/announcer/" + m_Announcer + "/go.wav"; + Events::PlayAnonuncerVoice go; + go.FilePath = "Audio/Announcer/" + m_Announcer + "/Go.wav"; m_EventBroker->Publish(go); - // TEMP: starts bgm { - Events::PlayBackgroundMusic ev; - ev.FilePath = "Audio/bgm/ambient.wav"; + Events::ChangeBGM ev; + ev.FilePath = "Audio/BGM/Layer1.wav"; m_EventBroker->Publish(ev); } } @@ -54,82 +42,67 @@ bool SoundSystem::OnPlayerSpawned(const Events::PlayerSpawned &e) bool SoundSystem::OnInputCommand(const Events::InputCommand & e) { if (e.Command == "Jump" && e.Value > 0) { - if (e.PlayerID == -1) { // local player - playerJumps(); - return true; - } + if (e.PlayerID == -1) { + playerJumps(LocalPlayer); + } + return true; } - return false; } -void SoundSystem::playerJumps() +void SoundSystem::playerJumps(EntityWrapper player) { - if (!LocalPlayer.Valid()) { + if (!IsClient) { // Only play for clients return; } - - bool grounded = (bool)m_World->GetComponent(LocalPlayer.ID, "Physics")["IsOnGround"]; + if(!player.HasComponent("Physics")) { + return; + } + bool grounded = (bool)player["Physics"]["IsOnGround"]; if (grounded) { Events::PlaySoundOnEntity e; - e.EmitterID = LocalPlayer.ID; - e.FilePath = "Audio/jump/jump1.wav"; + e.Emitter = player; + e.FilePath = "Audio/Jump/Jump1.wav"; m_EventBroker->Publish(e); } } -bool SoundSystem::drumTimer(double dt) -{ - m_DrumTimer += dt; - if (m_DrumTimer > 15) { - m_DrumTimer = 0.0; - return true; - } else { - return false; - } -} - bool SoundSystem::OnCaptured(const Events::Captured & e) { - if (!LocalPlayer.Valid()) { + if (!IsClient) { // Only play for clients return false; } int homeTeam = (int)m_World->GetComponent(e.CapturePointTakenID, "Team")["Team"]; int team = (int)m_World->GetComponent(LocalPlayer.ID, "Team")["Team"]; - Events::PlaySoundOnEntity ev; + Events::PlayAnonuncerVoice ev; if (team == homeTeam) { - ev.FilePath = "Audio/announcer/" + m_Announcer + "/objective_achieved.wav"; + ev.FilePath = "Audio/Announcer/" + m_Announcer + "/ObjectiveAchieved.wav"; } else { - ev.FilePath = "Audio/announcer/" + m_Announcer + "/objective_failed.wav"; // have not been tested + ev.FilePath = "Audio/Announcer/" + m_Announcer + "/ObjectiveFailed.wav"; } - ev.EmitterID = LocalPlayer.ID; m_EventBroker->Publish(ev); - // Temp for play test. - m_DrumsIsPlaying = false; return false; } -// Testing purposes atm... bool SoundSystem::OnPlayerDamage(const Events::PlayerDamage & e) { if (!IsClient) { // Only play for clients return false; } - if (LocalPlayer.ID = e.Victim.ID) { // You're local player was the one who took dmg + if (!e.Victim.Valid() || !e.Inflictor.Valid()) { + return false; + } + auto victimTeam = m_World->GetComponent(e.Victim.ID, "Team"); + auto inflictorTeam = m_World->GetComponent(e.Inflictor.ID, "Team"); + if ((int)victimTeam["Team"] == (int)inflictorTeam["Team"]) { + // Victim and inflictor are the same team, should not play "hurt" sound. return false; } - std::uniform_int_distribution dist(1, 12); - int rand = dist(generator); std::vector paths; - paths.push_back("Audio/hurt/hurt" + std::to_string(rand) + ".wav"); + paths.push_back("Audio/Hurt/Hurt" + std::to_string(m_RandIntDistribution(m_RandomGenerator)) + ".wav"); - // // Breathe - // int ammountOfbreaths = (static_cast(e.Damage) / 10) + 2; // TEMP: Idk something stupid like this shit - // for (int i = 0; i < ammountOfbreaths; i++) { - // paths.push_back("Audio/exhausted/breath.wav"); - // } Events::PlayQueueOnEntity ev; - ev.Emitter = LocalPlayer; + ev.Emitter = e.Victim; ev.FilePaths = paths; m_EventBroker->Publish(ev); return false; @@ -137,7 +110,7 @@ bool SoundSystem::OnPlayerDamage(const Events::PlayerDamage & e) bool SoundSystem::OnPlayerDeath(const Events::PlayerDeath & e) { - if (e.Player.ID != LocalPlayer.ID) { + if (!e.Player.Valid()) { return false; } if (!IsClient) { @@ -146,8 +119,9 @@ bool SoundSystem::OnPlayerDeath(const Events::PlayerDeath & e) // The local player is dead. The local player might be invalid? // Play the sound from the listener. // TODO: We might want to hear other players die. - Events::PlayBackgroundMusic ev; - ev.FilePath = "Audio/die/die2.wav"; + Events::PlaySoundOnEntity ev; + ev.Emitter = e.Player; + ev.FilePath = "Audio/Die/Die2.wav"; m_EventBroker->Publish(ev); return false; } @@ -155,43 +129,25 @@ bool SoundSystem::OnPlayerDeath(const Events::PlayerDeath & e) bool SoundSystem::OnPlayerHealthPickup(const Events::PlayerHealthPickup & e) { Events::PlaySoundOnEntity ev; - ev.EmitterID = LocalPlayer.ID; - ev.FilePath = "Audio/pickup/pickup2.wav"; + ev.Emitter = LocalPlayer; + ev.FilePath = "Audio/Pickup/Pickup2.wav"; m_EventBroker->Publish(ev); return false; } -bool SoundSystem::OnTriggerTouch(const Events::TriggerTouch & e) -{ - // Temp for play test. - if (m_DrumsIsPlaying) { - return false; - } - if (m_World->HasComponent(e.Trigger.ID, "CapturePoint")) { - Events::PlaySoundOnEntity ev; // should be BGM - ev.EmitterID = LocalPlayer.ID; - ev.FilePath = "Audio/bgm/drumstest.wav"; - m_EventBroker->Publish(ev); - // Temp for play test. - m_DrumsIsPlaying = true; - } - return false; -} - bool SoundSystem::OnDoubleJump(const Events::DoubleJump & e) { - Events::PlaySoundOnEntity ev; - ev.EmitterID = LocalPlayer.ID; - ev.FilePath = "Audio/jump/jump2.wav"; - m_EventBroker->Publish(ev); - return false; -} - -bool SoundSystem::OnDashAbility(const Events::DashAbility &e) -{ - Events::PlaySoundOnEntity ev; - ev.EmitterID = LocalPlayer.ID; - ev.FilePath = "Audio/jump/dash1.wav"; - m_EventBroker->Publish(ev); + if (!m_World->ValidEntity(e.entityID)) { + return false; + } + if (!IsClient) { + return false; + } + if (e.entityID == LocalPlayer.ID) { + Events::PlaySoundOnEntity ev; + ev.Emitter = EntityWrapper(m_World, e.entityID); + ev.FilePath = "Audio/Jump/Jump2.wav"; + m_EventBroker->Publish(ev); + } return false; } \ No newline at end of file diff --git a/src/Game/Systems/SpawnerSystem.cpp b/src/Game/Systems/SpawnerSystem.cpp index 282c958b..825c9e99 100644 --- a/src/Game/Systems/SpawnerSystem.cpp +++ b/src/Game/Systems/SpawnerSystem.cpp @@ -76,9 +76,9 @@ EntityWrapper SpawnerSystem::Spawn(EntityWrapper spawner, EntityWrapper parent / void SpawnerSystem::transformEntityToSpawnPoint(EntityWrapper spawnedEntity, EntityWrapper spawnPoint) { // Set its position and orientation to that of the SpawnPoint - spawnedEntity["Transform"]["Position"] = Transform::AbsolutePosition(spawnPoint.World, spawnPoint.ID); + spawnedEntity["Transform"]["Position"] = TransformSystem::AbsolutePosition(spawnPoint.World, spawnPoint.ID); // TODO: Quaternions, bitch - spawnedEntity["Transform"]["Orientation"] = glm::eulerAngles(Transform::AbsoluteOrientation(spawnPoint)); + spawnedEntity["Transform"]["Orientation"] = glm::eulerAngles(TransformSystem::AbsoluteOrientation(spawnPoint)); } bool SpawnerSystem::spawnedEntityIsColliding(EntityWrapper spawnedEntity, EntityWrapper spawnPoint, const std::string& dontCollideComponent) @@ -86,7 +86,7 @@ bool SpawnerSystem::spawnedEntityIsColliding(EntityWrapper spawnedEntity, Entity transformEntityToSpawnPoint(spawnedEntity, spawnPoint); //Check if the spawned entity collides with anything, and if so, continue to the next spawnpoint. EntityAABB spawnedBox = *Collision::EntityAbsoluteAABB(spawnedEntity); - const ComponentPool* otherSpawnedEntities = spawnPoint.World->GetComponents(dontCollideComponent); + auto otherSpawnedEntities = spawnPoint.World->GetComponents(dontCollideComponent); for (const auto& obj : *otherSpawnedEntities) { if (spawnedEntity.ID == obj.EntityID) { continue; @@ -113,7 +113,7 @@ bool SpawnerSystem::spawnedEntityIsColliding(EntityWrapper spawnedEntity, Entity spawnedBox, model->Vertices(), model->m_Indices, - Transform::ModelMatrix(otherEntity))) { + TransformSystem::ModelMatrix(otherEntity))) { return true; } } diff --git a/src/Game/Systems/SpectatorCameraSystem.cpp b/src/Game/Systems/SpectatorCameraSystem.cpp index d1f2f1ce..ed624c69 100644 --- a/src/Game/Systems/SpectatorCameraSystem.cpp +++ b/src/Game/Systems/SpectatorCameraSystem.cpp @@ -8,6 +8,8 @@ SpectatorCameraSystem::SpectatorCameraSystem(SystemParams params) , m_PickedTeam(-1) { EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &SpectatorCameraSystem::OnInputCommand); + EVENT_SUBSCRIBE_MEMBER(m_EDisconnect, &SpectatorCameraSystem::OnDisconnect); + EVENT_SUBSCRIBE_MEMBER(m_EReset, &SpectatorCameraSystem::OnReset); } void SpectatorCameraSystem::Update(double dt) @@ -26,6 +28,14 @@ void SpectatorCameraSystem::Update(double dt) } } +void SpectatorCameraSystem::reset() +{ + m_CamSetToTeamPick = false; + // They will also be set to menu, so unlock mouse just in case they were in game with locked mouse. + Events::UnlockMouse unlock; + m_EventBroker->Publish(unlock); +} + bool SpectatorCameraSystem::OnInputCommand(const Events::InputCommand& e) { // Only the client should do this, and only if player is not spawned. @@ -87,4 +97,20 @@ bool SpectatorCameraSystem::OnInputCommand(const Events::InputCommand& e) } return true; -} \ No newline at end of file +} + +bool SpectatorCameraSystem::OnDisconnect(const Events::PlayerDisconnected& e) +{ + // If local player gets disconnected, they should be set to + // the spectator camera next time a map loads that has one. + if (e.Entity == LocalPlayer.ID) { + reset(); + } + return true; +} + +bool SpectatorCameraSystem::OnReset(const Events::Reset & e) +{ + reset(); + return true; +} diff --git a/src/Game/Systems/TextFieldReader.cpp b/src/Game/Systems/TextFieldReader.cpp index 71218ef8..c2d2a4e7 100644 --- a/src/Game/Systems/TextFieldReader.cpp +++ b/src/Game/Systems/TextFieldReader.cpp @@ -34,7 +34,7 @@ void TextFieldReader::UpdateComponent(EntityWrapper& entity, ComponentWrapper& c } const ComponentInfo::Field_t& field = component.Info.Fields.at(fieldName); - std::string& text = entity["Text"]["Content"]; + Field text = entity["Text"]["Content"]; if (field.Type == "int") { text = boost::lexical_cast((const int&)component[fieldName]); diff --git a/src/Game/Systems/Weapon/AssaultWeaponBehaviour.cpp b/src/Game/Systems/Weapon/AssaultWeaponBehaviour.cpp index 1af0e927..60f69609 100644 --- a/src/Game/Systems/Weapon/AssaultWeaponBehaviour.cpp +++ b/src/Game/Systems/Weapon/AssaultWeaponBehaviour.cpp @@ -2,7 +2,7 @@ void AssaultWeaponBehaviour::UpdateComponent(EntityWrapper& entity, ComponentWrapper& cWeapon, double dt) { - double& fireCooldown = cWeapon["FireCooldown"]; + Field fireCooldown = cWeapon["FireCooldown"]; fireCooldown = glm::max(0.0, fireCooldown - dt); WeaponBehaviour::UpdateComponent(entity, cWeapon, dt); @@ -11,30 +11,30 @@ void AssaultWeaponBehaviour::UpdateComponent(EntityWrapper& entity, ComponentWra void AssaultWeaponBehaviour::UpdateWeapon(ComponentWrapper cWeapon, WeaponInfo& wi, double dt) { // Start reloading automatically if at 0 mag ammo - int& magAmmo = cWeapon["MagazineAmmo"]; + Field magAmmo = cWeapon["MagazineAmmo"]; if (m_ConfigAutoReload && magAmmo <= 0) { OnReload(cWeapon, wi); } // Only start reloading once we're done firing - bool& reloadQueued = cWeapon["ReloadQueued"]; - double& fireCooldown = cWeapon["FireCooldown"]; - bool& isReloading = cWeapon["IsReloading"]; + Field reloadQueued = cWeapon["ReloadQueued"]; + Field fireCooldown = cWeapon["FireCooldown"]; + Field isReloading = cWeapon["IsReloading"]; if (reloadQueued && fireCooldown <= 0) { reloadQueued = fireCooldown; isReloading = true; } // Decrement reload timer - double& reloadTimer = cWeapon["ReloadTimer"]; + Field reloadTimer = cWeapon["ReloadTimer"]; if (isReloading) { reloadTimer = glm::max(0.0, reloadTimer - dt); } // Handle reloading if (isReloading && reloadTimer <= 0.0) { - int& magSize = cWeapon["MagazineSize"]; - int& ammo = cWeapon["Ammo"]; + Field magSize = cWeapon["MagazineSize"]; + Field ammo = cWeapon["Ammo"]; int usedAmmo = glm::max(0, magSize - magAmmo); magAmmo = glm::clamp(ammo + magAmmo, 0, magSize); @@ -56,15 +56,15 @@ void AssaultWeaponBehaviour::UpdateWeapon(ComponentWrapper cWeapon, WeaponInfo& // Restore view angle if (IsClient) { - float& currentTravel = cWeapon["CurrentTravel"]; - float& returnSpeed = cWeapon["ViewReturnSpeed"]; + Field currentTravel = cWeapon["CurrentTravel"]; + Field 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; + Field cameraOrientation = camera["Transform"]["Orientation"]; + cameraOrientation.x(cameraOrientation.x() - change); } } } @@ -79,7 +79,7 @@ void AssaultWeaponBehaviour::UpdateWeapon(ComponentWrapper cWeapon, WeaponInfo& if (rootNode.Valid()) { EntityWrapper blend = rootNode.FirstChildByName("MovementBlendAssault"); if (blend.Valid()) { - (double&)blend["Blend"]["Weight"] = animationWeight; + (Field)blend["Blend"]["Weight"] = animationWeight; } } @@ -104,24 +104,24 @@ void AssaultWeaponBehaviour::OnCeasePrimaryFire(ComponentWrapper cWeapon, Weapon void AssaultWeaponBehaviour::OnReload(ComponentWrapper cWeapon, WeaponInfo& wi) { - bool& reloadQueued = cWeapon["ReloadQueued"]; - bool& isReloading = cWeapon["IsReloading"]; + Field reloadQueued = cWeapon["ReloadQueued"]; + Field isReloading = cWeapon["IsReloading"]; if (reloadQueued || isReloading) { return; } - int& magAmmo = cWeapon["MagazineAmmo"]; - int& magSize = cWeapon["MagazineSize"]; + Field magAmmo = cWeapon["MagazineAmmo"]; + Field magSize = cWeapon["MagazineSize"]; if (magAmmo >= magSize) { return; } - int& ammo = cWeapon["Ammo"]; + Field ammo = cWeapon["Ammo"]; if (ammo <= 0) { return; } - double reloadTime = cWeapon["ReloadTime"]; - double& reloadTimer = cWeapon["ReloadTimer"]; + Field reloadTime = cWeapon["ReloadTime"]; + Field reloadTimer = cWeapon["ReloadTimer"]; // Start reload reloadQueued = true; @@ -161,7 +161,7 @@ void AssaultWeaponBehaviour::OnReload(ComponentWrapper cWeapon, WeaponInfo& wi) // Sound Events::PlaySoundOnEntity e; - e.EmitterID = wi.Player.ID; + e.Emitter = wi.Player; e.FilePath = "Audio/weapon/Assault/AssaultWeaponReload.wav"; m_EventBroker->Publish(e); } @@ -194,13 +194,32 @@ void AssaultWeaponBehaviour::fireBullet(ComponentWrapper cWeapon, WeaponInfo& wi cWeapon["FireCooldown"] = 60.0 / (double)cWeapon["RPM"]; // Ammo - int& magAmmo = cWeapon["MagazineAmmo"]; + Field magAmmo = cWeapon["MagazineAmmo"]; if (magAmmo <= 0) { return; } else { magAmmo -= 1; } + // View punch + if (IsClient) { + EntityWrapper camera = wi.Player.FirstChildByName("Camera"); + if (camera.Valid()) { + Field cameraOrientation = camera["Transform"]["Orientation"]; + float viewPunch = cWeapon["ViewPunch"]; + float maxTravelAngle = cWeapon["MaxTravelAngle"]; + Field currentTravel = cWeapon["CurrentTravel"]; + if (currentTravel < maxTravelAngle) { + float change = viewPunch; + if (currentTravel + change > maxTravelAngle) { + change = maxTravelAngle - currentTravel; + } + cameraOrientation.x(cameraOrientation.x() + change); + currentTravel += change; + } + } + } + // Get weapon model based on current person EntityWrapper weaponModelEntity = getRelevantWeaponEntity(wi); if (!weaponModelEntity.Valid()) { @@ -210,12 +229,12 @@ void AssaultWeaponBehaviour::fireBullet(ComponentWrapper cWeapon, WeaponInfo& wi // Tracer EntityWrapper tracerSpawner = weaponModelEntity.FirstChildByName("WeaponMuzzleRay"); if (tracerSpawner.Valid()) { - glm::vec3 origin = Transform::AbsolutePosition(tracerSpawner); - glm::vec3 direction = glm::quat(Transform::AbsoluteOrientationEuler(tracerSpawner)) * glm::vec3(0, 0, -1); + glm::vec3 origin = TransformSystem::AbsolutePosition(tracerSpawner); + glm::vec3 direction = glm::quat(TransformSystem::AbsoluteOrientationEuler(tracerSpawner)) * glm::vec3(0, 0, -1); float distance = traceRayDistance(origin, direction); EntityWrapper ray = SpawnerSystem::Spawn(tracerSpawner, tracerSpawner); if (ray.Valid()) { - ((glm::vec3&)ray["Transform"]["Scale"]).z = distance; + ((Field)ray["Transform"]["Scale"]).z(distance); } } //MuzzleFlash @@ -235,7 +254,7 @@ void AssaultWeaponBehaviour::fireBullet(ComponentWrapper cWeapon, WeaponInfo& wi if (hitMarkerSpawner.Valid()) { SpawnerSystem::Spawn(hitMarkerSpawner, hitMarkerSpawner); Events::PlaySoundOnEntity e; - e.EmitterID = wi.Player.ID; + e.Emitter = wi.Player; e.FilePath = "Audio/weapon/hitclick.wav"; m_EventBroker->Publish(e); } @@ -273,7 +292,7 @@ void AssaultWeaponBehaviour::fireBullet(ComponentWrapper cWeapon, WeaponInfo& wi // Sound Events::PlaySoundOnEntity e; - e.EmitterID = wi.Player.ID; + e.Emitter = wi.Player; e.FilePath = "Audio/weapon/Assault/AssaultWeaponFire.wav"; m_EventBroker->Publish(e); } diff --git a/src/Tests/WorldTest.cpp b/src/Tests/WorldTest.cpp index 633e617a..146310d2 100644 --- a/src/Tests/WorldTest.cpp +++ b/src/Tests/WorldTest.cpp @@ -30,14 +30,14 @@ BOOST_AUTO_TEST_CASE(WorldTestSingleAllocation, * boost::unit_test::tolerance(0. BOOST_TEST(vec3.z == 3.f); // Change values - ((int&)c["TestInteger"]) += 1; + ((Field)c["TestInteger"]) += 1; BOOST_TEST((int)c["TestInteger"] == 1338); - ((double&)c["TestDouble"]) += 1.11; + ((Field)c["TestDouble"]) += 1.11; std::cout << (double)c["TestDouble"] << std::endl; BOOST_TEST((double)c["TestDouble"] == 14.48); c["TestString"] = "Siesta"; BOOST_TEST((std::string)c["TestString"] == "Siesta"); - ((glm::vec3&)c["TestVec3"]).y += 1.f; + ((Field)c["TestVec3"]).y += 1.f; BOOST_TEST(((glm::vec3)c["TestVec3"]).y == 3.f); } @@ -100,16 +100,16 @@ BOOST_AUTO_TEST_CASE(WorldCopy, *utf::tolerance(0.00001)) // Check that built-in types are copied but don't reside in the same memory BOOST_CHECK((int)w1_c1["TestInteger"] == (int)w2_c1["TestInteger"]); - BOOST_CHECK(&(int&)w1_c1["TestInteger"] != &(int&)w2_c1["TestInteger"]); + BOOST_CHECK(&(Field)w1_c1["TestInteger"] != &(Field)w2_c1["TestInteger"]); BOOST_CHECK((double)w1_c1["TestDouble"] == (double)w2_c1["TestDouble"]); - BOOST_CHECK(&(int&)w1_c1["TestDouble"] != &(int&)w2_c1["TestDouble"]); + BOOST_CHECK(&(Field)w1_c1["TestDouble"] != &(Field)w2_c1["TestDouble"]); BOOST_CHECK((int)w1_c2["TestInteger"] == (int)w2_c2["TestInteger"]); - BOOST_CHECK(&(int&)w1_c2["TestInteger"] != &(int&)w2_c2["TestInteger"]); + BOOST_CHECK(&(Field)w1_c2["TestInteger"] != &(Field)w2_c2["TestInteger"]); BOOST_CHECK((double)w1_c2["TestDouble"] == (double)w2_c2["TestDouble"]); - BOOST_CHECK(&(int&)w1_c2["TestDouble"] != &(int&)w2_c2["TestDouble"]); + BOOST_CHECK(&(Field)w1_c2["TestDouble"] != &(Field)w2_c2["TestDouble"]); // Check that specially handled strings are fine BOOST_CHECK((std::string)w1_c1["TestString"] == (std::string)w2_c1["TestString"]); - BOOST_CHECK(&(std::string&)w1_c1["TestString"] != &(std::string&)w2_c1["TestString"]); + BOOST_CHECK(&(Field)w1_c1["TestString"] != &(Field)w2_c1["TestString"]); BOOST_CHECK((std::string)w1_c2["TestString"] == (std::string)w2_c2["TestString"]); - BOOST_CHECK(&(std::string&)w1_c2["TestString"] != &(std::string&)w2_c2["TestString"]); + BOOST_CHECK(&(Field)w1_c2["TestString"] != &(Field)w2_c2["TestString"]); } diff --git a/tools/MayaExporter/MayaExporter/Material.cpp b/tools/MayaExporter/MayaExporter/Material.cpp index a5717aa6..4d99f203 100644 --- a/tools/MayaExporter/MayaExporter/Material.cpp +++ b/tools/MayaExporter/MayaExporter/Material.cpp @@ -108,7 +108,7 @@ bool Material::findColorTexture(MaterialNode& material_node, MFnDependencyNode& return true; } else if (AllConnections[i].node().hasFn(MFn::kLayeredTexture)) { - MGlobal::displayInfo(MString() + "find splat map"); + MGlobal::displayInfo(MString() + "found color splat map"); return findSplatTextures(material_node, material_node.ColorMaps, MFnDependencyNode(AllConnections[i].node())); } } @@ -162,9 +162,9 @@ bool Material::findNormalTexture(MaterialNode& material_node, MFnDependencyNode& material_node.NormalMaps.push_back(newTexture); return true; - } else if (AllConnections[i].node().hasFn(MFn::kLayeredTexture)) { - MGlobal::displayInfo(MString() + "find splat map"); - return findSplatTextures(material_node, material_node.NormalMaps, MFnDependencyNode(AllConnections[i].node())); + } else if (AllBumpConnections[j].node().hasFn(MFn::kLayeredTexture)) { + MGlobal::displayInfo(MString() + "found normal splat map"); + return findSplatTextures(material_node, material_node.NormalMaps, MFnDependencyNode(AllBumpConnections[j].node())); } } } @@ -218,7 +218,7 @@ bool Material::findSpecularTexture(MaterialNode& material_node, MFnDependencyNod material_node.type = MaterialNode::MaterialType::SingleTextures; return true; } else if (AllConnections[i].node().hasFn(MFn::kLayeredTexture)) { - MGlobal::displayInfo(MString() + "find splat map"); + MGlobal::displayInfo(MString() + "found specular splat map"); return findSplatTextures(material_node, material_node.SpecularMaps, MFnDependencyNode(AllConnections[i].node())); } } @@ -270,7 +270,7 @@ bool Material::findIncandescenceTexture(MaterialNode& material_node, MFnDependen return true; } else if (AllConnections[i].node().hasFn(MFn::kLayeredTexture)) { - MGlobal::displayInfo(MString() + "find splat map"); + MGlobal::displayInfo(MString() + "found incandescens splat map"); return findSplatTextures(material_node, material_node.IncandescenceMaps, MFnDependencyNode(AllConnections[i].node())); } }