diff --git a/assets b/assets index 022890f8..902cbf2b 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 022890f8f522eb0a88f5ebc7cda9af0b235e438a +Subproject commit 902cbf2ba6b17127542a7be7916b07bcb048a256 diff --git a/deps b/deps index ed45883a..49ef5853 160000 --- a/deps +++ b/deps @@ -1 +1 @@ -Subproject commit ed45883a444c6de548b6211a83a079ff2ecfce15 +Subproject commit 49ef5853662500ec9634af75b73b61f8168a14f9 diff --git a/include/Engine/Collision/Collision.h b/include/Engine/Collision/Collision.h index 9e1a81db..1fd24cc6 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" @@ -48,13 +48,13 @@ bool RayVsTriangle(const Ray& ray, bool trueOnNegativeDistance = false); //Return true if the ray hits any of the triangles in the model. Stops checking when a hit is detected. bool RayVsModel(const Ray& ray, - const RawModel::Vertex* modelVertices, + const std::vector& modelVertices, const std::vector& modelIndices, const glm::mat4& modelMatrix); //Return true if the ray hits any of the triangles in the model. //Also returns the position of the intersection point. Will loop through all the whole model indices. bool RayVsModel(const Ray& ray, - const RawModel::Vertex* modelVertices, + const std::vector& modelVertices, const std::vector& modelIndices, const glm::mat4& modelMatrix, glm::vec3& outHitPosition); @@ -62,7 +62,7 @@ bool RayVsModel(const Ray& ray, //Also returns the distance from the ray origin to the closest //intersection point, and the barycentric u,v-coordinates. Will loop through all the whole model indices. bool RayVsModel(const Ray& ray, - const RawModel::Vertex* modelVertices, + const std::vector& modelVertices, const std::vector& modelIndices, const glm::mat4& modelMatrix, float& outDistance, @@ -70,7 +70,7 @@ bool RayVsModel(const Ray& ray, float& outVCoord); bool AABBvsTriangles(const AABB& box, - const RawModel::Vertex* modelVertices, + const std::vector& modelVertices, const std::vector& modelIndices, const glm::mat4& modelMatrix, glm::vec3& boxVelocity, @@ -80,7 +80,19 @@ bool AABBvsTriangles(const AABB& box, //Detects collision, but does not resolve. bool AABBvsTriangles(const AABB& box, - const RawModel::Vertex* modelVertices, + const std::vector& modelVertices, + const std::vector& modelIndices, + const glm::mat4& modelMatrix); + +enum Output +{ + OutContained, + OutSeparated, + OutIntersecting +}; +//Detects intersection and containment. +Output AABBvsTrianglesWContainment(const AABB& box, + const std::vector& modelVertices, const std::vector& modelIndices, const glm::mat4& modelMatrix); 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 d891c7b0..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" @@ -12,7 +12,9 @@ namespace Events struct Captured : Event { int TeamNumberThatCapturedCapturePoint; - EntityID CapturePointID; + EntityID CapturePointTakenID; + EntityWrapper BlueTeamNextCapturePoint; + EntityWrapper RedTeamNextCapturePoint; }; } 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/EPlayerDeath.h b/include/Engine/Core/EPlayerDeath.h index 363745a6..dca47205 100644 --- a/include/Engine/Core/EPlayerDeath.h +++ b/include/Engine/Core/EPlayerDeath.h @@ -10,8 +10,9 @@ namespace Events struct PlayerDeath : Event { //KilledBy,KilledByWhat is optional for now. It might be used later in the playerlog-system - EntityWrapper Player; - std::string KilledByWhat; + EntityWrapper Player = EntityWrapper::Invalid; + EntityWrapper Killer = EntityWrapper::Invalid; + std::string KilledByWhat = ""; }; } diff --git a/include/Engine/Core/EntityFile.h b/include/Engine/Core/EntityFile.h index 538e9047..fae39c51 100644 --- a/include/Engine/Core/EntityFile.h +++ b/include/Engine/Core/EntityFile.h @@ -1,164 +1,21 @@ #ifndef EntityFile_h__ #define EntityFile_h__ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "World.h" +#include "EntityXMLFile.h" +#include "EntityXMLFilePreprocessor.h" +#include "EntityXMLFileParser.h" +#include "EntityWrapper.h" -#include "../GLM.h" -#include "Util/XercesString.h" -#include "ResourceManager.h" -#include "Entity.h" -#include "ComponentInfo.h" - -class EntityFileHandler -{ - friend class EntityFileSAXHandler; -public: - // @param EntityID The entity found - // @param EntityID The parent of the entity - typedef std::function OnStartEntityCallback; - void SetStartEntityCallback(OnStartEntityCallback c) { m_OnStartEntityCallback = c; } - // @param EntityID The entity the component corresponds to - // @param std::string Type name of the component - typedef std::function OnStartComponentCallback; - void SetStartComponentCallback(OnStartComponentCallback c) { m_OnStartComponentCallback = c; } - // @param EntityID Entity - // @param std::string Component name - // @param std::string Field name - // @param std::map Field attribute names and values - typedef std::function&)> OnStartFieldCallback; - void SetStartFieldCallback(OnStartFieldCallback c) { m_OnStartFieldCallback = c; } - // @param EntityID Entity - // @param std::string Component name - // @param std::string Field name - // @param char* Field data - typedef std::function OnStartFieldDataCallback; - void SetStartFieldDataCallback(OnStartFieldDataCallback c) { m_OnStartFieldDataCallback = c; } - -private: - OnStartEntityCallback m_OnStartEntityCallback = nullptr; - OnStartComponentCallback m_OnStartComponentCallback = nullptr; - OnStartFieldCallback m_OnStartFieldCallback = nullptr; - OnStartFieldDataCallback m_OnStartFieldDataCallback = nullptr; -}; - -class EntityFileSAXHandler : public xercesc::DefaultHandler +class EntityFile : private World, public Resource { public: - enum class State - { - Unknown, - Entity, - Component, - ComponentField - }; + EntityFile(std::string path); - EntityFileSAXHandler(const EntityFileHandler* handler, xercesc::SAX2XMLReader* reader); - - void startElement(const XMLCh* const _uri, const XMLCh* const _localName, const XMLCh* const _qname, const xercesc::Attributes& attrs) override; - void characters(const XMLCh* const chars, const XMLSize_t length) override; - void endElement(const XMLCh* const _uri, const XMLCh* const _localName, const XMLCh* const _qname) override; - - void warning(const xercesc::SAXParseException& e); - void error(const xercesc::SAXParseException& e); - void fatalError(const xercesc::SAXParseException& e); + EntityWrapper MergeInto(World* other); private: - const EntityFileHandler* m_Handler; - xercesc::XMLGrammarPool* m_GrammarPool; - xercesc::SAX2XMLReader* m_Reader; - //State m_CurrentScope = State::Unknown; - std::stack m_StateStack; - unsigned int m_NextEntityID = 0; - std::stack m_EntityStack; - std::string m_CurrentComponent; - std::string m_CurrentField; - std::map m_CurrentAttributes; - - void onStartEntity(const xercesc::Attributes& attrs); - void onEndEntity(); - void onStartEntityRef(const xercesc::Attributes& attrs); - void onStartComponent(const std::string& name); - void onEndComponent(const std::string& name); - void onStartComponentField(const std::string& field, const xercesc::Attributes& attrs); - void onEndComponentField(const std::string& field); - void onFieldData(char* data); -}; - -class EntityFileXMLErrorHandler : public xercesc::ErrorHandler -{ -public: - void warning(const xercesc::SAXParseException& e) override - { - reportParseException("Warning", e); - } - void error(const xercesc::SAXParseException& e) override - { - reportParseException("Error", e); - } - void fatalError(const xercesc::SAXParseException& e) override - { - reportParseException("FATAL ERROR", e); - } - void resetErrors() override { } - -private: - void reportParseException(std::string type, const xercesc::SAXParseException& e) - { - char* message = xercesc::XMLString::transcode(e.getMessage()); - char* systemID = xercesc::XMLString::transcode(e.getSystemId()); - std::cerr << systemID << ":" << e.getLineNumber() << ":" << e.getColumnNumber() << std::endl; - std::cerr << type << ": " << message << std::endl; - xercesc::XMLString::release(&systemID); - xercesc::XMLString::release(&message); - } -}; - -class EntityFile : public Resource -{ - friend class ResourceManager; - friend class EntityFileSAXHandler; -private: - EntityFile(boost::filesystem::path path); - ~EntityFile(); - -public: - static unsigned int GetTypeStride(std::string typeName); - static void WriteAttributeData(char* outData, const ComponentInfo::Field_t& field, const std::map& attributes); - static void WriteValueData(char* outData, const ComponentInfo::Field_t& field, const char* valueData); - - xercesc::XMLGrammarPool* GrammarPool() const { return m_GrammarPool; } - - void Parse(const EntityFileHandler* handler) const; - -private: - boost::filesystem::path m_FilePath; - xercesc::XMLGrammarPool* m_GrammarPool; - xercesc::SAX2XMLReader* m_SAX2XMLReader; - //std::map m_ComponentInfo; - //std::vector m_EntityReferences; - - static void setReaderFeatures(xercesc::SAX2XMLReader* reader); + EntityID m_RootEntity = EntityID_Invalid; }; #endif \ No newline at end of file diff --git a/include/Engine/Core/EntityWrapper.h b/include/Engine/Core/EntityWrapper.h index 8ece8e59..01f3f22e 100644 --- a/include/Engine/Core/EntityWrapper.h +++ b/include/Engine/Core/EntityWrapper.h @@ -23,11 +23,13 @@ struct EntityWrapper static const EntityWrapper Invalid; - const std::string Name(); + const std::string Name() const; bool HasComponent(const std::string& componentType); void AttachComponent(const char* componentName); EntityWrapper Parent(); + EntityWrapper FirstParentByName(const std::string& parentEntityName); EntityWrapper FirstChildByName(const std::string& name); + EntityWrapper FirstLevelChildByName(const std::string& name); EntityWrapper FirstParentWithComponent(const std::string& componentType); EntityWrapper Clone(EntityWrapper parent = EntityWrapper::Invalid); std::vector ChildrenWithComponent(const std::string& componentType); @@ -43,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/EntityXMLFile.h b/include/Engine/Core/EntityXMLFile.h new file mode 100644 index 00000000..6f24154d --- /dev/null +++ b/include/Engine/Core/EntityXMLFile.h @@ -0,0 +1,164 @@ +#ifndef EntityXMLFile_h__ +#define EntityXMLFile_h__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../GLM.h" +#include "Util/XercesString.h" +#include "ResourceManager.h" +#include "Entity.h" +#include "ComponentInfo.h" + +class EntityFileHandler +{ + friend class EntityFileSAXHandler; +public: + // @param EntityID The entity found + // @param EntityID The parent of the entity + typedef std::function OnStartEntityCallback; + void SetStartEntityCallback(OnStartEntityCallback c) { m_OnStartEntityCallback = c; } + // @param EntityID The entity the component corresponds to + // @param std::string Type name of the component + typedef std::function OnStartComponentCallback; + void SetStartComponentCallback(OnStartComponentCallback c) { m_OnStartComponentCallback = c; } + // @param EntityID Entity + // @param std::string Component name + // @param std::string Field name + // @param std::map Field attribute names and values + typedef std::function&)> OnStartFieldCallback; + void SetStartFieldCallback(OnStartFieldCallback c) { m_OnStartFieldCallback = c; } + // @param EntityID Entity + // @param std::string Component name + // @param std::string Field name + // @param char* Field data + typedef std::function OnStartFieldDataCallback; + void SetStartFieldDataCallback(OnStartFieldDataCallback c) { m_OnStartFieldDataCallback = c; } + +private: + OnStartEntityCallback m_OnStartEntityCallback = nullptr; + OnStartComponentCallback m_OnStartComponentCallback = nullptr; + OnStartFieldCallback m_OnStartFieldCallback = nullptr; + OnStartFieldDataCallback m_OnStartFieldDataCallback = nullptr; +}; + +class EntityFileSAXHandler : public xercesc::DefaultHandler +{ +public: + enum class State + { + Unknown, + Entity, + Component, + ComponentField + }; + + EntityFileSAXHandler(const EntityFileHandler* handler, xercesc::SAX2XMLReader* reader); + + void startElement(const XMLCh* const _uri, const XMLCh* const _localName, const XMLCh* const _qname, const xercesc::Attributes& attrs) override; + void characters(const XMLCh* const chars, const XMLSize_t length) override; + void endElement(const XMLCh* const _uri, const XMLCh* const _localName, const XMLCh* const _qname) override; + + void warning(const xercesc::SAXParseException& e); + void error(const xercesc::SAXParseException& e); + void fatalError(const xercesc::SAXParseException& e); + +private: + const EntityFileHandler* m_Handler; + xercesc::XMLGrammarPool* m_GrammarPool; + xercesc::SAX2XMLReader* m_Reader; + //State m_CurrentScope = State::Unknown; + std::stack m_StateStack; + unsigned int m_NextEntityID = 0; + std::stack m_EntityStack; + std::string m_CurrentComponent; + std::string m_CurrentField; + std::map m_CurrentAttributes; + + void onStartEntity(const xercesc::Attributes& attrs); + void onEndEntity(); + void onStartEntityRef(const xercesc::Attributes& attrs); + void onStartComponent(const std::string& name); + void onEndComponent(const std::string& name); + void onStartComponentField(const std::string& field, const xercesc::Attributes& attrs); + void onEndComponentField(const std::string& field); + void onFieldData(char* data); +}; + +class EntityFileXMLErrorHandler : public xercesc::ErrorHandler +{ +public: + void warning(const xercesc::SAXParseException& e) override + { + reportParseException("Warning", e); + } + void error(const xercesc::SAXParseException& e) override + { + reportParseException("Error", e); + } + void fatalError(const xercesc::SAXParseException& e) override + { + reportParseException("FATAL ERROR", e); + } + void resetErrors() override { } + +private: + void reportParseException(std::string type, const xercesc::SAXParseException& e) + { + char* message = xercesc::XMLString::transcode(e.getMessage()); + char* systemID = xercesc::XMLString::transcode(e.getSystemId()); + std::cerr << systemID << ":" << e.getLineNumber() << ":" << e.getColumnNumber() << std::endl; + std::cerr << type << ": " << message << std::endl; + xercesc::XMLString::release(&systemID); + xercesc::XMLString::release(&message); + } +}; + +class EntityXMLFile : public Resource +{ + friend class ResourceManager; + friend class EntityFileSAXHandler; +private: + EntityXMLFile(boost::filesystem::path path); + ~EntityXMLFile(); + +public: + static unsigned int GetTypeStride(std::string typeName); + static void WriteAttributeData(char* outData, const ComponentInfo::Field_t& field, const std::map& attributes); + static void WriteValueData(char* outData, const ComponentInfo::Field_t& field, const char* valueData); + + xercesc::XMLGrammarPool* GrammarPool() const { return m_GrammarPool; } + + void Parse(const EntityFileHandler* handler) const; + +private: + boost::filesystem::path m_FilePath; + xercesc::XMLGrammarPool* m_GrammarPool; + xercesc::SAX2XMLReader* m_SAX2XMLReader; + //std::map m_ComponentInfo; + //std::vector m_EntityReferences; + + static void setReaderFeatures(xercesc::SAX2XMLReader* reader); +}; + +#endif \ No newline at end of file diff --git a/include/Engine/Core/EntityFileParser.h b/include/Engine/Core/EntityXMLFileParser.h similarity index 78% rename from include/Engine/Core/EntityFileParser.h rename to include/Engine/Core/EntityXMLFileParser.h index b4eee5b2..4bc2fab9 100644 --- a/include/Engine/Core/EntityFileParser.h +++ b/include/Engine/Core/EntityXMLFileParser.h @@ -1,18 +1,19 @@ -#ifndef EntityFileParser_h__ -#define EntityFileParser_h__ +#ifndef EntityXMLFileParser_h__ +#define EntityXMLFileParser_h__ -#include "EntityFile.h" +#include "EntityXMLFile.h" #include "World.h" -class EntityFileParser +class EntityXMLFileParser { + friend class EntityFile; public: - EntityFileParser(const EntityFile* entityFile); - - EntityID MergeEntities(World* world, EntityID baseParent = EntityID_Invalid); + EntityXMLFileParser(const EntityXMLFile* entityFile); private: - const EntityFile* m_EntityFile; + EntityID MergeEntities(World* world, EntityID baseParent = EntityID_Invalid); + + const EntityXMLFile* m_EntityFile; EntityFileHandler m_Handler; World* m_World = nullptr; EntityID m_FirstEntity = EntityID_Invalid; diff --git a/include/Engine/Core/EntityFilePreprocessor.h b/include/Engine/Core/EntityXMLFilePreprocessor.h similarity index 80% rename from include/Engine/Core/EntityFilePreprocessor.h rename to include/Engine/Core/EntityXMLFilePreprocessor.h index b46bd383..4f969291 100644 --- a/include/Engine/Core/EntityFilePreprocessor.h +++ b/include/Engine/Core/EntityXMLFilePreprocessor.h @@ -1,5 +1,5 @@ -#ifndef EntityFilePreprocessor_h__ -#define EntityFilePreprocessor_h__ +#ifndef EntityXMLFilePreprocessor_h__ +#define EntityXMLFilePreprocessor_h__ #include #include @@ -17,17 +17,18 @@ #include "Util/XercesString.h" #include "ResourceManager.h" #include "World.h" -#include "EntityFile.h" +#include "EntityXMLFile.h" -class EntityFilePreprocessor +class EntityXMLFilePreprocessor { + friend class EntityFile; public: - EntityFilePreprocessor(const EntityFile* entityFile); - - void RegisterComponents(World* world); + EntityXMLFilePreprocessor(const EntityXMLFile* entityFile); private: - const EntityFile* m_EntityFile; + void RegisterComponents(World* world); + + const EntityXMLFile* m_EntityFile; std::map m_ComponentCounts; std::map m_ComponentInfo; diff --git a/include/Engine/Core/EntityFileWriter.h b/include/Engine/Core/EntityXMLFileWriter.h similarity index 87% rename from include/Engine/Core/EntityFileWriter.h rename to include/Engine/Core/EntityXMLFileWriter.h index b75bc145..da073a73 100644 --- a/include/Engine/Core/EntityFileWriter.h +++ b/include/Engine/Core/EntityXMLFileWriter.h @@ -1,5 +1,5 @@ -#ifndef EntityFileWriter_h__ -#define EntityFileWriter_h__ +#ifndef EntityXMLFileWriter_h__ +#define EntityXMLFileWriter_h__ #include #include @@ -8,13 +8,13 @@ #include #include "Util/XercesString.h" -#include "EntityFile.h" +#include "EntityXMLFile.h" #include "World.h" -class EntityFileWriter +class EntityXMLFileWriter { public: - EntityFileWriter(boost::filesystem::path file) + EntityXMLFileWriter(boost::filesystem::path file) : m_FilePath(file) { using namespace xercesc; diff --git a/include/Engine/Core/MemoryPool.h b/include/Engine/Core/MemoryPool.h index fe836e52..da4af84e 100644 --- a/include/Engine/Core/MemoryPool.h +++ b/include/Engine/Core/MemoryPool.h @@ -118,9 +118,6 @@ public: else { m_ExtraMemory.push_back((char*)malloc(m_Stride)); //We should preferably not enter here to avoid performance issues. Set more numMaxElements in constructor instead. - if (!DisableMemoryPool::Value) { - //LOG_DEBUG("Allocated slots exceed Pool size, extra memory allocated dynamically. Pool size: %u, dynamic size: %u.", m_NumSlots, m_ExtraMemory.size()); - } return m_ExtraMemory.back(); } } diff --git a/include/Engine/Core/PerformanceTimer.h b/include/Engine/Core/PerformanceTimer.h index a3cdfa92..b7e0c60a 100644 --- a/include/Engine/Core/PerformanceTimer.h +++ b/include/Engine/Core/PerformanceTimer.h @@ -2,8 +2,11 @@ #define PerformanceTimer_h__ #include "../Common.h" + +#ifdef DEBUG #include using boost::timer::cpu_timer; +#endif //DEBUG class PerformanceTimer { @@ -17,9 +20,11 @@ public: static void CreateExcelData(); private: +#ifdef DEBUG static std::map timers; static cpu_timer m_Timer; static std::string currentTimerRunning; +#endif //DEBUG }; #endif 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/System.h b/include/Engine/Core/System.h index 23d5f9a5..8077fcc7 100644 --- a/include/Engine/Core/System.h +++ b/include/Engine/Core/System.h @@ -68,7 +68,7 @@ protected: const std::string m_ComponentType; - virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) = 0; + virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& cFade, double dt) = 0; }; class ImpureSystem : public virtual System 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 c9f738ce..dd7f2887 100644 --- a/include/Engine/Core/World.h +++ b/include/Engine/Core/World.h @@ -6,6 +6,7 @@ #include "ObjectPool.h" #include "ComponentPool.h" #include "EventBroker.h" +struct EntityWrapper; class World { @@ -18,13 +19,13 @@ public: World(const World& other); // Create empty entity - EntityID CreateEntity(EntityID parent = 0); + EntityID CreateEntity(EntityID parent = EntityID_Invalid); // Delete entity and all components within void DeleteEntity(EntityID entity); // Check if an entity exists bool ValidEntity(EntityID entity) const; // Register a component type and allocate space for it - void RegisterComponent(ComponentInfo& ci); + void RegisterComponent(const ComponentInfo& ci); // Attach a component to an entity and fill it with default values ComponentWrapper AttachComponent(EntityID entity, const std::string& componentType); // Check if an entity has a component @@ -34,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 @@ -49,6 +50,12 @@ public: void SetName(EntityID entity, const std::string& name); // Get the textual name of an entity std::string GetName(EntityID entity) const; + // Get the first entity in the world with the name. + EntityWrapper GetFirstEntityByName(const std::string& name); + + // Merge another world into this one + // Returns a map that maps entities from the other world to their copies in this one + std::unordered_map Merge(const World* other); private: EventBroker* m_EventBroker = nullptr; diff --git a/include/Engine/Editor/EditorCameraInputController.h b/include/Engine/Editor/EditorCameraInputController.h index 4c139e01..257e3424 100644 --- a/include/Engine/Editor/EditorCameraInputController.h +++ b/include/Engine/Editor/EditorCameraInputController.h @@ -12,8 +12,8 @@ template class EditorCameraInputController : public FirstPersonInputController { public: - EditorCameraInputController(EventBroker* eventBroker, unsigned int playerID) - : FirstPersonInputController(eventBroker, playerID) + EditorCameraInputController(EventBroker* eventBroker, unsigned int playerID, EntityWrapper playerEntity) + : FirstPersonInputController(eventBroker, playerID, playerEntity) { EVENT_SUBSCRIBE_MEMBER(m_EMousePress, &EditorCameraInputController::OnMousePress); EVENT_SUBSCRIBE_MEMBER(m_EMouseRelease, &EditorCameraInputController::OnMouseRelease); @@ -104,6 +104,11 @@ protected: if (!m_Enabled) { return false; } + + ImGuiIO& io = ImGui::GetIO(); + if (io.WantCaptureMouse || io.WantCaptureKeyboard) { + return false; + } m_SpeedMultiplier += e.DeltaY * (0.1 * m_SpeedMultiplier); m_Config->Set("Editor.CameraSpeed", m_SpeedMultiplier); diff --git a/include/Engine/Editor/EditorGUI.h b/include/Engine/Editor/EditorGUI.h index 57574e66..807bfc8b 100644 --- a/include/Engine/Editor/EditorGUI.h +++ b/include/Engine/Editor/EditorGUI.h @@ -22,6 +22,7 @@ #include "../Core/ELockMouse.h" #include "../Core/EFileDropped.h" #include "../Rendering/Texture.h" +#include "Game/Events/ESpawnerSpawn.h" class EditorGUI { diff --git a/include/Engine/Editor/EditorSystem.h b/include/Engine/Editor/EditorSystem.h index 06ee53b6..7fe8ce6f 100644 --- a/include/Engine/Editor/EditorSystem.h +++ b/include/Engine/Editor/EditorSystem.h @@ -5,9 +5,8 @@ #include "../Core/World.h" #include "../Core/SystemPipeline.h" #include "../Core/ResourceManager.h" -#include "../Core/EntityFilePreprocessor.h" -#include "../Core/EntityFileParser.h" -#include "../Core/EntityFileWriter.h" +#include "../Core/EntityFile.h" +#include "../Core/EntityXMLFileWriter.h" #include "../Core/EMousePress.h" #include "../Input/EInputCommand.h" #include "EditorGUI.h" @@ -48,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/GUI/MainMenuSystem.h b/include/Engine/GUI/MainMenuSystem.h deleted file mode 100644 index ba69ff0d..00000000 --- a/include/Engine/GUI/MainMenuSystem.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef MainMenuSystem_h__ -#define MainMenuSystem_h__ - -#include "../Core/System.h" -#include "../Rendering/IRenderer.h" -#include "../Core/ResourceManager.h" -#include "../Core/Event.h" - - -#include "EButtonClicked.h" -#include "EButtonPressed.h" -#include "EButtonReleased.h" - - -class MainMenuSystem : public ImpureSystem -{ -public: - MainMenuSystem(SystemParams params, IRenderer* renderer); - virtual void Update(double dt) override; - -private: - IRenderer* m_Renderer; - - EventRelay m_EClicked; - bool OnButtonClick(const Events::ButtonClicked& e); - EventRelay m_EReleased; - bool OnButtonRelease(const Events::ButtonReleased& e); - EventRelay m_EPressed; - bool OnButtonPress(const Events::ButtonPressed& e); - -}; - -#endif \ No newline at end of file diff --git a/include/Engine/Input/FirstPersonInputController.h b/include/Engine/Input/FirstPersonInputController.h index 7dc24a2c..777c0331 100644 --- a/include/Engine/Input/FirstPersonInputController.h +++ b/include/Engine/Input/FirstPersonInputController.h @@ -6,17 +6,20 @@ #include "../Core/ELockMouse.h" #include "../Game/Events/EDashAbility.h" #include "InputHandler.h" +#include "Rendering/EAutoAnimationBlend.h" +#include "Rendering/ESetBlendWeight.h" template class FirstPersonInputController : public InputController { public: - FirstPersonInputController(EventBroker* eventBroker, int playerID); + FirstPersonInputController(EventBroker* eventBroker, int playerID, EntityWrapper playerEntity); virtual const glm::vec3 Movement() const { return m_Movement; } 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; @@ -27,21 +30,24 @@ public: virtual bool OnCommand(const Events::InputCommand& e) override; virtual void Reset(); - void AssaultDashCheck(double dt, bool isJumping, double assaultDashCoolDownMaxTimer); + 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; } protected: const int m_PlayerID; + EntityWrapper m_PlayerEntity; + bool m_MouseLocked = false; glm::vec3 m_Rotation; glm::vec3 m_Movement; 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; - double m_AssaultDashCoolDownTimer = 0.0; //i will let m_AssaultDashDoubleTapSensitivityTimer stay hardcoded, its not really a gamevariable (more an inputvariable), //and its very unlikely that someone wants to change that value const float m_AssaultDashDoubleTapSensitivityTimer = 0.25f; @@ -52,7 +58,7 @@ protected: bool m_ShiftDashing = false; bool m_ValidDoubleTap = false; - //specialabilitys + //specialabilities bool m_MovementKeyDown = false; bool m_SpecialAbilityKeyDown = false; int m_NumberOfMovementKeysDown = 0; @@ -64,9 +70,10 @@ protected: }; template -FirstPersonInputController::FirstPersonInputController(EventBroker* eventBroker, int playerID) +FirstPersonInputController::FirstPersonInputController(EventBroker* eventBroker, int playerID, EntityWrapper playerEntity) : InputController(eventBroker) , m_PlayerID(playerID) + , m_PlayerEntity(playerEntity) { EVENT_SUBSCRIBE_MEMBER(m_ELockMouse, &FirstPersonInputController::OnLockMouse); EVENT_SUBSCRIBE_MEMBER(m_EUnlockMouse, &FirstPersonInputController::OnUnlockMouse); @@ -77,6 +84,7 @@ void FirstPersonInputController::Reset() { m_Rotation = glm::vec3(0.f, 0.f, 0.f); m_Jumping = false; + m_CrouchingLastFrame = m_Crouching; } template @@ -105,7 +113,6 @@ bool FirstPersonInputController::OnCommand(const Events::InputComm if (e.Command == "Pitch") { float val = glm::radians(e.Value); m_Rotation.x += -val; - //m_Rotation.x = glm::clamp(m_Rotation.x, -glm::half_pi(), glm::half_pi()); } if (e.Command == "Yaw") { @@ -117,16 +124,180 @@ bool FirstPersonInputController::OnCommand(const Events::InputComm if (e.Command == "Forward") { float val = glm::clamp(e.Value, -1.f, 1.f); m_Movement.z = -val; + + //Animation + if (m_PlayerEntity.Valid()) { + EntityWrapper playerModel = m_PlayerEntity.FirstChildByName("PlayerModel"); + if (playerModel.Valid()) { + if (val > 0) { // Walk/Run + Events::AutoAnimationBlend aeb; + aeb.Duration = 0.1; + if (m_Crouching) { + aeb.NodeName = "Walk"; + } else { + aeb.NodeName = "Run"; + } + aeb.RootNode = playerModel; + aeb.Start = true; + aeb.SingleLevelBlend = true; + m_EventBroker->Publish(aeb); + } else if (val < 0) { // Walk/run Backwards + Events::AutoAnimationBlend aeb; + aeb.Duration = 0.1; + if (m_Crouching) { + aeb.NodeName = "Walk"; + } else { + aeb.NodeName = "Run"; + } + aeb.RootNode = playerModel; + aeb.Start = true; + aeb.SingleLevelBlend = true; + aeb.Reverse = true; + m_EventBroker->Publish(aeb); + } + } + + + EntityWrapper firstPersonModel = m_PlayerEntity.FirstChildByName("Hands"); + if (firstPersonModel.Valid()) { + if (val > 0) { // Walk/Run + if (!m_Crouching) { + Events::AutoAnimationBlend aeb; + aeb.Duration = 0.1; + aeb.NodeName = "Run"; + aeb.RootNode = firstPersonModel; + aeb.SingleLevelBlend = true; + aeb.Start = true; + m_EventBroker->Publish(aeb); + } + } else if (val < 0) { // Walk/run Backwards + if (!m_Crouching) { + Events::AutoAnimationBlend aeb; + aeb.Duration = 0.1; + aeb.NodeName = "Run"; + aeb.RootNode = firstPersonModel; + aeb.SingleLevelBlend = true; + aeb.Start = true; + aeb.Reverse = true; + m_EventBroker->Publish(aeb); + } + } + } + } } if (e.Command == "Right") { float val = glm::clamp(e.Value, -1.f, 1.f); m_Movement.x = val; - } - if (glm::length2(m_Movement) > 0) { - m_Movement = glm::normalize(m_Movement); + + + //Animation + if (m_PlayerEntity.Valid()) { + EntityWrapper playerModel = m_PlayerEntity.FirstChildByName("PlayerModel"); + if (playerModel.Valid()) { //Right Strafe + if (val > 0) { + Events::AutoAnimationBlend aeb; + aeb.Duration = 0.1; + aeb.NodeName = "Right"; + aeb.RootNode = playerModel; + aeb.SingleLevelBlend = true; + aeb.Start = true; + m_EventBroker->Publish(aeb); + } else if (val < 0) { //LeftStrafe + Events::AutoAnimationBlend aeb; + aeb.Duration = 0.1; + aeb.NodeName = "Left"; + aeb.RootNode = playerModel; + aeb.SingleLevelBlend = true; + aeb.Start = true; + m_EventBroker->Publish(aeb); + } + } + + EntityWrapper firstPersonModel = m_PlayerEntity.FirstChildByName("Hands"); + if (firstPersonModel.Valid()) { + if (val > 0) { // Walk/Run + if (!m_Crouching) { + Events::AutoAnimationBlend aeb; + aeb.Duration = 0.1; + aeb.NodeName = "Run"; + aeb.RootNode = firstPersonModel; + aeb.SingleLevelBlend = true; + aeb.Start = true; + m_EventBroker->Publish(aeb); + } + } else if (val < 0) { // Walk/run Backwards + if (!m_Crouching) { + Events::AutoAnimationBlend aeb; + aeb.Duration = 0.1; + aeb.NodeName = "Run"; + aeb.RootNode = firstPersonModel; + aeb.SingleLevelBlend = true; + aeb.Start = true; + aeb.Reverse = true; + m_EventBroker->Publish(aeb); + } + } + } + } } } + if (m_PlayerEntity.Valid()) { + glm::vec2 movementXZ = glm::vec2(m_Movement.x, m_Movement.z); + if (glm::length(movementXZ) < 0.1f) { + //Blend to Idle + EntityWrapper playerModel = m_PlayerEntity.FirstChildByName("PlayerModel"); + if (playerModel.Valid()) { + Events::AutoAnimationBlend aeb; + aeb.Duration = 0.1; + aeb.NodeName = "Idle"; + aeb.RootNode = playerModel; + aeb.Start = true; + m_EventBroker->Publish(aeb); + } + EntityWrapper firstPersonModel = m_PlayerEntity.FirstChildByName("Hands"); + if (firstPersonModel.Valid()) { + Events::AutoAnimationBlend aeb; + aeb.Duration = 0.1; + aeb.NodeName = "Idle"; + aeb.RootNode = firstPersonModel; + aeb.Start = true; + m_EventBroker->Publish(aeb); + } + } else { + //Blend to movement + EntityWrapper playerModel = m_PlayerEntity.FirstChildByName("PlayerModel"); + if (playerModel.Valid()) { + Events::AutoAnimationBlend aeb; + aeb.Duration = 0.1; + aeb.NodeName = "DirectionBlend"; + aeb.RootNode = playerModel; + m_EventBroker->Publish(aeb); + } + } + } + + if (glm::length(m_Movement) > 0) { + m_Movement = glm::normalize(m_Movement); + + //Animation + // movement direction blend + if (m_PlayerEntity.Valid()) { + EntityWrapper playerModel = m_PlayerEntity.FirstChildByName("PlayerModel"); + if (playerModel.Valid()) { + glm::vec2 direction = glm::normalize(glm::vec2(m_Movement.x, m_Movement.z)); + double weight = glm::abs(glm::dot(glm::vec2(1, 0), direction)); + Events::SetBlendWeight sbw; + sbw.NodeName = "DirectionBlend"; + sbw.Weight = weight; + sbw.RootNode = playerModel; + m_EventBroker->Publish(sbw); + } + } + } + + + if (e.Command == "Forward" || e.Command == "Right") { if (e.Value != 0) { m_CurrentDirectionVector = e.Command == "Right" ? (e.Value > 0 ? "Right" : "Left") : (e.Value > 0 ? "Forward" : "Backward"); @@ -145,10 +316,10 @@ bool FirstPersonInputController::OnCommand(const Events::InputComm if (m_NumberOfMovementKeysDown == 0) { m_MovementKeyDown = false; } - //you have just released the key, store what key it was and reset the doubletap-sensitivity-timer - m_AssaultDashTapDirection = m_CurrentDirectionVector; - m_AssaultDashDoubleTapDeltaTime = 0.f; - + //you have just released the key, store what key it was and reset the doubletap-sensitivity-timer + m_AssaultDashTapDirection = m_CurrentDirectionVector; + m_AssaultDashDoubleTapDeltaTime = 0.f; + } } @@ -158,21 +329,42 @@ bool FirstPersonInputController::OnCommand(const Events::InputComm if (e.Command == "Crouch") { m_Crouching = e.Value > 0; + + + //Animation + if (m_PlayerEntity.Valid()) { + EntityWrapper playerModel = m_PlayerEntity.FirstChildByName("PlayerModel"); + if (playerModel.Valid()) { + if (e.Value == 0.f) { + Events::AutoAnimationBlend aeb; + aeb.Duration = 0.3; + aeb.NodeName = "StandMovement"; + aeb.RootNode = playerModel; + aeb.Start = true; + aeb.Restart = true; + aeb.SingleLevelBlend = true; + m_EventBroker->Publish(aeb); + } else if(e.Value == 1.0f) { + Events::AutoAnimationBlend aeb; + aeb.Duration = 0.3; + aeb.NodeName = "CrouchMovement"; + aeb.RootNode = playerModel; + aeb.Start = true; + aeb.Restart = true; + aeb.SingleLevelBlend = true; + m_EventBroker->Publish(aeb); + } + } + } + } if (e.Command == "SpecialAbility") { - if (e.Value > 0) { - m_SpecialAbilityKeyDown = true; - } else { - m_SpecialAbilityKeyDown = false; - } - } - if (m_SpecialAbilityKeyDown && m_MovementKeyDown) { - m_ShiftDashing = true; - } else { - m_ShiftDashing = false; + m_SpecialAbilityKeyDown = e.Value > 0; } + m_ShiftDashing = m_SpecialAbilityKeyDown && m_MovementKeyDown; + return true; } @@ -191,23 +383,27 @@ bool FirstPersonInputController::OnLockMouse(const Events::LockMou } template -void FirstPersonInputController::AssaultDashCheck(double dt, bool isJumping, double assaultDashCoolDownMaxTimer) { +void FirstPersonInputController::AssaultDashCheck(double dt, bool isJumping, double assaultDashCoolDownMaxTimer, Field assaultDashCoolDownTimer, EntityID playerID) { m_AssaultDashDoubleTapDeltaTime += dt; - m_AssaultDashCoolDownTimer -= dt; + assaultDashCoolDownTimer -= dt; //cooldown = assaultDashCoolDownMaxTimer sec, pretend the dash lasts 0.25 sec (for friction to do its work) - if (m_AssaultDashCoolDownTimer > (assaultDashCoolDownMaxTimer - 0.25f)) { + if (assaultDashCoolDownTimer > (assaultDashCoolDownMaxTimer - 0.25f)) { m_PlayerIsDashing = true; } else { m_PlayerIsDashing = false; } //dashing with shift - if (m_ShiftDashing && m_AssaultDashCoolDownTimer <= 0.0f) { + if (m_ShiftDashing && assaultDashCoolDownTimer <= 0.0f) { //player is dashing with shift //the wanted-direction is set in playermovement already so we dont need to check what direction we want to dash in! - m_AssaultDashCoolDownTimer = assaultDashCoolDownMaxTimer; + assaultDashCoolDownTimer = assaultDashCoolDownMaxTimer; m_AssaultDashDoubleTapped = true; m_AssaultDashDoubleTapDeltaTime = 0.f; + + Events::DashAbility e; + e.Player = playerID; + m_EventBroker->Publish(e); return; } @@ -227,7 +423,7 @@ void FirstPersonInputController::AssaultDashCheck(double dt, bool } m_ValidDoubleTap = false; - if (!(m_AssaultDashCoolDownTimer <= 0.0f)) { + if (!(assaultDashCoolDownTimer <= 0.0f)) { //if we cant dash at the moment, then just reset the tap-sensitivity-timer m_AssaultDashDoubleTapDeltaTime = 0.f; return; @@ -235,9 +431,10 @@ void FirstPersonInputController::AssaultDashCheck(double dt, bool //ok, we have a valid tap, lets do it m_AssaultDashDoubleTapped = true; m_AssaultDashDoubleTapDeltaTime = 0.f; - m_AssaultDashCoolDownTimer = assaultDashCoolDownMaxTimer; + assaultDashCoolDownTimer = assaultDashCoolDownMaxTimer; Events::DashAbility e; + e.Player = playerID; m_EventBroker->Publish(e); } diff --git a/include/Engine/Input/InputProxy.h b/include/Engine/Input/InputProxy.h index c9ba5ada..a38b8d24 100644 --- a/include/Engine/Input/InputProxy.h +++ b/include/Engine/Input/InputProxy.h @@ -18,7 +18,7 @@ public: void LoadBindings(std::string file); void Update(double dt); - void Process(); + void Process(bool suppressNewEvents = false); template void AddHandler(); void Publish(const Events::InputCommand& e); diff --git a/include/Engine/Network/Client.h b/include/Engine/Network/Client.h index be76e265..a4c2e229 100644 --- a/include/Engine/Network/Client.h +++ b/include/Engine/Network/Client.h @@ -10,35 +10,33 @@ #include #include +#include "Network/EKillDeath.h" +#include "Core/World.h" +#include "Core/EntityFile.h" +#include "Core/EventBroker.h" +#include "Core/ConfigFile.h" +#include "Core/EPlayerDeath.h" +#include "Core/EPlayerDamage.h" +#include "Core/EPlayerSpawned.h" +#include "Core/EAmmoPickup.h" +#include "Game/Events/EDoubleJump.h" +#include "Game/Events/EDashAbility.h" +#include "Game/Events/EReset.h" +#include "Input/EInputCommand.h" +#include "imgui/imgui.h" #include "Network/Network.h" #include "Network/MessageType.h" #include "Network/PlayerDefinition.h" #include "Network/UDPClient.h" #include "Network/TCPClient.h" #include "Network/SnapshotDefinitions.h" -#include "Core/World.h" -#include "Core/EventBroker.h" -#include "Core/ConfigFile.h" -#include "Core/EPlayerDeath.h" -#include "Input/EInputCommand.h" -#include "Core/EPlayerDamage.h" -#include "../Game/Events/EDoubleJump.h" +#include "Network/EDisplayServerlist.h" +#include "Network/EConnectRequest.h" +#include "Network/EPlayerDisconnected.h" +#include "Network/ESearchForServers.h" #include "Network/EInterpolate.h" #include "Network/SnapshotFilter.h" -#include "Core/EPlayerSpawned.h" -#include "Network/ESearchForServers.h" - -struct ServerInfo -{ - ServerInfo(std::string a, int b, std::string c, int d) - { - Address = a; Port = b; Name = c; PlayersConnected = d; - } - std::string Address = ""; - int Port = 0; - std::string Name = ""; - int PlayersConnected = 0; -}; +#include "Core/EWin.h" class Client : public Network { @@ -48,7 +46,7 @@ public: ~Client(); void Connect(std::string address, int port); - void Update() override; + void Update(double dt) override; private: UDPClient m_Unreliable; TCPClient m_Reliable; @@ -82,14 +80,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); @@ -106,7 +104,12 @@ private: void parsePlayerDamage(Packet& packet); void parseComponentDeletion(Packet& packet); void parseDoubleJump(Packet& packet); - void InterpolateFields(Packet & packet, const ComponentInfo & componentInfo, const EntityID & entityID, const std::string & componentType); + void parseDashEffect(Packet& packet); + void parseAmmoPickup(Packet& packet); + void parseRemoveWorld(Packet& packet); + void parseKDEvent(Packet& packet); + void parseWin(Packet& packet); + void InterpolateFields(Packet& packet, const ComponentInfo & componentInfo, const EntityID & entityID, const std::string & componentType); void parseSnapshot(Packet& packet); void identifyPacketLoss(); void hasServerTimedOut(); @@ -115,6 +118,7 @@ private: void sendLocalPlayerTransform(); void becomePlayer(); void displayServerlist(); + void createMainMenu(); // Mapping Logic // Returns if local EntityID exist in map bool clientServerMapsHasEntity(EntityID clientEntityID); @@ -133,12 +137,17 @@ private: EventRelay< Client, Events::SearchForServers> m_ESearchForServers; EventRelay m_EDoubleJump; bool OnDoubleJump(Events::DoubleJump & e); + EventRelay m_EDashAbility; + bool OnDashAbility(const Events::DashAbility& e); + EventRelay m_EConnectRequest; + bool OnConnectRequest(const Events::ConnectRequest& e); + bool OnSearchForServers(const Events::SearchForServers& e); 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/EConnectRequest.h b/include/Engine/Network/EConnectRequest.h new file mode 100644 index 00000000..b6bf781b --- /dev/null +++ b/include/Engine/Network/EConnectRequest.h @@ -0,0 +1,17 @@ +#ifndef Events_ConnectRequest_h__ +#define Events_ConnectRequest_h__ + +#include "Core/EventBroker.h" + +namespace Events +{ + +struct ConnectRequest : public Event +{ + std::string IP = ""; + int Port = 0; +}; + +} +#endif + diff --git a/include/Engine/Network/EDisplayServerlist.h b/include/Engine/Network/EDisplayServerlist.h new file mode 100644 index 00000000..d80ad1ba --- /dev/null +++ b/include/Engine/Network/EDisplayServerlist.h @@ -0,0 +1,29 @@ +#ifndef Events_DisplayServerlist_h__ +#define Events_DisplayServerlist_h__ + +#include +#include +#include "Core/Event.h" + +struct ServerInfo +{ + ServerInfo(std::string address, int port, std::string name, int players) + { + Address = address; Port = port; Name = name; PlayersConnected = players; + } + std::string Address = ""; + int Port = 0; + std::string Name = ""; + int PlayersConnected = 0; +}; + +namespace Events +{ + +struct DisplayServerlist : public Event +{ + std::vector Serverlist; +}; + +} +#endif diff --git a/include/Engine/Network/EKillDeath.h b/include/Engine/Network/EKillDeath.h new file mode 100644 index 00000000..04917f39 --- /dev/null +++ b/include/Engine/Network/EKillDeath.h @@ -0,0 +1,30 @@ +#ifndef Events_KillDeath_h__ +#define Events_KillDeath_h__ + +#include "Core/EventBroker.h" + +typedef unsigned int PlayerID; + +namespace Events +{ + +struct KillDeath : public Event +{ + int CasualtyTeam; + PlayerID Casualty = -1; + std::string CasualtyName; + + //1 = assault, 2 = defender, 3 = sniper + int CasualtyClass; + + int KillerTeam; + PlayerID Killer = -1; + std::string KillerName; + + //1 = assault, 2 = defender, 3 = sniper + int KillerClass; +}; + +} + +#endif \ No newline at end of file diff --git a/include/Engine/Network/EPlayerConnected.h b/include/Engine/Network/EPlayerConnected.h new file mode 100644 index 00000000..8c12dd3d --- /dev/null +++ b/include/Engine/Network/EPlayerConnected.h @@ -0,0 +1,17 @@ +#ifndef Events_PlayerConnected +#define Events_PlayerConnected + +#include "Core/EventBroker.h" + +namespace Events +{ + +struct PlayerConnected : public Event +{ + std::string PlayerName = ""; + int PlayerID = -1; +}; + +} +#endif // !Events_PlayerConnected + diff --git a/include/Engine/Network/MessageType.h b/include/Engine/Network/MessageType.h index 00a2a91f..d69b468b 100644 --- a/include/Engine/Network/MessageType.h +++ b/include/Engine/Network/MessageType.h @@ -20,7 +20,12 @@ enum class MessageType ComponentDeleted, PlayerTransform, OnDoubleJump, + OnDashEffect, ServerlistRequest, + AmmoPickup, + RemoveWorld, + KD, + Win, 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/NetworkClient.h b/include/Engine/Network/NetworkClient.h index 4adc68f5..1b6af2ea 100644 --- a/include/Engine/Network/NetworkClient.h +++ b/include/Engine/Network/NetworkClient.h @@ -11,7 +11,7 @@ class NetworkClient public: NetworkClient(); virtual ~NetworkClient(); - virtual void Connect(std::string playerName, std::string address, int port) = 0; + virtual bool Connect(std::string playerName, std::string address, int port) = 0; virtual void Disconnect() = 0; virtual void Receive(Packet& packet) = 0; virtual void Send(Packet & packet) = 0; diff --git a/include/Engine/Network/Packet.h b/include/Engine/Network/Packet.h index 95419e10..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 @@ -24,7 +26,10 @@ public: { // Check if we are trying to add more than the package can fit. if (m_MaxPacketSize < m_Offset + sizeof(T)) { - //LOG_WARNING("Packet AddPrimitive(): You are trying to add more than we have allocated for! New size is %i bytes\n", m_MaxPacketSize*2); + if (m_MaxPacketSize >= 32000) { + // 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(); } memcpy(m_Data + m_Offset, &val, sizeof(T)); @@ -55,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; @@ -70,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 aac4e4c8..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" @@ -20,6 +21,12 @@ #include "../Game/Events/EDoubleJump.h" #include "Core/EEntityDeleted.h" #include "Core/EComponentDeleted.h" +#include "Core/EAmmoPickup.h" +#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 { @@ -27,7 +34,7 @@ public: Server(World* world, EventBroker* eventBroker, int port); ~Server(); - void Update() override; + void Update(double dt) override; private: // Network channels @@ -37,6 +44,7 @@ private: // 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; @@ -44,18 +52,19 @@ 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 std::clock_t m_StartPingTime; + std::string m_ServerName = ""; // Packet loss logic PacketID m_PacketID = 0; @@ -66,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); @@ -76,19 +86,22 @@ private: void parseOnPlayerDamage(Packet& packet); void identifyPacketLoss(); void kick(PlayerID player); - PlayerID GetPlayerIDFromEndpoint(); + PlayerID getPlayerIDFromEndpoint(); + PlayerID getPlayerIDFromEntityID(EntityID entityID); + void resetMap(); void parsePlayerTransform(Packet& packet); void parseOnInputCommand(Packet& packet); void parseClientPing(); void parsePing(); bool parseDoubleJump(Packet& packet); + void parseDashEffect(Packet& packet); void parseUDPConnect(Packet& packet); void parseTCPConnect(Packet& packet); void parseDisconnect(); void parseServerlistRequest(boost::asio::ip::udp::endpoint endpoint); bool shouldSendToClient(EntityWrapper childEntity); - // Debug event + // Events EventRelay m_EInputCommand; bool OnInputCommand(const Events::InputCommand& e); EventRelay m_EPlayerSpawned; @@ -99,6 +112,12 @@ private: bool OnComponentDeleted(const Events::ComponentDeleted& e); EventRelay m_EPlayerDamage; bool OnPlayerDamage(const Events::PlayerDamage& e); + EventRelay m_EAmmoPickup; + 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/TCPClient.h b/include/Engine/Network/TCPClient.h index 2108fa3d..13bd2db5 100644 --- a/include/Engine/Network/TCPClient.h +++ b/include/Engine/Network/TCPClient.h @@ -10,7 +10,7 @@ public: TCPClient(); ~TCPClient(); - void Connect(std::string playerName, std::string address, int port); + bool Connect(std::string playerName, std::string address, int port); void Disconnect(); void Receive(Packet& packet); void Send(Packet & packet); diff --git a/include/Engine/Network/UDPClient.h b/include/Engine/Network/UDPClient.h index 42c27783..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" @@ -10,19 +12,30 @@ public: UDPClient(); ~UDPClient(); - void Connect(std::string playerName, std::string address, int port); + 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/AnimationSystem.h b/include/Engine/Rendering/AnimationSystem.h index dbe4b3fc..0305e7c7 100644 --- a/include/Engine/Rendering/AnimationSystem.h +++ b/include/Engine/Rendering/AnimationSystem.h @@ -3,27 +3,41 @@ #include "GLM.h" -#include "Common.h" -#include "Core/System.h" -#include "Core/ResourceManager.h" +#include "../Common.h" +#include "../Core/System.h" +#include "../Core/ResourceManager.h" #include "Rendering/Model.h" -#include "Rendering/EAnimationComplete.h" #include "Rendering/Skeleton.h" -#include +#include "Rendering/BlendTree.h" +#include "Rendering/EAutoAnimationBlend.h" +#include "../Core/EntityWrapper.h" +#include "Rendering/AutoBlendQueue.h" +#include "../Input/EInputCommand.h" +#include "../Core/EEntityDeleted.h" +#include "Rendering/ESetBlendWeight.h" +#include "imgui/imgui.h" -class AnimationSystem : public PureSystem +class AnimationSystem : public ImpureSystem { public: - AnimationSystem(SystemParams params) - : System(params) - , PureSystem("Animation") - { - - } + AnimationSystem(SystemParams params); ~AnimationSystem() { } - virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& animationComponent, double dt) override; + virtual void Update(double dt) override; private: + void CreateBlendTrees(); + void UpdateAnimations(double dt); + void UpdateWeights(double dt); + EventRelay m_EAutoAnimationBlend; + bool OnAutoAnimationBlend(Events::AutoAnimationBlend& e); + + EventRelay m_EEntityDeleted; + bool OnEntityDeleted(Events::EntityDeleted& e); + + EventRelay m_ESetBlendWeight; + bool OnSetBlendWeight(Events::SetBlendWeight& e); + + std::unordered_map m_AutoBlendQueues; }; #endif \ No newline at end of file diff --git a/include/Engine/Rendering/AutoBlendQueue.h b/include/Engine/Rendering/AutoBlendQueue.h new file mode 100644 index 00000000..71fe46d8 --- /dev/null +++ b/include/Engine/Rendering/AutoBlendQueue.h @@ -0,0 +1,48 @@ +#ifndef AutoBlendQueue_h__ +#define AutoBlendQueue_h__ + +#include "../Core/ResourceManager.h" +#include "Skeleton.h" +#include "Model.h" +#include "BlendTree.h" +#include "../Core/EntityWrapper.h" + +class AutoBlendQueue +{ +public: + struct AutoBlendJob + { + EntityWrapper RootNode = EntityWrapper::Invalid; + double Duration; + double CurrentTime = 0.0; + double Delay = 0.0; + EntityWrapper AnimationEntity = EntityWrapper::Invalid; + BlendTree::AutoBlendInfo BlendInfo; + }; + + struct AutoblendNode + { + AutoBlendJob BlendJob; + double StartTime; + double EndTime; + }; + + AutoBlendQueue() { }; + + void Insert(AutoBlendJob autoBlendJob); + void UpdateTime(double dt); + + void PrintQueue(); + bool HasActiveBlendJob(); + std::shared_ptr GetBlendTree(); + + AutoBlendQueue::AutoBlendJob& GetActiveBlendJob(); + + bool Empty() { return m_BlendQueue.empty(); } +private: + std::list m_BlendQueue; + + +}; + +#endif diff --git a/include/Engine/Rendering/BlendTree.h b/include/Engine/Rendering/BlendTree.h new file mode 100644 index 00000000..46ea7f0c --- /dev/null +++ b/include/Engine/Rendering/BlendTree.h @@ -0,0 +1,103 @@ +#ifndef BlendTree_h__ +#define BlendTree_h__ + +#include "Common.h" +#include "../GLM.h" +#include "Skeleton.h" +#include "../Core/EntityWrapper.h" +#include "../Core/World.h" +#include + +class BlendTree +{ +public: + enum class NodeType + { + Additive, + Blend, + Override, + Animation, + }; + + + + struct Node + { + std::string Name; + EntityWrapper Entity; + Node* Parent = nullptr; + Node* Child[2] = { nullptr, nullptr }; + NodeType Type; + std::map Pose; + bool SubTreeRoot = false; + double Weight = 0.0; + + Node* Next() { + Node* next = this; + + if (next->Child[1] == nullptr) { + // Node has no right child + next = this; + while (next->Parent != nullptr && next == next->Parent->Child[1]) { + next = next->Parent; + } + next = next->Parent; + } else { + // Find the leftmost node in the right subtree + next = next->Child[1]; + while (next->Child[0] != nullptr) { + next = next->Child[0]; + } + } + return next; + } + }; + + + struct AutoBlendInfo + { + std::string NodeName; + double progress; + bool Start; + bool SingleBlend; + double Weight; + std::unordered_map StartWeights; + }; + + + + BlendTree(EntityWrapper ModelEntity, Skeleton* skeleton); + ~BlendTree(); + + + std::vector GetFinalPose() { return m_FinalPose; } + glm::mat4 GetBoneTransform(int boneID); + bool IsValid() { return (m_Root == nullptr ? false : true); } + void PrintTree(); + BlendTree::AutoBlendInfo AutoBlendStep(AutoBlendInfo blendInfo); + + BlendTree::Node* GetCommonParent(std::string NodeName1, std::string NodeName2); + BlendTree::Node* FirstCommonParent(Node* node1, Node* node2); + + EntityWrapper GetSubTreeRoot(std::string nodeName); + std::vector GetSubTreeRoots(std::string nodeName); + + std::vector GetSingleLevelRoots(std::string name); + std::vector GetEntitesByName(std::string name); + + void SetWeightByName(std::string name, double weight); + +private: + Skeleton* m_Skeleton = nullptr; + Node* m_Root = nullptr; + + std::vector m_FinalPose; + std::map m_FinalBoneTransforms; + std::vector FindNodesByName(std::string name); + std::vector AccumulateFinalPose(); + BlendTree::Node* FillTreeByName(Node* parentNode, std::string name, EntityWrapper parentEntity); + + void Blend(std::map& pose); +}; + +#endif diff --git a/include/Engine/Rendering/BlurHUD.h b/include/Engine/Rendering/BlurHUD.h new file mode 100644 index 00000000..783e8a2f --- /dev/null +++ b/include/Engine/Rendering/BlurHUD.h @@ -0,0 +1,70 @@ +#ifndef BlurHUD_h__ +#define BlurHUD_h__ + +#include "IRenderer.h" +#include "DrawBloomPassState.h" +//#include "LightCullingPass.h" Finalpass om den skall skickas in +#include "FrameBuffer.h" +#include "ShaderProgram.h" +//#include "Util/UnorderedMapVec2.h" +#include "Texture.h" + +class BlurHUD +{ +public: + BlurHUD(IRenderer* renderer); + ~BlurHUD() { } + void InitializeTextures(); + void InitializeFrameBuffers(); + void InitializeShaderPrograms(); + void InitializeBuffers(); + void ClearBuffer(); + + void FillGaussianBuffer(FrameBuffer* fb); + + GLuint Draw(GLuint texture, RenderScene& scene); + + void OnWindowResize(); + void FillStencil(RenderScene& scene); + GLuint CombineTextures(GLuint texture1, GLuint texture2); + + //Getters + //Return the blurred result of the texture that was sent into draw + GLuint GaussianTexture() const { + if (m_Quality == 0) { + return m_BlackTexture->m_Texture; + } else { + return m_GaussianTexture_vert; + } + } + + +private: + Texture* m_BlackTexture; + Model* m_ScreenQuad; + + const IRenderer* m_Renderer; + ConfigFile* m_Config; + //const LightCullingPass* m_LightCullingPass + int m_Iterations = 3; + int m_Quality = 0; + float m_BlurQuality = 4.f; + + GLuint m_GaussianTexture_horiz = 0; + GLuint m_GaussianTexture_vert = 0; + GLuint m_DepthStencil_horiz = 0; + GLuint m_DepthStencil_vert = 0; + GLuint m_CombinedTexture = 0; + + FrameBuffer m_GaussianFrameBuffer_horiz; + FrameBuffer m_GaussianFrameBuffer_vert; + FrameBuffer m_CombinedTextureBuffer; + + ShaderProgram* m_GaussianProgram_horiz; + ShaderProgram* m_GaussianProgram_vert; + ShaderProgram* m_FillDepthStencilProgram; + ShaderProgram* m_CombineTexturesProgram; + +}; + +#endif \ No newline at end of file diff --git a/include/Engine/Rendering/BoneAttachmentSystem.h b/include/Engine/Rendering/BoneAttachmentSystem.h index 55c2a1c8..2791d877 100644 --- a/include/Engine/Rendering/BoneAttachmentSystem.h +++ b/include/Engine/Rendering/BoneAttachmentSystem.h @@ -8,6 +8,7 @@ #include "Core/ResourceManager.h" #include "Rendering/Model.h" #include "Rendering/Skeleton.h" +#include "Rendering/BlendTree.h" //Needs to be a higher orderlevel than AnimationSystem class BoneAttachmentSystem : public PureSystem diff --git a/include/Engine/Rendering/CubeMapPass.h b/include/Engine/Rendering/CubeMapPass.h index 3cda8cad..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 { @@ -15,13 +16,13 @@ public: void GenerateCubeMapTexture(); //GLuint CubeMapTexture() const { return m_CubeMapTexture; } - GLuint m_CubeMapTexture = -1; + GLuint m_CubeMapTexture = 0; 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/DDS.h b/include/Engine/Rendering/DDS.h new file mode 100644 index 00000000..18e06f78 --- /dev/null +++ b/include/Engine/Rendering/DDS.h @@ -0,0 +1,71 @@ +#ifndef DDS_h__ +#define DDS_h__ + +#include + +#include "../Common.h" +#include "../Core/ResourceManager.h" +#include "Image.h" + +// DXT5 +class DDS : public Image, public Resource +{ +public: + DDS(std::string path); + ~DDS(); + + void FlipY(unsigned char* data, std::size_t rowBytes, std::size_t totalSize, std::size_t numBlocksWide); + +private: + static const uint32_t MagicNumber = 0x20534444; // "DDS " + + struct Header_t + { + uint32_t Size; + uint32_t Flags; + uint32_t Height; + uint32_t Width; + uint32_t PitchOrLinearSize; + uint32_t Depth; + uint32_t MipMapCount; + uint32_t RESERVED1[11]; + struct PixelFormat_t + { + uint32_t Size; + uint32_t Flags; + uint32_t FourCC; + uint32_t RGBBitCount; + uint32_t RBitMask; + uint32_t GBitMask; + uint32_t BBitMask; + uint32_t ABitMask; + } PixelFormat; + uint32_t Caps; + uint32_t Caps2; + uint32_t Caps3; + uint32_t Caps4; + uint32_t RESERVED2; + } m_Header; + + struct Block_t + { + struct Alpha_t + { + uint8_t Colors[2]; + uint8_t Data[6]; + } Alpha; + struct Data_t + { + uint16_t Colors[2]; + uint8_t Data[4]; + } Data; + }; + + std::size_t m_NumBlocksWide; + std::size_t m_NumBlocksHigh; + std::size_t m_RowBytes; + + void flipBlock(Block_t* block); +}; + +#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/DrawBloomPass.h b/include/Engine/Rendering/DrawBloomPass.h index 07c90e23..eaf17570 100644 --- a/include/Engine/Rendering/DrawBloomPass.h +++ b/include/Engine/Rendering/DrawBloomPass.h @@ -12,8 +12,8 @@ class DrawBloomPass { public: - DrawBloomPass(IRenderer* renderer /* ,Texture or finalpass*/ ); - ~DrawBloomPass() { } + DrawBloomPass(IRenderer* renderer, ConfigFile* config); + ~DrawBloomPass(); void InitializeTextures(); void InitializeFrameBuffers(); void InitializeShaderPrograms(); @@ -23,32 +23,45 @@ public: void FillGaussianBuffer(FrameBuffer* fb); void Draw(GLuint texture); + void ChangeQuality(int quality); void OnWindowResize(); //Getters //Return the blurred result of the texture that was sent into draw - GLuint GaussianTexture() const { return m_GaussianTexture_vert; } + GLuint GaussianTexture() const { + if (m_Quality == 0) { + return m_BlackTexture->m_Texture; + } else { + return m_FinalGaussianTexture; + } + } private: - void GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type) const; - - Texture* m_WhiteTexture; + void GaussianLodPass(GLuint mipMap, GLuint texture); + void CombineGaussianBlur(); + Texture* m_BlackTexture; Model* m_ScreenQuad; const IRenderer* m_Renderer; + ConfigFile* m_Config; //const LightCullingPass* m_LightCullingPass - GLuint m_iterations = 9; + int m_Iterations; + int m_Quality = 0; + int m_BloomLod = 5; - GLuint m_GaussianTexture_horiz; - GLuint m_GaussianTexture_vert; + GLuint m_GaussianTexture_horiz = 0; + GLuint m_GaussianTexture_vert = 0; + GLuint m_FinalGaussianTexture = 0; - FrameBuffer m_GaussianFrameBuffer_horiz; - FrameBuffer m_GaussianFrameBuffer_vert; + FrameBuffer* m_GaussianFrameBuffer_horiz = nullptr; + FrameBuffer* m_GaussianFrameBuffer_vert = nullptr; + FrameBuffer m_GaussianCombineBuffer; ShaderProgram* m_GaussianProgram_horiz; ShaderProgram* m_GaussianProgram_vert; + ShaderProgram* m_GaussianCombineProgram; }; diff --git a/include/Engine/Rendering/DrawColorCorrectionPass.h b/include/Engine/Rendering/DrawColorCorrectionPass.h index 231e2d33..fcde73d7 100644 --- a/include/Engine/Rendering/DrawColorCorrectionPass.h +++ b/include/Engine/Rendering/DrawColorCorrectionPass.h @@ -17,7 +17,7 @@ public: void InitializeFrameBuffers(); void InitializeShaderPrograms(); - void Draw(GLuint sceneTexture, GLuint bloomTexture, GLuint sceneTextureLowRes, GLuint bloomTextureLowRes, GLfloat gamma, GLfloat exposure); + void Draw(GLuint sceneTexture, GLuint bloomTexture, GLfloat gamma, GLfloat exposure); private: const IRenderer* m_Renderer; diff --git a/include/Engine/Rendering/DrawFinalPass.h b/include/Engine/Rendering/DrawFinalPass.h index 1800c90e..2d333059 100644 --- a/include/Engine/Rendering/DrawFinalPass.h +++ b/include/Engine/Rendering/DrawFinalPass.h @@ -5,43 +5,104 @@ #include "DrawFinalPassState.h" #include "LightCullingPass.h" #include "CubeMapPass.h" +#include "SSAOPass.h" #include "FrameBuffer.h" #include "ShaderProgram.h" #include "Util/UnorderedMapVec2.h" #include "Util/CommonFunctions.h" #include "Texture.h" +#include "ShadowPass.h" +#include "BlurHUD.h" class DrawFinalPass { public: - DrawFinalPass(IRenderer* renderer, LightCullingPass* lightCullingPass, CubeMapPass* cubeMapPass); - ~DrawFinalPass() { } + DrawFinalPass(IRenderer* renderer, LightCullingPass* lightCullingPass, CubeMapPass* cubeMapPass, SSAOPass* ssaoPass, ShadowPass* shadowPass, ConfigFile* config); + ~DrawFinalPass(); void InitializeTextures(); void InitializeFrameBuffers(); void InitializeShaderPrograms(); - void Draw(RenderScene& scene, GLuint SSAOTexture); + void Draw(RenderScene& scene, BlurHUD* blurHUDPass); void ClearBuffer(); void OnWindowResize(); + void setMSAA(unsigned int numberOfSamples); //Return the texture that is used in later stages to apply the bloom effect - GLuint BloomTexture() const { return m_BloomTexture; } - GLuint BloomTextureLowRes() const { return m_BloomTextureLowRes; } + GLuint BloomTexture() { + if (m_MSAA){ + m_AntiAliasedFrameBuffer->Bind(); + glClearColor(0.f, 0.f, 0.f, 0.f); + glClear(GL_COLOR_BUFFER_BIT); + m_AntiAliasedFrameBuffer->Unbind(); + m_FinalPassFrameBuffer->Read(); + glReadBuffer(GL_COLOR_ATTACHMENT1); + m_AntiAliasedFrameBuffer->Draw(); + glBlitFramebuffer( + 0, 0, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height, + 0, 0, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height, + GL_COLOR_BUFFER_BIT, GL_NEAREST); + return m_AntiAliasedTexture; + } + return m_BloomTexture; } //Return the texture with diffuse and lighting of the scene. - GLuint SceneTexture() const { return m_SceneTexture; } - GLuint SceneTextureLowRes() const { return m_SceneTextureLowRes; } + GLuint DrawFinalPass::SceneTexture() { + if (m_MSAA) { + m_AntiAliasedFrameBuffer->Bind(); + glClearColor(0.f, 0.f, 0.f, 0.f); + glClear(GL_COLOR_BUFFER_BIT); + m_AntiAliasedFrameBuffer->Unbind(); + m_FinalPassFrameBuffer->Read(); + glReadBuffer(GL_COLOR_ATTACHMENT0); + m_AntiAliasedFrameBuffer->Draw(); + glBlitFramebuffer( + 0, 0, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height, + 0, 0, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height, + GL_COLOR_BUFFER_BIT, GL_NEAREST); + return m_AntiAliasedTexture; + } + return m_SceneTexture; + } + //Return the SceneTexture with the blurred HUD bits. + GLuint CombinedSceneTexture() { + if (m_MSAA) { + m_AntiAliasedFrameBuffer->Bind(); + glClearColor(0.f, 0.f, 0.f, 0.f); + glClear(GL_COLOR_BUFFER_BIT); + m_AntiAliasedFrameBuffer->Unbind(); + m_FinalPassFrameBuffer->Read(); + m_AntiAliasedFrameBuffer->Draw(); + glBlitFramebuffer( + 0, 0, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height, + 0, 0, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height, + GL_COLOR_BUFFER_BIT, GL_NEAREST); + return m_AntiAliasedTexture; + } + return m_CombinedTexture; } + //Return the blurred scene texture. + GLuint FullBlurredTexture() { + if (m_MSAA) { + m_AntiAliasedFrameBuffer->Bind(); + glClearColor(0.f, 0.f, 0.f, 0.f); + glClear(GL_COLOR_BUFFER_BIT); + m_AntiAliasedFrameBuffer->Unbind(); + m_FinalPassFrameBuffer->Read(); + m_AntiAliasedFrameBuffer->Draw(); + glBlitFramebuffer( + 0, 0, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height, + 0, 0, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height, + GL_COLOR_BUFFER_BIT, GL_NEAREST); + return m_AntiAliasedTexture; + } + return m_FullBlurredTexture; } //Return the framebuffer used in the scene rendering stage. - FrameBuffer* FinalPassFrameBuffer() { return &m_FinalPassFrameBuffer; } - FrameBuffer* FinalPassFrameBufferLowRes() { return &m_FinalPassFrameBufferLowRes; } + FrameBuffer* FinalPassFrameBuffer() { return m_FinalPassFrameBuffer; } private: - void GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type) const; - void GenerateMipMapTexture(GLuint* texture, GLenum wrapping, glm::vec2 dimensions, GLint format, GLenum type, GLint numMipMaps) const; - void DrawSprites(std::list>&jobs, RenderScene& scene); - void DrawModelRenderQueues(std::list>& jobs, RenderScene& scene, GLuint SSAOTexture); - void DrawShieldToStencilBuffer(std::list>& jobs, RenderScene& scene); + void DrawModelRenderQueues(std::list>& jobs, RenderScene& scene); + void DrawModelRenderQueuesWithShieldCheck(std::list>& jobs, RenderScene& scene); void DrawShieldedModelRenderQueue(std::list>& jobs, RenderScene& scene); - void DrawToDepthBuffer(std::list>& jobs, RenderScene& scene); + void DrawToDepthStencilBuffer(std::list>& jobs, RenderScene& scene); void BindExplosionUniforms(GLuint shaderHandle, std::shared_ptr& job, RenderScene& scene); void BindModelUniforms(GLuint shaderHandle, std::shared_ptr& job, RenderScene& scene); @@ -55,38 +116,54 @@ private: Texture* m_GreyTexture; Texture* m_ErrorTexture; - FrameBuffer m_FinalPassFrameBuffer; - FrameBuffer m_FinalPassFrameBufferLowRes; - GLuint m_BloomTexture; - GLuint m_SceneTexture; - GLuint m_BloomTextureLowRes; - GLuint m_SceneTextureLowRes; - GLuint m_DepthBuffer; - GLuint m_DepthBufferLowRes; - GLuint m_CubeMapTexture; + FrameBuffer* m_FinalPassFrameBuffer = nullptr; + FrameBuffer* m_ShieldDepthFrameBuffer = nullptr; + FrameBuffer* m_AntiAliasedFrameBuffer = nullptr; + GLuint m_BloomTexture = 0; + GLuint m_SceneTexture = 0; + GLuint m_DepthBuffer = 0; + GLuint m_ShieldBuffer = 0; + GLuint m_CubeMapTexture = 0; + GLuint m_FullBlurredTexture = 0; + GLuint m_CombinedTexture = 0; //This can be removed for less memory usage, just set m_sceneTexture to the return from m_BlurHUDPass.CombineTextures + GLuint m_AntiAliasedTexture = 0; //Is only used when MSAA is active; //maqke this component based i guess? GLuint m_ShieldPixelRate = 16; + unsigned int m_MSAA = 0; const IRenderer* m_Renderer; const LightCullingPass* m_LightCullingPass; const CubeMapPass* m_CubeMapPass; + const SSAOPass* m_SSAOPass; + const ShadowPass* m_ShadowPass; ShaderProgram* m_ForwardPlusProgram; ShaderProgram* m_ExplosionEffectProgram; ShaderProgram* m_ExplosionEffectSplatMapProgram; ShaderProgram* m_SpriteProgram; ShaderProgram* m_ForwardPlusSplatMapProgram; - ShaderProgram* m_ShieldToStencilProgram; - ShaderProgram* m_FillDepthBufferProgram; + ShaderProgram* m_FillDepthStencilBufferProgram; + + ShaderProgram* m_ForwardPlusShieldCheckProgram; + ShaderProgram* m_ExplosionEffectShieldCheckProgram; + ShaderProgram* m_ExplosionEffectSplatMapShieldCheckProgram; + ShaderProgram* m_SpriteShieldCheckProgram; + ShaderProgram* m_ForwardPlusSplatMapShieldCheckProgram; + ShaderProgram* m_ForwardPlusSkinnedProgram; ShaderProgram* m_ExplosionEffectSkinnedProgram; ShaderProgram* m_ExplosionEffectSplatMapSkinnedProgram; ShaderProgram* m_ForwardPlusSplatMapSkinnedProgram; - ShaderProgram* m_ShieldToStencilSkinnedProgram; - ShaderProgram* m_FillDepthBufferSkinnedProgram; + ShaderProgram* m_FillDepthStencilBufferSkinnedProgram; + + ShaderProgram* m_ForwardPlusSkinnedShieldCheckProgram; + ShaderProgram* m_ExplosionEffectSkinnedShieldCheckProgram; + ShaderProgram* m_ExplosionEffectSplatMapSkinnedShieldCheckProgram; + ShaderProgram* m_ForwardPlusSplatMapSkinnedShieldCheckProgram; + ShaderProgram* m_FillDepthBufferSkinnedShieldCheckProgram; }; #endif \ No newline at end of file diff --git a/include/Engine/Rendering/EAutoAnimationBlend.h b/include/Engine/Rendering/EAutoAnimationBlend.h new file mode 100644 index 00000000..86921f0f --- /dev/null +++ b/include/Engine/Rendering/EAutoAnimationBlend.h @@ -0,0 +1,28 @@ +#ifndef Events_AutoAnimationBlend_h__ +#define Events_AutoAnimationBlend_h__ + +#include "../Core/EventBroker.h" +#include "../Core/EntityWrapper.h" + +namespace Events +{ + +struct AutoAnimationBlend : Event +{ + EntityWrapper RootNode = EntityWrapper::Invalid; + std::string NodeName; + double Duration = 0.0; + double Delay = 0.0; + + bool Start = false; + bool Reverse = false; + bool Restart = false; + bool SingleLevelBlend = false; + double Weight = -1.0; + + EntityWrapper AnimationEntity = EntityWrapper::Invalid; +}; + +} + +#endif diff --git a/include/Engine/Rendering/EResolutionChanged.h b/include/Engine/Rendering/EResolutionChanged.h new file mode 100644 index 00000000..220a2c74 --- /dev/null +++ b/include/Engine/Rendering/EResolutionChanged.h @@ -0,0 +1,19 @@ +#ifndef EResolutionChanged_h__ +#define EResolutionChanged_h__ + +#include "../Core/Event.h" +#include "../Core/Util/Rectangle.h" + +namespace Events +{ + +// Fired when the framebuffer size changes +struct ResolutionChanged : Event +{ + Rectangle OldResolution; + Rectangle NewResolution; +}; + +} + +#endif \ No newline at end of file diff --git a/include/Engine/Rendering/ESetBlendWeight.h b/include/Engine/Rendering/ESetBlendWeight.h new file mode 100644 index 00000000..2a455d88 --- /dev/null +++ b/include/Engine/Rendering/ESetBlendWeight.h @@ -0,0 +1,20 @@ +#ifndef Events_SetBlendWeight_h__ +#define Events_SetBlendWeight_h__ + +#include "../Core/EventBroker.h" +#include "../Core/EntityWrapper.h" + +namespace Events +{ + +//Sets the blend weight for all nodes with "NodeName" +struct SetBlendWeight : Event +{ + EntityWrapper RootNode = EntityWrapper::Invalid; + std::string NodeName; + double Weight; +}; + +} + +#endif diff --git a/include/Engine/Rendering/ExplosionEffectJob.h b/include/Engine/Rendering/ExplosionEffectJob.h index 8f339526..d43c8476 100644 --- a/include/Engine/Rendering/ExplosionEffectJob.h +++ b/include/Engine/Rendering/ExplosionEffectJob.h @@ -15,18 +15,20 @@ 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) - : ModelJob(model, camera, matrix, matGroup, modelComponent, world, fillColor, fillPercentage) + 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/FrameBuffer.h b/include/Engine/Rendering/FrameBuffer.h index cf63b6c6..a4f5fed5 100644 --- a/include/Engine/Rendering/FrameBuffer.h +++ b/include/Engine/Rendering/FrameBuffer.h @@ -7,11 +7,13 @@ class BufferResource { public: - BufferResource(GLuint* resourceHandle, GLenum resourceType, GLenum attachment); + BufferResource(GLuint* resourceHandle, GLenum resourceType, GLenum attachment, GLuint mipMapLod, bool multiSampling); GLuint* m_ResourceHandle; GLenum m_ResourceType; GLenum m_Attachment; + GLuint m_MipMapLod = 0; + bool m_MultiSampling = false; private: }; @@ -20,29 +22,49 @@ template class ResourceType : public BufferResource { public: - ResourceType(GLuint* resourceHandle, GLenum attachment) - : BufferResource(resourceHandle, RESOURCETYPE, attachment) { } + ResourceType(GLuint* resourceHandle, GLenum attachment, GLuint mipMapLod, bool multiSampling) + : BufferResource(resourceHandle, RESOURCETYPE, attachment, mipMapLod, multiSampling) { } }; class Texture2D : public ResourceType { public: - Texture2D(GLuint* resourceHandle, GLenum attachment) - : ResourceType(resourceHandle, attachment) { }; + Texture2D(GLuint* resourceHandle, GLenum attachment, GLuint mipMapLod = 0) + : ResourceType(resourceHandle, attachment, mipMapLod, false) { }; ~Texture2D(); }; +class Texture2DMultiSample : public ResourceType +{ +public: + Texture2DMultiSample(GLuint* resourceHandle, GLenum attachment, GLuint mipMapLod = 0) + : ResourceType(resourceHandle, attachment, mipMapLod, true) { }; + + ~Texture2DMultiSample(); +}; + class RenderBuffer : public ResourceType { public: - RenderBuffer(GLuint* resourceHandle, GLenum attachment) - : ResourceType(resourceHandle, attachment) + RenderBuffer(GLuint* resourceHandle, GLenum attachment, bool multiSampling = false) + : ResourceType(resourceHandle, attachment, 0, multiSampling) { }; ~RenderBuffer(); }; +class Texture2DArray : public ResourceType +{ +public: + Texture2DArray(GLuint* resourceHandle, GLenum attachment) + : ResourceType(resourceHandle, attachment, 0, false) + { }; + + ~Texture2DArray(); +}; + + class FrameBuffer { public: @@ -54,9 +76,13 @@ public: void Generate(); void Bind(); void Unbind(); + void Read(); + void Draw(); GLuint GetHandle(); + bool MultiSampling() { return m_MultiSampling; }; private: + bool m_MultiSampling = true; GLuint m_BufferHandle; std::vector> m_Resources; }; diff --git a/include/Engine/Rendering/IRenderer.h b/include/Engine/Rendering/IRenderer.h index 4441bb7d..2e6f3a97 100644 --- a/include/Engine/Rendering/IRenderer.h +++ b/include/Engine/Rendering/IRenderer.h @@ -5,11 +5,13 @@ #include "../OpenGL.h" #include "../GLM.h" #include "../Core/Util/Rectangle.h" +#include "../Core/ConfigFile.h" #include "Util/ScreenCoords.h" #include "Camera.h" #include "RenderQueue.h" #include "Model.h" #include "../Core/World.h" //So temp +#include "Util/CommonFunctions.h" struct PickData diff --git a/include/Engine/Rendering/Image.h b/include/Engine/Rendering/Image.h index 19ef43c1..d150be69 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, @@ -13,7 +15,10 @@ struct Image unsigned int Width = 0; unsigned int Height = 0; ImageFormat Format = ImageFormat::Unknown; + unsigned int MipMapLevels = 0; + bool Compressed = false; unsigned char* Data = nullptr; + std::size_t ByteSize = 0; }; #endif diff --git a/include/Engine/Rendering/LightCullingPass.h b/include/Engine/Rendering/LightCullingPass.h index 914fb8bb..f3b21705 100644 --- a/include/Engine/Rendering/LightCullingPass.h +++ b/include/Engine/Rendering/LightCullingPass.h @@ -54,7 +54,7 @@ private: struct Frustum { Plane Planes[4]; }; - Frustum* m_Frustums; + Frustum* m_Frustums = nullptr; //This should be a component struct LightSource { @@ -74,11 +74,11 @@ private: glm::vec2 Padding = glm::vec2(1.f, 2.f); }; - LightGrid* m_LightGrid; + LightGrid* m_LightGrid = nullptr; int m_LightOffset = 0; - float* m_LightIndex; + float* m_LightIndex = nullptr; }; diff --git a/include/Engine/Rendering/Model.h b/include/Engine/Rendering/Model.h index 4c63b922..acdf64db 100644 --- a/include/Engine/Rendering/Model.h +++ b/include/Engine/Rendering/Model.h @@ -16,15 +16,18 @@ private: public: ~Model(); - const std::vector& MaterialGroups() const { return m_RawModel->m_Materials; } - const glm::mat4& Matrix() const { return m_RawModel->m_Matrix; } - const RawModel::Vertex* Vertices() const { return m_RawModel->Vertices(); } - unsigned int NumberOfVertices() const { return m_RawModel->NumVertices(); } + const std::vector& MaterialGroups() const { return m_Materials; } + unsigned int NumberOfVertices() const { return m_Vertices.size(); } + const AABB& Box() const { return m_Box; } - bool IsSkinned() const { return m_RawModel->IsSkinned(); } + bool IsSkinned() const { return m_IsSkinned; } GLuint VAO; GLuint ElementBuffer; - RawModel* m_RawModel; + //RawModel* m_RawModel; + + Skeleton* m_Skeleton = nullptr; + std::vector m_Vertices; + std::vector m_Indices; private: AABB m_Box; @@ -34,6 +37,9 @@ private: GLuint TangentNormalsBuffer; GLuint BiTangentNormalsBuffer; GLuint TextureCoordBuffer; + + std::vector m_Materials; + bool m_IsSkinned; }; #endif diff --git a/include/Engine/Rendering/ModelJob.h b/include/Engine/Rendering/ModelJob.h index c2a469d2..86b89ad6 100644 --- a/include/Engine/Rendering/ModelJob.h +++ b/include/Engine/Rendering/ModelJob.h @@ -12,37 +12,27 @@ #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" struct ModelJob : RenderJob { - ModelJob(Model* model, Camera* camera, glm::mat4 matrix, ::RawModel::MaterialProperties matProp, ComponentWrapper modelComponent, World* world, glm::vec4 fillColor, float fillPercentage) + ModelJob(Model* model, Camera* camera, glm::mat4 matrix, ::RawModel::MaterialProperties matProp, ComponentWrapper modelComponent, World* world, glm::vec4 fillColor, float fillPercentage, bool isShielded, bool shadow) : RenderJob() { Model = model; 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"]) { @@ -64,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; @@ -110,45 +94,33 @@ struct ModelJob : RenderJob Color = modelComponent["Color"]; GlowIntensity = ((double)modelComponent["GlowIntensity"]); Entity = modelComponent.EntityID; - glm::vec3 abspos = Transform::AbsolutePosition(world, modelComponent.EntityID); + glm::vec3 abspos = glm::vec3(matrix[3][0], matrix[3][1], matrix[3][2]); glm::vec3 worldpos = glm::vec3(camera->ViewMatrix() * glm::vec4(abspos, 1)); Depth = worldpos.z; World = world; + Shadow = shadow; FillColor = fillColor; FillPercentage = fillPercentage; + IsShielded = isShielded; + + if (world->HasComponent(Entity, "Unpickable")) { + NotPickable = true; + } if (model->IsSkinned()) { - Skeleton = Model->m_RawModel->m_Skeleton; + Skeleton = Model->m_Skeleton; if (Skeleton != nullptr) { - if (world->HasComponent(Entity, "Animation")) { - auto animationComponent = world->GetComponent(Entity, "Animation"); + EntityWrapper entityWrapper = EntityWrapper(world, modelComponent.EntityID); + - for (int i = 1; i <= 3; i++) { - ::Skeleton::AnimationData animationData; - animationData.animation = model->m_RawModel->m_Skeleton->GetAnimation(animationComponent["AnimationName" + std::to_string(i)]); - if (animationData.animation == nullptr) { - continue; - } - animationData.time = (double)animationComponent["Time" + std::to_string(i)]; - animationData.weight = (double)animationComponent["Weight" + std::to_string(i)]; - - Animations.push_back(animationData); - } - } - - if (world->HasComponent(Entity, "AnimationOffset")) { - auto animationOffsetComponent = world->GetComponent(Entity, "AnimationOffset"); - AnimationOffset.animation = model->m_RawModel->m_Skeleton->GetAnimation(animationOffsetComponent["AnimationName"]); - AnimationOffset.time = (double)animationOffsetComponent["Time"]; - } else { - AnimationOffset.animation = nullptr; + if(Skeleton->BlendTrees.find(entityWrapper) != Skeleton->BlendTrees.end()) { + BlendTree = Skeleton->BlendTrees.at(entityWrapper); } } } - }; unsigned int TextureID; @@ -167,10 +139,7 @@ struct ModelJob : RenderJob glm::vec4 Color; const ::Model* Model = nullptr; ::Skeleton* Skeleton = nullptr; - std::vector<::Skeleton::AnimationData> Animations; - ::Skeleton::AnimationOffset AnimationOffset; - - + std::shared_ptr<::BlendTree> BlendTree = nullptr; float GlowIntensity = 8.0; glm::vec4 DiffuseColor; glm::vec4 SpecularColor; @@ -181,10 +150,15 @@ struct ModelJob : RenderJob glm::vec4 FillColor = glm::vec4(0); float FillPercentage = 0.0; + bool IsShielded; + bool Shadow; + bool NotPickable = false; void CalculateHash() override { - Hash = ShaderID << 20 + ModelID << 10 + TextureID; + Hash = TextureID; + Hash += ModelID << 10; + Hash += ShaderID << 20; } }; diff --git a/include/Engine/Rendering/PickingPass.h b/include/Engine/Rendering/PickingPass.h index f6434781..14ce26ab 100644 --- a/include/Engine/Rendering/PickingPass.h +++ b/include/Engine/Rendering/PickingPass.h @@ -28,15 +28,13 @@ public: const ShaderProgram& PickingProgram() const { return *m_PickingProgram; } //const std::unordered_map& PickingColorsToEntity() const { return m_PickingColorsToEntity; } GLuint PickingTexture() const { return m_PickingTexture; } - GLuint DepthBuffer() const { return m_DepthBuffer; } + GLuint* DepthBuffer() { return &m_DepthBuffer; } const FrameBuffer& PickingBuffer() const { return m_PickingBuffer; } PickData Pick(glm::vec2 screenCoord); private: - void GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type) const; - EventBroker* m_EventBroker; const IRenderer* m_Renderer; @@ -54,8 +52,8 @@ private: std::unordered_map m_PickingColorsToEntity; - GLuint m_PickingTexture; - GLuint m_DepthBuffer; + GLuint m_PickingTexture = 0; + GLuint m_DepthBuffer = 0; FrameBuffer m_PickingBuffer; 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..12e54d3f 100644 --- a/include/Engine/Rendering/RawModelCustom.h +++ b/include/Engine/Rendering/RawModelCustom.h @@ -13,28 +13,25 @@ #include +#include #include "../Common.h" #include "../GLM.h" #include "../Core/ResourceManager.h" #include "Texture.h" #include "Skeleton.h" - -#include "boost\endian\buffers.hpp" - - +#include "ShaderProgram.h" class RawModelCustom : public Resource { friend class ResourceManager; - + friend class Model; protected: RawModelCustom(std::string fileName); public: ~RawModelCustom(); - - struct Vertex - { + + struct RenderVertex { glm::vec3 Position; glm::vec3 Normal; glm::vec3 Tangent; @@ -42,7 +39,7 @@ public: glm::vec2 TextureCoords; }; - struct SkinedVertex : public Vertex { + struct SkinedVertex : public RenderVertex { glm::vec4 BoneIndices; glm::vec4 BoneWeights; }; @@ -87,9 +84,10 @@ public: struct MaterialProperties { MaterialType type; MaterialBasic* material; + unsigned int ShaderID = 0; }; - const Vertex* Vertices() const { + const RenderVertex* Vertices() const { if (hasSkin) { return m_SkinedVertices.data(); } else { @@ -97,16 +95,16 @@ public: } }; - unsigned int VertexSize() const { + unsigned int VertexSize() const { if (hasSkin) { return sizeof(SkinedVertex); } else { - return sizeof(Vertex); + return sizeof(RenderVertex); } }; - unsigned int NumVertices() const { + size_t NumVertices() const { if (hasSkin) { return m_SkinedVertices.size(); } else { @@ -114,17 +112,39 @@ public: } }; + const std::vector& Indices() const { + return m_Indices; + } + bool IsSkinned() const { return hasSkin; }; + const std::vector& CollisionVertices(); + + size_t NumCollisionVertices() const { + return m_CollisionVertices.size(); + }; + + const std::vector& CollisionIndices() const { + if (hasCollisionMesh) { + return m_CollisionIndices; + } else { + return m_Indices; + } + }; + std::vector m_Materials; - std::vector m_Indices; + Skeleton* m_Skeleton = nullptr; glm::mat4 m_Matrix; private: bool hasSkin; - std::vector m_Vertices; + bool hasCollisionMesh = false; + std::vector m_Indices; + std::vector m_CollisionIndices; + std::vector m_CollisionVertices; + std::vector m_Vertices; std::vector m_SkinedVertices; void ReadMeshFile(std::string filePath); @@ -147,7 +167,12 @@ private: void ReadAnimationClips(std::size_t& offset, char* fileData, const unsigned int& fileByteSize, unsigned int numberOfClips); void ReadAnimationClipSingle(std::size_t& offset, char* fileData, const unsigned int& fileByteSize, unsigned int clipIndex); void ReadAnimationKeyFrame(std::size_t& offset, char* fileData, const unsigned int& fileByteSize, std::vector& animation); - + + + void ReadCollisionFile(std::string filePath); + void ReadCollisionFileData(std::size_t& offset, char* fileData, const unsigned int& fileByteSize); + + const std::vector& ConstructCollisionList(); //void CreateSkeleton(std::vector> &boneInfo, std::map &boneNameMapping, aiNode* node, int parentID); }; diff --git a/include/Engine/Rendering/RenderJob.h b/include/Engine/Rendering/RenderJob.h index bcffc4a5..6fd8963e 100644 --- a/include/Engine/Rendering/RenderJob.h +++ b/include/Engine/Rendering/RenderJob.h @@ -16,16 +16,15 @@ struct RenderJob public: float Depth; + bool operator<(const RenderJob& rhs) + { + return this->Hash < rhs.Hash; + } + protected: uint64_t Hash; virtual void CalculateHash() = 0; - - bool operator<(const RenderJob& rhs) - { - return this->Hash < rhs.Hash; - } - }; #endif \ No newline at end of file diff --git a/include/Engine/Rendering/RenderQueue.h b/include/Engine/Rendering/RenderQueue.h index 647adab8..f183b021 100644 --- a/include/Engine/Rendering/RenderQueue.h +++ b/include/Engine/Rendering/RenderQueue.h @@ -24,7 +24,6 @@ struct RenderScene std::list> OpaqueObjects; std::list> TransparentObjects; std::list> OpaqueShieldedObjects; - std::list> TransparentShieldedObjects; std::list> ShieldObjects; std::list> SpriteJob; std::list> PointLight; @@ -34,6 +33,7 @@ struct RenderScene Rectangle Viewport; bool ClearDepth = false; + bool ShouldBlur = false; glm::vec4 AmbientColor; void Clear() @@ -41,7 +41,6 @@ struct RenderScene Jobs.OpaqueObjects.clear(); Jobs.TransparentObjects.clear(); Jobs.OpaqueShieldedObjects.clear(); - Jobs.TransparentShieldedObjects.clear(); Jobs.ShieldObjects.clear(); Jobs.SpriteJob.clear(); Jobs.DirectionalLight.clear(); diff --git a/include/Engine/Rendering/RenderState.h b/include/Engine/Rendering/RenderState.h index c1886247..24f908a9 100644 --- a/include/Engine/Rendering/RenderState.h +++ b/include/Engine/Rendering/RenderState.h @@ -24,6 +24,8 @@ public: bool StencilFunc(GLenum func, GLint ref, GLuint mask); bool StencilMask(GLuint mask); bool DepthMask(GLboolean flag); + bool DepthFunc(GLenum func); + bool AlphaFunc(GLenum func, GLclampf thresholder); private: std::vector> m_ResetFunctions; diff --git a/include/Engine/Rendering/RenderSystem.h b/include/Engine/Rendering/RenderSystem.h index 7580d654..74fa6cad 100644 --- a/include/Engine/Rendering/RenderSystem.h +++ b/include/Engine/Rendering/RenderSystem.h @@ -14,11 +14,12 @@ #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" #include "../Core/ConfigFile.h" +#include "EResolutionChanged.h" class RenderSystem : public ImpureSystem { @@ -36,6 +37,8 @@ private: EntityWrapper m_LocalPlayer = EntityWrapper::Invalid; Octree* m_Octree; + EventRelay m_EResolutionChanged; + bool OnResolutionChanged(Events::ResolutionChanged &event); EventRelay m_ESetCamera; bool OnSetCamera(Events::SetCamera &event); EventRelay m_EInputCommand; diff --git a/include/Engine/Rendering/Renderer.h b/include/Engine/Rendering/Renderer.h index f3a6bf31..315dfe5f 100644 --- a/include/Engine/Rendering/Renderer.h +++ b/include/Engine/Rendering/Renderer.h @@ -18,23 +18,31 @@ #include "DrawColorCorrectionPass.h" #include "SSAOPass.h" #include "CubeMapPass.h" +#include "BlurHUD.h" #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" #include "Core/PerformanceTimer.h" +#include "ShadowPass.h" +#include "EResolutionChanged.h" class Renderer : public IRenderer { static void glfwFrameBufferCallback(GLFWwindow* window, int width, int height); + static void glfwWindowSizeCallback(GLFWwindow* window, int width, int height); public: - Renderer(EventBroker* eventBroker) - : m_EventBroker(eventBroker) + Renderer(EventBroker* eventBroker, ConfigFile* config) + : m_EventBroker(eventBroker) + , m_Config(config) { } + ~Renderer(); + + virtual void SetResolution(const Rectangle& resolution) override; virtual void Initialize() override; virtual void Update(double dt) override; @@ -42,11 +50,11 @@ public: virtual PickData Pick(glm::vec2 screenCoord) override; - private: //----------------------Variables----------------------// static std::unordered_map m_WindowToRenderer; + ConfigFile* m_Config; EventBroker* m_EventBroker; TextPass* m_TextPass; @@ -61,12 +69,9 @@ private: int m_DebugTextureToDraw = 0; int m_CubeMapTexture = 0; bool m_ResizeWindow = false; - float m_SSAO_Radius = 1.0f; - float m_SSAO_Bias = 0.05f; - float m_SSAO_Contrast = 1.5f; - float m_SSAO_IntensityScale = 1.0f; - int m_SSAO_NumOfSamples = 24; - int m_SSAO_NumOfTurns = 7; + int m_SSAO_Quality = 0; + int m_GLOW_Quality = 2; + unsigned int m_MSAA_Level = 0; PickingPass* m_PickingPass; LightCullingPass* m_LightCullingPass; @@ -77,6 +82,8 @@ private: DrawColorCorrectionPass* m_DrawColorCorrectionPass; SSAOPass* m_SSAOPass; CubeMapPass* m_CubeMapPass; + ShadowPass* m_ShadowPass; + BlurHUD* m_BlurHUDPass; //----------------------Functions----------------------// void InitializeWindow(); @@ -87,11 +94,14 @@ private: void InputUpdate(double dt); //void PickingPass(RenderQueueCollection& rq); //void DrawScreenQuad(GLuint textureToDraw); + void setWindowSize(Rectangle size); + void updateFramebufferSize(); static bool DepthSort(const std::shared_ptr &i, const std::shared_ptr &j) { return (i->Depth < j->Depth); } void SortRenderJobsByDepth(RenderScene &scene); void GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type); - //--------------------ShaderPrograms-------------------// + + //--------------------ShaderPrograms-------------------// ShaderProgram* m_BasicForwardProgram; ShaderProgram* m_ExplosionEffectProgram; diff --git a/include/Engine/Rendering/SSAOPass.h b/include/Engine/Rendering/SSAOPass.h index 792d1d82..ba92b6dc 100644 --- a/include/Engine/Rendering/SSAOPass.h +++ b/include/Engine/Rendering/SSAOPass.h @@ -13,18 +13,32 @@ class SSAOPass { public: - SSAOPass(IRenderer* rendere); - ~SSAOPass() { - delete m_DrawBloomPass; - }; + SSAOPass(IRenderer* renderer, ConfigFile* config); + ~SSAOPass(); + + void ChangeQuality(int quality); void Draw(GLuint depthBuffer, Camera* camera); - void Setting(float radius, float bias, float contrast, float intensityScale, int numOfSamples, int NumOfTurns); + void Setting(float radius, float bias, float contrast, float intensityScale, int numOfSamples, int numOfTurns, int iterations, int quality); void ClearBuffer(); void OnWindowResize(); //Return the SSAO of the texture sent to Draw - GLuint SSAOTexture() const { return m_DrawBloomPass->GaussianTexture(); } + GLuint SSAOTexture() const { + if (m_Quality == 0) { + return m_WhiteTexture->m_Texture; + } else { + return m_Gaussian_vert; + } + } + + int TextureQuality() const { + if (m_Quality == 0) { + return 13; + } else { + return m_TextureQuality; + } + } private: void InitializeTexture(); @@ -32,14 +46,13 @@ private: void InitializeShaderProgram(); void InitializeBuffer(); - void GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type) const; - //void blurHorizontal(GLuint depthBuffer); //void blurVertical(GLuint depthBuffer); Model* m_ScreenQuad; const IRenderer* m_Renderer; + ConfigFile* m_Config; float m_Radius; float m_Bias; @@ -47,17 +60,28 @@ private: float m_IntensityScale; int m_NumOfSamples; int m_NumOfTurns; + int m_Iterations; + int m_TextureQuality; + int m_Quality = 0; - GLuint m_SSAOTexture; + Texture* m_WhiteTexture; + + GLuint m_SSAOTexture = 0; FrameBuffer m_SSAOFramBuffer; - GLuint m_SSAOViewSpaceZTexture; + GLuint m_SSAOViewSpaceZTexture = 0; FrameBuffer m_SSAOViewSpaceZFramBuffer; + GLuint m_Gaussian_horiz = 0; + GLuint m_Gaussian_vert = 0; + + FrameBuffer m_GaussianFrameBuffer_horiz; + FrameBuffer m_GaussianFrameBuffer_vert; + ShaderProgram* m_SSAOProgram; ShaderProgram* m_SSAOViewSpaceZProgram; - - DrawBloomPass* m_DrawBloomPass; + ShaderProgram* m_GaussianProgram_horiz; + ShaderProgram* m_GaussianProgram_vert; }; #endif \ No newline at end of file diff --git a/include/Engine/Rendering/ShaderProgram.h b/include/Engine/Rendering/ShaderProgram.h index ad01c029..af90ff78 100644 --- a/include/Engine/Rendering/ShaderProgram.h +++ b/include/Engine/Rendering/ShaderProgram.h @@ -21,6 +21,8 @@ public: std::string GetFileName() const; GLuint GetHandle() const; bool IsCompiled() const; + static std::string ReadFile(std::string fileName); +private: protected: GLenum m_ShaderType; std::string m_FileName; diff --git a/include/Engine/Rendering/ShadowPass.h b/include/Engine/Rendering/ShadowPass.h new file mode 100644 index 00000000..122fbddd --- /dev/null +++ b/include/Engine/Rendering/ShadowPass.h @@ -0,0 +1,88 @@ +#ifndef ShadowPass_h__ +#define ShadowPass_h__ + +#include "IRenderer.h" +#include "FrameBuffer.h" +#include "ShaderProgram.h" +#include "../Core/EventBroker.h" +#include "../Core/World.h" +#include "ShadowPassState.h" +#include "imgui/imgui.h" + +#define MAX_SPLITS 4 + +enum NearFar { NEAR = 0, FAR = 1 }; +enum LRBT { LEFT = 0, RIGHT = 1, BOTTOM = 2, TOP = 3 }; + +struct ShadowFrustum +{ + float NearClip; + float FarClip; + float FOV; + float AspectRatio; + glm::vec3 MiddlePoint; + float Radius; + std::array LRBT; + std::array CornerPoint; +}; + +class ShadowPass +{ +public: + ShadowPass(IRenderer* renderer); + ShadowPass(IRenderer * renderer, int ShadowResX, int ShadowResY); + ~ShadowPass(); + + void InitializeFrameBuffers(); + void InitializeShaderPrograms(); + void ClearBuffer(); + void Draw(RenderScene& scene); + + void DebugGUI(); + + GLuint DepthMap() const { return m_DepthMap; } + std::array LightP() const { return m_LightProjection; } + std::array LightV() const { return m_LightView; } + std::array FarDistance() const { std::array f; for (int i = 0; i < MAX_SPLITS; i++) f[i] = m_shadowFrusta[i].FarClip; return f; } + int CurrentNrOfSplits() const { return m_CurrentNrOfSplits; } + + void SetSplitWeight(float split_weight) { m_SplitWeight = split_weight; }; +private: + void InitializeCameras(RenderScene & scene); + void UpdateSplitDist(std::array& frusta, float near_distance, float far_distance); + void UpdateFrustumPoints(ShadowFrustum& frustum, glm::vec3 camera_position, glm::vec3 view_dir); + void UpdateFrustumPoints(ShadowFrustum& frustum, glm::mat4 p, glm::mat4 v); + + void PointsToLightspace(ShadowFrustum& frustum, glm::mat4 v); + + float FindRadius(ShadowFrustum& frustum); + void RadiusToLightspace(ShadowFrustum& frustum); + + EventBroker* m_EventBroker; + const IRenderer* m_Renderer; + + GLuint m_DepthMap; + FrameBuffer m_DepthBuffer; + ShaderProgram* m_ShadowProgram; + ShaderProgram* m_ShadowProgramSkinned; + + std::array m_LightProjection; + std::array m_LightView; + + GLfloat m_NearFarPlane[2] = { -34.f, 27.f }; + GLuint m_ResolutionSizeWidth = 1024 * 2; + GLuint m_ResolutionSizeHeight = 1024 * 2; + + bool m_TransparentObjects = false; + bool m_TexturedShadows = false; + bool m_EnableShadows = true; + + int m_CurrentNrOfSplits = 4; + float m_SplitWeight = 0.962f; + + std::array m_shadowFrusta; + + Texture* m_WhiteTexture = ResourceManager::Load("Textures/Core/White.png"); +}; + +#endif \ No newline at end of file diff --git a/include/Engine/Rendering/ShadowPassState.h b/include/Engine/Rendering/ShadowPassState.h new file mode 100644 index 00000000..f881b48e --- /dev/null +++ b/include/Engine/Rendering/ShadowPassState.h @@ -0,0 +1,15 @@ +#ifndef ShadowPassState_h_ +#define ShadowPassState_h_ + +#include "Rendering/RenderState.h" + +class ShadowPassState : public RenderState +{ +public: + ShadowPassState(GLuint frameBuffer); + ~ShadowPassState(); + +private: +}; + +#endif \ No newline at end of file diff --git a/include/Engine/Rendering/Skeleton.h b/include/Engine/Rendering/Skeleton.h index 28a5ef6a..d14ab4ae 100644 --- a/include/Engine/Rendering/Skeleton.h +++ b/include/Engine/Rendering/Skeleton.h @@ -6,27 +6,9 @@ #include "../GLM.h" #include #include +#include "../Core/EntityWrapper.h" -//struct Bone -//{ -// Bone(std::string name, glm::mat4 offsetMatrix) -// : Name(name) -// , OffsetMatrix(offsetMatrix) -// { } -// -// ~Bone() -// { -// for (auto kv : Children) { -// delete kv.second; -// } -// } -// -// std::string Name; -// glm::mat4 OffsetMatrix; -// glm::mat4 LocalMatrix; -// -// std::map Children; -//}; +class BlendTree; class Skeleton { @@ -38,11 +20,14 @@ public: , Parent(parent) , Name(name) , OffsetMatrix(offsetMatrix) - { } + { + BindTransformMatrix = glm::inverse(offsetMatrix); + } std::string Name; glm::mat4 OffsetMatrix; int ID; + glm::mat4 BindTransformMatrix; Bone* Parent; std::vector Children; @@ -68,58 +53,43 @@ public: std::map> JointAnimations; }; - struct AnimationData - { - const Animation* animation; - float time; - float weight; - }; - - struct JointFrameTransform { - glm::vec3 PositionInterp = glm::vec3(0); - glm::quat RotationInterp = glm::quat(); - glm::vec3 ScaleInterp = glm::vec3(0); - float Weight; - }; - - struct AnimationOffset { - const Animation* animation; - float time; + struct PoseData { + glm::vec3 Translation; + glm::quat Orientation; + glm::vec3 Scale; }; Skeleton() { } ~Skeleton(); Bone* RootBone; - std::map Bones; + std::unordered_map> BlendTrees; + // Attach a new bone to the skeleton // Returns: New bone index int CreateBone(int ID, int parentID, std::string name, glm::mat4 offsetMatrix); - int GetBoneID(std::string name); - - std::vector GetFrameBones(std::vector animations, AnimationOffset animationOffset, bool noRootMotion = false); - std::vector GetFrameBones(std::vector animations, bool noRootMotion = false); - const Animation* GetAnimation(std::string name); - void AccumulateBoneTransforms(bool noRootMotion, std::vector animations, std::map& frameBones, const Bone* bone, glm::mat4 parentMatrix); - void AccumulateBoneTransforms(bool noRootMotion, std::vector animations, AnimationOffset animationOffset, std::map& frameBones, const Bone* bone, glm::mat4 parentMatrix); + std::map GetFrameBones(const Animation* animation, double time, bool additive, bool noRootMotion = false); + + std::map BlendPoses(const std::map& pose1, const std::map& pose2, double weight); + std::map OverridePose(const std::map& overridePose, const std::map& targetPose); + std::map BlendPoseAdditive(const std::map& additivePose, const std::map& targetPose); + void GetFinalPose(std::map& boneMatrices, std::vector& finalPose, std::map& boneTransforms); + + std::vector GetTPose(); - void PrintSkeleton(); - void PrintSkeleton(const Bone* parent, int depthCount); - std::map Animations; - - glm::mat4 GetBoneTransform(const Bone* bone, const Animation* animation, float time, glm::mat4 childMatrix); - glm::mat4 GetBoneTransform(bool noRootMotion, const Bone* bone, std::vector animations, AnimationOffset animationOffset, glm::mat4 childMatrix); - glm::mat4 GetBoneTransform(bool noRootMotion, const Bone* bone, std::vector animations, glm::mat4 childMatrix); - int GetKeyframe(const Animation& animation, double time); + std::map Animations; private: - - glm::mat4 GetOffsetTransform(const Bone* bone, AnimationOffset animationOffset); + Skeleton::PoseData GetAdditiveBonePose(const Bone* bone, const Animation* animation, double time); + + void AccumulateFinalPose(std::map& boneMatrices, std::map& poseDatas, std::map& boneTransforms, const Bone* bone, glm::mat4 parentMatrix); + void AdditiveBoneTransforms(const Animation* animation, double time, std::map& boneMatrices, const Bone* bone); + void AccumulateBoneTransforms(bool noRootMotion, const Animation* animation, double time, std::map& boneMatrices, const Bone* bone); std::map m_BonesByName; diff --git a/include/Engine/Rendering/SpriteJob.h b/include/Engine/Rendering/SpriteJob.h index 25c2d5cb..c2fbd9fb 100644 --- a/include/Engine/Rendering/SpriteJob.h +++ b/include/Engine/Rendering/SpriteJob.h @@ -7,12 +7,13 @@ #include "../GLM.h" #include "../Core/ComponentWrapper.h" #include "Texture.h" +#include "TextureSprite.h" #include "Model.h" #include "RenderJob.h" #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 @@ -20,20 +21,24 @@ struct SpriteJob : RenderJob SpriteJob(ComponentWrapper cSprite, Camera* camera, glm::mat4 matrix, World* world, glm::vec4 fillColor, float fillPercentage, bool depthSorted, bool isIndicator) : RenderJob() { - Model = ResourceManager::Load<::Model>("Models/Core/UnitQuad.mesh"); + Model = ResourceManager::Load<::Model>(cSprite["Model"]); ::RawModel::MaterialProperties matProp = Model->MaterialGroups().front(); TextureID = 0; - DiffuseTexture = CommonFunctions::LoadTexture(cSprite["DiffuseTexture"], true); + DiffuseTexture = CommonFunctions::TryLoadResource(cSprite["DiffuseTexture"]); + IncandescenceTexture = CommonFunctions::TryLoadResource(cSprite["GlowMap"]); - IncandescenceTexture = CommonFunctions::LoadTexture(cSprite["GlowMap"], true); + Linear = (bool)cSprite["Linear"]; + ClampToBorder = (bool)cSprite["ClampToBorder"]; StartIndex = matProp.material->StartIndex; EndIndex = matProp.material->EndIndex; Matrix = matrix; Color = cSprite["Color"]; + 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)); @@ -45,6 +50,26 @@ struct SpriteJob : RenderJob FillColor = fillColor; FillPercentage = fillPercentage; + + glm::vec3 scale = TransformSystem::AbsoluteScale(world, cSprite.EntityID); + + if((bool)cSprite["KeepRatio"] == true) { + if(scale.y >= scale.x) { + ScaleY = (scale.y)/(scale.x); + ScaleX = 1.f; + } else { + ScaleY = 1.f; + ScaleX = (scale.x)/(scale.y); + } + } else { + if ((bool)cSprite["KeepRatioX"] == true) { + ScaleX = scale.x; + } + if ((bool)cSprite["KeepRatioY"] == true) { + ScaleY = scale.y; + } + } + }; unsigned int TextureID; @@ -65,6 +90,11 @@ struct SpriteJob : RenderJob bool Pickable; bool IsIndicator = false; + bool BlurBackground = false; + float ScaleX = 1.f; + float ScaleY = 1.f; + bool Linear = false; + bool ClampToBorder = false; glm::vec4 FillColor = glm::vec4(0); float FillPercentage = 0.0; 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/Texture.h b/include/Engine/Rendering/Texture.h index d159e636..4053e8da 100644 --- a/include/Engine/Rendering/Texture.h +++ b/include/Engine/Rendering/Texture.h @@ -1,15 +1,17 @@ #ifndef Texture_h__ #define Texture_h__ +#include #include "../OpenGL.h" #include "BaseTexture.h" #include "PNG.h" +#include "DDS.h" class Texture : public BaseTexture { friend class ResourceManager; -private: +protected: Texture(std::string path); public: @@ -18,8 +20,9 @@ public: void Bind(GLenum textureUnit = GL_TEXTURE0); GLuint m_Texture = 0; - unsigned char* Data = nullptr; - + + enum TextureType : GLint { cInvalid = 0, cDDS = 1, cPNG = 2}; + TextureType m_Type; }; #endif diff --git a/include/Engine/Rendering/TextureSprite.h b/include/Engine/Rendering/TextureSprite.h new file mode 100644 index 00000000..f03727f0 --- /dev/null +++ b/include/Engine/Rendering/TextureSprite.h @@ -0,0 +1,19 @@ +#ifndef TextureSprite_h__ +#define TextureSprite_h__ + +#include "../OpenGL.h" +#include "BaseTexture.h" +#include "Texture.h" +#include "PNG.h" + +class TextureSprite : public Texture +{ + friend class ResourceManager; + +protected: + TextureSprite(std::string path); + +public: +}; + +#endif diff --git a/include/Engine/Rendering/Util/CommonFunctions.h b/include/Engine/Rendering/Util/CommonFunctions.h index e178f52d..5a60c5c9 100644 --- a/include/Engine/Rendering/Util/CommonFunctions.h +++ b/include/Engine/Rendering/Util/CommonFunctions.h @@ -8,7 +8,27 @@ namespace CommonFunctions { -Texture* LoadTexture(std::string path, bool threaded); + +//Loads Texture/SpriteTexture and return null if it fails +template +Texture* TryLoadResource(std::string path) +{ + Texture* img; + try { + img = ResourceManager::Load(path); + } catch (const Resource::StillLoadingException&) { + img = ResourceManager::Load("Textures/Core/ErrorTexture.png"); + } catch (const std::exception&) { + img = nullptr; + } + + return img; +} + +void GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type); +void GenerateMultiSampleTexture(GLuint* texture, int numSamples, glm::vec2 dimensions, GLint internalFormat); +void GenerateMipMapTexture(GLuint* texture, GLenum wrapping, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type, GLint numMipMaps, GLint MAGFilter, GLint MINFilter); +void DeleteTexture(GLuint* texture); }; #endif \ No newline at end of file diff --git a/include/Engine/Rendering/Util/GLError.h b/include/Engine/Rendering/Util/GLError.h index 2b244e1c..740a5a3c 100644 --- a/include/Engine/Rendering/Util/GLError.h +++ b/include/Engine/Rendering/Util/GLError.h @@ -16,7 +16,11 @@ inline bool _GLERROR(const char* info, const char* file, const char* func, unsig return false; } +#ifdef DEBUG #define GLERROR(function) \ _GLERROR(function, __BASE_FILE__, __func__, __LINE__) +#else +#define GLERROR(function) false +#endif #endif \ No newline at end of file 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..30e51e1b 100644 --- a/include/Engine/Sound/SoundManager.h +++ b/include/Engine/Sound/SoundManager.h @@ -9,32 +9,36 @@ #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" +#include "../Rendering/ESetCamera.h" + typedef std::pair> QueuedBuffers; enum class SoundType { SFX, - BGM + BGM, + Announcer }; struct Source @@ -43,6 +47,7 @@ struct Source Sound* SoundResource = nullptr; ALuint ALsource; SoundType Type; + float Duration; }; class SoundManager @@ -74,14 +79,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); + void setTimeOffsetSeconds(Source* source, float timeOffset); // 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; // Logic World* m_World = nullptr; @@ -93,6 +104,7 @@ private: float m_BGMVolumeChannel = 1.0f; float m_SFXVolumeChannel = 1.0f; + float m_AnnouncerVolumeChannel = 1.0f; EntityWrapper m_LocalPlayer = EntityWrapper(); // Events @@ -102,6 +114,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 +126,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 +138,10 @@ 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); + EventRelay m_ESetCamera; + bool OnSetCamera(const Events::SetCamera& e); }; diff --git a/include/Game/Events/EDashAbility.h b/include/Game/Events/EDashAbility.h index 62a2b935..c5078fab 100644 --- a/include/Game/Events/EDashAbility.h +++ b/include/Game/Events/EDashAbility.h @@ -2,11 +2,15 @@ #define Events_DashAbility_h__ #include "Core/Event.h" +#include "Core/EntityWrapper.h" namespace Events { -struct DashAbility : public Event { }; +struct DashAbility : public Event +{ + EntityID Player; +}; } 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/Game.h b/include/Game/Game.h index 06fd4703..4d173b48 100644 --- a/include/Game/Game.h +++ b/include/Game/Game.h @@ -13,13 +13,13 @@ #include "Input/KeyboardInputHandler.h" #include "Input/MouseInputHandler.h" #include "Core/EKeyDown.h" -#include "Core/EntityFilePreprocessor.h" +#include "Core/EntityXMLFilePreprocessor.h" #include "Core/SystemPipeline.h" #include "Systems/ExplosionEffectSystem.h" #include "Editor/EditorSystem.h" -#include "Core/EntityFile.h" +#include "Core/EntityXMLFile.h" #include "Rendering/RenderSystem.h" -#include "Core/EntityFileParser.h" +#include "Core/EntityXMLFileParser.h" #include "Core/Octree.h" #include "Rendering/Font.h" #include "Systems/InterpolationSystem.h" diff --git a/include/Game/Systems/AbilityCooldownHUDSystem.h b/include/Game/Systems/AbilityCooldownHUDSystem.h new file mode 100644 index 00000000..f2710ce3 --- /dev/null +++ b/include/Game/Systems/AbilityCooldownHUDSystem.h @@ -0,0 +1,18 @@ +#ifndef AbilityCooldownHUDSystem_h__ +#define AbilityCooldownHUDSystem_h__ + +#include "../../Engine/Core/System.h" +#include "../../Engine/GLM.h" + +class AbilityCooldownHUDSystem : public ImpureSystem +{ +public: + AbilityCooldownHUDSystem(SystemParams params) + : System(params) + { } + + virtual void Update(double dt) override; +private: +}; + +#endif \ No newline at end of file diff --git a/include/Game/Systems/AmmoPickupSystem.h b/include/Game/Systems/AmmoPickupSystem.h index 7c66acff..2276f071 100644 --- a/include/Game/Systems/AmmoPickupSystem.h +++ b/include/Game/Systems/AmmoPickupSystem.h @@ -2,9 +2,9 @@ #define AmmoPickupSystem_h__ #include "Core/System.h" -#include "Core/Transform.h" +#include "Core/TransformSystem.h" #include "Core/ResourceManager.h" -#include "Core/EntityFileParser.h" +#include "Core/EntityFile.h" #include "Core/EPickupSpawned.h" #include "Core/EAmmoPickup.h" #include "Engine/Collision/ETrigger.h" @@ -23,6 +23,9 @@ private: EventRelay m_ETriggerLeave; bool OnTriggerLeave(Events::TriggerLeave& e); + EventRelay m_EAmmoPickup; + bool OnAmmoPickup(Events::AmmoPickup& e); + struct NewAmmoPickup { glm::vec3 Pos; double AmmoGain; @@ -31,15 +34,23 @@ private: EntityID parentID; }; std::vector m_ETriggerTouchVector; - - struct EntityAtMaxValuePickupStruct { EntityWrapper player; - EntityWrapper pickup; - + EntityWrapper trigger; }; std::vector m_PickupAtMaximum; void DoPickup(EntityWrapper &player, EntityWrapper &trigger); - + //class + enum class PlayerClass { + Assault, + Defender, + Sniper, + None + }; + //helper methods + bool DoesPlayerHaveMaxAmmo(EntityWrapper &player); + PlayerClass DetermineClass(EntityWrapper &player); + void SetPlayerAmmo(EntityWrapper &player, int ammoGain); + int GetPlayerMaxAmmo(EntityWrapper &player); }; #endif diff --git a/include/Game/Systems/AmmunitionHUDSystem.h b/include/Game/Systems/AmmunitionHUDSystem.h deleted file mode 100644 index b22a85b5..00000000 --- a/include/Game/Systems/AmmunitionHUDSystem.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef AmmunitionHUDSystem_h__ -#define AmmunitionHUDSystem_h__ - -#include "../../Engine/Core/System.h" -#include "../../Engine/GLM.h" - -class AmmunitionHUDSystem : public ImpureSystem -{ -public: - AmmunitionHUDSystem(SystemParams params) - : System(params) - { } - - virtual void Update(double dt) override; -}; - -#endif \ No newline at end of file diff --git a/include/Game/Systems/BoostIconsHUDSystem.h b/include/Game/Systems/BoostIconsHUDSystem.h new file mode 100644 index 00000000..d8de777d --- /dev/null +++ b/include/Game/Systems/BoostIconsHUDSystem.h @@ -0,0 +1,19 @@ +#ifndef BoostIconsHUDSystem_h__ +#define BoostIconsHUDSystem_h__ + +#include "../../Engine/Core/System.h" +#include "../../Engine/GLM.h" + +class BoostIconsHUDSystem : public PureSystem +{ +public: + BoostIconsHUDSystem(SystemParams params) + : System(params) + , PureSystem("BoostIconsHUD") + { } + + virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& capturePoint, double dt) override; + +}; + +#endif \ No newline at end of file diff --git a/include/Game/Systems/BoostSystem.h b/include/Game/Systems/BoostSystem.h new file mode 100644 index 00000000..925ef438 --- /dev/null +++ b/include/Game/Systems/BoostSystem.h @@ -0,0 +1,24 @@ +#ifndef BoostSystem_h__ +#define BoostSystem_h__ + +#include "Core/System.h" +#include "Core/ResourceManager.h" +#include "Core/EntityFile.h" +#include "Core/EPlayerDamage.h" +#include "Common.h" +#include "SpawnerSystem.h" + +class BoostSystem : public System +{ +public: + BoostSystem(SystemParams params); + +private: + EventRelay m_EPlayerDamage; + bool OnPlayerDamage(Events::PlayerDamage& e); + + std::string DetermineClass(EntityWrapper player); + + void giveAmmo(EntityWrapper giver, EntityWrapper receiver); +}; +#endif \ No newline at end of file diff --git a/include/Game/Systems/CapturePointArrowHUDSystem.h b/include/Game/Systems/CapturePointArrowHUDSystem.h new file mode 100644 index 00000000..9f71e290 --- /dev/null +++ b/include/Game/Systems/CapturePointArrowHUDSystem.h @@ -0,0 +1,30 @@ +#ifndef CapturePointArrowHUDSystem_h__ +#define CapturePointArrowHUDSystem_h__ + +#include +#include +#include + +#include "Common.h" +#include "Core/System.h" +#include "Core/TransformSystem.h" +#include "Core/ECaptured.h" + + +class CapturePointArrowHUDSystem : public ImpureSystem +{ +public: + CapturePointArrowHUDSystem(SystemParams params); + + virtual void Update(double dt) override; + +private: + EventRelay m_ECapturedEvent; + bool OnCapturePointCaptured(Events::Captured& e); + + bool m_InitialtargetsSet = false; + glm::vec3 m_RedTeamCurrentTarget; + glm::vec3 m_BlueTeamCurrentTarget; +}; + +#endif \ No newline at end of file diff --git a/include/Game/Systems/CapturePointHUDSystem.h b/include/Game/Systems/CapturePointHUDSystem.h index 41db0c12..53ca9b73 100644 --- a/include/Game/Systems/CapturePointHUDSystem.h +++ b/include/Game/Systems/CapturePointHUDSystem.h @@ -7,7 +7,7 @@ #include "Common.h" #include "Core/System.h" -#include "Engine/Collision/ETrigger.h" +#include "Collision/ETrigger.h" class CapturePointHUDSystem : public ImpureSystem { diff --git a/include/Game/Systems/CapturePointSystem.h b/include/Game/Systems/CapturePointSystem.h index 34a23e14..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! @@ -42,9 +47,9 @@ private: int m_NumberOfCapturePoints = 0; std::map m_CapturePointNumberToEntityMap; - //std::vector - bool m_ResetTimers = false; + bool m_RecentlyCapturedNeedNextCapturePointNow = false; + Events::Captured m_CapturedEvent; //vectors which will keep track of enter/leave changes std::vector> m_ETriggerTouchVector; diff --git a/include/Game/Systems/DamageIndicatorSystem.h b/include/Game/Systems/DamageIndicatorSystem.h index ae9ba195..9caf4463 100644 --- a/include/Game/Systems/DamageIndicatorSystem.h +++ b/include/Game/Systems/DamageIndicatorSystem.h @@ -2,9 +2,9 @@ #define DamageIndicatorSystem_h__ #include "Core/System.h" -#include "Core/Transform.h" +#include "Core/TransformSystem.h" #include "Core/ResourceManager.h" -#include "Core/EntityFileParser.h" +#include "Core/EntityFile.h" #include "Core/EPlayerDamage.h" #include "Common.h" #include @@ -15,6 +15,7 @@ #include "Rendering/Util/CommonFunctions.h" //#define INDICATOR_TEST +#include "Core/ConfigFile.h" class DamageIndicatorSystem : public ImpureSystem { @@ -40,6 +41,8 @@ private: std::vector updateDamageIndicatorVector; float CalculateAngle(EntityWrapper player, glm::vec3 enemyPos); + bool m_NetworkEnabled; + //for tests #ifdef INDICATOR_TEST glm::vec3 DamageIndicatorTest(EntityWrapper player); diff --git a/include/Game/Systems/EndScreenSystem.h b/include/Game/Systems/EndScreenSystem.h new file mode 100644 index 00000000..1dabbb5e --- /dev/null +++ b/include/Game/Systems/EndScreenSystem.h @@ -0,0 +1,21 @@ +#ifndef EndScreenSystem_h__ +#define EndScreenSystem_h__ + +#include "Core/System.h" +#include "Input/EInputCommand.h" +#include "Rendering/ESetCamera.h" +#include "Core/EWin.h" + +class EndScreenSystem : public ImpureSystem +{ +public: + EndScreenSystem(SystemParams params); + + virtual void Update(double dt) override; + +private: + EventRelay m_EWin; + bool OnWin(const Events::Win& e); +}; + +#endif \ No newline at end of file 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/FadeSystem.h b/include/Game/Systems/FadeSystem.h new file mode 100644 index 00000000..e2e930df --- /dev/null +++ b/include/Game/Systems/FadeSystem.h @@ -0,0 +1,22 @@ +#ifndef FadeSystem_h__ +#define FadeSystem_h__ + +#include "Core/System.h" +#include "GLM.h" + +class FadeSystem : public PureSystem +{ +public: + FadeSystem(SystemParams params) + : System(params) + , PureSystem("Fade") + { + + } + + virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& cFadeOut, double dt) override; + +private: +}; + +#endif \ No newline at end of file diff --git a/include/Game/Systems/FloatingEffectSystem.h b/include/Game/Systems/FloatingEffectSystem.h new file mode 100644 index 00000000..942c75d0 --- /dev/null +++ b/include/Game/Systems/FloatingEffectSystem.h @@ -0,0 +1,19 @@ +#include "Common.h" +#include "Core/System.h" + +class FloatingEffectSystem : public PureSystem +{ +public: + FloatingEffectSystem(SystemParams params) + : System(params) + , PureSystem("FloatingEffect") + { } + + virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) override + { + ComponentWrapper& transform = m_World->GetComponent(component.EntityID, "Transform"); + (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/KillFeedSystem.h b/include/Game/Systems/KillFeedSystem.h index 31423999..57c7a98a 100644 --- a/include/Game/Systems/KillFeedSystem.h +++ b/include/Game/Systems/KillFeedSystem.h @@ -3,7 +3,7 @@ #include "../../Engine/Core/System.h" #include "../../Engine/GLM.h" -#include "Core/EPlayerDeath.h" +#include "Network/EKillDeath.h" class KillFeedSystem : public ImpureSystem { @@ -11,8 +11,7 @@ public: KillFeedSystem(SystemParams params) : System(params) { - EVENT_SUBSCRIBE_MEMBER(m_EPlayerDeath, &KillFeedSystem::OnPlayerDeath); - + EVENT_SUBSCRIBE_MEMBER(m_EKillDeath, &KillFeedSystem::OnPlayerKillDeath) } virtual void Update(double dt) override; @@ -22,16 +21,30 @@ private: - EventRelay m_EPlayerDeath; - bool KillFeedSystem::OnPlayerDeath(Events::PlayerDeath& e); + EventRelay m_EKillDeath; + bool KillFeedSystem::OnPlayerKillDeath(Events::KillDeath& e); struct KillFeedInfo { - std::string Content; - glm::vec4 Color; + std::string KillerName = ""; + int KillerClass = 0; + int KillerID = -1; + int KillerTeam = 0; + std::string KillerColor = ""; + + std::string VictimName = ""; + int VictimClass = 0; + int VictimID = -1; + int VictimTeam = 0; + std::string VictimColor = ""; + + bool redused; float TimeToLive = 5.f; }; + std::string m_RedColor = "\\C08366D"; + std::string m_BlueColor = "\\C6A1208"; + std::list m_DeathQueue; }; diff --git a/include/Game/Systems/LifetimeSystem.h b/include/Game/Systems/LifetimeSystem.h index 6dee644d..d19308d5 100644 --- a/include/Game/Systems/LifetimeSystem.h +++ b/include/Game/Systems/LifetimeSystem.h @@ -10,7 +10,7 @@ public: : System(params) , PureSystem("Lifetime") { - LOG_INFO("ASDASDASSA"); + } virtual void Update(double dt) override; diff --git a/include/Game/Systems/MainMenuSystem.h b/include/Game/Systems/MainMenuSystem.h new file mode 100644 index 00000000..96b6ee28 --- /dev/null +++ b/include/Game/Systems/MainMenuSystem.h @@ -0,0 +1,45 @@ +#ifndef MainMenuSystem_h__ +#define MainMenuSystem_h__ + +#include "Core/System.h" +#include "Rendering/IRenderer.h" +#include "Core/ResourceManager.h" +#include "Core/Event.h" +#include "Systems/SpawnerSystem.h" + +#include "GUI/EButtonClicked.h" +#include "GUI/EButtonPressed.h" +#include "GUI/EButtonReleased.h" +#include "Input/EInputCommand.h" +#include "Network/ESearchForServers.h" +#include "Network/EConnectRequest.h" +#include + + +class MainMenuSystem : public ImpureSystem +{ +public: + MainMenuSystem(SystemParams params, IRenderer* renderer); + virtual void Update(double dt) override; + +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); + EventRelay m_EReleased; + bool OnButtonRelease(const Events::ButtonReleased& e); + EventRelay m_EPressed; + bool OnButtonPress(const Events::ButtonPressed& e); + EventRelay m_EInputCommand; + bool OnInputCommand(const Events::InputCommand& e); + + std::string m_CurrentCommand = ""; + EntityWrapper m_OpenSubMenu = EntityWrapper::Invalid; + EntityWrapper m_DropDown = EntityWrapper::Invalid; + +}; + +#endif \ No newline at end of file diff --git a/include/Game/Systems/PickupSpawnSystem.h b/include/Game/Systems/PickupSpawnSystem.h new file mode 100644 index 00000000..de1fa024 --- /dev/null +++ b/include/Game/Systems/PickupSpawnSystem.h @@ -0,0 +1,41 @@ +#ifndef PickupSpawnSystem_h__ +#define PickupSpawnSystem_h__ + +#include "Core/System.h" +#include "Core/TransformSystem.h" +#include "Core/ResourceManager.h" +#include "Core/EntityFile.h" +#include "Core/EPickupSpawned.h" +#include "Core/EPlayerHealthPickup.h" +#include "Engine/Collision/ETrigger.h" +#include "Common.h" + +class PickupSpawnSystem : public ImpureSystem +{ +public: + PickupSpawnSystem(SystemParams params); + + virtual void Update(double dt) override; + +private: + EventRelay m_ETriggerTouch; + bool OnTriggerTouch(Events::TriggerTouch& e); + EventRelay m_ETriggerLeave; + bool OnTriggerLeave(Events::TriggerLeave& e); + + struct NewHealthPickup { + glm::vec3 Pos; + double HealthGain; + double RespawnTimer; + double DecreaseThisRespawnTimer; + EntityID parentID; + }; + std::vector m_ETriggerTouchVector; + struct EntityAtMaxValuePickupStruct { + EntityWrapper player; + EntityWrapper trigger; + }; + std::vector m_PickupAtMaximum; + void DoPickup(EntityWrapper &player, EntityWrapper &trigger); +}; +#endif diff --git a/include/Game/Systems/PlayerDeathSystem.h b/include/Game/Systems/PlayerDeathSystem.h index 112c202e..91b9997b 100644 --- a/include/Game/Systems/PlayerDeathSystem.h +++ b/include/Game/Systems/PlayerDeathSystem.h @@ -6,11 +6,9 @@ #include "GLM.h" #include "Rendering/ESetCamera.h" #include "Core/ConfigFile.h" - #include "Core/EntityFile.h" -#include "Core/EntityFileParser.h" - #include "Core/EPlayerDeath.h" +#include "Core/EEntityDeleted.h" class PlayerDeathSystem : public ImpureSystem { @@ -20,9 +18,16 @@ public: virtual void Update(double dt) override; private: + EntityWrapper m_LocalPlayerDeathEffect; + EventRelay m_OnPlayerDeath; bool OnPlayerDeath(Events::PlayerDeath& e); + EventRelay m_EEntityDeleted; + bool OnEntityDeleted(Events::EntityDeleted& e); + EventRelay m_EInputCommand; + bool OnInputCommand(Events::InputCommand& e); + void setSpectatorCamera(); void createDeathEffect(EntityWrapper player); }; diff --git a/include/Game/Systems/PlayerMovementSystem.h b/include/Game/Systems/PlayerMovementSystem.h index 92aa1915..60d25a42 100644 --- a/include/Game/Systems/PlayerMovementSystem.h +++ b/include/Game/Systems/PlayerMovementSystem.h @@ -6,9 +6,7 @@ #include #include "Events/EDoubleJump.h" #include "../Engine/Sound/EPlaySoundOnEntity.h" - #include "Core/EntityFile.h" -#include "Core/EntityFileParser.h" class PlayerMovementSystem : public ImpureSystem { @@ -32,8 +30,12 @@ private: bool m_LeftFoot = false; // To get a difference when calculating the walking state. glm::vec3 m_LastPosition = glm::vec3(); + // Used to track afterimages for sprint effect. + float m_SprintEffectTimer; + // Used to track afterimages for dash effect. + float m_DashEffectTimer; // 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); @@ -41,7 +43,11 @@ private: bool OnPlayerSpawned(Events::PlayerSpawned& e); EventRelay m_EDoubleJump; bool PlayerMovementSystem::OnDoubleJump(Events::DoubleJump & e); + EventRelay m_EDashAbility; + bool PlayerMovementSystem::OnDashAbility(Events::DashAbility & e); void updateMovementControllers(double dt); void updateVelocity(EntityWrapper player, double dt); + + void setAim(EntityWrapper root, std::string weaponNodeName, double time); }; \ No newline at end of file diff --git a/include/Game/Systems/PlayerSpawnSystem.h b/include/Game/Systems/PlayerSpawnSystem.h index bf87bef8..479f3bd0 100644 --- a/include/Game/Systems/PlayerSpawnSystem.h +++ b/include/Game/Systems/PlayerSpawnSystem.h @@ -13,14 +13,21 @@ public: PlayerSpawnSystem(SystemParams params); virtual void Update(double dt) override; - - static void SetRespawnTime(float respawnTime) { m_RespawnTime = respawnTime; }; private: + // This enum must correspond to the command values for PickTeam buttons. + enum class PlayerClass + { + None = 0, + Assault = 1, + Defender = 2, + Sniper = 2 + }; struct SpawnRequest { int PlayerID; ComponentInfo::EnumType Team; + PlayerClass Class; }; bool m_NetworkEnabled = false; @@ -31,8 +38,8 @@ private: //EntityWrapper ID -> Player ID. std::map m_PlayerIDs; - static float m_RespawnTime; - float m_Timer; + float m_ForcedRespawnTime; + bool m_DbgConfigForceRespawn; EventRelay m_OnInputCommand; bool OnInputCommand(Events::InputCommand& e); 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 new file mode 100644 index 00000000..6b2bb113 --- /dev/null +++ b/include/Game/Systems/ScoreScreenSystem.h @@ -0,0 +1,50 @@ +#ifndef ScoreScreenSystem_h__ +#define ScoreScreenSystem_h__ + +#include "Core/System.h" +#include "Core/ResourceManager.h" +#include "Core/EntityFile.h" +#include "Network/EKillDeath.h" +#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 +{ +public: + ScoreScreenSystem(SystemParams params); + + virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& scoreScreen, double dt) override; + + EventRelay m_EPlayerDeath; + bool OnPlayerDeath(const Events::KillDeath& e); + EventRelay m_EPlayerSpawned; + bool OnPlayerSpawn(const Events::PlayerSpawned& e); + EventRelay m_EPlayerConnected; + 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 { + int ID = -1; + std::string Name = ""; + int Team = 1; + int Kills = 0; + int Deaths = 0; + EntityWrapper Player = EntityWrapper::Invalid; + }; + + std::vector m_DisconnectedIdentities; + int m_PlayerCounter = 0; + std::unordered_map m_PlayerIdentities; +}; + +#endif \ No newline at end of file diff --git a/include/Game/Systems/ServerListSystem.h b/include/Game/Systems/ServerListSystem.h new file mode 100644 index 00000000..014c8881 --- /dev/null +++ b/include/Game/Systems/ServerListSystem.h @@ -0,0 +1,29 @@ +#ifndef ServerListSystem_h__ +#define ServerListSystem_h__ + +#include "Core/System.h" +#include "Rendering/IRenderer.h" +#include "Core/ResourceManager.h" +#include "Core/Event.h" +#include "Systems/SpawnerSystem.h" +#include "Core/EventBroker.h" + +#include "Network/ESearchForServers.h" +#include "Network/EDisplayServerlist.h" + +class ServerListSystem : public PureSystem +{ +public: + ServerListSystem(SystemParams params, IRenderer* renderer); + virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& cServerList, double dt) override; + + void RefreshList(); + +private: + IRenderer* m_Renderer; + + EventRelay m_EServerListRecieved; + bool OnServerListRecieved(const Events::DisplayServerlist& e); +}; + +#endif \ No newline at end of file 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 e4a44738..96b33cb6 100644 --- a/include/Game/Systems/SpawnerSystem.h +++ b/include/Game/Systems/SpawnerSystem.h @@ -6,9 +6,9 @@ #include "GLM.h" #include "Core/System.h" #include "Events/ESpawnerSpawn.h" -#include "Core/Transform.h" -#include "Core/ResourceManager.h" -#include "Core/EntityFileParser.h" +#include "Core/TransformSystem.h" +#include "Core/EntityFile.h" +#include "Rendering/Model.h" class SpawnerSystem : public System { @@ -19,6 +19,7 @@ public: // will try to pick a spawn location so that the spawned entity doesn't // collide with anything that has that component and is collidable. static EntityWrapper Spawn(EntityWrapper spawner, EntityWrapper parent = EntityWrapper::Invalid, const std::string& dontCollideComponent = ""); + static EntityWrapper SpawnEntityFile(const std::string& entityFilePath, EntityWrapper spawner, EntityWrapper parent = EntityWrapper::Invalid, const std::string& dontCollideComponent = ""); private: EventRelay m_OnSpawnerSpawn; diff --git a/include/Game/Systems/SpectatorCameraSystem.h b/include/Game/Systems/SpectatorCameraSystem.h new file mode 100644 index 00000000..6ba7294d --- /dev/null +++ b/include/Game/Systems/SpectatorCameraSystem.h @@ -0,0 +1,29 @@ +#ifndef SpectatorCameraSystem_h__ +#define SpectatorCameraSystem_h__ + +#include "Core/System.h" +#include "Input/EInputCommand.h" +#include "Network/EPlayerDisconnected.h" +#include "Game/Events/EReset.h" + +class SpectatorCameraSystem : public ImpureSystem +{ +public: + SpectatorCameraSystem(SystemParams params); + + virtual void Update(double dt) override; + +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/StartSystem.h b/include/Game/Systems/StartSystem.h new file mode 100644 index 00000000..fb2231e9 --- /dev/null +++ b/include/Game/Systems/StartSystem.h @@ -0,0 +1,23 @@ +#ifndef StartSystem_h__ +#define StartSystem_h__ + +#include "Core/System.h" +#include "Core/ResourceManager.h" +#include "Core/Event.h" +#include "Core/EventBroker.h" +#include "Rendering/ESetCamera.h" + +class StartSystem : public ImpureSystem +{ +public: + StartSystem(SystemParams params); + virtual void Update(double dt) override; + +private: + EntityWrapper m_ActiveCamera = EntityWrapper::Invalid; + + EventRelay m_ECameraActivated; + bool OnCameraActivated(const Events::SetCamera& e); +}; + +#endif \ No newline at end of file diff --git a/include/Game/Systems/TextFieldReader.h b/include/Game/Systems/TextFieldReader.h new file mode 100644 index 00000000..290bedbc --- /dev/null +++ b/include/Game/Systems/TextFieldReader.h @@ -0,0 +1,21 @@ +#ifndef AmmunitionHUDSystem_h__ +#define AmmunitionHUDSystem_h__ + +#include +#include +#include +#include "../../Engine/Core/System.h" +#include "../../Engine/GLM.h" + +class TextFieldReader : public PureSystem +{ +public: + TextFieldReader(SystemParams params) + : System(params) + , PureSystem("TextFieldReader") + { } + + virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& cTextFieldReader, double dt) override; +}; + +#endif \ No newline at end of file diff --git a/include/Game/Systems/Weapon/AssaultWeaponBehaviour.h b/include/Game/Systems/Weapon/AssaultWeaponBehaviour.h index 993dd060..5783cf31 100644 --- a/include/Game/Systems/Weapon/AssaultWeaponBehaviour.h +++ b/include/Game/Systems/Weapon/AssaultWeaponBehaviour.h @@ -1,47 +1,44 @@ #ifndef AssaultWeaponBehaviour_h__ #define AssaultWeaponBehaviour_h__ -#include "Sound/EPlaySoundOnEntity.h" -#include "Collision/Collision.h" -#include "Core/ConfigFile.h" #include "WeaponBehaviour.h" -#include "../SpawnerSystem.h" +#include "Collision/Collision.h" #include "Core/EPlayerDamage.h" -#include "Core/EShoot.h" +#include "Sound/EPlaySoundOnEntity.h" +#include "Rendering/EAutoAnimationBlend.h" class AssaultWeaponBehaviour : public WeaponBehaviour { public: AssaultWeaponBehaviour(SystemParams systemParams, IRenderer* renderer, Octree* collisionOctree) - : WeaponBehaviour(systemParams, "AssaultWeapon", renderer, collisionOctree) + : System(systemParams) + , WeaponBehaviour(systemParams, "AssaultWeapon", renderer, collisionOctree) + , m_RandomEngine(m_RandomDevice()) { } -protected: - virtual void OnPrimaryFire(WeaponInfo& wi) override; - virtual void OnCeasePrimaryFire(WeaponInfo& wi) override; - virtual void OnReload(WeaponInfo& wi) override; + void UpdateComponent(EntityWrapper& entity, ComponentWrapper& cWeapon, double dt) override; + void UpdateWeapon(ComponentWrapper cWeapon, WeaponInfo& wi, double dt) override; + void OnPrimaryFire(ComponentWrapper cWeapon, WeaponInfo& wi) override; + void OnCeasePrimaryFire(ComponentWrapper cWeapon, WeaponInfo& wi) override; + void OnReload(ComponentWrapper cWeapon, WeaponInfo& wi) override; + void OnEquip(ComponentWrapper cWeapon, WeaponInfo& wi) override; + void OnHolster(ComponentWrapper cWeapon, WeaponInfo& wi) override; + //bool OnInputCommand(ComponentWrapper cWeapon, WeaponInfo& wi, const Events::InputCommand& e) override; private: - // State - bool m_Firing = false; - bool m_Reloading = false; - double m_ReloadTimer = 0.0; - double m_TimeSinceLastFire = 0.0; - EntityWrapper m_FirstPersonReloadImpostor; + std::random_device m_RandomDevice; + std::mt19937 m_RandomEngine; + + // Weapon functions + void fireBullet(ComponentWrapper cWeapon, WeaponInfo& wi); + bool canFire(ComponentWrapper cWeapon, WeaponInfo& wi); + bool dealDamage(ComponentWrapper cWeapon, WeaponInfo& wi); + + // Utility + //Camera cameraFromEntity(EntityWrapper camera); + + void CheckBoost(ComponentWrapper cWeapon, WeaponInfo& wi); - bool hasAmmo(); - void fireRound(); - void spawnTracer(); - float traceRayDistance(glm::vec3 origin, glm::vec3 direction); - void playFireSound(); - void playEmptySound(); - void viewPunch(); - void finishReload(); - void playShootAnimation(); - void playIdleAnimation(); - void playReloadAnimation(); - bool shoot(double damage); - void showHitMarker(); }; #endif \ No newline at end of file diff --git a/include/Game/Systems/Weapon/DefenderWeaponBehaviour.h b/include/Game/Systems/Weapon/DefenderWeaponBehaviour.h index 5ca13d3e..178f4eaf 100644 --- a/include/Game/Systems/Weapon/DefenderWeaponBehaviour.h +++ b/include/Game/Systems/Weapon/DefenderWeaponBehaviour.h @@ -1,7 +1,12 @@ +#ifndef DefenderWeaponBehaviour_h__ +#define DefenderWeaponBehaviour_h__ + #include "WeaponBehaviour.h" #include "Collision/Collision.h" #include "Core/EPlayerDamage.h" -#include "Rendering/ESetCamera.h" +#include "Sound/EPlaySoundOnEntity.h" +#include "Sound/EPlaySoundOnEntity.h" +#include class DefenderWeaponBehaviour : public WeaponBehaviour { @@ -10,29 +15,33 @@ public: : System(systemParams) , WeaponBehaviour(systemParams, "DefenderWeapon", renderer, collisionOctree) , m_RandomEngine(m_RandomDevice()) - { - EVENT_SUBSCRIBE_MEMBER(m_ESetCamera, &DefenderWeaponBehaviour::OnSetCamera); - } + { } void UpdateComponent(EntityWrapper& entity, ComponentWrapper& cWeapon, double dt) override; - void UpdateWeapon(WeaponInfo& wi, double dt) override; - void OnPrimaryFire(WeaponInfo& wi) override; - void OnCeasePrimaryFire(WeaponInfo& wi) override; - bool OnInputCommand(WeaponInfo& wi, const Events::InputCommand& e) override; + void UpdateWeapon(ComponentWrapper cWeapon, WeaponInfo& wi, double dt) override; + void OnPrimaryFire(ComponentWrapper cWeapon, WeaponInfo& wi) override; + void OnCeasePrimaryFire(ComponentWrapper cWeapon, WeaponInfo& wi) override; + void OnReload(ComponentWrapper cWeapon, WeaponInfo& wi) override; + void OnHolster(ComponentWrapper cWeapon, WeaponInfo& wi) override; + bool OnInputCommand(ComponentWrapper cWeapon, WeaponInfo& wi, const Events::InputCommand& e) override; + void OnEquip(ComponentWrapper cWeapon, WeaponInfo& wi) override; + private: std::random_device m_RandomDevice; std::mt19937 m_RandomEngine; - EntityWrapper m_CurrentCamera; - EventRelay m_ESetCamera; - bool OnSetCamera(const Events::SetCamera& e); + // Weapon functions - void fireShell(WeaponInfo& wi); - void dealDamage(WeaponInfo& wi, glm::vec3 direction, double damage); + void fireShell(ComponentWrapper cWeapon, WeaponInfo& wi); + void dealDamage(ComponentWrapper cWeapon, WeaponInfo& wi, const std::vector& pattern); + void spawnTracers(ComponentWrapper cWeapon, WeaponInfo& wi, std::vector pattern); + bool canFire(ComponentWrapper cWeapon, WeaponInfo& wi); // Utility - float traceRayDistance(glm::vec3 origin, glm::vec3 direction); Camera cameraFromEntity(EntityWrapper camera); -}; \ No newline at end of file + void CheckBoost(ComponentWrapper cWeapon, WeaponInfo& wi); +}; + +#endif \ No newline at end of file diff --git a/include/Game/Systems/Weapon/SidearmWeaponBehaviour.h b/include/Game/Systems/Weapon/SidearmWeaponBehaviour.h new file mode 100644 index 00000000..7eaca082 --- /dev/null +++ b/include/Game/Systems/Weapon/SidearmWeaponBehaviour.h @@ -0,0 +1,51 @@ +#ifndef SidearmWeaponBehaviour_h__ +#define SidearmWeaponBehaviour_h__ + +#include "WeaponBehaviour.h" +#include "Collision/Collision.h" +#include "Core/EPlayerDamage.h" +#include "Sound/EPlaySoundOnEntity.h" +#include "Rendering/EAutoAnimationBlend.h" + +class SidearmWeaponBehaviour : public WeaponBehaviour +{ +public: + SidearmWeaponBehaviour(SystemParams systemParams, IRenderer* renderer, Octree* collisionOctree) + : System(systemParams) + , WeaponBehaviour(systemParams, "SidearmWeapon", renderer, collisionOctree) + , m_RandomEngine(m_RandomDevice()) + { } + + void UpdateComponent(EntityWrapper& entity, ComponentWrapper& cWeapon, double dt) override; + void UpdateWeapon(ComponentWrapper cWeapon, WeaponInfo& wi, double dt) override; + void OnPrimaryFire(ComponentWrapper cWeapon, WeaponInfo& wi) override; + void OnCeasePrimaryFire(ComponentWrapper cWeapon, WeaponInfo& wi) override; + void OnReload(ComponentWrapper cWeapon, WeaponInfo& wi) override; + void OnEquip(ComponentWrapper cWeapon, WeaponInfo& wi) override; + void OnHolster(ComponentWrapper cWeapon, WeaponInfo& wi) override; + +private: + std::random_device m_RandomDevice; + std::mt19937 m_RandomEngine; + + // Weapon functions + void fireBullet(ComponentWrapper cWeapon, WeaponInfo& wi); + //void dealDamage(WeaponInfo& wi, glm::vec3 direction, double damage); + + // Utility + bool canFire(ComponentWrapper cWeapon); + bool playerInFirstPerson(EntityWrapper player); + + bool dealDamage(ComponentWrapper cWeapon, WeaponInfo& wi); + // void giveAmmo(ComponentWrapper cWeapon, WeaponInfo& wi, EntityWrapper receiver); + + void spawnTracer(ComponentWrapper cWeapon, WeaponInfo& wi); + + void CheckAmmo(ComponentWrapper cWeapon, WeaponInfo& wi); + void RemoveFrindlyAmmoHUD(WeaponInfo& wi); + + + //float traceRayDistance(glm::vec3 origin, glm::vec3 direction); +}; + +#endif \ No newline at end of file diff --git a/include/Game/Systems/Weapon/WeaponBehaviour.h b/include/Game/Systems/Weapon/WeaponBehaviour.h index f23269df..bafc907e 100644 --- a/include/Game/Systems/Weapon/WeaponBehaviour.h +++ b/include/Game/Systems/Weapon/WeaponBehaviour.h @@ -7,6 +7,9 @@ #include "Collision/EntityAABB.h" #include "Input/EInputCommand.h" #include "Systems/SpawnerSystem.h" +#include "Rendering/ESetCamera.h" +#include "Core/ConfigFile.h" +#include "Rendering/EAutoAnimationBlend.h" template class WeaponBehaviour : public PureSystem @@ -20,42 +23,159 @@ public: , m_Renderer(renderer) , m_CollisionOctree(collisionOctree) { - EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &WeaponBehaviour::_OnInputCommand) + EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &WeaponBehaviour::_OnInputCommand); + EVENT_SUBSCRIBE_MEMBER(m_ESetCamera, &WeaponBehaviour::_OnSetCamera); + auto config = ResourceManager::Load("Config.ini"); + m_ConfigAutoReload = config->Get("Gameplay.AutoReload", true); } virtual ~WeaponBehaviour() = default; - virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) override + virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& cWeapon, double dt) override { + /* EntityWrapper firstPersonWeapon = entity.FirstChildByName("Hands").FirstChildByName("AssaultWeapon"); + EntityWrapper thirdPersonWeapon = entity.FirstChildByName("PlayerModel").FirstChildByName("AssaultWeapon"); + if (IsClient && (firstPersonWeapon.Valid() || thirdPersonWeapon.Valid())) { + if (m_ActiveWeapons.count(entity) == 0) { + WeaponInfo& wi = m_ActiveWeapons[entity]; + wi.Player = entity; + wi.WeaponEntity = entity; + wi.FirstPersonEntity = firstPersonWeapon; + wi.ThirdPersonEntity = thirdPersonWeapon; + + OnEquip(cWeapon, wi); + } + }*/ + auto weapon = getActiveWeapon(entity); if (!weapon) { return; } else { - UpdateWeapon(*weapon, dt); + UpdateWeapon(cWeapon, *weapon, dt); } } protected: struct WeaponInfo { - std::string WeaponComponent; EntityWrapper Player; EntityWrapper WeaponEntity; EntityWrapper FirstPersonEntity; + EntityWrapper FirstPersonPlayerModel; EntityWrapper ThirdPersonEntity; - ComponentWrapper GetComponent() { return WeaponEntity[WeaponComponent]; } + EntityWrapper ThirdPersonPlayerModel; }; IRenderer* m_Renderer; + EntityWrapper m_CurrentCamera; Octree* m_CollisionOctree; std::unordered_map m_ActiveWeapons; + bool m_ConfigAutoReload; - virtual void UpdateWeapon(WeaponInfo& wi, double dt) { } - virtual void OnPrimaryFire(WeaponInfo& wi) { } - virtual void OnCeasePrimaryFire(WeaponInfo& wi) { } - virtual void OnReload(WeaponInfo& wi) { } - virtual bool OnInputCommand(WeaponInfo& wi, const Events::InputCommand& e) { return false; } + virtual void UpdateWeapon(ComponentWrapper cWeapon, WeaponInfo& wi, double dt) { } + virtual void OnPrimaryFire(ComponentWrapper cWeapon, WeaponInfo& wi) { } + virtual void OnCeasePrimaryFire(ComponentWrapper cWeapon, WeaponInfo& wi) { } + virtual void OnReload(ComponentWrapper cWeapon, WeaponInfo& wi) { } + virtual void OnEquip(ComponentWrapper cWeapon, WeaponInfo& wi) { } + virtual void OnHolster(ComponentWrapper cWeapon, WeaponInfo& wi) { } + virtual bool OnInputCommand(ComponentWrapper cWeapon, WeaponInfo& wi, const Events::InputCommand& e) { return false; } + + bool isPlayerInFirstPerson(EntityWrapper player) + { + if (!m_CurrentCamera.Valid()) { + return false; + } else { + return m_CurrentCamera == player || m_CurrentCamera.IsChildOf(player); + } + } + + // Returns wi.FirstPersonEntity or wi.ThirdPersonEntity depending on + // if the player is in first person mode or not. + EntityWrapper getRelevantWeaponEntity(WeaponInfo& wi) + { + if (isPlayerInFirstPerson(wi.Player)) { + return wi.FirstPersonEntity; + } else { + return wi.ThirdPersonEntity; + } + } + + float traceRayDistance(glm::vec3 origin, glm::vec3 direction) + { + float distance; + glm::vec3 pos; + auto entity = Collision::EntityFirstHitByRay(Ray(origin, direction), m_CollisionOctree, distance, pos); + if (entity) { + return distance; + } else { + return 100.f; + } + } + + void playAnimation(EntityWrapper weaponModelEntity, const std::string& subTreeName, const std::string& animationNodeName) + { + EntityWrapper root = weaponModelEntity.FirstParentWithComponent("Model"); + if (!root.Valid()) { + return; + } + + EntityWrapper subTree = root.FirstChildByName(subTreeName); + if (!subTree.Valid()) { + return; + } + + EntityWrapper animationNode = subTree.FirstChildByName(animationNodeName); + if (!animationNode.Valid()) { + return; + } + + Events::AutoAnimationBlend eFireBlend; + eFireBlend.RootNode = root; + eFireBlend.NodeName = animationNodeName; + eFireBlend.Restart = true; + eFireBlend.Start = true; + m_EventBroker->Publish(eFireBlend); + } + + void playAnimationAndReturn(EntityWrapper weaponModelEntity, const std::string& subTreeName, const std::string& animationNodeName) + { + EntityWrapper root = weaponModelEntity; + if (!root.Valid()) { + return; + } + + EntityWrapper subTree = root.FirstChildByName(subTreeName); + if (!subTree.Valid()) { + return; + } + + EntityWrapper animationNode = subTree.FirstChildByName(animationNodeName); + if (!animationNode.Valid()) { + return; + } + + Events::AutoAnimationBlend eFireBlend; + eFireBlend.RootNode = root; + eFireBlend.NodeName = animationNodeName; + eFireBlend.Restart = true; + eFireBlend.Start = true; + m_EventBroker->Publish(eFireBlend); + + Events::AutoAnimationBlend eIdleBlend; + eIdleBlend.RootNode = root; + eIdleBlend.NodeName = "Idle"; + eIdleBlend.AnimationEntity = animationNode; + eIdleBlend.Delay = -0.2; + eIdleBlend.Duration = 0.2; + m_EventBroker->Publish(eIdleBlend); + } private: + EventRelay m_ESetCamera; + bool _OnSetCamera(const Events::SetCamera& e) + { + m_CurrentCamera = e.CameraEntity; + return true; + } EventRelay m_EInputCommand; bool _OnInputCommand(const Events::InputCommand& e) { @@ -70,15 +190,19 @@ private: } // Make sure the player has this weapon - auto weapon = getWeaponComponent(player); - if (!weapon) { + auto cWeapon = getWeaponComponent(player); + if (!cWeapon) { return false; } // Weapon selection if (e.Command == "SelectWeapon") { - if (static_cast(e.Value) == static_cast((*weapon)["Slot"])) { - selectWeapon(player); + if (e.Value > 0) { + if (static_cast(e.Value) == static_cast((*cWeapon)["Slot"])) { + selectWeapon(*cWeapon, player); + } else { + holsterWeapon(*cWeapon, player); + } } } @@ -91,18 +215,18 @@ private: // Fire if (e.Command == "PrimaryFire") { if (e.Value > 0) { - OnPrimaryFire(*activeWeapon); + OnPrimaryFire(*cWeapon, *activeWeapon); } else { - OnCeasePrimaryFire(*activeWeapon); + OnCeasePrimaryFire(*cWeapon, *activeWeapon); } } // Reload if (e.Command == "Reload" && e.Value != 0) { - OnReload(*activeWeapon); + OnReload(*cWeapon, *activeWeapon); } - return OnInputCommand(*activeWeapon, e); + return OnInputCommand(*cWeapon, *activeWeapon, e); } boost::optional getWeaponComponent(EntityWrapper player) @@ -129,15 +253,25 @@ private: return activeWeapon; } - void selectWeapon(EntityWrapper player) + void selectWeapon(ComponentWrapper cWeapon, EntityWrapper player) { + //if (!IsServer) { + // return; + //} + + // Don't reselect weapon if it's already active + if (getActiveWeapon(player)) { + return; + } + // Find the weapon attachments matching the weapon type std::vector weaponAttachments = player.ChildrenWithComponent("WeaponAttachment"); EntityWrapper firstPersonAttachment; 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; @@ -152,29 +286,52 @@ private: return; } - // Purge other weapon entities - for (auto& attachment : weaponAttachments) { - //if (attachment == firstPersonAttachment || attachment == thirdPersonAttachment) { - // continue; - //} - attachment.DeleteChildren(); - } - // Spawn the weapon(s) EntityWrapper firstPersonWeapon; EntityWrapper thirdPersonWeapon; - if (firstPersonAttachment.Valid()) { - firstPersonWeapon = SpawnerSystem::Spawn(firstPersonAttachment, firstPersonAttachment); + if (IsClient) { + if (firstPersonAttachment.Valid()) { + firstPersonWeapon = SpawnerSystem::Spawn(firstPersonAttachment, firstPersonAttachment); + } } if (thirdPersonAttachment.Valid()) { thirdPersonWeapon = SpawnerSystem::Spawn(thirdPersonAttachment, thirdPersonAttachment); } - m_ActiveWeapons[player].WeaponComponent = m_ComponentType; - m_ActiveWeapons[player].Player = player; - m_ActiveWeapons[player].WeaponEntity = player; - m_ActiveWeapons[player].FirstPersonEntity = firstPersonWeapon; - m_ActiveWeapons[player].ThirdPersonEntity = thirdPersonWeapon; + WeaponInfo& wi = m_ActiveWeapons[player]; + wi.Player = player; + wi.WeaponEntity = player; + wi.FirstPersonEntity = firstPersonWeapon; + wi.FirstPersonPlayerModel = firstPersonWeapon; + wi.ThirdPersonEntity = thirdPersonWeapon; + wi.ThirdPersonPlayerModel = thirdPersonWeapon.FirstParentWithComponent("Model"); + + player["Player"]["CurrentWeapon"] = cWeapon.Info.Name; + + OnEquip(cWeapon, wi); + } + + void holsterWeapon(ComponentWrapper cWeapon, EntityWrapper player) + { + auto activeWeapon = getActiveWeapon(player); + if (!activeWeapon) { + return; + } + WeaponInfo& wi = *activeWeapon; + + // Send holster event + OnHolster(cWeapon, wi); + + // Delete weapon entities + if (wi.FirstPersonEntity.Valid()) { + m_World->DeleteEntity(wi.FirstPersonEntity.ID); + } + if (wi.ThirdPersonEntity.Valid()) { + m_World->DeleteEntity(wi.ThirdPersonEntity.ID); + } + + // Make weapon inactive + m_ActiveWeapons.erase(player); } }; diff --git a/include/Game/Systems/Weapon/WeaponSystem.h b/include/Game/Systems/Weapon/WeaponSystem.h index b8278bc4..f6543ffb 100644 --- a/include/Game/Systems/Weapon/WeaponSystem.h +++ b/include/Game/Systems/Weapon/WeaponSystem.h @@ -9,8 +9,8 @@ #include "Core/EShoot.h" #include "Core/EPlayerSpawned.h" #include "Input/EInputCommand.h" -#include "Core/EntityFile.h" -#include "Core/EntityFileParser.h" +#include "Core/EntityXMLFile.h" +#include "Core/EntityXMLFileParser.h" #include "Core/Octree.h" #include "Collision/EntityAABB.h" #include "Systems/SpawnerSystem.h" diff --git a/resources/Axyz.ico b/resources/Axyz.ico new file mode 100755 index 00000000..b033831f Binary files /dev/null and b/resources/Axyz.ico differ diff --git a/resources/DefaultConfig.ini b/resources/DefaultConfig.ini index 60ee4823..7d954d1b 100644 --- a/resources/DefaultConfig.ini +++ b/resources/DefaultConfig.ini @@ -1,10 +1,13 @@ +[Gameplay] +AutoReload=true + [Debug] LogLevel=1 -LoadMap= +LoadMap=Schema/Entities/StartMenu.xml ; if true -> Pool allocation is not used when calling Allocate/Free, just use regular dynamic allocation. ; if false -> Use pool allocation. DisableMemoryPool=false -RespawnTime = 8.0 +RespawnTime=-1.0 EditorEnabled=false OutOfBodyExperience=false @@ -19,7 +22,7 @@ Height=720 FOV=45 [Networking] -StartNetwork=false +StartNetwork=true IsServer=false Name=Bob Address=127.0.0.1 @@ -27,7 +30,7 @@ Port=27666 MaxConnections=8 SnapshotInterval=0.05 SendInputIntervalMs=33 -PingIntervalMs= 1000 +PingIntervalMs=1000 TimeoutMs=15000 [Multithreading] @@ -36,4 +39,53 @@ ResourceLoading=true [Sound] BGMVolume=1.0 SFXVolume=1.0 -Announcer=female \ No newline at end of file +AnnouncerVolume=1.0 +Announcer=female + +[SSAO] +Quality=1 + +[SSAO1] +Radius=1.0 +Bias=0.02 +Contrast=1.5 +Intensity=1.0 +NumSamples=8 +NumTurns=3 +NumIterations=5 +TextureQuality=2 + +[SSAO2] +Radius=1.0 +Bias=0.02 +Contrast=1.5 +Intensity=1.0 +NumSamples=16 +NumTurns=13 +NumIterations=9 +TextureQuality=1 + +[SSAO3] +Radius=1.0 +Bias=0.02 +Contrast=1.5 +Intensity=1.0 +NumSamples=24 +NumTurns=17 +NumIterations=9 +TextureQuality=0 + +[GLOW] +Quality=1 + +[GLOW1] +NumIterations=2 + +[GLOW2] +NumIterations=4 + +[GLOW3] +NumIterations=6 + +[MSAA] +Level=2 diff --git a/resources/DefaultInput.ini b/resources/DefaultInput.ini index 776cbecd..9d1a1706 100644 --- a/resources/DefaultInput.ini +++ b/resources/DefaultInput.ini @@ -1,5 +1,5 @@ [Mouse] -Sensitivity=0.5 +Sensitivity=0.05 InvertPitch=false [Keyboard] @@ -27,4 +27,6 @@ M=SwitchToClient P=SwitchToPlayer K=TakeDamage,1500 F2=PerformanceTimingResetAllTimers -F3=PerformanceTimingCreateExcelData \ No newline at end of file +F3=PerformanceTimingCreateExcelData +Comma=SwapToClassPick +Period=SwapToTeamPick \ No newline at end of file diff --git a/resources/README.txt b/resources/README.txt new file mode 100755 index 00000000..f56aab3a --- /dev/null +++ b/resources/README.txt @@ -0,0 +1,17 @@ +To start a server + + 1. Run "Axyz Server" from the start menu or "Server.bat" in the installation directory (C:\Program Files\Axyz) + 2. Press F1 to open the editor mode + 3. Expand the Entities window if it is minimized, by double-clicking it + 4. Mark StartMenu_Origin and hit Delete twice + 5. Hit Import and choose CP_Valhalla.xml + 6. Press F1 again to leave editor mode for an acceptable framerate + +To join a game + + 1. Run "Axyz" from the start menu or "Axyz.exe" in the installation directory (C:\Program Files\Axyz) + 2. Press Play + 3. Hit the refresh icon if no server is visible + 4. Click the server you want to join + 5. Follow on-screen directions + 6. Enjoy the game :) \ No newline at end of file diff --git a/resources/Schema/Components.xsd b/resources/Schema/Components.xsd index abd420d9..d4386cc0 100644 --- a/resources/Schema/Components.xsd +++ b/resources/Schema/Components.xsd @@ -33,20 +33,44 @@ - + + + + + - + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/resources/Schema/Components/AbilityCooldownHUD.xml b/resources/Schema/Components/AbilityCooldownHUD.xml new file mode 100644 index 00000000..8f91bbc3 --- /dev/null +++ b/resources/Schema/Components/AbilityCooldownHUD.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/resources/Schema/Components/AbilityCooldownHUD.xsd b/resources/Schema/Components/AbilityCooldownHUD.xsd new file mode 100644 index 00000000..5bfb01a8 --- /dev/null +++ b/resources/Schema/Components/AbilityCooldownHUD.xsd @@ -0,0 +1,9 @@ + + + + + + HUD element for tracking ability cooldown. If it has a sprite and fill component it will fill the sprite with chosen color depending on the cooldown.\n A child with text component named "Cooldown" + + + \ No newline at end of file diff --git a/resources/Schema/Components/AmmunitionHUD.xml b/resources/Schema/Components/AmmunitionHUD.xml deleted file mode 100644 index 63b86150..00000000 --- a/resources/Schema/Components/AmmunitionHUD.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/resources/Schema/Components/AmmunitionHUD.xsd b/resources/Schema/Components/AmmunitionHUD.xsd deleted file mode 100644 index 1a48d8d1..00000000 --- a/resources/Schema/Components/AmmunitionHUD.xsd +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - Hud element for tracking ammunition from parent with AssaultWeapon component. Child with the name "MagazineAmmo" tracks clip ammunition. Child with the name "Ammo" tracks ammo. - - - \ No newline at end of file diff --git a/resources/Schema/Components/Animation.xml b/resources/Schema/Components/Animation.xml index ae42009d..8e7fd69b 100644 --- a/resources/Schema/Components/Animation.xml +++ b/resources/Schema/Components/Animation.xml @@ -1,18 +1,10 @@ - - 1.0 - 0 - 0 - true - - 1.0 - 0 - 0 - true - - 1.0 - 0 - 0 - true + + + false + false + 1 + true + false \ No newline at end of file diff --git a/resources/Schema/Components/Animation.xsd b/resources/Schema/Components/Animation.xsd index f39aac18..1090c4c7 100644 --- a/resources/Schema/Components/Animation.xsd +++ b/resources/Schema/Components/Animation.xsd @@ -2,27 +2,17 @@ - - - - - - - - - - - - - - - - + + + + + + + - \ No newline at end of file diff --git a/resources/Schema/Components/AnimationOffset.xml b/resources/Schema/Components/AnimationOffset.xml deleted file mode 100644 index 4aef8219..00000000 --- a/resources/Schema/Components/AnimationOffset.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/resources/Schema/Components/AssaultWeapon.xml b/resources/Schema/Components/AssaultWeapon.xml index c835217b..0cb381c2 100755 --- a/resources/Schema/Components/AssaultWeapon.xml +++ b/resources/Schema/Components/AssaultWeapon.xml @@ -1,12 +1,22 @@ + 32 32 - 360 - 360 - 5 - 120 - 0.01 - 2 - + 320 + 320 + 15 + 0.174533 + 0.10 + 420 + 0.03 + 0.18 + 1.65 + 0.5 + false + 0 + false + false + 0 + 0 \ No newline at end of file diff --git a/resources/Schema/Components/AssaultWeapon.xsd b/resources/Schema/Components/AssaultWeapon.xsd index 7e9854a2..1faf14fa 100755 --- a/resources/Schema/Components/AssaultWeapon.xsd +++ b/resources/Schema/Components/AssaultWeapon.xsd @@ -7,6 +7,7 @@ + Ammo currently loaded into the magazine @@ -20,16 +21,33 @@ Maximum ammo able to be carried + + Spread angle in radians + + + Maximum vertical aim travel angle in radians + Rate of fire in rounds per minute - View punch in radians for each bullet fired + View punch in radians for each shell fired + + + The speed in radians per second the view returns to its original position after being punched - Time it takes to reload the weapon in seconds + Time it takes to load ONE SHELL into the weapon in seconds - + + Time it takes from selecting the weapon until it's ready to fire + + + + + + + diff --git a/resources/Schema/Components/Blend.xml b/resources/Schema/Components/Blend.xml new file mode 100644 index 00000000..a4a328ca --- /dev/null +++ b/resources/Schema/Components/Blend.xml @@ -0,0 +1,7 @@ + + + + + 0.5 + false + \ No newline at end of file diff --git a/resources/Schema/Components/Blend.xsd b/resources/Schema/Components/Blend.xsd new file mode 100644 index 00000000..34d32385 --- /dev/null +++ b/resources/Schema/Components/Blend.xsd @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/resources/Schema/Components/BlendAdditive.xml b/resources/Schema/Components/BlendAdditive.xml new file mode 100644 index 00000000..758917f9 --- /dev/null +++ b/resources/Schema/Components/BlendAdditive.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/resources/Schema/Components/BlendAdditive.xsd b/resources/Schema/Components/BlendAdditive.xsd new file mode 100644 index 00000000..ab931d52 --- /dev/null +++ b/resources/Schema/Components/BlendAdditive.xsd @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/resources/Schema/Components/BlendOverride.xml b/resources/Schema/Components/BlendOverride.xml new file mode 100644 index 00000000..c44a2d22 --- /dev/null +++ b/resources/Schema/Components/BlendOverride.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/resources/Schema/Components/BlendOverride.xsd b/resources/Schema/Components/BlendOverride.xsd new file mode 100644 index 00000000..8cf6dbd6 --- /dev/null +++ b/resources/Schema/Components/BlendOverride.xsd @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/resources/Schema/Components/BoostAssault.xml b/resources/Schema/Components/BoostAssault.xml new file mode 100644 index 00000000..29378aec --- /dev/null +++ b/resources/Schema/Components/BoostAssault.xml @@ -0,0 +1,4 @@ + + + 1.35 + diff --git a/resources/Schema/Components/BoostAssault.xsd b/resources/Schema/Components/BoostAssault.xsd new file mode 100644 index 00000000..f7d348b7 --- /dev/null +++ b/resources/Schema/Components/BoostAssault.xsd @@ -0,0 +1,18 @@ + + + + + + + + This is the assault's class boost component + + + + + This is the strength of the boost effect + + + + + diff --git a/resources/Schema/Components/BoostDefender.xml b/resources/Schema/Components/BoostDefender.xml new file mode 100644 index 00000000..fad0d2b7 --- /dev/null +++ b/resources/Schema/Components/BoostDefender.xml @@ -0,0 +1,4 @@ + + + 10 + diff --git a/resources/Schema/Components/BoostDefender.xsd b/resources/Schema/Components/BoostDefender.xsd new file mode 100644 index 00000000..167b41dd --- /dev/null +++ b/resources/Schema/Components/BoostDefender.xsd @@ -0,0 +1,18 @@ + + + + + + + + This is the defender's class boost component + + + + + This is the strength of the boost effect + + + + + diff --git a/resources/Schema/Components/BoostIconsHUD.xml b/resources/Schema/Components/BoostIconsHUD.xml new file mode 100644 index 00000000..e25d9611 --- /dev/null +++ b/resources/Schema/Components/BoostIconsHUD.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/resources/Schema/Components/BoostIconsHUD.xsd b/resources/Schema/Components/BoostIconsHUD.xsd new file mode 100644 index 00000000..c5fe2e5d --- /dev/null +++ b/resources/Schema/Components/BoostIconsHUD.xsd @@ -0,0 +1,10 @@ + + + + + + + Origin for the 3 boost states. Create 3 children with Sprite and Fill components, name them "Sprint", "Defender", "Assault" + + + \ No newline at end of file diff --git a/resources/Schema/Components/BoostSniper.xml b/resources/Schema/Components/BoostSniper.xml new file mode 100644 index 00000000..844b7c59 --- /dev/null +++ b/resources/Schema/Components/BoostSniper.xml @@ -0,0 +1,4 @@ + + + 10 + diff --git a/resources/Schema/Components/BoostSniper.xsd b/resources/Schema/Components/BoostSniper.xsd new file mode 100644 index 00000000..2d62a9da --- /dev/null +++ b/resources/Schema/Components/BoostSniper.xsd @@ -0,0 +1,18 @@ + + + + + + + + This is the sniper's class boost component + + + + + This is the strength of the boost effect + + + + + diff --git a/resources/Schema/Components/Camera.xml b/resources/Schema/Components/Camera.xml index b9c28d53..00edcc00 100644 --- a/resources/Schema/Components/Camera.xml +++ b/resources/Schema/Components/Camera.xml @@ -1,6 +1,6 @@ - 45 + 59 0.01 5000 \ No newline at end of file diff --git a/resources/Schema/Components/CapturePointArrowHUD.xml b/resources/Schema/Components/CapturePointArrowHUD.xml new file mode 100644 index 00000000..ebe8727a --- /dev/null +++ b/resources/Schema/Components/CapturePointArrowHUD.xml @@ -0,0 +1,4 @@ + + + 0 + \ No newline at end of file diff --git a/resources/Schema/Components/CapturePointArrowHUD.xsd b/resources/Schema/Components/CapturePointArrowHUD.xsd new file mode 100644 index 00000000..d1c035f6 --- /dev/null +++ b/resources/Schema/Components/CapturePointArrowHUD.xsd @@ -0,0 +1,18 @@ + + + + + + HUD element for tracking next capturable Capture Point. + + + + + + Corresponds to the current capturepoint the arrow points Towards + + + + + + \ No newline at end of file diff --git a/resources/Schema/Components/CapturePointGameMode.xml b/resources/Schema/Components/CapturePointGameMode.xml new file mode 100644 index 00000000..f8e04eaf --- /dev/null +++ b/resources/Schema/Components/CapturePointGameMode.xml @@ -0,0 +1,6 @@ + + + 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 new file mode 100644 index 00000000..791b75b1 --- /dev/null +++ b/resources/Schema/Components/CapturePointGameMode.xsd @@ -0,0 +1,21 @@ + + + + + + + + + + The time since the last respawn wave. Players will be spawned when this reaches MaxRespawnTime. + + + Players will be spawned when RespawnTime reaches this. + + + The map will be reset when time reaches 0. + + + + + \ No newline at end of file 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/DashAbility.xml b/resources/Schema/Components/DashAbility.xml index a313c447..a71e4e52 100644 --- a/resources/Schema/Components/DashAbility.xml +++ b/resources/Schema/Components/DashAbility.xml @@ -1,4 +1,5 @@ 2.0 + 0.0 \ No newline at end of file diff --git a/resources/Schema/Components/DashAbility.xsd b/resources/Schema/Components/DashAbility.xsd index 4273cc71..6fc59c77 100644 --- a/resources/Schema/Components/DashAbility.xsd +++ b/resources/Schema/Components/DashAbility.xsd @@ -10,7 +10,10 @@ - This is the cooldown on dash + This is the max cooldown on dash + + + This is the current cooldown on dash diff --git a/resources/Schema/Components/DefenderWeapon.xml b/resources/Schema/Components/DefenderWeapon.xml index 998f3bde..f2e7b3d9 100755 --- a/resources/Schema/Components/DefenderWeapon.xml +++ b/resources/Schema/Components/DefenderWeapon.xml @@ -1,16 +1,21 @@ - 8 + + 9999 8 64 64 90 - 0.174533 - 10 + 10 + 0.174533 + 9 120 - 0.01 + 0.15 + 0.3 0.5 - - false - 0 + false + 0 + false + 0 + 0 \ No newline at end of file diff --git a/resources/Schema/Components/DefenderWeapon.xsd b/resources/Schema/Components/DefenderWeapon.xsd index 3fe5a64a..4968fa5d 100755 --- a/resources/Schema/Components/DefenderWeapon.xsd +++ b/resources/Schema/Components/DefenderWeapon.xsd @@ -4,9 +4,22 @@ + + + + + + + + + + + + + Ammo currently loaded into the magazine @@ -23,7 +36,10 @@ Damage dealt if all shotgun pellets hit - Spread angle in radians + The spread angle radius. + + + Maximum vertical aim travel angle in radians @@ -32,12 +48,17 @@ View punch in radians for each shell fired + + The speed in radians per second the view returns to its original position after being punched + Time it takes to load ONE SHELL into the weapon in seconds - - - + + + + + diff --git a/resources/Schema/Components/EndScreen.xml b/resources/Schema/Components/EndScreen.xml new file mode 100644 index 00000000..8a556256 --- /dev/null +++ b/resources/Schema/Components/EndScreen.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/resources/Schema/Components/EndScreen.xsd b/resources/Schema/Components/EndScreen.xsd new file mode 100644 index 00000000..9056f210 --- /dev/null +++ b/resources/Schema/Components/EndScreen.xsd @@ -0,0 +1,10 @@ + + + + + + + Put this on the camera that will show the final screen. + + + \ No newline at end of file diff --git a/resources/Schema/Components/ExplosionEffect.xml b/resources/Schema/Components/ExplosionEffect.xml index 22692729..80022738 100644 --- a/resources/Schema/Components/ExplosionEffect.xml +++ b/resources/Schema/Components/ExplosionEffect.xml @@ -1,17 +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 cdde5e52..f0edcc8e 100644 --- a/resources/Schema/Components/ExplosionEffect.xsd +++ b/resources/Schema/Components/ExplosionEffect.xsd @@ -18,6 +18,8 @@ How many seconds the death animation should be + + @@ -42,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/Fade.xml b/resources/Schema/Components/Fade.xml new file mode 100644 index 00000000..2383b2a4 --- /dev/null +++ b/resources/Schema/Components/Fade.xml @@ -0,0 +1,8 @@ + + + 1 + + true + true + false + \ No newline at end of file diff --git a/resources/Schema/Components/Fade.xsd b/resources/Schema/Components/Fade.xsd new file mode 100644 index 00000000..c019678c --- /dev/null +++ b/resources/Schema/Components/Fade.xsd @@ -0,0 +1,23 @@ + + + + + + + + + + + + If the entity should fade out or in. + + + If the effect should loop when it is done. + + + If the entity should reverse the fade after finishing, this will double the speed. + + + + + \ No newline at end of file diff --git a/resources/Schema/Components/FloatingEffect.xml b/resources/Schema/Components/FloatingEffect.xml new file mode 100644 index 00000000..f1fd237a --- /dev/null +++ b/resources/Schema/Components/FloatingEffect.xml @@ -0,0 +1,8 @@ + + + 1 + 1 + + + + \ No newline at end of file diff --git a/resources/Schema/Components/AnimationOffset.xsd b/resources/Schema/Components/FloatingEffect.xsd similarity index 51% rename from resources/Schema/Components/AnimationOffset.xsd rename to resources/Schema/Components/FloatingEffect.xsd index c3430cc2..a71006f5 100644 --- a/resources/Schema/Components/AnimationOffset.xsd +++ b/resources/Schema/Components/FloatingEffect.xsd @@ -3,14 +3,14 @@ - - - Aim animation offset for the skeleton - + - + + + + diff --git a/resources/Schema/Components/InputCmdButton.xml b/resources/Schema/Components/InputCmdButton.xml new file mode 100644 index 00000000..58c3ba2c --- /dev/null +++ b/resources/Schema/Components/InputCmdButton.xml @@ -0,0 +1,5 @@ + + + + 0.0 + \ No newline at end of file diff --git a/resources/Schema/Components/InputCmdButton.xsd b/resources/Schema/Components/InputCmdButton.xsd new file mode 100644 index 00000000..f4dd8d3f --- /dev/null +++ b/resources/Schema/Components/InputCmdButton.xsd @@ -0,0 +1,19 @@ + + + + + + + Used with a Button component, the button will send an inputCommand event instead of ButtonPressed/Released event. + + + + The command name for the inputCommand. + + + The value in inputCommand.Value that will be sent on button press. + + + + + \ No newline at end of file diff --git a/resources/Schema/Components/Model.xml b/resources/Schema/Components/Model.xml index f81c8210..99190e1f 100644 --- a/resources/Schema/Components/Model.xml +++ b/resources/Schema/Components/Model.xml @@ -8,5 +8,6 @@ true true true - 3.0 + true + 1.0 \ No newline at end of file diff --git a/resources/Schema/Components/Model.xsd b/resources/Schema/Components/Model.xsd index 31203ff6..29f65613 100644 --- a/resources/Schema/Components/Model.xsd +++ b/resources/Schema/Components/Model.xsd @@ -36,6 +36,9 @@ Intensity of the glow map + + Whether the object cast/recieve shadows or not + diff --git a/resources/Schema/Components/NetworkComponent.xml b/resources/Schema/Components/NetworkComponent.xml new file mode 100644 index 00000000..7d5dda6f --- /dev/null +++ b/resources/Schema/Components/NetworkComponent.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/resources/Schema/Components/NetworkComponent.xsd b/resources/Schema/Components/NetworkComponent.xsd new file mode 100644 index 00000000..19cfeb92 --- /dev/null +++ b/resources/Schema/Components/NetworkComponent.xsd @@ -0,0 +1,10 @@ + + + + + + + If an entity has this component, it will be broadcasted to clients in a snapshot. + + + \ No newline at end of file diff --git a/resources/Schema/Components/PlayerSpawn.xml b/resources/Schema/Components/PlayerSpawn.xml index edc1394e..b5d64879 100644 --- a/resources/Schema/Components/PlayerSpawn.xml +++ b/resources/Schema/Components/PlayerSpawn.xml @@ -1,2 +1,6 @@ - \ No newline at end of file + + Schema/Entities/PlayerAssaultBlue.xml + Schema/Entities/PlayerDefenderBlue.xml + + \ No newline at end of file diff --git a/resources/Schema/Components/PlayerSpawn.xsd b/resources/Schema/Components/PlayerSpawn.xsd index 6e321724..9c3afb00 100644 --- a/resources/Schema/Components/PlayerSpawn.xsd +++ b/resources/Schema/Components/PlayerSpawn.xsd @@ -7,5 +7,12 @@ Combined with a Spawner and a Team component, defines a spawn point for a player team. + + + + + + + diff --git a/resources/Schema/Components/ScoreIdentity.xml b/resources/Schema/Components/ScoreIdentity.xml new file mode 100644 index 00000000..a4aa0639 --- /dev/null +++ b/resources/Schema/Components/ScoreIdentity.xml @@ -0,0 +1,10 @@ + + + + -1 + 0.0 + 0 + 0 + 0 + true + \ No newline at end of file diff --git a/resources/Schema/Components/ScoreIdentity.xsd b/resources/Schema/Components/ScoreIdentity.xsd new file mode 100644 index 00000000..d1a85bee --- /dev/null +++ b/resources/Schema/Components/ScoreIdentity.xsd @@ -0,0 +1,32 @@ + + + + + A component tracking data for the score of a player. + + + + A name for tracking score identities, this should be unique. + + + An id for tracking identities + + + The Kills per death score. + + + The amount of kills. + + + The amount of deaths. + + + Ping of a player. + + + If the player is currently connected or not + + + + + \ No newline at end of file diff --git a/resources/Schema/Components/ScoreScreen.xml b/resources/Schema/Components/ScoreScreen.xml new file mode 100644 index 00000000..d3571d07 --- /dev/null +++ b/resources/Schema/Components/ScoreScreen.xml @@ -0,0 +1,6 @@ + + + 0 + 0 + + \ No newline at end of file diff --git a/resources/Schema/Components/ScoreScreen.xsd b/resources/Schema/Components/ScoreScreen.xsd new file mode 100644 index 00000000..fb285813 --- /dev/null +++ b/resources/Schema/Components/ScoreScreen.xsd @@ -0,0 +1,20 @@ + + + + + The screen where player scores will be shown. + + + + The amount of score identities this scoreboard hold + + + Where the next scoreIdentity should be placed. + + + How much offset should be applied per position + + + + + \ No newline at end of file diff --git a/resources/Schema/Components/ServerIdentity.xml b/resources/Schema/Components/ServerIdentity.xml new file mode 100644 index 00000000..1d44e690 --- /dev/null +++ b/resources/Schema/Components/ServerIdentity.xml @@ -0,0 +1,7 @@ + + + 123.123.123.123 + 65999 + UnkownServer + 0 + \ No newline at end of file diff --git a/resources/Schema/Components/ServerIdentity.xsd b/resources/Schema/Components/ServerIdentity.xsd new file mode 100644 index 00000000..961a69c5 --- /dev/null +++ b/resources/Schema/Components/ServerIdentity.xsd @@ -0,0 +1,23 @@ + + + + + A component for tracking the data of servers in the serverlist. + + + + The IP adress of the server. + + + Port used to connect to the server. + + + Name of the server. + + + Amount of players connected to the server. + + + + + \ No newline at end of file diff --git a/resources/Schema/Components/ServerList.xml b/resources/Schema/Components/ServerList.xml new file mode 100644 index 00000000..e4dbfcad --- /dev/null +++ b/resources/Schema/Components/ServerList.xml @@ -0,0 +1,6 @@ + + + 0 + 0 + + \ No newline at end of file diff --git a/resources/Schema/Components/ServerList.xsd b/resources/Schema/Components/ServerList.xsd new file mode 100644 index 00000000..b422acda --- /dev/null +++ b/resources/Schema/Components/ServerList.xsd @@ -0,0 +1,20 @@ + + + + + The menulist where servers will be listed. + + + + The amount of server identities in this list. + + + Where the next serverIdentity should be placed. + + + How much offset should be applied per position + + + + + \ No newline at end of file diff --git a/resources/Schema/Components/ShieldAbility.xml b/resources/Schema/Components/ShieldAbility.xml new file mode 100644 index 00000000..d66dca31 --- /dev/null +++ b/resources/Schema/Components/ShieldAbility.xml @@ -0,0 +1,4 @@ + + + false + \ No newline at end of file diff --git a/resources/Schema/Components/ShieldAbility.xsd b/resources/Schema/Components/ShieldAbility.xsd new file mode 100644 index 00000000..bbb30c82 --- /dev/null +++ b/resources/Schema/Components/ShieldAbility.xsd @@ -0,0 +1,18 @@ + + + + + + + + A shield component for one of the classes + + + + + If the shield is active or not + + + + + \ No newline at end of file diff --git a/resources/Schema/Components/SidearmWeapon.xml b/resources/Schema/Components/SidearmWeapon.xml new file mode 100644 index 00000000..6f505d0c --- /dev/null +++ b/resources/Schema/Components/SidearmWeapon.xml @@ -0,0 +1,20 @@ + + + + 16 + 16 + 20 + 500 + false + 0.05 + 0.174533 + 0.2 + 1.0 + 0.5 + false + 0 + false + false + 0 + 0 + \ No newline at end of file diff --git a/resources/Schema/Components/SidearmWeapon.xsd b/resources/Schema/Components/SidearmWeapon.xsd new file mode 100644 index 00000000..fcb40c8f --- /dev/null +++ b/resources/Schema/Components/SidearmWeapon.xsd @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + Ammo currently loaded into the magazine + + + Max number of rounds in a magazine + + + Damage dealt if all shotgun pellets hit + + + Rate of fire in rounds per minute + + + + View punch in radians for each shell fired + + + Maximum vertical aim travel angle in radians + + + The speed in radians per second the view returns to its original position after being punched + + + Time it takes to load ONE SHELL into the weapon in seconds + + + Time it takes from selecting the weapon until it's ready to fire + + + + + + + + + + + diff --git a/resources/Schema/Components/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/SprintAbility.xml b/resources/Schema/Components/SprintAbility.xml new file mode 100644 index 00000000..d9727ed9 --- /dev/null +++ b/resources/Schema/Components/SprintAbility.xml @@ -0,0 +1,5 @@ + + + 1.3 + false + \ No newline at end of file diff --git a/resources/Schema/Components/SprintAbility.xsd b/resources/Schema/Components/SprintAbility.xsd new file mode 100644 index 00000000..7fe0d65a --- /dev/null +++ b/resources/Schema/Components/SprintAbility.xsd @@ -0,0 +1,21 @@ + + + + + + + + A sprint component for one of the classes + + + + + This is the strength of the sprint effect + + + True if currently sprinting. + + + + + \ No newline at end of file diff --git a/resources/Schema/Components/Sprite.xml b/resources/Schema/Components/Sprite.xml index ce4a6e1b..a67f5dde 100644 --- a/resources/Schema/Components/Sprite.xml +++ b/resources/Schema/Components/Sprite.xml @@ -1,8 +1,15 @@ + Models/Core/UnitQuad.mesh true true + false + false + false + true + false + false diff --git a/resources/Schema/Components/Sprite.xsd b/resources/Schema/Components/Sprite.xsd index 3c3d124a..44456ec7 100644 --- a/resources/Schema/Components/Sprite.xsd +++ b/resources/Schema/Components/Sprite.xsd @@ -9,14 +9,17 @@ + + The model the sprite will use. + - Diffuse Texture file + Diffuse Texture file. - GlowMap file + GlowMap file. - Color tint + Color tint. Whether the model is visible or not @@ -24,6 +27,24 @@ Whether the sprite should be sorted with depth or not. Only use false for textures that are on HUD + + Wether the sprite should repeat in x instead of stretch when scaled. + + + Wether the sprite should repeat in y instead of stretch when scaled. + + + Keep a 1:1 ratio between X and Y. + + + If it should use Linear or Nearest sampling method. + + + If it should clamp to border or repeat the texture. + + + Wether the background should be blurred begind this sprite. + diff --git a/resources/Schema/Components/Text.xml b/resources/Schema/Components/Text.xml index d38d3961..cda29b86 100644 --- a/resources/Schema/Components/Text.xml +++ b/resources/Schema/Components/Text.xml @@ -1,7 +1,7 @@ - + Fonts/DroidSans.ttf,64 true
diff --git a/resources/Schema/Components/TextFieldReader.xml b/resources/Schema/Components/TextFieldReader.xml new file mode 100644 index 00000000..52430804 --- /dev/null +++ b/resources/Schema/Components/TextFieldReader.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/resources/Schema/Components/TextFieldReader.xsd b/resources/Schema/Components/TextFieldReader.xsd new file mode 100644 index 00000000..7c77890d --- /dev/null +++ b/resources/Schema/Components/TextFieldReader.xsd @@ -0,0 +1,21 @@ + + + + + + Reads a value from a specific field of a compoent of parent entity and writes it to the Text component on this entity. + + + + The name of the parent entity to read the component field from. Leave empty to read from this entity. + + + The component type to read the field value from. + + + The field name to read the value from. + + + + + \ No newline at end of file diff --git a/resources/Schema/Components/Unpickable.xml b/resources/Schema/Components/Unpickable.xml new file mode 100644 index 00000000..07fe9a90 --- /dev/null +++ b/resources/Schema/Components/Unpickable.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/resources/Schema/Components/Unpickable.xsd b/resources/Schema/Components/Unpickable.xsd new file mode 100644 index 00000000..114886a8 --- /dev/null +++ b/resources/Schema/Components/Unpickable.xsd @@ -0,0 +1,11 @@ + + + + + + + + Makes the entity unpickable + + + \ No newline at end of file diff --git a/resources/Schema/Entities/10Degrees.xml b/resources/Schema/Entities/10Degrees.xml new file mode 100644 index 00000000..0039ca82 --- /dev/null +++ b/resources/Schema/Entities/10Degrees.xml @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Effects/Ray.png + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Effects/Ray.png + + + + + + + + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Effects/Ray.png + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Effects/Ray.png + + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/AmmoHUD b/resources/Schema/Entities/AmmoHUD deleted file mode 100644 index 6cdb6568..00000000 --- a/resources/Schema/Entities/AmmoHUD +++ /dev/null @@ -1,98 +0,0 @@ - - - - - - - - - - - - - - - - Textures/Core/UnitHexagon.png - - - - - - - - - - - - - - - - - - 0 - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - 360 - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - - - - - - - - - - - 0 - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - 360 - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - - - diff --git a/resources/Schema/Entities/AmmoPickup.xml b/resources/Schema/Entities/AmmoPickup.xml index bebde467..a8415489 100644 --- a/resources/Schema/Entities/AmmoPickup.xml +++ b/resources/Schema/Entities/AmmoPickup.xml @@ -3,19 +3,25 @@ - - Models/Props/PickUps/AmmoPickUp.mesh - + 8 + + Models/Props/PickUps/AmmoPickUp.mesh + + + + + 1.5 + 3 + - + + - - diff --git a/resources/Schema/Entities/AmmoPickupWithModel.xml b/resources/Schema/Entities/AmmoPickupWithModel.xml new file mode 100644 index 00000000..6c7ed50a --- /dev/null +++ b/resources/Schema/Entities/AmmoPickupWithModel.xml @@ -0,0 +1,38 @@ + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + 8 + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/AmmoShareEffectView.xml b/resources/Schema/Entities/AmmoShareEffectView.xml new file mode 100644 index 00000000..28997ab0 --- /dev/null +++ b/resources/Schema/Entities/AmmoShareEffectView.xml @@ -0,0 +1,34 @@ + + + + + + 1.2000000476837158 + + + + + 1.2000000476837158 + -1 + 1.2000000476837158 + + true + true + + + 16.040000915527344 + Models/Effects/JumpEffectHexagon.mesh + + true + + + + + + + + + + + + diff --git a/resources/Schema/Entities/AnimationTests2.xml b/resources/Schema/Entities/AnimationTests2.xml index 413c7e67..b5b46c85 100644 --- a/resources/Schema/Entities/AnimationTests2.xml +++ b/resources/Schema/Entities/AnimationTests2.xml @@ -2,6 +2,10 @@ + + 0.30000001192092896 + 3 + @@ -9,138 +13,542 @@ - + + - + + 0 + Models/Widgets/Lights/DirectionalLightWidget.mesh - + - - - - Run - 0.5 - 0.60188997954429357 - -1 - 1 - 0.5 - 0.96957233017255007 - 0.093923612201312068 - 1 - - - AimRifle - - - - Models/Characters/Assault/AssaultAnimations.mesh - - - - - - - - - - R_Arm_Weapon_Joint - - - - Models/Weapons/Red/AssaultWeaponRed.mesh - - - - - - - - - - - + - 10 + 8 + 0.60000002384185791 - + + + + + + + AimBlend + FinalBlend + + + 5 + Models/Characters/Assault/AssaultBlue.mesh + + + - + - - - 10 - + + R_Arm_Weapon_Joint + + + Models/Weapons/Blue/AssaultWeaponBlue.mesh + - + + + + + + + AimPrimary + AimSecondary + 0 + + + + + + + + AimRifleA + + false + true + + + + + + + + + AimSecWepA + + false + true + + + + + + + + + + + ReloadSwitchBlend + MovementBlend + + + + + + + + StandCrouchBlend + JumpDashBlend + 0 + + + + + + + + StandMovement + CrouchMovement + 0 + + + + + + + + MovementBlend + Idle + 0 + + + + + + + + RunWalkBlend + StrafeLRBlend + 0 + + + + + + + + Walk + Run + 1 + + + + + + + + WalkF + + + + + + + + + RunF + + 1 + + + + + + + + + + + Left + Right + 0 + + + + + + + + StrafeLeftF + + + + + + + + + StrafeRightF + + + + + + + + + + + + + IdleF + + 1 + + + + + + + + + + + MovementBlend + Idle + + + + + + + + Walk + StrafeLRBlend + 0 + + + + + + + + Left + Right + 0 + + + + + + + + CrouchStrafeLeftF + + + + + + + + + CrouchStrafeRightF + + + + + + + + + + + CrouchWalkF + + + + + + + + + + + CrouchF + + 1 + + + + + + + + + + + + + Jump + DashBlend + 1 + + + + + + + + JumpF + + + + + + + + + + DashFBBlend + DashLRBlend + 0 + + + + + + + + DashForward + DashBackward + 1 + + + + + + + + DashForwardF + false + + + + + + + + + DashBackwardF + + false + + + + + + + + + + + DashLeft + DashRight + 0 + + + + + + + + DashLeftF + + false + + + + + + + + + DashRightF + false + + + + + + + + + + + + + + + + + ReloadSwitch + WeaponActionBlend + 1 + + + + + + + + ReloadSwitchU + + 1 + + + + + + + + + IdleBlend + ShootBlend + 1 + + + + + + + + IdlePrimary + IdleSecondary + + + + + + + + IdleAssaultRifleU + + + + + + + + + IdleSecWepU + + + + + + + + + + + ShootPrimary + ShootSecondary + 0 + + + + + + + + ShootFastRifleU + + 1 + + + + + + + + + ShootSecWepFastU + + + + + + + + + + + + + - + Models/Core/UnitPlane.mesh - + - + - - ShootFastRifle - 0.056234247235838808 - 1 - 1 - Idl - 0.5 - 1.8308673495784191 - StrafeRigh - 0.5 - 0.32167823998061529 - 1 - - - Models/Characters/Assault/AssaultAnimations.mesh - - + + + 8 + 0.60000002384185791 + + + + - - - - - R_Arm_Weapon_Joint - - - Models/Weapons/Red/AssaultWeaponRed.mesh - - - - - - - - + + + + + + 8 + 0.80000001192092896 + + + + + + diff --git a/resources/Schema/Entities/AssaultWeaponWorld.xml b/resources/Schema/Entities/AssaultWeaponWorld.xml deleted file mode 100755 index 6fcb97b3..00000000 --- a/resources/Schema/Entities/AssaultWeaponWorld.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - R_Arm_Weapon_Joint - - - Models/Weapons/Blue/AssaultWeaponBlue.mesh - - - - - - - - - - - - Schema/Entities/RayBlue.xml - - - - - - - - - - - Schema/Entities/ReloadEffectWorld.xml - - - - - - - - diff --git a/resources/Schema/Entities/BlendTreeAim.xml b/resources/Schema/Entities/BlendTreeAim.xml new file mode 100644 index 00000000..a340c8d5 --- /dev/null +++ b/resources/Schema/Entities/BlendTreeAim.xml @@ -0,0 +1,41 @@ + + + + + + AimPrimary + AimSecondary + 0 + true + + + + + + + + + AimSecWepA + + false + true + + + + + + + + + AimRifleA + + false + true + + + + + + + + diff --git a/resources/Schema/Entities/BlendTreeAssault.xml b/resources/Schema/Entities/BlendTreeAssault.xml new file mode 100644 index 00000000..1cd121eb --- /dev/null +++ b/resources/Schema/Entities/BlendTreeAssault.xml @@ -0,0 +1,445 @@ + + + + + + ReloadSwitchBlend + MovementBlend + + + + + + + + + StandCrouchBlend + JumpDashBlend + 2.5146881298480398e-63 + true + + + + + + + + StandMovement + CrouchMovement + 0 + true + + + + + + + + MovementBlend + Idle + 1 + + + + + + + + Walk + StrafeLRBlend + 0 + + + + + + + + Left + Right + 0.033793529385008014 + + + + + + + + CrouchStrafeLeftF + + 1 + true + + + + + + + + + CrouchStrafeRightF + + 1 + true + + + + + + + + + + + CrouchWalkF + + 1 + true + + + + + + + + + + + CrouchF + + 1 + + + + + + + + + + + MovementBlend + Idle + 1 + + + + + + + + RunWalkBlend + StrafeLRBlend + 2.4565650245976452e-16 + + + + + + + + Walk + Run + 1.2938206818383024e-24 + + + + + + + + WalkF + + 1 + true + + + + + + + + + RunF + + 1 + true + + + + + + + + + + + Left + Right + 0.033793529385008014 + + + + + + + + StrafeLeftF + + 1 + true + + + + + + + + + StrafeRightF + + 1 + true + + + + + + + + + + + + + IdleF + + 1 + true + + + + + + + + + + + + + Jump + DashBlend + 1 + true + + + + + + + + JumpF + + 1 + false + + + + + + + + + DashFBBlend + DashLRBlend + 0.014621149736541383 + + + + + + + + DashForward + DashBackward + 0.014363533804961248 + + + + + + + + DashForwardF + + 1 + false + + + + + + + + + DashBackwardF + + 1 + false + + + + + + + + + + + DashLeft + DashRight + 4.3244885367500671e-16 + + + + + + + + DashLeftF + + 1 + false + + + + + + + + + DashRightF + + 1 + false + + + + + + + + + + + + + + + + + ReloadSwitch + WeaponActionBlend + 1 + true + + + + + + + + ReloadSwitchU + + 1 + + + + + + + + + IdleBlend + ShootBlend + 0 + + + + + + + + IdlePrimary + IdleSecondary + 0 + + + + + + + + IdleAssaultRifleU + + 1 + true + + + + + + + + + IdleSecWepU + + 1 + true + + + + + + + + + + + ShootPrimary + ShootSecondary + 0 + + + + + + + + ShootFastRifleU + + 1 + + + + + + + + + ShootSecWepFastU + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/BlendTreeAssaultWeapon.xml b/resources/Schema/Entities/BlendTreeAssaultWeapon.xml new file mode 100644 index 00000000..2bdaa0bb --- /dev/null +++ b/resources/Schema/Entities/BlendTreeAssaultWeapon.xml @@ -0,0 +1,220 @@ + + + + + + MovementBlend + FinalBlend + + + Models/Characters/Assault/FirstPersonAssaultBlue.mesh + + + + + + + + + BlendTreeAssaultWeapon + BlendTreeSecondaryWeapon + 0 + true + + + + + + + + Fire + Reload + 0 + true + + + + + + + + ReloadSwitchF + 0.5 + false + + + + + + + + + ShootRifleF + 1 + false + + + + + + + + + + + + + + + + + + + Idle + Run + 0 + true + + + + + + + + RunF + 1 + true + true + + + + + + + + + IdleF + 1 + true + true + + + + + + + + + + + R_Arm_Weapon_Joint + + + Models/Weapons/Blue/AssaultWeaponBlue.mesh + + + + + + + + + + + Schema/Entities/RayBlue.xml + + + + + + + + + + + + Schema/Entities/WeaponAssaultReloadEffectView.xml + + + + + + + + + + + R_Ammo_Joint + + true + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + + + + + + + + 32 + Fonts/DroidSans.ttf,64 + + + + PlayerAssault + AssaultWeapon + MagazineAmmo + + + + + + + + + + + 320 + Fonts/DroidSans.ttf,64 + + + + PlayerAssault + AssaultWeapon + Ammo + + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/BlendTreeDefenderWeapon.xml b/resources/Schema/Entities/BlendTreeDefenderWeapon.xml new file mode 100644 index 00000000..3f22d57f --- /dev/null +++ b/resources/Schema/Entities/BlendTreeDefenderWeapon.xml @@ -0,0 +1,159 @@ + + + + + + MovementBlend + FinalBlend + + + Models/Characters/Defender/FirstPersonDefenderBlue.mesh + + + + + + + + + BlendTreeDefenderWeapon + BlendTreeSecondaryWeapon + 0 + true + + + + + + + + ActionBlend + Shield + 0 + true + + + + + + + + ActivateDeactiveShieldF + + 1 + false + + + + + + + + + Idle + ActionBlend2 + 0 + true + + + + + + + + IdleF + + + + + + + + + Fire + Reload + 0 + + + + + + + + ShootShotgunF + + 1 + false + + + + + + + + + ShotgunReloadTwoF + + 1 + false + + + + + + + + + + + + + + + + + + + + + + + Idle + Run + 0 + true + + + + + + + + RunF + + 1 + true + true + + + + + + + + + IdleF + + 1 + true + true + + + + + + + + + + diff --git a/resources/Schema/Entities/BlendTreeSidearmWeapon.xml b/resources/Schema/Entities/BlendTreeSidearmWeapon.xml new file mode 100644 index 00000000..627829e5 --- /dev/null +++ b/resources/Schema/Entities/BlendTreeSidearmWeapon.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/resources/Schema/Entities/BlendTreeTest.xml b/resources/Schema/Entities/BlendTreeTest.xml new file mode 100644 index 00000000..79e2e223 --- /dev/null +++ b/resources/Schema/Entities/BlendTreeTest.xml @@ -0,0 +1,598 @@ + + + + + + 0.30000001192092896 + 3 + + + + + + + + + + + + + + + + + 0 + + + Models/Widgets/Lights/DirectionalLightWidget.mesh + + + + + + + + + + + + + 8 + 0.60000002384185791 + + + + + + + + + + + AimBlend + FinalBlend + + + 5 + Models/Characters/Assault/AssaultBlue.mesh + + + + + + + + R_Arm_Weapon_Joint + + + Models/Weapons/Blue/AssaultWeaponBlue.mesh + + + + + + + + + + + + + AimPrimary + AimSecondary + 0 + true + + + + + + + + AimSecWepA + + false + true + + + + + + + + + AimRifleA + + false + true + + + + + + + + + + + ReloadSwitchBlend + MovementBlend + + + + + + + + StandCrouchBlend + JumpDashBlend + 2.5146881298480398e-63 + true + + + + + + + + StandMovement + CrouchMovement + 0.012867419418159054 + true + + + + + + + + MovementBlend + Idle + 1 + + + + + + + + RunWalkBlend + StrafeLRBlend + 2.4565650245976452e-16 + + + + + + + + Walk + Run + 1.2938206818383024e-24 + + + + + + + + WalkF + + 1 + true + + + + + + + + + RunF + + 1 + true + + + + + + + + + + + Left + Right + 0.033793529385008014 + + + + + + + + StrafeLeftF + + 1 + true + + + + + + + + + StrafeRightF + + 1 + true + + + + + + + + + + + + + IdleF + + 1 + true + + + + + + + + + + + MovementBlend + Idle + 0 + + + + + + + + Walk + StrafeLRBlend + 2.4565650245976452e-16 + + + + + + + + Left + Right + 0.033793529385008014 + + + + + + + + CrouchStrafeLeftF + + 1 + true + + + + + + + + + CrouchStrafeRightF + + 1 + true + + + + + + + + + + + CrouchWalkF + + 1 + true + + + + + + + + + + + CrouchF + + 1 + + + + + + + + + + + + + Jump + DashBlend + 1 + true + + + + + + + + JumpF + + 1 + false + + + + + + + + + DashFBBlend + DashLRBlend + 0.014621149736541383 + + + + + + + + DashForward + DashBackward + 0.014363533804961248 + + + + + + + + DashForwardF + + 1 + false + + + + + + + + + DashBackwardF + + 1 + false + + + + + + + + + + + DashLeft + DashRight + 4.3244885367500671e-16 + + + + + + + + DashLeftF + + 1 + false + + + + + + + + + DashRightF + + 1 + false + + + + + + + + + + + + + + + + + ReloadSwitch + WeaponActionBlend + 1 + true + + + + + + + + ReloadSwitchU + + 1 + + + + + + + + + IdleBlend + ShootBlend + 0 + + + + + + + + IdlePrimary + IdleSecondary + 0 + + + + + + + + IdleAssaultRifleU + + 1 + true + + + + + + + + + IdleSecWepU + + 1 + true + + + + + + + + + + + ShootPrimary + ShootSecondary + 0 + + + + + + + + ShootFastRifleU + + 1 + + + + + + + + + ShootSecWepFastU + + + + + + + + + + + + + + + + + + + Models/Core/UnitPlane.mesh + + + + + + + + + + + + 8 + 0.60000002384185791 + + + + + + + + + + + 8 + 0.80000001192092896 + + + + + + + + + + + + diff --git a/resources/Schema/Entities/BoneMarker b/resources/Schema/Entities/BoneMarker deleted file mode 100644 index eda56d56..00000000 --- a/resources/Schema/Entities/BoneMarker +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - R_Leg_Top - - - - Models/Core/UnitCube.mesh - - - - - - - - - - - - diff --git a/resources/Schema/Entities/BoostAssault.xml b/resources/Schema/Entities/BoostAssault.xml new file mode 100644 index 00000000..9c8e54fd --- /dev/null +++ b/resources/Schema/Entities/BoostAssault.xml @@ -0,0 +1,14 @@ + + + + + + + 10 + + + + + + + diff --git a/resources/Schema/Entities/BoostAssaultTest.xml b/resources/Schema/Entities/BoostAssaultTest.xml new file mode 100644 index 00000000..89dcd0d7 --- /dev/null +++ b/resources/Schema/Entities/BoostAssaultTest.xml @@ -0,0 +1,5311 @@ + + + + + + + + + + + + + + + + + + Models/Props/Ground.mesh + + + + + + + + + Models/Props/Highground1.mesh + + + + + + + + + + Models/Props/Highground2.mesh + + + + + + + + + + Models/Props/Highground1.mesh + + + + + + + + + + + + Models/Props/Highground2.mesh + + + + + + + + + + + + Models/Props/Highground3.mesh + + + + + + + + + + Models/Props/Highground4.mesh + + + + + + + + + + Models/Props/Highground5.mesh + + + + + + + + + + + Models/Props/Highground6.mesh + + + + + + + + + + Models/Props/Walls/SciFiWallTop.mesh + + + + + + + + + Models/Props/Walls/SciFiWallBig.mesh + + + + + + + + + + Models/Props/Walls/SciFiWallMedium.mesh + + + + + + + + + + Models/Props/Walls/SciFiWallSmall1.mesh + + + + + + + + + + Models/Props/Walls/SciFiWallSmall2.mesh + + + + + + + + + + Models/Props/Walls/SciFiWallBig.mesh + + + + + + + + + + + + Models/Props/Walls/SciFiWallMedium.mesh + + + + + + + + + + + + Models/Props/Walls/SciFiWallSmall3.mesh + + + + + + + + + + Models/Props/Walls/SciFiWallSmall4.mesh + + + + + + + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar1Blue.mesh + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar1Red.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar3Blue.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar1Blue.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar1Red.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar3Red.mesh + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.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/SmallWall2.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall4.mesh + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + Models/Props/Walls/SmallWall2.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall2.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall2.mesh + + + + + + + + + + + + + Models/Props/Walls/MediumWall2.mesh + + + + + + + + + + + + Models/Props/Walls/MediumWall2.mesh + + + + + + + + + + + + + + Models/Props/Walls/MediumWall1.mesh + + + + + + + + + + + + Models/Props/Walls/MediumWall1.mesh + + + + + + + + + + + + + + Models/Props/Walls/MediumWall1.mesh + + + + + + + + + + + + Models/Props/Walls/MediumWall1.mesh + + + + + + + + + + + + Models/Props/Walls/MediumWall1.mesh + + + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall4.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall4.mesh + + + + + + + + + + + + Models/Props/Walls/SmallWall2.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall2.mesh + + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + + + Models/Props/Walls/SmallWall2.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall2.mesh + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + + + Models/Props/Walls/MediumWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + Models/Props/Walls/SmallWall2.mesh + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.mesh + + + + + + + + + + + + + + Models/Props/Flora/SpecialRoot.mesh + + + + + + + + + + + + + + Models/Props/Walls/MediumWall1.mesh + + + + + + + + + + + + + Models/Props/Walls/MediumWall1.mesh + + + + + + + + + + + + + Models/Props/Walls/MediumWall1.mesh + + + + + + + + + + + + Models/Props/Walls/MediumWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/MediumWall1.mesh + + + + + + + + + + + + Models/Props/Walls/MediumWall1.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall2.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall2.mesh + + + + + + + + + + + + Models/Props/Walls/SmallWall2.mesh + + + + + + + + + + + + Models/Props/Walls/MediumWall3.mesh + + + + + + + + + + + + Models/Props/Walls/MediumWall2.mesh + + + + + + + + + + + Models/Props/Walls/MediumWall2.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + Models/Props/Walls/SmallWall4.mesh + + + + + + + + + + + + + + + + Models/Props/Walls/MediumWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/MediumWall2.mesh + + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.mesh + + + + + + + + + + + + + + Models/Props/Walls/MediumWall1.mesh + + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.mesh + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.mesh + + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.mesh + + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.mesh + + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.mesh + + + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.mesh + + + + + + + + + + + + + + + + + + + + + Models/Props/Bridges/WoodenBridge.mesh + + + + + + + + + + + + + + Models/Props/Bridges/WoodenBridge.mesh + + + + + + + + + + + + + + Models/Props/Bridges/WoodenBridge.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/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/Bridges/SciFiBridge1Blue.mesh + + + + + + + + + + + + + Models/Props/Pillars/SciFiBridgePillar1.mesh + + + + + + + + + + + + + + Models/Props/Bridges/SciFiBridge1Red.mesh + + + + + + + + + + + + + Models/Props/Bridges/SciFiBridge1Red.mesh + + + + + + + + + + + + + Models/Props/Bridges/WoodenBridge.mesh + + + + + + + + + + + + + + + + + + + + + Models/Props/Pillars/SciFiBridgePillar1.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiBridgePillar1.mesh + + + + + + + + + + + + + + Models/Props/Walls/MediumWall2.mesh + + + + + + + + + + + Models/Props/Walls/MediumWall2.mesh + + + + + + + + + + + + + + + Models/Props/Walls/MediumWall3.mesh + + + + + + + + + + + Models/Props/Walls/MediumWall3.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiBridgePillar1.mesh + + + + + + + + + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + + Models/Props/Walls/MediumWall1.mesh + + + + + + + + + + + + Models/Props/Walls/MediumWall1.mesh + + + + + + + + + + + + Models/Props/Walls/MediumWall1.mesh + + + + + + + + + + + + + + Models/Props/Walls/MediumWall1.mesh + + + + + + + + + + + Models/Props/Walls/MediumWall1.mesh + + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + Models/Core/UnitPlane.mesh + + true + + + + + + + + + + + + + Models/Core/UnitPlane.mesh + + true + + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + + + Models/Props/Pillars/SciFiBridgePillar1.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiBridgePillar1.mesh + + + + + + + + + + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + + + + + Models/Props/Flora/TreeLog.mesh + + + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + + + + Models/Props/Flora/SpecialRoot.mesh + + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + + + + Models/Props/Flora/SpecialRoot.mesh + + + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + + + + Models/Props/Flora/SpecialRoot.mesh + + + + + + + + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + Models/Props/Stones/MediumStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone1.mesh + + + + + + + + + + + + + + + Models/Props/Stones/MediumStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + Models/Props/Walls/MediumWall1.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/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/MediumStone1.mesh + + + + + + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.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/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/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/MediumStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.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/SciFiHolder1.mesh + + + + + + + + + + + + + Models/Props/SciFiHolder1.mesh + + + + + + + + + + + + + Models/Props/SciFiHolder1.mesh + + + + + + + + + + + + + Models/Props/SciFiHolder1.mesh + + + + + + + + + + + + + Models/Props/SciFiHolder1.mesh + + + + + + + + + + + + + Models/Props/SciFiHolder1.mesh + + + + + + + + + + + + + Models/Props/SciFiHolder1.mesh + + + + + + + + + + + + + Models/Props/SciFiHolder1.mesh + + + + + + + + + + + + + + + + + + + + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointBlue.mesh + + + + + + + + + + + + + 4 + + + Models/Core/UnitCylinder.mesh + + true + + + + + + + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointNeutral.mesh + + + + + + + + + + 3 + + + Models/Core/UnitCylinder.mesh + + true + + + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointNeutral.mesh + + + + + + + + + + 2 + + + Models/Core/UnitCylinder.mesh + + true + + + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointNeutral.mesh + + + + + + + + + + 1.5498908015879351 + 1 + + + Models/Core/UnitCylinder.mesh + + true + + + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointRed.mesh + + + + + + + + + + + + + + + Models/Core/UnitCylinder.mesh + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + + + + + + + + 10 + + + + + + + + + + 10 + + + + + + + + + + + + + 10 + + + + + + + + + + + 10 + + + + + + + + + + + 10 + + + + + + + + + + + 1 + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + Models/Props/PickUps/HealthPickUp.mesh + + + 0.10000000149011612 + + + + + + + + + + + + + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + 0.10000000149011612 + + + + + + + + + + + + + + + + Models/Props/PickUps/HealthPickUp.mesh + + + 0.10000000149011612 + + + + + + + + + + + + + + + + Models/Props/PickUps/HealthPickUp.mesh + + + 0.10000000149011612 + + + + + + + + + + + + + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + 0.10000000149011612 + + + + + + + + + + + + + + + + Models/Props/PickUps/HealthPickUp.mesh + + + 0.10000000149011612 + + + + + + + + + + + + + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + 0.10000000149011612 + + + + + + + + + + + + + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + 0.10000000149011612 + + + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/BoostDefender.xml b/resources/Schema/Entities/BoostDefender.xml new file mode 100644 index 00000000..f22b404e --- /dev/null +++ b/resources/Schema/Entities/BoostDefender.xml @@ -0,0 +1,14 @@ + + + + + + + 10 + + + + + + + diff --git a/resources/Schema/Entities/BoostSniper.xml b/resources/Schema/Entities/BoostSniper.xml new file mode 100644 index 00000000..a82a7a5d --- /dev/null +++ b/resources/Schema/Entities/BoostSniper.xml @@ -0,0 +1,14 @@ + + + + + + + 10 + + + + + + + diff --git a/resources/Schema/Entities/CP_Rocky2.xml b/resources/Schema/Entities/CP_Rocky2.xml new file mode 100644 index 00000000..b8ba85ec --- /dev/null +++ b/resources/Schema/Entities/CP_Rocky2.xml @@ -0,0 +1,18401 @@ + + + + + + 6.1665781578731185 + + + + + + + + + + + + + + + 2 + Models/Props/GroundTest.mesh + + + + + + + + Models/Props/Walls/SciFiWallTop.mesh + + false + + + + + + + + + 2.4600000381469727 + Models/Props/Walls/SciFiWallMedium.mesh + + false + + + + + + + + + + 2.4600000381469727 + Models/Props/Walls/SciFiWallSmall1.mesh + + + + + + + + + + + 2.4600000381469727 + Models/Props/Walls/SciFiWallSmall2.mesh + + + + + + + + + + + 2.4600000381469727 + Models/Props/Walls/SciFiWallBig.mesh + + false + + + + + + + + + + + + 2.4600000381469727 + Models/Props/Walls/SciFiWallBig.mesh + + false + + + + + + + + + + 2.4500000476837158 + Models/Props/Walls/SciFiWallMedium.mesh + + false + + + + + + + + + + + + 2.4600000381469727 + Models/Props/Walls/SciFiWallSmall3.mesh + + false + + + + + + + + + + 2.4600000381469727 + Models/Props/Walls/SciFiWallSmall4.mesh + + + + + + + + + + + + + Models/Highgrounds/Highground1.mesh + + + + + + + + + + Models/Highgrounds/Highground2.mesh + + + + + + + + + + Models/Highgrounds/Highground3.mesh + + + + + + + + + + Models/Highgrounds/Highground24.mesh + + + + + + + + + + + Models/Highgrounds/Hg13.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg25.mesh + + + + + + + + + + + + Models/Highgrounds/Hg26.mesh + + + + + + + + + + + + Models/Highgrounds/Hg9.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg4.mesh + + + + + + + + + + + + + + Models/Highgrounds/Hg10.mesh + + + + + + + + + + + + + + Models/Highgrounds/Hg19.mesh + + + + + + + + + + + + + + Models/Highgrounds/Hg19.mesh + + + + + + + + + + + + + + + Models/Highgrounds/Highground12.mesh + + + + + + + + + + + + Models/Highgrounds/Hg16.mesh + + + + + + + + + + + + Models/Highgrounds/Hg15.mesh + + + + + + + + + + + + Models/Highgrounds/Hg14.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg13.mesh + + + + + + + + + + + + Models/Highgrounds/Hg11.mesh + + + + + + + + + + + + Models/Highgrounds/Hg20.mesh + + + + + + + + + + + + Models/Highgrounds/Hg18.mesh + + + + + + + + + + + + Models/Highgrounds/Hg19.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg17.mesh + + + + + + + + + + + + + + + Models/Highgrounds/Hg8.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg7.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg3.mesh + + + + + + + + + + + + + + + Models/Highgrounds/Highground3.mesh + + + + + + + + + + + + Models/Highgrounds/Highground1.mesh + + + + + + + + + + + Models/Highgrounds/Highground2.mesh + + + + + + + + + + + + + + Models/Highgrounds/Hg1.mesh + + + + + + + + + + + Models/Highgrounds/Hg2.mesh + + + + + + + + + + + + + + Models/Highgrounds/Highground5.mesh + + + + + + + + + + + + Models/Highgrounds/Hg7.mesh + + + + + + + + + + + + Models/Highgrounds/Hg17.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg19.mesh + + + + + + + + + + + + Models/Highgrounds/Hg18.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg20.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg6.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg8.mesh + + + + + + + + + + + + Models/Highgrounds/Hg10.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg4.mesh + + + + + + + + + + + + Models/Highgrounds/Hg16.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg9.mesh + + + + + + + + + + + + Models/Highgrounds/Hg3.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg19.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + Models/Highgrounds/Hg10.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + + + + Models/Highgrounds/Highground22.mesh + + + + + + + + + + + + Models/Highgrounds/Hg8.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg19.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg21.mesh + + + + + + + + + + + + Models/Highgrounds/Hg11.mesh + + + + + + + + + + + + Models/Highgrounds/Hg3.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg17.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg8.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Red.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 + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + + + Models/Highgrounds/Hg28.mesh + + + + + + + + + + + Models/Highgrounds/Hg10.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg27.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg15.mesh + + + + + + + + + + + + + + Models/Highgrounds/Hg13.mesh + + + + + + + + + + + + + + + Models/Highgrounds/Hg27.mesh + + + + + + + + + + + + Models/Highgrounds/Hg23.mesh + + + + + + + + + + + + + + + Models/Highgrounds/Hg27.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg23.mesh + + + + + + + + + + + + + + + Models/Highgrounds/Hg28.mesh + + + + + + + + + + + + Models/Highgrounds/Hg10.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg27.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg15.mesh + + + + + + + + + + + + + + Models/Highgrounds/Hg13.mesh + + + + + + + + + + + + + + + Models/Highgrounds/Hg1.mesh + + + + + + + + + + + + Models/Highgrounds/Hg2.mesh + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.5 + Models/Props/Bridges/Bridge1_SciFi_Blue.mesh + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh + + + + + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh + + + + + + + + + + + + + + + + + + + + 1.5 + Models/Props/Bridges/Bridge1_SciFi_Blue.mesh + + + + + + + + + + + + 1.5 + Models/Props/Bridges/Bridge1_SciFi_Blue.mesh + + + + + + + + + + + + 1.5 + Models/Props/Bridges/SciFi_Bridge_Support_Top_Blue.mesh + + + + + + + + + + + + Models/Props/Bridges/SciFi_Bridge_Support_Bot_Blue.mesh + + + + + + + + + + + 12 + + + + + + + + + + + + + 1.5 + Models/Props/Bridges/SciFi_Bridge_Support_Middle_Blue.mesh + + + + + + + + + + + + + + + + + + 1.1499999761581421 + Models/Props/Bridges/SciFi_Bridge_Support_Top_Blue.mesh + + + + + + + + + + + + Models/Props/Bridges/SciFi_Bridge_Support_Bot_Blue.mesh + + + + + + + + + + + 12 + + + + + + + + + + + + + 1.5 + Models/Props/Bridges/SciFi_Bridge_Support_Middle_Blue.mesh + + + + + + + + + + + + + + + + + + 1.5 + Models/Props/Bridges/Bridge1_SciFi_Blue.mesh + + + + + + + + + + + + + + 1.1499999761581421 + Models/Props/Bridges/SciFi_Bridge_Support_Top_Blue.mesh + + + + + + + + + + + + + Models/Props/Bridges/SciFi_Bridge_Support_Bot_Blue.mesh + + + + + + + + + + + 12 + + + + + + + + + + + + + 1.5 + Models/Props/Bridges/SciFi_Bridge_Support_Middle_Blue.mesh + + + + + + + + + + + + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.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 + + + + + + + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + + 1.7999999523162842 + Models/Props/Pillars/SciFiPillar1Blue.mesh + + + + + + + + + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Medium_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + 1.7999999523162842 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + 2 + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + + + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Medium_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + + 1.6000000238418579 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Medium_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Medium_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Medium_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Walls/Medium_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Medium_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + + + Models/Core/UnitPlane.mesh + + true + + + + + + + + + + + + + + + + + + + Models/Props/Bridge_Holder_Blue.mesh + + + + + + + + + + + + + Models/Props/SciFiHolder1.mesh + + + + + + + + + + + + + Models/Props/Bridge_Holder_Blue.mesh + + + + + + + + + + + + + Models/Props/Bridge_Holder_Blue.mesh + + + + + + + + + + + + + + + + + + + + 2.5 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 2 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 1.7999999523162842 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + 2 + + + + + + + + + + + + 2 + 1 + + + + + + + + + + + + 3 + + + + + + + + + + + + + + 2.2999999523162842 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 2 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 3 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 15 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 2 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + 2 + + + + + + + + + + + + + + 2 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 2.2000000476837158 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 2.2999999523162842 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + 2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + 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/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/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + 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/BigStone.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/MediumStone2.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/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/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.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/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/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/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/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/mediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + + + + + + 0.44999998807907104 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + 1.5 + 1 + + + + + + + + + + + + + + + + + + 0.34999999403953552 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + 1.5 + 1 + + + + + + + + + + + + + + + + + + 0.44999998807907104 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + 1.5 + 1 + + + + + + + + + + + + + + + + + + 0.30000001192092896 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + + + 1.5 + 1 + + + + + + + + + + + + + + + + + + 0.44999998807907104 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + 1.5 + 1 + + + + + + + + + + + + + + + + + + 0.40000000596046448 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + + + 1.5 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar3Red.mesh + + + + + + + + + + + + + + 2 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + 2 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar3Red.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + 1.2999999523162842 + Models/Props/Pillars/SciFiPillar1Red.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + 2 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar1Red.mesh + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + 2 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + + + + + + + + 2.4000000953674316 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar1Blue.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh + + + + + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + true + false + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + true + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + true + + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + 3 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + 2 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 3 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + 2.4000000953674316 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 2.4000000953674316 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh + + + + + + + + + + + + + 2.2999999523162842 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 3 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh + + + + + + + + + + + + + Models/Props/Bridge_Holder_Blue.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh + + + + + + + + + + + + + + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.mesh + + + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.mesh + + + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.mesh + + + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.mesh + + + + + + + + + + + + + + + + + + + + + 1.5 + Models/Props/Bridges/Bridge1_SciFi_Red.mesh + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + + + + + + + + + + 1.5 + Models/Props/Bridges/Bridge1_SciFi_Red.mesh + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Bridges/Bridge1_SciFi_Red.mesh + + + + + + + + + + + + Models/Props/Bridges/SciFi_Bridge_Support_Top_Red.mesh + + + + + + + + + + + 12 + + + + + + + + + + + + + 1.5 + Models/Props/Bridges/SciFi_Bridge_Support_Middle_Red.mesh + + + + + + + + + + + + + + Models/Props/Bridges/SciFi_Bridge_Support_Bot_Red.mesh + + + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + + + Models/Props/Bridges/SciFi_Bridge_Support_Top_Red.mesh + + + + + + + + + + + + Models/Props/Bridges/SciFi_Bridge_Support_Bot_Red.mesh + + + + + + + + + + + 12 + + + + + + + + + + + + + 1.5 + Models/Props/Bridges/SciFi_Bridge_Support_Middle_Red.mesh + + + + + + + + + + + + + + + + + + Models/Props/Bridges/SciFi_Bridge_Support_Top_Red.mesh + + + + + + + + + + + + + Models/Props/Bridges/SciFi_Bridge_Support_Bot_Red.mesh + + + + + + + + + + + 12 + + + + + + + + + + + + + Models/Props/Bridges/SciFi_Bridge_Support_Middle_Red.mesh + + + + + + + + + + + + + + + + 1.5 + Models/Props/Bridges/Bridge1_SciFi_Red.mesh + + + + + + + + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar1Red.mesh + + + + + + + + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Core/UnitPlane.mesh + + true + + + + + + + + + + + + + + + + + + + 2.2000000476837158 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 2 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 1.7999999523162842 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 2 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 2.5 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 1.7999999523162842 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 2 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 2 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + 3 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 2 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + 2.4000000953674316 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 1.7999999523162842 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 2.2000000476837158 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 2.2000000476837158 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + + + + + + + + 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/Bridge_Holder_Red.mesh + + + + + + + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + Models/Props/Stones/SmallStone2.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/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/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/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/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/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/MediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.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/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/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.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/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.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/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/mediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + + + + + + + 0.30000001192092896 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + 1.5 + 1 + + + + + + + + + + + + + + + + + + 0.40000000596046448 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + + + 1.5 + 1 + + + + + + + + + + + + + + + + + + 0.44999998807907104 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + 1.5 + 1 + + + + + + + + + + + + + + + + + + 0.30000001192092896 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + 1.5 + 1 + + + + + + + + + + + + + + + + + + 0.40000000596046448 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + 1.5 + 1 + + + + + + + + + + + + + + + + + + 0.37999999523162842 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + 1.5 + 1 + + + + + + + + + + + + + + + + + + 0.44999998807907104 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + 1.5 + 1 + + + + + + + + + + + + + + + + + + 0.40000000596046448 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + + + 1.5 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Medium_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/Medium_Wall_SciFi_Red.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + 2 + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + + + 2 + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Medium_Wall_SciFi_Red.mesh + + + + + + + + + + + + + Models/Props/Walls/Small_Wall_SciFi_Red.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + + 2 + 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 + + + + + + + + + + + + + + Models/Props/Walls/Small_Wall_SciFi_Red.mesh + + + + + + + + + + + + + 2 + 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 + + + + + + + + + + + + + + 1.5 + Models/Props/Walls/BigWallBlue.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 + + + + + + + + + + + + + + 1.5 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh + + + + + + + + + + + + + + + + + + + + Models/Props/Flora/Root.mesh + + + + + + + + + + + + + + Models/Props/Flora/Root.mesh + + + + + + + + + + + + + + Models/Props/Flora/Root.mesh + + + + + + + + + + + + + + Models/Props/Flora/Root.mesh + + + + + + + + + + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + true + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + true + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + true + false + + + + + + + + + + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + false + true + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + false + true + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush1.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush1.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + Models/Props/Stones/SmallStone1.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/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/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Medium_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Red.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 + + + + + + + + + + + + + + + + + + + 0.44999998807907104 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + 1.5 + 1 + + + + + + + + + + + + + + + + + + 0.60000002384185791 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + + + 1.5 + 3 + + + + + + + + + + + + + + + + + + + + + + + + + + 2.4000000953674316 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 2 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar3Blue.mesh + + + + + + + + + + + + + + 1.7000000476837158 + Models/Props/Pillars/SciFiPillar3Blue.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar1Blue.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + 2.5 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + 1.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 + + + + + + + + + + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + false + true + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + false + true + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush1.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush1.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + + + + + + + + + + + Schema/Entities/PlayerAssaultBlue.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 + + + + + + + + + + + + + + + + + + 1 + + + + Models/Props/CapturePoint/CapturePointCylinder.mesh + + false + true + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointNeutral.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.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 + + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointRed.mesh + 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 + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + + 2 + + + + Models/Props/CapturePoint/CapturePointCylinder.mesh + + false + true + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointBlue.mesh + 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 + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + 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.5 + + + + 20 + + + 3 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer2.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 + + + + + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointRed.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 + + + + + + + + + + + + + + + + + + + + 15 + + + + + + + + + + + Models/Props/CapturePoint/CapturePointCylinder.mesh + + false + 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.30000001192092896 + + + + 30 + + + 3.5 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer1.mesh + + false + false + + + + + + + + + + + 0.5 + + + + 20 + + + 3 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer2.mesh + + false + 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 + + + + + + + + + + + + + + 6 + + + 0.10000000149011612 + + + + + + + + + + Models/Props/CapturePoint/DoubleSidedCylinder.mesh + + false + true + + + + + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointRed.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.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 + + + + + + + + + + + + + + + 0.30000001192092896 + + + + 30 + + + 3.5 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer1.mesh + + false + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + + 3 + + + + Models/Props/CapturePoint/CapturePointCylinder.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 + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointBlue.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 + + + + + + + + + + + + + + + + + + + + -15 + + + + 4 + + + + + + + + Models/Props/CapturePoint/CapturePointCylinder.mesh + + false + true + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointRed.mesh + 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 + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + 0.30000001192092896 + + + + 30 + + + 3.5 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer1.mesh + + false + false + + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointNeutral.mesh + 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 + + + + + + + + + + + + + + + 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/CapturePointBlue.mesh + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Schema/Entities/ScoreBoard_Red.xml + + + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + Name + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Kills + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + KD + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + ID + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Deaths + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + + + Models/Core/UnitCube.mesh + false + + + + + + + + + + + Models/Core/UnitCube.mesh + false + + + + + + + + + + + + Schema/Entities/ScoreBoard_Blue.xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + KD + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Kills + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Deaths + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Name + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + ID + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + false + + + + + + + + + + + + + + + + + + + + 0.049999997019767761 + + + + + + + + + + + + + + + + + + + + 0.20000000298023224 + 300 + + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + PickTeam + 1 + + + + + + + + + + + Spectator + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + PickTeam + 3 + + + + + + + + + + + Blue + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + false + + + SwapToClassPick + 1 + + + + + + + + + + + Class + Fonts/DroidSans.ttf,64 + false + + + + + + + + + + + + Change + Fonts/DroidSans.ttf,64 + false + + + + + + + + + + + + + + Pick Team + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + PickTeam + 2 + + + + + + + + + + + Red + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + 0.20000000298023224 + 300 + + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Icons/Classes/Defender-01.png + + + PickClass + 2 + + + + + + + + + + + Defender + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Icons/Classes/Assault-01.png + + + PickClass + 1 + + + + + + + + + + + Assault + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Pick Class + 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/Sniper-01.png + + + PickClass + 3 + + + + + + + + + + + Sniper + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + 0.20000000298023224 + 300 + + + + + + + + + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + + + 1 + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + + + 2 + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + + + + + + + + 1 + + + + 4 + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + + + 3 + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + + + + + + + + 1 + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + false + + + SwapToClassPick + 1 + + + + + + + + + + + Change + Fonts/DroidSans.ttf,64 + false + + + + + + + + + + + + Class + Fonts/DroidSans.ttf,64 + false + + + + + + + + + + + + + + 2 + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + SwapToTeamPick + 1 + + + + + + + + + + + Change + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + Team + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 4 + 0.5 + + + + + + + + + + + + 4 + 0.5 + + + + + + + + + + + + 4 + 0.5 + + + + + + + + + + + 2 + + + + + + + + + + + 2 + 0.5 + + + + + + + + + + + + 4 + 0.5 + + + + + + + + + + + 1.3999999761581421 + + + + + + + + + + + + 4 + 0.5 + + + + + + + + + + + + 4 + 0.5 + + + + + + + + + + + 2.5 + + + + + + + + + + + 2 + + + + + + + + + + + + 3 + 0.40000000596046448 + + + + + + + + + + + + 4 + 0.5 + + + + + + + + + + + + 4 + 0.30000001192092896 + + + + + + + + + + + + 4 + 0.5 + + + + + + + + + + + + 3 + 0.5 + + + + + + + + + + + + 4 + 0.34999999403953552 + + + + + + + + + + + + + + 10 + + + + + + + + + + + 8 + + + + + + + + + + + + 10 + + + + + + + + + + + + 0.72000002861022949 + + + + + + + + + + + + + + + + + 6 + 0.69999998807907104 + + + + + + + + + + + + 3 + 0.60000002384185791 + + + + + + + + + + + + 5 + 1 + + + + + + + + + + + + 5 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + 6 + 1 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + 3 + 0.5 + + + + + + + + + + + + + + + + + + + + + + + + 5 + 2 + 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 + 2 + 0.5 + + + + + + + + + + + + + + + + + + + + + 3 + 1 + 0.5 + + + + + + + + + + + + 2 + 1 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + 5 + 1 + 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 + 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 + + + + + + + + + + + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + + + + + 6 + 0.5 + + + + + + + + + + + + 15 + 1 + + + + + + + + + + + + + + + + + 10 + 1 + + + + + + + + + + + + 10 + 1 + + + + + + + + + + + + 10 + 1 + + + + + + + + + + + + + + 5 + 1 + + + + + + + + + + + + 4 + 1 + + + + + + + + + + + + + 10 + + + + + + + + + + + + 1.1000000238418579 + 1.2999999523162842 + + + + + + + + 3 + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + + + + + 15 + 1 + + + + + + + + + + + + 5 + 1 + + + + + + + + + + + + + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 6 + 2 + 0.5 + + + + + + + + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + + + + + + + + + + 6 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + + + + + + + + + + 10 + 1 + + + + + + + + + + + + 10 + 1 + + + + + + + + + + + + 10 + 1 + + + + + + + + + + + + + + 5 + 0.69999998807907104 + + + + + + + + + + + + 5 + 0.69999998807907104 + + + + + + + + + + + + 5 + 1 + + + + + + + + + + + + 5 + 1 + + + + + + + + + + + + + + + + + + + 0.55000001192092896 + 1.6000000238418579 + false + + + + + + + + + + + + + 0.55000001192092896 + 1.6000000238418579 + false + + + + + + + + + + + + + 0.55000001192092896 + 1.6000000238418579 + false + + + + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/CP_Valhalla.xml b/resources/Schema/Entities/CP_Valhalla.xml new file mode 100755 index 00000000..9368e6ff --- /dev/null +++ b/resources/Schema/Entities/CP_Valhalla.xml @@ -0,0 +1,20946 @@ + + + + + + 1.1834302279689197 + 4 + + + + + + + + + + + + + + + 2 + Models/Props/GroundTest.mesh + + + + + + + + Models/Props/Walls/SciFiWallTop.mesh + + false + + + + + + + + + 2.4600000381469727 + Models/Props/Walls/SciFiWallMedium.mesh + + false + + + + + + + + + + 2.4600000381469727 + Models/Props/Walls/SciFiWallSmall1.mesh + + false + + + + + + + + + + 2.4600000381469727 + Models/Props/Walls/SciFiWallSmall2.mesh + + false + + + + + + + + + + 2.4600000381469727 + Models/Props/Walls/SciFiWallBig.mesh + + false + + + + + + + + + + + + 2.4600000381469727 + Models/Props/Walls/SciFiWallBig.mesh + + false + + + + + + + + + + 2.4500000476837158 + Models/Props/Walls/SciFiWallMedium.mesh + + false + + + + + + + + + + + + 2.4600000381469727 + Models/Props/Walls/SciFiWallSmall3.mesh + + false + + + + + + + + + + 2.4600000381469727 + Models/Props/Walls/SciFiWallSmall4.mesh + + false + + + + + + + + + + + + Models/Highgrounds/Highground1.mesh + + + + + + + + + + Models/Highgrounds/Highground2.mesh + + + + + + + + + + Models/Highgrounds/Highground3.mesh + + + + + + + + + + Models/Highgrounds/Highground24.mesh + + + + + + + + + + + Models/Highgrounds/Hg13.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg25.mesh + + + + + + + + + + + + Models/Highgrounds/Hg26.mesh + + + + + + + + + + + + Models/Highgrounds/Hg9.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg4.mesh + + + + + + + + + + + + + + Models/Highgrounds/Hg10.mesh + + + + + + + + + + + + + + Models/Highgrounds/Hg19.mesh + + + + + + + + + + + + + + Models/Highgrounds/Hg19.mesh + + + + + + + + + + + + + + + Models/Highgrounds/Highground12.mesh + + + + + + + + + + + + Models/Highgrounds/Hg16.mesh + + + + + + + + + + + + Models/Highgrounds/Hg15.mesh + + + + + + + + + + + + Models/Highgrounds/Hg14.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg13.mesh + + + + + + + + + + + + Models/Highgrounds/Hg11.mesh + + + + + + + + + + + + Models/Highgrounds/Hg20.mesh + + + + + + + + + + + + Models/Highgrounds/Hg18.mesh + + + + + + + + + + + + Models/Highgrounds/Hg19.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg17.mesh + + + + + + + + + + + + + + + Models/Highgrounds/Hg8.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg7.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg3.mesh + + + + + + + + + + + + + + + Models/Highgrounds/Highground3.mesh + + + + + + + + + + + + Models/Highgrounds/Highground1.mesh + + + + + + + + + + + Models/Highgrounds/Highground2.mesh + + + + + + + + + + + + + + Models/Highgrounds/Hg1.mesh + + + + + + + + + + + Models/Highgrounds/Hg2.mesh + + + + + + + + + + + + + + Models/Highgrounds/Highground5.mesh + + + + + + + + + + + + Models/Highgrounds/Hg20.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg6.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg8.mesh + + + + + + + + + + + + Models/Highgrounds/Hg10.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg4.mesh + + + + + + + + + + + + Models/Highgrounds/Hg7.mesh + + + + + + + + + + + + Models/Highgrounds/Hg17.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg19.mesh + + + + + + + + + + + + Models/Highgrounds/Hg18.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg16.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg9.mesh + + + + + + + + + + + + Models/Highgrounds/Hg3.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg19.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + Models/Highgrounds/Hg10.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + + + + Models/Highgrounds/Highground22.mesh + + + + + + + + + + + + Models/Highgrounds/Hg8.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg19.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg21.mesh + + + + + + + + + + + + Models/Highgrounds/Hg11.mesh + + + + + + + + + + + + Models/Highgrounds/Hg3.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg17.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg8.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Red.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 + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + + + Models/Highgrounds/Hg28.mesh + + + + + + + + + + + Models/Highgrounds/Hg10.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg27.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg15.mesh + + + + + + + + + + + + + + Models/Highgrounds/Hg13.mesh + + + + + + + + + + + + + + + Models/Highgrounds/Hg27.mesh + + + + + + + + + + + + Models/Highgrounds/Hg23.mesh + + + + + + + + + + + + + + + Models/Highgrounds/Hg27.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg23.mesh + + + + + + + + + + + + + + + Models/Highgrounds/Hg28.mesh + + + + + + + + + + + + Models/Highgrounds/Hg10.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg27.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg15.mesh + + + + + + + + + + + + + + Models/Highgrounds/Hg13.mesh + + + + + + + + + + + + + + + Models/Highgrounds/Hg1.mesh + + + + + + + + + + + + Models/Highgrounds/Hg2.mesh + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.5 + Models/Props/Bridges/Bridge1_SciFi_Blue.mesh + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh + + + + + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh + + + + + + + + + + + + + + + + + + + + 1.5 + Models/Props/Bridges/Bridge1_SciFi_Blue.mesh + + + + + + + + + + + + 1.5 + Models/Props/Bridges/Bridge1_SciFi_Blue.mesh + + + + + + + + + + + + 1.5 + Models/Props/Bridges/SciFi_Bridge_Support_Top_Blue.mesh + + + + + + + + + + + + Models/Props/Bridges/SciFi_Bridge_Support_Bot_Blue.mesh + + + + + + + + + + + 12 + + + + + + + + + + + + + 1.5 + Models/Props/Bridges/SciFi_Bridge_Support_Middle_Blue.mesh + + + + + + + + + + + + + + + + + + 1.1499999761581421 + Models/Props/Bridges/SciFi_Bridge_Support_Top_Blue.mesh + + + + + + + + + + + + Models/Props/Bridges/SciFi_Bridge_Support_Bot_Blue.mesh + + + + + + + + + + + 12 + + + + + + + + + + + + + 1.5 + Models/Props/Bridges/SciFi_Bridge_Support_Middle_Blue.mesh + + + + + + + + + + + + + + + + + + 1.5 + Models/Props/Bridges/Bridge1_SciFi_Blue.mesh + + + + + + + + + + + + + + 1.1499999761581421 + Models/Props/Bridges/SciFi_Bridge_Support_Top_Blue.mesh + + + + + + + + + + + + + Models/Props/Bridges/SciFi_Bridge_Support_Bot_Blue.mesh + + + + + + + + + + + 12 + + + + + + + + + + + + + 1.5 + Models/Props/Bridges/SciFi_Bridge_Support_Middle_Blue.mesh + + + + + + + + + + + + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.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 + + + + + + + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + + 1.7999999523162842 + Models/Props/Pillars/SciFiPillar1Blue.mesh + + + + + + + + + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Medium_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + 1.7999999523162842 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + 2 + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + + + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Medium_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + + 1.6000000238418579 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Medium_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Medium_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Medium_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Walls/Medium_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Medium_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + + + Models/Core/UnitPlane.mesh + + false + true + + + + + + + + + + + + + + + + + + + Models/Props/Bridge_Holder_Blue.mesh + + + + + + + + + + + + + Models/Props/SciFiHolder1.mesh + + + + + + + + + + + + + Models/Props/Bridge_Holder_Blue.mesh + + + + + + + + + + + + + Models/Props/Bridge_Holder_Blue.mesh + + + + + + + + + + + + + + + + + + + + 2.5 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 2 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 1.7999999523162842 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + 2 + + + + + + + + + + + + 2 + 1 + + + + + + + + + + + + 3 + + + + + + + + + + + + + + 2.2999999523162842 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 2 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 3 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 15 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 2 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + 2 + + + + + + + + + + + + + + 2 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 2.2000000476837158 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 2.2999999523162842 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + 2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + + + + + + + + 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/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/SmallStone1.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/BigStone.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.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/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.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/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/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.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/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + 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/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/mediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + + + + + + 0.44999998807907104 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + 1.5 + 1 + + + + + + + + + + + + + + + + + + 0.34999999403953552 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + 1.5 + 1 + + + + + + + + + + + + + + + + + + 0.44999998807907104 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + 1.5 + 1 + + + + + + + + + + + + + + + + + + 0.30000001192092896 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + + + 1.5 + 1 + + + + + + + + + + + + + + + + + + 0.44999998807907104 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + 1.5 + 1 + + + + + + + + + + + + + + + + + + 0.40000000596046448 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + + + 1.5 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + 2 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar1Red.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + 2 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar3Red.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + 1.2999999523162842 + Models/Props/Pillars/SciFiPillar1Red.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar3Red.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + 2 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + + + + + + + + 2.4000000953674316 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar1Blue.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh + + + + + + + + + + + + + 2.4000000953674316 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 2 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 3 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + true + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + true + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + true + false + + + + + + + + + + + + + + + + 3 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh + + + + + + + + + + + + + 2.2999999523162842 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 2.4000000953674316 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh + + + + + + + + + + + + + 3 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh + + + + + + + + + + + + + Models/Props/Bridge_Holder_Blue.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh + + + + + + + + + + + + + + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.mesh + + + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.mesh + + + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.mesh + + + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.mesh + + + + + + + + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + Models/Core/UnitPlane.mesh + + false + false + true + + + + + + + + + + + + + + + + + + + 2.4000000953674316 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 2 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 2.2000000476837158 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 2 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + 1.7999999523162842 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 2 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 2.2000000476837158 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 2.2000000476837158 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 1.7999999523162842 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 3 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 2 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + 1.7999999523162842 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 2 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 2.5 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + + + + + + + 1.5 + Models/Props/Bridges/Bridge1_SciFi_Red.mesh + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + + + + + + + + + + 1.5 + Models/Props/Bridges/Bridge1_SciFi_Red.mesh + + + + + + + + + + + + + + Models/Props/Bridges/SciFi_Bridge_Support_Top_Red.mesh + + + + + + + + + + + + + Models/Props/Bridges/SciFi_Bridge_Support_Bot_Red.mesh + + + + + + + + + + + 12 + + + + + + + + + + + + + Models/Props/Bridges/SciFi_Bridge_Support_Middle_Red.mesh + + + + + + + + + + + + + + + + 1.5 + Models/Props/Bridges/Bridge1_SciFi_Red.mesh + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + + + Models/Props/Bridges/SciFi_Bridge_Support_Top_Red.mesh + + + + + + + + + + + 12 + + + + + + + + + + + + + 1.5 + Models/Props/Bridges/SciFi_Bridge_Support_Middle_Red.mesh + + + + + + + + + + + + + + Models/Props/Bridges/SciFi_Bridge_Support_Bot_Red.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Bridges/Bridge1_SciFi_Red.mesh + + + + + + + + + + + + Models/Props/Bridges/SciFi_Bridge_Support_Top_Red.mesh + + + + + + + + + + + + Models/Props/Bridges/SciFi_Bridge_Support_Bot_Red.mesh + + + + + + + + + + + 12 + + + + + + + + + + + + + 1.5 + Models/Props/Bridges/SciFi_Bridge_Support_Middle_Red.mesh + + + + + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar1Red.mesh + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + + + + + + + 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/Bridge_Holder_Red.mesh + + + + + + + + + + + + + + + + + + + + Models/Props/Stones/mediumStone2.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/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/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 + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.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 + + + + + + + + + + + + + Models/Props/Stones/mediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/mediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + 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/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.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/BigStone.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/MediumStone2.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/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/SmallStone1.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/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/mediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + + + + + + + 0.30000001192092896 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + 1.5 + 1 + + + + + + + + + + + + + + + + + + 0.40000000596046448 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + 1.5 + 1 + + + + + + + + + + + + + + + + + + 0.40000000596046448 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + + + 1.5 + 1 + + + + + + + + + + + + + + + + + + 0.37999999523162842 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + 1.5 + 1 + + + + + + + + + + + + + + + + + + 0.44999998807907104 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + 1.5 + 1 + + + + + + + + + + + + + + + + + + 0.44999998807907104 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + 1.5 + 1 + + + + + + + + + + + + + + + + + + 0.30000001192092896 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + 1.5 + 1 + + + + + + + + + + + + + + + + + + 0.40000000596046448 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + + + 1.5 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + + 2 + Models/Props/Walls/Medium_Wall_SciFi_Red.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh + + + + + + + + + + + + + + Models/Props/Walls/Small_Wall_SciFi_Red.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Walls/Small_Wall_SciFi_Red.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/Medium_Wall_SciFi_Red.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + 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/BigWallRed.mesh + + + + + + + + + + + 2 + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Medium_Wall_SciFi_Red.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Medium_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/Medium_Wall_SciFi_Red.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Medium_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 + + + + + + + + + + + + + + 1.5 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh + + + + + + + + + + + + + + + + + + + + Models/Props/Flora/Root.mesh + + + + + + + + + + + + + + Models/Props/Flora/Root.mesh + + + + + + + + + + + + + + Models/Props/Flora/Root.mesh + + + + + + + + + + + + + + Models/Props/Flora/Root.mesh + + + + + + + + + + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + true + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + true + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + true + false + + + + + + + + + + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + false + true + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush1.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + false + true + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush1.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + 2.5 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar1Blue.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar3Blue.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + 2.5 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + 1.7000000476837158 + Models/Props/Pillars/SciFiPillar3Blue.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + 2.5 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + + + + + + + + + + + + + 2.4000000953674316 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 2 + Models/Props/Stones/ShinyStoneCrystalRed.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/Flora/HangingBush2.mesh + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + true + + + + + + + + + + + + + + + + + + + + + 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/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.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/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + + + + + + + + 2 + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Medium_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh + + + + + + + + + + + + + + + + + + + + 0.44999998807907104 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + 1.5 + 1 + + + + + + + + + + + + + + + + + + 0.60000002384185791 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + + + 1.5 + 3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush1.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + false + true + + + + + + + + + + + + Models/Props/Flora/HangingBush1.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + false + true + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + + + + + + + + + + 1 + + + + Models/Props/CapturePoint/CapturePointCylinder.mesh + + false + true + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointRed.mesh + 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 + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointNeutral.mesh + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + 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.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 + + + + + + + + + + + + + + + + + + + + 15 + + + + + + + + + + + Models/Props/CapturePoint/CapturePointCylinder.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 + 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/CapturePointBlue.mesh + 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 + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + 0.5 + + + + 20 + + + 3 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer2.mesh + + false + false + true + + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointRed.mesh + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + 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/CapturePointCylinder.mesh + + false + true + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointNeutral.mesh + + + + + + + + + + + + + + + 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.5 + + + + 20 + + + 3 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer2.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 + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + 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/CapturePointBlue.mesh + 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 + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + + -15 + + + + 4 + + + + + + + + Models/Props/CapturePoint/CapturePointCylinder.mesh + + false + true + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointNeutral.mesh + 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 + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + + + Models/Props/CapturePoint/CenterCrystal.mesh + false + false + + + + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointRed.mesh + 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 + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + + + + + 0.5 + + + + 20 + + + 3 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer2.mesh + + false + false + + + + + + + + + + + + + + + + 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.5 + + + + 20 + + + 3 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer2.mesh + + false + + + + + + + + + + + 0.30000001192092896 + + + + 30 + + + 3.5 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer1.mesh + + false + + + + + + + + + + + + + + + + + 3 + + + + Models/Props/CapturePoint/CapturePointCylinder.mesh + + false + true + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointBlue.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 + + + + + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointNeutral.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.30000001192092896 + + + + 30 + + + 3.5 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer1.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.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.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 + + + + + + + + + + + + + + + + + + + + + + + + + + + Schema/Entities/PlayerAssaultRed.xml + Schema/Entities/PlayerDefenderRed.xml + + + + 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 + + + + + + + + + + + + + + + + + + Schema/Entities/PlayerAssaultBlue.xml + Schema/Entities/PlayerDefenderBlue.xml + + + + Schema/Entities/PlayerAssaultBlue.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/ScoreBoard_Main.xml + + + + + + + + + + + + + + + + + + + 0.80000019073486328 + Models/Props/ScoreBoard/Scoreboard.mesh + false + + + + + + + + + + + 0.70000028610229492 + Models/Props/ScoreBoard/Spectatorboard.mesh + false + + + + + + + + + + + + Schema/Entities/ScoreBoard_Red.xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Kills + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Deaths + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + KD + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Name + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + ID + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + false + + + + + + + + + + + + + + + + Schema/Entities/ScoreBoard_Blue.xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + KD + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Name + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Deaths + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Kills + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + ID + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 10 + + + + + + + + + + + + 10 + + + + + + + + + + + + 1.2299997806549072 + 1.5699996948242188 + + + + + + + + 3 + + + + + + + + + + + + + + 10 + + + + + + + + + + + + + + + + + 4 + 0.34999999403953552 + + + + + + + + + + + + 4 + 0.5 + + + + + + + + + + + + 4 + 0.5 + + + + + + + + + + + 2 + + + + + + + + + + + 1.3999999761581421 + + + + + + + + + + + 2 + + + + + + + + + + + + 4 + 0.5 + + + + + + + + + + + + 4 + 0.5 + + + + + + + + + + + 2 + 0.5 + + + + + + + + + + + + 4 + 0.30000001192092896 + + + + + + + + + + + + 3 + 0.40000000596046448 + + + + + + + + + + + + 4 + 0.5 + + + + + + + + + + + + 4 + 0.5 + + + + + + + + + + + + 4 + 0.5 + + + + + + + + + + + + 4 + 0.5 + + + + + + + + + + + + 3 + 0.5 + + + + + + + + + + + 2.5 + + + + + + + + + + + + + 10 + + + + + + + + + + + + + + + + + 5 + 1 + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + 6 + 1 + 0.5 + + + + + + + + + + + + + + + + + + + + + 6 + 1 + 0.5 + + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + + + + + + + + 6 + 1 + 0.5 + + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + + + + + + + + + 3 + 0.60000002384185791 + + + + + + + + + + + + 15 + 1 + + + + + + + + + + + + + + + + + 10 + 1 + + + + + + + + + + + + 10 + 1 + + + + + + + + + + + + 10 + 1 + + + + + + + + + + + + + + 6 + 0.5 + + + + + + + + + + + + 3 + 0.5 + + + + + + + + + + + + + + + + + + + + + + + + 3 + 1 + 0.5 + + + + + + + + + + + + 2 + 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 + + + + + + + + + + + + 3 + 1 + 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 + 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 + 2 + 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 + 2 + 0.5 + + + + + + + + + + + + + + + + 5 + 1 + + + + + + + + + + + + 6 + 0.69999998807907104 + + + + + + + + + + + + 5 + 1 + + + + + + + + + + + + 4 + 1 + + + + + + + + + + + + + + + + + + + 5 + 1 + + + + + + + + + + + + + + + + + 10 + 1 + + + + + + + + + + + + 10 + 1 + + + + + + + + + + + + 10 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 6 + 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 + + + + + + + + + + + + + + + + + + + + + 6 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + + + + + 5 + 0.69999998807907104 + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + 5 + 1 + + + + + + + + + + + + 15 + 1 + + + + + + + + + + + + + + + + + + + 0.55000001192092896 + 1.6000000238418579 + false + + + + + + + + + + + + + 0.55000001192092896 + 1.6000000238418579 + false + + + + + + + + + + + + + 0.55000001192092896 + 1.6000000238418579 + false + + + + + + + + + + + + + + + 5 + 0.69999998807907104 + + + + + + + + + + + + 5 + 1 + + + + + + + + + + + + + 8 + + + + + + + + + + + + 0.66000008583068848 + + + + + + + + + + + + + 0.014999999664723873 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + PickTeam + 1 + + + + + + + + Blend + + + + + 1.6000000238418579 + Models/Characters/Defender/DefenderBluePose.mesh + false + + + + + + + + + + + + DefenderPoseF + + true + + + + + + + + + R_Arm_Weapon_Joint + + + Models/Weapons/Blue/DefenderWeaponBlue.mesh + + + + + + + + + + + + Models/Core/UnitSphere.mesh + false + + + 0.30000001192092896 + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Core/White.png + + + + PickClass + 2 + + + + + + + + + + + + + + + + + + Defender + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + 150 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + \2 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Personal Shield + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Icons/Abilities/Square/SheildDots-01.png + + + + + + + + + + + + + + + + + + + + + + + + Team Shield Boost + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + \2 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + \7 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + \5 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + PickTeam + 1 + + + + + + + + + + Blend + + + + + 1.6000000238418579 + Models/Characters/Assault/AssaultBluePose.mesh + false + + + + + + + + + + + + Models/Core/UnitSphere.mesh + false + + + 0.30000001192092896 + + + + + + + + + + + + AssaultPoseF + + true + + + + + + + + + R_Arm_Weapon_Joint + + + Models/Weapons/Blue/AssaultWeaponBlue.mesh + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + + + + Assault + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + \1 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + 100 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Core/White.png + + + + PickClass + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + \4 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + \7 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + + + + Team Speed Boost + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + \1 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + + + + + + Dash + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Icons/Abilities/Square/Superman-01.png + + + + + + + + + + + + + + + + + + + + + + x2 Jump + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Icons/Shoe-01.png + + + + + + + + + + + + + + + + + + + + PickTeam + 1 + + + + + + + + + + Blend + + + + + 1.6000000238418579 + Models/Characters/Sniper/SniperBluePose.mesh + false + + + + + + + + + + + + Models/Core/UnitSphere.mesh + false + + + 0.30000001192092896 + + + + + + + + + + + + SniperPoseF + + true + + + + + + + + + R_Arm_Weapon_Joint + + + Models/Weapons/Blue/SecondaryWeaponBlue.mesh + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Team Accuracy Boost + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + \3 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + + + + + + Sprint + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Icons/Abilities/Square/Dash-01.png + + + + + + + + + + + + + + + + + + + + + + + + \7 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + \6 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Core/White.png + + + + PickClass + 3 + + + + + + + + + + + + + + + + + + \3 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + 100 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + Sniper + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Blue + Fonts/DroidSans.ttf,64 + false + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/BlueTeam.png + true + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Core/White.png + true + + + + PickTeam + 3 + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + true + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + true + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + true + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + true + + + + + + + + + + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Core/White.png + true + + + + PickTeam_ + 1 + + + + + + + + + + + Spectator + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + true + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + true + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + true + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + true + + + + + + + + + + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Core/White.png + true + + + + PickTeam + 2 + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + true + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + true + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + true + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + true + + + + + + + + + + + + + + + Blue + Fonts/DroidSans.ttf,64 + false + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/RedTeam.png + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + + + 2 + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + + + + + + + + 1 + + + + 4 + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + + + 3 + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + + + 1 + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + + + + + + + + 1 + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + + + 3 + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + + + + + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/White.png + true + + + + SwapToTeamPick + 1 + + + + + + + + + + + Change Team + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + Change Class + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/White.png + true + + + + SwapToClassPick + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + PickTeam + 1 + + + + + + + + + + Blend + + + + + 1.6000000238418579 + Models/Characters/Assault/AssaultRedPose.mesh + false + + + + + + + + + + + + AssaultPoseF + + true + + + + + + + + + Models/Core/UnitSphere.mesh + false + + + 0.30000001192092896 + + + + + + + + + + + + R_Arm_Weapon_Joint + + + Models/Weapons/Red/AssaultWeaponRed.mesh + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + + + \1 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + Assault + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + 100 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Core/White.png + + + + PickClass + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + \1 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + Team Speed Boost + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + + + + \4 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + \7 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Icons/Shoe-01.png + + + + + + + + + + + + x2 Jump + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + + + + Dash + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Icons/Abilities/Square/Superman-01.png + + + + + + + + + + + + + + + + + + + + + PickTeam + 1 + + + + + + + + + + + + + + + \2 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + Defender + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + 150 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Core/White.png + + + + PickClass + 2 + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + Blend + + + + + 1.6000000238418579 + Models/Characters/Defender/DefenderRedPose.mesh + false + + + + + + + + + + + + Models/Core/UnitSphere.mesh + false + + + 0.30000001192092896 + + + + + + + + + + + + DefenderPoseF + + true + + + + + + + + + R_Arm_Weapon_Joint + + + Models/Weapons/Red/DefenderWeaponRed.mesh + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \7 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + \5 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Icons/Abilities/Square/SheildDots-01.png + + + + + + + + + + + + + Personal Shield + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + + + + + + Team Shield Boost + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + \2 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + PickTeam + 1 + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Core/White.png + + + + PickClass + 3 + + + + + + + + + + + Blend + + + + + 1.6000000238418579 + Models/Characters/Sniper/SniperRedPose.mesh + false + + + + + + + + + + + + SniperPoseF + + true + + + + + + + + + Models/Core/UnitSphere.mesh + false + + + 0.30000001192092896 + + + + + + + + + + + + R_Arm_Weapon_Joint + + + Models/Weapons/Red/SecondaryWeaponRed.mesh + + + + + + + + + + + + + + + + + + + + + Sniper + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + 100 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + \3 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \6 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + \7 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + + + + Team Accuracy Boost + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + \3 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Icons/Abilities/Square/Dash-01.png + + + + + + + + + + + + + Sprint + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/CP_Valhalla_Menu.xml b/resources/Schema/Entities/CP_Valhalla_Menu.xml new file mode 100755 index 00000000..83b4335c --- /dev/null +++ b/resources/Schema/Entities/CP_Valhalla_Menu.xml @@ -0,0 +1,17367 @@ + + + + + + 0.083480921511537076 + 4 + + + + + + + + + + + + + + + 2 + Models/Props/GroundTest.mesh + + + + + + + + Models/Props/Walls/SciFiWallTop.mesh + + false + + + + + + + + + 2.4600000381469727 + Models/Props/Walls/SciFiWallBig.mesh + + false + + + + + + + + + + 2.4600000381469727 + Models/Props/Walls/SciFiWallMedium.mesh + + false + + + + + + + + + + 2.4600000381469727 + Models/Props/Walls/SciFiWallSmall1.mesh + + false + + + + + + + + + + 2.4600000381469727 + Models/Props/Walls/SciFiWallSmall2.mesh + + false + + + + + + + + + + 2.4600000381469727 + Models/Props/Walls/SciFiWallBig.mesh + + false + + + + + + + + + + + + 2.4500000476837158 + Models/Props/Walls/SciFiWallMedium.mesh + + false + + + + + + + + + + + + 2.4600000381469727 + Models/Props/Walls/SciFiWallSmall3.mesh + + false + + + + + + + + + + 2.4600000381469727 + Models/Props/Walls/SciFiWallSmall4.mesh + + false + + + + + + + + + + + + Models/Highgrounds/Highground1.mesh + + + + + + + + + + Models/Highgrounds/Highground2.mesh + + + + + + + + + + Models/Highgrounds/Highground3.mesh + + + + + + + + + + Models/Highgrounds/Highground24.mesh + + + + + + + + + + + Models/Highgrounds/Hg13.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg25.mesh + + + + + + + + + + + + Models/Highgrounds/Hg26.mesh + + + + + + + + + + + + Models/Highgrounds/Hg9.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg4.mesh + + + + + + + + + + + + + + Models/Highgrounds/Hg10.mesh + + + + + + + + + + + + + + Models/Highgrounds/Hg19.mesh + + + + + + + + + + + + + + Models/Highgrounds/Hg19.mesh + + + + + + + + + + + + + + + Models/Highgrounds/Highground12.mesh + + + + + + + + + + + + Models/Highgrounds/Hg16.mesh + + + + + + + + + + + + Models/Highgrounds/Hg15.mesh + + + + + + + + + + + + Models/Highgrounds/Hg14.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg13.mesh + + + + + + + + + + + + Models/Highgrounds/Hg11.mesh + + + + + + + + + + + + Models/Highgrounds/Hg20.mesh + + + + + + + + + + + + Models/Highgrounds/Hg18.mesh + + + + + + + + + + + + Models/Highgrounds/Hg19.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg17.mesh + + + + + + + + + + + + + + + Models/Highgrounds/Hg8.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg7.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg3.mesh + + + + + + + + + + + + + + + Models/Highgrounds/Highground3.mesh + + + + + + + + + + + + Models/Highgrounds/Highground1.mesh + + + + + + + + + + + Models/Highgrounds/Highground2.mesh + + + + + + + + + + + + + + Models/Highgrounds/Hg1.mesh + + + + + + + + + + + Models/Highgrounds/Hg2.mesh + + + + + + + + + + + + + + Models/Highgrounds/Highground5.mesh + + + + + + + + + + + + Models/Highgrounds/Hg18.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg20.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg6.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg8.mesh + + + + + + + + + + + + Models/Highgrounds/Hg10.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg4.mesh + + + + + + + + + + + + Models/Highgrounds/Hg7.mesh + + + + + + + + + + + + Models/Highgrounds/Hg17.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg19.mesh + + + + + + + + + + + + Models/Highgrounds/Hg16.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg9.mesh + + + + + + + + + + + + Models/Highgrounds/Hg3.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg19.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + Models/Highgrounds/Hg10.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + + + + Models/Highgrounds/Highground22.mesh + + + + + + + + + + + + Models/Highgrounds/Hg8.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg19.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg21.mesh + + + + + + + + + + + + Models/Highgrounds/Hg11.mesh + + + + + + + + + + + + Models/Highgrounds/Hg3.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg17.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg8.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Red.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 + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + + + Models/Highgrounds/Hg28.mesh + + + + + + + + + + + Models/Highgrounds/Hg10.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg27.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg15.mesh + + + + + + + + + + + + + + Models/Highgrounds/Hg13.mesh + + + + + + + + + + + + + + + Models/Highgrounds/Hg27.mesh + + + + + + + + + + + + Models/Highgrounds/Hg23.mesh + + + + + + + + + + + + + + + Models/Highgrounds/Hg27.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg23.mesh + + + + + + + + + + + + + + + Models/Highgrounds/Hg28.mesh + + + + + + + + + + + + Models/Highgrounds/Hg10.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg27.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg15.mesh + + + + + + + + + + + + + + Models/Highgrounds/Hg13.mesh + + + + + + + + + + + + + + + Models/Highgrounds/Hg1.mesh + + + + + + + + + + + + Models/Highgrounds/Hg2.mesh + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.5 + Models/Props/Bridges/Bridge1_SciFi_Blue.mesh + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh + + + + + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh + + + + + + + + + + + + + + + + + + + + 1.5 + Models/Props/Bridges/Bridge1_SciFi_Blue.mesh + + + + + + + + + + + + 1.5 + Models/Props/Bridges/Bridge1_SciFi_Blue.mesh + + + + + + + + + + + + 1.5 + Models/Props/Bridges/SciFi_Bridge_Support_Top_Blue.mesh + + + + + + + + + + + + Models/Props/Bridges/SciFi_Bridge_Support_Bot_Blue.mesh + + + + + + + + + + + 12 + + + + + + + + + + + + + 1.5 + Models/Props/Bridges/SciFi_Bridge_Support_Middle_Blue.mesh + + + + + + + + + + + + + + + + + + 1.1499999761581421 + Models/Props/Bridges/SciFi_Bridge_Support_Top_Blue.mesh + + + + + + + + + + + + Models/Props/Bridges/SciFi_Bridge_Support_Bot_Blue.mesh + + + + + + + + + + + 12 + + + + + + + + + + + + + 1.5 + Models/Props/Bridges/SciFi_Bridge_Support_Middle_Blue.mesh + + + + + + + + + + + + + + + + + + 1.5 + Models/Props/Bridges/Bridge1_SciFi_Blue.mesh + + + + + + + + + + + + + + 1.1499999761581421 + Models/Props/Bridges/SciFi_Bridge_Support_Top_Blue.mesh + + + + + + + + + + + + + Models/Props/Bridges/SciFi_Bridge_Support_Bot_Blue.mesh + + + + + + + + + + + 12 + + + + + + + + + + + + + 1.5 + Models/Props/Bridges/SciFi_Bridge_Support_Middle_Blue.mesh + + + + + + + + + + + + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.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 + + + + + + + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + + 1.7999999523162842 + Models/Props/Pillars/SciFiPillar1Blue.mesh + + + + + + + + + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Medium_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + 1.7999999523162842 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + 2 + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + + + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Medium_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + + 1.6000000238418579 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Medium_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Medium_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Medium_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Walls/Medium_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Medium_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + + + Models/Core/UnitPlane.mesh + + false + true + + + + + + + + + + + + + + + + + + + Models/Props/Bridge_Holder_Blue.mesh + + + + + + + + + + + + + Models/Props/SciFiHolder1.mesh + + + + + + + + + + + + + Models/Props/Bridge_Holder_Blue.mesh + + + + + + + + + + + + + Models/Props/Bridge_Holder_Blue.mesh + + + + + + + + + + + + + + + + + + + + 2.5 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 2 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 1.7999999523162842 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + 2 + + + + + + + + + + + + 2 + 1 + + + + + + + + + + + + 3 + + + + + + + + + + + + + + 2.2999999523162842 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 2 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 3 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 15 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 2 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + 2 + + + + + + + + + + + + + + 2 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 2.2000000476837158 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 2.2999999523162842 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + 2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.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/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/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/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/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.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/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.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/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/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.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/SmallStone1.mesh + + + + + + + + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + + + + + + 0.44999998807907104 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + 1.5 + 1 + + + + + + + + + + + + + + + + + + 0.44999998807907104 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + 1.5 + 1 + + + + + + + + + + + + + + + + + + 0.44999998807907104 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + 1.5 + 1 + + + + + + + + + + + + + + + + + + 0.34999999403953552 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + 1.5 + 1 + + + + + + + + + + + + + + + + + + 0.30000001192092896 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + + + 1.5 + 1 + + + + + + + + + + + + + + + + + + 0.40000000596046448 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + + + 1.5 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + 2 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + 1.2999999523162842 + Models/Props/Pillars/SciFiPillar1Red.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + 2 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar1Red.mesh + + + + + + + + + + + + + 2 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar3Red.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar3Red.mesh + + + + + + + + + + + + + + 2 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + + + + + + + + 2.4000000953674316 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar1Blue.mesh + + + + + + + + + + + + + + 3 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + 3 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + 3 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + 2.4000000953674316 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh + + + + + + + + + + + + + 2.4000000953674316 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh + + + + + + + + + + + + + 2 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + true + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + true + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + true + false + + + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + 2.2999999523162842 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh + + + + + + + + + + + + + Models/Props/Bridge_Holder_Blue.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh + + + + + + + + + + + + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar1Red.mesh + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Core/UnitPlane.mesh + + false + false + true + + + + + + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.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 + + + + + + + + + + + + + + 1.5 + Models/Props/Bridges/Bridge1_SciFi_Red.mesh + + + + + + + + + + + + 1.5 + Models/Props/Bridges/Bridge1_SciFi_Red.mesh + + + + + + + + + + + + Models/Props/Bridges/SciFi_Bridge_Support_Top_Red.mesh + + + + + + + + + + + + Models/Props/Bridges/SciFi_Bridge_Support_Bot_Red.mesh + + + + + + + + + + + 12 + + + + + + + + + + + + + 1.5 + Models/Props/Bridges/SciFi_Bridge_Support_Middle_Red.mesh + + + + + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + + + Models/Props/Bridges/SciFi_Bridge_Support_Top_Red.mesh + + + + + + + + + + + 12 + + + + + + + + + + + + + 1.5 + Models/Props/Bridges/SciFi_Bridge_Support_Middle_Red.mesh + + + + + + + + + + + + + + Models/Props/Bridges/SciFi_Bridge_Support_Bot_Red.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + + + + + 1.5 + Models/Props/Bridges/Bridge1_SciFi_Red.mesh + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + + + + + + + + + + 1.5 + Models/Props/Bridges/Bridge1_SciFi_Red.mesh + + + + + + + + + + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.mesh + + + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.mesh + + + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.mesh + + + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.mesh + + + + + + + + + + + + + + + + + + + + + 2.2000000476837158 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 2.4000000953674316 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 1.7999999523162842 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 1.7999999523162842 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 2.2000000476837158 + 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.2000000476837158 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 3 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 1.7999999523162842 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 2.5 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + + + + + + + + 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/Bridge_Holder_Red.mesh + + + + + + + + + + + + + + + + + + + + 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/mediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.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/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + 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/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/mediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.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/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/SmallStone2.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/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/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/mediumStone2.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/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/mediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + + + + + + 0.30000001192092896 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + 1.5 + 1 + + + + + + + + + + + + + + + + + + 0.40000000596046448 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + + + 1.5 + 1 + + + + + + + + + + + + + + + + + + 0.44999998807907104 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + 1.5 + 1 + + + + + + + + + + + + + + + + + + 0.30000001192092896 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + 1.5 + 1 + + + + + + + + + + + + + + + + + + 0.40000000596046448 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + 1.5 + 1 + + + + + + + + + + + + + + + + + + 0.37999999523162842 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + 1.5 + 1 + + + + + + + + + + + + + + + + + + 0.44999998807907104 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + 1.5 + 1 + + + + + + + + + + + + + + + + + + 0.40000000596046448 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + + + 1.5 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Medium_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/BigWallRed.mesh + + + + + + + + + + + 2 + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + + + 2 + Models/Props/Walls/Medium_Wall_SciFi_Red.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh + + + + + + + + + + + + + + Models/Props/Walls/Small_Wall_SciFi_Red.mesh + + + + + + + + + + + + + + 1.5 + 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/Medium_Wall_SciFi_Red.mesh + + + + + + + + + + + + + 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/Small_Wall_SciFi_Red.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Medium_Wall_SciFi_Red.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Medium_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/Medium_Wall_SciFi_Red.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh + + + + + + + + + + + + + + + + + + + + Models/Props/Flora/Root.mesh + + + + + + + + + + + + + + Models/Props/Flora/Root.mesh + + + + + + + + + + + + + + Models/Props/Flora/Root.mesh + + + + + + + + + + + + + + Models/Props/Flora/Root.mesh + + + + + + + + + + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + true + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + true + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + true + false + + + + + + + + + + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush1.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + false + true + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush1.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + false + true + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar3Blue.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + 2.5 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar1Blue.mesh + + + + + + + + + + + + + 1.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 + + + + + + + + + + + + + + 1.7000000476837158 + Models/Props/Pillars/SciFiPillar3Blue.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + 2.5 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + + + + + + + + + + + + + 2.4000000953674316 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 2 + Models/Props/Stones/ShinyStoneCrystalRed.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/Flora/HangingBush2.mesh + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + true + + + + + + + + + + + + + + + + + + + + + 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/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/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + Models/Props/Stones/SmallStone1.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/MediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + + + + + + + + 2 + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Medium_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh + + + + + + + + + + + + + + + + + + + + 0.44999998807907104 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + 1.5 + 1 + + + + + + + + + + + + + + + + + + 0.60000002384185791 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + + + 1.5 + 3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Models/Props/Flora/HangingBush1.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + false + true + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + false + true + + + + + + + + + + + + Models/Props/Flora/HangingBush1.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + + + + + + + + + + Schema/Entities/PlayerAssaultBlue.xml + Schema/Entities/PlayerDefenderBlue.xml + + + + Schema/Entities/PlayerAssaultBlue.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 + + + + + + + + + + + + + + + + + + 1 + + + + Models/Props/CapturePoint/CapturePointCylinder.mesh + + false + 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 + + + + + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointRed.mesh + 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 + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointNeutral.mesh + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + + 3 + + + + Models/Props/CapturePoint/CapturePointCylinder.mesh + + false + 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 + + + + + + + + + + + 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 + + + + + + + + + + + + + + + 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.30000001192092896 + + + + 30 + + + 3.5 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer1.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 + + + + + + + + + + + + + + + 0.5 + + + + 20 + + + 3 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer2.mesh + false + + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointRed.mesh + 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 + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + + + -15 + + + + 4 + + + + + + + + Models/Props/CapturePoint/CapturePointCylinder.mesh + + false + true + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointRed.mesh + 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 + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + Models/Props/CapturePoint/CenterCrystal.mesh + + false + false + + + + + + + + + + + 1 + + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointNeutral.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 + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + + + 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/CapturePointBlue.mesh + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + + 15 + + + + + + + + + + + Models/Props/CapturePoint/CapturePointCylinder.mesh + + false + true + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointNeutral.mesh + 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 + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointBlue.mesh + 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 + + + + + + + + + + + + + + + + + + + + + + + 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 + true + + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointRed.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.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 + + + + + + + + + + + + + + + 0.30000001192092896 + + + + 30 + + + 3.5 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer1.mesh + + false + + + + + + + + + + + + + + + + + 2 + + + + Models/Props/CapturePoint/CapturePointCylinder.mesh + + false + 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.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.5 + + + + 20 + + + 3 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer2.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 + + + + + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointBlue.mesh + 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 + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + Schema/Entities/PlayerAssaultRed.xml + Schema/Entities/PlayerDefenderRed.xml + + + + 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 + + + + + + + + + + + + + + + + + + + + + + + + 4 + 0.5 + + + + + + + + + + + 2 + + + + + + + + + + + + 3 + 0.5 + + + + + + + + + + + + 4 + 0.5 + + + + + + + + + + + + 4 + 0.34999999403953552 + + + + + + + + + + + 2 + 0.5 + + + + + + + + + + + + 4 + 0.5 + + + + + + + + + + + 2 + + + + + + + + + + + + 4 + 0.5 + + + + + + + + + + + 1.3999999761581421 + + + + + + + + + + + + 4 + 0.5 + + + + + + + + + + + + 4 + 0.5 + + + + + + + + + + + + 4 + 0.30000001192092896 + + + + + + + + + + + + 3 + 0.40000000596046448 + + + + + + + + + + + + 4 + 0.5 + + + + + + + + + + + + 4 + 0.5 + + + + + + + + + + + 2.5 + + + + + + + + + + + + + + 0.66000008583068848 + + + + + + + + + + + 10 + + + + + + + + + + + 8 + + + + + + + + + + + + 10 + + + + + + + + + + + + 1.2299997806549072 + 1.5699996948242188 + + + + + + + + 3 + + + + + + + + + + + + + + 10 + + + + + + + + + + + 10 + + + + + + + + + + + + + + + + + 6 + 0.5 + + + + + + + + + + + + 3 + 0.60000002384185791 + + + + + + + + + + + + + + + + + + + + + + + + 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 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + + + + + + + + + + 3 + 1 + 0.5 + + + + + + + + + + + + 2 + 1 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 1 + 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 + 2 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 2 + 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 + + + + + + + + + + + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + + + + + 5 + 1 + + + + + + + + + + + + 15 + 1 + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + + + + + + + + 6 + 1 + 0.5 + + + + + + + + + + + + + + + + + + + 6 + 1 + 0.5 + + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + 6 + 1 + 0.5 + + + + + + + + + + + + + + + + + + 5 + 1 + + + + + + + + + + + + + + + + + 10 + 1 + + + + + + + + + + + + 10 + 1 + + + + + + + + + + + + 10 + 1 + + + + + + + + + + + + + + 3 + 0.5 + + + + + + + + + + + + 6 + 0.69999998807907104 + + + + + + + + + + + + 5 + 1 + + + + + + + + + + + + 4 + 1 + + + + + + + + + + + + + + + + + + + 5 + 1 + + + + + + + + + + + + 15 + 1 + + + + + + + + + + + + + + + + + 10 + 1 + + + + + + + + + + + + 10 + 1 + + + + + + + + + + + + 10 + 1 + + + + + + + + + + + + + + 5 + 1 + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + + + 6 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + + + + + + + + + + 6 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + + + + + 5 + 0.69999998807907104 + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + + + + + 0.55000001192092896 + 1.6000000238418579 + false + + + + + + + + + + + + + 0.55000001192092896 + 1.6000000238418579 + false + + + + + + + + + + + + + 0.55000001192092896 + 1.6000000238418579 + false + + + + + + + + + + + + + + + 5 + 0.69999998807907104 + + + + + + + + + + + + 5 + 1 + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/CapturePoint.xml b/resources/Schema/Entities/CapturePoint.xml index 9f33c4de..35c89e3e 100644 --- a/resources/Schema/Entities/CapturePoint.xml +++ b/resources/Schema/Entities/CapturePoint.xml @@ -4,14 +4,39 @@ - - Models/Core/UnitSphere.mesh - - + - + + + + + models/core/unitcube.mesh + + + + + + + + + models/core/unitcube.mesh + + + + + + + + + models/core/unitcube.mesh + + + + + + 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/CapturePointHUDGroup.xml b/resources/Schema/Entities/CapturePointHUDGroup.xml index d35e1bde..0987cc56 100644 --- a/resources/Schema/Entities/CapturePointHUDGroup.xml +++ b/resources/Schema/Entities/CapturePointHUDGroup.xml @@ -13,38 +13,8 @@ Textures/Core/UnitHexagon.png - - - - - - - - - - - 2 - - - - - - Textures/Core/UnitHexagon_Rotated.png - - - - - - - - - - - - - - - Textures/Core/UnitHexagon.png + + false @@ -54,20 +24,21 @@ + + + 3 - - 0.80222018197612788 - - Textures/Core/UnitHexagon_Rotated.png + + false - + @@ -78,6 +49,8 @@ Textures/Core/UnitHexagon.png + + false @@ -87,19 +60,21 @@ - - 4 - + + 4 + Textures/Core/UnitHexagon_Rotated.png + + false - + @@ -110,6 +85,44 @@ Textures/Core/UnitHexagon.png + + false + + + + + + + + + + + + + + 2 + + + Textures/Core/UnitHexagon_Rotated.png + + false + + + + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + false @@ -119,19 +132,21 @@ - - 1 - + + 1 + Textures/Core/UnitHexagon_Rotated.png + + false - + @@ -142,7 +157,9 @@ Textures/Core/UnitHexagon.png - + + false + @@ -151,17 +168,19 @@ - + Textures/Core/UnitHexagon_Rotated.png + + false - + diff --git a/resources/Schema/Entities/RayBlue b/resources/Schema/Entities/DDS.xml similarity index 52% rename from resources/Schema/Entities/RayBlue rename to resources/Schema/Entities/DDS.xml index d34e185e..e7f8f210 100644 --- a/resources/Schema/Entities/RayBlue +++ b/resources/Schema/Entities/DDS.xml @@ -2,13 +2,15 @@ - - Models/Core/UnitCylinder.mesh - - + + + + + Textures/Core/UnitRaptor.png + + - - + diff --git a/resources/Schema/Entities/DeadGirl.xlm b/resources/Schema/Entities/DeadGirl.xlm deleted file mode 100644 index 90a0411d..00000000 --- a/resources/Schema/Entities/DeadGirl.xlm +++ /dev/null @@ -1,255 +0,0 @@ - - - - - - - - - - 600 - - - - - - - - - 5 - - - - - - - - - - - - - - - - - - - - - - - - Fonts/DroidSans.ttf,100 - - - - - - - - - - - - - - Models/Widgets/Camera.mesh - false - - - - - - - - - - - - - - - - - - - 1 - - - - - Models/Core/UnitHexagon.mesh - - - - - - - - - - - - - - Textures/Weapons/Crosshair/SmallThickHoleDot.png - false - - - - - - - - - - - - - - Idle - 0.28963486380924053 - 1 - - - Models/Characters/Assault/FirstPerson.mesh - true - - - - - - - - R_Arm_Weapon_Joint - - - Models/Weapons/Blue/AssaultWeaponBlue.mesh - true - - - - - - - - - - - Schema/Entities/RayBlue.xml - - - - - - - - - - - - - Schema/Entities/WeaponReloadEffect.xml - - - - - - - - - - - - - - Models/Widgets/Camera.mesh - false - - - - - - - - - - - - Idle - 0.42156525436696768 - 1 - - - AimRifle - - - - - Models/Characters/Assault/AssaultAnimations.mesh - - - - - - - - - R_Arm_Weapon_Joint - - - Models/Weapons/Blue/AssaultWeaponBlue.mesh - false - - - - - - - - - - - Schema/Entities/RayBlue.xml - - - - - - - - - - - - - - - Models/Core/UnitCube.mesh - - false - - - - - - - - - - - - Models/Core/UnitCube.mesh - - false - - - - - - - - - - diff --git a/resources/Schema/Entities/DefenderShield.xml b/resources/Schema/Entities/DefenderShield.xml index da760e72..d2cca1da 100755 --- a/resources/Schema/Entities/DefenderShield.xml +++ b/resources/Schema/Entities/DefenderShield.xml @@ -1,39 +1,96 @@ - + - - - - Models/Core/UnitPlane.mesh - - - - - - - - - - + + + Deploy + Idle + 0 + - Models/Core/UnitHexagon.mesh - + Models/Characters/Defender/DefenderShieldBack.mesh + + false true + false + false + false + false - - - - - + - + + + + + ActivateShieldU + false + + + + + + + + + ShieldFrontU + true + + + + + + + + + + + Deploy + Idle + 0 + + + Models/Characters/Defender/DefenderShieldFront.mesh + + false + true + false + false + false + false + + + + + + + + + ActivateShieldU + false + + + + + + + + + ShieldFrontU + false + + + + + + diff --git a/resources/Schema/Entities/DefenderWeaponView.xml b/resources/Schema/Entities/DefenderWeaponView.xml deleted file mode 100755 index f6b6e89d..00000000 --- a/resources/Schema/Entities/DefenderWeaponView.xml +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - R_Arm_Weapon_Joint - - - - Models/Weapons/Blue/DefenderGunBlue.mesh - - - - - - - - - - - Schema/Entities/RayBlue.xml - - - - - - - - - - - Schema/Entities/ReloadEffectView.xml - - - - - - - - - - - - - - - - - - Textures/Core/UnitHexagon.png - - - - - - - - - - - - - - - - - - - 32 - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - 360 - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - - - - - diff --git a/resources/Schema/Entities/DefenderWeaponViewRed.xml b/resources/Schema/Entities/DefenderWeaponViewRed.xml deleted file mode 100755 index b5b1c322..00000000 --- a/resources/Schema/Entities/DefenderWeaponViewRed.xml +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - R_Arm_Weapon_Joint - - - - Models/Weapons/Red/DefenderGunRed.mesh - - - - - - - - - - - Schema/Entities/RayRed.xml - - - - - - - - - - - Schema/Entities/ReloadEffectView.xml - - - - - - - - - - - - - - - - - - Textures/Core/UnitHexagon.png - - - - - - - - - - - - - - - - - - - 32 - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - 360 - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - - - - - diff --git a/resources/Schema/Entities/DefenderWeaponWorld.xml b/resources/Schema/Entities/DefenderWeaponWorld.xml deleted file mode 100755 index 826301b4..00000000 --- a/resources/Schema/Entities/DefenderWeaponWorld.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - R_Arm_Weapon_Joint - - - - Models/Weapons/Blue/DefenderGunBlue.mesh - - - - - - - - - - - - Schema/Entities/RayBlue.xml - - - - - - - - - - - Schema/Entities/ReloadEffectWorld.xml - - - - - - - - diff --git a/resources/Schema/Entities/DefenderWeaponWorldRed.xml b/resources/Schema/Entities/DefenderWeaponWorldRed.xml deleted file mode 100755 index 7f697304..00000000 --- a/resources/Schema/Entities/DefenderWeaponWorldRed.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - R_Arm_Weapon_Joint - - - - Models/Weapons/Red/DefenderGunRed.mesh - - - - - - - - - - - - Schema/Entities/RayRed.xml - - - - - - - - - - - Schema/Entities/ReloadEffectWorld.xml - - - - - - - - diff --git a/resources/Schema/Entities/EndScreen.xml b/resources/Schema/Entities/EndScreen.xml new file mode 100644 index 00000000..7b8b055f --- /dev/null +++ b/resources/Schema/Entities/EndScreen.xml @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/FirstPersonArms b/resources/Schema/Entities/FirstPersonArms deleted file mode 100644 index bf749a4e..00000000 --- a/resources/Schema/Entities/FirstPersonArms +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - Run - 0.5 - 0.97312056690160276 - 1 - 1 - ReloadSwitch - 0.91310356788604263 - LeftRight - 0 - 0.040207288496060478 - 1 - - - DownUp - - - - Models/Characters/Assault/FirstPerson.mesh - - true - - - - - - - - - - - R_Arm_Weapon_Joint - - - Models/Weapons/Blue/AssaultWeapon.mesh - - - - - - - - - - - - - - - - - - diff --git a/resources/Schema/Entities/FloatingBridgePillar.xml b/resources/Schema/Entities/FloatingBridgePillar.xml new file mode 100644 index 00000000..0426cc1d --- /dev/null +++ b/resources/Schema/Entities/FloatingBridgePillar.xml @@ -0,0 +1,56 @@ + + + + + + + Models/Props/Bridges/SciFi_Bridge_Support_Top_Red.mesh + + + + + + + + + + + + + Models/Props/Bridges/SciFi_Bridge_Support_Bot_Red.mesh + + + + + + + + + + + 12 + + + + + + + + + + + + + Models/Props/Bridges/SciFi_Bridge_Support_Middle_Red.mesh + + + + + + + + + + + + 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/FriendlyAmmoHUD.xml b/resources/Schema/Entities/FriendlyAmmoHUD.xml new file mode 100644 index 00000000..57209829 --- /dev/null +++ b/resources/Schema/Entities/FriendlyAmmoHUD.xml @@ -0,0 +1,63 @@ + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + + + + + + + + + 88 + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + 88 + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/FriendlyBoostAttachement.xml b/resources/Schema/Entities/FriendlyBoostAttachement.xml new file mode 100644 index 00000000..38ac6643 --- /dev/null +++ b/resources/Schema/Entities/FriendlyBoostAttachement.xml @@ -0,0 +1,15 @@ + + + + + + Schema/Entities/FriendlyBoostBlueHUD.xml + + + + + + + + + diff --git a/resources/Schema/Entities/FriendlyBoostBlueHUD.xml b/resources/Schema/Entities/FriendlyBoostBlueHUD.xml new file mode 100644 index 00000000..1e0deebb --- /dev/null +++ b/resources/Schema/Entities/FriendlyBoostBlueHUD.xml @@ -0,0 +1,151 @@ + + + + + + 0.5 + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + + + + + + + + + + + + + + + + + \1 + Fonts/Hind-Edited.otf,64 + + false + + + + + + + + + + + \1 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + \2 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + \2 + Fonts/Hind-Edited.otf,64 + + false + + + + + + + + + + + + + + + + + + + + + \3 + Fonts/Hind-Edited.otf,64 + + false + + + + + + + + + + + \3 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/FriendlyBoostRedHUD.xml b/resources/Schema/Entities/FriendlyBoostRedHUD.xml new file mode 100644 index 00000000..bdf08281 --- /dev/null +++ b/resources/Schema/Entities/FriendlyBoostRedHUD.xml @@ -0,0 +1,151 @@ + + + + + + 0.5 + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + + + + + + + + + + + + + + + + + \1 + Fonts/Hind-Edited.otf,64 + + false + + + + + + + + + + + \1 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + \2 + Fonts/Hind-Edited.otf,64 + + false + + + + + + + + + + + \2 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + \3 + Fonts/Hind-Edited.otf,64 + + false + + + + + + + + + + + \3 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/GameMap.xml b/resources/Schema/Entities/GameMap.xml index c3a16361..473b9037 100644 --- a/resources/Schema/Entities/GameMap.xml +++ b/resources/Schema/Entities/GameMap.xml @@ -245,6 +245,13 @@ + + + + + + + diff --git a/resources/Schema/Entities/HealthHUDAssault.xml b/resources/Schema/Entities/HealthHUDAssault.xml new file mode 100644 index 00000000..efd91399 --- /dev/null +++ b/resources/Schema/Entities/HealthHUDAssault.xml @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + 1 + + + + 100/100 + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + 1 + + + + + Textures/HealthHUD3.png + + + + + + + + + + + + + + + + + + + + + + + + Textures/Icons/Boosts/Assault-01.png + + false + + + + + + + + + + + + + + + + + Textures/Icons/Boosts/Defender-01.png + + false + + + + + + + + + + + + + + + + + Textures/Icons/Boosts/Sniper-01.png + + false + + + + + + + + + + + + + + + + + + + + Textures/Icons/Abilities/Superman-01.png + + false + + + + + + + + + + + + + 0.0 + Fonts/DroidSans.ttf,64 + + false + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/HealthHUDDefender.xml b/resources/Schema/Entities/HealthHUDDefender.xml new file mode 100644 index 00000000..504fbd21 --- /dev/null +++ b/resources/Schema/Entities/HealthHUDDefender.xml @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + 1 + + + + 100/100 + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + 1 + + + + + Textures/HealthHUD3.png + + + + + + + + + + + + + + + + + + + + + + + + Textures/Icons/Boosts/Assault-01.png + + false + + + + + + + + + + + + + + + + + Textures/Icons/Boosts/Defender-01.png + + false + + + + + + + + + + + + + + + + + Textures/Icons/Boosts/Sniper-01.png + + false + + + + + + + + + + + + + + + + + + + + Textures/Icons/Abilities/SheildDots-01.png + + false + + + + + + + + + + + + + 0.0 + Fonts/DroidSans.ttf,64 + + false + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/HealthHUDSniper.xml b/resources/Schema/Entities/HealthHUDSniper.xml new file mode 100644 index 00000000..13b6dc4d --- /dev/null +++ b/resources/Schema/Entities/HealthHUDSniper.xml @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + 1 + + + + 100/100 + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + 1 + + + + + Textures/HealthHUD3.png + + + + + + + + + + + + + + + + + + + + + + + + Textures/Icons/Boosts/Assault-01.png + + false + + + + + + + + + + + + + + + + + Textures/Icons/Boosts/Defender-01.png + + false + + + + + + + + + + + + + + + + + Textures/Icons/Boosts/Sniper-01.png + + false + + + + + + + + + + + + + + + + + + + + Textures/Icons/Abilities/Dash-01.png + + false + + + + + + + + + + + + + 0.0 + Fonts/DroidSans.ttf,64 + + false + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/HealthPickup.xml b/resources/Schema/Entities/HealthPickup.xml index b4b83392..af9530aa 100644 --- a/resources/Schema/Entities/HealthPickup.xml +++ b/resources/Schema/Entities/HealthPickup.xml @@ -3,19 +3,25 @@ - - Models/Props/PickUps/HealthPickUp.mesh - + 8 + + Models/Props/PickUps/HealthPickUp.mesh + + + + + 1.5 + 3 + - + + - - diff --git a/resources/Schema/Entities/HealthPickupWithModel.xml b/resources/Schema/Entities/HealthPickupWithModel.xml new file mode 100644 index 00000000..8465e922 --- /dev/null +++ b/resources/Schema/Entities/HealthPickupWithModel.xml @@ -0,0 +1,38 @@ + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + + Models/Props/PickUps/HealthPickUp.mesh + + + 8 + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/HitTest.xml b/resources/Schema/Entities/HitTest.xml new file mode 100644 index 00000000..4649072b --- /dev/null +++ b/resources/Schema/Entities/HitTest.xml @@ -0,0 +1,27 @@ + + + + + + 10 + + + + 1 + true + true + + + Models/Core/UnitSphere.mesh + + false + true + + + + + + + + + diff --git a/resources/Schema/Entities/MainMenu.xml b/resources/Schema/Entities/MainMenu.xml new file mode 100644 index 00000000..e6cc6ef4 --- /dev/null +++ b/resources/Schema/Entities/MainMenu.xml @@ -0,0 +1,344 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Textures/Core/White.png + true + + false + + + + Play + 1 + + + + + + + + + + + Play + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + + Textures/HUD/ButtonCorner_16.png + + + + + + + + + + + + + Textures/HUD/ButtonCorner_16.png + + + + + + + + + + + + + + + + + + + + + + + + + + Textures/Core/White.png + true + + false + + + + + + + + + + + + Credits + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + + Textures/HUD/ButtonCorner_16.png + + + + + + + + + + + + + Textures/HUD/ButtonCorner_16.png + + + + + + + + + + + + + + + + + + + + + + + + + + Textures/Core/White.png + true + + false + + + + + + + + + + + + Option + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + + Textures/HUD/ButtonCorner_16.png + + + + + + + + + + + + + Textures/HUD/ButtonCorner_16.png + + + + + + + + + + + + + + + + + + + + + + + + + + Textures/Core/White.png + true + + false + + + + + + + + + + + + Quit + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + + Textures/HUD/ButtonCorner_16.png + + + + + + + + + + + + + Textures/HUD/ButtonCorner_16.png + + + + + + + + + + + + + + + + + + + + + + + + + + + Schema/Entities/ServerList.xml + + + + + + + + + + diff --git a/resources/Schema/Entities/ModelCollisionTest.xml b/resources/Schema/Entities/ModelCollisionTest.xml index c4a3f81b..2adcc989 100644 --- a/resources/Schema/Entities/ModelCollisionTest.xml +++ b/resources/Schema/Entities/ModelCollisionTest.xml @@ -2,64 +2,168 @@ - - - + - + - - + + + + + + + + Schema/Entities/PlayerAssaultFallbackRed.xml + - - - - - - - - - - - ../assets/Models/Core/Tri.obj - - - - - + + - ../assets/Models/Core/Tri.obj + Models/Characters/Assault/AssaultRed.mesh - + + + + + + + + + + Models/Characters/Assault/AssaultRed.mesh + + + + - + - - + + 0.5 + 4 + + - ../assets/Models/Core/UnitCube.obj + sModels/Widgets/Lights/DirectionalLightWidget.mesh - - + + + + + + + Models/Test/ObstacleCourse.mesh + + + + + + + + + + + + + + + Schema/Entities/Player.xml + + + + + + + + + + + Models/Characters/Assault/AssaultBlue.mesh + + + + + + + + + + + + + Models/Characters/Assault/AssaultBlue.mesh + + + + + + + + + + + + + + ActivateDeactive + + + + Models/Characters/Defender/FirstPersonDefenderBlue.mesh + + + + + + + + + + ActivateDeactiveShieldF + + 1 + true + + + + + + + + + R_Arm_Weapon_Joint + + + Models/Weapons/Blue/DefenderWeaponBlue.mesh + + + + + + + + + + diff --git a/resources/Schema/Entities/MovementTest.xml b/resources/Schema/Entities/MovementTest.xml index 41474568..df9d7b06 100644 --- a/resources/Schema/Entities/MovementTest.xml +++ b/resources/Schema/Entities/MovementTest.xml @@ -2,21 +2,31 @@ - + + 0.10012471663946698 + 0.5 + + + + - - - Schema/Entities/PlayerRed.xml - + + Schema/Entities/PlayerAssaultRed.xml + Schema/Entities/PlayerDefenderRed.xml + + + + Schema/Entities/PlayerDefenderBlue.xml + @@ -26,7 +36,7 @@ - Models/Characters/Assault/AssaultTPose.mesh + Models/Characters/Assault/AssaultRed.mesh @@ -39,7 +49,7 @@ - Models/Characters/Assault/AssaultTPose.mesh + Models/Characters/Assault/AssaultRed.mesh @@ -52,7 +62,10 @@ - + + 0.49999982118606567 + 2.5599997043609619 + sModels/Widgets/Lights/DirectionalLightWidget.mesh @@ -76,15 +89,19 @@ - - - Schema/Entities/Player.xml - + + Schema/Entities/PlayerAssaultBlue.xml + Schema/Entities/PlayerDefenderBlue.xml + + + + Schema/Entities/PlayerAssaultBlue.xml + @@ -94,7 +111,7 @@ - Models/Characters/Assault/AssaultTPose.mesh + Models/Characters/Assault/AssaultBlue.mesh @@ -107,17 +124,3316 @@ - Models/Characters/Assault/AssaultTPose.mesh + Models/Characters/Assault/AssaultBlue.mesh - + + + + + ActivateDeactive + + + + Models/Characters/Defender/FirstPersonDefenderBlue.mesh + + + + + + + + + + ActivateDeactiveShieldF + + true + + + + + + + + + R_Arm_Weapon_Joint + + + Models/Weapons/Blue/DefenderWeaponBlue.mesh + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Effects/Ray.png + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Effects/Ray.png + + + + + + + + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Effects/Ray.png + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Effects/Ray.png + + + + + + + + + + + + + + + + + + 0.014999999664723873 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + PickTeam + 1 + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Core/White.png + + + + PickClass + 1 + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + Blend + + + + + 1.6000000238418579 + Models/Characters/Assault/AssaultBluePose.mesh + false + + + + + + + + + + + + AssaultPoseF + + true + + + + + + + + + R_Arm_Weapon_Joint + + + Models/Weapons/Blue/AssaultWeaponBlue.mesh + + + + + + + + + + + + Models/Core/UnitSphere.mesh + false + + + 0.30000001192092896 + + + + + + + + + + + + + + + + + + + + + \1 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + Assault + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + 100 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Team Speed Boost + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + \1 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + \4 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + \7 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Dash + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Icons/Abilities/Square/Superman-01.png + + + + + + + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Icons/Shoe-01.png + + + + + + + + + + + + x2 Jump + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + + + PickTeam + 1 + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Core/White.png + + + + PickClass + 2 + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + Blend + + + + + 1.6000000238418579 + Models/Characters/Defender/DefenderBluePose.mesh + false + + + + + + + + + + + + DefenderPoseF + + true + + + + + + + + + R_Arm_Weapon_Joint + + + Models/Weapons/Blue/DefenderWeaponBlue.mesh + + + + + + + + + + + + Models/Core/UnitSphere.mesh + false + + + 0.30000001192092896 + + + + + + + + + + + + + + + + + + + + + \2 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + Defender + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + 150 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Team Shield Boost + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + \2 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + \5 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + \7 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Personal Shield + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Icons/Abilities/Square/SheildDots-01.png + + + + + + + + + + + + + + + + + + + + + PickTeam + 1 + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Core/White.png + + + + PickClass + 3 + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + Blend + + + + + 1.6000000238418579 + Models/Characters/Sniper/SniperBluePose.mesh + false + + + + + + + + + + + + SniperPoseF + + true + + + + + + + + + R_Arm_Weapon_Joint + + + Models/Weapons/Blue/SecondaryWeaponBlue.mesh + + + + + + + + + + + + Models/Core/UnitSphere.mesh + false + + + 0.30000001192092896 + + + + + + + + + + + + + + + + + + + + + \3 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + Sniper + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + 100 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Team Accuracy Boost + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + \3 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + \6 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + \7 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Sprint + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Icons/Abilities/Square/Dash-01.png + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Core/White.png + true + + + + PickTeam + 3 + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + true + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + true + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + true + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + true + + + + + + + + + + + + + + + Blue + Fonts/DroidSans.ttf,64 + false + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/BlueTeam.png + true + + + + + + + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Core/White.png + true + + + + PickTeam_ + 1 + + + + + + + + + + + Spectator + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + true + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + true + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + true + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + true + + + + + + + + + + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Core/White.png + true + + + + PickTeam + 2 + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + true + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + true + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + true + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + true + + + + + + + + + + + + + + + Blue + Fonts/DroidSans.ttf,64 + false + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/RedTeam.png + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + + + 3 + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + + + + + + + + 1 + + + + 4 + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + + + 2 + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + + + 1 + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + + + + + + + + 1 + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/White.png + true + + + + SwapToTeamPick + 1 + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + + + + + + + + + + + + + + Change Team + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/White.png + true + + + + SwapToClassPick + 1 + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + + + + + + + + + + + + + + Change Class + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + PickTeam + 1 + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Core/White.png + + + + PickClass + 1 + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + Blend + + + + + 1.6000000238418579 + Models/Characters/Assault/AssaultRedPose.mesh + false + + + + + + + + + + + + AssaultPoseF + + true + + + + + + + + + R_Arm_Weapon_Joint + + + Models/Weapons/Red/AssaultWeaponRed.mesh + + + + + + + + + + + + Models/Core/UnitSphere.mesh + false + + + 0.30000001192092896 + + + + + + + + + + + + + + + + + + + + + \1 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + Assault + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + 100 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Team Speed Boost + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + \1 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + \4 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + \7 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Dash + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Icons/Abilities/Square/Superman-01.png + + + + + + + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Icons/Shoe-01.png + + + + + + + + + + + + x2 Jump + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + + + PickTeam + 1 + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Core/White.png + + + + PickClass + 2 + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + Blend + + + + + 1.6000000238418579 + Models/Characters/Defender/DefenderRedPose.mesh + false + + + + + + + + + + + + DefenderPoseF + + true + + + + + + + + + R_Arm_Weapon_Joint + + + Models/Weapons/Red/DefenderWeaponRed.mesh + + + + + + + + + + + + Models/Core/UnitSphere.mesh + false + + + 0.30000001192092896 + + + + + + + + + + + + + + + + + + + + + \2 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + Defender + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + 150 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Team Shield Boost + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + \2 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + \5 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + \7 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Personal Shield + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Icons/Abilities/Square/SheildDots-01.png + + + + + + + + + + + + + + + + + + + + + PickTeam + 1 + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Core/White.png + + + + PickClass + 3 + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + Blend + + + + + 1.6000000238418579 + Models/Characters/Sniper/SniperRedPose.mesh + false + + + + + + + + + + + + SniperPoseF + + true + + + + + + + + + R_Arm_Weapon_Joint + + + Models/Weapons/Red/SecondaryWeaponRed.mesh + + + + + + + + + + + + Models/Core/UnitSphere.mesh + false + + + 0.30000001192092896 + + + + + + + + + + + + + + + + + + + + + \3 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + Sniper + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + 100 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Team Accuracy Boost + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + \3 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + \6 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + \7 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Sprint + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Icons/Abilities/Square/Dash-01.png + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/MuzzleFlashBlue.xml b/resources/Schema/Entities/MuzzleFlashBlue.xml new file mode 100644 index 00000000..840a2365 --- /dev/null +++ b/resources/Schema/Entities/MuzzleFlashBlue.xml @@ -0,0 +1,227 @@ + + + + + + 0.08 + + + + + + + + + + + + + + 0.08 + true + + + 2 + Models/Effects/MuzzleFlash/Blue/Cone1Outside.mesh + false + true + + + + + + + + + 0.08 + true + + + 2 + Models/Effects/MuzzleFlash/Blue/Cone1Inside.mesh + false + true + + + + + + + + + + + + + + + + + + 0.08 + true + + + 2 + Models/Effects/MuzzleFlash/Blue/Cone2Inside.mesh + false + true + + + + + + + + + 0.08 + true + + + 2 + Models/Effects/MuzzleFlash/Blue/Cone2Outside.mesh + false + true + + + + + + + + + + + + + + + + + + 0.08 + true + + + 2 + Models/Effects/MuzzleFlash/Blue/PlaneLeft.mesh + false + true + + + + + + + + + 0.08 + true + + + 2 + Models/Effects/MuzzleFlash/Blue/PlaneRight.mesh + false + true + + + + + + + + + 0.08 + true + + + 2 + Models/Effects/MuzzleFlash/Blue/PlaneUp.mesh + false + true + + + + + + + + + 0.08 + true + + + 2 + Models/Effects/MuzzleFlash/Blue/PlaneDown.mesh + false + true + + + + + + + + + + + + + + + + Models/Core/UnitSphere.mesh + false + false + + + + + + + + + + + + + + + Models/Core/UnitSphere.mesh + + false + false + + + + 0.40000000596046448 + + + + + + + + + + + + Models/Core/UnitSphere.mesh + false + false + + + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/MuzzleFlashFire.xml b/resources/Schema/Entities/MuzzleFlashFire.xml new file mode 100644 index 00000000..c1d47b2a --- /dev/null +++ b/resources/Schema/Entities/MuzzleFlashFire.xml @@ -0,0 +1,135 @@ + + + + + + 0.039999999105930328 + + + + + + + + + + + + + + 2 + Models/Effects/MuzzleFlash/Fire/Cone1Outside.mesh + false + true + + + + + + + + + 2 + Models/Effects/MuzzleFlash/Fire/Cone1Inside.mesh + false + true + + + + + + + + + + + + + + + + + + 2 + Models/Effects/MuzzleFlash/Fire/Cone2Inside.mesh + false + true + + + + + + + + + 2 + Models/Effects/MuzzleFlash/Fire/Cone2Outside.mesh + false + true + + + + + + + + + + + + + + + + + + 2 + Models/Effects/MuzzleFlash/Fire/PlaneLeft.mesh + false + true + + + + + + + + + 2 + Models/Effects/MuzzleFlash/Fire/PlaneRight.mesh + false + true + + + + + + + + + 2 + Models/Effects/MuzzleFlash/Fire/PlaneUp.mesh + false + true + + + + + + + + + 2 + Models/Effects/MuzzleFlash/Fire/PlaneDown.mesh + false + true + + + + + + + + + + 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/MuzzleFlashGreen.xml b/resources/Schema/Entities/MuzzleFlashGreen.xml new file mode 100644 index 00000000..966a2c8d --- /dev/null +++ b/resources/Schema/Entities/MuzzleFlashGreen.xml @@ -0,0 +1,135 @@ + + + + + + 0.039999999105930328 + + + + + + + + + + + + + + 2 + Models/Effects/MuzzleFlash/Green/Cone1Outside.mesh + false + true + + + + + + + + + 2 + Models/Effects/MuzzleFlash/Green/Cone1Inside.mesh + false + true + + + + + + + + + + + + + + + + + + 2 + Models/Effects/MuzzleFlash/Green/Cone2Inside.mesh + false + true + + + + + + + + + 2 + Models/Effects/MuzzleFlash/Green/Cone2Outside.mesh + false + true + + + + + + + + + + + + + + + + + + 2 + Models/Effects/MuzzleFlash/Green/PlaneLeft.mesh + false + true + + + + + + + + + 2 + Models/Effects/MuzzleFlash/Green/PlaneRight.mesh + false + true + + + + + + + + + 2 + Models/Effects/MuzzleFlash/Green/PlaneUp.mesh + false + true + + + + + + + + + 2 + Models/Effects/MuzzleFlash/Green/PlaneDown.mesh + false + true + + + + + + + + + + diff --git a/resources/Schema/Entities/MuzzleFlashLightBlue.xml b/resources/Schema/Entities/MuzzleFlashLightBlue.xml new file mode 100644 index 00000000..86c0b76c --- /dev/null +++ b/resources/Schema/Entities/MuzzleFlashLightBlue.xml @@ -0,0 +1,135 @@ + + + + + + 0.039999999105930328 + + + + + + + + + + + + + + 2 + Models/Effects/MuzzleFlash/LightBlue/Cone1Outside.mesh + false + true + + + + + + + + + 2 + Models/Effects/MuzzleFlash/LightBlue/Cone1Inside.mesh + false + true + + + + + + + + + + + + + + + + + + 2 + Models/Effects/MuzzleFlash/LightBlue/Cone2Inside.mesh + false + true + + + + + + + + + 2 + Models/Effects/MuzzleFlash/LightBlue/Cone2Outside.mesh + false + true + + + + + + + + + + + + + + + + + + 2 + Models/Effects/MuzzleFlash/LightBlue/PlaneLeft.mesh + false + true + + + + + + + + + 2 + Models/Effects/MuzzleFlash/LightBlue/PlaneRight.mesh + false + true + + + + + + + + + 2 + Models/Effects/MuzzleFlash/LightBlue/PlaneUp.mesh + false + true + + + + + + + + + 2 + Models/Effects/MuzzleFlash/LightBlue/PlaneDown.mesh + false + true + + + + + + + + + + diff --git a/resources/Schema/Entities/MuzzleFlashPink.xml b/resources/Schema/Entities/MuzzleFlashPink.xml new file mode 100644 index 00000000..7664cf0f --- /dev/null +++ b/resources/Schema/Entities/MuzzleFlashPink.xml @@ -0,0 +1,135 @@ + + + + + + 0.039999999105930328 + + + + + + + + + + + + + + 2 + Models/Effects/MuzzleFlash/Pink/Cone1Outside.mesh + false + true + + + + + + + + + 2 + Models/Effects/MuzzleFlash/Pink/Cone1Inside.mesh + false + true + + + + + + + + + + + + + + + + + + 2 + Models/Effects/MuzzleFlash/Pink/Cone2Inside.mesh + false + true + + + + + + + + + 2 + Models/Effects/MuzzleFlash/Pink/Cone2Outside.mesh + false + true + + + + + + + + + + + + + + + + + + 2 + Models/Effects/MuzzleFlash/Pink/PlaneLeft.mesh + false + true + + + + + + + + + 2 + Models/Effects/MuzzleFlash/Pink/PlaneRight.mesh + false + true + + + + + + + + + 2 + Models/Effects/MuzzleFlash/Pink/PlaneUp.mesh + false + true + + + + + + + + + 2 + Models/Effects/MuzzleFlash/Pink/PlaneDown.mesh + false + true + + + + + + + + + + diff --git a/resources/Schema/Entities/MuzzleFlashPurple.xml b/resources/Schema/Entities/MuzzleFlashPurple.xml new file mode 100644 index 00000000..c867fbc2 --- /dev/null +++ b/resources/Schema/Entities/MuzzleFlashPurple.xml @@ -0,0 +1,135 @@ + + + + + + 0.039999999105930328 + + + + + + + + + + + + + + 2 + Models/Effects/MuzzleFlash/Purple/Cone1Outside.mesh + false + true + + + + + + + + + 2 + Models/Effects/MuzzleFlash/Purple/Cone1Inside.mesh + false + true + + + + + + + + + + + + + + + + + + 2 + Models/Effects/MuzzleFlash/Purple/Cone2Inside.mesh + false + true + + + + + + + + + 2 + Models/Effects/MuzzleFlash/Purple/Cone2Outside.mesh + false + true + + + + + + + + + + + + + + + + + + 2 + Models/Effects/MuzzleFlash/Purple/PlaneLeft.mesh + false + true + + + + + + + + + 2 + Models/Effects/MuzzleFlash/Purple/PlaneRight.mesh + false + true + + + + + + + + + 2 + Models/Effects/MuzzleFlash/Purple/PlaneUp.mesh + false + true + + + + + + + + + 2 + Models/Effects/MuzzleFlash/Purple/PlaneDown.mesh + false + true + + + + + + + + + + diff --git a/resources/Schema/Entities/MuzzleFlashRainbow.xml b/resources/Schema/Entities/MuzzleFlashRainbow.xml new file mode 100644 index 00000000..27da23d0 --- /dev/null +++ b/resources/Schema/Entities/MuzzleFlashRainbow.xml @@ -0,0 +1,135 @@ + + + + + + 0.039999999105930328 + + + + + + + + + + + + + + 2 + Models/Effects/MuzzleFlash/Rainbow/Cone1Outside.mesh + false + true + + + + + + + + + 2 + Models/Effects/MuzzleFlash/Rainbow/Cone1Inside.mesh + false + true + + + + + + + + + + + + + + + + + + 2 + Models/Effects/MuzzleFlash/Rainbow/Cone2Inside.mesh + false + true + + + + + + + + + 2 + Models/Effects/MuzzleFlash/Rainbow/Cone2Outside.mesh + false + true + + + + + + + + + + + + + + + + + + 2 + Models/Effects/MuzzleFlash/Rainbow/PlaneLeft.mesh + false + true + + + + + + + + + 2 + Models/Effects/MuzzleFlash/Rainbow/PlaneRight.mesh + false + true + + + + + + + + + 2 + Models/Effects/MuzzleFlash/Rainbow/PlaneUp.mesh + false + true + + + + + + + + + 2 + Models/Effects/MuzzleFlash/Rainbow/PlaneDown.mesh + false + true + + + + + + + + + + diff --git a/resources/Schema/Entities/MuzzleFlashRed.xml b/resources/Schema/Entities/MuzzleFlashRed.xml new file mode 100644 index 00000000..97fe29c8 --- /dev/null +++ b/resources/Schema/Entities/MuzzleFlashRed.xml @@ -0,0 +1,195 @@ + + + + + + 0.039999999105930328 + + + + + + + + + + + + + + 2 + Models/Effects/MuzzleFlash/Red/Cone1Outside.mesh + false + true + + + + + + + + + 2 + Models/Effects/MuzzleFlash/Red/Cone1Inside.mesh + false + true + + + + + + + + + + + + + + + + + + 2 + Models/Effects/MuzzleFlash/Red/Cone2Inside.mesh + false + true + + + + + + + + + 2 + Models/Effects/MuzzleFlash/Red/Cone2Outside.mesh + false + true + + + + + + + + + + + + + + + + + + 2 + Models/Effects/MuzzleFlash/Red/PlaneLeft.mesh + false + true + + + + + + + + + 2 + Models/Effects/MuzzleFlash/Red/PlaneRight.mesh + false + true + + + + + + + + + 2 + Models/Effects/MuzzleFlash/Red/PlaneUp.mesh + false + true + + + + + + + + + 2 + Models/Effects/MuzzleFlash/Red/PlaneDown.mesh + false + true + + + + + + + + + + + + + + + + Models/Core/UnitSphere.mesh + false + false + + + + + + + + + + + + + + + Models/Core/UnitSphere.mesh + + false + false + + + + 0.40000000596046448 + + + + + + + + + + + + Models/Core/UnitSphere.mesh + false + false + + + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/MuzzleFlashSideArmBlue.xml b/resources/Schema/Entities/MuzzleFlashSideArmBlue.xml new file mode 100644 index 00000000..2d4dd59b --- /dev/null +++ b/resources/Schema/Entities/MuzzleFlashSideArmBlue.xml @@ -0,0 +1,219 @@ + + + + + + 0.08 + + + + + + + + + + + + + + 0.08 + + + 2 + Models/Effects/MuzzleFlash/Blue/Cone1Outside.mesh + false + true + + + + + + + + + 0.08 + + + 2 + Models/Effects/MuzzleFlash/Blue/Cone1Inside.mesh + false + true + + + + + + + + + + + + + + + + + + 0.08 + + + 2 + Models/Effects/MuzzleFlash/Blue/Cone2Inside.mesh + false + true + + + + + + + + + 0.08 + + + 2 + Models/Effects/MuzzleFlash/Blue/Cone2Outside.mesh + false + true + + + + + + + + + + + + + + + + + + 0.08 + + + 2 + Models/Effects/MuzzleFlash/Blue/PlaneLeft.mesh + false + true + + + + + + + + + 0.08 + + + 2 + Models/Effects/MuzzleFlash/Blue/PlaneRight.mesh + false + true + + + + + + + + + 0.08 + + + 2 + Models/Effects/MuzzleFlash/Blue/PlaneUp.mesh + false + true + + + + + + + + + 0.08 + + + 2 + Models/Effects/MuzzleFlash/Blue/PlaneDown.mesh + false + true + + + + + + + + + + + + + + + + Models/Core/UnitSphere.mesh + false + false + + + + + + + + + + + + + + + Models/Core/UnitSphere.mesh + + false + false + + + + 0.40000000596046448 + + + + + + + + + + + + Models/Core/UnitSphere.mesh + false + false + + + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/MuzzleFlashSideArmRed.xml b/resources/Schema/Entities/MuzzleFlashSideArmRed.xml new file mode 100644 index 00000000..1f8220c4 --- /dev/null +++ b/resources/Schema/Entities/MuzzleFlashSideArmRed.xml @@ -0,0 +1,219 @@ + + + + + + 0.080000000000000002 + + + + + + + + + + + + + + 0.080000000000000002 + + + 2 + Models/Effects/MuzzleFlash/Red/Cone1Outside.mesh + false + true + + + + + + + + + 0.080000000000000002 + + + 2 + Models/Effects/MuzzleFlash/Red/Cone1Inside.mesh + false + true + + + + + + + + + + + + + + + + + + 0.080000000000000002 + + + 2 + Models/Effects/MuzzleFlash/Red/Cone2Inside.mesh + false + true + + + + + + + + + 0.080000000000000002 + + + 2 + Models/Effects/MuzzleFlash/Red/Cone2Outside.mesh + false + true + + + + + + + + + + + + + + + + + + 0.080000000000000002 + + + 2 + Models/Effects/MuzzleFlash/Red/PlaneLeft.mesh + false + true + + + + + + + + + 0.080000000000000002 + + + 2 + Models/Effects/MuzzleFlash/Red/PlaneRight.mesh + false + true + + + + + + + + + 0.080000000000000002 + + + 2 + Models/Effects/MuzzleFlash/Red/PlaneUp.mesh + false + true + + + + + + + + + 0.080000000000000002 + + + 2 + Models/Effects/MuzzleFlash/Red/PlaneDown.mesh + false + true + + + + + + + + + + + + + + + + Models/Core/UnitSphere.mesh + false + false + + + + + + + + + + + + + + + Models/Core/UnitSphere.mesh + + false + false + + + + 0.40000000596046448 + + + + + + + + + + + + Models/Core/UnitSphere.mesh + false + false + + + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/MuzzleFlashWhite.xml b/resources/Schema/Entities/MuzzleFlashWhite.xml new file mode 100644 index 00000000..a810631a --- /dev/null +++ b/resources/Schema/Entities/MuzzleFlashWhite.xml @@ -0,0 +1,135 @@ + + + + + + 0.039999999105930328 + + + + + + + + + + + + + + 2 + Models/Effects/MuzzleFlash/White/Cone1Outside.mesh + false + true + + + + + + + + + 2 + Models/Effects/MuzzleFlash/White/Cone1Inside.mesh + false + true + + + + + + + + + + + + + + + + + + 2 + Models/Effects/MuzzleFlash/White/Cone2Inside.mesh + false + true + + + + + + + + + 2 + Models/Effects/MuzzleFlash/White/Cone2Outside.mesh + false + true + + + + + + + + + + + + + + + + + + 2 + Models/Effects/MuzzleFlash/White/PlaneLeft.mesh + false + true + + + + + + + + + 2 + Models/Effects/MuzzleFlash/White/PlaneRight.mesh + false + true + + + + + + + + + 2 + Models/Effects/MuzzleFlash/White/PlaneUp.mesh + false + true + + + + + + + + + 2 + Models/Effects/MuzzleFlash/White/PlaneDown.mesh + false + true + + + + + + + + + + diff --git a/resources/Schema/Entities/MuzzleFlashYellow.xml b/resources/Schema/Entities/MuzzleFlashYellow.xml new file mode 100644 index 00000000..c6c3b4cf --- /dev/null +++ b/resources/Schema/Entities/MuzzleFlashYellow.xml @@ -0,0 +1,135 @@ + + + + + + 0.039999999105930328 + + + + + + + + + + + + + + 2 + Models/Effects/MuzzleFlash/Yellow/Cone1Outside.mesh + false + true + + + + + + + + + 2 + Models/Effects/MuzzleFlash/Yellow/Cone1Inside.mesh + false + true + + + + + + + + + + + + + + + + + + 2 + Models/Effects/MuzzleFlash/Yellow/Cone2Inside.mesh + false + true + + + + + + + + + 2 + Models/Effects/MuzzleFlash/Yellow/Cone2Outside.mesh + false + true + + + + + + + + + + + + + + + + + + 2 + Models/Effects/MuzzleFlash/Yellow/PlaneLeft.mesh + false + true + + + + + + + + + 2 + Models/Effects/MuzzleFlash/Yellow/PlaneRight.mesh + false + true + + + + + + + + + 2 + Models/Effects/MuzzleFlash/Yellow/PlaneUp.mesh + false + true + + + + + + + + + 2 + Models/Effects/MuzzleFlash/Yellow/PlaneDown.mesh + false + true + + + + + + + + + + diff --git a/resources/Schema/Entities/NewMap.xml b/resources/Schema/Entities/NewMap.xml index 00dc476f..8fb8d9f4 100644 --- a/resources/Schema/Entities/NewMap.xml +++ b/resources/Schema/Entities/NewMap.xml @@ -5019,7 +5019,7 @@ - + @@ -5089,7 +5089,7 @@ - + @@ -5165,7 +5165,7 @@ - + @@ -5184,7 +5184,7 @@ - + @@ -5203,7 +5203,7 @@ - + @@ -5222,7 +5222,7 @@ - + @@ -5241,7 +5241,7 @@ - + @@ -5260,7 +5260,7 @@ - + @@ -5279,7 +5279,7 @@ - + @@ -5298,7 +5298,7 @@ - + diff --git a/resources/Schema/Entities/NewMap2.xml b/resources/Schema/Entities/NewMap2.xml new file mode 100644 index 00000000..ad2ae770 --- /dev/null +++ b/resources/Schema/Entities/NewMap2.xml @@ -0,0 +1,2913 @@ + + + + + + + + + + + + + + + + + + Models/Props/GroundTest.mesh + + + + + + + + + Models/Props/Walls/SciFiWallTop.mesh + + + + + + + + + Models/Props/Walls/SciFiWallBig.mesh + true + + + + + + + + + + Models/Props/Walls/SciFiWallMedium.mesh + + + + + + + + + + Models/Props/Walls/SciFiWallSmall1.mesh + + + + + + + + + + Models/Props/Walls/SciFiWallSmall2.mesh + + + + + + + + + + Models/Props/Walls/SciFiWallBig.mesh + + + + + + + + + + + + Models/Props/Walls/SciFiWallMedium.mesh + + + + + + + + + + + + Models/Props/Walls/SciFiWallSmall3.mesh + + + + + + + + + + Models/Props/Walls/SciFiWallSmall4.mesh + + + + + + + + + + + + Models/Props/HighgroundTest1.mesh + + + + + + + + + + Models/Props/HighgroundTest2.mesh + + + + + + + + + + + Models/Props/HighgroundTest3.mesh + + + + + + + + + + + Models/Props/HighgroundTest4.mesh + + + + + + + + + + + Models/Props/HighgroundTest5.mesh + + + + + + + + + + Models/Props/HighgroundTest6.mesh + + + + + + + + + + + Models/Props/HighgroundTest7.mesh + + + + + + + + + + + + + Models/Props/HighgroundTest8.mesh + + + + + + + + + + + + + Models/Props/HighgroundTest9.mesh + + + + + + + + + + + + + Models/Props/HighgroundTest10.mesh + + + + + + + + + + + + + Models/Props/HighgroundTest6.mesh + + + + + + + + + + + + + Models/Props/HighgroundTest1.mesh + + + + + + + + + + + + Models/Props/HighgroundTest2.mesh + + + + + + + + + + + + + Models/Props/HighgroundTest3.mesh + + + + + + + + + + + + + Models/Props/HighgroundTest4.mesh + + + + + + + + + + + + + Models/Props/HighgroundTest5.mesh + + + + + + + + + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar1Blue.mesh + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar1Red.mesh + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar3Blue.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar1Blue.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar1Red.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar3Red.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + + Models/Props/Bridges/SciFiBridge1Blue.mesh + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + Models/Props/PickUps/HealthPickUp.mesh + + + 8 + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + Models/Props/PickUps/HealthPickUp.mesh + + + 8 + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + 8 + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + 8 + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + Models/Props/PickUps/HealthPickUp.mesh + + + 8 + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + Models/Props/PickUps/HealthPickUp.mesh + + + 8 + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + 8 + + + + + + + + + + + + + + + + + + + + + + + + + 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/SciFiHolder1.mesh + + + + + + + + + + + + + Models/Props/SciFiHolder1.mesh + + + + + + + + + + + + + + + + + + + + Models/Props/Flora/SpecialRoot.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 + + + + + + + + + + + + + + + + + + + + + + + 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/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + Models/Props/PickUps/HealthPickUp.mesh + + + 8 + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + 8 + + + + + + + + + + + + + + + + + + + + + + + + + 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/SmallWall2.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointBlue.mesh + + + + + + + + + + + + + 4 + + + Models/Core/UnitCylinder.mesh + + true + + + + + + + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointNeutral.mesh + + + + + + + + + + 3 + + + Models/Core/UnitCylinder.mesh + + true + + + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointNeutral.mesh + + + + + + + + + + 2 + + + Models/Core/UnitCylinder.mesh + + true + + + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointNeutral.mesh + + + + + + + + + + 1.5498908015879351 + 1 + + + Models/Core/UnitCylinder.mesh + + true + + + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointRed.mesh + + + + + + + + + + + + + + + Models/Core/UnitCylinder.mesh + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + + + + + + + + 10 + + + + + + + + + + 10 + + + + + + + + + + + + + 10 + + + + + + + + + + + 10 + + + + + + + + + + + 10 + + + + + + + + + + + 1 + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + 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/NewMap2version2.xml b/resources/Schema/Entities/NewMap2version2.xml index d1964a84..8089073f 100644 --- a/resources/Schema/Entities/NewMap2version2.xml +++ b/resources/Schema/Entities/NewMap2version2.xml @@ -120,7 +120,7 @@ - Models/Props/HighgroundTest1.mesh + Models/Props/Highground1.mesh @@ -130,7 +130,7 @@ - Models/Props/HighgroundTest2.mesh + Models/Props/Highground2.mesh @@ -141,7 +141,7 @@ - Models/Props/HighgroundTest3.mesh + Models/Props/Highground3.mesh @@ -152,7 +152,7 @@ - Models/Props/HighgroundTest4.mesh + Models/Props/Highground4.mesh @@ -163,7 +163,7 @@ - Models/Props/HighgroundTest5.mesh + Models/Props/Highground5.mesh @@ -173,7 +173,7 @@ - Models/Props/HighgroundTest6.mesh + Models/Props/Highground6.mesh @@ -184,7 +184,7 @@ - Models/Props/HighgroundTest7.mesh + Models/Props/Highground7.mesh @@ -197,7 +197,7 @@ - Models/Props/HighgroundTest8.mesh + Models/Props/Highground8.mesh @@ -210,7 +210,7 @@ - Models/Props/HighgroundTest9.mesh + Models/Props/Highground9.mesh @@ -223,7 +223,7 @@ - Models/Props/HighgroundTest10.mesh + Models/Props/Highground10.mesh @@ -236,7 +236,7 @@ - Models/Props/HighgroundTest6.mesh + Models/Props/Highground6.mesh @@ -249,7 +249,7 @@ - Models/Props/HighgroundTest1.mesh + Models/Props/Highground1.mesh @@ -261,7 +261,7 @@ - Models/Props/HighgroundTest2.mesh + Models/Props/Highground2.mesh @@ -274,7 +274,7 @@ - Models/Props/HighgroundTest3.mesh + Models/Props/Highground3.mesh @@ -287,7 +287,7 @@ - Models/Props/HighgroundTest4.mesh + Models/Props/Highground4.mesh @@ -300,7 +300,7 @@ - Models/Props/HighgroundTest5.mesh + Models/Props/Highground5.mesh @@ -322,6 +322,7 @@ + 6 Models/Props/Pillars/SciFiPillar1Blue.mesh @@ -335,6 +336,7 @@ + 6 Models/Props/Pillars/SciFiPillar1Red.mesh @@ -348,6 +350,7 @@ + 4 Models/Props/Pillars/SciFiPillar2Red.mesh @@ -361,12 +364,13 @@ + 6 Models/Props/Pillars/SciFiPillar3Blue.mesh - + - + @@ -375,6 +379,7 @@ + 6 Models/Props/Pillars/SciFiPillar1Blue.mesh @@ -389,6 +394,7 @@ + 4 Models/Props/Pillars/SciFiPillar1Red.mesh @@ -403,10 +409,11 @@ + 4 Models/Props/Pillars/SciFiPillar3Red.mesh - + @@ -430,6 +437,7 @@ + 6 Models/Props/Pillars/SciFiPillar2Red.mesh @@ -443,6 +451,7 @@ + 6 Models/Props/Pillars/SciFiPillar2Blue.mesh @@ -457,6 +466,7 @@ + 6 Models/Props/Pillars/SciFiPillar2Blue.mesh @@ -474,9 +484,9 @@ Models/Props/Pillars/SciFiPillar2Blue.mesh - - - + + + @@ -485,6 +495,7 @@ + 6 Models/Props/Pillars/SciFiPillar2Blue.mesh @@ -498,12 +509,13 @@ + 4 Models/Props/Pillars/SciFiPillar2Red.mesh - - - + + + @@ -512,6 +524,7 @@ + 6 Models/Props/Pillars/SciFiPillar2Red.mesh @@ -525,6 +538,7 @@ + 6 Models/Props/Pillars/SciFiPillar2Red.mesh @@ -539,6 +553,7 @@ + 6 Models/Props/Pillars/SciFiPillar2Red.mesh @@ -568,8 +583,9 @@ Models/Props/Stones/ShinyStoneCrystalRed.mesh - - + + + @@ -617,7 +633,7 @@ Models/Props/Stones/ShinyStoneCrystalRed.mesh - + @@ -632,7 +648,7 @@ Models/Props/Stones/ShinyStoneCrystalRed.mesh - + @@ -647,9 +663,9 @@ Models/Props/Stones/ShinyStoneCrystalRed.mesh - + - + @@ -690,7 +706,7 @@ - + @@ -743,9 +759,9 @@ Models/Props/Stones/ShinyStoneCrystalRed.mesh - + - + @@ -758,8 +774,9 @@ Models/Props/Stones/ShinyStoneCrystalRed.mesh - - + + + @@ -785,22 +802,36 @@ - - - Models/Props/PickUps/HealthPickUp.mesh - - - 8 - - + + + + 2 + - - - + - - + + + + + + Models/Props/PickUps/HealthPickUp.mesh + + + 8 + + + + + + + + + + + + @@ -818,22 +849,36 @@ - - - Models/Props/PickUps/HealthPickUp.mesh - - - 8 - - + + + + 2 + - - - + - - + + + + + + Models/Props/PickUps/HealthPickUp.mesh + + + 8 + + + + + + + + + + + + @@ -851,22 +896,36 @@ - - - Models/Props/PickUps/AmmoPickUp.mesh - - - 8 - - + + + + 2 + - - - + - - + + + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + 8 + + + + + + + + + + + + @@ -876,7 +935,7 @@ Models/Props/PickUps/PickUpHolder.mesh - + @@ -884,22 +943,36 @@ - - - Models/Props/PickUps/AmmoPickUp.mesh - - - 8 - - + + + + 2 + - - - + - - + + + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + 8 + + + + + + + + + + + + @@ -909,30 +982,44 @@ Models/Props/PickUps/PickUpHolder.mesh - + - + - - - Models/Props/PickUps/HealthPickUp.mesh - - - 8 - - + + + + 2 + - - - + - - + + + + + + Models/Props/PickUps/HealthPickUp.mesh + + + 8 + + + + + + + + + + + + @@ -950,22 +1037,36 @@ - - - Models/Props/PickUps/HealthPickUp.mesh - - - 8 - - + + + + 2 + - - - + - - + + + + + + Models/Props/PickUps/HealthPickUp.mesh + + + 8 + + + + + + + + + + + + @@ -983,22 +1084,36 @@ - - - Models/Props/PickUps/AmmoPickUp.mesh - - - 8 - - + + + + 2 + - - - + - - + + + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + 8 + + + + + + + + + + + + @@ -1016,7 +1131,7 @@ Models/Props/Stones/BigStone.mesh - + @@ -1054,7 +1169,7 @@ Models/Props/Stones/BigStone.mesh - + @@ -1121,7 +1236,7 @@ Models/Props/Stones/MediumStone2.mesh - + @@ -1148,7 +1263,7 @@ Models/Props/Stones/MediumStone1.mesh - + @@ -1188,7 +1303,7 @@ Models/Props/Stones/BigStone.mesh - + @@ -1201,8 +1316,8 @@ Models/Props/Stones/MediumStone2.mesh - - + + @@ -1228,7 +1343,7 @@ Models/Props/Stones/SmallStone2.mesh - + @@ -1241,7 +1356,7 @@ Models/Props/Stones/BigStone.mesh - + @@ -1280,7 +1395,7 @@ Models/Props/Stones/SmallStone2.mesh - + @@ -1293,8 +1408,8 @@ Models/Props/Stones/SmallStone2.mesh - - + + @@ -1308,9 +1423,9 @@ Models/Props/Stones/MediumStone2.mesh - + - + @@ -1373,7 +1488,7 @@ Models/Props/Stones/MediumStone2.mesh - + @@ -1387,8 +1502,8 @@ Models/Props/Stones/BigStone.mesh - - + + @@ -1400,7 +1515,7 @@ Models/Props/Stones/BigStone.mesh - + @@ -1413,7 +1528,7 @@ Models/Props/Stones/MediumStone1.mesh - + @@ -1426,7 +1541,7 @@ Models/Props/Stones/SmallStone1.mesh - + @@ -1579,7 +1694,7 @@ Models/Props/Bridges/SciFiBridge1Red.mesh - + @@ -1591,7 +1706,7 @@ Models/Props/Pillars/SciFiBridgePillar1.mesh - + @@ -1613,6 +1728,20 @@ + + + + + Models/Props/Bridges/SciFiBridge1Red.mesh + + + + + + + + + @@ -1640,7 +1769,7 @@ Models/Props/SciFiHolder1.mesh - + @@ -1666,19 +1795,6 @@ - - - - - Models/Props/Flora/SpecialRoot.mesh - - - - - - - - @@ -1693,7 +1809,7 @@ Models/Props/Walls/BigWallRed.mesh - + @@ -1719,7 +1835,7 @@ Models/Props/Walls/SmallWall3.mesh - + @@ -1733,8 +1849,8 @@ Models/Props/Walls/MediumWall2.mesh - - + + @@ -1746,8 +1862,8 @@ Models/Props/Walls/MediumWall2.mesh - - + + @@ -1759,8 +1875,8 @@ Models/Props/Walls/MediumWall2.mesh - - + + @@ -1772,8 +1888,8 @@ Models/Props/Walls/MediumWall2.mesh - - + + @@ -1861,7 +1977,7 @@ Models/Props/Walls/SmallWall3.mesh - + @@ -1874,7 +1990,7 @@ Models/Props/Walls/SmallWall3.mesh - + @@ -1935,7 +2051,7 @@ Models/Props/Stones/AssaultHolder.mesh - + @@ -1975,7 +2091,7 @@ Models/Props/Stones/AssaultHolder.mesh - + @@ -1987,7 +2103,7 @@ Models/Props/Stones/AssaultHolder.mesh - + @@ -2007,12 +2123,13 @@ + 6 Models/Props/Pillars/SciFiPillar1Red.mesh - + - + @@ -2024,7 +2141,7 @@ Models/Props/Pillars/StonePillar.mesh - + @@ -2090,7 +2207,7 @@ Models/Props/Stones/AssaultHolder.mesh - + @@ -2102,7 +2219,7 @@ Models/Props/Stones/AssaultHolder.mesh - + @@ -2114,7 +2231,7 @@ Models/Props/Stones/AssaultHolder.mesh - + @@ -2125,7 +2242,7 @@ Models/Props/Stones/AssaultHolder.mesh - + @@ -2143,7 +2260,7 @@ Models/Props/Stones/AssaultHolder.mesh - + @@ -2157,7 +2274,7 @@ Models/Props/Stones/AssaultHolder.mesh - + @@ -2169,10 +2286,49 @@ Models/Props/Stones/AssaultHolder.mesh - + - + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + @@ -2197,22 +2353,36 @@ - - - Models/Props/PickUps/HealthPickUp.mesh - - - 8 - - + + + + 2 + - - - + - - + + + + + + Models/Props/PickUps/HealthPickUp.mesh + + + 8 + + + + + + + + + + + + @@ -2222,7 +2392,7 @@ Models/Props/PickUps/PickUpHolder.mesh - + @@ -2230,22 +2400,36 @@ - - - Models/Props/PickUps/AmmoPickUp.mesh - - - 8 - - + + + + 2 + - - - + - - + + + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + 8 + + + + + + + + + + + + @@ -2263,7 +2447,7 @@ Models/Props/Stones/BigStone.mesh - + @@ -2351,7 +2535,7 @@ Models/Props/Stones/ShinyStoneCrystalRed.mesh - + @@ -2366,7 +2550,7 @@ Models/Props/Stones/ShinyStoneCrystalBlue.mesh - + @@ -2387,25 +2571,12 @@ Models/Props/Walls/SmallWall2.mesh - + - - - - - Models/Props/Walls/SmallWall2.mesh - - - - - - - - @@ -2426,7 +2597,7 @@ Models/Props/Walls/SmallWall3.mesh - + @@ -2440,7 +2611,7 @@ Models/Props/Walls/SmallWall3.mesh - + @@ -2454,7 +2625,7 @@ Models/Props/Walls/SmallWall3.mesh - + @@ -2475,6 +2646,19 @@ + + + + + Models/Props/Walls/MediumWall1.mesh + + + + + + + + @@ -2499,15 +2683,16 @@ Models/Props/Stones/ShinyStoneCrystalBlue.mesh - - + + + - + @@ -2518,7 +2703,7 @@ - + @@ -2529,7 +2714,7 @@ - + 2 @@ -2548,7 +2733,7 @@ Models/Props/Stones/ShinyStoneCrystalBlue.mesh - + @@ -2563,7 +2748,7 @@ Models/Props/Stones/ShinyStoneCrystalBlue.mesh - + @@ -2578,9 +2763,9 @@ Models/Props/Stones/ShinyStoneCrystalBlue.mesh - + - + @@ -2621,7 +2806,7 @@ - + @@ -2630,7 +2815,7 @@ - + 2 @@ -2642,7 +2827,7 @@ - + 3 @@ -2654,7 +2839,7 @@ - + 2 1 @@ -2674,9 +2859,9 @@ Models/Props/Stones/ShinyStoneCrystalBlue.mesh - + - + @@ -2689,8 +2874,9 @@ Models/Props/Stones/ShinyStoneCrystalBlue.mesh - - + + + @@ -2716,22 +2902,36 @@ - - - Models/Props/PickUps/HealthPickUp.mesh - - - 8 - - + + + + 2 + - - - + - - + + + + + + Models/Props/PickUps/HealthPickUp.mesh + + + 8 + + + + + + + + + + + + @@ -2749,22 +2949,36 @@ - - - Models/Props/PickUps/HealthPickUp.mesh - - - 8 - - + + + + 2 + - - - + - - + + + + + + Models/Props/PickUps/HealthPickUp.mesh + + + 8 + + + + + + + + + + + + @@ -2782,22 +2996,36 @@ - - - Models/Props/PickUps/AmmoPickUp.mesh - - - 8 - - + + + + 2 + - - - + - - + + + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + 8 + + + + + + + + + + + + @@ -2807,7 +3035,7 @@ Models/Props/PickUps/PickUpHolder.mesh - + @@ -2815,22 +3043,36 @@ - - - Models/Props/PickUps/AmmoPickUp.mesh - - - 8 - - + + + + 2 + - - - + - - + + + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + 8 + + + + + + + + + + + + @@ -2840,30 +3082,44 @@ Models/Props/PickUps/PickUpHolder.mesh - + - + - - - Models/Props/PickUps/HealthPickUp.mesh - - - 8 - - + + + + 2 + - - - + - - + + + + + + Models/Props/PickUps/HealthPickUp.mesh + + + 8 + + + + + + + + + + + + @@ -2881,22 +3137,36 @@ - - - Models/Props/PickUps/HealthPickUp.mesh - - - 8 - - + + + + 2 + - - - + - - + + + + + + Models/Props/PickUps/HealthPickUp.mesh + + + 8 + + + + + + + + + + + + @@ -2906,7 +3176,7 @@ Models/Props/PickUps/PickUpHolder.mesh - + @@ -2914,22 +3184,36 @@ - - - Models/Props/PickUps/AmmoPickUp.mesh - - - 8 - - + + + + 2 + - - - + - - + + + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + 8 + + + + + + + + + + + + @@ -2947,7 +3231,7 @@ Models/Props/Stones/BigStone.mesh - + @@ -2985,7 +3269,7 @@ Models/Props/Stones/BigStone.mesh - + @@ -3052,7 +3336,7 @@ Models/Props/Stones/MediumStone2.mesh - + @@ -3079,7 +3363,7 @@ Models/Props/Stones/MediumStone1.mesh - + @@ -3119,7 +3403,7 @@ Models/Props/Stones/BigStone.mesh - + @@ -3132,8 +3416,8 @@ Models/Props/Stones/MediumStone2.mesh - - + + @@ -3159,7 +3443,7 @@ Models/Props/Stones/SmallStone2.mesh - + @@ -3172,7 +3456,7 @@ Models/Props/Stones/BigStone.mesh - + @@ -3211,7 +3495,7 @@ Models/Props/Stones/SmallStone2.mesh - + @@ -3224,8 +3508,8 @@ Models/Props/Stones/SmallStone2.mesh - - + + @@ -3239,9 +3523,9 @@ Models/Props/Stones/MediumStone2.mesh - + - + @@ -3304,7 +3588,7 @@ Models/Props/Stones/MediumStone2.mesh - + @@ -3318,8 +3602,8 @@ Models/Props/Stones/BigStone.mesh - - + + @@ -3331,7 +3615,7 @@ Models/Props/Stones/BigStone.mesh - + @@ -3344,7 +3628,7 @@ Models/Props/Stones/MediumStone1.mesh - + @@ -3357,7 +3641,7 @@ Models/Props/Stones/SmallStone1.mesh - + @@ -3369,7 +3653,7 @@ Models/Props/Stones/SmallStone2.mesh - + @@ -3378,19 +3662,6 @@ - - - - - Models/Props/Stones/BigStone.mesh - - - - - - - - @@ -3523,7 +3794,7 @@ Models/Props/Bridges/SciFiBridge1Blue.mesh - + @@ -3535,7 +3806,7 @@ Models/Props/Pillars/SciFiBridgePillar1.mesh - + @@ -3557,6 +3828,20 @@ + + + + + Models/Props/Bridges/SciFiBridge1Blue.mesh + + + + + + + + + @@ -3584,7 +3869,7 @@ Models/Props/SciFiHolder1.mesh - + @@ -3610,19 +3895,6 @@ - - - - - Models/Props/Flora/SpecialRoot.mesh - - - - - - - - @@ -3637,7 +3909,7 @@ Models/Props/Walls/BigWallRed.mesh - + @@ -3663,7 +3935,7 @@ Models/Props/Walls/SmallWall3.mesh - + @@ -3677,8 +3949,8 @@ Models/Props/Walls/MediumWall2.mesh - - + + @@ -3690,8 +3962,8 @@ Models/Props/Walls/MediumWall2.mesh - - + + @@ -3703,8 +3975,8 @@ Models/Props/Walls/MediumWall2.mesh - - + + @@ -3716,8 +3988,8 @@ Models/Props/Walls/MediumWall2.mesh - - + + @@ -3753,7 +4025,7 @@ Models/Props/Walls/BigWallBlue.mesh - + @@ -3765,7 +4037,7 @@ Models/Props/Walls/BigWallBlue.mesh - + @@ -3805,7 +4077,7 @@ Models/Props/Walls/SmallWall3.mesh - + @@ -3818,7 +4090,7 @@ Models/Props/Walls/SmallWall3.mesh - + @@ -3879,7 +4151,7 @@ Models/Props/Stones/AssaultHolder.mesh - + @@ -3919,7 +4191,7 @@ Models/Props/Stones/AssaultHolder.mesh - + @@ -3931,7 +4203,7 @@ Models/Props/Stones/AssaultHolder.mesh - + @@ -3951,12 +4223,13 @@ + 6 Models/Props/Pillars/SciFiPillar1Blue.mesh - + - + @@ -3968,7 +4241,7 @@ Models/Props/Pillars/StonePillar.mesh - + @@ -4074,8 +4347,8 @@ - - + + @@ -4106,8 +4379,8 @@ - - + + @@ -4129,7 +4402,6 @@ - 1.5498908015879351 1 @@ -4139,8 +4411,8 @@ - - + + @@ -4177,8 +4449,8 @@ - - + + @@ -4208,30 +4480,7 @@ 10 - - - - - - - - 10 - - - - - - - - - - - - - 10 - - - + @@ -4242,7 +4491,7 @@ 10 - + @@ -4253,7 +4502,19 @@ 10 - + + + + + + + + + + 10 + + + @@ -4262,6 +4523,7 @@ 1 + false @@ -4269,6 +4531,18 @@ + + + + + 10 + + + + + + + @@ -4283,7 +4557,7 @@ - + diff --git a/resources/Schema/Entities/NewMap2version4NEW.xml b/resources/Schema/Entities/NewMap2version4NEW.xml new file mode 100644 index 00000000..0b94f444 --- /dev/null +++ b/resources/Schema/Entities/NewMap2version4NEW.xml @@ -0,0 +1,8770 @@ + + + + + + + + + + + + + + + + + + 2 + Models/Props/GroundTest.mesh + + + + + + + + + Models/Props/Walls/SciFiWallTop.mesh + + + + + + + + + Models/Props/Walls/SciFiWallBig.mesh + true + + + + + + + + + + Models/Props/Walls/SciFiWallMedium.mesh + + + + + + + + + + Models/Props/Walls/SciFiWallSmall1.mesh + + + + + + + + + + Models/Props/Walls/SciFiWallSmall2.mesh + + + + + + + + + + Models/Props/Walls/SciFiWallBig.mesh + + + + + + + + + + + + Models/Props/Walls/SciFiWallMedium.mesh + + + + + + + + + + + + Models/Props/Walls/SciFiWallSmall3.mesh + + + + + + + + + + Models/Props/Walls/SciFiWallSmall4.mesh + + + + + + + + + + + + Models/Props/Highground1.mesh + + + + + + + + + + Models/Props/Highground2.mesh + + + + + + + + + + + Models/Props/Highground3.mesh + + + + + + + + + + + Models/Highgrounds/Highground24.mesh + + + + + + + + + + + + Models/Highgrounds/Hg13.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg25.mesh + + + + + + + + + + + + Models/Highgrounds/Hg26.mesh + + + + + + + + + + + + Models/Highgrounds/Hg9.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg4.mesh + + + + + + + + + + + + + + Models/Highgrounds/Hg10.mesh + + + + + + + + + + + + + + Models/Highgrounds/Hg19.mesh + + + + + + + + + + + + + + Models/Highgrounds/Hg19.mesh + + + + + + + + + + + + + + + Models/Highgrounds/Highground12.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg16.mesh + + + + + + + + + + + + Models/Highgrounds/Hg15.mesh + + + + + + + + + + + + Models/Highgrounds/Hg14.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg13.mesh + + + + + + + + + + + + Models/Highgrounds/Hg11.mesh + + + + + + + + + + + + Models/Highgrounds/Hg20.mesh + + + + + + + + + + + + Models/Highgrounds/Hg18.mesh + + + + + + + + + + + + Models/Highgrounds/Hg19.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg17.mesh + + + + + + + + + + + + + + + Models/Highgrounds/Hg8.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg7.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg3.mesh + + + + + + + + + + + + + + + Models/Props/Highground1.mesh + + + + + + + + + + + + Models/Props/Highground2.mesh + + + + + + + + + + + + + Models/Props/Highground3.mesh + + + + + + + + + + + + + Models/Highgrounds/Highground1.mesh + + + + + + + + + + + Models/Highgrounds/Highground2.mesh + + + + + + + + + + + + + + Models/Highgrounds/Hg1.mesh + + + + + + + + + + + Models/Highgrounds/Hg2.mesh + + + + + + + + + + + + + + Models/Highgrounds/Highground5.mesh + + + + + + + + + + + + Models/Highgrounds/Hg17.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg19.mesh + + + + + + + + + + + + Models/Highgrounds/Hg18.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg20.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg6.mesh + + + + + + + + + + + + Models/Highgrounds/Hg8.mesh + + + + + + + + + + + + Models/Highgrounds/Hg7.mesh + + + + + + + + + + + + Models/Highgrounds/Hg10.mesh + + + + + + + + + + + + Models/Highgrounds/Hg4.mesh + + + + + + + + + + + + Models/Highgrounds/Hg16.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg9.mesh + + + + + + + + + + + + Models/Highgrounds/Hg3.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg19.mesh + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + Models/Highgrounds/Hg10.mesh + + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + + + + Models/Highgrounds/Highground22.mesh + + + + + + + + + + + + Models/Highgrounds/Hg8.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg19.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg21.mesh + + + + + + + + + + + + Models/Highgrounds/Hg11.mesh + + + + + + + + + + + + Models/Highgrounds/Hg3.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg17.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg8.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Red.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/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + + + Models/Highgrounds/Hg28.mesh + + + + + + + + + + + Models/Highgrounds/Hg10.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg27.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg15.mesh + + + + + + + + + + + + + + Models/Highgrounds/Hg13.mesh + + + + + + + + + + + + + + + Models/Highgrounds/Hg27.mesh + + + + + + + + + + + + Models/Highgrounds/Hg23.mesh + + + + + + + + + + + + + + + Models/Highgrounds/Hg27.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg23.mesh + + + + + + + + + + + + + + + Models/Highgrounds/Hg28.mesh + + + + + + + + + + + + Models/Highgrounds/Hg10.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg27.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg15.mesh + + + + + + + + + + + + + + Models/Highgrounds/Hg13.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 + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + Models/Props/Stones/ShinyStoneCrystalRed.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/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/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/Stones/BigStone.mesh + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + + Models/Props/Stones/BigStone.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/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.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/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/mediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + Models/Props/Stones/SmallStone2.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/SmallStone1.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/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/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/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/SmallStone1.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/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/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/mediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/mediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/mediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/mediumStone2.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/Bridges/SciFiBridge1Red.mesh + + + + + + + + + + + + Models/Props/Pillars/SciFiBridgePillar1.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/SciFiBridge1Red.mesh + + + + + + + + + + + + + + + + + + + + + Models/Props/SciFiHolder1.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/BigWallRed.mesh + + + + + + + + + + + Models/Props/Walls/BigWallRed.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/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/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + Models/Props/Walls/BigWallRed.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/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/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 + + + + + + + + + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar1Red.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 + + + + + + + + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.mesh + + + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.mesh + + + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.mesh + + + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.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/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + + + + + + + + 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/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.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/mediumStone2.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.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/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalRed.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/BigWallBlue.mesh + + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/smallWall3.mesh + + + + + + + + + + + + + + + + + + + + + + + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 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/Stones/ShinyStoneCrystalBlue.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 + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + + + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + + + + + + + + + + + + 5 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + 2 + + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 4 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 2 + + + + + + + + + + + + 3 + + + + + + + + + + + + 2 + 1 + + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 4 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalBlue.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/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/AmmoPickUp.mesh + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + + + + + + + + + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + + Models/Props/Stones/BigStone.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/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.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/BigStone.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 + + + + + + + + + + + + + + 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/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.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/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/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/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.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/SmallStone2.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/Bridges/SciFiBridge1Blue.mesh + + + + + + + + + + + + Models/Props/Pillars/SciFiBridgePillar1.mesh + + + + + + + + + + + + + Models/Props/Bridges/SciFiBridge1Blue.mesh + + + + + + + + + + + + Models/Props/Pillars/SciFiBridgePillar1.mesh + + + + + + + + + + + + + + + + + Models/Props/Pillars/SciFiBridgePillar1.mesh + + + + + + + + + + + + + + Models/Props/Bridges/SciFiBridge1Blue.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/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/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/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/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/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/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 + + + + + + + + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar1Blue.mesh + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.mesh + + + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.mesh + + + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.mesh + + + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.mesh + + + + + + + + + + + + + + + + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar1Blue.mesh + + + + + + + + + + + + + 4 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + 4 + Models/Props/Pillars/SciFiPillar3Blue.mesh + + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + 4 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + 6 + 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/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + 4 + Models/Props/Pillars/SciFiPillar3Blue.mesh + + + + + + + + + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointBlue.mesh + + + + + + + + + + + + + -15 + 4 + + + Models/Core/UnitCylinder.mesh + + true + + + + + + + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointNeutral.mesh + + + + + + + + + + 3 + + + Models/Core/UnitCylinder.mesh + + true + + + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointNeutral.mesh + + + + + + + + + + 15 + 2 + + + Models/Core/UnitCylinder.mesh + + true + + + + + + + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointNeutral.mesh + + + + + + + + + + 15 + 1 + + + Models/Core/UnitCylinder.mesh + + true + + + + + + + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointRed.mesh + + + + + + + + + + + + + 15 + + + Models/Core/UnitCylinder.mesh + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + + + + + + + + 10 + + + + + + + + + + + 10 + + + + + + + + + + + 10 + + + + + + + + + + + + 10 + + + + + + + + + + + 1 + + + + + + + + + + + + 10 + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + 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/NewMap2version5NEW.xml b/resources/Schema/Entities/NewMap2version5NEW.xml new file mode 100644 index 00000000..aa709967 --- /dev/null +++ b/resources/Schema/Entities/NewMap2version5NEW.xml @@ -0,0 +1,8765 @@ + + + + + + 2.4355835422707059 + + + + + + + + + + + + + + + 2 + Models/Props/GroundTest.mesh + + + + + + + + Models/Props/Walls/SciFiWallTop.mesh + + + + + + + + + Models/Props/Walls/SciFiWallMedium.mesh + + + + + + + + + + Models/Props/Walls/SciFiWallSmall1.mesh + + + + + + + + + + Models/Props/Walls/SciFiWallSmall2.mesh + + + + + + + + + + Models/Props/Walls/SciFiWallBig.mesh + + + + + + + + + + + + Models/Props/Walls/SciFiWallBig.mesh + true + + + + + + + + + + Models/Props/Walls/SciFiWallMedium.mesh + + + + + + + + + + + + Models/Props/Walls/SciFiWallSmall3.mesh + + + + + + + + + + Models/Props/Walls/SciFiWallSmall4.mesh + + + + + + + + + + + + Models/Highgrounds/Highground1.mesh + + + + + + + + + + Models/Highgrounds/Highground2.mesh + + + + + + + + + + + Models/Highgrounds/Highground3.mesh + + + + + + + + + + + Models/Highgrounds/Highground24.mesh + + + + + + + + + + + Models/Highgrounds/Hg13.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg25.mesh + + + + + + + + + + + + Models/Highgrounds/Hg26.mesh + + + + + + + + + + + + Models/Highgrounds/Hg9.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg4.mesh + + + + + + + + + + + + + + Models/Highgrounds/Hg10.mesh + + + + + + + + + + + + + + Models/Highgrounds/Hg19.mesh + + + + + + + + + + + + + + Models/Highgrounds/Hg19.mesh + + + + + + + + + + + + + + + Models/Highgrounds/Highground12.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg16.mesh + + + + + + + + + + + + Models/Highgrounds/Hg15.mesh + + + + + + + + + + + + Models/Highgrounds/Hg14.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg13.mesh + + + + + + + + + + + + Models/Highgrounds/Hg11.mesh + + + + + + + + + + + + Models/Highgrounds/Hg20.mesh + + + + + + + + + + + + Models/Highgrounds/Hg18.mesh + + + + + + + + + + + + Models/Highgrounds/Hg19.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg17.mesh + + + + + + + + + + + + + + + Models/Highgrounds/Hg8.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg7.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg3.mesh + + + + + + + + + + + + + + + Models/Highgrounds/Highground3.mesh + + + + + + + + + + + + Models/Highgrounds/Highground1.mesh + + + + + + + + + + + Models/Highgrounds/Highground2.mesh + + + + + + + + + + + + + + Models/Highgrounds/Hg1.mesh + + + + + + + + + + + Models/Highgrounds/Hg2.mesh + + + + + + + + + + + + + + Models/Highgrounds/Highground5.mesh + + + + + + + + + + + + Models/Highgrounds/Hg8.mesh + + + + + + + + + + + + Models/Highgrounds/Hg10.mesh + + + + + + + + + + + + Models/Highgrounds/Hg4.mesh + + + + + + + + + + + + Models/Highgrounds/Hg7.mesh + + + + + + + + + + + + Models/Highgrounds/Hg17.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg19.mesh + + + + + + + + + + + + Models/Highgrounds/Hg18.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg20.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg6.mesh + + + + + + + + + + + + Models/Highgrounds/Hg16.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg9.mesh + + + + + + + + + + + + Models/Highgrounds/Hg3.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg19.mesh + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + Models/Highgrounds/Hg10.mesh + + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + + + + Models/Highgrounds/Highground22.mesh + + + + + + + + + + + + Models/Highgrounds/Hg8.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg19.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg21.mesh + + + + + + + + + + + + Models/Highgrounds/Hg11.mesh + + + + + + + + + + + + Models/Highgrounds/Hg3.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg17.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg8.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Red.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/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + + + Models/Highgrounds/Hg28.mesh + + + + + + + + + + + Models/Highgrounds/Hg10.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg27.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg15.mesh + + + + + + + + + + + + + + Models/Highgrounds/Hg13.mesh + + + + + + + + + + + + + + + Models/Highgrounds/Hg27.mesh + + + + + + + + + + + + Models/Highgrounds/Hg23.mesh + + + + + + + + + + + + + + + Models/Highgrounds/Hg27.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg23.mesh + + + + + + + + + + + + + + + Models/Highgrounds/Hg28.mesh + + + + + + + + + + + + Models/Highgrounds/Hg10.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg27.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg15.mesh + + + + + + + + + + + + + + Models/Highgrounds/Hg13.mesh + + + + + + + + + + + + + + + Models/Highgrounds/Hg1.mesh + + + + + + + + + + + + Models/Highgrounds/Hg2.mesh + + + + + + + + + + + + + + + + + + + + + Models/Props/Stones/ShinyStoneCrystalBlue.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 + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + + + + + + + + Models/Props/Flora/SpecialRoot.mesh + + + + + + + + + + + + + + Models/Props/Flora/SpecialRoot.mesh + + + + + + + + + + + + + + Models/Props/Flora/SpecialRoot.mesh + + + + + + + + + + + + + + Models/Props/Flora/SpecialRoot.mesh + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + + + + + + + Models/Props/Bridges/SciFiBridge1Red.mesh + + + + + + + + + + + + Models/Props/Bridges/SciFiBridge1Red.mesh + + + + + + + + + + + + Models/Props/Pillars/SciFiBridgePillar1.mesh + + + + + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + + + Models/Props/Pillars/SciFiBridgePillar1.mesh + + + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + + + + + Models/Props/Pillars/SciFiBridgePillar1.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/StonePillar.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar1Red.mesh + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Red.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/Pillars/StonePillar.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/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/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/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/BigStone.mesh + + + + + + + + + + + + Models/Props/Stones/SmallStone2.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/MediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/mediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/mediumStone2.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/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/BigStone.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/SmallStone2.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/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/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/mediumStone2.mesh + + + + + + + + + + + + + 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 + + + + + + + + + + + + + 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/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/mediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.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/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/mediumStone2.mesh + + + + + + + + + + + + + + + + + + + + + Models/Props/SciFiHolder1.mesh + + + + + + + + + + + + + Models/Props/SciFiHolder1.mesh + + + + + + + + + + + + + Models/Props/SciFiHolder1.mesh + + + + + + + + + + + + + Models/Props/SciFiHolder1.mesh + + + + + + + + + + + + + Models/Props/SciFiHolder1.mesh + + + + + + + + + + + + + + + + + + + + Models/Props/Walls/MediumWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + Models/Props/Walls/MediumWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/BigWallRed.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/MediumWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + + Models/Props/Walls/MediumWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/MediumWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/MediumWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/BigWallRed.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/SmallWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.mesh + + + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.mesh + + + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.mesh + + + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.mesh + + + + + + + + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + Models/Core/UnitPlane.mesh + + true + + + + + + + + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + + + + + + + + + + + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/smallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/MediumWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.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/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Stones/mediumStone2.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/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.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 + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + 2 + + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + + + + + + + + + + + + 5 + 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 + + + + + + + + + + + + + + 4 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalBlue.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/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.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/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.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/SmallStone1.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/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/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.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/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/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/MediumStone2.mesh + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + + Models/Props/Stones/mediumStone2.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/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/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/Walls/SpecialWall1.mesh + + + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.mesh + + + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.mesh + + + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.mesh + + + + + + + + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar1Blue.mesh + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.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/Bridges/SciFiBridge1Blue.mesh + + + + + + + + + + + + Models/Props/Bridges/SciFiBridge1Blue.mesh + + + + + + + + + + + + Models/Props/Pillars/SciFiBridgePillar1.mesh + + + + + + + + + + + + + + + Models/Props/Pillars/SciFiBridgePillar1.mesh + + + + + + + + + + + + + + + Models/Props/Pillars/SciFiBridgePillar1.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/MediumWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/MediumWall3.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/BigWallBlue.mesh + + + + + + + + + + + Models/Props/Walls/BigWallBlue.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/MediumWall3.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/MediumWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.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 + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + 4 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + 4 + Models/Props/Pillars/SciFiPillar3Blue.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 + + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + 4 + Models/Props/Pillars/SciFiPillar3Blue.mesh + + + + + + + + + + + + + + + + + + + + + + 10 + + + + + + + + + + + + 10 + + + + + + + + + + + 10 + + + + + + + + + + + 1 + + + + + + + + + + + + 10 + + + + + + + + + + + 1 + + + + + + + + + 10 + + + + + + + + + + + + + + + + + + + Schema/Entities/PlayerAssaultRed.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 + + + + + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointNeutral.mesh + + + + + + + + + + 3 + + + + + Models/Core/UnitCylinder.mesh + + true + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointNeutral.mesh + + + + + + + + + + 15 + 1 + + + + + + + + + Models/Core/UnitCylinder.mesh + + true + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointBlue.mesh + + + + + + + + + + -15 + + + + 4 + + + + + + + + + Models/Core/UnitCylinder.mesh + + true + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointNeutral.mesh + + + + + + + + + + 15 + 2 + + + + + + + + + Models/Core/UnitCylinder.mesh + + true + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointRed.mesh + + + + + + + + + + 15 + + + + + + + + + + + + Models/Core/UnitCylinder.mesh + + true + + + + + + + + + + + + + + + + + + + + + + Schema/Entities/PlayerAssaultBlue.xml + + + + + + + + + + + Models/Core/UnitCube.mesh + + + + + + + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + diff --git a/resources/Schema/Entities/NewMap2version6NEW.xml b/resources/Schema/Entities/NewMap2version6NEW.xml new file mode 100644 index 00000000..5544ba82 --- /dev/null +++ b/resources/Schema/Entities/NewMap2version6NEW.xml @@ -0,0 +1,11874 @@ + + + + + + + + + + + + + + + + + + 2 + Models/Props/GroundTest.mesh + + + + + + + + 2 + Models/Props/Walls/SciFiWallTop.mesh + + + + + + + + + 2 + Models/Props/Walls/SciFiWallBig.mesh + + + + + + + + + + + + 2 + Models/Props/Walls/SciFiWallBig.mesh + + + + + + + + + + 2 + Models/Props/Walls/SciFiWallMedium.mesh + + + + + + + + + + 2 + Models/Props/Walls/SciFiWallSmall1.mesh + + + + + + + + + + 2 + Models/Props/Walls/SciFiWallSmall2.mesh + + + + + + + + + + 2 + Models/Props/Walls/SciFiWallMedium.mesh + + + + + + + + + + + + 2 + Models/Props/Walls/SciFiWallSmall3.mesh + + + + + + + + + + 2 + Models/Props/Walls/SciFiWallSmall4.mesh + + + + + + + + + + + + Models/Highgrounds/Highground1.mesh + + + + + + + + + + Models/Highgrounds/Highground2.mesh + + + + + + + + + + Models/Highgrounds/Highground3.mesh + + + + + + + + + + + Models/Highgrounds/Highground24.mesh + + + + + + + + + + + Models/Highgrounds/Hg13.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg25.mesh + + + + + + + + + + + + Models/Highgrounds/Hg26.mesh + + + + + + + + + + + + Models/Highgrounds/Hg9.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg4.mesh + + + + + + + + + + + + + + Models/Highgrounds/Hg10.mesh + + + + + + + + + + + + + + Models/Highgrounds/Hg19.mesh + + + + + + + + + + + + + + Models/Highgrounds/Hg19.mesh + + + + + + + + + + + + + + + Models/Highgrounds/Highground12.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg16.mesh + + + + + + + + + + + + Models/Highgrounds/Hg15.mesh + + + + + + + + + + + + Models/Highgrounds/Hg14.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg13.mesh + + + + + + + + + + + + Models/Highgrounds/Hg11.mesh + + + + + + + + + + + + Models/Highgrounds/Hg20.mesh + + + + + + + + + + + + Models/Highgrounds/Hg18.mesh + + + + + + + + + + + + Models/Highgrounds/Hg19.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg17.mesh + + + + + + + + + + + + + + + Models/Highgrounds/Hg8.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg7.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg3.mesh + + + + + + + + + + + + + + + Models/Highgrounds/Highground3.mesh + + + + + + + + + + + + Models/Highgrounds/Highground1.mesh + + + + + + + + + + + + Models/Highgrounds/Highground2.mesh + + + + + + + + + + + + + + Models/Highgrounds/Hg1.mesh + + + + + + + + + + + Models/Highgrounds/Hg2.mesh + + + + + + + + + + + + + + Models/Highgrounds/Highground5.mesh + + + + + + + + + + + + Models/Highgrounds/Hg10.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg4.mesh + + + + + + + + + + + + Models/Highgrounds/Hg7.mesh + + + + + + + + + + + + Models/Highgrounds/Hg17.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg19.mesh + + + + + + + + + + + + Models/Highgrounds/Hg18.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg20.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg6.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg8.mesh + + + + + + + + + + + + Models/Highgrounds/Hg16.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg9.mesh + + + + + + + + + + + + Models/Highgrounds/Hg3.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg19.mesh + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + Models/Highgrounds/Hg10.mesh + + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + + + + Models/Highgrounds/Highground22.mesh + + + + + + + + + + + + Models/Highgrounds/Hg8.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg19.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg21.mesh + + + + + + + + + + + + Models/Highgrounds/Hg11.mesh + + + + + + + + + + + + Models/Highgrounds/Hg3.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg17.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg8.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Red.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/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + + + Models/Highgrounds/Hg28.mesh + + + + + + + + + + + Models/Highgrounds/Hg10.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg27.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg15.mesh + + + + + + + + + + + + + + Models/Highgrounds/Hg13.mesh + + + + + + + + + + + + + + + Models/Highgrounds/Hg27.mesh + + + + + + + + + + + + Models/Highgrounds/Hg23.mesh + + + + + + + + + + + + + + + Models/Highgrounds/Hg27.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg23.mesh + + + + + + + + + + + + + + + Models/Highgrounds/Hg28.mesh + + + + + + + + + + + + Models/Highgrounds/Hg10.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg27.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg15.mesh + + + + + + + + + + + + + + Models/Highgrounds/Hg13.mesh + + + + + + + + + + + + + + + Models/Highgrounds/Hg1.mesh + + + + + + + + + + + + Models/Highgrounds/Hg2.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 + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + Models/Props/SciFiHolder1.mesh + + + + + + + + + + + + + Models/Props/SciFiHolder1.mesh + + + + + + + + + + + + + Models/Props/SciFiHolder1.mesh + + + + + + + + + + + + + Models/Props/SciFiHolder1.mesh + + + + + + + + + + + + + + + + + + + + 15 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + 15 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + 2 + + + + + + + + + + + + + + 15 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 15 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 15 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + 2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 15 + Models/Props/Stones/ShinyStoneCrystalBlue.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/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/MediumStone2.mesh + + + + + + + + + + + + Models/Props/Stones/SmallStone1.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/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/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.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/SmallStone1.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/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.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/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.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/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 + + + + + + + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.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/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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + + + + + + + + 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/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 + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + Models/Props/Walls/BigWallRed.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/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/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 + + + + + + + + + + + + + + + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.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/Core/UnitPlane.mesh + + true + + + + + + + + + + + + + + + + + + + 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/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/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 + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.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/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.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/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 + + + + + + + + + + + + + + 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/BigStone.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/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 + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + 6 + 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/SciFiPillar3Red.mesh + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + 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 + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar2Blue.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/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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + 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 + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + 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/NewMapWSpectatorCam.xml b/resources/Schema/Entities/NewMapWSpectatorCam.xml new file mode 100644 index 00000000..66561969 --- /dev/null +++ b/resources/Schema/Entities/NewMapWSpectatorCam.xml @@ -0,0 +1,6020 @@ + + + + + + 10.841646792775492 + 15 + + + + + + + + + + + + + + + Models/Props/Ground.mesh + + + + + + + + + Models/Props/Highground4.mesh + + + + + + + + + + Models/Props/Highground1.mesh + + + + + + + + + + Models/Props/Highground2.mesh + + + + + + + + + + Models/Props/Highground1.mesh + + + + + + + + + + + + Models/Props/Highground2.mesh + + + + + + + + + + + + Models/Props/Highground3.mesh + + + + + + + + + + Models/Props/Highground5.mesh + + + + + + + + + + + Models/Props/Highground6.mesh + + + + + + + + + + Models/Props/Walls/SciFiWallTop.mesh + + + + + + + + + Models/Props/Walls/SciFiWallBig.mesh + + + + + + + + + + Models/Props/Walls/SciFiWallMedium.mesh + + + + + + + + + + Models/Props/Walls/SciFiWallSmall1.mesh + + + + + + + + + + Models/Props/Walls/SciFiWallSmall2.mesh + + + + + + + + + + Models/Props/Walls/SciFiWallBig.mesh + + + + + + + + + + + + Models/Props/Walls/SciFiWallMedium.mesh + + + + + + + + + + + + Models/Props/Walls/SciFiWallSmall3.mesh + + + + + + + + + + Models/Props/Walls/SciFiWallSmall4.mesh + + + + + + + + + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar1Blue.mesh + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar1Red.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar3Blue.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar1Blue.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar1Red.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar3Red.mesh + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + + + Models/Props/Walls/MediumWall3.mesh + + + + + + + + + + + + Models/Props/Walls/MediumWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall2.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall4.mesh + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + Models/Props/Walls/SmallWall2.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall2.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall2.mesh + + + + + + + + + + + + + Models/Props/Walls/MediumWall2.mesh + + + + + + + + + + + + Models/Props/Walls/MediumWall2.mesh + + + + + + + + + + + + + + Models/Props/Walls/MediumWall1.mesh + + + + + + + + + + + + Models/Props/Walls/MediumWall1.mesh + + + + + + + + + + + + + + Models/Props/Walls/MediumWall1.mesh + + + + + + + + + + + + Models/Props/Walls/MediumWall1.mesh + + + + + + + + + + + + Models/Props/Walls/MediumWall1.mesh + + + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall4.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall4.mesh + + + + + + + + + + + + Models/Props/Walls/SmallWall2.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall2.mesh + + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + + + Models/Props/Walls/SmallWall2.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall2.mesh + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + + + Models/Props/Walls/MediumWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + Models/Props/Walls/SmallWall2.mesh + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.mesh + + + + + + + + + + + + + + Models/Props/Flora/SpecialRoot.mesh + + + + + + + + + + + + + + Models/Props/Walls/MediumWall1.mesh + + + + + + + + + + + + + Models/Props/Walls/MediumWall1.mesh + + + + + + + + + + + + + Models/Props/Walls/MediumWall1.mesh + + + + + + + + + + + + Models/Props/Walls/MediumWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/MediumWall1.mesh + + + + + + + + + + + + Models/Props/Walls/MediumWall1.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall2.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall2.mesh + + + + + + + + + + + + Models/Props/Walls/SmallWall2.mesh + + + + + + + + + + + + Models/Props/Walls/MediumWall3.mesh + + + + + + + + + + + + Models/Props/Walls/MediumWall2.mesh + + + + + + + + + + + Models/Props/Walls/MediumWall2.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + Models/Props/Walls/SmallWall4.mesh + + + + + + + + + + + + + + + + Models/Props/Walls/MediumWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/MediumWall2.mesh + + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.mesh + + + + + + + + + + + + + + Models/Props/Walls/MediumWall1.mesh + + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.mesh + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.mesh + + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.mesh + + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.mesh + + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.mesh + + + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.mesh + + + + + + + + + + + + + + + + + + + + + Models/Props/Bridges/SciFiBridge1Blue.mesh + + + + + + + + + + + + + Models/Props/Bridges/WoodenBridge.mesh + + + + + + + + + + + + + Models/Props/Bridges/WoodenBridge.mesh + + + + + + + + + + + + + + Models/Props/Bridges/WoodenBridge.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/Bridges/SciFiBridge1Blue.mesh + + + + + + + + + + + + + Models/Props/Pillars/SciFiBridgePillar1.mesh + + + + + + + + + + + + + + Models/Props/Bridges/SciFiBridge1Red.mesh + + + + + + + + + + + + + Models/Props/Bridges/WoodenBridge.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/Pillars/SciFiBridgePillar1.mesh + + + + + + + + + + + + + + Models/Props/Bridges/SciFiBridge1Red.mesh + + + + + + + + + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + + + Models/Props/Flora/SpecialRoot.mesh + + + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + + + + Models/Props/Flora/SpecialRoot.mesh + + + + + + + + + + + + + Models/Props/Flora/TreeLog.mesh + + + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + + + + Models/Props/Flora/SpecialRoot.mesh + + + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + + + + Models/Props/Flora/AliveBush.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/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/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Walls/MediumWall1.mesh + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + Models/Props/Stones/BigStone.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/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + + + + 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/SmallStone2.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 + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/MediumStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/MediumStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/MediumStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + Models/Props/Stones/MediumStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone1.mesh + + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.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/Core/UnitCube.mesh + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + + + Models/Props/Pillars/SciFiBridgePillar1.mesh + + + + + + + + + + + + + Models/Core/UnitPlane.mesh + + true + + + + + + + + + + + + + + Models/Props/Walls/MediumWall2.mesh + + + + + + + + + + + Models/Props/Walls/MediumWall2.mesh + + + + + + + + + + + + + + + Models/Props/Walls/MediumWall1.mesh + + + + + + + + + + + Models/Props/Walls/MediumWall1.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiBridgePillar1.mesh + + + + + + + + + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + + Models/Props/Pillars/SciFiBridgePillar1.mesh + + + + + + + + + + + + + + Models/Props/Walls/MediumWall3.mesh + + + + + + + + + + + Models/Props/Walls/MediumWall3.mesh + + + + + + + + + + + + + Models/Core/UnitPlane.mesh + + true + + + + + + + + + + + + + + Models/Props/Pillars/SciFiBridgePillar1.mesh + + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + + Models/Props/Walls/MediumWall1.mesh + + + + + + + + + + + + Models/Props/Walls/MediumWall1.mesh + + + + + + + + + + + + Models/Props/Walls/MediumWall1.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiBridgePillar1.mesh + + + + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + + + + + + + + + Models/Props/SciFiHolder1.mesh + + + + + + + + + + + + + Models/Props/SciFiHolder1.mesh + + + + + + + + + + + + + Models/Props/SciFiHolder1.mesh + + + + + + + + + + + + + Models/Props/SciFiHolder1.mesh + + + + + + + + + + + + + Models/Props/SciFiHolder1.mesh + + + + + + + + + + + + + Models/Props/SciFiHolder1.mesh + + + + + + + + + + + + + Models/Props/SciFiHolder1.mesh + + + + + + + + + + + + + Models/Props/SciFiHolder1.mesh + + + + + + + + + + + + + + + + + + + + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + + + + + + + + + + + 0.10000000149011612 + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + + + + + + + + + + + + + 0.10000000149011612 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + + + + + + + + + + + 0.10000000149011612 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + + + + + + + + + + + 0.10000000149011612 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + + + + + + + + + + + 0.10000000149011612 + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + + + + + + + + + + + + + 0.10000000149011612 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + + + + + + + + + + + 0.10000000149011612 + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + + + + + + + + + + + + + 0.10000000149011612 + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + + + + + + + + + + + + + + + + + + 10 + + + + + + + + + + 10 + + + + + + + + + + + + + 10 + + + + + + + + + + + 10 + + + + + + + + + + + 10 + + + + + + + + + + + 1 + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointNeutral.mesh + + + + + + + + + + 1.5498908015879351 + 1 + + + + + Models/Core/UnitCylinder.mesh + + true + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointNeutral.mesh + + + + + + + + + + 2 + + + + + Models/Core/UnitCylinder.mesh + + true + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointRed.mesh + + + + + + + + + + + + + + + + + + + + + Models/Core/UnitCylinder.mesh + + true + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointNeutral.mesh + + + + + + + + + + 3 + + + + + Models/Core/UnitCylinder.mesh + + true + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointBlue.mesh + + + + + + + + + + + + + 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 + + + + + + + + + + + + + 0.049999997019767761 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Textures/Icons/Classes/Assault-01.png + + false + + + PickClass + 1 + + + + + + + + + + + Assault + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + Textures/Icons/Classes/Defender-01.png + + false + + + PickClass + 2 + + + + + + + + + + + Defender + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + Textures/Icons/Classes/Sniper-01.png + + false + + + PickClass + 3 + + + + + + + + + + + Sniper + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Pick Class + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + false + + + + SwapToTeamPick + 1 + + + + + + + + + + + Change + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + Team + 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 + 2 + + + + + + + + + + + Red + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + false + + + + PickTeam + 3 + + + + + + + + + + + Blue + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + false + + false + + + SwapToClassPick + 1 + + + + + + + + + + + Change + Fonts/DroidSans.ttf,64 + false + + + + + + + + + + + + Class + Fonts/DroidSans.ttf,64 + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + false + + + + + + + + + + + + + + 3 + + + Textures/Core/UnitHexagon_Rotated.png + + false + + + + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + false + + + + + + + + + + + + + + 4 + + + Textures/Core/UnitHexagon_Rotated.png + + false + + + + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + false + + + + + + + + + + + + + + 2 + + + Textures/Core/UnitHexagon_Rotated.png + + false + + + + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + false + + + + + + + + + + + 0.10332605343919568 + + + + 1 + + + Textures/Core/UnitHexagon_Rotated.png + + false + + + + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + false + + + + + + + + + + + + + + + Textures/Core/UnitHexagon_Rotated.png + + false + + + + + + + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + false + + + + SwapToTeamPick + 1 + + + + + + + + + + + Change + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + Team + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + false + + + + SwapToClassPick + 1 + + + + + + + + + + + Change + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + Class + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/OliviaTestWorld.xml b/resources/Schema/Entities/OliviaTestWorld.xml new file mode 100644 index 00000000..23c2b283 --- /dev/null +++ b/resources/Schema/Entities/OliviaTestWorld.xml @@ -0,0 +1,1558 @@ + + + + + + + + + + + + + + + + Models/Core/UnitPlane.mesh + + + + + + + + + + + 90 + + + + + + + + + + + + 1 + + + + + + + + + + + Audio/crosscounter.wav + true + + + + + + + + + + SoundEmitter + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + + + Sound Test + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + 0.80000001192092896 + + + Models/DirectionalLightWidget.mesh + + + 1 + + + + + + + + + + + + + + + + + + + + + Run + + 1 + + + models/AssaultAnimated.mesh + + + + + + + + + + + Walk + + 1 + + + models/AssaultAnimated.mesh + + + + + + + + + Animation test + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + Models/Core/UnitCylinder.mesh + + + + + + + + + + + + + + + + + + + + 0.5 + + + + + + + + + + + Run + + 1 + + + Models/AssaultAnimated.mesh + + + + + + + + + + + + + + + + + + + + + + + + models/NormSpecIncdMapSphere.mesh + + + + + + + + + 1 + + + + + + + + + + + Models/Core/UnitSphere.mesh + + + + 3 + 1.1399998664855957 + + + + + + + + + + + + Models/Core/UnitSphere.mesh + + + + 5.0100002288818359 + 0.69999998807907104 + + + + + + + + + + + + Models/Core/UnitSphere.mesh + + + + 4 + 0.80000001192092896 + + + + + + + + + + + + + + 1 + + + + + + + + + + + Models/NormalMapSphere.mesh + + + + + + + + + + + Models/SpecularMapSphere.mesh + + + + + + + + + + 1 + + + + + + + + + + + Models/Core/UnitSphere.mesh + + + + 3 + 1.1399998664855957 + + + + + + + + + + + + + + + + Models/IncandescenceMapSphere.mesh + + + + + + + + + + + + + TextureMap's Test + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + 1.3999999761581421 + + + + + + + + + + + + + + + + + Schema/Entities/Player.xml + + + + + + + + + + + + + + + + Models/Assault.mesh + + + + + + + + + + + + + Models/Assault.mesh + + + + + + + + + + + + + Models/Assault.mesh + + + + + + + + + + + + + Models/Assault.mesh + + + + + + + + + + + + + + + Schema/Entities/Player.xml + + + + + + + + + + + + + + + + + Models/Assault.mesh + + + + + + + + + + + + + Models/Assault.mesh + + + + + + + + + + + + + Models/Assault.mesh + + + + + + + + + + + + + Models/Assault.mesh + + + + + + + + + + + + + + Spawn Test + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + true + + + + + + + + + + + Models/Core/UnitCylinder.mesh + + true + + + + + + + + + + + + Models/Core/UnitRaptor.mesh + + true + + + + + + + + + + + Models/Assault.mesh + + true + + + + + + + + + + + + Models/Core/UnitCube.mesh + + true + + + + + + + + + + + + + Transparency Test + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + + + Models/Core/UnitCylinder.mesh + + + + + + + + + + + + + + + + + + + + 0.5 + + + + + + + + + + + Models/AssaultBlueWeapon.mesh + + + + + + + + + + + + + + + + Models/Core/UnitCylinder.mesh + + + + + + + + + + + + + + + + + + + + 0.5 + + + + + + + + + + + Models/AssaultRedWeapon.mesh + + + + + + + + + + + + + + + + Asset Test + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + Models/Core/UnitCylinder.mesh + + + + + + + + + + + + + + + + + + + + 0.5 + + + + + + + + + + + Models/SecondaryWeapon.mesh + + + + + + + + + + + + + + + + Models/Core/UnitCylinder.mesh + + + + + + + + + + + + + + + + + + + + 0.5 + + + + + + + + + + + Models/AssualtSoft.mesh + + + + + + + + + + + + + + + Models/Core/UnitCylinder.mesh + + + + + + + + + + + + + + + + + + + + 0.5 + + + + + + + + + + + Models/DefenderGunBlue.mesh + + + + + + + + + + + + + + + + Models/Core/UnitCylinder.mesh + + + + + + + + + + + + + + + + + + + + 0.5 + + + + + + + + + + + Models/DefenderGunRed.mesh + + + + + + + + + + + + + + + + Models/Core/UnitCylinder.mesh + + + + + + + + + + + + + + + + + + + + 0.5 + + + + + + + + + + + Models/Assualt.mesh + + + + + + + + + + + + + + + + + + + + + + + + CapturePoint Test + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + Models/CapturePoint.mesh + + + + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + true + + + + + + + + + + + + + + + + + + Red team home point + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Models/CapturePoint.mesh + + + + + + + + + + + 1 + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + + RedMiddle Point + Fonts/DroidSans.ttf + + + + + + + + + + + + + + + Models/CapturePoint.mesh + + + + + + + + + 2 + + + Models/Core/UnitCube.mesh + true + + + + + + + + + + + + + + Middle Point + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Models/CapturePoint.mesh + + + + + + + + + + + -12.033302729641917 + 3 + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + + BlueMiddle Point + Fonts/DroidSans.ttf + + + + + + + + + + + + + + + Models/CapturePoint.mesh + + + + + + + + + + + + + + 4 + + + Models/Core/UnitCube.mesh + + true + + + + + + + + + + + + + + + + + + Blue team home point + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Models/Test/ObstacleCourse.mesh + + + + + + + + + + + Collision Test + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + + + + + + + + Models/Core/UnitCylinder.mesh + + + + + + + + + + + + + + + + + + + + 0.5 + + + + + + + + + + + true + + 2.3331127968986038 + 3.7999999523162842 + + true + + + Models/AssaultWeaponBlue.mesh + true + + + + + + + + + + + + + + + + Models/Core/UnitCylinder.mesh + + + + + + + + + + + + + + + + + + + + 0.5 + + + + + + + + + + + + + 0.28322599621543532 + + + Models/Assault.mesh + true + + + + + + + + + + + + + + + Models/Core/UnitCylinder.mesh + + + + + + + + + + + + + + + + + + + + 0.5 + + + + + + + + + + + Walk + + 1 + + + true + + + 1.8831113377486872 + + true + + + Models/AssaultAnimated.mesh + true + + + + + + + + + + + + + + + ExplosionEffect Test + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + + + Remember to pick random entities. + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + 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/OverwatchCamera.xml b/resources/Schema/Entities/OverwatchCamera.xml new file mode 100644 index 00000000..dd60816a --- /dev/null +++ b/resources/Schema/Entities/OverwatchCamera.xml @@ -0,0 +1,3169 @@ + + + + + + 0.014999999664723873 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + PickTeam + 1 + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Core/White.png + + + + PickClass + 1 + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + Blend + + + + + 1.6000000238418579 + Models/Characters/Assault/AssaultBluePose.mesh + false + + + + + + + + + + + + AssaultPoseF + + true + + + + + + + + + R_Arm_Weapon_Joint + + + Models/Weapons/Blue/AssaultWeaponBlue.mesh + + + + + + + + + + + + Models/Core/UnitSphere.mesh + false + + + 0.30000001192092896 + + + + + + + + + + + + + + + + + + + + + \1 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + Assault + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + 100 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Team Speed Boost + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + \1 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + \4 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + \7 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Dash + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Icons/Abilities/Square/Superman-01.png + + + + + + + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Icons/Shoe-01.png + + + + + + + + + + + + x2 Jump + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + + + PickTeam + 1 + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Core/White.png + + + + PickClass + 2 + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + Blend + + + + + 1.6000000238418579 + Models/Characters/Defender/DefenderBluePose.mesh + false + + + + + + + + + + + + DefenderPoseF + + true + + + + + + + + + R_Arm_Weapon_Joint + + + Models/Weapons/Blue/DefenderWeaponBlue.mesh + + + + + + + + + + + + Models/Core/UnitSphere.mesh + false + + + 0.30000001192092896 + + + + + + + + + + + + + + + + + + + + + \2 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + Defender + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + 150 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Team Shield Boost + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + \2 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + \5 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + \7 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Personal Shield + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Icons/Abilities/Square/SheildDots-01.png + + + + + + + + + + + + + + + + + + + + + PickTeam + 1 + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Core/White.png + + + + PickClass + 3 + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + Blend + + + + + 1.6000000238418579 + Models/Characters/Sniper/SniperBluePose.mesh + false + + + + + + + + + + + + SniperPoseF + + true + + + + + + + + + R_Arm_Weapon_Joint + + + Models/Weapons/Blue/SecondaryWeaponBlue.mesh + + + + + + + + + + + + Models/Core/UnitSphere.mesh + false + + + 0.30000001192092896 + + + + + + + + + + + + + + + + + + + + + \3 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + Sniper + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + 100 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Team Accuracy Boost + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + \3 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + \6 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + \7 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Sprint + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Icons/Abilities/Square/Dash-01.png + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Core/White.png + true + + + + PickTeam + 3 + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + true + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + true + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + true + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + true + + + + + + + + + + + + + + + Blue + Fonts/DroidSans.ttf,64 + false + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/BlueTeam.png + true + + + + + + + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Core/White.png + true + + + + PickTeam_ + 1 + + + + + + + + + + + Spectator + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + true + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + true + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + true + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + true + + + + + + + + + + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Core/White.png + true + + + + PickTeam + 2 + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + true + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + true + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + true + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + true + + + + + + + + + + + + + + + Blue + Fonts/DroidSans.ttf,64 + false + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/RedTeam.png + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + + + 3 + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + + + + + + + + 1 + + + + 4 + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + + + 2 + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + + + 1 + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + + + + + + + + 1 + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/White.png + true + + + + SwapToTeamPick + 1 + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + + + + + + + + + + + + + + Change Team + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/White.png + true + + + + SwapToClassPick + 1 + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + + + + + + + + + + + + + + Change Class + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + PickTeam + 1 + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Core/White.png + + + + PickClass + 1 + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + Blend + + + + + 1.6000000238418579 + Models/Characters/Assault/AssaultRedPose.mesh + false + + + + + + + + + + + + AssaultPoseF + + true + + + + + + + + + R_Arm_Weapon_Joint + + + Models/Weapons/Red/AssaultWeaponRed.mesh + + + + + + + + + + + + Models/Core/UnitSphere.mesh + false + + + 0.30000001192092896 + + + + + + + + + + + + + + + + + + + + + \1 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + Assault + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + 100 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Team Speed Boost + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + \1 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + \4 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + \7 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Dash + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Icons/Abilities/Square/Superman-01.png + + + + + + + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Icons/Shoe-01.png + + + + + + + + + + + + x2 Jump + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + + + PickTeam + 1 + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Core/White.png + + + + PickClass + 2 + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + Blend + + + + + 1.6000000238418579 + Models/Characters/Defender/DefenderRedPose.mesh + false + + + + + + + + + + + + DefenderPoseF + + true + + + + + + + + + R_Arm_Weapon_Joint + + + Models/Weapons/Red/DefenderWeaponRed.mesh + + + + + + + + + + + + Models/Core/UnitSphere.mesh + false + + + 0.30000001192092896 + + + + + + + + + + + + + + + + + + + + + \2 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + Defender + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + 150 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Team Shield Boost + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + \2 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + \5 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + \7 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Personal Shield + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Icons/Abilities/Square/SheildDots-01.png + + + + + + + + + + + + + + + + + + + + + PickTeam + 1 + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Core/White.png + + + + PickClass + 3 + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + Blend + + + + + 1.6000000238418579 + Models/Characters/Sniper/SniperRedPose.mesh + false + + + + + + + + + + + + SniperPoseF + + true + + + + + + + + + R_Arm_Weapon_Joint + + + Models/Weapons/Red/SecondaryWeaponRed.mesh + + + + + + + + + + + + Models/Core/UnitSphere.mesh + false + + + 0.30000001192092896 + + + + + + + + + + + + + + + + + + + + + \3 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + Sniper + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + 100 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Team Accuracy Boost + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + \3 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + \6 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + \7 + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Sprint + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Icons/Abilities/Square/Dash-01.png + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/Player.xml b/resources/Schema/Entities/Player.xml deleted file mode 100644 index 88f153ae..00000000 --- a/resources/Schema/Entities/Player.xml +++ /dev/null @@ -1,557 +0,0 @@ - - - - - - - - - - - - - - - - 1.6944730461160304 - - - - - - - - 5 - - - - - - - - - - - - - - - - - - - - - - - - - Models/Widgets/Camera.mesh - false - - - - - - - - - - - - - - - - - - - Textures/Weapons/Crosshair/SmallThickHoleDot.png - false - - - - - - - - - - - - - Schema/Entities/HitMarker.xml - - - - - - - - - - - - - - 1 - - - - - 100/100 - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - - - 1 - - - - Textures/HealthHUD3.png - - - - - - - - - - - - - - - - - - - - - - - - - - Textures/Core/UnitHexagon.png - - - - - - - - - - - - 2 - - - - - - Textures/Core/UnitHexagon_Rotated.png - - - - - - - - - - - - - - - - Textures/Core/UnitHexagon.png - - - - - - - - - - - - 3 - - - 0.80222018197612788 - - - - Textures/Core/UnitHexagon_Rotated.png - - - - - - - - - - - - - - - - Textures/Core/UnitHexagon.png - - - - - - - - - - - - 4 - - - - - - Textures/Core/UnitHexagon_Rotated.png - - - - - - - - - - - - - - - - Textures/Core/UnitHexagon.png - - - - - - - - - - - - 1 - - - - - - Textures/Core/UnitHexagon_Rotated.png - - - - - - - - - - - - - - - - Textures/Core/UnitHexagon.png - - - - - - - - - - - - - - - - Textures/Core/UnitHexagon_Rotated.png - - - - - - - - - - - - - - - - - - - - - - - - - - - - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - - - - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - - - - - - - Idle - 0.67172915251515519 - 1 - - - - - Models/Characters/Assault/FirstPerson.mesh - - - - - - - - - Schema/Entities/DefenderWeaponView.xml - - - - DefenderWeapon - - - - - - - - Schema/Entities/AssaultWeaponView.xml - - - - AssaultWeapon - - - - - - - - - - - - - Models/Widgets/Camera.mesh - false - - - - - - - - - - - - Idle - 1 - - - - - AimRifle - - - - - - Models/Characters/Assault/AssaultAnimations.mesh - - - - - - - - - Schema/Entities/DefenderWeaponWorld.xml - - - - DefenderWeapon - - - - - - - - - - - Schema/Entities/AssaultWeaponWorld.xml - - - - AssaultWeapon - - - - - - - - - - - - - Models/Core/UnitCube.mesh - - false - - - - - - - - - - - - Models/Core/UnitCube.mesh - - false - - - - - - - - - - - Insert name here - Fonts/DroidSans.ttf,100 - - - - - - - - - - - - - - Textures/Icons/Arrow.png - false - - - - - - 50 - true - - - - - - - - - - - - Schema/Entities/DefenderShield.xml - - - - - - - - - - diff --git a/resources/Schema/Entities/PlayerAssaultBlue.xml b/resources/Schema/Entities/PlayerAssaultBlue.xml new file mode 100644 index 00000000..19a8a717 --- /dev/null +++ b/resources/Schema/Entities/PlayerAssaultBlue.xml @@ -0,0 +1,1416 @@ + + + + + + + + + + + + + + + + + + + 10 + + + + + + + + 5 + + + + + + + + + + + + 0.10000000149011612 + 300 + + + + + + + + + + Models/Widgets/Camera.mesh + false + + + + + + + + + + + + Schema/Entities/PlayerHUD.xml + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Weapons/Crosshair/SmallThickHoleDot.png + + + + + + + + + + + + Schema/Entities/HitMarker.xml + + + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + + + 2 + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + + + 3 + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + + + + + + + + 1 + + + + 4 + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + + + 1 + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + + + + + + + + 1 + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + + + + + + + + + + + + + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + Models/Widgets/Arrows/ArrowBlue.mesh + + + + + + + + + + + + + + + + + + + + + 1 + + + + + 100/100 + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + 1 + + + + + Models/Core/UnitQuad.mesh + + Textures/HealthHUD3.png + + + + + + + + + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Icons/Boosts/Assault-01.png + + + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Icons/Boosts/Defender-01.png + + + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Icons/Boosts/Sniper-01.png + + + + + + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Icons/Abilities/Long/Superman-01.png + + + + + + + + + + + + + + + + + + + + + + + + + Schema/Entities/WeaponAssaultBlueView.xml + + + + AssaultWeapon + + + + + + + + Schema/Entities/WeaponSidearmAssaultBlueView.xml + + + + SidearmWeapon + + + + + + + + + + + + 0.10000000149011612 + 300 + + + Models/Widgets/Camera.mesh + false + + + + + + + + + + + + BlendTreeUpper + BlendTreeLower + + + + + 2.2000000476837158 + Models/Characters/Assault/AssaultBlue.mesh + + + + + + + + R_Arm_Weapon_Joint + + + Schema/Entities/WeaponAssaultBlueWorld.xml + + + + + + + AssaultWeapon + + + + + + + + + + + R_Arm_Weapon_Joint + + + Schema/Entities/SidearmWeaponBlueWorld.xml + + + + + + + SidearmWeapon + + + + + + + + + + + MovementBlend + JumpDashBlend + 2.5146881298480398e-63 + true + + + + + + + + StandMovement + CrouchMovement + 0 + true + + + + + + + + DirectionBlend + Idle + 1 + + + + + + + + Walk + StrafeLRBlend + 0 + + + + + + + + Left + Right + 0.033793529385008014 + + + + + + + + CrouchStrafeLeftF + + true + + + + + + + + + CrouchStrafeRightF + + true + + + + + + + + + + + CrouchWalkF + + true + + + + + + + + + + + CrouchF + + true + + + + + + + + + + + DirectionBlend + Idle + 1 + + + + + + + + RunWalkBlend + StrafeLRBlend + 2.4565650245976452e-16 + + + + + + + + Walk + Run + 1.2938206818383024e-24 + + + + + + + + WalkF + + true + + + + + + + + + RunF + + 2 + true + + + + + + + + + + + Left + Right + 0.033793529385008014 + + + + + + + + StrafeLeftF + + 2 + true + + + + + + + + + StrafeRightF + + 2 + true + + + + + + + + + + + + + IdleF + + true + + + + + + + + + + + + + Jump + DashBlend + 1 + true + + + + + + + + JumpF + + false + + + + + + + + + DashFBBlend + DashLRBlend + 0.014621149736541383 + + + + + + + + DashForward + DashBackward + 0.014363533804961248 + + + + + + + + DashForwardF + + 1.7999999523162842 + false + + + + + + + + + DashBackwardF + + 1.7999999523162842 + false + + + + + + + + + + + DashLeft + DashRight + 4.3244885367500671e-16 + + + + + + + + DashRightF + + 1.7999999523162842 + false + + + + + + + + + DashLeftF + + 1.7999999523162842 + false + + + + + + + + + + + + + + + + + AssaultWeapon + SidearmWeapon + 0 + true + + + + + + + + Aim + WeaponBlend + + + + + + + + IdleAssault + ActionBlend + + + + + + + + Fire + Reload + 1 + + + + + + + + ReloadSwitchU + 0.5 + false + + + + + + + + + ShootFastRifleU + false + + + + + + + + + + + IdleAssaultRifleU + + true + true + + + + + + + + + + + AimRifleA + + 0.10000000149011612 + false + true + + + + + + + + + + + Aim + WeaponBlend + + + + + + + + IdleSidearm + ActionBlend + + + + + + + + Reload + Fire + 1 + + + + + + + + ReloadSwitchU + false + + + + + + + + + ShootSecWepU + false + + + + + + + + + + + IdleSecWepU + true + + + + + + + + + + + AimSecWepA + + false + true + + + + + + + + + + + + + + + + + + L_Elbow + + + + + + + + + + + + 0.10000000149011612 + + + + + + + + + + + + 0.10000000149011612 + + + + + + + + + + + + + R_Elbow + + + + + + + + + + + + 0.10000000149011612 + + + + + + + + + + + + 0.10000000149011612 + + + + + + + + + + + + + Head + + + + + + + + + + + + 0.10000000149011612 + + + + + + + + + + + + 0.10000000149011612 + + + + + + + + + + + + + L_Leg_Top + + + + + 0.10000000149011612 + + + + + + + + + + + + R_Leg_Top + + + + + 0.10000000149011612 + + + + + + + + + + + + L_Leg_Bottomdw + + + + + + + + + + + + 0.10000000149011612 + + + + + + + + + + + + 0.10000000149011612 + + + + + + + + + + + + + R_Leg_Bottom + + + + + + + + + + + + 0.10000000149011612 + + + + + + + + + + + + 0.10000000149011612 + + + + + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + false + + + + + + + + + + + + Models/Core/UnitCube.mesh + + false + + + + + + + + + + + + Fonts/DroidSans.ttf,100 + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Icons/Arrow.png + + + + + 50 + true + + + + + + + + + + + + Schema/Entities/DefenderShield.xml + + + + + + + + + + diff --git a/resources/Schema/Entities/PlayerAssaultRed.xml b/resources/Schema/Entities/PlayerAssaultRed.xml new file mode 100644 index 00000000..6c25ce85 --- /dev/null +++ b/resources/Schema/Entities/PlayerAssaultRed.xml @@ -0,0 +1,1417 @@ + + + + + + + + + + + + + + + + + + + 10 + + + + + + + + 5 + + + + + + + + + + + + 0.10000000149011612 + 300 + + + + + + + + + + Models/Widgets/Camera.mesh + false + + + + + + + + + + + + Schema/Entities/PlayerHUD.xml + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Weapons/Crosshair/SmallThickHoleDot.png + + + + + + + + + + + + Schema/Entities/HitMarker.xml + + + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + + + 2 + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + + + 3 + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + + + + + + + + 1 + + + + 4 + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + + + 1 + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + + + + + + + + 1 + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + + + + + + + + + + + + + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + Models/Widgets/Arrows/ArrowBlue.mesh + false + + + + + + + + + + + + + + + + + + + + + 1 + + + + + 100/100 + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + 1 + + + + + Models/Core/UnitQuad.mesh + + Textures/HealthHUD3.png + + + + + + + + + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Icons/Boosts/Assault-01.png + + + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Icons/Boosts/Defender-01.png + + + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Icons/Boosts/Sniper-01.png + + + + + + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Icons/Abilities/Long/Superman-01.png + + + + + + + + + + + + + + + + + + + + + + + + + Schema/Entities/WeaponAssaultRedView.xml + + + + AssaultWeapon + + + + + + + + Schema/Entities/WeaponSidearmAssaultRedView.xml + + + + SidearmWeapon + + + + + + + + + + + + 0.10000000149011612 + 300 + + + Models/Widgets/Camera.mesh + false + + + + + + + + + + + + BlendTreeUpper + BlendTreeLower + + + + + 2.2000000476837158 + Models/Characters/Assault/AssaultRed.mesh + + + + + + + + R_Arm_Weapon_Joint + + + Schema/Entities/WeaponAssaultRedWorld.xml + + + + + + + AssaultWeapon + + + + + + + + + + + R_Arm_Weapon_Joint + + + Schema/Entities/SidearmWeaponRedWorld.xml + + + + + + + SidearmWeapon + + + + + + + + + + + MovementBlend + JumpDashBlend + 2.5146881298480398e-63 + true + + + + + + + + StandMovement + CrouchMovement + 0 + true + + + + + + + + DirectionBlend + Idle + 1 + + + + + + + + Walk + StrafeLRBlend + 0 + + + + + + + + Left + Right + 0.033793529385008014 + + + + + + + + CrouchStrafeLeftF + + true + + + + + + + + + CrouchStrafeRightF + + true + + + + + + + + + + + CrouchWalkF + + true + + + + + + + + + + + CrouchF + + true + + + + + + + + + + + DirectionBlend + Idle + 1 + + + + + + + + RunWalkBlend + StrafeLRBlend + 2.4565650245976452e-16 + + + + + + + + Walk + Run + 1.2938206818383024e-24 + + + + + + + + WalkF + + true + + + + + + + + + RunF + + 2 + true + + + + + + + + + + + Left + Right + 0.033793529385008014 + + + + + + + + StrafeLeftF + + 2 + true + + + + + + + + + StrafeRightF + + 2 + true + + + + + + + + + + + + + IdleF + + true + + + + + + + + + + + + + Jump + DashBlend + 1 + true + + + + + + + + JumpF + + false + + + + + + + + + DashFBBlend + DashLRBlend + 0.014621149736541383 + + + + + + + + DashForward + DashBackward + 0.014363533804961248 + + + + + + + + DashForwardF + + 1.7999999523162842 + false + + + + + + + + + DashBackwardF + + 1.7999999523162842 + false + + + + + + + + + + + DashLeft + DashRight + 4.3244885367500671e-16 + + + + + + + + DashLeftF + + 1.7999999523162842 + false + + + + + + + + + DashRightF + + 1.7999999523162842 + false + + + + + + + + + + + + + + + + + AssaultWeapon + SidearmWeapon + 0 + true + + + + + + + + Aim + WeaponBlend + + + + + + + + IdleAssault + ActionBlend + + + + + + + + Fire + Reload + 1 + + + + + + + + ReloadSwitchU + 0.5 + false + + + + + + + + + ShootFastRifleU + false + + + + + + + + + + + IdleAssaultRifleU + + true + true + + + + + + + + + + + AimRifleA + + 0.10000000149011612 + false + true + + + + + + + + + + + Aim + WeaponBlend + + + + + + + + IdleSidearm + ActionBlend + + + + + + + + Reload + Fire + 1 + + + + + + + + ReloadSwitchU + false + + + + + + + + + ShootSecWepU + false + + + + + + + + + + + IdleSecWepU + true + + + + + + + + + + + AimSecWepA + + false + true + + + + + + + + + + + + + + + + + + L_Elbow + + + + + + + + + + + + 0.10000000149011612 + + + + + + + + + + + + 0.10000000149011612 + + + + + + + + + + + + + R_Elbow + + + + + + + + + + + + 0.10000000149011612 + + + + + + + + + + + + 0.10000000149011612 + + + + + + + + + + + + + Head + + + + + + + + + + + + 0.10000000149011612 + + + + + + + + + + + + 0.10000000149011612 + + + + + + + + + + + + + L_Leg_Top + + + + + 0.10000000149011612 + + + + + + + + + + + + R_Leg_Top + + + + + 0.10000000149011612 + + + + + + + + + + + + L_Leg_Bottomdw + + + + + + + + + + + + 0.10000000149011612 + + + + + + + + + + + + 0.10000000149011612 + + + + + + + + + + + + + R_Leg_Bottom + + + + + + + + + + + + 0.10000000149011612 + + + + + + + + + + + + 0.10000000149011612 + + + + + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + false + + + + + + + + + + + + Models/Core/UnitCube.mesh + + false + + + + + + + + + + + + Fonts/DroidSans.ttf,100 + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Icons/Arrow.png + + + + + 50 + true + + + + + + + + + + + + Schema/Entities/DefenderShield.xml + + + + + + + + + + diff --git a/resources/Schema/Entities/PlayerDefenderBlue.xml b/resources/Schema/Entities/PlayerDefenderBlue.xml new file mode 100644 index 00000000..965fe839 --- /dev/null +++ b/resources/Schema/Entities/PlayerDefenderBlue.xml @@ -0,0 +1,1425 @@ + + + + + + + + + + + + + + + + 120 + 8 + 5 + + + 10 + + + 150 + 150 + + + + + + + + 5 + + + + + + + + + + + + 0.10000000149011612 + 300 + + + + + + + + + + Models/Widgets/Camera.mesh + false + + + + + + + + + + + + + + + + + Schema/Entities/WeaponDefenderBlueView.xml + + + + DefenderWeapon + + + + + + + + Schema/Entities/WeaponSidearmDefenderBlueView.xml + + + + SidearmWeapon + + + + + + + + + + Schema/Entities/PlayerHUD.xml + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Weapons/Crosshair/SmallThickHoleDot.png + + + + + + + + + + + + Schema/Entities/HitMarker.xml + + + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + + + 2 + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + + + 3 + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + + + + + + + + 1 + + + + 4 + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + + + 1 + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + + + + + + + + 1 + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + + + + + + + + + + + + + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + Models/Widgets/Arrows/ArrowBlue.mesh + + + + + + + + + + + + + + + + + + + + + 1 + + + + + 150/150 + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + 1 + + + + + Models/Core/UnitQuad.mesh + + Textures/HealthHUD3.png + + + + + + + + + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Icons/Boosts/Assault-01.png + + + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Icons/Boosts/Defender-01.png + + + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Icons/Boosts/Sniper-01.png + + + + + + + + + + + + + + + + + 1 + + + + false + Models/Core/UnitQuad.mesh + + Textures/Icons/Abilities/Long/SheildDots-01.png + + + + + + + + + + + + + + + + + + + + + + 0.10000000149011612 + 300 + + + Models/Widgets/Camera.mesh + false + + + + + + + + + + + + BlendTreeUpper + BlendTreeLower + + + + + 2.2000000476837158 + Models/Characters/Defender/DefenderBlue.mesh + + + + + + + + R_Arm_Weapon_Joint + + + Schema/Entities/WeaponDefenderBlueWorld.xml + + + + + + + DefenderWeapon + + + + + + + + + + + R_Arm_Weapon_Joint + + + Schema/Entities/SidearmWeaponBlueWorld.xml + + + + + + + SidearmWeapon + + + + + + + + + + + MovementBlend + Jump + 0 + true + + + + + + + + StandMovement + CrouchMovement + 0 + true + + + + + + + + DirectionBlend + Idle + 1 + + + + + + + + Walk + StrafeLRBlend + 0 + + + + + + + + Left + Right + 0.033793529385008014 + + + + + + + + CrouchStrafeLeftF + + true + + + + + + + + + CrouchStrafeRightF + + true + + + + + + + + + + + CrouchWalkF + + true + + + + + + + + + + + CrouchF + + true + + + + + + + + + + + DirectionBlend + Idle + 1 + + + + + + + + RunWalkBlend + StrafeLRBlend + 2.4565650245976452e-16 + + + + + + + + Walk + Run + 1.2938206818383024e-24 + + + + + + + + WalkF + + true + + + + + + + + + RunF + + 2 + true + + + + + + + + + + + Left + Right + 0.033793529385008014 + + + + + + + + StrafeLeftF + + 2 + true + + + + + + + + + StrafeRightF + + 2 + true + + + + + + + + + + + + + IdleF + + true + + + + + + + + + + + + + JumpF + + false + + + + + + + + + + + DefenderWeapon + SidearmWeapon + 1 + true + + + + + + + + Aim + WeaponBlend + + + + + + + + IdleDefender + FinalBlend + + + + + + + + ShieldBlend + ActionBlend + 1 + + + + + + + + ActivateShield + SheildFront + 1 + + + + + + + + ActivateShieldU + + 2 + false + + + + + + + + + ShieldFrontU + + true + + + + + + + + + + + Fire + Reload + 0 + + + + + + + + ShootgunReloadU + + 0.5 + + + + + + + + + ShootRifleU + + false + + + + + + + + + + + + + IdleAssaultRifleU + + true + true + + + + + + + + + + + AimRifleA + + true + + + + + + + + + + + Aim + WeaponBlend + + + + + + + + IdleSidearm + ActionBlend + + + + + + + + Reload + Fire + + + + + + + + ReloadSwitchU + false + + + + + + + + + ShootSecWepU + false + + + + + + + + + + + IdleSecWepU + true + + + + + + + + + + + AimSecWepA + + 0.10000000149011612 + false + true + + + + + + + + + + + + + + + + + + Head + + + + + + + + + + + + 0.5 + 0.20000000298023224 + + + + + + + + + + + + 0.5 + 0.20000000298023224 + + + + + + + + + + + + 0.20000000298023224 + + + + + + + + + + + + + L_Shoulder_Armor_Joint + + + + + + + + + + + + 0.20000000298023224 + + + + + + + + + + + + + R_Shoulder_Armor_Joint + + + + + + + + + + + + 0.20000000298023224 + + + + + + + + + + + + + L_Elbow + + + + + + + + + + + + 0.20000000298023224 + + + + + + + + + + + + 0.20000000298023224 + + + + + + + + + + + + + R_Elbow + + + + + + + + + + + + 0.20000000298023224 + + + + + + + + + + + + 0.20000000298023224 + + + + + + + + + + + + + Spine_3 + + + + + + + + + + + + 0.20000000298023224 + + + + + + + + + + + + + L_Leg_Bottom + + + + + + + + + + + + 0.10000000149011612 + + + + + + + + + + + + 0.10000000149011612 + + + + + + + + + + + + + R_Leg_Bottom + + + + + + + + + + + + 0.10000000149011612 + + + + + + + + + + + + 0.10000000149011612 + + + + + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + false + + + + + + + + + + + + Models/Core/UnitCube.mesh + + false + + + + + + + + + + + + Fonts/DroidSans.ttf,100 + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Icons/Arrow.png + + + + + 50 + true + + + + + + + + + + + + Schema/Entities/DefenderShield.xml + + + + + + + + diff --git a/resources/Schema/Entities/PlayerDefenderRed.xml b/resources/Schema/Entities/PlayerDefenderRed.xml new file mode 100644 index 00000000..3dbb9289 --- /dev/null +++ b/resources/Schema/Entities/PlayerDefenderRed.xml @@ -0,0 +1,1426 @@ + + + + + + + + + + + + + + + + 120 + 8 + 5 + + + 10 + + + 150 + 150 + + + + + + + + 5 + + + + + + + + + + + + 0.10000000149011612 + 300 + + + + + + + + + + Models/Widgets/Camera.mesh + false + + + + + + + + + + + + + + + + + Schema/Entities/WeaponDefenderRedView.xml + + + + DefenderWeapon + + + + + + + + Schema/Entities/WeaponSidearmDefenderRedView.xml + + + + SidearmWeapon + + + + + + + + + + Schema/Entities/PlayerHUD.xml + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Weapons/Crosshair/SmallThickHoleDot.png + + + + + + + + + + + + Schema/Entities/HitMarker.xml + + + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + + + 2 + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + + + 3 + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + + + + + + + + 1 + + + + 4 + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + + + 1 + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + + + + + + + + 1 + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + + + + + + + + + + + + + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + Models/Widgets/Arrows/ArrowBlue.mesh + false + + + + + + + + + + + + + + + + + + + + + 1 + + + + + 150/150 + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + 1 + + + + + Models/Core/UnitQuad.mesh + + Textures/HealthHUD3.png + + + + + + + + + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Icons/Boosts/Assault-01.png + + + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Icons/Boosts/Defender-01.png + + + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Icons/Boosts/Sniper-01.png + + + + + + + + + + + + + + + + + 1 + + + + false + Models/Core/UnitQuad.mesh + + Textures/Icons/Abilities/Long/SheildDots-01.png + + + + + + + + + + + + + + + + + + + + + + 0.10000000149011612 + 300 + + + Models/Widgets/Camera.mesh + false + + + + + + + + + + + + BlendTreeUpper + BlendTreeLower + + + + + 2.2000000476837158 + Models/Characters/Defender/DefenderRed.mesh + + + + + + + + R_Arm_Weapon_Joint + + + Schema/Entities/WeaponDefenderRedWorld.xml + + + + + + + DefenderWeapon + + + + + + + + + + + R_Arm_Weapon_Joint + + + Schema/Entities/SidearmWeaponRedWorld.xml + + + + + + + SidearmWeapon + + + + + + + + + + + MovementBlend + Jump + 0 + true + + + + + + + + StandMovement + CrouchMovement + 0 + true + + + + + + + + DirectionBlend + Idle + 1 + + + + + + + + Walk + StrafeLRBlend + 0 + + + + + + + + Left + Right + 0.033793529385008014 + + + + + + + + CrouchStrafeLeftF + + true + + + + + + + + + CrouchStrafeRightF + + true + + + + + + + + + + + CrouchWalkF + + true + + + + + + + + + + + CrouchF + + true + + + + + + + + + + + DirectionBlend + Idle + 1 + + + + + + + + RunWalkBlend + StrafeLRBlend + 2.4565650245976452e-16 + + + + + + + + Walk + Run + 1.2938206818383024e-24 + + + + + + + + WalkF + + true + + + + + + + + + RunF + + 2 + true + + + + + + + + + + + Left + Right + 0.033793529385008014 + + + + + + + + StrafeLeftF + + 2 + true + + + + + + + + + StrafeRightF + + 2 + true + + + + + + + + + + + + + IdleF + + true + + + + + + + + + + + + + JumpF + + false + + + + + + + + + + + DefenderWeapon + SidearmWeapon + 1 + true + + + + + + + + Aim + WeaponBlend + + + + + + + + IdleDefender + FinalBlend + + + + + + + + ShieldBlend + ActionBlend + 1 + + + + + + + + ActivateShield + SheildFront + 1 + + + + + + + + ActivateShieldU + + 2 + false + + + + + + + + + ShieldFrontU + + true + + + + + + + + + + + Fire + Reload + 0 + + + + + + + + ShootgunReloadU + + 0.5 + + + + + + + + + ShootRifleU + + false + + + + + + + + + + + + + IdleAssaultRifleU + + true + true + + + + + + + + + + + AimRifleA + + true + + + + + + + + + + + Aim + WeaponBlend + + + + + + + + IdleSidearm + ActionBlend + + + + + + + + Reload + Fire + + + + + + + + ReloadSwitchU + false + + + + + + + + + ShootSecWepU + false + + + + + + + + + + + IdleSecWepU + true + + + + + + + + + + + AimSecWepA + + 0.10000000149011612 + false + true + + + + + + + + + + + + + + + + + + Head + + + + + + + + + + + + 0.5 + 0.20000000298023224 + + + + + + + + + + + + 0.5 + 0.20000000298023224 + + + + + + + + + + + + 0.20000000298023224 + + + + + + + + + + + + + L_Shoulder_Armor_Joint + + + + + + + + + + + + 0.20000000298023224 + + + + + + + + + + + + + R_Shoulder_Armor_Joint + + + + + + + + + + + + 0.20000000298023224 + + + + + + + + + + + + + L_Elbow + + + + + + + + + + + + 0.20000000298023224 + + + + + + + + + + + + 0.20000000298023224 + + + + + + + + + + + + + R_Elbow + + + + + + + + + + + + 0.20000000298023224 + + + + + + + + + + + + 0.20000000298023224 + + + + + + + + + + + + + Spine_3 + + + + + + + + + + + + 0.20000000298023224 + + + + + + + + + + + + + L_Leg_Bottom + + + + + + + + + + + + 0.10000000149011612 + + + + + + + + + + + + 0.10000000149011612 + + + + + + + + + + + + + R_Leg_Bottom + + + + + + + + + + + + 0.10000000149011612 + + + + + + + + + + + + 0.10000000149011612 + + + + + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + false + + + + + + + + + + + + Models/Core/UnitCube.mesh + + false + + + + + + + + + + + + Fonts/DroidSans.ttf,100 + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Icons/Arrow.png + + + + + 50 + true + + + + + + + + + + + + Schema/Entities/DefenderShield.xml + + + + + + + + diff --git a/resources/Schema/Entities/PlayerHUD.xml b/resources/Schema/Entities/PlayerHUD.xml new file mode 100644 index 00000000..48123411 --- /dev/null +++ b/resources/Schema/Entities/PlayerHUD.xml @@ -0,0 +1,450 @@ + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Weapons/Crosshair/SmallThickHoleDot.png + + + + + + + + + + + + Schema/Entities/HitMarker.xml + + + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + + + 3 + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + + + + + + + + 1 + + + + 4 + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + + + 2 + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + + + 1 + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + + + + + + + + 1 + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + + + + + + + + + + + + + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + Fonts/Hind-Edited.otf,64 + + + + + + + + + + + + + + + + + + + + + + Models/Widgets/Arrows/ArrowBlue.mesh + + + + + + + + + + + + + + + + + + + + + 1 + + + + + 100/100 + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + 1 + + + + + Models/Core/UnitQuad.mesh + + Textures/HealthHUD3.png + + + + + + + + + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Icons/Boosts/Assault-01.png + + + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Icons/Boosts/Defender-01.png + + + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Icons/Boosts/Sniper-01.png + + + + + + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Test/aM4ME4GR.png + + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/PlayerModel.xml b/resources/Schema/Entities/PlayerModel.xml new file mode 100644 index 00000000..a26fbc08 --- /dev/null +++ b/resources/Schema/Entities/PlayerModel.xml @@ -0,0 +1,542 @@ + + + + + + BlendTreeAim + BlendTreeAssault + + + + + Models/Characters/Assault/AssaultBlue.mesh + + false + + + + + + + + + R_Arm_Weapon_Joint + + + AssaultWeapon + + + + + + Schema/Entities/WeaponAssaultBlueWorld.xml + + + + + + + + + + + + R_Arm_Weapon_Joint + + + SidearmWeapon + + + + + + Schema/Entities/SidearmWeaponWorld.xml + + + + + + + + + + + + AimPrimary + AimSecondary + 0 + true + + + + + + + + AimSecWepA + + false + true + + + + + + + + + AimRifleA + + false + true + + + + + + + + + + + ReloadSwitchBlend + FinalMovementBlend + + + + + + + + StandCrouchBlend + JumpDashBlend + 2.5146881298480398e-63 + true + + + + + + + + StandMovement + CrouchMovement + 0 + true + + + + + + + + MovementBlend + Idle + 1 + + + + + + + + Walk + StrafeLRBlend + 0 + + + + + + + + Left + Right + 0.033793529385008014 + + + + + + + + CrouchStrafeLeftF + + 1 + true + + + + + + + + + CrouchStrafeRightF + + 1 + true + + + + + + + + + + + CrouchWalkF + + 1 + true + + + + + + + + + + + CrouchF + + 1 + + + + + + + + + + + MovementBlend + Idle + 1 + + + + + + + + RunWalkBlend + StrafeLRBlend + 2.4565650245976452e-16 + + + + + + + + Walk + Run + 1.2938206818383024e-24 + + + + + + + + WalkF + + 1 + true + + + + + + + + + RunF + + 1 + true + + + + + + + + + + + Left + Right + 0.033793529385008014 + + + + + + + + StrafeLeftF + + 1 + true + + + + + + + + + StrafeRightF + + 1 + true + + + + + + + + + + + + + IdleF + + 1 + true + + + + + + + + + + + + + Jump + DashBlend + 1 + true + + + + + + + + JumpF + + 1 + false + + + + + + + + + DashFBBlend + DashLRBlend + 0.014621149736541383 + + + + + + + + DashForward + DashBackward + 0.014363533804961248 + + + + + + + + DashForwardF + + 2 + false + + + + + + + + + DashBackwardF + + 2 + false + + + + + + + + + + + DashLeft + DashRight + 4.3244885367500671e-16 + + + + + + + + DashLeftF + + 2 + false + + + + + + + + + DashRightF + + 2 + false + + + + + + + + + + + + + + + + + ReloadSwitch + WeaponActionBlend + 1 + true + + + + + + + + ReloadSwitchU + + 1 + + + + + + + + + IdleBlend + ShootBlend + 0 + + + + + + + + IdlePrimary + IdleSecondary + 0 + + + + + + + + IdleAssaultRifleU + + 1 + true + + + + + + + + + IdleSecWepU + + 1 + true + + + + + + + + + + + ShootPrimary + ShootSecondary + 0 + + + + + + + + ShootFastRifleU + + 1 + + + + + + + + + ShootSecWepFastU + + + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/PlayerRed.xml b/resources/Schema/Entities/PlayerRed.xml index 3cf17558..9fa7be05 100644 --- a/resources/Schema/Entities/PlayerRed.xml +++ b/resources/Schema/Entities/PlayerRed.xml @@ -2,6 +2,7 @@ + @@ -13,7 +14,7 @@ - 1.6944730461160304 + 22.22055262342397 @@ -37,7 +38,10 @@ - + + 0.10000000149011612 + 300 + @@ -372,7 +376,7 @@ Idle - 0.67172915251515519 + 1.1978087298230946 1 @@ -386,25 +390,25 @@ + + DefenderWeapon + Schema/Entities/DefenderWeaponViewRed.xml - - DefenderWeapon - + + AssaultWeapon + Schema/Entities/AssaultWeaponView.xml - - AssaultWeapon - @@ -414,7 +418,10 @@ - + + 0.10000000149011612 + 300 + Models/Widgets/Camera.mesh false @@ -430,6 +437,7 @@ Idle + 0.69274608502888668 1 @@ -449,31 +457,31 @@ - - Schema/Entities/DefenderWeaponWorldRed.xml - - DefenderWeapon + + Schema/Entities/DefenderWeaponWorldRed.xml + + - - Schema/Entities/AssaultWeaponWorld.xml - - AssaultWeapon + + Schema/Entities/AssaultWeaponWorld.xml + + diff --git a/resources/Schema/Entities/QualityAssurance.xml b/resources/Schema/Entities/QualityAssurance.xml index 0aa2fbe7..cd89d64a 100644 --- a/resources/Schema/Entities/QualityAssurance.xml +++ b/resources/Schema/Entities/QualityAssurance.xml @@ -2,12 +2,122 @@ + + 6.5024371606521605 + + + + + + + + + + + + + + + + + + + + + + + + + Models/Characters/Assault/AssaultAnimated.mesh + + + + + + + + + + + + + + Models/Characters/Assault/AssaultAnimated.mesh + + + + + + + + + Animation test + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + Models/Core/UnitCylinder.mesh + + + + + + + + + + + 0.5 + + + + + + + + + + + + + + Models/Characters/Assault/AssaultAnimated.mesh + + + + + + + + + + + + + + + + + + + + + + @@ -40,7 +150,7 @@ - + @@ -81,115 +191,23 @@ + + 1 + + 0.80000001192092896 Models/Widgets/Lights/DirectionalLightWidget.mesh - - 1 - - - + - - - - - - - - - - - - - Models/Characters/Assault/AssaultAnimated.mesh - - - - - - - - - - - - Models/Characters/Assault/AssaultAnimated.mesh - - - - - - - - - Animation test - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - Models/Core/UnitCylinder.mesh - - - - - - - - - - - - - - - - - - - - 0.5 - - - - - - - - - - - - Models/Characters/Assault/AssaultAnimated.mesh - - - - - - - - - - - - - @@ -213,7 +231,7 @@ - + @@ -277,7 +295,7 @@ - + @@ -309,7 +327,7 @@ - + @@ -380,15 +398,15 @@ - - - Schema/Entities/Player.xml - + + + Schema/Entities/Player.xml + @@ -450,15 +468,15 @@ - - - Schema/Entities/Player.xml - + + + Schema/Entities/Player.xml + @@ -544,8 +562,8 @@ - Models/Core/UnitCube.mesh - + Models/BushAlive.mesh + true @@ -604,8 +622,8 @@ - + @@ -632,6 +650,52 @@ + + + + Models/Core/UnitCylinder.mesh + + + + + + + + + + + + + + + + + + + + 0.5 + + + + + + + + + + + Models/Test/AssaultTPoseSoftEdge.mesh + + + + + + + + + + + @@ -659,7 +723,7 @@ - + @@ -706,7 +770,7 @@ - + @@ -766,7 +830,7 @@ - + @@ -786,52 +850,6 @@ - - - - Models/Core/UnitCylinder.mesh - - - - - - - - - - - - - - - - - - - - 0.5 - - - - - - - - - - - Models/Test/AssaultTPoseSoftEdge.mesh - - - - - - - - - - - @@ -859,7 +877,7 @@ - + @@ -906,7 +924,7 @@ - + @@ -953,7 +971,7 @@ - + @@ -1008,21 +1026,21 @@ + 15 - 15 - - Models/Core/UnitCube.mesh - - true - + + Models/Core/UnitCube.mesh + + true + @@ -1039,8 +1057,8 @@ - + @@ -1063,12 +1081,12 @@ 1 + Models/Core/UnitCube.mesh true - @@ -1085,8 +1103,8 @@ - + @@ -1107,12 +1125,12 @@ 2 + Models/Core/UnitCube.mesh true - @@ -1129,8 +1147,8 @@ - + @@ -1153,12 +1171,12 @@ 3 + Models/Core/UnitCube.mesh true - @@ -1175,8 +1193,8 @@ - + @@ -1197,22 +1215,22 @@ + -15 - -15 4 - - Models/Core/UnitCube.mesh - - true - + + Models/Core/UnitCube.mesh + + true + @@ -1229,8 +1247,8 @@ - + @@ -1270,8 +1288,8 @@ - + @@ -1367,19 +1385,19 @@ - + - true - 0.8256214817261025 + 1.3579803859829696 3.7999999523162842 true + true Models/Weapons/Blue/AssaultWeaponBlue.mesh @@ -1423,7 +1441,7 @@ - + @@ -1432,7 +1450,7 @@ - 1.8641349174045843 + 0.79164215554514783 Models/Characters/Assault/AssaultTPose.mesh @@ -1475,20 +1493,22 @@ - + - + + + - true - 1.8641349174045843 + 0.79164215554514783 true + true Models/Characters/Assault/AssaultAnimated.mesh @@ -1531,21 +1551,21 @@ - + - true - 1.2301962937648341 + 7.7876951610054306 10 3 true + true Models/Core/UnitSphere.mesh @@ -1589,20 +1609,20 @@ - + - true - 3.4214855659573402 - true + 2.6357521906414902 5 true + true + true Models/Assault.mesh @@ -1636,8 +1656,8 @@ - + @@ -1682,6 +1702,11 @@ + + + + + @@ -1690,12 +1715,8 @@ 5 + - - - - - @@ -1712,13 +1733,14 @@ + Fonts/DroidSans.ttf,100 - + @@ -1756,8 +1778,8 @@ - + @@ -1769,8 +1791,8 @@ - + @@ -1778,12 +1800,12 @@ - true - 0.8256214817261025 + 1.3579803859829696 3.7999999523162842 true + true Models/AssaultWeaponRed.mesh @@ -1823,7 +1845,9 @@ - + + + @@ -1890,8 +1914,8 @@ - + @@ -1924,6 +1948,8 @@ + Models/Core/UnitQuad.mesh + Textures/Props/FoliageDiff.png @@ -1933,6 +1959,8 @@ + Models/Core/UnitQuad.mesh + Textures/Props/FoliageDiff.png @@ -1953,6 +1981,8 @@ + Models/Core/UnitQuad.mesh + Textures/Core/UnitHexagon.png @@ -1963,19 +1993,21 @@ - - 2 - + + 2 + + Models/Core/UnitQuad.mesh + Textures/Core/UnitHexagon_Rotated.png - + @@ -1985,6 +2017,8 @@ + Models/Core/UnitQuad.mesh + Textures/Core/UnitHexagon.png @@ -1995,19 +2029,21 @@ - - 3 - + + 3 + + Models/Core/UnitQuad.mesh + Textures/Core/UnitHexagon_Rotated.png - + @@ -2017,6 +2053,8 @@ + Models/Core/UnitQuad.mesh + Textures/Core/UnitHexagon.png @@ -2027,20 +2065,22 @@ - - 4 - 1 + + 4 + + Models/Core/UnitQuad.mesh + Textures/Core/UnitHexagon_Rotated.png - + @@ -2050,6 +2090,8 @@ + Models/Core/UnitQuad.mesh + Textures/Core/UnitHexagon.png @@ -2060,19 +2102,21 @@ - - 1 - + + 1 + + Models/Core/UnitQuad.mesh + Textures/Core/UnitHexagon_Rotated.png - + @@ -2082,6 +2126,8 @@ + Models/Core/UnitQuad.mesh + Textures/Core/UnitHexagon.png @@ -2092,18 +2138,20 @@ - 1 + + Models/Core/UnitQuad.mesh + Textures/Core/UnitHexagon_Rotated.png - + @@ -2129,14 +2177,24 @@ - + + + + + + + + + + + - + @@ -2166,6 +2224,8 @@ + Models/Core/UnitQuad.mesh + Textures/Core/ErrorTexture.png @@ -2177,6 +2237,8 @@ + Models/Core/UnitQuad.mesh + Textures/Core/White.png @@ -2205,6 +2267,8 @@ + Models/Core/UnitQuad.mesh + Textures/Core/White.png @@ -2233,6 +2297,8 @@ + Models/Core/UnitQuad.mesh + Textures/Core/White.png @@ -2261,6 +2327,8 @@ + Models/Core/UnitQuad.mesh + Textures/Core/White.png @@ -2289,6 +2357,8 @@ + Models/Core/UnitQuad.mesh + Textures/Core/White.png @@ -2330,7 +2400,11 @@ + Models/Core/UnitQuad.mesh + Textures/Core/ErrorTexture.png + true + @@ -2341,7 +2415,10 @@ + Models/Core/UnitQuad.mesh + Textures/Core/White.png + false @@ -2355,6 +2432,7 @@ 1920x1080 Fonts/DroidSans.ttf,64 + false @@ -2369,7 +2447,10 @@ + Models/Core/UnitQuad.mesh + Textures/Core/White.png + false @@ -2383,6 +2464,7 @@ 1280x720 Fonts/DroidSans.ttf,64 + false @@ -2397,6 +2479,8 @@ + Models/Core/UnitQuad.mesh + Textures/Core/White.png @@ -2425,6 +2509,8 @@ + Models/Core/UnitQuad.mesh + Textures/Core/White.png @@ -2482,6 +2568,36 @@ + + + + + + + + + + + + + + + + + 2 + + + Models/Weapons/Blue/AssaultWeaponBlue.mesh + + + + + + + + + + diff --git a/resources/Schema/Entities/RayAssaultBlue.xml b/resources/Schema/Entities/RayAssaultBlue.xml new file mode 100644 index 00000000..b474ff2c --- /dev/null +++ b/resources/Schema/Entities/RayAssaultBlue.xml @@ -0,0 +1,47 @@ + + + + + + 0.079999998211860657 + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Effects/NewRay5.png + + true + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Effects/NewRay5.png + + true + + + + + + + + + + + diff --git a/resources/Schema/Entities/RayAssaultRed.xml b/resources/Schema/Entities/RayAssaultRed.xml new file mode 100644 index 00000000..e215f9ef --- /dev/null +++ b/resources/Schema/Entities/RayAssaultRed.xml @@ -0,0 +1,47 @@ + + + + + + 0.079999998211860657 + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Effects/NewRay5.png + + true + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Effects/NewRay5.png + + true + + + + + + + + + + + diff --git a/resources/Schema/Entities/RayBlue.xml b/resources/Schema/Entities/RayBlue.xml index 022d7769..c358a4d5 100644 --- a/resources/Schema/Entities/RayBlue.xml +++ b/resources/Schema/Entities/RayBlue.xml @@ -1,20 +1,50 @@ - + - 0.25 + 0.079999998211860657 - - Models/Effects/CylinderShot.mesh - - true - - - - + - + + + + + Models/Core/UnitQuad.mesh + + Textures/Effects/NewRay5.png + + true + true + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Effects/NewRay5.png + + true + true + + + + + + + + + + diff --git a/resources/Schema/Entities/RayDefenderBlue.xml b/resources/Schema/Entities/RayDefenderBlue.xml new file mode 100644 index 00000000..56a416ce --- /dev/null +++ b/resources/Schema/Entities/RayDefenderBlue.xml @@ -0,0 +1,47 @@ + + + + + + 0.079999998211860657 + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Effects/NewRay7.png + + true + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Effects/NewRay7.png + + true + + + + + + + + + + + diff --git a/resources/Schema/Entities/RayDefenderRed.xml b/resources/Schema/Entities/RayDefenderRed.xml new file mode 100644 index 00000000..5ab225e2 --- /dev/null +++ b/resources/Schema/Entities/RayDefenderRed.xml @@ -0,0 +1,47 @@ + + + + + + 0.079999998211860657 + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Effects/NewRay7.png + + true + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Effects/NewRay7.png + + true + + + + + + + + + + + diff --git a/resources/Schema/Entities/RayRed b/resources/Schema/Entities/RayRed deleted file mode 100644 index d34e185e..00000000 --- a/resources/Schema/Entities/RayRed +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - Models/Core/UnitCylinder.mesh - - - - - - - - - - - diff --git a/resources/Schema/Entities/RayRed.xml b/resources/Schema/Entities/RayRed.xml index 0a20f148..70ab685e 100644 --- a/resources/Schema/Entities/RayRed.xml +++ b/resources/Schema/Entities/RayRed.xml @@ -1,20 +1,46 @@ - + - 0.25 + 0.10000000149011612 - - Models/Effects/CylinderShot.mesh - - true - - + - + + + + + Textures/Effects/Ray.png + + + + + + + + + + + + + + + Textures/Effects/Ray.png + + + + + + + + + + + + diff --git a/resources/Schema/Entities/RaySideArmBlue.xml b/resources/Schema/Entities/RaySideArmBlue.xml new file mode 100644 index 00000000..f48a8fc3 --- /dev/null +++ b/resources/Schema/Entities/RaySideArmBlue.xml @@ -0,0 +1,50 @@ + + + + + + 0.080000000000000002 + + + 0.080000000000000002 + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Effects/NewRay5.png + + true + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Effects/NewRay5.png + + true + + + + + + + + + + + diff --git a/resources/Schema/Entities/RaySideArmRed.xml b/resources/Schema/Entities/RaySideArmRed.xml new file mode 100644 index 00000000..197d56ba --- /dev/null +++ b/resources/Schema/Entities/RaySideArmRed.xml @@ -0,0 +1,50 @@ + + + + + + 0.080000000000000002 + + + 0.080000000000000002 + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Effects/NewRay5.png + + true + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Effects/NewRay5.png + + true + + + + + + + + + + + diff --git a/resources/Schema/Entities/RedSideModels.xml b/resources/Schema/Entities/RedSideModels.xml new file mode 100644 index 00000000..afa478ec --- /dev/null +++ b/resources/Schema/Entities/RedSideModels.xml @@ -0,0 +1,1522 @@ + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + Models/Props/PickUps/HealthPickUp.mesh + + + 8 + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + Models/Props/PickUps/HealthPickUp.mesh + + + 8 + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + 8 + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + 8 + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + Models/Props/PickUps/HealthPickUp.mesh + + + 8 + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + Models/Props/PickUps/HealthPickUp.mesh + + + 8 + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + 8 + + + + + + + + + + + + + + + + + + + + + + + + + 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/SciFiHolder1.mesh + + + + + + + + + + + + + Models/Props/SciFiHolder1.mesh + + + + + + + + + + + + + + + + + + + + Models/Props/Flora/SpecialRoot.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 + + + + + + + + + + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar1Red.mesh + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + diff --git a/resources/Schema/Entities/ReloadEffectView.xml b/resources/Schema/Entities/ReloadEffectView.xml index ca7e6e1a..8aa6b8ec 100644 --- a/resources/Schema/Entities/ReloadEffectView.xml +++ b/resources/Schema/Entities/ReloadEffectView.xml @@ -1,20 +1,20 @@ - + - 2 + 1 - true - - - true - + + + 1 + true Models/Weapons/Blue/AssaultWeaponBlue.mesh + true diff --git a/resources/Schema/Entities/ReloadEffectViewRed.xml b/resources/Schema/Entities/ReloadEffectViewRed.xml index 56b9d140..731dff09 100644 --- a/resources/Schema/Entities/ReloadEffectViewRed.xml +++ b/resources/Schema/Entities/ReloadEffectViewRed.xml @@ -1,20 +1,20 @@ - + - 2 + 1 - true - - - true - + + + 1 + true Models/Weapons/Red/AssaultWeaponRed.mesh + true diff --git a/resources/Schema/Entities/ReloadEffectWorld.xml b/resources/Schema/Entities/ReloadEffectWorld.xml index ae6d3a3e..a5ffb087 100644 --- a/resources/Schema/Entities/ReloadEffectWorld.xml +++ b/resources/Schema/Entities/ReloadEffectWorld.xml @@ -6,12 +6,14 @@ 2 - true - - - true - + + + + 1.3399996757507324 true + true + true + 5.0899982452392578 Models/Weapons/Blue/AssaultWeaponBlue.mesh diff --git a/resources/Schema/Entities/ReloadEffectWorldRed.xml b/resources/Schema/Entities/ReloadEffectWorldRed.xml index 55c37389..94739beb 100644 --- a/resources/Schema/Entities/ReloadEffectWorldRed.xml +++ b/resources/Schema/Entities/ReloadEffectWorldRed.xml @@ -6,12 +6,14 @@ 2 - true - - - true - + + + + 1.3399996757507324 true + true + true + 5.0899982452392578 Models/Weapons/Red/AssaultWeaponRed.mesh 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..cdebfc55 --- /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/ScoreBoard.xml b/resources/Schema/Entities/ScoreBoard.xml new file mode 100644 index 00000000..b3798e72 --- /dev/null +++ b/resources/Schema/Entities/ScoreBoard.xml @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/ScoreBoard_Blue.xml b/resources/Schema/Entities/ScoreBoard_Blue.xml new file mode 100644 index 00000000..6b1a7bdd --- /dev/null +++ b/resources/Schema/Entities/ScoreBoard_Blue.xml @@ -0,0 +1,121 @@ + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/ScoreBoard_Main.xml b/resources/Schema/Entities/ScoreBoard_Main.xml new file mode 100644 index 00000000..38db3e4b --- /dev/null +++ b/resources/Schema/Entities/ScoreBoard_Main.xml @@ -0,0 +1,405 @@ + + + + + + + + + + + + + + + Schema/Entities/ScoreBoard_Red.xml + + + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + + + 0.80000019073486328 + Models/Props/ScoreBoard/Scoreboard.mesh + false + + + + + + + + + + + 0.70000028610229492 + Models/Props/ScoreBoard/Spectatorboard.mesh + false + + + + + + + + + + + + Schema/Entities/ScoreBoard_Blue.xml + + + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + 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/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 + + + + + + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/ScoreBoard_Red.xml b/resources/Schema/Entities/ScoreBoard_Red.xml new file mode 100644 index 00000000..7c69656b --- /dev/null +++ b/resources/Schema/Entities/ScoreBoard_Red.xml @@ -0,0 +1,121 @@ + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/ScoreIdentity.xml b/resources/Schema/Entities/ScoreIdentity.xml new file mode 100644 index 00000000..2d1b471a --- /dev/null +++ b/resources/Schema/Entities/ScoreIdentity.xml @@ -0,0 +1,119 @@ + + + + + + + + + + + + + + + -1 + Fonts/DroidSans.ttf,64 + + + + + + ScoreIdentity + ScoreIdentity + ID + + + + + + + + + + + + + Fonts/DroidSans.ttf,64 + + + + + + ScoreIdentity + ScoreIdentity + Name + + + + + + + + + + + + 0.0 + Fonts/DroidSans.ttf,64 + + + + + + ScoreIdentity + ScoreIdentity + KD + + + + + + + + + + + + 0 + Fonts/DroidSans.ttf,64 + + + + + + ScoreIdentity + ScoreIdentity + Kills + + + + + + + + + + + + 0 + Fonts/DroidSans.ttf,64 + + + + + + ScoreIdentity + ScoreIdentity + Deaths + + + + + + + + + + + diff --git a/resources/Schema/Entities/ServerIdentity.xml b/resources/Schema/Entities/ServerIdentity.xml new file mode 100644 index 00000000..1a24fb8a --- /dev/null +++ b/resources/Schema/Entities/ServerIdentity.xml @@ -0,0 +1,188 @@ + + + + + + + + + + + + + + + + + + 123.123.123.123 + Fonts/DroidSans.ttf,64 + + + + + + ServerIdentity + ServerIdentity + IP + + + + + + + + + + + + 65999 + Fonts/DroidSans.ttf,64 + + + + + + ServerIdentity + ServerIdentity + Port + + + + + + + + + + + + UnkownServer + Fonts/DroidSans.ttf,64 + + + + + + ServerIdentity + ServerIdentity + ServerName + + + + + + + + + + + 0 + Fonts/DroidSans.ttf,64 + + + + + + ServerIdentity + ServerIdentity + PlayersConnected + + + + + + + + + + + + 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/ServerList.xml b/resources/Schema/Entities/ServerList.xml new file mode 100644 index 00000000..aa8f787b --- /dev/null +++ b/resources/Schema/Entities/ServerList.xml @@ -0,0 +1,201 @@ + + + + + + + + + + + + + + + + + + + + + + Schema/Entities/ServerIdentity.xml + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Core/White.png + true + + + + RefreshServerList + 1 + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Icons/rotate.png + + + + + + + + + + + + + + + + + + + + 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/ShinyStoneCrystalBlueLights.xml b/resources/Schema/Entities/ShinyStoneCrystalBlueLights.xml new file mode 100644 index 00000000..e583756a --- /dev/null +++ b/resources/Schema/Entities/ShinyStoneCrystalBlueLights.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + diff --git a/resources/Schema/Entities/ShootingRange.xml b/resources/Schema/Entities/ShootingRange.xml new file mode 100644 index 00000000..a05403c0 --- /dev/null +++ b/resources/Schema/Entities/ShootingRange.xml @@ -0,0 +1,273 @@ + + + + + + + + + + + + + + + + + + + + + + Models/Core/UnitCylinder.mesh + + + + + + + + + + + Models/Core/UnitCylinder.mesh + + + + + + + + + + + Models/Core/UnitCylinder.mesh + + + + + + + + + + + Models/Core/UnitCylinder.mesh + + + + + + + + + + + Models/Core/UnitCylinder.mesh + + + + + + + + + + + Models/Core/UnitCylinder.mesh + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Models/Core/UnitCylinder.mesh + + + + + + + + + + + Models/Core/UnitCylinder.mesh + + + + + + + + + + + Models/Core/UnitCylinder.mesh + + + + + + + + + + + Models/Core/UnitCylinder.mesh + + + + + + + + + + + Models/Core/UnitCylinder.mesh + + + + + + + + + + + Models/Core/UnitCylinder.mesh + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Models/Core/UnitCylinder.mesh + + + + + + + + + + + Models/Core/UnitCylinder.mesh + + + + + + + + + + + Models/Core/UnitCylinder.mesh + + + + + + + + + + + Models/Core/UnitCylinder.mesh + + + + + + + + + + + Models/Core/UnitCylinder.mesh + + + + + + + + + + + Models/Core/UnitCylinder.mesh + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/SidearmWeaponBlendTree.xlm b/resources/Schema/Entities/SidearmWeaponBlendTree.xlm new file mode 100644 index 00000000..8a3dfb8e --- /dev/null +++ b/resources/Schema/Entities/SidearmWeaponBlendTree.xlm @@ -0,0 +1,101 @@ + + + + + + Aim + WeaponBlend + + + + + + + + + MovementBlend2 + ActionBlend + + + + + + + + Reload + Fire + + + + + + + + ReloadSwitchU + false + + + + + + + + + ShootSecWepU + false + + + + + + + + + + + Idle + Run + + + + + + + + IdleSecWepU + true + + + + + + + + + IdleSecWepU + true + + + + + + + + + + + + + AimSecWepA + + 0.10000000149011612 + false + true + + + + + + + + diff --git a/resources/Schema/Entities/SidearmWeaponBlueWorld.xml b/resources/Schema/Entities/SidearmWeaponBlueWorld.xml new file mode 100644 index 00000000..d32c0dee --- /dev/null +++ b/resources/Schema/Entities/SidearmWeaponBlueWorld.xml @@ -0,0 +1,47 @@ + + + + + + + Models/Weapons/Blue/SecondaryWeaponBlue.mesh + + + + + + + + + + + + + + + + Schema/Entities/RaySideArmBlue.xml + + + + + + + + + + + Schema/Entities/MuzzleFlashSideArmBlue.xml + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/SidearmWeaponRedWorld.xml b/resources/Schema/Entities/SidearmWeaponRedWorld.xml new file mode 100644 index 00000000..0dc94319 --- /dev/null +++ b/resources/Schema/Entities/SidearmWeaponRedWorld.xml @@ -0,0 +1,47 @@ + + + + + + + Models/Weapons/Red/SecondaryWeaponRed.mesh + + + + + + + + + + + + + + + + Schema/Entities/RaySideArmRed.xml + + + + + + + + + + + Schema/Entities/MuzzleFlashSideArmRed.xml + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/AssaultWeaponView.xml b/resources/Schema/Entities/SidearmWeaponView.xml old mode 100755 new mode 100644 similarity index 50% rename from resources/Schema/Entities/AssaultWeaponView.xml rename to resources/Schema/Entities/SidearmWeaponView.xml index 4b985fbb..11e049d4 --- a/resources/Schema/Entities/AssaultWeaponView.xml +++ b/resources/Schema/Entities/SidearmWeaponView.xml @@ -1,45 +1,25 @@ - + - - R_Arm_Weapon_Joint - - Models/Weapons/Blue/AssaultWeaponBlue.mesh + Models/Weapons/SecondaryWeapon.mesh - - + - - - - Schema/Entities/RayBlue.xml - - - - - - - - - - - Schema/Entities/ReloadEffectView.xml - - - - - - + + + + + - + @@ -47,12 +27,13 @@ - Textures/Core/UnitHexagon.png + Models/Core/UnitQuad.mesh + Textures/Core/UnitHexagon.png - + @@ -66,25 +47,32 @@ - 32 + 16 Fonts/DroidSans.ttf,64 + + Player + SidearmWeapon + MagazineAmmo + + - + - 360 + 8 Fonts/DroidSans.ttf,64 - + + @@ -94,6 +82,37 @@ + + + + + + + + + + + Schema/Entities/RaySideArmBlue.xml + + + + + + + + + + + Schema/Entities/MuzzleFlashSideArmBlue.xml + + + + + + + + + diff --git a/resources/Schema/Entities/SidearmWeaponWorld.xml b/resources/Schema/Entities/SidearmWeaponWorld.xml new file mode 100644 index 00000000..21cb26a7 --- /dev/null +++ b/resources/Schema/Entities/SidearmWeaponWorld.xml @@ -0,0 +1,27 @@ + + + + + + Models/Weapons/SecondaryWeapon.mesh + + + + + + + + + + + Schema/Entities/RayBlue.xml + + + + + + + + + + diff --git a/resources/Schema/Entities/Skeleton.xml b/resources/Schema/Entities/Skeleton.xml index b8deb2eb..76674dec 100644 --- a/resources/Schema/Entities/Skeleton.xml +++ b/resources/Schema/Entities/Skeleton.xml @@ -18,9 +18,9 @@ true - + - + @@ -29,16 +29,17 @@ R_Hand - + + true Models/Core/UnitCube.mesh - - - + + + @@ -47,16 +48,17 @@ R_Arm - + + true Models/Core/UnitCube.mesh - - - + + + @@ -65,16 +67,17 @@ R_Shoulder - + + true Models/Core/UnitCube.mesh - - - + + + @@ -83,16 +86,17 @@ Neck - + + true Models/Core/UnitCube.mesh - - - + + + @@ -101,16 +105,17 @@ Spine_3 - + + true Models/Core/UnitCube.mesh - - - + + + @@ -119,16 +124,17 @@ Spine_2 - + + true Models/Core/UnitCube.mesh - - - + + + @@ -137,16 +143,17 @@ Spine_1 - + + true Models/Core/UnitCube.mesh - - - + + + @@ -155,15 +162,17 @@ Hip - + + true Models/Core/UnitCube.mesh - - + + + @@ -172,16 +181,17 @@ L_Leg_Top - + + true Models/Core/UnitCube.mesh - + - + @@ -190,16 +200,17 @@ L_Leg_Bottom - + + true Models/Core/UnitCube.mesh - + - + @@ -208,16 +219,17 @@ L_Foot - + + true Models/Core/UnitCube.mesh - - - + + + @@ -226,16 +238,17 @@ L_Toe - + + true Models/Core/UnitCube.mesh - - - + + + @@ -244,16 +257,17 @@ L_Shoulder - + + true Models/Core/UnitCube.mesh - - - + + + @@ -262,16 +276,17 @@ L_Arm - + + true Models/Core/UnitCube.mesh - - - + + + @@ -280,16 +295,17 @@ L_Hand - + + true Models/Core/UnitCube.mesh - - - + + + @@ -298,16 +314,17 @@ L_Shoulder_Armor_Joint - + + true Models/Core/UnitCube.mesh - - - + + + @@ -316,16 +333,17 @@ Chin - + + true Models/Core/UnitCube.mesh - - - + + + @@ -334,16 +352,17 @@ Head - + + true Models/Core/UnitCube.mesh - - - + + + @@ -352,16 +371,17 @@ Perietal - + + true Models/Core/UnitCube.mesh - - - + + + @@ -370,16 +390,17 @@ L_Elbow - + + true Models/Core/UnitCube.mesh - - - + + + @@ -388,16 +409,17 @@ R_Leg_Bottom - + + true Models/Core/UnitCube.mesh - - - + + + @@ -406,16 +428,17 @@ R_Elbow - + + true Models/Core/UnitCube.mesh - - - + + + @@ -424,16 +447,17 @@ R_Leg_Top - + + true Models/Core/UnitCube.mesh - - - + + + @@ -442,16 +466,17 @@ R_Foot - + + true Models/Core/UnitCube.mesh - - - + + + @@ -460,16 +485,17 @@ R_Toe - + + true Models/Core/UnitCube.mesh - - - + + + @@ -478,16 +504,17 @@ R_Shoulder_Armor_Joint - + + true Models/Core/UnitCube.mesh - - - + + + diff --git a/resources/Schema/Entities/Spawnpoint b/resources/Schema/Entities/Spawnpoint deleted file mode 100644 index a53aaa08..00000000 --- a/resources/Schema/Entities/Spawnpoint +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - Models/Core/UnitCube.mesh - - - Schema/Entities/Player.xml - - - - - - - - - - - - - - - - - - - - - - diff --git a/resources/Schema/Entities/SprintEffect.xml b/resources/Schema/Entities/SprintEffect.xml new file mode 100644 index 00000000..6e892f8f --- /dev/null +++ b/resources/Schema/Entities/SprintEffect.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + 0.15 + + + + 0.15 + + + + + + + + + + diff --git a/resources/Schema/Entities/StartMenu.xml b/resources/Schema/Entities/StartMenu.xml new file mode 100644 index 00000000..1fbf65ce --- /dev/null +++ b/resources/Schema/Entities/StartMenu.xml @@ -0,0 +1,17844 @@ + + + + + + + + + + + + + + + + + Schema/Entities/CP_Valhalla_Menu.xml + + + + + + + + 3.3337628933792587 + 4 + + + + + + + + + + + + + + 2 + Models/Props/GroundTest.mesh + + + + + + + + Models/Props/Walls/SciFiWallTop.mesh + + false + + + + + + + + + 2.4600000381469727 + Models/Props/Walls/SciFiWallMedium.mesh + + false + + + + + + + + + + 2.4600000381469727 + Models/Props/Walls/SciFiWallBig.mesh + + false + + + + + + + + + + 2.4600000381469727 + Models/Props/Walls/SciFiWallSmall1.mesh + + false + + + + + + + + + + 2.4600000381469727 + Models/Props/Walls/SciFiWallSmall2.mesh + + false + + + + + + + + + + 2.4600000381469727 + Models/Props/Walls/SciFiWallBig.mesh + + false + + + + + + + + + + + + 2.4500000476837158 + Models/Props/Walls/SciFiWallMedium.mesh + + false + + + + + + + + + + + + 2.4600000381469727 + Models/Props/Walls/SciFiWallSmall3.mesh + + false + + + + + + + + + + 2.4600000381469727 + Models/Props/Walls/SciFiWallSmall4.mesh + + false + + + + + + + + + + + + Models/Highgrounds/Highground1.mesh + + + + + + + + + + Models/Highgrounds/Highground2.mesh + + + + + + + + + + Models/Highgrounds/Highground3.mesh + + + + + + + + + + Models/Highgrounds/Highground24.mesh + + + + + + + + + + + Models/Highgrounds/Hg13.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg25.mesh + + + + + + + + + + + + Models/Highgrounds/Hg26.mesh + + + + + + + + + + + + Models/Highgrounds/Hg9.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg4.mesh + + + + + + + + + + + + + + Models/Highgrounds/Hg10.mesh + + + + + + + + + + + + + + Models/Highgrounds/Hg19.mesh + + + + + + + + + + + + + + Models/Highgrounds/Hg19.mesh + + + + + + + + + + + + + + + Models/Highgrounds/Highground12.mesh + + + + + + + + + + + + Models/Highgrounds/Hg16.mesh + + + + + + + + + + + + Models/Highgrounds/Hg15.mesh + + + + + + + + + + + + Models/Highgrounds/Hg14.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg13.mesh + + + + + + + + + + + + Models/Highgrounds/Hg11.mesh + + + + + + + + + + + + Models/Highgrounds/Hg20.mesh + + + + + + + + + + + + Models/Highgrounds/Hg18.mesh + + + + + + + + + + + + Models/Highgrounds/Hg19.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg17.mesh + + + + + + + + + + + + + + + Models/Highgrounds/Hg8.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg7.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg3.mesh + + + + + + + + + + + + + + + Models/Highgrounds/Highground3.mesh + + + + + + + + + + + + Models/Highgrounds/Highground1.mesh + + + + + + + + + + + Models/Highgrounds/Highground2.mesh + + + + + + + + + + + + + + Models/Highgrounds/Hg1.mesh + + + + + + + + + + + Models/Highgrounds/Hg2.mesh + + + + + + + + + + + + + + Models/Highgrounds/Highground5.mesh + + + + + + + + + + + + Models/Highgrounds/Hg4.mesh + + + + + + + + + + + + Models/Highgrounds/Hg18.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg20.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg6.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg8.mesh + + + + + + + + + + + + Models/Highgrounds/Hg10.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg7.mesh + + + + + + + + + + + + Models/Highgrounds/Hg17.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg19.mesh + + + + + + + + + + + + Models/Highgrounds/Hg16.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg9.mesh + + + + + + + + + + + + Models/Highgrounds/Hg3.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg19.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + Models/Highgrounds/Hg10.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + + + + Models/Highgrounds/Highground22.mesh + + + + + + + + + + + + Models/Highgrounds/Hg8.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg19.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg21.mesh + + + + + + + + + + + + Models/Highgrounds/Hg11.mesh + + + + + + + + + + + + Models/Highgrounds/Hg3.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg17.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg8.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Red.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 + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + + + Models/Highgrounds/Hg28.mesh + + + + + + + + + + + Models/Highgrounds/Hg10.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg27.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg15.mesh + + + + + + + + + + + + + + Models/Highgrounds/Hg13.mesh + + + + + + + + + + + + + + + Models/Highgrounds/Hg27.mesh + + + + + + + + + + + + Models/Highgrounds/Hg23.mesh + + + + + + + + + + + + + + + Models/Highgrounds/Hg27.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg23.mesh + + + + + + + + + + + + + + + Models/Highgrounds/Hg28.mesh + + + + + + + + + + + + Models/Highgrounds/Hg10.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg27.mesh + + + + + + + + + + + + + Models/Highgrounds/Hg15.mesh + + + + + + + + + + + + + + Models/Highgrounds/Hg13.mesh + + + + + + + + + + + + + + + Models/Highgrounds/Hg1.mesh + + + + + + + + + + + + Models/Highgrounds/Hg2.mesh + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.5 + Models/Props/Bridges/Bridge1_SciFi_Blue.mesh + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh + + + + + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh + + + + + + + + + + + + + + + + + + + + 1.5 + Models/Props/Bridges/Bridge1_SciFi_Blue.mesh + + + + + + + + + + + + 1.5 + Models/Props/Bridges/Bridge1_SciFi_Blue.mesh + + + + + + + + + + + + 1.5 + Models/Props/Bridges/SciFi_Bridge_Support_Top_Blue.mesh + + + + + + + + + + + + Models/Props/Bridges/SciFi_Bridge_Support_Bot_Blue.mesh + + + + + + + + + + + 12 + + + + + + + + + + + + + 1.5 + Models/Props/Bridges/SciFi_Bridge_Support_Middle_Blue.mesh + + + + + + + + + + + + + + + + + + 1.1499999761581421 + Models/Props/Bridges/SciFi_Bridge_Support_Top_Blue.mesh + + + + + + + + + + + + Models/Props/Bridges/SciFi_Bridge_Support_Bot_Blue.mesh + + + + + + + + + + + 12 + + + + + + + + + + + + + 1.5 + Models/Props/Bridges/SciFi_Bridge_Support_Middle_Blue.mesh + + + + + + + + + + + + + + + + + + 1.5 + Models/Props/Bridges/Bridge1_SciFi_Blue.mesh + + + + + + + + + + + + + + 1.1499999761581421 + Models/Props/Bridges/SciFi_Bridge_Support_Top_Blue.mesh + + + + + + + + + + + + + Models/Props/Bridges/SciFi_Bridge_Support_Bot_Blue.mesh + + + + + + + + + + + 12 + + + + + + + + + + + + + 1.5 + Models/Props/Bridges/SciFi_Bridge_Support_Middle_Blue.mesh + + + + + + + + + + + + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.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/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + + 1.7999999523162842 + Models/Props/Pillars/SciFiPillar1Blue.mesh + + + + + + + + + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Medium_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + 1.7999999523162842 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + 2 + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + + + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Medium_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + + 1.6000000238418579 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Medium_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Medium_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Medium_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Walls/Medium_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Medium_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + + + + + + + + 0.34999999403953552 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + 1.5 + 1 + + + + + + + + + + + + + + + + + + 0.44999998807907104 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + 1.5 + 1 + + + + + + + + + + + + + + + + + + 0.40000000596046448 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + + + 1.5 + 1 + + + + + + + + + + + + + + + + + + 0.44999998807907104 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + 1.5 + 1 + + + + + + + + + + + + + + + + + + 0.44999998807907104 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + 1.5 + 1 + + + + + + + + + + + + + + + + + + 0.30000001192092896 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + + + 1.5 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Core/UnitPlane.mesh + + false + true + + + + + + + + + + + + + + + + + + + Models/Props/Bridge_Holder_Blue.mesh + + + + + + + + + + + + + Models/Props/SciFiHolder1.mesh + + + + + + + + + + + + + Models/Props/Bridge_Holder_Blue.mesh + + + + + + + + + + + + + Models/Props/Bridge_Holder_Blue.mesh + + + + + + + + + + + + + + + + + + + + 2.5 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 2 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 1.7999999523162842 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + 2 + + + + + + + + + + + + 2 + 1 + + + + + + + + + + + + 3 + + + + + + + + + + + + + + 2.2999999523162842 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 2 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 3 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 15 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 2 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + 2 + + + + + + + + + + + + + + 2 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 2.2000000476837158 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 2.2999999523162842 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + 2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + Models/Props/Stones/ShinyStoneCrystalBlue.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/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/BigStone.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/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.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/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/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/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/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.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/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/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + + + + + + + + + + + + + 1.2999999523162842 + Models/Props/Pillars/SciFiPillar1Red.mesh + + + + + + + + + + + + + + 2 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + 2 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + 2 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + 2 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar1Red.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar3Red.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar3Red.mesh + + + + + + + + + + + + + + + + + + + + + 2.4000000953674316 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh + + + + + + + + + + + + + 3 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + 2.4000000953674316 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh + + + + + + + + + + + + + 3 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + true + false + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + true + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + true + + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar1Blue.mesh + + + + + + + + + + + + + + 3 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + 2.4000000953674316 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 2 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh + + + + + + + + + + + + + 2.2999999523162842 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Blue.mesh + + + + + + + + + + + + + Models/Props/Bridge_Holder_Blue.mesh + + + + + + + + + + + + + + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.mesh + + + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.mesh + + + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.mesh + + + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.mesh + + + + + + + + + + + + + + + + + + + + + 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/Bridge_Holder_Red.mesh + + + + + + + + + + + + + + + + + + + 0.40000000596046448 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + + + 1.5 + 1 + + + + + + + + + + + + + + + + + + 0.30000001192092896 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + 1.5 + 1 + + + + + + + + + + + + + + + + + + 0.37999999523162842 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + 1.5 + 1 + + + + + + + + + + + + + + + + + + 0.30000001192092896 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + 1.5 + 1 + + + + + + + + + + + + + + + + + + 0.44999998807907104 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + 1.5 + 1 + + + + + + + + + + + + + + + + + + 0.40000000596046448 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + 1.5 + 1 + + + + + + + + + + + + + + + + + + 0.44999998807907104 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + 1.5 + 1 + + + + + + + + + + + + + + + + + + 0.40000000596046448 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + + + 1.5 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + 1.5 + Models/Props/Bridges/Bridge1_SciFi_Red.mesh + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_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 + + + + + + + + + + + + + + 1.5 + Models/Props/Bridges/Bridge1_SciFi_Red.mesh + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + + + Models/Props/Bridges/SciFi_Bridge_Support_Top_Red.mesh + + + + + + + + + + + 12 + + + + + + + + + + + + + 1.5 + Models/Props/Bridges/SciFi_Bridge_Support_Middle_Red.mesh + + + + + + + + + + + + + + Models/Props/Bridges/SciFi_Bridge_Support_Bot_Red.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Bridges/Bridge1_SciFi_Red.mesh + + + + + + + + + + + + Models/Props/Bridges/SciFi_Bridge_Support_Top_Red.mesh + + + + + + + + + + + + Models/Props/Bridges/SciFi_Bridge_Support_Bot_Red.mesh + + + + + + + + + + + 12 + + + + + + + + + + + + + 1.5 + Models/Props/Bridges/SciFi_Bridge_Support_Middle_Red.mesh + + + + + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/Bridge_Pillar1_SciFi_Red.mesh + + + + + + + + + + + + + + + 1.5 + Models/Props/Bridges/Bridge1_SciFi_Red.mesh + + + + + + + + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar1Red.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + + + Models/Core/UnitPlane.mesh + + false + false + true + + + + + + + + + + + + + + + + + + + 2 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + 2.2000000476837158 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 2.2000000476837158 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 2 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + 1.7999999523162842 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 1.7999999523162842 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 2.2000000476837158 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 2.4000000953674316 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 1.7999999523162842 + 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 + + + + + + + + + + + + + + 2.5 + Models/Props/Stones/ShinyStoneCrystalRed.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/BigStone.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/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/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.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/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/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/mediumStone2.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/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/mediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/BigStone.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/MediumStone2.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/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.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 + + + + + + + + + + + + + + + + + + + + 2 + Models/Props/Walls/BigWallRed.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 + + + + + + + + + + + + + 1.5 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Medium_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/BigWallRed.mesh + + + + + + + + + + + + + + + 2 + Models/Props/Walls/Medium_Wall_SciFi_Red.mesh + + + + + + + + + + + + + Models/Props/Walls/Small_Wall_SciFi_Red.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Medium_Wall_SciFi_Red.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Medium_Wall_SciFi_Red.mesh + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + 1.5 + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Medium_Wall_SciFi_Red.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Medium_Wall_SciFi_Red.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh + + + + + + + + + + + + + + + + + + + + + Models/Props/Flora/Root.mesh + + + + + + + + + + + + + + Models/Props/Flora/Root.mesh + + + + + + + + + + + + + + Models/Props/Flora/Root.mesh + + + + + + + + + + + + + + Models/Props/Flora/Root.mesh + + + + + + + + + + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + true + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + true + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + true + false + + + + + + + + + + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush1.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + false + true + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush1.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + false + true + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar3Blue.mesh + + + + + + + + + + + + + + 2.5 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar1Blue.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + 1.5 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + 2.5 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + 1.7000000476837158 + Models/Props/Pillars/SciFiPillar3Blue.mesh + + + + + + + + + + + + + + 2.5 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + + + + + + + + + + + + + 2.4000000953674316 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 2 + Models/Props/Stones/ShinyStoneCrystalRed.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/Flora/HangingBush2.mesh + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + true + + + + + + + + + + + + + + + + + + + + + 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/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/mediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + + + + + + + + 2 + Models/Props/Walls/Medium_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + 1.5 + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Blue.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh + + + + + + + + + + + + + + 2 + Models/Props/Walls/Small_Wall_SciFi_Red.mesh + + + + + + + + + + + + + + + + + + + + 0.44999998807907104 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + 1.5 + 1 + + + + + + + + + + + + + + + + + + 0.60000002384185791 + Models/Props/PickUps/PickUpHolder.mesh + false + + + + + + + + + + + + 2 + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + + + 1.5 + 3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + false + true + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush1.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush1.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + false + true + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush3.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + 15 + 1 + + + + + + + + + + + + + + + + + + + + + + 5 + 2 + 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 + + + + + + + + + + + + 6 + 2 + 0.5 + + + + + + + + + + + + + + + + + + + + + 6 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + + + + + + + + + + 10 + 1 + + + + + + + + + + + + 10 + 1 + + + + + + + + + + + + 10 + 1 + + + + + + + + + + + + + + 5 + 0.69999998807907104 + + + + + + + + + + + + 5 + 1 + + + + + + + + + + + + 5 + 1 + + + + + + + + + + + + 5 + 0.69999998807907104 + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + + + + + 0.55000001192092896 + 1.6000000238418579 + false + + + + + + + + + + + + + 0.55000001192092896 + 1.6000000238418579 + false + + + + + + + + + + + + + 0.55000001192092896 + 1.6000000238418579 + false + + + + + + + + + + + + + + + 5 + 1 + + + + + + + + + + + + + 10 + + + + + + + + + + + + + + + + + 4 + 0.5 + + + + + + + + + + + + 4 + 0.5 + + + + + + + + + + + + 4 + 0.5 + + + + + + + + + + + 2.5 + + + + + + + + + + + + 4 + 0.5 + + + + + + + + + + + 2 + + + + + + + + + + + 2 + 0.5 + + + + + + + + + + + + 3 + 0.40000000596046448 + + + + + + + + + + + 2 + + + + + + + + + + + + 3 + 0.5 + + + + + + + + + + + + 4 + 0.5 + + + + + + + + + + + + 4 + 0.34999999403953552 + + + + + + + + + + + 1.3999999761581421 + + + + + + + + + + + + 4 + 0.5 + + + + + + + + + + + + 4 + 0.5 + + + + + + + + + + + + 4 + 0.30000001192092896 + + + + + + + + + + + + 4 + 0.5 + + + + + + + + + + + + + + 1.2499997615814209 + 1.0299992561340332 + + + + + + + + 3 + + + + + + + + + + + + + + 0.17000000178813934 + + + + + + + + + + + 10 + + + + + + + + + + + 8 + + + + + + + + + + + + 10 + + + + + + + + + + + + 10 + + + + + + + + + + + + + + + + + 3 + 0.60000002384185791 + + + + + + + + + + + + 6 + 0.69999998807907104 + + + + + + + + + + + + + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + 5 + 2 + 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 + + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + + + + + + + + + + 2 + 1 + 0.5 + + + + + + + + + + + + 3 + 1 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 1 + 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 + 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 + + + + + + + + + + + + 4 + 1 + + + + + + + + + + + + 6 + 0.5 + + + + + + + + + + + + 5 + 1 + + + + + + + + + + + + 15 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + 1 + 0.5 + + + + + + + + + + + + 6 + 1 + 0.5 + + + + + + + + + + + + + + + + + + + 6 + 1 + 0.5 + + + + + + + + + + + + 5 + 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 + + + + + + + + + + + + + + + + + 10 + 1 + + + + + + + + + + + + 10 + 1 + + + + + + + + + + + + 10 + 1 + + + + + + + + + + + + + + 3 + 0.5 + + + + + + + + + + + + + + + + + + + + Schema/Entities/PlayerAssaultBlue.xml + Schema/Entities/PlayerDefenderBlue.xml + + + + Schema/Entities/PlayerAssaultBlue.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 + + + + + + + + + + + + + + + + + + 2 + + + + Models/Props/CapturePoint/CapturePointCylinder.mesh + + false + true + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointNeutral.mesh + + + + + + + + + + + + + + + 0.5 + + + + 20 + + + 3 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer2.mesh + false + + + + + + + + + + + 0.30000001192092896 + + + + 30 + + + 3.5 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer1.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 + + + + + + + + + + + + + + + + + + + + + + + + 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.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/CapturePointBlue.mesh + 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 + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + 15 + + + + + + + + + + + Models/Props/CapturePoint/CapturePointCylinder.mesh + + false + true + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointBlue.mesh + 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 + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + + 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 + 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 + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + + 1 + + + + Models/Props/CapturePoint/CapturePointCylinder.mesh + + false + true + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointNeutral.mesh + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + 0.5 + + + + 20 + + + 3 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer2.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 + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointRed.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 + + + + + + + + + + + + + + + + + + + + 3 + + + + Models/Props/CapturePoint/CapturePointCylinder.mesh + + false + true + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointRed.mesh + 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 + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + 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 + + + + + + + + + + + + + + + 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.30000001192092896 + + + + 30 + + + 3.5 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer1.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.5 + + + + 20 + + + 3 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer2.mesh + false + + + + + + + + + + + + + + + + + -15 + + + + 4 + + + + + + + + Models/Props/CapturePoint/CapturePointCylinder.mesh + + false + true + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointNeutral.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 + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + 4.5 + 0.5 + + + + + + + + + + + + + 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/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 + + + + + + + + + + + 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/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.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 + + + + + + + + + + + + + + + 0.30000001192092896 + + + + 30 + + + 3.5 + + + + + + + + + + + Models/Props/CapturePoint/CrystalsLayer1.mesh + + false + + + + + + + + + + + + + + + + + + + + + + + + Schema/Entities/PlayerAssaultRed.xml + Schema/Entities/PlayerDefenderRed.xml + + + + 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 + + + + + + + + + + + + + + + + + + + + + + + + 0.10000000149011612 + + + + + + + + + + + 0.20000000298023224 + + + + + + + + + + + + + + + + + + + + + + + + + Schema/Entities/MainMenu.xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + + + + + + + + + + + + + + + Quit + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/White.png + true + + + + Quit + 1 + + + + + + + + + + + + + + + + + + + + Options + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + + 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 + + + + Options + 1 + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + Play + 1 + + + + + + + + + + + Play + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + Credits + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + + + + + + + + Schema/Entities/ServerList.xml + + + + + + + + + Schema/Entities/OptionMenu.xml + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Icons/AxyzWhite-01.png + true + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/StartMenu_simple.xml b/resources/Schema/Entities/StartMenu_simple.xml new file mode 100644 index 00000000..d6a31372 --- /dev/null +++ b/resources/Schema/Entities/StartMenu_simple.xml @@ -0,0 +1,476 @@ + + + + + + + + + + + + + + + + + Schema/Entities/NewMap2version5NEW.xml + + + + + + + + + + + + + + + + 0.10000000149011612 + + + + + + + + + + + 0.20000000298023224 + + + + + + + + + + + + + + + + + + + + + + + + + Schema/Entities/MainMenu.xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/White.png + true + + + + Play + 1 + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + + + + + + + + + + + + + + Play + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/White.png + true + + + + + + + + + + + + Credits + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/White.png + true + + + + Options + 1 + + + + + + + + + + + Options + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + + + + + + + false + Models/Core/UnitQuad.mesh + + Textures/Core/White.png + true + + + + + + + + + + + + Quit + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/HUD/ButtonCorner_16.png + false + + + + + + + + + + + + + + + + + + + + + + + + + Schema/Entities/ServerList.xml + + + + + + + + + Schema/Entities/OptionMenu.xml + + + + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Test/SmallDiff.png + true + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/Testingu b/resources/Schema/Entities/Testingu deleted file mode 100644 index 145550f4..00000000 --- a/resources/Schema/Entities/Testingu +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - Models/Core/UnitPlane.mesh - - - - - - - - - - - - Schema/Entities/Player.xml - - - - - - - - - - - - - - - - - - - - - diff --git a/resources/Schema/Entities/ThirdPersonBlendTree.xml b/resources/Schema/Entities/ThirdPersonBlendTree.xml new file mode 100644 index 00000000..eb6f319e --- /dev/null +++ b/resources/Schema/Entities/ThirdPersonBlendTree.xml @@ -0,0 +1,528 @@ + + + + + + BlendTreeAim + BlendTreeAssault + + + + + Models/Characters/Assault/AssaultBlue.mesh + + + + + + + + + + R_Arm_Weapon_Joint + + + AssaultWeapon + + + + + + Schema/Entities/WeaponAssaultBlueWorld.xml + + + + + + + + + + + + R_Arm_Weapon_Joint + + + SidearmWeapon + + + + + + Schema/Entities/SidearmWeaponWorld.xml + + + + + + + + + + + + AimPrimary + AimSecondary + 0 + true + + + + + + + + AimSecWepA + + false + true + + + + + + + + + AimRifleA + + false + true + + + + + + + + + + + ReloadSwitchBlend + FinalMovementBlend + + + + + + + + StandCrouchBlend + JumpDashBlend + 2.5146881298480398e-63 + true + + + + + + + + StandMovement + CrouchMovement + 0 + true + + + + + + + + MovementBlend + Idle + 1 + + + + + + + + Walk + StrafeLRBlend + 0 + + + + + + + + Left + Right + 0.033793529385008014 + + + + + + + + CrouchStrafeLeftF + + true + + + + + + + + + CrouchStrafeRightF + + true + + + + + + + + + + + CrouchWalkF + + true + + + + + + + + + + + CrouchF + + + + + + + + + + + + MovementBlend + Idle + 1 + + + + + + + + RunWalkBlend + StrafeLRBlend + 0 + + + + + + + + Walk + Run + 1 + + + + + + + + WalkF + + true + + + + + + + + + RunF + + true + true + + + + + + + + + + + Left + Right + 0.033793529385008014 + + + + + + + + StrafeLeftF + + true + + + + + + + + + StrafeRightF + + true + + + + + + + + + + + + + IdleF + + true + + + + + + + + + + + + + Jump + DashBlend + 1 + true + + + + + + + + JumpF + + false + + + + + + + + + DashFBBlend + DashLRBlend + 0.014621149736541383 + + + + + + + + DashForward + DashBackward + 0.014363533804961248 + + + + + + + + DashForwardF + + 2 + false + + + + + + + + + DashBackwardF + + 2 + false + + + + + + + + + + + DashLeft + DashRight + 4.3244885367500671e-16 + + + + + + + + DashLeftF + + 2 + false + + + + + + + + + DashRightF + + 2 + false + + + + + + + + + + + + + + + + + ReloadSwitch + WeaponActionBlend + 1 + true + + + + + + + + ReloadSwitchU + + + + + + + + + + IdleBlend + ShootBlend + 0 + + + + + + + + IdlePrimary + IdleSecondary + 0 + + + + + + + + IdleAssaultRifleU + + true + + + + + + + + + IdleSecWepU + + true + + + + + + + + + + + ShootPrimary + ShootSecondary + 0 + + + + + + + + ShootFastRifleU + + + + + + + + + + ShootSecWepFastU + + + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/WeaponAssaultBlueView.xml b/resources/Schema/Entities/WeaponAssaultBlueView.xml new file mode 100644 index 00000000..1c1e9cf7 --- /dev/null +++ b/resources/Schema/Entities/WeaponAssaultBlueView.xml @@ -0,0 +1,233 @@ + + + + + + MovementBlend + ActionBlend + + + Models/Characters/Assault/FirstPersonAssaultBlue.mesh + false + + + + + + + + + Fire + Reload + 0 + true + + + + + + + + ReloadSwitchF + 0.5 + false + + + + + + + + + ShootRifleF + false + + + + + + + + + + + Idle + Run + 0 + true + + + + + + + + RunF + true + true + + + + + + + + + IdleF + true + true + + + + + + + + + + + R_Arm_Weapon_Joint + + + 1.5 + Models/Weapons/Blue/AssaultWeaponBlue.mesh + false + + + + + + + + + + + Schema/Entities/WeaponAssaultReloadEffectView.xml + + + + + + + + + + + + + + + + + Schema/Entities/MuzzleFlashBlue.xml + + + + + + + + + + + Schema/Entities/RayAssaultBlue.xml + + + + + + + + + + + + + + + R_Ammo_Joint + + true + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + + + + + + + 32 + Fonts/DroidSans.ttf,64 + + + + + AssaultWeapon + MagazineAmmo + + + + + + + + + + + 320 + Fonts/DroidSans.ttf,64 + + + + + AssaultWeapon + Ammo + + + + + + + + + + + + + + Schema/Entities/FriendlyBoostBlueHUD.xml + + + + + + + + + + + + diff --git a/resources/Schema/Entities/WeaponAssaultBlueWorld.xml b/resources/Schema/Entities/WeaponAssaultBlueWorld.xml new file mode 100644 index 00000000..aa844329 --- /dev/null +++ b/resources/Schema/Entities/WeaponAssaultBlueWorld.xml @@ -0,0 +1,56 @@ + + + + + + + Models/Weapons/Blue/AssaultWeaponBlue.mesh + + + + + + + + + Schema/Entities/ReloadEffectWorld.xml + + + + + + + + + + + + + + + + + Schema/Entities/MuzzleFlashBlue.xml + + + + + + + + + + + Schema/Entities/RayAssaultBlue.xml + + + + + + + + + + + + diff --git a/resources/Schema/Entities/WeaponAssaultRedView.xml b/resources/Schema/Entities/WeaponAssaultRedView.xml new file mode 100644 index 00000000..f3dcac06 --- /dev/null +++ b/resources/Schema/Entities/WeaponAssaultRedView.xml @@ -0,0 +1,233 @@ + + + + + + MovementBlend + ActionBlend + + + Models/Characters/Assault/FirstPersonAssaultRed.mesh + false + + + + + + + + + Fire + Reload + 0 + true + + + + + + + + ReloadSwitchF + 0.5 + false + + + + + + + + + ShootRifleF + false + + + + + + + + + + + Idle + Run + 0 + true + + + + + + + + RunF + true + true + + + + + + + + + IdleF + true + true + + + + + + + + + + + R_Arm_Weapon_Joint + + + 1.5 + Models/Weapons/Red/AssaultWeaponRed.mesh + false + + + + + + + + + + + Schema/Entities/WeaponAssaultReloadEffectViewRed.xml + + + + + + + + + + + + + + + + + Schema/Entities/MuzzleFlashRed.xml + + + + + + + + + + + Schema/Entities/RayAssaultRed.xml + + + + + + + + + + + + + + + R_Ammo_Joint + + true + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + + + + + + + 32 + Fonts/DroidSans.ttf,64 + + + + + AssaultWeapon + MagazineAmmo + + + + + + + + + + + 320 + Fonts/DroidSans.ttf,64 + + + + + AssaultWeapon + Ammo + + + + + + + + + + + + + + Schema/Entities/FriendlyBoostRedHUD.xml + + + + + + + + + + + + diff --git a/resources/Schema/Entities/WeaponAssaultRedWorld.xml b/resources/Schema/Entities/WeaponAssaultRedWorld.xml new file mode 100644 index 00000000..18d4096c --- /dev/null +++ b/resources/Schema/Entities/WeaponAssaultRedWorld.xml @@ -0,0 +1,56 @@ + + + + + + + Models/Weapons/Red/AssaultWeaponRed.mesh + + + + + + + + + Schema/Entities/ReloadEffectWorldRed.xml + + + + + + + + + + + + + + + + + Schema/Entities/MuzzleFlashRed.xml + + + + + + + + + + + Schema/Entities/RayAssaultRed.xml + + + + + + + + + + + + diff --git a/resources/Schema/Entities/WeaponAssaultReloadEffectView.xml b/resources/Schema/Entities/WeaponAssaultReloadEffectView.xml new file mode 100644 index 00000000..fe33de28 --- /dev/null +++ b/resources/Schema/Entities/WeaponAssaultReloadEffectView.xml @@ -0,0 +1,54 @@ + + + + + + 2 + + + + + + + + + + + 1 + 1 + -1 + 1 + + true + + + Models/Weapons/Blue/AssaultWeaponBlue.mesh + true + + + + + + + + + 1 + + + + + 1 + + true + + + Models/Weapons/Blue/AssaultWeaponBlue.mesh + true + + + + + + + + diff --git a/resources/Schema/Entities/WeaponAssaultReloadEffectViewRed.xml b/resources/Schema/Entities/WeaponAssaultReloadEffectViewRed.xml new file mode 100644 index 00000000..3cbb0fdc --- /dev/null +++ b/resources/Schema/Entities/WeaponAssaultReloadEffectViewRed.xml @@ -0,0 +1,54 @@ + + + + + + 2 + + + + + + + + + + + 1 + 1 + -1 + 1 + + true + + + Models/Weapons/Red/AssaultWeaponRed.mesh + true + + + + + + + + + 1 + + + + + 1 + + true + + + Models/Weapons/Red/AssaultWeaponRed.mesh + true + + + + + + + + diff --git a/resources/Schema/Entities/WeaponDefenderBlueView.xml b/resources/Schema/Entities/WeaponDefenderBlueView.xml new file mode 100644 index 00000000..65475dc2 --- /dev/null +++ b/resources/Schema/Entities/WeaponDefenderBlueView.xml @@ -0,0 +1,303 @@ + + + + + + MovementBlend + FinalBlend + + + Models/Characters/Defender/FirstPersonDefenderBlue.mesh + false + + + + + + + + + ActionBlend + Shield + 0 + true + + + + + + + + ActivateShieldF + false + + + + + + + + + Fire + ReloadBlend + 0 + + + + + + + + ShootShotgunF + false + + + + + + + + + ReloadLoop + ReloadTransitionBlend + 1 + + + + + + + + ShotgunReloadTwoF + + + + + + + + + ReloadStart + ReloadEnd + 0 + + + + + + + + ShotgunReloadOneF + false + + + + + + + + + ShotgunReloadThreeF + false + + + + + + + + + + + + + + + + + Idle + Run + 0 + true + + + + + + + + IdleF + true + true + + + + + + + + + RunF + true + true + + + + + + + + + + + R_Ammo_Joint + + true + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + + + + + + + 38 + Fonts/DroidSans.ttf,64 + + + + + DefenderWeapon + Ammo + + + + + + + + + + + + 5 + Fonts/DroidSans.ttf,64 + + + + + DefenderWeapon + MagazineAmmo + + + + + + + + + + + + + Schema/Entities/FriendlyBoostBlueHUD.xml + + + + + + + + + + + + + + + + + + R_Arm_Weapon_Joint + + + Models/Weapons/Blue/DefenderWeaponBlue.mesh + false + + + + + + + + + + + Schema/Entities/ReloadEffectView.xml + + + + + + + + + + + + + + + + + + Schema/Entities/RayDefenderBlue.xml + + + + + + + + + + + Schema/Entities/MuzzleFlashBlue.xml + + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/WeaponDefenderBlueWorld.xml b/resources/Schema/Entities/WeaponDefenderBlueWorld.xml new file mode 100644 index 00000000..18cf28da --- /dev/null +++ b/resources/Schema/Entities/WeaponDefenderBlueWorld.xml @@ -0,0 +1,56 @@ + + + + + + + Models/Weapons/Blue/DefenderWeaponBlue.mesh + + + + + + + + + Schema/Entities/ReloadEffectWorld.xml + + + + + + + + + + + + + + + + Schema/Entities/RayDefenderBlue.xml + + + + + + + + + + + Schema/Entities/MuzzleFlashBlue.xml + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/WeaponDefenderRedView.xml b/resources/Schema/Entities/WeaponDefenderRedView.xml new file mode 100644 index 00000000..b13d11d1 --- /dev/null +++ b/resources/Schema/Entities/WeaponDefenderRedView.xml @@ -0,0 +1,303 @@ + + + + + + MovementBlend + FinalBlend + + + Models/Characters/Defender/FirstPersonDefenderRed.mesh + false + + + + + + + + + ActionBlend + Shield + 0 + true + + + + + + + + ActivateShieldF + false + + + + + + + + + Fire + ReloadBlend + 0 + + + + + + + + ShootShotgunF + false + + + + + + + + + ReloadLoop + ReloadTransitionBlend + 1 + + + + + + + + ShotgunReloadTwoF + + + + + + + + + ReloadStart + ReloadEnd + 0 + + + + + + + + ShotgunReloadOneF + false + + + + + + + + + ShotgunReloadThreeF + false + + + + + + + + + + + + + + + + + Idle + Run + 0 + true + + + + + + + + IdleF + true + true + + + + + + + + + RunF + true + true + + + + + + + + + + + R_Ammo_Joint + + true + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + + + + + + + 38 + Fonts/DroidSans.ttf,64 + + + + + DefenderWeapon + Ammo + + + + + + + + + + + + 5 + Fonts/DroidSans.ttf,64 + + + + + DefenderWeapon + MagazineAmmo + + + + + + + + + + + + + Schema/Entities/FriendlyBoostRedHUD.xml + + + + + + + + + + + + + + + + + + R_Arm_Weapon_Joint + + + Models/Weapons/Red/DefenderWeaponRed.mesh + false + + + + + + + + + + + Schema/Entities/ReloadEffectView.xml + + + + + + + + + + + + + + + + + + Schema/Entities/RayDefenderRed.xml + + + + + + + + + + + Schema/Entities/MuzzleFlashRed.xml + + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/WeaponDefenderRedWorld.xml b/resources/Schema/Entities/WeaponDefenderRedWorld.xml new file mode 100644 index 00000000..19e5d332 --- /dev/null +++ b/resources/Schema/Entities/WeaponDefenderRedWorld.xml @@ -0,0 +1,56 @@ + + + + + + + Models/Weapons/Red/DefenderWeaponRed.mesh + + + + + + + + + Schema/Entities/ReloadEffectWorld.xml + + + + + + + + + + + + + + + + Schema/Entities/RayDefenderRed.xml + + + + + + + + + + + Schema/Entities/MuzzleFlashRed.xml + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/WeaponSidearmAssaultBlueView.xml b/resources/Schema/Entities/WeaponSidearmAssaultBlueView.xml new file mode 100644 index 00000000..d0a98be5 --- /dev/null +++ b/resources/Schema/Entities/WeaponSidearmAssaultBlueView.xml @@ -0,0 +1,239 @@ + + + + + + MovementBlend + ActionBlend + + + Models/Characters/Assault/FirstPersonAssaultBlue.mesh + false + + + + + + + + + Idle + Run + 1 + true + + + + + + + + IdleSecF + true + true + + + + + + + + + RunSecF + true + true + + + + + + + + + + + Fire + Reload + 0 + + + + + + + + ShootSecF + false + + + + + + + + + ReloadSwitchSecF + false + + + + + + + + + + + R_Ammo_Joint + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + + + + + + + 16 + Fonts/DroidSans.ttf,64 + + + + + SidearmWeapon + MagazineAmmo + + + + + + + + + + + + 8 + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + Schema/Entities/FriendlyAmmoHUD.xml + + + + + + + + + + + Schema/Entities/AmmoShareEffectView.xml + + + + + + + + + + + + + + + + R_Arm_Weapon_Joint + + + 1.2999999523162842 + Models/Weapons/Blue/SecondaryWeaponBlue.mesh + false + + + + + + + + + + + Schema/Entities/WeaponSidearmReloadEffectView.xml + + + + + + + + + + + + + + + + + + Schema/Entities/RaySideArmBlue.xml + + + + + + + + + Schema/Entities/MuzzleFlashSideArmBlue.xml + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/WeaponSidearmAssaultRedView.xml b/resources/Schema/Entities/WeaponSidearmAssaultRedView.xml new file mode 100644 index 00000000..b869d7ae --- /dev/null +++ b/resources/Schema/Entities/WeaponSidearmAssaultRedView.xml @@ -0,0 +1,239 @@ + + + + + + MovementBlend + ActionBlend + + + Models/Characters/Assault/FirstPersonAssaultRed.mesh + false + + + + + + + + + Idle + Run + 1 + true + + + + + + + + IdleSecF + true + true + + + + + + + + + RunSecF + true + true + + + + + + + + + + + Fire + Reload + 0 + + + + + + + + ShootSecF + false + + + + + + + + + ReloadSwitchSecF + false + + + + + + + + + + + R_Ammo_Joint + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + + + + + + + 16 + Fonts/DroidSans.ttf,64 + + + + + SidearmWeapon + MagazineAmmo + + + + + + + + + + + + 8 + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + Schema/Entities/FriendlyAmmoHUD.xml + + + + + + + + + + + Schema/Entities/AmmoShareEffectView.xml + + + + + + + + + + + + + + + + R_Arm_Weapon_Joint + + + 1.2999999523162842 + Models/Weapons/Red/SecondaryWeaponRed.mesh + false + + + + + + + + + + + Schema/Entities/WeaponSidearmReloadEffectViewRed.xml + + + + + + + + + + + + + + + + + + Schema/Entities/RaySideArmRed.xml + + + + + + + + + Schema/Entities/MuzzleFlashSideArmRed.xml + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/WeaponSidearmDefenderBlueView.xml b/resources/Schema/Entities/WeaponSidearmDefenderBlueView.xml new file mode 100644 index 00000000..0d647ba7 --- /dev/null +++ b/resources/Schema/Entities/WeaponSidearmDefenderBlueView.xml @@ -0,0 +1,239 @@ + + + + + + MovementBlend + ActionBlend + + + Models/Characters/Defender/FirstPersonDefenderBlue.mesh + false + + + + + + + + + Idle + Run + 1 + true + + + + + + + + IdleSecF + true + true + + + + + + + + + RunSecF + true + true + + + + + + + + + + + Fire + Reload + 0 + + + + + + + + ShootSecF + false + + + + + + + + + ReloadSwitchSecF + false + + + + + + + + + + + R_Ammo_Joint + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + + + + + + + 16 + Fonts/DroidSans.ttf,64 + + + + + SidearmWeapon + MagazineAmmo + + + + + + + + + + + + 8 + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + Schema/Entities/FriendlyAmmoHUD.xml + + + + + + + + + + + Schema/Entities/AmmoShareEffectView.xml + + + + + + + + + + + + + + + + R_Arm_Weapon_Joint + + + 1.5 + Models/Weapons/Blue/SecondaryWeaponBlue.mesh + false + + + + + + + + + + + Schema/Entities/WeaponSidearmReloadEffectView.xml + + + + + + + + + + + + + + + + + + Schema/Entities/RaySideArmBlue.xml + + + + + + + + + Schema/Entities/MuzzleFlashSideArmBlue.xml + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/WeaponSidearmDefenderRedView.xml b/resources/Schema/Entities/WeaponSidearmDefenderRedView.xml new file mode 100644 index 00000000..2f1a9b0d --- /dev/null +++ b/resources/Schema/Entities/WeaponSidearmDefenderRedView.xml @@ -0,0 +1,239 @@ + + + + + + MovementBlend + ActionBlend + + + Models/Characters/Defender/FirstPersonDefenderRed.mesh + false + + + + + + + + + Idle + Run + 1 + true + + + + + + + + IdleSecF + true + true + + + + + + + + + RunSecF + true + true + + + + + + + + + + + Fire + Reload + 0 + + + + + + + + ShootSecF + false + + + + + + + + + ReloadSwitchSecF + false + + + + + + + + + + + R_Ammo_Joint + + + + + + + + + + + + Models/Core/UnitQuad.mesh + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + + + + + + + 16 + Fonts/DroidSans.ttf,64 + + + + + SidearmWeapon + MagazineAmmo + + + + + + + + + + + + 8 + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + Schema/Entities/FriendlyAmmoHUD.xml + + + + + + + + + + + Schema/Entities/AmmoShareEffectView.xml + + + + + + + + + + + + + + + + R_Arm_Weapon_Joint + + + 1.5 + Models/Weapons/Red/SecondaryWeaponRed.mesh + false + + + + + + + + + + + Schema/Entities/WeaponSidearmReloadEffectViewRed.xml + + + + + + + + + + + + + + + + + + Schema/Entities/RaySideArmRed.xml + + + + + + + + + Schema/Entities/MuzzleFlashSideArmRed.xml + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/WeaponSidearmReloadEffectView.xml b/resources/Schema/Entities/WeaponSidearmReloadEffectView.xml new file mode 100644 index 00000000..bae68bc2 --- /dev/null +++ b/resources/Schema/Entities/WeaponSidearmReloadEffectView.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + 0.5 + 0.5 + -1 + 0.5 + + true + + + 1.5 + Models/Weapons/Blue/SecondaryWeaponBlue.mesh + false + true + + + + + + + + + 0.5 + + + + 0.5 + + true + + + 1.5 + Models/Weapons/Blue/SecondaryWeaponBlue.mesh + false + true + + + + + + + + diff --git a/resources/Schema/Entities/WeaponSidearmReloadEffectViewRed.xml b/resources/Schema/Entities/WeaponSidearmReloadEffectViewRed.xml new file mode 100644 index 00000000..e20080b6 --- /dev/null +++ b/resources/Schema/Entities/WeaponSidearmReloadEffectViewRed.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + 0.5 + 0.5 + -1 + 0.5 + + true + + + 1.5 + Models/Weapons/Red/SecondaryWeaponRed.mesh + false + true + + + + + + + + + 0.5 + + + + 0.5 + + true + + + 1.5 + Models/Weapons/Red/SecondaryWeaponRed.mesh + false + true + + + + + + + + diff --git a/resources/Schema/Entities/aaaatestremoveme.xml b/resources/Schema/Entities/aaaatestremoveme.xml deleted file mode 100644 index 8da40b58..00000000 --- a/resources/Schema/Entities/aaaatestremoveme.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - Models/Core/Unithexagon.mesh - - - - - - - - - - - - - - - - - - - 2.2000000476837158 - - - - - - - - diff --git a/resources/Schema/Entities/aim_rays.xml b/resources/Schema/Entities/aim_rays.xml deleted file mode 100644 index c8dac9a3..00000000 --- a/resources/Schema/Entities/aim_rays.xml +++ /dev/null @@ -1,261 +0,0 @@ - - - - - - - - - - - - - - models/core/unitcube.mesh - - - - - - - - - - - - - - - models/core/unitcube.mesh - - - - - - - - - - - - - - - - - - - - - - - - models/core/unitcube.mesh - - - - - - - - - - - - - - - models/core/unitcube.mesh - - - - - - - - - - - - - - - models/core/unitcube.mesh - - - - - - - - - - - - - - Schema/Entities/Player.xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Schema/Entities/Player.xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - models/core/unitcube.mesh - - - - - - - - - - - - - - - - - - Models\Core\UnitCube.mesh - - - - - - - - - - - - - - - - - - - - - - - 1 - - - Models\Core\UnitCube.mesh - - - - - - - - - - - - - - - - - - diff --git a/resources/Schema/Entities/aim_rays_with_capturep.xml b/resources/Schema/Entities/aim_rays_with_capturep.xml new file mode 100644 index 00000000..60030ba5 --- /dev/null +++ b/resources/Schema/Entities/aim_rays_with_capturep.xml @@ -0,0 +1,449 @@ + + + + + + + + + + + + + + models/core/unitcube.mesh + + false + + + + + + + + + + + + + + models/core/unitcube.mesh + + false + + + + + + + + + + + + + + + + + + + + + + + models/core/unitcube.mesh + + false + + + + + + + + + + + + + + models/core/unitcube.mesh + + false + + + + + + + + + + + + + + models/core/unitcube.mesh + + false + + + + + + + + + + + + + + + + + + Schema/Entities/PlayerRed.xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Schema/Entities/Player.xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + models/core/unitcube.mesh + + false + + + + + + + + + + + + + + + + + 15 + + + + + + + + + + + + + + false + + + + + + + + + + models/core/unitcube.mesh + + + + + + + + + + + + + + + + + + + + + + + + + + + + models/core/unitcube.mesh + + + + + + + + + + + + + + + + + + + + + + + + + + + + + models/core/unitcube.mesh + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 12 + + + + 1 + + + + + + + + + + + + + + + + models/core/unitcube.mesh + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + models/core/unitcube.mesh + + + + + + + + + + + + models/core/unitcube.mesh + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/awdawd b/resources/Schema/Entities/awdawd deleted file mode 100644 index d8dacb54..00000000 --- a/resources/Schema/Entities/awdawd +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - L_Foot - true - - - Models/Core/UnitCube.mesh - - - - - - - - - - - - diff --git a/resources/Schema/Entities/derp.xml b/resources/Schema/Entities/derp.xml new file mode 100644 index 00000000..b8735335 --- /dev/null +++ b/resources/Schema/Entities/derp.xml @@ -0,0 +1,298 @@ + + + + + + Aim + FinalBlend + + + 4 + Models/Characters/Sniper/SniperBlue.mesh + + + + + + + + + R_Arm_Weapon_Joint + + + Models/Weapons/Blue/AssaultWeaponBlue.mesh + + + + + + + + + + + + + 3 + + + + + + + + + + + AimRifleA + + false + true + + + + + + + + + WeaponBlend + MovementBlend + + + + + + + + ShootBlend + Reload + 1 + + + + + + + + ShootFast + ShootSlow + 1 + + + + + + + + ShootFastRifleU + + 1 + + + + + + + + + ShootRifleU + + 1 + + + + + + + + + + + ReloadSwitchU + + false + + + + + + + + + + + StandCrouchBlend + Jump + 1 + + + + + + + + StandMovement + CrouchMovement + 1 + + + + + + + + Walk + StrafeBlend + 1 + + + + + + + + CrouchWalkF + + 1 + + + + + + + + + Left + Right + 1 + + + + + + + + CrouchStrafeLeftF + + 1 + + + + + + + + + CrouchStrafeRightF + + 1 + + + + + + + + + + + + + RunWalkBlend + StrafeBlend + 1 + + + + + + + + Run + Walk + 1 + + + + + + + + RunF + + 1 + + + + + + + + + WalkF + + 1 + + + + + + + + + + + Left + Right + 0 + + + + + + + + StrafeLeftF + + 1 + + + + + + + + + StrafeRightF + + 1 + + + + + + + + + + + + + + + JumpF + + false + + + + + + + + + + + + diff --git a/resources/Schema/Entities/temp b/resources/Schema/Entities/temp deleted file mode 100644 index baf4ce61..00000000 --- a/resources/Schema/Entities/temp +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - 0 - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - 360 - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - diff --git a/resources/Schema/Types/Entity.xsd b/resources/Schema/Types/Entity.xsd index 0965ef89..51bb8e13 100644 --- a/resources/Schema/Types/Entity.xsd +++ b/resources/Schema/Types/Entity.xsd @@ -43,15 +43,39 @@ - + + + + - + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/Setup/Inno Setup Script.iss b/resources/Setup/Inno Setup Script.iss new file mode 100755 index 00000000..fd5af749 --- /dev/null +++ b/resources/Setup/Inno Setup Script.iss @@ -0,0 +1,81 @@ +; Script generated by the Inno Setup Script Wizard. +; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES! + +#define MyAppName "Axyz" +#define MyAppVersion "1.0" +#define MyAppURL "https://github.com/teamfisk/TacticalZ" +#define MyAppExeName "Axyz.exe" + +[Setup] +; NOTE: The value of AppId uniquely identifies this application. +; Do not use the same AppId value in installers for other applications. +; (To generate a new GUID, click Tools | Generate GUID inside the IDE.) +AppId={{38D77EB2-6B56-4B4F-BAAE-43F9E6E1A191} +AppName={#MyAppName} +AppVersion={#MyAppVersion} +;AppVerName={#MyAppName} {#MyAppVersion} +AppPublisherURL={#MyAppURL} +AppSupportURL={#MyAppURL} +AppUpdatesURL={#MyAppURL} +DefaultDirName={pf}\{#MyAppName} +DisableProgramGroupPage=yes +OutputBaseFilename=Axyz Setup +SetupIconFile=..\Axyz.ico +Compression=lzma2 +SolidCompression=yes +; "ArchitecturesAllowed=x64" specifies that Setup cannot run on +; anything but x64. +ArchitecturesAllowed=x64 +; "ArchitecturesInstallIn64BitMode=x64" requests that the install be +; done in "64-bit mode" on x64, meaning it should use the native +; 64-bit Program Files directory and the 64-bit view of the registry. +ArchitecturesInstallIn64BitMode=x64 +OutputDir=. +DisableWelcomePage=false +;WizardSmallImageFile= +WizardImageFile=Setup Banner.bmp + +[Languages] +Name: "english"; MessagesFile: "compiler:Default.isl" + +[Tasks] +Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked + +[Files] +Source: "..\..\bin\Audio\*"; DestDir: "{app}\Audio\"; Flags: ignoreversion createallsubdirs recursesubdirs +Source: "..\..\bin\Fonts\*"; DestDir: "{app}\Fonts\"; Flags: ignoreversion createallsubdirs recursesubdirs +Source: "..\..\bin\Licenses\*"; DestDir: "{app}\Licenses\"; Flags: ignoreversion createallsubdirs recursesubdirs +Source: "..\..\bin\Models\*"; DestDir: "{app}\Models\"; Flags: ignoreversion createallsubdirs recursesubdirs +Source: "..\..\bin\Schema\*"; DestDir: "{app}\Schema\"; Flags: ignoreversion createallsubdirs recursesubdirs +Source: "..\..\bin\Shaders\*"; DestDir: "{app}\Shaders\"; Flags: ignoreversion createallsubdirs recursesubdirs +Source: "..\..\bin\Textures\*"; DestDir: "{app}\Textures\"; Flags: ignoreversion createallsubdirs recursesubdirs +Source: "..\..\bin\assimp.dll"; DestDir: "{app}"; Flags: ignoreversion +Source: "..\..\resources\DefaultConfig.ini"; DestDir: "{app}"; Flags: ignoreversion +Source: "..\..\resources\DefaultInput.ini"; DestDir: "{app}"; Flags: ignoreversion +Source: "..\..\bin\glew32.dll"; DestDir: "{app}"; Flags: ignoreversion +Source: "..\..\bin\glfw3.dll"; DestDir: "{app}"; Flags: ignoreversion +Source: "..\..\bin\OpenAL32.dll"; DestDir: "{app}"; Flags: ignoreversion +Source: "..\..\bin\imgui.ini"; DestDir: "{app}"; Flags: ignoreversion +Source: "..\..\bin\Input.ini"; DestDir: "{app}"; Flags: ignoreversion +Source: "..\..\bin\libpng16.dll"; DestDir: "{app}"; Flags: ignoreversion +Source: "..\..\bin\Axyz.exe"; DestDir: "{app}"; Flags: ignoreversion +Source: "..\..\bin\Server.bat"; DestDir: "{app}"; Flags: ignoreversion +Source: "..\..\bin\xerces-c_3_1.dll"; DestDir: "{app}"; Flags: ignoreversion +Source: "..\..\bin\zlib.dll"; DestDir: "{app}"; Flags: ignoreversion +Source: "..\..\resources\README.txt"; DestDir: "{app}"; Flags: ignoreversion +Source: "..\..\deps\redist\VC_redist.x64.exe"; DestDir: "{tmp}"; Flags: deleteafterinstall + +[Icons] +Name: "{commonprograms}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}" +Name: "{commondesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon +Name: "{commonprograms}\{#MyAppName} Server"; Filename: "{app}\{#MyAppExeName}"; Parameters: "--server" +Name: "{commondesktop}\{#MyAppName} Server"; Filename: "{app}\{#MyAppExeName}"; Parameters: "--server"; Tasks: desktopicon + +[INI] +Filename: "{app}\Config.ini"; Section: "Networking"; Key: "Name"; String: "{%USERNAME}"; Flags: createkeyifdoesntexist + +[Run] +Filename: "{tmp}\VC_redist.x64.exe"; Parameters: "/norestart /passive"; StatusMsg: "Installing Microsoft Visual C++ 2015 x64 Redistributable...."; + +[ThirdParty] +UseRelativePaths=True \ No newline at end of file diff --git a/resources/Setup/Setup Banner.bmp b/resources/Setup/Setup Banner.bmp new file mode 100755 index 00000000..69384103 Binary files /dev/null and b/resources/Setup/Setup Banner.bmp differ diff --git a/resources/Shaders/CombineGaussianTexture.frag.glsl b/resources/Shaders/CombineGaussianTexture.frag.glsl new file mode 100644 index 00000000..93c36fb8 --- /dev/null +++ b/resources/Shaders/CombineGaussianTexture.frag.glsl @@ -0,0 +1,21 @@ +#version 430 + +layout (binding = 0) uniform sampler2D Texture; +uniform int MaxMipMap; + + +in VertexData{ + vec2 TextureCoordinate; +}Input; + +out vec4 fragmentColor; + +void main() +{ + vec4 result = vec4(0.0, 0.0, 0.0, 0.0); + + for(int i = 0; i < MaxMipMap; i++) { + result += textureLod(Texture, Input.TextureCoordinate, i); + } + fragmentColor = result; +} diff --git a/resources/Shaders/CombineGaussianTexture.vert.glsl b/resources/Shaders/CombineGaussianTexture.vert.glsl new file mode 100644 index 00000000..346bc141 --- /dev/null +++ b/resources/Shaders/CombineGaussianTexture.vert.glsl @@ -0,0 +1,13 @@ +#version 430 + +layout (location = 0) in vec3 Position; + +out VertexData{ + vec2 TextureCoordinate; +}Output; + +void main() +{ + gl_Position = vec4(Position, 1.0); + Output.TextureCoordinate = (vec2(Position) + 1) / 2; +} \ No newline at end of file diff --git a/resources/Shaders/CombineTexture.frag.glsl b/resources/Shaders/CombineTexture.frag.glsl new file mode 100644 index 00000000..fd4acaac --- /dev/null +++ b/resources/Shaders/CombineTexture.frag.glsl @@ -0,0 +1,31 @@ +#version 430 + +layout (binding = 0) uniform sampler2D Texture0; +layout (binding = 1)uniform sampler2D Texture1; + + +in VertexData{ + vec2 TextureCoordinate; +}Input; + +out vec4 sceneColor; +out vec4 bloomColor; + +void main() +{ + vec4 texel0 = texture(Texture0, Input.TextureCoordinate); + vec4 texel1 = texture(Texture1, Input.TextureCoordinate); + float texel1_total = (texel1.r + texel1.g + texel1.b) * texel1.a; + texel1_total = ceil(clamp(texel1_total, 0, 1)); + + vec4 result0 = texel0 * (1.0 - texel1_total); + vec4 result1 = texel1 * texel1_total; + + //vec4 final = texel1 * texel1_total + texel0 * (1.0 - texel1_total); + //float res = 1.0 - texel1_total; + //vec4 final = vec4(texel1_total, texel1_total, texel1_total, 1.0); + sceneColor = result1; + bloomColor = vec4(0.0, 0.0, 0.0, 0.0); +} + + diff --git a/resources/Shaders/CombineTexture.vert.glsl b/resources/Shaders/CombineTexture.vert.glsl new file mode 100644 index 00000000..346bc141 --- /dev/null +++ b/resources/Shaders/CombineTexture.vert.glsl @@ -0,0 +1,13 @@ +#version 430 + +layout (location = 0) in vec3 Position; + +out VertexData{ + vec2 TextureCoordinate; +}Output; + +void main() +{ + gl_Position = vec4(Position, 1.0); + Output.TextureCoordinate = (vec2(Position) + 1) / 2; +} \ No newline at end of file diff --git a/resources/Shaders/DrawColorCorrection.frag.glsl b/resources/Shaders/DrawColorCorrection.frag.glsl index bae50887..d8273547 100644 --- a/resources/Shaders/DrawColorCorrection.frag.glsl +++ b/resources/Shaders/DrawColorCorrection.frag.glsl @@ -2,8 +2,6 @@ layout (binding = 0) uniform sampler2D SceneTexture; layout (binding = 1) uniform sampler2D BloomTexture; -layout (binding = 2) uniform sampler2D SceneTextureLowRes; -layout (binding = 3) uniform sampler2D BloomTextureLowRes; uniform float Exposure; uniform float Gamma; @@ -17,21 +15,12 @@ void main() { vec4 hdrColor = texture(SceneTexture, Input.TextureCoordinate); vec4 bloomColor = texture(BloomTexture, Input.TextureCoordinate); - vec4 hdrColorLowRes = texture(SceneTextureLowRes, Input.TextureCoordinate); - vec4 bloomColorLowRes = texture(BloomTextureLowRes, Input.TextureCoordinate); //hdrColor = hdrColor * SSAO; hdrColor += bloomColor; - hdrColorLowRes; - float hdrColorsum = hdrColorLowRes.r + hdrColorLowRes.g + hdrColorLowRes.b; //Toon mapping thingy - vec3 result; - if(hdrColorsum > 0.0) { - result = vec3(1.0) - exp(-hdrColorLowRes.rgb * Exposure); - } else { - result = vec3(1.0) - exp(-hdrColor.rgb * Exposure); - } + vec3 result = vec3(1.0) - exp(-hdrColor.rgb * Exposure); //gamme correction result = pow(result, vec3(1.0 / Gamma)); diff --git a/resources/Shaders/ExplosionEffect.frag.glsl b/resources/Shaders/ExplosionEffect.frag.glsl index 32ababe5..d506e70f 100644 --- a/resources/Shaders/ExplosionEffect.frag.glsl +++ b/resources/Shaders/ExplosionEffect.frag.glsl @@ -1,14 +1,11 @@ #version 430 -uniform mat4 M; -uniform mat4 V; -uniform mat4 P; uniform vec4 Color; - uniform sampler2D texture0; in VertexData{ vec3 Position; + vec4 ViewSpacePosition; vec3 Normal; vec2 TextureCoordinate; vec4 DiffuseColor; diff --git a/resources/Shaders/ExplosionEffect.geom.glsl b/resources/Shaders/ExplosionEffect.geom.glsl index 44b44aa6..5a355fac 100644 --- a/resources/Shaders/ExplosionEffect.geom.glsl +++ b/resources/Shaders/ExplosionEffect.geom.glsl @@ -1,5 +1,8 @@ #version 430 +#define MAX_SPLITS 4 + +uniform mat4 PVM; uniform mat4 M; uniform mat4 V; uniform mat4 P; @@ -13,185 +16,170 @@ 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; + vec4 ViewSpacePosition; vec3 Normal; vec3 Tangent; vec3 BiTangent; vec2 TextureCoordinate; vec4 ExplosionColor; float ExplosionPercentageElapsed; + vec4 PositionLightSpace[MAX_SPLITS]; }Input[]; out VertexData{ vec3 Position; + vec4 ViewSpacePosition; vec3 Normal; vec3 Tangent; vec3 BiTangent; vec2 TextureCoordinate; vec4 ExplosionColor; float ExplosionPercentageElapsed; + vec4 PositionLightSpace[MAX_SPLITS]; }Output; 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.ViewSpacePosition = Input[index].ViewSpacePosition; + 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; - - // 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; - - } - - // 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; - - // no change in position, pass through vertex - gl_Position = gl_in[i].gl_Position; - EmitVertex(); - } + Output.ExplosionPercentageElapsed = timePercetage; } - //EndPrimitive(); -} + vec3 ExplodedPosition; + for (int i = 0; i < gl_in.length(); i++) + { + // move the triangle to the blast radius + ExplodedPosition = Input[i].Position + (triangleCenter2ExplosionRadius * isInsideBlastRadius); + + // pass through vertex data + PassThingsThrough(i); + for (int j = 0; j < MAX_SPLITS; j++) + { + Output.PositionLightSpace[j] = Input[i].PositionLightSpace[j]; + } + for (int j = 0; j < MAX_SPLITS; j++) + { + Output.PositionLightSpace[j] = Input[i].PositionLightSpace[j]; + } + + // convert to window space + gl_Position = PVM * vec4(ExplodedPosition, 1.0); + EmitVertex(); + } +} \ No newline at end of file diff --git a/resources/Shaders/FillDepthBuffer.vert.glsl b/resources/Shaders/FillDepthBuffer.vert.glsl index ff849790..e8f6838d 100644 --- a/resources/Shaders/FillDepthBuffer.vert.glsl +++ b/resources/Shaders/FillDepthBuffer.vert.glsl @@ -1,8 +1,6 @@ #version 430 -uniform mat4 M; -uniform mat4 V; -uniform mat4 P; +uniform mat4 PVM; layout(location = 0) in vec3 Position; layout(location = 5) in vec4 BoneIndices; @@ -15,7 +13,7 @@ out VertexData{ void main() { - gl_Position = P * V * M * vec4(Position, 1.0); + gl_Position = PVM * vec4(Position, 1.0); Output.Position = Position; } \ No newline at end of file diff --git a/resources/Shaders/FillDepthBufferSkinned.vert.glsl b/resources/Shaders/FillDepthBufferSkinned.vert.glsl index ce2a142d..a1ad5c14 100644 --- a/resources/Shaders/FillDepthBufferSkinned.vert.glsl +++ b/resources/Shaders/FillDepthBufferSkinned.vert.glsl @@ -1,8 +1,6 @@ #version 430 -uniform mat4 M; -uniform mat4 V; -uniform mat4 P; +uniform mat4 PVM; uniform mat4 Bones[100]; @@ -27,7 +25,7 @@ void main() + BoneWeights[3] * Bones[int(BoneIndices[3])]; } - gl_Position = P*V*M*boneTransform * vec4(Position, 1.0); + gl_Position = PVM*boneTransform * vec4(Position, 1.0); Output.Position = vec3(0.0); } \ No newline at end of file diff --git a/resources/Shaders/ForwardPlus.frag.glsl b/resources/Shaders/ForwardPlus.frag.glsl index 6fbc9c27..f160c7f8 100644 --- a/resources/Shaders/ForwardPlus.frag.glsl +++ b/resources/Shaders/ForwardPlus.frag.glsl @@ -1,6 +1,9 @@ #version 430 +#include "Shaders/Util/CommonNormalFunc.glsl" + #define MIN_AMBIENT_LIGHT 0.3 +#define MAX_SPLITS 4 uniform mat4 M; uniform mat4 V; @@ -11,9 +14,12 @@ uniform vec2 ScreenDimensions; uniform vec4 FillColor; uniform vec4 AmbientColor; uniform float FillPercentage; -uniform float GlowIntensity = 10; +uniform float GlowIntensity; uniform vec3 CameraPosition; +uniform int SSAOQuality; +uniform float FarDistance[MAX_SPLITS]; +uniform int NormalTextureType; uniform vec2 DiffuseUVRepeat; uniform vec2 NormalUVRepeat; uniform vec2 SpecularUVRepeat; @@ -24,6 +30,7 @@ layout (binding = 2) uniform sampler2D NormalMapTexture; layout (binding = 3) uniform sampler2D SpecularMapTexture; layout (binding = 4) uniform sampler2D GlowMapTexture; layout (binding = 5) uniform samplerCube CubeMap; +layout (binding = 30) uniform sampler2DArrayShadow DepthMap; #define TILE_SIZE 16 @@ -58,15 +65,16 @@ layout (std430, binding = 4) buffer LightIndexBuffer float LightIndex[]; }; - in VertexData{ vec3 Position; + vec4 ViewSpacePosition; vec3 Normal; vec3 Tangent; vec3 BiTangent; vec2 TextureCoordinate; vec4 ExplosionColor; float ExplosionPercentageElapsed; + vec4 PositionLightSpace[MAX_SPLITS]; }Input; out vec4 sceneColor; @@ -77,6 +85,25 @@ struct LightResult { vec4 Specular; }; +vec2 poissonDisk[16] = vec2[]( + vec2( -0.94201624, -0.39906216 ), + vec2( 0.94558609, -0.76890725 ), + vec2( -0.094184101, -0.92938870 ), + vec2( 0.34495938, 0.29387760 ), + vec2( -0.91588581, 0.45771432 ), + vec2( -0.81544232, -0.87912464 ), + vec2( -0.38277543, 0.27676845 ), + vec2( 0.97484398, 0.75648379 ), + vec2( 0.44323325, -0.97511554 ), + vec2( 0.53742981, -0.47373420 ), + vec2( -0.26496911, -0.41893023 ), + vec2( 0.79197514, 0.19090188 ), + vec2( -0.24188840, 0.99706507 ), + vec2( -0.81409955, 0.91437590 ), + vec2( 0.19984126, 0.78641367 ), + vec2( 0.14383161, -0.14100790 ) + ); + float CalcAttenuation(float radius, float dist, float falloff) { return 1.0 - smoothstep(radius * falloff, radius, dist); } @@ -116,25 +143,165 @@ LightResult CalcDirectionalLightSource(vec4 direction, vec4 color, float intensi return result; } -vec4 CalcNormalMappedValue(vec3 normal, vec3 tangent, vec3 bitangent, vec2 textureCoordinate, sampler2D normalMap) +// Returns a "random" value. +float Random(vec3 seed, int i) { - mat3 TBN = mat3(tangent, bitangent, normal); - vec3 NormalMap = texture(normalMap, textureCoordinate).xyz * 2.0 - vec3(1.0); - return vec4(TBN * normalize(NormalMap), 0.0); + vec4 seed4 = vec4(seed, i); + float dot_product = dot(seed4, vec4(12.9898, 78.233, 45.164, 94.673)); + return fract(sin(dot_product) * 43758.5453); +} + +int getShadowIndex(float far_distance[1]) +{ + return 0; +} + +int getShadowIndex(float far_distance[2]) +{ + float depth = gl_FragCoord.z / gl_FragCoord.w; + + int index = 1; + if ( depth < far_distance[0] ) + { + index = 0; + } + + return index; +} + +int getShadowIndex(float far_distance[3]) +{ + float depth = gl_FragCoord.z / gl_FragCoord.w; + + int index = 2; + if ( depth < far_distance[0] ) + { + index = 0; + } + else if ( depth < far_distance[1] && depth > far_distance[0] ) + { + index = 1; + } + + return index; +} + +int getShadowIndex(float far_distance[4]) +{ + float depth = gl_FragCoord.z / gl_FragCoord.w; + + int index = 3; + if ( depth < far_distance[0] ) + { + index = 0; + } + else if ( depth < far_distance[1] && depth > far_distance[0] ) + { + index = 1; + } + else if ( depth < far_distance[2] && depth > far_distance[1] ) + { + index = 2; + } + + return index; +} + +// Standard hardware-calculated PCF method +float PCFShadow(sampler2DArrayShadow depth_texture_array, vec3 projection_coords, int layer_index) +{ + return texture(depth_texture_array, vec4(projection_coords.xy, layer_index, projection_coords.z)); +} + +// PCF + Poisson model method +float PoissonShadow(sampler2DArrayShadow depth_texture_array, vec3 projection_coords, int layer_index, int taps, float spread) +{ + int loop; + float multiplier = 1.0 / float(taps); + float shadowMapDepth; + + for (int i = 0; i < taps; i++) + { + loop = i; + vec3 newProjCoords = projection_coords + vec3(poissonDisk[loop], 0.0) / (spread * (1.0 + layer_index)); + shadowMapDepth += multiplier * texture(depth_texture_array, vec4(newProjCoords.xy, layer_index, newProjCoords.z)); + } + + return shadowMapDepth; +} + +// PCF + Poisson + RandomSample model method +float PoissonDotShadow(sampler2DArrayShadow depth_texture_array, vec3 projection_coords, int layer_index, int taps, float spread) +{ + int loop; + float multiplier = 1.0 / float(taps); + float shadowMapDepth; + + for (int i = 0; i < taps; i++) + { + loop = int(16.0 * Random(gl_FragCoord.xyy, i)) % 16; + vec3 newProjCoords = projection_coords + vec3(poissonDisk[loop], 0.0) / (spread * (1.0 + layer_index)); + shadowMapDepth += multiplier * texture(depth_texture_array, vec4(newProjCoords.xy, layer_index, newProjCoords.z)); + } + + return shadowMapDepth; +} + +// Hardware PCF + Additional software PCF method +float SoftwarePCF(sampler2DArrayShadow depth_texture_array, vec3 projection_coords, int layer_index, float bias) +{ + float shadow = 0.0; + + vec3 texelSize = 1.0 / textureSize(depth_texture_array, 0); + for(int x = -1; x <= 1; x++) + { + for(int y = -1; y <= 1; y++) + { + shadow += texture(depth_texture_array, vec4(projection_coords.xy + vec2(x, y) * texelSize.xy / (1.0 + layer_index), layer_index, projection_coords.z)); + } + } + + return shadow / 9.0; +} + +float CalcShadowValue(vec4 light_space_pos, vec3 normal, vec3 light_dir, sampler2DArrayShadow depth_texture_array, int layer_index) +{ + float shadowMapDepth; + float bias = 0.005; + + // Various bias methods. + + //bias = max(0.05 * (1.0 - dot(normal, light_dir)), bias); + //bias = bias * tan(acos(clamp(dot(normal, -light_dir), 0.0, 1.0))); + bias = bias + bias * tan(acos(clamp(dot(normal, -light_dir), 0.0, 1.0))); + + // Calculate coordinates in projection space. + + vec3 projCoords = vec3(light_space_pos.xy, light_space_pos.z + bias) / light_space_pos.w; + projCoords = projCoords * 0.5 + 0.5; + //projCoords = (floor(projCoords * 255.0)) / 255.0; + + // Various methods for shadow calculation in fastest to slowest order. + + //shadowMapDepth = PCFShadow(depth_texture_array, projCoords, layer_index); + //shadowMapDepth = PoissonShadow(depth_texture_array, projCoords, layer_index, 4, 25.0 * FarDistance[MAX_SPLITS - 1]); + //shadowMapDepth = PoissonDotShadow(depth_texture_array, projCoords, layer_index, 4, 25.0 * FarDistance[MAX_SPLITS - 1]); + shadowMapDepth = SoftwarePCF(depth_texture_array, projCoords, layer_index, bias); + + return shadowMapDepth; } void main() { - float ao = texelFetch(AOTexture, ivec2(gl_FragCoord.xy), 0).r; + float ao = texelFetch(AOTexture, ivec2(gl_FragCoord.xy) >> int(SSAOQuality), 0).r; ao = (clamp(1.0 - (1.0 - ao), 0.0, 1.0) + MIN_AMBIENT_LIGHT) / (1.0 + MIN_AMBIENT_LIGHT); vec4 diffuseTexel = texture2D(DiffuseTexture, Input.TextureCoordinate * DiffuseUVRepeat); vec4 glowTexel = texture2D(GlowMapTexture, Input.TextureCoordinate * GlowUVRepeat); vec4 specularTexel = texture2D(SpecularMapTexture, Input.TextureCoordinate * SpecularUVRepeat); - vec4 position = V * M * vec4(Input.Position, 1.0); - vec4 normal = V * CalcNormalMappedValue(Input.Normal, Input.Tangent, Input.BiTangent, Input.TextureCoordinate * NormalUVRepeat, NormalMapTexture); + vec4 normal = V * CalcNormalMappedValue(Input.Normal, Input.Tangent, Input.BiTangent, Input.TextureCoordinate * NormalUVRepeat, NormalMapTexture, NormalTextureType); normal = normalize(normal); //vec4 normal = normalize(V * vec4(Input.Normal, 0.0)); - vec4 viewVec = normalize(-position); + vec4 viewVec = normalize(-Input.ViewSpacePosition); vec3 I = normalize(vec3(M * vec4(Input.Position, 1.0)) - CameraPosition); vec3 R = reflect(-I, Input.Normal); //R = vec3(P * vec4(R, 1.0)); @@ -150,6 +317,8 @@ void main() int start = int(LightGrids.Data[currentTile].Start); int amount = int(LightGrids.Data[currentTile].Amount); + + float shadowFactor = 0.0; for(int i = start; i < start + amount; i++) { @@ -159,18 +328,24 @@ void main() LightResult light_result; //These if statements should be removed. if(light.Type == 1) { // point - light_result = CalcPointLightSource(V * light.Position, light.Radius, light.Color, light.Intensity, viewVec, position, normal, light.Falloff); + light_result = CalcPointLightSource(V * light.Position, light.Radius, light.Color, light.Intensity, viewVec, Input.ViewSpacePosition, normal, light.Falloff); } else if (light.Type == 2) { //Directional + int DepthMapIndex = getShadowIndex(FarDistance); light_result = CalcDirectionalLightSource(V * light.Direction, light.Color, light.Intensity, viewVec, normal); + shadowFactor = CalcShadowValue(Input.PositionLightSpace[DepthMapIndex], Input.Normal, vec3(light.Direction), DepthMap, DepthMapIndex); } totalLighting.Diffuse += vec4(light_result.Diffuse.rgb * ao, light_result.Diffuse.a); totalLighting.Specular += vec4(light_result.Specular.rgb * ao, light_result.Specular.a); } + + totalLighting.Diffuse *= vec4(min(vec3(shadowFactor) + AmbientColor.xyz, vec3(1.0)), 1.0); + totalLighting.Specular *= vec4(min(vec3(shadowFactor) + AmbientColor.xyz, vec3(1.0)), 1.0); vec4 color_result = mix((Color * diffuseTexel * DiffuseColor), Input.ExplosionColor, Input.ExplosionPercentageElapsed); color_result = color_result * (totalLighting.Diffuse + (totalLighting.Specular * specularTexel)); float specularResult = (specularTexel.r + specularTexel.g + specularTexel.b)/3.0; - color_result = color_result * clamp(1/specularTexel, 0, 1)*2 + reflectionColor * clamp(specularTexel, 0, 1)/2; + vec4 reflectionTotal = reflectionColor * (1-specularTexel.a) * color_result.a * (totalLighting.Diffuse + (totalLighting.Specular * specularTexel)); + color_result = color_result * clamp(1/specularTexel.a, 0, 1) + reflectionTotal; //vec4 color_result = (DiffuseColor + Input.ExplosionColor) * (totalLighting.Diffuse + (totalLighting.Specular * specularTexel)) * diffuseTexel * Color; @@ -180,10 +355,11 @@ void main() color_result += FillColor; } sceneColor = vec4(color_result.xyz, clamp(color_result.a, 0, 1)); + //sceneColor = CommonUniforms.testColour; //sceneColor = vec4(reflectionColor.xyz, 1); - color_result += glowTexel*GlowIntensity; + color_result.xyz += glowTexel.xyz*GlowIntensity; - bloomColor = vec4(clamp(color_result.xyz - 1.0, 0, 100), clamp(color_result.a, 0, 1)); + bloomColor = vec4(max(color_result.xyz - 1.0, 0.0), clamp(color_result.a, 0, 1)); //Tiled Debug Code /* diff --git a/resources/Shaders/ForwardPlus.vert.glsl b/resources/Shaders/ForwardPlus.vert.glsl index 26686222..783e2f92 100644 --- a/resources/Shaders/ForwardPlus.vert.glsl +++ b/resources/Shaders/ForwardPlus.vert.glsl @@ -1,8 +1,14 @@ #version 430 +uniform mat4 PVM; +uniform mat4 VM; +#define MAX_SPLITS 4 +uniform mat4 TIM; uniform mat4 M; uniform mat4 V; uniform mat4 P; +uniform mat4 LightV[MAX_SPLITS]; +uniform mat4 LightP[MAX_SPLITS]; layout(location = 0) in vec3 Position; layout(location = 1) in vec3 Normal; @@ -12,23 +18,31 @@ layout(location = 4) in vec2 TextureCoords; out VertexData{ vec3 Position; + vec4 ViewSpacePosition; vec3 Normal; vec3 Tangent; vec3 BiTangent; vec2 TextureCoordinate; vec4 ExplosionColor; float ExplosionPercentageElapsed; + vec4 PositionLightSpace[MAX_SPLITS]; }Output; void main() { - gl_Position = P*V*M * vec4(Position, 1.0); - mat4 TIM = transpose(inverse(M)); + gl_Position = PVM * vec4(Position, 1.0); + //mat4 TIM = transpose(inverse(M)); Output.Position = Position; + Output.ViewSpacePosition = VM * vec4(Position, 1.0); Output.TextureCoordinate = TextureCoords; Output.Normal = vec3(TIM * vec4(Normal, 0.0)); Output.Tangent = vec3(TIM * vec4(Tangent, 0.0)); Output.BiTangent = vec3(TIM * vec4(BiTangent, 0.0)); Output.ExplosionColor = vec4(1.0); Output.ExplosionPercentageElapsed = 0.0; + + for(int i = 0; i < MAX_SPLITS; i++) + { + Output.PositionLightSpace[i] = LightP[i] * LightV[i] * M * vec4(Position, 1.0); + } } \ No newline at end of file diff --git a/resources/Shaders/ForwardPlusShieldCheck.frag.glsl b/resources/Shaders/ForwardPlusShieldCheck.frag.glsl new file mode 100644 index 00000000..a95e4914 --- /dev/null +++ b/resources/Shaders/ForwardPlusShieldCheck.frag.glsl @@ -0,0 +1,206 @@ +#version 430 + +#include "Shaders/Util/CommonNormalFunc.glsl" + +#define MIN_AMBIENT_LIGHT 0.3 +#define MAX_SPLITS 4 + +uniform mat4 VM; +uniform mat4 M; +uniform mat4 V; +uniform mat4 P; +uniform vec4 Color; +uniform vec4 DiffuseColor; +uniform vec2 ScreenDimensions; +uniform vec4 FillColor; +uniform vec4 AmbientColor; +uniform float FillPercentage; +uniform float GlowIntensity; +uniform vec3 CameraPosition; +uniform int SSAOQuality; + +uniform int NormalTextureType; +uniform vec2 DiffuseUVRepeat; +uniform vec2 NormalUVRepeat; +uniform vec2 SpecularUVRepeat; +uniform vec2 GlowUVRepeat; +layout (binding = 0) uniform sampler2D AOTexture; +layout (binding = 1) uniform sampler2D DiffuseTexture; +layout (binding = 2) uniform sampler2D NormalMapTexture; +layout (binding = 3) uniform sampler2D SpecularMapTexture; +layout (binding = 4) uniform sampler2D GlowMapTexture; +layout (binding = 5) uniform samplerCube CubeMap; +layout (binding = 31) uniform sampler2D ShieldBuffer; + +#define TILE_SIZE 16 + +struct LightSource { + vec4 Position; + vec4 Direction; + vec4 Color; + float Radius; + float Intensity; + float Falloff; + int Type; +}; + +layout (std430, binding = 1) buffer LightBuffer +{ + LightSource List[]; +} LightSources; + +struct LightGrid { + float Start; + float Amount; + vec2 Padding; +}; + +layout (std430, binding = 2) buffer LightGridBuffer +{ + LightGrid Data[]; +} LightGrids; + +layout (std430, binding = 4) buffer LightIndexBuffer +{ + float LightIndex[]; +}; + + +in VertexData{ + vec3 Position; + vec4 ViewSpacePosition; + vec3 Normal; + vec3 Tangent; + vec3 BiTangent; + vec2 TextureCoordinate; + vec4 ExplosionColor; + float ExplosionPercentageElapsed; + vec4 PositionLightSpace[MAX_SPLITS]; +}Input; + +out vec4 sceneColor; +out vec4 bloomColor; + +struct LightResult { + vec4 Diffuse; + vec4 Specular; +}; + +float CalcAttenuation(float radius, float dist, float falloff) { + return 1.0 - smoothstep(radius * falloff, radius, dist); +} + +vec4 CalcSpecular(vec4 lightColor, vec4 viewVec, vec4 lightVec, vec4 normal) { + vec4 R = normalize( reflect(-lightVec, normal)); + float RdotV = max( dot(R, viewVec), 0.0); + return lightColor * pow(RdotV, 90.0); +} + +vec4 CalcDiffuse(vec4 lightColor, vec4 lightVec, vec4 normal) { + float power = max( dot(normal, lightVec), 0.0); + return lightColor * power; +} + +LightResult CalcPointLightSource(vec4 lightPos, float lightRadius, vec4 lightColor, float intensity, vec4 viewVec, vec4 position, vec4 normal, float falloff) +{ + vec4 L = lightPos - position; + float dist = length(L); + L = normalize(L); + + float attenuation = CalcAttenuation(lightRadius, dist, falloff); + + LightResult result; + result.Diffuse = CalcDiffuse(lightColor, L, normal) * attenuation * intensity; + result.Specular = CalcSpecular(lightColor, viewVec, L, normal) * attenuation * intensity; + return result; +} + +LightResult CalcDirectionalLightSource(vec4 direction, vec4 color, float intensity, vec4 viewVec, vec4 vertNormal) +{ + vec4 L = normalize( -vec4(direction.xyz, 0) ); + + LightResult result; + result.Diffuse = CalcDiffuse(color, L, vertNormal) * intensity; + result.Specular = CalcSpecular(color, viewVec, L, vertNormal) * intensity; + return result; +} + +void main() +{ + float shieldDepthValue = texelFetch(ShieldBuffer, ivec2(gl_FragCoord.xy), 0).r; + + if(shieldDepthValue < gl_FragCoord.z){ + discard; + } + + float ao = texelFetch(AOTexture, ivec2(gl_FragCoord.xy) >> int(SSAOQuality), 0).r; + ao = (clamp(1.0 - (1.0 - ao), 0.0, 1.0) + MIN_AMBIENT_LIGHT) / (1.0 + MIN_AMBIENT_LIGHT); + vec4 diffuseTexel = texture2D(DiffuseTexture, Input.TextureCoordinate * DiffuseUVRepeat); + vec4 glowTexel = texture2D(GlowMapTexture, Input.TextureCoordinate * GlowUVRepeat); + vec4 specularTexel = texture2D(SpecularMapTexture, Input.TextureCoordinate * SpecularUVRepeat); + vec4 normal = V * CalcNormalMappedValue(Input.Normal, Input.Tangent, Input.BiTangent, Input.TextureCoordinate * NormalUVRepeat, NormalMapTexture, NormalTextureType); + normal = normalize(normal); + //vec4 normal = normalize(V * vec4(Input.Normal, 0.0)); + vec4 viewVec = normalize(-Input.ViewSpacePosition); + vec3 I = normalize(vec3(M * vec4(Input.Position, 1.0)) - CameraPosition); + vec3 R = reflect(-I, Input.Normal); + //R = vec3(P * vec4(R, 1.0)); + vec4 reflectionColor = texture(CubeMap, R); + + vec2 tilePos; + tilePos.x = int(gl_FragCoord.x/TILE_SIZE); + tilePos.y = int(gl_FragCoord.y/TILE_SIZE); + + LightResult totalLighting; + totalLighting.Diffuse = vec4(AmbientColor.rgb * ao, 1.0); + int currentTile = int(floor(gl_FragCoord.x/TILE_SIZE) + (floor(gl_FragCoord.y/TILE_SIZE) * int(ScreenDimensions.x/TILE_SIZE))); + + int start = int(LightGrids.Data[currentTile].Start); + int amount = int(LightGrids.Data[currentTile].Amount); + + for(int i = start; i < start + amount; i++) { + + int l = int(LightIndex[i]); + LightSource light = LightSources.List[l]; + + LightResult light_result; + //These if statements should be removed. + if(light.Type == 1) { // point + light_result = CalcPointLightSource(V * light.Position, light.Radius, light.Color, light.Intensity, viewVec, Input.ViewSpacePosition, normal, light.Falloff); + } else if (light.Type == 2) { //Directional + light_result = CalcDirectionalLightSource(V * light.Direction, light.Color, light.Intensity, viewVec, normal); + } + totalLighting.Diffuse += vec4(light_result.Diffuse.rgb * ao, light_result.Diffuse.a); + totalLighting.Specular += vec4(light_result.Specular.rgb * ao, light_result.Specular.a); + } + + vec4 color_result = mix((Color * diffuseTexel * DiffuseColor), Input.ExplosionColor, Input.ExplosionPercentageElapsed); + color_result = color_result * (totalLighting.Diffuse + (totalLighting.Specular * specularTexel)); + float specularResult = (specularTexel.r + specularTexel.g + specularTexel.b)/3.0; + vec4 reflectionTotal = reflectionColor * (1-specularTexel.a) * color_result.a * (totalLighting.Diffuse + (totalLighting.Specular * specularTexel)); + color_result = color_result * clamp(1/specularTexel.a, 0, 1) + reflectionTotal; + //vec4 color_result = (DiffuseColor + Input.ExplosionColor) * (totalLighting.Diffuse + (totalLighting.Specular * specularTexel)) * diffuseTexel * Color; + + + float pos = ((P * vec4(Input.Position, 1)).y + 1.0)/2.0; + + if(pos <= FillPercentage) { + color_result += FillColor; + } + sceneColor = vec4(color_result.xyz, clamp(color_result.a, 0, 1)); + //sceneColor = vec4(reflectionColor.xyz, 1); + color_result.xyz += glowTexel.xyz*GlowIntensity; + + bloomColor = vec4(max(color_result.xyz - 1.0, 0.0), clamp(color_result.a, 0, 1)); + + //Tiled Debug Code + /* + if(int(gl_FragCoord.x)%16 == 0 || int(gl_FragCoord.y)%16 == 0 ) { + sceneColor += vec4(0.5, 0, 0, 0); + } else { + sceneColor += vec4(LightGrids.Data[int(tilePos.x + tilePos.y*80)].Amount/LightSources.List.length(), 0, 0, 1); + } + */ +} + + diff --git a/resources/Shaders/ForwardPlusSkinned.vert.glsl b/resources/Shaders/ForwardPlusSkinned.vert.glsl index 5fd55a8c..427e33ba 100644 --- a/resources/Shaders/ForwardPlusSkinned.vert.glsl +++ b/resources/Shaders/ForwardPlusSkinned.vert.glsl @@ -1,9 +1,16 @@ #version 430 +#define MAX_SPLITS 4 + +uniform mat4 PVM; +uniform mat4 VM; +uniform mat4 TIM; uniform mat4 M; uniform mat4 V; uniform mat4 P; uniform mat4 Bones[100]; +uniform mat4 LightV[MAX_SPLITS]; +uniform mat4 LightP[MAX_SPLITS]; layout(location = 0) in vec3 Position; layout(location = 1) in vec3 Normal; @@ -15,32 +22,38 @@ layout(location = 6) in vec4 BoneWeights; out VertexData{ vec3 Position; + vec4 ViewSpacePosition; vec3 Normal; vec3 Tangent; vec3 BiTangent; vec2 TextureCoordinate; vec4 ExplosionColor; float ExplosionPercentageElapsed; + vec4 PositionLightSpace[MAX_SPLITS]; }Output; void main() { mat4 boneTransform = mat4(1); - if(BoneWeights[0] > 0.0f){ boneTransform = BoneWeights[0] * Bones[int(BoneIndices[0])] + BoneWeights[1] * Bones[int(BoneIndices[1])] + BoneWeights[2] * Bones[int(BoneIndices[2])] + BoneWeights[3] * Bones[int(BoneIndices[3])]; - } - gl_Position = P*V*M*boneTransform * vec4(Position, 1.0); + gl_Position = PVM*boneTransform * vec4(Position, 1.0); Output.Position = (boneTransform * vec4(Position, 1.0)).xyz; + Output.ViewSpacePosition = VM * vec4(Position, 1.0); Output.TextureCoordinate = TextureCoords; Output.Normal = vec3(M * boneTransform * vec4(Normal, 0.0)); Output.Tangent = vec3(M * vec4(Tangent, 0.0)); Output.BiTangent = vec3(M * vec4(BiTangent, 0.0)); Output.ExplosionColor = vec4(1.0); Output.ExplosionPercentageElapsed = 0.0; + + for(int i = 0; i < MAX_SPLITS; i++) + { + Output.PositionLightSpace[i] = LightP[i] * LightV[i] * M * boneTransform * vec4(Position, 1.0); + } } \ No newline at end of file diff --git a/resources/Shaders/ForwardPlusSplatMap.frag.glsl b/resources/Shaders/ForwardPlusSplatMap.frag.glsl index 239c51b5..655f5502 100644 --- a/resources/Shaders/ForwardPlusSplatMap.frag.glsl +++ b/resources/Shaders/ForwardPlusSplatMap.frag.glsl @@ -1,5 +1,7 @@ #version 430 +#define MAX_SPLITS 4 + uniform mat4 M; uniform mat4 V; uniform mat4 P; @@ -95,6 +97,7 @@ in VertexData{ vec2 TextureCoordinate; vec4 ExplosionColor; float ExplosionPercentageElapsed; + vec4 PositionLightSpace[MAX_SPLITS]; }Input; out vec4 sceneColor; diff --git a/resources/Shaders/ForwardPlusSplatMapRGB.frag.glsl b/resources/Shaders/ForwardPlusSplatMapRGB.frag.glsl index cf358b96..7b1d9e08 100644 --- a/resources/Shaders/ForwardPlusSplatMapRGB.frag.glsl +++ b/resources/Shaders/ForwardPlusSplatMapRGB.frag.glsl @@ -1,7 +1,9 @@ #version 430 -#define MIN_AMBIENT_LIGHT 0.3 +#include "Shaders/Util/CommonNormalFunc.glsl" +#define MIN_AMBIENT_LIGHT 0.3 +#define MAX_SPLITS 4 uniform mat4 M; uniform mat4 V; uniform mat4 P; @@ -11,8 +13,17 @@ uniform vec4 DiffuseColor; uniform vec4 FillColor; uniform vec4 Color; uniform vec4 AmbientColor; +uniform int SSAOQuality; +uniform float FarDistance[MAX_SPLITS]; + +layout (binding = 0) uniform sampler2D AOTexture; +layout (binding = 30) uniform sampler2DArrayShadow DepthMap; //Get bineded at the same time as the textures +uniform int NormalTextureType1; +uniform int NormalTextureType2; +uniform int NormalTextureType3; + uniform vec2 DiffuseUVRepeat1; uniform vec2 DiffuseUVRepeat2; uniform vec2 DiffuseUVRepeat3; @@ -25,7 +36,6 @@ uniform vec2 SpecularUVRepeat3; uniform vec2 GlowUVRepeat1; uniform vec2 GlowUVRepeat2; uniform vec2 GlowUVRepeat3; -layout (binding = 0) uniform sampler2D AOTexture; layout (binding = 1) uniform sampler2D SplatMapTexture; layout (binding = 2) uniform sampler2D DiffuseTexture1; layout (binding = 3) uniform sampler2D DiffuseTexture2; @@ -76,12 +86,14 @@ layout (std430, binding = 4) buffer LightIndexBuffer in VertexData{ vec3 Position; + vec4 ViewSpacePosition; vec3 Normal; vec3 Tangent; vec3 BiTangent; vec2 TextureCoordinate; vec4 ExplosionColor; float ExplosionPercentageElapsed; + vec4 PositionLightSpace[MAX_SPLITS]; }Input; out vec4 sceneColor; @@ -92,6 +104,25 @@ struct LightResult { vec4 Specular; }; +vec2 poissonDisk[16] = vec2[]( + vec2( -0.94201624, -0.39906216 ), + vec2( 0.94558609, -0.76890725 ), + vec2( -0.094184101, -0.92938870 ), + vec2( 0.34495938, 0.29387760 ), + vec2( -0.91588581, 0.45771432 ), + vec2( -0.81544232, -0.87912464 ), + vec2( -0.38277543, 0.27676845 ), + vec2( 0.97484398, 0.75648379 ), + vec2( 0.44323325, -0.97511554 ), + vec2( 0.53742981, -0.47373420 ), + vec2( -0.26496911, -0.41893023 ), + vec2( 0.79197514, 0.19090188 ), + vec2( -0.24188840, 0.99706507 ), + vec2( -0.81409955, 0.91437590 ), + vec2( 0.19984126, 0.78641367 ), + vec2( 0.14383161, -0.14100790 ) + ); + float CalcAttenuation(float radius, float dist, float falloff) { return 1.0 - smoothstep(radius * 0.3, radius, dist); } @@ -156,11 +187,12 @@ vec4 CalcBlendedTexel(vec4 blendValue, sampler2D R, sampler2D G, sampler2D B, } vec4 CalcBlendedNormal(vec4 blendValue, sampler2D R, sampler2D G, sampler2D B, - vec2 R_TileValues, vec2 G_TileValues, vec2 B_TileValues){ + vec2 R_TileValues, vec2 G_TileValues, vec2 B_TileValues, + int R_TextureType, int G_TextureType, int B_TextureType) { mat3 TBN = mat3(Input.Tangent, Input.BiTangent, Input.Normal); - vec3 R_Channel = texture(R, Input.TextureCoordinate * R_TileValues).xyz * 2.0 - vec3(1.0); - vec3 G_Channel = texture(G, Input.TextureCoordinate * G_TileValues).xyz * 2.0 - vec3(1.0); - vec3 B_Channel = texture(B, Input.TextureCoordinate * B_TileValues).xyz * 2.0 - vec3(1.0); + vec3 R_Channel = NormalMapValue(Input.TextureCoordinate * R_TileValues, R, R_TextureType); + vec3 G_Channel = NormalMapValue(Input.TextureCoordinate * G_TileValues, G, G_TextureType); + vec3 B_Channel = NormalMapValue(Input.TextureCoordinate * B_TileValues, B, B_TextureType); float total = blendValue.r + blendValue.g + blendValue.b + blendValue.a; float totalDiv = 1 / total; @@ -175,9 +207,157 @@ vec4 CalcBlendedNormal(vec4 blendValue, sampler2D R, sampler2D G, sampler2D B, return vec4(TBN * normalize(Normal_result), 0.0); } +// Returns a "random" value. +float Random(vec3 seed, int i) +{ + vec4 seed4 = vec4(seed, i); + float dot_product = dot(seed4, vec4(12.9898, 78.233, 45.164, 94.673)); + return fract(sin(dot_product) * 43758.5453); +} + +int getShadowIndex(float far_distance[1]) +{ + return 0; +} + +int getShadowIndex(float far_distance[2]) +{ + float depth = gl_FragCoord.z / gl_FragCoord.w; + + int index = 1; + if ( depth < far_distance[0] ) + { + index = 0; + } + + return index; +} + +int getShadowIndex(float far_distance[3]) +{ + float depth = gl_FragCoord.z / gl_FragCoord.w; + + int index = 2; + if ( depth < far_distance[0] ) + { + index = 0; + } + else if ( depth < far_distance[1] && depth > far_distance[0] ) + { + index = 1; + } + + return index; +} + +int getShadowIndex(float far_distance[4]) +{ + float depth = gl_FragCoord.z / gl_FragCoord.w; + + int index = 3; + if ( depth < far_distance[0] ) + { + index = 0; + } + else if ( depth < far_distance[1] && depth > far_distance[0] ) + { + index = 1; + } + else if ( depth < far_distance[2] && depth > far_distance[1] ) + { + index = 2; + } + + return index; +} + +// Standard hardware-calculated PCF method +float PCFShadow(sampler2DArrayShadow depth_texture_array, vec3 projection_coords, int layer_index) +{ + return texture(depth_texture_array, vec4(projection_coords.xy, layer_index, projection_coords.z)); +} + +// PCF + Poisson model method +float PoissonShadow(sampler2DArrayShadow depth_texture_array, vec3 projection_coords, int layer_index, int taps, float spread) +{ + int loop; + float multiplier = 1.0 / float(taps); + float shadowMapDepth; + + for (int i = 0; i < taps; i++) + { + loop = i; + vec3 newProjCoords = projection_coords + vec3(poissonDisk[loop], 0.0) / (spread * (1.0 + layer_index)); + shadowMapDepth += multiplier * texture(depth_texture_array, vec4(newProjCoords.xy, layer_index, newProjCoords.z)); + } + + return shadowMapDepth; +} + +// PCF + Poisson + RandomSample model method +float PoissonDotShadow(sampler2DArrayShadow depth_texture_array, vec3 projection_coords, int layer_index, int taps, float spread) +{ + int loop; + float multiplier = 1.0 / float(taps); + float shadowMapDepth; + + for (int i = 0; i < taps; i++) + { + loop = int(16.0 * Random(gl_FragCoord.xyy, i)) % 16; + vec3 newProjCoords = projection_coords + vec3(poissonDisk[loop], 0.0) / (spread * (1.0 + layer_index)); + shadowMapDepth += multiplier * texture(depth_texture_array, vec4(newProjCoords.xy, layer_index, newProjCoords.z)); + } + + return shadowMapDepth; +} + +// Hardware PCF + Additional software PCF method +float SoftwarePCF(sampler2DArrayShadow depth_texture_array, vec3 projection_coords, int layer_index, float bias) +{ + float shadow = 0.0; + + vec3 texelSize = 1.0 / textureSize(depth_texture_array, 0); + for(int x = -1; x <= 1; x++) + { + for(int y = -1; y <= 1; y++) + { + shadow += texture(depth_texture_array, vec4(projection_coords.xy + vec2(x, y) * texelSize.xy / (1.0 + layer_index), layer_index, projection_coords.z)); + } + } + + return shadow / 9.0; +} + +float CalcShadowValue(vec4 light_space_pos, vec3 normal, vec3 light_dir, sampler2DArrayShadow depth_texture_array, int layer_index) +{ + float shadowMapDepth; + float bias = 0.005; + + // Various bias methods. + + //bias = max(0.05 * (1.0 - dot(normal, light_dir)), bias); + //bias = bias * tan(acos(clamp(dot(normal, -light_dir), 0.0, 1.0))); + bias = bias + bias * tan(acos(clamp(dot(normal, -light_dir), 0.0, 1.0))); + + // Calculate coordinates in projection space. + + vec3 projCoords = vec3(light_space_pos.xy, light_space_pos.z + bias) / light_space_pos.w; + projCoords = projCoords * 0.5 + 0.5; + //projCoords = (floor(projCoords * 255.0)) / 255.0; + + // Various methods for shadow calculation in fastest to slowest order. + + //shadowMapDepth = PCFShadow(depth_texture_array, projCoords, layer_index); + //shadowMapDepth = PoissonShadow(depth_texture_array, projCoords, layer_index, 4, 25.0 * FarDistance[MAX_SPLITS - 1]); + //shadowMapDepth = PoissonDotShadow(depth_texture_array, projCoords, layer_index, 4, 25.0 * FarDistance[MAX_SPLITS - 1]); + shadowMapDepth = SoftwarePCF(depth_texture_array, projCoords, layer_index, bias); + + return shadowMapDepth; +} + void main() { - float ao = texelFetch(AOTexture, ivec2(gl_FragCoord.xy), 0).r; + float ao = texelFetch(AOTexture, ivec2(gl_FragCoord.xy) >> int(SSAOQuality), 0).r; ao = (clamp(1.0 - (1.0 - ao), 0.0, 1.0) + MIN_AMBIENT_LIGHT) / (1.0 + MIN_AMBIENT_LIGHT); vec4 splatTexel = texture2D(SplatMapTexture, Input.TextureCoordinate); @@ -188,13 +368,13 @@ void main() GlowUVRepeat1, GlowUVRepeat2, GlowUVRepeat3); vec4 specularTexel = CalcBlendedTexel(splatTexel, SpecularMapTexture1, SpecularMapTexture2, SpecularMapTexture3, SpecularUVRepeat1, SpecularUVRepeat2, SpecularUVRepeat3); - vec4 position = V * M * vec4(Input.Position, 1.0); //vec4 normal = V * CalcNormalMappedValue(Input.Normal, Input.Tangent, Input.BiTangent, Input.TextureCoordinate, SplatMapTexture); vec4 normal = V * CalcBlendedNormal(splatTexel, NormalMapTexture1, NormalMapTexture2, NormalMapTexture3, - NormalUVRepeat1, NormalUVRepeat2, NormalUVRepeat3); + NormalUVRepeat1, NormalUVRepeat2, NormalUVRepeat3, + NormalTextureType1, NormalTextureType2, NormalTextureType3); normal = normalize(normal); //vec4 normal = normalize(V * vec4(Input.Normal, 0.0)); - vec4 viewVec = normalize(-position); + vec4 viewVec = normalize(-Input.ViewSpacePosition); vec2 tilePos; tilePos.x = int(gl_FragCoord.x/TILE_SIZE); @@ -207,6 +387,8 @@ void main() int start = int(LightGrids.Data[currentTile].Start); int amount = int(LightGrids.Data[currentTile].Amount); + float shadowFactor = 0.0; + for(int i = start; i < start + amount; i++) { int l = int(LightIndex[i]); @@ -215,14 +397,19 @@ void main() LightResult light_result; //These if statements should be removed. if(light.Type == 1) { // point - light_result = CalcPointLightSource(V * light.Position, light.Radius, light.Color, light.Intensity, viewVec, position, normal, light.Falloff); + light_result = CalcPointLightSource(V * light.Position, light.Radius, light.Color, light.Intensity, viewVec, Input.ViewSpacePosition, normal, light.Falloff); } else if (light.Type == 2) { //Directional + int DepthMapIndex = getShadowIndex(FarDistance); light_result = CalcDirectionalLightSource(V * light.Direction, light.Color, light.Intensity, viewVec, normal); + shadowFactor = CalcShadowValue(Input.PositionLightSpace[DepthMapIndex], Input.Normal, vec3(light.Direction), DepthMap, DepthMapIndex); } totalLighting.Diffuse += vec4(light_result.Diffuse.rgb * ao, light_result.Diffuse.a); totalLighting.Specular += vec4(light_result.Specular.rgb * ao, light_result.Specular.a); } + totalLighting.Diffuse *= vec4(min(vec3(shadowFactor) + AmbientColor.xyz, vec3(1.0)), 1.0); + totalLighting.Specular *= vec4(min(vec3(shadowFactor) + AmbientColor.xyz, vec3(1.0)), 1.0); + vec4 color_result = mix((Color * diffuseTexel * DiffuseColor), Input.ExplosionColor, Input.ExplosionPercentageElapsed); color_result = color_result * (totalLighting.Diffuse + (totalLighting.Specular * specularTexel)); //vec4 color_result = (DiffuseColor + Input.ExplosionColor) * (totalLighting.Diffuse + (totalLighting.Specular * specularTexel)) * diffuseTexel * Color; diff --git a/resources/Shaders/ForwardPlusSplatMapRGBShieldCheck.frag.glsl b/resources/Shaders/ForwardPlusSplatMapRGBShieldCheck.frag.glsl new file mode 100644 index 00000000..e18bf0ad --- /dev/null +++ b/resources/Shaders/ForwardPlusSplatMapRGBShieldCheck.frag.glsl @@ -0,0 +1,262 @@ +#version 430 + +#include "Shaders/Util/CommonNormalFunc.glsl" + +#define MIN_AMBIENT_LIGHT 0.3 +#define MAX_SPLITS 4 +uniform mat4 M; +uniform mat4 V; +uniform mat4 P; +uniform vec2 ScreenDimensions; +uniform float FillPercentage; +uniform vec4 DiffuseColor; +uniform vec4 FillColor; +uniform vec4 Color; +uniform vec4 AmbientColor; +uniform int SSAOQuality; + +//Get bineded at the same time as the textures +uniform int NormalTextureType1; +uniform int NormalTextureType2; +uniform int NormalTextureType3; + +uniform vec2 DiffuseUVRepeat1; +uniform vec2 DiffuseUVRepeat2; +uniform vec2 DiffuseUVRepeat3; +uniform vec2 NormalUVRepeat1; +uniform vec2 NormalUVRepeat2; +uniform vec2 NormalUVRepeat3; +uniform vec2 SpecularUVRepeat1; +uniform vec2 SpecularUVRepeat2; +uniform vec2 SpecularUVRepeat3; +uniform vec2 GlowUVRepeat1; +uniform vec2 GlowUVRepeat2; +uniform vec2 GlowUVRepeat3; +layout (binding = 0) uniform sampler2D AOTexture; +layout (binding = 1) uniform sampler2D SplatMapTexture; +layout (binding = 2) uniform sampler2D DiffuseTexture1; +layout (binding = 3) uniform sampler2D DiffuseTexture2; +layout (binding = 4) uniform sampler2D DiffuseTexture3; +layout (binding = 5) uniform sampler2D NormalMapTexture1; +layout (binding = 6) uniform sampler2D NormalMapTexture2; +layout (binding = 7) uniform sampler2D NormalMapTexture3; +layout (binding = 8) uniform sampler2D SpecularMapTexture1; +layout (binding = 9) uniform sampler2D SpecularMapTexture2; +layout (binding = 10) uniform sampler2D SpecularMapTexture3; +layout (binding = 11) uniform sampler2D GlowMapTexture1; +layout (binding = 12) uniform sampler2D GlowMapTexture2; +layout (binding = 13) uniform sampler2D GlowMapTexture3; +layout (binding = 31) uniform samplerCube ShieldBuffer; + +#define TILE_SIZE 16 + +struct LightSource { + vec4 Position; + vec4 Direction; + vec4 Color; + float Radius; + float Intensity; + float Falloff; + int Type; +}; + +layout (std430, binding = 1) buffer LightBuffer +{ + LightSource List[]; +} LightSources; + +struct LightGrid { + float Start; + float Amount; + vec2 Padding; +}; + +layout (std430, binding = 2) buffer LightGridBuffer +{ + LightGrid Data[]; +} LightGrids; + +layout (std430, binding = 4) buffer LightIndexBuffer +{ + float LightIndex[]; +}; + + +in VertexData{ + vec3 Position; + vec4 ViewSpacePosition; + vec3 Normal; + vec3 Tangent; + vec3 BiTangent; + vec2 TextureCoordinate; + vec4 ExplosionColor; + float ExplosionPercentageElapsed; + vec4 PositionLightSpace[MAX_SPLITS]; +}Input; + +out vec4 sceneColor; +out vec4 bloomColor; + +struct LightResult { + vec4 Diffuse; + vec4 Specular; +}; + +float CalcAttenuation(float radius, float dist, float falloff) { + return 1.0 - smoothstep(radius * 0.3, radius, dist); +} + +vec4 CalcSpecular(vec4 lightColor, vec4 viewVec, vec4 lightVec, vec4 normal) { + vec4 R = normalize( reflect(-lightVec, normal)); + float RdotV = max( dot(R, viewVec), 0.0); + return lightColor * pow(RdotV, 90.0); +} + +vec4 CalcDiffuse(vec4 lightColor, vec4 lightVec, vec4 normal) { + float power = max( dot(normal, lightVec), 0.0); + return lightColor * power; +} + +LightResult CalcPointLightSource(vec4 lightPos, float lightRadius, vec4 lightColor, float intensity, vec4 viewVec, vec4 position, vec4 normal, float falloff) +{ + vec4 L = lightPos - position; + float dist = length(L); + L = normalize(L); + + float attenuation = CalcAttenuation(lightRadius, dist, falloff); + + LightResult result; + result.Diffuse = CalcDiffuse(lightColor, L, normal) * attenuation * intensity; + result.Specular = CalcSpecular(lightColor, viewVec, L, normal) * attenuation * intensity; + return result; +} + +LightResult CalcDirectionalLightSource(vec4 direction, vec4 color, float intensity, vec4 viewVec, vec4 vertNormal) +{ + vec4 L = normalize( -vec4(direction.xyz, 0) ); + + LightResult result; + result.Diffuse = CalcDiffuse(color, L, vertNormal) * intensity; + result.Specular = CalcSpecular(color, viewVec, L, vertNormal) * intensity; + return result; +} + +vec4 CalcNormalMappedValue(vec3 normal, vec3 tangent, vec3 bitangent, vec2 textureCoordinate, sampler2D normalMap) +{ + mat3 TBN = mat3(tangent, bitangent, normal); + vec3 NormalMap = texture(normalMap, textureCoordinate).xyz * 2.0 - vec3(1.0); + return vec4(TBN * normalize(NormalMap), 0.0); +} + +vec4 CalcBlendedTexel(vec4 blendValue, sampler2D R, sampler2D G, sampler2D B, + vec2 R_TileValues, vec2 G_TileValues, vec2 B_TileValues){ + vec4 R_Channel = texture2D(R, Input.TextureCoordinate * R_TileValues); + vec4 G_Channel = texture2D(G, Input.TextureCoordinate * G_TileValues); + vec4 B_Channel = texture2D(B, Input.TextureCoordinate * B_TileValues); + + float total = blendValue.r + blendValue.g + blendValue.b; + float totalDiv = 1.0f / total; + blendValue.r = blendValue.r * totalDiv; + blendValue.g = blendValue.g * totalDiv; + blendValue.b = blendValue.b * totalDiv; + + return blendValue.r * R_Channel + + blendValue.g * G_Channel + + blendValue.b * B_Channel; +} + +vec4 CalcBlendedNormal(vec4 blendValue, sampler2D R, sampler2D G, sampler2D B, + vec2 R_TileValues, vec2 G_TileValues, vec2 B_TileValues, + int R_TextureType, int G_TextureType, int B_TextureType) { + mat3 TBN = mat3(Input.Tangent, Input.BiTangent, Input.Normal); + vec3 R_Channel = NormalMapValue(Input.TextureCoordinate * R_TileValues, R, R_TextureType); + vec3 G_Channel = NormalMapValue(Input.TextureCoordinate * G_TileValues, G, G_TextureType); + vec3 B_Channel = NormalMapValue(Input.TextureCoordinate * B_TileValues, B, B_TextureType); + + float total = blendValue.r + blendValue.g + blendValue.b + blendValue.a; + float totalDiv = 1 / total; + blendValue.r = blendValue.r * totalDiv; + blendValue.g = blendValue.g * totalDiv; + blendValue.b = blendValue.b * totalDiv; + + vec3 Normal_result = blendValue.r * R_Channel + + blendValue.g * G_Channel + + blendValue.b * B_Channel; + + return vec4(TBN * normalize(Normal_result), 0.0); +} + +void main() +{ + float ao = texelFetch(AOTexture, ivec2(gl_FragCoord.xy) >> int(SSAOQuality), 0).r; + ao = (clamp(1.0 - (1.0 - ao), 0.0, 1.0) + MIN_AMBIENT_LIGHT) / (1.0 + MIN_AMBIENT_LIGHT); + + vec4 splatTexel = texture2D(SplatMapTexture, Input.TextureCoordinate); + + vec4 diffuseTexel = CalcBlendedTexel(splatTexel, DiffuseTexture1, DiffuseTexture2, DiffuseTexture3, + DiffuseUVRepeat1, DiffuseUVRepeat2, DiffuseUVRepeat3); + vec4 glowTexel = CalcBlendedTexel(splatTexel, GlowMapTexture1, GlowMapTexture2, GlowMapTexture3, + GlowUVRepeat1, GlowUVRepeat2, GlowUVRepeat3); + vec4 specularTexel = CalcBlendedTexel(splatTexel, SpecularMapTexture1, SpecularMapTexture2, SpecularMapTexture3, + SpecularUVRepeat1, SpecularUVRepeat2, SpecularUVRepeat3); + //vec4 normal = V * CalcNormalMappedValue(Input.Normal, Input.Tangent, Input.BiTangent, Input.TextureCoordinate, SplatMapTexture); + vec4 normal = V * CalcBlendedNormal(splatTexel, NormalMapTexture1, NormalMapTexture2, NormalMapTexture3, + NormalUVRepeat1, NormalUVRepeat2, NormalUVRepeat3, + NormalTextureType1, NormalTextureType2, NormalTextureType3); + normal = normalize(normal); + //vec4 normal = normalize(V * vec4(Input.Normal, 0.0)); + vec4 viewVec = normalize(-Input.ViewSpacePosition); + + vec2 tilePos; + tilePos.x = int(gl_FragCoord.x/TILE_SIZE); + tilePos.y = int(gl_FragCoord.y/TILE_SIZE); + + LightResult totalLighting; + totalLighting.Diffuse = vec4(AmbientColor.rgb * ao, 1.0); + int currentTile = int(floor(gl_FragCoord.x/TILE_SIZE) + (floor(gl_FragCoord.y/TILE_SIZE) * int(ScreenDimensions.x/TILE_SIZE))); + + int start = int(LightGrids.Data[currentTile].Start); + int amount = int(LightGrids.Data[currentTile].Amount); + + for(int i = start; i < start + amount; i++) { + + int l = int(LightIndex[i]); + LightSource light = LightSources.List[l]; + + LightResult light_result; + //These if statements should be removed. + if(light.Type == 1) { // point + light_result = CalcPointLightSource(V * light.Position, light.Radius, light.Color, light.Intensity, viewVec, Input.ViewSpacePosition, normal, light.Falloff); + } else if (light.Type == 2) { //Directional + light_result = CalcDirectionalLightSource(V * light.Direction, light.Color, light.Intensity, viewVec, normal); + } + totalLighting.Diffuse += vec4(light_result.Diffuse.rgb * ao, light_result.Diffuse.a); + totalLighting.Specular += vec4(light_result.Specular.rgb * ao, light_result.Specular.a); + } + + vec4 color_result = mix((Color * diffuseTexel * DiffuseColor), Input.ExplosionColor, Input.ExplosionPercentageElapsed); + color_result = color_result * (totalLighting.Diffuse + (totalLighting.Specular * specularTexel)); + //vec4 color_result = (DiffuseColor + Input.ExplosionColor) * (totalLighting.Diffuse + (totalLighting.Specular * specularTexel)) * diffuseTexel * Color; + + + float pos = ((P * vec4(Input.Position, 1)).y + 1.0)/2.0; + + if(pos <= FillPercentage) { + color_result += FillColor; + } + sceneColor = vec4(color_result.xyz, clamp(color_result.a, 0, 1)); + color_result += glowTexel*3; + + bloomColor = vec4(clamp(color_result.xyz - 1.0, 0, 100), 1.0); + + //Tiled Debug Code + /* + if(int(gl_FragCoord.x)%16 == 0 || int(gl_FragCoord.y)%16 == 0 ) { + sceneColor += vec4(0.5, 0, 0, 0); + } else { + sceneColor += vec4(LightGrids.Data[int(tilePos.x + tilePos.y*80)].Amount/LightSources.List.length(), 0, 0, 1); + } + */ +} + + diff --git a/resources/Shaders/Gaussian_horiz.frag.glsl b/resources/Shaders/Gaussian_horiz.frag.glsl index 6a9572c2..06426ed3 100644 --- a/resources/Shaders/Gaussian_horiz.frag.glsl +++ b/resources/Shaders/Gaussian_horiz.frag.glsl @@ -2,6 +2,7 @@ #extension GL_EXT_gpu_shader4 : enable layout (binding = 0) uniform sampler2D Texture; +uniform int Lod; in VertexData{ vec2 TextureCoordinate; @@ -10,15 +11,21 @@ in VertexData{ out vec4 fragmentColor; uniform float weight[5] = float[](0.227027, 0.1945946, 0.1216216, 0.054054, 0.016216); +//uniform float weight[3] = float[](0.265495, 0.226535, 0.140718); void main() { - vec2 tex_offset = 1.0 / textureSize2D(Texture, 0); - vec3 result = texture(Texture, Input.TextureCoordinate).rgb * weight[0]; + vec2 tex_offset = 1.0 / textureSize(Texture, Lod); + vec3 center = texture(Texture, Input.TextureCoordinate).rgb; + vec3 result = center * weight[0]; for(int i = 1; i < 5; ++i) { - result += texture(Texture, Input.TextureCoordinate + vec2(tex_offset.x * i, 0.0)).rgb * weight[i]; - result += texture(Texture, Input.TextureCoordinate - vec2(tex_offset.x * i, 0.0)).rgb * weight[i]; + vec4 eastFragments = texture(Texture, Input.TextureCoordinate + vec2(tex_offset.x * i, 0.0)); + vec4 westFragments = texture(Texture, Input.TextureCoordinate - vec2(tex_offset.x * i, 0.0)); + result += eastFragments.rgb * weight[i] * eastFragments.a; + result += westFragments.rgb * weight[i] * westFragments.a; + result += center * weight[i] * (1.0 - westFragments.a); + result += center * weight[i] * (1.0 - eastFragments.a); } fragmentColor = vec4(result, 1.0); } \ No newline at end of file diff --git a/resources/Shaders/Gaussian_vert.frag.glsl b/resources/Shaders/Gaussian_vert.frag.glsl index 8b0e861a..3924450a 100644 --- a/resources/Shaders/Gaussian_vert.frag.glsl +++ b/resources/Shaders/Gaussian_vert.frag.glsl @@ -2,6 +2,7 @@ #extension GL_EXT_gpu_shader4 : enable layout (binding = 0) uniform sampler2D Texture; +uniform int Lod; in VertexData{ vec2 TextureCoordinate; @@ -10,15 +11,21 @@ in VertexData{ out vec4 fragmentColor; uniform float weight[5] = float[](0.227027, 0.1945946, 0.1216216, 0.054054, 0.016216); +//uniform float weight[3] = float[](0.265495, 0.226535, 0.140718); void main() { - vec2 tex_offset = 1.0 / textureSize2D(Texture, 0); - vec3 result = texture(Texture, Input.TextureCoordinate).rgb * weight[0]; + vec2 tex_offset = 1.0 / textureSize(Texture, Lod); + vec3 center = texture(Texture, Input.TextureCoordinate).rgb; + vec3 result = center * weight[0]; for(int i = 1; i < 5; ++i) { - result += texture(Texture, Input.TextureCoordinate + vec2(0.0, tex_offset.y * i)).rgb * weight[i]; - result += texture(Texture, Input.TextureCoordinate - vec2(0.0, tex_offset.y * i)).rgb * weight[i]; + vec4 northFragments = texture(Texture, Input.TextureCoordinate + vec2(0.0, tex_offset.y * i)); + vec4 southFragments = texture(Texture, Input.TextureCoordinate - vec2(0.0, tex_offset.y * i)); + result += northFragments.rgb * weight[i] * northFragments.a; + result += southFragments.rgb * weight[i] * southFragments.a; + result += center * weight[i] * (1.0 - northFragments.a); + result += center * weight[i] * (1.0 - southFragments.a); } fragmentColor = vec4(result, 1.0); } \ No newline at end of file diff --git a/resources/Shaders/Picking.vert.glsl b/resources/Shaders/Picking.vert.glsl index f888cd16..00013383 100644 --- a/resources/Shaders/Picking.vert.glsl +++ b/resources/Shaders/Picking.vert.glsl @@ -1,8 +1,5 @@ #version 430 - -uniform mat4 M; -uniform mat4 V; -uniform mat4 P; +uniform mat4 PVM; layout(location = 0) in vec3 Position; layout(location = 1) in vec3 Normal; @@ -16,6 +13,6 @@ out VertexData{ void main() { - gl_Position = P*V*M * vec4(Position, 1.0); + gl_Position = PVM * vec4(Position, 1.0); Output.Position = Position, 1.0; } \ No newline at end of file diff --git a/resources/Shaders/PickingSkinned.vert.glsl b/resources/Shaders/PickingSkinned.vert.glsl index 205a8fdd..44061e64 100644 --- a/resources/Shaders/PickingSkinned.vert.glsl +++ b/resources/Shaders/PickingSkinned.vert.glsl @@ -1,8 +1,5 @@ #version 430 - -uniform mat4 M; -uniform mat4 V; -uniform mat4 P; +uniform mat4 PVM; uniform mat4 Bones[100]; layout(location = 0) in vec3 Position; @@ -20,13 +17,11 @@ out VertexData{ void main() { mat4 boneTransform = mat4(1); - if(BoneWeights[0] > 0.0f){ boneTransform = BoneWeights[0] * Bones[int(BoneIndices[0])] + BoneWeights[1] * Bones[int(BoneIndices[1])] + BoneWeights[2] * Bones[int(BoneIndices[2])] + BoneWeights[3] * Bones[int(BoneIndices[3])]; - } - gl_Position = P*V*M*boneTransform * vec4(Position, 1.0); + gl_Position = PVM*boneTransform * vec4(Position, 1.0); Output.Position = (boneTransform * vec4(Position, 1.0)).xyz; } \ No newline at end of file diff --git a/resources/Shaders/SSAO.frag.glsl b/resources/Shaders/SSAO.frag.glsl index 68c830f8..749881c4 100644 --- a/resources/Shaders/SSAO.frag.glsl +++ b/resources/Shaders/SSAO.frag.glsl @@ -2,11 +2,11 @@ //Number of samples per pixel uniform int uNumOfSamples; -//#define NUM_SAMPLES (11) +//#define uNumOfSamples (11) //Number of turns around the cirle uniform int uNumOfTurns; -//#define NUM_TURNS (7) +//#define uNumOfTurns (7) layout (binding = 0) uniform sampler2D ViewSpaceZ; @@ -16,15 +16,16 @@ uniform float uProjScale; //#define ProjScale 500 uniform float uRadius; -//#define Radius 1.0f +//#define uRadius 1.0f uniform float uBias; -//#define Bias 0.012f +//#define uBias 0.05f uniform float uContrast; -//#define IntensityDivR6 1 +//#define uContrast 1.5f uniform float uIntensityScale; +//#define uIntensityScale 1.0f out float AO; @@ -88,13 +89,7 @@ void main() { vec3 origin = getVSPosition(originScreenCoord); - float radius; - if(origin.z < uRadius){ - radius = origin.z; - } else { - radius = uRadius; - } - + float radius = min(origin.z, uRadius); vec3 originNormal = getVSFaceNormal(origin); diff --git a/resources/Shaders/SSAO.vert.glsl b/resources/Shaders/SSAO.vert.glsl index a019c5ef..346bc141 100644 --- a/resources/Shaders/SSAO.vert.glsl +++ b/resources/Shaders/SSAO.vert.glsl @@ -2,7 +2,12 @@ layout (location = 0) in vec3 Position; +out VertexData{ + vec2 TextureCoordinate; +}Output; + void main() { gl_Position = vec4(Position, 1.0); + Output.TextureCoordinate = (vec2(Position) + 1) / 2; } \ No newline at end of file diff --git a/resources/Shaders/SSAOViewSpaceZ.frag.glsl b/resources/Shaders/SSAOViewSpaceZ.frag.glsl index dbcfd899..d1bf6f17 100644 --- a/resources/Shaders/SSAOViewSpaceZ.frag.glsl +++ b/resources/Shaders/SSAOViewSpaceZ.frag.glsl @@ -3,11 +3,15 @@ layout (binding = 0) uniform sampler2D DepthBuffer; uniform vec3 ClipInfo; +in VertexData{ + vec2 TextureCoordinate; +}Input; + out float depthLinear; //Just for Debug, should be depthLinear //out vec4 fragmentColor; void main() { - float depthSample = texelFetch(DepthBuffer, ivec2(gl_FragCoord.xy), 0).r; + float depthSample = texture2D(DepthBuffer, Input.TextureCoordinate).r; depthLinear = ClipInfo[0] / (ClipInfo[1] * depthSample + ClipInfo[2]); //float depthLinear = (NearClip) / ( -depthSample + 1.0f); //fragmentColor = vec4(depthLinear, depthLinear, depthLinear, 1.0f); diff --git a/resources/Shaders/Shadow.frag.glsl b/resources/Shaders/Shadow.frag.glsl new file mode 100644 index 00000000..c7d153c3 --- /dev/null +++ b/resources/Shaders/Shadow.frag.glsl @@ -0,0 +1,22 @@ +#version 430 + +#define ALPHA_CUTOFF 0.3 + +layout (binding = 24) uniform sampler2D DiffuseTexture; +uniform float Alpha; + +in VertexData{ + vec2 TextureCoordinate; +}Input; + +layout (location = 0) out float ShadowMap; + +void main() +{ + vec4 diffuseTexel = texture(DiffuseTexture, Input.TextureCoordinate) * Alpha; + + if (diffuseTexel.a < ALPHA_CUTOFF) + { + discard; + } +} \ No newline at end of file diff --git a/resources/Shaders/Shadow.vert.glsl b/resources/Shaders/Shadow.vert.glsl new file mode 100644 index 00000000..667b0401 --- /dev/null +++ b/resources/Shaders/Shadow.vert.glsl @@ -0,0 +1,16 @@ +#version 430 + +uniform mat4 PVM; + +layout (location = 0) in vec3 Position; +layout (location = 4) in vec2 TextureCoords; + +out VertexData{ + vec2 TextureCoordinate; +}Output; + +void main() +{ + gl_Position = PVM * vec4(Position, 1.0); + Output.TextureCoordinate = TextureCoords; +} \ No newline at end of file diff --git a/resources/Shaders/ShadowSkinned.vert.glsl b/resources/Shaders/ShadowSkinned.vert.glsl new file mode 100644 index 00000000..ce20aec2 --- /dev/null +++ b/resources/Shaders/ShadowSkinned.vert.glsl @@ -0,0 +1,25 @@ +#version 430 + +uniform mat4 PVM; +uniform mat4 Bones[100]; + +layout (location = 0) in vec3 Position; +layout (location = 4) in vec2 TextureCoords; +layout(location = 5) in vec4 BoneIndices; +layout(location = 6) in vec4 BoneWeights; + +out VertexData{ + vec2 TextureCoordinate; +}Output; + +void main() +{ + mat4 boneTransform = mat4(1); + boneTransform = BoneWeights[0] * Bones[int(BoneIndices[0])] + + BoneWeights[1] * Bones[int(BoneIndices[1])] + + BoneWeights[2] * Bones[int(BoneIndices[2])] + + BoneWeights[3] * Bones[int(BoneIndices[3])]; + + gl_Position = PVM * boneTransform * vec4(Position, 1.0); + Output.TextureCoordinate = TextureCoords; +} \ No newline at end of file diff --git a/resources/Shaders/Sprite.frag.glsl b/resources/Shaders/Sprite.frag.glsl index 754be6ac..6a7169e1 100644 --- a/resources/Shaders/Sprite.frag.glsl +++ b/resources/Shaders/Sprite.frag.glsl @@ -3,8 +3,8 @@ uniform vec4 Color; uniform vec4 FillColor; uniform float FillPercentage; -uniform mat4 M; -uniform mat4 V; +uniform float ScaleX; +uniform float ScaleY; uniform mat4 P; layout (binding = 1) uniform sampler2D DiffuseTexture; @@ -23,19 +23,21 @@ out vec4 bloomColor; void main() { - vec4 diffuseTexel = texture2D(DiffuseTexture, Input.TextureCoordinate); - vec4 glowTexel = texture2D(GlowMapTexture, Input.TextureCoordinate); + vec4 diffuseTexel = texture2D(DiffuseTexture, vec2(Input.TextureCoordinate.x*ScaleX, Input.TextureCoordinate.y*ScaleY)); + vec4 glowTexel = texture2D(GlowMapTexture, vec2(Input.TextureCoordinate.x*ScaleX, Input.TextureCoordinate.y*ScaleY)); vec4 color_result = Color * diffuseTexel; float pos = ((P * vec4(Input.Position, 1)).y + 1.0)/2.0; - if(pos <= FillPercentage) { - color_result = FillColor*diffuseTexel.a; - } + float fillResult = clamp(floor(pos/FillPercentage), 0, 1); + + color_result = FillColor*diffuseTexel.a*(1 - fillResult) + color_result*fillResult; + sceneColor = vec4(color_result.xyz, clamp(color_result.a, 0, 1)); //bloomColor = vec4(clamp((glowTexel.xyz*3) - 1.0, 0, 100), 1.0); - bloomColor = vec4(1.0, 1.0, 1.0, 0.0); + bloomColor = vec4(max(color_result.xyz - 1.0, 0.0), clamp(color_result.a, 0, 1)); + //bloomColor = vec4(1.0, 1.0, 1.0, 0.0); } diff --git a/resources/Shaders/Sprite.vert.glsl b/resources/Shaders/Sprite.vert.glsl index c09d745b..82c4c9bb 100644 --- a/resources/Shaders/Sprite.vert.glsl +++ b/resources/Shaders/Sprite.vert.glsl @@ -1,8 +1,6 @@ #version 430 -uniform mat4 M; -uniform mat4 V; -uniform mat4 P; +uniform mat4 PVM; layout(location = 0) in vec3 Position; layout(location = 1) in vec3 Normal; @@ -17,7 +15,7 @@ out VertexData{ void main() { - gl_Position = P * V * M * vec4(Position, 1.0); + gl_Position = PVM* vec4(Position, 1.0); Output.Position = Position; Output.TextureCoordinate = TextureCoords; diff --git a/resources/Shaders/SpriteShieldCheck.frag.glsl b/resources/Shaders/SpriteShieldCheck.frag.glsl new file mode 100644 index 00000000..754be6ac --- /dev/null +++ b/resources/Shaders/SpriteShieldCheck.frag.glsl @@ -0,0 +1,41 @@ +#version 430 + +uniform vec4 Color; +uniform vec4 FillColor; +uniform float FillPercentage; +uniform mat4 M; +uniform mat4 V; +uniform mat4 P; + +layout (binding = 1) uniform sampler2D DiffuseTexture; +layout (binding = 2) uniform sampler2D GlowMapTexture; + + +in VertexData{ + vec3 Position; + vec3 Normal; + vec2 TextureCoordinate; +}Input; + + +out vec4 sceneColor; +out vec4 bloomColor; + +void main() +{ + vec4 diffuseTexel = texture2D(DiffuseTexture, Input.TextureCoordinate); + vec4 glowTexel = texture2D(GlowMapTexture, Input.TextureCoordinate); + + vec4 color_result = Color * diffuseTexel; + + float pos = ((P * vec4(Input.Position, 1)).y + 1.0)/2.0; + if(pos <= FillPercentage) { + color_result = FillColor*diffuseTexel.a; + } + sceneColor = vec4(color_result.xyz, clamp(color_result.a, 0, 1)); + + //bloomColor = vec4(clamp((glowTexel.xyz*3) - 1.0, 0, 100), 1.0); + bloomColor = vec4(1.0, 1.0, 1.0, 0.0); +} + + diff --git a/resources/Shaders/Util/CommonNormalFunc.glsl b/resources/Shaders/Util/CommonNormalFunc.glsl new file mode 100644 index 00000000..ea6cc3f1 Binary files /dev/null and b/resources/Shaders/Util/CommonNormalFunc.glsl differ diff --git a/resources/Shaders/Util/CommonUniforms.glsl b/resources/Shaders/Util/CommonUniforms.glsl new file mode 100644 index 00000000..de6700ae --- /dev/null +++ b/resources/Shaders/Util/CommonUniforms.glsl @@ -0,0 +1,6 @@ +vec4 CalcNormalMappedValue(vec3 normal, vec3 tangent, vec3 bitangent, vec2 textureCoordinate, sampler2D normalMap) +{ + mat3 TBN = mat3(tangent, bitangent, normal); + vec3 NormalMap = texture(normalMap, textureCoordinate).xyz * 2.0 - vec3(1.0); + return vec4(TBN * normalize(NormalMap), 0.0); +} \ No newline at end of file diff --git a/resources/TacticalZ.rc b/resources/TacticalZ.rc new file mode 100755 index 00000000..640a9490 Binary files /dev/null and b/resources/TacticalZ.rc differ diff --git a/src/Engine/Collision/Collision.cpp b/src/Engine/Collision/Collision.cpp index 68d99d92..ae09aeaf 100644 --- a/src/Engine/Collision/Collision.cpp +++ b/src/Engine/Collision/Collision.cpp @@ -146,14 +146,14 @@ bool RayVsTriangle(const Ray& ray, } bool RayVsModel(const Ray& ray, - const RawModel::Vertex* modelVertices, + const std::vector& modelVertices, const std::vector& modelIndices, 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++]], modelMatrix); + glm::vec3 v1 = TransformSystem::TransformPoint(modelVertices[modelIndices[i++]], modelMatrix); + glm::vec3 v2 = TransformSystem::TransformPoint(modelVertices[modelIndices[i++]], modelMatrix); if (RayVsTriangle(ray, v0, v1, v2)) { return true; } @@ -194,7 +194,7 @@ bool RayVsTriangle(const Ray& ray, } bool RayVsModel(const Ray& ray, - const RawModel::Vertex* modelVertices, + const std::vector& modelVertices, const std::vector& modelIndices, const glm::mat4& modelMatrix, float& outDistance, @@ -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++]], modelMatrix); + glm::vec3 v1 = TransformSystem::TransformPoint(modelVertices[modelIndices[i++]], modelMatrix); + glm::vec3 v2 = TransformSystem::TransformPoint(modelVertices[modelIndices[i++]], modelMatrix); float dist = outDistance; float u; float v; @@ -221,7 +221,7 @@ bool RayVsModel(const Ray& ray, } bool RayVsModel(const Ray& ray, - const RawModel::Vertex* modelVertices, + const std::vector& modelVertices, const std::vector& modelIndices, const glm::mat4& modelMatrix, glm::vec3& outHitPosition) @@ -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,11 +544,11 @@ bool AABBvsTriangle(const AABB& box, boxVelocity = boxVelocity - glm::dot(boxVelocity, projNorm) * projNorm; } } - return true; + return BoxTriRes::Intersect; } -bool AABBvsTriangles(const AABB& box, - const RawModel::Vertex* modelVertices, +Output AABBvsTriangles(const AABB& box, + const std::vector& modelVertices, const std::vector& modelIndices, const glm::mat4& modelMatrix, glm::vec3& boxVelocity, @@ -546,38 +557,45 @@ 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++]], modelMatrix), + TransformSystem::TransformPoint(modelVertices[modelIndices[i++]], modelMatrix), + TransformSystem::TransformPoint(modelVertices[modelIndices[i++]], 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, - const RawModel::Vertex* modelVertices, + const std::vector& modelVertices, const std::vector& modelIndices, const glm::mat4& modelMatrix, glm::vec3& boxVelocity, @@ -593,11 +611,29 @@ bool AABBvsTriangles(const AABB& box, verticalStepHeight, isOnGround, outResolutionVector, - true); + true) == Output::OutIntersecting; } bool AABBvsTriangles(const AABB& box, - const RawModel::Vertex* modelVertices, + const std::vector& 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 std::vector& modelVertices, const std::vector& modelIndices, const glm::mat4& modelMatrix) { @@ -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->m_Vertices, model->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 95609ea6..e53143ac 100644 --- a/src/Engine/Collision/CollisionSystem.cpp +++ b/src/Engine/Collision/CollisionSystem.cpp @@ -17,105 +17,114 @@ void CollisionSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& c EntityAABB& boxA = *boundingBox; bool everHitTheGround = false; - auto prevPosIt = m_PrevPositions.find(entity); - if (prevPosIt != m_PrevPositions.end()) { - glm::vec3 size = boxA.Size(); - float diameter = std::min(size.x, size.z); - glm::vec3 prevOrigin = prevPosIt->second; - glm::vec3 toCurrentPos = boxA.Origin() - prevOrigin; - float rayLength = glm::length(toCurrentPos) + 0.5f*diameter; - //If the entity has moved farther than the size of its box, we need to handle it specially. - if (rayLength > diameter) { - Ray ray(prevOrigin, toCurrentPos); - m_OctreeResult.clear(); - m_Octree->ObjectsPossiblyHitByRay(ray, m_OctreeResult); - for (auto& boxB : m_OctreeResult) { - if (boxA.Entity == boxB.Entity) { - continue; - } - bool hit; - float dist; - if (boxB.Entity.HasComponent("Model")) { - RawModel* model; - std::string res = (std::string)boxB.Entity["Model"]["Resource"]; - try { - model = ResourceManager::Load(res); - } catch (const std::exception&) { + if (entity == LocalPlayer) { + auto prevPosIt = m_PrevPositions.find(entity); + if (prevPosIt != m_PrevPositions.end()) { + glm::vec3 size = boxA.Size(); + float diameter = std::min(size.x, size.z); + glm::vec3 prevOrigin = prevPosIt->second; + glm::vec3 toCurrentPos = boxA.Origin() - prevOrigin; + float rayLength = glm::length(toCurrentPos) + 0.5f*diameter; + //If the entity has moved farther than the size of its box, we need to handle it specially. + if (rayLength > diameter) { + Ray ray(prevOrigin, toCurrentPos); + m_OctreeResult.clear(); + m_Octree->ObjectsPossiblyHitByRay(ray, m_OctreeResult); + for (auto& boxB : m_OctreeResult) { + if (boxA.Entity == boxB.Entity) { continue; } - float u, v; - hit = Collision::RayVsModel(ray, model->Vertices(), model->m_Indices, Transform::ModelMatrix(boxB.Entity), dist, u, v); - } else { - hit = Collision::RayVsAABB(ray, boxB, dist); - } - if (hit && dist < rayLength) { - //Set the entity to where it was colliding, minus the maximum box size. - //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; - boxA = *Collision::EntityAbsoluteAABB(entity); - if (resolve.y > 0) { - everHitTheGround = true; - (bool)cPhysics["IsOnGround"] = true; - ((glm::vec3&)cPhysics["Velocity"]).y = 0.f; + bool hit; + float dist; + if (boxB.Entity.HasComponent("Model")) { + if (!((bool)boxB.Entity["Model"]["Visible"])) { + // Don't collide against invisible models. + continue; + } + Model* model; + std::string res = (std::string)boxB.Entity["Model"]["Resource"]; + try { + model = ResourceManager::Load(res); + } catch (const std::exception&) { + continue; + } + float u, v; + hit = Collision::RayVsModel(ray, model->m_Vertices, model->m_Indices, TransformSystem::ModelMatrix(boxB.Entity), dist, u, v); + } else { + hit = Collision::RayVsAABB(ray, boxB, dist); + } + if (hit && dist < rayLength) { + //Set the entity to where it was colliding, minus the maximum box size. + //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(); + (Field)cTransform["Position"] += resolve; + boxA = *Collision::EntityAbsoluteAABB(entity); + if (resolve.y > 0) { + everHitTheGround = true; + cPhysics["IsOnGround"] = true; + ((Field)cPhysics["Velocity"]).y(0.f); + } + break; } - break; } } } - } - // Collide against octree items - m_OctreeResult.clear(); - m_Octree->ObjectsInSameRegion(*boundingBox, m_OctreeResult); - for (auto& boxB : m_OctreeResult) { - glm::vec3 resolutionVector; - if (boxA.Entity == boxB.Entity) { - continue; - } - - if (boxB.Entity.HasComponent("Model") && Collision::AABBVsAABB(boxA, boxB)) { - //Here we know boxB is a entity with Collideable, AABB, and Model. - RawModel* model; - try { - model = ResourceManager::Load(boxB.Entity["Model"]["Resource"]); - } catch (const std::exception&) { + // Collide against octree items + m_OctreeResult.clear(); + m_Octree->ObjectsInSameRegion(*boundingBox, m_OctreeResult); + for (auto& boxB : m_OctreeResult) { + glm::vec3 resolutionVector; + if (boxA.Entity == boxB.Entity) { continue; } - glm::mat4 modelMatrix = Transform::ModelMatrix(boxB.Entity); + if (boxB.Entity.HasComponent("Model") && Collision::AABBVsAABB(boxA, boxB)) { + // 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; + } + Model* model; + try { + model = ResourceManager::Load(boxB.Entity["Model"]["Resource"]); + } catch (const std::exception&) { + continue; + } - 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; + glm::mat4 modelMatrix = TransformSystem::ModelMatrix(boxB.Entity); + + glm::vec3 inOutVelocity = (glm::vec3)cPhysics["Velocity"]; + bool isOnGround = (bool)cPhysics["IsOnGround"]; + float verticalStepHeight = (float)(double)cPhysics["VerticalStepHeight"]; + if (Collision::AABBvsTriangles(boxA, model->m_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. + (Field)cTransform["Position"] += resolutionVector; + boxA = *Collision::EntityAbsoluteAABB(entity); + cPhysics["Velocity"] = inOutVelocity; + if (isOnGround) { + everHitTheGround = true; + (bool)cPhysics["IsOnGround"] = true; + } + } + } else if (Collision::AABBVsAABB(boxA, boxB, resolutionVector)) { + //Enter here if boxB has no Model. + (Field)cTransform["Position"] += resolutionVector; boxA = *Collision::EntityAbsoluteAABB(entity); - cPhysics["Velocity"] = inOutVelocity; - if (isOnGround) { + if (resolutionVector.y > 0) { everHitTheGround = true; (bool)cPhysics["IsOnGround"] = true; + ((Field)cPhysics["Velocity"]).y(0.f); } } - } else if (Collision::AABBVsAABB(boxA, boxB, resolutionVector)) { - //Enter here if boxB has no Model. - (glm::vec3&)cTransform["Position"] += resolutionVector; - boxA = *Collision::EntityAbsoluteAABB(entity); - if (resolutionVector.y > 0) { - everHitTheGround = true; - (bool)cPhysics["IsOnGround"] = true; - ((glm::vec3&)cPhysics["Velocity"]).y = 0.f; - } } - } - //This should apply air friction and such, iff zero models were hit. - if (!everHitTheGround) { - (bool)cPhysics["IsOnGround"] = false; - } + //This should apply air friction and such, iff zero models were hit. + if (!everHitTheGround) { + (bool)cPhysics["IsOnGround"] = false; + } - m_PrevPositions[entity] = boxA.Origin(); + m_PrevPositions[entity] = boxA.Origin(); + } } diff --git a/src/Engine/Collision/TriggerSystem.cpp b/src/Engine/Collision/TriggerSystem.cpp index 21a47721..ef790bc9 100644 --- a/src/Engine/Collision/TriggerSystem.cpp +++ b/src/Engine/Collision/TriggerSystem.cpp @@ -10,6 +10,16 @@ void TriggerSystem::UpdateComponent(EntityWrapper& triggerEntity, ComponentWrapp return; } + Model* 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->m_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/EntityFile.cpp b/src/Engine/Core/EntityFile.cpp index 3987b092..997b9c46 100644 --- a/src/Engine/Core/EntityFile.cpp +++ b/src/Engine/Core/EntityFile.cpp @@ -1,291 +1,25 @@ #include "Core/EntityFile.h" -EntityFile::EntityFile(boost::filesystem::path path) - : m_FilePath(path) +EntityFile::EntityFile(std::string path) { - using namespace xercesc; - XMLPlatformUtils::Initialize(); - m_GrammarPool = new XMLGrammarPoolImpl(); - m_SAX2XMLReader = XMLReaderFactory::createXMLReader(XMLPlatformUtils::fgMemoryManager, m_GrammarPool); -} + EntityXMLFile* xml = ResourceManager::Load(path); -EntityFile::~EntityFile() -{ - delete m_SAX2XMLReader; - delete m_GrammarPool; - xercesc::XMLPlatformUtils::Terminate(); -} + EntityXMLFilePreprocessor preprocessor(xml); + preprocessor.RegisterComponents(this); -void EntityFile::Parse(const EntityFileHandler* handler) const -{ - using namespace xercesc; + EntityXMLFileParser parser(xml); + m_RootEntity = parser.MergeEntities(this); - EntityFileSAXHandler saxHandler(handler, m_SAX2XMLReader); - setReaderFeatures(m_SAX2XMLReader); - m_SAX2XMLReader->setContentHandler(&saxHandler); - m_SAX2XMLReader->setErrorHandler(&saxHandler); - m_SAX2XMLReader->setDeclarationHandler(&saxHandler); - m_SAX2XMLReader->parse(m_FilePath.string().c_str()); -} - -void EntityFile::setReaderFeatures(xercesc::SAX2XMLReader* reader) -{ - using namespace xercesc; - reader->setFeature(XMLUni::fgXercesCacheGrammarFromParse, true); - reader->setFeature(XMLUni::fgXercesUseCachedGrammarInParse, true); - reader->setFeature(XMLUni::fgSAX2CoreValidation, true); - reader->setFeature(XMLUni::fgSAX2CoreNameSpaces, true); - reader->setFeature(XMLUni::fgXercesSchema, true); - reader->setFeature(XMLUni::fgXercesSchemaFullChecking, true); - reader->setFeature(XMLUni::fgXercesCalculateSrcOfs, true); - reader->setFeature(XMLUni::fgXercesIdentityConstraintChecking, true); -} - -unsigned int EntityFile::GetTypeStride(std::string typeName) -{ - std::map typeStrides{ - { "bool", sizeof(bool) }, - { "int", sizeof(int) }, - { "float", sizeof(float) }, - { "double", sizeof(double) }, - { "string", sizeof(std::string) }, - { "enum", sizeof(ComponentInfo::EnumType) }, - { "Vector", sizeof(glm::vec3) }, - { "Quaternion", sizeof(glm::quat) }, - { "Color", sizeof(glm::vec4) } - }; - - auto it = typeStrides.find(typeName); - return (it != typeStrides.end()) ? it->second : 0; -} - -void EntityFile::WriteAttributeData(char* outData, const ComponentInfo::Field_t& field, const std::map& attributes) -{ - if (field.Type == "Vector") { - glm::vec3 vec; - vec.x = boost::lexical_cast(attributes.at("X")); - vec.y = boost::lexical_cast(attributes.at("Y")); - vec.z = boost::lexical_cast(attributes.at("Z")); - memcpy(outData, reinterpret_cast(&vec), field.Stride); - } else if (field.Type == "Color") { - glm::vec4 vec; - vec.r = boost::lexical_cast(attributes.at("R")); - vec.g = boost::lexical_cast(attributes.at("G")); - vec.b = boost::lexical_cast(attributes.at("B")); - vec.a = boost::lexical_cast(attributes.at("A")); - memcpy(outData, reinterpret_cast(&vec), field.Stride); - } else if (field.Type == "Quaternion") { - glm::quat q; - q.x = boost::lexical_cast(attributes.at("X")); - q.y = boost::lexical_cast(attributes.at("Y")); - q.z = boost::lexical_cast(attributes.at("Z")); - q.w = boost::lexical_cast(attributes.at("W")); - memcpy(outData, reinterpret_cast(&q), field.Stride); - } else if (!attributes.empty()) { - LOG_WARNING("%i attributes not handled by any type conversion!", attributes.size()); - } -} - -void EntityFile::WriteValueData(char* outData, const ComponentInfo::Field_t& field, const char* valueData) -{ - // Catch and ignore casting errors so whitespace around string enums won't mess anything up - try { - if (field.Type == "int") { - int value = boost::lexical_cast(valueData); - memcpy(outData, reinterpret_cast(&value), field.Stride); - } else if (field.Type == "enum") { - ComponentInfo::EnumType value = boost::lexical_cast(valueData); - memcpy(outData, reinterpret_cast(&value), field.Stride); - } else if (field.Type == "float") { - float value = boost::lexical_cast(valueData); - memcpy(outData, reinterpret_cast(&value), field.Stride); - } else if (field.Type == "double") { - double value = boost::lexical_cast(valueData); - memcpy(outData, reinterpret_cast(&value), field.Stride); - } else if (field.Type == "bool") { - bool value = (valueData[0] == 't'); // Lazy bool evaluation - memcpy(outData, reinterpret_cast(&value), field.Stride); - } else if (field.Type == "string") { - new (outData) std::string(valueData); - } else { - LOG_WARNING("Unknown value data type: %s", field.Type.c_str()); - } - } catch (const boost::bad_lexical_cast&) { } -} - -EntityFileSAXHandler::EntityFileSAXHandler(const EntityFileHandler* handler, xercesc::SAX2XMLReader* reader) - : m_Handler(handler) - , m_Reader(reader) -{ - // 0 is imaginary base parent - m_EntityStack.push(0); - m_StateStack.push(State::Unknown); -} - -void EntityFileSAXHandler::startElement(const XMLCh* const _uri, const XMLCh* const _localName, const XMLCh* const _qname, const xercesc::Attributes& attrs) -{ - std::string name = XS::ToString(_localName); - - if (m_StateStack.top() == State::Unknown || m_StateStack.top() == State::Entity) { - if (name == "Entity") { - m_StateStack.push(State::Entity); - onStartEntity(attrs); - return; - } - if (name == "EntityRef") { - onStartEntityRef(attrs); - return; - } + if (m_RootEntity == EntityID_Invalid) { + ResourceManager::Release("EntityXMLFile", path); + throw Resource::FailedLoadingException("Failed to merge entities; root entity is invalid"); } - std::string uri = XS::ToString(_uri); - if (m_StateStack.top() == State::Entity) { - if (uri == "components") { - m_StateStack.push(State::Component); - onStartComponent(name); - return; - } - } - - if (m_StateStack.top() == State::Component) { - m_StateStack.push(State::ComponentField); - onStartComponentField(name, attrs); - return; - } + ResourceManager::Release("EntityXMLFile", path); } -void EntityFileSAXHandler::endElement(const XMLCh* const _uri, const XMLCh* const _localName, const XMLCh* const _qname) +EntityWrapper EntityFile::MergeInto(World* other) { - std::string name = XS::ToString(_localName); - if (m_StateStack.top() == State::Entity) { - if (name == "Entity") { - m_StateStack.pop(); - onEndEntity(); - return; - } - } - - std::string uri = XS::ToString(_uri); - if (m_StateStack.top() == State::Component) { - //if (uri == "components") { - m_StateStack.pop(); - onEndComponent(name); - return; - //} - } - - if (m_StateStack.top() == State::ComponentField && name == m_CurrentField) { - m_StateStack.pop(); - onEndComponentField(name); - return; - } -} - -void EntityFileSAXHandler::characters(const XMLCh* const chars, const XMLSize_t length) -{ - if (m_StateStack.top() == State::ComponentField) { - char* transcoded = xercesc::XMLString::transcode(chars); - onFieldData(transcoded); - } -} - -void EntityFileSAXHandler::fatalError(const xercesc::SAXParseException& e) -{ - std::string message = XS::ToString(e.getMessage()); - std::string systemId = XS::ToString(e.getSystemId()); - XMLFileLoc line = e.getLineNumber(); - XMLFileLoc column = e.getColumnNumber(); - LOG_ERROR("SAXParseException\n\tLocation: %s:%i:%i\n\tFatal Error: %s", systemId.c_str(), line, column, message.c_str()); -} - -void EntityFileSAXHandler::error(const xercesc::SAXParseException& e) -{ - std::string message = XS::ToString(e.getMessage()); - std::string systemId = XS::ToString(e.getSystemId()); - XMLFileLoc line = e.getLineNumber(); - XMLFileLoc column = e.getColumnNumber(); - LOG_ERROR("SAXParseException\n\tLocation: %s:%i:%i\n\tError: %s", systemId.c_str(), line, column, message.c_str()); -} - -void EntityFileSAXHandler::warning(const xercesc::SAXParseException& e) -{ - std::string message = XS::ToString(e.getMessage()); - std::string systemId = XS::ToString(e.getSystemId()); - XMLFileLoc line = e.getLineNumber(); - XMLFileLoc column = e.getColumnNumber(); - LOG_ERROR("SAXParseException\n\tLocation: %s:%i:%i\n\tWarning: %s", systemId.c_str(), line, column, message.c_str()); -} - -void EntityFileSAXHandler::onStartEntity(const xercesc::Attributes& attrs) -{ - EntityID parent = m_EntityStack.top(); - - if (m_Handler->m_OnStartEntityCallback) { - std::string name; - auto xName = attrs.getValue(XS::ToXMLCh("name")); - if (xName != nullptr) { - name = XS::ToString(xName); - } - m_Handler->m_OnStartEntityCallback(m_NextEntityID, parent, name); - } - - m_EntityStack.push(m_NextEntityID); - m_NextEntityID++; -} - -void EntityFileSAXHandler::onEndEntity() -{ - m_EntityStack.pop(); -} - -void EntityFileSAXHandler::onStartEntityRef(const xercesc::Attributes& attrs) -{ - std::string path = XS::ToString(attrs.getValue(XS::ToXMLCh("file"))); - - xercesc::SAX2XMLReader* reader = xercesc::XMLReaderFactory::createXMLReader(); - EntityFile::setReaderFeatures(reader); - reader->setContentHandler(this); - reader->setErrorHandler(this); - reader->parse(path.c_str()); - delete reader; -} - -void EntityFileSAXHandler::onStartComponentField(const std::string& field, const xercesc::Attributes& attrs) -{ - //LOG_DEBUG(" Field: %s", field.c_str()); - m_CurrentField = field; - m_CurrentAttributes.clear(); - for (int i = 0; i < attrs.getLength(); i++) { - auto name = attrs.getQName(i); - auto value = attrs.getValue(name); - //LOG_DEBUG(" %s = %s", (char*)XS::ToString(name), (char*)XS::ToString(value)); - m_CurrentAttributes[XS::ToString(name).operator std::string()] = XS::ToString(value).operator std::string(); - } - - if (m_Handler->m_OnStartFieldCallback) { - m_Handler->m_OnStartFieldCallback(m_EntityStack.top(), m_CurrentComponent, field, m_CurrentAttributes); - } -} - -void EntityFileSAXHandler::onEndComponent(const std::string& name) { } - -void EntityFileSAXHandler::onStartComponent(const std::string& name) -{ - //LOG_DEBUG(" Component: %s", name.c_str()); - m_CurrentComponent = name; - if (m_Handler->m_OnStartComponentCallback) { - m_Handler->m_OnStartComponentCallback(m_EntityStack.top(), name); - } -} - -void EntityFileSAXHandler::onEndComponentField(const std::string& field) { } - -void EntityFileSAXHandler::onFieldData(char* data) -{ - //LOG_DEBUG(" Data: %s", data); - if (m_Handler->m_OnStartFieldDataCallback) { - m_Handler->m_OnStartFieldDataCallback(m_EntityStack.top(), m_CurrentComponent, m_CurrentField, data); - } - - xercesc::XMLString::release(&data); -} + auto mapping = other->Merge(this); + return EntityWrapper(other, mapping.at(m_RootEntity)); +} \ No newline at end of file diff --git a/src/Engine/Core/EntityFileParser.cpp b/src/Engine/Core/EntityFileParser.cpp deleted file mode 100644 index 23c0c4c4..00000000 --- a/src/Engine/Core/EntityFileParser.cpp +++ /dev/null @@ -1,74 +0,0 @@ -#include "Core/EntityFileParser.h" - -EntityFileParser::EntityFileParser(const EntityFile* entityFile) - : m_EntityFile(entityFile) -{ - m_Handler.SetStartEntityCallback(std::bind(&EntityFileParser::onStartEntity, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); - m_Handler.SetStartComponentCallback(std::bind(&EntityFileParser::onStartComponent, this, std::placeholders::_1, std::placeholders::_2)); - m_Handler.SetStartFieldCallback(std::bind(&EntityFileParser::onStartComponentField, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4)); - m_Handler.SetStartFieldDataCallback(std::bind(&EntityFileParser::onFieldData, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4)); -} - -EntityID EntityFileParser::MergeEntities(World* world, EntityID baseParent /*= EntityID_Invalid */) -{ - m_World = world; - m_EntityIDMapper[0] = baseParent; - m_EntityFile->Parse(&m_Handler); - return m_FirstEntity; -} - -void EntityFileParser::onStartEntity(EntityID entity, EntityID parent, const std::string& name) -{ - EntityID realParent = m_EntityIDMapper.at(parent); - EntityID realEntity = m_World->CreateEntity(realParent); - if (m_FirstEntity == EntityID_Invalid) { - m_FirstEntity = realEntity; - } - if (!name.empty()) { - m_World->SetName(realEntity, name); - } - m_EntityIDMapper[entity] = realEntity; - //LOG_DEBUG("Created entity #%i (%i) with parent %i (%i)", entity, realEntity, parent, realParent); -} - -void EntityFileParser::onStartComponent(EntityID entity, const std::string& component) -{ - EntityID realEntity = m_EntityIDMapper.at(entity); - m_World->AttachComponent(realEntity, component); - //LOG_DEBUG("Attached component of type \"%s\" to entity #%i (%i)", component.c_str(), entity, realEntity); -} - -void EntityFileParser::onStartComponentField(EntityID entity, const std::string& componentType, const std::string& fieldName, const std::map& attributes) -{ - EntityID realEntity = m_EntityIDMapper.at(entity); - ComponentWrapper component = m_World->GetComponent(realEntity, componentType); - auto fieldIt = component.Info.Fields.find(fieldName); - if (fieldIt == component.Info.Fields.end()) { - LOG_ERROR("Tried to set unknown field \"%s\" of component type \"%s\"! Ignoring.", fieldName.c_str(), componentType.c_str()); - return; - } - auto& field = fieldIt->second; - - //LOG_DEBUG("Field \"%s\" type \"%s\"", fieldName.c_str(), field.Type.c_str()); - //LOG_DEBUG("Attributes:"); - //for (auto& kv : attributes) { - // LOG_DEBUG("\t%s = %s", kv.first.c_str(), kv.second.c_str()); - //} - - char* data = component.Data + field.Offset; - EntityFile::WriteAttributeData(data, field, attributes); -} - -void EntityFileParser::onFieldData(EntityID entity, const std::string& componentType, const std::string& fieldName, const char* fieldData) -{ - EntityID realEntity = m_EntityIDMapper.at(entity); - ComponentWrapper component = m_World->GetComponent(realEntity, componentType); - auto fieldIt = component.Info.Fields.find(fieldName); - if (fieldIt == component.Info.Fields.end()) { - return; - } - auto& field = fieldIt->second; - - char* data = component.Data + field.Offset; - EntityFile::WriteValueData(data, field, fieldData); -} diff --git a/src/Engine/Core/EntityWrapper.cpp b/src/Engine/Core/EntityWrapper.cpp index b3bef55a..ba6cafe0 100644 --- a/src/Engine/Core/EntityWrapper.cpp +++ b/src/Engine/Core/EntityWrapper.cpp @@ -3,7 +3,7 @@ const EntityWrapper EntityWrapper::Invalid = EntityWrapper(nullptr, EntityID_Invalid); -const std::string EntityWrapper::Name() +const std::string EntityWrapper::Name() const { return World->GetName(ID); } @@ -27,20 +27,69 @@ void EntityWrapper::AttachComponent(const char* componentName) EntityWrapper EntityWrapper::Parent() { - if (this->World == nullptr || this->ID == EntityID_Invalid) { + if (!Valid()) { return EntityWrapper::Invalid; } else { return EntityWrapper(this->World, this->World->GetParent(this->ID)); } } +EntityWrapper EntityWrapper::FirstParentByName(const std::string& parentEntityName) +{ + if (!Valid()) { + return EntityWrapper::Invalid; + } + + EntityWrapper entity = *this; + while (entity.Parent().Valid()) { + entity = entity.Parent(); + if (entity.Name() == parentEntityName) { + return entity; + } + } + return EntityWrapper::Invalid; +} + EntityWrapper EntityWrapper::FirstChildByName(const std::string& name) { + if (!Valid()) { + return EntityWrapper::Invalid; + } + return firstChildByNameRecursive(name, this->ID); } + +EntityWrapper EntityWrapper::FirstLevelChildByName(const std::string& name) +{ + EntityID parent = this->ID; + if (!this->World->ValidEntity(parent)) { + return EntityWrapper::Invalid; + } + + auto itPair = this->World->GetDirectChildren(parent); + if (itPair.first == itPair.second) { + return EntityWrapper::Invalid; + } + + for (auto it = itPair.first; it != itPair.second; ++it) { + std::string itName = this->World->GetName(it->second); + if (itName == name) { + return EntityWrapper(this->World, it->second); + } else if (it->second != EntityID_Invalid) { + continue; + } + } + + return EntityWrapper::Invalid; +} + EntityWrapper EntityWrapper::FirstParentWithComponent(const std::string& componentType) { + if (!Valid()) { + return EntityWrapper::Invalid; + } + EntityWrapper entity = *this; while (entity.Parent().Valid()) { entity = entity.Parent(); @@ -57,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; } @@ -170,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); @@ -209,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/EntityXMLFile.cpp b/src/Engine/Core/EntityXMLFile.cpp new file mode 100644 index 00000000..b32d952d --- /dev/null +++ b/src/Engine/Core/EntityXMLFile.cpp @@ -0,0 +1,291 @@ +#include "Core/EntityXMLFile.h" + +EntityXMLFile::EntityXMLFile(boost::filesystem::path path) + : m_FilePath(path) +{ + using namespace xercesc; + XMLPlatformUtils::Initialize(); + m_GrammarPool = new XMLGrammarPoolImpl(); + m_SAX2XMLReader = XMLReaderFactory::createXMLReader(XMLPlatformUtils::fgMemoryManager, m_GrammarPool); +} + +EntityXMLFile::~EntityXMLFile() +{ + delete m_SAX2XMLReader; + delete m_GrammarPool; + xercesc::XMLPlatformUtils::Terminate(); +} + +void EntityXMLFile::Parse(const EntityFileHandler* handler) const +{ + using namespace xercesc; + + EntityFileSAXHandler saxHandler(handler, m_SAX2XMLReader); + setReaderFeatures(m_SAX2XMLReader); + m_SAX2XMLReader->setContentHandler(&saxHandler); + m_SAX2XMLReader->setErrorHandler(&saxHandler); + m_SAX2XMLReader->setDeclarationHandler(&saxHandler); + m_SAX2XMLReader->parse(m_FilePath.string().c_str()); +} + +void EntityXMLFile::setReaderFeatures(xercesc::SAX2XMLReader* reader) +{ + using namespace xercesc; + reader->setFeature(XMLUni::fgXercesCacheGrammarFromParse, true); + reader->setFeature(XMLUni::fgXercesUseCachedGrammarInParse, true); + reader->setFeature(XMLUni::fgSAX2CoreValidation, true); + reader->setFeature(XMLUni::fgSAX2CoreNameSpaces, true); + reader->setFeature(XMLUni::fgXercesSchema, true); + reader->setFeature(XMLUni::fgXercesSchemaFullChecking, true); + reader->setFeature(XMLUni::fgXercesCalculateSrcOfs, true); + reader->setFeature(XMLUni::fgXercesIdentityConstraintChecking, true); +} + +unsigned int EntityXMLFile::GetTypeStride(std::string typeName) +{ + std::map typeStrides{ + { "bool", sizeof(bool) }, + { "int", sizeof(int) }, + { "float", sizeof(float) }, + { "double", sizeof(double) }, + { "string", sizeof(std::string) }, + { "enum", sizeof(ComponentInfo::EnumType) }, + { "Vector", sizeof(glm::vec3) }, + { "Quaternion", sizeof(glm::quat) }, + { "Color", sizeof(glm::vec4) } + }; + + auto it = typeStrides.find(typeName); + return (it != typeStrides.end()) ? it->second : 0; +} + +void EntityXMLFile::WriteAttributeData(char* outData, const ComponentInfo::Field_t& field, const std::map& attributes) +{ + if (field.Type == "Vector") { + glm::vec3 vec; + vec.x = boost::lexical_cast(attributes.at("X")); + vec.y = boost::lexical_cast(attributes.at("Y")); + vec.z = boost::lexical_cast(attributes.at("Z")); + memcpy(outData, reinterpret_cast(&vec), field.Stride); + } else if (field.Type == "Color") { + glm::vec4 vec; + vec.r = boost::lexical_cast(attributes.at("R")); + vec.g = boost::lexical_cast(attributes.at("G")); + vec.b = boost::lexical_cast(attributes.at("B")); + vec.a = boost::lexical_cast(attributes.at("A")); + memcpy(outData, reinterpret_cast(&vec), field.Stride); + } else if (field.Type == "Quaternion") { + glm::quat q; + q.x = boost::lexical_cast(attributes.at("X")); + q.y = boost::lexical_cast(attributes.at("Y")); + q.z = boost::lexical_cast(attributes.at("Z")); + q.w = boost::lexical_cast(attributes.at("W")); + memcpy(outData, reinterpret_cast(&q), field.Stride); + } else if (!attributes.empty()) { + LOG_WARNING("%i attributes not handled by any type conversion!", attributes.size()); + } +} + +void EntityXMLFile::WriteValueData(char* outData, const ComponentInfo::Field_t& field, const char* valueData) +{ + // Catch and ignore casting errors so whitespace around string enums won't mess anything up + try { + if (field.Type == "int") { + int value = boost::lexical_cast(valueData); + memcpy(outData, reinterpret_cast(&value), field.Stride); + } else if (field.Type == "enum") { + ComponentInfo::EnumType value = boost::lexical_cast(valueData); + memcpy(outData, reinterpret_cast(&value), field.Stride); + } else if (field.Type == "float") { + float value = boost::lexical_cast(valueData); + memcpy(outData, reinterpret_cast(&value), field.Stride); + } else if (field.Type == "double") { + double value = boost::lexical_cast(valueData); + memcpy(outData, reinterpret_cast(&value), field.Stride); + } else if (field.Type == "bool") { + bool value = (valueData[0] == 't'); // Lazy bool evaluation + memcpy(outData, reinterpret_cast(&value), field.Stride); + } else if (field.Type == "string") { + new (outData) std::string(valueData); + } else { + LOG_WARNING("Unknown value data type: %s", field.Type.c_str()); + } + } catch (const boost::bad_lexical_cast&) { } +} + +EntityFileSAXHandler::EntityFileSAXHandler(const EntityFileHandler* handler, xercesc::SAX2XMLReader* reader) + : m_Handler(handler) + , m_Reader(reader) +{ + // 0 is imaginary base parent + m_EntityStack.push(0); + m_StateStack.push(State::Unknown); +} + +void EntityFileSAXHandler::startElement(const XMLCh* const _uri, const XMLCh* const _localName, const XMLCh* const _qname, const xercesc::Attributes& attrs) +{ + std::string name = XS::ToString(_localName); + + if (m_StateStack.top() == State::Unknown || m_StateStack.top() == State::Entity) { + if (name == "Entity") { + m_StateStack.push(State::Entity); + onStartEntity(attrs); + return; + } + if (name == "EntityRef") { + onStartEntityRef(attrs); + return; + } + } + + std::string uri = XS::ToString(_uri); + if (m_StateStack.top() == State::Entity) { + if (uri == "components") { + m_StateStack.push(State::Component); + onStartComponent(name); + return; + } + } + + if (m_StateStack.top() == State::Component) { + m_StateStack.push(State::ComponentField); + onStartComponentField(name, attrs); + return; + } +} + +void EntityFileSAXHandler::endElement(const XMLCh* const _uri, const XMLCh* const _localName, const XMLCh* const _qname) +{ + std::string name = XS::ToString(_localName); + if (m_StateStack.top() == State::Entity) { + if (name == "Entity") { + m_StateStack.pop(); + onEndEntity(); + return; + } + } + + std::string uri = XS::ToString(_uri); + if (m_StateStack.top() == State::Component) { + //if (uri == "components") { + m_StateStack.pop(); + onEndComponent(name); + return; + //} + } + + if (m_StateStack.top() == State::ComponentField && name == m_CurrentField) { + m_StateStack.pop(); + onEndComponentField(name); + return; + } +} + +void EntityFileSAXHandler::characters(const XMLCh* const chars, const XMLSize_t length) +{ + if (m_StateStack.top() == State::ComponentField) { + char* transcoded = xercesc::XMLString::transcode(chars); + onFieldData(transcoded); + } +} + +void EntityFileSAXHandler::fatalError(const xercesc::SAXParseException& e) +{ + std::string message = XS::ToString(e.getMessage()); + std::string systemId = XS::ToString(e.getSystemId()); + XMLFileLoc line = e.getLineNumber(); + XMLFileLoc column = e.getColumnNumber(); + LOG_ERROR("SAXParseException\n\tLocation: %s:%i:%i\n\tFatal Error: %s", systemId.c_str(), line, column, message.c_str()); +} + +void EntityFileSAXHandler::error(const xercesc::SAXParseException& e) +{ + std::string message = XS::ToString(e.getMessage()); + std::string systemId = XS::ToString(e.getSystemId()); + XMLFileLoc line = e.getLineNumber(); + XMLFileLoc column = e.getColumnNumber(); + LOG_ERROR("SAXParseException\n\tLocation: %s:%i:%i\n\tError: %s", systemId.c_str(), line, column, message.c_str()); +} + +void EntityFileSAXHandler::warning(const xercesc::SAXParseException& e) +{ + std::string message = XS::ToString(e.getMessage()); + std::string systemId = XS::ToString(e.getSystemId()); + XMLFileLoc line = e.getLineNumber(); + XMLFileLoc column = e.getColumnNumber(); + LOG_ERROR("SAXParseException\n\tLocation: %s:%i:%i\n\tWarning: %s", systemId.c_str(), line, column, message.c_str()); +} + +void EntityFileSAXHandler::onStartEntity(const xercesc::Attributes& attrs) +{ + EntityID parent = m_EntityStack.top(); + + if (m_Handler->m_OnStartEntityCallback) { + std::string name; + auto xName = attrs.getValue(XS::ToXMLCh("name")); + if (xName != nullptr) { + name = XS::ToString(xName); + } + m_Handler->m_OnStartEntityCallback(m_NextEntityID, parent, name); + } + + m_EntityStack.push(m_NextEntityID); + m_NextEntityID++; +} + +void EntityFileSAXHandler::onEndEntity() +{ + m_EntityStack.pop(); +} + +void EntityFileSAXHandler::onStartEntityRef(const xercesc::Attributes& attrs) +{ + std::string path = XS::ToString(attrs.getValue(XS::ToXMLCh("file"))); + + xercesc::SAX2XMLReader* reader = xercesc::XMLReaderFactory::createXMLReader(); + EntityXMLFile::setReaderFeatures(reader); + reader->setContentHandler(this); + reader->setErrorHandler(this); + reader->parse(path.c_str()); + delete reader; +} + +void EntityFileSAXHandler::onStartComponentField(const std::string& field, const xercesc::Attributes& attrs) +{ + //LOG_DEBUG(" Field: %s", field.c_str()); + m_CurrentField = field; + m_CurrentAttributes.clear(); + for (int i = 0; i < attrs.getLength(); i++) { + auto name = attrs.getQName(i); + auto value = attrs.getValue(name); + //LOG_DEBUG(" %s = %s", (char*)XS::ToString(name), (char*)XS::ToString(value)); + m_CurrentAttributes[XS::ToString(name).operator std::string()] = XS::ToString(value).operator std::string(); + } + + if (m_Handler->m_OnStartFieldCallback) { + m_Handler->m_OnStartFieldCallback(m_EntityStack.top(), m_CurrentComponent, field, m_CurrentAttributes); + } +} + +void EntityFileSAXHandler::onEndComponent(const std::string& name) { } + +void EntityFileSAXHandler::onStartComponent(const std::string& name) +{ + //LOG_DEBUG(" Component: %s", name.c_str()); + m_CurrentComponent = name; + if (m_Handler->m_OnStartComponentCallback) { + m_Handler->m_OnStartComponentCallback(m_EntityStack.top(), name); + } +} + +void EntityFileSAXHandler::onEndComponentField(const std::string& field) { } + +void EntityFileSAXHandler::onFieldData(char* data) +{ + //LOG_DEBUG(" Data: %s", data); + if (m_Handler->m_OnStartFieldDataCallback) { + m_Handler->m_OnStartFieldDataCallback(m_EntityStack.top(), m_CurrentComponent, m_CurrentField, data); + } + + xercesc::XMLString::release(&data); +} diff --git a/src/Engine/Core/EntityXMLFileParser.cpp b/src/Engine/Core/EntityXMLFileParser.cpp new file mode 100644 index 00000000..9c79775c --- /dev/null +++ b/src/Engine/Core/EntityXMLFileParser.cpp @@ -0,0 +1,84 @@ +#include "Core/EntityXMLFileParser.h" + +EntityXMLFileParser::EntityXMLFileParser(const EntityXMLFile* entityFile) + : m_EntityFile(entityFile) +{ + m_Handler.SetStartEntityCallback(std::bind(&EntityXMLFileParser::onStartEntity, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); + m_Handler.SetStartComponentCallback(std::bind(&EntityXMLFileParser::onStartComponent, this, std::placeholders::_1, std::placeholders::_2)); + m_Handler.SetStartFieldCallback(std::bind(&EntityXMLFileParser::onStartComponentField, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4)); + m_Handler.SetStartFieldDataCallback(std::bind(&EntityXMLFileParser::onFieldData, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4)); +} + +EntityID EntityXMLFileParser::MergeEntities(World* world, EntityID baseParent /*= EntityID_Invalid */) +{ + m_World = world; + m_EntityIDMapper[0] = baseParent; + m_EntityFile->Parse(&m_Handler); + return m_FirstEntity; +} + +void EntityXMLFileParser::onStartEntity(EntityID entity, EntityID parent, const std::string& name) +{ + EntityID realParent = m_EntityIDMapper.at(parent); + EntityID realEntity = m_World->CreateEntity(realParent); + if (m_FirstEntity == EntityID_Invalid) { + m_FirstEntity = realEntity; + } + if (!name.empty()) { + m_World->SetName(realEntity, name); + } + m_EntityIDMapper[entity] = realEntity; + //LOG_DEBUG("Created entity #%i (%i) with parent %i (%i)", entity, realEntity, parent, realParent); +} + +void EntityXMLFileParser::onStartComponent(EntityID entity, const std::string& component) +{ + if (m_World->GetComponentPools().count(component) != 0) { + EntityID realEntity = m_EntityIDMapper.at(entity); + m_World->AttachComponent(realEntity, component); + } else { + LOG_ERROR("Tried to attach unregistered component \"%s\"! to entity #%i. Ignoring.", component.c_str(), entity); + } + //LOG_DEBUG("Attached component of type \"%s\" to entity #%i (%i)", component.c_str(), entity, realEntity); +} + +void EntityXMLFileParser::onStartComponentField(EntityID entity, const std::string& componentType, const std::string& fieldName, const std::map& attributes) +{ + if (m_World->GetComponentPools().count(componentType) == 0) { + return; + } + EntityID realEntity = m_EntityIDMapper.at(entity); + ComponentWrapper component = m_World->GetComponent(realEntity, componentType); + auto fieldIt = component.Info.Fields.find(fieldName); + if (fieldIt == component.Info.Fields.end()) { + LOG_ERROR("Tried to set unknown field \"%s\" of component type \"%s\"! Ignoring.", fieldName.c_str(), componentType.c_str()); + return; + } + auto& field = fieldIt->second; + + //LOG_DEBUG("Field \"%s\" type \"%s\"", fieldName.c_str(), field.Type.c_str()); + //LOG_DEBUG("Attributes:"); + //for (auto& kv : attributes) { + // LOG_DEBUG("\t%s = %s", kv.first.c_str(), kv.second.c_str()); + //} + + char* data = component.Data + field.Offset; + EntityXMLFile::WriteAttributeData(data, field, attributes); +} + +void EntityXMLFileParser::onFieldData(EntityID entity, const std::string& componentType, const std::string& fieldName, const char* fieldData) +{ + if (m_World->GetComponentPools().count(componentType) == 0) { + return; + } + EntityID realEntity = m_EntityIDMapper.at(entity); + ComponentWrapper component = m_World->GetComponent(realEntity, componentType); + auto fieldIt = component.Info.Fields.find(fieldName); + if (fieldIt == component.Info.Fields.end()) { + return; + } + auto& field = fieldIt->second; + + char* data = component.Data + field.Offset; + EntityXMLFile::WriteValueData(data, field, fieldData); +} diff --git a/src/Engine/Core/EntityFilePreprocessor.cpp b/src/Engine/Core/EntityXMLFilePreprocessor.cpp similarity index 92% rename from src/Engine/Core/EntityFilePreprocessor.cpp rename to src/Engine/Core/EntityXMLFilePreprocessor.cpp index 592daedb..132d962a 100644 --- a/src/Engine/Core/EntityFilePreprocessor.cpp +++ b/src/Engine/Core/EntityXMLFilePreprocessor.cpp @@ -1,10 +1,10 @@ -#include "Core/EntityFilePreprocessor.h" +#include "Core/EntityXMLFilePreprocessor.h" -EntityFilePreprocessor::EntityFilePreprocessor(const EntityFile* entityFile) +EntityXMLFilePreprocessor::EntityXMLFilePreprocessor(const EntityXMLFile* entityFile) : m_EntityFile(entityFile) { EntityFileHandler handler; - handler.SetStartComponentCallback(std::bind(&EntityFilePreprocessor::onStartComponent, this, std::placeholders::_1, std::placeholders::_2)); + handler.SetStartComponentCallback(std::bind(&EntityXMLFilePreprocessor::onStartComponent, this, std::placeholders::_1, std::placeholders::_2)); m_EntityFile->Parse(&handler); //LOG_DEBUG("___ COMPONENT DEFINITIONS ___"); @@ -28,20 +28,20 @@ EntityFilePreprocessor::EntityFilePreprocessor(const EntityFile* entityFile) parseDefaults(); } -void EntityFilePreprocessor::RegisterComponents(World* world) +void EntityXMLFilePreprocessor::RegisterComponents(World* world) { for (auto& kv : m_ComponentInfo) { world->RegisterComponent(kv.second); } } -void EntityFilePreprocessor::onStartComponent(EntityID entity, std::string type) +void EntityXMLFilePreprocessor::onStartComponent(EntityID entity, std::string type) { //LOG_DEBUG("Component: %s", type.c_str()); m_ComponentCounts[type]++; } -void EntityFilePreprocessor::parseComponentInfo() +void EntityXMLFilePreprocessor::parseComponentInfo() { using namespace xercesc; EntityFileXMLErrorHandler errorHandler; @@ -125,6 +125,7 @@ void EntityFilePreprocessor::parseComponentInfo() auto modelGroup = modelGroupParticle->getModelGroupTerm(); // getParticles(); for (unsigned int i = 0; i < particles->size(); ++i) { @@ -141,9 +142,9 @@ void EntityFilePreprocessor::parseComponentInfo() std::string baseType = XS::ToString(elementDeclaration->getTypeDefinition()->getBaseType()->getName()); std::string effectiveType = type; - unsigned int stride = EntityFile::GetTypeStride(type); + unsigned int stride = EntityXMLFile::GetTypeStride(type); if (stride == 0) { - stride = EntityFile::GetTypeStride(baseType); + stride = EntityXMLFile::GetTypeStride(baseType); if (stride == 0) { LOG_WARNING("Field \"%s\" in component \"%s\" uses unexpected field type \"%s\" with base type \"%s\". Skipping.", name.c_str(), compInfo.Name.c_str(), type.c_str(), baseType.c_str()); continue; @@ -182,12 +183,14 @@ void EntityFilePreprocessor::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; } @@ -196,7 +199,7 @@ void EntityFilePreprocessor::parseComponentInfo() } } -void EntityFilePreprocessor::parseDefaults() +void EntityXMLFilePreprocessor::parseDefaults() { using namespace xercesc; @@ -261,7 +264,7 @@ void EntityFilePreprocessor::parseDefaults() auto attribItem = attributeMap->item(i); attributes[XS::ToString(attribItem->getNodeName())] = XS::ToString(attribItem->getNodeValue()); } - EntityFile::WriteAttributeData(data, field, attributes); + EntityXMLFile::WriteAttributeData(data, field, attributes); } auto childNode = fieldElement->getFirstChild(); @@ -278,14 +281,14 @@ void EntityFilePreprocessor::parseDefaults() // Handle potential field values if (childNode->getNodeType() == DOMNode::TEXT_NODE) { char* cstrValue = XMLString::transcode(childNode->getNodeValue()); - EntityFile::WriteValueData(data, field, cstrValue); + EntityXMLFile::WriteValueData(data, field, cstrValue); XMLString::release(&cstrValue); } } } } -std::string EntityFilePreprocessor::parseAnnotationXML(const XMLCh* xml) +std::string EntityXMLFilePreprocessor::parseAnnotationXML(const XMLCh* xml) { using namespace xercesc; diff --git a/src/Engine/Core/EntityFileWriter.cpp b/src/Engine/Core/EntityXMLFileWriter.cpp similarity index 94% rename from src/Engine/Core/EntityFileWriter.cpp rename to src/Engine/Core/EntityXMLFileWriter.cpp index 06a3c4ca..a98d3fbd 100644 --- a/src/Engine/Core/EntityFileWriter.cpp +++ b/src/Engine/Core/EntityXMLFileWriter.cpp @@ -1,13 +1,13 @@ -#include "Core/EntityFileWriter.h" +#include "Core/EntityXMLFileWriter.h" #define X(str) XS::ToXMLCh(str) -void EntityFileWriter::WriteWorld(World* world) +void EntityXMLFileWriter::WriteWorld(World* world) { WriteEntity(world, 0); } -void EntityFileWriter::WriteEntity(World* world, EntityID entity) +void EntityXMLFileWriter::WriteEntity(World* world, EntityID entity) { using namespace xercesc; DOMDocument* doc = m_DOMImplementation->createDocument(nullptr, X("Entity"), nullptr); @@ -41,7 +41,7 @@ void EntityFileWriter::WriteEntity(World* world, EntityID entity) doc->release(); } -void EntityFileWriter::appendEntityChildren(xercesc::DOMElement* parentElement, const World* world, EntityID entity) +void EntityXMLFileWriter::appendEntityChildren(xercesc::DOMElement* parentElement, const World* world, EntityID entity) { using namespace xercesc; DOMDocument* doc = parentElement->getOwnerDocument(); @@ -67,7 +67,7 @@ void EntityFileWriter::appendEntityChildren(xercesc::DOMElement* parentElement, } } -void EntityFileWriter::appentEntityComponents(xercesc::DOMElement* parentElement, const World* world, EntityID entity) +void EntityXMLFileWriter::appentEntityComponents(xercesc::DOMElement* parentElement, const World* world, EntityID entity) { using namespace xercesc; DOMDocument* doc = parentElement->getOwnerDocument(); diff --git a/src/Engine/Core/PerformanceTimer.cpp b/src/Engine/Core/PerformanceTimer.cpp index 50983e79..b2e425aa 100644 --- a/src/Engine/Core/PerformanceTimer.cpp +++ b/src/Engine/Core/PerformanceTimer.cpp @@ -1,7 +1,10 @@ #include "Core/PerformanceTimer.h" + +#ifdef DEBUG #include #include + cpu_timer PerformanceTimer::m_Timer; std::map PerformanceTimer::timers; std::string PerformanceTimer::currentTimerRunning = ""; @@ -74,3 +77,15 @@ void PerformanceTimer::CreateExcelData() } someFileStream.close(); } + +#else + +void PerformanceTimer::StartTimer(std::string nameOfTimer) {}; +void PerformanceTimer::StartTimerAndStopPrevious(std::string nameOfTimer) {}; +void PerformanceTimer::StopTimer(std::string nameOfTimer) {}; +void PerformanceTimer::SetFrameNumber(int frameNumber) {}; + +void PerformanceTimer::ResetAllTimers() {}; +void PerformanceTimer::CreateExcelData() {}; + +#endif //DEBUG diff --git a/src/Engine/Core/Transform.cpp b/src/Engine/Core/Transform.cpp deleted file mode 100644 index 333c3532..00000000 --- a/src/Engine/Core/Transform.cpp +++ /dev/null @@ -1,103 +0,0 @@ -#include "Core/Transform.h" - -glm::mat4 Transform::AbsoluteTransformation(EntityWrapper entity) -{ - glm::mat4 t = glm::mat4(1.f); - - 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(); - } - - 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::AbsoluteOrientation(world, parent) * (glm::vec3)transform["Position"]; - entity = parent; - } - - return position; -} - -glm::vec3 Transform::AbsoluteOrientationEuler(EntityWrapper entity) -{ - glm::vec3 orientation; - - while (entity.Valid()) { - ComponentWrapper transform = entity["Transform"]; - orientation += (glm::vec3)transform["Orientation"]; - entity = entity.Parent(); - } - - return orientation; -} - -glm::quat Transform::AbsoluteOrientation(EntityWrapper entity) -{ - return AbsoluteOrientation(entity.World, entity.ID); -} - -glm::quat Transform::AbsoluteOrientation(World* world, EntityID 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); - } - - return orientation; -} - -glm::vec3 Transform::AbsoluteScale(EntityWrapper entity) -{ - return AbsoluteScale(entity.World, entity.ID); -} - -glm::vec3 Transform::AbsoluteScale(World* world, EntityID 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); - } - - return scale; -} - -glm::mat4 Transform::ModelMatrix(EntityWrapper entity) -{ - return ModelMatrix(entity.ID, entity.World); -} - -glm::mat4 Transform::ModelMatrix(EntityID entity, World* world) -{ - 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; -} - -glm::vec3 Transform::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/Util/Logging.cpp b/src/Engine/Core/Util/Logging.cpp index c7612fd8..63a6f380 100644 --- a/src/Engine/Core/Util/Logging.cpp +++ b/src/Engine/Core/Util/Logging.cpp @@ -33,8 +33,8 @@ void _LOG(_LOG_LEVEL logLevel, const char* file, const char* func, unsigned int va_end(args); if (logLevel == LOG_LEVEL_ERROR) { - //std::cerr << file << ":" << line << " " << func << std::endl; - //std::cerr << _LOG_LEVEL_PREFIX[logLevel] << message << std::endl; + std::cerr << file << ":" << line << " " << func << std::endl; + std::cerr << _LOG_LEVEL_PREFIX[logLevel] << message << std::endl; } else { std::cout << _LOG_LEVEL_PREFIX[logLevel] << message << std::endl; } diff --git a/src/Engine/Core/World.cpp b/src/Engine/Core/World.cpp index 9b323ff4..baf39fc8 100644 --- a/src/Engine/Core/World.cpp +++ b/src/Engine/Core/World.cpp @@ -1,6 +1,7 @@ #include "Core/World.h" #include "Core/EEntityDeleted.h" #include "Core/EComponentDeleted.h" +#include "Core/EntityWrapper.h" World::~World() { @@ -44,10 +45,10 @@ bool World::ValidEntity(EntityID entity) const return m_EntityParents.find(entity) != m_EntityParents.end(); } -void World::RegisterComponent(ComponentInfo& ci) +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); } } @@ -94,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; @@ -151,6 +152,62 @@ std::string World::GetName(EntityID entity) const } } +EntityWrapper World::GetFirstEntityByName(const std::string& name) +{ + auto itPair = GetDirectChildren(EntityID_Invalid); + for (auto it = itPair.first; it != itPair.second; it++) { + EntityID childEntityID = it->second; + EntityWrapper childEntity(this, childEntityID); + if (!childEntity.Valid()) { + continue; + } + EntityWrapper entityWithName = childEntity.Name() == name ? childEntity : childEntity.FirstChildByName(name); + if (entityWithName.Valid()) { + return entityWithName; + } + } + return EntityWrapper::Invalid; +} + +std::unordered_map World::Merge(const World* other) +{ + std::unordered_map oldToNew; + + // Create new entities + for (auto& kv : other->m_EntityParents) { + EntityID entity = kv.first; + + EntityID newEntity = CreateEntity(); + SetName(newEntity, other->GetName(entity)); + oldToNew[entity] = newEntity; + } + // Fix relationships + for (auto& kv : other->m_EntityParents) { + EntityID entity = kv.first; + EntityID parent = kv.second; + if (parent != EntityID_Invalid) { + SetParent(oldToNew.at(entity), oldToNew.at(parent)); + } + } + + // Transfer components + for (auto& kv : other->m_ComponentPools) { + auto& componentType = kv.first; + ComponentPool* pool = kv.second; + // Register pool if it's not present in world + if (m_ComponentPools.count(componentType) == 0) { + RegisterComponent(pool->ComponentInfo()); + } + // Copy components + for (auto component : *pool) { + ComponentWrapper newComponent = AttachComponent(oldToNew.at(component.EntityID), componentType); + component.Copy(newComponent); + } + } + + return oldToNew; +} + EntityID World::generateEntityID() { // TODO: Make EntityID generation smarter @@ -166,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 f2690f13..ef9b4408 100644 --- a/src/Engine/Editor/EditorGUI.cpp +++ b/src/Engine/Editor/EditorGUI.cpp @@ -157,7 +157,7 @@ void EditorGUI::drawEntitiesRecursive(World* world, EntityID parent) auto entityChildren = world->GetEntityChildren(); auto range = entityChildren.equal_range(parent); for (auto it = range.first; it != range.second; it++) { - if (EditorGUI::drawEntityNode(EntityWrapper(world, it->second))) { + if (drawEntityNode(EntityWrapper(world, it->second))) { drawEntitiesRecursive(world, it->second); ImGui::TreePop(); } @@ -217,6 +217,7 @@ bool EditorGUI::drawEntityNode(EntityWrapper entity) ImGui::EndPopup(); } + ImGui::PushID(("EntityNode" + std::to_string(entity.ID)).c_str()); ImGui::SetNextTreeNodeOpened(true, ImGuiSetCond_Once); if (ImGui::TreeNode(formatEntityName(entity).c_str())) { // Handle drop events for reparenting @@ -224,8 +225,10 @@ bool EditorGUI::drawEntityNode(EntityWrapper entity) entityChangeParent(m_CurrentlyDragging, entity); m_CurrentlyDragging = EntityWrapper::Invalid; } + ImGui::PopID(); return true; } else { + ImGui::PopID(); return false; } } @@ -338,6 +341,15 @@ bool EditorGUI::drawComponentNode(EntityWrapper entity, const ComponentInfo& ci) } } + if (ci.Name == "Spawner") { + if (ImGui::Button("Activate")) { + Events::SpawnerSpawn e; + e.Spawner = entity; + e.Parent = entity; + m_EventBroker->Publish(e); + } + } + return true; } @@ -369,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; @@ -381,14 +397,52 @@ bool EditorGUI::drawComponentField_Vector(ComponentWrapper &c, const ComponentIn // Limit scale values to a minimum of 0 return ImGui::DragFloat3("", glm::value_ptr(val), 0.1f, 0.f, std::numeric_limits::max()); } else if (field.Name == "Orientation") { - // Make orentations have a period of 2*Pi - glm::vec3 tempVal = glm::fmod(val, glm::vec3(glm::two_pi())); - if (ImGui::SliderFloat3("", glm::value_ptr(tempVal), 0.f, glm::two_pi())) { - val = tempVal; - return true; - } else { - return false; + //glm::vec3 tempVal = val; + glm::vec3 originalVal = val; + + ImVec2 cursorPos = ImGui::GetCursorScreenPos(); + glm::tvec3 isSnapping(false, false, false); + bool changed = ImGui::DragFloat3("", glm::value_ptr(val), 0.066666f); + if (changed) { + // Make orentations have a period of 2*Pi + val = glm::fmod(val, glm::vec3(glm::two_pi())); + for (int i = 0; i < 3; i++) { + if (val[i] < 0) { + val[i] += glm::two_pi(); + } + } } + + // Snap to angle + //float snapRange = glm::pi() / 15.f; + //float snapAngle = glm::quarter_pi(); + //glm::vec3 snap = glm::fmod(val, glm::vec3(snapAngle)); + //for (int i = 0; i < 3; i++) { + // isSnapping[i] = glm::abs(snap[i] - (snapRange / 2.f)) < snapRange; + //} + //if (changed && ImGui::IsMouseDown(0)) { + // glm::vec3 change = val - originalVal; + // for (int i = 0; i < 3; i++) { + // if (isSnapping[i] && glm::abs(change[i]) < snapRange) { + // val[i] -= snap[i] - snapRange; + // } + // } + //} + + // Draw snapping outline + float width = ImGui::CalcItemWidth() / 3.f;; + float spacing = GImGui->Style.ItemInnerSpacing.x; + for (int i = 0; i < 3; i++) { + if (isSnapping[i]) { + ImVec2 pos = cursorPos + ImVec2(i * (width + spacing), 0.f); + ImRect bb(pos - ImVec2(1, 1), pos + ImVec2(width, 17)); + auto window = ImGui::GetCurrentWindow(); + const ImU32 col = window->Color(ImGuiCol_HeaderActive); + window->DrawList->AddRect(bb.Min, bb.Max, col, 3.f); + } + } + + return changed; } else { return ImGui::DragFloat3("", glm::value_ptr(val), 0.1f, std::numeric_limits::lowest(), std::numeric_limits::max()); } @@ -580,6 +634,11 @@ void EditorGUI::createWidgetToolButton(WidgetMode mode) bool EditorGUI::OnKeyDown(const Events::KeyDown& e) { + ImGuiIO& io = ImGui::GetIO(); + if (io.WantCaptureKeyboard) { + return false; + } + if (e.ModCtrl && e.KeyCode == GLFW_KEY_S) { if (m_CurrentSelection.Valid()) { EntityWrapper baseParent = m_CurrentSelection; diff --git a/src/Engine/Editor/EditorRenderSystem.cpp b/src/Engine/Editor/EditorRenderSystem.cpp index 9a385e7d..f365579c 100644 --- a/src/Engine/Editor/EditorRenderSystem.cpp +++ b/src/Engine/Editor/EditorRenderSystem.cpp @@ -7,7 +7,7 @@ EditorRenderSystem::EditorRenderSystem(SystemParams params, IRenderer* renderer, { EVENT_SUBSCRIBE_MEMBER(m_ESetCamera, &EditorRenderSystem::OnSetCamera); auto resolution = Rectangle::Rectangle(1280, 720); - m_EditorCamera = new Camera((float)resolution.Width / resolution.Height, glm::radians(45.f), 0.01f, 5000.f); + m_EditorCamera = new Camera((float)resolution.Width / resolution.Height, glm::radians(45.f), 0.001f, 500.f); } void EditorRenderSystem::Update(double dt) @@ -52,9 +52,9 @@ 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); + 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"]) { scene.Jobs.TransparentObjects.push_back(modelJob); } else { @@ -86,7 +86,7 @@ bool EditorRenderSystem::OnSetCamera(Events::SetCamera& e) { ComponentWrapper cTransform = e.CameraEntity["Transform"]; ComponentWrapper cCamera = e.CameraEntity["Camera"]; - m_EditorCamera->SetFOV(static_cast((double)cCamera["FOV"])); + m_EditorCamera->SetFOV(glm::radians(static_cast((double)cCamera["FOV"]))); m_EditorCamera->SetNearClip(static_cast((double)cCamera["NearClip"])); m_EditorCamera->SetFarClip(static_cast((double)cCamera["FarClip"])); m_EditorCamera->SetPosition(cTransform["Position"]); diff --git a/src/Engine/Editor/EditorSystem.cpp b/src/Engine/Editor/EditorSystem.cpp index 4bee1427..e3b47036 100644 --- a/src/Engine/Editor/EditorSystem.cpp +++ b/src/Engine/Editor/EditorSystem.cpp @@ -2,8 +2,9 @@ #include "Core/UniformScaleSystem.h" #include "Editor/EditorRenderSystem.h" #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) @@ -13,12 +14,12 @@ 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"); m_EditorWorld->AttachComponent(m_EditorCamera.ID, "Camera"); - m_EditorCameraInputController = new EditorCameraInputController(m_EventBroker, -1); + m_EditorCameraInputController = new EditorCameraInputController(m_EventBroker, -1, EntityWrapper::Invalid); m_EditorGUI = new EditorGUI(m_World, m_EventBroker); m_EditorGUI->SetEntitySelectedCallback(std::bind(&EditorSystem::OnEntitySelected, this, std::placeholders::_1)); @@ -46,6 +47,7 @@ EditorSystem::EditorSystem(SystemParams params, IRenderer* renderer, RenderFrame Enable(); } else { Disable(); + m_EventBroker->Publish(Events::UnlockMouse()); } } @@ -70,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; } } @@ -100,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 @@ -129,7 +133,7 @@ void EditorSystem::OnEntitySelected(EntityWrapper entity) void EditorSystem::OnEntitySave(EntityWrapper entity, boost::filesystem::path filePath) { - EntityFileWriter writer(filePath); + EntityXMLFileWriter writer(filePath); writer.WriteEntity(entity.World, entity.ID); } @@ -201,17 +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)); + parentOrientation = glm::inverse(TransformSystem::AbsoluteOrientation(parent)); + parentScale = TransformSystem::AbsoluteScale(parent); } - (glm::vec3&)m_CurrentSelection["Transform"]["Position"] += parentOrientation * e.Translation; + (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 = TransformSystem::AbsoluteScale(parent); + } glm::quat selectionOri = glm::quat((glm::vec3)m_CurrentSelection["Transform"]["Orientation"]); - glm::vec3 localTranslation = selectionOri * e.Translation; - (glm::vec3&)m_CurrentSelection["Transform"]["Position"] += localTranslation; + glm::vec3 localTranslation = selectionOri * e.Translation / parentScale; + (Field)m_CurrentSelection["Transform"]["Position"] += localTranslation; } m_EditorGUI->SetDirty(m_CurrentSelection); } @@ -260,12 +274,11 @@ EntityWrapper EditorSystem::importEntity(EntityWrapper parent, boost::filesystem try { auto entityFile = ResourceManager::Load(filePath.string()); - EntityFilePreprocessor fpp(entityFile); - fpp.RegisterComponents(parent.World); - EntityFileParser fp(entityFile); - EntityID newEntity = fp.MergeEntities(parent.World, parent.ID); - return EntityWrapper(parent.World, newEntity); - } catch (const std::exception&) { + EntityWrapper newEntity = entityFile->MergeInto(parent.World); + parent.World->SetParent(newEntity.ID, parent.ID); + return newEntity; + } catch (const std::exception& e) { + LOG_ERROR("Failed to import entity \"%s\": \"%s\"", filePath.string().c_str(), e.what()); return EntityWrapper::Invalid; } } @@ -299,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/GUI/ButtonSystem.cpp b/src/Engine/GUI/ButtonSystem.cpp index 93ae1811..44c8a13c 100644 --- a/src/Engine/GUI/ButtonSystem.cpp +++ b/src/Engine/GUI/ButtonSystem.cpp @@ -1,4 +1,5 @@ #include "GUI/ButtonSystem.h" +#include "Input/EInputCommand.h" ButtonSystem::ButtonSystem(SystemParams params, IRenderer* renderer) : System(params) @@ -37,10 +38,20 @@ bool ButtonSystem::OnMousePress(const Events::MousePress& e) m_PickEntity = EntityWrapper(m_World, m_PickData.Entity); //You have clicked on a button entity, send pressed event. - Events::ButtonPressed ePressed; - ePressed.Entity = m_PickEntity; - ePressed.EntityName = m_PickEntity.Name(); - m_EventBroker->Publish(ePressed); + if (m_World->HasComponent(m_PickData.Entity, "InputCmdButton")) { + Events::InputCommand eInputCmd; + eInputCmd.PlayerID = -1; + eInputCmd.Player = LocalPlayer; + EntityWrapper button = EntityWrapper(m_World, m_PickData.Entity); + eInputCmd.Command = (std::string)button["InputCmdButton"]["Command"]; + eInputCmd.Value = (float)button["InputCmdButton"]["PressValue"]; + m_EventBroker->Publish(eInputCmd); + } else { + Events::ButtonPressed ePressed; + ePressed.Entity = m_PickEntity; + ePressed.EntityName = m_PickEntity.Name(); + m_EventBroker->Publish(ePressed); + } } } } @@ -55,10 +66,20 @@ bool ButtonSystem::OnMouseRelease(const Events::MouseRelease& e) if(m_PickData.Entity != EntityID_Invalid && m_PickData.World == m_World) { EntityWrapper ent = EntityWrapper(m_World, m_PickData.Entity); - Events::ButtonReleased eReleased; - eReleased.EntityName = m_PickEntity.Name(); - eReleased.Entity = m_PickEntity; - m_EventBroker->Publish(eReleased); + if (m_World->HasComponent(m_PickData.Entity, "InputCmdButton")) { + Events::InputCommand eInputCmd; + eInputCmd.PlayerID = -1; + eInputCmd.Player = LocalPlayer; + EntityWrapper button = EntityWrapper(m_World, m_PickData.Entity); + eInputCmd.Command = (std::string)button["InputCmdButton"]["Command"]; + eInputCmd.Value = 0; + m_EventBroker->Publish(eInputCmd); + } else { + Events::ButtonReleased eReleased; + eReleased.EntityName = m_PickEntity.Name(); + eReleased.Entity = m_PickEntity; + m_EventBroker->Publish(eReleased); + } if(m_World->HasComponent(m_PickData.Entity, "Button")) { if (ent == m_PickEntity) { diff --git a/src/Engine/GUI/MainMenuSystem.cpp b/src/Engine/GUI/MainMenuSystem.cpp deleted file mode 100644 index f8bf032b..00000000 --- a/src/Engine/GUI/MainMenuSystem.cpp +++ /dev/null @@ -1,57 +0,0 @@ -#include "GUI/MainMenuSystem.h" - -MainMenuSystem::MainMenuSystem(SystemParams params, IRenderer* renderer) - : System(params) - , ImpureSystem() - , m_Renderer(renderer) -{ - EVENT_SUBSCRIBE_MEMBER(m_EPressed, &MainMenuSystem::OnButtonPress); - EVENT_SUBSCRIBE_MEMBER(m_EReleased, &MainMenuSystem::OnButtonRelease); - EVENT_SUBSCRIBE_MEMBER(m_EClicked, &MainMenuSystem::OnButtonClick); -} - -void MainMenuSystem::Update(double dt) -{ - -} - -bool MainMenuSystem::OnButtonClick(const Events::ButtonClicked& e) -{ - if(e.EntityName == "Play") { - //Run play code - } else if(e.EntityName == "Connect") { - //Run connect code - } else if(e.EntityName == "Host") { - //Run host code - } else if(e.EntityName == "Quit") { - printf("No, you stay"); - } else if (e.EntityName == "Res1080") { - glfwSetWindowSize(m_Renderer->Window(), 1920, 1080); - printf("\n1080"); - } else if (e.EntityName == "Res720") { - glfwSetWindowSize(m_Renderer->Window(), 1280, 720); - glViewport(0, 0, 1280, 720); - printf("\n720"); - } else if (e.EntityName == "Res480") { - glfwSetWindowSize(m_Renderer->Window(), 854, 480); - glViewport(0, 0, 854, 480); - printf("\n480"); - } else if (e.EntityName == "FullScreen") { - printf("No fullscreen for now"); - } - - return true; -} - -bool MainMenuSystem::OnButtonRelease(const Events::ButtonReleased& e) -{ - - return true; -} - -bool MainMenuSystem::OnButtonPress(const Events::ButtonPressed& e) -{ - - return true; -} - diff --git a/src/Engine/Input/InputProxy.cpp b/src/Engine/Input/InputProxy.cpp index 6c3591e3..662aea52 100644 --- a/src/Engine/Input/InputProxy.cpp +++ b/src/Engine/Input/InputProxy.cpp @@ -45,7 +45,7 @@ void InputProxy::Update(double dt) } } -void InputProxy::Process() +void InputProxy::Process(bool suppressNewEvents /*= false*/) { for (auto& pair : m_CommandHandlers) { const std::string& command = pair.first; @@ -62,8 +62,10 @@ void InputProxy::Process() e.PlayerID = -1; e.Command = command; e.Value = currentValue; - m_EventBroker->Publish(e); - //LOG_DEBUG("Input: Published command %s=%f for player %i", e.Command.c_str(), e.Value, e.PlayerID); + if (!suppressNewEvents || e.Value == 0) { + m_EventBroker->Publish(e); + //LOG_DEBUG("Input: Published command %s=%f for player %i", e.Command.c_str(), e.Value, e.PlayerID); + } m_LastCommandValues[command] = currentValue; } } @@ -78,8 +80,10 @@ void InputProxy::Process() e.Value += value; } //e.Value = std::max(-1.f, std::min(e.Value, 1.f)); - m_EventBroker->Publish(e); - //LOG_DEBUG("Input: Published command %s=%f for player %i", e.Command.c_str(), e.Value, e.PlayerID); + if (!suppressNewEvents || e.Value == 0) { + m_EventBroker->Publish(e); + //LOG_DEBUG("Input: Published command %s=%f for player %i", e.Command.c_str(), e.Value, e.PlayerID); + } } m_CommandQueue.clear(); } diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index 2a5238ab..b6b63e81 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); @@ -33,7 +34,9 @@ void Client::Connect(std::string address, int port) EVENT_SUBSCRIBE_MEMBER(m_EPlayerDamage, &Client::OnPlayerDamage); EVENT_SUBSCRIBE_MEMBER(m_EPlayerSpawned, &Client::OnPlayerSpawned); EVENT_SUBSCRIBE_MEMBER(m_EDoubleJump, &Client::OnDoubleJump); + EVENT_SUBSCRIBE_MEMBER(m_EDashAbility, &Client::OnDashAbility); EVENT_SUBSCRIBE_MEMBER(m_ESearchForServers, &Client::OnSearchForServers); + EVENT_SUBSCRIBE_MEMBER(m_EConnectRequest, &Client::OnConnectRequest); auto config = ResourceManager::Load("Config.ini"); m_Address = address; if (address.empty()) { @@ -45,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); + 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(packet); + parseMessageType(parsedPacket); } } + while (m_Reliable.IsSocketAvailable()) { // Packet will get real data in receive Packet packet(MessageType::Invalid); @@ -79,31 +85,45 @@ 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(); + //displayServerlist(); + Events::DisplayServerlist e; + e.Serverlist = m_Serverlist; + m_EventBroker->Publish(e); } } 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(); hasServerTimedOut(); } - //Network::Update(); + + if (ImGui::BeginPopupModal("Disconnected", nullptr, ImGuiWindowFlags_AlwaysAutoResize)) { + ImGui::Text("You have been disconnected from server.\n\n"); + ImGui::SetCursorPosX(ImGui::GetContentRegionAvailWidth() - 120); + if (ImGui::Button("OK", ImVec2(120, 0))) { + ImGui::CloseCurrentPopup(); + } + ImGui::EndPopup(); + } } void Client::parseMessageType(Packet& packet) { - // Pop packetSize which is used by TCP Client to - // create a packet of the correct size - packet.ReadPrimitive(); + // Pop packetSize, sequenceNumber and packetsInSequence. + popNetworkSegmentOfHeader(packet); + int messageType = packet.ReadPrimitive(); if (messageType == -1) return; @@ -144,6 +164,21 @@ void Client::parseMessageType(Packet& packet) case MessageType::OnDoubleJump: parseDoubleJump(packet); break; + case MessageType::OnDashEffect: + parseDashEffect(packet); + break; + case MessageType::AmmoPickup: + parseAmmoPickup(packet); + break; + case MessageType::RemoveWorld: + parseRemoveWorld(packet); + break; + case MessageType::KD: + parseKDEvent(packet); + break; + case MessageType::Win: + parseWin(packet); + break; default: break; } @@ -152,27 +187,30 @@ 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); - LOG_INFO("Sent UDP Connect Server"); + + // LOG_INFO("Sent UDP Connect Server"); } void Client::parsePlayerConnected(Packet & packet) @@ -198,10 +236,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(); @@ -214,7 +253,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() @@ -233,7 +272,6 @@ void Client::parseSpawnEvents() m_EventBroker->Publish(e); } m_PlayerSpawnEvents = tempSpawn; - // m_PlayerSpawnEvents.clear(); } void Client::parsePlayersSpawned(Packet& packet) @@ -261,7 +299,7 @@ void Client::parseEntityDeletion(Packet & packet) if (m_ServerIDToClientID.find(entityToDelete) != m_ServerIDToClientID.end()) { EntityID localEntity = m_ServerIDToClientID.at(entityToDelete); if (m_World->ValidEntity(localEntity)) { - if (m_World->HasComponent(localEntity,"Player")) { + if (m_World->HasComponent(localEntity, "Player")) { Events::PlayerDeath e; e.Player = EntityWrapper(m_World, localEntity); m_EventBroker->Publish(e); @@ -296,6 +334,58 @@ void Client::parseDoubleJump(Packet & packet) } } + +void Client::parseDashEffect(Packet& packet) +{ + EntityID serverID = packet.ReadPrimitive(); + if (!serverClientMapsHasEntity(serverID)) { + return; + } + Events::DashAbility e; + e.Player = m_ServerIDToClientID.at(serverID); + if (e.Player != m_LocalPlayer.ID) { + m_EventBroker->Publish(e); + } +} + +void Client::parseAmmoPickup(Packet & packet) +{ + Events::AmmoPickup e; + e.AmmoGain = packet.ReadPrimitive(); + e.Player = m_LocalPlayer; + m_EventBroker->Publish(e); +} + +void Client::parseRemoveWorld(Packet & packet) +{ + removeWorld(); + Events::Reset e; + m_EventBroker->Publish(e); +} + +void Client::parseKDEvent(Packet & packet) +{ + Events::KillDeath e; + e.Casualty = packet.ReadPrimitive(); + e.CasualtyClass = packet.ReadPrimitive(); + e.CasualtyName = packet.ReadString(); + e.CasualtyTeam = packet.ReadPrimitive(); + + e.Killer = packet.ReadPrimitive(); + e.KillerClass = packet.ReadPrimitive(); + e.KillerName = packet.ReadString(); + e.KillerTeam = packet.ReadPrimitive(); + + m_EventBroker->Publish(e); +} + +void Client::parseWin(Packet& packet) +{ + Events::Win e; + e.TeamThatWon = packet.ReadPrimitive(); + m_EventBroker->Publish(e); +} + void Client::updateFields(Packet& packet, const ComponentInfo& componentInfo, const EntityID& entityID) { for (auto field : componentInfo.FieldsInOrder) { @@ -379,7 +469,7 @@ void Client::parseSnapshot(Packet& packet) if (m_SnapshotFilter != nullptr) { shouldApply = m_SnapshotFilter->FilterComponent(localEntity, newComponent); } - if (shouldApply) { + if (shouldApply) { ComponentWrapper currentComponent = m_World->GetComponent(localEntityID, componentType); memcpy(currentComponent.Data, newComponent.Data, componentInfo.Stride); } @@ -426,22 +516,23 @@ void Client::parseSnapshot(Packet& packet) void Client::disconnect() { + removeWorld(); m_IsConnected = false; m_PreviousPacketID = 0; 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(); } bool Client::OnInputCommand(const Events::InputCommand & e) { - // TEMP - if (e.Command == "SearchForServers" && e.Value > 0) { - Events::SearchForServers e; - m_EventBroker->Publish(e); - } - if (e.PlayerID != -1) { return false; } @@ -509,12 +600,41 @@ bool Client::OnPlayerSpawned(const Events::PlayerSpawned& e) return true; } + +bool Client::OnDashAbility(const Events::DashAbility& e) +{ + if (!clientServerMapsHasEntity(e.Player) || e.Player != m_LocalPlayer.ID) { + return false; + } + Packet packet(MessageType::OnDashEffect); + packet.WritePrimitive(m_ClientIDToServerID.at(e.Player)); + m_Reliable.Send(packet); + return true; +} + + +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; + + } else { + // The client could not send a successful connect message + createMainMenu(); + // Load the main menu again ? + return false; + } + return false; +} + bool Client::OnSearchForServers(const Events::SearchForServers& e) { m_SearchingForServers = true; - m_StartSearchTime = std::clock(); + m_TimeSearched = 0; m_Serverlist.clear(); - LOG_INFO("Searching for LAN servers...\n"); Packet packet(MessageType::ServerlistRequest); m_ServerlistRequest.Broadcast(packet, 13); // TODO: Config return true; @@ -557,8 +677,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); @@ -593,6 +713,7 @@ void Client::hasServerTimedOut() if (timeSincePing > m_TimeoutMs) { // Clear everything and go to menu. LOG_INFO("Server has timed out, returning to menu, Beep Boop."); + ImGui::OpenPopup("Disconnected"); disconnect(); } } @@ -636,6 +757,12 @@ void Client::displayServerlist() } } +void Client::createMainMenu() +{ + auto entityFile = ResourceManager::Load("Schema/Entities/StartMenu.xml"); + entityFile->MergeInto(m_World); +} + bool Client::clientServerMapsHasEntity(EntityID clientEntityID) { if (m_ClientIDToServerID.find(clientEntityID) != m_ClientIDToServerID.end()) { 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 475ca673..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; @@ -49,18 +69,24 @@ void Packet::WriteString(const std::string& str) // Message, add one extra byte for null terminator size_t sizeOfString = str.size() + 1; if (m_Offset + sizeOfString > m_MaxPacketSize) { - //LOG_WARNING("Package::WriteString(): Data size in packet exceeded maximum package size. New size is %i bytes\n", m_MaxPacketSize*2); + if (m_MaxPacketSize >= 32000) { + //LOG_WARNING("Package::WriteString(): New size is huge %i bytes\n", m_MaxPacketSize*2); + } resizeData(); } - memcpy(m_Data + m_Offset, str.data(), sizeOfString * sizeof(char)); - m_Offset += sizeOfString * sizeof(char); + memcpy(m_Data + m_Offset, str.data(), str.size() * sizeof(char)); + m_Offset += str.size() * sizeof(char); + m_Data[m_Offset] = '\0'; + m_Offset += 1; } void Packet::WriteData(char * data, int sizeOfData) { if (m_Offset + sizeOfData > m_MaxPacketSize) { - //LOG_WARNING("Packet::WriteData(): Data size in packet exceeded maximum packet size. New size is %i bytes\n", m_MaxPacketSize*2); + if (m_MaxPacketSize >= 32000) { + //LOG_WARNING("Package::WriteData(): New size is huge %i bytes\n", m_MaxPacketSize*2); + } while (m_Offset + sizeOfData > m_MaxPacketSize) { resizeData(); } @@ -98,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) @@ -117,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 7c614cee..76cdd1ec 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -5,15 +5,19 @@ 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 EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &Server::OnInputCommand); EVENT_SUBSCRIBE_MEMBER(m_EPlayerSpawned, &Server::OnPlayerSpawned); EVENT_SUBSCRIBE_MEMBER(m_EEntityDeleted, &Server::OnEntityDeleted); EVENT_SUBSCRIBE_MEMBER(m_EComponentDeleted, &Server::OnComponentDeleted); 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); @@ -27,7 +31,7 @@ Server::~Server() } -void Server::Update() +void Server::Update(double dt) { m_Reliable.AcceptNewConnections(m_NextPlayerID, m_ConnectedPlayers); @@ -66,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)); @@ -81,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 @@ -141,6 +165,9 @@ void Server::parseMessageType(Packet& packet) case MessageType::OnDoubleJump: parseDoubleJump(packet); break; + case MessageType::OnDashEffect: + parseDashEffect(packet); + break; default: break; } @@ -156,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 @@ -171,6 +195,13 @@ void Server::sendSnapshot() unreliableBroadcast(packet); } +// Send snapshot fields +void Server::createWorldSnapshot(Packet& packet) +{ + addInputCommandsToPacket(packet); + addChildrenToPacket(packet, EntityID_Invalid); +} + void Server::addInputCommandsToPacket(Packet& packet) { // Number of input commands @@ -218,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); @@ -262,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); @@ -293,8 +324,6 @@ void Server::sendPing() reliableBroadcast(packet); } - - void Server::checkForTimeOuts() { double startPing = 1000 * m_StartPingTime @@ -311,22 +340,21 @@ 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(); + //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(); - // 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()); @@ -338,8 +366,9 @@ void Server::parseUDPConnect(Packet & packet) 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 @@ -347,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(); + PlayerID playerID = getPlayerIDFromEndpoint(); if (playerID == -1) { + LOG_INFO("Server::parseTCPConnect: Not connected"); return; } // Create a new player @@ -360,6 +389,11 @@ void Server::parseTCPConnect(Packet & packet) m_ConnectedPlayers.at(playerID).TCPAddress = m_Address; m_ConnectedPlayers.at(playerID).TCPPort = m_Port; + Events::PlayerConnected e; + e.PlayerID = playerID; + e.PlayerName = m_ConnectedPlayers.at(playerID).Name; + m_EventBroker->Publish(e); + LOG_INFO("parseTCPConnect: Spectator \"%s\" connected on IP: %s", m_ConnectedPlayers.at(playerID).Name.c_str(), m_ConnectedPlayers.at(playerID).TCPAddress.to_string().c_str()); @@ -367,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 @@ -398,7 +431,7 @@ void Server::parseServerlistRequest(boost::asio::ip::udp::endpoint endpoint) Packet packet(MessageType::ServerlistRequest); packet.WriteString(m_Reliable.Address()); packet.WritePrimitive(m_Reliable.Port()); - packet.WriteString("SERVERNAME"); + packet.WriteString(m_ServerName); packet.WritePrimitive(m_ConnectedPlayers.size()); m_ServerlistRequest.Send(packet); } @@ -480,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; @@ -510,10 +543,82 @@ bool Server::OnPlayerDamage(const Events::PlayerDamage& e) return true; } +bool Server::OnAmmoPickup(const Events::AmmoPickup & e) +{ + for (auto& kv : m_ConnectedPlayers) { + if (e.Player.ID == kv.second.EntityID) { + Packet packet(MessageType::AmmoPickup); + // We dont send playerID as it will be set at client to local + packet.WritePrimitive(e.AmmoGain); + m_Reliable.Send(packet, kv.second); + } + } + return true; +} + + +bool Server::OnPlayerDeath(const Events::PlayerDeath& e) +{ + Events::KillDeath eKD; + auto entity = e; + eKD.Casualty = getPlayerIDFromEntityID(e.Player.ID); + eKD.Killer = getPlayerIDFromEntityID(e.Killer.ID); + + eKD.CasualtyName = m_ConnectedPlayers.at(getPlayerIDFromEntityID(e.Player.ID)).Name; + eKD.KillerName = m_ConnectedPlayers.at(getPlayerIDFromEntityID(e.Killer.ID)).Name; + + if(entity.Player.HasComponent("Team")) { + eKD.CasualtyTeam = (const int&)entity.Player["Team"]["Team"]; + } + if (entity.Killer.HasComponent("Team")) { + eKD.KillerTeam = (const int&)entity.Killer["Team"]["Team"]; + } + + if(entity.Player.HasComponent("DashAbility")) { + eKD.CasualtyClass = 1; + } else if (entity.Player.HasComponent("ShieldAbility")) { + eKD.CasualtyClass = 2; + } else if (entity.Player.HasComponent("SprintAbility")) { + eKD.CasualtyClass = 3; + } + if (entity.Killer.HasComponent("DashAbility")) { + eKD.KillerClass = 1; + } else if (entity.Killer.HasComponent("ShieldAbility")) { + eKD.KillerClass = 2; + } else if (entity.Killer.HasComponent("SprintAbility")) { + eKD.KillerClass = 3; + } + + m_EventBroker->Publish(eKD); + + Packet kdPacket(MessageType::KD); + kdPacket.WritePrimitive(eKD.Casualty); + kdPacket.WritePrimitive(eKD.CasualtyClass); + kdPacket.WriteString(eKD.CasualtyName); + kdPacket.WritePrimitive(eKD.CasualtyTeam); + + kdPacket.WritePrimitive(eKD.Killer); + kdPacket.WritePrimitive(eKD.KillerClass); + kdPacket.WriteString(eKD.KillerName); + kdPacket.WritePrimitive(eKD.KillerTeam); + reliableBroadcast(kdPacket); + return false; +} + +bool Server::OnWin(const Events::Win & e) +{ + // Postpone the gameover reset + m_GameIsOver = true; + Packet winPacket = Packet(MessageType::Win); + winPacket.WritePrimitive(e.TeamThatWon); + reliableBroadcast(winPacket); + return true; +} + void Server::parseClientPing() { LOG_INFO("%i: Parsing ping", m_PacketID); - PlayerID player = GetPlayerIDFromEndpoint(); + PlayerID player = getPlayerIDFromEndpoint(); if (player == -1) { return; } @@ -542,11 +647,16 @@ bool Server::parseDoubleJump(Packet & packet) return true; } +void Server::parseDashEffect(Packet& packet) +{ + reliableBroadcast(packet); +} + void Server::parseOnInputCommand(Packet& packet) { PlayerID player = -1; // Check which player it was who sent the message - player = GetPlayerIDFromEndpoint(); + player = getPlayerIDFromEndpoint(); if (player != -1) { while (packet.DataReadSize() < packet.Size()) { Events::InputCommand e; @@ -565,7 +675,7 @@ void Server::parseOnInputCommand(Packet& packet) void Server::parsePlayerTransform(Packet& packet) { - PlayerID playerID = GetPlayerIDFromEndpoint(); + PlayerID playerID = getPlayerIDFromEndpoint(); if (playerID == -1) { return; } @@ -601,18 +711,10 @@ void Server::parsePlayerTransform(Packet& packet) bool Server::shouldSendToClient(EntityWrapper childEntity) { - auto children = m_World->GetDirectChildren(childEntity.ID); - for (auto it = children.first; it != children.second; it++) { - EntityWrapper child(m_World, it->second); - if(child.HasComponent("CapturePoint")) { - return true; - } - } - return childEntity.HasComponent("Player") || childEntity.FirstParentWithComponent("Player").Valid() - || childEntity.HasComponent("CapturePoint"); + return childEntity.HasComponent("NetworkComponent") || childEntity.FirstParentWithComponent("NetworkComponent").Valid(); } -PlayerID Server::GetPlayerIDFromEndpoint() +PlayerID Server::getPlayerIDFromEndpoint() { // check both tcp and udp connection for (auto& kv : m_ConnectedPlayers) { @@ -624,4 +726,30 @@ PlayerID Server::GetPlayerIDFromEndpoint() } } return -1; +} + +PlayerID Server::getPlayerIDFromEntityID(EntityID entityID) +{ + for (auto& kv : m_ConnectedPlayers) { + if (entityID == kv.second.EntityID) { + return kv.first; + } + } + 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_Valhalla.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 f3394d3d..28da80ce 100644 --- a/src/Engine/Network/TCPClient.cpp +++ b/src/Engine/Network/TCPClient.cpp @@ -3,24 +3,14 @@ using namespace boost::asio::ip; TCPClient::TCPClient() -{ -} +{ } TCPClient::~TCPClient() -{ -} +{ } -void TCPClient::Connect(std::string playerName, std::string address, int port) +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!"); - } - } - 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)); @@ -34,24 +24,20 @@ void TCPClient::Connect(std::string playerName, std::string address, int port) packet.WriteString(playerName); Send(packet); LOG_INFO("Connect message sent!"); - } - // If error - else { + return true; + } else { // If error m_Socket->close(); m_Socket = nullptr; + return false; } } } 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) @@ -63,7 +49,7 @@ void TCPClient::Receive(Packet& packet) } size_t TCPClient::readBuffer() -{ +{ if (!m_Socket) { return 0; } @@ -74,7 +60,10 @@ size_t TCPClient::readBuffer() boost::asio::ip::tcp::socket::message_peek, error); unsigned int sizeOfPacket = 0; memcpy(&sizeOfPacket, m_ReadBuffer, sizeof(int)); - + if (sizeOfPacket > m_Socket->available()) { + LOG_WARNING("TCPClient::readBuffer(): We haven't got the whole packet yet."); + //return 0; + } // if the buffer is to small increase the size of it // TODO if message is huge 1 time the buffer will not decrease. if (sizeOfPacket > m_BufferSize) { @@ -82,12 +71,15 @@ size_t TCPClient::readBuffer() m_ReadBuffer = new char[sizeOfPacket]; m_BufferSize = sizeOfPacket; } - // Read the rest of the message - size_t bytesReceived = m_Socket->read_some(boost - ::asio::buffer((void*)(m_ReadBuffer), sizeOfPacket), - error); - if (error) { - //LOG_ERROR("receive: %s", error.message().c_str()); + size_t bytesReceived = 0; + while (sizeOfPacket > bytesReceived) { + // Read the rest of the message + bytesReceived += m_Socket->read_some(boost + ::asio::buffer((void*)(m_ReadBuffer + bytesReceived), sizeOfPacket - bytesReceived), + error); + if (error) { + //LOG_ERROR("receive: %s", error.message().c_str()); + } } if (sizeOfPacket > 1000000) LOG_WARNING("The packets received are bigger than 1MB"); diff --git a/src/Engine/Network/TCPServer.cpp b/src/Engine/Network/TCPServer.cpp index acd3d6d0..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); @@ -106,7 +107,10 @@ int TCPServer::readBuffer(PlayerDefinition & playerDefinition) boost::asio::ip::tcp::socket::message_peek, error); unsigned int sizeOfPacket = 0; memcpy(&sizeOfPacket, m_ReadBuffer, sizeof(int)); - + if (sizeOfPacket > playerDefinition.TCPSocket->available()) { + LOG_WARNING("TCPServer::readBuffer(): We haven't got the whole packet yet."); + return 0; + } // if the buffer is to small increase the size of it if (sizeOfPacket > m_BufferSize) { delete[] m_ReadBuffer; diff --git a/src/Engine/Network/UDPClient.cpp b/src/Engine/Network/UDPClient.cpp index 51c29920..872d567c 100644 --- a/src/Engine/Network/UDPClient.cpp +++ b/src/Engine/Network/UDPClient.cpp @@ -1,38 +1,51 @@ #include "Network/UDPClient.h" +#include "boost/asio/basic_datagram_socket.hpp" using namespace boost::asio::ip; UDPClient::UDPClient() -{ -} +{ } UDPClient::~UDPClient() -{ -} +{ } -void UDPClient::Connect(std::string playerName, std::string address, int port) +bool UDPClient::Connect(std::string playerName, std::string address, int port) { if (m_Socket) { - return; + return false; } 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) { @@ -40,12 +53,15 @@ 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()) { + LOG_WARNING("UDPClient::readBuffer(): We haven't got the whole packet yet."); + //return 0; + } // if the buffer is to small increase the size of it if (sizeOfPacket > m_BufferSize) { delete[] m_ReadBuffer; @@ -68,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(); @@ -75,7 +157,7 @@ void UDPClient::Send(Packet& packet) packet.Data(), packet.Size()), m_ReceiverEndpoint, 0); -} +} void UDPClient::Broadcast(Packet& packet, int port) { @@ -91,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 635ebd4d..e67a66c4 100644 --- a/src/Engine/Network/UDPServer.cpp +++ b/src/Engine/Network/UDPServer.cpp @@ -12,42 +12,123 @@ 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); + // 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(); - 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); } // Broadcasting respond specific logic void UDPServer::Send(Packet & packet, boost::asio::ip::udp::endpoint endpoint) { packet.UpdateSize(); - m_Socket->send_to( + size_t bytesSent = m_Socket->send_to( boost::asio::buffer( packet.Data(), packet.Size()), endpoint, 0); + //LOG_INFO("Size of packet is %i", bytesSent); } // Broadcasting @@ -55,11 +136,11 @@ void UDPServer::Broadcast(Packet & packet, int port) { packet.UpdateSize(); m_Socket->set_option(boost::asio::socket_base::broadcast(true)); - m_Socket->send_to( + size_t bytesSent = m_Socket->send_to( 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)); } @@ -86,12 +167,17 @@ 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; memcpy(&sizeOfPacket, m_ReadBuffer, sizeof(int)); + if (sizeOfPacket > m_Socket->available()) { + LOG_WARNING("UDPServer::readBuffer(): We haven't got the whole packet yet."); + //return 0; + } + // if the buffer is to small increase the size of it if (sizeOfPacket > m_BufferSize) { delete[] m_ReadBuffer; @@ -104,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 02d72409..3e53612b 100644 --- a/src/Engine/Rendering/AnimationSystem.cpp +++ b/src/Engine/Rendering/AnimationSystem.cpp @@ -1,71 +1,355 @@ #include "Rendering/AnimationSystem.h" -void AnimationSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& animationComponent, double dt) +AnimationSystem::AnimationSystem(SystemParams params) + : System(params) { - if(!entity.HasComponent("Model")) { + EVENT_SUBSCRIBE_MEMBER(m_EAutoAnimationBlend, &AnimationSystem::OnAutoAnimationBlend); + EVENT_SUBSCRIBE_MEMBER(m_EEntityDeleted, &AnimationSystem::OnEntityDeleted); + EVENT_SUBSCRIBE_MEMBER(m_ESetBlendWeight, &AnimationSystem::OnSetBlendWeight); +} + +void AnimationSystem::Update(double dt) +{ + UpdateAnimations(dt); + CreateBlendTrees(); + UpdateWeights(dt); + + + for(auto& autoBlendQueue : m_AutoBlendQueues) { + autoBlendQueue.second.UpdateTime(dt); + } +} + +void AnimationSystem::CreateBlendTrees() +{ + auto modelComponents = m_World->GetComponents("Model"); + if (modelComponents == nullptr) { return; } + for (auto& modelC : *modelComponents) { + EntityWrapper entity = EntityWrapper(m_World, modelC.EntityID); + + Model* model; + try { + model = ResourceManager::Load<::Model, true>(entity["Model"]["Resource"]); + } catch (const std::exception&) { + continue;; + } + + Skeleton* skeleton = model->m_Skeleton; + if (skeleton == nullptr) { + continue; + } + + if (entity.HasComponent("Blend") || entity.HasComponent("BlendOverride") || + entity.HasComponent("BlendAdditive") || entity.HasComponent("Animation")) + { + std::shared_ptr blendTree = std::shared_ptr(new BlendTree(entity, skeleton)); + + if(blendTree->IsValid()) { + skeleton->BlendTrees[entity] = blendTree; + } + + } + } +} + +void AnimationSystem::UpdateAnimations(double dt) +{ + auto animationComponents = m_World->GetComponents("Animation"); + if(animationComponents == nullptr) { + return; + } + + for (auto& animationC : *animationComponents) { + EntityWrapper entity = EntityWrapper(m_World, animationC.EntityID); + EntityWrapper modelEntity; + if(!entity.HasComponent("Model")) { + modelEntity = entity.FirstParentWithComponent("Model"); + } else { + modelEntity = entity; + } + + Model* model; + try { + Field res = modelEntity["Model"]["Resource"]; + model = ResourceManager::Load<::Model, true>(res); + } catch (const std::exception&) { + continue; + } + + Skeleton* skeleton = model->m_Skeleton; + if (skeleton == nullptr) { + continue; + } + + const Skeleton::Animation* animation = skeleton->GetAnimation(animationC["AnimationName"]); + + if (animation == nullptr) { + continue; + } + + double animationSpeed = (const double&)animationC["Speed"]; + + if((const bool&)animationC["Reverse"]) { + animationSpeed *= -1; + } + + + if ((const bool&)animationC["Play"]) { + + double nextTime = (Field)animationC["Time"] + animationSpeed * dt; + if (!(Field)animationC["Loop"]) { + if (nextTime > animation->Duration) { + nextTime = animation->Duration; + (Field)animationC["Play"] = false; + } else if (nextTime < 0) { + nextTime = 0; + (Field)animationC["Play"] = false; + } + } else { + if (nextTime > animation->Duration) { + + while (nextTime > animation->Duration) { + nextTime -= animation->Duration; + } + } else if (nextTime < 0) { + while (nextTime < 0) { + nextTime += animation->Duration; + } + } + } + (Field)animationC["Time"] = nextTime; + } + } +} + +void AnimationSystem::UpdateWeights(double dt) +{ + for (auto it = m_AutoBlendQueues.begin(); it != m_AutoBlendQueues.end(); ) { + //LOG_INFO("%s", it->first.Name().c_str()); + //it->second.PrintQueue(); + + if(it->second.HasActiveBlendJob()) { + AutoBlendQueue::AutoBlendJob& blendJob = it->second.GetActiveBlendJob(); + //LOG_INFO("%s", blendJob.RootNode.Name().c_str()); + std::shared_ptr blendTree = it->second.GetBlendTree(); + if (blendTree != nullptr) { + if (blendJob.Duration != 0.0) { + blendJob.BlendInfo.progress = glm::clamp(blendJob.CurrentTime / blendJob.Duration, 0.0, 1.0); + } else { + blendJob.BlendInfo.progress = 1.0; + } + + blendJob.BlendInfo = blendTree->AutoBlendStep(blendJob.BlendInfo); + } else { + it = m_AutoBlendQueues.erase(it); + } + it++; + } else { + if (it->second.Empty()) { + it = m_AutoBlendQueues.erase(it); + } else { + it++; + } + } + } +} + +bool AnimationSystem::OnAutoAnimationBlend(Events::AutoAnimationBlend& e) +{ + if (!e.RootNode.Valid()) { + LOG_ERROR("%s, RootNode invalid %s", e.NodeName, e.RootNode.Name().c_str()); + return false; + } + + if (!e.RootNode.HasComponent("Model")) { + LOG_ERROR("%s, RootNode has no model %s", e.NodeName, e.RootNode.Name().c_str()); + return false; + } + Model* model; try { - model = ResourceManager::Load<::Model, true>(entity["Model"]["Resource"]); + model = ResourceManager::Load<::Model, true>((std::string)e.RootNode["Model"]["Resource"]); } catch (const std::exception&) { - return; - } - - Skeleton* skeleton = model->m_RawModel->m_Skeleton; - if(skeleton == nullptr) { - return; + LOG_ERROR("%s, RootNode model not finished loading %s", e.NodeName, e.RootNode.Name().c_str()); + return false; } - for (int i = 1; i <= 3; i++) { - const Skeleton::Animation* animation = skeleton->GetAnimation(animationComponent["AnimationName" + std::to_string(i)]); + Skeleton* skeleton = model->m_Skeleton; + if (skeleton == nullptr) { + LOG_ERROR("%s, RootNode skeleton invalid %s", e.NodeName, e.RootNode.Name().c_str()); + return false; + } - if (animation == nullptr) { - continue;; + std::shared_ptr blendTree; + if (skeleton->BlendTrees.find(e.RootNode) != skeleton->BlendTrees.end()) { + blendTree = skeleton->BlendTrees.at(e.RootNode); + } else { + LOG_ERROR("%s, No blendtree was found invalid %s", e.NodeName, e.RootNode.Name().c_str()); + return false; + } + + EntityWrapper subTreeRoot; + + + if (e.SingleLevelBlend) { + subTreeRoot = blendTree->GetSubTreeRoot(e.NodeName); + + if (!subTreeRoot.Valid()) { + LOG_ERROR("%s, subTreeRoot invalid", e.NodeName); + return false; } - double animationSpeed = (double)animationComponent["Speed" + std::to_string(i)]; + AutoBlendQueue::AutoBlendJob abj; + abj.AnimationEntity = e.AnimationEntity; + abj.CurrentTime = 0.0; + abj.Delay = e.Delay; + abj.Duration = e.Duration; + abj.RootNode = e.RootNode; - if (animationSpeed != 0.0) { - double nextTime = (double)animationComponent["Time" + std::to_string(i)] + animationSpeed * dt; + abj.BlendInfo.NodeName = e.NodeName; + abj.BlendInfo.progress = 0.0; + abj.BlendInfo.Start = e.Start; + abj.BlendInfo.SingleBlend = e.SingleLevelBlend; + abj.BlendInfo.Weight = e.Weight; + std::vector animationEntities = blendTree->GetEntitesByName(e.NodeName); // more than one + for(auto entity : animationEntities) + if (entity.Valid()) { + if (entity.HasComponent("Animation")) { + const Skeleton::Animation* animation = skeleton->GetAnimation(entity["Animation"]["AnimationName"]); + (Field)entity["Animation"]["Reverse"] = e.Reverse; - if (!(bool)animationComponent["Loop" + std::to_string(i)]) { - if (nextTime > animation->Duration) { - nextTime = animation->Duration; - Events::AnimationComplete e; - e.Entity = entity; - e.Name = (std::string)animationComponent["AnimationName" + std::to_string(i)]; - m_EventBroker->Publish(e); - } else if (nextTime < 0) { - Events::AnimationComplete e; - e.Entity = entity; - e.Name = (std::string)animationComponent["AnimationName" + std::to_string(i)]; - m_EventBroker->Publish(e); - nextTime = 0; - } - - (double&)animationComponent["Speed" + std::to_string(i)] = 0.0; - - } else { - if (nextTime > animation->Duration) { - Events::AnimationComplete e; - e.Entity = entity; - e.Name = (std::string)animationComponent["AnimationName" + std::to_string(i)]; - m_EventBroker->Publish(e); - nextTime -= animation->Duration; - } else if (nextTime < 0) { - Events::AnimationComplete e; - e.Entity = entity; - e.Name = (std::string)animationComponent["AnimationName" + std::to_string(i)]; - m_EventBroker->Publish(e); - nextTime += animation->Duration; + if (e.Restart) { + if (animation != nullptr) { + if (e.Restart) { + if (e.Reverse) { + (Field)entity["Animation"]["Time"] = animation->Duration; + } else { + (Field)entity["Animation"]["Time"] = 0.0; + } + } + } } } - - (double&)animationComponent["Time" + std::to_string(i)] = nextTime; } - } + m_AutoBlendQueues[subTreeRoot].Insert(abj); + } else { + std::vector subtreeroots = blendTree->GetSingleLevelRoots(e.NodeName); + + for(auto entity : subtreeroots) { + subTreeRoot = entity; + + if (!subTreeRoot.Valid()) { + LOG_ERROR("%s, subTreeRoot invalid", e.NodeName); + return false; + } + + AutoBlendQueue::AutoBlendJob abj; + abj.AnimationEntity = e.AnimationEntity; + abj.CurrentTime = 0.0; + abj.Delay = e.Delay; + abj.Duration = e.Duration; + abj.RootNode = e.RootNode; + + abj.BlendInfo.NodeName = e.NodeName; + abj.BlendInfo.progress = 0.0; + abj.BlendInfo.Start = e.Start; + abj.BlendInfo.SingleBlend = e.SingleLevelBlend; + abj.BlendInfo.Weight = e.Weight; + m_AutoBlendQueues[subTreeRoot].Insert(abj); + } + + std::vector animationEntities = blendTree->GetEntitesByName(e.NodeName); // more than one + for (auto entity : animationEntities) + if (entity.Valid()) { + if (entity.HasComponent("Animation")) { + const Skeleton::Animation* animation = skeleton->GetAnimation(entity["Animation"]["AnimationName"]); + entity["Animation"]["Reverse"] = e.Reverse; + + if (e.Restart) { + if (animation != nullptr) { + if (e.Restart) { + if (e.Reverse) { + entity["Animation"]["Time"] = animation->Duration; + } else { + entity["Animation"]["Time"] = 0.0; + } + } + } + } + } + } + } + + + return true; } +bool AnimationSystem::OnEntityDeleted(Events::EntityDeleted& e) +{ + EntityWrapper entity = e.DeletedEntity; + + if (entity.HasComponent("Model")) { + Model* model; + try { + model = ResourceManager::Load<::Model, true>(entity["Model"]["Resource"]); + } catch (const std::exception&) { + return false; + } + + Skeleton* skeleton = model->m_Skeleton; + if (skeleton == nullptr) { + return false; + } + + if (skeleton->BlendTrees.find(entity) != skeleton->BlendTrees.end()) { + skeleton->BlendTrees.erase(entity); + } + + + } + +} + +bool AnimationSystem::OnSetBlendWeight(Events::SetBlendWeight& e) +{ + if (!e.RootNode.Valid()) { + return false; + } + + if (!e.RootNode.HasComponent("Model")) { + return false; + } + + Model* model; + try { + model = ResourceManager::Load<::Model, true>((std::string)e.RootNode["Model"]["Resource"]); + } catch (const std::exception&) { + return false; + } + + Skeleton* skeleton = model->m_Skeleton; + if (skeleton == nullptr) { + return false; + } + + std::shared_ptr blendTree; + if (skeleton->BlendTrees.find(e.RootNode) != skeleton->BlendTrees.end()) { + blendTree = skeleton->BlendTrees.at(e.RootNode); + } else { + return false; + } + + if(e.Weight >= 0 && e.Weight <= 1) { + + blendTree->SetWeightByName(e.NodeName, e.Weight); + + return true; + } else { + return false; + } + +} diff --git a/src/Engine/Rendering/AutoBlendQueue.cpp b/src/Engine/Rendering/AutoBlendQueue.cpp new file mode 100644 index 00000000..016ae420 --- /dev/null +++ b/src/Engine/Rendering/AutoBlendQueue.cpp @@ -0,0 +1,197 @@ +#include "Rendering/AutoBlendQueue.h" + +void AutoBlendQueue::Insert(AutoBlendJob autoBlendJob) +{ + if(!autoBlendJob.RootNode.HasComponent("Model")) { + return; + } + + AutoblendNode blendNode; + blendNode.BlendJob = autoBlendJob; + blendNode.StartTime = autoBlendJob.Delay; + blendNode.EndTime = autoBlendJob.Delay + autoBlendJob.Duration; + + + + if (autoBlendJob.AnimationEntity.Valid()) { + if (autoBlendJob.AnimationEntity.HasComponent("Animation")) { + Model* model; + try { + model = ResourceManager::Load<::Model, true>((std::string)autoBlendJob.RootNode["Model"]["Resource"]); + } catch (const std::exception&) { + return; + } + + Skeleton* skeleton = model->m_Skeleton; + if (skeleton == nullptr) { + return; + } + + const Skeleton::Animation* animation = skeleton->GetAnimation((std::string)autoBlendJob.AnimationEntity["Animation"]["AnimationName"]); + + if (animation == nullptr) { + return; + } + + double AnimationDuration = 0.0; + + double animationSpeed = (double)autoBlendJob.AnimationEntity["Animation"]["Speed"]; + double animationTime = (double)autoBlendJob.AnimationEntity["Animation"]["Time"]; + + if (animationSpeed != 0) { + if ((bool)autoBlendJob.AnimationEntity["Animation"]["Reverse"]) { + AnimationDuration = (animation->Duration / animationSpeed) - (animation->Duration - animationTime); + } else { + AnimationDuration = (animation->Duration / animationSpeed) - animationTime; + } + } else { + return; + } + + blendNode.StartTime += AnimationDuration; + blendNode.EndTime += AnimationDuration; + if (m_BlendQueue.size() == 0) { + m_BlendQueue.push_back(blendNode); + } else { + for (auto it = m_BlendQueue.begin(); it != m_BlendQueue.end(); it++) { + auto next = std::next(it, 1); + + + if (it->BlendJob.BlendInfo.NodeName == autoBlendJob.BlendInfo.NodeName) { + (*it) = blendNode; + } + + if (next != m_BlendQueue.end()) { + if (it->StartTime >= blendNode.StartTime && next->StartTime <= blendNode.StartTime) { + m_BlendQueue.insert(next, blendNode); + return; + } + } else if(it->StartTime > blendNode.StartTime){ + m_BlendQueue.push_front(blendNode); + return; + } else if (it->StartTime <= blendNode.StartTime) { + m_BlendQueue.push_back(blendNode); + return; + } + } + } + } + } + + m_BlendQueue.clear(); + m_BlendQueue.push_back(blendNode); +} + +void AutoBlendQueue::UpdateTime(double dt) +{ + for (auto it = m_BlendQueue.begin(); it != m_BlendQueue.end();) { + if (it->EndTime <= 0) { + it = m_BlendQueue.erase(it); + } else { + it->EndTime -= dt; + it->StartTime -= dt; + it++; + } + } +} + +void AutoBlendQueue::PrintQueue() +{ + for (auto it = m_BlendQueue.begin(); it != m_BlendQueue.end(); it++) { + LOG_INFO("Start: %f End: %f \t %s", it->StartTime, it->EndTime, it->BlendJob.BlendInfo.NodeName.c_str()); + } +} + + +bool AutoBlendQueue::HasActiveBlendJob() +{ + if(m_BlendQueue.empty()) { + return false; + } else { + AutoblendNode blendNode = m_BlendQueue.front(); + if (blendNode.StartTime <= 0) { + AutoBlendJob blendJob = blendNode.BlendJob; + + if (!blendJob.RootNode.Valid()) { + m_BlendQueue.pop_front(); + return false; + } + + if (!blendJob.RootNode.HasComponent("Model")) { + m_BlendQueue.pop_front(); + return HasActiveBlendJob(); + } + + Model* model; + try { + model = ResourceManager::Load<::Model, true>(blendJob.RootNode["Model"]["Resource"]); + } catch (const std::exception&) { + //m_BlendQueue.pop_front(); + return HasActiveBlendJob(); + } + + Skeleton* skeleton = model->m_Skeleton; + if (skeleton == nullptr) { + m_BlendQueue.pop_front(); + return HasActiveBlendJob(); + } + + + if (skeleton->BlendTrees.find(blendJob.RootNode) != skeleton->BlendTrees.end()) { + return true; + } else { + m_BlendQueue.pop_front(); + return HasActiveBlendJob(); + } + + + } else { + return false; + } + } +} + + +std::shared_ptr AutoBlendQueue::GetBlendTree() +{ + AutoblendNode blendNode = m_BlendQueue.front(); + AutoBlendJob blendJob = blendNode.BlendJob; + + if (!blendJob.RootNode.Valid()) { + m_BlendQueue.pop_front(); + return false; + } + + if (!blendJob.RootNode.HasComponent("Model")) { + return nullptr; + } + + Model* model; + try { + model = ResourceManager::Load<::Model, true>(blendJob.RootNode["Model"]["Resource"]); + } catch (const std::exception&) { + return nullptr; + } + + Skeleton* skeleton = model->m_Skeleton; + if (skeleton == nullptr) { + return nullptr; + } + + + if (skeleton->BlendTrees.find(blendJob.RootNode) != skeleton->BlendTrees.end()) { + return skeleton->BlendTrees.at(blendJob.RootNode); + } else { + return nullptr; + } + + + +} + +AutoBlendQueue::AutoBlendJob& AutoBlendQueue::GetActiveBlendJob() +{ + AutoblendNode& blendNode = m_BlendQueue.front(); + blendNode.BlendJob.CurrentTime = -blendNode.StartTime; + return blendNode.BlendJob; +} diff --git a/src/Engine/Rendering/BlendTree.cpp b/src/Engine/Rendering/BlendTree.cpp new file mode 100644 index 00000000..f1ca25c7 --- /dev/null +++ b/src/Engine/Rendering/BlendTree.cpp @@ -0,0 +1,546 @@ +#include "Rendering/BlendTree.h" + +BlendTree::BlendTree(EntityWrapper ModelEntity, Skeleton* skeleton) +{ + m_Skeleton = skeleton; + + if (ModelEntity.HasComponent("Animation")) { + const Skeleton::Animation* animation = skeleton->GetAnimation(ModelEntity["Animation"]["AnimationName"]); + if (animation == nullptr) { + return; + } + + m_Root = new Node(); + m_Root->Entity = ModelEntity; + m_Root->Name = ModelEntity.Name(); + 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; + + } else if (ModelEntity.HasComponent("Blend")) { + m_Root = new Node(); + m_Root->Entity = ModelEntity; + m_Root->Name = ModelEntity.Name(); + m_Root->Parent = nullptr; + m_Root->Type = NodeType::Blend; + 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); + + } else if (ModelEntity.HasComponent("BlendOverride")) { + m_Root = new Node(); + m_Root->Entity = ModelEntity; + m_Root->Name = ModelEntity.Name(); + m_Root->Parent = nullptr; + m_Root->Type = NodeType::Override; + m_Root->Child[0] = FillTreeByName(m_Root, (std::string)ModelEntity["BlendOverride"]["Master"], ModelEntity); + m_Root->Child[1] = FillTreeByName(m_Root, (std::string)ModelEntity["BlendOverride"]["Slave"], ModelEntity); + + } else if (ModelEntity.HasComponent("BlendAdditive")) { + m_Root = new Node(); + m_Root->Entity = ModelEntity; + m_Root->Name = ModelEntity.Name(); + m_Root->Parent = nullptr; + m_Root->Type = NodeType::Additive; + m_Root->Child[0] = FillTreeByName(m_Root, (std::string)ModelEntity["BlendAdditive"]["Adder"], ModelEntity); + m_Root->Child[1] = FillTreeByName(m_Root, (std::string)ModelEntity["BlendAdditive"]["Receiver"], ModelEntity); + } + + m_FinalPose = AccumulateFinalPose(); + // PrintTree(); +} + +BlendTree::~BlendTree() +{ + Node* currentNode = m_Root; + if (currentNode != nullptr) { + while (currentNode->Child[0] != nullptr) { + currentNode = currentNode->Child[0]; + } + + std::list m_NodesToRemove; + + while (currentNode != nullptr) { + m_NodesToRemove.push_back(currentNode); + currentNode = currentNode->Next(); + } + + for (auto it = m_NodesToRemove.begin(); it != m_NodesToRemove.end(); it++) { + delete (*it); + } + } +} + + +glm::mat4 BlendTree::GetBoneTransform(int boneID) +{ + if(m_FinalBoneTransforms.find(boneID) != m_FinalBoneTransforms.end()) { + return m_FinalBoneTransforms.at(boneID); + } else { + return glm::mat4(1); + } + +} + +void BlendTree::PrintTree() +{ + Node* currentNode = m_Root; + LOG_INFO("\n\n"); + + while(currentNode->Child[0] != nullptr) { + currentNode = currentNode->Child[0]; + } + + while (currentNode != nullptr) + { + LOG_INFO("%s", currentNode->Name.c_str()); + currentNode = currentNode->Next(); + } +} + +BlendTree::Node* BlendTree::FillTreeByName(Node* parentNode, std::string name, EntityWrapper parentEntity) +{ + EntityWrapper childEntity = parentEntity.FirstLevelChildByName(name); // Make first level child by name + + if (!childEntity.Valid()) { + return nullptr; + } + + if (childEntity.HasComponent("Animation")) { + const Skeleton::Animation* animation = m_Skeleton->GetAnimation(childEntity["Animation"]["AnimationName"]); + if (animation == nullptr) { + return nullptr; + } + + Node* node = new Node(); + node->Entity = childEntity; + node->Name = childEntity.Name(); + 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; + + } else if (childEntity.HasComponent("Blend")) { + Node* node = new Node(); + node->Entity = childEntity; + node->Name = childEntity.Name(); + node->Parent = parentNode; + node->Type = NodeType::Blend; + 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); + /* } else if (node->Weight == 1.f) { + node->Child[0] = FillTreeByName(node, (std::string)childEntity["Blend"]["Pose1"], childEntity); + } else if (node->Weight == 0.f) { + node->Child[1] = FillTreeByName(node, (std::string)childEntity["Blend"]["Pose2"], childEntity); + }*/ + + if(node->Child[0] == nullptr && node->Child[1] == nullptr) { + return nullptr; + } else { + return node; + } + + } else if (childEntity.HasComponent("BlendOverride")) { + Node* node = new Node(); + node->Entity = childEntity; + node->Name = childEntity.Name(); + node->Parent = parentNode; + node->Type = NodeType::Override; + node->Child[0] = FillTreeByName(node, (std::string)childEntity["BlendOverride"]["Master"], childEntity); + node->Child[1] = FillTreeByName(node, (std::string)childEntity["BlendOverride"]["Slave"], childEntity); + + if (node->Child[0] == nullptr && node->Child[1] == nullptr) { + return nullptr; + } else { + return node; + } + } else if (childEntity.HasComponent("BlendAdditive")) { + Node* node = new Node(); + node->Entity = childEntity; + node->Name = childEntity.Name(); + node->Parent = parentNode; + node->Type = NodeType::Additive; + node->Child[0] = FillTreeByName(node, (std::string)childEntity["BlendAdditive"]["Adder"], childEntity); + node->Child[1] = FillTreeByName(node, (std::string)childEntity["BlendAdditive"]["Receiver"], childEntity); + + if(node->Child[0] == nullptr && node->Child[1] == nullptr) { + return nullptr; + } else { + return node; + } + } + + + return nullptr; +} + + +std::vector BlendTree::FindNodesByName(std::string name) +{ + std::vector Nodes; + Node* currentNode = m_Root; + + while (currentNode->Child[0] != nullptr) { + currentNode = currentNode->Child[0]; + } + + while (currentNode != nullptr) { + if(currentNode->Name == name) { + Nodes.push_back(currentNode); + } + currentNode = currentNode->Next(); + } + return Nodes; +} + + +BlendTree::AutoBlendInfo BlendTree::AutoBlendStep(AutoBlendInfo blendInfo) +{ + std::vector goalNodes = FindNodesByName(blendInfo.NodeName); + + if(blendInfo.Weight >= 0 && blendInfo.Weight <= 1.0) { + for (auto it = goalNodes.begin(); it != goalNodes.end(); it++) { + EntityWrapper entity = (*it)->Entity; + + if (entity.Valid()) { + if (entity.HasComponent("Blend")) { + entity["Blend"]["Weight"] = blendInfo.Weight; + } + } + } + return blendInfo; + } + + + + if (blendInfo.Start) { + for (auto it = goalNodes.begin(); it != goalNodes.end(); it++) { + EntityWrapper entity = (*it)->Entity; + + if (entity.Valid()) { + if (entity.HasComponent("Animation")) { + entity["Animation"]["Play"] = true; + } + } + } + } + + if(goalNodes.size() == 0) { + return blendInfo; + } else if(goalNodes.size() == 1) { + Node* currentNode = goalNodes[0]->Parent; + Node* lastNode = goalNodes[0]; + + while (currentNode != nullptr) + { + if(!currentNode->Entity.HasComponent("Blend")) { + return blendInfo; + } + + double startWeight; + if(blendInfo.StartWeights.find(currentNode->Entity) != blendInfo.StartWeights.end()) { + startWeight = blendInfo.StartWeights.at(currentNode->Entity); + } else { + startWeight = currentNode->Weight; + blendInfo.StartWeights[currentNode->Entity] = startWeight; + } + + double goalWeight; + if(currentNode->Child[0] == lastNode) { + goalWeight = 0.0; + } else if (currentNode->Child[1] == lastNode) { + goalWeight = 1.0; + } + + double weight = ((goalWeight - startWeight) * blendInfo.progress) + startWeight; + currentNode->Entity["Blend"]["Weight"] = weight; + currentNode->Weight = weight; + + lastNode = currentNode; + currentNode = currentNode->Parent; + + if (blendInfo.SingleBlend) { + return blendInfo;; + } + } + } else if(goalNodes.size() >= 2) { + std::vector sharedParents; + std::vector nodes = goalNodes; + + for (auto it = nodes.begin(); it != nodes.end(); it++) { + auto next = std::next(it, 1); + if (next != nodes.end()) { + Node* commonParent = FirstCommonParent((*it), (*next)); + sharedParents.push_back(commonParent); + (*next) = commonParent; + nodes.erase(it); + it = nodes.begin(); + } + } + + + for (auto it = goalNodes.begin(); it != goalNodes.end(); it++) { + + Node* currentNode = (*it)->Parent; + Node* lastNode = (*it); + + while (currentNode != nullptr) { + if (!currentNode->Entity.HasComponent("Blend")) { + return blendInfo; + } + + bool ShouldBreak = false; + for (auto it = sharedParents.begin(); it != sharedParents.end(); it++) { + if(currentNode == (*it)) { + ShouldBreak = true; + } + } + + if(ShouldBreak) { + break; + } + + double startWeight; + if (blendInfo.StartWeights.find(currentNode->Entity) != blendInfo.StartWeights.end()) { + startWeight = blendInfo.StartWeights.at(currentNode->Entity); + } else { + startWeight = currentNode->Weight; + blendInfo.StartWeights[currentNode->Entity] = startWeight; + } + + double goalWeight; + if (currentNode->Child[0] == lastNode) { + goalWeight = 0.0; + } else if (currentNode->Child[1] == lastNode) { + goalWeight = 1.0; + } + + double weight = ((goalWeight - startWeight) * blendInfo.progress) + startWeight; + currentNode->Entity["Blend"]["Weight"] = weight; + currentNode->Weight = weight; + + lastNode = currentNode; + currentNode = currentNode->Parent; + if (blendInfo.SingleBlend) { + return blendInfo; + } + } + } + } + + return blendInfo; +} + +BlendTree::Node* BlendTree::GetCommonParent(std::string NodeName1, std::string NodeName2) +{ + std::vector nodes1 = FindNodesByName(NodeName1); + std::vector nodes2 = FindNodesByName(NodeName2); + + for (auto it = nodes1.begin(); it != nodes1.end(); it++) { + auto next = std::next(it, 1); + + if(next != nodes1.end()) { + Node* commonParent = FirstCommonParent((*it), (*next)); + (*next) = commonParent; + nodes1.erase(it); + it = nodes1.begin(); + } + } + + for (auto it = nodes2.begin(); it != nodes2.end(); it++) { + auto next = std::next(it, 1); + + if (next != nodes2.end()) { + Node* commonParent = FirstCommonParent((*it), (*next)); + (*next) = commonParent; + nodes2.erase(it); + it = nodes2.begin(); + } + } + + return FirstCommonParent(nodes1.front(), nodes2.front());; +} + + +BlendTree::Node* BlendTree::FirstCommonParent(Node* node1, Node* node2) +{ + std::list node1Parents; + + Node* currentNode = node1; + while (currentNode != nullptr) { + node1Parents.push_back(currentNode); + currentNode = currentNode->Parent; + } + + currentNode = node2; + while (currentNode != nullptr) { + for (auto it = node1Parents.begin(); it != node1Parents.end(); it++) { + if (currentNode == (*it)) { + return currentNode; + } + } + currentNode = currentNode->Parent; + } + + return nullptr; +} + + +EntityWrapper BlendTree::GetSubTreeRoot(std::string nodeName) +{ + std::vector nodes = FindNodesByName(nodeName); + + if (nodes.size() == 0) { + return EntityWrapper::Invalid; + } + + std::vector subTreeRoots; + + for (auto it = nodes.begin(); it != nodes.end(); it++) { + Node* currentNode = (*it)->Parent; + while (!currentNode->SubTreeRoot) { + currentNode = currentNode->Parent; + } + subTreeRoots.push_back(currentNode); + } + + + for (auto it = subTreeRoots.begin(); it != subTreeRoots.end(); it++) { + auto next = std::next(it, 1); + + if (next != subTreeRoots.end()) { + Node* commonParent = FirstCommonParent((*it), (*next)); + (*next) = commonParent; + subTreeRoots.erase(it); + it = subTreeRoots.begin(); + } + } + + return subTreeRoots.front()->Entity; +} + + +std::vector BlendTree::GetSingleLevelRoots(std::string name) +{ + std::vector nodes = FindNodesByName(name); + std::vector entities; + + for (auto it = nodes.begin(); it != nodes.end(); it++) { + Node* currentNode = (*it)->Parent; + + if(currentNode->Entity.Valid()) { + entities.push_back(currentNode->Entity); + } + } + + return entities; +} + + +std::vector BlendTree::GetEntitesByName(std::string name) +{ + std::vector nodes = FindNodesByName(name); + std::vector entities; + + for (auto it = nodes.begin(); it != nodes.end(); it++) { + Node* currentNode = (*it); + + if (currentNode->Entity.Valid()) { + entities.push_back(currentNode->Entity); + } + } + + return entities; +} + + +void BlendTree::SetWeightByName(std::string name, double weight) +{ + std::vector nodes = FindNodesByName(name); + + for (auto node : nodes) { + EntityWrapper entity = node->Entity; + + if(entity.HasComponent("Blend")) { + entity["Blend"]["Weight"] = weight; + node->Weight = weight; + } + } +} + +void BlendTree::Blend(std::map& pose) +{ + Node* currentNode; + Node* start = m_Root; + while (start->Child[0] != nullptr) { + start = start->Child[0]; + } + + currentNode = start; + + while (m_Root->Pose.size() == 0) { + if(currentNode->Pose.size() == 0) { + if (currentNode->Child[0] != nullptr && currentNode->Child[1] != nullptr) { + if (currentNode->Child[0]->Pose.size() != 0 && currentNode->Child[1]->Pose.size() != 0) { + switch (currentNode->Type) { + case BlendTree::NodeType::Additive: + currentNode->Pose = m_Skeleton->BlendPoseAdditive(currentNode->Child[0]->Pose, currentNode->Child[1]->Pose); + break; + case BlendTree::NodeType::Blend: + currentNode->Pose = m_Skeleton->BlendPoses(currentNode->Child[0]->Pose, currentNode->Child[1]->Pose, currentNode->Weight); + break; + case BlendTree::NodeType::Override: + currentNode->Pose = m_Skeleton->OverridePose(currentNode->Child[0]->Pose, currentNode->Child[1]->Pose); + break; + case BlendTree::NodeType::Animation: + // do nothing + break; + } + } + } else if (currentNode->Child[0] != nullptr) { + if (currentNode->Child[0]->Pose.size() != 0) { + currentNode->Pose = currentNode->Child[0]->Pose; + } + } else if (currentNode->Child[1] != nullptr) { + if (currentNode->Child[1]->Pose.size() != 0) { + currentNode->Pose = currentNode->Child[1]->Pose; + } + } + } + + currentNode = currentNode->Next(); + + if (currentNode == nullptr) { + currentNode = start; + } + + } + + pose = m_Root->Pose; +} + +std::vector BlendTree::AccumulateFinalPose() +{ + std::vector finalPose; + if (m_Skeleton == nullptr || m_Root == nullptr || (m_Root->Child[0] == nullptr && m_Root->Child[1] == nullptr)) { + + for (int i = 0; i < m_Skeleton->Bones.size(); i++) { + finalPose.push_back(glm::mat4(1)); + } + return finalPose; + } + + std::map pose; + Blend(pose); + + m_Skeleton->GetFinalPose(pose, finalPose, m_FinalBoneTransforms); + + return finalPose; +} + diff --git a/src/Engine/Rendering/BlurHUD.cpp b/src/Engine/Rendering/BlurHUD.cpp new file mode 100644 index 00000000..e16a7b78 --- /dev/null +++ b/src/Engine/Rendering/BlurHUD.cpp @@ -0,0 +1,302 @@ +#include "Rendering/BlurHUD.h" + +BlurHUD::BlurHUD(IRenderer* renderer) + : m_Renderer(renderer) +{ + InitializeShaderPrograms(); + InitializeBuffers(); + InitializeTextures(); +} + +void BlurHUD::InitializeTextures() +{ + m_BlackTexture = CommonFunctions::TryLoadResource("Textures/Core/Black.png"); + m_ScreenQuad = ResourceManager::Load("Models/Core/ScreenQuad.mesh"); +} + +void BlurHUD::InitializeShaderPrograms() +{ + m_GaussianProgram_horiz = ResourceManager::Load("##GaussianProgramHoriz"); + if (m_GaussianProgram_horiz->GetHandle() == 0) { + m_GaussianProgram_horiz->AddShader(std::shared_ptr(new VertexShader("Shaders/Gaussian_horiz.vert.glsl"))); + m_GaussianProgram_horiz->AddShader(std::shared_ptr(new FragmentShader("Shaders/Gaussian_horiz.frag.glsl"))); + m_GaussianProgram_horiz->Compile(); + m_GaussianProgram_horiz->BindFragDataLocation(0, "fragmentColor"); + m_GaussianProgram_horiz->Link(); + } + + m_GaussianProgram_vert = ResourceManager::Load("##GaussianProgramVert"); + if (m_GaussianProgram_vert->GetHandle() == 0) { + m_GaussianProgram_vert->AddShader(std::shared_ptr(new VertexShader("Shaders/Gaussian_vert.vert.glsl"))); + m_GaussianProgram_vert->AddShader(std::shared_ptr(new FragmentShader("Shaders/Gaussian_vert.frag.glsl"))); + m_GaussianProgram_vert->Compile(); + m_GaussianProgram_vert->BindFragDataLocation(0, "fragmentColor"); + m_GaussianProgram_vert->Link(); + } + m_FillDepthStencilProgram = ResourceManager::Load("#FillDepthStencilProgram"); + if (m_FillDepthStencilProgram->GetHandle() == 0) { + m_FillDepthStencilProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/FillDepthBuffer.vert.glsl"))); + m_FillDepthStencilProgram->Compile(); + m_FillDepthStencilProgram->Link(); + } + m_CombineTexturesProgram = ResourceManager::Load("#CombineTexturesProgram"); + if (m_CombineTexturesProgram->GetHandle() == 0) { + m_CombineTexturesProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/CombineTexture.vert.glsl"))); + m_CombineTexturesProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/CombineTexture.frag.glsl"))); + m_CombineTexturesProgram->Compile(); + m_CombineTexturesProgram->BindFragDataLocation(0, "sceneColor"); + m_CombineTexturesProgram->BindFragDataLocation(1, "bloomColor"); + m_CombineTexturesProgram->Link(); + } + GLERROR("Creating DepthFill program"); +} + +void BlurHUD::InitializeBuffers() +{ + glm::vec2 res = glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); + glm::vec2 res2 = glm::vec2(m_Renderer->GetViewportSize().Width/m_BlurQuality, m_Renderer->GetViewportSize().Height/m_BlurQuality); + + + CommonFunctions::GenerateTexture(&m_DepthStencil_horiz, GL_CLAMP_TO_BORDER, GL_NEAREST, + res2, GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8); + CommonFunctions::GenerateTexture(&m_GaussianTexture_horiz, GL_CLAMP_TO_EDGE, GL_NEAREST, + res2, GL_RGBA16F, GL_RGBA, GL_FLOAT); + + if (m_GaussianFrameBuffer_horiz.GetHandle() == 0) { + m_GaussianFrameBuffer_horiz.AddResource(std::shared_ptr(new Texture2D(&m_DepthStencil_horiz, GL_DEPTH_STENCIL_ATTACHMENT))); + m_GaussianFrameBuffer_horiz.AddResource(std::shared_ptr(new Texture2D(&m_GaussianTexture_horiz, GL_COLOR_ATTACHMENT0))); + } + m_GaussianFrameBuffer_horiz.Generate(); + + //CommonFunctions::GenerateTexture(&m_DepthStencil_vert, GL_CLAMP_TO_BORDER, GL_NEAREST, + // res2, GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8); + CommonFunctions::GenerateTexture(&m_GaussianTexture_vert, GL_CLAMP_TO_EDGE, GL_NEAREST, + res2, GL_RGBA16F, GL_RGBA, GL_FLOAT); + + if (m_GaussianFrameBuffer_vert.GetHandle() == 0) { + m_GaussianFrameBuffer_vert.AddResource(std::shared_ptr(new Texture2D(&m_DepthStencil_horiz, GL_DEPTH_STENCIL_ATTACHMENT))); + m_GaussianFrameBuffer_vert.AddResource(std::shared_ptr(new Texture2D(&m_GaussianTexture_vert, GL_COLOR_ATTACHMENT0))); + } + m_GaussianFrameBuffer_vert.Generate(); + + CommonFunctions::GenerateTexture(&m_CombinedTexture, GL_CLAMP_TO_BORDER, GL_NEAREST, + res, GL_RGB16F, GL_RGB, GL_FLOAT); + + if (m_CombinedTextureBuffer.GetHandle() == 0) { + m_CombinedTextureBuffer.AddResource(std::shared_ptr(new Texture2D(&m_CombinedTexture, GL_COLOR_ATTACHMENT0))); + } + m_CombinedTextureBuffer.Generate(); +} + + +void BlurHUD::ClearBuffer() +{ + GLERROR("PRE"); + m_GaussianFrameBuffer_horiz.Bind(); + glClearColor(0.f, 0.f, 0.f, 0.f); + glClearStencil(0x00); + glStencilMask(~0); + glDisable(GL_SCISSOR_TEST); + glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + m_GaussianFrameBuffer_horiz.Unbind(); + m_GaussianFrameBuffer_vert.Bind(); + glClearColor(0.f, 0.f, 0.f, 0.f); + glClearStencil(0x00); + glStencilMask(~0); + glDisable(GL_SCISSOR_TEST); + glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + m_GaussianFrameBuffer_vert.Unbind(); + + m_CombinedTextureBuffer.Bind(); + glClearColor(0.f, 0.f, 0.f, 0.f); + glClear(GL_COLOR_BUFFER_BIT); + m_CombinedTextureBuffer.Unbind(); + GLERROR("END"); +} + +//Returns the finished blurred texture +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; + state.Disable(GL_BLEND); + state.Disable(GL_DEPTH_TEST); + state.Disable(GL_CULL_FACE); + + state.Enable(GL_STENCIL_TEST); + state.StencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + state.StencilFunc(GL_EQUAL, 1, 0xFF); + state.StencilMask(0x00); + state.DepthMask(GL_FALSE); + state.Enable(GL_SCISSOR_TEST); + + GLuint shaderHandle_horiz = m_GaussianProgram_horiz->GetHandle(); + GLuint shaderHandle_vert = m_GaussianProgram_vert->GetHandle(); + + //Horizontal pass, first use the given texture then save it to the horizontal framebuffer. + m_GaussianFrameBuffer_horiz.Bind(); + + 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 + , GL_UNSIGNED_INT, 0, m_ScreenQuad->MaterialGroups()[0].material->StartIndex); + //Iterate some times to make it more gaussian. + for (int i = 1; i < m_Iterations; i++) { + //Vertical pass + m_GaussianFrameBuffer_vert.Bind(); + m_GaussianProgram_vert->Bind(); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, m_GaussianTexture_horiz); + + 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 + m_GaussianFrameBuffer_vert.Unbind(); + m_GaussianFrameBuffer_horiz.Bind(); + m_GaussianProgram_horiz->Bind(); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, m_GaussianTexture_vert); + + 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(); + } + + //final vertical gaussian after the iterations are done + + m_GaussianFrameBuffer_vert.Bind(); + m_GaussianProgram_vert->Bind(); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, m_GaussianTexture_horiz); + + 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); + + GLERROR("DrawBloomPass::Draw: END"); + glViewport(0, 0, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); + glScissor(0, 0, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); + + + return m_GaussianTexture_vert; +} + + +void BlurHUD::OnWindowResize() +{ + InitializeBuffers(); +} + +void BlurHUD::FillStencil(RenderScene& scene) +{ + RenderState state; + + state.BindFramebuffer(m_GaussianFrameBuffer_horiz.GetHandle()); + state.Enable(GL_DEPTH_TEST); + state.Enable(GL_CULL_FACE); + state.Enable(GL_STENCIL_TEST); + state.StencilFunc(GL_ALWAYS, 1, 0xFF); + state.StencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + state.StencilMask(0xFF); + + state.AlphaFunc(GL_GEQUAL, 0.95f); + state.Enable(GL_ALPHA_TEST); + + glViewport(0, 0, m_Renderer->GetViewportSize().Width/m_BlurQuality, m_Renderer->GetViewportSize().Height/m_BlurQuality); + + m_FillDepthStencilProgram->Bind(); + + GLuint shaderHandle = m_FillDepthStencilProgram->GetHandle(); + glm::mat4 VP = scene.Camera->ProjectionMatrix() * scene.Camera->ViewMatrix(); + + + for (auto& job : scene.Jobs.SpriteJob) { + auto spriteJob = std::dynamic_pointer_cast(job); + if (!spriteJob) { + continue; + } + if (!spriteJob->BlurBackground) { + continue; + } + + 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); + glDrawElements(GL_TRIANGLES, spriteJob->EndIndex - spriteJob->StartIndex + 1, GL_UNSIGNED_INT, (void*)(spriteJob->StartIndex*sizeof(unsigned int))); + } + + //state.BindFramebuffer(m_GaussianFrameBuffer_vert.GetHandle()); + //for (auto& job : scene.Jobs.SpriteJob) { + // auto spriteJob = std::dynamic_pointer_cast(job); + // if (!spriteJob) { + // continue; + // } + // if(!spriteJob->BlurBackground) { + // continue; + // } + // 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); + // glDrawElements(GL_TRIANGLES, spriteJob->EndIndex - spriteJob->StartIndex + 1, GL_UNSIGNED_INT, (void*)(spriteJob->StartIndex*sizeof(unsigned int))); + //} + glViewport(0, 0, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); +} + +//Texture 1 will be used if texture 2 is black at that texel, else texture 2 is used. +GLuint BlurHUD::CombineTextures(GLuint texture1, GLuint texture2) +{ + //RenderState state; + //state.BindFramebuffer(m_CombinedTextureBuffer.GetHandle()); + //state.Disable(GL_DEPTH_TEST); + //state.Disable(GL_STENCIL_TEST); + + m_CombineTexturesProgram->Bind(); + + glActiveTexture(GL_TEXTURE0); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, texture1); + glBindTexture(GL_TEXTURE_2D, texture2); + 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); + + return m_CombinedTexture; +} diff --git a/src/Engine/Rendering/BoneAttachmentSystem.cpp b/src/Engine/Rendering/BoneAttachmentSystem.cpp index 3effaf2c..82fd9507 100644 --- a/src/Engine/Rendering/BoneAttachmentSystem.cpp +++ b/src/Engine/Rendering/BoneAttachmentSystem.cpp @@ -8,10 +8,13 @@ void BoneAttachmentSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapp return; } - auto parent = entity.FirstParentWithComponent("Animation"); - if (!parent.HasComponent("Model")) { + auto parent = entity.FirstParentWithComponent("Model"); + + if(!parent.Valid()) { return; } + + Model* model; try { model = ResourceManager::Load<::Model, true>(parent["Model"]["Resource"]); @@ -23,7 +26,7 @@ void BoneAttachmentSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapp return; } - Skeleton* skeleton = model->m_RawModel->m_Skeleton; + Skeleton* skeleton = model->m_Skeleton; if(skeleton == nullptr) { return; @@ -35,66 +38,31 @@ void BoneAttachmentSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapp return; } - std::vector<::Skeleton::AnimationData> Animations; - ::Skeleton::AnimationOffset AnimationOffset; - glm::mat4 boneTransform; + if (skeleton->BlendTrees.find(parent) != skeleton->BlendTrees.end()) { - if (parent.HasComponent("Animation")) { - for (int i = 1; i <= 3; i++) { - ::Skeleton::AnimationData animationData; - animationData.animation = model->m_RawModel->m_Skeleton->GetAnimation(parent["Animation"]["AnimationName" + std::to_string(i)]); - if (animationData.animation == nullptr) { - continue; - } - animationData.time = (double)parent["Animation"]["Time" + std::to_string(i)]; - animationData.weight = (double)parent["Animation"]["Weight" + std::to_string(i)]; - Animations.push_back(animationData); - } - } + glm::mat4 boneTransform = skeleton->BlendTrees.at(parent)->GetBoneTransform(id); - if (parent.HasComponent("AnimationOffset")) { - AnimationOffset.animation = model->m_RawModel->m_Skeleton->GetAnimation(parent["AnimationOffset"]["AnimationName"]); - AnimationOffset.time = (double)parent["AnimationOffset"]["Time"]; + glm::vec3 scale; + glm::quat rotation; + glm::vec3 translation; + glm::vec3 skew; + glm::vec4 perspective; + glm::decompose(boneTransform, scale, rotation, translation, skew, perspective); - if(AnimationOffset.animation != nullptr) { - boneTransform = skeleton->GetBoneTransform(false, skeleton->Bones.at(id), Animations, AnimationOffset, glm::mat4(1)); - } else { - boneTransform = skeleton->GetBoneTransform(false, skeleton->Bones.at(id), Animations, glm::mat4(1)); - } + rotation = glm::quat((glm::vec3)entity["BoneAttachment"]["OrientationOffset"]) * rotation; + rotation = glm::inverse(rotation); + glm::vec3 angles = glm::eulerAngles(rotation); - } else { - boneTransform = skeleton->GetBoneTransform(false, skeleton->Bones.at(id), Animations, glm::mat4(1)); + if ((bool)entity["BoneAttachment"]["InheritPosition"]) { + entity["Transform"]["Position"] = translation + (glm::vec3)entity["BoneAttachment"]["PositionOffset"]; + } + if ((bool)entity["BoneAttachment"]["InheritOrientation"]) { + entity["Transform"]["Orientation"] = angles; + } + if ((bool)entity["BoneAttachment"]["InheritScale"]) { + entity["Transform"]["Scale"] = scale * (glm::vec3)entity["BoneAttachment"]["ScaleOffset"]; + } } - - - glm::vec3 scale; - glm::quat rotation; - glm::vec3 translation; - glm::vec3 skew; - glm::vec4 perspective; - glm::decompose(boneTransform, scale, rotation, translation, skew, perspective); - - glm::vec3 angles = glm::vec3(-glm::pitch(rotation), -glm::yaw(rotation), -glm::roll(rotation)); -/* - - angles.y = asin(-boneTransform[0][2]); - if (cos(angles.y) != 0) { - angles.x = atan2(boneTransform[1][2], boneTransform[2][2]); - angles.z = atan2(boneTransform[0][1], boneTransform[0][0]); - } else { - angles.x = atan2(-boneTransform[2][0], boneTransform[1][1]); - angles.z = 0; - }*/ - - if ((bool)entity["BoneAttachment"]["InheritPosition"]) { - (glm::vec3&)entity["Transform"]["Position"] = translation + (glm::vec3)entity["BoneAttachment"]["PositionOffset"]; - } - if ((bool)entity["BoneAttachment"]["InheritOrientation"]) { - (glm::vec3&)entity["Transform"]["Orientation"] = angles + (glm::vec3)entity["BoneAttachment"]["OrientationOffset"]; - } - if ((bool)entity["BoneAttachment"]["InheritScale"]) { - (glm::vec3&)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..c567789b 100644 --- a/src/Engine/Rendering/CubeMapPass.cpp +++ b/src/Engine/Rendering/CubeMapPass.cpp @@ -6,30 +6,37 @@ 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) + ".dds"; + m_CubeMapTextures.push_back(path); } GenerateCubeMapTexture(); - m_PreviusCubeMapTexture = input; + m_PreviusCubeMapTexture = cubemapName; } } void CubeMapPass::GenerateCubeMapTexture() { - if (m_CubeMapTexture == -1) { + if (m_CubeMapTexture == 0) { glGenTextures(1, &m_CubeMapTexture); } 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); + DDS* img = ResourceManager::Load(m_CubeMapTextures[i]); + std::size_t bpe = 16; + std::size_t numBlocksWide = std::max(1, (img->Width + 3) / 4); + std::size_t numBlocksHigh = std::max(1, (img->Height + 3) / 4); + std::size_t rowBytes = numBlocksWide * bpe; + std::size_t numRows = numBlocksHigh; + std::size_t numBytes = rowBytes * numBlocksHigh; + glCompressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, img->Width, img->Height, 0, numBytes, img->Data); + //glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA32F, img->Width, img->Height, 0, GL_COMPRESSED_RGBA, GL_UNSIGNED_BYTE, img->Data); + ResourceManager::Release("DDS", 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/DDS.cpp b/src/Engine/Rendering/DDS.cpp new file mode 100644 index 00000000..8348c9a9 --- /dev/null +++ b/src/Engine/Rendering/DDS.cpp @@ -0,0 +1,121 @@ +#include "Rendering/DDS.h" + +DDS::DDS(std::string path) +{ + std::ifstream in(path.c_str(), std::ios_base::binary | std::ios_base::ate); + if (!in.is_open()) { + throw Resource::FailedLoadingException("Failed to open file."); + } + unsigned int fileSize = static_cast(in.tellg()); + in.seekg(0, std::ios_base::beg); + + if (fileSize < sizeof(MagicNumber) + sizeof(DDS::Header_t)) { + throw Resource::FailedLoadingException("Invalid DDS file; not even big enough to contain the DDS header!"); + } + + // Read magic number + uint32_t magicNumber; + in.read(reinterpret_cast(&magicNumber), sizeof(MagicNumber)); + if (magicNumber != DDS::MagicNumber) { + throw Resource::FailedLoadingException("Invalid DDS file; magic number doesn't match."); + } + + // Read header + in.read(reinterpret_cast(&m_Header), sizeof(DDS::Header_t)); + + // Validate header + if (m_Header.Size != sizeof(DDS::Header_t) || m_Header.PixelFormat.Size != sizeof(DDS::Header_t::PixelFormat_t)) { + throw Resource::FailedLoadingException("Corrupt DDS file; header size doesn't match!"); + } + + // Make sure it's DC3 (DXT5) + char format[5]; + memcpy(&format, &m_Header.PixelFormat.FourCC, 4); + format[4] = '\0'; + if (strcmp(format, "DXT5")) { + std::stringstream ss; + ss << "Invalid DDS file; Unsupported compression format \"" << format << "\""; + throw Resource::FailedLoadingException(ss.str().c_str()); + } + + this->Width = m_Header.Width; + this->Height = m_Header.Height; + this->Format = Image::ImageFormat::RGBA; + this->Compressed = true; + if (m_Header.MipMapCount != 0) { + this->MipMapLevels = m_Header.MipMapCount - 1; + } + + // Read data + std::size_t dataSize = fileSize - sizeof(MagicNumber) - sizeof(DDS::Header_t); + this->Data = new unsigned char[dataSize]; + this->ByteSize = dataSize; + in.read(reinterpret_cast(this->Data), dataSize); + + // Flip! + unsigned int w = this->Width; + unsigned int h = this->Height; + unsigned char* mipMapData = this->Data; + for (unsigned int i = 0; i < this->MipMapLevels; ++i) { + std::size_t bpe = 16; + std::size_t numBlocksWide = std::max(1, (w + 3) / 4); + std::size_t numBlocksHigh = std::max(1, (h + 3) / 4); + std::size_t rowBytes = numBlocksWide * bpe; + std::size_t numRows = numBlocksHigh; + std::size_t numBytes = rowBytes * numBlocksHigh; + FlipY(mipMapData, rowBytes, numBytes, numBlocksWide); + w = w >> 1; + h = h >> 1; + mipMapData += numBytes; + } +} + +DDS::~DDS() +{ + if (this->Data != nullptr) { + delete[] this->Data; + this->Data = nullptr; + } +} + +void DDS::FlipY(unsigned char* data, std::size_t rowBytes, std::size_t totalSize, std::size_t numBlocksWide) +{ + std::size_t height = totalSize / rowBytes; + unsigned char* topLine = data; + unsigned char* bottomLine = data + (height - 1) * rowBytes; + for (std::size_t line = 0; line < height / 2; ++line) { + Block_t* topBlocks = reinterpret_cast(topLine); + Block_t* bottomBlocks = reinterpret_cast(bottomLine); + for (std::size_t block = 0; block < numBlocksWide; ++block) { + flipBlock(&topBlocks[block]); + flipBlock(&bottomBlocks[block]); + std::swap(topBlocks[block], bottomBlocks[block]); + } + topLine += rowBytes; + bottomLine -= rowBytes; + } +} + +void DDS::flipBlock(Block_t* block) +{ + // Extract both rows of pixel Data into a 32 bit sized values. + uint32_t pixelRow0 = block->Alpha.Data[0] + ((block->Alpha.Data[1] + (block->Alpha.Data[2] << 8)) << 8); + uint32_t pixelRow1 = block->Alpha.Data[3] + ((block->Alpha.Data[4] + (block->Alpha.Data[5] << 8)) << 8); + + // Swap the extracted row Data. These values will be read from and shifted into the final block locations. + uint32_t pixelRow0Swapped = ((pixelRow0 & 0x000fff) << 12) | ((pixelRow0 & 0xfff000) >> 12); + uint32_t pixelRow1Swapped = ((pixelRow1 & 0x000fff) << 12) | ((pixelRow1 & 0xfff000) >> 12); + + // Swapped Data from row 1 is written + block->Alpha.Data[0] = static_cast(pixelRow1Swapped & 0x0000ff); + block->Alpha.Data[1] = static_cast((pixelRow1Swapped & 0x00ff00) >> 8); + block->Alpha.Data[2] = static_cast((pixelRow1Swapped & 0xff0000) >> 16); + + // Swapped Data from row 0 is written + block->Alpha.Data[3] = static_cast(pixelRow0Swapped & 0x0000ff); + block->Alpha.Data[4] = static_cast((pixelRow0Swapped & 0x00ff00) >> 8); + block->Alpha.Data[5] = static_cast((pixelRow0Swapped & 0xff0000) >> 16); + + std::swap(block->Data.Data[0], block->Data.Data[3]); + std::swap(block->Data.Data[1], block->Data.Data[2]); +} diff --git a/src/Engine/Rendering/DrawBloomPass.cpp b/src/Engine/Rendering/DrawBloomPass.cpp index e8ad4cd5..13d1a934 100644 --- a/src/Engine/Rendering/DrawBloomPass.cpp +++ b/src/Engine/Rendering/DrawBloomPass.cpp @@ -1,19 +1,46 @@ #include "Rendering/DrawBloomPass.h" -DrawBloomPass::DrawBloomPass(IRenderer* renderer) +DrawBloomPass::DrawBloomPass(IRenderer* renderer, ConfigFile* config) + : m_Renderer(renderer) + , m_Config(config) { - m_Renderer = renderer; + InitializeTextures(); - m_ScreenQuad = ResourceManager::Load("Models/Core/ScreenQuad.mesh"); + ChangeQuality(m_Config->Get("GLOW.Quality", 2)); +} - InitializeTextures(); - InitializeBuffers(); - InitializeShaderPrograms(); +DrawBloomPass::~DrawBloomPass() { + CommonFunctions::DeleteTexture(&m_GaussianTexture_horiz); + CommonFunctions::DeleteTexture(&m_GaussianTexture_vert); + CommonFunctions::DeleteTexture(&m_FinalGaussianTexture); } void DrawBloomPass::InitializeTextures() { - m_WhiteTexture = CommonFunctions::LoadTexture("Textures/Core/White.png", false); + m_BlackTexture = CommonFunctions::TryLoadResource("Textures/Core/Black.png"); +} + +void DrawBloomPass::ChangeQuality(int quality) +{ + if (m_Quality == quality) { + return; + } + m_Quality = quality; + + m_ScreenQuad = ResourceManager::Load("Models/Core/ScreenQuad.mesh"); + + if (m_Quality == 0) { + CommonFunctions::DeleteTexture(&m_GaussianTexture_horiz); + CommonFunctions::DeleteTexture(&m_GaussianTexture_vert); + CommonFunctions::DeleteTexture(&m_FinalGaussianTexture); + return; + } + InitializeTextures(); + + InitializeBuffers(); + InitializeShaderPrograms(); + std::string qStr = std::to_string(m_Quality); + m_Iterations = m_Config->Get("GLOW" + qStr + ".NumIterations", 0); } void DrawBloomPass::InitializeShaderPrograms() @@ -23,6 +50,7 @@ void DrawBloomPass::InitializeShaderPrograms() m_GaussianProgram_horiz->AddShader(std::shared_ptr(new VertexShader("Shaders/Gaussian_horiz.vert.glsl"))); m_GaussianProgram_horiz->AddShader(std::shared_ptr(new FragmentShader("Shaders/Gaussian_horiz.frag.glsl"))); m_GaussianProgram_horiz->Compile(); + m_GaussianProgram_horiz->BindFragDataLocation(0, "fragmentColor"); m_GaussianProgram_horiz->Link(); } @@ -31,52 +59,120 @@ void DrawBloomPass::InitializeShaderPrograms() m_GaussianProgram_vert->AddShader(std::shared_ptr(new VertexShader("Shaders/Gaussian_vert.vert.glsl"))); m_GaussianProgram_vert->AddShader(std::shared_ptr(new FragmentShader("Shaders/Gaussian_vert.frag.glsl"))); m_GaussianProgram_vert->Compile(); + m_GaussianProgram_vert->BindFragDataLocation(0, "fragmentColor"); m_GaussianProgram_vert->Link(); } -} + m_GaussianCombineProgram = ResourceManager::Load("#GaussianCombineProgram"); + if (m_GaussianCombineProgram->GetHandle() == 0) { + m_GaussianCombineProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/CombineGaussianTexture.vert.glsl"))); + m_GaussianCombineProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/CombineGaussianTexture.frag.glsl"))); + m_GaussianCombineProgram->Compile(); + m_GaussianCombineProgram->BindFragDataLocation(0, "fragmentColor"); + m_GaussianCombineProgram->Link(); + } +} void DrawBloomPass::InitializeBuffers() { - GenerateTexture(&m_GaussianTexture_horiz, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_RGB16F, GL_RGB, GL_FLOAT); + CommonFunctions::GenerateMipMapTexture( + &m_GaussianTexture_horiz, GL_CLAMP_TO_BORDER, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), + GL_RGB16F, GL_RGB, GL_FLOAT, m_BloomLod, GL_LINEAR, GL_LINEAR_MIPMAP_NEAREST); + CommonFunctions::GenerateMipMapTexture( + &m_GaussianTexture_vert, GL_CLAMP_TO_BORDER, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), + GL_RGB16F, GL_RGB, GL_FLOAT, m_BloomLod, GL_LINEAR, GL_LINEAR_MIPMAP_NEAREST); + CommonFunctions::GenerateTexture(&m_FinalGaussianTexture, GL_CLAMP_TO_BORDER, GL_NEAREST, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_RGB16F, GL_RGB, GL_FLOAT); - m_GaussianFrameBuffer_horiz.AddResource(std::shared_ptr(new Texture2D(&m_GaussianTexture_horiz, GL_COLOR_ATTACHMENT0))); - m_GaussianFrameBuffer_horiz.Generate(); + if (m_GaussianCombineBuffer.GetHandle() == 0) { + m_GaussianCombineBuffer.AddResource(std::shared_ptr(new Texture2D(&m_FinalGaussianTexture, GL_COLOR_ATTACHMENT0))); + } + m_GaussianCombineBuffer.Generate(); - GenerateTexture(&m_GaussianTexture_vert, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_RGB16F, GL_RGB, GL_FLOAT); + if(m_GaussianFrameBuffer_horiz == nullptr) { + m_GaussianFrameBuffer_horiz = new FrameBuffer[m_BloomLod]; + } + if (m_GaussianFrameBuffer_vert == nullptr) { + m_GaussianFrameBuffer_vert = new FrameBuffer[m_BloomLod]; + } - m_GaussianFrameBuffer_vert.AddResource(std::shared_ptr(new Texture2D(&m_GaussianTexture_vert, GL_COLOR_ATTACHMENT0))); - m_GaussianFrameBuffer_vert.Generate(); + for (int i = 0; i < m_BloomLod; i++) { + if(m_GaussianFrameBuffer_horiz[i].GetHandle() == 0) { + m_GaussianFrameBuffer_horiz[i].AddResource(std::shared_ptr(new Texture2D(&m_GaussianTexture_horiz, GL_COLOR_ATTACHMENT0, i))); + } + m_GaussianFrameBuffer_horiz[i].Generate(); + + if (m_GaussianFrameBuffer_vert[i].GetHandle() == 0) { + m_GaussianFrameBuffer_vert[i].AddResource(std::shared_ptr(new Texture2D(&m_GaussianTexture_vert, GL_COLOR_ATTACHMENT0, i))); + } + m_GaussianFrameBuffer_vert[i].Generate(); + } } void DrawBloomPass::ClearBuffer() { + if (m_Quality == 0) { + return; + } GLERROR("PRE"); - m_GaussianFrameBuffer_horiz.Bind(); + for (int i = 0; i < m_BloomLod; i++) { + m_GaussianFrameBuffer_horiz[i].Bind(); + glClearColor(0.f, 0.f, 0.f, 0.f); + glClear(GL_COLOR_BUFFER_BIT); + m_GaussianFrameBuffer_horiz[i].Unbind(); + m_GaussianFrameBuffer_vert[i].Bind(); + glClearColor(0.f, 0.f, 0.f, 0.f); + glClear(GL_COLOR_BUFFER_BIT); + m_GaussianFrameBuffer_vert[i].Unbind(); + + } + m_GaussianCombineBuffer.Bind(); glClearColor(0.f, 0.f, 0.f, 0.f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - m_GaussianFrameBuffer_horiz.Unbind(); - m_GaussianFrameBuffer_vert.Bind(); - glClearColor(0.f, 0.f, 0.f, 0.f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - m_GaussianFrameBuffer_vert.Unbind(); + glClear(GL_COLOR_BUFFER_BIT); + m_GaussianCombineBuffer.Unbind(); GLERROR("END"); } void DrawBloomPass::Draw(GLuint texture) { - GLERROR("DrawBloomPass::Draw: Pre"); + if (m_Quality == 0) { + return; + } + for (int i = 0; i < m_BloomLod; i++) { + GaussianLodPass(i, texture); + } + CombineGaussianBlur(); +} + + +void DrawBloomPass::OnWindowResize() +{ + if (m_Quality == 0) { + return; + } + InitializeBuffers(); +} + +void DrawBloomPass::GaussianLodPass(GLuint mipMap, GLuint texture) +{ + GLERROR("DrawBloomPass::Draw: Pre"); + glViewport(0, 0, m_Renderer->GetViewportSize().Width/(glm::pow(2, mipMap)), m_Renderer->GetViewportSize().Height/(glm::pow(2, mipMap))); DrawBloomPassState state; GLuint shaderHandle_horiz = m_GaussianProgram_horiz->GetHandle(); GLuint shaderHandle_vert = m_GaussianProgram_vert->GetHandle(); + m_GaussianProgram_vert->Bind(); + glUniform1i(glGetUniformLocation(shaderHandle_vert, "Lod"), mipMap); + m_GaussianProgram_horiz->Bind(); + glUniform1i(glGetUniformLocation(shaderHandle_horiz, "Lod"), mipMap); + //Horizontal pass, first use the given texture then save it to the horizontal framebuffer. - m_GaussianFrameBuffer_horiz.Bind(); - m_GaussianProgram_horiz->Bind(); + m_GaussianFrameBuffer_horiz[mipMap].Bind(); + + glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texture); glBindVertexArray(m_ScreenQuad->VAO); @@ -84,61 +180,58 @@ void DrawBloomPass::Draw(GLuint texture) 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); //Iterate some times to make it more gaussian. - for (int i = 1; i < m_iterations; i++) { + for (int i = 1; i < m_Iterations; i++) { //Vertical pass - m_GaussianFrameBuffer_vert.Bind(); + m_GaussianFrameBuffer_vert[mipMap].Bind(); m_GaussianProgram_vert->Bind(); + + 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 + m_GaussianFrameBuffer_vert[mipMap].Unbind(); - m_GaussianFrameBuffer_horiz.Bind(); + m_GaussianFrameBuffer_horiz[mipMap].Bind(); m_GaussianProgram_horiz->Bind(); + 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[mipMap].Unbind(); } //final vertical gaussian after the iterations are done - m_GaussianFrameBuffer_vert.Bind(); + m_GaussianFrameBuffer_vert[mipMap].Bind(); m_GaussianProgram_vert->Bind(); + 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); GLERROR("DrawBloomPass::Draw: END"); + glViewport(0, 0, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); + m_GaussianFrameBuffer_vert[mipMap].Unbind(); + } - -void DrawBloomPass::OnWindowResize() +void DrawBloomPass::CombineGaussianBlur() { - GenerateTexture(&m_GaussianTexture_vert, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_RGB16F, GL_RGB, GL_FLOAT); - m_GaussianFrameBuffer_vert.Generate(); - GenerateTexture(&m_GaussianTexture_horiz, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_RGB16F, GL_RGB, GL_FLOAT); - m_GaussianFrameBuffer_horiz.Generate(); -} + m_GaussianCombineBuffer.Bind(); + m_GaussianCombineProgram->Bind(); + glUniform1i(glGetUniformLocation(m_GaussianCombineProgram->GetHandle(), "MaxMipMap"), m_BloomLod); -void DrawBloomPass::GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type) const -{ - glGenTextures(1, texture); - glBindTexture(GL_TEXTURE_2D, *texture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapping); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapping); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering); - glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, dimensions.x, dimensions.y, 0, format, type, nullptr);//TODO: Renderer: Fix the precision and Resolution - GLERROR("Texture initialization failed"); + 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); } diff --git a/src/Engine/Rendering/DrawColorCorrectionPass.cpp b/src/Engine/Rendering/DrawColorCorrectionPass.cpp index c82d614f..70d3a053 100644 --- a/src/Engine/Rendering/DrawColorCorrectionPass.cpp +++ b/src/Engine/Rendering/DrawColorCorrectionPass.cpp @@ -18,7 +18,7 @@ void DrawColorCorrectionPass::InitializeShaderPrograms() m_ColorCorrectionProgram->Link(); } -void DrawColorCorrectionPass::Draw(GLuint sceneTexture, GLuint bloomTexture, GLuint sceneTextureLowRes, GLuint bloomTextureLowRes, GLfloat gamma, GLfloat exposure) +void DrawColorCorrectionPass::Draw(GLuint sceneTexture, GLuint bloomTexture, GLfloat gamma, GLfloat exposure) { //glBindFramebuffer(GL_FRAMEBUFFER, 0); GLERROR("DrawScreenQuadPass::Draw: Pre"); @@ -33,10 +33,6 @@ void DrawColorCorrectionPass::Draw(GLuint sceneTexture, GLuint bloomTexture, GLu glBindTexture(GL_TEXTURE_2D, sceneTexture); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, bloomTexture); - glActiveTexture(GL_TEXTURE2); - glBindTexture(GL_TEXTURE_2D, sceneTextureLowRes); - glActiveTexture(GL_TEXTURE3); - glBindTexture(GL_TEXTURE_2D, bloomTextureLowRes); glBindVertexArray(m_ScreenQuad->VAO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ScreenQuad->ElementBuffer); diff --git a/src/Engine/Rendering/DrawFinalPass.cpp b/src/Engine/Rendering/DrawFinalPass.cpp index 6cd2c1f1..be5bf1ea 100644 --- a/src/Engine/Rendering/DrawFinalPass.cpp +++ b/src/Engine/Rendering/DrawFinalPass.cpp @@ -1,64 +1,127 @@ #include "Rendering/DrawFinalPass.h" - -DrawFinalPass::DrawFinalPass(IRenderer* renderer, LightCullingPass* lightCullingPass, CubeMapPass* cubeMapPass) - : m_Renderer(renderer) - , m_LightCullingPass(lightCullingPass) - , m_CubeMapPass(cubeMapPass) +DrawFinalPass::DrawFinalPass(IRenderer* renderer, LightCullingPass* lightCullingPass, CubeMapPass* cubeMapPass, SSAOPass* ssaoPass, ShadowPass* shadowPass, ConfigFile* config) + : m_Renderer(renderer) + , m_LightCullingPass(lightCullingPass) + , m_CubeMapPass(cubeMapPass) + , m_SSAOPass(ssaoPass) + , m_ShadowPass(shadowPass) { //TODO: Make sure that uniforms are not sent into shader if not needed. m_ShieldPixelRate = 8; + m_FinalPassFrameBuffer = new FrameBuffer(); + m_ShieldDepthFrameBuffer = new FrameBuffer(); + + setMSAA(config->Get("MSAA.Level", 0)); + InitializeTextures(); InitializeShaderPrograms(); InitializeFrameBuffers(); } +DrawFinalPass::~DrawFinalPass(){ + CommonFunctions::DeleteTexture(&m_BloomTexture); + CommonFunctions::DeleteTexture(&m_SceneTexture); + CommonFunctions::DeleteTexture(&m_DepthBuffer); + CommonFunctions::DeleteTexture(&m_ShieldBuffer); + CommonFunctions::DeleteTexture(&m_CubeMapTexture); + + delete m_FinalPassFrameBuffer; + delete m_ShieldDepthFrameBuffer; +} + void DrawFinalPass::InitializeTextures() { - m_WhiteTexture = CommonFunctions::LoadTexture("Textures/Core/White.png", false); - m_BlackTexture = CommonFunctions::LoadTexture("Textures/Core/Black.png", false); - m_NeutralNormalTexture = CommonFunctions::LoadTexture("Textures/Core/NeutralNormalMap.png", false); - m_GreyTexture = CommonFunctions::LoadTexture("Textures/Core/Grey.png", false); - m_ErrorTexture = CommonFunctions::LoadTexture("Textures/Core/ErrorTexture.png", false); + m_WhiteTexture = CommonFunctions::TryLoadResource("Textures/Core/White.png"); + m_BlackTexture = CommonFunctions::TryLoadResource("Textures/Core/Black.png"); + m_NeutralNormalTexture = CommonFunctions::TryLoadResource("Textures/Core/NeutralNormalMap.png"); + m_GreyTexture = CommonFunctions::TryLoadResource("Textures/Core/Grey.png"); + m_ErrorTexture = CommonFunctions::TryLoadResource("Textures/Core/ErrorTexture.png"); } void DrawFinalPass::InitializeFrameBuffers() { - glGenRenderbuffers(1, &m_DepthBuffer); - glBindRenderbuffer(GL_RENDERBUFFER, m_DepthBuffer); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); - GLERROR("RenderBuffer generation"); + if (m_MSAA) { + CommonFunctions::GenerateTexture(&m_AntiAliasedTexture, GL_CLAMP_TO_BORDER, GL_NEAREST, + glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_RGB16F, GL_RGB, GL_FLOAT); + if (m_AntiAliasedFrameBuffer == nullptr) { + m_AntiAliasedFrameBuffer = new FrameBuffer(); + m_AntiAliasedFrameBuffer->AddResource(std::shared_ptr(new Texture2D(&m_AntiAliasedTexture, GL_COLOR_ATTACHMENT0))); + } + m_AntiAliasedFrameBuffer->Generate(); - GenerateTexture(&m_SceneTexture, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_RGB16F, GL_RGB, GL_FLOAT); - //GenerateTexture(&m_BloomTexture, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewPortSize().Width, m_Renderer->GetViewPortSize().Height), GL_RGB16F, GL_RGB, GL_FLOAT); - GenerateTexture(&m_BloomTexture, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_RGB16F, GL_RGB, GL_FLOAT); - //GenerateMipMapTexture(&m_BloomTexture, GL_CLAMP_TO_EDGE, glm::vec2(m_Renderer->GetViewPortSize().Width, m_Renderer->GetViewPortSize().Height), GL_RGB16F, GL_FLOAT, 4); - //GenerateTexture(&m_StencilTexture, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_STENCIL, GL_STENCIL_INDEX8, GL_INT); + if (m_SceneTexture != 0) { + glDeleteRenderbuffers(1, &m_SceneTexture); + } + glGenRenderbuffers(1, &m_SceneTexture); + GLERROR("FBO 1"); + glBindRenderbuffer(GL_RENDERBUFFER, m_SceneTexture); + GLERROR("FBO 11"); + glRenderbufferStorageMultisample(GL_RENDERBUFFER, m_MSAA, GL_RGB16F, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); + GLERROR("FBO 111"); - m_FinalPassFrameBuffer.AddResource(std::shared_ptr(new RenderBuffer(&m_DepthBuffer, GL_DEPTH_STENCIL_ATTACHMENT))); - //m_FinalPassFrameBuffer.AddResource(std::shared_ptr(new Texture2D(&m_StencilTexture, GL_STENCIL_ATTACHMENT))); - m_FinalPassFrameBuffer.AddResource(std::shared_ptr(new Texture2D(&m_SceneTexture, GL_COLOR_ATTACHMENT0))); - m_FinalPassFrameBuffer.AddResource(std::shared_ptr(new Texture2D(&m_BloomTexture, GL_COLOR_ATTACHMENT1))); - m_FinalPassFrameBuffer.Generate(); + if (m_BloomTexture != 0) { + glDeleteRenderbuffers(1, &m_BloomTexture); + } + glGenRenderbuffers(1, &m_BloomTexture); + GLERROR("FBO 2"); + glBindRenderbuffer(GL_RENDERBUFFER, m_BloomTexture); + GLERROR("FBO 22"); + glRenderbufferStorageMultisample(GL_RENDERBUFFER, m_MSAA, GL_RGB16F, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); + GLERROR("FBO 222"); + + if (m_DepthBuffer != 0) { + glDeleteRenderbuffers(1, &m_DepthBuffer); + } + glGenRenderbuffers(1, &m_DepthBuffer); + GLERROR("FBO 3"); + glBindRenderbuffer(GL_RENDERBUFFER, m_DepthBuffer); + GLERROR("FBO 33"); + glRenderbufferStorageMultisample(GL_RENDERBUFFER, m_MSAA, GL_DEPTH24_STENCIL8, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); + GLERROR("FBO 333"); + + //CommonFunctions::GenerateMultiSampleTexture(&m_SceneTexture, m_MSAA, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_RGB16F); + //CommonFunctions::GenerateMultiSampleTexture(&m_BloomTexture, m_MSAA, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_RGB16F); + + //CommonFunctions::GenerateMultiSampleTexture(&m_DepthBuffer, m_MSAA, + //glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_DEPTH24_STENCIL8); + + //CommonFunctions::GenerateMultiSampleTexture(&m_ShieldBuffer, m_MSAA, + //glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_DEPTH_COMPONENT32F); + } else { + CommonFunctions::GenerateTexture(&m_SceneTexture, GL_CLAMP_TO_BORDER, GL_LINEAR, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_RGB16F, GL_RGB, GL_FLOAT); + //GenerateTexture(&m_BloomTexture, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewPortSize().Width, m_Renderer->GetViewPortSize().Height), GL_RGB16F, GL_RGB, GL_FLOAT); + CommonFunctions::GenerateTexture(&m_BloomTexture, GL_CLAMP_TO_BORDER, GL_LINEAR, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_RGB16F, GL_RGB, GL_FLOAT); + //GenerateMipMapTexture(&m_BloomTexture, GL_CLAMP_TO_EDGE, glm::vec2(m_Renderer->GetViewPortSize().Width, m_Renderer->GetViewPortSize().Height), GL_RGB16F, GL_FLOAT, 4); + //GenerateTexture(&m_StencilTexture, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_STENCIL, GL_STENCIL_INDEX8, GL_INT); + + CommonFunctions::GenerateTexture(&m_DepthBuffer, GL_CLAMP_TO_BORDER, GL_NEAREST, + glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8); + } + + CommonFunctions::GenerateTexture(&m_ShieldBuffer, GL_CLAMP_TO_BORDER, GL_NEAREST, + glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT); + + if (m_FinalPassFrameBuffer->GetHandle() == 0) { + if (m_MSAA) { + m_FinalPassFrameBuffer->AddResource(std::shared_ptr(new RenderBuffer(&m_DepthBuffer, GL_DEPTH_STENCIL_ATTACHMENT))); + //m_FinalPassFrameBuffer->AddResource(std::shared_ptr(new Texture2D(&m_StencilTexture, GL_STENCIL_ATTACHMENT))); + m_FinalPassFrameBuffer->AddResource(std::shared_ptr(new RenderBuffer(&m_SceneTexture, GL_COLOR_ATTACHMENT0))); + m_FinalPassFrameBuffer->AddResource(std::shared_ptr(new RenderBuffer(&m_BloomTexture, GL_COLOR_ATTACHMENT1))); + } else { + m_FinalPassFrameBuffer->AddResource(std::shared_ptr(new Texture2D(&m_DepthBuffer, GL_DEPTH_STENCIL_ATTACHMENT))); + //m_FinalPassFrameBuffer->AddResource(std::shared_ptr(new Texture2D(&m_StencilTexture, GL_STENCIL_ATTACHMENT))); + m_FinalPassFrameBuffer->AddResource(std::shared_ptr(new Texture2D(&m_SceneTexture, GL_COLOR_ATTACHMENT0))); + m_FinalPassFrameBuffer->AddResource(std::shared_ptr(new Texture2D(&m_BloomTexture, GL_COLOR_ATTACHMENT1))); + } + } + m_FinalPassFrameBuffer->Generate(); GLERROR("FBO generation"); - glGenRenderbuffers(1, &m_DepthBufferLowRes); - glBindRenderbuffer(GL_RENDERBUFFER, m_DepthBufferLowRes); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, (int)(m_Renderer->GetViewportSize().Width/m_ShieldPixelRate), (int)(m_Renderer->GetViewportSize().Height/m_ShieldPixelRate)); - GLERROR("RenderBufferLowRes generation"); - - GenerateTexture(&m_SceneTextureLowRes, GL_CLAMP_TO_EDGE, GL_NEAREST, glm::vec2((int)(m_Renderer->GetViewportSize().Width/m_ShieldPixelRate), (int)(m_Renderer->GetViewportSize().Height/m_ShieldPixelRate)), GL_RGB16F, GL_RGB, GL_FLOAT); - //GenerateTexture(&m_BloomTexture, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewPortSize().Width, m_Renderer->GetViewPortSize().Height), GL_RGB16F, GL_RGB, GL_FLOAT); - GenerateTexture(&m_BloomTextureLowRes, GL_CLAMP_TO_EDGE, GL_NEAREST, glm::vec2((int)(m_Renderer->GetViewportSize().Width/m_ShieldPixelRate), (int)(m_Renderer->GetViewportSize().Height/m_ShieldPixelRate)), GL_RGB16F, GL_RGB, GL_FLOAT); - //GenerateMipMapTexture(&m_BloomTexture, GL_CLAMP_TO_EDGE, glm::vec2(m_Renderer->GetViewPortSize().Width, m_Renderer->GetViewPortSize().Height), GL_RGB16F, GL_FLOAT, 4); - //GenerateTexture(&m_StencilTexture, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_STENCIL, GL_STENCIL_INDEX8, GL_INT); - - m_FinalPassFrameBufferLowRes.AddResource(std::shared_ptr(new RenderBuffer(&m_DepthBufferLowRes, GL_DEPTH_STENCIL_ATTACHMENT))); - //m_FinalPassFrameBufferLowRes.AddResource(std::shared_ptr(new Texture2D(&m_StencilTexture, GL_STENCIL_ATTACHMENT))); - m_FinalPassFrameBufferLowRes.AddResource(std::shared_ptr(new Texture2D(&m_SceneTextureLowRes, GL_COLOR_ATTACHMENT0))); - m_FinalPassFrameBufferLowRes.AddResource(std::shared_ptr(new Texture2D(&m_BloomTextureLowRes, GL_COLOR_ATTACHMENT1))); - m_FinalPassFrameBufferLowRes.Generate(); - GLERROR("FBO2 generation"); + if (m_ShieldDepthFrameBuffer->GetHandle() == 0) { + m_ShieldDepthFrameBuffer->AddResource(std::shared_ptr(new Texture2D(&m_ShieldBuffer, GL_DEPTH_ATTACHMENT))); + } + m_ShieldDepthFrameBuffer->Generate(); } void DrawFinalPass::InitializeShaderPrograms() @@ -90,6 +153,7 @@ void DrawFinalPass::InitializeShaderPrograms() m_SpriteProgram->BindFragDataLocation(1, "bloomColor"); m_SpriteProgram->Link(); GLERROR("Creating sprite program"); + m_ForwardPlusSplatMapProgram = ResourceManager::Load("#ForwardPlusSplatMapProgram"); m_ForwardPlusSplatMapProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/ForwardPlus.vert.glsl"))); m_ForwardPlusSplatMapProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/ForwardPlusSplatMapRGB.frag.glsl"))); @@ -145,40 +209,120 @@ void DrawFinalPass::InitializeShaderPrograms() m_ForwardPlusSplatMapSkinnedProgram->BindFragDataLocation(1, "bloomColor"); m_ForwardPlusSplatMapSkinnedProgram->Link(); GLERROR("Creating Forward SplatMap Skinned program"); + + m_FillDepthStencilBufferProgram = ResourceManager::Load("#FillDepthBufferProgram"); + m_FillDepthStencilBufferProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/FillDepthBuffer.vert.glsl"))); + m_FillDepthStencilBufferProgram->Compile(); + m_FillDepthStencilBufferProgram->Link(); + GLERROR("Creating DepthFill program"); + + m_FillDepthStencilBufferSkinnedProgram = ResourceManager::Load("#FillDepthBufferProgramSkinned"); + m_FillDepthStencilBufferSkinnedProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/FillDepthBufferSkinned.vert.glsl"))); + m_FillDepthStencilBufferSkinnedProgram->Compile(); + m_FillDepthStencilBufferSkinnedProgram->Link(); + GLERROR("Creating DepthFill program"); + + + + + + m_ForwardPlusShieldCheckProgram = ResourceManager::Load("#ForwardPlusShieldCheckProgram"); + m_ForwardPlusShieldCheckProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/ForwardPlus.vert.glsl"))); + m_ForwardPlusShieldCheckProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/ForwardPlusShieldCheck.frag.glsl"))); + m_ForwardPlusShieldCheckProgram->Compile(); + m_ForwardPlusShieldCheckProgram->BindFragDataLocation(0, "sceneColor"); + m_ForwardPlusShieldCheckProgram->BindFragDataLocation(1, "bloomColor"); + m_ForwardPlusShieldCheckProgram->Link(); + GLERROR("Creating forward+ program"); + + m_ExplosionEffectShieldCheckProgram = ResourceManager::Load("#ExplosionEffectShieldCheckProgram"); + m_ExplosionEffectShieldCheckProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/ForwardPlus.vert.glsl"))); + m_ExplosionEffectShieldCheckProgram->AddShader(std::shared_ptr(new GeometryShader("Shaders/ExplosionEffect.geom.glsl"))); + m_ExplosionEffectShieldCheckProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/ForwardPlusShieldCheck.frag.glsl"))); + m_ExplosionEffectShieldCheckProgram->Compile(); + m_ExplosionEffectShieldCheckProgram->BindFragDataLocation(0, "sceneColor"); + m_ExplosionEffectShieldCheckProgram->BindFragDataLocation(1, "bloomColor"); + m_ExplosionEffectShieldCheckProgram->Link(); + GLERROR("Creating explosion program"); + + m_SpriteShieldCheckProgram = ResourceManager::Load("#SpriteShieldCheckProgram"); + m_SpriteShieldCheckProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/Sprite.vert.glsl"))); + m_SpriteShieldCheckProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/SpriteShieldCheck.frag.glsl"))); + m_SpriteShieldCheckProgram->Compile(); + m_SpriteShieldCheckProgram->BindFragDataLocation(0, "sceneColor"); + m_SpriteShieldCheckProgram->BindFragDataLocation(1, "bloomColor"); + m_SpriteShieldCheckProgram->Link(); + GLERROR("Creating sprite program"); + + m_ForwardPlusSplatMapShieldCheckProgram = ResourceManager::Load("#ForwardPlusSplatMapShieldCheckProgram"); + m_ForwardPlusSplatMapShieldCheckProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/ForwardPlus.vert.glsl"))); + m_ForwardPlusSplatMapShieldCheckProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/ForwardPlusSplatMapRGBShieldCheck.frag.glsl"))); + m_ForwardPlusSplatMapShieldCheckProgram->Compile(); + m_ForwardPlusSplatMapShieldCheckProgram->BindFragDataLocation(0, "sceneColor"); + m_ForwardPlusSplatMapShieldCheckProgram->BindFragDataLocation(1, "bloomColor"); + m_ForwardPlusSplatMapShieldCheckProgram->Link(); + GLERROR("Creating Forward SplatMap program"); + + m_ExplosionEffectSplatMapShieldCheckProgram = ResourceManager::Load("#ExplosionEffectSplatMapShieldCheckProgram"); + m_ExplosionEffectSplatMapShieldCheckProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/ForwardPlus.vert.glsl"))); + m_ExplosionEffectSplatMapShieldCheckProgram->AddShader(std::shared_ptr(new GeometryShader("Shaders/ExplosionEffect.geom.glsl"))); + m_ExplosionEffectSplatMapShieldCheckProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/ForwardPlusSplatMapRGBShieldCheck.frag.glsl"))); + m_ExplosionEffectSplatMapShieldCheckProgram->Compile(); + m_ExplosionEffectSplatMapShieldCheckProgram->BindFragDataLocation(0, "sceneColor"); + m_ExplosionEffectSplatMapShieldCheckProgram->BindFragDataLocation(1, "bloomColor"); + m_ExplosionEffectSplatMapShieldCheckProgram->Link(); + GLERROR("Creating explosion SplatMap program"); + + m_ForwardPlusSkinnedShieldCheckProgram = ResourceManager::Load("#ForwardPlusSkinnedShieldCheckProgram"); + m_ForwardPlusSkinnedShieldCheckProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/ForwardPlusSkinned.vert.glsl"))); + m_ForwardPlusSkinnedShieldCheckProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/ForwardPlusShieldCheck.frag.glsl"))); + m_ForwardPlusSkinnedShieldCheckProgram->Compile(); + m_ForwardPlusSkinnedShieldCheckProgram->BindFragDataLocation(0, "sceneColor"); + m_ForwardPlusSkinnedShieldCheckProgram->BindFragDataLocation(1, "bloomColor"); + m_ForwardPlusSkinnedShieldCheckProgram->Link(); + GLERROR("Creating forward+ Skinned program"); + + m_ExplosionEffectSkinnedShieldCheckProgram = ResourceManager::Load("#ExplosionEffectSkinnedShieldCheckProgram"); + m_ExplosionEffectSkinnedShieldCheckProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/ForwardPlusSkinned.vert.glsl"))); + m_ExplosionEffectSkinnedShieldCheckProgram->AddShader(std::shared_ptr(new GeometryShader("Shaders/ExplosionEffect.geom.glsl"))); + m_ExplosionEffectSkinnedShieldCheckProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/ForwardPlusShieldCheck.frag.glsl"))); + m_ExplosionEffectSkinnedShieldCheckProgram->Compile(); + m_ExplosionEffectSkinnedShieldCheckProgram->BindFragDataLocation(0, "sceneColor"); + m_ExplosionEffectSkinnedShieldCheckProgram->BindFragDataLocation(1, "bloomColor"); + m_ExplosionEffectSkinnedShieldCheckProgram->Link(); + GLERROR("Creating explosion Skinned program"); + + m_ExplosionEffectSplatMapSkinnedShieldCheckProgram = ResourceManager::Load("#ExplosionEffectSplatMapSkinnedShieldCheckProgram"); + m_ExplosionEffectSplatMapSkinnedShieldCheckProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/ForwardPlusSkinned.vert.glsl"))); + m_ExplosionEffectSplatMapSkinnedShieldCheckProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/ForwardPlusSplatMapRGBShieldCheck.frag.glsl"))); + m_ExplosionEffectSplatMapSkinnedShieldCheckProgram->Compile(); + m_ExplosionEffectSplatMapSkinnedShieldCheckProgram->BindFragDataLocation(0, "sceneColor"); + m_ExplosionEffectSplatMapSkinnedShieldCheckProgram->BindFragDataLocation(1, "bloomColor"); + m_ExplosionEffectSplatMapSkinnedShieldCheckProgram->Link(); + GLERROR("Creating Forward SplatMap Skinned program"); + + m_ForwardPlusSplatMapSkinnedShieldCheckProgram = ResourceManager::Load("#ForwardPlusSplatMapSkinnedShieldCheckProgram"); + m_ForwardPlusSplatMapSkinnedShieldCheckProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/ForwardPlusSkinned.vert.glsl"))); + m_ForwardPlusSplatMapSkinnedShieldCheckProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/ForwardPlusSplatMapRGBShieldCheck.frag.glsl"))); + m_ForwardPlusSplatMapSkinnedShieldCheckProgram->Compile(); + m_ForwardPlusSplatMapSkinnedShieldCheckProgram->BindFragDataLocation(0, "sceneColor"); + m_ForwardPlusSplatMapSkinnedShieldCheckProgram->BindFragDataLocation(1, "bloomColor"); + m_ForwardPlusSplatMapSkinnedShieldCheckProgram->Link(); + GLERROR("Creating Forward SplatMap Skinned program"); - m_ShieldToStencilProgram = ResourceManager::Load("#ShieldToStencilProgram"); - m_ShieldToStencilProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/ShieldStencil.vert.glsl"))); - m_ShieldToStencilProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/ShieldStencil.frag.glsl"))); - m_ShieldToStencilProgram->Compile(); - m_ShieldToStencilProgram->Link(); - GLERROR("Creating Shield program"); - - m_ShieldToStencilSkinnedProgram = ResourceManager::Load("#ShieldToStencilProgramSkinned"); - m_ShieldToStencilSkinnedProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/ShieldStencilSkinned.vert.glsl"))); - m_ShieldToStencilSkinnedProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/ShieldStencil.frag.glsl"))); - m_ShieldToStencilSkinnedProgram->Compile(); - m_ShieldToStencilSkinnedProgram->Link(); - GLERROR("Creating Shield Skinned program"); - - m_FillDepthBufferProgram = ResourceManager::Load("#FillDepthBufferProgram"); - m_FillDepthBufferProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/FillDepthBuffer.vert.glsl"))); - m_FillDepthBufferProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/FillDepthBuffer.frag.glsl"))); - m_FillDepthBufferProgram->Compile(); - m_FillDepthBufferProgram->Link(); - GLERROR("Creating DepthFill program"); - - m_FillDepthBufferSkinnedProgram = ResourceManager::Load("#FillDepthBufferProgramSkinned"); - m_FillDepthBufferSkinnedProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/FillDepthBufferSkinned.vert.glsl"))); - m_FillDepthBufferSkinnedProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/FillDepthBuffer.frag.glsl"))); - m_FillDepthBufferSkinnedProgram->Compile(); - m_FillDepthBufferSkinnedProgram->Link(); - GLERROR("Creating DepthFill program"); } -void DrawFinalPass::Draw(RenderScene& scene, GLuint SSAOTexture) +void DrawFinalPass::Draw(RenderScene& scene, BlurHUD* blurHUDPass) { GLERROR("Pre"); - DrawFinalPassState* state = new DrawFinalPassState(m_FinalPassFrameBuffer.GetHandle()); + DrawFinalPassState* stateDethp = new DrawFinalPassState(m_ShieldDepthFrameBuffer->GetHandle()); + //Draw shields to stencil + DrawToDepthStencilBuffer(scene.Jobs.ShieldObjects, scene); + GLERROR("StencilPass"); + delete stateDethp; + + + DrawFinalPassState* state = new DrawFinalPassState(m_FinalPassFrameBuffer->GetHandle()); if (scene.ClearDepth) { //glClear(GL_DEPTH_BUFFER_BIT); state->Disable(GL_DEPTH_TEST); @@ -188,389 +332,878 @@ void DrawFinalPass::Draw(RenderScene& scene, GLuint SSAOTexture) glClearStencil(0x00); glClear(GL_STENCIL_BUFFER_BIT); - //Fill depth buffer - - state->StencilMask(0x00); - DrawModelRenderQueues(scene.Jobs.OpaqueObjects, scene, SSAOTexture); - GLERROR("OpaqueObjects"); - state->BlendFunc(GL_ONE, GL_ONE); - DrawModelRenderQueues(scene.Jobs.TransparentObjects, scene, SSAOTexture); - GLERROR("TransparentObjects"); - state->BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - DrawSprites(scene.Jobs.SpriteJob, scene); - GLERROR("SpriteJobs"); - - //DrawStencilState* stencilState = new DrawStencilState(m_FinalPassFrameBuffer.GetHandle()); - //Draw shields to stencil pass - state->StencilFunc(GL_ALWAYS, 1, 0xFF); - state->StencilMask(0xFF); - DrawShieldToStencilBuffer(scene.Jobs.ShieldObjects, scene); - GLERROR("StencilPass"); //Draw Opaque shielded objects + state->Disable(GL_STENCIL_TEST); state->StencilFunc(GL_NOTEQUAL, 1, 0xFF); state->StencilMask(0x00); - DrawModelRenderQueues(scene.Jobs.OpaqueShieldedObjects, scene, SSAOTexture); //might need changing + DrawModelRenderQueuesWithShieldCheck(scene.Jobs.OpaqueShieldedObjects, scene); //might need changing GLERROR("Shielded Opaque object"); - //Draw Transparen Shielded objects - DrawModelRenderQueues(scene.Jobs.TransparentShieldedObjects, scene, SSAOTexture); //might need changing - GLERROR("Shielded Transparent objects"); + //Draw Opaque objects + //state->StencilMask(0x00); + DrawModelRenderQueues(scene.Jobs.OpaqueObjects, scene); + GLERROR("OpaqueObjects"); - GLERROR("END"); + //state->Disable(GL_STENCIL_TEST); + //Draw Transparen objects + state->BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + DrawModelRenderQueuesWithShieldCheck(scene.Jobs.TransparentObjects, scene); //might need changing + GLERROR("Transparent objects"); + + //Generate blur texture. delete state; + if (scene.ShouldBlur) { + //This needs to be drawn only when the full scene is being renderd, and then let be, otherwise sprite and other shit will show on it. + GLuint sceneTexture = SceneTexture(); + m_FullBlurredTexture = blurHUDPass->Draw(sceneTexture, scene); + } + DrawFinalPassState* stateSprite; + if(scene.ShouldBlur) { + //Combine nonblur and blur texture + GLuint sceneTexture = SceneTexture(); + stateSprite = new DrawFinalPassState(m_FinalPassFrameBuffer->GetHandle()); + stateSprite->Disable(GL_DEPTH_TEST); + stateSprite->Disable(GL_STENCIL_TEST); + m_CombinedTexture = blurHUDPass->CombineTextures(sceneTexture, m_FullBlurredTexture); - DrawFinalPassState* stateLowRes = new DrawFinalPassState(m_FinalPassFrameBufferLowRes.GetHandle()); - //Draw the lowres texture that will be shown behind the shield. - stateLowRes->Enable(GL_SCISSOR_TEST); - stateLowRes->Enable(GL_DEPTH_TEST); - //TODO: Viewports and scissor should be in state - glViewport(0, 0, m_Renderer->GetViewportSize().Width/m_ShieldPixelRate, m_Renderer->GetViewportSize().Height/m_ShieldPixelRate); - glScissor(0, 0, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); + } else { + stateSprite = new DrawFinalPassState(m_FinalPassFrameBuffer->GetHandle()); + } + stateSprite->Enable(GL_DEPTH_TEST); + //stateSprite->AlphaFunc(GL_GEQUAL, 0.05f); + //stateSprite->Enable(GL_ALPHA_TEST); + DrawSprites(scene.Jobs.SpriteJob, scene); + GLERROR("SpriteJobs"); - glClearStencil(0x00); - glClear(GL_STENCIL_BUFFER_BIT); - - //TODO: This should not be here... - stateLowRes->StencilFunc(GL_ALWAYS, 1, 0xFF); - stateLowRes->StencilMask(0x00); - DrawToDepthBuffer(scene.Jobs.OpaqueObjects, scene); - DrawToDepthBuffer(scene.Jobs.TransparentObjects, scene); - - //Draw shields to stencil pass - stateLowRes->StencilFunc(GL_ALWAYS, 1, 0xFF); - stateLowRes->StencilMask(0xFF); - stateLowRes->Enable(GL_DEPTH_TEST); - DrawShieldToStencilBuffer(scene.Jobs.ShieldObjects, scene); - GLERROR("StencilPass"); - - //glClear(GL_DEPTH_BUFFER_BIT); - - stateLowRes->Enable(GL_DEPTH_TEST); - stateLowRes->StencilFunc(GL_LEQUAL, 1, 0xFF); - stateLowRes->StencilMask(0x00); - DrawModelRenderQueues(scene.Jobs.OpaqueObjects, scene, SSAOTexture); - GLERROR("OpaqueObjects"); - DrawModelRenderQueues(scene.Jobs.TransparentObjects, scene, SSAOTexture); - GLERROR("TransparentObjects"); - glViewport(0, 0, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); - glScissor(0, 0, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); - delete stateLowRes; + delete stateSprite; + GLERROR("END"); + } void DrawFinalPass::ClearBuffer() { GLERROR("PRE"); - m_FinalPassFrameBufferLowRes.Bind(); - GLERROR("Bind LowRes"); - - glViewport(0, 0, m_Renderer->GetViewportSize().Width/m_ShieldPixelRate, m_Renderer->GetViewportSize().Height/m_ShieldPixelRate); - glScissor(0, 0, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); - GLERROR("ViewPort,Scissor LowRes"); - - glClearColor(0.f, 0.f, 0.f, 0.f); - GLERROR("1"); - - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - GLERROR("2"); - - glDisable(GL_SCISSOR_TEST); - GLERROR("3"); - - m_FinalPassFrameBufferLowRes.Unbind(); - - GLERROR("prebind HighRes"); - m_FinalPassFrameBuffer.Bind(); + m_ShieldDepthFrameBuffer->Bind(); + glClear(GL_DEPTH_BUFFER_BIT); + m_ShieldDepthFrameBuffer->Unbind(); + m_FinalPassFrameBuffer->Bind(); GLERROR("Bind HighRes"); glViewport(0, 0, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); glScissor(0, 0, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); GLERROR("ViewPort,Scissor LowRes"); glClearColor(0.f, 0.f, 0.f, 0.f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - m_FinalPassFrameBuffer.Unbind(); + m_FinalPassFrameBuffer->Unbind(); GLERROR("END"); } - void DrawFinalPass::OnWindowResize() { - //InitializeFrameBuffers(); - glBindRenderbuffer(GL_RENDERBUFFER, m_DepthBuffer); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); + if (m_FinalPassFrameBuffer->MultiSampling() != (bool)m_MSAA) { + delete m_FinalPassFrameBuffer; + delete m_ShieldDepthFrameBuffer; + m_FinalPassFrameBuffer = new FrameBuffer(); + m_ShieldDepthFrameBuffer = new FrameBuffer(); + } - GenerateTexture(&m_SceneTexture, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_RGB16F, GL_RGB, GL_FLOAT); - GenerateTexture(&m_BloomTexture, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_RGB16F, GL_RGB, GL_FLOAT); - m_FinalPassFrameBuffer.Generate(); + if (m_MSAA) { + if (m_AntiAliasedFrameBuffer != nullptr) { + delete m_AntiAliasedFrameBuffer; + m_AntiAliasedFrameBuffer = nullptr; + } + } - - glBindRenderbuffer(GL_RENDERBUFFER, m_DepthBufferLowRes); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, (int)(m_Renderer->GetViewportSize().Width/m_ShieldPixelRate), (int)(m_Renderer->GetViewportSize().Height/m_ShieldPixelRate)); - - GenerateTexture(&m_SceneTextureLowRes, GL_CLAMP_TO_EDGE, GL_NEAREST, glm::vec2((int)(m_Renderer->GetViewportSize().Width/m_ShieldPixelRate), (int)(m_Renderer->GetViewportSize().Height/m_ShieldPixelRate)), GL_RGB16F, GL_RGB, GL_FLOAT); - GenerateTexture(&m_BloomTextureLowRes, GL_CLAMP_TO_EDGE, GL_NEAREST, glm::vec2((int)(m_Renderer->GetViewportSize().Width/m_ShieldPixelRate), (int)(m_Renderer->GetViewportSize().Height/m_ShieldPixelRate)), GL_RGB16F, GL_RGB, GL_FLOAT); - m_FinalPassFrameBufferLowRes.Generate(); + InitializeFrameBuffers(); GLERROR("Error changing texture resolutions"); } -void DrawFinalPass::GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type) const -{ - glGenTextures(1, texture); - glBindTexture(GL_TEXTURE_2D, *texture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapping); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapping); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering); - glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, dimensions.x, dimensions.y, 0, format, type, nullptr);//TODO: Renderer: Fix the precision and Resolution - GLERROR("Texture initialization failed"); +void DrawFinalPass::setMSAA(unsigned int numberOfSamples) { + if (m_MSAA == numberOfSamples) { + return; + } + + if (!(bool)numberOfSamples) { + if (m_AntiAliasedFrameBuffer != nullptr) { + delete m_AntiAliasedFrameBuffer; + m_AntiAliasedFrameBuffer = nullptr; + } + delete m_FinalPassFrameBuffer; + m_FinalPassFrameBuffer = new FrameBuffer(); + } + + if ((bool)numberOfSamples && !(bool)m_MSAA) { + delete m_FinalPassFrameBuffer; + m_FinalPassFrameBuffer = new FrameBuffer(); + } + + m_MSAA = numberOfSamples; + + InitializeFrameBuffers(); + + } -void DrawFinalPass::GenerateMipMapTexture(GLuint* texture, GLenum wrapping, glm::vec2 dimensions, GLint format, GLenum type, GLint numMipMaps) const -{ - glGenTextures(1, texture); - glBindTexture(GL_TEXTURE_2D, *texture); - glTexStorage2D(GL_TEXTURE_2D, numMipMaps, GL_RGBA8, dimensions.x, dimensions.y); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, dimensions.x, dimensions.y, format, type, texture); - glGenerateMipmap(GL_TEXTURE_2D); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapping); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapping); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - GLERROR("MipMap Texture initialization failed"); -} - -void DrawFinalPass::DrawModelRenderQueues(std::list>& jobs, RenderScene& scene, GLuint SSAOTexture) +void DrawFinalPass::DrawModelRenderQueues(std::list>& jobs, RenderScene& scene) { GLuint forwardHandle = m_ForwardPlusProgram->GetHandle(); - GLERROR("forwardHandle"); GLuint explosionHandle = m_ExplosionEffectProgram->GetHandle(); - GLERROR("explosionHandle"); GLuint explosionSplatMapHandle = m_ExplosionEffectSplatMapProgram->GetHandle(); - GLERROR("explosionSplatMapHandle"); - GLuint forwardSplatHandle = m_ForwardPlusSplatMapProgram->GetHandle(); - GLERROR("forwardSplatHandle"); + GLuint forwardSplatMapHandle = m_ForwardPlusSplatMapProgram->GetHandle(); GLuint forwardSkinnedHandle = m_ForwardPlusSkinnedProgram->GetHandle(); - GLERROR("forwardSkinnedHandle"); GLuint explosionSkinnedHandle = m_ExplosionEffectSkinnedProgram->GetHandle(); - GLERROR("explosionSkinnedHandle"); GLuint explosionSplatMapSkinnedHandle = m_ExplosionEffectSplatMapSkinnedProgram->GetHandle(); - GLERROR("explosionSplatMapSkinnedHandle"); GLuint forwardSplatMapSkinnedHandle = m_ForwardPlusSplatMapSkinnedProgram->GetHandle(); - GLERROR("forwardSplatSkinnedHandle"); + GLuint lastShader = 0; + unsigned int lastModel = 0; glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_LightCullingPass->LightSSBO()); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_LightCullingPass->LightGridSSBO()); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_LightCullingPass->LightIndexSSBO()); glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, SSAOTexture); + glBindTexture(GL_TEXTURE_2D, m_SSAOPass->SSAOTexture()); + + glActiveTexture(GL_TEXTURE30); + if (m_ShadowPass->DepthMap() != NULL) { + glBindTexture(GL_TEXTURE_2D_ARRAY, m_ShadowPass->DepthMap()); + } else { + glBindTexture(GL_TEXTURE_2D_ARRAY, m_WhiteTexture->m_Texture); + } for (auto &job : jobs) { auto explosionEffectJob = std::dynamic_pointer_cast(job); if (explosionEffectJob) { switch (explosionEffectJob->Type) { case RawModel::MaterialType::Basic: - case RawModel::MaterialType::SingleTextures: - { - if (explosionEffectJob->Model->IsSkinned()) { + case RawModel::MaterialType::SingleTextures: + { + if (explosionEffectJob->Model->IsSkinned()) { + if (lastShader != m_ExplosionEffectSkinnedProgram->GetHandle()) { + m_ExplosionEffectSkinnedProgram->Bind(); + lastShader = m_ExplosionEffectSkinnedProgram->GetHandle(); + GLERROR("Bind ExplosionEffectSkinned program"); + glUniform1i(glGetUniformLocation(explosionSkinnedHandle, "SSAOQuality"), m_SSAOPass->TextureQuality()); + glUniformMatrix4fv(glGetUniformLocation(explosionSkinnedHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); + glUniformMatrix4fv(glGetUniformLocation(explosionSkinnedHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); + glUniform2f(glGetUniformLocation(explosionSkinnedHandle, "ScreenDimensions"), m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); + glUniform4fv(glGetUniformLocation(explosionSkinnedHandle, "AmbientColor"), 1, glm::value_ptr(scene.AmbientColor)); + GLERROR("Bind ExplosionEffectSkinned Uniforms"); + } + //bind uniforms + BindExplosionUniforms(explosionSkinnedHandle, explosionEffectJob, scene); + //bind textures + BindExplosionTextures(explosionSkinnedHandle, explosionEffectJob); + glActiveTexture(GL_TEXTURE5); + glBindTexture(GL_TEXTURE_CUBE_MAP, m_CubeMapPass->m_CubeMapTexture); + glUniform3fv(glGetUniformLocation(explosionSkinnedHandle, "CameraPosition"), 1, glm::value_ptr(scene.Camera->Position())); + + std::vector frameBones; + if (explosionEffectJob->BlendTree != nullptr) { + frameBones = explosionEffectJob->BlendTree->GetFinalPose(); + } else { + frameBones = explosionEffectJob->Skeleton->GetTPose(); + } + glUniformMatrix4fv(glGetUniformLocation(explosionSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); - m_ExplosionEffectSkinnedProgram->Bind(); - GLERROR("Bind ExplosionEffectSkinned program"); - //bind uniforms - BindExplosionUniforms(explosionSkinnedHandle, explosionEffectJob, scene); - //bind textures - BindExplosionTextures(explosionSkinnedHandle, explosionEffectJob); - glActiveTexture(GL_TEXTURE5); - glBindTexture(GL_TEXTURE_CUBE_MAP, m_CubeMapPass->m_CubeMapTexture); - glUniform3fv(glGetUniformLocation(forwardHandle, "CameraPosition"), 1, glm::value_ptr(scene.Camera->Position())); - std::vector frameBones; - if (explosionEffectJob->AnimationOffset.animation != nullptr) { - frameBones = explosionEffectJob->Skeleton->GetFrameBones(explosionEffectJob->Animations, explosionEffectJob->AnimationOffset); - } else { - frameBones = explosionEffectJob->Skeleton->GetFrameBones(explosionEffectJob->Animations); } - glUniformMatrix4fv(glGetUniformLocation(explosionSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); - } else { - m_ExplosionEffectProgram->Bind(); - GLERROR("Bind ExplosionEffect program"); - //bind uniforms - BindExplosionUniforms(explosionHandle, explosionEffectJob, scene); - //bind textures - BindExplosionTextures(explosionHandle, explosionEffectJob); - glActiveTexture(GL_TEXTURE5); - glBindTexture(GL_TEXTURE_CUBE_MAP, m_CubeMapPass->m_CubeMapTexture); - glUniform3fv(glGetUniformLocation(forwardHandle, "CameraPosition"), 1, glm::value_ptr(scene.Camera->Position())); + else { + if (lastShader != m_ExplosionEffectProgram->GetHandle()) { + m_ExplosionEffectProgram->Bind(); + lastShader = m_ExplosionEffectProgram->GetHandle(); + GLERROR("Bind ExplosionEffect program"); + glUniform1i(glGetUniformLocation(explosionHandle, "SSAOQuality"), m_SSAOPass->TextureQuality()); + glUniformMatrix4fv(glGetUniformLocation(explosionHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); + glUniformMatrix4fv(glGetUniformLocation(explosionHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); + glUniform2f(glGetUniformLocation(explosionHandle, "ScreenDimensions"), m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); + glUniform4fv(glGetUniformLocation(explosionHandle, "AmbientColor"), 1, glm::value_ptr(scene.AmbientColor)); + GLERROR("Bind ExplosionEffect Uniforms"); + } + //bind uniforms + BindExplosionUniforms(explosionHandle, explosionEffectJob, scene); + //bind textures + BindExplosionTextures(explosionHandle, explosionEffectJob); + glActiveTexture(GL_TEXTURE5); + glBindTexture(GL_TEXTURE_CUBE_MAP, m_CubeMapPass->m_CubeMapTexture); + glUniform3fv(glGetUniformLocation(explosionHandle, "CameraPosition"), 1, glm::value_ptr(scene.Camera->Position())); + } + break; + } + case RawModel::MaterialType::SplatMapping: + { + if (explosionEffectJob->Model->IsSkinned()) { + if (lastShader != m_ExplosionEffectSplatMapSkinnedProgram->GetHandle()) { + m_ExplosionEffectSplatMapSkinnedProgram->Bind(); + lastShader = m_ExplosionEffectSplatMapSkinnedProgram->GetHandle(); + GLERROR("Bind ExplosionEffectSplatMapSkinned program"); + glUniform1i(glGetUniformLocation(explosionSplatMapSkinnedHandle, "SSAOQuality"), m_SSAOPass->TextureQuality()); + glUniformMatrix4fv(glGetUniformLocation(explosionSplatMapSkinnedHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); + glUniformMatrix4fv(glGetUniformLocation(explosionSplatMapSkinnedHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); + glUniform2f(glGetUniformLocation(explosionSplatMapSkinnedHandle, "ScreenDimensions"), m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); + glUniform4fv(glGetUniformLocation(explosionSplatMapSkinnedHandle, "AmbientColor"), 1, glm::value_ptr(scene.AmbientColor)); + GLERROR("Bind ExplosionEffectSplatMapSkinned Uniforms"); + } + //bind uniforms + BindExplosionUniforms(explosionSplatMapSkinnedHandle, explosionEffectJob, scene); + //bind textures + BindExplosionTextures(explosionSplatMapSkinnedHandle, explosionEffectJob); + GLERROR("asdasd"); + std::vector frameBones; + if (explosionEffectJob->BlendTree != nullptr) { + frameBones = explosionEffectJob->BlendTree->GetFinalPose(); + } else { + frameBones = explosionEffectJob->Skeleton->GetTPose(); + } + glUniformMatrix4fv(glGetUniformLocation(explosionSplatMapSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); - } - break; - } - case RawModel::MaterialType::SplatMapping: - { - if (explosionEffectJob->Model->IsSkinned()) { - m_ExplosionEffectSplatMapSkinnedProgram->Bind(); - GLERROR("Bind ExplosionEffectSplatMapSkinned program"); - //bind uniforms - BindExplosionUniforms(explosionSplatMapSkinnedHandle, explosionEffectJob, scene); - //bind textures - BindExplosionTextures(explosionSplatMapSkinnedHandle, explosionEffectJob); - GLERROR("asdasd"); - std::vector frameBones; - if (explosionEffectJob->AnimationOffset.animation != nullptr) { - frameBones = explosionEffectJob->Skeleton->GetFrameBones(explosionEffectJob->Animations, explosionEffectJob->AnimationOffset); - } else { - frameBones = explosionEffectJob->Skeleton->GetFrameBones(explosionEffectJob->Animations); } - glUniformMatrix4fv(glGetUniformLocation(explosionSplatMapSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); - - } else { - m_ExplosionEffectSplatMapProgram->Bind(); - GLERROR("Bind ExplosionEffectSplatMap program"); - //bind uniforms - //bind uniforms - BindExplosionUniforms(explosionSplatMapHandle, explosionEffectJob, scene); - //bind textures - BindExplosionTextures(explosionSplatMapHandle, explosionEffectJob); - GLERROR("asdasd"); - } - break; - } + else { + if (lastShader != m_ExplosionEffectSplatMapProgram->GetHandle()) { + m_ExplosionEffectSplatMapProgram->Bind(); + lastShader = m_ExplosionEffectSplatMapProgram->GetHandle(); + GLERROR("Bind ExplosionEffectSplatMap program"); + glUniform1i(glGetUniformLocation(explosionSplatMapHandle, "SSAOQuality"), m_SSAOPass->TextureQuality()); + glUniformMatrix4fv(glGetUniformLocation(explosionSplatMapHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); + glUniformMatrix4fv(glGetUniformLocation(explosionSplatMapHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); + glUniform2f(glGetUniformLocation(explosionSplatMapHandle, "ScreenDimensions"), m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); + glUniform4fv(glGetUniformLocation(explosionSplatMapHandle, "AmbientColor"), 1, glm::value_ptr(scene.AmbientColor)); + GLERROR("Bind ExplosionEffectSplatMap Uniforms"); + } + //bind uniforms + BindExplosionUniforms(explosionSplatMapHandle, explosionEffectJob, scene); + //bind textures + BindExplosionTextures(explosionSplatMapHandle, explosionEffectJob); + GLERROR("asdasd"); + } + break; + } } glDisable(GL_CULL_FACE); //draw - glBindVertexArray(explosionEffectJob->Model->VAO); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, explosionEffectJob->Model->ElementBuffer); + if (lastModel != explosionEffectJob->ModelID) { + glBindVertexArray(explosionEffectJob->Model->VAO); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, explosionEffectJob->Model->ElementBuffer); + lastModel = explosionEffectJob->ModelID; + } glDrawElements(GL_TRIANGLES, explosionEffectJob->EndIndex - explosionEffectJob->StartIndex + 1, GL_UNSIGNED_INT, (void*)(explosionEffectJob->StartIndex*sizeof(unsigned int))); glEnable(GL_CULL_FACE); GLERROR("explosion effect end"); - } else { - auto modelJob = std::dynamic_pointer_cast(job); - if (modelJob) { - //bind forward program - //TODO: JOHAN/TOBIAS: Bind shader based on ModelJob->ShaderID; - switch (modelJob->Type) { - case RawModel::MaterialType::Basic: - case RawModel::MaterialType::SingleTextures: - { - if (modelJob->Model->IsSkinned()) { - m_ForwardPlusSkinnedProgram->Bind(); - GLERROR("Bind ForwardPlusSkinnedProgram"); - //bind uniforms - BindModelUniforms(forwardSkinnedHandle, modelJob, scene); - //bind textures - BindModelTextures(forwardSkinnedHandle, modelJob); - glActiveTexture(GL_TEXTURE5); - glBindTexture(GL_TEXTURE_CUBE_MAP, m_CubeMapPass->m_CubeMapTexture); - glUniform3fv(glGetUniformLocation(forwardHandle, "CameraPosition"), 1, glm::value_ptr(scene.Camera->Position())); - - std::vector frameBones; - if (modelJob->AnimationOffset.animation != nullptr) { - frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations, modelJob->AnimationOffset); - } else { - frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations); - } - glUniformMatrix4fv(glGetUniformLocation(forwardSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); - - } else { - m_ForwardPlusProgram->Bind(); - GLERROR("Bind ForwardPlusProgram"); - //bind uniforms - BindModelUniforms(forwardHandle, modelJob, scene); - //bind textures - BindModelTextures(forwardHandle, modelJob); - glActiveTexture(GL_TEXTURE5); - glBindTexture(GL_TEXTURE_CUBE_MAP, m_CubeMapPass->m_CubeMapTexture); - glUniform3fv(glGetUniformLocation(forwardHandle, "CameraPosition"), 1, glm::value_ptr(scene.Camera->Position())); + } else { + auto modelJob = std::dynamic_pointer_cast(job); + if (modelJob) { + //bind forward program + //TODO: JOHAN/TOBIAS: Bind shader based on ModelJob->ShaderID; + switch (modelJob->Type) { + case RawModel::MaterialType::Basic: + case RawModel::MaterialType::SingleTextures: + { + if (modelJob->Model->IsSkinned()) { + if (lastShader != m_ForwardPlusSkinnedProgram->GetHandle()) { + m_ForwardPlusSkinnedProgram->Bind(); + lastShader = m_ForwardPlusSkinnedProgram->GetHandle(); + GLERROR("Bind ForwardPlusSkinnedProgram program"); + glUniform1i(glGetUniformLocation(forwardSkinnedHandle, "SSAOQuality"), m_SSAOPass->TextureQuality()); + glUniformMatrix4fv(glGetUniformLocation(forwardSkinnedHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); + glUniformMatrix4fv(glGetUniformLocation(forwardSkinnedHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); + glUniform2f(glGetUniformLocation(forwardSkinnedHandle, "ScreenDimensions"), m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); + glUniform4fv(glGetUniformLocation(forwardSkinnedHandle, "AmbientColor"), 1, glm::value_ptr(scene.AmbientColor)); + GLERROR("Bind ForwardPlusSkinnedProgram Uniforms"); + } + //bind uniforms + BindModelUniforms(forwardSkinnedHandle, modelJob, scene); + //bind textures + BindModelTextures(forwardSkinnedHandle, modelJob); + glActiveTexture(GL_TEXTURE5); + glBindTexture(GL_TEXTURE_CUBE_MAP, m_CubeMapPass->m_CubeMapTexture); + glUniform3fv(glGetUniformLocation(forwardSkinnedHandle, "CameraPosition"), 1, glm::value_ptr(scene.Camera->Position())); + + std::vector frameBones; + if (modelJob->BlendTree != nullptr) { + frameBones = modelJob->BlendTree->GetFinalPose(); + } else if (modelJob->Skeleton != nullptr) { + frameBones = modelJob->Skeleton->GetTPose(); } - break; + glUniformMatrix4fv(glGetUniformLocation(forwardSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); } - case RawModel::MaterialType::SplatMapping: - { - if (modelJob->Model->IsSkinned()) { - m_ForwardPlusSplatMapSkinnedProgram->Bind(); - GLERROR("Bind SplatMap program"); - //bind uniforms - BindModelUniforms(forwardSplatMapSkinnedHandle, modelJob, scene); - //bind textures - BindModelTextures(forwardSplatMapSkinnedHandle, modelJob); - GLERROR("asdasd"); - std::vector frameBones; - if (modelJob->AnimationOffset.animation != nullptr) { - frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations, modelJob->AnimationOffset); - } else { - frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations); - } - glUniformMatrix4fv(glGetUniformLocation(forwardSplatMapSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); - + else { + if (lastShader != m_ForwardPlusProgram->GetHandle()) { + m_ForwardPlusProgram->Bind(); + lastShader = m_ForwardPlusProgram->GetHandle(); + GLERROR("Bind ForwardPlusProgram program"); + glUniform1i(glGetUniformLocation(forwardHandle, "SSAOQuality"), m_SSAOPass->TextureQuality()); + glUniformMatrix4fv(glGetUniformLocation(forwardHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); + glUniformMatrix4fv(glGetUniformLocation(forwardHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); + glUniform2f(glGetUniformLocation(forwardHandle, "ScreenDimensions"), m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); + glUniform4fv(glGetUniformLocation(forwardHandle, "AmbientColor"), 1, glm::value_ptr(scene.AmbientColor)); + GLERROR("Bind ForwardPlusProgram Uniforms"); + } + //bind uniforms + BindModelUniforms(forwardHandle, modelJob, scene); + //bind textures + BindModelTextures(forwardHandle, modelJob); + glActiveTexture(GL_TEXTURE5); + glBindTexture(GL_TEXTURE_CUBE_MAP, m_CubeMapPass->m_CubeMapTexture); + glUniform3fv(glGetUniformLocation(forwardHandle, "CameraPosition"), 1, glm::value_ptr(scene.Camera->Position())); + } + break; + } + case RawModel::MaterialType::SplatMapping: + { + if (modelJob->Model->IsSkinned()) { + if (lastShader != m_ForwardPlusSplatMapSkinnedProgram->GetHandle()) { + m_ForwardPlusSplatMapSkinnedProgram->Bind(); + lastShader = m_ForwardPlusSplatMapSkinnedProgram->GetHandle(); + GLERROR("Bind SkinnedSplatMapProgram program"); + glUniform1i(glGetUniformLocation(forwardSplatMapSkinnedHandle, "SSAOQuality"), m_SSAOPass->TextureQuality()); + glUniformMatrix4fv(glGetUniformLocation(forwardSplatMapSkinnedHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); + glUniformMatrix4fv(glGetUniformLocation(forwardSplatMapSkinnedHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); + glUniform2f(glGetUniformLocation(forwardSplatMapSkinnedHandle, "ScreenDimensions"), m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); + glUniform4fv(glGetUniformLocation(forwardSplatMapSkinnedHandle, "AmbientColor"), 1, glm::value_ptr(scene.AmbientColor)); + GLERROR("Bind SkinnedSplatMapProgram Uniforms"); + } + //bind uniforms + BindModelUniforms(forwardSplatMapSkinnedHandle, modelJob, scene); + //bind textures + BindModelTextures(forwardSplatMapSkinnedHandle, modelJob); + GLERROR("asdasd"); + std::vector frameBones; + if (modelJob->BlendTree != nullptr) { + frameBones = modelJob->BlendTree->GetFinalPose(); } else { - m_ForwardPlusSplatMapProgram->Bind(); - GLERROR("Bind SplatMap program"); - //bind uniforms - BindModelUniforms(forwardSplatHandle, modelJob, scene); - //bind textures - BindModelTextures(forwardSplatHandle, modelJob); - GLERROR("asdasd"); + frameBones = modelJob->Skeleton->GetTPose(); } - break; - } - } - //draw - glBindVertexArray(modelJob->Model->VAO); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, modelJob->Model->ElementBuffer); - glDrawElements(GL_TRIANGLES, modelJob->EndIndex - modelJob->StartIndex + 1, GL_UNSIGNED_INT, (void*)(modelJob->StartIndex*sizeof(unsigned int))); - if (GLERROR("models end")) { - continue; - } + glUniformMatrix4fv(glGetUniformLocation(forwardSplatMapSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); + + } + else { + if (lastShader != m_ForwardPlusSplatMapProgram->GetHandle()) { + m_ForwardPlusSplatMapProgram->Bind(); + lastShader = m_ForwardPlusSplatMapProgram->GetHandle(); + GLERROR("Bind SplatMap program"); + glUniform1i(glGetUniformLocation(forwardSplatMapHandle, "SSAOQuality"), m_SSAOPass->TextureQuality()); + glUniformMatrix4fv(glGetUniformLocation(forwardSplatMapHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); + glUniformMatrix4fv(glGetUniformLocation(forwardSplatMapHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); + glUniform2f(glGetUniformLocation(forwardSplatMapHandle, "ScreenDimensions"), m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); + glUniform4fv(glGetUniformLocation(forwardSplatMapHandle, "AmbientColor"), 1, glm::value_ptr(scene.AmbientColor)); + GLERROR("Bind SplatMap Uniforms"); + } + //bind uniforms + BindModelUniforms(forwardSplatMapHandle, modelJob, scene); + //bind textures + BindModelTextures(forwardSplatMapHandle, modelJob); + GLERROR("asdasd"); + } + break; + } } - } - } -} - - -void DrawFinalPass::DrawShieldToStencilBuffer(std::list>& jobs, RenderScene& scene) -{ - - - for (auto &job : jobs) { - auto modelJob = std::dynamic_pointer_cast(job); - if (modelJob) { - - if(modelJob->Model->IsSkinned()) { - m_ShieldToStencilSkinnedProgram->Bind(); - GLuint shaderHandle = m_ShieldToStencilSkinnedProgram->GetHandle(); - - glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->Matrix)); - 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())); - std::vector frameBones; - if (modelJob->AnimationOffset.animation != nullptr) { - frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations, modelJob->AnimationOffset); - } else { - frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations); + //draw + if (lastModel != modelJob->ModelID) { + glBindVertexArray(modelJob->Model->VAO); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, modelJob->Model->ElementBuffer); + lastModel = modelJob->ModelID; + } + glDrawElements(GL_TRIANGLES, modelJob->EndIndex - modelJob->StartIndex + 1, GL_UNSIGNED_INT, (void*)(modelJob->StartIndex*sizeof(unsigned int))); + if (GLERROR("models end")) { + continue; } - glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); - } else { - m_ShieldToStencilProgram->Bind(); - GLuint shaderHandle = m_ShieldToStencilProgram->GetHandle(); - - glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->Matrix)); - 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())); - - } - - glBindVertexArray(modelJob->Model->VAO); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, modelJob->Model->ElementBuffer); - glDrawElements(GL_TRIANGLES, modelJob->EndIndex - modelJob->StartIndex + 1, GL_UNSIGNED_INT, (void*)(modelJob->StartIndex*sizeof(unsigned int))); - if (GLERROR("models end")) { - continue; } } } } +void DrawFinalPass::DrawModelRenderQueuesWithShieldCheck(std::list>& jobs, RenderScene& scene) +{ + GLuint forwardHandle = m_ForwardPlusProgram->GetHandle(); + GLuint explosionHandle = m_ExplosionEffectProgram->GetHandle(); + GLuint explosionSplatMapHandle = m_ExplosionEffectSplatMapProgram->GetHandle(); + GLuint forwardSplatMapHandle = m_ForwardPlusSplatMapProgram->GetHandle(); + GLuint forwardSkinnedHandle = m_ForwardPlusSkinnedProgram->GetHandle(); + GLuint explosionSkinnedHandle = m_ExplosionEffectSkinnedProgram->GetHandle(); + GLuint explosionSplatMapSkinnedHandle = m_ExplosionEffectSplatMapSkinnedProgram->GetHandle(); + GLuint forwardSplatMapSkinnedHandle = m_ForwardPlusSplatMapSkinnedProgram->GetHandle(); + + GLuint forwardShieldCheckHandle = m_ForwardPlusShieldCheckProgram->GetHandle(); + GLuint explosionShieldCheckHandle = m_ExplosionEffectShieldCheckProgram->GetHandle(); + GLuint explosionSplatMapShieldCheckHandle = m_ExplosionEffectSplatMapShieldCheckProgram->GetHandle(); + GLuint forwardSplatShieldCheckHandle = m_ForwardPlusSplatMapShieldCheckProgram->GetHandle(); + GLuint forwardSkinnedShieldCheckHandle = m_ForwardPlusSkinnedShieldCheckProgram->GetHandle(); + GLuint explosionSkinnedShieldCheckHandle = m_ExplosionEffectSkinnedShieldCheckProgram->GetHandle(); + GLuint explosionSplatMapSkinnedShieldCheckHandle = m_ExplosionEffectSplatMapSkinnedShieldCheckProgram->GetHandle(); + GLuint forwardSplatMapSkinnedShieldCheckHandle = m_ForwardPlusSplatMapSkinnedShieldCheckProgram->GetHandle(); + GLuint lastShader = 0; + unsigned int lastModel = 0; + + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_LightCullingPass->LightSSBO()); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_LightCullingPass->LightGridSSBO()); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_LightCullingPass->LightIndexSSBO()); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, m_SSAOPass->SSAOTexture()); + + glActiveTexture(GL_TEXTURE31); + glBindTexture(GL_TEXTURE_2D, m_ShieldBuffer); + + for (auto &job : jobs) { + auto explosionEffectJob = std::dynamic_pointer_cast(job); + if (explosionEffectJob) { + if (explosionEffectJob->IsShielded) { + switch (explosionEffectJob->Type) { + case RawModel::MaterialType::Basic: + case RawModel::MaterialType::SingleTextures: + { + if (explosionEffectJob->Model->IsSkinned()) { + if (lastShader != m_ExplosionEffectSkinnedShieldCheckProgram->GetHandle()) { + m_ExplosionEffectSkinnedShieldCheckProgram->Bind(); + lastShader = m_ExplosionEffectSkinnedShieldCheckProgram->GetHandle(); + GLERROR("Bind ExplosionEffectSkinned program"); + glUniform1i(glGetUniformLocation(explosionSkinnedShieldCheckHandle, "SSAOQuality"), m_SSAOPass->TextureQuality()); + glUniformMatrix4fv(glGetUniformLocation(explosionSkinnedShieldCheckHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); + glUniformMatrix4fv(glGetUniformLocation(explosionSkinnedShieldCheckHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); + glUniform2f(glGetUniformLocation(explosionSkinnedShieldCheckHandle, "ScreenDimensions"), m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); + glUniform4fv(glGetUniformLocation(explosionSkinnedShieldCheckHandle, "AmbientColor"), 1, glm::value_ptr(scene.AmbientColor)); + GLERROR("Bind ExplosionEffectSkinned Uniforms"); + } + //bind uniforms + BindExplosionUniforms(explosionSkinnedShieldCheckHandle, explosionEffectJob, scene); + //bind textures + BindExplosionTextures(explosionSkinnedShieldCheckHandle, explosionEffectJob); + glActiveTexture(GL_TEXTURE5); + glBindTexture(GL_TEXTURE_CUBE_MAP, m_CubeMapPass->m_CubeMapTexture); + glUniform3fv(glGetUniformLocation(explosionSkinnedShieldCheckHandle, "CameraPosition"), 1, glm::value_ptr(scene.Camera->Position())); + + std::vector frameBones; + if (explosionEffectJob->BlendTree != nullptr) { + frameBones = explosionEffectJob->BlendTree->GetFinalPose(); + } else { + frameBones = explosionEffectJob->Skeleton->GetTPose(); + } + glUniformMatrix4fv(glGetUniformLocation(explosionSkinnedShieldCheckHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); + + } + else { + if (lastShader != m_ExplosionEffectShieldCheckProgram->GetHandle()) { + m_ExplosionEffectShieldCheckProgram->Bind(); + lastShader = m_ExplosionEffectShieldCheckProgram->GetHandle(); + GLERROR("Bind ExplosionEffect program"); + glUniform1i(glGetUniformLocation(explosionShieldCheckHandle, "SSAOQuality"), m_SSAOPass->TextureQuality()); + glUniformMatrix4fv(glGetUniformLocation(explosionShieldCheckHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); + glUniformMatrix4fv(glGetUniformLocation(explosionShieldCheckHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); + glUniform2f(glGetUniformLocation(explosionShieldCheckHandle, "ScreenDimensions"), m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); + glUniform4fv(glGetUniformLocation(explosionShieldCheckHandle, "AmbientColor"), 1, glm::value_ptr(scene.AmbientColor)); + GLERROR("Bind ExplosionEffect Uniforms"); + } + //bind uniforms + BindExplosionUniforms(explosionShieldCheckHandle, explosionEffectJob, scene); + //bind textures + BindExplosionTextures(explosionShieldCheckHandle, explosionEffectJob); + glActiveTexture(GL_TEXTURE5); + glBindTexture(GL_TEXTURE_CUBE_MAP, m_CubeMapPass->m_CubeMapTexture); + glUniform3fv(glGetUniformLocation(explosionShieldCheckHandle, "CameraPosition"), 1, glm::value_ptr(scene.Camera->Position())); + + } + break; + } + case RawModel::MaterialType::SplatMapping: + { + if (explosionEffectJob->Model->IsSkinned()) { + if (lastShader != m_ExplosionEffectSplatMapSkinnedShieldCheckProgram->GetHandle()) { + m_ExplosionEffectSplatMapSkinnedShieldCheckProgram->Bind(); + lastShader = m_ExplosionEffectSplatMapSkinnedShieldCheckProgram->GetHandle(); + GLERROR("Bind ExplosionEffectSplatMapSkinned program"); + glUniform1i(glGetUniformLocation(explosionSplatMapSkinnedShieldCheckHandle, "SSAOQuality"), m_SSAOPass->TextureQuality()); + glUniformMatrix4fv(glGetUniformLocation(explosionSplatMapSkinnedShieldCheckHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); + glUniformMatrix4fv(glGetUniformLocation(explosionSplatMapSkinnedShieldCheckHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); + glUniform2f(glGetUniformLocation(explosionSplatMapSkinnedShieldCheckHandle, "ScreenDimensions"), m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); + glUniform4fv(glGetUniformLocation(explosionSplatMapSkinnedShieldCheckHandle, "AmbientColor"), 1, glm::value_ptr(scene.AmbientColor)); + GLERROR("Bind ExplosionEffectSplatMapSkinned Uniforms"); + } + //bind uniforms + BindExplosionUniforms(explosionSplatMapSkinnedShieldCheckHandle, explosionEffectJob, scene); + //bind textures + BindExplosionTextures(explosionSplatMapSkinnedShieldCheckHandle, explosionEffectJob); + GLERROR("asdasd"); + + std::vector frameBones; + if (explosionEffectJob->BlendTree != nullptr) { + frameBones = explosionEffectJob->BlendTree->GetFinalPose(); + } else { + frameBones = explosionEffectJob->Skeleton->GetTPose(); + } + glUniformMatrix4fv(glGetUniformLocation(explosionSplatMapSkinnedShieldCheckHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); + + } + else { + if (lastShader != m_ExplosionEffectSplatMapShieldCheckProgram->GetHandle()) { + m_ExplosionEffectSplatMapShieldCheckProgram->Bind(); + lastShader = m_ExplosionEffectSplatMapShieldCheckProgram->GetHandle(); + GLERROR("Bind ExplosionEffectSplatMap program"); + glUniform1i(glGetUniformLocation(explosionSplatMapShieldCheckHandle, "SSAOQuality"), m_SSAOPass->TextureQuality()); + glUniformMatrix4fv(glGetUniformLocation(explosionSplatMapShieldCheckHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); + glUniformMatrix4fv(glGetUniformLocation(explosionSplatMapShieldCheckHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); + glUniform2f(glGetUniformLocation(explosionSplatMapShieldCheckHandle, "ScreenDimensions"), m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); + glUniform4fv(glGetUniformLocation(explosionSplatMapShieldCheckHandle, "AmbientColor"), 1, glm::value_ptr(scene.AmbientColor)); + GLERROR("Bind ExplosionEffectSplatMap Uniforms"); + } + //bind uniforms + BindExplosionUniforms(explosionSplatMapShieldCheckHandle, explosionEffectJob, scene); + //bind textures + BindExplosionTextures(explosionSplatMapShieldCheckHandle, explosionEffectJob); + GLERROR("asdasd"); + } + break; + } + } + } else { + switch (explosionEffectJob->Type) { + case RawModel::MaterialType::Basic: + case RawModel::MaterialType::SingleTextures: + { + if (explosionEffectJob->Model->IsSkinned()) { + if (lastShader != m_ExplosionEffectSkinnedProgram->GetHandle()) { + m_ExplosionEffectSkinnedProgram->Bind(); + lastShader = m_ExplosionEffectSkinnedProgram->GetHandle(); + GLERROR("Bind ExplosionEffectSkinned program"); + glUniform1i(glGetUniformLocation(explosionSkinnedHandle, "SSAOQuality"), m_SSAOPass->TextureQuality()); + glUniformMatrix4fv(glGetUniformLocation(explosionSkinnedHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); + glUniformMatrix4fv(glGetUniformLocation(explosionSkinnedHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); + glUniform2f(glGetUniformLocation(explosionSkinnedHandle, "ScreenDimensions"), m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); + glUniform4fv(glGetUniformLocation(explosionSkinnedHandle, "AmbientColor"), 1, glm::value_ptr(scene.AmbientColor)); + GLERROR("Bind ExplosionEffectSkinned Uniforms"); + } + //bind uniforms + BindExplosionUniforms(explosionSkinnedHandle, explosionEffectJob, scene); + //bind textures + BindExplosionTextures(explosionSkinnedHandle, explosionEffectJob); + glActiveTexture(GL_TEXTURE5); + glBindTexture(GL_TEXTURE_CUBE_MAP, m_CubeMapPass->m_CubeMapTexture); + glUniform3fv(glGetUniformLocation(explosionSkinnedHandle, "CameraPosition"), 1, glm::value_ptr(scene.Camera->Position())); + + std::vector frameBones; + if (explosionEffectJob->BlendTree != nullptr) { + frameBones = explosionEffectJob->BlendTree->GetFinalPose(); + } else { + frameBones = explosionEffectJob->Skeleton->GetTPose(); + } + glUniformMatrix4fv(glGetUniformLocation(explosionSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); + } + else { + if (lastShader != m_ExplosionEffectProgram->GetHandle()) { + m_ExplosionEffectProgram->Bind(); + lastShader = m_ExplosionEffectProgram->GetHandle(); + GLERROR("Bind ExplosionEffect program"); + glUniform1i(glGetUniformLocation(explosionHandle, "SSAOQuality"), m_SSAOPass->TextureQuality()); + glUniformMatrix4fv(glGetUniformLocation(explosionHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); + glUniformMatrix4fv(glGetUniformLocation(explosionHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); + glUniform2f(glGetUniformLocation(explosionHandle, "ScreenDimensions"), m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); + glUniform4fv(glGetUniformLocation(explosionHandle, "AmbientColor"), 1, glm::value_ptr(scene.AmbientColor)); + GLERROR("Bind ExplosionEffect Uniforms"); + } + //bind uniforms + BindExplosionUniforms(explosionHandle, explosionEffectJob, scene); + //bind textures + BindExplosionTextures(explosionHandle, explosionEffectJob); + glActiveTexture(GL_TEXTURE5); + glBindTexture(GL_TEXTURE_CUBE_MAP, m_CubeMapPass->m_CubeMapTexture); + glUniform3fv(glGetUniformLocation(explosionHandle, "CameraPosition"), 1, glm::value_ptr(scene.Camera->Position())); + } + break; + } + case RawModel::MaterialType::SplatMapping: + { + if (explosionEffectJob->Model->IsSkinned()) { + if (lastShader != m_ExplosionEffectSplatMapSkinnedProgram->GetHandle()) { + m_ExplosionEffectSplatMapSkinnedProgram->Bind(); + lastShader = m_ExplosionEffectSplatMapSkinnedProgram->GetHandle(); + GLERROR("Bind ExplosionEffectSkinnedSplatMap program"); + glUniform1i(glGetUniformLocation(explosionSplatMapSkinnedHandle, "SSAOQuality"), m_SSAOPass->TextureQuality()); + glUniformMatrix4fv(glGetUniformLocation(explosionSplatMapSkinnedHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); + glUniformMatrix4fv(glGetUniformLocation(explosionSplatMapSkinnedHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); + glUniform2f(glGetUniformLocation(explosionSplatMapSkinnedHandle, "ScreenDimensions"), m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); + glUniform4fv(glGetUniformLocation(explosionSplatMapSkinnedHandle, "AmbientColor"), 1, glm::value_ptr(scene.AmbientColor)); + GLERROR("Bind ExplosionEffectSkinnedSplatMap Uniforms"); + } + //bind uniforms + BindExplosionUniforms(explosionSplatMapSkinnedHandle, explosionEffectJob, scene); + //bind textures + BindExplosionTextures(explosionSplatMapSkinnedHandle, explosionEffectJob); + GLERROR("asdasd"); + std::vector frameBones; + if (explosionEffectJob->BlendTree != nullptr) { + frameBones = explosionEffectJob->BlendTree->GetFinalPose(); + } else { + frameBones = explosionEffectJob->Skeleton->GetTPose(); + } + glUniformMatrix4fv(glGetUniformLocation(explosionSplatMapSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); + + } + else { + if (lastShader != m_ExplosionEffectSplatMapProgram->GetHandle()) { + m_ExplosionEffectSplatMapProgram->Bind(); + lastShader = m_ExplosionEffectSplatMapProgram->GetHandle(); + GLERROR("Bind ExplosionEffectSplatMap program"); + glUniform1i(glGetUniformLocation(explosionSplatMapHandle, "SSAOQuality"), m_SSAOPass->TextureQuality()); + glUniformMatrix4fv(glGetUniformLocation(explosionSplatMapHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); + glUniformMatrix4fv(glGetUniformLocation(explosionSplatMapHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); + glUniform2f(glGetUniformLocation(explosionSplatMapHandle, "ScreenDimensions"), m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); + glUniform4fv(glGetUniformLocation(explosionSplatMapHandle, "AmbientColor"), 1, glm::value_ptr(scene.AmbientColor)); + GLERROR("Bind ExplosionEffectSplatMap Uniforms"); + } + //bind uniforms + BindExplosionUniforms(explosionSplatMapHandle, explosionEffectJob, scene); + //bind textures + BindExplosionTextures(explosionSplatMapHandle, explosionEffectJob); + GLERROR("asdasd"); + } + break; + } + } + } + glDisable(GL_CULL_FACE); + + //draw + if (lastModel != explosionEffectJob->ModelID) { + glBindVertexArray(explosionEffectJob->Model->VAO); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, explosionEffectJob->Model->ElementBuffer); + lastModel = explosionEffectJob->ModelID; + } + glDrawElements(GL_TRIANGLES, explosionEffectJob->EndIndex - explosionEffectJob->StartIndex + 1, GL_UNSIGNED_INT, (void*)(explosionEffectJob->StartIndex*sizeof(unsigned int))); + glEnable(GL_CULL_FACE); + GLERROR("explosion effect end"); + } else { + auto modelJob = std::dynamic_pointer_cast(job); + if (modelJob) { + //bind forward program + //TODO: JOHAN/TOBIAS: Bind shader based on ModelJob->ShaderID; + if (modelJob->IsShielded) { + switch (modelJob->Type) { + case RawModel::MaterialType::Basic: + case RawModel::MaterialType::SingleTextures: + { + if (modelJob->Model->IsSkinned()) { + if (lastShader != m_ForwardPlusSkinnedShieldCheckProgram->GetHandle()) { + m_ForwardPlusSkinnedShieldCheckProgram->Bind(); + lastShader = m_ForwardPlusSkinnedShieldCheckProgram->GetHandle(); + GLERROR("Bind ForwardPlusSkinnedProgram program"); + glUniform1i(glGetUniformLocation(forwardSkinnedShieldCheckHandle, "SSAOQuality"), m_SSAOPass->TextureQuality()); + glUniformMatrix4fv(glGetUniformLocation(forwardSkinnedShieldCheckHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); + glUniformMatrix4fv(glGetUniformLocation(forwardSkinnedShieldCheckHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); + glUniform2f(glGetUniformLocation(forwardSkinnedShieldCheckHandle, "ScreenDimensions"), m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); + glUniform4fv(glGetUniformLocation(forwardSkinnedShieldCheckHandle, "AmbientColor"), 1, glm::value_ptr(scene.AmbientColor)); + GLERROR("Bind ForwardPlusSkinnedProgram Uniforms"); + } + //bind uniforms + BindModelUniforms(forwardSkinnedShieldCheckHandle, modelJob, scene); + //bind textures + BindModelTextures(forwardSkinnedShieldCheckHandle, modelJob); + glActiveTexture(GL_TEXTURE5); + glBindTexture(GL_TEXTURE_CUBE_MAP, m_CubeMapPass->m_CubeMapTexture); + glUniform3fv(glGetUniformLocation(forwardSkinnedShieldCheckHandle, "CameraPosition"), 1, glm::value_ptr(scene.Camera->Position())); + + std::vector frameBones; + if (modelJob->BlendTree != nullptr) { + frameBones = modelJob->BlendTree->GetFinalPose(); + } else { + frameBones = modelJob->Skeleton->GetTPose(); + } + glUniformMatrix4fv(glGetUniformLocation(forwardSkinnedShieldCheckHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); + + } + else { + if (lastShader != m_ForwardPlusShieldCheckProgram->GetHandle()) { + m_ForwardPlusShieldCheckProgram->Bind(); + lastShader = m_ForwardPlusShieldCheckProgram->GetHandle(); + GLERROR("Bind ForwardPlusProgram program"); + glUniform1i(glGetUniformLocation(forwardShieldCheckHandle, "SSAOQuality"), m_SSAOPass->TextureQuality()); + glUniformMatrix4fv(glGetUniformLocation(forwardShieldCheckHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); + glUniformMatrix4fv(glGetUniformLocation(forwardShieldCheckHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); + glUniform2f(glGetUniformLocation(forwardShieldCheckHandle, "ScreenDimensions"), m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); + glUniform4fv(glGetUniformLocation(forwardShieldCheckHandle, "AmbientColor"), 1, glm::value_ptr(scene.AmbientColor)); + GLERROR("Bind ForwardPlusProgram Uniforms"); + } + //bind uniforms + BindModelUniforms(forwardShieldCheckHandle, modelJob, scene); + //bind textures + BindModelTextures(forwardShieldCheckHandle, modelJob); + glActiveTexture(GL_TEXTURE5); + glBindTexture(GL_TEXTURE_CUBE_MAP, m_CubeMapPass->m_CubeMapTexture); + glUniform3fv(glGetUniformLocation(forwardShieldCheckHandle, "CameraPosition"), 1, glm::value_ptr(scene.Camera->Position())); + } + break; + } + case RawModel::MaterialType::SplatMapping: + { + if (modelJob->Model->IsSkinned()) { + if (lastShader != m_ForwardPlusSplatMapSkinnedShieldCheckProgram->GetHandle()) { + m_ForwardPlusSplatMapSkinnedShieldCheckProgram->Bind(); + lastShader = m_ForwardPlusSplatMapSkinnedShieldCheckProgram->GetHandle(); + GLERROR("Bind ForwardPlusProgramSplatMapSkinned program"); + glUniform1i(glGetUniformLocation(forwardSplatMapSkinnedShieldCheckHandle, "SSAOQuality"), m_SSAOPass->TextureQuality()); + glUniformMatrix4fv(glGetUniformLocation(forwardSplatMapSkinnedShieldCheckHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); + glUniformMatrix4fv(glGetUniformLocation(forwardSplatMapSkinnedShieldCheckHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); + glUniform2f(glGetUniformLocation(forwardSplatMapSkinnedShieldCheckHandle, "ScreenDimensions"), m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); + glUniform4fv(glGetUniformLocation(forwardSplatMapSkinnedShieldCheckHandle, "AmbientColor"), 1, glm::value_ptr(scene.AmbientColor)); + GLERROR("Bind ForwardPlusProgramSplatMapSkinned Uniforms"); + } + //bind uniforms + BindModelUniforms(forwardSplatMapSkinnedShieldCheckHandle, modelJob, scene); + //bind textures + BindModelTextures(forwardSplatMapSkinnedShieldCheckHandle, modelJob); + GLERROR("asdasd"); + + std::vector frameBones; + if (modelJob->BlendTree != nullptr) { + frameBones = modelJob->BlendTree->GetFinalPose(); + } else { + frameBones = modelJob->Skeleton->GetTPose(); + } + glUniformMatrix4fv(glGetUniformLocation(forwardSplatMapSkinnedShieldCheckHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); + } + else { + if (lastShader != m_ForwardPlusSplatMapShieldCheckProgram->GetHandle()) { + m_ForwardPlusSplatMapShieldCheckProgram->Bind(); + lastShader = m_ForwardPlusSplatMapShieldCheckProgram->GetHandle(); + GLERROR("Bind SplatMap program"); + glUniform1i(glGetUniformLocation(forwardSplatShieldCheckHandle, "SSAOQuality"), m_SSAOPass->TextureQuality()); + glUniformMatrix4fv(glGetUniformLocation(forwardSplatShieldCheckHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); + glUniformMatrix4fv(glGetUniformLocation(forwardSplatShieldCheckHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); + glUniform2f(glGetUniformLocation(forwardSplatShieldCheckHandle, "ScreenDimensions"), m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); + glUniform4fv(glGetUniformLocation(forwardSplatShieldCheckHandle, "AmbientColor"), 1, glm::value_ptr(scene.AmbientColor)); + GLERROR("Bind SplatMap Uniforms"); + } + //bind uniforms + BindModelUniforms(forwardSplatShieldCheckHandle, modelJob, scene); + //bind textures + BindModelTextures(forwardSplatShieldCheckHandle, modelJob); + GLERROR("asdasd"); + } + break; + } + } + } else { + switch (modelJob->Type) { + case RawModel::MaterialType::Basic: + case RawModel::MaterialType::SingleTextures: + { + if (modelJob->Model->IsSkinned()) { + if (lastShader != m_ForwardPlusSkinnedProgram->GetHandle()) { + m_ForwardPlusSkinnedProgram->Bind(); + lastShader = m_ForwardPlusSkinnedProgram->GetHandle(); + GLERROR("Bind ForwardPlusSkinnedProgram program"); + glUniform1i(glGetUniformLocation(forwardSkinnedHandle, "SSAOQuality"), m_SSAOPass->TextureQuality()); + glUniformMatrix4fv(glGetUniformLocation(forwardSkinnedHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); + glUniformMatrix4fv(glGetUniformLocation(forwardSkinnedHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); + glUniform2f(glGetUniformLocation(forwardSkinnedHandle, "ScreenDimensions"), m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); + glUniform4fv(glGetUniformLocation(forwardSkinnedHandle, "AmbientColor"), 1, glm::value_ptr(scene.AmbientColor)); + GLERROR("Bind ForwardPlusSkinnedProgram Uniforms"); + } + //bind uniforms + BindModelUniforms(forwardSkinnedHandle, modelJob, scene); + //bind textures + BindModelTextures(forwardSkinnedHandle, modelJob); + glActiveTexture(GL_TEXTURE5); + glBindTexture(GL_TEXTURE_CUBE_MAP, m_CubeMapPass->m_CubeMapTexture); + glUniform3fv(glGetUniformLocation(forwardSkinnedHandle, "CameraPosition"), 1, glm::value_ptr(scene.Camera->Position())); + + std::vector frameBones; + if (modelJob->BlendTree != nullptr) { + frameBones = modelJob->BlendTree->GetFinalPose(); + } else { + frameBones = modelJob->Skeleton->GetTPose(); + } + glUniformMatrix4fv(glGetUniformLocation(forwardSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); + + } + else { + if (lastShader != m_ForwardPlusProgram->GetHandle()) { + m_ForwardPlusProgram->Bind(); + lastShader = m_ForwardPlusProgram->GetHandle(); + GLERROR("Bind ForwardPlusProgram program"); + glUniform1i(glGetUniformLocation(forwardHandle, "SSAOQuality"), m_SSAOPass->TextureQuality()); + glUniformMatrix4fv(glGetUniformLocation(forwardHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); + glUniformMatrix4fv(glGetUniformLocation(forwardHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); + glUniform2f(glGetUniformLocation(forwardHandle, "ScreenDimensions"), m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); + glUniform4fv(glGetUniformLocation(forwardHandle, "AmbientColor"), 1, glm::value_ptr(scene.AmbientColor)); + GLERROR("Bind ForwardPlusProgram Uniforms"); + } + //bind uniforms + BindModelUniforms(forwardHandle, modelJob, scene); + //bind textures + BindModelTextures(forwardHandle, modelJob); + glActiveTexture(GL_TEXTURE5); + glBindTexture(GL_TEXTURE_CUBE_MAP, m_CubeMapPass->m_CubeMapTexture); + glUniform3fv(glGetUniformLocation(forwardHandle, "CameraPosition"), 1, glm::value_ptr(scene.Camera->Position())); + } + break; + } + case RawModel::MaterialType::SplatMapping: + { + if (modelJob->Model->IsSkinned()) { + if (lastShader != m_ForwardPlusSplatMapSkinnedProgram->GetHandle()) { + m_ForwardPlusSplatMapSkinnedProgram->Bind(); + lastShader = m_ForwardPlusSplatMapSkinnedProgram->GetHandle(); + GLERROR("Bind SplatMap program"); + glUniform1i(glGetUniformLocation(forwardSplatMapSkinnedHandle, "SSAOQuality"), m_SSAOPass->TextureQuality()); + glUniformMatrix4fv(glGetUniformLocation(forwardSplatMapSkinnedHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); + glUniformMatrix4fv(glGetUniformLocation(forwardSplatMapSkinnedHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); + glUniform2f(glGetUniformLocation(forwardSplatMapSkinnedHandle, "ScreenDimensions"), m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); + glUniform4fv(glGetUniformLocation(forwardSplatMapSkinnedHandle, "AmbientColor"), 1, glm::value_ptr(scene.AmbientColor)); + GLERROR("Bind SplatMap Uniforms"); + } + //bind uniforms + BindModelUniforms(forwardSplatMapSkinnedHandle, modelJob, scene); + //bind textures + BindModelTextures(forwardSplatMapSkinnedHandle, modelJob); + GLERROR("asdasd"); + + std::vector frameBones; + if (modelJob->BlendTree != nullptr) { + frameBones = modelJob->BlendTree->GetFinalPose(); + } else { + frameBones = modelJob->Skeleton->GetTPose(); + } + glUniformMatrix4fv(glGetUniformLocation(forwardSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); + } + else { + if (lastShader != m_ForwardPlusSplatMapProgram->GetHandle()) { + m_ForwardPlusSplatMapProgram->Bind(); + lastShader = m_ForwardPlusSplatMapProgram->GetHandle(); + GLERROR("Bind SplatMap program"); + glUniform1i(glGetUniformLocation(forwardSplatMapHandle, "SSAOQuality"), m_SSAOPass->TextureQuality()); + glUniformMatrix4fv(glGetUniformLocation(forwardSplatMapHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); + glUniformMatrix4fv(glGetUniformLocation(forwardSplatMapHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); + glUniform2f(glGetUniformLocation(forwardSplatMapHandle, "ScreenDimensions"), m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); + glUniform4fv(glGetUniformLocation(forwardSplatMapHandle, "AmbientColor"), 1, glm::value_ptr(scene.AmbientColor)); + GLERROR("Bind SplatMap Uniforms"); + } + //bind uniforms + BindModelUniforms(forwardSplatMapHandle, modelJob, scene); + //bind textures + BindModelTextures(forwardSplatMapHandle, modelJob); + GLERROR("asdasd"); + } + break; + } + } + } + //draw + if (lastModel != modelJob->ModelID) { + glBindVertexArray(modelJob->Model->VAO); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, modelJob->Model->ElementBuffer); + lastModel = modelJob->ModelID; + } + glDrawElements(GL_TRIANGLES, modelJob->EndIndex - modelJob->StartIndex + 1, GL_UNSIGNED_INT, (void*)(modelJob->StartIndex*sizeof(unsigned int))); + if (GLERROR("models end")) { + continue; + } + } + } + } +} + void DrawFinalPass::DrawShieldedModelRenderQueue(std::list>& jobs, RenderScene& scene) { GLuint forwardHandle = m_ForwardPlusProgram->GetHandle(); @@ -603,10 +1236,10 @@ void DrawFinalPass::DrawShieldedModelRenderQueue(std::list frameBones; - if (explosionEffectJob->AnimationOffset.animation != nullptr) { - frameBones = explosionEffectJob->Skeleton->GetFrameBones(explosionEffectJob->Animations, explosionEffectJob->AnimationOffset); + if (explosionEffectJob->BlendTree != nullptr) { + frameBones = explosionEffectJob->BlendTree->GetFinalPose(); } else { - frameBones = explosionEffectJob->Skeleton->GetFrameBones(explosionEffectJob->Animations); + frameBones = explosionEffectJob->Skeleton->GetTPose(); } glUniformMatrix4fv(glGetUniformLocation(explosionHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); @@ -642,11 +1275,12 @@ void DrawFinalPass::DrawShieldedModelRenderQueue(std::list frameBones; - if (modelJob->AnimationOffset.animation != nullptr) { - frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations, modelJob->AnimationOffset); + if (modelJob->BlendTree != nullptr) { + frameBones = modelJob->BlendTree->GetFinalPose(); } else { - frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations); + frameBones = modelJob->Skeleton->GetTPose(); } + glUniformMatrix4fv(glGetUniformLocation(forwardHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); @@ -663,34 +1297,41 @@ void DrawFinalPass::DrawShieldedModelRenderQueue(std::list>& jobs, RenderScene& scene) +void DrawFinalPass::DrawToDepthStencilBuffer(std::list>& jobs, RenderScene& scene) { - - + GLuint shaderSkinnedHandle = m_FillDepthStencilBufferSkinnedProgram->GetHandle(); + GLuint shaderHandle = m_FillDepthStencilBufferProgram->GetHandle(); + GLuint lastShader = 0; for (auto &job : jobs) { auto modelJob = std::dynamic_pointer_cast(job); if(modelJob->Model->IsSkinned()) { - m_FillDepthBufferSkinnedProgram->Bind(); - GLuint shaderHandle = m_FillDepthBufferSkinnedProgram->GetHandle(); - 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())); - glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->Matrix)); + if (lastShader != m_FillDepthStencilBufferSkinnedProgram->GetHandle()) { + m_FillDepthStencilBufferSkinnedProgram->Bind(); + lastShader = m_FillDepthStencilBufferSkinnedProgram->GetHandle(); + GLERROR("Bind Uniforms 1"); + } + + glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "PVM"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix() * scene.Camera->ViewMatrix() * modelJob->Matrix)); + GLERROR("Bind PVM uniform"); std::vector frameBones; - if (modelJob->AnimationOffset.animation != nullptr) { - frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations, modelJob->AnimationOffset); + if (modelJob->BlendTree != nullptr) { + frameBones = modelJob->BlendTree->GetFinalPose(); } else { - frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations); + frameBones = modelJob->Skeleton->GetTPose(); } - glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); + glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); } else { - m_FillDepthBufferProgram->Bind(); - GLuint shaderHandle = m_FillDepthBufferProgram->GetHandle(); - 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())); - glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->Matrix)); + if (lastShader != m_FillDepthStencilBufferProgram->GetHandle()) { + m_FillDepthStencilBufferProgram->Bind(); + lastShader = m_FillDepthStencilBufferProgram->GetHandle(); + GLERROR("Bind Uniforms 2"); + } + + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "PVM"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix() * scene.Camera->ViewMatrix() * modelJob->Matrix)); + GLERROR("Bind PVM uniform"); } @@ -712,25 +1353,43 @@ void DrawFinalPass::DrawSprites(std::list>&jobs, Rend GLuint shaderHandle = m_SpriteProgram->GetHandle(); + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); + glUniform3fv(glGetUniformLocation(shaderHandle, "CameraPos"), 1, glm::value_ptr(scene.Camera->Position())); + RenderState* jobState = new RenderState(); + + for(auto& job : jobs) { auto spriteJob = std::dynamic_pointer_cast(job); - RenderState jobState; if (spriteJob) { if(spriteJob->Depth == 0) { - jobState.Disable(GL_DEPTH_TEST); + jobState->Disable(GL_DEPTH_TEST); } - glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(spriteJob->Matrix)); - 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())); - glUniform3fv(glGetUniformLocation(shaderHandle, "CameraPos"), 1, glm::value_ptr(scene.Camera->Position())); + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "PVM"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix() * scene.Camera->ViewMatrix() * spriteJob->Matrix)); glUniform4fv(glGetUniformLocation(shaderHandle, "Color"), 1, glm::value_ptr(spriteJob->Color)); glUniform4fv(glGetUniformLocation(shaderHandle, "FillColor"), 1, glm::value_ptr(spriteJob->FillColor)); glUniform1f(glGetUniformLocation(shaderHandle, "FillPercentage"), spriteJob->FillPercentage); + glUniform1f(glGetUniformLocation(shaderHandle, "ScaleX"), spriteJob->ScaleX); + glUniform1f(glGetUniformLocation(shaderHandle, "ScaleY"), spriteJob->ScaleY); glActiveTexture(GL_TEXTURE1); if (spriteJob->DiffuseTexture != nullptr) { glBindTexture(GL_TEXTURE_2D, spriteJob->DiffuseTexture->m_Texture); + if (spriteJob->Linear) { + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } else { + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + } + if (spriteJob->ClampToBorder) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); + } + else { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + } } else { glBindTexture(GL_TEXTURE_2D, m_ErrorTexture->m_Texture); } @@ -748,25 +1407,29 @@ void DrawFinalPass::DrawSprites(std::list>&jobs, Rend glDrawElements(GL_TRIANGLES, spriteJob->EndIndex - spriteJob->StartIndex + 1, GL_UNSIGNED_INT, (void*)(spriteJob->StartIndex*sizeof(unsigned int))); } } + delete jobState; // m_SpriteProgram->Unbind(); } void DrawFinalPass::BindExplosionUniforms(GLuint shaderHandle, std::shared_ptr& job, RenderScene& scene) { - GLERROR("Bind 1 uniform"); glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(job->Matrix)); GLERROR("Bind 2 uniform"); - glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); - GLERROR("Bind 3 uniform"); - glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); - GLERROR("Bind 4 uniform"); - - glUniform2f(glGetUniformLocation(shaderHandle, "ScreenDimensions"), m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); - GLERROR("Bind 5 uniform"); + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "PVM"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix() * scene.Camera->ViewMatrix() * job->Matrix)); + GLERROR("Bind PVM uniform"); + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "VM"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix() * job->Matrix)); + GLERROR("Bind VM uniform"); + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "TIM"), 1, GL_FALSE, glm::value_ptr(glm::transpose(glm::inverse(job->Matrix)))); + GLERROR("Bind TIM uniform"); glUniform3fv(glGetUniformLocation(shaderHandle, "ExplosionOrigin"), 1, glm::value_ptr(job->ExplosionOrigin)); 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"); @@ -784,6 +1447,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"); @@ -793,28 +1460,25 @@ void DrawFinalPass::BindExplosionUniforms(GLuint shaderHandle, std::shared_ptrFillPercentage); GLERROR("Bind 19 uniform"); - glUniform4fv(glGetUniformLocation(shaderHandle, "AmbientColor"), 1, glm::value_ptr(scene.AmbientColor)); - GLERROR("Bind 20 uniform"); glUniform1f(glGetUniformLocation(shaderHandle, "GlowIntensity"), job->GlowIntensity); + + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "LightP"), MAX_SPLITS, GL_FALSE, glm::value_ptr(*m_ShadowPass->LightP().data())); + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "LightV"), MAX_SPLITS, GL_FALSE, glm::value_ptr(*m_ShadowPass->LightV().data())); + glUniform1fv(glGetUniformLocation(shaderHandle, "FarDistance"), MAX_SPLITS, m_ShadowPass->FarDistance().data()); GLERROR("END"); } void DrawFinalPass::BindModelUniforms(GLuint shaderHandle, std::shared_ptr& job, RenderScene& scene) { - GLERROR("Bind 1 uniform"); GLint Location_M = glGetUniformLocation(shaderHandle, "M"); glUniformMatrix4fv(Location_M, 1, GL_FALSE, glm::value_ptr(job->Matrix)); GLERROR("Bind 2 uniform"); - GLint Location_V = glGetUniformLocation(shaderHandle, "V"); - glUniformMatrix4fv(Location_V, 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); - GLERROR("Bind 3 uniform"); - GLint Location_P = glGetUniformLocation(shaderHandle, "P"); - glUniformMatrix4fv(Location_P, 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); - GLERROR("Bind 4 uniform"); - - GLint Location_ScreenDimensions = glGetUniformLocation(shaderHandle, "ScreenDimensions"); - glUniform2f(Location_ScreenDimensions, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); - GLERROR("Bind 5 uniform"); + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "PVM"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix() * scene.Camera->ViewMatrix() * job->Matrix)); + GLERROR("Bind PVM uniform"); + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "VM"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix() * job->Matrix)); + GLERROR("Bind VM uniform"); + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "TIM"), 1, GL_FALSE, glm::value_ptr(glm::transpose(glm::inverse(job->Matrix)))); + GLERROR("Bind TIM uniform"); GLint Location_FillPercentage = glGetUniformLocation(shaderHandle, "FillPercentage"); glUniform1f(Location_FillPercentage, job->FillPercentage); @@ -827,14 +1491,12 @@ void DrawFinalPass::BindModelUniforms(GLuint shaderHandle, std::shared_ptrColor)); - GLERROR("Bind 9 uniform"); - GLint Location_AmbientColor = glGetUniformLocation(shaderHandle, "AmbientColor"); - glUniform4fv(Location_AmbientColor, 1, glm::value_ptr(scene.AmbientColor)); - - GLERROR("Bind 10 uniform"); GLint Location_GlowIntensity = glGetUniformLocation(shaderHandle, "GlowIntensity"); + glUniform1f(Location_GlowIntensity, job->GlowIntensity); - glUniform1f(Location_GlowIntensity, job->GlowIntensity); + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "LightP"), MAX_SPLITS, GL_FALSE, glm::value_ptr(*m_ShadowPass->LightP().data())); + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "LightV"), MAX_SPLITS, GL_FALSE, glm::value_ptr(*m_ShadowPass->LightV().data())); + glUniform1fv(glGetUniformLocation(shaderHandle, "FarDistance"), MAX_SPLITS, m_ShadowPass->FarDistance().data()); GLERROR("END"); } @@ -861,10 +1523,12 @@ void DrawFinalPass::BindExplosionTextures(GLuint shaderHandle, std::shared_ptrNormalTexture.size() > 0 && job->NormalTexture[0]->Texture != nullptr) { glBindTexture(GL_TEXTURE_2D, job->NormalTexture[0]->Texture->m_Texture); glUniform2fv(glGetUniformLocation(shaderHandle, "NormalUVRepeat"), 1, glm::value_ptr(job->NormalTexture[0]->UVRepeat)); + glUniform1i(glGetUniformLocation(shaderHandle, "NormalTextureType"), job->NormalTexture[0]->Texture->m_Type); } else { glBindTexture(GL_TEXTURE_2D, m_NeutralNormalTexture->m_Texture); glUniform2fv(glGetUniformLocation(shaderHandle, "NormalUVRepeat"), 1, glm::value_ptr(glm::vec2(1.0f, 1.0f))); + glUniform1i(glGetUniformLocation(shaderHandle, "NormalTextureType"), m_NeutralNormalTexture->m_Type); } glActiveTexture(GL_TEXTURE3); @@ -917,10 +1581,12 @@ void DrawFinalPass::BindExplosionTextures(GLuint shaderHandle, std::shared_ptrNormalTexture.size() > i && job->NormalTexture[i]->Texture != nullptr) { glBindTexture(GL_TEXTURE_2D, job->NormalTexture[i]->Texture->m_Texture); glUniform2fv(glGetUniformLocation(shaderHandle, std::string(UniformName + ((char)(i + '1'))).c_str()), 1, glm::value_ptr(job->NormalTexture[i]->UVRepeat)); + glUniform1i(glGetUniformLocation(shaderHandle, "NormalTextureType"), job->NormalTexture[0]->Texture->m_Type); } else { glBindTexture(GL_TEXTURE_2D, m_NeutralNormalTexture->m_Texture); glUniform2fv(glGetUniformLocation(shaderHandle, std::string(UniformName + ((char)(i + '1'))).c_str()), 1, glm::value_ptr(glm::vec2(1.0f, 1.0f))); + glUniform1i(glGetUniformLocation(shaderHandle, "NormalTextureType"), m_NeutralNormalTexture->m_Type); } texturePosition++; } @@ -979,10 +1645,12 @@ void DrawFinalPass::BindModelTextures(GLuint shaderHandle, std::shared_ptrNormalTexture.size() > 0 && job->NormalTexture[0]->Texture != nullptr) { glBindTexture(GL_TEXTURE_2D, job->NormalTexture[0]->Texture->m_Texture); glUniform2fv(glGetUniformLocation(shaderHandle, "NormalUVRepeat"), 1, glm::value_ptr(job->NormalTexture[0]->UVRepeat)); + glUniform1i(glGetUniformLocation(shaderHandle, "NormalTextureType"), job->NormalTexture[0]->Texture->m_Type); } else { glBindTexture(GL_TEXTURE_2D, m_NeutralNormalTexture->m_Texture); - glUniform2fv(glGetUniformLocation(shaderHandle, "NormalUVRepeat"), 1, glm::value_ptr(glm::vec2(1.0f, 1.0f))); + //glUniform2fv(glGetUniformLocation(shaderHandle, "NormalUVRepeat"), 1, glm::value_ptr(glm::vec2(1.0f, 1.0f))); + glUniform1i(glGetUniformLocation(shaderHandle, "NormalTextureType"), m_NeutralNormalTexture->m_Type); } glActiveTexture(GL_TEXTURE3); @@ -1014,57 +1682,60 @@ void DrawFinalPass::BindModelTextures(GLuint shaderHandle, std::shared_ptrDiffuseTexture.size() > i && job->DiffuseTexture[i]->Texture != nullptr) { glBindTexture(GL_TEXTURE_2D, job->DiffuseTexture[i]->Texture->m_Texture); - glUniform2fv(glGetUniformLocation(shaderHandle, std::string(UniformName + ((char)(i + '1'))).c_str()), 1, glm::value_ptr(job->DiffuseTexture[i]->UVRepeat)); + glUniform2fv(glGetUniformLocation(shaderHandle, std::string(UVRepeatName + ((char)(i + '1'))).c_str()), 1, glm::value_ptr(job->DiffuseTexture[i]->UVRepeat)); } else { glBindTexture(GL_TEXTURE_2D, m_WhiteTexture->m_Texture); - glUniform2fv(glGetUniformLocation(shaderHandle, std::string(UniformName + ((char)(i + '1'))).c_str()), 1, glm::value_ptr(glm::vec2(1.0f, 1.0f))); + glUniform2fv(glGetUniformLocation(shaderHandle, std::string(UVRepeatName + ((char)(i + '1'))).c_str()), 1, glm::value_ptr(glm::vec2(1.0f, 1.0f))); } texturePosition++; } //Bind 5 Normal textures - UniformName = "NormalUVRepeat"; + std::string textureType = "NormalTextureType"; + UVRepeatName = "NormalUVRepeat"; for (unsigned int i = 0; i < 3; i++) { glActiveTexture(texturePosition); if (job->NormalTexture.size() > i && job->NormalTexture[i]->Texture != nullptr) { glBindTexture(GL_TEXTURE_2D, job->NormalTexture[i]->Texture->m_Texture); - glUniform2fv(glGetUniformLocation(shaderHandle, std::string(UniformName + ((char)(i + '1'))).c_str()), 1, glm::value_ptr(job->NormalTexture[i]->UVRepeat)); + glUniform2fv(glGetUniformLocation(shaderHandle, std::string(UVRepeatName + ((char)(i + '1'))).c_str()), 1, glm::value_ptr(job->NormalTexture[i]->UVRepeat)); + glUniform1i(glGetUniformLocation(shaderHandle, std::string(textureType + ((char)(i + '1'))).c_str()), job->NormalTexture[i]->Texture->m_Type); } else { glBindTexture(GL_TEXTURE_2D, m_NeutralNormalTexture->m_Texture); - glUniform2fv(glGetUniformLocation(shaderHandle, std::string(UniformName + ((char)(i + '1'))).c_str()), 1, glm::value_ptr(glm::vec2(1.0f, 1.0f))); + glUniform2fv(glGetUniformLocation(shaderHandle, std::string(UVRepeatName + ((char)(i + '1'))).c_str()), 1, glm::value_ptr(glm::vec2(1.0f, 1.0f))); + glUniform1i(glGetUniformLocation(shaderHandle, std::string(textureType + ((char)(i + '1'))).c_str()), m_NeutralNormalTexture->m_Type); } texturePosition++; } //Bind 5 Specular textures - UniformName = "SpecularUVRepeat"; + UVRepeatName = "SpecularUVRepeat"; for (unsigned int i = 0; i < 3; i++) { glActiveTexture(texturePosition); if (job->SpecularTexture.size() > i && job->SpecularTexture[i]->Texture != nullptr) { glBindTexture(GL_TEXTURE_2D, job->SpecularTexture[i]->Texture->m_Texture); - glUniform2fv(glGetUniformLocation(shaderHandle, std::string(UniformName + ((char)(i + '1'))).c_str()), 1, glm::value_ptr(job->SpecularTexture[i]->UVRepeat)); + glUniform2fv(glGetUniformLocation(shaderHandle, std::string(UVRepeatName + ((char)(i + '1'))).c_str()), 1, glm::value_ptr(job->SpecularTexture[i]->UVRepeat)); } else { glBindTexture(GL_TEXTURE_2D, m_GreyTexture->m_Texture); - glUniform2fv(glGetUniformLocation(shaderHandle, std::string(UniformName + ((char)(i + '1'))).c_str()), 1, glm::value_ptr(glm::vec2(1.0f, 1.0f))); + glUniform2fv(glGetUniformLocation(shaderHandle, std::string(UVRepeatName + ((char)(i + '1'))).c_str()), 1, glm::value_ptr(glm::vec2(1.0f, 1.0f))); } texturePosition++; } //Bind 5 Incandescence textures - UniformName = "GlowUVRepeat"; + UVRepeatName = "GlowUVRepeat"; for (unsigned int i = 0; i < 3; i++) { glActiveTexture(texturePosition); if (job->IncandescenceTexture.size() > i && job->IncandescenceTexture[i]->Texture != nullptr) { glBindTexture(GL_TEXTURE_2D, job->IncandescenceTexture[i]->Texture->m_Texture); - glUniform2fv(glGetUniformLocation(shaderHandle, std::string(UniformName + ((char)(i + '1'))).c_str()), 1, glm::value_ptr(job->IncandescenceTexture[i]->UVRepeat)); + glUniform2fv(glGetUniformLocation(shaderHandle, std::string(UVRepeatName + ((char)(i + '1'))).c_str()), 1, glm::value_ptr(job->IncandescenceTexture[i]->UVRepeat)); } else { glBindTexture(GL_TEXTURE_2D, m_BlackTexture->m_Texture); - glUniform2fv(glGetUniformLocation(shaderHandle, std::string(UniformName + ((char)(i + '1'))).c_str()), 1, glm::value_ptr(glm::vec2(1.0f, 1.0f))); + glUniform2fv(glGetUniformLocation(shaderHandle, std::string(UVRepeatName + ((char)(i + '1'))).c_str()), 1, glm::value_ptr(glm::vec2(1.0f, 1.0f))); } texturePosition++; } diff --git a/src/Engine/Rendering/DrawFinalPassState.cpp b/src/Engine/Rendering/DrawFinalPassState.cpp index 8b5ddc8b..811d9d84 100644 --- a/src/Engine/Rendering/DrawFinalPassState.cpp +++ b/src/Engine/Rendering/DrawFinalPassState.cpp @@ -8,11 +8,14 @@ DrawFinalPassState::DrawFinalPassState(GLuint frameBuffer) Enable(GL_BLEND); BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); Enable(GL_DEPTH_TEST); + DepthMask(GL_TRUE); Enable(GL_CULL_FACE); - Enable(GL_STENCIL_TEST); - StencilFunc(GL_NOTEQUAL, 1, 0xFF); - StencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); - StencilMask(0xFF); + 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); + // StencilMask(0xFF); ClearColor(glm::vec4(0.f, 0.f, 0.f, 0.f)); } @@ -24,11 +27,9 @@ DrawFinalPassState::~DrawFinalPassState() DrawStencilState::DrawStencilState(GLuint frameBuffer) { BindFramebuffer(frameBuffer); - Enable(GL_STENCIL_TEST); - StencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); - StencilFunc(GL_ALWAYS, 1, 0xFF); - StencilMask(0xFF); Enable(GL_DEPTH_TEST); + DepthMask(GL_TRUE); + Enable(GL_CULL_FACE); ClearColor(glm::vec4(0.f)); } diff --git a/src/Engine/Rendering/FrameBuffer.cpp b/src/Engine/Rendering/FrameBuffer.cpp index 794fb84e..f436b25a 100644 --- a/src/Engine/Rendering/FrameBuffer.cpp +++ b/src/Engine/Rendering/FrameBuffer.cpp @@ -2,11 +2,13 @@ #include "Rendering/FrameBuffer.h" -BufferResource::BufferResource(GLuint* resourceHandle, GLenum resourceType, GLenum attachment) +BufferResource::BufferResource(GLuint* resourceHandle, GLenum resourceType, GLenum attachment, GLuint mipMapLod, bool multiSampling) { m_ResourceHandle = resourceHandle; m_ResourceType = resourceType; m_Attachment = attachment; + m_MipMapLod = mipMapLod; + m_MultiSampling = multiSampling; } Texture2D::~Texture2D() @@ -14,14 +16,31 @@ Texture2D::~Texture2D() if (m_ResourceHandle != 0) { glDeleteTextures(1, m_ResourceHandle); } + *m_ResourceHandle = 0; } +Texture2DMultiSample::~Texture2DMultiSample() +{ + if (m_ResourceHandle != 0) { + glDeleteTextures(1, m_ResourceHandle); + } + *m_ResourceHandle = 0; +} RenderBuffer::~RenderBuffer() { if (m_ResourceHandle != 0) { glDeleteRenderbuffers(1, m_ResourceHandle); } + *m_ResourceHandle = 0; +} + +Texture2DArray::~Texture2DArray() +{ + if (m_ResourceHandle != 0) { + glDeleteTextures(1, m_ResourceHandle); + } + *m_ResourceHandle = 0; } @@ -34,6 +53,14 @@ FrameBuffer::~FrameBuffer() void FrameBuffer::AddResource(std::shared_ptr resource) { + //m_MultiSampling is true when initialized + if (m_MultiSampling != resource->m_MultiSampling) { + if (m_MultiSampling == false) { + GLERROR("All renderbuffers is/is not using multisampling"); + } else { + m_MultiSampling = false; + } + } m_Resources.push_back(resource); } @@ -42,35 +69,41 @@ void FrameBuffer::Generate() GLERROR("PRE"); std::vector attachments; - - glGenFramebuffers(1, &m_BufferHandle); + if (m_BufferHandle == 0) { + glGenFramebuffers(1, &m_BufferHandle); + } glBindFramebuffer(GL_FRAMEBUFFER, m_BufferHandle); GLERROR("1"); + for (auto it = m_Resources.begin(); it != m_Resources.end(); it++) { + switch ((*it)->m_ResourceType) { + case GL_TEXTURE_2D_MULTISAMPLE: + glFramebufferTexture2D(GL_FRAMEBUFFER, (*it)->m_Attachment, GL_TEXTURE_2D_MULTISAMPLE, 0, 0); + GLERROR("FrameBuffer generate: GL_TEXTURE_2D_MULTISAMPLE"); + break; + case GL_TEXTURE_2D: + glFramebufferTexture(GL_FRAMEBUFFER, (*it)->m_Attachment, *(*it)->m_ResourceHandle, (*it)->m_MipMapLod); + GLERROR("FrameBuffer generate: GL_TEXTURE_2D"); + break; + case GL_RENDERBUFFER: + glFramebufferRenderbuffer(GL_FRAMEBUFFER, (*it)->m_Attachment, (*it)->m_ResourceType, *(*it)->m_ResourceHandle); + GLERROR("FrameBuffer generate: GL_RENDERBUFFER"); + break; + case GL_TEXTURE_2D_ARRAY: + glFramebufferTexture(GL_FRAMEBUFFER, (*it)->m_Attachment, *(*it)->m_ResourceHandle, 0); + GLERROR("FrameBuffer generate: GL_TEXTURE_2D_ARRAY"); + break; + } + GLERROR("2"); - for (auto it = m_Resources.begin(); it != m_Resources.end(); it++) { - switch ((*it)->m_ResourceType) { - case GL_TEXTURE_2D: - glFramebufferTexture2D(GL_FRAMEBUFFER, (*it)->m_Attachment, (*it)->m_ResourceType, *(*it)->m_ResourceHandle, 0); - GLERROR("FrameBuffer generate: glFramebufferTexture2D"); + if ((*it)->m_Attachment != GL_DEPTH_ATTACHMENT && (*it)->m_Attachment != GL_STENCIL_ATTACHMENT && (*it)->m_Attachment != GL_DEPTH_STENCIL_ATTACHMENT) { + attachments.push_back((*it)->m_Attachment); + } + GLERROR("Attachment"); + } - break; - case GL_RENDERBUFFER: - glFramebufferRenderbuffer(GL_FRAMEBUFFER, (*it)->m_Attachment, (*it)->m_ResourceType, *(*it)->m_ResourceHandle); - GLERROR("FrameBuffer generate: glFramebufferRenderbuffer"); - break; - } - GLERROR("2"); + GLERROR("3"); - if ((*it)->m_Attachment != GL_DEPTH_ATTACHMENT && (*it)->m_Attachment != GL_STENCIL_ATTACHMENT && (*it)->m_Attachment != GL_DEPTH_STENCIL_ATTACHMENT) { - attachments.push_back((*it)->m_Attachment); - } - GLERROR("Attachment"); - - } - GLERROR("3"); - - - GLenum* bufferTextures = &attachments[0]; + GLenum* bufferTextures = attachments.data(); glDrawBuffers(attachments.size(), bufferTextures); if (GLERROR("GLBufferAttachement error")) { printf(": AttachmentSize %i", attachments.size()); @@ -78,7 +111,7 @@ void FrameBuffer::Generate() if (GLenum frameBufferStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { GLERROR("Framebuffer incomplete"); - //LOG_ERROR("FrameBuffer incomplete: 0x%x\n", frameBufferStatus); + LOG_ERROR("FrameBuffer incomplete: 0x%x\n", glCheckFramebufferStatus(GL_FRAMEBUFFER)); exit(EXIT_FAILURE); } GLERROR("END"); @@ -99,3 +132,11 @@ GLuint FrameBuffer::GetHandle() { return m_BufferHandle; } + +void FrameBuffer::Read() { + glBindFramebuffer(GL_READ_FRAMEBUFFER, m_BufferHandle); +} + +void FrameBuffer::Draw() { + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_BufferHandle); +} diff --git a/src/Engine/Rendering/LightCullingPass.cpp b/src/Engine/Rendering/LightCullingPass.cpp index 1ce1f88c..9a6e19cf 100644 --- a/src/Engine/Rendering/LightCullingPass.cpp +++ b/src/Engine/Rendering/LightCullingPass.cpp @@ -42,6 +42,15 @@ void LightCullingPass::SetSSBOSizes() { m_NumberOfTiles = (int)(m_Renderer->GetViewportSize().Width/TILE_SIZE) * (int)(m_Renderer->GetViewportSize().Height/TILE_SIZE); + if (m_Frustums != nullptr) { + delete[] m_Frustums; + } + if (m_LightGrid != nullptr) { + delete[] m_LightGrid; + } + if (m_LightIndex != nullptr) { + delete[] m_LightIndex; + } m_Frustums = new Frustum[m_NumberOfTiles]; m_LightGrid = new LightGrid[m_NumberOfTiles]; m_LightIndex = new float[m_NumberOfTiles*MAX_LIGHTS_PER_TILE]; diff --git a/src/Engine/Rendering/Model.cpp b/src/Engine/Rendering/Model.cpp index 3f8e20e1..596e254b 100644 --- a/src/Engine/Rendering/Model.cpp +++ b/src/Engine/Rendering/Model.cpp @@ -3,38 +3,38 @@ Model::Model(std::string fileName) { //Try loading the model asyncronously, if it throws any exceptions then let it propagate back to caller. - m_RawModel = ResourceManager::Load(fileName); + auto rawModel = ResourceManager::Load(fileName); - for (auto& materialProperty : m_RawModel->m_Materials) { + for (auto& materialProperty : rawModel->m_Materials) { switch (materialProperty.type) { case RawModel::MaterialType::SingleTextures: { RawModel::MaterialSingleTextures* materialSingleTexture = static_cast(materialProperty.material); - materialSingleTexture->ColorMap.Texture = CommonFunctions::LoadTexture(materialSingleTexture->ColorMap.TexturePath, false); - materialSingleTexture->NormalMap.Texture = CommonFunctions::LoadTexture(materialSingleTexture->NormalMap.TexturePath, false); - materialSingleTexture->SpecularMap.Texture = CommonFunctions::LoadTexture(materialSingleTexture->SpecularMap.TexturePath, false); - materialSingleTexture->IncandescenceMap.Texture = CommonFunctions::LoadTexture(materialSingleTexture->IncandescenceMap.TexturePath, false); + materialSingleTexture->ColorMap.Texture = CommonFunctions::TryLoadResource(materialSingleTexture->ColorMap.TexturePath); + materialSingleTexture->NormalMap.Texture = CommonFunctions::TryLoadResource(materialSingleTexture->NormalMap.TexturePath); + materialSingleTexture->SpecularMap.Texture = CommonFunctions::TryLoadResource(materialSingleTexture->SpecularMap.TexturePath); + materialSingleTexture->IncandescenceMap.Texture = CommonFunctions::TryLoadResource(materialSingleTexture->IncandescenceMap.TexturePath); } break; case RawModel::MaterialType::SplatMapping: { RawModel::MaterialSplatMapping* materialSplatMapping = static_cast(materialProperty.material); - materialSplatMapping->SplatMap.Texture = CommonFunctions::LoadTexture(materialSplatMapping->SplatMap.TexturePath, false); + materialSplatMapping->SplatMap.Texture = CommonFunctions::TryLoadResource(materialSplatMapping->SplatMap.TexturePath); for (auto& texture : materialSplatMapping->ColorMaps) { - texture.Texture = CommonFunctions::LoadTexture(texture.TexturePath, false); + texture.Texture = CommonFunctions::TryLoadResource(texture.TexturePath); } for (auto& texture : materialSplatMapping->NormalMaps) { - texture.Texture = CommonFunctions::LoadTexture(texture.TexturePath, false); + texture.Texture = CommonFunctions::TryLoadResource(texture.TexturePath); } for (auto& texture : materialSplatMapping->SpecularMaps) { - texture.Texture = CommonFunctions::LoadTexture(texture.TexturePath, false); + texture.Texture = CommonFunctions::TryLoadResource(texture.TexturePath); } for (auto& texture : materialSplatMapping->IncandescenceMaps) { - texture.Texture = CommonFunctions::LoadTexture(texture.TexturePath, false); + texture.Texture = CommonFunctions::TryLoadResource(texture.TexturePath); } } break; @@ -46,11 +46,11 @@ Model::Model(std::string fileName) glGenBuffers(1, &buffer); glBindBuffer(GL_ARRAY_BUFFER, buffer); - glBufferData(GL_ARRAY_BUFFER, m_RawModel->NumVertices() * m_RawModel->VertexSize(), m_RawModel->Vertices(), GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, rawModel->NumVertices() * rawModel->VertexSize(), rawModel->Vertices(), GL_STATIC_DRAW); glGenBuffers(1, &ElementBuffer); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ElementBuffer); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_RawModel->m_Indices.size() * sizeof(unsigned int), &m_RawModel->m_Indices[0], GL_STATIC_DRAW); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, rawModel->Indices().size() * sizeof(unsigned int), rawModel->Indices().data(), GL_STATIC_DRAW); glGenVertexArrays(1, &VAO); glBindVertexArray(VAO); @@ -58,7 +58,7 @@ Model::Model(std::string fileName) glBindBuffer(GL_ARRAY_BUFFER, buffer); std::vector structSizes; - if (m_RawModel->IsSkinned()) { + if (rawModel->IsSkinned()) { structSizes = { 3, 3, 3, 3, 2, 4, 4 }; } else { structSizes = { 3, 3, 3, 3, 2 }; @@ -77,7 +77,7 @@ Model::Model(std::string fileName) glVertexAttribPointer(element, structSizes[element], GL_FLOAT, GL_FALSE, stride, (GLvoid*)(sizeof(GLfloat) * (offset += structSizes[element - 1]))); element++; glVertexAttribPointer(element, structSizes[element], GL_FLOAT, GL_FALSE, stride, (GLvoid*)(sizeof(GLfloat) * (offset += structSizes[element - 1]))); element++; glVertexAttribPointer(element, structSizes[element], GL_FLOAT, GL_FALSE, stride, (GLvoid*)(sizeof(GLfloat) * (offset += structSizes[element - 1]))); element++; - if (m_RawModel->IsSkinned()) { + if (rawModel->IsSkinned()) { glVertexAttribPointer(element, structSizes[element], GL_FLOAT, GL_FALSE, stride, (GLvoid*)(sizeof(GLfloat) * (offset += structSizes[element - 1]))); element++; glVertexAttribPointer(element, structSizes[element], GL_FLOAT, GL_FALSE, stride, (GLvoid*)(sizeof(GLfloat) * (offset += structSizes[element - 1]))); element++; } @@ -89,7 +89,7 @@ Model::Model(std::string fileName) glEnableVertexAttribArray(2); glEnableVertexAttribArray(3); glEnableVertexAttribArray(4); - if (m_RawModel->IsSkinned()) { + if (rawModel->IsSkinned()) { glEnableVertexAttribArray(5); glEnableVertexAttribArray(6); } @@ -99,17 +99,29 @@ Model::Model(std::string fileName) glm::vec3 mini(INFINITY); glm::vec3 maxi(-INFINITY); - - for (unsigned int i = 0; i < m_RawModel->NumVertices(); i++) { - const auto& v = m_RawModel->Vertices()[i]; + for (unsigned int i = 0; i < rawModel->NumVertices(); i++) { + const auto& v = rawModel->Vertices()[i]; mini = glm::min(mini, v.Position); maxi = glm::max(maxi, v.Position); } - m_Box = AABB(mini, maxi); + + m_Skeleton = rawModel->m_Skeleton; + m_Materials = rawModel->m_Materials; + m_Indices = rawModel->CollisionIndices(); + m_IsSkinned = rawModel->IsSkinned(); + // Copy vertex positions for collisions later + m_Vertices = rawModel->CollisionVertices(); + + ResourceManager::Release("RawModel", fileName); } Model::~Model() { - + if (m_Skeleton != nullptr) { + delete m_Skeleton; + } + for (auto material : m_Materials) { + delete material.material; + } } diff --git a/src/Engine/Rendering/PNG.cpp b/src/Engine/Rendering/PNG.cpp index 409da9b1..8febc160 100644 --- a/src/Engine/Rendering/PNG.cpp +++ b/src/Engine/Rendering/PNG.cpp @@ -96,10 +96,10 @@ PNG::~PNG() void PNG::pngErrorFunction(png_structp png_ptr, png_const_charp error_msg) { - LOG_WARNING("%s", error_msg); + LOG_WARNING("libpng error: %s", error_msg); } void PNG::pngWarningFunction(png_structp png_ptr, png_const_charp warning_msg) { - LOG_WARNING("%s", warning_msg); + LOG_WARNING("libpng warning: %s", warning_msg); } diff --git a/src/Engine/Rendering/PickingPass.cpp b/src/Engine/Rendering/PickingPass.cpp index 1eab9939..f75372d7 100644 --- a/src/Engine/Rendering/PickingPass.cpp +++ b/src/Engine/Rendering/PickingPass.cpp @@ -12,22 +12,24 @@ PickingPass::PickingPass(IRenderer* renderer, EventBroker* eb) PickingPass::~PickingPass() { - + CommonFunctions::DeleteTexture(&m_PickingTexture); + CommonFunctions::DeleteTexture(&m_DepthBuffer); } void PickingPass::InitializeTextures() { - GenerateTexture(&m_PickingTexture, GL_CLAMP_TO_BORDER, GL_LINEAR, + CommonFunctions::GenerateTexture(&m_PickingTexture, GL_CLAMP_TO_BORDER, GL_LINEAR, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_RG8, GL_RG, GL_UNSIGNED_BYTE); - GenerateTexture(&m_DepthBuffer, GL_CLAMP_TO_BORDER, GL_NEAREST, - glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8); + CommonFunctions::GenerateTexture(&m_DepthBuffer, GL_CLAMP_TO_BORDER, GL_NEAREST, + glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT); } void PickingPass::InitializeFrameBuffers() { + m_PickingBuffer.AddResource(std::shared_ptr(new Texture2D(&m_DepthBuffer, GL_DEPTH_ATTACHMENT))); m_PickingBuffer.AddResource(std::shared_ptr(new Texture2D(&m_PickingTexture, GL_COLOR_ATTACHMENT0))); m_PickingBuffer.Generate(); @@ -60,8 +62,9 @@ void PickingPass::Draw(RenderScene& scene) //TODO: Render: Add code for more jobs than modeljobs. GLuint shaderHandle = m_PickingProgram->GetHandle(); GLuint shaderSkinnedHandle = m_PickingSkinnedProgram->GetHandle(); + GLuint lastShader = 0; + unsigned int lastModel = 0; m_PickingProgram->Bind(); - if (scene.ClearDepth) { //glClear(GL_DEPTH_BUFFER_BIT); state->Disable(GL_DEPTH_TEST); @@ -73,6 +76,11 @@ void PickingPass::Draw(RenderScene& scene) auto modelJob = std::dynamic_pointer_cast(job); if (modelJob) { + if(modelJob->NotPickable) { + continue; + } + + int pickColor[2] = { m_ColorCounter[0], m_ColorCounter[1] }; PickingInfo pickInfo; @@ -97,32 +105,36 @@ void PickingPass::Draw(RenderScene& scene) m_PickingColorsToEntity[glm::ivec2(pickColor[0], pickColor[1])] = pickInfo; if (modelJob->Model->IsSkinned()) { - m_PickingSkinnedProgram->Bind(); - glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->Matrix)); - glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); - glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); + if (lastShader != m_PickingSkinnedProgram->GetHandle()) { + m_PickingSkinnedProgram->Bind(); + lastShader = m_PickingSkinnedProgram->GetHandle(); + } + glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "PVM"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix() * scene.Camera->ViewMatrix() * modelJob->Matrix)); glUniform2fv(glGetUniformLocation(shaderSkinnedHandle, "PickingColor"), 1, glm::value_ptr(glm::vec2(pickColor[0], pickColor[1]))); - if (modelJob->Model->m_RawModel->m_Skeleton != nullptr) { - - std::vector frameBones; - if (modelJob->AnimationOffset.animation != nullptr) { - frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations, modelJob->AnimationOffset); - } else { - frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations); - } - glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); + std::vector frameBones; + if (modelJob->BlendTree != nullptr) { + frameBones = modelJob->BlendTree->GetFinalPose(); + } else if (modelJob->Skeleton != nullptr) { + frameBones = modelJob->Skeleton->GetTPose(); } + glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); + + } else { - m_PickingProgram->Bind(); - glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->Matrix)); - 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())); + if (lastShader != m_PickingProgram->GetHandle()) { + m_PickingProgram->Bind(); + lastShader = m_PickingProgram->GetHandle(); + } + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "PVM"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix() * scene.Camera->ViewMatrix() * modelJob->Matrix)); glUniform2fv(glGetUniformLocation(shaderHandle, "PickingColor"), 1, glm::value_ptr(glm::vec2(pickColor[0], pickColor[1]))); } - glBindVertexArray(modelJob->Model->VAO); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, modelJob->Model->ElementBuffer); + if (lastModel != modelJob->ModelID) { + glBindVertexArray(modelJob->Model->VAO); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, modelJob->Model->ElementBuffer); + lastModel = modelJob->ModelID; + } glDrawElements(GL_TRIANGLES, modelJob->EndIndex - modelJob->StartIndex + 1, GL_UNSIGNED_INT, (void*)(modelJob->StartIndex * sizeof(unsigned int))); } } @@ -161,13 +173,11 @@ void PickingPass::Draw(RenderScene& scene) glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); glUniform2fv(glGetUniformLocation(shaderSkinnedHandle, "PickingColor"), 1, glm::value_ptr(glm::vec2(pickColor[0], pickColor[1]))); - std::vector frameBones; - if (modelJob->AnimationOffset.animation != nullptr) { - frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations, modelJob->AnimationOffset); - } else { - frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations); + if (modelJob->BlendTree != nullptr) { + std::vector frameBones; + frameBones = modelJob->BlendTree->GetFinalPose(); + glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); } - glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); } else { m_PickingProgram->Bind(); glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->Matrix)); @@ -210,34 +220,41 @@ void PickingPass::Draw(RenderScene& scene) m_PickingColorsToEntity[glm::ivec2(pickColor[0], pickColor[1])] = pickInfo; if (modelJob->Model->IsSkinned()) { - m_PickingSkinnedProgram->Bind(); - glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->Matrix)); - glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); - glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); + if (lastShader != m_PickingSkinnedProgram->GetHandle()) { + m_PickingSkinnedProgram->Bind(); + lastShader = m_PickingSkinnedProgram->GetHandle(); + } + glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "PVM"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix() * scene.Camera->ViewMatrix() * modelJob->Matrix)); glUniform2fv(glGetUniformLocation(shaderSkinnedHandle, "PickingColor"), 1, glm::value_ptr(glm::vec2(pickColor[0], pickColor[1]))); std::vector frameBones; - if (modelJob->AnimationOffset.animation != nullptr) { - frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations, modelJob->AnimationOffset); + if (modelJob->BlendTree != nullptr) { + frameBones = modelJob->BlendTree->GetFinalPose(); } else { - frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations); + frameBones = modelJob->Skeleton->GetTPose(); } + glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); } else { - m_PickingProgram->Bind(); - glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->Matrix)); - 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())); + if (lastShader != m_PickingProgram->GetHandle()) { + m_PickingProgram->Bind(); + lastShader = m_PickingProgram->GetHandle(); + } + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "PVM"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix() * scene.Camera->ViewMatrix() * modelJob->Matrix)); glUniform2fv(glGetUniformLocation(shaderHandle, "PickingColor"), 1, glm::value_ptr(glm::vec2(pickColor[0], pickColor[1]))); } - glBindVertexArray(modelJob->Model->VAO); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, modelJob->Model->ElementBuffer); + if (lastModel != modelJob->ModelID) { + glBindVertexArray(modelJob->Model->VAO); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, modelJob->Model->ElementBuffer); + lastModel = modelJob->ModelID; + } glDrawElements(GL_TRIANGLES, modelJob->EndIndex - modelJob->StartIndex + 1, GL_UNSIGNED_INT, (void*)(modelJob->StartIndex * sizeof(unsigned int))); } } + m_PickingProgram->Bind(); for (auto& job : scene.Jobs.SpriteJob) { auto spriteJob = std::dynamic_pointer_cast(job); if (!spriteJob->Pickable) { @@ -272,14 +289,11 @@ void PickingPass::Draw(RenderScene& scene) m_PickingColorsToEntity[glm::ivec2(pickColor[0], pickColor[1])] = pickInfo; - m_PickingProgram->Bind(); - glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(spriteJob->Matrix)); - 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())); + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "PVM"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix() * scene.Camera->ViewMatrix() * spriteJob->Matrix)); glUniform2fv(glGetUniformLocation(shaderHandle, "PickingColor"), 1, glm::value_ptr(glm::vec2(pickColor[0], pickColor[1]))); - glBindVertexArray(spriteJob->Model->VAO); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, spriteJob->Model->ElementBuffer); + glBindVertexArray(spriteJob->Model->VAO); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, spriteJob->Model->ElementBuffer); glDrawElements(GL_TRIANGLES, spriteJob->EndIndex - spriteJob->StartIndex + 1, GL_UNSIGNED_INT, (void*)(spriteJob->StartIndex * sizeof(unsigned int))); } } @@ -321,16 +335,10 @@ void PickingPass::Draw(RenderScene& scene) glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); glUniform2fv(glGetUniformLocation(shaderSkinnedHandle, "PickingColor"), 1, glm::value_ptr(glm::vec2(pickColor[0], pickColor[1]))); - if (modelJob->Model->m_RawModel->m_Skeleton != nullptr) { - + if (modelJob->BlendTree != nullptr) { std::vector frameBones; - if (modelJob->AnimationOffset.animation != nullptr) { - frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations, modelJob->AnimationOffset); - } else { - frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations); - } + frameBones = modelJob->BlendTree->GetFinalPose(); glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); - } } else { m_PickingProgram->Bind(); @@ -366,7 +374,7 @@ void PickingPass::ClearPicking() m_PickingBuffer.Bind(); glClearColor(0.f, 0.f, 0.f, 0.f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); m_PickingBuffer.Unbind(); GLERROR("END"); } @@ -407,16 +415,3 @@ PickData PickingPass::Pick(glm::vec2 screenCoord) pickData.World = pickInfo.World; return pickData; } - -void PickingPass::GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type) const -{ - //TODO: Renderer: Make this in a sparate class - glGenTextures(1, texture); - glBindTexture(GL_TEXTURE_2D, *texture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapping); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapping); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering); - glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, dimensions.x, dimensions.y, 0, format, type, nullptr);//TODO: Renderer: Fix the precision and Resolution - GLERROR("Texture initialization failed"); -} diff --git a/src/Engine/Rendering/PickingPassState.cpp b/src/Engine/Rendering/PickingPassState.cpp index f2d42bff..767b9577 100644 --- a/src/Engine/Rendering/PickingPassState.cpp +++ b/src/Engine/Rendering/PickingPassState.cpp @@ -9,11 +9,11 @@ PickingPassState::PickingPassState(GLuint frameBuffer) Enable(GL_DEPTH_TEST); Enable(GL_CULL_FACE); Disable(GL_BLEND); - glm::vec4 clearColor = glm::vec4(0.f); //ClearColor(clearColor); //Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); GLERROR("END"); + } PickingPassState::~PickingPassState() diff --git a/src/Engine/Rendering/RawModelCustom.cpp b/src/Engine/Rendering/RawModelCustom.cpp index dd6a96de..a5cb9d43 100644 --- a/src/Engine/Rendering/RawModelCustom.cpp +++ b/src/Engine/Rendering/RawModelCustom.cpp @@ -11,6 +11,7 @@ RawModelCustom::RawModelCustom(std::string fileName) ReadMeshFile(fileName); ReadMaterialFile(fileName); ReadAnimationFile(fileName); + ReadCollisionFile(fileName); } void RawModelCustom::ReadMeshFile(std::string filePath) @@ -71,11 +72,11 @@ void RawModelCustom::ReadVertices(std::size_t& offset, char* fileData, const uns memcpy(&m_SkinedVertices[0], fileData + offset, m_SkinedVertices.size() * sizeof(SkinedVertex)); offset += m_SkinedVertices.size() * sizeof(SkinedVertex); } else { - if (offset + m_Vertices.size() * sizeof(Vertex) > fileByteSize) { + if (offset + m_Vertices.size() * sizeof(RenderVertex) > fileByteSize) { throw Resource::FailedLoadingException("Reading vertices failed"); } - memcpy(&m_Vertices[0], fileData + offset, m_Vertices.size() * sizeof(Vertex)); - offset += m_Vertices.size() * sizeof(Vertex); + memcpy(&m_Vertices[0], fileData + offset, m_Vertices.size() * sizeof(RenderVertex)); + offset += m_Vertices.size() * sizeof(RenderVertex); } #else #endif @@ -148,14 +149,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"); @@ -271,7 +287,7 @@ void RawModelCustom::ReadMaterialTextureProperties(RawModelCustom::TextureProper } texture.TexturePath = "Textures/"; texture.TexturePath += (fileData + offset); - texture.TexturePath += ".png"; + texture.TexturePath += ".dds"; offset += nameLength; if (offset + sizeof(glm::vec2) > fileByteSize) { throw Resource::FailedLoadingException("Reading Material texture UVTiling failed"); @@ -476,14 +492,90 @@ void RawModelCustom::ReadAnimationKeyFrame(std::size_t& offset, char* fileData, } +void RawModelCustom::ReadCollisionFile(std::string filePath) { + char* fileData; + filePath += ".colli"; + std::ifstream in(filePath.c_str(), std::ios_base::binary | std::ios_base::ate); + + if (!in.is_open()) { + return; + } + unsigned int fileByteSize = static_cast(in.tellg()); + in.seekg(0, std::ios_base::beg); + + fileData = new char[fileByteSize]; + in.read(fileData, fileByteSize); + in.close(); + + std::size_t offset = 0; + if (fileByteSize > 0) { + ReadCollisionFileData(offset, fileData, fileByteSize); + } + hasCollisionMesh = true; + delete[] fileData; +} + +const std::vector& RawModelCustom::CollisionVertices() { + if (hasCollisionMesh) { + return m_CollisionVertices; + } + else if (hasSkin) { + // We don't do collisions against skinned meshes now. + m_CollisionVertices = std::vector(); + return m_CollisionVertices; + } + else { + return ConstructCollisionList(); + } +}; + +void RawModelCustom::ReadCollisionFileData(std::size_t& offset, char* fileData, const unsigned int& fileByteSize){ + m_CollisionVertices.resize(static_cast(*(unsigned int*)(fileData + offset))); + offset += sizeof(unsigned int); + m_CollisionIndices.resize(static_cast(*(unsigned int*)(fileData + offset))); + offset += sizeof(unsigned int); + + if (offset + m_CollisionVertices.size() * sizeof(glm::vec3) > fileByteSize) { + throw Resource::FailedLoadingException("Reading collision vertices failed"); + } + memcpy(&m_CollisionVertices[0], fileData + offset, m_CollisionVertices.size() * sizeof(glm::vec3)); + offset += m_CollisionVertices.size() * sizeof(glm::vec3); + + if (offset + m_CollisionIndices.size() * sizeof(unsigned int) > fileByteSize) { + throw Resource::FailedLoadingException("Reading collision indices failed"); + } + memcpy(&m_CollisionIndices[0], fileData + offset, m_CollisionIndices.size() * sizeof(unsigned int)); + offset += m_CollisionIndices.size() * sizeof(unsigned int); +} + +const std::vector& RawModelCustom::ConstructCollisionList() +{ + if (!hasCollisionMesh && m_CollisionVertices.size() == 0) { + if (hasSkin) { + m_CollisionVertices.reserve(m_SkinedVertices.size()); + for (const auto& vertex : m_SkinedVertices) { + m_CollisionVertices.push_back(vertex.Position); + } + } else { + m_CollisionVertices.reserve(m_Vertices.size()); + for (const auto& vertex : m_Vertices) { + m_CollisionVertices.push_back(vertex.Position); + } + } + } + + return m_CollisionVertices; +} + RawModelCustom::~RawModelCustom() { - if (m_Skeleton != nullptr) { - delete m_Skeleton; - } - for (auto material : m_Materials) { - delete material.material; - } + // Ownership of skeleton and materials get transferred to Model + // if (m_Skeleton != nullptr) { + // delete m_Skeleton; + // } + //for (auto material : m_Materials) { + // delete material.material; + //} } #endif \ No newline at end of file diff --git a/src/Engine/Rendering/RenderState.cpp b/src/Engine/Rendering/RenderState.cpp index 26ba18a1..56812f9a 100644 --- a/src/Engine/Rendering/RenderState.cpp +++ b/src/Engine/Rendering/RenderState.cpp @@ -135,6 +135,26 @@ bool RenderState::DepthMask(GLboolean flag) return !GLERROR("DepthMask"); } +bool RenderState::DepthFunc(GLenum func) +{ + GLint original; + glGetIntegerv(GL_DEPTH_FUNC, &original); + m_ResetFunctions.push_back(std::bind(glDepthFunc, original)); + glDepthFunc(func); + return !GLERROR("DepthFunc"); +} + +bool RenderState::AlphaFunc(GLenum func, GLclampf thresholder) +{ + GLint originalFunc; + glGetIntegerv(GL_ALPHA_TEST_FUNC, &originalFunc); + GLint originalRef; + glGetIntegerv(GL_ALPHA_TEST_REF, &originalRef); + m_ResetFunctions.push_back(std::bind(glAlphaFunc, originalFunc, originalRef)); + glAlphaFunc(func, thresholder); + return !GLERROR("AlphaFunc"); +} + RenderState::~RenderState() { for (auto& f : boost::adaptors::reverse(m_ResetFunctions)) { diff --git a/src/Engine/Rendering/RenderSystem.cpp b/src/Engine/Rendering/RenderSystem.cpp index 7b0ea84f..578ab44c 100644 --- a/src/Engine/Rendering/RenderSystem.cpp +++ b/src/Engine/Rendering/RenderSystem.cpp @@ -9,10 +9,11 @@ RenderSystem::RenderSystem(SystemParams params, const IRenderer* renderer, Rende , m_Octree(frustumCullOctree) { EVENT_SUBSCRIBE_MEMBER(m_ESetCamera, &RenderSystem::OnSetCamera); + EVENT_SUBSCRIBE_MEMBER(m_EResolutionChanged, &RenderSystem::OnResolutionChanged); EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &RenderSystem::OnInputCommand); EVENT_SUBSCRIBE_MEMBER(m_EPlayerSpawned, &RenderSystem::OnPlayerSpawned); - m_Camera = new Camera((float)m_Renderer->Resolution().Width / m_Renderer->Resolution().Height, glm::radians(45.f), 0.01f, 5000.f); + m_Camera = new Camera((float)m_Renderer->GetViewportSize().Width / m_Renderer->GetViewportSize().Height, glm::radians(45.f), 0.01f, 5000.f); } RenderSystem::~RenderSystem() @@ -20,11 +21,18 @@ RenderSystem::~RenderSystem() delete m_Camera; } +bool RenderSystem::OnResolutionChanged(Events::ResolutionChanged& e) +{ + // Update camera aspect ration on resolution change + m_Camera->SetAspectRatio((float)e.NewResolution.Width / e.NewResolution.Height); + return true; +} + bool RenderSystem::OnSetCamera(Events::SetCamera& e) { ComponentWrapper cTransform = e.CameraEntity["Transform"]; ComponentWrapper cCamera = e.CameraEntity["Camera"]; - m_Camera->SetFOV((double)cCamera["FOV"]); + m_Camera->SetFOV(glm::radians((double)cCamera["FOV"])); m_Camera->SetNearClip((double)cCamera["NearClip"]); m_Camera->SetFarClip((double)cCamera["FarClip"]); m_Camera->SetPosition(cTransform["Position"]); @@ -63,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; @@ -130,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); @@ -143,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); } @@ -176,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)) @@ -240,7 +248,9 @@ void RenderSystem::fillModels(RenderScene::Queues &Jobs) fillColor = (glm::vec4)fillComponent["Color"]; } - glm::mat4 modelMatrix = Transform::ModelMatrix(cModel.EntityID, m_World); + bool isShielded = m_World->HasComponent(cModel.EntityID, "Shielded") || m_World->HasComponent(cModel.EntityID, "Player"); + + 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 @@ -255,20 +265,20 @@ void RenderSystem::fillModels(RenderScene::Queues &Jobs) cModel, m_World, fillColor, - fillPercentage + fillPercentage, + isShielded, + false )); if (m_World->HasComponent(cModel.EntityID, "Shield")){ explosionEffectJob->CalculateHash(); Jobs.ShieldObjects.push_back(explosionEffectJob); - } else if (m_World->HasComponent(cModel.EntityID, "Shielded") - || m_World->HasComponent(cModel.EntityID, "Player")) { - + } else if (isShielded) { if (explosionEffectJob->Color.a != 1.f || explosionEffectJob->EndColor.a != 1.f || explosionEffectJob->DiffuseColor.a != 1.f) { cModel["Transparent"] = true; } if (cModel["Transparent"]) { - Jobs.TransparentShieldedObjects.push_back(explosionEffectJob); + Jobs.TransparentObjects.push_back(explosionEffectJob); } else { explosionEffectJob->CalculateHash(); Jobs.OpaqueShieldedObjects.push_back(explosionEffectJob); @@ -294,20 +304,21 @@ void RenderSystem::fillModels(RenderScene::Queues &Jobs) cModel, m_World, fillColor, - fillPercentage + fillPercentage, + isShielded, + (bool)cModel["Shadow"] )); if (m_World->HasComponent(cModel.EntityID, "Shield")) { modelJob->CalculateHash(); Jobs.ShieldObjects.push_back(modelJob); - } else if (m_World->HasComponent(cModel.EntityID, "Shielded") - || m_World->HasComponent(cModel.EntityID, "Player")) { + } else if (isShielded) { if (modelJob->Color.a != 1.f || modelJob->DiffuseColor.a != 1.f) { cModel["Transparent"] = true; } if (cModel["Transparent"]) { - Jobs.TransparentShieldedObjects.push_back(modelJob); + Jobs.TransparentObjects.push_back(modelJob); } else { modelJob->CalculateHash(); Jobs.OpaqueShieldedObjects.push_back(modelJob); @@ -351,6 +362,11 @@ void RenderSystem::fillPointLights(std::list>& jobs, continue; } + EntityWrapper entity(world, pointlightC.EntityID); + if (!isEntityVisible(entity)) { + continue; + } + std::shared_ptr pointLightJob = std::shared_ptr(new PointLightJob(transformC, pointlightC, m_World)); jobs.push_back(pointLightJob); } @@ -411,7 +427,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); @@ -429,11 +445,12 @@ 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; + scene.ShouldBlur = true; scene.Camera = m_Camera; scene.Viewport = Rectangle(1280, 720); @@ -447,7 +464,7 @@ void RenderSystem::Update(double dt) fillModels(scene.Jobs); fillPointLights(scene.Jobs.PointLight, m_World); //TODO: Make sure all objects needed are also sorted. - scene.Jobs.OpaqueObjects.sort(); + scene.Jobs.OpaqueObjects.sort([](auto& a, auto& b) {return *a < *b; }); fillSprites(scene.Jobs.SpriteJob, m_World); fillDirectionalLights(scene.Jobs.DirectionalLight, m_World); fillText(scene.Jobs.Text, m_World); diff --git a/src/Engine/Rendering/Renderer.cpp b/src/Engine/Rendering/Renderer.cpp index 251bba2b..8db7e7d3 100644 --- a/src/Engine/Rendering/Renderer.cpp +++ b/src/Engine/Rendering/Renderer.cpp @@ -2,8 +2,23 @@ std::unordered_map Renderer::m_WindowToRenderer; +Renderer::~Renderer() { + delete m_PickingPass; + delete m_LightCullingPass; + delete m_ImGuiRenderPass; + delete m_DrawFinalPass; + delete m_DrawScreenQuadPass; + delete m_DrawBloomPass; + delete m_DrawColorCorrectionPass; + delete m_SSAOPass; + delete m_CubeMapPass; + delete m_TextPass; +} + void Renderer::Initialize() { + m_SSAO_Quality = m_Config->Get("SSAO.Quality", 0); + m_GLOW_Quality = m_Config->Get("GLOW.Quality", 0); InitializeWindow(); InitializeRenderPasses(); @@ -15,22 +30,30 @@ void Renderer::Initialize() m_TextPass->Initialize(); /* m_ScreenQuad = ResourceManager::Load("Models/Core/ScreenQuad.obj"); - m_UnitQuad = ResourceManager::Load("Models/Core/UnitQuad.obj"); + m_UnitQuad = ResourceManager::Load(sModels/Core/UnitQuad.obj"); m_UnitSphere = ResourceManager::Load("Models/Core/UnitSphere.obj");*/ m_ImGuiRenderPass = new ImGuiRenderPass(this, m_EventBroker); } +void Renderer::glfwWindowSizeCallback(GLFWwindow* window, int width, int height) +{ + m_WindowToRenderer[window]->setWindowSize(Rectangle(width, height)); +} + void Renderer::glfwFrameBufferCallback(GLFWwindow* window, int width, int height) { - glViewport(0, 0, width, height); - Renderer* currentRenderer = m_WindowToRenderer[window]; - currentRenderer->m_ViewportSize = Rectangle(width, height); - currentRenderer->m_DrawFinalPass->OnWindowResize(); - currentRenderer->m_LightCullingPass->OnWindowResize(); - currentRenderer->m_PickingPass->OnWindowResize(); - currentRenderer->m_DrawBloomPass->OnWindowResize(); - currentRenderer->m_SSAOPass->OnWindowResize(); + m_WindowToRenderer[window]->updateFramebufferSize(); +} + +void Renderer::SetResolution(const Rectangle& resolution) +{ + m_Resolution = resolution; + + if (m_Window != nullptr) { + setWindowSize(resolution); + updateFramebufferSize(); + } } void Renderer::InitializeWindow() @@ -44,14 +67,24 @@ void Renderer::InitializeWindow() // Create a window GLFWmonitor* monitor = nullptr; if (m_Fullscreen) { - monitor = glfwGetPrimaryMonitor(); + //monitor = glfwGetPrimaryMonitor(); + //const GLFWvidmode* mode = glfwGetVideoMode(monitor); + + //glfwWindowHint(GLFW_RED_BITS, mode->redBits); + //glfwWindowHint(GLFW_GREEN_BITS, mode->greenBits); + //glfwWindowHint(GLFW_BLUE_BITS, mode->blueBits); + //glfwWindowHint(GLFW_REFRESH_RATE, mode->refreshRate); + glfwWindowHint(GLFW_DECORATED, false); + //glfwWindowHint(GLFW_AUTO_ICONIFY, false); } - //glfwWindowHint(GLFW_SAMPLES, 8); - m_Window = glfwCreateWindow(m_Resolution.Width, m_Resolution.Height, "daydream", monitor, nullptr); + + //glfwWindowHint(GLFW_SAMPLES, 8); + m_Window = glfwCreateWindow(m_Resolution.Width, m_Resolution.Height + 1, "daydream", monitor, nullptr); if (!m_Window) { LOG_ERROR("GLFW: Failed to create window"); exit(EXIT_FAILURE); } + glfwSetWindowSizeCallback(m_Window, &glfwWindowSizeCallback); glfwSetFramebufferSizeCallback(m_Window, &glfwFrameBufferCallback); glfwMakeContextCurrent(m_Window); @@ -96,6 +129,32 @@ void Renderer::InputUpdate(double dt) } +void Renderer::setWindowSize(Rectangle size) +{ + m_Resolution = size; + glfwSetWindowSize(m_Window, size.Width, size.Height); +} + +void Renderer::updateFramebufferSize() +{ + Events::ResolutionChanged e; + e.OldResolution = m_ViewportSize; + + int width, height; + glfwGetFramebufferSize(m_Window, &width, &height); + glViewport(0, 0, width, height); + m_ViewportSize = Rectangle(width, height); + m_PickingPass->OnWindowResize(); + m_DrawFinalPass->OnWindowResize(); + m_LightCullingPass->OnWindowResize(); + m_DrawBloomPass->OnWindowResize(); + m_SSAOPass->OnWindowResize(); + m_BlurHUDPass->OnWindowResize(); + + e.NewResolution = m_ViewportSize; + m_EventBroker->Publish(e); +} + void Renderer::Update(double dt) { m_EventBroker->Process(); @@ -107,49 +166,57 @@ void Renderer::Update(double dt) void Renderer::Draw(RenderFrame& frame) { GLERROR("PRE"); - ImGui::Combo("Draw textures", &m_DebugTextureToDraw, "Final\0Scene\0Bloom\0SceneLowRes\0BloomLowRes\0Gaussian\0Picking\0Ambient Occlusion"); + glBindFramebuffer(GL_FRAMEBUFFER, 0); +#ifdef DEBUG + ImGui::Combo("Draw textures", &m_DebugTextureToDraw, "Final\0Scene\0Bloom\0Gaussian\0Picking\0Ambient Occlusion\0Combined Scene Texture\0Full Blurred Texture"); ImGui::Combo("CubeMap", &m_CubeMapTexture, "Nevada(512)\0Sky(1024)"); +#endif if(m_CubeMapTexture == 0) { m_CubeMapPass->LoadTextures("Nevada"); } else if (m_CubeMapTexture == 1) { m_CubeMapPass->LoadTextures("Sky"); } - ImGui::SliderFloat("SSAO sample radius", &m_SSAO_Radius, 0.01f, 5.0f); - ImGui::SliderFloat("SSAO bias", &m_SSAO_Bias, 0.0f, 0.1f); - ImGui::SliderFloat("SSAO contrast", &m_SSAO_Contrast, 0.0f, 10.0f); - ImGui::SliderFloat("SSAO IntensityScale", &m_SSAO_IntensityScale, 0.0f, 10.0f); - ImGui::SliderInt("SSAO Number of Samples", &m_SSAO_NumOfSamples, 2, 100); - ImGui::SliderInt("SSAO Number of Turns", &m_SSAO_NumOfTurns, 0, 50); - m_SSAOPass->Setting(m_SSAO_Radius, m_SSAO_Bias, m_SSAO_Contrast, m_SSAO_IntensityScale, m_SSAO_NumOfSamples, m_SSAO_NumOfTurns); +#ifdef DEBUG + ImGui::SliderInt("SSAO Quality", &m_SSAO_Quality, 0, 3); + ImGui::SliderInt("Glow Quality", &m_GLOW_Quality, 0, 3); + ImGui::SliderInt("MSAA Level", (int*)&m_MSAA_Level, 0, 16); +#endif + m_SSAOPass->ChangeQuality(m_SSAO_Quality); + m_DrawBloomPass->ChangeQuality(m_GLOW_Quality); + m_DrawFinalPass->setMSAA(m_MSAA_Level); GLERROR("SSAO Settings"); //clear buffer 0 glClearColor(0.f, 0.f, 0.f, 0.f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - //Clear other buffers + //Clear other buffers PerformanceTimer::StartTimer("Renderer-ClearBuffers"); m_PickingPass->ClearPicking(); m_DrawFinalPass->ClearBuffer(); m_DrawBloomPass->ClearBuffer(); m_SSAOPass->ClearBuffer(); + m_ShadowPass->ClearBuffer(); + m_BlurHUDPass->ClearBuffer(); + m_ShadowPass->DebugGUI(); PerformanceTimer::StopTimer("Renderer-ClearBuffers"); GLERROR("ClearBuffers"); for (auto scene : frame.RenderScenes) { - PerformanceTimer::StartTimer("Renderer-Depth"); + PerformanceTimer::StartTimer("Renderer-PickingPass"); m_PickingPass->Draw(*scene); GLERROR("Drawing pickingpass"); - PerformanceTimer::StopTimer("Renderer-Depth"); + PerformanceTimer::StopTimer("Renderer-PickingPass"); } - PerformanceTimer::StartTimer("AO generation"); - m_SSAOPass->Draw(m_PickingPass->DepthBuffer(), frame.RenderScenes.front()->Camera); - GLuint ao = m_SSAOPass->SSAOTexture(); - PerformanceTimer::StopTimer("AO generation"); + PerformanceTimer::StartTimer("Renderer-AO generation"); + m_SSAOPass->Draw(*m_PickingPass->DepthBuffer(), frame.RenderScenes.front()->Camera); + PerformanceTimer::StopTimer("Renderer-AO generation"); for (auto scene : frame.RenderScenes){ - - PerformanceTimer::StartTimer("Renderer-Drawing PickingPass"); + PerformanceTimer::StartTimer("Renderer-Depth"); SortRenderJobsByDepth(*scene); GLERROR("SortByDepth"); + PerformanceTimer::StartTimerAndStopPrevious("Draw shadow maps"); + m_ShadowPass->Draw(*scene); + GLERROR("Draw shadow maps"); PerformanceTimer::StartTimerAndStopPrevious("Renderer-Generate Frustrums"); m_LightCullingPass->GenerateNewFrustum(*scene); GLERROR("Generate frustums"); @@ -159,8 +226,8 @@ void Renderer::Draw(RenderFrame& frame) PerformanceTimer::StartTimerAndStopPrevious("Renderer-Light Culling"); m_LightCullingPass->CullLights(*scene); GLERROR("LightCulling"); - m_DrawFinalPass->Draw(*scene, ao); - PerformanceTimer::StartTimerAndStopPrevious("Renderer-Draw Geometry+Light"); + PerformanceTimer::StartTimerAndStopPrevious("Renderer-Draw Geometry+Light"); + m_DrawFinalPass->Draw(*scene, m_BlurHUDPass); GLERROR("Draw Geometry+Light"); //m_DrawScenePass->Draw(*scene); @@ -176,7 +243,8 @@ void Renderer::Draw(RenderFrame& frame) if (m_DebugTextureToDraw == 0) { PerformanceTimer::StartTimer("Renderer-Color Correction Pass"); - m_DrawColorCorrectionPass->Draw(m_DrawFinalPass->SceneTexture(), m_DrawBloomPass->GaussianTexture(), m_DrawFinalPass->SceneTextureLowRes(), m_DrawFinalPass->BloomTextureLowRes(), frame.Gamma, frame.Exposure); + GLuint test = m_DrawFinalPass->SceneTexture(); + m_DrawColorCorrectionPass->Draw(test, m_DrawBloomPass->GaussianTexture(), frame.Gamma, frame.Exposure); PerformanceTimer::StopTimer("Renderer-Color Correction Pass"); } @@ -188,27 +256,30 @@ void Renderer::Draw(RenderFrame& frame) m_DrawScreenQuadPass->Draw(m_DrawFinalPass->BloomTexture()); } if (m_DebugTextureToDraw == 3) { - m_DrawScreenQuadPass->Draw(m_DrawFinalPass->SceneTextureLowRes()); - } - if (m_DebugTextureToDraw == 4) { - m_DrawScreenQuadPass->Draw(m_DrawFinalPass->BloomTextureLowRes()); - } - if (m_DebugTextureToDraw == 5) { m_DrawScreenQuadPass->Draw(m_DrawBloomPass->GaussianTexture()); } - if (m_DebugTextureToDraw == 6) { + if (m_DebugTextureToDraw == 4) { m_DrawScreenQuadPass->Draw(m_PickingPass->PickingTexture()); } - if (m_DebugTextureToDraw == 7) { + if (m_DebugTextureToDraw == 5) { m_DrawScreenQuadPass->Draw(m_SSAOPass->SSAOTexture()); } + if (m_DebugTextureToDraw == 6) { + m_DrawScreenQuadPass->Draw(m_DrawFinalPass->CombinedSceneTexture()); + } + if (m_DebugTextureToDraw == 7) { + m_DrawScreenQuadPass->Draw(m_DrawFinalPass->FullBlurredTexture()); + } PerformanceTimer::StopTimer("Renderer-Misc Debug Draws"); PerformanceTimer::StartTimer("Renderer-ImGuiRenderPass"); m_ImGuiRenderPass->Draw(); GLERROR("Imgui draw"); + PerformanceTimer::StopTimer("Renderer-ImGuiRenderPass"); + + PerformanceTimer::StartTimer("Renderer-SwapBuffer"); glfwSwapBuffers(m_Window); - PerformanceTimer::StopTimer("Renderer-ImGuiRenderPass"); + PerformanceTimer::StopTimer("Renderer-SwapBuffer"); } PickData Renderer::Pick(glm::vec2 screenCoord) @@ -218,8 +289,8 @@ PickData Renderer::Pick(glm::vec2 screenCoord) void Renderer::InitializeTextures() { - m_ErrorTexture = CommonFunctions::LoadTexture("Textures/Core/ErrorTexture.png", false); - m_WhiteTexture = CommonFunctions::LoadTexture("Textures/Core/White.png", false); + m_ErrorTexture = CommonFunctions::TryLoadResource("Textures/Core/ErrorTexture.png"); + m_WhiteTexture = CommonFunctions::TryLoadResource("Textures/Core/White.png"); } @@ -243,14 +314,18 @@ void Renderer::GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filterin GLERROR("Texture initialization failed"); } + void Renderer::InitializeRenderPasses() { m_PickingPass = new PickingPass(this, m_EventBroker); m_LightCullingPass = new LightCullingPass(this); m_CubeMapPass = new CubeMapPass(this); - m_DrawFinalPass = new DrawFinalPass(this, m_LightCullingPass, m_CubeMapPass); + m_SSAOPass = new SSAOPass(this, m_Config); + m_ShadowPass = new ShadowPass(this); + m_BlurHUDPass = new BlurHUD(this); + m_DrawFinalPass = new DrawFinalPass(this, m_LightCullingPass, m_CubeMapPass, m_SSAOPass, m_ShadowPass, m_Config); m_DrawScreenQuadPass = new DrawScreenQuadPass(this); - m_DrawBloomPass = new DrawBloomPass(this); + m_DrawBloomPass = new DrawBloomPass(this, m_Config); m_DrawColorCorrectionPass = new DrawColorCorrectionPass(this); - m_SSAOPass = new SSAOPass(this); -} + +} \ No newline at end of file diff --git a/src/Engine/Rendering/SSAOPass.cpp b/src/Engine/Rendering/SSAOPass.cpp index d4cdcb19..166bf924 100644 --- a/src/Engine/Rendering/SSAOPass.cpp +++ b/src/Engine/Rendering/SSAOPass.cpp @@ -1,84 +1,179 @@ #include "Rendering/SSAOPass.h" -SSAOPass::SSAOPass(IRenderer* renderer) +SSAOPass::SSAOPass(IRenderer* renderer, ConfigFile* config) + : m_Renderer(renderer) + , m_Config(config) { - m_Renderer = renderer; + m_WhiteTexture = CommonFunctions::TryLoadResource("Textures/Core/White.png"); + + ChangeQuality(m_Config->Get("SSAO.Quality", 0)); + +} + +SSAOPass::~SSAOPass() { + CommonFunctions::DeleteTexture(&m_SSAOTexture); + CommonFunctions::DeleteTexture(&m_SSAOViewSpaceZTexture); + CommonFunctions::DeleteTexture(&m_Gaussian_horiz); + CommonFunctions::DeleteTexture(&m_Gaussian_vert); +} + +void SSAOPass::ChangeQuality(int quality) +{ + if (m_Quality == quality) { + return; + } + + m_Quality = quality; + + if (m_Quality == 0) { + CommonFunctions::DeleteTexture(&m_SSAOTexture); + CommonFunctions::DeleteTexture(&m_SSAOViewSpaceZTexture); + CommonFunctions::DeleteTexture(&m_Gaussian_horiz); + CommonFunctions::DeleteTexture(&m_Gaussian_vert); + return; + } + + std::string qStr = std::to_string(m_Quality); + Setting( + m_Config->Get("SSAO" + qStr + ".Radius", 0.01), + m_Config->Get("SSAO" + qStr + ".Bias", 0.012), + m_Config->Get("SSAO" + qStr + ".Contrast", 1.0), + m_Config->Get("SSAO" + qStr + ".Intensity", 1.0), + m_Config->Get("SSAO" + qStr + ".NumSamples", 0), + m_Config->Get("SSAO" + qStr + ".NumTurns", 0), + m_Config->Get("SSAO" + qStr + ".NumIterations", 0), + m_Config->Get("SSAO" + qStr + ".TextureQuality", 4) + ); + + m_ScreenQuad = ResourceManager::Load("Models/Core/ScreenQuad.mesh"); InitializeTexture(); InitializeBuffer(); InitializeShaderProgram(); - Setting(0.1f, 0.012f, 1.0f, 1.0f, 13, 7); - m_DrawBloomPass = new DrawBloomPass(renderer); + } void SSAOPass::InitializeShaderProgram() { m_SSAOProgram = ResourceManager::Load("##SSAOProgram"); - m_SSAOProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/SSAO.vert.glsl"))); - m_SSAOProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/SSAO.frag.glsl"))); - m_SSAOProgram->Compile(); - m_SSAOProgram->Link(); + if (m_SSAOProgram->GetHandle() == 0) { + m_SSAOProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/SSAO.vert.glsl"))); + m_SSAOProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/SSAO.frag.glsl"))); + m_SSAOProgram->Compile(); + m_SSAOProgram->BindFragDataLocation(0, "AO"); + m_SSAOProgram->Link(); + } m_SSAOViewSpaceZProgram = ResourceManager::Load("##SSAOViewSpaceZProgram"); - m_SSAOViewSpaceZProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/SSAO.vert.glsl"))); - m_SSAOViewSpaceZProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/SSAOViewSpaceZ.frag.glsl"))); - m_SSAOViewSpaceZProgram->Compile(); - m_SSAOViewSpaceZProgram->Link(); + if (m_SSAOViewSpaceZProgram->GetHandle() == 0) { + m_SSAOViewSpaceZProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/SSAO.vert.glsl"))); + m_SSAOViewSpaceZProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/SSAOViewSpaceZ.frag.glsl"))); + m_SSAOViewSpaceZProgram->Compile(); + m_SSAOViewSpaceZProgram->BindFragDataLocation(0, "depthLinear"); + m_SSAOViewSpaceZProgram->Link(); + } + + m_GaussianProgram_horiz = ResourceManager::Load("##GaussianProgramHoriz"); + if (m_GaussianProgram_horiz->GetHandle() == 0) { + m_GaussianProgram_horiz->AddShader(std::shared_ptr(new VertexShader("Shaders/Gaussian_horiz.vert.glsl"))); + m_GaussianProgram_horiz->AddShader(std::shared_ptr(new FragmentShader("Shaders/Gaussian_horiz.frag.glsl"))); + m_GaussianProgram_horiz->Compile(); + m_GaussianProgram_horiz->BindFragDataLocation(0, "fragmentColor"); + m_GaussianProgram_horiz->Link(); + } + + m_GaussianProgram_vert = ResourceManager::Load("##GaussianProgramVert"); + if (m_GaussianProgram_vert->GetHandle() == 0) { + m_GaussianProgram_vert->AddShader(std::shared_ptr(new VertexShader("Shaders/Gaussian_vert.vert.glsl"))); + m_GaussianProgram_vert->AddShader(std::shared_ptr(new FragmentShader("Shaders/Gaussian_vert.frag.glsl"))); + m_GaussianProgram_vert->Compile(); + m_GaussianProgram_vert->BindFragDataLocation(0, "fragmentColor"); + m_GaussianProgram_vert->Link(); + } } void SSAOPass::InitializeTexture() { - GenerateTexture(&m_SSAOTexture, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_R8, GL_RED, GL_FLOAT); - GenerateTexture(&m_SSAOViewSpaceZTexture, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_R32F, GL_RED, GL_FLOAT); + CommonFunctions::GenerateTexture(&m_SSAOTexture, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewportSize().Width >> m_TextureQuality, m_Renderer->GetViewportSize().Height >> m_TextureQuality), GL_R8, GL_RED, GL_FLOAT); + CommonFunctions::GenerateTexture(&m_SSAOViewSpaceZTexture, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewportSize().Width >> m_TextureQuality, m_Renderer->GetViewportSize().Height >> m_TextureQuality), GL_R32F, GL_RED, GL_FLOAT); + + CommonFunctions::GenerateTexture(&m_Gaussian_horiz, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewportSize().Width >> m_TextureQuality, m_Renderer->GetViewportSize().Height >> m_TextureQuality), GL_R8, GL_RED, GL_FLOAT); + CommonFunctions::GenerateTexture(&m_Gaussian_vert, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewportSize().Width >> m_TextureQuality, m_Renderer->GetViewportSize().Height >> m_TextureQuality), GL_R8, GL_RED, GL_FLOAT); } void SSAOPass::InitializeBuffer() { - m_SSAOFramBuffer.AddResource(std::shared_ptr(new Texture2D(&m_SSAOTexture, GL_COLOR_ATTACHMENT0))); + if (m_SSAOFramBuffer.GetHandle() == 0) { + m_SSAOFramBuffer.AddResource(std::shared_ptr(new Texture2D(&m_SSAOTexture, GL_COLOR_ATTACHMENT0))); + } m_SSAOFramBuffer.Generate(); - m_SSAOViewSpaceZFramBuffer.AddResource(std::shared_ptr(new Texture2D(&m_SSAOViewSpaceZTexture, GL_COLOR_ATTACHMENT0))); + + if (m_SSAOViewSpaceZFramBuffer.GetHandle() == 0) { + m_SSAOViewSpaceZFramBuffer.AddResource(std::shared_ptr(new Texture2D(&m_SSAOViewSpaceZTexture, GL_COLOR_ATTACHMENT0))); + } m_SSAOViewSpaceZFramBuffer.Generate(); + + + + if (m_GaussianFrameBuffer_horiz.GetHandle() == 0) { + m_GaussianFrameBuffer_horiz.AddResource(std::shared_ptr(new Texture2D(&m_Gaussian_horiz, GL_COLOR_ATTACHMENT0))); + } + m_GaussianFrameBuffer_horiz.Generate(); + + + if (m_GaussianFrameBuffer_vert.GetHandle() == 0) { + m_GaussianFrameBuffer_vert.AddResource(std::shared_ptr(new Texture2D(&m_Gaussian_vert, GL_COLOR_ATTACHMENT0))); + } + m_GaussianFrameBuffer_vert.Generate(); + } void SSAOPass::ClearBuffer() { + if (m_Quality == 0) { + return; + } m_SSAOFramBuffer.Bind(); glClearColor(1.f, 1.f, 1.f, 1.f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glClear(GL_COLOR_BUFFER_BIT); m_SSAOFramBuffer.Unbind(); m_SSAOViewSpaceZFramBuffer.Bind(); glClearColor(1.f, 1.f, 1.f, 1.f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glClear(GL_COLOR_BUFFER_BIT); m_SSAOViewSpaceZFramBuffer.Unbind(); + + m_GaussianFrameBuffer_horiz.Bind(); + glClearColor(1.f, 1.f, 1.f, 1.f); + glClear(GL_COLOR_BUFFER_BIT); + m_GaussianFrameBuffer_horiz.Unbind(); + + m_GaussianFrameBuffer_vert.Bind(); + glClearColor(1.f, 1.f, 1.f, 1.f); + glClear(GL_COLOR_BUFFER_BIT); + m_GaussianFrameBuffer_vert.Unbind(); } -void SSAOPass::Setting(float radius, float bias, float contrast, float intensityScale, int numOfSamples, int NumOfTurns) { +void SSAOPass::Setting(float radius, float bias, float contrast, float intensityScale, int numOfSamples, int numOfTurns, int iterations, int quality) { m_Radius = radius; m_Bias = bias; m_Contrast = contrast; m_IntensityScale = intensityScale; m_NumOfSamples = numOfSamples; - m_NumOfTurns = NumOfTurns; -} - -void SSAOPass::GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type) const -{ - glGenTextures(1, texture); - glBindTexture(GL_TEXTURE_2D, *texture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapping); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapping); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering); - glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, dimensions.x, dimensions.y, 0, format, type, nullptr); - GLERROR("Texture initialization failed"); + m_NumOfTurns = numOfTurns; + m_Iterations = iterations; + m_TextureQuality = quality; } void SSAOPass::Draw(GLuint depthBuffer, Camera* camera) { + if (m_Quality == 0) { + return; + } + SSAOPassState state; GLuint viewSpaceZPShaderHandle = m_SSAOViewSpaceZProgram->GetHandle(); GLuint SSAOShaderHandle = m_SSAOProgram->GetHandle(); @@ -98,6 +193,7 @@ void SSAOPass::Draw(GLuint depthBuffer, Camera* camera) (-1.0f), (+1.0f) );*/ + glViewport(0, 0, (m_Renderer->GetViewportSize().Width >> m_TextureQuality), (m_Renderer->GetViewportSize().Height >> m_TextureQuality)); //JOHAN TODO: Get this into state glUniform3fv(glGetUniformLocation(viewSpaceZPShaderHandle, "ClipInfo"), 1, glm::value_ptr(clipInfo)); glBindVertexArray(m_ScreenQuad->VAO); @@ -107,9 +203,9 @@ void SSAOPass::Draw(GLuint depthBuffer, Camera* camera) glm::vec4 projInfo = glm::vec4( ((1.0 - camera->ProjectionMatrix()[0][2]) / camera->ProjectionMatrix()[0][0]), - (-2.0 / (m_Renderer->GetViewportSize().Width * camera->ProjectionMatrix()[0][0])), + (-2.0 / ((m_Renderer->GetViewportSize().Width >> m_TextureQuality) * camera->ProjectionMatrix()[0][0])), ((1.0 + camera->ProjectionMatrix()[1][2]) / camera->ProjectionMatrix()[1][1]), - (-2.0 / (m_Renderer->GetViewportSize().Height * camera->ProjectionMatrix()[1][1])) + (-2.0 / ((m_Renderer->GetViewportSize().Height >> m_TextureQuality) * camera->ProjectionMatrix()[1][1])) ); @@ -120,26 +216,84 @@ void SSAOPass::Draw(GLuint depthBuffer, Camera* camera) glBindTexture(GL_TEXTURE_2D, m_SSAOViewSpaceZTexture); // How many pixel there are in a 1m long object 1m away from the camera - glUniform1f(glGetUniformLocation(SSAOShaderHandle, "uProjScale"), m_Renderer->GetViewportSize().Height / (-2.0f * glm::tan(camera->FOV() * 0.5f))); + glUniform1f(glGetUniformLocation(SSAOShaderHandle, "uProjScale"), (m_Renderer->GetViewportSize().Height >> m_TextureQuality) / (-2.0f * glm::tan(camera->FOV() * 0.5f))); glUniform1f(glGetUniformLocation(SSAOShaderHandle, "uRadius"), m_Radius); glUniform1f(glGetUniformLocation(SSAOShaderHandle, "uBias"), m_Bias); glUniform1f(glGetUniformLocation(SSAOShaderHandle, "uContrast"), m_Contrast); glUniform1f(glGetUniformLocation(SSAOShaderHandle, "uIntensityScale"), m_IntensityScale); glUniform1i(glGetUniformLocation(SSAOShaderHandle, "uNumOfSamples"), m_NumOfSamples); - glUniform1i(glGetUniformLocation(SSAOShaderHandle, "uNumOfTurns"), m_NumOfTurns);; + glUniform1i(glGetUniformLocation(SSAOShaderHandle, "uNumOfTurns"), m_NumOfTurns); glUniform4fv(glGetUniformLocation(SSAOShaderHandle, "uProjInfo"), 1, glm::value_ptr(projInfo)); 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_DrawBloomPass->ClearBuffer(); - m_DrawBloomPass->Draw(m_SSAOTexture); + DrawBloomPassState BloomState; + GLuint shaderHandle_horiz = m_GaussianProgram_horiz->GetHandle(); + GLuint shaderHandle_vert = m_GaussianProgram_vert->GetHandle(); + + m_GaussianProgram_vert->Bind(); + glUniform1i(glGetUniformLocation(shaderHandle_vert, "Lod"), 0); + m_GaussianProgram_horiz->Bind(); + glUniform1i(glGetUniformLocation(shaderHandle_horiz, "Lod"), 0); + + m_GaussianFrameBuffer_horiz.Bind(); + m_GaussianProgram_horiz->Bind(); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, m_SSAOTexture); + + 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); + //Iterate some times to make it more gaussian. + for (int i = 1; i < m_Iterations; i++) { + //Vertical pass + m_GaussianFrameBuffer_vert.Bind(); + m_GaussianProgram_vert->Bind(); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, m_Gaussian_horiz); + + 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 + m_GaussianFrameBuffer_vert.Unbind(); + + m_GaussianFrameBuffer_horiz.Bind(); + m_GaussianProgram_horiz->Bind(); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, m_Gaussian_vert); + + 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(); + } + + //final vertical gaussian after the iterations are done + + m_GaussianFrameBuffer_vert.Bind(); + m_GaussianProgram_vert->Bind(); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, m_Gaussian_horiz); + + 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_vert.Unbind(); + + glViewport(0, 0, (m_Renderer->GetViewportSize().Width), (m_Renderer->GetViewportSize().Height)); } void SSAOPass::OnWindowResize() { - m_DrawBloomPass->OnWindowResize(); + if (m_Quality == 0) { + return; + } + InitializeTexture(); - m_SSAOFramBuffer.Generate(); - m_SSAOViewSpaceZFramBuffer.Generate(); + InitializeBuffer(); } \ No newline at end of file diff --git a/src/Engine/Rendering/ShaderProgram.cpp b/src/Engine/Rendering/ShaderProgram.cpp index ae536bc0..d2a45888 100644 --- a/src/Engine/Rendering/ShaderProgram.cpp +++ b/src/Engine/Rendering/ShaderProgram.cpp @@ -4,22 +4,32 @@ GLuint Shader::CompileShader(GLenum shaderType, std::string fileName) { LOG_INFO("Compiling shader \"%s\"", fileName.c_str()); - std::string shaderFile; - std::ifstream in(fileName, std::ios::in); - if (!in) { - LOG_ERROR("Error: Failed to open shader file \"%s\"", fileName.c_str()); - return 0; - } - in.seekg(0, std::ios::end); - shaderFile.resize((int)in.tellg()); - in.seekg(0, std::ios::beg); - in.read(&shaderFile[0], shaderFile.size()); - in.close(); + std::string shaderFile = ReadFile(fileName); GLuint shader = glCreateShader(shaderType); if (GLERROR("glCreateShader")) return 0; + std::size_t startPos = 0; + std::size_t SEofNewFile[2]; + std::string key = "#include"; + while((startPos = shaderFile.find(key, startPos)) != std::string::npos) + { + SEofNewFile[0] = shaderFile.find('"', startPos+key.length())+1; + SEofNewFile[1] = shaderFile.find('"', SEofNewFile[0]); + if (SEofNewFile[0] == std::string::npos || SEofNewFile[1] == std::string::npos) + return 0; + + std::string replacementFileName = shaderFile.substr(SEofNewFile[0], SEofNewFile[1] - SEofNewFile[0]); + std::string replacementString = ReadFile(replacementFileName); + size_t firstof = replacementString.find_first_of((char)0); + replacementString.erase(firstof, replacementString.size() - firstof); + if (replacementString.length() <= 0) + return 0; + shaderFile.replace(startPos, SEofNewFile[1]+2 - startPos, replacementString + "\n"); + startPos += replacementString.length(); //This might not be wanted. + } + const GLchar* shaderFiles = shaderFile.c_str(); const GLint length = static_cast(shaderFile.length()); glShaderSource(shader, 1, &shaderFiles, &length); @@ -46,6 +56,24 @@ GLuint Shader::CompileShader(GLenum shaderType, std::string fileName) return shader; } +std::string Shader::ReadFile(std::string fileName) +{ + std::string shaderFile; + std::ifstream in(fileName, std::ios::in); + if (!in) { + LOG_ERROR("Error: Failed to open shader file \"%s\"", fileName.c_str()); + return ""; + } + + in.seekg(0, std::ios::end); + shaderFile.resize((int)in.tellg()); + in.seekg(0, std::ios::beg); + in.read(&shaderFile[0], shaderFile.size()); + in.close(); + return shaderFile; +} + + Shader::Shader(GLenum shaderType, std::string fileName) : m_ShaderType(shaderType), m_FileName(fileName) { m_ShaderHandle = 0; diff --git a/src/Engine/Rendering/ShadowPass.cpp b/src/Engine/Rendering/ShadowPass.cpp new file mode 100644 index 00000000..05430708 --- /dev/null +++ b/src/Engine/Rendering/ShadowPass.cpp @@ -0,0 +1,365 @@ +#include "Rendering/ShadowPass.h" + +ShadowPass::ShadowPass(IRenderer * renderer, int shadow_res_x, int shadow_res_y) +{ + m_Renderer = renderer; + m_ResolutionSizeWidth = shadow_res_x; + m_ResolutionSizeHeight = shadow_res_y; + + InitializeFrameBuffers(); + InitializeShaderPrograms(); +} + +ShadowPass::ShadowPass(IRenderer * renderer) +{ + m_Renderer = renderer; + + InitializeFrameBuffers(); + InitializeShaderPrograms(); +} + +ShadowPass::~ShadowPass() +{ + +} + +void ShadowPass::DebugGUI() +{ +#ifdef DEBUG + ImGui::Checkbox("EnableShadows", &m_EnableShadows); + ImGui::DragFloat2("ShadowMapNearFar", m_NearFarPlane, 1.f, -1000.f, 1000.f); + ImGui::DragFloat("ShadowClippingWeight", &m_SplitWeight, 0.001f, 0.f, 1.f); + ImGui::Checkbox("ShadowTransparentObjects", &m_TransparentObjects); + ImGui::Checkbox("ShadowOnTextureAlphas", &m_TexturedShadows); +#endif +} + +void ShadowPass::InitializeCameras(RenderScene & scene) +{ + for (int i = 0; i < m_CurrentNrOfSplits; i++) { + m_shadowFrusta[i].AspectRatio = scene.Camera->AspectRatio(); + m_shadowFrusta[i].FOV = scene.Camera->FOV(); + } +} + +// UpdateSplitDist computes the near and far distances for every frustum slice +// in camera eye space - that is, at what distance does a slice start and end +void ShadowPass::UpdateSplitDist(std::array& frusta, float near_distance, float far_distance) +{ + float lambda = m_SplitWeight; + float ratio = far_distance / near_distance; + + frusta[0].NearClip = near_distance; + + for (int i = 1; i < m_CurrentNrOfSplits; i++) { + float si = i / static_cast(m_CurrentNrOfSplits); + + frusta[i].NearClip = lambda * (near_distance * powf(ratio, si)) + (1 - lambda) * (near_distance + (far_distance - near_distance) * si); + frusta[i - 1].FarClip = frusta[i].NearClip * 1.005f; + } + + frusta[m_CurrentNrOfSplits - 1].FarClip = far_distance; +} + +void ShadowPass::UpdateFrustumPoints(ShadowFrustum& frustum, glm::mat4 p, glm::mat4 v) +{ + std::array CornerPoint = { + glm::vec4(-1.f, -1.f, -1.f, 1.f), + glm::vec4(-1.f, 1.f, -1.f, 1.f), + glm::vec4(1.f, 1.f, -1.f, 1.f), + glm::vec4(1.f, -1.f, -1.f, 1.f), + glm::vec4(-1.f, -1.f, 1.f, 1.f), + glm::vec4(-1.f, 1.f, 1.f, 1.f), + glm::vec4(1.f, 1.f, 1.f, 1.f), + glm::vec4(1.f, -1.f, 1.f, 1.f) + }; + + for (int i = 0; i < 8; i++) { + glm::vec4 NDC = glm::inverse(p) * CornerPoint[i]; + NDC = NDC / NDC.w; + frustum.CornerPoint[i] = glm::vec3(glm::inverse(v) * NDC); + } +} + +// Compute the 8 corner points of the current view frustum in world space +void ShadowPass::UpdateFrustumPoints(ShadowFrustum& frustum, glm::vec3 camera_position, glm::vec3 view_dir) +{ + glm::vec3 up = glm::vec3(0.f, 1.f, 0.f); + glm::vec3 right = glm::normalize(glm::cross(view_dir, up)); + + glm::vec3 far_center = camera_position + glm::normalize(view_dir) * frustum.FarClip; + glm::vec3 near_center = camera_position + glm::normalize(view_dir) * frustum.NearClip; + frustum.MiddlePoint = near_center + (far_center - near_center) * 0.5f; + + up = glm::normalize(glm::cross(right, view_dir)); + + // these heights and widths are half the heights and widths of the near and far plane rectangles. + float near_height = tan(frustum.FOV / 2.f) * frustum.NearClip; + float near_width = near_height * frustum.AspectRatio; + float far_height = tan(frustum.FOV / 2.f) * frustum.FarClip; + float far_width = far_height * frustum.AspectRatio; + + frustum.CornerPoint[0] = near_center - up * near_height - right * near_width; + frustum.CornerPoint[1] = near_center + up * near_height - right * near_width; + frustum.CornerPoint[2] = near_center + up * near_height + right * near_width; + frustum.CornerPoint[3] = near_center - up * near_height + right * near_width; + + frustum.CornerPoint[4] = far_center - up * far_height - right * far_width; + frustum.CornerPoint[5] = far_center + up * far_height - right * far_width; + frustum.CornerPoint[6] = far_center + up * far_height + right * far_width; + frustum.CornerPoint[7] = far_center - up * far_height + right * far_width; +} + +float ShadowPass::FindRadius(ShadowFrustum& frustum) +{ + float radius = 0.f; + + for (int i = 0; i < 8; i++) { + float distance = glm::distance(frustum.MiddlePoint, frustum.CornerPoint[i]); + if (distance > radius) { + radius = distance; + } + } + + frustum.Radius = radius; + return radius; +} + +void ShadowPass::InitializeFrameBuffers() +{ + // Depth texture + glGenTextures(1, &m_DepthMap); + + glBindTexture(GL_TEXTURE_2D_ARRAY, m_DepthMap); + glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_DEPTH_COMPONENT16, m_ResolutionSizeWidth, m_ResolutionSizeHeight, m_CurrentNrOfSplits); + + //glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, m_ResolutionSizeWidth, m_ResolutionSizeHeight, m_CurrentNrOfSplits, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr); + + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE); + glTexParameterfv(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BORDER_COLOR, glm::vec4(1.f).data); + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL); + + m_DepthBuffer.AddResource(std::shared_ptr(new Texture2DArray(&m_DepthMap, GL_DEPTH_ATTACHMENT))); + m_DepthBuffer.Generate(); + + GLERROR("depthMap failed END"); +} + +void ShadowPass::InitializeShaderPrograms() +{ + m_ShadowProgram = ResourceManager::Load("#ShadowProgram"); + m_ShadowProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/Shadow.vert.glsl"))); + m_ShadowProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/Shadow.frag.glsl"))); + m_ShadowProgram->Compile(); + m_ShadowProgram->BindFragDataLocation(0, "ShadowMap"); + m_ShadowProgram->Link(); + + m_ShadowProgramSkinned = ResourceManager::Load("#ShadowProgramSkinned"); + m_ShadowProgramSkinned->AddShader(std::shared_ptr(new VertexShader("Shaders/ShadowSkinned.vert.glsl"))); + m_ShadowProgramSkinned->AddShader(std::shared_ptr(new FragmentShader("Shaders/Shadow.frag.glsl"))); + m_ShadowProgramSkinned->Compile(); + m_ShadowProgramSkinned->BindFragDataLocation(0, "ShadowMap"); + m_ShadowProgramSkinned->Link(); +} + +void ShadowPass::ClearBuffer() +{ + m_DepthBuffer.Bind(); + + for (int i = 0; i < m_CurrentNrOfSplits; i++) { + glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, m_DepthMap, 0, i); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + } + + m_DepthBuffer.Unbind(); +} + +void ShadowPass::PointsToLightspace(ShadowFrustum& frustum, glm::mat4 v) +{ + float left = INFINITY; + float right = -INFINITY; + float bottom = INFINITY; + float top = -INFINITY; + + for (int i = 0; i < 8; i++) + { + glm::vec3 tempPoint = glm::vec3(v * glm::vec4(frustum.CornerPoint[i], 1.f)); + + if (tempPoint.x < left) { left = tempPoint.x; } + if (tempPoint.x > right) { right = tempPoint.x; } + if (tempPoint.y < bottom) { bottom = tempPoint.y; } + if (tempPoint.y > top) { top = tempPoint.y; } + } + + frustum.LRBT = { left, right, bottom, top }; +} + +void ShadowPass::RadiusToLightspace(ShadowFrustum& frustum) +{ + float quantizationStep = 1.0f / m_ResolutionSizeHeight; + + float left = -frustum.Radius; + float right = frustum.Radius; + float bottom = -frustum.Radius; + float top = frustum.Radius; + + frustum.LRBT = { left, right, bottom, top }; +} + +void ShadowPass::Draw(RenderScene & scene) +{ + if (m_EnableShadows) { + InitializeCameras(scene); + UpdateSplitDist(m_shadowFrusta, scene.Camera->NearClip(), scene.Camera->FarClip()); + + ShadowPassState* state = new ShadowPassState(m_DepthBuffer.GetHandle()); + + + glViewport(0, 0, m_ResolutionSizeWidth, m_ResolutionSizeHeight); + + for (int i = 0; i < m_CurrentNrOfSplits; i++) { + UpdateFrustumPoints(m_shadowFrusta[i], scene.Camera->Position(), scene.Camera->Forward()); + + glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, m_DepthMap, 0, i); + + + GLuint shaderHandle = 0; + GLuint lastModel = 0; + for (auto &job : scene.Jobs.DirectionalLight) { + + auto directionalLightJob = std::dynamic_pointer_cast(job); + + if (directionalLightJob) { + m_LightView[i] = glm::lookAt(glm::vec3(-directionalLightJob->Direction) + m_shadowFrusta[i].MiddlePoint, m_shadowFrusta[i].MiddlePoint, glm::vec3(0.f, 1.f, 0.f)); + + PointsToLightspace(m_shadowFrusta[i], m_LightView[i]); + //FindRadius(m_shadowFrusta[i]); + //RadiusToLightspace(m_shadowFrusta[i]); + m_LightProjection[i] = glm::ortho(m_shadowFrusta[i].LRBT[LEFT], m_shadowFrusta[i].LRBT[RIGHT], m_shadowFrusta[i].LRBT[BOTTOM], m_shadowFrusta[i].LRBT[TOP], m_NearFarPlane[NEAR], m_NearFarPlane[FAR]); + + GLERROR("ShadowLight ERROR"); + + for (auto &objectJob : scene.Jobs.OpaqueObjects) { + if (!std::dynamic_pointer_cast(objectJob)) { + auto modelJob = std::dynamic_pointer_cast(objectJob); + + if (!modelJob->Shadow) { + continue; + } + + if(modelJob->Model->IsSkinned()) { + if (shaderHandle != m_ShadowProgramSkinned->GetHandle()) { + m_ShadowProgramSkinned->Bind(); + shaderHandle = m_ShadowProgramSkinned->GetHandle(); + } + + std::vector frameBones; + if (modelJob->BlendTree != nullptr) { + frameBones = modelJob->BlendTree->GetFinalPose(); + } else if (modelJob->Skeleton != nullptr) { + frameBones = modelJob->Skeleton->GetTPose(); + } + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); + + } else { + if (shaderHandle != m_ShadowProgram->GetHandle()) { + m_ShadowProgram->Bind(); + shaderHandle = m_ShadowProgram->GetHandle(); + } + } + + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "PVM"), 1, GL_FALSE, glm::value_ptr(m_LightProjection[i] * m_LightView[i] * modelJob->Matrix)); + glUniform1f(glGetUniformLocation(shaderHandle, "Alpha"), 1.f); + + if (lastModel != modelJob->ModelID) { + glBindVertexArray(modelJob->Model->VAO); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, modelJob->Model->ElementBuffer); + } + glDrawElements(GL_TRIANGLES, modelJob->EndIndex - modelJob->StartIndex + 1, GL_UNSIGNED_INT, (void*)(modelJob->StartIndex * sizeof(unsigned int))); + + GLERROR("Shadow Draw ERROR"); + } + } + if (m_TransparentObjects) { + state->CullFace(GL_BACK); + for (auto &objectJob : scene.Jobs.TransparentObjects) { + if (!std::dynamic_pointer_cast(objectJob)) { + auto modelJob = std::dynamic_pointer_cast(objectJob); + + if (!modelJob->Shadow) { + continue; + } + + if (modelJob->Model->IsSkinned()) { + if (shaderHandle != m_ShadowProgramSkinned->GetHandle()) { + m_ShadowProgramSkinned->Bind(); + shaderHandle = m_ShadowProgramSkinned->GetHandle(); + } + + std::vector frameBones; + if (modelJob->BlendTree != nullptr) { + frameBones = modelJob->BlendTree->GetFinalPose(); + } else { + frameBones = modelJob->Skeleton->GetTPose(); + } + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); + + } else { + if (shaderHandle != m_ShadowProgram->GetHandle()) { + m_ShadowProgram->Bind(); + shaderHandle = m_ShadowProgram->GetHandle(); + } + } + + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "PVM"), 1, GL_FALSE, glm::value_ptr(m_LightProjection[i] * m_LightView[i] * modelJob->Matrix)); + glUniform1f(glGetUniformLocation(shaderHandle, "Alpha"), modelJob->Color.a); + + if (m_TexturedShadows) { + switch (modelJob->Type) { + case RawModel::MaterialType::SingleTextures: + case RawModel::MaterialType::Basic: + { + glActiveTexture(GL_TEXTURE24); + if (modelJob->DiffuseTexture.size() > 0 && modelJob->DiffuseTexture[0]->Texture != nullptr) { + glBindTexture(GL_TEXTURE_2D, modelJob->DiffuseTexture[0]->Texture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, "DiffuseUVRepeat"), 1, glm::value_ptr(modelJob->DiffuseTexture[0]->UVRepeat)); + } + else { + glBindTexture(GL_TEXTURE_2D, m_WhiteTexture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, "DiffuseUVRepeat"), 1, glm::value_ptr(glm::vec2(1.0f, 1.0f))); + } + break; + } + case RawModel::MaterialType::SplatMapping: + { + glActiveTexture(GL_TEXTURE24); + glBindTexture(GL_TEXTURE_2D, m_WhiteTexture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, "DiffuseUVRepeat"), 1, glm::value_ptr(glm::vec2(1.0f, 1.0f))); + break; + } + } + } + if (lastModel != modelJob->ModelID) { + glBindVertexArray(modelJob->Model->VAO); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, modelJob->Model->ElementBuffer); + } + glDrawElements(GL_TRIANGLES, modelJob->EndIndex - modelJob->StartIndex + 1, GL_UNSIGNED_INT, (void*)(modelJob->StartIndex * sizeof(unsigned int))); + + GLERROR("Shadow Draw ERROR"); + } + } + state->CullFace(GL_FRONT); + } + } + } + } + glViewport(0, 0, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); + m_DepthBuffer.Unbind(); + delete state; + } +} \ No newline at end of file diff --git a/src/Engine/Rendering/ShadowPassState.cpp b/src/Engine/Rendering/ShadowPassState.cpp new file mode 100644 index 00000000..2211e3ab --- /dev/null +++ b/src/Engine/Rendering/ShadowPassState.cpp @@ -0,0 +1,19 @@ +#include "Rendering/ShadowPassState.h" + +ShadowPassState::ShadowPassState(GLuint frameBuffer) +{ + BindFramebuffer(frameBuffer); + Enable(GL_DEPTH_TEST); + Enable(GL_CULL_FACE); + Disable(GL_BLEND); + Disable(GL_TEXTURE_2D); + CullFace(GL_FRONT); + ClearColor(glm::vec4(0.f, 0.f, 0.f, 0.f)); + //Enable(GL_ALPHA_TEST); + //glAlphaFunc(GL_GREATER, 0.9f); +} + +ShadowPassState::~ShadowPassState() +{ + +} \ No newline at end of file diff --git a/src/Engine/Rendering/Skeleton.cpp b/src/Engine/Rendering/Skeleton.cpp index 2957b1b6..eb6a130d 100644 --- a/src/Engine/Rendering/Skeleton.cpp +++ b/src/Engine/Rendering/Skeleton.cpp @@ -1,372 +1,149 @@ #include "Rendering/Skeleton.h" -int Skeleton::CreateBone(int ID, int parentID, std::string name, glm::mat4 offsetMatrix) +std::map Skeleton::GetFrameBones(const Animation* animation, double time, bool additive, bool noRootMotion /*= false*/) { - if (m_BonesByName.find(name) != m_BonesByName.end()) { - return m_BonesByName.at(name)->ID; - } else { - Bone* bone; - - if (parentID == -1) { - bone = new Bone(ID, nullptr, name, offsetMatrix); - RootBone = bone; - } else { - Bone* parent = Bones[parentID]; - bone = new Bone(ID, parent, name, offsetMatrix); - parent->Children.push_back(bone); - } - - Bones[ID] = bone; - m_BonesByName[name] = bone; - return ID; - } -} - -Skeleton::~Skeleton() -{ - for (auto &kv : Bones) { - delete kv.second; - } -} - - - -const Skeleton::Animation* Skeleton::GetAnimation(std::string name) -{ - auto it = Animations.find(name); - if (it != Animations.end()) { - return const_cast(&it->second); - } else { - return nullptr; - } -} - -std::vector Skeleton::GetFrameBones(std::vector animations, bool noRootMotion /*= false*/) -{ - if (animations.size() <= 0) { - std::vector finalMatrices; + if (animation == nullptr) { + std::map finalMatrices; for (auto& b : Bones) { - finalMatrices.push_back(glm::mat4(1));//b.second->OffsetMatrix); + PoseData poseData; + poseData.Translation = glm::vec3(0); + poseData.Orientation = glm::quat(); + poseData.Scale = glm::vec3(1); + + + finalMatrices[b.second->ID] = poseData; } return finalMatrices; } - std::map frameBones; - AccumulateBoneTransforms(true, animations, frameBones, RootBone, glm::mat4(1)); - std::vector finalMatrices; - for (auto &kv : frameBones) { - finalMatrices.push_back(kv.second); + std::map frameBones; + + if(!additive) { + AccumulateBoneTransforms(true, animation, time, frameBones, RootBone); + } else { + AdditiveBoneTransforms(animation, time, frameBones, RootBone); } - return finalMatrices; + + return frameBones; } -std::vector Skeleton::GetFrameBones(std::vector animations, AnimationOffset animationOffset, bool noRootMotion /*= false*/) +void Skeleton::AccumulateBoneTransforms(bool noRootMotion, const Animation* animation, double time, std::map& boneMatrices, const Bone* bone) { - if (animations.size() <= 0 || animationOffset.animation == nullptr) { - std::vector finalMatrices; - for (auto& b : Bones) { - finalMatrices.push_back(glm::mat4(1));//b.second->OffsetMatrix); - } - return finalMatrices; - } - + PoseData poseData; - std::map frameBones; - AccumulateBoneTransforms(true, animations, animationOffset, frameBones, RootBone, glm::mat4(1)); - - std::vector finalMatrices; - for (auto &kv : frameBones) { - finalMatrices.push_back(kv.second); - } - return finalMatrices; -} - -void Skeleton::AccumulateBoneTransforms(bool noRootMotion, std::vector animations, std::map& boneMatrices, const Bone* bone, glm::mat4 parentMatrix) -{ - glm::mat4 boneMatrix; - std::vector JointTransforms; - - for (const AnimationData animationData : animations) { - const Animation* animation = animationData.animation; - const float time = animationData.time; - - JointFrameTransform jointTransform; - jointTransform.Weight = animationData.weight;; - - if (animation->JointAnimations.find(bone->ID) != animation->JointAnimations.end()) { - std::vector boneKeyFrames = animation->JointAnimations.at(bone->ID); - - Animation::Keyframe currentFrame; - Animation::Keyframe nextFrame; - - if (boneKeyFrames.size() > 1) { // 2+ keyframes for the current bone - for (int index = boneKeyFrames.size()-1; index >= 0; index--) { // find the bone keyframes that surrounds the current frame - if (time >= boneKeyFrames.at(index).Time) { - currentFrame = boneKeyFrames.at(index); - nextFrame = boneKeyFrames.at((index + 1) % boneKeyFrames.size()); - break; - } - } - - float progress; - - if (nextFrame.Index == 0) { - nextFrame = currentFrame; - progress = (time - currentFrame.Time) / (animation->Duration - currentFrame.Time); - } else { - progress = (time - currentFrame.Time) / (nextFrame.Time - currentFrame.Time); - - } - - - if (progress > 1.0f || progress < 0.0f) { - progress = glm::clamp(progress, 0.0f, 1.0f); - } - Animation::Keyframe::BoneProperty currentBoneProperty = currentFrame.BoneProperties; - Animation::Keyframe::BoneProperty nextBoneProperty = nextFrame.BoneProperties; - - jointTransform.PositionInterp = currentBoneProperty.Position * (1.f - progress) + nextBoneProperty.Position * progress; - jointTransform.RotationInterp = glm::slerp(currentBoneProperty.Rotation, nextBoneProperty.Rotation, progress); - jointTransform.ScaleInterp = currentBoneProperty.Scale * (1.f - progress) + nextBoneProperty.Scale * progress; - - // Flag for no root motion - if (bone == RootBone && noRootMotion) { - jointTransform.PositionInterp.x = 0; - jointTransform.PositionInterp.z = 0; - } - - JointTransforms.push_back(jointTransform); - - } else { // 1 keyframes for the current bone - currentFrame = boneKeyFrames.at(0); - jointTransform.PositionInterp = currentFrame.BoneProperties.Position; - jointTransform.RotationInterp = currentFrame.BoneProperties.Rotation; - jointTransform.ScaleInterp = currentFrame.BoneProperties.Scale; - JointTransforms.push_back(jointTransform); - - } - } else { // 0 keyframes for the current bone - - } - - } - - if (JointTransforms.size() <= 0) { - if (bone->Parent) { - boneMatrix = parentMatrix * glm::inverse(bone->OffsetMatrix) * bone->Parent->OffsetMatrix; - boneMatrices[bone->ID] = boneMatrix * bone->OffsetMatrix; - } else { - boneMatrix = glm::inverse(bone->OffsetMatrix); - boneMatrices[bone->ID] = parentMatrix; - } - } else if (JointTransforms.size() == 1) { - boneMatrix = parentMatrix *(glm::translate(JointTransforms.at(0).PositionInterp) * glm::toMat4(JointTransforms.at(0).RotationInterp) * glm::scale(JointTransforms.at(0).ScaleInterp)); - boneMatrices[bone->ID] = boneMatrix * bone->OffsetMatrix; - } else { - - glm::vec3 finalPosInterp; - glm::quat finalRotInterp; - glm::vec3 finalScaleInterp; - float totalWeight = 0; - - for (JointFrameTransform jointTransform : JointTransforms) { - totalWeight += jointTransform.Weight; - } - - - for (JointFrameTransform jointTransform : JointTransforms) { - if (jointTransform.Weight == 1.0f) { - finalPosInterp = jointTransform.PositionInterp; - finalRotInterp = jointTransform.RotationInterp; - finalScaleInterp = jointTransform.ScaleInterp; - break; - } else { - finalPosInterp += jointTransform.PositionInterp * (jointTransform.Weight/totalWeight); - finalRotInterp *= glm::slerp(glm::quat(), jointTransform.RotationInterp, (jointTransform.Weight/totalWeight)); - finalScaleInterp += jointTransform.ScaleInterp * (jointTransform.Weight/totalWeight); - } - - } - - boneMatrix = parentMatrix *(glm::translate(finalPosInterp) * glm::toMat4(finalRotInterp) * glm::scale(finalScaleInterp)); - boneMatrices[bone->ID] = boneMatrix * bone->OffsetMatrix; - } - - - - for (auto &child : bone->Children) { - AccumulateBoneTransforms(noRootMotion, animations, boneMatrices, child, boneMatrix); - } -} - -void Skeleton::AccumulateBoneTransforms(bool noRootMotion, std::vector animations, AnimationOffset animationOffset, std::map& boneMatrices, const Bone* bone, glm::mat4 parentMatrix) -{ - glm::mat4 boneMatrix; - - std::vector JointTransforms; - - for (const AnimationData animationData : animations) { - const Animation* animation = animationData.animation; - const float time = animationData.time; - - JointFrameTransform jointTransform; - jointTransform.Weight = animationData.weight;; - - if (animation->JointAnimations.find(bone->ID) != animation->JointAnimations.end()) { - std::vector boneKeyFrames = animation->JointAnimations.at(bone->ID); - - Animation::Keyframe currentFrame; - Animation::Keyframe nextFrame; - - if (boneKeyFrames.size() > 1) { // 2+ keyframes for the current bone - for (int index = boneKeyFrames.size()-1; index >= 0; index--) { // find the bone keyframes that surrounds the current frame - if (time >= boneKeyFrames.at(index).Time) { - currentFrame = boneKeyFrames.at(index); - nextFrame = boneKeyFrames.at((index + 1) % boneKeyFrames.size()); - break; - } - } - - float progress; - - if (nextFrame.Index == 0) { - nextFrame = currentFrame; - progress = (time - currentFrame.Time) / (animation->Duration - currentFrame.Time); - } else { - progress = (time - currentFrame.Time) / (nextFrame.Time - currentFrame.Time); - - } - - - if (progress > 1.0f || progress < 0.0f) { - progress = glm::clamp(progress, 0.0f, 1.0f); - } - Animation::Keyframe::BoneProperty currentBoneProperty = currentFrame.BoneProperties; - Animation::Keyframe::BoneProperty nextBoneProperty = nextFrame.BoneProperties; - - jointTransform.PositionInterp = currentBoneProperty.Position * (1.f - progress) + nextBoneProperty.Position * progress; - jointTransform.RotationInterp = glm::slerp(currentBoneProperty.Rotation, nextBoneProperty.Rotation, progress); - jointTransform.ScaleInterp = currentBoneProperty.Scale * (1.f - progress) + nextBoneProperty.Scale * progress; - - // Flag for no root motion - if (bone == RootBone && noRootMotion) { - jointTransform.PositionInterp.x = 0; - jointTransform.PositionInterp.z = 0; - } - - JointTransforms.push_back(jointTransform); - - } else { // 1 keyframes for the current bone - currentFrame = boneKeyFrames.at(0); - jointTransform.PositionInterp = currentFrame.BoneProperties.Position; - jointTransform.RotationInterp = currentFrame.BoneProperties.Rotation; - jointTransform.ScaleInterp = currentFrame.BoneProperties.Scale; - JointTransforms.push_back(jointTransform); - - } - } else { // 0 keyframes for the current bone - - } - - } - - - glm::mat4 offset = GetOffsetTransform(bone, animationOffset); - - if (JointTransforms.size() == 0) { - if (bone->Parent) { - if (offset != glm::mat4(1)) { - boneMatrix = parentMatrix * offset;// *((glm::inverse(bone->OffsetMatrix) * bone->Parent->OffsetMatrix)); - } else { - boneMatrix = parentMatrix *((glm::inverse(bone->OffsetMatrix) * bone->Parent->OffsetMatrix)); - - } - boneMatrices[bone->ID] = boneMatrix * bone->OffsetMatrix; - } else { - boneMatrix = offset * glm::inverse(bone->OffsetMatrix); - boneMatrices[bone->ID] = parentMatrix; - } - } else { - - glm::vec3 finalPosInterp; - glm::quat finalRotInterp; - glm::vec3 finalScaleInterp; - float totalWeight = 0; - - for (JointFrameTransform jointTransform : JointTransforms) { - totalWeight += jointTransform.Weight; - } - - - for (JointFrameTransform jointTransform : JointTransforms) { - if (jointTransform.Weight == 1.0f) { - finalPosInterp = jointTransform.PositionInterp; - finalRotInterp = jointTransform.RotationInterp; - finalScaleInterp = jointTransform.ScaleInterp; - break; - } else { - finalPosInterp += jointTransform.PositionInterp * (jointTransform.Weight/totalWeight); - finalRotInterp *= glm::slerp(glm::quat(), jointTransform.RotationInterp, (jointTransform.Weight/totalWeight)); - finalScaleInterp += jointTransform.ScaleInterp * (jointTransform.Weight/totalWeight); - } - - } - - - - if (offset != glm::mat4(1)) { - boneMatrix = parentMatrix * ((glm::translate(finalPosInterp) * glm::toMat4(finalRotInterp) * glm::scale(finalScaleInterp)) + offset); - } else { - boneMatrix = parentMatrix * (glm::translate(finalPosInterp) * glm::toMat4(finalRotInterp) * glm::scale(finalScaleInterp)); - } - - boneMatrices[bone->ID] = boneMatrix * bone->OffsetMatrix; - } - - for (auto &child : bone->Children) { - AccumulateBoneTransforms(noRootMotion, animations, animationOffset, boneMatrices, child, boneMatrix); - } -} - -glm::mat4 Skeleton::GetOffsetTransform(const Bone* bone, AnimationOffset animationOffset) -{ - const Animation* animation = animationOffset.animation; - float time = animationOffset.time; - - glm::vec3 position = glm::vec3(0); - glm::quat rotation = glm::quat(); - glm::vec3 scale = glm::vec3(1); - if (animation->JointAnimations.find(bone->ID) != animation->JointAnimations.end()) { - std::vector boneKeyFrames = animation->JointAnimations.at(bone->ID); + const std::vector& boneKeyFrames = animation->JointAnimations.at(bone->ID); - Animation::Keyframe currentFrame; - Animation::Keyframe nextFrame; + const Animation::Keyframe* currentFrame; + const Animation::Keyframe* nextFrame; if (boneKeyFrames.size() > 1) { // 2+ keyframes for the current bone for (int index = boneKeyFrames.size()-1; index >= 0; index--) { // find the bone keyframes that surrounds the current frame if (time >= boneKeyFrames.at(index).Time) { - currentFrame = boneKeyFrames.at(index); - nextFrame = boneKeyFrames.at((index + 1) % boneKeyFrames.size()); + currentFrame = &boneKeyFrames.at(index); + nextFrame = &boneKeyFrames.at((index + 1) % boneKeyFrames.size()); break; } } float progress; - if (nextFrame.Index == 0) { + if (nextFrame->Index == 0) { nextFrame = currentFrame; - progress = (time - currentFrame.Time) / (animation->Duration - currentFrame.Time); + progress = (time - currentFrame->Time) / (animation->Duration - currentFrame->Time); } else { - progress = (time - currentFrame.Time) / (nextFrame.Time - currentFrame.Time); + progress = (time - currentFrame->Time) / (nextFrame->Time - currentFrame->Time); } + progress = glm::clamp(progress, 0.0f, 1.0f); + const Animation::Keyframe::BoneProperty& currentBoneProperty = currentFrame->BoneProperties; + const Animation::Keyframe::BoneProperty& nextBoneProperty = nextFrame->BoneProperties; + + glm::vec3 position = currentBoneProperty.Position * (1.f - progress) + nextBoneProperty.Position * progress; + glm::quat rotation = glm::normalize(glm::slerp(currentBoneProperty.Rotation, nextBoneProperty.Rotation, progress)); + glm::vec3 scale = currentBoneProperty.Scale * (1.f - progress) + nextBoneProperty.Scale * progress; + + // Flag for no root motion + if (bone == RootBone && noRootMotion) { + position.x = 0; + position.z = 0; + } + + poseData.Translation = position; + poseData.Orientation = rotation; + poseData.Scale = scale; + boneMatrices[bone->ID] = poseData; + + } else { // 1 keyframes for the current bone + currentFrame = &boneKeyFrames.at(0); + poseData.Translation = currentFrame->BoneProperties.Position; + poseData.Orientation = currentFrame->BoneProperties.Rotation; + poseData.Scale = currentFrame->BoneProperties.Scale; + boneMatrices[bone->ID] = poseData; + } + } + + for (auto &child : bone->Children) { + AccumulateBoneTransforms(noRootMotion, animation, time, boneMatrices, child); + } +} + + +void Skeleton::AdditiveBoneTransforms(const Animation* animation, double time, std::map& boneMatrices, const Bone* bone) +{ + if (animation->JointAnimations.find(bone->ID) != animation->JointAnimations.end()) { + PoseData refPose = GetAdditiveBonePose(bone, animation, 0.0); + PoseData srcPose = GetAdditiveBonePose(bone, animation, time + 1.0/60.0); + + PoseData finalPose; + finalPose.Translation = srcPose.Translation - refPose.Translation; + finalPose.Orientation = srcPose.Orientation * glm::inverse(refPose.Orientation); + finalPose.Scale = srcPose.Scale - refPose.Scale; + + boneMatrices[bone->ID] = finalPose; + } + + for (auto &child : bone->Children) { + AdditiveBoneTransforms(animation, time, boneMatrices, child); + } +} + +Skeleton::PoseData Skeleton::GetAdditiveBonePose(const Bone* bone, const Animation* animation, double time) +{ + glm::vec3 position = glm::vec3(0); + glm::quat rotation = glm::quat(); + glm::vec3 scale = glm::vec3(1); + + if (animation->JointAnimations.find(bone->ID) != animation->JointAnimations.end()) { + const std::vector& boneKeyFrames = animation->JointAnimations.at(bone->ID); + + const Animation::Keyframe* currentFrame; + const Animation::Keyframe* nextFrame; + + if (boneKeyFrames.size() > 1) { // 2+ keyframes for the current bone + for (int index = boneKeyFrames.size()-1; index >= 0; index--) { // find the bone keyframes that surrounds the current frame + if (time >= boneKeyFrames.at(index).Time) { + currentFrame = &boneKeyFrames.at(index); + nextFrame = &boneKeyFrames.at((index + 1) % boneKeyFrames.size()); + break; + } + } + + float progress; + + if (nextFrame->Index == 0) { + nextFrame = currentFrame; + progress = (time - currentFrame->Time) / (animation->Duration - currentFrame->Time); + } else { + progress = (time - currentFrame->Time) / (nextFrame->Time - currentFrame->Time); + } + progress = glm::clamp(progress, 0.0f, 1.0f); - Animation::Keyframe::BoneProperty currentBoneProperty = currentFrame.BoneProperties; - Animation::Keyframe::BoneProperty nextBoneProperty = nextFrame.BoneProperties; + const Animation::Keyframe::BoneProperty& currentBoneProperty = currentFrame->BoneProperties; + const Animation::Keyframe::BoneProperty& nextBoneProperty = nextFrame->BoneProperties; position = currentBoneProperty.Position * (1.f - progress) + nextBoneProperty.Position * progress; rotation = glm::slerp(currentBoneProperty.Rotation, nextBoneProperty.Rotation, progress); @@ -374,315 +151,137 @@ glm::mat4 Skeleton::GetOffsetTransform(const Bone* bone, AnimationOffset animati } else { // 1 keyframes for the current bone - currentFrame = boneKeyFrames.at(0); - position = currentFrame.BoneProperties.Position; - rotation = currentFrame.BoneProperties.Rotation; - scale = currentFrame.BoneProperties.Scale; + currentFrame = &boneKeyFrames.at(0); + position = currentFrame->BoneProperties.Position; + rotation = currentFrame->BoneProperties.Rotation; + scale = currentFrame->BoneProperties.Scale; } } - return (glm::translate(position) * glm::toMat4(rotation) * glm::scale(scale)); + PoseData finalPose; + finalPose.Translation = position; + finalPose.Orientation = rotation; + finalPose.Scale = scale; + + return finalPose; +} + +std::map Skeleton::BlendPoses(const std::map& pose1, const std::map& pose2, double weight) +{ + std::map finalPose; + + float weight1 = (float)(1.0 - weight); + float weight2 = (float)(weight); + + for (auto& b : Bones) { + int boneID = b.second->ID; + PoseData blendedPose; + blendedPose.Translation = glm::vec3(0); + blendedPose.Orientation = glm::quat(); + blendedPose.Scale = glm::vec3(1); + + if(pose1.find(boneID) != pose1.end() && pose2.find(boneID) != pose2.end()) { + blendedPose.Translation = pose1.at(boneID).Translation * weight1 + pose2.at(boneID).Translation * weight2; + blendedPose.Orientation = glm::slerp(pose1.at(boneID).Orientation, pose2.at(boneID).Orientation, weight2); + blendedPose.Scale = pose1.at(boneID).Scale * weight1 + pose2.at(boneID).Scale * weight2; + finalPose[boneID] = blendedPose; + } else if(pose1.find(boneID) != pose1.end()) { + finalPose[boneID] = pose1.at(boneID); + } else if (pose2.find(boneID) != pose2.end()) { + finalPose[boneID] = pose2.at(boneID); + } + } + + return finalPose; +} + +std::map Skeleton::OverridePose(const std::map& overridePose, const std::map& targetPose) +{ + std::map finalPose; + + for (auto& b : Bones) { + int boneID = b.second->ID; + if (overridePose.find(boneID) != overridePose.end()) { + finalPose[boneID] = overridePose.at(boneID); + } else if (targetPose.find(boneID) != targetPose.end()) { + finalPose[boneID] = targetPose.at(boneID); + } + } + return finalPose; +} + +std::map Skeleton::BlendPoseAdditive(const std::map& additivePose, const std::map& targetPose) +{ + std::map finalPose; + + for (auto& b : Bones) { + int boneID = b.second->ID; + PoseData blendedPose; + blendedPose.Translation = glm::vec3(0); + blendedPose.Orientation = glm::quat(); + blendedPose.Scale = glm::vec3(1); + + if (additivePose.find(boneID) != additivePose.end() && targetPose.find(boneID) != targetPose.end()) { + blendedPose.Translation = additivePose.at(boneID).Translation + targetPose.at(boneID).Translation; + blendedPose.Orientation = additivePose.at(boneID).Orientation * targetPose.at(boneID).Orientation; + blendedPose.Scale = additivePose.at(boneID).Scale + targetPose.at(boneID).Scale; + finalPose[boneID] = blendedPose; + } else if (additivePose.find(boneID) != additivePose.end()) { + finalPose[boneID] = additivePose.at(boneID); + } else if (targetPose.find(boneID) != targetPose.end()) { + finalPose[boneID] = targetPose.at(boneID); + } + } + + return finalPose; +} + +void Skeleton::GetFinalPose(std::map& poseDatas, std::vector& finalPose, std::map& boneTransforms) +{ + + std::map boneMatrices; + + AccumulateFinalPose(boneMatrices, poseDatas, boneTransforms, RootBone, glm::mat4(1)); + + for(auto& b : boneMatrices) { + finalPose.push_back(b.second); + } + } -glm::mat4 Skeleton::GetBoneTransform(const Bone* bone, const Animation* animation, float time, glm::mat4 childMatrix) +std::vector Skeleton::GetTPose() { - glm::mat4 boneMatrix; + std::vector finalMatrices; - Animation::Keyframe currentFrame; - Animation::Keyframe nextFrame; - - if (animation->JointAnimations.find(bone->ID) != animation->JointAnimations.end()) { - std::vector boneKeyFrames = animation->JointAnimations.at(bone->ID); - - if (boneKeyFrames.size() > 1) { // 2+ keyframes for the current bone - for (int index = boneKeyFrames.size()-1; index >= 0; index--) { // find the bone keyframes that surrounds the current frame - if (time >= boneKeyFrames.at(index).Time) { - currentFrame = boneKeyFrames.at(index); - nextFrame = boneKeyFrames.at((index + 1) % boneKeyFrames.size()); - break; - } - } - - float progress; - - if (nextFrame.Index == 0) { - nextFrame = currentFrame; - progress = (time - currentFrame.Time) / (animation->Duration - currentFrame.Time); - } else { - progress = (time - currentFrame.Time) / (nextFrame.Time - currentFrame.Time); - } - - if (progress > 1.0f || progress < 0.0f) { - LOG_INFO("Progress %f", progress); - progress = glm::clamp(progress, 0.0f, 1.0f); - } - Animation::Keyframe::BoneProperty currentBoneProperty = currentFrame.BoneProperties; - Animation::Keyframe::BoneProperty nextBoneProperty = nextFrame.BoneProperties; - - glm::vec3 positionInterp = currentBoneProperty.Position * (1.f - progress) + nextBoneProperty.Position * progress; - glm::quat rotationInterp = glm::slerp(currentBoneProperty.Rotation, nextBoneProperty.Rotation, progress); - glm::vec3 scaleInterp = currentBoneProperty.Scale * (1.f - progress) + nextBoneProperty.Scale * progress; - - boneMatrix = (glm::translate(positionInterp) * glm::toMat4(rotationInterp) * glm::scale(scaleInterp)) * childMatrix; - - } else { // 1 keyframes for the current bone - currentFrame = boneKeyFrames.at(0); - boneMatrix = (glm::translate(currentFrame.BoneProperties.Position) * glm::toMat4(currentFrame.BoneProperties.Rotation) * glm::scale(currentFrame.BoneProperties.Scale)) * childMatrix; - - } - } else { // 0 keyframes for the current bone - if (bone->Parent) { - boneMatrix = bone->Parent->OffsetMatrix * glm::inverse(bone->OffsetMatrix) * childMatrix; - } else { - boneMatrix = glm::inverse(bone->OffsetMatrix) * childMatrix; - } + for (auto b : Bones) { + finalMatrices.push_back(glm::mat4(1)); } - if (bone->Parent) { - return GetBoneTransform(bone->Parent, animation, time, boneMatrix); - } else { - return boneMatrix; - } + return finalMatrices; } - -glm::mat4 Skeleton::GetBoneTransform(bool noRootMotion, const Bone* bone, std::vector animations, AnimationOffset animationOffset, glm::mat4 childMatrix) +void Skeleton::AccumulateFinalPose(std::map& boneMatrices, std::map& poseDatas, std::map& boneTransforms, const Bone* bone, glm::mat4 parentMatrix) { glm::mat4 boneMatrix; - std::vector JointTransforms; - - for (const AnimationData animationData : animations) { - const Animation* animation = animationData.animation; - const float time = animationData.time; - - JointFrameTransform jointTransform; - jointTransform.Weight = animationData.weight;; - - if (animation->JointAnimations.find(bone->ID) != animation->JointAnimations.end()) { - std::vector boneKeyFrames = animation->JointAnimations.at(bone->ID); - - Animation::Keyframe currentFrame; - Animation::Keyframe nextFrame; - - if (boneKeyFrames.size() > 1) { // 2+ keyframes for the current bone - for (int index = boneKeyFrames.size()-1; index >= 0; index--) { // find the bone keyframes that surrounds the current frame - if (time >= boneKeyFrames.at(index).Time) { - currentFrame = boneKeyFrames.at(index); - nextFrame = boneKeyFrames.at((index + 1) % boneKeyFrames.size()); - break; - } - } - - float progress; - - if (nextFrame.Index == 0) { - nextFrame = currentFrame; - progress = (time - currentFrame.Time) / (animation->Duration - currentFrame.Time); - } else { - progress = (time - currentFrame.Time) / (nextFrame.Time - currentFrame.Time); - - } - - - if (progress > 1.0f || progress < 0.0f) { - progress = glm::clamp(progress, 0.0f, 1.0f); - } - Animation::Keyframe::BoneProperty currentBoneProperty = currentFrame.BoneProperties; - Animation::Keyframe::BoneProperty nextBoneProperty = nextFrame.BoneProperties; - - jointTransform.PositionInterp = currentBoneProperty.Position * (1.f - progress) + nextBoneProperty.Position * progress; - jointTransform.RotationInterp = glm::slerp(currentBoneProperty.Rotation, nextBoneProperty.Rotation, progress); - jointTransform.ScaleInterp = currentBoneProperty.Scale * (1.f - progress) + nextBoneProperty.Scale * progress; - - // Flag for no root motion - if (bone == RootBone && noRootMotion) { - jointTransform.PositionInterp.x = 0; - jointTransform.PositionInterp.z = 0; - } - - JointTransforms.push_back(jointTransform); - - } else { // 1 keyframes for the current bone - currentFrame = boneKeyFrames.at(0); - jointTransform.PositionInterp = currentFrame.BoneProperties.Position; - jointTransform.RotationInterp = currentFrame.BoneProperties.Rotation; - jointTransform.ScaleInterp = currentFrame.BoneProperties.Scale; - JointTransforms.push_back(jointTransform); - - } - } else { // 0 keyframes for the current bone - - } - - } - - - glm::mat4 offset = GetOffsetTransform(bone, animationOffset); - - if (JointTransforms.size() == 0) { + if (poseDatas.find(bone->ID) != poseDatas.end()) { + boneMatrix = parentMatrix * (glm::translate(poseDatas.at(bone->ID).Translation) * glm::mat4(poseDatas.at(bone->ID).Orientation) * glm::scale(poseDatas.at(bone->ID).Scale)); + boneMatrices[bone->ID] = boneMatrix * bone->OffsetMatrix; + } else { if (bone->Parent) { - if (offset != glm::mat4(1)) { - boneMatrix = offset * childMatrix;// *((glm::inverse(bone->OffsetMatrix) * bone->Parent->OffsetMatrix)); - } else { - boneMatrix = ((glm::inverse(bone->OffsetMatrix) * bone->Parent->OffsetMatrix)) * childMatrix; - } + boneMatrix = parentMatrix * bone->BindTransformMatrix * bone->Parent->OffsetMatrix; + boneMatrices[bone->ID] = boneMatrix * bone->OffsetMatrix; } else { - boneMatrix = offset * glm::inverse(bone->OffsetMatrix); - } - } else { - - glm::vec3 finalPosInterp; - glm::quat finalRotInterp; - glm::vec3 finalScaleInterp; - float totalWeight = 0; - - for (JointFrameTransform jointTransform : JointTransforms) { - totalWeight += jointTransform.Weight; - } - - - for (JointFrameTransform jointTransform : JointTransforms) { - if (jointTransform.Weight == 1.0f) { - finalPosInterp = jointTransform.PositionInterp; - finalRotInterp = jointTransform.RotationInterp; - finalScaleInterp = jointTransform.ScaleInterp; - break; - } else { - finalPosInterp += jointTransform.PositionInterp * (jointTransform.Weight/totalWeight); - finalRotInterp *= glm::slerp(glm::quat(), jointTransform.RotationInterp, (jointTransform.Weight/totalWeight)); - finalScaleInterp += jointTransform.ScaleInterp * (jointTransform.Weight/totalWeight); - } - - } - - if (offset != glm::mat4(1)) { - boneMatrix = ((glm::translate(finalPosInterp) * glm::toMat4(finalRotInterp) * glm::scale(finalScaleInterp)) + offset) * childMatrix; - } else { - boneMatrix = (glm::translate(finalPosInterp) * glm::toMat4(finalRotInterp) * glm::scale(finalScaleInterp)) * childMatrix; + boneMatrix = bone->BindTransformMatrix; + boneMatrices[bone->ID] = parentMatrix; } } - if (bone->Parent != nullptr) { - return GetBoneTransform(noRootMotion, bone->Parent, animations, animationOffset, boneMatrix); - } else { - return boneMatrix; - } -} + boneTransforms[bone->ID] = boneMatrix; - -glm::mat4 Skeleton::GetBoneTransform(bool noRootMotion, const Bone* bone, std::vector animations, glm::mat4 childMatrix) -{ - glm::mat4 boneMatrix; - std::vector JointTransforms; - - for (const AnimationData animationData : animations) { - const Animation* animation = animationData.animation; - const float time = animationData.time; - - JointFrameTransform jointTransform; - jointTransform.Weight = animationData.weight;; - - if (animation->JointAnimations.find(bone->ID) != animation->JointAnimations.end()) { - std::vector boneKeyFrames = animation->JointAnimations.at(bone->ID); - - Animation::Keyframe currentFrame; - Animation::Keyframe nextFrame; - - if (boneKeyFrames.size() > 1) { // 2+ keyframes for the current bone - for (int index = boneKeyFrames.size()-1; index >= 0; index--) { // find the bone keyframes that surrounds the current frame - if (time >= boneKeyFrames.at(index).Time) { - currentFrame = boneKeyFrames.at(index); - nextFrame = boneKeyFrames.at((index + 1) % boneKeyFrames.size()); - break; - } - } - - float progress; - - if (nextFrame.Index == 0) { - nextFrame = currentFrame; - progress = (time - currentFrame.Time) / (animation->Duration - currentFrame.Time); - } else { - progress = (time - currentFrame.Time) / (nextFrame.Time - currentFrame.Time); - } - - - if (progress > 1.0f || progress < 0.0f) { - progress = glm::clamp(progress, 0.0f, 1.0f); - } - Animation::Keyframe::BoneProperty currentBoneProperty = currentFrame.BoneProperties; - Animation::Keyframe::BoneProperty nextBoneProperty = nextFrame.BoneProperties; - - jointTransform.PositionInterp = currentBoneProperty.Position * (1.f - progress) + nextBoneProperty.Position * progress; - jointTransform.RotationInterp = glm::slerp(currentBoneProperty.Rotation, nextBoneProperty.Rotation, progress); - jointTransform.ScaleInterp = currentBoneProperty.Scale * (1.f - progress) + nextBoneProperty.Scale * progress; - - // Flag for no root motion - if (bone == RootBone && noRootMotion) { - jointTransform.PositionInterp.x = 0; - jointTransform.PositionInterp.z = 0; - } - - JointTransforms.push_back(jointTransform); - - } else { // 1 keyframes for the current bone - currentFrame = boneKeyFrames.at(0); - jointTransform.PositionInterp = currentFrame.BoneProperties.Position; - jointTransform.RotationInterp = currentFrame.BoneProperties.Rotation; - jointTransform.ScaleInterp = currentFrame.BoneProperties.Scale; - JointTransforms.push_back(jointTransform); - - } - } else { // 0 keyframes for the current bone - - } - - } - - if (JointTransforms.size() <= 0) { - if (bone->Parent) { - boneMatrix = glm::inverse(bone->OffsetMatrix) * bone->Parent->OffsetMatrix * childMatrix; - } else { - boneMatrix = glm::inverse(bone->OffsetMatrix) * childMatrix; - } - } else if (JointTransforms.size() == 1) { - boneMatrix = (glm::translate(JointTransforms.at(0).PositionInterp) * glm::toMat4(JointTransforms.at(0).RotationInterp) * glm::scale(JointTransforms.at(0).ScaleInterp)) * childMatrix; - } else { - - glm::vec3 finalPosInterp; - glm::quat finalRotInterp; - glm::vec3 finalScaleInterp; - float totalWeight = 0; - - for (JointFrameTransform jointTransform : JointTransforms) { - totalWeight += jointTransform.Weight; - } - - - for (JointFrameTransform jointTransform : JointTransforms) { - if (jointTransform.Weight == 1.0f) { - finalPosInterp = jointTransform.PositionInterp; - finalRotInterp = jointTransform.RotationInterp; - finalScaleInterp = jointTransform.ScaleInterp; - break; - } else { - finalPosInterp += jointTransform.PositionInterp * (jointTransform.Weight/totalWeight); - finalRotInterp *= glm::slerp(glm::quat(), jointTransform.RotationInterp, (jointTransform.Weight/totalWeight)); - finalScaleInterp += jointTransform.ScaleInterp * (jointTransform.Weight/totalWeight); - } - } - - boneMatrix = (glm::translate(finalPosInterp) * glm::toMat4(finalRotInterp) * glm::scale(finalScaleInterp)) * childMatrix; - } - - - - if (bone->Parent != nullptr) { - return GetBoneTransform(noRootMotion, bone->Parent, animations, boneMatrix); - } else { - return boneMatrix; + for (auto &child : bone->Children) { + AccumulateFinalPose(boneMatrices, poseDatas, boneTransforms, child, boneMatrix); } } @@ -695,46 +294,43 @@ int Skeleton::GetBoneID(std::string name) } } -void Skeleton::PrintSkeleton() +int Skeleton::CreateBone(int ID, int parentID, std::string name, glm::mat4 offsetMatrix) { - if (LOG_LEVEL < LOG_LEVEL_DEBUG) { - return; - } - PrintSkeleton(RootBone, 0); + if (m_BonesByName.find(name) != m_BonesByName.end()) { + return m_BonesByName.at(name)->ID; + } else { + Bone* bone; + + if (parentID == -1) { + bone = new Bone(ID, nullptr, name, offsetMatrix); + RootBone = bone; + } else { + Bone* parent = Bones[parentID]; + bone = new Bone(ID, parent, name, offsetMatrix); + parent->Children.push_back(bone); + } + + Bones[ID] = bone; + m_BonesByName[name] = bone; + return ID; + } } -void Skeleton::PrintSkeleton(const Bone* bone, int depthCount) +Skeleton::~Skeleton() { - std::stringstream ss; - ss << std::string(depthCount, ' '); - ss << bone->ID << ": " << bone->Name; - std::cout << ss.str() << std::endl; - - depthCount++; + for (auto &kv : Bones) { + delete kv.second; + } - for (auto &child : bone->Children) { - PrintSkeleton(child, depthCount); - } + BlendTrees.clear(); } -int Skeleton::GetKeyframe(const Animation& animation, double time) +const Skeleton::Animation* Skeleton::GetAnimation(std::string name) { - -/* - if (time < 0) { - time = 0; - } - if (time >= animation.Duration) { - return animation..size() - 1; - } - - for (int keyframe = 0; keyframe < animation.Keyframes.size(); ++keyframe) { - if (animation.Keyframes[keyframe].Time > time) { - return (keyframe - 1) % animation.Keyframes.size(); - } - } -*/ - - - return 0; -} + auto it = Animations.find(name); + if (it != Animations.end()) { + return const_cast(&it->second); + } else { + return nullptr; + } +} \ No newline at end of file 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 03347044..3d2de0db 100644 --- a/src/Engine/Rendering/Texture.cpp +++ b/src/Engine/Rendering/Texture.cpp @@ -2,23 +2,21 @@ Texture::Texture(std::string path) { - PNG* img = ResourceManager::Load(path); //TODO: Make this threaded. Catch exeptions in all other load places. - - //PNG image(path); - - //if (img->Width == 0 && img->Height == 0 || img->Format == Image::ImageFormat::Unknown) { - // //image = PNG("Textures/Core/ErrorTexture.png"); - // //return; // Temporary fix to remove crash - - // if (img->Width == 0 && img->Height == 0 || img->Format == Image::ImageFormat::Unknown) { - // LOG_ERROR("Couldn't even load the error texture. This is a dark day indeed."); - // return; - // } - //} + std::string ext = boost::filesystem::path(path).extension().string(); + Image* img; + if (ext == ".png") { + img = ResourceManager::Load(path); + m_Type = TextureType::cPNG; + } else if (ext == ".dds") { + img = ResourceManager::Load(path); + m_Type = TextureType::cDDS; + } else { + m_Type = TextureType::cInvalid; + throw Resource::FailedLoadingException("Texture extension is not .png nor .dds"); + } this->Width = img->Width; this->Height = img->Height; - this->Data = img->Data; GLint format; switch (img->Format) { @@ -29,19 +27,59 @@ Texture::Texture(std::string path) format = GL_RGBA; break; } - + + //Master hade PNG release here... // Construct the OpenGL texture glGenTextures(1, &m_Texture); glBindTexture(GL_TEXTURE_2D, m_Texture); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glTexImage2D(GL_TEXTURE_2D, 0, format, img->Width, img->Height, 0, format, GL_UNSIGNED_BYTE, img->Data); - glGenerateMipmap(GL_TEXTURE_2D); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - 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"); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + if (!img->Compressed) { + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + } + unsigned int w = img->Width; + unsigned int h = img->Width; + unsigned char* data = img->Data; + for (int mipLevel = 0; mipLevel < 1 + img->MipMapLevels; mipLevel++) { + if (img->Compressed) { + //LOG_DEBUG("mipLevel: %i", mipLevel); + //LOG_DEBUG("w: %i", w); + //LOG_DEBUG("h: %i", h); + + std::size_t bpe = 16; + std::size_t numBlocksWide = std::max(1, (w + 3) / 4); + std::size_t numBlocksHigh = std::max(1, (h + 3) / 4); + std::size_t rowBytes = numBlocksWide * bpe; + std::size_t numRows = numBlocksHigh; + std::size_t numBytes = rowBytes * numBlocksHigh; + //LOG_DEBUG("numBytes: %i", numBytes); + glCompressedTexImage2D(GL_TEXTURE_2D, mipLevel, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, w, h, 0, numBytes, data); + data += numBytes; + } else { + glTexImage2D(GL_TEXTURE_2D, mipLevel, format, img->Width, img->Height, 0, format, GL_UNSIGNED_BYTE, img->Data); + } + + w = w >> 1; + h = h >> 1; + } + //LOG_DEBUG("REMAINDER: %i", img->ByteSize - (data - img->Data)); + // Generate mipmaps if the image file doesn't contain them + if (img->MipMapLevels == 0) { + glGenerateMipmap(GL_TEXTURE_2D); + } + + if (ext == ".png") { + ResourceManager::Release("PNG", path); + } else if (ext == ".dds") { + ResourceManager::Release("DDS", path); + } + + if (GLERROR("Texture load")) { + throw Resource::FailedLoadingException("GL texture generation failed"); + } } Texture::~Texture() diff --git a/src/Engine/Rendering/TextureSprite.cpp b/src/Engine/Rendering/TextureSprite.cpp new file mode 100644 index 00000000..70d086cd --- /dev/null +++ b/src/Engine/Rendering/TextureSprite.cpp @@ -0,0 +1,11 @@ +#include "Rendering/TextureSprite.h" + +TextureSprite::TextureSprite(std::string path) + :Texture(path) +{ + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + GLERROR("Texture load"); +} \ No newline at end of file diff --git a/src/Engine/Rendering/Util/CommonFunctions.cpp b/src/Engine/Rendering/Util/CommonFunctions.cpp index 382cb790..b24a3a9e 100644 --- a/src/Engine/Rendering/Util/CommonFunctions.cpp +++ b/src/Engine/Rendering/Util/CommonFunctions.cpp @@ -1,19 +1,47 @@ #include "Rendering/Util/CommonFunctions.h" -Texture* CommonFunctions::LoadTexture(std::string path, bool threaded) +void CommonFunctions::GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type) { - Texture* img; - try { - if(threaded) { - img = ResourceManager::Load(path); - } else { - img = ResourceManager::Load(path); - } - } catch (const Resource::StillLoadingException&) { - img = ResourceManager::Load("Textures/Core/ErrorTexture.png"); - } catch (const std::exception&) { - img = nullptr; - } - - return img; + glDeleteTextures(1, texture); + glGenTextures(1, texture); + glBindTexture(GL_TEXTURE_2D, *texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapping); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapping); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering); + glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, dimensions.x, dimensions.y, 0, format, type, nullptr); + GLERROR("Texture initialization failed"); } + +void CommonFunctions::GenerateMultiSampleTexture(GLuint* texture, int numSamples, glm::vec2 dimensions, GLint internalFormat) +{ + glDeleteTextures(1, texture); + glGenTextures(1, texture); + glBindTexture(GL_TEXTURE_2D, *texture); + GLERROR("Texture initialization failed 1"); + glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, numSamples, internalFormat, dimensions.x, dimensions.y, GL_FALSE); + GLERROR("Texture initialization failed"); +} + + +void CommonFunctions::GenerateMipMapTexture(GLuint* texture, GLenum wrapping, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type, GLint numMipMaps, GLint MAGFilter, GLint MINFilter) +{ + glDeleteTextures(1, texture); + glGenTextures(1, texture); + glBindTexture(GL_TEXTURE_2D, *texture); + glTexStorage2D(GL_TEXTURE_2D, numMipMaps, internalFormat, dimensions.x, dimensions.y); + //glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, dimensions.x, dimensions.y, format, type, NULL); + GLERROR("MipMap Texture glTexSubImage2D failed"); + glGenerateMipmap(GL_TEXTURE_2D); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapping); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapping); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, MAGFilter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, MINFilter); + GLERROR("MipMap Texture initialization failed"); +} + +void CommonFunctions::DeleteTexture(GLuint* texture) +{ + glDeleteTextures(1, texture); + *texture = 0; +} \ No newline at end of file diff --git a/src/Engine/Rendering/Util/ScreenCoords.cpp b/src/Engine/Rendering/Util/ScreenCoords.cpp index 36f1295e..a8d8a662 100644 --- a/src/Engine/Rendering/Util/ScreenCoords.cpp +++ b/src/Engine/Rendering/Util/ScreenCoords.cpp @@ -31,22 +31,23 @@ glm::vec3 ScreenCoords::ToWorldPos(glm::vec2 screenCoord, float depth, float scr ScreenCoords::PixelData ScreenCoords::ToPixelData(float x, float y, FrameBuffer* PickDataBuffer, GLuint DepthBuffer) { + GLERROR("Pre"); PickDataBuffer->Bind(); unsigned char pdata[3]; glReadPixels(x, y, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &pdata); - PickDataBuffer->Unbind(); - - glBindFramebuffer(GL_FRAMEBUFFER, DepthBuffer); + GLERROR("glReadPixels(pdata) Error"); float depthData; glReadPixels(x, y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depthData); + GLERROR("glReadPixels(depthData) Error"); glBindFramebuffer(GL_FRAMEBUFFER, 0); + GLERROR("glBindFramebuffer(0) Error"); PixelData p; p.Color[0] = (int)pdata[0]; p.Color[1] = (int)pdata[1]; p.Depth = depthData; - GLERROR("ScreenCoords::ToPixelData Error"); + GLERROR("End"); return p; } diff --git a/src/Engine/Sound/SoundManager.cpp b/src/Engine/Sound/SoundManager.cpp index 8e103d5c..a8161f5d 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,20 @@ 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); + EVENT_SUBSCRIBE_MEMBER(m_ESetCamera, &SoundManager::OnSetCamera); } SoundManager::~SoundManager() @@ -56,13 +61,10 @@ 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); + matchBGMLoop(); } void SoundManager::deleteInactiveEmitters() @@ -113,18 +115,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 +149,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 +168,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 +219,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 +234,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 +271,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 +287,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 +321,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") { @@ -306,7 +364,6 @@ bool SoundManager::OnPlayerSpawned(const Events::PlayerSpawned &e) return false; } - bool SoundManager::OnPlayQueueOnEntity(const Events::PlayQueueOnEntity &e) { Source* source = createSource(*e.FilePaths.begin()); @@ -321,6 +378,56 @@ bool SoundManager::OnPlayQueueOnEntity(const Events::PlayQueueOnEntity &e) return true; } +bool SoundManager::OnChangeBGM(const Events::ChangeBGM &e) +{ + if (m_CurrentBGM != nullptr) { + if (getSourceState(m_CurrentBGM->ALsource) == AL_PLAYING) { + 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; +} + +bool SoundManager::OnSetCamera(const Events::SetCamera& e) +{ + if (e.CameraEntity.Name() == "Overview_Camera_Start_Menu") { + if (m_CurrentBGMCombo != nullptr) { + if (getSourceState(m_CurrentBGMCombo->ALsource) == AL_PLAYING) { + stopSound(m_CurrentBGMCombo); + } + } + Events::ChangeBGM changeBGM; + changeBGM.FilePath = "Audio/BGM/MenuMusic.wav"; + m_EventBroker->Publish(changeBGM); + } else if (e.CameraEntity.Name() == "PickTeamCamera") { + Events::ChangeBGM changeBGM; + changeBGM.FilePath = "Audio/BGM/Layer1.wav"; + m_EventBroker->Publish(changeBGM); + if (m_CurrentBGMCombo != nullptr) { + if (getSourceState(m_CurrentBGMCombo->ALsource) == AL_PLAYING) { + stopSound(m_CurrentBGMCombo); + } + } + 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); + } else if (m_World->HasComponent(e.CameraEntity.ID, "EndScreen")) { + float timeOffset = getTimeOffsetSeconds(m_CurrentBGM); + stopSound(m_CurrentBGM); + m_CurrentBGM = createSource("Audio/BGM/Layer3.wav"); + m_CurrentBGM->Type = SoundType::BGM; + alSourcei(m_CurrentBGM->ALsource, AL_LOOPING, 1); + playSound(m_CurrentBGM); + setTimeOffsetSeconds(m_CurrentBGM, timeOffset); + } +} + ALenum SoundManager::getSourceState(ALuint source) { ALenum state; @@ -335,15 +442,54 @@ 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::setTimeOffsetSeconds(Source * source, float timeOffset) +{ + alSourcef(source->ALsource, AL_SEC_OFFSET, timeOffset); +} + void SoundManager::initOpenAL() { // Initialize OpenAL diff --git a/src/Game/CMakeLists.txt b/src/Game/CMakeLists.txt index d8ba8599..a9aa829f 100644 --- a/src/Game/CMakeLists.txt +++ b/src/Game/CMakeLists.txt @@ -53,10 +53,11 @@ target_link_libraries(Game ${LIBRARIES} ) -add_executable(TacticalZ +add_executable(Axyz main.cpp + ${CMAKE_SOURCE_DIR}/resources/TacticalZ.rc ) -target_link_libraries(TacticalZ +target_link_libraries(Axyz Game ${LIBRARIES} ) diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index 1f9879ba..a916f3f8 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -10,13 +10,17 @@ #include "Systems/SpawnerSystem.h" #include "Systems/PlayerSpawnSystem.h" #include "Systems/PlayerDeathSystem.h" -#include "Core/EntityFileWriter.h" +#include "Systems/FloatingEffectSystem.h" +#include "Core/EntityFile.h" +#include "Core/EntityXMLFileWriter.h" #include "Game/Systems/CapturePointSystem.h" #include "Game/Systems/CapturePointHUDSystem.h" -#include "Game/Systems/HealthPickupSystem.h" +#include "Game/Systems/PickupSpawnSystem.h" #include "Game/Systems/AmmoPickupSystem.h" #include "Game/Systems/DamageIndicatorSystem.h" +#include "Game/Systems/Weapon/AssaultWeaponBehaviour.h" #include "Game/Systems/Weapon/DefenderWeaponBehaviour.h" +#include "Game/Systems/Weapon/SidearmWeaponBehaviour.h" #include "Rendering/AnimationSystem.h" #include "Game/Systems/HealthHUDSystem.h" #include "Rendering/BoneAttachmentSystem.h" @@ -24,10 +28,21 @@ #include "../Engine/Core/UniformScaleSystem.h" #include "Rendering/AnimationSystem.h" #include "Network/MultiplayerSnapshotFilter.h" -#include "Game/Systems/AmmunitionHUDSystem.h" +#include "Game/Systems/TextFieldReader.h" +#include "Game/Systems/AbilityCooldownHUDSystem.h" +#include "Game/Systems/CapturePointArrowHUDSystem.h" #include "Game/Systems/KillFeedSystem.h" +#include "Game/Systems/BoostSystem.h" +#include "Game/Systems/BoostIconsHUDSystem.h" +#include "Game/Systems/ScoreScreenSystem.h" +#include "Game/Systems/SpectatorCameraSystem.h" #include "GUI/ButtonSystem.h" -#include "GUI/MainMenuSystem.h" +#include "Game/Systems/MainMenuSystem.h" +#include "Game/Systems/ServerListSystem.h" +#include "Game/Systems/StartSystem.h" +#include "Game/Systems/EndScreenSystem.h" +#include "Game/Systems/FadeSystem.h" +#include "Rendering/TextureSprite.h" Game::Game(int argc, char* argv[]) @@ -39,22 +54,24 @@ Game::Game(int argc, char* argv[]) ResourceManager::RegisterType("Model"); ResourceManager::RegisterType("RawModel"); ResourceManager::RegisterType("Texture"); - ResourceManager::RegisterType("Png"); + ResourceManager::RegisterType("PNG"); + ResourceManager::RegisterType("TextureSprite"); + ResourceManager::RegisterType("DDS"); ResourceManager::RegisterType("ShaderProgram"); ResourceManager::RegisterType("EntityFile"); + ResourceManager::RegisterType("EntityXMLFile"); ResourceManager::RegisterType("FontFile"); m_Config = ResourceManager::Load("Config.ini"); ResourceManager::UseThreading = m_Config->Get("Multithreading.ResourceLoading", true); DisableMemoryPool::Value = m_Config->Get("Debug.DisableMemoryPool", false); LOG_LEVEL = static_cast<_LOG_LEVEL>(m_Config->Get("Debug.LogLevel", 1)); - PlayerSpawnSystem::SetRespawnTime(m_Config->Get("Debug.RespawnTime", 15.0f)); // Create the core event broker m_EventBroker = new EventBroker(); // Create the renderer - m_Renderer = new Renderer(m_EventBroker); + m_Renderer = new Renderer(m_EventBroker, m_Config); m_Renderer->SetFullscreen(m_Config->Get("Video.Fullscreen", false)); m_Renderer->SetVSYNC(m_Config->Get("Video.VSYNC", false)); m_Renderer->SetResolution(Rectangle::Rectangle( @@ -79,10 +96,7 @@ Game::Game(int argc, char* argv[]) std::string mapToLoad = m_Config->Get("Debug.LoadMap", ""); if (!mapToLoad.empty()) { auto file = ResourceManager::Load(mapToLoad); - EntityFilePreprocessor fpp(file); - fpp.RegisterComponents(m_World); - EntityFileParser fp(file); - fp.MergeEntities(m_World); + file->MergeInto(m_World); } // Create the sound manager @@ -106,7 +120,7 @@ Game::Game(int argc, char* argv[]) // Create Octrees // TODO: Perhaps the world bounds should be set in some non-arbitrary way instead of this. - AABB boxContainingTheWorld(glm::vec3(-300), glm::vec3(300)); + AABB boxContainingTheWorld = AABB::FromOriginSize(glm::vec3(0.f, 10.7f, 0.f), glm::vec3(140.f, 31.f, 190.f)); m_OctreeCollision = new Octree(boxContainingTheWorld, 4); m_OctreeTrigger = new Octree(boxContainingTheWorld, 4); m_OctreeFrustrumCulling = new Octree(boxContainingTheWorld, 4); @@ -116,25 +130,39 @@ 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); + m_SystemPipeline->AddSystem(updateOrderLevel); m_SystemPipeline->AddSystem(updateOrderLevel); m_SystemPipeline->AddSystem(updateOrderLevel); m_SystemPipeline->AddSystem(updateOrderLevel); m_SystemPipeline->AddSystem(updateOrderLevel); m_SystemPipeline->AddSystem(updateOrderLevel); + m_SystemPipeline->AddSystem(updateOrderLevel, m_Renderer, m_OctreeCollision); m_SystemPipeline->AddSystem(updateOrderLevel, m_Renderer, m_OctreeCollision); + m_SystemPipeline->AddSystem(updateOrderLevel, m_Renderer, m_OctreeCollision); m_SystemPipeline->AddSystem(updateOrderLevel); m_SystemPipeline->AddSystem(updateOrderLevel); m_SystemPipeline->AddSystem(updateOrderLevel); - m_SystemPipeline->AddSystem(updateOrderLevel); + m_SystemPipeline->AddSystem(updateOrderLevel); + m_SystemPipeline->AddSystem(updateOrderLevel); + m_SystemPipeline->AddSystem(updateOrderLevel); + m_SystemPipeline->AddSystem(updateOrderLevel); + m_SystemPipeline->AddSystem(updateOrderLevel); m_SystemPipeline->AddSystem(updateOrderLevel); m_SystemPipeline->AddSystem(updateOrderLevel); - m_SystemPipeline->AddSystem(updateOrderLevel); - m_SystemPipeline->AddSystem(updateOrderLevel); + m_SystemPipeline->AddSystem(updateOrderLevel); m_SystemPipeline->AddSystem(updateOrderLevel, m_Renderer); m_SystemPipeline->AddSystem(updateOrderLevel, m_Renderer); + m_SystemPipeline->AddSystem(updateOrderLevel); + m_SystemPipeline->AddSystem(updateOrderLevel); + m_SystemPipeline->AddSystem(updateOrderLevel); + m_SystemPipeline->AddSystem(updateOrderLevel, m_Renderer); + m_SystemPipeline->AddSystem(updateOrderLevel); + m_SystemPipeline->AddSystem(updateOrderLevel); + m_SystemPipeline->AddSystem(updateOrderLevel); // Populate Octree with collidables ++updateOrderLevel; m_SystemPipeline->AddSystem(updateOrderLevel, m_OctreeCollision, "Collidable"); @@ -197,20 +225,22 @@ void Game::Tick() PerformanceTimer::StartTimerAndStopPrevious("InputProxy"); m_InputProxy->Update(dt); m_EventBroker->Swap(); - m_InputProxy->Process(); + m_InputProxy->Process(ImGui::GetIO().WantCaptureKeyboard || ImGui::GetIO().WantCaptureMouse); 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); @@ -226,6 +256,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/Network/MultiplayerSnapshotFilter.cpp b/src/Game/Network/MultiplayerSnapshotFilter.cpp index 295cdd7a..db3d998e 100644 --- a/src/Game/Network/MultiplayerSnapshotFilter.cpp +++ b/src/Game/Network/MultiplayerSnapshotFilter.cpp @@ -14,8 +14,11 @@ bool MultiplayerSnapshotFilter::FilterComponent(EntityWrapper entity, SharedComp || component.Info.Name == "Physics" || component.Info.Name == "AssaultWeapon" || component.Info.Name == "DefenderWeapon" + || component.Info.Name == "SidearmWeapon" || component.Info.Name == "Animation" - || component.Info.Name == "AnimationOffset" + || component.Info.Name == "Blend" + || component.Info.Name == "BlendAdditive" + || component.Info.Name == "BlendOverride" || entity.Name() == "PlayerName" ) { return false; diff --git a/src/Game/Systems/AbilityCooldownHUDSystem.cpp b/src/Game/Systems/AbilityCooldownHUDSystem.cpp new file mode 100644 index 00000000..c89b4251 --- /dev/null +++ b/src/Game/Systems/AbilityCooldownHUDSystem.cpp @@ -0,0 +1,85 @@ +#include "Game/Systems/AbilityCooldownHUDSystem.h" + +void AbilityCooldownHUDSystem::Update(double dt) +{ + //HUD element for tracking cooldown on the parent entity with Dashability TODO: Make sure it support other abilities when they are made. + + auto abilityHUDs = m_World->GetComponents("AbilityCooldownHUD"); + if (abilityHUDs == nullptr) + return; + + for (auto& abilityHUDC : *abilityHUDs) { + EntityWrapper entity = EntityWrapper(m_World, abilityHUDC.EntityID); + EntityWrapper abilityEntity = entity.FirstParentWithComponent("DashAbility"); + std::string abilityName = ""; + + if (!abilityEntity.Valid()) { + //If we dont have a dash ability on player, we check for Sprint ability + abilityEntity = entity.FirstParentWithComponent("SprintAbility"); + + if (!abilityEntity.Valid()) { + //If we dont have a sprint ability on player, we check for shield ability + abilityEntity = entity.FirstParentWithComponent("ShieldAbility"); + + if (!abilityEntity.Valid()) { + //If we dont have a shield ability, we return, since we cannot do anything. + if (entity.HasComponent("Sprite")) { + (Field)entity["Sprite"]["DiffuseTexture"] = "Textures/Test/aM4ME4GR.png"; + } + return; + } else { + //If we have a shield ability, we set the right icon + abilityName = "ShieldAbility"; + if (entity.HasComponent("Sprite")) { + (Field)entity["Sprite"]["DiffuseTexture"] = "Textures/Icons/Abilities/Long/SheildDots-01.png"; + } + } + } else { + //If we do have a sprint ability, we change the icon + abilityName = "SprintAbility"; + if (entity.HasComponent("Sprite")) { + (Field)entity["Sprite"]["DiffuseTexture"] = "Textures/Icons/Abilities/Long/Dash-01.png"; + } + } + } else { + //If we have a dash ability, we set the icon to the correct one. + abilityName = "DashAbility"; + if (entity.HasComponent("Sprite")) { + (Field)entity["Sprite"]["DiffuseTexture"] = "Textures/Icons/Abilities/Long/Superman-01.png"; + } + } + + EntityWrapper cooldownTextEntity = entity.FirstChildByName("Cooldown"); + //TODO: Fix so this track correctly for shield and sprint depending on how they work. + double maxAbilityCD, currentAbilityCD; + + if (abilityName == "DashAbility") { + maxAbilityCD = (double)abilityEntity[abilityName]["CoolDownMaxTimer"]; + currentAbilityCD = (double)abilityEntity[abilityName]["CoolDownTimer"]; + currentAbilityCD = currentAbilityCD >= 0.0 ? currentAbilityCD : 0.0; + + if (cooldownTextEntity.Valid()) { + if (cooldownTextEntity.HasComponent("Text")) { + (Field)cooldownTextEntity["Text"]["Content"] = std::to_string(currentAbilityCD).substr(0, 3); + } + } + } + + if (abilityName == "ShieldAbility") { + maxAbilityCD = 1.0; + currentAbilityCD = 1 - (bool)abilityEntity[abilityName]["Active"]; + } + + if (abilityName == "SprintAbility") { + maxAbilityCD = 1.0; + currentAbilityCD = 1 - (bool)abilityEntity[abilityName]["Active"]; + } + + if (entity.HasComponent("Fill")) { + (Field)entity["Fill"]["Percentage"] = currentAbilityCD/maxAbilityCD; + } + + + + } +} diff --git a/src/Game/Systems/AmmoPickupSystem.cpp b/src/Game/Systems/AmmoPickupSystem.cpp index 196e3e28..34749d4e 100644 --- a/src/Game/Systems/AmmoPickupSystem.cpp +++ b/src/Game/Systems/AmmoPickupSystem.cpp @@ -3,105 +3,183 @@ AmmoPickupSystem::AmmoPickupSystem(SystemParams params) : System(params) { - EVENT_SUBSCRIBE_MEMBER(m_ETriggerTouch, &AmmoPickupSystem::OnTriggerTouch); - EVENT_SUBSCRIBE_MEMBER(m_ETriggerLeave, &AmmoPickupSystem::OnTriggerLeave); + if (IsServer) { + EVENT_SUBSCRIBE_MEMBER(m_ETriggerTouch, &AmmoPickupSystem::OnTriggerTouch); + EVENT_SUBSCRIBE_MEMBER(m_ETriggerLeave, &AmmoPickupSystem::OnTriggerLeave); + } + if (IsClient) { + EVENT_SUBSCRIBE_MEMBER(m_EAmmoPickup, &AmmoPickupSystem::OnAmmoPickup); + } } void AmmoPickupSystem::Update(double dt) { - for (auto it = m_ETriggerTouchVector.begin(); it != m_ETriggerTouchVector.end(); ++it) - { - auto& somePickup = *it; - //set the double timer value (value 3) - somePickup.DecreaseThisRespawnTimer -= dt; - if (somePickup.DecreaseThisRespawnTimer < 0.0) { - //spawn and delete the vector item - auto entityFile = ResourceManager::Load("Schema/Entities/AmmoPickup.xml"); - EntityFileParser parser(entityFile); - EntityID ammoPickupID = parser.MergeEntities(m_World); + if (IsServer) { + auto it = m_ETriggerTouchVector.begin(); + while (it != m_ETriggerTouchVector.end()) { + auto& somePickup = *it; + somePickup.DecreaseThisRespawnTimer -= dt; + if (somePickup.DecreaseThisRespawnTimer < 0.0) { + auto entityFile = ResourceManager::Load("Schema/Entities/AmmoPickup.xml"); + EntityWrapper ammoPickup = entityFile->MergeInto(m_World); - //let the world know a pickup has spawned (graphics effects, etc) - Events::PickupSpawned ePickupSpawned; - ePickupSpawned.Pickup = EntityWrapper(m_World, ammoPickupID); - m_EventBroker->Publish(ePickupSpawned); + //let the world know a pickup has spawned + Events::PickupSpawned ePickupSpawned; + ePickupSpawned.Pickup = ammoPickup; + m_EventBroker->Publish(ePickupSpawned); - //set values from the old entity to the new entity - auto& newAmmoPickupEntity = EntityWrapper(m_World, ammoPickupID); - newAmmoPickupEntity["Transform"]["Position"] = somePickup.Pos; - newAmmoPickupEntity["AmmoPickup"]["AmmoGain"] = somePickup.AmmoGain; - newAmmoPickupEntity["AmmoPickup"]["RespawnTimer"] = somePickup.RespawnTimer; - m_World->SetParent(newAmmoPickupEntity.ID, somePickup.parentID); + //copy values from the old entity to the new entity + auto& newAmmoPickupEntity = ammoPickup; + newAmmoPickupEntity["Transform"]["Position"] = somePickup.Pos; + newAmmoPickupEntity["AmmoPickup"]["AmmoGain"] = somePickup.AmmoGain; + newAmmoPickupEntity["AmmoPickup"]["RespawnTimer"] = somePickup.RespawnTimer; + m_World->SetParent(newAmmoPickupEntity.ID, somePickup.parentID); - //erase the current element (somePickup) - m_ETriggerTouchVector.erase(it); - break; + //erase the current element (somePickup) + it = m_ETriggerTouchVector.erase(it); + } else { + it++; + } + } + //still touching m_PickupAtMaximum? + for (auto& it = m_PickupAtMaximum.begin(); it != m_PickupAtMaximum.end(); ++it) { + if (!it->player.Valid()) { + m_PickupAtMaximum.erase(it); + break; + } + if (!DoesPlayerHaveMaxAmmo(it->player)) { + DoPickup(it->player, it->trigger); + m_PickupAtMaximum.erase(it); + break; + } } } - //still touching AmmoPickupAtMaxHealthAmmo? - for (auto& it = m_PickupAtMaximum.begin(); it != m_PickupAtMaximum.end(); ++it) { - if (!it->player.Valid() || !it->pickup.Valid()) { - m_PickupAtMaximum.erase(it); - break; - - } - if ((int)it->player["AssaultWeapon"]["Ammo"] < (int)it->player["AssaultWeapon"]["MaxAmmo"]) { - DoPickup(it->player, it->pickup); - m_PickupAtMaximum.erase(it); - break; - - } +} +bool AmmoPickupSystem::DoesPlayerHaveMaxAmmo(EntityWrapper &player) { + PlayerClass playerClass = DetermineClass(player); + if (playerClass == PlayerClass::Defender) { + return !((int)player["DefenderWeapon"]["Ammo"] < (int)player["DefenderWeapon"]["MaxAmmo"]); + } else if (playerClass == PlayerClass::Sniper) { + return !((int)player["SniperWeapon"]["Ammo"] < (int)player["SniperWeapon"]["MaxAmmo"]); + } else if (playerClass == PlayerClass::Assault) { + return !((int)player["AssaultWeapon"]["Ammo"] < (int)player["AssaultWeapon"]["MaxAmmo"]); + } else { + return false; } } +void AmmoPickupSystem::SetPlayerAmmo(EntityWrapper &player, int ammoGain) { + int maxWeaponAmmo = GetPlayerMaxAmmo(player); + + PlayerClass playerClass = DetermineClass(player); + if (playerClass == PlayerClass::Defender) { + (Field)player["DefenderWeapon"]["Ammo"] = std::min((int)player["DefenderWeapon"]["Ammo"] + ammoGain, maxWeaponAmmo); + } else if (playerClass == PlayerClass::Sniper) { + (Field)player["SniperWeapon"]["Ammo"] = std::min((int)player["SniperWeapon"]["Ammo"] + ammoGain, maxWeaponAmmo); + } else if (playerClass == PlayerClass::Assault) { + (Field)player["AssaultWeapon"]["Ammo"] = std::min((int)player["AssaultWeapon"]["Ammo"] + ammoGain, maxWeaponAmmo); + } else { + //unknown class - ignore + } +} +int AmmoPickupSystem::GetPlayerMaxAmmo(EntityWrapper &player) { + PlayerClass playerClass = DetermineClass(player); + if (playerClass == PlayerClass::Defender) { + return (int)player["DefenderWeapon"]["MaxAmmo"]; + } else if (playerClass == PlayerClass::Sniper) { + return (int)player["SniperWeapon"]["MaxAmmo"]; + } else if (playerClass == PlayerClass::Assault) { + return (int)player["AssaultWeapon"]["MaxAmmo"]; + } else { + return -1; + } +} +AmmoPickupSystem::PlayerClass AmmoPickupSystem::DetermineClass(EntityWrapper &player) +{ + //determine the class based on what component the inflictor-player has + if (m_World->HasComponent(player.ID, "DashAbility")) { + return PlayerClass::Assault; + } + if (m_World->HasComponent(player.ID, "ShieldAbility")) { + return PlayerClass::Defender; + } + if (m_World->HasComponent(player.ID, "SprintAbility")) { + return PlayerClass::Sniper; + } + return PlayerClass::None; +} bool AmmoPickupSystem::OnTriggerTouch(Events::TriggerTouch& e) { + if (!e.Entity.Valid()) { + return false; + } //TODO: add other weapontypes - if (!e.Entity.HasComponent("AssaultWeapon")) { + if (DetermineClass(e.Entity) == PlayerClass::None) { return false; } if (!e.Trigger.HasComponent("AmmoPickup")) { return false; } - //cant pick up ammopacks if you are already at MaxAmmo - if ((int)e.Entity["AssaultWeapon"]["Ammo"] >= (int)e.Entity["AssaultWeapon"]["MaxAmmo"]) { + //if at maxammo, save the trigger-touch to a vector since standing inside it will not re-trigger the trigger + if (DoesPlayerHaveMaxAmmo(e.Entity)) { m_PickupAtMaximum.push_back({ e.Entity, e.Trigger }); return false; } DoPickup(e.Entity, e.Trigger); + return true; +} + +bool AmmoPickupSystem::OnAmmoPickup(Events::AmmoPickup & e) +{ + if (!e.Player.Valid()) { + return false; + } + //TODO: add other weapontypes + if (DetermineClass(e.Player) == PlayerClass::None) { + return false; + } + //cant pick up ammopacks if you are already at MaxAmmo + if (DoesPlayerHaveMaxAmmo(e.Player)) { + return false; + } + SetPlayerAmmo(e.Player, e.AmmoGain); return true; } + bool AmmoPickupSystem::OnTriggerLeave(Events::TriggerLeave& e) { + if (!e.Trigger.HasComponent("AmmoPickup")) { + return false; + } //triggerleave erases possible m_PickupAtMaximum for (auto& it = m_PickupAtMaximum.begin(); it != m_PickupAtMaximum.end(); ++it) { - if (it->pickup.ID == e.Trigger.ID && it->player.ID == e.Entity.ID) { + if (it->trigger.ID == e.Trigger.ID && it->player.ID == e.Entity.ID) { m_PickupAtMaximum.erase(it); break; - } } return true; } + void AmmoPickupSystem::DoPickup(EntityWrapper &player, EntityWrapper &trigger) { - int maxWeaponAmmo = (int)player["AssaultWeapon"]["MaxAmmo"]; - int& currentAmmo = (int)player["AssaultWeapon"]["Ammo"]; + //trigger should be valid but if it isnt we just return (to avoid crash) + if (!trigger.Valid()) { + return; + } + int maxWeaponAmmo = GetPlayerMaxAmmo(player); int ammoGiven = 0.01*(double)trigger["AmmoPickup"]["AmmoGain"] * maxWeaponAmmo; - //personEntered = e.Entity, thingEntered = e.Trigger Events::AmmoPickup ePlayerAmmoPickup; ePlayerAmmoPickup.AmmoGain = ammoGiven; ePlayerAmmoPickup.Player = player; m_EventBroker->Publish(ePlayerAmmoPickup); - //immediately give the player the ammo - currentAmmo = std::min(currentAmmo + ammoGiven, maxWeaponAmmo); - //copy position, ammogain, respawntimer (twice since one of the values will be counted down to 0, the other will be set in the new object) //we need to copy all values since each value can be different for each ammoPickup - m_ETriggerTouchVector.push_back({ trigger["Transform"]["Position"], trigger["AmmoPickup"]["AmmoGain"], + m_ETriggerTouchVector.push_back({ (glm::vec3)trigger["Transform"]["Position"], trigger["AmmoPickup"]["AmmoGain"], trigger["AmmoPickup"]["RespawnTimer"], trigger["AmmoPickup"]["RespawnTimer"], m_World->GetParent(trigger.ID) }); //delete the ammopickup m_World->DeleteEntity(trigger.ID); -} \ No newline at end of file +} diff --git a/src/Game/Systems/AmmunitionHUDSystem.cpp b/src/Game/Systems/AmmunitionHUDSystem.cpp deleted file mode 100644 index c9d87072..00000000 --- a/src/Game/Systems/AmmunitionHUDSystem.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#include "Game/Systems/AmmunitionHUDSystem.h" - -void AmmunitionHUDSystem::Update(double dt) -{ - //Hud element for tracking ammunition from parent with AssaultWeapon component.Child with the name "MagazineAmmo" tracks clip ammunition.Child with the name "Ammo" tracks ammo. - - auto ammunitionHUDs = m_World->GetComponents("AmmunitionHUD"); - if (ammunitionHUDs == nullptr) { - return; - } - - for (auto& ammunitionHUDComponent : *ammunitionHUDs) { - EntityWrapper entity = EntityWrapper(m_World, ammunitionHUDComponent.EntityID); - - EntityWrapper playerEntity = entity.FirstParentWithComponent("AssaultWeapon"); - - if (!playerEntity.Valid()) { - return; - } - - - EntityWrapper magazineAmmo = entity.FirstChildByName("MagazineAmmo"); - if(magazineAmmo.Valid()) { - if(magazineAmmo.HasComponent("Text")) { - (std::string&)magazineAmmo["Text"]["Content"] = std::to_string((int)playerEntity["AssaultWeapon"]["MagazineAmmo"]); - } - } - - EntityWrapper ammo = entity.FirstChildByName("Ammo"); - if (ammo.Valid()) { - if (ammo.HasComponent("Text")) { - (std::string&)ammo["Text"]["Content"] = std::to_string((int)playerEntity["AssaultWeapon"]["Ammo"]); - } - } - } -} diff --git a/src/Game/Systems/BoostIconsHUDSystem.cpp b/src/Game/Systems/BoostIconsHUDSystem.cpp new file mode 100644 index 00000000..1f0331e2 --- /dev/null +++ b/src/Game/Systems/BoostIconsHUDSystem.cpp @@ -0,0 +1,44 @@ +#include "Game/Systems/BoostIconsHUDSystem.h" + +void BoostIconsHUDSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& capturePoint, double dt) +{ + EntityWrapper assaultEntity = entity.FirstChildByName("Assault"); + EntityWrapper defenderEntity = entity.FirstChildByName("Defender"); + EntityWrapper sniperEntity = entity.FirstChildByName("Sniper"); + EntityWrapper player = entity.FirstParentWithComponent("Player"); + + + if(assaultEntity.Valid()) { + if (assaultEntity.HasComponent("Fill")) { + EntityWrapper assaultBoost = player.FirstChildByName("BoostAssault"); + if (assaultBoost.Valid()) { + (Field)assaultEntity["Fill"]["Percentage"] = 1.0; + } else { + (Field)assaultEntity["Fill"]["Percentage"] = 0.0; + } + } + } + + if (defenderEntity.Valid()) { + if (defenderEntity.HasComponent("Fill")) { + EntityWrapper defenderBoost = player.FirstChildByName("BoostDefender"); + if (defenderBoost.Valid()) { + (Field)defenderEntity["Fill"]["Percentage"] = 1.0; + } else { + (Field)defenderEntity["Fill"]["Percentage"] = 0.0; + } + } + } + + if (sniperEntity.Valid()) { + if (sniperEntity.HasComponent("Fill")) { + EntityWrapper sniperBoost = player.FirstChildByName("BoostSniper"); + if (sniperBoost.Valid()) { + (Field)sniperEntity["Fill"]["Percentage"] = 1.0; + } else { + (Field)sniperEntity["Fill"]["Percentage"] = 0.0; + } + } + } +} + diff --git a/src/Game/Systems/BoostSystem.cpp b/src/Game/Systems/BoostSystem.cpp new file mode 100644 index 00000000..5a04e3f8 --- /dev/null +++ b/src/Game/Systems/BoostSystem.cpp @@ -0,0 +1,113 @@ +#include "Systems/BoostSystem.h" + +BoostSystem::BoostSystem(SystemParams params) + : System(params) +{ + EVENT_SUBSCRIBE_MEMBER(m_EPlayerDamage, &BoostSystem::OnPlayerDamage); +} + +bool BoostSystem::OnPlayerDamage(Events::PlayerDamage& e) +{ + + + if (e.Victim == e.Inflictor) { + return false; + } + + if (!e.Victim.Valid() || !e.Inflictor.Valid()) { + return false; + } + + + //if its not friendly fire, return + if ((int)m_World->GetComponent(e.Inflictor.ID, "Team")["Team"] != (int)m_World->GetComponent(e.Victim.ID, "Team")["Team"]) { + return false; + } + + //determine the inflictors class + auto className = DetermineClass(e.Inflictor); + if (className == "") { + return false; + } + + if (className == "SidearmWeapon") { // give ammo + giveAmmo(e.Inflictor, e.Victim); + } else { //give boost + if (!IsServer) { + return false; + } + //get the XML file, example: "Schema/Entities/BoostclassName.xml" + std::string classXML = "Schema/Entities/" + className + ".xml"; + + //check if player already has a child with the component, if so delete that child + auto playerBoostAssaultEntity = e.Victim.FirstChildByName(className); + if (playerBoostAssaultEntity.Valid()) { + m_World->DeleteEntity(playerBoostAssaultEntity.ID); + } + //load boost XML file, set it entity parented with the victim player + auto entityFile = ResourceManager::Load(classXML); + EntityWrapper boostAssaultEntity = entityFile->MergeInto(m_World); + m_World->SetName(boostAssaultEntity.ID, className); + m_World->SetParent(boostAssaultEntity.ID, e.Victim.ID); + } + + + return true; +} + +std::string BoostSystem::DetermineClass(EntityWrapper inflictorPlayer) +{ + //determine the class based on what component the inflictor-player has + if (inflictorPlayer.HasComponent("Player")) { + if ((std::string)inflictorPlayer["Player"]["CurrentWeapon"] == "AssaultWeapon") { + return "BoostAssault"; + } + if ((std::string)inflictorPlayer["Player"]["CurrentWeapon"] == "DefenderWeapon") { + return "BoostDefender"; + } + if ((std::string)inflictorPlayer["Player"]["CurrentWeapon"] == "SniperWeapon") { + return "BoostSniper"; + } + if ((std::string)inflictorPlayer["Player"]["CurrentWeapon"] == "SidearmWeapon") { + return "SidearmWeapon"; + } + } + return ""; +} + +void BoostSystem::giveAmmo(EntityWrapper giver, EntityWrapper receiver) +{ + if (receiver.HasComponent("AssaultWeapon")) { + int magazineSize = receiver["AssaultWeapon"]["MagazineSize"]; + Field magazineAmmo = receiver["AssaultWeapon"]["MagazineAmmo"]; + int prevMagazineAmmo = receiver["AssaultWeapon"]["MagazineAmmo"]; + int maxAmmo = receiver["AssaultWeapon"]["MaxAmmo"]; + Field ammo = receiver["AssaultWeapon"]["Ammo"]; + + int givenAmmo = 20; + + magazineAmmo = glm::clamp(magazineAmmo + givenAmmo, 0, magazineSize); + if (magazineAmmo > prevMagazineAmmo) { + givenAmmo = prevMagazineAmmo + givenAmmo - magazineSize; + } + if (givenAmmo > 0) { + ammo = glm::clamp(ammo + givenAmmo, 0, maxAmmo); + } + } else if (receiver.HasComponent("DefenderWeapon")) { + int magazineSize = receiver["DefenderWeapon"]["MagazineSize"]; + Field magazineAmmo = receiver["DefenderWeapon"]["MagazineAmmo"]; + int prevMagazineAmmo = receiver["DefenderWeapon"]["MagazineAmmo"]; + int maxAmmo = receiver["DefenderWeapon"]["MaxAmmo"]; + Field ammo = receiver["DefenderWeapon"]["Ammo"]; + + int givenAmmo = 3; + + magazineAmmo = glm::clamp(magazineAmmo + givenAmmo, 0, magazineSize); + if (magazineAmmo > prevMagazineAmmo) { + givenAmmo = prevMagazineAmmo + givenAmmo - magazineSize; + } + if (givenAmmo > 0) { + ammo = glm::clamp(ammo + givenAmmo, 0, maxAmmo); + } + } +} diff --git a/src/Game/Systems/CapturePointArrowHUDSystem.cpp b/src/Game/Systems/CapturePointArrowHUDSystem.cpp new file mode 100644 index 00000000..e0b0297c --- /dev/null +++ b/src/Game/Systems/CapturePointArrowHUDSystem.cpp @@ -0,0 +1,183 @@ +#include "Systems/CapturePointArrowHUDSystem.h" + +CapturePointArrowHUDSystem::CapturePointArrowHUDSystem(SystemParams params) + : System(params) + , ImpureSystem() +{ + EVENT_SUBSCRIBE_MEMBER(m_ECapturedEvent, &CapturePointArrowHUDSystem::OnCapturePointCaptured); +} + + +void CapturePointArrowHUDSystem::Update(double dt) +{ + bool loadCheck = true; + int redTeamEnum; + int blueTeamEnum; + int spectatorTeamEnum; + + //Get list for all CapturePointArrowHUDComponents + auto arrowHUDs = m_World->GetComponents("CapturePointArrowHUD"); + auto capturePoints = m_World->GetComponents("CapturePoint"); + if(arrowHUDs == nullptr) { + return; + } + + for(auto& cArrowHUD : *arrowHUDs) { + //Get what team the current arrow corresponds to + EntityWrapper arrowEntity = EntityWrapper(m_World, cArrowHUD.EntityID); + if (!arrowEntity.Valid()) { + continue; + } + if(!arrowEntity.HasComponent("Team")) { + continue; + } + auto cTeam = arrowEntity["Team"]; + int currentTeam = (int)cTeam["Team"]; + + if (loadCheck) { + redTeamEnum = (int)cTeam["Team"].Enum("Red"); + blueTeamEnum = (int)cTeam["Team"].Enum("Blue"); + spectatorTeamEnum = (int)cTeam["Team"].Enum("Spectator"); + loadCheck = false; + + + if (!m_InitialtargetsSet) { + std::unordered_map blueTargets, redTargets; + EntityWrapper homeBlue, homeRed; + int lastCP = -INFINITY; + int firstCP = INFINITY; + + for (auto& cCP : *capturePoints) { + auto homePointTeam = (int)cCP["HomePointForTeam"]; + EntityWrapper capturePointEntity = EntityWrapper(m_World, cCP.EntityID); + int capturePointID = (int)capturePointEntity["CapturePoint"]["CapturePointNumber"]; + + if(capturePointID < firstCP) { + firstCP = capturePointID; + } + + if(capturePointID > lastCP) { + lastCP = capturePointID; + } + + if (!capturePointEntity.HasComponent("Team")) { + continue; + } + + int currentOwner = (int)capturePointEntity["Team"]["Team"]; + + if(currentOwner != redTeamEnum) { + //This capturePoint is not owned by the red team and is therefor an eligible target for red team + 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 = TransformSystem::AbsolutePosition(capturePointEntity); + blueTargets.insert(std::pair(capturePointID, targetPos)); + } + + if(homePointTeam == blueTeamEnum) { + //CP is the home point for blue team. + homeBlue = capturePointEntity; + } else if (homePointTeam == redTeamEnum) { + //CP is the home point for red team. + homeRed = capturePointEntity; + } + } + + if(!homeRed.Valid() || !homeBlue.Valid()) { + //One or both teams have no home point, cant continue + return; + } + + std::unordered_map::const_iterator got; + //Find next target for red team. + if((int)homeRed["CapturePoint"]["CapturePointNumber"] == lastCP) { + //Red home base is the last capture point, count back from lastCP and find next target + for (int i = lastCP; i >= firstCP; i--) { + got = redTargets.find(i); + if(got == redTargets.end()) { + continue; + } else { + m_RedTeamCurrentTarget = got->second; + break; + } + } + } else if ((int)homeRed["CapturePoint"]["CapturePointNumber"] == firstCP) { + //Red home is the first capture point, count forward from firstCP and find next target. + for (int i = firstCP; i <= lastCP; i++) { + got = redTargets.find(i); + if(got == redTargets.end()) { + //Target was not found, try the next one after that. + continue; + } else { + m_RedTeamCurrentTarget = got->second; + break; + } + } + } + + //Find next target for blue team + if ((int)homeBlue["CapturePoint"]["CapturePointNumber"] == lastCP) { + //Red home base is the last capture point, count back from lastCP and find next target + for (int i = lastCP; i >= firstCP; i--) { + got = blueTargets.find(i); + if (got == blueTargets.end()) { + continue; + } else { + m_BlueTeamCurrentTarget = got->second; + break; + } + } + } else if ((int)homeBlue["CapturePoint"]["CapturePointNumber"] == firstCP) { + //Red home is the first capture point, count forward from firstCP and find next target. + for (int i = firstCP; i <= lastCP; i++) { + got = blueTargets.find(i); + if (got == blueTargets.end()) { + //Target was not found, try the next one after that. + continue; + } else { + m_BlueTeamCurrentTarget = got->second; + break; + } + } + } + } + } + //if red team, get red team next point, otherwise blue team next point. + //Untill this is awailable we will just use the hardcoded value in the component. + //This will also give us a position, so we wont need to loop through all capturePoints. + glm::vec3 pos; + if(currentTeam == redTeamEnum) { + pos = m_RedTeamCurrentTarget; + } else if (currentTeam == blueTeamEnum) { + pos = m_BlueTeamCurrentTarget; + } + + 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); + EntityWrapper parent = arrowEntity.Parent(); + if (parent.Valid()) { + arrowOri -= TransformSystem::AbsoluteOrientationEuler(parent); + } + } +} + +bool CapturePointArrowHUDSystem::OnCapturePointCaptured(Events::Captured& e) +{ + if(!e.BlueTeamNextCapturePoint.Valid() || !e.RedTeamNextCapturePoint.Valid()) { + return 0; + } + + 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 6f1392e0..1c0b1f8e 100644 --- a/src/Game/Systems/CapturePointHUDSystem.cpp +++ b/src/Game/Systems/CapturePointHUDSystem.cpp @@ -9,7 +9,7 @@ CapturePointHUDSystem::CapturePointHUDSystem(SystemParams params) void CapturePointHUDSystem::Update(double dt) { - bool LoadCheck = true; + bool loadCheck = true; int redTeam; int blueTeam; int spectatorTeam; @@ -35,11 +35,11 @@ void CapturePointHUDSystem::Update(double dt) //Check if the HUD corresponds to the Capture Point Number if (HUD_ID == (int)entityCP["CapturePoint"]["CapturePointNumber"]) { ComponentWrapper& teamComponent = entityCP["Team"]; - if (LoadCheck) { + if (loadCheck) { redTeam = (int)teamComponent["Team"].Enum("Red"); blueTeam = (int)teamComponent["Team"].Enum("Blue"); spectatorTeam = (int)teamComponent["Team"].Enum("Spectator"); - LoadCheck = false; + loadCheck = false; } //Color hud with team color auto capturePointTeam = (int)teamComponent["Team"]; @@ -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 c99a36a6..6739b814 100644 --- a/src/Game/Systems/CapturePointSystem.cpp +++ b/src/Game/Systems/CapturePointSystem.cpp @@ -6,24 +6,45 @@ CapturePointSystem::CapturePointSystem(SystemParams params) , PureSystem("CapturePoint") { //subscribe/listenTo playerdamage,healthpickup events (using the eventBroker) - if (!IsClient) { + if (IsServer) { 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 //NOTE: needs to run each frame, since we're possibly modifying the captureTimer for the capturePoints by dt void CapturePointSystem::UpdateComponent(EntityWrapper& capturePointEntity, ComponentWrapper& cCapturePoint, double dt) { - if (IsClient) { + if (!IsServer) { return; } 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; } @@ -69,6 +90,7 @@ void CapturePointSystem::UpdateComponent(EntityWrapper& capturePointEntity, Comp int ownedBy = teamComponent["Team"]; int redTeamPlayersStandingInside = 0; int blueTeamPlayersStandingInside = 0; + //note: old color system if (capturePointEntity.HasComponent("Model")) { //Now sets team color to the capturepoint, or white if it is uncaptured. capturePointEntity["Model"]["Color"] = ownedBy == blueTeam ? glm::vec4(0, 0.0f, 1, 0.3) : ownedBy == redTeam ? glm::vec4(1, 0.0f, 0, 0.3) : glm::vec4(1, 1, 1, 0.3); @@ -103,6 +125,23 @@ void CapturePointSystem::UpdateComponent(EntityWrapper& capturePointEntity, Comp } } + if (m_RecentlyCapturedNeedNextCapturePointNow) { + //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").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 + m_CapturedEvent.BlueTeamNextCapturePoint = m_CapturePointNumberToEntityMap[nextPossibleCapturePoint["Blue"]]; + m_CapturedEvent.RedTeamNextCapturePoint = m_CapturePointNumberToEntityMap[nextPossibleCapturePoint["Red"]]; + m_EventBroker->Publish(m_CapturedEvent); + m_RecentlyCapturedNeedNextCapturePointNow = false; + } + //reset timers and reset the bool that triggers this if (m_ResetTimers) { for (int i = 0; i < m_NumberOfCapturePoints; i++) { @@ -188,10 +227,9 @@ void CapturePointSystem::UpdateComponent(EntityWrapper& capturePointEntity, Comp teamComponent["Team"] = currentTeam; cCapturePoint["CaptureTimer"] = glm::sign((double)cCapturePoint["CaptureTimer"])*captureTimeToTakeOver; //publish Captured event - Events::Captured e; - e.CapturePointID = cCapturePoint.EntityID; - e.TeamNumberThatCapturedCapturePoint = currentTeam; - m_EventBroker->Publish(e); + m_RecentlyCapturedNeedNextCapturePointNow = true; + m_CapturedEvent.CapturePointTakenID = cCapturePoint.EntityID; + m_CapturedEvent.TeamNumberThatCapturedCapturePoint = currentTeam; //NextPossibleCapturePoint will be calculated in the next update... } } @@ -215,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 @@ -239,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 ca26052d..8783816f 100644 --- a/src/Game/Systems/DamageIndicatorSystem.cpp +++ b/src/Game/Systems/DamageIndicatorSystem.cpp @@ -8,12 +8,13 @@ DamageIndicatorSystem::DamageIndicatorSystem(SystemParams params) EVENT_SUBSCRIBE_MEMBER(m_ESetCamera, &DamageIndicatorSystem::OnSetCamera); //load texture to cache - auto texture = CommonFunctions::LoadTexture("Textures/DamageIndicator.png", false); - auto entityFile = ResourceManager::Load("Schema/Entities/DamageIndicator.xml"); + auto texture = CommonFunctions::TryLoadResource("Textures/DamageIndicator.png"); + auto entityFile = ResourceManager::Load("Schema/Entities/DamageIndicator.xml"); + m_NetworkEnabled = ResourceManager::Load("Config.ini")->Get("Networking.StartNetwork", false); } void DamageIndicatorSystem::Update(double dt) { - if (!IsServer && LocalPlayer.Valid()) { + if ((!IsServer || !m_NetworkEnabled) && LocalPlayer.Valid()) { for (auto& iter = updateDamageIndicatorVector.begin(); iter != updateDamageIndicatorVector.end(); iter++) { if (!iter->spriteEntity.Valid()) { updateDamageIndicatorVector.erase(iter); @@ -40,25 +41,28 @@ bool DamageIndicatorSystem::OnPlayerDamage(Events::PlayerDamage& e) return false; } + //friendly fire - return + if (e.Damage < 0.1f) { + return false; + } + glm::vec3 inflictorPos = e.Inflictor["Transform"]["Position"]; //if testing #ifdef INDICATOR_TEST - inflictorPos = DamageIndicatorTest(e.Victim); + inflictorPos = DamageIndicatorTest(e.Victim); #endif float angleBetweenVectors = CalculateAngle(e.Victim, inflictorPos); //load & set the "2d" sprite auto entityFile = ResourceManager::Load("Schema/Entities/DamageIndicator.xml"); - EntityFileParser parser(entityFile); - EntityID spriteID = parser.MergeEntities(m_World); - m_World->SetParent(spriteID, m_CurrentCamera); - auto spriteWrapper = EntityWrapper(m_World, spriteID); + EntityWrapper sprite = entityFile->MergeInto(m_World); + m_World->SetParent(sprite.ID, m_CurrentCamera); //simply set the rotation z-wise to the angleBetweenVectors - spriteWrapper["Transform"]["Orientation"] = glm::vec3(0, 0, angleBetweenVectors); + sprite["Transform"]["Orientation"] = glm::vec3(0, 0, angleBetweenVectors); - if (!IsServer) { - updateDamageIndicatorVector.emplace_back(spriteWrapper, inflictorPos); + if (!IsServer || !m_NetworkEnabled) { + updateDamageIndicatorVector.emplace_back(sprite, inflictorPos); } return true; @@ -83,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)); @@ -124,11 +128,11 @@ glm::vec3 DamageIndicatorSystem::DamageIndicatorTest(EntityWrapper player) { } m_TestVar++; - auto inflictorPos = glm::vec3(currentPos.x + testVar*6.0f, currentPos.y, currentPos.z + testVar2*6.0f); + auto inflictorPos = glm::vec3(currentPos.x + testVar*6.0f, currentPos.y, currentPos.z + testVar2*6.0f); //load the explosioneffect XML - auto deathEffect = ResourceManager::Load("Schema/Entities/PlayerDeathExplosionWithCamera.xml"); - EntityFileParser parser(deathEffect); + auto deathEffect = ResourceManager::Load("Schema/Entities/PlayerDeathExplosionWithCamera.xml"); + EntityXMLFileParser parser(deathEffect); EntityID deathEffectID = parser.MergeEntities(m_World); EntityWrapper deathEffectEW = EntityWrapper(m_World, deathEffectID); diff --git a/src/Game/Systems/EndScreenSystem.cpp b/src/Game/Systems/EndScreenSystem.cpp new file mode 100644 index 00000000..59c261bd --- /dev/null +++ b/src/Game/Systems/EndScreenSystem.cpp @@ -0,0 +1,74 @@ +#include "Systems/EndScreenSystem.h" + + +EndScreenSystem::EndScreenSystem(SystemParams params) + : System(params) + , ImpureSystem() +{ + EVENT_SUBSCRIBE_MEMBER(m_EWin, &EndScreenSystem::OnWin); +} + +void EndScreenSystem::Update(double dt) +{ + +} + +bool EndScreenSystem::OnWin(const Events::Win& e) +{ + auto endScreenCameras = m_World->GetComponents("EndScreen"); + if(endScreenCameras == nullptr) { + LOG_ERROR("Win event recieved but no Endscreen camera is present."); + return 1; + } + for(auto& camera : *endScreenCameras) { + EntityWrapper entity = EntityWrapper(m_World, camera.EntityID); + + Events::SetCamera event; + event.CameraEntity = entity; + m_EventBroker->Publish(event); + + EntityWrapper redSprite = entity.FirstChildByName("SpriteRed"); + EntityWrapper blueSprite = entity.FirstChildByName("SpriteBlue"); + EntityWrapper redText = entity.FirstChildByName("TextRed"); + EntityWrapper blueText = entity.FirstChildByName("TextBlue"); + + if (e.TeamThatWon == 2) { + //Red team won + if(redSprite.HasComponent("Sprite")) + (Field)redSprite["Sprite"]["Visible"] = true; + if (redText.HasComponent("Text")) + (Field)redText["Text"]["Visible"] = true; + + if (blueSprite.HasComponent("Sprite")) + (Field)blueSprite["Sprite"]["Visible"] = false; + if (blueText.HasComponent("Text")) + (Field)blueText["Text"]["Visible"] = false; + + }else if (e.TeamThatWon == 3) { + //Blue team won + if (redSprite.HasComponent("Sprite")) + (Field)redSprite["Sprite"]["Visible"] = false; + if (redText.HasComponent("Text")) + (Field)redText["Text"]["Visible"] = false; + + if (blueSprite.HasComponent("Sprite")) + (Field)blueSprite["Sprite"]["Visible"] = true; + if (blueText.HasComponent("Text")) + (Field)blueText["Text"]["Visible"] = true; + } else { + //No team won? + if (redSprite.HasComponent("Sprite")) + (Field)redSprite["Sprite"]["Visible"] = false; + if (blueSprite.HasComponent("Sprite")) + (Field)blueSprite["Sprite"]["Visible"] = false; + + if (redText.HasComponent("Text")) + (Field)redText["Text"]["Visible"] = false; + if (blueText.HasComponent("Text")) + (Field)blueText["Text"]["Visible"] = false; + } + } + + + return 1; +} diff --git a/src/Game/Systems/ExplosionEffectSystem.cpp b/src/Game/Systems/ExplosionEffectSystem.cpp index 2704d2da..f3d43cb4 100644 --- a/src/Game/Systems/ExplosionEffectSystem.cpp +++ b/src/Game/Systems/ExplosionEffectSystem.cpp @@ -2,13 +2,20 @@ void ExplosionEffectSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) { - if ((double)component["TimeSinceDeath"] > (double)component["ExplosionDuration"]) { - (double)component["TimeSinceDeath"] = 0.f; + Field delay = component["Delay"]; + if (delay > 0) { + delay = std::max(0.0, delay - dt); } - (double&)component["TimeSinceDeath"] += dt; - //if ((bool)Component["Gravity"] == true) { - // (bool)Component["ExponentialAccelaration"] = false; - //} + 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/FadeSystem.cpp b/src/Game/Systems/FadeSystem.cpp new file mode 100644 index 00000000..f0e83eb5 --- /dev/null +++ b/src/Game/Systems/FadeSystem.cpp @@ -0,0 +1,49 @@ +#include "Systems/FadeSystem.h" + +void FadeSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& cFade, double dt) +{ + double dTime = dt; + if (dTime == 0.0) { + return; + } + + if (!entity.Valid()) { + return; + } + + if ((bool)cFade["Out"]) { + dTime *= -1; + } + + if((bool)cFade["Reverse"]) { + dTime *= 2; + } + + double fadeTime = cFade["FadeTime"]; + Field currentTime = cFade["Time"]; + currentTime += dTime; + + if(currentTime > fadeTime) { + currentTime = 0.0 + fadeTime * (bool)cFade["Loop"]; + if ((bool)cFade["Reverse"]) { + (Field)cFade["Out"] = !(bool)cFade["Out"]; + currentTime = fadeTime; + } + } + if(currentTime < 0.0) { + currentTime = fadeTime * (bool)cFade["Loop"]; + if ((bool)cFade["Reverse"]) { + (Field)cFade["Out"] = !(bool)cFade["Out"]; + currentTime = 0.0; + } + } + double ratio = currentTime/fadeTime; + + if(entity.HasComponent("Model")){ + ((Field)entity["Model"]["Color"]).w(ratio); + } + if (entity.HasComponent("Sprite")) { + ((Field)entity["Sprite"]["Color"]).w(ratio); + + } +} \ No newline at end of file diff --git a/src/Game/Systems/HealthHUDSystem.cpp b/src/Game/Systems/HealthHUDSystem.cpp index 74258d6e..70ccf465 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")) { + double health = (const double&)entityIDParent["Health"]["Health"]; + double maxHealth = (const double&)entityIDParent["Health"]["MaxHealth"]; 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; + double health = (const double&)entityIDParent["Health"]["Health"]; + double maxHealth = (const double&)entityIDParent["Health"]["MaxHealth"]; + 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 94f23c67..a6ff96a0 100644 --- a/src/Game/Systems/HealthSystem.cpp +++ b/src/Game/Systems/HealthSystem.cpp @@ -12,15 +12,7 @@ HealthSystem::HealthSystem(SystemParams params) } void HealthSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& cHealth, double dt) -{ - double& health = cHealth["Health"]; - if (health <= 0.0) { - Events::PlayerDeath ePlayerDeath; - ePlayerDeath.Player = entity; - m_EventBroker->Publish(ePlayerDeath); - //Note: we will delete the entity in PlayerDeathSystem - } -} +{ } bool HealthSystem::OnPlayerDamaged(Events::PlayerDamage& e) { @@ -29,8 +21,22 @@ bool HealthSystem::OnPlayerDamaged(Events::PlayerDamage& e) } ComponentWrapper cHealth = e.Victim["Health"]; - double& health = cHealth["Health"]; - health -= e.Damage; + 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()) { + e.Damage -= (const double&)playerBoostDefenderEntity["BoostDefender"]["StrengthOfEffect"]; + } + if (health > 0 && e.Damage > 0) { + health -= e.Damage; + if (health <= 0.0) { + Events::PlayerDeath ePlayerDeath; + ePlayerDeath.Player = e.Victim; + ePlayerDeath.Killer = e.Inflictor; + m_EventBroker->Publish(ePlayerDeath); + //Note: we will delete the entity in PlayerDeathSystem + } + } return true; } @@ -50,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(*health, (const 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..01a474ad 100644 --- a/src/Game/Systems/KillFeedSystem.cpp +++ b/src/Game/Systems/KillFeedSystem.cpp @@ -7,19 +7,20 @@ void KillFeedSystem::Update(double dt) return; } + for (auto it = m_DeathQueue.begin(); it != m_DeathQueue.end(); it++) { + (*it).TimeToLive -= dt; + } + for (auto& killFeedComponent : *killFeeds) { EntityWrapper entity = EntityWrapper(m_World, killFeedComponent.EntityID); 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"] = ""; } } - - - - + int feedIndex = 1; for (auto it = m_DeathQueue.begin(); it != m_DeathQueue.end(); ) { bool remove = false; @@ -27,14 +28,19 @@ 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; - (*it).TimeToLive -= dt; + std::string str = ""; + //Add killer to the start of string. + str = (*it).KillerColor + "\\" + std::to_string((*it).KillerClass) + "\\CFFFFFF" + " " + (*it).KillerName + " "; + //Add Weapon to middle of string. + str += "\\" + std::to_string((*it).KillerClass+3) + " "; + //Add victim to the end of string + str += (*it).VictimColor + "\\" + std::to_string((*it).VictimClass) + "\\CFFFFFF" + " " + (*it).VictimName; + + (Field)child["Text"]["Content"] = str; if ((*it).TimeToLive <= 0.f) { - (std::string&)child["Text"]["Content"] = ""; - (glm::vec4&)child["Text"]["Color"] = (*it).Color; + (Field)child["Text"]["Content"] = ""; remove = true; } } @@ -52,29 +58,30 @@ void KillFeedSystem::Update(double dt) } } -bool KillFeedSystem::OnPlayerDeath(Events::PlayerDeath& e) +bool KillFeedSystem::OnPlayerKillDeath(Events::KillDeath& e) { - KillFeedInfo kfInfo; + KillFeedInfo info; - if (e.Player.HasComponent("Team")) { - int red = e.Player["Team"].Enum("Team", "Red"); - int blue = e.Player["Team"].Enum("Team", "Blue"); - - if ((int)e.Player["Team"]["Team"] == red) { - kfInfo.Content = "Blue Player killed Red Player"; - kfInfo.Color = glm::vec4(0.f, 0.2f, 1.f, 0.8f); - m_DeathQueue.push_back(kfInfo); - } else if ((int)e.Player["Team"]["Team"] == blue) { - kfInfo.Content = "Red Player killed blue Player"; - kfInfo.Color = glm::vec4(1.f, 0.f, 0.f, 0.8f); - m_DeathQueue.push_back(kfInfo); - } + info.KillerName = e.KillerName; + info.KillerID = e.Killer; + info.KillerClass = e.KillerClass; + info.KillerTeam = e.KillerTeam; + if(info.KillerTeam == 2){ + info.KillerColor = m_BlueColor; + } else if (info.KillerTeam == 3) { + info.KillerColor = m_RedColor; } - - if(m_DeathQueue.size() > 3) { - m_DeathQueue.pop_front(); + info.VictimName = e.CasualtyName; + info.VictimID = e.Casualty; + info.VictimClass = e.CasualtyClass; + info.VictimTeam = e.CasualtyTeam; + if (info.VictimTeam == 2) { + info.VictimColor = m_BlueColor; + } else if (info.VictimTeam == 3) { + info.VictimColor = m_RedColor; } - return true; + m_DeathQueue.push_back(info); + return 1; } 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 new file mode 100644 index 00000000..1be751f0 --- /dev/null +++ b/src/Game/Systems/MainMenuSystem.cpp @@ -0,0 +1,142 @@ +#include "../Game/Systems/MainMenuSystem.h" + +MainMenuSystem::MainMenuSystem(SystemParams params, IRenderer* renderer) + : System(params) + , ImpureSystem() + , m_Renderer(renderer) +{ + EVENT_SUBSCRIBE_MEMBER(m_EPressed, &MainMenuSystem::OnButtonPress); + EVENT_SUBSCRIBE_MEMBER(m_EReleased, &MainMenuSystem::OnButtonRelease); + EVENT_SUBSCRIBE_MEMBER(m_EClicked, &MainMenuSystem::OnButtonClick); + EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &MainMenuSystem::OnInputCommand); +} + +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) +{ + EntityWrapper entity = e.Entity; + if (entity.Name() == "ServerIdentityConnect") { + EntityWrapper serverIdentityEntity = entity.FirstParentWithComponent("ServerIdentity"); + if(serverIdentityEntity.Valid()) { + Events::ConnectRequest event; + event.IP = (std::string)serverIdentityEntity["ServerIdentity"]["IP"]; + event.Port = (int)serverIdentityEntity["ServerIdentity"]["Port"]; + 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; +} + +bool MainMenuSystem::OnButtonRelease(const Events::ButtonReleased& e) +{ + return true; +} + +bool MainMenuSystem::OnButtonPress(const Events::ButtonPressed& e) +{ + return true; +} + +bool MainMenuSystem::OnInputCommand(const Events::InputCommand& e) +{ + if(e.Command == "Play" && e.Value == 1) { + 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); + } else if (e.Command == "Quit" && e.Value == 1) { + exit(EXIT_FAILURE); + } + return true; +} \ No newline at end of file diff --git a/src/Game/Systems/PickupSpawnSystem.cpp b/src/Game/Systems/PickupSpawnSystem.cpp new file mode 100644 index 00000000..c05d3bd2 --- /dev/null +++ b/src/Game/Systems/PickupSpawnSystem.cpp @@ -0,0 +1,105 @@ +#include "Systems/PickupSpawnSystem.h" + +PickupSpawnSystem::PickupSpawnSystem(SystemParams params) + : System(params) +{ + if (IsServer) { + EVENT_SUBSCRIBE_MEMBER(m_ETriggerTouch, &PickupSpawnSystem::OnTriggerTouch); + EVENT_SUBSCRIBE_MEMBER(m_ETriggerLeave, &PickupSpawnSystem::OnTriggerLeave); + } +} + +void PickupSpawnSystem::Update(double dt) +{ + if (IsServer) { + auto it = m_ETriggerTouchVector.begin(); + while (it != m_ETriggerTouchVector.end()) { + auto& somePickup = *it; + somePickup.DecreaseThisRespawnTimer -= dt; + if (somePickup.DecreaseThisRespawnTimer < 0.0) { + //spawn the new healthPickup + auto entityFile = ResourceManager::Load("Schema/Entities/HealthPickup.xml"); + EntityWrapper healthPickup = entityFile->MergeInto(m_World); + + //let the world know a pickup has spawned (graphics effects, etc) + Events::PickupSpawned ePickupSpawned; + ePickupSpawned.Pickup = healthPickup; + m_EventBroker->Publish(ePickupSpawned); + + //copy values from the old entity to the new entity + auto& newHealthPickupEntity = healthPickup; + newHealthPickupEntity["Transform"]["Position"] = somePickup.Pos; + newHealthPickupEntity["HealthPickup"]["HealthGain"] = somePickup.HealthGain; + newHealthPickupEntity["HealthPickup"]["RespawnTimer"] = somePickup.RespawnTimer; + m_World->SetParent(newHealthPickupEntity.ID, somePickup.parentID); + + //erase the current element (somePickup) + it = m_ETriggerTouchVector.erase(it); + } else { + it++; + } + } + //still touching PickupAtMaximum? + for (auto& it = m_PickupAtMaximum.begin(); it != m_PickupAtMaximum.end(); ++it) { + if (!it->player.Valid()) { + m_PickupAtMaximum.erase(it); + break; + } + if ((const double&)it->player["Health"]["Health"] < (const double&)it->player["Health"]["MaxHealth"]) { + DoPickup(it->player, it->trigger); + m_PickupAtMaximum.erase(it); + break; + } + } + } +} +bool PickupSpawnSystem::OnTriggerTouch(Events::TriggerTouch& e) +{ + if (!e.Trigger.HasComponent("HealthPickup")) { + return false; + } + //if at maxhealth, save the trigger-touch to a vector since standing inside it will not re-trigger the trigger + if ((const double&)e.Entity["Health"]["Health"] >= (const double&)e.Entity["Health"]["MaxHealth"]) { + m_PickupAtMaximum.push_back({ e.Entity, e.Trigger }); + return false; + } + + DoPickup(e.Entity, e.Trigger); + return true; +} +bool PickupSpawnSystem::OnTriggerLeave(Events::TriggerLeave& e) +{ + if (!e.Trigger.HasComponent("HealthPickup")) { + return false; + } + //triggerleave erases possible m_PickupAtMaximum + for (auto& it = m_PickupAtMaximum.begin(); it != m_PickupAtMaximum.end(); ++it) { + if (it->trigger.ID == e.Trigger.ID && it->player.ID == e.Entity.ID) { + m_PickupAtMaximum.erase(it); + break; + } + } + return true; +} +void PickupSpawnSystem::DoPickup(EntityWrapper &player, EntityWrapper &trigger) +{ + //trigger should be valid but if it isnt we just return (to avoid crash) + if (!trigger.Valid()) { + return; + } + double healthGiven = 0.01*(const double&)trigger["HealthPickup"]["HealthGain"] * (const double&)player["Health"]["MaxHealth"]; + + //only the server will increase the players hp and set it in the next delta + Events::PlayerHealthPickup ePlayerHealthPickup; + ePlayerHealthPickup.HealthAmount = healthGiven; + ePlayerHealthPickup.Player = player; + m_EventBroker->Publish(ePlayerHealthPickup); + + //copy position, healthgain, respawntimer (twice since one of the values will be counted down to 0, the other will be set in the new object) + //we need to copy all values since each value can be different for each healthPickup + m_ETriggerTouchVector.push_back({ (glm::vec3)trigger["Transform"]["Position"], trigger["HealthPickup"]["HealthGain"], + trigger["HealthPickup"]["RespawnTimer"], trigger["HealthPickup"]["RespawnTimer"], m_World->GetParent(trigger.ID) }); + + //delete the healthpickup + m_World->DeleteEntity(trigger.ID); +} diff --git a/src/Game/Systems/PlayerDeathSystem.cpp b/src/Game/Systems/PlayerDeathSystem.cpp index 844d2ed1..7b618644 100644 --- a/src/Game/Systems/PlayerDeathSystem.cpp +++ b/src/Game/Systems/PlayerDeathSystem.cpp @@ -1,14 +1,16 @@ #include "Systems/PlayerDeathSystem.h" +#include "Core/ELockMouse.h" PlayerDeathSystem::PlayerDeathSystem(SystemParams params) : System(params) { EVENT_SUBSCRIBE_MEMBER(m_OnPlayerDeath, &PlayerDeathSystem::OnPlayerDeath); + EVENT_SUBSCRIBE_MEMBER(m_EEntityDeleted, &PlayerDeathSystem::OnEntityDeleted); + EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &PlayerDeathSystem::OnInputCommand); } void PlayerDeathSystem::Update(double dt) -{ -} +{ } bool PlayerDeathSystem::OnPlayerDeath(Events::PlayerDeath& e) { @@ -27,41 +29,79 @@ bool PlayerDeathSystem::OnPlayerDeath(Events::PlayerDeath& e) void PlayerDeathSystem::createDeathEffect(EntityWrapper player) { //load the explosioneffect XML - auto deathEffect = ResourceManager::Load("Schema/Entities/PlayerDeathExplosionWithCamera.xml"); - EntityFileParser parser(deathEffect); - EntityID deathEffectID = parser.MergeEntities(m_World); - EntityWrapper deathEffectEW = EntityWrapper(m_World, deathEffectID); + auto entityFile = ResourceManager::Load("Schema/Entities/PlayerDeathExplosionWithCamera.xml"); + EntityWrapper deathEffectEW = entityFile->MergeInto(m_World); - //components that we need from player auto playerModel = player.FirstChildByName("PlayerModel"); if (!playerModel.Valid()) { + if (player == LocalPlayer) { + setSpectatorCamera(); + } return; } - if (!playerModel.HasComponent("Model") || !playerModel.HasComponent("Animation")) { + if (!playerModel.HasComponent("Model")) { return; } - auto playerEntityModel = playerModel["Model"]; - auto playerEntityAnimation = playerModel["Animation"]; - - //copy the data from player to explosioneffectmodel - playerEntityModel.Copy(deathEffectEW["Model"]); - playerEntityAnimation.Copy(deathEffectEW["Animation"]); - //freeze the animation - deathEffectEW["Animation"]["Speed1"] = 0.0; - deathEffectEW["Animation"]["Speed2"] = 0.0; - deathEffectEW["Animation"]["Speed3"] = 0.0; - - //copy the models position,orientation - deathEffectEW["Transform"]["Position"] = (glm::vec3)player["Transform"]["Position"]; - deathEffectEW["Transform"]["Orientation"] = (glm::vec3)player["Transform"]["Orientation"]; - //effect,camera is relative to playersPosition - //deathEffectEW["ExplosionEffect"]["ExplosionOrigin"] = glm::vec3(0, 0, 0); - + EntityWrapper deathEffect = playerModel.Clone(); + for (auto& cAnim : deathEffect.ChildrenWithComponent("Animation")) { + cAnim["Animation"]["Play"] = false; + } + deathEffect.AttachComponent("ExplosionEffect"); + deathEffectEW["ExplosionEffect"].Copy(deathEffect["ExplosionEffect"]); + deathEffect.AttachComponent("Lifetime"); + deathEffectEW["Lifetime"].Copy(deathEffect["Lifetime"]); + deathEffect["Transform"]["Position"] = (glm::vec3)player["Transform"]["Position"]; + deathEffect["Transform"]["Orientation"] = (glm::vec3)player["Transform"]["Orientation"]; + for (auto& cModel : deathEffect.ChildrenWithComponent("Model")) { + EntityWrapper e(m_World, cModel.ID); + e.AttachComponent("ExplosionEffect"); + deathEffectEW["ExplosionEffect"].Copy(e["ExplosionEffect"]); + } + EntityWrapper cam = deathEffectEW.FirstChildByName("Camera").Clone(deathEffect); //camera (with lifetime) behind the player if (player == LocalPlayer) { - auto cam = deathEffectEW.FirstChildByName("Camera"); + m_LocalPlayerDeathEffect = deathEffect; Events::SetCamera eSetCamera; eSetCamera.CameraEntity = cam; m_EventBroker->Publish(eSetCamera); } } + +bool PlayerDeathSystem::OnEntityDeleted(Events::EntityDeleted& e) +{ + // We only care about when the local players death effect is removed. + if (m_LocalPlayerDeathEffect != e.DeletedEntity) { + return false; + } + + // If the player hasn't spawned already, activate the spectator camera. + if (!LocalPlayer.Valid()) { + setSpectatorCamera(); + } + return true; +} + +void PlayerDeathSystem::setSpectatorCamera() +{ + // Look for the spectator camera entity in the level. + EntityWrapper spectatorCam = m_World->GetFirstEntityByName("SpectatorCamera"); + if (!spectatorCam.HasComponent("Camera")) { + return; + } + Events::SetCamera eSetCamera; + eSetCamera.CameraEntity = spectatorCam; + m_EventBroker->Publish(eSetCamera); + Events::UnlockMouse unlock; + m_EventBroker->Publish(unlock); +} + +bool PlayerDeathSystem::OnInputCommand(Events::InputCommand& e) +{ + if (e.Value == 0 || e.Command != "SwapToTeamPick" && e.Command != "SwapToClassPick") { + return false; + } + + // Ensure that we don't set spectator camera if the player deliberately changes to class/team pick. + m_LocalPlayerDeathEffect = EntityWrapper::Invalid; + return true; +} \ No newline at end of file diff --git a/src/Game/Systems/PlayerMovementSystem.cpp b/src/Game/Systems/PlayerMovementSystem.cpp index b9ce23d4..1f5050e2 100644 --- a/src/Game/Systems/PlayerMovementSystem.cpp +++ b/src/Game/Systems/PlayerMovementSystem.cpp @@ -2,9 +2,12 @@ PlayerMovementSystem::PlayerMovementSystem(SystemParams params) : System(params) + , m_SprintEffectTimer(0.f) + , m_DashEffectTimer(0.f) { EVENT_SUBSCRIBE_MEMBER(m_EPlayerSpawned, &PlayerMovementSystem::OnPlayerSpawned); EVENT_SUBSCRIBE_MEMBER(m_EDoubleJump, &PlayerMovementSystem::OnDoubleJump); + EVENT_SUBSCRIBE_MEMBER(m_EDashAbility, &PlayerMovementSystem::OnDashAbility); } PlayerMovementSystem::~PlayerMovementSystem() @@ -17,14 +20,93 @@ PlayerMovementSystem::~PlayerMovementSystem() void PlayerMovementSystem::Update(double dt) { updateMovementControllers(dt); - if (IsServer) { - for (auto& kv : m_PlayerInputControllers) { - updateVelocity(kv.first, dt); - } - } else { - if (LocalPlayer.Valid()) { + // Only do physics calculations on client and only for themselves. + if (IsClient) { + if (LocalPlayer.Valid()){ updateVelocity(LocalPlayer, dt); } + //m_SprintEffectTimer += dt; + //if (m_SprintEffectTimer < 0.016f) { + // return; + //} + //m_SprintEffectTimer = 0.f; + //auto pool = m_World->GetComponents("SprintAbility"); + //if (pool == nullptr) { + // return; + //} + //for (auto cSprint : *pool) { + // if (cSprint.EntityID != LocalPlayer.ID && (bool)cSprint["Active"]) { + // // Spawn one afterimage for each player that sprints. + // EntityWrapper player(m_World, cSprint.EntityID); + // auto entityFile = ResourceManager::Load("Schema/Entities/SprintEffect.xml"); + // EntityWrapper sprintEffect = entityFile->MergeInto(m_World); + // auto playerModel = player.FirstChildByName("PlayerModel"); + // if (!playerModel.Valid()) { + // continue; + // } + // if (!playerModel.HasComponent("Model")) { + // continue; + // } + // if (!playerModel.HasComponent("Animation")) { + // continue; + // } + // auto playerEntityModel = playerModel["Model"]; + // auto playerEntityAnimation = playerModel["Animation"]; + // playerEntityModel.Copy(sprintEffect["Model"]); + // playerEntityAnimation.Copy(sprintEffect["Animation"]); + // sprintEffect["ExplosionEffect"]["EndColor"] = (glm::vec4)playerEntityModel["Color"]; + // ((Field)sprintEffect["ExplosionEffect"]["EndColor"]).w(0.f); + // sprintEffect["Animation"]["Speed1"] = 0.0; + // sprintEffect["Animation"]["Speed2"] = 0.0; + // sprintEffect["Animation"]["Speed3"] = 0.0; + // sprintEffect["Transform"]["Position"] = (glm::vec3)player["Transform"]["Position"]; + // sprintEffect["Transform"]["Orientation"] = (glm::vec3)player["Transform"]["Orientation"]; + // } + //} + m_DashEffectTimer += dt; + if (m_DashEffectTimer < 0.075f) { + return; + } + m_DashEffectTimer = 0.f; + auto pool = m_World->GetComponents("DashAbility"); + if (pool == nullptr) { + return; + } + for (auto cDash : *pool) { + if (cDash.EntityID != LocalPlayer.ID && (double)cDash["CoolDownMaxTimer"] - (double)cDash["CoolDownTimer"] < 0.5) { + // Spawn one afterimage for each player that Dashes. + EntityWrapper player(m_World, cDash.EntityID); + auto playerModel = player.FirstChildByName("PlayerModel"); + if (!playerModel.Valid()) { + continue; + } + if (!playerModel.HasComponent("Model")) { + continue; + } + EntityWrapper dashEffect = playerModel.Clone(); + for (auto& cAnim : dashEffect.ChildrenWithComponent("Animation")) { + cAnim["Animation"]["Play"] = false; + } + const double fadeTime = 0.5f; + for (auto& cModel : dashEffect.ChildrenWithComponent("Model")) { + EntityWrapper e(m_World, cModel.ID); + e.AttachComponent("Lifetime"); + e.AttachComponent("Fade"); + e["Fade"]["Loop"] = false; + e["Fade"]["FadeTime"] = fadeTime; + e["Fade"]["Time"] = fadeTime; + e["Lifetime"]["Lifetime"] = fadeTime; + } + dashEffect.AttachComponent("Lifetime"); + dashEffect.AttachComponent("Fade"); + dashEffect["Fade"]["Loop"] = false; + dashEffect["Fade"]["FadeTime"] = fadeTime; + dashEffect["Fade"]["Time"] = fadeTime; + dashEffect["Lifetime"]["Lifetime"] = fadeTime; + dashEffect["Transform"]["Position"] = (glm::vec3)player["Transform"]["Position"]; + dashEffect["Transform"]["Orientation"] = (glm::vec3)player["Transform"]["Orientation"]; + } + } } } @@ -40,33 +122,51 @@ 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()); + // Set third person model aim pitch EntityWrapper playerModel = player.FirstChildByName("PlayerModel"); if (playerModel.Valid()) { - ComponentWrapper cAnimationOffset = playerModel["AnimationOffset"]; - float pitch = cameraOrientation.x + 0.2; - double time = (pitch + glm::half_pi()) / glm::pi(); - cAnimationOffset["Time"] = time; + setAim(playerModel, "SidearmWeapon", time); + setAim(playerModel, "AssaultWeapon", time); + setAim(playerModel, "DefenderWeapon", time); } } 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"]; + playerCrouchSpeed *= (double)playerBoostAssaultEntity["BoostAssault"]["StrengthOfEffect"]; + } + bool sniperSprinting = false; + if (player.HasComponent("SprintAbility")) { + (bool)player["SprintAbility"]["Active"] = controller->SpecialAbilityKeyDown(); + if (controller->SpecialAbilityKeyDown()) { + playerMovementSpeed *= (double)player["SprintAbility"]["StrengthOfEffect"]; + playerCrouchSpeed *= (double)player["SprintAbility"]["StrengthOfEffect"]; + sniperSprinting = true; + } + } if (player.HasComponent("Physics")) { ComponentWrapper cPhysics = player["Physics"]; //Assault Dash Check if (player.HasComponent("DashAbility")) { - controller->AssaultDashCheck(dt, ((glm::vec3)cPhysics["Velocity"]).y != 0.0f, player["DashAbility"]["CoolDownMaxTimer"]); + 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 @@ -80,21 +180,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); @@ -102,18 +202,33 @@ void PlayerMovementSystem::updateMovementControllers(double dt) if (addSpeed > 0) { static float accel = 15.f; +#ifdef DEBUG ImGui::InputFloat("accel", &accel); +#endif static float airAccel = 0.5f; +#ifdef DEBUG ImGui::InputFloat("airAccel", &airAccel); +#endif float actualAccel = isOnGround ? accel : airAccel; static float surfaceFriction = 5.f; +#ifdef DEBUG ImGui::InputFloat("surfaceFriction", &surfaceFriction); +#endif float accelerationSpeed = actualAccel * (float)dt * wishSpeed * surfaceFriction; //if doubleTapped do Assault Dash - but only boost maximum 50.0f float doubleTapDashBoost = controller->AssaultDashDoubleTapped() ? 40.0f : 1.0f; accelerationSpeed = glm::min(doubleTapDashBoost*glm::min(accelerationSpeed, addSpeed), 50.0f); - velocity += accelerationSpeed * wishDirection; - ImGui::Text("velocity: (%f, %f, %f) |%f|", velocity.x, velocity.y, velocity.z, glm::length(velocity)); + //if player has Boost from an Assault class, accelerate the player faster + if (playerBoostAssaultEntity.Valid()) { + accelerationSpeed *= (double)playerBoostAssaultEntity["BoostAssault"]["StrengthOfEffect"]; + } + if (sniperSprinting) { + accelerationSpeed *= (double)player["SprintAbility"]["StrengthOfEffect"]; + } + velocity += accelerationSpeed * (glm::vec3)wishDirection; +#ifdef DEBUG + ImGui::Text("velocity: (%f, %f, %f) |%f|", velocity.x(), velocity.y(), velocity.z(), glm::length((glm::vec3)velocity)); +#endif } if (isOnGround) { @@ -123,11 +238,65 @@ 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()) { + EntityWrapper playerModel = player.FirstChildByName("PlayerModel"); + if (playerModel.Valid()) { + { + Events::AutoAnimationBlend aeb; + aeb.Duration = 0.15; + aeb.NodeName = "Jump"; + aeb.RootNode = playerModel; + aeb.Start = true; + aeb.Restart = true; + m_EventBroker->Publish(aeb); + } + { + Events::AutoAnimationBlend aeb; + aeb.Duration = 0.25; + aeb.NodeName = "MovementBlend"; + aeb.RootNode = playerModel; + aeb.Start = true; + aeb.Restart = false; + aeb.AnimationEntity = playerModel.FirstChildByName("Jump"); + m_EventBroker->Publish(aeb); + } + } + } + + } 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"); + if (playerModel.Valid()) { + { + Events::AutoAnimationBlend aeb; + aeb.Duration = 0.15; + aeb.NodeName = "Jump"; + aeb.RootNode = playerModel; + aeb.Start = true; + aeb.Restart = true; + m_EventBroker->Publish(aeb); + } + { + Events::AutoAnimationBlend aeb; + aeb.Duration = 0.25; + aeb.NodeName = "MovementBlend"; + aeb.RootNode = playerModel; + aeb.Start = true; + aeb.Restart = false; + aeb.AnimationEntity = playerModel.FirstChildByName("BlendTreeLower").FirstChildByName("Jump"); + m_EventBroker->Publish(aeb); + } + } + } + // If IsServer and network is off this will not work if (IsClient) { //put a hexagon at the players feet @@ -142,94 +311,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); - } - } - - // Animations - EntityWrapper playerModel = player.FirstChildByName("PlayerModel"); - if (playerModel.Valid()) { - ComponentWrapper cAnimation = playerModel["Animation"]; - std::string& animationName1 = cAnimation["AnimationName1"]; - std::string& animationName2 = cAnimation["AnimationName2"]; - double& animationTime1 = cAnimation["Time1"]; - double& animationTime2 = cAnimation["Time2"]; - double& animationSpeed1 = cAnimation["Speed1"]; - double& animationSpeed2 = cAnimation["Speed2"]; - double& animationWeight1 = cAnimation["Weight1"]; - double& animationWeight2 = cAnimation["Weight2"]; - - float movementLength = glm::length(groundVelocity); - //TODO: add assault dash animation here - if (glm::length(controller->Movement()) > 0.f) { - double forwardMovement = controller->Movement().z; - double strafeMovement = controller->Movement().x; - - if (controller->Crouching() && animationName1 != "CrouchWalk") { - animationName1 = "CrouchWalk"; - animationSpeed1 = 1.0 * -glm::sign(controller->Movement().z); - } else { - if (glm::abs(forwardMovement) > 0) { - if (animationName1 != "Run") { - animationName1 = "Run"; - if (animationName2 == "StrafeLeft" || animationName2 == "StrafeRight") { - animationTime1 = animationTime2; - } else { - animationTime1 = 0.0; - } - } - animationSpeed1 = 2.f * -glm::sign(forwardMovement); - } - - if (glm::abs(strafeMovement) > 0) { - if (animationName2 != "StrafeLeft" && animationName2 != "StrafeRight") { - if (strafeMovement < 0) { - animationName2 = "StrafeLeft"; - } - if (strafeMovement > 0) { - animationName2 = "StrafeRight"; - } - if (animationName1 == "Run") { - animationTime2 = animationTime1; - } else { - animationTime2 = 0.0; - } - } - animationSpeed2 = 2.f * glm::abs(strafeMovement); - } - - double strafeWeight = glm::abs(strafeMovement) / (glm::abs(forwardMovement) + glm::abs(strafeMovement)); - animationWeight2 = strafeWeight; - animationWeight1 = 1.0 - strafeWeight; - } - } else { - if (controller->Crouching()) { - animationName1 = "Crouch"; - animationName2 = ""; - animationSpeed1 = 1.0; - animationSpeed2 = 0.0; - animationWeight1 = 1.0; - animationWeight2 = 0.0; - } else { - animationName1 = "Idle"; - animationName2 = ""; - animationSpeed1 = 1.f; - animationSpeed2 = 0.0; - animationWeight1 = 1.0; - animationWeight2 = 0.0; - //cAnimation["AnimationName2"] = "Idle"; + 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); } @@ -238,39 +338,62 @@ 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; +#ifdef DEBUG ImGui::InputFloat("groundFriction", &groundFriction); +#endif static float airFriction = 2.f; +#ifdef DEBUG ImGui::InputFloat("airFriction", &airFriction); +#endif float friction = isOnGround ? groundFriction : airFriction; 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; } -void PlayerMovementSystem::playerStep(double dt) + +void PlayerMovementSystem::setAim(EntityWrapper root, std::string weaponNodeName, double time) { - if (!m_LocalPlayer.Valid()) { + if (root.Valid()) { + EntityWrapper blendTreeUpper = root.FirstChildByName("BlendTreeUpper"); + if (blendTreeUpper.Valid()) { + EntityWrapper weapon = blendTreeUpper.FirstChildByName(weaponNodeName); + if(weapon.Valid()) { + EntityWrapper aim = weapon.FirstChildByName("Aim"); + if (aim.Valid()) { + if (aim.HasComponent("Animation")) { + (Field)aim["Animation"]["Time"] = time; + } + } + } + } + } +} + +void PlayerMovementSystem::playerStep(double dt, EntityWrapper player) +{ + // 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"]; @@ -281,8 +404,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; @@ -292,7 +415,7 @@ void PlayerMovementSystem::playerStep(double dt) bool PlayerMovementSystem::OnPlayerSpawned(Events::PlayerSpawned& e) { // When a player spawns, create an input controller for them - m_PlayerInputControllers[e.Player] = new FirstPersonInputController(m_EventBroker, e.PlayerID); + m_PlayerInputControllers[e.Player] = new FirstPersonInputController(m_EventBroker, e.PlayerID, e.Player); if (e.PlayerID == -1) { // Keep track of the local player m_LocalPlayer = e.Player; @@ -303,22 +426,162 @@ bool PlayerMovementSystem::OnPlayerSpawned(Events::PlayerSpawned& e) bool PlayerMovementSystem::OnDoubleJump(Events::DoubleJump & e) { // If entity does not exist, exit - if (!EntityWrapper(m_World, e.entityID).Valid()) { + if (!EntityWrapper(m_World, e.entityID).Valid()) { return false; } // If entity IsLocalPlayer, exit - if (e.entityID == m_LocalPlayer.ID) { + if (e.entityID == m_LocalPlayer.ID) { return false; } spawnHexagon(EntityWrapper(m_World, e.entityID)); + return true; } void PlayerMovementSystem::spawnHexagon(EntityWrapper target) -{ +{ //put a hexagon at the entitys... feet? - auto hexagonEffect = ResourceManager::Load("Schema/Entities/DoubleJumpHexagon.xml"); - EntityFileParser parser(hexagonEffect); - EntityID hexagonEffectID = parser.MergeEntities(m_World); - EntityWrapper hexagonEW = EntityWrapper(m_World, hexagonEffectID); + auto entityFile = ResourceManager::Load("Schema/Entities/DoubleJumpHexagon.xml"); + EntityWrapper hexagonEW = entityFile->MergeInto(m_World); hexagonEW["Transform"]["Position"] = (glm::vec3)target["Transform"]["Position"]; -} \ No newline at end of file +} + +bool PlayerMovementSystem::OnDashAbility(Events::DashAbility & e) +{ + EntityWrapper eventPlayer(m_World, e.Player); + if (!eventPlayer.Valid()){// || IsServer || eventPlayer.ID == LocalPlayer.ID) { + return false; + } + +// auto entityFile = ResourceManager::Load("Schema/Entities/DashEffect.xml"); + // EntityWrapper dashEffect = entityFile->MergeInto(m_World); + EntityWrapper playerModel = eventPlayer.FirstChildByName("PlayerModel"); + + for (auto& kv : m_PlayerInputControllers) { + EntityWrapper player = kv.first; + if(player != eventPlayer) { + continue; + } + + + auto& controller = kv.second; + + if (!player.Valid()) { + continue; + } + + if (player.Valid()) { + EntityWrapper playerModel = player.FirstChildByName("PlayerModel"); + if (playerModel.Valid()) { + if (glm::abs(controller->Movement().x) > glm::abs(controller->Movement().z)) { + if (controller->Movement().x > 0) { + { + Events::AutoAnimationBlend aeb; + aeb.Duration = 0.1; + aeb.NodeName = "DashRight"; + aeb.RootNode = playerModel; + aeb.Restart = true; + aeb.Start = true; + m_EventBroker->Publish(aeb); + } + { + Events::AutoAnimationBlend aeb; + aeb.Duration = 0.2; + aeb.NodeName = "MovementBlend"; + aeb.RootNode = playerModel; + aeb.Start = true; + aeb.Restart = false; + aeb.AnimationEntity = playerModel.FirstChildByName("DashRight"); + m_EventBroker->Publish(aeb); + } + } else { + { + Events::AutoAnimationBlend aeb; + aeb.Duration = 0.1; + aeb.NodeName = "DashLeft"; + aeb.RootNode = playerModel; + aeb.Restart = true; + aeb.Start = true; + m_EventBroker->Publish(aeb); + } + { + Events::AutoAnimationBlend aeb; + aeb.Duration = 0.2; + aeb.NodeName = "MovementBlend"; + aeb.RootNode = playerModel; + aeb.Start = true; + aeb.Restart = false; + aeb.AnimationEntity = playerModel.FirstChildByName("DashLeft"); + m_EventBroker->Publish(aeb); + } + } + } else { + if (controller->Movement().z < 0) { + { + Events::AutoAnimationBlend aeb; + aeb.Duration = 0.1; + aeb.NodeName = "DashForward"; + aeb.RootNode = playerModel; + aeb.Restart = true; + aeb.Start = true; + m_EventBroker->Publish(aeb); + } + { + Events::AutoAnimationBlend aeb; + aeb.Duration = 0.2; + aeb.NodeName = "MovementBlend"; + aeb.RootNode = playerModel; + aeb.Start = true; + aeb.Restart = false; + aeb.AnimationEntity = playerModel.FirstChildByName("DashForward"); + m_EventBroker->Publish(aeb); + } + } else { + { + Events::AutoAnimationBlend aeb; + aeb.Duration = 0.1; + aeb.NodeName = "DashBackward"; + aeb.RootNode = playerModel; + aeb.Restart = true; + aeb.Start = true; + m_EventBroker->Publish(aeb); + } + { + Events::AutoAnimationBlend aeb; + aeb.Duration = 0.2; + aeb.NodeName = "MovementBlend"; + aeb.RootNode = playerModel; + aeb.Start = true; + aeb.Restart = false; + aeb.AnimationEntity = playerModel.FirstChildByName("DashBackward"); + m_EventBroker->Publish(aeb); + } + } + } + +/* + EntityWrapper dashEffectModel; + dashEffectModel = playerModel.Clone(); + player["Transform"].Copy(dashEffectModel["Transform"]); + + + dashEffectModel.AttachComponent("ExplosionEffect"); + dashEffectModel["ExplosionEffect"]["EndColor"] = (glm::vec4)playerModel["Model"]["Color"]; + ((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()); + + + + + auto animationChildren = dashEffectModel.ChildrenWithComponent("Animation"); + + for (auto animationEntity : animationChildren) { + (Field)animationEntity["Animation"]["Play"] = false; + } + */ + } + + } + } + return true; +} diff --git a/src/Game/Systems/PlayerSpawnSystem.cpp b/src/Game/Systems/PlayerSpawnSystem.cpp index 6254c674..339a850c 100644 --- a/src/Game/Systems/PlayerSpawnSystem.cpp +++ b/src/Game/Systems/PlayerSpawnSystem.cpp @@ -1,29 +1,55 @@ #include "Systems/PlayerSpawnSystem.h" - -//This should be set by the config anyway. -float PlayerSpawnSystem::m_RespawnTime = 15.0f; +#include "Core/ELockMouse.h" PlayerSpawnSystem::PlayerSpawnSystem(SystemParams params) : System(params) - , m_Timer(0.f) + , m_DbgConfigForceRespawn(false) { EVENT_SUBSCRIBE_MEMBER(m_OnInputCommand, &PlayerSpawnSystem::OnInputCommand); EVENT_SUBSCRIBE_MEMBER(m_OnPlayerSpawnerd, &PlayerSpawnSystem::OnPlayerSpawned); EVENT_SUBSCRIBE_MEMBER(m_OnPlayerDeath, &PlayerSpawnSystem::OnPlayerDeath); - m_NetworkEnabled = ResourceManager::Load("Config.ini")->Get("Networking.StartNetwork", false); + ConfigFile* config = ResourceManager::Load("Config.ini"); + m_NetworkEnabled = config->Get("Networking.StartNetwork", false); + m_ForcedRespawnTime = config->Get("Debug.RespawnTime", -1.0f); + m_DbgConfigForceRespawn = m_ForcedRespawnTime > 0 && IsServer; } void PlayerSpawnSystem::Update(double dt) { - //Increase timer. - m_Timer += dt; - if (m_Timer < m_RespawnTime) { - return; + // If there are no CapturePointGameMode components we will just spawn immediately. + // Should be able to support older maps with this. + // TODO: In the future we might want to return instead, to avoid spawning in the menu for instance. + auto pool = m_World->GetComponents("CapturePointGameMode"); + if (pool != nullptr && pool->size() > 0) + { + // Take the first CapturePointGameMode component found. + ComponentWrapper& modeComponent = *pool->begin(); + // Increase timer. + Field timer = modeComponent["RespawnTime"]; + timer += dt; + if (m_DbgConfigForceRespawn) { + (Field)modeComponent["MaxRespawnTime"] = m_ForcedRespawnTime; + } + double maxRespawnTime = (double)modeComponent["MaxRespawnTime"]; + EntityWrapper spectatorCam = m_World->GetFirstEntityByName("SpectatorCamera"); + if (spectatorCam.Valid()) { + EntityWrapper HUD = spectatorCam.FirstChildByName("SpectatorHUD"); + if (HUD.Valid()) { + EntityWrapper respawnTimer = spectatorCam.FirstChildByName("RespawnTimer"); + if (respawnTimer.Valid()) { + //Update respawn time in the HUD element. + respawnTimer["Text"]["Content"] = std::to_string(1 + (int)(maxRespawnTime - timer)); + } + } + } + if (timer < maxRespawnTime) { + return; + } + // If respawn time has passed, we spawn all players that have requested to be spawned. + timer = 0; } - //If respawn time has passed, we spawn all players that have requested to be spawned. - m_Timer = 0.f; - //If there are no spawn requests, return immediately, if we are client the SpawnRequests should always be empty. + // If there are no spawn requests, return immediately, if we are client the SpawnRequests should always be empty. if (m_SpawnRequests.size() == 0) { return; } @@ -34,7 +60,15 @@ void PlayerSpawnSystem::Update(double dt) } int numSpawnedPlayers = 0; - for (auto& req : m_SpawnRequests) { + int playersSpectating = 0; + const int numRequestsToHandle = (int)m_SpawnRequests.size(); + for (auto it = m_SpawnRequests.begin(); it != m_SpawnRequests.end(); ++it) { + // It is valid if they didn't pick class yet + // but don't spawn anything, goto next spawnrequest. + if (it->Class == PlayerClass::None) { + ++playersSpectating; + continue; + } for (auto& cPlayerSpawn : *playerSpawns) { EntityWrapper spawner(m_World, cPlayerSpawn.EntityID); if (!spawner.HasComponent("Spawner")) { @@ -43,37 +77,63 @@ void PlayerSpawnSystem::Update(double dt) // If the spawner has a team affiliation, check it if (spawner.HasComponent("Team")) { - if ((int)spawner["Team"]["Team"] != req.Team) { - continue; + auto cSpawnerTeam = spawner["Team"]; + if ((int)cSpawnerTeam["Team"] != it->Team) { + // If they somehow has a valid class as spectator, don't spawn them. + if (it->Team == cSpawnerTeam["Team"].Enum("Spectator")) { + ++playersSpectating; + break; + } else { + continue; + } } } + // TODO: Choose a different spawner depending on class picked? + std::string playerEntityFile; + if (it->Class == PlayerClass::Assault) { + playerEntityFile = (const std::string&)cPlayerSpawn["AssaultFile"]; + } else if (it->Class == PlayerClass::Defender) { + playerEntityFile = (const std::string&)cPlayerSpawn["DefenderFile"]; + } else if (it->Class == PlayerClass::Sniper) { + playerEntityFile = (const std::string&)cPlayerSpawn["SniperFile"]; + } + // Spawn the player! - EntityWrapper player = SpawnerSystem::Spawn(spawner, EntityWrapper::Invalid, "Player"); + EntityWrapper player = SpawnerSystem::SpawnEntityFile(playerEntityFile, spawner, EntityWrapper::Invalid, "Player"); // Set the player team affiliation - player["Team"]["Team"] = req.Team; + player["Team"]["Team"] = it->Team; // Publish a PlayerSpawned event Events::PlayerSpawned e; - e.PlayerID = req.PlayerID; + e.PlayerID = it->PlayerID; e.Player = player; e.Spawner = spawner; m_EventBroker->Publish(e); ++numSpawnedPlayers; + it = m_SpawnRequests.erase(it); + break; + } + if (it == m_SpawnRequests.end()) { break; } } - if (numSpawnedPlayers != (int)m_SpawnRequests.size()) { - LOG_DEBUG("%i players were supposed to be spawned, but %i was spawned.", (int)m_SpawnRequests.size(), numSpawnedPlayers); + if (numSpawnedPlayers != numRequestsToHandle - playersSpectating) { + LOG_DEBUG("%i players were supposed to be spawned, but only %i was successfully.", numRequestsToHandle - playersSpectating, numSpawnedPlayers); } else { - LOG_DEBUG("%i players were spawned.", numSpawnedPlayers); + std::string dbg = numSpawnedPlayers != 0 ? std::to_string(numSpawnedPlayers) + " players were spawned. " : ""; + dbg += playersSpectating != 0 ? std::to_string(playersSpectating) + " players are spectating/picking class. " : ""; + LOG_DEBUG(dbg.c_str()); } - m_SpawnRequests.clear(); } bool PlayerSpawnSystem::OnInputCommand(Events::InputCommand& e) { - if (e.Command != "PickTeam") { + if (e.Command != "PickTeam" && e.Command != "PickClass" && e.Command != "SwapToTeamPick" && e.Command != "SwapToClassPick") { + return false; + } + + if (e.Value == 0) { return false; } @@ -83,34 +143,42 @@ bool PlayerSpawnSystem::OnInputCommand(Events::InputCommand& e) return false; } - if (e.Value == 0) { - return false; - } - - //TODO: Spectating? - //Right now, return if someone picks spectator. - //1 signifies spectator here, could not get Playerteam component since it may be invalid or without team comp. - if ((ComponentInfo::EnumType)e.Value == 1) { - return false; - } - - //Check if the player already requested spawn. + // Check if the player already requested spawn. auto iter = m_SpawnRequests.begin(); for (; iter != m_SpawnRequests.end(); ++iter) { if (iter->PlayerID == e.PlayerID) { + // If player wants to switch team or class , remove their selected class so they don't spawn. + if (e.Command == "SwapToTeamPick" || e.Command == "SwapToClassPick") { + iter->Class = PlayerClass::None; + return true; + } break; } } + //If we get here we got a PickTeam or PickClass, so add or alter a spawn request. + if (iter != m_SpawnRequests.end()) { - //If player is in queue to spawn, then change their team affiliation in the request. - iter->Team = (ComponentInfo::EnumType)e.Value; + // If player is in queue to spawn, then change their team affiliation or class in the request. + if (e.Command == "PickTeam") { + iter->Team = (ComponentInfo::EnumType)e.Value; + } else { + iter->Class = static_cast((int)e.Value); + } } else if (m_PlayerEntities.count(e.PlayerID) == 0 || !m_PlayerEntities[e.PlayerID].Valid()) { - //If player is not in queue to spawn, then create a spawn request, - //but only if they are spectating and/or just connected. + // If player is not in queue to spawn, then create a spawn request, + // but only if they are spectating and/or just connected. SpawnRequest req; req.PlayerID = e.PlayerID; - req.Team = (ComponentInfo::EnumType)e.Value; + if (e.Command == "PickTeam") { + req.Team = (ComponentInfo::EnumType)e.Value; + req.Class = PlayerClass::None; + } else { + // Should never get here, since you should have picked a team before you ever get a chance to pick class. + LOG_WARNING("Sequence error: Should not be able to pick class before team"); + req.Team = 1; // TODO: 1 Signifies spectator, should probably have real enum here later. + req.Class = static_cast((int)e.Value); + } m_SpawnRequests.push_back(req); } else { return false; @@ -145,18 +213,8 @@ bool PlayerSpawnSystem::OnPlayerSpawned(Events::PlayerSpawned& e) Events::SetCamera e; e.CameraEntity = cameraEntity; m_EventBroker->Publish(e); - } - - // HACK: Set the player model color to team color - EntityWrapper playerModel = e.Player.FirstChildByName("PlayerModel"); - if (playerModel.Valid() && e.Player.HasComponent("Team")) { - ComponentWrapper cTeam = e.Player["Team"]; - ComponentWrapper cModel = playerModel["Model"]; - if ((ComponentInfo::EnumType)cTeam["Team"] == cTeam["Team"].Enum("Red")) { - cModel["Color"] = glm::vec3(1.f, 0.f, 0.f); - } else if ((ComponentInfo::EnumType)cTeam["Team"] == cTeam["Team"].Enum("Blue")) { - cModel["Color"] = glm::vec3(0.f, 0.25f, 1.f); - } + Events::LockMouse lock; + m_EventBroker->Publish(lock); } return true; @@ -164,7 +222,7 @@ bool PlayerSpawnSystem::OnPlayerSpawned(Events::PlayerSpawned& e) bool PlayerSpawnSystem::OnPlayerDeath(Events::PlayerDeath& e) { - //Only spawn request if network is disabled or we are server. + // Only spawn request if network is disabled or we are server. if (!IsServer && m_NetworkEnabled) { return false; } @@ -172,10 +230,6 @@ bool PlayerSpawnSystem::OnPlayerDeath(Events::PlayerDeath& e) return false; } ComponentWrapper cTeam = e.Player["Team"]; - //A spectator can't die anyway - if ((ComponentInfo::EnumType)cTeam["Team"] == cTeam["Team"].Enum("Spectator")) { - return false; - } if (m_PlayerIDs.count(e.Player.ID) == 0) { return false; @@ -184,6 +238,16 @@ bool PlayerSpawnSystem::OnPlayerDeath(Events::PlayerDeath& e) SpawnRequest req; req.PlayerID = m_PlayerIDs.at(e.Player.ID); req.Team = cTeam["Team"]; + // TODO: Something better than temp class state code, if we ever add class enums in .xml + if (e.Player.HasComponent("DashAbility")) { + req.Class = PlayerClass::Assault; + } else if (e.Player.HasComponent("SprintAbility")) { + req.Class = PlayerClass::Sniper; + } else if (e.Player.HasComponent("ShieldAbility")) { + req.Class = PlayerClass::Defender; + } else { + req.Class = PlayerClass::None; + } m_SpawnRequests.push_back(req); return true; diff --git a/src/Game/Systems/ScoreScreenSystem.cpp b/src/Game/Systems/ScoreScreenSystem.cpp new file mode 100644 index 00000000..02518b8c --- /dev/null +++ b/src/Game/Systems/ScoreScreenSystem.cpp @@ -0,0 +1,182 @@ +#include "Game/Systems/ScoreScreenSystem.h" + + +ScoreScreenSystem::ScoreScreenSystem(SystemParams params) + : System(params) + , PureSystem("ScoreScreen") +{ + EVENT_SUBSCRIBE_MEMBER(m_EPlayerDeath, &ScoreScreenSystem::OnPlayerDeath); + 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) +{ + if (!IsServer) { + return; + } + + if(!entity.HasComponent("ScoreScreen")){ + return; + } + + int currentTeam = 0; + + if(entity.HasComponent("Team")) { + currentTeam = (int)entity["Team"]["Team"]; + } else { + return; + } + + auto children = entity.ChildrenWithComponent("ScoreIdentity"); + + float position = 0.f; + + for (auto it = m_PlayerIdentities.begin(); it != m_PlayerIdentities.end(); ++it) { + bool found = false; + for (auto& child : children) { + int ID = (int)child["ScoreIdentity"]["ID"]; + if (it->first == ID) { + if (it->second.Team != currentTeam) { + m_World->DeleteEntity(child.ID); + (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); + (Field)entity["ScoreScreen"]["TotalIdentities"] -= 1; + it2 = m_DisconnectedIdentities.erase(it2); + it = m_PlayerIdentities.erase(it); + + //Remove from m_playerIdentities + break; + } + } + found = true; + if(!child.Valid()) { + break; + } + //Update Deaths for child + (Field)child["ScoreIdentity"]["Kills"] = it->second.Kills; + //Update Kills for child + (Field)child["ScoreIdentity"]["Deaths"] = it->second.Deaths; + //KD is not updated at the moment. + if (it->second.Deaths != 0) { + (Field)child["ScoreIdentity"]["KD"] = it->second.Kills/it->second.Deaths; + } + + //Update position for child + glm::vec3 offset = (glm::vec3)entity["ScoreScreen"]["Offset"]; + (Field) child["Transform"]["Position"] = offset * position; + position += 1.f; + + break; + } + } + + if (it == m_PlayerIdentities.end()) { + break; + } + + if(found == false) { + if(it->second.Team != currentTeam) { + //This player is not the same team as this scoreboard should show. + continue; + } + //There is no entry for this player, create one. + auto entityFile = ResourceManager::Load("Schema/Entities/ScoreIdentity.xml"); + EntityWrapper scoreIdentity = entityFile->MergeInto(m_World); + glm::vec3 offset = (glm::vec3)entity["ScoreScreen"]["Offset"]; + int newPosition = (int)entity["ScoreScreen"]["TotalIdentities"]; + (Field) scoreIdentity["Transform"]["Position"] = offset * (float)newPosition; + auto cScoreIdentity = scoreIdentity["ScoreIdentity"]; + auto data = it->second; + + (Field)cScoreIdentity["Name"] = data.Name; + (Field)cScoreIdentity["ID"] = data.ID; + + m_World->SetParent(scoreIdentity.ID, entity.ID); + + (Field)entity["ScoreScreen"]["TotalIdentities"] += 1; + + } + } + //Local player should have an icon, compare with LocalPlayer somthing +} + +bool ScoreScreenSystem::OnPlayerDeath(const Events::KillDeath& e) +{ + //When player die, add it to his score, and when possible the player who killed him. + std::unordered_map::iterator got; + got = m_PlayerIdentities.find(e.Casualty); + if(got != m_PlayerIdentities.end()) { + got->second.Deaths++; + } + got = m_PlayerIdentities.find(e.Killer); + if (got != m_PlayerIdentities.end()) { + got->second.Kills++; + } + return 0; +} + +bool ScoreScreenSystem::OnPlayerSpawn(const Events::PlayerSpawned& e) +{ + //When a player spawn, add data to the list entry with the same ID. + + std::unordered_map::iterator got; + + got = m_PlayerIdentities.find(e.PlayerID); + if(got == m_PlayerIdentities.end()) { + LOG_ERROR("Player spawned without having an entry on score screen"); + return 0; + } + auto& data = got->second; + data.Player = e.Player; + data.Team = (int)data.Player["Team"]["Team"]; + + return 0; +} + +bool ScoreScreenSystem::OnPlayerConnected(const Events::PlayerConnected& e) +{ + //player has connected, add his data to the list of ScoreIdentities + PlayerData data; + data.ID = e.PlayerID; + data.Name = e.PlayerName; + m_PlayerIdentities.insert( {data.ID, data} ); + + return 0; +} + +bool ScoreScreenSystem::OnPlayerDisconnected(const Events::PlayerDisconnected& e) +{ + //player has disconnected, remove him from list of ScoreIdentities + 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 new file mode 100644 index 00000000..2db23c1a --- /dev/null +++ b/src/Game/Systems/ServerListSystem.cpp @@ -0,0 +1,53 @@ +#include "../Game/Systems/ServerListSystem.h" + +ServerListSystem::ServerListSystem(SystemParams params, IRenderer* renderer) + : System(params) + , PureSystem("ServerList") + , m_Renderer(renderer) +{ + EVENT_SUBSCRIBE_MEMBER(m_EServerListRecieved, &ServerListSystem::OnServerListRecieved); +} + +void ServerListSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& cServerList, double dt) +{ + +} + +void ServerListSystem::RefreshList() +{ + Events::SearchForServers event; + m_EventBroker->Publish(event); +} + + +bool ServerListSystem::OnServerListRecieved(const Events::DisplayServerlist& e) +{ + if (e.Serverlist.size() == 0) { + return 1; + } + auto serverLists = m_World->GetComponents("ServerList"); + if (serverLists == nullptr) + return 1; + for (auto& cServerList : *serverLists) { + EntityWrapper serverListEntity = EntityWrapper(m_World, cServerList.EntityID); + EntityWrapper identitySpawner = serverListEntity.FirstChildByName("ServerIdentitySpawner"); + identitySpawner.DeleteChildren(); + + (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"]; + (Field)serverIdentityEntity["Transform"]["Position"] = offset * (float)i; + + auto& cIdentity = serverIdentityEntity["ServerIdentity"]; + (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 b4a37ad0..6db01305 100644 --- a/src/Game/Systems/SoundSystem.cpp +++ b/src/Game/Systems/SoundSystem.cpp @@ -6,47 +6,30 @@ 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"; - m_EventBroker->Publish(ev); - } } return true; } @@ -54,82 +37,70 @@ 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.CapturePointID, "Team")["Team"]; + 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; + } + if (e.Victim.ID != LocalPlayer.ID) { + 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 +108,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 +117,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 +127,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 6500460f..f444827b 100644 --- a/src/Game/Systems/SpawnerSystem.cpp +++ b/src/Game/Systems/SpawnerSystem.cpp @@ -8,6 +8,17 @@ SpawnerSystem::SpawnerSystem(SystemParams params) } EntityWrapper SpawnerSystem::Spawn(EntityWrapper spawner, EntityWrapper parent /*= EntityWrapper::Invalid*/, const std::string& dontCollideComponent) +{ + // Load the entity file and parse it + const std::string& entityFilePath = spawner["Spawner"]["EntityFile"]; + if (!entityFilePath.empty()) { + return SpawnEntityFile(entityFilePath, spawner, parent, dontCollideComponent); + } else { + return EntityWrapper::Invalid; + } +} + +EntityWrapper SpawnerSystem::SpawnEntityFile(const std::string& entityFilePath, EntityWrapper spawner, EntityWrapper parent /*= EntityWrapper::Invalid*/, const std::string& dontCollideComponent /*= ""*/) { // Spawn the entity in the parent's world if it exists, otherwise in the spawner's world World* world = parent.World; @@ -15,17 +26,17 @@ EntityWrapper SpawnerSystem::Spawn(EntityWrapper spawner, EntityWrapper parent / world = spawner.World; } - // Load the entity file and parse it - const std::string& entityFilePath = spawner["Spawner"]["EntityFile"]; - auto entityFile = ResourceManager::Load(entityFilePath); - if (entityFile == nullptr) { + EntityWrapper spawnedEntity; + try { + auto entityFile = ResourceManager::Load(entityFilePath); + spawnedEntity = entityFile->MergeInto(world); + world->SetParent(spawnedEntity.ID, parent.ID); + } catch (const Resource::FailedLoadingException& e) { return EntityWrapper::Invalid; } - EntityFileParser parser(entityFile); - EntityWrapper spawnedEntity(world, parser.MergeEntities(world, parent.ID)); - //If the spawned entity is collideable, then we must not spawn it where it collides with something that - //has a dontCollideComponent attached. + // If the spawned entity is collidable, then we must not spawn it where it collides with something that + // has a dontCollideComponent attached. bool spawnOnCollidable = dontCollideComponent.empty() || !spawnedEntity.HasComponent("Collidable"); if (!spawnOnCollidable) { boost::optional optBox = Collision::EntityAbsoluteAABB(spawnedEntity); @@ -37,7 +48,7 @@ EntityWrapper SpawnerSystem::Spawn(EntityWrapper spawner, EntityWrapper parent / // Find any SpawnPoints existing as children of spawner auto children = spawner.World->GetDirectChildren(spawner.ID); - std::vector spawnPoints; + std::list spawnPoints; for (auto kv = children.first; kv != children.second; ++kv) { const EntityID& child = kv->second; if (spawner.World->HasComponent(child, "SpawnPoint")) { @@ -74,9 +85,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) @@ -84,7 +95,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; @@ -101,17 +112,17 @@ bool SpawnerSystem::spawnedEntityIsColliding(EntityWrapper spawnedEntity, Entity if (!spawnedBox.Entity.HasComponent("Model")) { return true; } - RawModel* model = nullptr; + Model* model = nullptr; try { - model = ResourceManager::Load(otherEntity["Model"]["Resource"]); + model = ResourceManager::Load(otherEntity["Model"]["Resource"]); } catch (const std::exception&) { } if (model != nullptr && Collision::AABBvsTriangles( spawnedBox, - model->Vertices(), + model->m_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 new file mode 100644 index 00000000..88e50e80 --- /dev/null +++ b/src/Game/Systems/SpectatorCameraSystem.cpp @@ -0,0 +1,120 @@ +#include "Systems/SpectatorCameraSystem.h" +#include "Rendering/ESetCamera.h" +#include "Core/ELockMouse.h" + +SpectatorCameraSystem::SpectatorCameraSystem(SystemParams params) + : System(params) + , m_CamSetToTeamPick(false) + , 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) +{ + if (!m_CamSetToTeamPick && IsClient) { + // Find the class pick camera and set them to it, since they need to pick a team before they can leave the screen. + EntityWrapper spectatorCam = m_World->GetFirstEntityByName("PickTeamCamera"); + if (spectatorCam.HasComponent("Camera")) { + m_CamSetToTeamPick = true; + Events::SetCamera eSetCamera; + eSetCamera.CameraEntity = spectatorCam; + m_EventBroker->Publish(eSetCamera); + Events::UnlockMouse unlock; + m_EventBroker->Publish(unlock); + } + } +} + +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. + if (!IsClient || LocalPlayer.Valid()) { + return false; + } + bool swapToClass = e.Command == "PickTeam" || e.Command == "SwapToClassPick"; + if (e.Value == 0 || !swapToClass && e.Command != "SwapToTeamPick" && e.Command != "PickClass") { + return false; + } + + if (e.Command == "PickTeam") { + m_PickedTeam = e.Value; + } + + // If a team has not been picked, they may not exit the pick team screen. + if (m_PickedTeam == -1) { + return false; + } + + // A dead client should be able to swap to and between the overwatch cameras. + std::string camName; + // TODO: 1 Signifies spectator, should probably have real enum here later. + // Spectators should never end up at the class select, instead put them at the SpectatorCamera. + if (swapToClass && m_PickedTeam != 1) { + if (m_PickedTeam == 2) { + camName = "PickClassCameraRed"; + } else if (m_PickedTeam == 3) { + camName = "PickClassCameraBlue"; + } + } else if (e.Command == "SwapToTeamPick") { + camName = "PickTeamCamera"; + } else { + camName = "SpectatorCamera"; + } + EntityWrapper spectatorCam = m_World->GetFirstEntityByName(camName); + // Set the camera as active, if it exists. + if (spectatorCam.HasComponent("Camera")) { + // Set the class pick button visible if a blue or red team is picked, else invisible. + EntityWrapper HUD; + if (camName == "SpectatorCamera") { + HUD = spectatorCam.FirstChildByName("SpectatorHUD"); + } else if (camName == "PickTeamCamera") { + HUD = spectatorCam.FirstChildByName("PickTeamHUD"); + } + // If we are at the class pick already, or if HUD is invalid for any other reason, do nothing. + if (HUD.Valid()) { + EntityWrapper toClassButton = spectatorCam.FirstChildByName("ToClassPick"); + if (toClassButton.Valid()) { + // Set ClassButton as invisible if spectator, else visible. + bool visible = m_PickedTeam != 1; // TODO: 1 Signifies spectator. + toClassButton["Sprite"]["Visible"] = visible; + for (auto& child : toClassButton.ChildrenWithComponent("Text")) { + child["Text"]["Visible"] = visible; + } + } + } + Events::SetCamera eSetCamera; + eSetCamera.CameraEntity = spectatorCam; + m_EventBroker->Publish(eSetCamera); + Events::UnlockMouse unlock; + m_EventBroker->Publish(unlock); + } + + return true; +} + +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/StartSystem.cpp b/src/Game/Systems/StartSystem.cpp new file mode 100644 index 00000000..3efc2ec3 --- /dev/null +++ b/src/Game/Systems/StartSystem.cpp @@ -0,0 +1,33 @@ +#include "../Game/Systems/StartSystem.h" + +StartSystem::StartSystem(SystemParams params) + : System(params) + , ImpureSystem() +{ + EVENT_SUBSCRIBE_MEMBER(m_ECameraActivated, &StartSystem::OnCameraActivated); +} + +void StartSystem::Update(double dt) +{ + auto cameras = m_World->GetComponents("Camera"); + if(cameras == nullptr) { + return; + } + for(auto& cCamera: *cameras) { + EntityWrapper cameraEntity = EntityWrapper(m_World, cCamera.EntityID); + if(cameraEntity == m_ActiveCamera){ + return; + } + if(cameraEntity.Name() == "Overview_Camera_Start_Menu") { + Events::SetCamera event; + event.CameraEntity = cameraEntity; + m_EventBroker->Publish(event); + } + } +} + +bool StartSystem::OnCameraActivated(const Events::SetCamera& e) +{ + m_ActiveCamera = e.CameraEntity; + return 1; +} diff --git a/src/Game/Systems/TextFieldReader.cpp b/src/Game/Systems/TextFieldReader.cpp new file mode 100644 index 00000000..c2d2a4e7 --- /dev/null +++ b/src/Game/Systems/TextFieldReader.cpp @@ -0,0 +1,58 @@ +#include "Game/Systems/TextFieldReader.h" + +void TextFieldReader::UpdateComponent(EntityWrapper& entity, ComponentWrapper& cAmmunitionHUD, double dt) +{ + if (!entity.HasComponent("Text")) { + return; + } + + // Find the entity to read from + const std::string& entityName = cAmmunitionHUD["ParentEntityName"]; + const std::string& componentType = cAmmunitionHUD["ComponentType"]; + EntityWrapper readEntity = entity; + if (entityName.empty()) { + if (!readEntity.HasComponent(componentType)) { + readEntity = readEntity.FirstParentWithComponent(componentType); + } + } else { + readEntity = entity.FirstParentByName(entityName); + } + if (!readEntity.Valid()) { + return; + } + + // Find the component to read from + if (componentType.empty() || !readEntity.HasComponent(componentType)) { + return; + } + ComponentWrapper component = readEntity[componentType]; + + // Find the field to read from + const std::string& fieldName = cAmmunitionHUD["Field"]; + if (fieldName.empty() || component.Info.Fields.count(fieldName) == 0) { + return; + } + const ComponentInfo::Field_t& field = component.Info.Fields.at(fieldName); + + Field text = entity["Text"]["Content"]; + + if (field.Type == "int") { + text = boost::lexical_cast((const int&)component[fieldName]); + } else if (field.Type == "float") { + std::ostringstream ss; + float f = (float)component[fieldName]; + ss << std::fixed << std::setprecision(2); + ss << f; + text = ss.str(); + } else if (field.Type == "double") { + std::ostringstream ss; + double d = (double)component[fieldName]; + ss << std::fixed << std::setprecision(1); + ss << d; + text = ss.str(); + } else if (field.Type == "bool") { + text = boost::lexical_cast((const bool&)component[fieldName]); + } else if (field.Type == "string") { + text = (const std::string&)component[fieldName]; + } +} diff --git a/src/Game/Systems/Weapon/AssaultWeaponBehaviour.cpp b/src/Game/Systems/Weapon/AssaultWeaponBehaviour.cpp new file mode 100644 index 00000000..5a334369 --- /dev/null +++ b/src/Game/Systems/Weapon/AssaultWeaponBehaviour.cpp @@ -0,0 +1,522 @@ +#include "Systems/Weapon/AssaultWeaponBehaviour.h" + +void AssaultWeaponBehaviour::UpdateComponent(EntityWrapper& entity, ComponentWrapper& cWeapon, double dt) +{ + Field fireCooldown = cWeapon["FireCooldown"]; + fireCooldown = glm::max(0.0, fireCooldown - dt); + + WeaponBehaviour::UpdateComponent(entity, cWeapon, dt); +} + +void AssaultWeaponBehaviour::UpdateWeapon(ComponentWrapper cWeapon, WeaponInfo& wi, double dt) +{ + CheckBoost(cWeapon, wi); + // Start reloading automatically if at 0 mag ammo + Field magAmmo = cWeapon["MagazineAmmo"]; + if (m_ConfigAutoReload && magAmmo <= 0) { + //OnReload(cWeapon, wi); + // Send an input command instead of reloading immediately so the server + // has a chance to catch up. + if (IsClient) { + Events::InputCommand e; + e.Player = wi.Player; + e.PlayerID = -1; + e.Command = "Reload"; + e.Value = 1; + m_EventBroker->Publish(e); + e.Value = 0; + m_EventBroker->Publish(e); + } + } + + // Only start reloading once we're done firing + Field reloadQueued = cWeapon["ReloadQueued"]; + Field fireCooldown = cWeapon["FireCooldown"]; + Field isReloading = cWeapon["IsReloading"]; + if (reloadQueued && fireCooldown <= 0) { + reloadQueued = fireCooldown; + isReloading = true; + } + + // Decrement reload timer + Field reloadTimer = cWeapon["ReloadTimer"]; + if (isReloading) { + reloadTimer = glm::max(0.0, reloadTimer - dt); + } + + // Handle reloading + if (isReloading && reloadTimer <= 0.0) { + Field magSize = cWeapon["MagazineSize"]; + Field ammo = cWeapon["Ammo"]; + + int usedAmmo = glm::max(0, *magSize - *magAmmo); + magAmmo = glm::clamp(*ammo + *magAmmo, 0, *magSize); + ammo = glm::max(0, *ammo - usedAmmo); + + + isReloading = false; + if (wi.FirstPersonEntity.Valid()) { + wi.FirstPersonEntity.FirstChildByName("ViewModel")["Model"]["Visible"] = true; + } + if (wi.ThirdPersonEntity.Valid()) { + wi.ThirdPersonEntity["Model"]["Visible"] = true; + } + } + double reloadTime = cWeapon["ReloadTime"]; + if (isReloading && reloadTimer <= reloadTime / 2) { + + } + + // Restore view angle + if (IsClient) { + 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()) { + Field cameraOrientation = camera["Transform"]["Orientation"]; + cameraOrientation.x(cameraOrientation.x() - change); + } + } + } + + // Update first person run animation + ComponentWrapper cPlayer = wi.Player["Player"]; + ComponentWrapper cPhysics = wi.Player["Physics"]; + const float& movementSpeed = cPlayer["MovementSpeed"]; + float speed = glm::length((const glm::vec3&)cPhysics["Velocity"]); + float animationWeight = glm::min(speed, movementSpeed) / movementSpeed; + EntityWrapper rootNode = wi.FirstPersonEntity; + if (rootNode.Valid()) { + EntityWrapper blend = rootNode.FirstChildByName("MovementBlendAssault"); + if (blend.Valid()) { + (Field)blend["Blend"]["Weight"] = animationWeight; + } + } + + // Fire if we're able to fire + if (canFire(cWeapon, wi)) { + fireBullet(cWeapon, wi); + } +} + +void AssaultWeaponBehaviour::OnPrimaryFire(ComponentWrapper cWeapon, WeaponInfo& wi) +{ + cWeapon["TriggerHeld"] = true; + if (canFire(cWeapon, wi)) { + fireBullet(cWeapon, wi); + } +} + +void AssaultWeaponBehaviour::OnCeasePrimaryFire(ComponentWrapper cWeapon, WeaponInfo& wi) +{ + cWeapon["TriggerHeld"] = false; +} + +void AssaultWeaponBehaviour::OnReload(ComponentWrapper cWeapon, WeaponInfo& wi) +{ + Field reloadQueued = cWeapon["ReloadQueued"]; + Field isReloading = cWeapon["IsReloading"]; + if (reloadQueued || isReloading) { + return; + } + + Field magAmmo = cWeapon["MagazineAmmo"]; + Field magSize = cWeapon["MagazineSize"]; + if (magAmmo >= magSize) { + return; + } + Field ammo = cWeapon["Ammo"]; + if (ammo <= 0) { + return; + } + + Field reloadTime = cWeapon["ReloadTime"]; + Field reloadTimer = cWeapon["ReloadTimer"]; + + // Start reload + reloadQueued = true; + reloadTimer = reloadTime; + + // Play animation + playAnimationAndReturn(wi.FirstPersonEntity, "ActionBlend", "Reload"); + // Third person anim + Events::AutoAnimationBlend b1; + b1.RootNode = wi.ThirdPersonPlayerModel; + b1.NodeName = "Reload"; + b1.Restart = true; + b1.Start = true; + m_EventBroker->Publish(b1); + + // Spawn explosion effect + if (wi.FirstPersonEntity.Valid()) { + if (IsClient) { + EntityWrapper reloadEffectSpawner = wi.FirstPersonEntity.FirstChildByName("ReloadSpawner"); + if (reloadEffectSpawner.Valid()) { + reloadEffectSpawner.DeleteChildren(); + SpawnerSystem::Spawn(reloadEffectSpawner, reloadEffectSpawner); + } + } + wi.FirstPersonEntity.FirstChildByName("ViewModel")["Model"]["Visible"] = false; + } + if (wi.ThirdPersonEntity.Valid()) { + if (IsServer) { + EntityWrapper reloadEffectSpawner = wi.ThirdPersonEntity.FirstChildByName("ReloadSpawner"); + if (reloadEffectSpawner.Valid()) { + reloadEffectSpawner.DeleteChildren(); + SpawnerSystem::Spawn(reloadEffectSpawner, reloadEffectSpawner); + } + } + wi.ThirdPersonEntity["Model"]["Visible"] = false; + } + + // Sound + Events::PlaySoundOnEntity e; + e.Emitter = wi.Player; + e.FilePath = "Audio/weapon/Assault/AssaultWeaponReload.wav"; + m_EventBroker->Publish(e); +} + +void AssaultWeaponBehaviour::OnEquip(ComponentWrapper cWeapon, WeaponInfo& wi) +{ + cWeapon["FireCooldown"] = (double)cWeapon["EquipTime"]; + + if (wi.ThirdPersonPlayerModel.Valid()) { + Events::AutoAnimationBlend b1; + b1.RootNode = wi.ThirdPersonPlayerModel; + b1.NodeName = "AssaultWeapon"; + b1.SingleLevelBlend = true; + m_EventBroker->Publish(b1); + } +} + +void AssaultWeaponBehaviour::OnHolster(ComponentWrapper cWeapon, WeaponInfo& wi) +{ + // Make sure the trigger is released if weapon is holstered while firing + cWeapon["TriggerHeld"] = false; + + // Cancel any reload + cWeapon["IsReloading"] = false; + cWeapon["ReloadTimer"] = 0.0; +} + +void AssaultWeaponBehaviour::fireBullet(ComponentWrapper cWeapon, WeaponInfo& wi) +{ + cWeapon["FireCooldown"] = 60.0 / (double)cWeapon["RPM"]; + + // Ammo + 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()) { + return; + } + + // Tracer + EntityWrapper tracerSpawner = weaponModelEntity.FirstChildByName("WeaponMuzzleRay"); + if (tracerSpawner.Valid()) { + 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()) { + ((Field)ray["Transform"]["Scale"]).x(distance); + ((Field)ray["Transform"]["Position"]).z(-distance/2.f); + } + } + //MuzzleFlash + EntityWrapper muzzleFlashSpawner = weaponModelEntity.FirstChildByName("WeaponMuzzleFlash"); + if (muzzleFlashSpawner.Valid()) { + std::uniform_real_distribution randomSpreadAngle(0.f, 3.1415f*2); + EntityWrapper flash = SpawnerSystem::Spawn(muzzleFlashSpawner, muzzleFlashSpawner); + if (flash.Valid()) { + ((Field)flash["Transform"]["Orientation"]).z(randomSpreadAngle(m_RandomEngine)); + } + } + + // Deal damage + if (dealDamage(cWeapon, wi)) { + // Show hit marker + EntityWrapper hitMarkerSpawner = wi.Player.FirstChildByName("HitMarkerSpawner"); + if (hitMarkerSpawner.Valid()) { + SpawnerSystem::Spawn(hitMarkerSpawner, hitMarkerSpawner); + Events::PlaySoundOnEntity e; + e.Emitter = wi.Player; + e.FilePath = "Audio/weapon/hitclick.wav"; + m_EventBroker->Publish(e); + } + } + + // 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; + } + } + } + + // Play animation + playAnimationAndReturn(wi.FirstPersonEntity, "ActionBlend", "Fire"); + + // Third person anim + Events::AutoAnimationBlend b1; + b1.RootNode = wi.ThirdPersonPlayerModel; + b1.NodeName = "Fire"; + b1.Restart = true; + b1.Start = true; + m_EventBroker->Publish(b1); + + // Sound + Events::PlaySoundOnEntity e; + e.Emitter = wi.Player; + e.FilePath = "Audio/weapon/Assault/AssaultWeaponFire.wav"; + m_EventBroker->Publish(e); +} + +bool AssaultWeaponBehaviour::canFire(ComponentWrapper cWeapon, WeaponInfo& wi) +{ + bool triggerHeld = cWeapon["TriggerHeld"]; + bool cooldownPassed = (double)cWeapon["FireCooldown"] <= 0.0; + bool isNotReloading = !(bool)cWeapon["IsReloading"]; + return triggerHeld && cooldownPassed && isNotReloading; +} + +bool AssaultWeaponBehaviour::dealDamage(ComponentWrapper cWeapon, WeaponInfo& wi) +{ + // Only deal damage client side + if (!IsClient) { + return false; + } + + // Only handle damage for the local player + if (wi.Player != LocalPlayer) { + return false; + } + + // Make sure the player isn't shooting from the grave + if (!wi.Player.Valid()) { + return false; + } + + // 3D-pick middle of screen + Rectangle viewport = m_Renderer->GetViewportSize(); + glm::vec2 centerScreen(viewport.Width / 2, viewport.Height / 2); + // TODO: Some horizontal spread + PickData pickData = m_Renderer->Pick(centerScreen); + EntityWrapper victim(m_World, pickData.Entity); + if (!victim.Valid()) { + return false; + } + + // Don't let us somehow shoot ourselves in the foot + if (victim == LocalPlayer) { + return false; + } + + // Only care about players being hit + if (!victim.HasComponent("Player")) { + victim = victim.FirstParentWithComponent("Player"); + } + if (!victim.Valid()) { + return false; + } + + double damage = cWeapon["BaseDamage"]; + // If friendly fire, reduce damage to 0 (needed to make Boosts, Ammosharing work) + if ((ComponentInfo::EnumType)victim["Team"]["Team"] == (ComponentInfo::EnumType)wi.Player["Team"]["Team"]) { + damage = 0; + } + + // Deal damage! + Events::PlayerDamage ePlayerDamage; + ePlayerDamage.Inflictor = wi.Player; + ePlayerDamage.Victim = victim; + ePlayerDamage.Damage = damage; + m_EventBroker->Publish(ePlayerDamage); + + return damage > 0; +} + +void AssaultWeaponBehaviour::CheckBoost(ComponentWrapper cWeapon, WeaponInfo& wi) +{ + // Only check ammo client side + if (!IsClient) { + return; + } + + // Only handle ammo check for the local player + if (wi.Player != LocalPlayer) { + return; + } + + // Make sure the player isn't checking from the grave + if (!wi.Player.Valid()) { + return; + } + + // 3D-pick middle of screen + Rectangle viewport = m_Renderer->GetViewportSize(); + glm::vec2 centerScreen(viewport.Width / 2, viewport.Height / 2); + // TODO: Some horizontal spread + PickData pickData = m_Renderer->Pick(centerScreen); + EntityWrapper victim(m_World, pickData.Entity); + if (!victim.Valid()) { + return; + } + + // Don't let us somehow shoot ourselves in the foot + if (victim == LocalPlayer) { + return; + } + + // Only care about players being hit + if (!victim.HasComponent("Player")) { + victim = victim.FirstParentWithComponent("Player"); + } + if (!victim.Valid()) { + return; + } + + + // If friendly fire, reduce damage to 0 (needed to make Boosts, Ammosharing work) + if ((ComponentInfo::EnumType)victim["Team"]["Team"] == (ComponentInfo::EnumType)wi.Player["Team"]["Team"]) { + + EntityWrapper friendlyBoostHudSpawner = wi.FirstPersonPlayerModel.FirstChildByName("FriendlyBoostAttachment"); + if (friendlyBoostHudSpawner.Valid()) { + + EntityWrapper assaultBoost = victim.FirstChildByName("BoostAssault"); + EntityWrapper defenderBoost = victim.FirstChildByName("BoostDefender"); + EntityWrapper sniperBoost = victim.FirstChildByName("BoostSniper"); + + auto children = m_World->GetDirectChildren(friendlyBoostHudSpawner.ID); + + if (children.first == children.second) { + if (friendlyBoostHudSpawner.HasComponent("Spawner")) { + + EntityWrapper friendlyBoostHud = SpawnerSystem::Spawn(friendlyBoostHudSpawner, friendlyBoostHudSpawner); + if (friendlyBoostHud.Valid()) { + EntityWrapper assaultBoostEntity = friendlyBoostHud.FirstChildByName("AssaultBoost"); + if (assaultBoostEntity.Valid()) { + EntityWrapper active = assaultBoostEntity.FirstChildByName("Active"); + if (active.HasComponent("Text")) { + if (assaultBoost.Valid()) { + (Field)active["Text"]["Visible"] = true; + } else { + (Field)active["Text"]["Visible"] = false; + } + } + } + + EntityWrapper defenderBoostEntity = friendlyBoostHud.FirstChildByName("DefenderBoost"); + if (defenderBoostEntity.Valid()) { + EntityWrapper active = defenderBoostEntity.FirstChildByName("Active"); + if (active.HasComponent("Text")) { + if (defenderBoost.Valid()) { + (Field)active["Text"]["Visible"] = true; + } else { + (Field)active["Text"]["Visible"] = false; + } + } + } + + EntityWrapper sniperBoostEntity = friendlyBoostHud.FirstChildByName("SniperBoost"); + if (sniperBoostEntity.Valid()) { + EntityWrapper active = sniperBoostEntity.FirstChildByName("Active"); + if (active.HasComponent("Text")) { + if (sniperBoost.Valid()) { + (Field)active["Text"]["Visible"] = true; + } else { + (Field)active["Text"]["Visible"] = false; + } + } + } + } + } + } else { + EntityWrapper friendlyBoostHud = friendlyBoostHudSpawner.FirstChildByName("FriendlyBoostHUD"); + if (friendlyBoostHud.Valid()) { + if(friendlyBoostHud.HasComponent("Lifetime")) { + (Field)friendlyBoostHud["Lifetime"]["Lifetime"] = 0.5; + } + + + + EntityWrapper assaultBoostEntity = friendlyBoostHud.FirstChildByName("AssaultBoost"); + if (assaultBoostEntity.Valid()) { + EntityWrapper active = assaultBoostEntity.FirstChildByName("Active"); + if (active.HasComponent("Text")) { + if (assaultBoost.Valid()) { + (Field)active["Text"]["Visible"] = true; + } else { + (Field)active["Text"]["Visible"] = false; + } + } + } + + EntityWrapper defenderBoostEntity = friendlyBoostHud.FirstChildByName("DefenderBoost"); + if (defenderBoostEntity.Valid()) { + EntityWrapper active = defenderBoostEntity.FirstChildByName("Active"); + if (active.HasComponent("Text")) { + if (defenderBoost.Valid()) { + (Field)active["Text"]["Visible"] = true; + } else { + (Field)active["Text"]["Visible"] = false; + } + } + } + + EntityWrapper sniperBoostEntity = friendlyBoostHud.FirstChildByName("SniperBoost"); + if (sniperBoostEntity.Valid()) { + EntityWrapper active = sniperBoostEntity.FirstChildByName("Active"); + if (active.HasComponent("Text")) { + if (sniperBoost.Valid()) { + (Field)active["Text"]["Visible"] = true; + } else { + (Field)active["Text"]["Visible"] = false; + } + } + } + } + } + } + } +} + diff --git a/src/Game/Systems/Weapon/AssaultWeaponBehaviour.cpp_ b/src/Game/Systems/Weapon/AssaultWeaponBehaviour.cpp_ index c3b3385f..547ed36a 100644 --- a/src/Game/Systems/Weapon/AssaultWeaponBehaviour.cpp_ +++ b/src/Game/Systems/Weapon/AssaultWeaponBehaviour.cpp_ @@ -366,9 +366,10 @@ bool AssaultWeaponBehaviour::shoot(double damage) return false; } - // Check for friendly fire + + // If friendly fire - reduce damage to 0 (needed to make Boosts, Ammosharing work) if ((ComponentInfo::EnumType)victim["Team"]["Team"] == (ComponentInfo::EnumType)m_Player["Team"]["Team"]) { - return false; + damage = 0; } // Deal damage! diff --git a/src/Game/Systems/Weapon/DefenderWeaponBehaviour.cpp b/src/Game/Systems/Weapon/DefenderWeaponBehaviour.cpp index 028bd10c..b700583b 100644 --- a/src/Game/Systems/Weapon/DefenderWeaponBehaviour.cpp +++ b/src/Game/Systems/Weapon/DefenderWeaponBehaviour.cpp @@ -2,48 +2,266 @@ void DefenderWeaponBehaviour::UpdateComponent(EntityWrapper& entity, ComponentWrapper& cWeapon, double dt) { - (double&)cWeapon["TimeSinceLastFire"] += dt; + Field fireCooldown = cWeapon["FireCooldown"]; + fireCooldown = glm::max(0.0, fireCooldown - dt); + WeaponBehaviour::UpdateComponent(entity, cWeapon, dt); } -void DefenderWeaponBehaviour::UpdateWeapon(WeaponInfo& wi, double dt) +void DefenderWeaponBehaviour::UpdateWeapon(ComponentWrapper cWeapon, WeaponInfo& wi, double dt) { - ComponentWrapper cWeapon = wi.GetComponent(); + CheckBoost(cWeapon, wi); + // Decrement reload timer + Field reloadTimer = cWeapon["ReloadTimer"]; + reloadTimer = glm::max(0.0, reloadTimer - dt); - bool isFiring = cWeapon["IsFiring"]; - bool cooldownPassed = (double)cWeapon["TimeSinceLastFire"] >= (60.0 / (double)cWeapon["RPM"]); - bool isNotShielding = wi.Player.ChildrenWithComponent("Shield").size() == 0; - if (isFiring && cooldownPassed && isNotShielding) { - fireShell(wi); + // Start reloading automatically if at 0 mag ammo + Field magAmmo = cWeapon["MagazineAmmo"]; + if (m_ConfigAutoReload && magAmmo <= 0) { + OnReload(cWeapon, wi); + } + + // Handle reloading + Field isReloading = cWeapon["IsReloading"]; + if (isReloading && reloadTimer <= 0.0) { + double reloadTime = cWeapon["ReloadTime"]; + Field magSize = cWeapon["MagazineSize"]; + Field ammo = cWeapon["Ammo"]; + if (magAmmo < magSize && ammo > 0) { + ammo -= 1; + magAmmo += 1; + reloadTimer = reloadTime; + Events::PlaySoundOnEntity e; + e.Emitter = wi.Player; + e.FilePath = "Audio/weapon/Zoom.wav"; + m_EventBroker->Publish(e); + } else { + isReloading = false; + playAnimationAndReturn(wi.FirstPersonEntity, "FinalBlend", "ReloadEnd"); + + if (wi.ThirdPersonPlayerModel.Valid()) { + Events::AutoAnimationBlend eFireIdle; + eFireIdle.Duration = 0.2; + eFireIdle.RootNode = wi.ThirdPersonPlayerModel; + eFireIdle.NodeName = "Fire"; + eFireIdle.Start = false; + m_EventBroker->Publish(eFireIdle); + } + + } + } + + // Restore view angle + if (IsClient) { + 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()) { + Field cameraOrientation = camera["Transform"]["Orientation"]; + cameraOrientation.x(cameraOrientation.x() - change); + } + } + } + + // Fire if we're able to fire + if (canFire(cWeapon, wi)) { + fireShell(cWeapon, wi); } } -void DefenderWeaponBehaviour::OnPrimaryFire(WeaponInfo& wi) +void DefenderWeaponBehaviour::OnPrimaryFire(ComponentWrapper cWeapon, WeaponInfo& wi) { - ComponentWrapper cWeapon = wi.GetComponent(); - cWeapon["IsFiring"] = true; - bool cooldownPassed = (double)cWeapon["TimeSinceLastFire"] >= (60.0 / (double)cWeapon["RPM"]); - bool isNotShielding = wi.Player.ChildrenWithComponent("Shield").size() == 0; - if (cooldownPassed && isNotShielding) { - fireShell(wi); + cWeapon["TriggerHeld"] = true; + if (canFire(cWeapon, wi)) { + fireShell(cWeapon, wi); } } -void DefenderWeaponBehaviour::OnCeasePrimaryFire(WeaponInfo& wi) +void DefenderWeaponBehaviour::OnCeasePrimaryFire(ComponentWrapper cWeapon, WeaponInfo& wi) { - ComponentWrapper cWeapon = wi.GetComponent(); - cWeapon["IsFiring"] = false; + cWeapon["TriggerHeld"] = false; } -bool DefenderWeaponBehaviour::OnInputCommand(WeaponInfo& wi, const Events::InputCommand& e) +void DefenderWeaponBehaviour::OnReload(ComponentWrapper cWeapon, WeaponInfo& wi) { - if (e.Command == "SpecialAbility" && IsServer) { + Field isReloading = cWeapon["IsReloading"]; + if (isReloading) { + return; + } + + Field magAmmo = cWeapon["MagazineAmmo"]; + Field magSize = cWeapon["MagazineSize"]; + if (magAmmo >= magSize) { + return; + } + Field ammo = cWeapon["Ammo"]; + if (ammo <= 0) { + return; + } + + double reloadTime = cWeapon["ReloadTime"]; + Field reloadTimer = cWeapon["ReloadTimer"]; + + // Start reload + isReloading = true; + reloadTimer = reloadTime; + + // Play animation + if (wi.FirstPersonEntity.Valid()) { + Events::AutoAnimationBlend eBlendStart; + eBlendStart.RootNode = wi.FirstPersonEntity; + eBlendStart.NodeName = "ReloadStart"; + eBlendStart.Restart = true; + eBlendStart.Start = true; + m_EventBroker->Publish(eBlendStart); + Events::AutoAnimationBlend eBlendLoop; + eBlendLoop.RootNode = wi.FirstPersonEntity; + eBlendLoop.NodeName = "ReloadLoop"; + eBlendLoop.Restart = true; + eBlendLoop.Start = true; + eBlendLoop.AnimationEntity = wi.FirstPersonEntity.FirstChildByName("ReloadStart"); + m_EventBroker->Publish(eBlendLoop); + } + + if(wi.ThirdPersonPlayerModel.Valid()) { + Events::AutoAnimationBlend eReload; + eReload.Duration = 0.2; + eReload.RootNode = wi.ThirdPersonPlayerModel; + eReload.NodeName = "Reload"; + eReload.Restart = true; + eReload.Start = true; + m_EventBroker->Publish(eReload); + } +} + +void DefenderWeaponBehaviour::OnHolster(ComponentWrapper cWeapon, WeaponInfo& wi) +{ + // Make sure the trigger is released if weapon is holstered while firing + cWeapon["TriggerHeld"] = false; + + // Cancel any reload + cWeapon["IsReloading"] = false; + cWeapon["ReloadTimer"] = 0.0; +} + +bool DefenderWeaponBehaviour::OnInputCommand(ComponentWrapper cWeapon, WeaponInfo& wi, const Events::InputCommand& e) +{ + if (e.Command == "SpecialAbility") { EntityWrapper attachment = wi.Player.FirstChildByName("ShieldAttachment"); if (attachment.Valid()) { if (e.Value > 0) { - SpawnerSystem::Spawn(attachment, attachment); + + if(wi.Player.Valid()) { + if(wi.Player.HasComponent("ShieldAbility")) { + (Field)wi.Player["ShieldAbility"]["Active"] = true; + } + } + + if (IsServer) { + SpawnerSystem::Spawn(attachment, attachment); + } + + EntityWrapper backAttachment = attachment.FirstChildByName("Back"); + if (backAttachment.Valid()) { + Events::AutoAnimationBlend eDeployShieldAttachement; + eDeployShieldAttachement.RootNode = backAttachment; + eDeployShieldAttachement.NodeName = "Deploy"; + eDeployShieldAttachement.Restart = true; + eDeployShieldAttachement.Start = true; + m_EventBroker->Publish(eDeployShieldAttachement); + } + EntityWrapper frontAttachment = attachment.FirstChildByName("Front"); + if (frontAttachment.Valid()) { + Events::AutoAnimationBlend eDeployShieldAttachement; + eDeployShieldAttachement.RootNode = frontAttachment; + eDeployShieldAttachement.NodeName = "Deploy"; + eDeployShieldAttachement.Restart = true; + eDeployShieldAttachement.Start = true; + m_EventBroker->Publish(eDeployShieldAttachement); + + } + + if (IsClient) { + EntityWrapper root = wi.FirstPersonEntity; + if (root.Valid()) { + EntityWrapper animationNode = root.FirstChildByName("Shield"); + if (animationNode.Valid()) { + Events::AutoAnimationBlend eShieldBlend; + eShieldBlend.RootNode = root; + eShieldBlend.NodeName = "Shield"; + eShieldBlend.Restart = true; + eShieldBlend.Start = true; + m_EventBroker->Publish(eShieldBlend); + } + } + } else { // server only + EntityWrapper root = wi.ThirdPersonPlayerModel; + if (root.Valid()) { + Events::AutoAnimationBlend eShieldActivateBlend; + eShieldActivateBlend.RootNode = root; + eShieldActivateBlend.NodeName = "ActivateShield"; + eShieldActivateBlend.Restart = true; + eShieldActivateBlend.Start = true; + m_EventBroker->Publish(eShieldActivateBlend); + + EntityWrapper animationNode = root.FirstChildByName("ActivateShield"); + if (animationNode.Valid()) { + Events::AutoAnimationBlend eShieldIdleBlend; + eShieldIdleBlend.RootNode = root; + eShieldIdleBlend.NodeName = "ShieldFront"; + eShieldIdleBlend.Restart = true; + eShieldIdleBlend.Start = true; + eShieldIdleBlend.AnimationEntity = animationNode; + m_EventBroker->Publish(eShieldIdleBlend); + } + } + } } else { attachment.DeleteChildren(); + + if (wi.Player.Valid()) { + if (wi.Player.HasComponent("ShieldAbility")) { + (Field)wi.Player["ShieldAbility"]["Active"] = false; + } + } + + if (IsClient) { + EntityWrapper root = wi.FirstPersonEntity; + if (root.Valid()) { + EntityWrapper animationNode = root.FirstChildByName("ActionBlend"); + if (animationNode.Valid()) { + Events::AutoAnimationBlend eFireBlend; + eFireBlend.RootNode = root; + eFireBlend.NodeName = "ActionBlend"; + eFireBlend.Restart = true; + eFireBlend.Start = true; + m_EventBroker->Publish(eFireBlend); + } + } + } else { // server only + EntityWrapper root = wi.ThirdPersonPlayerModel; + if (root.Valid()) { + Events::AutoAnimationBlend eShieldDeactivateBlend; + eShieldDeactivateBlend.RootNode = root; + eShieldDeactivateBlend.NodeName = "ActivateShield"; + eShieldDeactivateBlend.Restart = true; + eShieldDeactivateBlend.Start = true; + eShieldDeactivateBlend.Reverse = true; + m_EventBroker->Publish(eShieldDeactivateBlend); + + EntityWrapper animationNode = root.FirstChildByName("ActivateShield"); + if (animationNode.Valid()) { + Events::AutoAnimationBlend eActionBlend; + eActionBlend.RootNode = root; + eActionBlend.NodeName = "ActionBlend"; + eActionBlend.AnimationEntity = animationNode; + m_EventBroker->Publish(eActionBlend); + } + } + } } } } @@ -51,57 +269,150 @@ bool DefenderWeaponBehaviour::OnInputCommand(WeaponInfo& wi, const Events::Input return false; } -bool DefenderWeaponBehaviour::OnSetCamera(const Events::SetCamera& e) + +void DefenderWeaponBehaviour::OnEquip(ComponentWrapper cWeapon, WeaponInfo& wi) { - m_CurrentCamera = e.CameraEntity; - return true; + if (wi.ThirdPersonPlayerModel.Valid()) { + Events::AutoAnimationBlend b1; + b1.RootNode = wi.ThirdPersonPlayerModel; + b1.NodeName = "DefenderWeapon"; + b1.SingleLevelBlend = true; + m_EventBroker->Publish(b1); + } } -void DefenderWeaponBehaviour::fireShell(WeaponInfo& wi) +void DefenderWeaponBehaviour::fireShell(ComponentWrapper cWeapon, WeaponInfo& wi) { - ComponentWrapper cWeapon = wi.GetComponent(); + cWeapon["FireCooldown"] = 60.0 / (double)cWeapon["RPM"]; - cWeapon["TimeSinceLastFire"] = 0.0; - int numPellets = cWeapon["NumPellets"]; - float spreadAngle = cWeapon["SpreadAngle"]; - std::uniform_real_distribution randomSpreadAngle(-spreadAngle, spreadAngle); + // Stop reloading + Field isReloading = cWeapon["IsReloading"]; + isReloading = false; - // Calculate pellet angles - // HACK: Random for now? - // TODO: Make distribution even for each quadrant - std::vector pelletAngles; - for (int i = 0; i < numPellets; i++) { - pelletAngles.push_back(glm::vec2(randomSpreadAngle(m_RandomEngine), randomSpreadAngle(m_RandomEngine))); - LOG_DEBUG("%f %f", pelletAngles[i].x, pelletAngles[i].y); - } - - double pelletDamage = (double)cWeapon["BaseDamage"] / numPellets; - - // Tracers - EntityWrapper weaponModelEntity; - if (wi.Player == LocalPlayer) { - weaponModelEntity = wi.FirstPersonEntity; + // Ammo + Field magAmmo = cWeapon["MagazineAmmo"]; + if (magAmmo <= 0) { + return; } else { - weaponModelEntity = wi.ThirdPersonEntity; + magAmmo -= 1; } - if (weaponModelEntity.Valid()) { - EntityWrapper spawner = weaponModelEntity.FirstChildByName("WeaponMuzzle"); - for (auto& angles : pelletAngles) { - glm::vec3 direction = Transform::AbsoluteOrientation(spawner) * glm::quat(glm::vec3(angles, 0.f)) * glm::vec3(0, 0, -1); - float distance = traceRayDistance(Transform::AbsolutePosition(spawner), direction); - EntityWrapper ray = SpawnerSystem::Spawn(spawner); - ((glm::vec3&)ray["Transform"]["Scale"]).z = (distance / 100.f); - glm::vec3& orientation = ray["Transform"]["Orientation"]; - orientation.x += angles.x; - orientation.y += angles.y; - glm::vec3 trajectory = direction * distance; - dealDamage(wi, direction, pelletDamage); + + // We can't really do any valuable calculations without a valid camera + if (!m_CurrentCamera.Valid()) { + return; + } + + int numPellets = cWeapon["NumPellets"]; + + // Create a spread pattern + std::vector pattern; + // The first pellet is always centered + pattern.push_back(glm::vec2(0, 0)); + // Any additional pellets form circles around the middle + int numOuterPellets = numPellets - 1; + float angleIncrement = glm::two_pi() / numOuterPellets; + for (int i = 0; i < numOuterPellets; ++i) { + float angle = angleIncrement * i; + glm::vec2 pellet = glm::vec2(glm::cos(angle), glm::sin(angle)); + pattern.push_back(pellet); + } + + // Deal damage (clientside) + dealDamage(cWeapon, wi, pattern); + + // Spawn tracers + spawnTracers(cWeapon, wi, pattern); + + // View punch + if (IsClient) { + EntityWrapper camera = wi.Player.FirstChildByName("Camera"); + if (camera.Valid()) { + Field cameraOrientation = camera["Transform"]["Orientation"]; + float viewPunch = cWeapon["ViewPunch"]; + float maxTravelAngle = (const float&)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; + } } } + // Play animation + playAnimationAndReturn(wi.FirstPersonEntity, "FinalBlend", "Fire"); + playAnimationAndReturn(wi.ThirdPersonPlayerModel, "FinalBlend", "Fire"); + + // Sound + Events::PlaySoundOnEntity e; + e.Emitter = wi.Player; + e.FilePath = "Audio/weapon/Blast.wav"; + m_EventBroker->Publish(e); } -void DefenderWeaponBehaviour::dealDamage(WeaponInfo& wi, glm::vec3 direction, double damage) +void DefenderWeaponBehaviour::spawnTracers(ComponentWrapper cWeapon, WeaponInfo& wi, std::vector pattern) +{ + EntityWrapper flashSpawner = getRelevantWeaponEntity(wi).FirstChildByName("WeaponMuzzleFlash"); + if (flashSpawner.Valid()) { + std::uniform_real_distribution randomSpreadAngle(0.f, 3.1415f*2); + EntityWrapper flash = SpawnerSystem::Spawn(flashSpawner, flashSpawner); + if (flash.Valid()) { + ((Field)flash["Transform"]["Orientation"]).z(randomSpreadAngle(m_RandomEngine)); + } + } + + EntityWrapper muzzle = getRelevantWeaponEntity(wi).FirstChildByName("WeaponMuzzleRay"); + if (!muzzle.Valid()) { + return; + } + + EntityWrapper camera = wi.Player.FirstChildByName("Camera"); + if (!camera.Valid()) { + return; + } + + float spreadAngle = glm::radians((float)cWeapon["SpreadAngle"]); + + for (auto& pellet : pattern) { + glm::quat pelletRotation = glm::quat(TransformSystem::AbsoluteOrientationEuler(camera)) * glm::quat(glm::vec3(pellet.y, pellet.x, 0) * spreadAngle); + glm::vec3 cameraPosition = TransformSystem::AbsolutePosition(camera); + glm::vec3 direction = pelletRotation * glm::vec3(0, 0, -1); + + float distance; + glm::vec3 hitPosition; + if (Collision::EntityFirstHitByRay(Ray(cameraPosition, direction), m_CollisionOctree, distance, hitPosition) != boost::none) { // don't spawn ray if you "miss the world" + + EntityWrapper ray = SpawnerSystem::Spawn(muzzle); + if (ray.Valid()) { + ComponentWrapper cTransform = ray["Transform"]; + Field rayOrigin = cTransform["Position"]; + Field rayOrientation = cTransform["Orientation"]; + Field rayScale = cTransform["Scale"]; + + glm::vec3 muzzlePosition = TransformSystem::AbsolutePosition(muzzle); + glm::quat muzzleOrientation = TransformSystem::AbsoluteOrientation(muzzle); + + + glm::vec3 muzzleToHit = hitPosition - muzzlePosition; + + rayOrigin = muzzlePosition + (muzzleToHit/2.f); + + + glm::vec3 lookVector = glm::normalize(-muzzleToHit); + float pitch = std::asin(-lookVector.y); + float yaw = std::atan2(lookVector.x, lookVector.z); + glm::quat orientation = glm::quat(glm::vec3(pitch, yaw, 0)); + rayOrientation = glm::eulerAngles(orientation); + rayScale.x(glm::length(muzzleToHit)); + } + } + } +} + +void DefenderWeaponBehaviour::dealDamage(ComponentWrapper cWeapon, WeaponInfo& wi, const std::vector& pattern) { // Only deal damage client side if (!IsClient) { @@ -117,59 +428,88 @@ void DefenderWeaponBehaviour::dealDamage(WeaponInfo& wi, glm::vec3 direction, do if (!wi.Player.Valid()) { return; } - - glm::vec3 maxRange = direction * 2.f; - EntityWrapper camera = wi.Player.FirstChildByName("Camera"); - glm::vec3 cameraPosition = Transform::AbsolutePosition(camera); - if (!camera.Valid()) { - return; - } - Rectangle screenResolution = m_Renderer->GetViewportSize(); - glm::vec2 centerScreen = glm::vec2(screenResolution.Width / 2, screenResolution.Height / 2); - glm::vec2 screenCoords = cameraFromEntity(m_CurrentCamera).WorldToScreen(cameraPosition + maxRange, m_Renderer->GetViewportSize()); - PickData pickData = m_Renderer->Pick(centerScreen + screenCoords); - EntityWrapper victim(m_World, pickData.Entity); - if (!victim.Valid()) { - return; + + // Convert the spread angle to screen coordinates, taking FOV into account + Rectangle res = m_Renderer->GetViewportSize(); + float spreadAngle = glm::radians((float)cWeapon["SpreadAngle"]); + float nearClip = (double)m_CurrentCamera["Camera"]["NearClip"]; + float farClip = (double)m_CurrentCamera["Camera"]["FarClip"]; + float yFOV = glm::radians((double)m_CurrentCamera["Camera"]["FOV"]); + //float yRefFOV = glm::radians(59.f); + //float yRef = glm::tan(yRefFOV) * nearClip; + //float yRatio = yRef / (glm::tan(yFOV) * nearClip); + //float yMax = (yRatio / 2.f) * spreadAngle * (res.Height / 2.f); + float yRefFOV = glm::radians(59.f); + float yRef = glm::tan(yRefFOV) * nearClip; + float yRatio = yRef / (glm::tan(yFOV) * nearClip); + float yMax = yRatio * (glm::tan(spreadAngle) * (farClip - nearClip)) * glm::pi(); // ????? Good enough???? + + LOG_DEBUG("Ratio: %f", yRatio); + LOG_DEBUG("fatClip: %f", farClip); + LOG_DEBUG("yMax: %f", yMax); + double pelletDamage = (double)cWeapon["BaseDamage"] / pattern.size(); + + // Pick! + std::unordered_map damageSum; + glm::vec2 screenCenter(res.Width / 2.f, res.Height / 2.f); + for (auto& pellet : pattern) { + glm::vec2 pickCoord = screenCenter + (pellet * glm::vec2(yMax, yMax)); + PickData pick = m_Renderer->Pick(pickCoord); + + EntityWrapper victim(m_World, pick.Entity); + if (!victim.Valid()) { + continue; + } + + // Temp hit decal +// EntityWrapper hit = ResourceManager::Load("Schema/Entities/HitTest.xml")->MergeInto(m_World); +// (Field)hit["Transform"]["Position"] = pick.Position; + + // Don't let us shoot ourselves in the foot somehow + if (victim == LocalPlayer) { + continue; + } + + // Only care about players being hit + if (!victim.HasComponent("Player")) { + victim = victim.FirstParentWithComponent("Player"); + if (!victim.Valid()) { + continue; + } + } + + // Check for friendly fire + if ((ComponentInfo::EnumType)victim["Team"]["Team"] == (ComponentInfo::EnumType)wi.Player["Team"]["Team"]) { + // Give boost + Events::PlayerDamage ePlayerDamage; + ePlayerDamage.Inflictor = wi.Player; + ePlayerDamage.Victim = victim; + ePlayerDamage.Damage = 0; + m_EventBroker->Publish(ePlayerDamage); + continue; + } + + damageSum[victim] += pelletDamage; + // ((Field)hit["Model"]["Color"]).z(1.f); } - // Don't let us shoot ourselves in the foot somehow - if (victim == LocalPlayer) { - return; + // Deal damage! + for (auto& kv : damageSum) { + // Deal damage! + Events::PlayerDamage ePlayerDamage; + ePlayerDamage.Inflictor = wi.Player; + ePlayerDamage.Victim = kv.first; + ePlayerDamage.Damage = kv.second; + m_EventBroker->Publish(ePlayerDamage); } - - // Only care about players being hit - if (!victim.HasComponent("Player")) { - victim = victim.FirstParentWithComponent("Player"); - } - if (!victim.Valid()) { - return; - } - - // Check for friendly fire - if ((ComponentInfo::EnumType)victim["Team"]["Team"] == (ComponentInfo::EnumType)wi.Player["Team"]["Team"]) { - return; - } - - // Deal damage! - Events::PlayerDamage ePlayerDamage; - ePlayerDamage.Inflictor = wi.Player; - ePlayerDamage.Victim = victim; - ePlayerDamage.Damage = damage; - m_EventBroker->Publish(ePlayerDamage); - LOG_DEBUG("Damage: %f", damage); } -float DefenderWeaponBehaviour::traceRayDistance(glm::vec3 origin, glm::vec3 direction) +bool DefenderWeaponBehaviour::canFire(ComponentWrapper cWeapon, WeaponInfo& wi) { - float distance; - glm::vec3 pos; - auto entity = Collision::EntityFirstHitByRay(Ray(origin, direction), m_CollisionOctree, distance, pos); - if (entity) { - return distance; - } else { - return 100.f; - } + bool triggerHeld = cWeapon["TriggerHeld"]; + bool cooldownPassed = (double)cWeapon["FireCooldown"] <= 0.0; + bool isNotShielding = wi.Player.ChildrenWithComponent("Shield").size() == 0; + return triggerHeld && cooldownPassed && isNotShielding; } Camera DefenderWeaponBehaviour::cameraFromEntity(EntityWrapper camera) @@ -186,3 +526,148 @@ Camera DefenderWeaponBehaviour::cameraFromEntity(EntityWrapper camera) cam.SetOrientation(glm::quat((const glm::vec3&)cTransform["Orientation"])); return cam; } + +void DefenderWeaponBehaviour::CheckBoost(ComponentWrapper cWeapon, WeaponInfo& wi) +{ + // Only check ammo client side + if (!IsClient) { + return; + } + + // Only handle ammo check for the local player + if (wi.Player != LocalPlayer) { + return; + } + + // Make sure the player isn't checking from the grave + if (!wi.Player.Valid()) { + return; + } + + // 3D-pick middle of screen + Rectangle viewport = m_Renderer->GetViewportSize(); + glm::vec2 centerScreen(viewport.Width / 2, viewport.Height / 2); + // TODO: Some horizontal spread + PickData pickData = m_Renderer->Pick(centerScreen); + EntityWrapper victim(m_World, pickData.Entity); + if (!victim.Valid()) { + return; + } + + // Don't let us somehow shoot ourselves in the foot + if (victim == LocalPlayer) { + return; + } + + // Only care about players being hit + if (!victim.HasComponent("Player")) { + victim = victim.FirstParentWithComponent("Player"); + } + if (!victim.Valid()) { + return; + } + + + // If friendly fire, reduce damage to 0 (needed to make Boosts, Ammosharing work) + if ((ComponentInfo::EnumType)victim["Team"]["Team"] == (ComponentInfo::EnumType)wi.Player["Team"]["Team"]) { + + EntityWrapper friendlyBoostHudSpawner = wi.FirstPersonPlayerModel.FirstChildByName("FriendlyBoostAttachment"); + if (friendlyBoostHudSpawner.Valid()) { + + EntityWrapper assaultBoost = victim.FirstChildByName("BoostAssault"); + EntityWrapper defenderBoost = victim.FirstChildByName("BoostDefender"); + EntityWrapper sniperBoost = victim.FirstChildByName("BoostSniper"); + + auto children = m_World->GetDirectChildren(friendlyBoostHudSpawner.ID); + + if (children.first == children.second) { + if (friendlyBoostHudSpawner.HasComponent("Spawner")) { + + EntityWrapper friendlyBoostHud = SpawnerSystem::Spawn(friendlyBoostHudSpawner, friendlyBoostHudSpawner); + if (friendlyBoostHud.Valid()) { + EntityWrapper assaultBoostEntity = friendlyBoostHud.FirstChildByName("AssaultBoost"); + if (assaultBoostEntity.Valid()) { + EntityWrapper active = assaultBoostEntity.FirstChildByName("Active"); + if (active.HasComponent("Text")) { + if (assaultBoost.Valid()) { + (Field)active["Text"]["Visible"] = true; + } else { + (Field)active["Text"]["Visible"] = false; + } + } + } + + EntityWrapper defenderBoostEntity = friendlyBoostHud.FirstChildByName("DefenderBoost"); + if (defenderBoostEntity.Valid()) { + EntityWrapper active = defenderBoostEntity.FirstChildByName("Active"); + if (active.HasComponent("Text")) { + if (defenderBoost.Valid()) { + (Field)active["Text"]["Visible"] = true; + } else { + (Field)active["Text"]["Visible"] = false; + } + } + } + + EntityWrapper sniperBoostEntity = friendlyBoostHud.FirstChildByName("SniperBoost"); + if (sniperBoostEntity.Valid()) { + EntityWrapper active = sniperBoostEntity.FirstChildByName("Active"); + if (active.HasComponent("Text")) { + if (sniperBoost.Valid()) { + (Field)active["Text"]["Visible"] = true; + } else { + (Field)active["Text"]["Visible"] = false; + } + } + } + } + } + } else { + EntityWrapper friendlyBoostHud = friendlyBoostHudSpawner.FirstChildByName("FriendlyBoostHUD"); + if (friendlyBoostHud.Valid()) { + if (friendlyBoostHud.HasComponent("Lifetime")) { + (Field)friendlyBoostHud["Lifetime"]["Lifetime"] = 0.5; + } + + + + EntityWrapper assaultBoostEntity = friendlyBoostHud.FirstChildByName("AssaultBoost"); + if (assaultBoostEntity.Valid()) { + EntityWrapper active = assaultBoostEntity.FirstChildByName("Active"); + if (active.HasComponent("Text")) { + if (assaultBoost.Valid()) { + (Field)active["Text"]["Visible"] = true; + } else { + (Field)active["Text"]["Visible"] = false; + } + } + } + + EntityWrapper defenderBoostEntity = friendlyBoostHud.FirstChildByName("DefenderBoost"); + if (defenderBoostEntity.Valid()) { + EntityWrapper active = defenderBoostEntity.FirstChildByName("Active"); + if (active.HasComponent("Text")) { + if (defenderBoost.Valid()) { + (Field)active["Text"]["Visible"] = true; + } else { + (Field)active["Text"]["Visible"] = false; + } + } + } + + EntityWrapper sniperBoostEntity = friendlyBoostHud.FirstChildByName("SniperBoost"); + if (sniperBoostEntity.Valid()) { + EntityWrapper active = sniperBoostEntity.FirstChildByName("Active"); + if (active.HasComponent("Text")) { + if (sniperBoost.Valid()) { + (Field)active["Text"]["Visible"] = true; + } else { + (Field)active["Text"]["Visible"] = false; + } + } + } + } + } + } + } +} diff --git a/src/Game/Systems/Weapon/SidearmWeaponBehaviour.cpp b/src/Game/Systems/Weapon/SidearmWeaponBehaviour.cpp new file mode 100644 index 00000000..8ce9d444 --- /dev/null +++ b/src/Game/Systems/Weapon/SidearmWeaponBehaviour.cpp @@ -0,0 +1,578 @@ +#include "Systems/Weapon/SidearmWeaponBehaviour.h" + +void SidearmWeaponBehaviour::UpdateComponent(EntityWrapper& entity, ComponentWrapper& cWeapon, double dt) +{ + Field cooldown = cWeapon["FireCooldown"]; + if (cooldown > 0) { + cooldown -= dt; + if (cooldown < 0) { + cooldown = 0; + } + } + WeaponBehaviour::UpdateComponent(entity, cWeapon, dt); +} + +void SidearmWeaponBehaviour::UpdateWeapon(ComponentWrapper cWeapon, WeaponInfo& wi, double dt) +{ + CheckAmmo(cWeapon, wi); + + // Start reloading automatically if at 0 mag ammo + Field magAmmo = cWeapon["MagazineAmmo"]; + if (m_ConfigAutoReload && magAmmo <= 0) { + OnReload(cWeapon, wi); + } + + // Only start reloading once we're done firing + Field reloadQueued = cWeapon["ReloadQueued"]; + Field fireCooldown = cWeapon["FireCooldown"]; + Field isReloading = cWeapon["IsReloading"]; + if (reloadQueued && fireCooldown <= 0) { + reloadQueued = fireCooldown; + isReloading = true; + } + + // Decrement reload timer + Field reloadTimer = cWeapon["ReloadTimer"]; + if (isReloading) { + reloadTimer = glm::max(0.0, reloadTimer - dt); + } + + // Handle reloading + if (isReloading && reloadTimer <= 0.0) { + Field magSize = cWeapon["MagazineSize"]; + + magAmmo = magSize; + isReloading = false; + if (wi.FirstPersonEntity.Valid()) { + wi.FirstPersonEntity.FirstChildByName("ViewModel")["Model"]["Visible"] = true; + } + if (wi.ThirdPersonEntity.Valid()) { + wi.ThirdPersonEntity["Model"]["Visible"] = true; + } + } + double reloadTime = cWeapon["ReloadTime"]; + if (isReloading && reloadTimer <= reloadTime / 2) { + + } + + // Update first person run animation + ComponentWrapper cPlayer = wi.Player["Player"]; + ComponentWrapper cPhysics = wi.Player["Physics"]; + const float& movementSpeed = cPlayer["MovementSpeed"]; + float speed = glm::length((const glm::vec3&)cPhysics["Velocity"]); + float animationWeight = glm::min(speed, movementSpeed) / movementSpeed; + EntityWrapper rootNode = wi.FirstPersonEntity; + if (rootNode.Valid()) { + EntityWrapper blend = rootNode.FirstChildByName("MovementBlendSidearm"); + if (blend.Valid()) { + (Field)blend["Blend"]["Weight"] = animationWeight; + } + } + + // Restore view angle + if (IsClient) { + 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()) { + Field cameraOrientation = camera["Transform"]["Orientation"]; + cameraOrientation.x(cameraOrientation.x() - change); + } + } + } + + if ((bool)cWeapon["Automatic"] && canFire(cWeapon)) { + fireBullet(cWeapon, wi); + } +} + +void SidearmWeaponBehaviour::OnPrimaryFire(ComponentWrapper cWeapon, WeaponInfo& wi) +{ + cWeapon["TriggerHeld"] = true; + if (canFire(cWeapon)) { + fireBullet(cWeapon, wi); + } +} + +void SidearmWeaponBehaviour::OnCeasePrimaryFire(ComponentWrapper cWeapon, WeaponInfo& wi) +{ + cWeapon["TriggerHeld"] = false; +} + + +void SidearmWeaponBehaviour::OnReload(ComponentWrapper cWeapon, WeaponInfo& wi) +{ + Field reloadQueued = cWeapon["ReloadQueued"]; + Field isReloading = cWeapon["IsReloading"]; + if (reloadQueued || isReloading) { + return; + } + + Field magAmmo = cWeapon["MagazineAmmo"]; + Field magSize = cWeapon["MagazineSize"]; + if (magAmmo >= magSize) { + return; + } + + double reloadTime = cWeapon["ReloadTime"]; + Field reloadTimer = cWeapon["ReloadTimer"]; + + // Start reload + reloadQueued = true; + reloadTimer = reloadTime; + + // Play animation + playAnimationAndReturn(wi.FirstPersonEntity, "ActionBlend", "Reload"); + // Third person anim + Events::AutoAnimationBlend eReloadBlend; + eReloadBlend.RootNode = wi.ThirdPersonPlayerModel; + eReloadBlend.NodeName = "Reload"; + eReloadBlend.Restart = true; + eReloadBlend.Start = true; + m_EventBroker->Publish(eReloadBlend); + + // Spawn explosion effect + if (wi.FirstPersonEntity.Valid()) { + if (IsClient) { + EntityWrapper reloadEffectSpawner = wi.FirstPersonEntity.FirstChildByName("ReloadSpawner"); + if (reloadEffectSpawner.Valid()) { + reloadEffectSpawner.DeleteChildren(); + SpawnerSystem::Spawn(reloadEffectSpawner, reloadEffectSpawner); + } + } + wi.FirstPersonEntity.FirstChildByName("ViewModel")["Model"]["Visible"] = false; + } + if (wi.ThirdPersonEntity.Valid()) { + if (IsServer) { + EntityWrapper reloadEffectSpawner = wi.ThirdPersonEntity.FirstChildByName("ReloadSpawner"); + if (reloadEffectSpawner.Valid()) { + reloadEffectSpawner.DeleteChildren(); + SpawnerSystem::Spawn(reloadEffectSpawner, reloadEffectSpawner); + } + } + wi.ThirdPersonEntity["Model"]["Visible"] = false; + } + + // Sound + Events::PlaySoundOnEntity e; + e.Emitter = wi.Player; + e.FilePath = "Audio/weapon/Assault/AssaultWeaponReload.wav"; + m_EventBroker->Publish(e); +} + +void SidearmWeaponBehaviour::OnEquip(ComponentWrapper cWeapon, WeaponInfo& wi) +{ + cWeapon["FireCooldown"] = (double)cWeapon["EquipTime"]; + + if(wi.ThirdPersonPlayerModel.Valid()) { + Events::AutoAnimationBlend b1; + b1.RootNode = wi.ThirdPersonPlayerModel; + b1.NodeName = "SidearmWeapon"; + b1.SingleLevelBlend = true; + m_EventBroker->Publish(b1); + } +} + +void SidearmWeaponBehaviour::OnHolster(ComponentWrapper cWeapon, WeaponInfo& wi) +{ + // Make sure the trigger is released if weapon is holstered while firing + cWeapon["TriggerHeld"] = false; + + // Cancel any reload + cWeapon["IsReloading"] = false; + cWeapon["ReloadTimer"] = 0.0; +} + +void SidearmWeaponBehaviour::fireBullet(ComponentWrapper cWeapon, WeaponInfo& wi) +{ + cWeapon["FireCooldown"] = 60.0 / (double)cWeapon["RPM"]; + + // Ammo + 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()) { + return; + } + + // Tracer + EntityWrapper tracerSpawner = weaponModelEntity.FirstChildByName("WeaponMuzzleRay"); + if (tracerSpawner.Valid()) { + 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()) { + ((Field)ray["Transform"]["Scale"]).x(distance); + ((Field)ray["Transform"]["Position"]).z(-distance/2.f); + } + } + + //Flash + EntityWrapper flashSpawner = weaponModelEntity.FirstChildByName("WeaponMuzzleFlash"); + if (flashSpawner.Valid()) { + std::uniform_real_distribution randomSpreadAngle(0.f, 3.1415f*2); + EntityWrapper flash = SpawnerSystem::Spawn(flashSpawner, flashSpawner); + if(flash.Valid()){ + ((Field)flash["Transform"]["Orientation"]).z(randomSpreadAngle(m_RandomEngine)); + } + } + + + // Deal damage + if (dealDamage(cWeapon, wi)) { + // Show hit marker + EntityWrapper hitMarkerSpawner = wi.Player.FirstChildByName("HitMarkerSpawner"); + if (hitMarkerSpawner.Valid()) { + SpawnerSystem::Spawn(hitMarkerSpawner, hitMarkerSpawner); + Events::PlaySoundOnEntity e; + e.Emitter = wi.Player; + e.FilePath = "Audio/weapon/hitclick.wav"; + m_EventBroker->Publish(e); + } + } + + + // Play animation + playAnimationAndReturn(wi.FirstPersonEntity, "ActionBlend", "Fire"); + + // Third person anim + if (wi.ThirdPersonPlayerModel.Valid()) { + Events::AutoAnimationBlend b1; + b1.RootNode = wi.ThirdPersonPlayerModel; + b1.NodeName = "Fire"; + b1.Restart = true; + b1.Start = true; + m_EventBroker->Publish(b1); + } +} + +bool SidearmWeaponBehaviour::canFire(ComponentWrapper cWeapon) +{ + bool triggerHeld = cWeapon["TriggerHeld"]; + bool cooldownPassed = (double)cWeapon["FireCooldown"] <= 0.0; + bool isNotReloading = !(bool)cWeapon["IsReloading"]; + return triggerHeld && cooldownPassed && isNotReloading; +} + +bool SidearmWeaponBehaviour::dealDamage(ComponentWrapper cWeapon, WeaponInfo& wi) +{ + // Only deal damage client side + if (!IsClient) { + return false; + } + + // Only handle damage for the local player + if (wi.Player != LocalPlayer) { + return false; + } + + // Make sure the player isn't shooting from the grave + if (!wi.Player.Valid()) { + return false; + } + + // 3D-pick middle of screen + Rectangle viewport = m_Renderer->GetViewportSize(); + glm::vec2 centerScreen(viewport.Width / 2, viewport.Height / 2); + // TODO: Some horizontal spread + PickData pickData = m_Renderer->Pick(centerScreen); + EntityWrapper victim(m_World, pickData.Entity); + if (!victim.Valid()) { + return false; + } + + // Don't let us somehow shoot ourselves in the foot + if (victim == LocalPlayer) { + return false; + } + + // Only care about players being hit + if (!victim.HasComponent("Player")) { + victim = victim.FirstParentWithComponent("Player"); + } + if (!victim.Valid()) { + return false; + } + + double damage = cWeapon["BaseDamage"]; + // If friendly fire, reduce damage to 0 (needed to make Boosts, Ammosharing work) + if ((ComponentInfo::EnumType)victim["Team"]["Team"] == (ComponentInfo::EnumType)wi.Player["Team"]["Team"]) { + damage = 0; + + bool gaveAmmo = false; + + if (victim.HasComponent("AssaultWeapon")) { + int magazineSize = victim["AssaultWeapon"]["MagazineSize"]; + int magazineAmmo = victim["AssaultWeapon"]["MagazineAmmo"]; + + int maxAmmo = victim["AssaultWeapon"]["MaxAmmo"]; + int ammo = victim["AssaultWeapon"]["Ammo"]; + + if (magazineAmmo < magazineSize) { + gaveAmmo = true; + } else if (ammo < maxAmmo) { + gaveAmmo = true; + } + } else if (victim.HasComponent("DefenderWeapon")) { + int magazineSize = victim["DefenderWeapon"]["MagazineSize"]; + int magazineAmmo = victim["DefenderWeapon"]["MagazineAmmo"]; + + int maxAmmo = victim["DefenderWeapon"]["MaxAmmo"]; + int ammo = victim["DefenderWeapon"]["Ammo"]; + + if (magazineAmmo < magazineSize) { + gaveAmmo = true; + } else if (ammo < maxAmmo) { + gaveAmmo = true; + } + } + + + if (gaveAmmo) { + EntityWrapper effectSpawner = wi.FirstPersonEntity.FirstChildByName("AmmoShareEffectSpawner"); + if (effectSpawner.Valid()) { + if (effectSpawner.HasComponent("Spawner")) { + SpawnerSystem::Spawn(effectSpawner, effectSpawner); + } + } + } + } + + spawnTracer(cWeapon, wi); + + // Deal damage! + Events::PlayerDamage ePlayerDamage; + ePlayerDamage.Inflictor = wi.Player; + ePlayerDamage.Victim = victim; + ePlayerDamage.Damage = damage; + m_EventBroker->Publish(ePlayerDamage); + + return damage > 0; +} + +void SidearmWeaponBehaviour::spawnTracer(ComponentWrapper cWeapon, WeaponInfo& wi) +{ + EntityWrapper muzzle = getRelevantWeaponEntity(wi).FirstChildByName("WeaponMuzzle"); + if (!muzzle.Valid()) { + return; + } + + EntityWrapper camera = wi.Player.FirstChildByName("Camera"); + if (!camera.Valid()) { + return; + } + + glm::vec3 cameraPosition = TransformSystem::AbsolutePosition(camera); + glm::vec3 direction = glm::vec3(0, 0, -1); + + float distance; + glm::vec3 hitPosition; + Collision::EntityFirstHitByRay(Ray(cameraPosition, direction), m_CollisionOctree, distance, hitPosition); + + EntityWrapper ray = SpawnerSystem::Spawn(muzzle); + if (ray.Valid()) { + ComponentWrapper cTransform = ray["Transform"]; + Field rayOrigin = cTransform["Position"]; + Field rayOrientation = cTransform["Orientation"]; + Field rayScale = cTransform["Scale"]; + + glm::vec3 muzzlePosition = TransformSystem::AbsolutePosition(muzzle); + glm::quat muzzleOrientation = TransformSystem::AbsoluteOrientation(muzzle); + + rayOrigin = muzzlePosition; + + glm::vec3 muzzleToHit = hitPosition - muzzlePosition; + glm::vec3 lookVector = glm::normalize(-muzzleToHit); + float pitch = std::asin(-lookVector.y); + float yaw = std::atan2(lookVector.x, lookVector.z); + glm::quat orientation = glm::quat(glm::vec3(pitch, yaw, 0)); + rayOrientation = glm::eulerAngles(orientation); + rayScale.z(glm::length(muzzleToHit)); + } + +} + +/* + +void SidearmWeaponBehaviour::giveAmmo(ComponentWrapper cWeapon, WeaponInfo& wi, EntityWrapper receiver) +{ + bool gaveAmmo = false; + + if (receiver.HasComponent("AssaultWeapon")) { + int magazineSize = receiver["AssaultWeapon"]["MagazineSize"]; + int& magazineAmmo = receiver["AssaultWeapon"]["MagazineAmmo"]; + + int maxAmmo = receiver["AssaultWeapon"]["MaxAmmo"]; + int& ammo = receiver["AssaultWeapon"]["Ammo"]; + + if(magazineAmmo < magazineSize) { + magazineAmmo += 1; + gaveAmmo = true; + } else if (ammo < maxAmmo) { + ammo += 1; + gaveAmmo = true; + } + } else if (receiver.HasComponent("DefenderWeapon")) { + int magazineSize = receiver["DefenderWeapon"]["MagazineSize"]; + int& magazineAmmo = receiver["DefenderWeapon"]["MagazineAmmo"]; + + int maxAmmo = receiver["DefenderWeapon"]["MaxAmmo"]; + int& ammo = receiver["DefenderWeapon"]["Ammo"]; + + if (magazineAmmo < magazineSize) { + magazineAmmo += 1; + gaveAmmo = true; + } else if (ammo < maxAmmo) { + ammo += 1; + gaveAmmo = true; + } + } + + + if(gaveAmmo) { + EntityWrapper effectSpawner = wi.FirstPersonEntity.FirstChildByName("AmmoShareEffectSpawner"); + if(effectSpawner.Valid()) { + if (effectSpawner.HasComponent("Spawner")) { + SpawnerSystem::Spawn(effectSpawner, effectSpawner); + } + } + } +}*/ + +void SidearmWeaponBehaviour::CheckAmmo(ComponentWrapper cWeapon, WeaponInfo& wi) +{ + // Only check ammo client side + if (!IsClient) { + return; + } + + // Only handle ammo check for the local player + if (wi.Player != LocalPlayer) { + return; + } + + // Make sure the player isn't checking from the grave + if (!wi.Player.Valid()) { + return; + } + + // 3D-pick middle of screen + Rectangle viewport = m_Renderer->GetViewportSize(); + glm::vec2 centerScreen(viewport.Width / 2, viewport.Height / 2); + // TODO: Some horizontal spread + PickData pickData = m_Renderer->Pick(centerScreen); + EntityWrapper victim(m_World, pickData.Entity); + if (!victim.Valid()) { + RemoveFrindlyAmmoHUD(wi); + return; + } + + // Don't let us somehow shoot ourselves in the foot + if (victim == LocalPlayer) { + RemoveFrindlyAmmoHUD(wi); + return; + } + + // Only care about players being hit + if (!victim.HasComponent("Player")) { + victim = victim.FirstParentWithComponent("Player"); + } + if (!victim.Valid()) { + RemoveFrindlyAmmoHUD(wi); + return; + } + + + // If friendly fire, reduce damage to 0 (needed to make Boosts, Ammosharing work) + if ((ComponentInfo::EnumType)victim["Team"]["Team"] == (ComponentInfo::EnumType)wi.Player["Team"]["Team"]) { + int magazineAmmo = 0; + int ammo = 0; + if (victim.HasComponent("AssaultWeapon")) { + magazineAmmo = (int)victim["AssaultWeapon"]["MagazineAmmo"]; + ammo = (int)victim["AssaultWeapon"]["Ammo"]; + + } else if (victim.HasComponent("DefenderWeapon")) { + magazineAmmo = (int)victim["DefenderWeapon"]["MagazineAmmo"]; + ammo = (int)victim["DefenderWeapon"]["Ammo"]; + } + + + EntityWrapper friendlyAmmoHudSpawner = wi.FirstPersonPlayerModel.FirstChildByName("FriendlyAmmoAttachment"); + if (friendlyAmmoHudSpawner.Valid()) { + + auto children = m_World->GetDirectChildren(friendlyAmmoHudSpawner.ID); + + if (children.first == children.second) { + if (friendlyAmmoHudSpawner.HasComponent("Spawner")) { + EntityWrapper friendlyAmmoHud = SpawnerSystem::Spawn(friendlyAmmoHudSpawner, friendlyAmmoHudSpawner); + if (friendlyAmmoHud.Valid()) { + EntityWrapper textEntity = friendlyAmmoHud.FirstChildByName("MagazineAmmo"); + if (textEntity.Valid()) { + if (textEntity.HasComponent("Text")) { + (Field)textEntity["Text"]["Content"] = std::to_string(magazineAmmo); + } + } + + EntityWrapper ammoTextEntity = friendlyAmmoHud.FirstChildByName("Ammo"); + if (ammoTextEntity.Valid()) { + if (ammoTextEntity.HasComponent("Text")) { + (Field)ammoTextEntity["Text"]["Content"] = std::to_string(ammo); + } + } + } + } + } else { + EntityWrapper textEntity = friendlyAmmoHudSpawner.FirstChildByName("MagazineAmmo"); + if (textEntity.Valid()) { + if (textEntity.HasComponent("Text")) { + (Field)textEntity["Text"]["Content"] = std::to_string(magazineAmmo); + } + } + + EntityWrapper ammoTextEntity = friendlyAmmoHudSpawner.FirstChildByName("Ammo"); + if (ammoTextEntity.Valid()) { + if (ammoTextEntity.HasComponent("Text")) { + (Field)ammoTextEntity["Text"]["Content"] = std::to_string(ammo); + } + } + } + } + } +} + +void SidearmWeaponBehaviour::RemoveFrindlyAmmoHUD(WeaponInfo& wi) +{ + EntityWrapper friendlyAmmoHudSpawner = wi.FirstPersonPlayerModel.FirstChildByName("FriendlyAmmoAttachment"); + if (friendlyAmmoHudSpawner.Valid()) { + friendlyAmmoHudSpawner.DeleteChildren(); + } +} diff --git a/src/Game/main.cpp b/src/Game/main.cpp index dd2a5a84..3c9b6d38 100644 --- a/src/Game/main.cpp +++ b/src/Game/main.cpp @@ -9,7 +9,9 @@ int main(int argc, char* argv[]) Game game(argc, argv); while (game.Running()) { + PerformanceTimer::StartTimer("Game-Tick"); game.Tick(); + PerformanceTimer::StopTimer("Game-Tick"); } return 0; diff --git a/src/Tests/CapturePointTest.cpp b/src/Tests/CapturePointTest.cpp index 8a9baf40..8fb7869c 100644 --- a/src/Tests/CapturePointTest.cpp +++ b/src/Tests/CapturePointTest.cpp @@ -7,7 +7,7 @@ using boost::unit_test_framework::test_case; #include "Collision/TriggerSystem.h" #include "Collision/CollisionSystem.h" -#include "Core/EntityFileWriter.h" +#include "Core/EntityXMLFileWriter.h" #include "Game/Systems/CapturePointSystem.h" BOOST_AUTO_TEST_SUITE(CapturePointTestSuite) @@ -82,7 +82,7 @@ bool CapturePointTest::CapturePoint_Game_Loop_OneHundredTimes() { CapturePointTest::CapturePointTest(int runTestNumber) { ResourceManager::RegisterType("ConfigFile"); - ResourceManager::RegisterType("EntityFile"); + ResourceManager::RegisterType("EntityFile"); m_Config = ResourceManager::Load("Config.ini"); LOG_LEVEL = static_cast<_LOG_LEVEL>(m_Config->Get("Debug.LogLevel", 1)); @@ -99,10 +99,10 @@ CapturePointTest::CapturePointTest(int runTestNumber) m_SystemPipeline->AddSystem(1); //must register components (Components.xsd), else you cant create entities. Easiest done by loading a test xsd file - auto file = ResourceManager::Load("Schema/Entities/TeamTest.xml"); - EntityFilePreprocessor fpp(file); + auto file = ResourceManager::Load("Schema/Entities/TeamTest.xml"); + EntityXMLFilePreprocessor fpp(file); fpp.RegisterComponents(m_World); - EntityFileParser fp(file); + EntityXMLFileParser fp(file); fp.MergeEntities(m_World); EntityID playerID = m_World->CreateEntity(); diff --git a/src/Tests/CapturePointTest.h b/src/Tests/CapturePointTest.h index 54bdc55c..1046f714 100644 --- a/src/Tests/CapturePointTest.h +++ b/src/Tests/CapturePointTest.h @@ -9,12 +9,12 @@ #include "Input/KeyboardInputHandler.h" #include "Input/MouseInputHandler.h" #include "Core/EKeyDown.h" -#include "Core/EntityFile.h" +#include "Core/EntityXMLFile.h" #include "Core/SystemPipeline.h" -#include "Core/EntityFilePreprocessor.h" -#include "Core/EntityFileParser.h" -#include "Core/EntityFileWriter.h" +#include "Core/EntityXMLFilePreprocessor.h" +#include "Core/EntityXMLFileParser.h" +#include "Core/EntityXMLFileWriter.h" #include "Engine/Collision/ETrigger.h" diff --git a/src/Tests/HealthPickupTest.cpp b/src/Tests/HealthPickupTest.cpp index bcdda99e..cd4cf5fa 100644 --- a/src/Tests/HealthPickupTest.cpp +++ b/src/Tests/HealthPickupTest.cpp @@ -30,7 +30,7 @@ BOOST_AUTO_TEST_SUITE_END() PickupSpawnTest::PickupSpawnTest(int runTestNumber) { ResourceManager::RegisterType("ConfigFile"); - ResourceManager::RegisterType("EntityFile"); + ResourceManager::RegisterType("EntityFile"); m_Config = ResourceManager::Load("Config.ini"); LOG_LEVEL = static_cast<_LOG_LEVEL>(m_Config->Get("Debug.LogLevel", 1)); @@ -44,10 +44,10 @@ PickupSpawnTest::PickupSpawnTest(int runTestNumber) m_SystemPipeline->AddSystem(1); //must register components (Components.xsd), else you cant create entities. Easiest done by loading a test xsd file - auto file = ResourceManager::Load("Schema/Entities/HealthPickup.xml"); - EntityFilePreprocessor fpp(file); + auto file = ResourceManager::Load("Schema/Entities/HealthPickup.xml"); + EntityXMLFilePreprocessor fpp(file); fpp.RegisterComponents(m_World); - EntityFileParser fp(file); + EntityXMLFileParser fp(file); //connect the healthpickup to the world m_HealthPickupID = fp.MergeEntities(m_World); diff --git a/src/Tests/HealthPickupTest.h b/src/Tests/HealthPickupTest.h index a66f7bc1..ce3f99ca 100644 --- a/src/Tests/HealthPickupTest.h +++ b/src/Tests/HealthPickupTest.h @@ -9,12 +9,12 @@ #include "Input/KeyboardInputHandler.h" #include "Input/MouseInputHandler.h" #include "Core/EKeyDown.h" -#include "Core/EntityFile.h" +#include "Core/EntityXMLFile.h" #include "Core/SystemPipeline.h" -#include "Core/EntityFilePreprocessor.h" -#include "Core/EntityFileParser.h" -#include "Core/EntityFileWriter.h" +#include "Core/EntityXMLFilePreprocessor.h" +#include "Core/EntityXMLFileParser.h" +#include "Core/EntityXMLFileWriter.h" #include "Engine/Collision/ETrigger.h" @@ -29,7 +29,7 @@ //#include #include "Collision/TriggerSystem.h" #include "Collision/CollisionSystem.h" -#include "Core/EntityFileWriter.h" +#include "Core/EntityXMLFileWriter.h" #include "Game/Systems/HealthSystem.h" #include "Game/Systems/HealthPickupSystem.h" diff --git a/src/Tests/HealthSystemTest.cpp b/src/Tests/HealthSystemTest.cpp index bf2650a3..0a8758ae 100644 --- a/src/Tests/HealthSystemTest.cpp +++ b/src/Tests/HealthSystemTest.cpp @@ -30,7 +30,7 @@ BOOST_AUTO_TEST_SUITE_END() GameHealthSystemTest::GameHealthSystemTest() { ResourceManager::RegisterType("ConfigFile"); - ResourceManager::RegisterType("EntityFile"); + ResourceManager::RegisterType("EntityFile"); m_Config = ResourceManager::Load("Config.ini"); LOG_LEVEL = static_cast<_LOG_LEVEL>(m_Config->Get("Debug.LogLevel", 1)); @@ -41,10 +41,10 @@ GameHealthSystemTest::GameHealthSystemTest() // Create a world m_World = new World(); - auto file = ResourceManager::Load("Schema/Entities/TeamTest.xml"); - EntityFilePreprocessor fpp(file); + auto file = ResourceManager::Load("Schema/Entities/TeamTest.xml"); + EntityXMLFilePreprocessor fpp(file); fpp.RegisterComponents(m_World); - EntityFileParser fp(file); + EntityXMLFileParser fp(file); fp.MergeEntities(m_World); // Create system pipeline diff --git a/src/Tests/HealthSystemTest.h b/src/Tests/HealthSystemTest.h index 275558d2..787a2d0e 100644 --- a/src/Tests/HealthSystemTest.h +++ b/src/Tests/HealthSystemTest.h @@ -11,7 +11,7 @@ #include "Input/KeyboardInputHandler.h" #include "Input/MouseInputHandler.h" #include "Core/EKeyDown.h" -#include "Core/EntityFile.h" +#include "Core/EntityXMLFile.h" #include "Core/SystemPipeline.h" #include "Editor/EditorSystem.h" 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/Export.cpp b/tools/MayaExporter/MayaExporter/Export.cpp index 3497fd04..28112cd6 100644 --- a/tools/MayaExporter/MayaExporter/Export.cpp +++ b/tools/MayaExporter/MayaExporter/Export.cpp @@ -5,7 +5,7 @@ Export::Export() } -bool Export::Meshes(std::string pathName, bool selectedOnly) +bool Export::Meshes(std::string pathName, bool selectedOnly, bool isCollision) { MStatus status; if (pathName.empty()) { @@ -92,8 +92,14 @@ bool Export::Meshes(std::string pathName, bool selectedOnly) Objects.append(node); } } - GetMeshData(Objects); - WriteMeshData(pathName); + GetMeshData(Objects, isCollision); + + if (!isCollision) { + WriteMeshData(pathName); + } else { + WriteCollisionData(pathName); + } + MGlobal::displayInfo(MString() + "Enabling IKSolvers"); status = MGlobal::executeCommand("doEnableNodeItems true all;"); if (status != MS::kSuccess) { @@ -144,9 +150,9 @@ bool Export::Animations(std::string pathName, std::vector animInf return true; } -bool Export::GetMeshData(MObjectArray object) +bool Export::GetMeshData(MObjectArray object, bool collision) { - meshes = m_MeshHandler.GetMeshData(object); + meshes = m_MeshHandler.GetMeshData(object, collision); return true; } @@ -185,6 +191,17 @@ void Export::WriteMeshData(std::string pathName) m_MeshFile.CloseFiles(); } +void Export::WriteCollisionData(std::string pathName) { + m_ColliFile.ASCIIFilePath(pathName + "_colli.txt"); + m_ColliFile.binaryFilePath(pathName + ".colli"); + + m_ColliFile.OpenFiles(); + + m_ColliFile.writeToFiles((OutputData*)&meshes); + + m_ColliFile.CloseFiles(); +} + void Export::WriteAnimData(std::string pathName) { if (allBindPoses.size() > 0) { diff --git a/tools/MayaExporter/MayaExporter/Export.h b/tools/MayaExporter/MayaExporter/Export.h index 42b40445..c22cd26e 100644 --- a/tools/MayaExporter/MayaExporter/Export.h +++ b/tools/MayaExporter/MayaExporter/Export.h @@ -22,18 +22,19 @@ public: int End; }; - bool Meshes(std::string pathName, bool selectedOnly = false); + bool Meshes(std::string pathName, bool selectedOnly = false, bool isCollision = false); bool Materials(std::string pathName); bool Animations(std::string pathName, std::vector animInfo); private: - bool GetMeshData(MObjectArray object); + bool GetMeshData(MObjectArray object, bool collision); bool GetMaterialData(); bool GetAnimationData(AnimationInfo info); void WriteMeshData(std::string pathName); void WriteAnimData(std::string pathName); void WriteMaterialData(std::string pathName); + void WriteCollisionData(std::string pathName); Material m_MaterialHandler; Skeleton m_SkeletonHandler; @@ -44,6 +45,7 @@ private: WriteToFile m_MeshFile; WriteToFile m_AnimFile; WriteToFile m_MtrlFile; + WriteToFile m_ColliFile; //Mesh Data Mesh meshes; 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())); } } diff --git a/tools/MayaExporter/MayaExporter/Menu.cpp b/tools/MayaExporter/MayaExporter/Menu.cpp index 02810018..ed3761df 100644 --- a/tools/MayaExporter/MayaExporter/Menu.cpp +++ b/tools/MayaExporter/MayaExporter/Menu.cpp @@ -25,6 +25,7 @@ Menu::Menu(QDialog* dialog) m_ExportSelectedButton = new QCheckBox(tr("&Export Selected")); m_ExportAnimationsButton = new QCheckBox(tr("&Export Animations")); m_ExportMaterialButton = new QCheckBox(tr("&Export Material"));; + m_IsCollision = new QCheckBox(tr("&Export as collision mesh")); m_ExportAnimationsButton->setChecked(true); m_ExportMaterialButton->setChecked(true); @@ -32,6 +33,7 @@ Menu::Menu(QDialog* dialog) vbox->addWidget(m_ExportSelectedButton); vbox->addWidget(m_ExportAnimationsButton); vbox->addWidget(m_ExportMaterialButton); + vbox->addWidget(m_IsCollision); vbox->addStretch(1); optionsBox->setLayout(vbox); @@ -46,6 +48,7 @@ Menu::Menu(QDialog* dialog) connect(m_ExportSelectedButton, SIGNAL(clicked(bool)), this, SLOT(NULL)); connect(m_ExportAnimationsButton, SIGNAL(clicked(bool)), this, SLOT(NULL)); connect(m_ExportMaterialButton, SIGNAL(clicked(bool)), this, SLOT(NULL)); + connect(m_IsCollision, SIGNAL(clicked(bool)), this, SLOT(NULL)); // Creating several layouts, adding widgets & adding them to one layout in the end QHBoxLayout* topLayout = new QHBoxLayout; @@ -163,40 +166,42 @@ void Menu::RemoveClipClicked(bool) void Menu::ExportAll(bool) { - if (m_ExportPath->text().isEmpty()) { - MGlobal::displayError(MString() + "Please select a folder."); - return; - } + if (m_ExportPath->text().isEmpty()) { + MGlobal::displayError(MString() + "Please select a folder."); + return; + } - //Export meshes - if (!m_Export.Meshes(m_ExportPath->text().toLocal8Bit().constData(), m_ExportSelectedButton->isChecked())) { - MGlobal::displayError(MString() + "Could not export mesh"); - return; - } + //Export meshes + if (!m_Export.Meshes(m_ExportPath->text().toLocal8Bit().constData(), m_ExportSelectedButton->isChecked(), m_IsCollision->isChecked())) { + MGlobal::displayError(MString() + "Could not export mesh"); + return; + } - if (m_ExportMaterialButton->isChecked()) { - if (!m_Export.Materials(m_ExportPath->text().toLocal8Bit().constData())) { - MGlobal::displayError(MString() + "Could not export materials"); - return; - } - } + if (!m_IsCollision->isChecked()){ + if (m_ExportMaterialButton->isChecked()) { + if (!m_Export.Materials(m_ExportPath->text().toLocal8Bit().constData())) { + MGlobal::displayError(MString() + "Could not export materials"); + return; + } + } - std::vector animations; - for (unsigned int i = 0; i < m_AnimationClipName.size(); i++) { - Export::AnimationInfo thisClip; - thisClip.Name = std::string(m_AnimationClipName[i]->text().toLocal8Bit().constData()); - thisClip.Start = m_StartFrameLines[i]->text().toInt(); - thisClip.End = m_EndFrameLines[i]->text().toInt(); + std::vector animations; + for (unsigned int i = 0; i < m_AnimationClipName.size(); i++) { + Export::AnimationInfo thisClip; + thisClip.Name = std::string(m_AnimationClipName[i]->text().toLocal8Bit().constData()); + thisClip.Start = m_StartFrameLines[i]->text().toInt(); + thisClip.End = m_EndFrameLines[i]->text().toInt(); - animations.push_back(thisClip); - } - if (m_ExportAnimationsButton->isChecked()) { - //Export Animations - if (!m_Export.Animations(m_ExportPath->text().toLocal8Bit().constData(), animations)) { - MGlobal::displayError(MString() + "Could not export animations"); - return; - } - } + animations.push_back(thisClip); + } + if (m_ExportAnimationsButton->isChecked()) { + //Export Animations + if (!m_Export.Animations(m_ExportPath->text().toLocal8Bit().constData(), animations)) { + MGlobal::displayError(MString() + "Could not export animations"); + return; + } + } + } } void Menu::CancelClicked(bool) diff --git a/tools/MayaExporter/MayaExporter/Menu.h b/tools/MayaExporter/MayaExporter/Menu.h index fb95a953..89211a12 100644 --- a/tools/MayaExporter/MayaExporter/Menu.h +++ b/tools/MayaExporter/MayaExporter/Menu.h @@ -66,6 +66,7 @@ private: QCheckBox* m_ExportSelectedButton = nullptr; QCheckBox* m_ExportAnimationsButton = nullptr; QCheckBox* m_ExportMaterialButton = nullptr; + QCheckBox* m_IsCollision = nullptr; QLineEdit* m_ExportPath = nullptr; QFileDialog* m_FileDialog = nullptr; diff --git a/tools/MayaExporter/MayaExporter/Mesh.cpp b/tools/MayaExporter/MayaExporter/Mesh.cpp index ee5a6022..6868e792 100644 --- a/tools/MayaExporter/MayaExporter/Mesh.cpp +++ b/tools/MayaExporter/MayaExporter/Mesh.cpp @@ -94,33 +94,37 @@ MeshClass::MeshClass() // return weightMap; //} -Mesh MeshClass::GetMeshData(MObjectArray object) +Mesh MeshClass::GetMeshData(MObjectArray object, bool collision) { MS status; Mesh newMesh; + newMesh.isCollison = collision; vector& vertexList = newMesh.Vertices; map>& indexLists = newMesh.Indices; for (int ObjectID = 0; ObjectID < object.length(); ObjectID++) { if (!object[ObjectID].hasFn(MFn::kMesh)) continue; + MObject node = object[ObjectID]; MFnDependencyNode thisNode(node); MPlugArray connections; thisNode.findPlug("inMesh").connectedTo(connections, true, true); MPlug weightList, weights; MObject weightListObject; - for (unsigned int i = 0; i < connections.length(); i++) { - if (connections[i].node().apiType() == MFn::kSkinClusterFilter) { - MFnSkinCluster skinCluster(connections[i].node()); - weightList = skinCluster.findPlug("weightList", &status); - weightListObject = weightList.attribute(); - weights = skinCluster.findPlug("weights"); - newMesh.hasSkin = true; - break; - } - } + if (!collision) { + for (unsigned int i = 0; i < connections.length(); i++) { + if (connections[i].node().apiType() == MFn::kSkinClusterFilter) { + MFnSkinCluster skinCluster(connections[i].node()); + weightList = skinCluster.findPlug("weightList", &status); + weightListObject = weightList.attribute(); + weights = skinCluster.findPlug("weights"); + newMesh.hasSkin = true; + break; + } + } + } // In here, we retrieve triangulated polygons from the mesh MFnMesh mesh(object[ObjectID]); @@ -257,62 +261,62 @@ Mesh MeshClass::GetMeshData(MObjectArray object) thisVertex.Pos[0] = pos.x; thisVertex.Pos[1] = pos.y; thisVertex.Pos[2] = pos.z; + thisVertex.isCollision = collision; - status = faceVert.getNormal(normal, MSpace::kObject); - if (status != MS::kSuccess) { - MGlobal::displayError(MString() + "faceVert.getNormal() ERROR: " + status.errorString() + "for local vertex " + i + " in " + faceID + " in mesh " + thisMeshPath.fullPathName()); - break; - } + if (!collision) { + status = faceVert.getNormal(normal, MSpace::kObject); + if (status != MS::kSuccess) { + MGlobal::displayError(MString() + "faceVert.getNormal() ERROR: " + status.errorString() + "for local vertex " + i + " in " + faceID + " in mesh " + thisMeshPath.fullPathName()); + break; + } - thisVertex.Normal[0] = normal[0]; - thisVertex.Normal[1] = normal[1]; - thisVertex.Normal[2] = normal[2]; + thisVertex.Normal[0] = normal[0]; + thisVertex.Normal[1] = normal[1]; + thisVertex.Normal[2] = normal[2]; - MFloatVector Tangent = Tangents[faceVert.tangentId()]; - //MVector tmp = faceVert.getTangent(MSpace::kObject, NULL); - //tmp.get(biTangent); - thisVertex.Tangent[0] = Tangent[0]; - thisVertex.Tangent[1] = Tangent[1]; - thisVertex.Tangent[2] = Tangent[2]; + MFloatVector Tangent = Tangents[faceVert.tangentId()]; + //MVector tmp = faceVert.getTangent(MSpace::kObject, NULL); + //tmp.get(biTangent); + thisVertex.Tangent[0] = Tangent[0]; + thisVertex.Tangent[1] = Tangent[1]; + thisVertex.Tangent[2] = Tangent[2]; - MFloatVector biNormal = biNormals[faceVert.tangentId()]; - //faceVert.getBinormal().get(biNormal); - thisVertex.BiNormal[0] = biNormal[0]; - thisVertex.BiNormal[1] = biNormal[1]; - thisVertex.BiNormal[2] = biNormal[2]; + MFloatVector biNormal = biNormals[faceVert.tangentId()]; + //faceVert.getBinormal().get(biNormal); + thisVertex.BiNormal[0] = biNormal[0]; + thisVertex.BiNormal[1] = biNormal[1]; + thisVertex.BiNormal[2] = biNormal[2]; - status = faceVert.getUV(UV); - if (status != MS::kSuccess) { - MGlobal::displayError(MString() + " faceVert.getUV() ERROR: " + status.errorString() + "for local vertex " + i + " in " + faceID + " in mesh " + thisMeshPath.fullPathName()); - break; - } - thisVertex.Uv[0] = UV[0]; - thisVertex.Uv[1] = UV[1]; + status = faceVert.getUV(UV); + if (status != MS::kSuccess) { + MGlobal::displayError(MString() + " faceVert.getUV() ERROR: " + status.errorString() + "for local vertex " + i + " in " + faceID + " in mesh " + thisMeshPath.fullPathName()); + break; + } + thisVertex.Uv[0] = UV[0]; + thisVertex.Uv[1] = UV[1]; - if (newMesh.hasSkin) { - thisVertex.useWeights = true; - float totalWeight = 0.0f; - unsigned int totalBones = 0; - MIntArray jointIDs /* ??? */; - weights.selectAncestorLogicalIndex(vertexIndex, weightListObject); - weights.getExistingArrayAttributeIndices(jointIDs); - for (unsigned int i = 0; i < jointIDs.length() && i < 4; i++) { - if (weights[i].asFloat() > 0.001f) { - thisVertex.BoneIndices[totalBones] = jointIDs[i]; - thisVertex.BoneWeights[totalBones] = weights[i].asFloat(); - totalWeight = totalWeight + weights[i].asFloat(); - totalBones++; - } - } + if (newMesh.hasSkin) { + thisVertex.useWeights = true; + float totalWeight = 0.0f; + unsigned int totalBones = 0; + MIntArray jointIDs /* ??? */; + weights.selectAncestorLogicalIndex(vertexIndex, weightListObject); + weights.getExistingArrayAttributeIndices(jointIDs); + for (unsigned int i = 0; i < jointIDs.length() && i < 4; i++) { + if (weights[i].asFloat() > 0.001f) { + thisVertex.BoneIndices[totalBones] = jointIDs[i]; + thisVertex.BoneWeights[totalBones] = weights[i].asFloat(); + totalWeight = totalWeight + weights[i].asFloat(); + totalBones++; + } + } - for (unsigned int i = 0; i < 4; i++) { - //thisVertex.BoneWeights[i] = thisVertex.BoneWeights[i] / totalWeight; - } - } else { - thisVertex.useWeights = false; + for (unsigned int i = 0; i < 4; i++) { + //thisVertex.BoneWeights[i] = thisVertex.BoneWeights[i] / totalWeight; + } + } } - //float totalWeight = thisVertex.BoneWeights[0] + thisVertex.BoneWeights[1] + thisVertex.BoneWeights[2] + thisVertex.BoneWeights[3]; //if (totalWeight > 0.0001f) { // thisVertex.BoneWeights[0] /= totalWeight; diff --git a/tools/MayaExporter/MayaExporter/Mesh.h b/tools/MayaExporter/MayaExporter/Mesh.h index affc4320..f9376a8c 100644 --- a/tools/MayaExporter/MayaExporter/Mesh.h +++ b/tools/MayaExporter/MayaExporter/Mesh.h @@ -11,7 +11,8 @@ class VertexLayout : public OutputData { public: - bool useWeights = true; + bool isCollision = false; + bool useWeights = false; float Pos[3]{ 0 }; float Normal[3]{ 0 }; float Tangent[3]{ 0 }; @@ -23,28 +24,31 @@ public: virtual void WriteBinary(std::ostream& out) { out.write((char*)&Pos, sizeof(float) * 3); - out.write((char*)&Normal, sizeof(float) * 3); - out.write((char*)&Tangent, sizeof(float) * 3); - out.write((char*)&BiNormal, sizeof(float) * 3); - out.write((char*)&Uv, sizeof(float) * 2); - if (useWeights) { - out.write((char*)&BoneIndices, sizeof(float) * 4); - out.write((char*)&BoneWeights, sizeof(float) * 4); + if (!isCollision) { + out.write((char*)&Normal, sizeof(float) * 3); + out.write((char*)&Tangent, sizeof(float) * 3); + out.write((char*)&BiNormal, sizeof(float) * 3); + out.write((char*)&Uv, sizeof(float) * 2); + if (useWeights) { + out.write((char*)&BoneIndices, sizeof(float) * 4); + out.write((char*)&BoneWeights, sizeof(float) * 4); + } } } virtual void WriteASCII(std::ostream& out) const { out << Pos[0] << " " << Pos[1] << " " << Pos[2] << endl; - out << Normal[0] << " " << Normal[1] << " " << Normal[2] << endl; - out << Tangent[0] << " " << Tangent[1] << " " << Tangent[2] << endl; - out << BiNormal[0] << " " << BiNormal[1] << " " << BiNormal[2] << endl; - out << Uv[0] << " " << Uv[1] << endl; - if (useWeights) { - out << BoneIndices[0] << " " << BoneIndices[1] << " " << BoneIndices[2] << " " << BoneIndices[3] << endl; - out << BoneWeights[0] << " " << BoneWeights[1] << " " << BoneWeights[2] << " " << BoneWeights[3] << endl; + if (!isCollision) { + out << Normal[0] << " " << Normal[1] << " " << Normal[2] << endl; + out << Tangent[0] << " " << Tangent[1] << " " << Tangent[2] << endl; + out << BiNormal[0] << " " << BiNormal[1] << " " << BiNormal[2] << endl; + out << Uv[0] << " " << Uv[1] << endl; + if (useWeights) { + out << BoneIndices[0] << " " << BoneIndices[1] << " " << BoneIndices[2] << " " << BoneIndices[3] << endl; + out << BoneWeights[0] << " " << BoneWeights[1] << " " << BoneWeights[2] << " " << BoneWeights[3] << endl; + } } - } bool operator==(const VertexLayout& right) { @@ -62,6 +66,7 @@ public: class Mesh : public OutputData { public: + bool isCollison = false; bool hasSkin = false; unsigned int NumVertices; unsigned int NumIndices; @@ -70,7 +75,9 @@ public: virtual void WriteBinary(std::ostream& out) { - out.write((char*)&hasSkin, sizeof(bool)); + if (!isCollison) { + out.write((char*)&hasSkin, sizeof(bool)); + } out.write((char*)&NumVertices, sizeof(int)); out.write((char*)&NumIndices, sizeof(int)); for (auto aVertex : Vertices) { @@ -86,11 +93,13 @@ public: virtual void WriteASCII(std::ostream& out) const { out << "New Mesh _ not in binary" << endl; - out << "hasSkin: "; - if(hasSkin) - out << "true" << endl; - else - out << "false" << endl; + if (!isCollison) { + out << "hasSkin: "; + if (hasSkin) + out << "true" << endl; + else + out << "false" << endl; + } out << "Number of vertices: " << NumVertices << endl; out << "number of indices: " << NumIndices << endl; int vertexNumber = 0; @@ -115,7 +124,7 @@ class MeshClass { public: MeshClass(); - Mesh GetMeshData(MObjectArray Object); + Mesh GetMeshData(MObjectArray Object, bool collision = false); ~MeshClass(); private: struct WeightInfo {