diff --git a/include/Engine/Core/ECaptured.h b/include/Engine/Core/ECaptured.h index 48771cd7..047c5d7d 100644 --- a/include/Engine/Core/ECaptured.h +++ b/include/Engine/Core/ECaptured.h @@ -13,7 +13,8 @@ struct Captured : Event { int TeamNumberThatCapturedCapturePoint; EntityID CapturePointTakenID; - EntityWrapper NextCapturePoint; + EntityWrapper BlueTeamNextCapturePoint; + EntityWrapper RedTeamNextCapturePoint; }; } 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..305fc21f 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); 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 053e75aa..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/System.h b/include/Engine/Core/System.h index 23d5f9a5..1ca1c824 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& scoreScreen, double dt) = 0; }; class ImpureSystem : public virtual System diff --git a/include/Engine/Core/World.h b/include/Engine/Core/World.h index c9f738ce..9ae38021 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 @@ -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 6cb31d99..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); 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..655ac9b9 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" diff --git a/include/Engine/Input/FirstPersonInputController.h b/include/Engine/Input/FirstPersonInputController.h index d86af088..30d1f945 100644 --- a/include/Engine/Input/FirstPersonInputController.h +++ b/include/Engine/Input/FirstPersonInputController.h @@ -6,12 +6,14 @@ #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; } @@ -27,12 +29,15 @@ public: virtual bool OnCommand(const Events::InputCommand& e) override; virtual void Reset(); - void AssaultDashCheck(double dt, bool isJumping, double assaultDashCoolDownMaxTimer, double& assaultDashCoolDownTimer); + void AssaultDashCheck(double dt, bool isJumping, double assaultDashCoolDownMaxTimer, double& 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; @@ -51,7 +56,7 @@ protected: bool m_ShiftDashing = false; bool m_ValidDoubleTap = false; - //specialabilitys + //specialabilities bool m_MovementKeyDown = false; bool m_SpecialAbilityKeyDown = false; int m_NumberOfMovementKeysDown = 0; @@ -63,9 +68,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); @@ -104,7 +110,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") { @@ -116,16 +121,155 @@ 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.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.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); + } + } + } } } + //Animation + if (glm::length2(m_Movement) < 0.25f) { + //Blend to Idle + if (m_PlayerEntity.Valid()) { + 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 + if (m_PlayerEntity.Valid()) { + 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::length2(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"); @@ -144,10 +288,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; + } } @@ -157,21 +301,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; } @@ -190,7 +355,7 @@ bool FirstPersonInputController::OnLockMouse(const Events::LockMou } template -void FirstPersonInputController::AssaultDashCheck(double dt, bool isJumping, double assaultDashCoolDownMaxTimer, double& assaultDashCoolDownTimer) { +void FirstPersonInputController::AssaultDashCheck(double dt, bool isJumping, double assaultDashCoolDownMaxTimer, double& assaultDashCoolDownTimer, EntityID playerID) { m_AssaultDashDoubleTapDeltaTime += dt; assaultDashCoolDownTimer -= dt; //cooldown = assaultDashCoolDownMaxTimer sec, pretend the dash lasts 0.25 sec (for friction to do its work) @@ -207,6 +372,10 @@ void FirstPersonInputController::AssaultDashCheck(double dt, bool assaultDashCoolDownTimer = assaultDashCoolDownMaxTimer; m_AssaultDashDoubleTapped = true; m_AssaultDashDoubleTapDeltaTime = 0.f; + + Events::DashAbility e; + e.Player = playerID; + m_EventBroker->Publish(e); return; } @@ -237,6 +406,7 @@ void FirstPersonInputController::AssaultDashCheck(double dt, bool 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 c407f7f8..3033542d 100644 --- a/include/Engine/Network/Client.h +++ b/include/Engine/Network/Client.h @@ -17,6 +17,7 @@ #include "Network/TCPClient.h" #include "Network/SnapshotDefinitions.h" #include "Core/World.h" +#include "Core/EntityFile.h" #include "Core/EventBroker.h" #include "Core/ConfigFile.h" #include "Core/EPlayerDeath.h" @@ -28,19 +29,9 @@ #include "Core/EPlayerSpawned.h" #include "Core/EAmmoPickup.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 "../Game/Events/EDashAbility.h" +#include "Network/EDisplayServerlist.h" +#include "Network/EConnectRequest.h" class Client : public Network { public: @@ -51,7 +42,7 @@ public: void Connect(std::string address, int port); void Update() override; private: - UDPClient m_Unreliable; + //UDPClient m_Unreliable; TCPClient m_Reliable; std::vector m_PlayerSpawnEvents; void parseSpawnEvents(); @@ -107,6 +98,7 @@ private: void parsePlayerDamage(Packet& packet); void parseComponentDeletion(Packet& packet); void parseDoubleJump(Packet& packet); + void parseDashEffect(Packet& packet); void parseAmmoPickup(Packet& packet); void InterpolateFields(Packet& packet, const ComponentInfo & componentInfo, const EntityID & entityID, const std::string & componentType); void parseSnapshot(Packet& packet); @@ -117,6 +109,8 @@ private: void sendLocalPlayerTransform(); void becomePlayer(); void displayServerlist(); + void removeWorld(); + void createMainMenu(); // Mapping Logic // Returns if local EntityID exist in map bool clientServerMapsHasEntity(EntityID clientEntityID); @@ -135,6 +129,11 @@ 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; 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..e53f3b8c --- /dev/null +++ b/include/Engine/Network/EKillDeath.h @@ -0,0 +1,19 @@ +#ifndef Events_KillDeath_h__ +#define Events_KillDeath_h__ + +#include "Core/EventBroker.h" + +typedef unsigned int PlayerID; + +namespace Events +{ + +struct KillDeath : public Event +{ + PlayerID Casualty = -1; + PlayerID Killer = -1; +}; + +} + +#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 bf773618..c34f584e 100644 --- a/include/Engine/Network/MessageType.h +++ b/include/Engine/Network/MessageType.h @@ -20,6 +20,7 @@ enum class MessageType ComponentDeleted, PlayerTransform, OnDoubleJump, + OnDashEffect, ServerlistRequest, AmmoPickup, Invalid 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 b688b8c6..e7444d9d 100644 --- a/include/Engine/Network/Packet.h +++ b/include/Engine/Network/Packet.h @@ -24,7 +24,9 @@ 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) { + LOG_WARNING("Package::WritePrimitive(): New size is huge %i bytes\n", m_MaxPacketSize*2); + } resizeData(); } memcpy(m_Data + m_Offset, &val, sizeof(T)); diff --git a/include/Engine/Network/Server.h b/include/Engine/Network/Server.h index 3c956ed9..f96a4a7d 100644 --- a/include/Engine/Network/Server.h +++ b/include/Engine/Network/Server.h @@ -21,6 +21,9 @@ #include "Core/EEntityDeleted.h" #include "Core/EComponentDeleted.h" #include "Core/EAmmoPickup.h" +#include "Core/EPlayerDeath.h" +#include "Network/EPlayerConnected.h" +#include "Network/EKillDeath.h" class Server : public Network { @@ -33,7 +36,7 @@ public: private: // Network channels TCPServer m_Reliable; - UDPServer m_Unreliable; + //UDPServer m_Unreliable; UDPServer m_ServerlistRequest; // dont forget to set these in the childrens receive logic boost::asio::ip::address m_Address; @@ -57,6 +60,7 @@ private: std::vector m_InputCommandsToBroadcast; //Timers std::clock_t m_StartPingTime; + std::string m_ServerName = ""; // Packet loss logic PacketID m_PacketID = 0; @@ -77,12 +81,14 @@ private: void parseOnPlayerDamage(Packet& packet); void identifyPacketLoss(); void kick(PlayerID player); - PlayerID GetPlayerIDFromEndpoint(); + PlayerID getPlayerIDFromEndpoint(); + PlayerID getPlayerIDFromEntityID(EntityID entityID); 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(); @@ -102,6 +108,8 @@ private: bool OnPlayerDamage(const Events::PlayerDamage& e); EventRelay m_EAmmoPickup; bool OnAmmoPickup(const Events::AmmoPickup& e); + EventRelay m_EPlayerDeath; + bool OnPlayerDeath(const Events::PlayerDeath& 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..0550b152 100644 --- a/include/Engine/Network/UDPClient.h +++ b/include/Engine/Network/UDPClient.h @@ -10,7 +10,7 @@ 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); 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..502a1cc9 --- /dev/null +++ b/include/Engine/Rendering/BlendTree.h @@ -0,0 +1,104 @@ +#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 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..02e8e7ba 100644 --- a/include/Engine/Rendering/CubeMapPass.h +++ b/include/Engine/Rendering/CubeMapPass.h @@ -15,7 +15,7 @@ public: void GenerateCubeMapTexture(); //GLuint CubeMapTexture() const { return m_CubeMapTexture; } - GLuint m_CubeMapTexture = -1; + GLuint m_CubeMapTexture = 0; private: IRenderer* m_Renderer; diff --git a/include/Engine/Rendering/DrawBloomPass.h b/include/Engine/Rendering/DrawBloomPass.h index ee3a8489..e6a87c11 100644 --- a/include/Engine/Rendering/DrawBloomPass.h +++ b/include/Engine/Rendering/DrawBloomPass.h @@ -13,7 +13,7 @@ class DrawBloomPass { public: DrawBloomPass(IRenderer* renderer, ConfigFile* config); - ~DrawBloomPass() { } + ~DrawBloomPass(); void InitializeTextures(); void InitializeFrameBuffers(); void InitializeShaderPrograms(); 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 97322603..26712088 100644 --- a/include/Engine/Rendering/DrawFinalPass.h +++ b/include/Engine/Rendering/DrawFinalPass.h @@ -11,35 +11,38 @@ #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, SSAOPass* ssaoPass, GLuint* depthBuffer); - ~DrawFinalPass() { } + DrawFinalPass(IRenderer* renderer, LightCullingPass* lightCullingPass, CubeMapPass* cubeMapPass, SSAOPass* ssaoPass, ShadowPass* shadowPass); + ~DrawFinalPass(); void InitializeTextures(); void InitializeFrameBuffers(); void InitializeShaderPrograms(); - void Draw(RenderScene& scene); + void Draw(RenderScene& scene, BlurHUD* blurHUDPass); void ClearBuffer(); void OnWindowResize(); //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; } //Return the texture with diffuse and lighting of the scene. GLuint SceneTexture() const { return m_SceneTexture; } - GLuint SceneTextureLowRes() const { return m_SceneTextureLowRes; } + //Return the SceneTexture with the blurred HUD bits. + GLuint CombinedSceneTexture() const { return m_CombinedTexture; } + //Return the blurred scene texture. + GLuint FullBlurredTexture() const { return m_FullBlurredTexture; } //Return the framebuffer used in the scene rendering stage. FrameBuffer* FinalPassFrameBuffer() { return &m_FinalPassFrameBuffer; } - FrameBuffer* FinalPassFrameBufferLowRes() { return &m_FinalPassFrameBufferLowRes; } private: void DrawSprites(std::list>&jobs, RenderScene& scene); void DrawModelRenderQueues(std::list>& jobs, RenderScene& scene); - void DrawShieldToStencilBuffer(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); @@ -54,14 +57,14 @@ private: 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_ShieldDepthFrameBuffer; + GLuint m_BloomTexture = 0; + GLuint m_SceneTexture = 0; + GLuint m_DepthBuffer = 0; + GLuint m_ShieldBuffer = 0; + GLuint m_CubeMapTexture = 0; + GLuint m_FullBlurredTexture; + GLuint m_CombinedTexture; //This can be removed for less memory usage, just set m_sceneTexture to the return from m_BlurHUDPass.CombineTextures //maqke this component based i guess? GLuint m_ShieldPixelRate = 16; @@ -70,22 +73,34 @@ private: 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/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..a86b59af 100644 --- a/include/Engine/Rendering/ExplosionEffectJob.h +++ b/include/Engine/Rendering/ExplosionEffectJob.h @@ -15,8 +15,8 @@ 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"]; diff --git a/include/Engine/Rendering/FrameBuffer.h b/include/Engine/Rendering/FrameBuffer.h index cf63b6c6..e9171894 100644 --- a/include/Engine/Rendering/FrameBuffer.h +++ b/include/Engine/Rendering/FrameBuffer.h @@ -43,6 +43,16 @@ public: ~RenderBuffer(); }; +class Texture2DArray : public ResourceType +{ +public: + Texture2DArray(GLuint* resourceHandle, GLenum attachment) + : ResourceType(resourceHandle, attachment) + { }; + + ~Texture2DArray(); +}; + class FrameBuffer { public: diff --git a/include/Engine/Rendering/ModelJob.h b/include/Engine/Rendering/ModelJob.h index c2a469d2..dc4c8cb5 100644 --- a/include/Engine/Rendering/ModelJob.h +++ b/include/Engine/Rendering/ModelJob.h @@ -15,10 +15,11 @@ #include "../Core/Transform.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; @@ -110,45 +111,28 @@ 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 (model->IsSkinned()) { Skeleton = Model->m_RawModel->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 +151,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 +162,14 @@ struct ModelJob : RenderJob glm::vec4 FillColor = glm::vec4(0); float FillPercentage = 0.0; + bool IsShielded; + bool Shadow; 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 df99a615..14ce26ab 100644 --- a/include/Engine/Rendering/PickingPass.h +++ b/include/Engine/Rendering/PickingPass.h @@ -52,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/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/Renderer.h b/include/Engine/Rendering/Renderer.h index a64a4aa3..16bdea9e 100644 --- a/include/Engine/Rendering/Renderer.h +++ b/include/Engine/Rendering/Renderer.h @@ -18,6 +18,7 @@ #include "DrawColorCorrectionPass.h" #include "SSAOPass.h" #include "CubeMapPass.h" +#include "BlurHUD.h" #include "../Core/EventBroker.h" #include "ImGuiRenderPass.h" #include "Camera.h" @@ -26,6 +27,7 @@ #include "TextPass.h" #include "Util/CommonFunctions.h" #include "Core/PerformanceTimer.h" +#include "ShadowPass.h" class Renderer : public IRenderer { @@ -36,6 +38,7 @@ public: : m_EventBroker(eventBroker) , m_Config(config) { } + ~Renderer(); virtual void Initialize() override; virtual void Update(double dt) override; @@ -75,6 +78,8 @@ private: DrawColorCorrectionPass* m_DrawColorCorrectionPass; SSAOPass* m_SSAOPass; CubeMapPass* m_CubeMapPass; + ShadowPass* m_ShadowPass; + BlurHUD* m_BlurHUDPass; //----------------------Functions----------------------// void InitializeWindow(); diff --git a/include/Engine/Rendering/SSAOPass.h b/include/Engine/Rendering/SSAOPass.h index 1cb28009..ba92b6dc 100644 --- a/include/Engine/Rendering/SSAOPass.h +++ b/include/Engine/Rendering/SSAOPass.h @@ -14,7 +14,7 @@ class SSAOPass { public: SSAOPass(IRenderer* renderer, ConfigFile* config); - ~SSAOPass() { }; + ~SSAOPass(); void ChangeQuality(int quality); 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..6db8a624 --- /dev/null +++ b/include/Engine/Rendering/ShadowPass.h @@ -0,0 +1,87 @@ +#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; + + 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..3711c8b2 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 { @@ -68,58 +50,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..c323fa06 100644 --- a/include/Engine/Rendering/SpriteJob.h +++ b/include/Engine/Rendering/SpriteJob.h @@ -7,6 +7,7 @@ #include "../GLM.h" #include "../Core/ComponentWrapper.h" #include "Texture.h" +#include "TextureSprite.h" #include "Model.h" #include "RenderJob.h" #include "../Core/ResourceManager.h" @@ -24,14 +25,16 @@ struct SpriteJob : RenderJob ::RawModel::MaterialProperties matProp = Model->MaterialGroups().front(); TextureID = 0; - DiffuseTexture = CommonFunctions::LoadTexture(cSprite["DiffuseTexture"], true); + DiffuseTexture = CommonFunctions::TryLoadResource(cSprite["DiffuseTexture"]); - IncandescenceTexture = CommonFunctions::LoadTexture(cSprite["GlowMap"], true); + IncandescenceTexture = CommonFunctions::TryLoadResource(cSprite["GlowMap"]); 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); Depth = 0; @@ -65,6 +68,7 @@ struct SpriteJob : RenderJob bool Pickable; bool IsIndicator = false; + bool BlurBackground = false; glm::vec4 FillColor = glm::vec4(0); float FillPercentage = 0.0; diff --git a/include/Engine/Rendering/Texture.h b/include/Engine/Rendering/Texture.h index 95acaf65..5720fe1e 100644 --- a/include/Engine/Rendering/Texture.h +++ b/include/Engine/Rendering/Texture.h @@ -11,7 +11,7 @@ class Texture : public BaseTexture { friend class ResourceManager; -private: +protected: Texture(std::string path); public: diff --git a/include/Engine/Rendering/TextureSprite.h b/include/Engine/Rendering/TextureSprite.h new file mode 100644 index 00000000..f8527664 --- /dev/null +++ b/include/Engine/Rendering/TextureSprite.h @@ -0,0 +1,26 @@ +#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: + ~TextureSprite(); + + void Bind(GLenum textureUnit = GL_TEXTURE0); + + GLuint m_Texture = 0; + unsigned char* Data = nullptr; + +}; + +#endif diff --git a/include/Engine/Rendering/Util/CommonFunctions.h b/include/Engine/Rendering/Util/CommonFunctions.h index 1ed3d82a..94cf8683 100644 --- a/include/Engine/Rendering/Util/CommonFunctions.h +++ b/include/Engine/Rendering/Util/CommonFunctions.h @@ -8,7 +8,23 @@ 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 format, GLenum type, GLint numMipMaps); 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/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 e4a6df59..1e61dd32 100644 --- a/include/Game/Systems/AmmoPickupSystem.h +++ b/include/Game/Systems/AmmoPickupSystem.h @@ -4,7 +4,7 @@ #include "Core/System.h" #include "Core/Transform.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" @@ -20,6 +20,9 @@ public: private: EventRelay m_ETriggerTouch; bool OnTriggerTouch(Events::TriggerTouch& e); + EventRelay m_ETriggerLeave; + bool OnTriggerLeave(Events::TriggerLeave& e); + EventRelay m_EAmmoPickup; bool OnAmmoPickup(Events::AmmoPickup& e); @@ -31,5 +34,23 @@ private: EntityID parentID; }; std::vector m_ETriggerTouchVector; + struct EntityAtMaxValuePickupStruct { + EntityWrapper player; + 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..f02e9472 --- /dev/null +++ b/include/Game/Systems/BoostSystem.h @@ -0,0 +1,21 @@ +#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" + +class BoostSystem : public System +{ +public: + BoostSystem(SystemParams params); + +private: + EventRelay m_EPlayerDamage; + bool OnPlayerDamage(Events::PlayerDamage& e); + + std::string DetermineClass(EntityWrapper player); +}; +#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..26462879 --- /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/Transform.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/DamageIndicatorSystem.h b/include/Game/Systems/DamageIndicatorSystem.h index ae9ba195..f3a95817 100644 --- a/include/Game/Systems/DamageIndicatorSystem.h +++ b/include/Game/Systems/DamageIndicatorSystem.h @@ -4,7 +4,7 @@ #include "Core/System.h" #include "Core/Transform.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/FloatingEffectSystem.h b/include/Game/Systems/FloatingEffectSystem.h new file mode 100644 index 00000000..56931001 --- /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"); + (double&)component["Time"] += dt; + (glm::vec3&)transform["Position"] = (float)(double)component["Amplitude"] * glm::sin((glm::two_pi() / (float)(double)component["Period"]) * (float)(double)component["Time"]) * (glm::vec3)component["Axis"]; + + } +}; \ No newline at end of file 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/Engine/GUI/MainMenuSystem.h b/include/Game/Systems/MainMenuSystem.h similarity index 52% rename from include/Engine/GUI/MainMenuSystem.h rename to include/Game/Systems/MainMenuSystem.h index ba69ff0d..ddefcbf4 100644 --- a/include/Engine/GUI/MainMenuSystem.h +++ b/include/Game/Systems/MainMenuSystem.h @@ -1,15 +1,19 @@ #ifndef MainMenuSystem_h__ #define MainMenuSystem_h__ -#include "../Core/System.h" -#include "../Rendering/IRenderer.h" -#include "../Core/ResourceManager.h" -#include "../Core/Event.h" +#include "Core/System.h" +#include "Rendering/IRenderer.h" +#include "Core/ResourceManager.h" +#include "Core/Event.h" +#include "Systems/SpawnerSystem.h" -#include "EButtonClicked.h" -#include "EButtonPressed.h" -#include "EButtonReleased.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" class MainMenuSystem : public ImpureSystem @@ -27,6 +31,11 @@ private: 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; }; diff --git a/include/Game/Systems/PickupSpawnSystem.h b/include/Game/Systems/PickupSpawnSystem.h index 66c5f630..b72b8b25 100644 --- a/include/Game/Systems/PickupSpawnSystem.h +++ b/include/Game/Systems/PickupSpawnSystem.h @@ -4,12 +4,11 @@ #include "Core/System.h" #include "Core/Transform.h" #include "Core/ResourceManager.h" -#include "Core/EntityFileParser.h" +#include "Core/EntityFile.h" #include "Core/EPickupSpawned.h" #include "Core/EPlayerHealthPickup.h" #include "Engine/Collision/ETrigger.h" #include "Common.h" -#include class PickupSpawnSystem : public ImpureSystem { @@ -21,6 +20,8 @@ public: private: EventRelay m_ETriggerTouch; bool OnTriggerTouch(Events::TriggerTouch& e); + EventRelay m_ETriggerLeave; + bool OnTriggerLeave(Events::TriggerLeave& e); struct NewHealthPickup { glm::vec3 Pos; @@ -30,5 +31,11 @@ private: 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..981fc13a 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,6 +30,8 @@ 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; // The logic for making the sound play when player is moving void playerStep(double dt); // Spawn a hexagon at origin of an Entity @@ -41,6 +41,8 @@ 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); diff --git a/include/Game/Systems/PlayerSpawnSystem.h b/include/Game/Systems/PlayerSpawnSystem.h index 70f94807..f74032f7 100644 --- a/include/Game/Systems/PlayerSpawnSystem.h +++ b/include/Game/Systems/PlayerSpawnSystem.h @@ -15,10 +15,19 @@ public: virtual void Update(double dt) override; private: + // This enum must correspond to the command values for PickTeam buttons. + enum class PlayerClass + { + None = 0, + Assault, + Defender, + Sniper + }; struct SpawnRequest { int PlayerID; ComponentInfo::EnumType Team; + PlayerClass Class; }; bool m_NetworkEnabled = false; diff --git a/include/Game/Systems/ScoreScreenSystem.h b/include/Game/Systems/ScoreScreenSystem.h new file mode 100644 index 00000000..2559bfb3 --- /dev/null +++ b/include/Game/Systems/ScoreScreenSystem.h @@ -0,0 +1,44 @@ +#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 "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); + +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/SpawnerSystem.h b/include/Game/Systems/SpawnerSystem.h index e4a44738..f36f7259 100644 --- a/include/Game/Systems/SpawnerSystem.h +++ b/include/Game/Systems/SpawnerSystem.h @@ -7,8 +7,7 @@ #include "Core/System.h" #include "Events/ESpawnerSpawn.h" #include "Core/Transform.h" -#include "Core/ResourceManager.h" -#include "Core/EntityFileParser.h" +#include "Core/EntityFile.h" class SpawnerSystem : public System { diff --git a/include/Game/Systems/SpectatorCameraSystem.h b/include/Game/Systems/SpectatorCameraSystem.h new file mode 100644 index 00000000..5a00279b --- /dev/null +++ b/include/Game/Systems/SpectatorCameraSystem.h @@ -0,0 +1,22 @@ +#ifndef SpectatorCameraSystem_h__ +#define SpectatorCameraSystem_h__ + +#include "Core/System.h" +#include "Input/EInputCommand.h" + +class SpectatorCameraSystem : public ImpureSystem +{ +public: + SpectatorCameraSystem(SystemParams params); + + virtual void Update(double dt) override; + +private: + int m_PickedTeam; + bool m_CamSetToTeamPick; + + EventRelay m_EInputCommand; + bool OnInputCommand(const Events::InputCommand& 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..d577e22f 100644 --- a/include/Game/Systems/Weapon/AssaultWeaponBehaviour.h +++ b/include/Game/Systems/Weapon/AssaultWeaponBehaviour.h @@ -1,47 +1,42 @@ #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; - 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(); + // Weapon functions + void fireBullet(ComponentWrapper cWeapon, WeaponInfo& wi); + //void dealDamage(ComponentWrapper cWeapon, WeaponInfo& wi, glm::vec3 direction, double damage); + bool canFire(ComponentWrapper cWeapon, WeaponInfo& wi); + bool dealDamage(ComponentWrapper cWeapon, WeaponInfo& wi); + + // Utility + //Camera cameraFromEntity(EntityWrapper camera); }; #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..9e7d4991 100644 --- a/include/Game/Systems/Weapon/DefenderWeaponBehaviour.h +++ b/include/Game/Systems/Weapon/DefenderWeaponBehaviour.h @@ -1,7 +1,10 @@ +#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" class DefenderWeaponBehaviour : public WeaponBehaviour { @@ -10,29 +13,27 @@ 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; 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, glm::vec3 direction, double damage); + 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 +}; + +#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..10e6105a --- /dev/null +++ b/include/Game/Systems/Weapon/SidearmWeaponBehaviour.h @@ -0,0 +1,38 @@ +#ifndef SidearmWeaponBehaviour_h__ +#define SidearmWeaponBehaviour_h__ + +#include "WeaponBehaviour.h" +#include "Collision/Collision.h" +#include "Core/EPlayerDamage.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 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); + //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..cd067f36 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,8 +253,17 @@ 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; @@ -152,29 +285,50 @@ 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"); + + 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/DefaultConfig.ini b/resources/DefaultConfig.ini index d4696bba..92e7bad3 100644 --- a/resources/DefaultConfig.ini +++ b/resources/DefaultConfig.ini @@ -1,10 +1,13 @@ +[Gameplay] +AutoReload=true + [Debug] LogLevel=1 LoadMap= ; 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 @@ -68,5 +71,17 @@ Contrast=1.5 Intensity=1.0 NumSamples=24 NumTurns=17 -NumIterations=13 -TextureQuality=0 \ No newline at end of file +NumIterations=9 +TextureQuality=0 + +[GLOW] +Quality=3 + +[GLOW1] +NumIterations=5 + +[GLOW2] +NumIterations=9 + +[GLOW3] +NumIterations=13 \ No newline at end of file diff --git a/resources/DefaultInput.ini b/resources/DefaultInput.ini index 776cbecd..18fb943f 100644 --- a/resources/DefaultInput.ini +++ b/resources/DefaultInput.ini @@ -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/Schema/Components.xsd b/resources/Schema/Components.xsd index eb41ed6a..bc6da932 100644 --- a/resources/Schema/Components.xsd +++ b/resources/Schema/Components.xsd @@ -33,21 +33,39 @@ - + + + + + - + + + + + + + + + + + + + + + \ 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..c76fe21e --- /dev/null +++ b/resources/Schema/Components/BoostAssault.xml @@ -0,0 +1,4 @@ + + + 2 + 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/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/DefenderWeapon.xml b/resources/Schema/Components/DefenderWeapon.xml index 998f3bde..b01955bc 100755 --- a/resources/Schema/Components/DefenderWeapon.xml +++ b/resources/Schema/Components/DefenderWeapon.xml @@ -1,16 +1,21 @@ + 8 8 64 64 90 0.174533 + 0.174533 10 120 - 0.01 + 0.03 + 0.2 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..53200952 100755 --- a/resources/Schema/Components/DefenderWeapon.xsd +++ b/resources/Schema/Components/DefenderWeapon.xsd @@ -4,9 +4,22 @@ + + + + + + + + + + + + + Ammo currently loaded into the magazine @@ -25,6 +38,9 @@ Spread angle in radians + + Maximum vertical aim travel angle in radians + Rate of fire in rounds per minute @@ -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/ExplosionEffect.xml b/resources/Schema/Components/ExplosionEffect.xml index 22692729..0b4a44c4 100644 --- a/resources/Schema/Components/ExplosionEffect.xml +++ b/resources/Schema/Components/ExplosionEffect.xml @@ -3,6 +3,8 @@ 0 2 + 1 + 0 diff --git a/resources/Schema/Components/ExplosionEffect.xsd b/resources/Schema/Components/ExplosionEffect.xsd index cdde5e52..bd29b2ed 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 + + 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..35b05b69 100644 --- a/resources/Schema/Components/Model.xml +++ b/resources/Schema/Components/Model.xml @@ -8,5 +8,6 @@ true true true + true 3.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/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..bc90c067 --- /dev/null +++ b/resources/Schema/Components/SidearmWeapon.xml @@ -0,0 +1,16 @@ + + + + 16 + 16 + 20 + 500 + false + 0.01 + 0.5 + 0.5 + false + 0 + false + 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..514bf354 --- /dev/null +++ b/resources/Schema/Components/SidearmWeapon.xsd @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + 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/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..e577ac96 100644 --- a/resources/Schema/Components/Sprite.xml +++ b/resources/Schema/Components/Sprite.xml @@ -5,4 +5,5 @@ true true + false diff --git a/resources/Schema/Components/Sprite.xsd b/resources/Schema/Components/Sprite.xsd index 3c3d124a..e26d71c9 100644 --- a/resources/Schema/Components/Sprite.xsd +++ b/resources/Schema/Components/Sprite.xsd @@ -24,6 +24,9 @@ Whether the sprite should be sorted with depth or not. Only use false for textures that are on HUD + + 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/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..ee3704f1 100644 --- a/resources/Schema/Entities/AmmoPickup.xml +++ b/resources/Schema/Entities/AmmoPickup.xml @@ -2,6 +2,7 @@ + Models/Props/PickUps/AmmoPickUp.mesh 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/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/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_RockHard.xml b/resources/Schema/Entities/CP_RockHard.xml new file mode 100644 index 00000000..9f11d052 --- /dev/null +++ b/resources/Schema/Entities/CP_RockHard.xml @@ -0,0 +1,9114 @@ + + + + + + 0.58443805362486501 + 3 + + + + + + + + + + + + + + + 2 + Models/Props/GroundTest.mesh + + + + + + + + + Models/Props/Walls/SciFiWallTop.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/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/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 + + + + + + + + + + + + + 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/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/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 + + + + + + + + + + + + + + + + + + + + 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/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/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + + Models/Props/Stones/mediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/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/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/mediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/mediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/mediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/mediumStone2.mesh + + + + + + + + + + + + + + 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/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/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/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/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/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/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.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/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/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + + + + + + + + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar1Red.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.mesh + + + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.mesh + + + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.mesh + + + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.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/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + + + Models/Props/Bridges/SciFiBridge1Red.mesh + + + + + + + + + + + + Models/Props/Pillars/SciFiBridgePillar1.mesh + + + + + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + + + Models/Props/Pillars/SciFiBridgePillar1.mesh + + + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + + + + + Models/Props/Pillars/SciFiBridgePillar1.mesh + + + + + + + + + + + + + + Models/Props/Bridges/SciFiBridge1Red.mesh + + + + + + + + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/MediumWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + + 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/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/MediumWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/MediumWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/MediumWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/MediumWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + Models/Core/UnitPlane.mesh + + true + + + + + + + + + + + + + + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 6 + 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/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/MediumWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + Models/Props/Walls/smallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/mediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + + + + + + + + + + + + + + + + + + + + + + + 4 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + 2 + + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 4 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 2 + 1 + + + + + + + + + + + + 2 + + + + + + + + + + + + 3 + + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 5 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + + + + + + + + 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/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/mediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + 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/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/SmallStone2.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/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + + + + + + + + + + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.mesh + + + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.mesh + + + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.mesh + + + + + + + + + + + + + + Models/Props/Walls/SpecialWall1.mesh + + + + + + + + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar1Blue.mesh + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Blue.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/Bridges/SciFiBridge1Blue.mesh + + + + + + + + + + + + + + Models/Props/Bridges/SciFiBridge1Blue.mesh + + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + + + + + + + + + + + + + + + + + Models/Props/SciFiHolder1.mesh + + + + + + + + + + + + + Models/Props/SciFiHolder1.mesh + + + + + + + + + + + + + Models/Props/SciFiHolder1.mesh + + + + + + + + + + + + + Models/Props/SciFiHolder1.mesh + + + + + + + + + + + + + + + + + + + + Models/Props/Flora/SpecialRoot.mesh + + + + + + + + + + + + + Models/Props/Flora/SpecialRoot.mesh + + + + + + + + + + + + + + Models/Props/Flora/SpecialRoot.mesh + + + + + + + + + + + + + + Models/Props/Flora/SpecialRoot.mesh + + + + + + + + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + Models/Props/Walls/MediumWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/MediumWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + Models/Props/Walls/MediumWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/MediumWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/MediumWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/MediumWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/MediumWall3.mesh + + + + + + + + + + + + + + Models/Core/UnitPlane.mesh + + true + + + + + + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar1Blue.mesh + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + 4 + Models/Props/Pillars/SciFiPillar3Blue.mesh + + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + 4 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + 4 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + 4 + Models/Props/Pillars/SciFiPillar3Blue.mesh + + + + + + + + + + + + + + + + + + + + + + + + + + + + Schema/Entities/PlayerAssaultFallbackBlue.xml + + + + + + + + + + + Models/Characters/Assault/Test/AssaultTPose.mesh + + + + + + + + + + Models/Characters/Assault/Test/AssaultTPose.mesh + + + + + + + + + + + + Models/Characters/Assault/Test/AssaultTPose.mesh + + + + + + + + + + + + Models/Characters/Assault/Test/AssaultTPose.mesh + + + + + + + + + + + + Models/Characters/Assault/Test/AssaultTPose.mesh + + + + + + + + + + + + Models/Characters/Assault/Test/AssaultTPose.mesh + + + + + + + + + + + + + + + + + + + Schema/Entities/PlayerAssaultFallbackRed.xml + + + + + + + + + + + Models/Characters/Assault/Test/AssaultTPose.mesh + + + + + + + + + + + + Models/Characters/Assault/Test/AssaultTPose.mesh + + + + + + + + + + + + Models/Characters/Assault/Test/AssaultTPose.mesh + + + + + + + + + + + + Models/Characters/Assault/Test/AssaultTPose.mesh + + + + + + + + + + + + Models/Characters/Assault/Test/AssaultTPose.mesh + + + + + + + + + + + + Models/Characters/Assault/Test/AssaultTPose.mesh + + + + + + + + + + + + + + + + + + + 10 + + + + + + + + + + + 10 + + + + + + + + + + + + 10 + + + + + + + + + + + 0.40000000596046448 + + + + + + + + + + + 10 + + + + + + + + + + + 0.69999998807907104 + 1.6000000238418579 + + + + + + + + + 10 + + + + + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointNeutral.mesh + + + + + + + + + + 3 + + + + + Models/Core/UnitCylinder.mesh + + true + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointNeutral.mesh + + + + + + + + + + 1 + + + + + Models/Core/UnitCylinder.mesh + + true + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointBlue.mesh + + + + + + + + + + -15 + + + + 4 + + + + + + + + + Models/Core/UnitCylinder.mesh + + true + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointNeutral.mesh + + + + + + + + + + 2 + + + + + Models/Core/UnitCylinder.mesh + + true + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointRed.mesh + + + + + + + + + + 15 + + + + + + + + + + + + Models/Core/UnitCylinder.mesh + + true + + + + + + + + + + + + + + + + 0.049999997019767761 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + + + + 2 + + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + + + + 1 + + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + + + + 3 + + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + 1 + + + + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + 1 + + + + 4 + + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + + + + 3 + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + + + PickClass + 2 + + + + + + + + + + + + + Textures/Core/UnitRaptor.png + + + + PickClass + 1 + + + + + + + + + + + + + Textures/Test/aM4ME4GR.png + + + + PickClass + 3 + + + + + + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/CP_Rocky.xml b/resources/Schema/Entities/CP_Rocky.xml new file mode 100644 index 00000000..d034be78 --- /dev/null +++ b/resources/Schema/Entities/CP_Rocky.xml @@ -0,0 +1,5317 @@ + + + + + + + + + + + + + + + + + + Models/Props/GroundTest.mesh + + + + + + + + + + Models/Props/Highground5.mesh + + + + + + + + + + Models/Props/Highground6.mesh + + + + + + + + + + + Models/Props/Highground7.mesh + + + + + + + + + + + + Models/Props/Walls/SciFiWallTop.mesh + + + + + + + + + Models/Props/Walls/SciFiWallSmall1.mesh + + + + + + + + + + Models/Props/Walls/SciFiWallBig.mesh + true + + + + + + + + + + Models/Props/Walls/SciFiWallBig.mesh + + + + + + + + + + + + Models/Props/Walls/SciFiWallMedium.mesh + + + + + + + + + + Models/Props/Walls/SciFiWallSmall2.mesh + + + + + + + + + + Models/Props/Walls/SciFiWallMedium.mesh + + + + + + + + + + + + Models/Props/Walls/SciFiWallSmall3.mesh + + + + + + + + + + Models/Props/Walls/SciFiWallSmall4.mesh + + + + + + + + + Schema/Entities/ScoreBoard_Main.xml + + + + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + Schema/Entities/ScoreBoard_Blue.xml + + + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + + + + + + + + + + + + + + + ID + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Name + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + KD + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Kills + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Deaths + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + + + Schema/Entities/ScoreBoard_Red.xml + + + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + + + + + + + + + + + + + + + ID + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Name + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + KD + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Kills + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Deaths + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + + + + + + + Schema/Entities/ScoreBoard_Main.xml + + + + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + Schema/Entities/ScoreBoard_Red.xml + + + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + + + + + + + + + + + + + + + ID + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Name + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + KD + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Kills + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Deaths + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + + + Schema/Entities/ScoreBoard_Blue.xml + + + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + + + + + + + + + + + + + + + ID + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Name + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + KD + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Kills + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Deaths + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + Models/Props/Highground1.mesh + + + + + + + + + + Models/Props/Highground2.mesh + + + + + + + + + + + Models/Props/Highground3.mesh + + + + + + + + + + + Models/Props/Highground4.mesh + + + + + + + + + + + Models/Props/Highground8.mesh + + + + + + + + + + + + + Models/Props/Highground9.mesh + + + + + + + + + + + + + Models/Props/Highground10.mesh + + + + + + + + + + + + + Models/Props/Highground6.mesh + + + + + + + + + + + + + Models/Props/Highground1.mesh + + + + + + + + + + + + Models/Props/Highground2.mesh + + + + + + + + + + + + + Models/Props/Highground3.mesh + + + + + + + + + + + + + Models/Props/Highground4.mesh + + + + + + + + + + + + + Models/Props/Highground5.mesh + + + + + + + + + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar1Blue.mesh + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar1Red.mesh + + + + + + + + + + + + + 4 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar3Blue.mesh + + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar1Blue.mesh + + + + + + + + + + + + + + 4 + Models/Props/Pillars/SciFiPillar1Red.mesh + + + + + + + + + + + + + + 4 + Models/Props/Pillars/SciFiPillar3Red.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + 4 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + + + + + + + + + + + + 5 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + 2 + + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + 4 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 2 + 1 + + + + + + + + + + + + 2 + + + + + + + + + + + + 3 + + + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + 2 + + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + 2 + + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + 2 + + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + 2 + + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + 2 + + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + 2 + + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + 2 + + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + + + + + + + + + + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + + Models/Props/Stones/MediumStone1.mesh + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/MediumStone1.mesh + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + + + + + + + + + + Models/Props/Bridges/SciFiBridge1Red.mesh + + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + + + + + + + + + + Models/Props/Bridges/SciFiBridge1Red.mesh + + + + + + + + + + + + Models/Props/Pillars/SciFiBridgePillar1.mesh + + + + + + + + + + + + + + + Models/Props/Pillars/SciFiBridgePillar1.mesh + + + + + + + + + + + + + + Models/Props/Bridges/SciFiBridge1Red.mesh + + + + + + + + + + + + + + + + + + + + + Models/Props/SciFiHolder1.mesh + + + + + + + + + + + + + Models/Props/SciFiHolder1.mesh + + + + + + + + + + + + + + + + + + + + Models/Props/Flora/SpecialRoot.mesh + + + + + + + + + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/MediumWall2.mesh + + + + + + + + + + + + + Models/Props/Walls/MediumWall2.mesh + + + + + + + + + + + + + Models/Props/Walls/MediumWall2.mesh + + + + + + + + + + + + + Models/Props/Walls/MediumWall2.mesh + + + + + + + + + + + + + Models/Props/Walls/MediumWall1.mesh + + + + + + + + + + + + Models/Props/Walls/MediumWall1.mesh + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Core/UnitPlane.mesh + + true + + + + + + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar1Red.mesh + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + 2 + + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + 2 + + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + + + + + + + + + + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + + + + + + + + Models/Props/Walls/SmallWall2.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall2.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/MediumWall1.mesh + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + + + + + + + Models/Props/Bridges/SciFiBridge1Blue.mesh + + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + + + + + + + + + + Models/Props/Pillars/SciFiBridgePillar1.mesh + + + + + + + + + + + + + + Models/Props/Bridges/SciFiBridge1Blue.mesh + + + + + + + + + + + + Models/Props/Pillars/SciFiBridgePillar1.mesh + + + + + + + + + + + + + + + Models/Props/Bridges/SciFiBridge1Blue.mesh + + + + + + + + + + + + + + + + + + + + + Models/Props/SciFiHolder1.mesh + + + + + + + + + + + + + Models/Props/SciFiHolder1.mesh + + + + + + + + + + + + + + Models/Core/UnitPlane.mesh + + true + + + + + + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/MediumWall1.mesh + + + + + + + + + + + + Models/Props/Walls/MediumWall2.mesh + + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/MediumWall1.mesh + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + + Models/Props/Walls/MediumWall2.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/MediumWall2.mesh + + + + + + + + + + + + + Models/Props/Walls/MediumWall2.mesh + + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + + + + + + + + Models/Props/Flora/SpecialRoot.mesh + + + + + + + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone1.mesh + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + Models/Props/Stones/MediumStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + + Models/Props/Stones/MediumStone1.mesh + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + 2 + + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + 4 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 3 + + + + + + + + + + + + 2 + 1 + + + + + + + + + + + + 2 + + + + + + + + + + + + + + 5 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + 2 + + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + 2 + + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + 2 + + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + 2 + + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + 2 + + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + 2 + + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + 2 + + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + + + + + + + + + + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar1Blue.mesh + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + + + + + + Schema/Entities/Player.xml + + + + + + + + + + + + + + + + Models/Characters/Assault/AssaultTPose.mesh + false + + + + + + + + + + + + Models/Characters/Assault/AssaultTPose.mesh + false + + + + + + + + + + + + Models/Characters/Assault/AssaultTPose.mesh + false + + + + + + + + + + + + Models/Characters/Assault/AssaultTPose.mesh + false + + + + + + + + + + + + + + Schema/Entities/PlayerRed.xml + + + + + + + + + + + + + + + + Models/Characters/Assault/AssaultTPose.mesh + false + + + + + + + + + + + + Models/Characters/Assault/AssaultTPose.mesh + false + + + + + + + + + + + + Models/Characters/Assault/AssaultTPose.mesh + false + + + + + + + + + + + + Models/Characters/Assault/AssaultTPose.mesh + false + + + + + + + + + + + + + + + + + + + 10 + + + + + + + + + + + 0.40000000596046448 + + + + + + + + + + + 10 + + + + + + + + + + + 10 + + + + + + + + + + + + 10 + + + + + + + + + + + 1 + + + + + + + + + 10 + + + + + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointNeutral.mesh + + + + + + + + + + 1 + + + + Models/Core/UnitCylinder.mesh + + true + + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointBlue.mesh + + + + + + + + + + -15 + + + + 4 + + + + Models/Core/UnitCylinder.mesh + + true + + + + + + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointNeutral.mesh + + + + + + + + + + 2 + + + + Models/Core/UnitCylinder.mesh + + true + + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointRed.mesh + + + + + + + + + + 15 + + + + + + + Models/Core/UnitCylinder.mesh + + true + + + + + + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointNeutral.mesh + + + + + + + + + + 3 + + + + Models/Core/UnitCylinder.mesh + + true + + + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/CP_Rocky2.xml b/resources/Schema/Entities/CP_Rocky2.xml new file mode 100644 index 00000000..93b7fd77 --- /dev/null +++ b/resources/Schema/Entities/CP_Rocky2.xml @@ -0,0 +1,11874 @@ + + + + + + + + + + + + + + + + + + 2 + Models/Props/GroundTest.mesh + + + + + + + + 2 + Models/Props/Walls/SciFiWallTop.mesh + + + + + + + + + 2 + Models/Props/Walls/SciFiWallSmall1.mesh + + + + + + + + + + 2 + Models/Props/Walls/SciFiWallSmall2.mesh + + + + + + + + + + 2 + Models/Props/Walls/SciFiWallBig.mesh + + + + + + + + + + + + 2 + Models/Props/Walls/SciFiWallBig.mesh + + + + + + + + + + 2 + Models/Props/Walls/SciFiWallMedium.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/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/Hg20.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/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/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/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/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/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/mediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/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/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/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.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/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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + 4 + Models/Props/Pillars/SciFiPillar3Red.mesh + + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar1Red.mesh + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + 4 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + 4 + Models/Props/Pillars/SciFiPillar3Red.mesh + + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + 4 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + 4 + Models/Props/Pillars/SciFiPillar1Red.mesh + + + + + + + + + + + + + + + + + + + + + 15 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 10 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 15 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + + + 15 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + 15 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar1Blue.mesh + + + + + + + + + + + + + + 15 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + + + 15 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + true + + + + + + + + + + + + Models/Props/Flora/HangingBush2.mesh + true + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + true + false + + + + + + + + + + + + + Models/Props/Flora/HangingBush4.mesh + true + + + + + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + 15 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + + + Models/Props/SciFiHolder1.mesh + + + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + + + + + + + + + Models/Core/UnitPlane.mesh + + true + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + 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/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/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/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 + + + + + + + + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.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 + + + + + + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.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/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/BigWallRed.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/MediumWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/MediumWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/MediumWall3.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/BigWallRed.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.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/MediumWall3.mesh + + + + + + + + + + + + + + + + + + + + Models/Props/SciFiHolder1.mesh + + + + + + + + + + + + + Models/Props/SciFiHolder1.mesh + + + + + + + + + + + + + Models/Props/SciFiHolder1.mesh + + + + + + + + + + + + + Models/Props/SciFiHolder1.mesh + + + + + + + + + + + + + Models/Props/SciFiHolder1.mesh + + + + + + + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + + + + + + + Models/Props/Stones/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/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/MediumStone2.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/BigStone.mesh + + + + + + + + + + + + Models/Props/Stones/SmallStone1.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/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/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/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/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/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/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/mediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/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/SmallStone2.mesh + + + + + + + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.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 + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar1Red.mesh + + + + + + + + + + + + + + + + + + + + + + + + + + + + 4 + Models/Props/Pillars/SciFiPillar3Blue.mesh + + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar1Blue.mesh + + + + + + + + + + + + + 4 + Models/Props/Pillars/SciFiPillar3Blue.mesh + + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + 4 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + 4 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + 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 + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + + + + + + + + Models/Props/Walls/MediumWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + Models/Props/Walls/BigWallRed.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/PickUps/PickUpHolder.mesh + + + + + + + + + + + + 2 + + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + 2 + + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + + + + + + + + + + + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.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/BigStone.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/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/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 15 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + + + + + + 0.049999997019767761 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Pick Class + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + Textures/Icons/Classes/Defender-01.png + + false + + + PickClass + 2 + + + + + + + + + + + Defender + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + 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/Core/UnitHexagon.png + + false + + + + PickTeam + 1 + + + + + + + + + + + Spectator + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + Pick Team + 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 7 + 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 + + + + SwapToTeamPick + 1 + + + + + + + + + + + Team + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + Change + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + false + + + + SwapToClassPick + 1 + + + + + + + + + + + Class + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + Change + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + Schema/Entities/ScoreBoard_Red.xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Kills + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + KD + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Deaths + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Name + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + ID + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + Schema/Entities/ScoreBoard_Blue.xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Schema/Entities/ScoreBoard_Blue.xml + + + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + + + + + + + + + + + + + + + ID + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Deaths + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Name + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Kills + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + KD + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + Schema/Entities/ScoreBoard_Red.xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Kills + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Name + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + KD + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + ID + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Deaths + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointNeutral.mesh + + + + + + + + + + 3 + + + + + Models/Core/UnitCylinder.mesh + + true + + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointRed.mesh + + + + + + + + + + 15 + + + + + + + + + + + + Models/Core/UnitCylinder.mesh + + true + + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointNeutral.mesh + + + + + + + + + + 2 + + + + + Models/Core/UnitCylinder.mesh + + true + + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointNeutral.mesh + + + + + + + + + + 1 + + + + + Models/Core/UnitCylinder.mesh + + true + + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointBlue.mesh + + + + + + + + + + -15 + + + + 4 + + + + + + + + + Models/Core/UnitCylinder.mesh + + true + + + + + + + + + + + + + + + + + + + + + + + 10 + + + + + + + + + + + + + + + + 4 + + + + + + + + + + + 4 + + + + + + + + + + + 4 + + + + + + + + + + + 4 + + + + + + + + + + + 4 + + + + + + + + + + + 4 + + + + + + + + + + + 4 + + + + + + + + + + + 4 + 2 + + + + + + + + + + + 4 + + + + + + + + + + + 4 + + + + + + + + + + + 5 + + + + + + + + + + + 4 + + + + + + + + + + + 4 + 1 + + + + + + + + + + + 4 + + + + + + + + + + + 4 + + + + + + + + + + + 4 + + + + + + + + + + + + + + 0.80000001192092896 + 1.2000000476837158 + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + 0.60000002384185791 + false + + + + + + + + + + + + 10 + + + + + + + + + + + 10 + + + + + + + + + + + 10 + + + + + + + + + + + + + + + + + 15 + 1 + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + 3 + 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 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + + + + + + + + + + 5 + 2 + 0.5 + + + + + + + + + + + + 5 + 2 + 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 + + + + + + + + + + + + + + + + + + + + + 10 + 1 + + + + + + + + + + + + 10 + 1 + + + + + + + + + + + + 10 + 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/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/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/DashEffect.xml b/resources/Schema/Entities/DashEffect.xml new file mode 100644 index 00000000..6f28784d --- /dev/null +++ b/resources/Schema/Entities/DashEffect.xml @@ -0,0 +1,13 @@ + + + + + + 0.5 + + + + + + + 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..5cb72116 100755 --- a/resources/Schema/Entities/DefenderShield.xml +++ b/resources/Schema/Entities/DefenderShield.xml @@ -2,36 +2,36 @@ + + Deploy + Idle + 0 + + + Models/Characters/Defender/DefenderShield.mesh + - + - - Models/Core/UnitPlane.mesh - - - - - - + + ActivateDeactiveShieldF + + 1 + + - + - - - Models/Core/UnitHexagon.mesh - - true - - - - - - + + ShieldFrontF + 1 + + 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/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/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/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..6474426f 100644 --- a/resources/Schema/Entities/HealthPickup.xml +++ b/resources/Schema/Entities/HealthPickup.xml @@ -2,6 +2,7 @@ + Models/Props/PickUps/HealthPickUp.mesh 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/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 d7bf28a6..53113810 100644 --- a/resources/Schema/Entities/MovementTest.xml +++ b/resources/Schema/Entities/MovementTest.xml @@ -2,21 +2,23 @@ - + + + - - - Schema/Entities/PlayerRed.xml - + + + Schema/Entities/PlayerDefenderBlue.xml + @@ -26,7 +28,7 @@ - Models/Characters/Assault/AssaultTPose.mesh + Models/Characters/Assault/AssaultRed.mesh @@ -39,7 +41,7 @@ - Models/Characters/Assault/AssaultTPose.mesh + Models/Characters/Assault/AssaultRed.mesh @@ -52,7 +54,10 @@ - + + 0.49999982118606567 + 2.5599997043609619 + sModels/Widgets/Lights/DirectionalLightWidget.mesh @@ -76,15 +81,15 @@ - - - Schema/Entities/Player.xml - + + + Schema/Entities/PlayerAssaultBlue.xml + @@ -94,11 +99,11 @@ - Models/Characters/Assault/AssaultTPose.mesh + Models/Characters/Assault/AssaultBlue.mesh - + @@ -107,11 +112,53 @@ - 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 + + + + 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 new file mode 100644 index 00000000..8089073f --- /dev/null +++ b/resources/Schema/Entities/NewMap2version2.xml @@ -0,0 +1,4690 @@ + + + + + + + + + + + + + + + + + + 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/Props/Highground4.mesh + + + + + + + + + + + Models/Props/Highground5.mesh + + + + + + + + + + Models/Props/Highground6.mesh + + + + + + + + + + + Models/Props/Highground7.mesh + + + + + + + + + + + + + Models/Props/Highground8.mesh + + + + + + + + + + + + + Models/Props/Highground9.mesh + + + + + + + + + + + + + Models/Props/Highground10.mesh + + + + + + + + + + + + + Models/Props/Highground6.mesh + + + + + + + + + + + + + Models/Props/Highground1.mesh + + + + + + + + + + + + Models/Props/Highground2.mesh + + + + + + + + + + + + + Models/Props/Highground3.mesh + + + + + + + + + + + + + Models/Props/Highground4.mesh + + + + + + + + + + + + + Models/Props/Highground5.mesh + + + + + + + + + + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar1Blue.mesh + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar1Red.mesh + + + + + + + + + + + + + 4 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar3Blue.mesh + + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar1Blue.mesh + + + + + + + + + + + + + + 4 + Models/Props/Pillars/SciFiPillar1Red.mesh + + + + + + + + + + + + + + 4 + Models/Props/Pillars/SciFiPillar3Red.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + 4 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar2Red.mesh + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + 2 + + + + + + + + + + + Models/Props/PickUps/HealthPickUp.mesh + + + 8 + + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + + 2 + + + + + + + + + + + Models/Props/PickUps/HealthPickUp.mesh + + + 8 + + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + + 2 + + + + + + + + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + 8 + + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + + 2 + + + + + + + + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + 8 + + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + + 2 + + + + + + + + + + + Models/Props/PickUps/HealthPickUp.mesh + + + 8 + + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + + 2 + + + + + + + + + + + Models/Props/PickUps/HealthPickUp.mesh + + + 8 + + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + + 2 + + + + + + + + + + + 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/Bridges/SciFiBridge1Red.mesh + + + + + + + + + + + + + + + + + + + + + Models/Props/SciFiHolder1.mesh + + + + + + + + + + + + + Models/Props/SciFiHolder1.mesh + + + + + + + + + + + + + + + + + + + + Models/Props/Flora/SpecialRoot.mesh + + + + + + + + + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/MediumWall2.mesh + + + + + + + + + + + + + Models/Props/Walls/MediumWall2.mesh + + + + + + + + + + + + + Models/Props/Walls/MediumWall2.mesh + + + + + + + + + + + + + Models/Props/Walls/MediumWall2.mesh + + + + + + + + + + + + + Models/Props/Walls/MediumWall1.mesh + + + + + + + + + + + + Models/Props/Walls/MediumWall1.mesh + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Core/UnitPlane.mesh + + true + + + + + + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar1Red.mesh + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + + 2 + + + + + + + + + + + Models/Props/PickUps/HealthPickUp.mesh + + + 8 + + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + + 2 + + + + + + + + + + + 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/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/MediumWall1.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 + + + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + + 2 + + + + + + + + + + + Models/Props/PickUps/HealthPickUp.mesh + + + 8 + + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + + 2 + + + + + + + + + + + Models/Props/PickUps/HealthPickUp.mesh + + + 8 + + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + + 2 + + + + + + + + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + 8 + + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + + 2 + + + + + + + + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + 8 + + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + + 2 + + + + + + + + + + + Models/Props/PickUps/HealthPickUp.mesh + + + 8 + + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + + 2 + + + + + + + + + + + Models/Props/PickUps/HealthPickUp.mesh + + + 8 + + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + + 2 + + + + + + + + + + + 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/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/Pillars/SciFiBridgePillar1.mesh + + + + + + + + + + + + + + Models/Props/Bridges/SciFiBridge1Blue.mesh + + + + + + + + + + + + + + + + + + + + + Models/Props/SciFiHolder1.mesh + + + + + + + + + + + + + Models/Props/SciFiHolder1.mesh + + + + + + + + + + + + + + + + + + + + Models/Props/Flora/SpecialRoot.mesh + + + + + + + + + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/MediumWall2.mesh + + + + + + + + + + + + + Models/Props/Walls/MediumWall2.mesh + + + + + + + + + + + + + Models/Props/Walls/MediumWall2.mesh + + + + + + + + + + + + + Models/Props/Walls/MediumWall2.mesh + + + + + + + + + + + + + Models/Props/Walls/MediumWall1.mesh + + + + + + + + + + + + Models/Props/Walls/MediumWall1.mesh + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + + Models/Props/Walls/BigWallRed.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Core/UnitPlane.mesh + + true + + + + + + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar1Blue.mesh + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.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 + + + Models/Core/UnitCylinder.mesh + + true + + + + + + + + + + + + + + + + + Models/Props/CapturePoint/CapturePointRed.mesh + + + + + + + + + + + + + + + Models/Core/UnitCylinder.mesh + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + + + + + + + + 10 + + + + + + + + + + + 10 + + + + + + + + + + + 10 + + + + + + + + + + + + 10 + + + + + + + + + + + 1 + false + + + + + + + + + + + + 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/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/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/OverwatchCamera.xml b/resources/Schema/Entities/OverwatchCamera.xml new file mode 100644 index 00000000..6c93f033 --- /dev/null +++ b/resources/Schema/Entities/OverwatchCamera.xml @@ -0,0 +1,705 @@ + + + + + + 0.049999997019767761 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + Textures/Icons/Classes/Assault-01.png + + false + + + PickClass + 1 + + + + + + + + + + + Assault + 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 7 + 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/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..64141757 --- /dev/null +++ b/resources/Schema/Entities/PlayerAssaultBlue.xml @@ -0,0 +1,1120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + + + + + + + + + + + + + 0.10000000149011612 + 300 + + + + + + + + + + Models/Widgets/Camera.mesh + false + + + + + + + + + + + + + + + + + + + Textures/Weapons/Crosshair/SmallThickHoleDot.png + + false + + + + + + + + + + + + Schema/Entities/HitMarker.xml + + + + + + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + + + + 2 + + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + + + + 3 + + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + 1 + + + + 4 + + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + + + + 1 + + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + 1 + + + + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + + + + + + + + + + + + + + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + + + + Models/Widgets/Arrows/Arrow5.mesh + + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + + + + + + Schema/Entities/WeaponAssaultBlueView.xml + + + + AssaultWeapon + + + + + + + + Schema/Entities/WeaponDefenderBlueView.xml + + + + DefenderWeapon + + + + + + + + + + + + 0.10000000149011612 + 300 + + + Models/Widgets/Camera.mesh + false + + + + + + + + + + + + BlendTreeUpper + BlendTreeLower + + + + + Models/Characters/Assault/AssaultBlue.mesh + + + + + + + + R_Arm_Weapon_Joint + + + Schema/Entities/WeaponAssaultBlueWorld.xml + + + + + + + AssaultWeapon + + + + + + + + + + + R_Arm_Weapon_Joint + + + Schema/Entities/SidearmWeaponWorld.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 + + + + + + + + + + + + + + + + + AssaultWeaponBlend + SidearmWeapon + 0 + true + + + + + + + + Aim + WeaponBlend + + + + + + + + MovementBlend + ActionBlend + + + + + + + + Fire + Reload + 1 + + + + + + + + ReloadSwitchU + 0.5 + false + + + + + + + + + ShootFastRifleU + false + + + + + + + + + + + Idle + Run + 0 + + + + + + + + IdleAssaultRifleU + + true + true + + + + + + + + + IdleAssaultRifleU + + true + true + + + + + + + + + + + + + AimRifleA + + 0.10000000149011612 + false + true + + + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + false + + + + + + + + + + + + Models/Core/UnitCube.mesh + + false + + + + + + + + + + + + Fonts/DroidSans.ttf,100 + + + + + + + + + + + + + + Textures/Icons/Arrow.png + + false + + + + + 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..24bfee2b --- /dev/null +++ b/resources/Schema/Entities/PlayerDefenderBlue.xml @@ -0,0 +1,1362 @@ + + + + + + + + + + + + + + + + + 4 + 52 + + + + 150 + 150 + + + + + true + + + 5 + + + + + + + + + + + + + 0.10000000149011612 + 300 + + + + + + + + + + + Models/Widgets/Camera.mesh + false + + + + + + + + + + + + + + + + + + + Textures/Weapons/Crosshair/SmallThickHoleDot.png + + false + + + + + + + + + + + + Schema/Entities/HitMarker.xml + + + + + + + + + + + + + + 1 + + + + + Textures/HealthHUD3.png + + + + + + + + + + + + + + + + + + + + + + + Textures/Core/White.png + + false + + + + + + + + + + + + + + + + Textures/Core/White.png + + false + + + + + + + + + + + + + + + + Textures/Core/White.png + + false + + + + + + + + + + + + + + + + + + + Textures/Core/White.png + + false + + + + + + + + + + + 0.0 + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + 1 + + + + 150/150 + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + + + + 2 + + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + + + + 3 + + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + 1 + + + + 4 + + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + + + + 1 + + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + 1 + + + + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + + + + + + + + + + + + + + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + + + + Models/Widgets/Arrows/Arrow5.mesh + + + + + + + + + + + + + + + MovementBlend + FinalBlend + + + Models/Characters/Defender/FirstPersonDefenderBlue.mesh + + + + + + + + R_Arm_Weapon_Joint + + + DefenderWeapon + + + Schema/Entities/WeaponDefenderBlueView.xml + + + + + + + + + + + + R_Arm_Weapon_Joint + + + SidearmWeapon + + + Schema/Entities/SidearmWeaponView.xml + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + 0.10000000149011612 + 300 + + + Models/Widgets/Camera.mesh + false + + + + + + + + + + + + BlendTreeAim + BlendTreeAssault + + + + + Models/Characters/Defender/DefenderBlue.mesh + + + + + + + + + R_Arm_Weapon_Joint + + + AssaultWeapon + + + + + + Schema/Entities/WeaponDefenderBlueWorld.xml + + + + + + + + + + + + R_Arm_Weapon_Joint + + + SidearmWeapon + + + + + + Schema/Entities/SidearmWeaponWorld.xml + + + + + + + + + + + + AimPrimary + AimSecondary + 0 + true + + + + + + + + AimSecWepA + + false + true + + + + + + + + + AimRifleA + + false + true + + + + + + + + + + + ReloadSwitchBlend + MovementBlend + + + + + + + + StandCrouchBlend + JumpDashBlend + 2.5146881298480398e-63 + true + + + + + + + + StandMovement + CrouchMovement + 0 + true + + + + + + + + MovementBlend + Idle + 1 + + + + + + + + Walk + StrafeLRBlend + 0 + + + + + + + + Left + Right + 0.033793529385008014 + + + + + + + + CrouchStrafeRightF + + 1 + true + + + + + + + + + CrouchStrafeLeftF + + 1 + true + + + + + + + + + + + CrouchWalkF + + 1 + true + + + + + + + + + + + CrouchF + + 1 + + + + + + + + + + + MovementBlend + Idle + 1 + + + + + + + + RunWalkBlend + StrafeLRBlend + 2.4565650245976452e-16 + + + + + + + + Left + Right + 0.033793529385008014 + + + + + + + + StrafeRightF + + 1 + true + + + + + + + + + StrafeLeftF + + 1 + true + + + + + + + + + + + Walk + Run + 1.2938206818383024e-24 + + + + + + + + WalkF + + 1 + true + + + + + + + + + RunF + + 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 + + + + + + + + + + + + + + + + + + + + + + + + Deploy + Idle + 0 + + + Models/Characters/Defender/DefenderShield.mesh + + + + + + + + ActivateDeactiveShieldF + 1 + + + + + + + + + ShieldFrontF + 1 + + + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + false + + + + + + + + + + + + Models/Core/UnitCube.mesh + + false + + + + + + + + + + + + Fonts/DroidSans.ttf,100 + + + + + + + + + + + + + + Textures/Icons/Arrow.png + + false + + + + + 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..cf07bc56 --- /dev/null +++ b/resources/Schema/Entities/PlayerHUD.xml @@ -0,0 +1,433 @@ + + + + + + + + + + + + + + Textures/Weapons/Crosshair/SmallThickHoleDot.png + + false + + + + + + + + + + + + Schema/Entities/HitMarker.xml + + + + + + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + false + + + + + + + + + + + + + + 3 + + + Textures/Core/UnitHexagon_Rotated.png + + false + + + + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + false + + + + + + + + + + + 1 + + + + 4 + + + Textures/Core/UnitHexagon_Rotated.png + + false + + + + + + + + + + + + + + + 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 + + + + + Textures/Core/UnitHexagon_Rotated.png + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + + + + Models/Widgets/Arrows/Arrow5.mesh + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + 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..2fbd9527 100644 --- a/resources/Schema/Entities/QualityAssurance.xml +++ b/resources/Schema/Entities/QualityAssurance.xml @@ -2,102 +2,15 @@ + + 3.6154132075906489 + - - - - - - Models/Core/UnitPlane.mesh - - - - - - - - - - - 90 - - - - - - - - - - - - 1 - - - - - - - - - - - Audio/crosscounter.wav - true - - - - - - - - - - SoundEmitter - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - - - - - - - - - - - - 0.80000001192092896 - - - Models/Widgets/Lights/DirectionalLightWidget.mesh - - - 1 - - - - - - - - - @@ -108,7 +21,9 @@ - + + + Models/Characters/Assault/AssaultAnimated.mesh @@ -120,7 +35,9 @@ - + + + Models/Characters/Assault/AssaultAnimated.mesh @@ -168,13 +85,15 @@ - + - + + + Models/Characters/Assault/AssaultAnimated.mesh @@ -190,6 +109,96 @@ + + + + + + Models/Core/UnitPlane.mesh + + + + + + + + + + + 90 + + + + + + + + + + + + 1 + + + + + + + + + + + Audio/crosscounter.wav + true + + + + + + + + + + SoundEmitter + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + + + + + 1 + + + + 0.80000001192092896 + + + Models/Widgets/Lights/DirectionalLightWidget.mesh + + + + + + + + @@ -213,7 +222,7 @@ - + @@ -277,7 +286,7 @@ - + @@ -309,7 +318,7 @@ - + @@ -380,15 +389,15 @@ - - - Schema/Entities/Player.xml - + + + Schema/Entities/Player.xml + @@ -450,15 +459,15 @@ - - - Schema/Entities/Player.xml - + + + Schema/Entities/Player.xml + @@ -544,8 +553,8 @@ - Models/Core/UnitCube.mesh - + Models/BushAlive.mesh + true @@ -604,8 +613,8 @@ - + @@ -659,7 +668,7 @@ - + @@ -706,7 +715,7 @@ - + @@ -766,7 +775,7 @@ - + @@ -813,7 +822,7 @@ - + @@ -859,7 +868,7 @@ - + @@ -906,7 +915,7 @@ - + @@ -953,7 +962,7 @@ - + @@ -1008,26 +1017,26 @@ + 15 - 15 - - Models/Core/UnitCube.mesh - - true - + + + Models/Core/UnitCube.mesh + + true + - @@ -1039,8 +1048,8 @@ - + @@ -1063,17 +1072,17 @@ 1 + + Models/Core/UnitCube.mesh true - - @@ -1085,8 +1094,8 @@ - + @@ -1107,17 +1116,17 @@ 2 + + Models/Core/UnitCube.mesh true - - @@ -1129,8 +1138,8 @@ - + @@ -1153,17 +1162,17 @@ 3 + + Models/Core/UnitCube.mesh true - - @@ -1175,8 +1184,8 @@ - + @@ -1197,27 +1206,27 @@ + -15 - -15 4 - - Models/Core/UnitCube.mesh - - true - + + + Models/Core/UnitCube.mesh + + true + - @@ -1229,8 +1238,8 @@ - + @@ -1270,8 +1279,8 @@ - + @@ -1367,7 +1376,7 @@ - + @@ -1376,7 +1385,7 @@ true - 0.8256214817261025 + 1.5712751414989441 3.7999999523162842 true @@ -1423,7 +1432,7 @@ - + @@ -1432,7 +1441,7 @@ - 1.8641349174045843 + 0.85439856235552725 Models/Characters/Assault/AssaultTPose.mesh @@ -1475,18 +1484,20 @@ - + - + + + true - 1.8641349174045843 + 0.85439856235552725 true @@ -1531,7 +1542,7 @@ - + @@ -1541,7 +1552,7 @@ true - 1.2301962937648341 + 7.5223549108000043 10 3 @@ -1589,7 +1600,7 @@ - + @@ -1599,7 +1610,7 @@ true - 3.4214855659573402 + 0.39702717854592606 true 5 true @@ -1636,8 +1647,8 @@ - + @@ -1682,6 +1693,11 @@ + + + + + @@ -1690,12 +1706,8 @@ 5 + - - - - - @@ -1712,13 +1724,14 @@ + Fonts/DroidSans.ttf,100 - + @@ -1756,8 +1769,8 @@ - + @@ -1769,8 +1782,8 @@ - + @@ -1780,7 +1793,7 @@ true - 0.8256214817261025 + 1.5712751414989441 3.7999999523162842 true @@ -1823,7 +1836,9 @@ - + + + @@ -1890,8 +1905,8 @@ - + @@ -1925,6 +1940,7 @@ Textures/Props/FoliageDiff.png + @@ -1934,6 +1950,7 @@ Textures/Props/FoliageDiff.png + @@ -1954,6 +1971,7 @@ Textures/Core/UnitHexagon.png + @@ -1963,19 +1981,20 @@ - - 2 - + + 2 + Textures/Core/UnitHexagon_Rotated.png + - + @@ -1986,6 +2005,7 @@ Textures/Core/UnitHexagon.png + @@ -1995,19 +2015,20 @@ - - 3 - + + 3 + Textures/Core/UnitHexagon_Rotated.png + - + @@ -2018,6 +2039,7 @@ Textures/Core/UnitHexagon.png + @@ -2027,20 +2049,21 @@ - - 4 - 1 + + 4 + Textures/Core/UnitHexagon_Rotated.png + - + @@ -2051,6 +2074,7 @@ Textures/Core/UnitHexagon.png + @@ -2060,19 +2084,20 @@ - - 1 - + + 1 + Textures/Core/UnitHexagon_Rotated.png + - + @@ -2083,6 +2108,7 @@ Textures/Core/UnitHexagon.png + @@ -2092,18 +2118,19 @@ - 1 + Textures/Core/UnitHexagon_Rotated.png + - + @@ -2129,14 +2156,24 @@ - + + + + + + + + + + + - + @@ -2167,6 +2204,7 @@ Textures/Core/ErrorTexture.png + @@ -2178,6 +2216,7 @@ Textures/Core/White.png + @@ -2206,6 +2245,7 @@ Textures/Core/White.png + @@ -2234,6 +2274,7 @@ Textures/Core/White.png + @@ -2262,6 +2303,7 @@ Textures/Core/White.png + @@ -2290,6 +2332,7 @@ Textures/Core/White.png + @@ -2331,6 +2374,9 @@ Textures/Core/ErrorTexture.png + true + + @@ -2342,6 +2388,8 @@ Textures/Core/White.png + + false @@ -2355,6 +2403,7 @@ 1920x1080 Fonts/DroidSans.ttf,64 + false @@ -2370,6 +2419,8 @@ Textures/Core/White.png + + false @@ -2383,6 +2434,7 @@ 1280x720 Fonts/DroidSans.ttf,64 + false @@ -2398,6 +2450,7 @@ Textures/Core/White.png + @@ -2426,6 +2479,7 @@ Textures/Core/White.png + @@ -2482,6 +2536,36 @@ + + + + + + + + + + + + + + + + + 2 + + + Models/Weapons/Blue/AssaultWeaponBlue.mesh + + + + + + + + + + diff --git a/resources/Schema/Entities/RayBlue b/resources/Schema/Entities/RayBlue deleted file mode 100644 index d34e185e..00000000 --- a/resources/Schema/Entities/RayBlue +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - Models/Core/UnitCylinder.mesh - - - - - - - - - - - diff --git a/resources/Schema/Entities/RayBlue.xml b/resources/Schema/Entities/RayBlue.xml index 022d7769..83adbe51 100644 --- a/resources/Schema/Entities/RayBlue.xml +++ b/resources/Schema/Entities/RayBlue.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/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/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/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..ccc1df68 --- /dev/null +++ b/resources/Schema/Entities/ScoreBoard_Main.xml @@ -0,0 +1,68 @@ + + + + + + + + + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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..3c47e045 --- /dev/null +++ b/resources/Schema/Entities/ServerIdentity.xml @@ -0,0 +1,122 @@ + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + Textures/Core/White.png + true + + false + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/ServerList.xml b/resources/Schema/Entities/ServerList.xml new file mode 100644 index 00000000..f9a601f5 --- /dev/null +++ b/resources/Schema/Entities/ServerList.xml @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + + + + Schema/Entities/ServerIdentity.xml + + + + + + + + + + + + + + Textures/Core/White.png + true + + + + + + + + + + + + + + Textures/Core/White.png + true + + + + + RefreshServerList + 1 + + + + + + + + + + + Textures/Icons/rotate.png + + + + + + + + + + + + + + + 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/AssaultWeaponView.xml b/resources/Schema/Entities/SidearmWeaponView.xml old mode 100755 new mode 100644 similarity index 62% rename from resources/Schema/Entities/AssaultWeaponView.xml rename to resources/Schema/Entities/SidearmWeaponView.xml index 4b985fbb..d3dcda66 --- a/resources/Schema/Entities/AssaultWeaponView.xml +++ b/resources/Schema/Entities/SidearmWeaponView.xml @@ -1,16 +1,12 @@ - + - - R_Arm_Weapon_Joint - - Models/Weapons/Blue/AssaultWeaponBlue.mesh + Models/Weapons/SecondaryWeapon.mesh - - + @@ -18,28 +14,23 @@ - Schema/Entities/RayBlue.xml + Schema/Entities/Ray2Red.xml - + - - - - Schema/Entities/ReloadEffectView.xml - - - - - - + + + + + - + @@ -52,7 +43,7 @@ - + @@ -65,26 +56,33 @@ + + Player + SidearmWeapon + MagazineAmmo + - 32 + 16 Fonts/DroidSans.ttf,64 + - + - 360 + 8 Fonts/DroidSans.ttf,64 - + + 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..2ad8f377 --- /dev/null +++ b/resources/Schema/Entities/StartMenu.xml @@ -0,0 +1,9190 @@ + + + + + + + + + + + + + + + + + Schema/Entities/NewMap2version5NEW.xml + + + + + + + + 7.0999304984909202 + + + + + + + + + + + + + + 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/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/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/Hg20.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/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.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/MediumStone2.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/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/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.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/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/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/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + Models/Props/Stones/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/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/mediumStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/mediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/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 + + + + + + + + + + + + + Models/Props/Stones/BigStone.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/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/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/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/BigWallRed.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/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/BigWallRed.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/Walls/BigWallBlue.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/BigWallRed.mesh + + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/AmmoPickUp.mesh + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + + + + + + + + + 8 + + + + Models/Props/PickUps/HealthPickUp.mesh + + + + + + + + + + + + + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalRed.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/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/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/MediumStone2.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/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.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 + + + + + + + + + + + + + 2 + + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalRed.mesh + + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 4 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + 2 + + + + + + + + + + + + 3 + + + + + + + + + + + + 2 + 1 + + + + + + + + + + + + + + 4 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + + 6 + Models/Props/Stones/ShinyStoneCrystalBlue.mesh + + + + + + + + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.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/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/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/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/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/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/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/MediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/MediumStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone1.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/SmallStone2.mesh + + + + + + + + + + + + + Models/Props/Stones/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/SmallStone2.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/SmallStone2.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/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/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/StonePillar.mesh + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar1Blue.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/Bridges/SciFiBridge1Blue.mesh + + + + + + + + + + + + + + Models/Props/Bridges/SciFiBridge1Blue.mesh + + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + Models/Props/Bridges/SciFiBridgeDefense.mesh + + + + + + + + + + + + + + + + + + + + + + + + + + + Models/Props/SciFiHolder1.mesh + + + + + + + + + + + + + Models/Props/SciFiHolder1.mesh + + + + + + + + + + + + + Models/Props/SciFiHolder1.mesh + + + + + + + + + + + + + Models/Props/SciFiHolder1.mesh + + + + + + + + + + + + + + + + + + + + Models/Props/Flora/SpecialRoot.mesh + + + + + + + + + + + + + + Models/Props/Flora/SpecialRoot.mesh + + + + + + + + + + + + + Models/Props/Flora/SpecialRoot.mesh + + + + + + + + + + + + + + Models/Props/Flora/SpecialRoot.mesh + + + + + + + + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + Models/Props/Walls/MediumWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/BigWallBlue.mesh + + + + + + + + + + + + + Models/Props/Walls/MediumWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/MediumWall3.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/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/MediumWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/MediumWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/MediumWall3.mesh + + + + + + + + + + + + + + Models/Core/UnitPlane.mesh + + true + + + + + + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + Models/Props/Stones/AssaultHolder.mesh + + + + + + + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + 4 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar2Blue.mesh + + + + + + + + + + + + + 4 + Models/Props/Pillars/SciFiPillar3Blue.mesh + + + + + + + + + + + + + + 6 + Models/Props/Pillars/SciFiPillar1Blue.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 + + + + + + + + + + + + + + + + + + + + + + 10 + + + + + + + + + + + 10 + + + + + + + + + + + 10 + + + + + + + + + + + + 10 + + + + + + + + + + + 1 + + + + + + + + + + + + 10 + + + + + + + + + + + 1 + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + + + + + + 0.10000000149011612 + + + + + + + + + + + 0.20000000298023224 + + + + + + + + + + + + + + + + + + + + + + + + + Schema/Entities/MainMenu.xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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/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..520c9906 --- /dev/null +++ b/resources/Schema/Entities/WeaponAssaultBlueView.xml @@ -0,0 +1,198 @@ + + + + + + MovementBlend + ActionBlend + + + Models/Characters/Assault/FirstPersonAssaultBlue.mesh + + + + + + + + + Fire + Reload + 0 + true + + + + + + + + ReloadSwitchF + 0.5 + false + + + + + + + + + ShootRifleF + false + + + + + + + + + + + Idle + Run + 0 + true + + + + + + + + RunF + true + true + + + + + + + + + IdleF + 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 + + + + + AssaultWeapon + MagazineAmmo + + + + + + + + + + + 320 + Fonts/DroidSans.ttf,64 + + + + + AssaultWeapon + Ammo + + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/AssaultWeaponWorld.xml b/resources/Schema/Entities/WeaponAssaultBlueWorld.xml old mode 100755 new mode 100644 similarity index 61% rename from resources/Schema/Entities/AssaultWeaponWorld.xml rename to resources/Schema/Entities/WeaponAssaultBlueWorld.xml index 6fcb97b3..cb1acae6 --- a/resources/Schema/Entities/AssaultWeaponWorld.xml +++ b/resources/Schema/Entities/WeaponAssaultBlueWorld.xml @@ -1,17 +1,11 @@ - + - - R_Arm_Weapon_Joint - Models/Weapons/Blue/AssaultWeaponBlue.mesh - - - - + @@ -26,7 +20,7 @@ - + Schema/Entities/ReloadEffectWorld.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/WeaponDefenderBlueView.xml b/resources/Schema/Entities/WeaponDefenderBlueView.xml new file mode 100644 index 00000000..c22e7200 --- /dev/null +++ b/resources/Schema/Entities/WeaponDefenderBlueView.xml @@ -0,0 +1,260 @@ + + + + + + MovementBlend + FinalBlend + + + Models/Characters/Defender/FirstPersonDefenderBlue.mesh + + + + + + + + + ActionBlend + Shield + 0 + true + + + + + + + + ActivateDeactivateShieldF + 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_Arm_Weapon_Joint + + + Models/Weapons/Blue/DefenderWeaponBlue.mesh + + + + + + + + + + + Schema/Entities/RayBlue.xml + + + + + + + + + + + Schema/Entities/ReloadEffectView.xml + + + + + + + + + + + R_Ammo_Joint + true + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + + + + + + + + 38 + Fonts/DroidSans.ttf,64 + + + + + DefenderWeapon + Ammo + + + + + + + + + + + + 5 + Fonts/DroidSans.ttf,64 + + + + + DefenderWeapon + MagazineAmmo + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/DefenderWeaponWorld.xml b/resources/Schema/Entities/WeaponDefenderBlueWorld.xml old mode 100755 new mode 100644 similarity index 69% rename from resources/Schema/Entities/DefenderWeaponWorld.xml rename to resources/Schema/Entities/WeaponDefenderBlueWorld.xml index 826301b4..6c750964 --- a/resources/Schema/Entities/DefenderWeaponWorld.xml +++ b/resources/Schema/Entities/WeaponDefenderBlueWorld.xml @@ -2,17 +2,10 @@ - - R_Arm_Weapon_Joint - - - Models/Weapons/Blue/DefenderGunBlue.mesh + Models/Weapons/Blue/DefenderWeaponBlue.mesh - - - - + 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_with_capturep.xml similarity index 60% rename from resources/Schema/Entities/aim_rays.xml rename to resources/Schema/Entities/aim_rays_with_capturep.xml index c8dac9a3..6aa3246a 100644 --- a/resources/Schema/Entities/aim_rays.xml +++ b/resources/Schema/Entities/aim_rays_with_capturep.xml @@ -92,15 +92,15 @@ - - - Schema/Entities/Player.xml - + + + Schema/Entities/Player.xml + @@ -143,15 +143,15 @@ - - - Schema/Entities/Player.xml - + + + Schema/Entities/Player.xml + @@ -207,54 +207,129 @@ - - - - - - - - Models\Core\UnitCube.mesh - - - - - - - - - - - - + - + + + + + + 15 + + + + + + + + + + + + + + + + + + + models/core/unitcube.mesh + + + + + + + + + + + models/core/unitcube.mesh + + + + + + + + + + + models/core/unitcube.mesh + + + + + + + + + + - - - - - - 1 - - - Models\Core\UnitCube.mesh - - - - - - - - - - - - + - + + + + + + -15 + + + + 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..c0ac15aa 100644 --- a/resources/Schema/Types/Entity.xsd +++ b/resources/Schema/Types/Entity.xsd @@ -43,15 +43,34 @@ - + + + + - + + + + + + + + + + + + + + + + + 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.geom.glsl b/resources/Shaders/ExplosionEffect.geom.glsl index 44b44aa6..19944cac 100644 --- a/resources/Shaders/ExplosionEffect.geom.glsl +++ b/resources/Shaders/ExplosionEffect.geom.glsl @@ -1,5 +1,7 @@ #version 430 +#define MAX_SPLITS 4 + uniform mat4 M; uniform mat4 V; uniform mat4 P; @@ -22,6 +24,7 @@ in VertexData{ vec2 TextureCoordinate; vec4 ExplosionColor; float ExplosionPercentageElapsed; + vec4 PositionLightSpace[MAX_SPLITS]; }Input[]; out VertexData{ @@ -32,6 +35,7 @@ out VertexData{ vec2 TextureCoordinate; vec4 ExplosionColor; float ExplosionPercentageElapsed; + vec4 PositionLightSpace[MAX_SPLITS]; }Output; layout(triangles) in; @@ -145,6 +149,10 @@ void main() Output.TextureCoordinate = Input[i].TextureCoordinate; Output.Tangent = Input[i].Tangent; Output.BiTangent = Input[i].BiTangent; + for (int j = 0; j < MAX_SPLITS; j++) + { + Output.PositionLightSpace[j] = Input[i].PositionLightSpace[j]; + } // convert to model space for the gravity to always be in -y vec4 ExplodedPositionInModelSpace = M * vec4(ExplodedPosition, 1.0); @@ -186,6 +194,10 @@ void main() Output.TextureCoordinate = Input[i].TextureCoordinate; Output.Tangent = Input[i].Tangent; Output.BiTangent = Input[i].BiTangent; + for (int j = 0; j < MAX_SPLITS; j++) + { + Output.PositionLightSpace[j] = Input[i].PositionLightSpace[j]; + } // no change in position, pass through vertex gl_Position = gl_in[i].gl_Position; 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 aa45d118..112d8de5 100644 --- a/resources/Shaders/ForwardPlus.frag.glsl +++ b/resources/Shaders/ForwardPlus.frag.glsl @@ -1,7 +1,9 @@ #version 430 #define MIN_AMBIENT_LIGHT 0.3 +#define MAX_SPLITS 4 +uniform mat4 VM; uniform mat4 M; uniform mat4 V; uniform mat4 P; @@ -11,9 +13,10 @@ 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 vec2 DiffuseUVRepeat; uniform vec2 NormalUVRepeat; @@ -25,6 +28,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 @@ -59,7 +63,6 @@ layout (std430, binding = 4) buffer LightIndexBuffer float LightIndex[]; }; - in VertexData{ vec3 Position; vec3 Normal; @@ -68,6 +71,7 @@ in VertexData{ vec2 TextureCoordinate; vec4 ExplosionColor; float ExplosionPercentageElapsed; + vec4 PositionLightSpace[MAX_SPLITS]; }Input; out vec4 sceneColor; @@ -78,6 +82,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); } @@ -124,6 +147,154 @@ vec4 CalcNormalMappedValue(vec3 normal, vec3 tangent, vec3 bitangent, vec2 textu return vec4(TBN * normalize(NormalMap), 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) >> int(SSAOQuality), 0).r; @@ -131,7 +302,7 @@ void main() 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 position = VM * vec4(Input.Position, 1.0); vec4 normal = V * CalcNormalMappedValue(Input.Normal, Input.Tangent, Input.BiTangent, Input.TextureCoordinate * NormalUVRepeat, NormalMapTexture); normal = normalize(normal); //vec4 normal = normalize(V * vec4(Input.Normal, 0.0)); @@ -151,6 +322,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++) { @@ -162,16 +335,21 @@ void main() if(light.Type == 1) { // point light_result = CalcPointLightSource(V * light.Position, light.Radius, light.Color, light.Intensity, viewVec, position, 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; - vec4 reflectionTotal = reflectionColor * (1-specularTexel.a) * color_result.a; + 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; @@ -182,6 +360,7 @@ 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.xyz += glowTexel.xyz*GlowIntensity; diff --git a/resources/Shaders/ForwardPlus.vert.glsl b/resources/Shaders/ForwardPlus.vert.glsl index 26686222..70cb6ab6 100644 --- a/resources/Shaders/ForwardPlus.vert.glsl +++ b/resources/Shaders/ForwardPlus.vert.glsl @@ -1,8 +1,13 @@ #version 430 +uniform mat4 PVM; +#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; @@ -18,12 +23,13 @@ out VertexData{ 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.TextureCoordinate = TextureCoords; Output.Normal = vec3(TIM * vec4(Normal, 0.0)); @@ -31,4 +37,9 @@ void main() 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..dd407078 --- /dev/null +++ b/resources/Shaders/ForwardPlusShieldCheck.frag.glsl @@ -0,0 +1,210 @@ +#version 430 + +#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 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; + 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; +} + +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); +} + +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 position = VM * vec4(Input.Position, 1.0); + vec4 normal = V * CalcNormalMappedValue(Input.Normal, Input.Tangent, Input.BiTangent, Input.TextureCoordinate * NormalUVRepeat, NormalMapTexture); + normal = normalize(normal); + //vec4 normal = normalize(V * vec4(Input.Normal, 0.0)); + vec4 viewVec = normalize(-position); + 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, position, 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..c40a1145 100644 --- a/resources/Shaders/ForwardPlusSkinned.vert.glsl +++ b/resources/Shaders/ForwardPlusSkinned.vert.glsl @@ -1,9 +1,15 @@ #version 430 +#define MAX_SPLITS 4 + +uniform mat4 PVM; +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; @@ -21,6 +27,7 @@ out VertexData{ vec2 TextureCoordinate; vec4 ExplosionColor; float ExplosionPercentageElapsed; + vec4 PositionLightSpace[MAX_SPLITS]; }Output; void main() @@ -34,7 +41,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 = (boneTransform * vec4(Position, 1.0)).xyz; Output.TextureCoordinate = TextureCoords; @@ -43,4 +50,9 @@ void main() 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 c67a9c99..d20a0c1c 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 +#define MAX_SPLITS 4 +uniform mat4 VM; uniform mat4 M; uniform mat4 V; uniform mat4 P; @@ -12,6 +14,10 @@ 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 vec2 DiffuseUVRepeat1; @@ -26,7 +32,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; @@ -83,6 +88,7 @@ in VertexData{ vec2 TextureCoordinate; vec4 ExplosionColor; float ExplosionPercentageElapsed; + vec4 PositionLightSpace[MAX_SPLITS]; }Input; out vec4 sceneColor; @@ -93,6 +99,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); } @@ -176,6 +201,154 @@ 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) >> int(SSAOQuality), 0).r; @@ -189,7 +362,7 @@ 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 position = VM * 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); @@ -208,6 +381,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]); @@ -218,12 +393,17 @@ void main() if(light.Type == 1) { // point light_result = CalcPointLightSource(V * light.Position, light.Radius, light.Color, light.Intensity, viewVec, position, 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..d1e75403 --- /dev/null +++ b/resources/Shaders/ForwardPlusSplatMapRGBShieldCheck.frag.glsl @@ -0,0 +1,256 @@ +#version 430 + +#define MIN_AMBIENT_LIGHT 0.3 +#define MAX_SPLITS 4 + +uniform mat4 VM; +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 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; + 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){ + 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); + + 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 position = VM * 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); + normal = normalize(normal); + //vec4 normal = normalize(V * vec4(Input.Normal, 0.0)); + vec4 viewVec = normalize(-position); + + 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, position, 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..8a306ec2 100644 --- a/resources/Shaders/Gaussian_horiz.frag.glsl +++ b/resources/Shaders/Gaussian_horiz.frag.glsl @@ -14,11 +14,15 @@ uniform float weight[5] = float[](0.227027, 0.1945946, 0.1216216, 0.054054, 0.01 void main() { vec2 tex_offset = 1.0 / textureSize2D(Texture, 0); - vec3 result = texture(Texture, Input.TextureCoordinate).rgb * weight[0]; - + 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..921ba55a 100644 --- a/resources/Shaders/Gaussian_vert.frag.glsl +++ b/resources/Shaders/Gaussian_vert.frag.glsl @@ -14,11 +14,15 @@ uniform float weight[5] = float[](0.227027, 0.1945946, 0.1216216, 0.054054, 0.01 void main() { vec2 tex_offset = 1.0 / textureSize2D(Texture, 0); - vec3 result = texture(Texture, Input.TextureCoordinate).rgb * weight[0]; - + 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..4d72fa49 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; @@ -27,6 +24,6 @@ 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 = (boneTransform * vec4(Position, 1.0)).xyz; } \ No newline at end of file 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..7b1b26fb --- /dev/null +++ b/resources/Shaders/Shadow.vert.glsl @@ -0,0 +1,18 @@ +#version 430 + +uniform mat4 M; +uniform mat4 V; +uniform mat4 P; + +layout (location = 0) in vec3 Position; +layout (location = 4) in vec2 TextureCoords; + +out VertexData{ + vec2 TextureCoordinate; +}Output; + +void main() +{ + gl_Position = P * V * M * 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..abad7df1 100644 --- a/resources/Shaders/Sprite.frag.glsl +++ b/resources/Shaders/Sprite.frag.glsl @@ -3,8 +3,6 @@ uniform vec4 Color; uniform vec4 FillColor; uniform float FillPercentage; -uniform mat4 M; -uniform mat4 V; uniform mat4 P; layout (binding = 1) uniform sampler2D DiffuseTexture; @@ -35,7 +33,8 @@ void main() 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/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/src/Engine/Collision/CollisionSystem.cpp b/src/Engine/Collision/CollisionSystem.cpp index 95609ea6..53cabfac 100644 --- a/src/Engine/Collision/CollisionSystem.cpp +++ b/src/Engine/Collision/CollisionSystem.cpp @@ -17,105 +17,107 @@ 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")) { + RawModel* 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->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; + } + 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. + RawModel* 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 = Transform::ModelMatrix(boxB.Entity); + + glm::vec3 inOutVelocity = (glm::vec3)cPhysics["Velocity"]; + bool notMovingxz = glm::all(glm::lessThan(glm::abs(glm::vec2(inOutVelocity.x, inOutVelocity.z)), glm::vec2(0.01f))) && prevPosIt != m_PrevPositions.end(); + bool isOnGround = (bool)cPhysics["IsOnGround"]; + float verticalStepHeight = (float)(double)cPhysics["VerticalStepHeight"]; + if (Collision::AABBvsTriangles(boxA, model->Vertices(), model->m_Indices, modelMatrix, inOutVelocity, verticalStepHeight, isOnGround, resolutionVector)) { + //Move the position to previous position if it is not moving in the xz-plane, else resolve with the resolution vector. + (glm::vec3&)cTransform["Position"] += notMovingxz ? prevPosIt->second - boxA.Origin() : resolutionVector; + 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. + (glm::vec3&)cTransform["Position"] += resolutionVector; boxA = *Collision::EntityAbsoluteAABB(entity); - cPhysics["Velocity"] = inOutVelocity; - if (isOnGround) { + if (resolutionVector.y > 0) { everHitTheGround = true; (bool)cPhysics["IsOnGround"] = true; + ((glm::vec3&)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/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..a85127ad 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); } @@ -34,11 +34,48 @@ EntityWrapper EntityWrapper::Parent() } } +EntityWrapper EntityWrapper::FirstParentByName(const std::string& parentEntityName) +{ + 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) { 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) { EntityWrapper entity = *this; 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 93% rename from src/Engine/Core/EntityFilePreprocessor.cpp rename to src/Engine/Core/EntityXMLFilePreprocessor.cpp index 592daedb..9695509d 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; @@ -141,9 +141,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; @@ -196,7 +196,7 @@ void EntityFilePreprocessor::parseComponentInfo() } } -void EntityFilePreprocessor::parseDefaults() +void EntityXMLFilePreprocessor::parseDefaults() { using namespace xercesc; @@ -261,7 +261,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 +278,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/Transform.cpp b/src/Engine/Core/Transform.cpp index 333c3532..e5cff11c 100644 --- a/src/Engine/Core/Transform.cpp +++ b/src/Engine/Core/Transform.cpp @@ -24,7 +24,7 @@ glm::vec3 Transform::AbsolutePosition(World* world, EntityID entity) while (entity != EntityID_Invalid) { ComponentWrapper transform = world->GetComponent(entity, "Transform"); EntityID parent = world->GetParent(entity); - position += Transform::AbsoluteOrientation(world, parent) * (glm::vec3)transform["Position"]; + position += Transform::AbsoluteScale(world, parent) * (Transform::AbsoluteOrientation(world, parent) * (glm::vec3)transform["Position"]); entity = parent; } @@ -89,12 +89,12 @@ 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::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::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) diff --git a/src/Engine/Core/World.cpp b/src/Engine/Core/World.cpp index 9b323ff4..0952a53b 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,7 +45,7 @@ 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); @@ -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 diff --git a/src/Engine/Editor/EditorGUI.cpp b/src/Engine/Editor/EditorGUI.cpp index 8ce15d0a..7435bca8 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; } @@ -381,14 +393,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()); } diff --git a/src/Engine/Editor/EditorRenderSystem.cpp b/src/Engine/Editor/EditorRenderSystem.cpp index 9a385e7d..97203dea 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) @@ -54,7 +54,7 @@ void EditorRenderSystem::Update(double dt) EntityWrapper entity(m_World, cModel.EntityID); glm::mat4 modelMatrix = Transform::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 { diff --git a/src/Engine/Editor/EditorSystem.cpp b/src/Engine/Editor/EditorSystem.cpp index 4bee1427..5e0d02fd 100644 --- a/src/Engine/Editor/EditorSystem.cpp +++ b/src/Engine/Editor/EditorSystem.cpp @@ -2,6 +2,7 @@ #include "Core/UniformScaleSystem.h" #include "Editor/EditorRenderSystem.h" #include "Editor/EditorWidgetSystem.h" +#include "Core/EntityFile.h" EditorSystem::EditorSystem(SystemParams params, IRenderer* renderer, RenderFrame* renderFrame) : System(params) @@ -18,7 +19,7 @@ EditorSystem::EditorSystem(SystemParams params, IRenderer* renderer, RenderFrame 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)); @@ -129,7 +130,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); } @@ -203,14 +204,21 @@ bool EditorSystem::OnWidgetDelta(const Events::WidgetDelta& e) if (m_CurrentSelection.Valid()) { if (m_WidgetSpace == EditorGUI::WidgetSpace::Global) { glm::quat parentOrientation; + glm::vec3 parentScale(1.f); EntityWrapper parent = m_CurrentSelection.Parent(); if (parent.Valid()) { parentOrientation = glm::inverse(Transform::AbsoluteOrientation(parent)); + parentScale = Transform::AbsoluteScale(parent); } - (glm::vec3&)m_CurrentSelection["Transform"]["Position"] += parentOrientation * e.Translation; + (glm::vec3&)m_CurrentSelection["Transform"]["Position"] += parentOrientation * e.Translation / parentScale; } else if (m_WidgetSpace == EditorGUI::WidgetSpace::Local) { + glm::vec3 parentScale(1.f); + EntityWrapper parent = m_CurrentSelection.Parent(); + if (parent.Valid()) { + parentScale = Transform::AbsoluteScale(parent); + } glm::quat selectionOri = glm::quat((glm::vec3)m_CurrentSelection["Transform"]["Orientation"]); - glm::vec3 localTranslation = selectionOri * e.Translation; + glm::vec3 localTranslation = selectionOri * e.Translation / parentScale; (glm::vec3&)m_CurrentSelection["Transform"]["Position"] += localTranslation; } m_EditorGUI->SetDirty(m_CurrentSelection); @@ -260,12 +268,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; } } 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 aa87f6ff..b4eafbcb 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -33,7 +33,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()) { @@ -48,16 +50,16 @@ void Client::Connect(std::string address, int port) void Client::Update() { m_EventBroker->Process(); - while (m_Unreliable.IsSocketAvailable()) { - // Packet will get real data in receive - Packet packet(MessageType::Invalid); - m_Unreliable.Receive(packet); - if (packet.GetMessageType() == MessageType::Connect) { - parseUDPConnect(packet); - } else { - parseMessageType(packet); - } - } + //while (m_Unreliable.IsSocketAvailable()) { + // // Packet will get real data in receive + // Packet packet(MessageType::Invalid); + // m_Unreliable.Receive(packet); + // if (packet.GetMessageType() == MessageType::Connect) { + // parseUDPConnect(packet); + // } else { + // parseMessageType(packet); + // } + //} while (m_Reliable.IsSocketAvailable()) { // Packet will get real data in receive Packet packet(MessageType::Invalid); @@ -81,7 +83,10 @@ void Client::Update() if (m_SearchingForServers) { if (m_SearchingTime < (1000* (std::clock() - m_StartSearchTime) / (double)CLOCKS_PER_SEC)) { m_SearchingForServers = false; - displayServerlist(); + //displayServerlist(); + Events::DisplayServerlist e; + e.Serverlist = m_Serverlist; + m_EventBroker->Publish(e); } } @@ -143,6 +148,9 @@ void Client::parseMessageType(Packet& packet) case MessageType::OnDoubleJump: parseDoubleJump(packet); break; + case MessageType::OnDashEffect: + parseDashEffect(packet); + break; case MessageType::AmmoPickup: parseAmmoPickup(packet); break; @@ -173,8 +181,8 @@ void Client::parseTCPConnect(Packet& packet) 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"); + // m_Unreliable.Send(packet); + // LOG_INFO("Sent UDP Connect Server"); } void Client::parsePlayerConnected(Packet & packet) @@ -262,7 +270,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); @@ -297,8 +305,22 @@ 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; @@ -388,7 +410,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); } @@ -435,30 +457,26 @@ 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_Reliable.Disconnect(); + 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; } if (e.Command == "ConnectToServer") { // Connect for now if (e.Value > 0) { - m_Reliable.Connect(m_PlayerName, m_Address, m_Port); - m_Unreliable.Connect(m_PlayerName, m_Address, m_Port); + //m_Reliable.Connect(m_PlayerName, m_Address, m_Port); + // m_Unreliable.Connect(m_PlayerName, m_Address, m_Port); } //LOG_DEBUG("Client::OnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID); return true; @@ -518,12 +536,40 @@ 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)) { + // 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_Serverlist.clear(); - LOG_INFO("Searching for LAN servers...\n"); Packet packet(MessageType::ServerlistRequest); m_ServerlistRequest.Broadcast(packet, 13); // TODO: Config return true; @@ -583,7 +629,7 @@ void Client::sendLocalPlayerTransform() packet.WritePrimitive((int)cAssaultWeapon["Ammo"]); } - m_Unreliable.Send(packet); + m_Reliable.Send(packet); } void Client::identifyPacketLoss() @@ -645,6 +691,26 @@ void Client::displayServerlist() } } + +void Client::removeWorld() +{ + std::vector childrenToBeDeleted; + auto rootEntites = m_World->GetDirectChildren(EntityID_Invalid); + for (auto it = rootEntites.first; it != rootEntites.second; it++) { + childrenToBeDeleted.push_back(it->second); + } + for (int i = 0; i < childrenToBeDeleted.size(); ++i) { + m_World->DeleteEntity(childrenToBeDeleted[i]); + } +} + + +void Client::createMainMenu() +{ + auto entityFile = ResourceManager::Load("Schema/Entities/StartMenu.xml"); + entityFile->MergeInto(m_World); +} + bool Client::clientServerMapsHasEntity(EntityID clientEntityID) { if (m_ClientIDToServerID.find(clientEntityID) != m_ClientIDToServerID.end()) { diff --git a/src/Engine/Network/Packet.cpp b/src/Engine/Network/Packet.cpp index 475ca673..6a4d0098 100644 --- a/src/Engine/Network/Packet.cpp +++ b/src/Engine/Network/Packet.cpp @@ -49,18 +49,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(); } diff --git a/src/Engine/Network/Server.cpp b/src/Engine/Network/Server.cpp index 08b72304..0dd761a0 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -7,6 +7,8 @@ Server::Server(World* world, EventBroker* eventBroker, int port) ConfigFile* config = ResourceManager::Load("Config.ini"); snapshotInterval = 1000 * config->Get("Networking.SnapshotInterval", 0.05f); pingIntervalMs = config->Get("Networking.PingIntervalMs", 1000); + m_ServerName = config->Get("Networking.Name", "Unnamed"); + // Subscribe to events EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &Server::OnInputCommand); EVENT_SUBSCRIBE_MEMBER(m_EPlayerSpawned, &Server::OnPlayerSpawned); @@ -14,6 +16,7 @@ Server::Server(World* world, EventBroker* eventBroker, int port) 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); // BindWW if (port == 0) { port = config->Get("Networking.Port", 27666); @@ -46,19 +49,19 @@ void Server::Update() } } - PlayerDefinition pd; - while (m_Unreliable.IsSocketAvailable()) { - // Packet will get real data in receive - Packet packet(MessageType::Invalid); - m_Unreliable.Receive(packet, pd); - m_Address = pd.Endpoint.address(); - m_Port = pd.Endpoint.port(); - if (packet.GetMessageType() == MessageType::Connect) { - parseUDPConnect(packet); - } else { - parseMessageType(packet); - } - } + //PlayerDefinition pd; + //while (m_Unreliable.IsSocketAvailable()) { + // // Packet will get real data in receive + // Packet packet(MessageType::Invalid); + // m_Unreliable.Receive(packet, pd); + // m_Address = pd.Endpoint.address(); + // m_Port = pd.Endpoint.port(); + // if (packet.GetMessageType() == MessageType::Connect) { + // parseUDPConnect(packet); + // } else { + // parseMessageType(packet); + // } + //} while (m_ServerlistRequest.IsSocketAvailable()) { Packet packet(MessageType::Invalid); @@ -141,6 +144,9 @@ void Server::parseMessageType(Packet& packet) case MessageType::OnDoubleJump: parseDoubleJump(packet); break; + case MessageType::OnDashEffect: + parseDashEffect(packet); + break; default: break; } @@ -158,7 +164,7 @@ void Server::unreliableBroadcast(Packet& packet) { for (auto& kv : m_ConnectedPlayers) { packet.ChangePacketID(kv.second.PacketID); - m_Unreliable.Send(packet, kv.second); + // m_Unreliable.Send(packet, kv.second); } } @@ -168,7 +174,7 @@ void Server::sendSnapshot() Packet packet(MessageType::Snapshot); addInputCommandsToPacket(packet); addPlayersToPacket(packet, EntityID_Invalid); - unreliableBroadcast(packet); + reliableBroadcast(packet); } void Server::addInputCommandsToPacket(Packet& packet) @@ -316,25 +322,28 @@ void Server::checkForTimeOuts() } } -void Server::parseUDPConnect(Packet & packet) -{ - // Pop size of message int - packet.ReadPrimitive(); - int messageType = packet.ReadPrimitive(); - // Read packet ID - m_PreviousPacketID = m_PacketID; // Set previous packet id - m_PacketID = packet.ReadPrimitive(); //Read new packet id - // parse player id and other stuff - PlayerID playerID = packet.ReadPrimitive(); - // Do something here? - boost::asio::ip::udp::endpoint endpoint(m_Address, m_Port); - m_ConnectedPlayers.at(playerID).Endpoint = endpoint; - LOG_INFO("parseUDPConnect: Spectator \"%s\" connected on IP: %s", m_ConnectedPlayers.at(playerID).Name.c_str(), m_ConnectedPlayers.at(playerID).Endpoint.address().to_string().c_str()); - // Send a message to the player that connected - Packet connnectPacket(MessageType::Connect, m_ConnectedPlayers.at(playerID).PacketID); - m_Unreliable.Send(connnectPacket); - LOG_INFO("UDP Connect sent to client"); -} +//void Server::parseUDPConnect(Packet & packet) +//{ +// // Pop size of message int +// packet.ReadPrimitive(); +// int messageType = packet.ReadPrimitive(); +// // Read packet ID +// m_PreviousPacketID = m_PacketID; // Set previous packet id +// m_PacketID = packet.ReadPrimitive(); //Read new packet id +// // parse player id and other stuff +// PlayerID playerID = packet.ReadPrimitive(); +// if (!EntityWrapper(m_World, playerID).Valid()) { +// +// } +// // Do something here? +// boost::asio::ip::udp::endpoint endpoint(m_Address, m_Port); +// m_ConnectedPlayers.at(playerID).Endpoint = endpoint; +// LOG_INFO("parseUDPConnect: Spectator \"%s\" connected on IP: %s", m_ConnectedPlayers.at(playerID).Name.c_str(), m_ConnectedPlayers.at(playerID).Endpoint.address().to_string().c_str()); +// // Send a message to the player that connected +// Packet connnectPacket(MessageType::Connect, m_ConnectedPlayers.at(playerID).PacketID); +// m_Unreliable.Send(connnectPacket); +// LOG_INFO("UDP Connect sent to client"); +//} void Server::parseTCPConnect(Packet & packet) { @@ -348,7 +357,7 @@ 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) { return; } @@ -360,6 +369,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()); @@ -398,7 +412,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); } @@ -523,10 +537,20 @@ bool Server::OnAmmoPickup(const Events::AmmoPickup & e) return true; } + +bool Server::OnPlayerDeath(const Events::PlayerDeath& e) +{ + Events::KillDeath eKD; + eKD.Casualty = getPlayerIDFromEntityID(e.Player.ID); + eKD.Killer = getPlayerIDFromEntityID(e.Killer.ID); + m_EventBroker->Publish(eKD); + return false; +} + void Server::parseClientPing() { LOG_INFO("%i: Parsing ping", m_PacketID); - PlayerID player = GetPlayerIDFromEndpoint(); + PlayerID player = getPlayerIDFromEndpoint(); if (player == -1) { return; } @@ -555,11 +579,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; @@ -578,7 +607,7 @@ void Server::parseOnInputCommand(Packet& packet) void Server::parsePlayerTransform(Packet& packet) { - PlayerID playerID = GetPlayerIDFromEndpoint(); + PlayerID playerID = getPlayerIDFromEndpoint(); if (playerID == -1) { return; } @@ -614,20 +643,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") || child.HasComponent("HealthPickup") - || child.HasComponent("AmmoPickup")) { - return true; - } - } - return childEntity.HasComponent("Player") || childEntity.FirstParentWithComponent("Player").Valid() - || childEntity.HasComponent("CapturePoint") || childEntity.HasComponent("HealthPickup") - || childEntity.HasComponent("AmmoPickup"); + 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) { @@ -639,4 +658,14 @@ PlayerID Server::GetPlayerIDFromEndpoint() } } return -1; -} \ No newline at end of file +} + +PlayerID Server::getPlayerIDFromEntityID(EntityID entityID) +{ + for (auto& kv : m_ConnectedPlayers) { + if (entityID == kv.second.EntityID) { + return kv.first; + } + } + return -1; +} diff --git a/src/Engine/Network/TCPClient.cpp b/src/Engine/Network/TCPClient.cpp index f3394d3d..df9c159a 100644 --- a/src/Engine/Network/TCPClient.cpp +++ b/src/Engine/Network/TCPClient.cpp @@ -10,7 +10,7 @@ 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) { @@ -19,6 +19,7 @@ void TCPClient::Connect(std::string playerName, std::string address, int port) Send(packet); LOG_INFO("Connect message sent again!"); } + return true; } else if (!m_IsConnected) { boost::system::error_code error = boost::asio::error::host_not_found; @@ -34,11 +35,13 @@ void TCPClient::Connect(std::string playerName, std::string address, int port) packet.WriteString(playerName); Send(packet); LOG_INFO("Connect message sent!"); + return true; } // If error else { m_Socket->close(); m_Socket = nullptr; + return false; } } } @@ -74,7 +77,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 +88,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), 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..ff35aa91 100644 --- a/src/Engine/Network/TCPServer.cpp +++ b/src/Engine/Network/TCPServer.cpp @@ -106,7 +106,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..15682000 100644 --- a/src/Engine/Network/UDPClient.cpp +++ b/src/Engine/Network/UDPClient.cpp @@ -10,14 +10,15 @@ 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()); + return true; } void UDPClient::Disconnect() @@ -45,7 +46,10 @@ int UDPClient::readBuffer() 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; diff --git a/src/Engine/Network/UDPServer.cpp b/src/Engine/Network/UDPServer.cpp index 635ebd4d..bfa27d69 100644 --- a/src/Engine/Network/UDPServer.cpp +++ b/src/Engine/Network/UDPServer.cpp @@ -21,33 +21,38 @@ void UDPServer::Send(Packet& packet, PlayerDefinition & playerDefinition) boost::asio::buffer(packet.Data(), packet.Size()), playerDefinition.Endpoint, 0); + LOG_INFO("Size of packet is %i", bytesSent); } 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(); } + } // 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,7 +60,7 @@ 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()), @@ -92,6 +97,11 @@ int UDPServer::readBuffer() 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; diff --git a/src/Engine/Rendering/AnimationSystem.cpp b/src/Engine/Rendering/AnimationSystem.cpp index 02d72409..93a603a7 100644 --- a/src/Engine/Rendering/AnimationSystem.cpp +++ b/src/Engine/Rendering/AnimationSystem.cpp @@ -1,71 +1,348 @@ #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; } - Model* model; - try { - model = ResourceManager::Load<::Model, true>(entity["Model"]["Resource"]); - } catch (const std::exception&) { - 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_RawModel->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; + } + + } } - - Skeleton* skeleton = model->m_RawModel->m_Skeleton; - if(skeleton == nullptr) { +} + +void AnimationSystem::UpdateAnimations(double dt) +{ + auto animationComponents = m_World->GetComponents("Animation"); + if(animationComponents == nullptr) { return; } - for (int i = 1; i <= 3; i++) { - const Skeleton::Animation* animation = skeleton->GetAnimation(animationComponent["AnimationName" + std::to_string(i)]); + 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 { + model = ResourceManager::Load<::Model, true>(modelEntity["Model"]["Resource"]); + } catch (const std::exception&) { + return; + } + + Skeleton* skeleton = model->m_RawModel->m_Skeleton; + if (skeleton == nullptr) { + return; + } + + const Skeleton::Animation* animation = skeleton->GetAnimation(animationC["AnimationName"]); if (animation == nullptr) { continue;; } - double animationSpeed = (double)animationComponent["Speed" + std::to_string(i)]; + double animationSpeed = (double)animationC["Speed"]; - if (animationSpeed != 0.0) { - double nextTime = (double)animationComponent["Time" + std::to_string(i)] + animationSpeed * dt; + if((bool)animationC["Reverse"]) { + animationSpeed *= -1; + } - if (!(bool)animationComponent["Loop" + std::to_string(i)]) { + if ((bool)animationC["Play"]) { + + double nextTime = (double)animationC["Time"] + animationSpeed * dt; + if (!(bool)animationC["Loop"]) { 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); + (bool&)animationC["Play"] = false; } 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; + (bool&)animationC["Play"] = false; } - - (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; + + while (nextTime > animation->Duration) { + 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; + while (nextTime < 0) { + nextTime += animation->Duration; + } } } - - (double&)animationComponent["Time" + std::to_string(i)] = nextTime; + (double&)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()) { + 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_RawModel->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; + } + + EntityWrapper subTreeRoot; + + + if (e.SingleLevelBlend) { + subTreeRoot = blendTree->GetSubTreeRoot(e.NodeName); + + if (!subTreeRoot.Valid()) { + 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; + + 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"]); + (bool&)entity["Animation"]["Reverse"] = e.Reverse; + + if (e.Restart) { + if (animation != nullptr) { + if (e.Restart) { + if (e.Reverse) { + (double&)entity["Animation"]["Time"] = animation->Duration; + } else { + (double&)entity["Animation"]["Time"] = 0.0; + } + } + } + } + } + } + m_AutoBlendQueues[subTreeRoot].Insert(abj); + } else { + std::vector subtreeroots = blendTree->GetSingleLevelRoots(e.NodeName); + + for(auto entity : subtreeroots) { + subTreeRoot = entity; + + if (!subTreeRoot.Valid()) { + 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"]); + (bool&)entity["Animation"]["Reverse"] = e.Reverse; + + if (e.Restart) { + if (animation != nullptr) { + if (e.Restart) { + if (e.Reverse) { + (double&)entity["Animation"]["Time"] = animation->Duration; + } else { + (double&)entity["Animation"]["Time"] = 0.0; + } + } + } + } + } + } + } + + + return true; +} + +bool AnimationSystem::OnEntityDeleted(Events::EntityDeleted& e) +{ + EntityWrapper entity = EntityWrapper(m_World, 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_RawModel->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_RawModel->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..f4a854ec --- /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_RawModel->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_RawModel->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_RawModel->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..ca22cd74 --- /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, (double)ModelEntity["Animation"]["Time"], (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 = (double)ModelEntity["Blend"]["Weight"]; + m_Root->SubTreeRoot = (bool)ModelEntity["Blend"]["SubTreeRoot"]; + (double&)ModelEntity["Blend"]["Weight"] = glm::clamp((double)ModelEntity["Blend"]["Weight"], 0.0, 1.0); + m_Root->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, (double)childEntity["Animation"]["Time"], (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; + (double&)childEntity["Blend"]["Weight"] = glm::clamp((double)childEntity["Blend"]["Weight"], 0.0, 1.0); + node->Weight = (double)childEntity["Blend"]["Weight"]; + node->SubTreeRoot = (bool)childEntity["Blend"]["SubTreeRoot"]; + //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")) { + (double&)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")) { + (bool&)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; + (double&)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; + (double&)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..8fdb7f1a --- /dev/null +++ b/src/Engine/Rendering/BlurHUD.cpp @@ -0,0 +1,282 @@ +#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_vert, 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); + 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); + 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"); + + 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_horiz->Bind(); + 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); + + 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.Unbind(); + m_GaussianFrameBuffer_horiz.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.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); + 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); + glScissor(0, 0, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); + + + return m_GaussianTexture_vert; +} + + +void BlurHUD::OnWindowResize() +{ + CommonFunctions::GenerateTexture(&m_GaussianTexture_vert, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewportSize().Width/m_BlurQuality, m_Renderer->GetViewportSize().Height/m_BlurQuality), GL_RGB16F, GL_RGB, GL_FLOAT); + m_GaussianFrameBuffer_vert.Generate(); + CommonFunctions::GenerateTexture(&m_GaussianTexture_horiz, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewportSize().Width/m_BlurQuality, m_Renderer->GetViewportSize().Height/m_BlurQuality), GL_RGB16F, GL_RGB, GL_FLOAT); + m_GaussianFrameBuffer_horiz.Generate(); +} + +void BlurHUD::FillStencil(RenderScene& scene) +{ + RenderState state; + + state.BindFramebuffer(m_GaussianFrameBuffer_horiz.GetHandle()); + state.Disable(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); + glViewport(0, 0, m_Renderer->GetViewportSize().Width/m_BlurQuality, m_Renderer->GetViewportSize().Height/m_BlurQuality); + + m_FillDepthStencilProgram->Bind(); + + GLuint shaderHandle = m_FillDepthStencilProgram->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())); + + for (auto& job : scene.Jobs.SpriteJob) { + auto spriteJob = std::dynamic_pointer_cast(job); + if (!spriteJob) { + continue; + } + if (!spriteJob->BlurBackground) { + continue; + } + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(spriteJob->Matrix)); + + 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; + } + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(spriteJob->Matrix)); + + 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..c1cdf0f2 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"]); @@ -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"]) { + (glm::vec3&)entity["Transform"]["Position"] = translation + (glm::vec3)entity["BoneAttachment"]["PositionOffset"]; + } + if ((bool)entity["BoneAttachment"]["InheritOrientation"]) { + (glm::vec3&)entity["Transform"]["Orientation"] = angles; + } + if ((bool)entity["BoneAttachment"]["InheritScale"]) { + (glm::vec3&)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/DrawBloomPass.cpp b/src/Engine/Rendering/DrawBloomPass.cpp index 12777941..4172118c 100644 --- a/src/Engine/Rendering/DrawBloomPass.cpp +++ b/src/Engine/Rendering/DrawBloomPass.cpp @@ -9,9 +9,14 @@ DrawBloomPass::DrawBloomPass(IRenderer* renderer, ConfigFile* config) ChangeQuality(m_Config->Get("GLOW.Quality", 2)); } +DrawBloomPass::~DrawBloomPass() { + CommonFunctions::DeleteTexture(&m_GaussianTexture_horiz); + CommonFunctions::DeleteTexture(&m_GaussianTexture_vert); +} + void DrawBloomPass::InitializeTextures() { - m_BlackTexture = CommonFunctions::LoadTexture("Textures/Core/Black.png", false); + m_BlackTexture = CommonFunctions::TryLoadResource("Textures/Core/Black.png"); } void DrawBloomPass::ChangeQuality(int quality) @@ -45,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(); } @@ -53,6 +59,7 @@ 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(); } } 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 44ab8fd4..67a67351 100644 --- a/src/Engine/Rendering/DrawFinalPass.cpp +++ b/src/Engine/Rendering/DrawFinalPass.cpp @@ -1,10 +1,10 @@ #include "Rendering/DrawFinalPass.h" -DrawFinalPass::DrawFinalPass(IRenderer* renderer, LightCullingPass* lightCullingPass, CubeMapPass* cubeMapPass, SSAOPass* ssaoPass, GLuint* depthBuffer) +DrawFinalPass::DrawFinalPass(IRenderer* renderer, LightCullingPass* lightCullingPass, CubeMapPass* cubeMapPass, SSAOPass* ssaoPass, ShadowPass* shadowPass) : m_Renderer(renderer) , m_LightCullingPass(lightCullingPass) , m_CubeMapPass(cubeMapPass) , m_SSAOPass(ssaoPass) - , m_DepthBuffer(depthBuffer) + , m_ShadowPass(shadowPass) { //TODO: Make sure that uniforms are not sent into shader if not needed. m_ShieldPixelRate = 8; @@ -13,13 +13,21 @@ DrawFinalPass::DrawFinalPass(IRenderer* renderer, LightCullingPass* lightCulling InitializeFrameBuffers(); } +DrawFinalPass::~DrawFinalPass(){ + CommonFunctions::DeleteTexture(&m_BloomTexture); + CommonFunctions::DeleteTexture(&m_SceneTexture); + CommonFunctions::DeleteTexture(&m_DepthBuffer); + CommonFunctions::DeleteTexture(&m_ShieldBuffer); + CommonFunctions::DeleteTexture(&m_CubeMapTexture); +} + 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() @@ -30,30 +38,20 @@ void DrawFinalPass::InitializeFrameBuffers() //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_FinalPassFrameBuffer.AddResource(std::shared_ptr(new Texture2D(m_DepthBuffer, GL_DEPTH_STENCIL_ATTACHMENT))); + 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); + + 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"); - - CommonFunctions::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); - CommonFunctions::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"); + CommonFunctions::GenerateTexture(&m_ShieldBuffer, GL_CLAMP_TO_BORDER, GL_NEAREST, + glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_DEPTH_COMPONENT32, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT); + m_ShieldDepthFrameBuffer.AddResource(std::shared_ptr(new Texture2D(&m_ShieldBuffer, GL_DEPTH_ATTACHMENT))); + m_ShieldDepthFrameBuffer.Generate(); } void DrawFinalPass::InitializeShaderPrograms() @@ -85,6 +83,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"))); @@ -140,152 +139,200 @@ 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) +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); + state->DepthMask(GL_FALSE); } //TODO: Do we need check for this or will it be per scene always? glClearStencil(0x00); glClear(GL_STENCIL_BUFFER_BIT); //Fill depth buffer - - state->StencilMask(0x00); - DrawModelRenderQueues(scene.Jobs.OpaqueObjects, scene); - GLERROR("OpaqueObjects"); - //state->BlendFunc(GL_ONE, GL_ONE); - state->BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - //state->BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - DrawModelRenderQueues(scene.Jobs.TransparentObjects, scene); - 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"); + state->Enable(GL_STENCIL_TEST); + state->StencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + state->StencilFunc(GL_ALWAYS, 1, 0xFF); + state->StencilMask(0xFF); + state->DepthMask(GL_FALSE); + //DrawToDepthStencilBuffer(scene.Jobs.ShieldObjects, scene); + state->DepthMask(GL_TRUE); //Draw Opaque shielded objects + state->Disable(GL_STENCIL_TEST); state->StencilFunc(GL_NOTEQUAL, 1, 0xFF); state->StencilMask(0x00); - DrawModelRenderQueues(scene.Jobs.OpaqueShieldedObjects, scene); //might need changing + DrawModelRenderQueuesWithShieldCheck(scene.Jobs.OpaqueShieldedObjects, scene); //might need changing GLERROR("Shielded Opaque object"); + //Draw Opaque objects + //state->StencilMask(0x00); + DrawModelRenderQueues(scene.Jobs.OpaqueObjects, scene); + GLERROR("OpaqueObjects"); + + //state->Disable(GL_STENCIL_TEST); //Draw Transparen Shielded objects - DrawModelRenderQueues(scene.Jobs.TransparentShieldedObjects, scene); //might need changing + state->BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + DrawModelRenderQueuesWithShieldCheck(scene.Jobs.TransparentObjects, scene); //might need changing GLERROR("Shielded Transparent objects"); - GLERROR("END"); + //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. + m_FullBlurredTexture = blurHUDPass->Draw(m_SceneTexture, scene); + } + DrawFinalPassState* stateSprite = new DrawFinalPassState(m_FinalPassFrameBuffer.GetHandle()); + if(scene.ShouldBlur) { + //Combine nonblur and blur texture + stateSprite->Disable(GL_DEPTH_TEST); + stateSprite->Disable(GL_STENCIL_TEST); + m_CombinedTexture = blurHUDPass->CombineTextures(m_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); + } + //Draw Transparen objects + //state->BlendFunc(GL_ONE, GL_ONE); + //state->StencilFunc(GL_EQUAL, 1, 0xFF); + //DrawModelRenderQueues(scene.Jobs.TransparentObjects, scene); + GLERROR("TransparentObjects"); + //state->BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + stateSprite->Enable(GL_DEPTH_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); - GLERROR("OpaqueObjects"); - DrawModelRenderQueues(scene.Jobs.TransparentObjects, scene); - 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 | GL_STENCIL_BUFFER_BIT); - GLERROR("2"); - - glDisable(GL_SCISSOR_TEST); - GLERROR("3"); - - m_FinalPassFrameBufferLowRes.Unbind(); - - GLERROR("prebind HighRes"); + 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); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); m_FinalPassFrameBuffer.Unbind(); GLERROR("END"); } @@ -294,39 +341,27 @@ void DrawFinalPass::ClearBuffer() void DrawFinalPass::OnWindowResize() { //InitializeFrameBuffers(); - + 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_SceneTexture, 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_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_RGB16F, GL_RGB, GL_FLOAT); m_FinalPassFrameBuffer.Generate(); - - 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)); - - CommonFunctions::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); - CommonFunctions::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(); GLERROR("Error changing texture resolutions"); } 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()); @@ -335,211 +370,744 @@ void DrawFinalPass::DrawModelRenderQueues(std::list>& glActiveTexture(GL_TEXTURE0); 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(explosionSkinnedHandle, "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(explosionHandle, "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(forwardSkinnedHandle, "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 { + 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 { - 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())); + 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(); @@ -572,10 +1140,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])); @@ -611,11 +1179,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])); @@ -632,34 +1201,51 @@ 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(); + glUniform1i(glGetUniformLocation(shaderSkinnedHandle, "SSAOQuality"), m_SSAOPass->TextureQuality()); + 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())); + glUniform2f(glGetUniformLocation(shaderSkinnedHandle, "ScreenDimensions"), m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); + glUniform4fv(glGetUniformLocation(shaderSkinnedHandle, "AmbientColor"), 1, glm::value_ptr(scene.AmbientColor)); + 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])); } 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(); + glUniform1i(glGetUniformLocation(shaderHandle, "SSAOQuality"), m_SSAOPass->TextureQuality()); + 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())); + glUniform2f(glGetUniformLocation(shaderHandle, "ScreenDimensions"), m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); + glUniform4fv(glGetUniformLocation(shaderHandle, "AmbientColor"), 1, glm::value_ptr(scene.AmbientColor)); + 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"); } @@ -681,6 +1267,9 @@ 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())); + for(auto& job : jobs) { auto spriteJob = std::dynamic_pointer_cast(job); RenderState jobState; @@ -689,10 +1278,7 @@ void DrawFinalPass::DrawSprites(std::list>&jobs, Rend if(spriteJob->Depth == 0) { 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); @@ -722,17 +1308,14 @@ void DrawFinalPass::DrawSprites(std::list>&jobs, Rend void DrawFinalPass::BindExplosionUniforms(GLuint shaderHandle, std::shared_ptr& job, RenderScene& scene) { - glUniform1i(glGetUniformLocation(shaderHandle, "SSAOQuality"), m_SSAOPass->TextureQuality()); - 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"); @@ -763,29 +1346,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) { - glUniform1i(glGetUniformLocation(shaderHandle, "SSAOQuality"), m_SSAOPass->TextureQuality()); - 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); @@ -798,14 +1377,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"); } diff --git a/src/Engine/Rendering/DrawFinalPassState.cpp b/src/Engine/Rendering/DrawFinalPassState.cpp index 6e1e3473..5c238985 100644 --- a/src/Engine/Rendering/DrawFinalPassState.cpp +++ b/src/Engine/Rendering/DrawFinalPassState.cpp @@ -8,13 +8,12 @@ DrawFinalPassState::DrawFinalPassState(GLuint frameBuffer) Enable(GL_BLEND); BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); Enable(GL_DEPTH_TEST); - DepthMask(GL_FALSE); - DepthFunc(GL_LEQUAL); + 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_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)); } @@ -26,11 +25,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 9ba0d2d8..c94423ba 100644 --- a/src/Engine/Rendering/FrameBuffer.cpp +++ b/src/Engine/Rendering/FrameBuffer.cpp @@ -24,6 +24,13 @@ RenderBuffer::~RenderBuffer() } } +Texture2DArray::~Texture2DArray() +{ + if (m_ResourceHandle != 0) { + glDeleteTextures(1, m_ResourceHandle); + } +} + FrameBuffer::~FrameBuffer() { @@ -53,12 +60,15 @@ void FrameBuffer::Generate() case GL_TEXTURE_2D: glFramebufferTexture2D(GL_FRAMEBUFFER, (*it)->m_Attachment, (*it)->m_ResourceType, *(*it)->m_ResourceHandle, 0); GLERROR("FrameBuffer generate: glFramebufferTexture2D"); - break; case GL_RENDERBUFFER: glFramebufferRenderbuffer(GL_FRAMEBUFFER, (*it)->m_Attachment, (*it)->m_ResourceType, *(*it)->m_ResourceHandle); GLERROR("FrameBuffer generate: glFramebufferRenderbuffer"); break; + case GL_TEXTURE_2D_ARRAY: + glFramebufferTexture(GL_FRAMEBUFFER, (*it)->m_Attachment, *(*it)->m_ResourceHandle, 0); + GLERROR("FrameBuffer generate: glFramebufferTexture2DArray"); + break; } GLERROR("2"); @@ -70,7 +80,7 @@ void FrameBuffer::Generate() } GLERROR("3"); - GLenum* bufferTextures = &attachments[0]; + GLenum* bufferTextures = attachments.data(); glDrawBuffers(attachments.size(), bufferTextures); if (GLERROR("GLBufferAttachement error")) { printf(": AttachmentSize %i", attachments.size()); diff --git a/src/Engine/Rendering/Model.cpp b/src/Engine/Rendering/Model.cpp index 3f8e20e1..d34ce809 100644 --- a/src/Engine/Rendering/Model.cpp +++ b/src/Engine/Rendering/Model.cpp @@ -10,31 +10,31 @@ Model::Model(std::string fileName) 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; diff --git a/src/Engine/Rendering/PickingPass.cpp b/src/Engine/Rendering/PickingPass.cpp index fb58edf7..b5162e72 100644 --- a/src/Engine/Rendering/PickingPass.cpp +++ b/src/Engine/Rendering/PickingPass.cpp @@ -12,7 +12,8 @@ PickingPass::PickingPass(IRenderer* renderer, EventBroker* eb) PickingPass::~PickingPass() { - + CommonFunctions::DeleteTexture(&m_PickingTexture); + CommonFunctions::DeleteTexture(&m_DepthBuffer); } @@ -23,11 +24,12 @@ void PickingPass::InitializeTextures() glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_RG8, GL_RG, GL_UNSIGNED_BYTE); 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); + glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_DEPTH_COMPONENT32, 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); @@ -97,32 +100,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 { + 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 +168,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 +215,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(shaderHandle, "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 +284,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 +330,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(); diff --git a/src/Engine/Rendering/RenderSystem.cpp b/src/Engine/Rendering/RenderSystem.cpp index 7b0ea84f..54da9666 100644 --- a/src/Engine/Rendering/RenderSystem.cpp +++ b/src/Engine/Rendering/RenderSystem.cpp @@ -240,6 +240,8 @@ void RenderSystem::fillModels(RenderScene::Queues &Jobs) fillColor = (glm::vec4)fillComponent["Color"]; } + bool isShielded = m_World->HasComponent(cModel.EntityID, "Shielded") || m_World->HasComponent(cModel.EntityID, "Player"); + glm::mat4 modelMatrix = Transform::ModelMatrix(cModel.EntityID, m_World); //Loop through all materialgroups of a model for (auto matGroup : model->MaterialGroups()) { @@ -255,20 +257,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 +296,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); @@ -434,6 +437,7 @@ void RenderSystem::Update(double dt) } RenderScene scene; + scene.ShouldBlur = true; scene.Camera = m_Camera; scene.Viewport = Rectangle(1280, 720); @@ -447,7 +451,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 e590cd97..90122f7c 100644 --- a/src/Engine/Rendering/Renderer.cpp +++ b/src/Engine/Rendering/Renderer.cpp @@ -2,6 +2,19 @@ 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); @@ -17,7 +30,7 @@ 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); @@ -110,7 +123,7 @@ void Renderer::Draw(RenderFrame& frame) { GLERROR("PRE"); glBindFramebuffer(GL_FRAMEBUFFER, 0); - ImGui::Combo("Draw textures", &m_DebugTextureToDraw, "Final\0Scene\0Bloom\0SceneLowRes\0BloomLowRes\0Gaussian\0Picking\0Ambient Occlusion"); + 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)"); if(m_CubeMapTexture == 0) { m_CubeMapPass->LoadTextures("Nevada"); @@ -133,6 +146,9 @@ void Renderer::Draw(RenderFrame& frame) 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) { @@ -148,6 +164,9 @@ void Renderer::Draw(RenderFrame& frame) 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"); @@ -158,7 +177,7 @@ void Renderer::Draw(RenderFrame& frame) m_LightCullingPass->CullLights(*scene); GLERROR("LightCulling"); PerformanceTimer::StartTimerAndStopPrevious("Renderer-Draw Geometry+Light"); - m_DrawFinalPass->Draw(*scene); + m_DrawFinalPass->Draw(*scene, m_BlurHUDPass); GLERROR("Draw Geometry+Light"); //m_DrawScenePass->Draw(*scene); @@ -174,7 +193,7 @@ 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); + m_DrawColorCorrectionPass->Draw(m_DrawFinalPass->SceneTexture(), m_DrawBloomPass->GaussianTexture(), frame.Gamma, frame.Exposure); PerformanceTimer::StopTimer("Renderer-Color Correction Pass"); } @@ -186,20 +205,20 @@ 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"); @@ -219,8 +238,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"); } @@ -250,9 +269,11 @@ void Renderer::InitializeRenderPasses() m_LightCullingPass = new LightCullingPass(this); m_CubeMapPass = new CubeMapPass(this); m_SSAOPass = new SSAOPass(this, m_Config); - m_DrawFinalPass = new DrawFinalPass(this, m_LightCullingPass, m_CubeMapPass, m_SSAOPass, m_PickingPass->DepthBuffer()); + m_ShadowPass = new ShadowPass(this); + m_BlurHUDPass = new BlurHUD(this); + m_DrawFinalPass = new DrawFinalPass(this, m_LightCullingPass, m_CubeMapPass, m_SSAOPass, m_ShadowPass); m_DrawScreenQuadPass = new DrawScreenQuadPass(this); m_DrawBloomPass = new DrawBloomPass(this, m_Config); m_DrawColorCorrectionPass = new DrawColorCorrectionPass(this); - + } \ No newline at end of file diff --git a/src/Engine/Rendering/SSAOPass.cpp b/src/Engine/Rendering/SSAOPass.cpp index 9992db70..f3c7f74c 100644 --- a/src/Engine/Rendering/SSAOPass.cpp +++ b/src/Engine/Rendering/SSAOPass.cpp @@ -4,12 +4,19 @@ SSAOPass::SSAOPass(IRenderer* renderer, ConfigFile* config) : m_Renderer(renderer) , m_Config(config) { - m_WhiteTexture = CommonFunctions::LoadTexture("Textures/Core/White.png", false); + 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) { @@ -56,6 +63,7 @@ void SSAOPass::InitializeShaderProgram() 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(); } @@ -64,6 +72,7 @@ void SSAOPass::InitializeShaderProgram() 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(); } @@ -72,6 +81,7 @@ void SSAOPass::InitializeShaderProgram() 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(); } @@ -80,6 +90,7 @@ void SSAOPass::InitializeShaderProgram() 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(); } } 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..15f03587 --- /dev/null +++ b/src/Engine/Rendering/ShadowPass.cpp @@ -0,0 +1,313 @@ +#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() +{ + 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); +} + +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(); + + +} + +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()); + + m_ShadowProgram->Bind(); + GLuint shaderHandle = m_ShadowProgram->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); + + 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]); + + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(m_LightProjection[i])); + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(m_LightView[i])); + + 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; + } + + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->Matrix)); + glUniform1f(glGetUniformLocation(shaderHandle, "Alpha"), 1.f); + + 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; + } + + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(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; + } + } + } + + 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..2883c53d 100644 --- a/src/Engine/Rendering/Skeleton.cpp +++ b/src/Engine/Rendering/Skeleton.cpp @@ -1,343 +1,37 @@ #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); @@ -364,37 +58,70 @@ glm::mat4 Skeleton::GetOffsetTransform(const Bone* bone, AnimationOffset animati } progress = glm::clamp(progress, 0.0f, 1.0f); - Animation::Keyframe::BoneProperty currentBoneProperty = currentFrame.BoneProperties; Animation::Keyframe::BoneProperty nextBoneProperty = nextFrame.BoneProperties; - position = currentBoneProperty.Position * (1.f - progress) + nextBoneProperty.Position * progress; - rotation = glm::slerp(currentBoneProperty.Rotation, nextBoneProperty.Rotation, progress); - scale = currentBoneProperty.Scale * (1.f - progress) + nextBoneProperty.Scale * progress; + 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); - position = currentFrame.BoneProperties.Position; - rotation = currentFrame.BoneProperties.Rotation; - scale = currentFrame.BoneProperties.Scale; + poseData.Translation = currentFrame.BoneProperties.Position; + poseData.Orientation = currentFrame.BoneProperties.Rotation; + poseData.Scale = currentFrame.BoneProperties.Scale; + boneMatrices[bone->ID] = poseData; } } - return (glm::translate(position) * glm::toMat4(rotation) * glm::scale(scale)); + for (auto &child : bone->Children) { + AccumulateBoneTransforms(noRootMotion, animation, time, boneMatrices, child); + } } -glm::mat4 Skeleton::GetBoneTransform(const Bone* bone, const Animation* animation, float time, glm::mat4 childMatrix) +void Skeleton::AdditiveBoneTransforms(const Animation* animation, double time, std::map& boneMatrices, const Bone* bone) { - glm::mat4 boneMatrix; + 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; - Animation::Keyframe currentFrame; - Animation::Keyframe nextFrame; + 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()) { 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) { @@ -413,276 +140,148 @@ glm::mat4 Skeleton::GetBoneTransform(const Bone* bone, const Animation* animatio 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); - } + 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; + position = currentBoneProperty.Position * (1.f - progress) + nextBoneProperty.Position * progress; + rotation = glm::slerp(currentBoneProperty.Rotation, nextBoneProperty.Rotation, progress); + scale = 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; + position = currentFrame.BoneProperties.Position; + rotation = currentFrame.BoneProperties.Rotation; + scale = currentFrame.BoneProperties.Scale; } } - if (bone->Parent) { - return GetBoneTransform(bone->Parent, animation, time, boneMatrix); - } else { - return boneMatrix; + 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(bool noRootMotion, const Bone* bone, std::vector animations, AnimationOffset animationOffset, glm::mat4 childMatrix) +std::vector Skeleton::GetTPose() { - 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 - - } + std::vector finalMatrices; + for (auto b : Bones) { + finalMatrices.push_back(glm::mat4(1)); } - - glm::mat4 offset = GetOffsetTransform(bone, animationOffset); - - if (JointTransforms.size() == 0) { - 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; - } - } 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; - } - } - - if (bone->Parent != nullptr) { - return GetBoneTransform(noRootMotion, bone->Parent, animations, animationOffset, boneMatrix); - } else { - return boneMatrix; - } + return finalMatrices; } - -glm::mat4 Skeleton::GetBoneTransform(bool noRootMotion, const Bone* bone, std::vector animations, 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 - - } - - } - - 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) { - boneMatrix = glm::inverse(bone->OffsetMatrix) * bone->Parent->OffsetMatrix * childMatrix; + boneMatrix = parentMatrix * (glm::inverse(bone->OffsetMatrix) * bone->Parent->OffsetMatrix); + boneMatrices[bone->ID] = boneMatrix * bone->OffsetMatrix; } else { - boneMatrix = glm::inverse(bone->OffsetMatrix) * childMatrix; + boneMatrix = glm::inverse(bone->OffsetMatrix); + boneMatrices[bone->ID] = parentMatrix; } - } 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; } + boneTransforms[bone->ID] = boneMatrix; - - 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/Texture.cpp b/src/Engine/Rendering/Texture.cpp index d184036f..9a81b472 100644 --- a/src/Engine/Rendering/Texture.cpp +++ b/src/Engine/Rendering/Texture.cpp @@ -12,18 +12,6 @@ Texture::Texture(std::string path) throw Resource::FailedLoadingException("Texture extension is not .png nor .dds"); } - //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; - // } - //} - this->Width = img->Width; this->Height = img->Height; @@ -38,6 +26,7 @@ Texture::Texture(std::string path) } // Construct the OpenGL texture + glGenTextures(1, &m_Texture); glBindTexture(GL_TEXTURE_2D, m_Texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); diff --git a/src/Engine/Rendering/TextureSprite.cpp b/src/Engine/Rendering/TextureSprite.cpp new file mode 100644 index 00000000..178aebf0 --- /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_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST_MIPMAP_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 51529a72..e1344928 100644 --- a/src/Engine/Rendering/Util/CommonFunctions.cpp +++ b/src/Engine/Rendering/Util/CommonFunctions.cpp @@ -1,23 +1,5 @@ #include "Rendering/Util/CommonFunctions.h" -Texture* CommonFunctions::LoadTexture(std::string path, bool threaded) -{ - 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 = ResourceManager::Load("Textures/Core/ErrorTexture.png"); - } - - return img; -} - void CommonFunctions::GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type) { glDeleteTextures(1, texture); diff --git a/src/Engine/Rendering/Util/ScreenCoords.cpp b/src/Engine/Rendering/Util/ScreenCoords.cpp index 8b7768c8..a858524d 100644 --- a/src/Engine/Rendering/Util/ScreenCoords.cpp +++ b/src/Engine/Rendering/Util/ScreenCoords.cpp @@ -37,7 +37,7 @@ ScreenCoords::PixelData ScreenCoords::ToPixelData(float x, float y, FrameBuffer* glReadPixels(x, y, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &pdata); GLERROR("glReadPixels(pdata) Error"); PickDataBuffer->Unbind(); - + GLERROR("Unbind Error"); glBindFramebuffer(GL_FRAMEBUFFER, DepthBuffer); GLERROR("glBindFramebuffer(DepthBuffer) Error"); float depthData; diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index 8ff42ebd..04abdd28 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/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,19 @@ #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 "Rendering/TextureSprite.h" Game::Game(int argc, char* argv[]) @@ -40,9 +53,11 @@ Game::Game(int argc, char* argv[]) ResourceManager::RegisterType("RawModel"); ResourceManager::RegisterType("Texture"); 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"); @@ -79,10 +94,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 +118,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); @@ -119,22 +131,33 @@ Game::Game(int argc, char* argv[]) ++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_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); // Populate Octree with collidables ++updateOrderLevel; m_SystemPipeline->AddSystem(updateOrderLevel, m_OctreeCollision, "Collidable"); @@ -197,7 +220,7 @@ 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"); diff --git a/src/Game/Network/MultiplayerSnapshotFilter.cpp b/src/Game/Network/MultiplayerSnapshotFilter.cpp index 295cdd7a..1131424b 100644 --- a/src/Game/Network/MultiplayerSnapshotFilter.cpp +++ b/src/Game/Network/MultiplayerSnapshotFilter.cpp @@ -15,7 +15,9 @@ bool MultiplayerSnapshotFilter::FilterComponent(EntityWrapper entity, SharedComp || component.Info.Name == "AssaultWeapon" || component.Info.Name == "DefenderWeapon" || 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..07461f95 --- /dev/null +++ b/src/Game/Systems/AbilityCooldownHUDSystem.cpp @@ -0,0 +1,82 @@ +#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. + return; + } else { + //If we have a shield ability, we set the right icon + abilityName = "ShieldAbility"; + if (entity.HasComponent("Sprite")) { + (std::string&)entity["Sprite"]["DiffuseTexture"] = "Textures\\Icons\\Abilities\\SheildDots-01.png"; + } + } + } else { + //If we do have a sprint ability, we change the icon + abilityName = "SprintAbility"; + if (entity.HasComponent("Sprite")) { + (std::string&)entity["Sprite"]["DiffuseTexture"] = "Textures\\Icons\\Abilities\\Dash-01.png"; + } + } + } else { + //If we have a dash ability, we set the icon to the correct one. + abilityName = "DashAbility"; + if (entity.HasComponent("Sprite")) { + (std::string&)entity["Sprite"]["DiffuseTexture"] = "Textures\\Icons\\Abilities\\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")) { + std::string t = (std::string&)cooldownTextEntity["Text"]["Content"] = std::to_string(currentAbilityCD).substr(0, 3); + } + } + } + + if (abilityName == "ShieldAbility") { + maxAbilityCD = 0.0; + currentAbilityCD = 1 - (bool)abilityEntity[abilityName]["Active"]; + } + + if (abilityName == "SprintAbility") { + maxAbilityCD = 0.0; + currentAbilityCD = 1 - (bool)abilityEntity[abilityName]["Active"]; + } + + if (entity.HasComponent("Fill")) { + entity["Fill"]["Percentage"] = currentAbilityCD/maxAbilityCD; + } + + + + } +} diff --git a/src/Game/Systems/AmmoPickupSystem.cpp b/src/Game/Systems/AmmoPickupSystem.cpp index 5927c495..ea4561c6 100644 --- a/src/Game/Systems/AmmoPickupSystem.cpp +++ b/src/Game/Systems/AmmoPickupSystem.cpp @@ -5,6 +5,7 @@ AmmoPickupSystem::AmmoPickupSystem(SystemParams params) { 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); @@ -14,77 +15,118 @@ AmmoPickupSystem::AmmoPickupSystem(SystemParams params) void AmmoPickupSystem::Update(double dt) { if (IsServer) { - for (auto it = m_ETriggerTouchVector.begin(); it != m_ETriggerTouchVector.end(); ++it) { - auto& ammoPickupPosition = *it; - //set the double timer value (value 3) - ammoPickupPosition.DecreaseThisRespawnTimer -= dt; - if (ammoPickupPosition.DecreaseThisRespawnTimer < 0.0) { - //spawn and delete the vector item + 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"); - EntityFileParser parser(entityFile); - EntityID ammoPickupID = parser.MergeEntities(m_World); + EntityWrapper ammoPickup = entityFile->MergeInto(m_World); - //let the world know a pickup has spawned (graphics effects, etc) + //let the world know a pickup has spawned Events::PickupSpawned ePickupSpawned; - ePickupSpawned.Pickup = EntityWrapper(m_World, ammoPickupID); + 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"] = ammoPickupPosition.Pos; - newAmmoPickupEntity["AmmoPickup"]["AmmoGain"] = ammoPickupPosition.AmmoGain; - newAmmoPickupEntity["AmmoPickup"]["RespawnTimer"] = ammoPickupPosition.RespawnTimer; - m_World->SetParent(newAmmoPickupEntity.ID, ammoPickupPosition.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 (AmmoPickupPosition) - m_ETriggerTouchVector.erase(it); + //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; } } } } +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) { + (int&)player["DefenderWeapon"]["Ammo"] = std::min((int)player["DefenderWeapon"]["Ammo"] + ammoGain, maxWeaponAmmo); + } else if (playerClass == PlayerClass::Sniper) { + (int&)player["SniperWeapon"]["Ammo"] = std::min((int)player["SniperWeapon"]["Ammo"] + ammoGain, maxWeaponAmmo); + } else if (playerClass == PlayerClass::Assault) { + (int&)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 != LocalPlayer) { - return false; - }*/ - 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; } - int maxWeaponAmmo = (int)e.Entity["AssaultWeapon"]["MaxAmmo"]; - int& currentAmmo = (int)e.Entity["AssaultWeapon"]["Ammo"]; - int ammoGiven = 0.01*(double)e.Trigger["AmmoPickup"]["AmmoGain"] * maxWeaponAmmo; - //cant pick up ammopacks if you are already at MaxAmmo - if (currentAmmo >= maxWeaponAmmo) { + //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; } - - //personEntered = e.Entity, thingEntered = e.Trigger - Events::AmmoPickup ePlayerAmmoPickup; - ePlayerAmmoPickup.AmmoGain = ammoGiven; - ePlayerAmmoPickup.Player = e.Entity; - 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({ e.Trigger["Transform"]["Position"], e.Trigger["AmmoPickup"]["AmmoGain"], - e.Trigger["AmmoPickup"]["RespawnTimer"], e.Trigger["AmmoPickup"]["RespawnTimer"], m_World->GetParent(e.Trigger.ID) }); - - //delete the ammopickup - m_World->DeleteEntity(e.Trigger.ID); + DoPickup(e.Entity, e.Trigger); return true; } @@ -94,16 +136,50 @@ bool AmmoPickupSystem::OnAmmoPickup(Events::AmmoPickup & e) return false; } //TODO: add other weapontypes - if (!e.Player.HasComponent("AssaultWeapon")) { + if (DetermineClass(e.Player) == PlayerClass::None) { return false; } - int maxWeaponAmmo = (int)e.Player["AssaultWeapon"]["MaxAmmo"]; - int& currentAmmo = (int)e.Player["AssaultWeapon"]["Ammo"]; //cant pick up ammopacks if you are already at MaxAmmo - if (currentAmmo >= maxWeaponAmmo) { + if (DoesPlayerHaveMaxAmmo(e.Player)) { return false; } + SetPlayerAmmo(e.Player, e.AmmoGain); - currentAmmo = std::min(currentAmmo + e.AmmoGain, maxWeaponAmmo); - return false; + 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->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) { + //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; + + Events::AmmoPickup ePlayerAmmoPickup; + ePlayerAmmoPickup.AmmoGain = ammoGiven; + ePlayerAmmoPickup.Player = player; + m_EventBroker->Publish(ePlayerAmmoPickup); + + //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({ (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); } 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..f83278ff --- /dev/null +++ b/src/Game/Systems/BoostIconsHUDSystem.cpp @@ -0,0 +1,42 @@ +#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"); + + if(assaultEntity.Valid()) { + if (assaultEntity.HasComponent("Fill")) { + EntityWrapper parentWithAssaultBoost = assaultEntity.FirstParentWithComponent("BoostAssault"); + if (parentWithAssaultBoost.Valid()) { + (double&)assaultEntity["Fill"]["Percentage"] = 1.0; + } else { + (double&)assaultEntity["Fill"]["Percentage"] = 0.0; + } + } + } + + if (defenderEntity.Valid()) { + if (defenderEntity.HasComponent("Fill")) { + EntityWrapper parentWithAssaultBoost = defenderEntity.FirstParentWithComponent("BoostDefender"); + if (parentWithAssaultBoost.Valid()) { + (double&)defenderEntity["Fill"]["Percentage"] = 1.0; + } else { + (double&)defenderEntity["Fill"]["Percentage"] = 0.0; + } + } + } + + if (sniperEntity.Valid()) { + if (sniperEntity.HasComponent("Fill")) { + EntityWrapper parentWithAssaultBoost = sniperEntity.FirstParentWithComponent("BoostSniper"); + if (parentWithAssaultBoost.Valid()) { + (double&)sniperEntity["Fill"]["Percentage"] = 1.0; + } else { + (double&)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..c3dc1f2b --- /dev/null +++ b/src/Game/Systems/BoostSystem.cpp @@ -0,0 +1,68 @@ +#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.ID == e.Inflictor.ID) { + return false; + } + + if (!e.Victim.Valid() || !LocalPlayer.Valid()) { + return false; + } + + if (e.Victim != LocalPlayer && !e.Victim.IsChildOf(LocalPlayer)) { + return false; + } + + if (!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; + } + + //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 (m_World->HasComponent(inflictorPlayer.ID, "DashAbility")) { + return "BoostAssault"; + } + if (m_World->HasComponent(inflictorPlayer.ID, "ShieldAbility")) { + return "BoostDefender"; + } + if (m_World->HasComponent(inflictorPlayer.ID, "SprintAbility")) { + return "BoostSniper"; + } + return ""; +} diff --git a/src/Game/Systems/CapturePointArrowHUDSystem.cpp b/src/Game/Systems/CapturePointArrowHUDSystem.cpp new file mode 100644 index 00000000..9e327a43 --- /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 = Transform::AbsolutePosition(capturePointEntity); + redTargets.insert(std::pair(capturePointID, targetPos)); + } + if(currentOwner != blueTeamEnum) { + //This capturePoint is not owned by the blue team and is therefor an eligible target for blue team + glm::vec3 targetPos = Transform::AbsolutePosition(capturePointEntity); + 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; + } + + glm::vec3& arrowOri = arrowEntity["Transform"]["Orientation"]; + glm::vec3 lookVector = glm::normalize(Transform::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 -= Transform::AbsoluteOrientationEuler(parent); + } + } +} + +bool CapturePointArrowHUDSystem::OnCapturePointCaptured(Events::Captured& e) +{ + if(!e.BlueTeamNextCapturePoint.Valid() || !e.RedTeamNextCapturePoint.Valid()) { + return 0; + } + + m_RedTeamCurrentTarget = Transform::AbsolutePosition(e.RedTeamNextCapturePoint); + m_BlueTeamCurrentTarget = Transform::AbsolutePosition(e.BlueTeamNextCapturePoint); + + m_InitialtargetsSet = true; + return 0; +} diff --git a/src/Game/Systems/CapturePointHUDSystem.cpp b/src/Game/Systems/CapturePointHUDSystem.cpp index 6f1392e0..b7376249 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"]; diff --git a/src/Game/Systems/CapturePointSystem.cpp b/src/Game/Systems/CapturePointSystem.cpp index f748ff09..4647d1b7 100644 --- a/src/Game/Systems/CapturePointSystem.cpp +++ b/src/Game/Systems/CapturePointSystem.cpp @@ -69,6 +69,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); @@ -102,10 +103,20 @@ void CapturePointSystem::UpdateComponent(EntityWrapper& capturePointEntity, Comp nextPossibleCapturePoint["Blue"] = i - 1; } } + if (m_RecentlyCapturedNeedNextCapturePointNow) { - m_CapturedEvent.NextCapturePoint = m_CapturedEvent.TeamNumberThatCapturedCapturePoint == blueTeam ? - m_CapturePointNumberToEntityMap[nextPossibleCapturePoint["Blue"]] : - m_CapturePointNumberToEntityMap[nextPossibleCapturePoint["Red"]]; + //change what model is displaying (change all in case 2 capturepoints has been captured on the same frame) + for (int i = 0; i < m_NumberOfCapturePoints; i++) { + auto owner = (int)m_CapturePointNumberToEntityMap[i]["Team"]["Team"]; + if (m_CapturePointNumberToEntityMap[i].FirstChildByName("Red").ID != EntityID_Invalid) { + (bool&)m_CapturePointNumberToEntityMap[i].FirstChildByName("Red")["Model"]["Visible"] = owner == redTeam ? true : false; + (bool&)m_CapturePointNumberToEntityMap[i].FirstChildByName("Blue")["Model"]["Visible"] = owner == blueTeam ? true : false; + (bool&)m_CapturePointNumberToEntityMap[i].FirstChildByName("Spectator")["Model"]["Visible"] = owner == spectatorTeam ? true : false; + } + } + //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; } diff --git a/src/Game/Systems/DamageIndicatorSystem.cpp b/src/Game/Systems/DamageIndicatorSystem.cpp index ca26052d..c4de21ff 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; @@ -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/ExplosionEffectSystem.cpp b/src/Game/Systems/ExplosionEffectSystem.cpp index 2704d2da..71de192a 100644 --- a/src/Game/Systems/ExplosionEffectSystem.cpp +++ b/src/Game/Systems/ExplosionEffectSystem.cpp @@ -2,13 +2,17 @@ void ExplosionEffectSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) { - if ((double)component["TimeSinceDeath"] > (double)component["ExplosionDuration"]) { - (double)component["TimeSinceDeath"] = 0.f; + double& delay = (double)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) { + double& timeSinceDeath = component["TimeSinceDeath"]; + timeSinceDeath += (double)component["Speed"] * dt; + if (timeSinceDeath < 0 || timeSinceDeath > (double)component["ExplosionDuration"]) { + timeSinceDeath = 0.0; + } + } } diff --git a/src/Game/Systems/HealthSystem.cpp b/src/Game/Systems/HealthSystem.cpp index 94f23c67..9fa570c2 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) { @@ -30,7 +22,21 @@ bool HealthSystem::OnPlayerDamaged(Events::PlayerDamage& e) ComponentWrapper cHealth = e.Victim["Health"]; double& health = cHealth["Health"]; - health -= e.Damage; + //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 -= (double)playerBoostDefenderEntity["BoostDefender"]["StrengthOfEffect"]; + } + if (health > 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; } diff --git a/src/Game/Systems/MainMenuSystem.cpp b/src/Game/Systems/MainMenuSystem.cpp new file mode 100644 index 00000000..848070b4 --- /dev/null +++ b/src/Game/Systems/MainMenuSystem.cpp @@ -0,0 +1,93 @@ +#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) +{ + +} + +bool MainMenuSystem::OnButtonClick(const Events::ButtonClicked& e) +{ + if (e.EntityName == "ServerIdentityConnect") { + EntityWrapper entity = e.Entity; + 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); + } + } + 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) { + auto menus = m_World->GetComponents("Menu"); + if (menus == nullptr) { + return 0; + } + + if (m_OpenSubMenu == EntityWrapper::Invalid) { + //No submenu is open, open one. + for (auto& menu : *menus) { + EntityWrapper menuEntity = EntityWrapper(m_World, menu.EntityID); + auto serverListSpawner = menuEntity.FirstChildByName(e.Command + "Spawner"); + if (!serverListSpawner.HasComponent("Spawner")) { + return 0; + } + m_OpenSubMenu = SpawnerSystem::Spawn(serverListSpawner, serverListSpawner); + Events::SearchForServers event; + m_EventBroker->Publish(event); + break; + } + + } else if(!m_OpenSubMenu.HasComponent("ServerList")) { + //Menu is open, but not the right one, delete the old one and open a new one. + m_World->DeleteEntity(m_OpenSubMenu.ID); + m_OpenSubMenu = EntityWrapper::Invalid; + + for (auto& menu : *menus) { + EntityWrapper menuEntity = EntityWrapper(m_World, menu.EntityID); + auto serverListSpawner = menuEntity.FirstChildByName(e.Command + "Spawner"); + if (!serverListSpawner.HasComponent("Spawner")) { + return 0; + } + m_OpenSubMenu = SpawnerSystem::Spawn(serverListSpawner, serverListSpawner); + Events::SearchForServers event; + m_EventBroker->Publish(event); + break; + } + } else { + //Serverlist submenu is open, close it. + m_World->DeleteEntity(m_OpenSubMenu.ID); + m_OpenSubMenu = EntityWrapper::Invalid; + } + } else if (e.Command == "RefreshServerList" && e.Value == 1){ + Events::SearchForServers event; + m_EventBroker->Publish(event); + } + return true; +} \ No newline at end of file diff --git a/src/Game/Systems/PickupSpawnSystem.cpp b/src/Game/Systems/PickupSpawnSystem.cpp index 94fee4c6..b0efd696 100644 --- a/src/Game/Systems/PickupSpawnSystem.cpp +++ b/src/Game/Systems/PickupSpawnSystem.cpp @@ -5,66 +5,101 @@ PickupSpawnSystem::PickupSpawnSystem(SystemParams params) { if (IsServer) { EVENT_SUBSCRIBE_MEMBER(m_ETriggerTouch, &PickupSpawnSystem::OnTriggerTouch); + EVENT_SUBSCRIBE_MEMBER(m_ETriggerLeave, &PickupSpawnSystem::OnTriggerLeave); } } void PickupSpawnSystem::Update(double dt) { if (IsServer) { - for (auto it = m_ETriggerTouchVector.begin(); it != m_ETriggerTouchVector.end(); ++it) { - auto& healthPickupPosition = *it; - //set the double timer value (value 3) - healthPickupPosition.DecreaseThisRespawnTimer -= dt; - if (healthPickupPosition.DecreaseThisRespawnTimer < 0) { - //spawn and delete the vector item + 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"); - EntityFileParser parser(entityFile); - EntityID healthPickupID = parser.MergeEntities(m_World); + EntityWrapper healthPickup = entityFile->MergeInto(m_World); //let the world know a pickup has spawned (graphics effects, etc) Events::PickupSpawned ePickupSpawned; - ePickupSpawned.Pickup = EntityWrapper(m_World, healthPickupID); + ePickupSpawned.Pickup = healthPickup; m_EventBroker->Publish(ePickupSpawned); - //set values from the old entity to the new entity - auto& newHealthPickupEntity = EntityWrapper(m_World, healthPickupID); - newHealthPickupEntity["Transform"]["Position"] = healthPickupPosition.Pos; - newHealthPickupEntity["HealthPickup"]["HealthGain"] = healthPickupPosition.HealthGain; - newHealthPickupEntity["HealthPickup"]["RespawnTimer"] = healthPickupPosition.RespawnTimer; - m_World->SetParent(newHealthPickupEntity.ID, healthPickupPosition.parentID); + //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 (healthPickupPosition) - m_ETriggerTouchVector.erase(it); + //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 ((double)it->player["Health"]["Health"] < (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; } - double healthGiven = 0.01*(double)e.Trigger["HealthPickup"]["HealthGain"] * (double)e.Entity["Health"]["MaxHealth"]; - //cant pick up healthpacks if you are already at MaxHealth + //if at maxhealth, save the trigger-touch to a vector since standing inside it will not re-trigger the trigger if ((double)e.Entity["Health"]["Health"] >= (double)e.Entity["Health"]["MaxHealth"]) { + m_PickupAtMaximum.push_back({ e.Entity, e.Trigger }); return false; } - //personEntered = e.Entity, thingEntered = e.Trigger + 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*(double)trigger["HealthPickup"]["HealthGain"] * (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 = e.Entity; + 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)e.Trigger["Transform"]["Position"], e.Trigger["HealthPickup"]["HealthGain"], - e.Trigger["HealthPickup"]["RespawnTimer"], e.Trigger["HealthPickup"]["RespawnTimer"], m_World->GetParent(e.Trigger.ID) }); + 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(e.Trigger.ID); - return true; + m_World->DeleteEntity(trigger.ID); } diff --git a/src/Game/Systems/PlayerDeathSystem.cpp b/src/Game/Systems/PlayerDeathSystem.cpp index 844d2ed1..9f2900fa 100644 --- a/src/Game/Systems/PlayerDeathSystem.cpp +++ b/src/Game/Systems/PlayerDeathSystem.cpp @@ -1,9 +1,12 @@ #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) @@ -27,17 +30,15 @@ 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()) { - return; - } if (!playerModel.HasComponent("Model") || !playerModel.HasComponent("Animation")) { + if (player == LocalPlayer) { + setSpectatorCamera(); + } return; } auto playerEntityModel = playerModel["Model"]; @@ -46,10 +47,6 @@ void PlayerDeathSystem::createDeathEffect(EntityWrapper player) //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"]; @@ -59,9 +56,49 @@ void PlayerDeathSystem::createDeathEffect(EntityWrapper player) //camera (with lifetime) behind the player if (player == LocalPlayer) { + m_LocalPlayerDeathEffect = deathEffectEW; auto cam = deathEffectEW.FirstChildByName("Camera"); 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.ID != 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 47612ca0..cfe7356c 100644 --- a/src/Game/Systems/PlayerMovementSystem.cpp +++ b/src/Game/Systems/PlayerMovementSystem.cpp @@ -2,9 +2,11 @@ PlayerMovementSystem::PlayerMovementSystem(SystemParams params) : System(params) + , m_SprintEffectTimer(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 +19,49 @@ 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; + const ComponentPool* 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"]; + ((glm::vec4&)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"]; + } + } } } @@ -44,13 +81,18 @@ void PlayerMovementSystem::updateMovementControllers(double dt) 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()); + // Set third person model aim pitch EntityWrapper playerModel = player.FirstChildByName("PlayerModel"); if (playerModel.Valid()) { - ComponentWrapper cAnimationOffset = playerModel["AnimationOffset"]; - float pitch = cameraOrientation.x + 0.2f; - double time = (pitch + glm::half_pi()) / glm::pi(); - cAnimationOffset["Time"] = time; + EntityWrapper aimPrimaryEntity = playerModel.FirstChildByName("Aim"); + if(aimPrimaryEntity.Valid()){ + if(aimPrimaryEntity.HasComponent("Animation")) { + float pitch = cameraOrientation.x; + double time = ((pitch + glm::half_pi()) / glm::pi()); + (double&)aimPrimaryEntity["Animation"]["Time"] = time; + } + } } } @@ -61,12 +103,26 @@ void PlayerMovementSystem::updateMovementControllers(double dt) float playerMovementSpeed = player["Player"]["MovementSpeed"]; float playerCrouchSpeed = player["Player"]["CrouchSpeed"]; glm::vec3& 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"], player["DashAbility"]["CoolDownTimer"]); + controller->AssaultDashCheck(dt, ((glm::vec3)cPhysics["Velocity"]).y != 0.0f, player["DashAbility"]["CoolDownMaxTimer"], player["DashAbility"]["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 @@ -112,6 +168,13 @@ void PlayerMovementSystem::updateMovementControllers(double dt) //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); + //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 * wishDirection; ImGui::Text("velocity: (%f, %f, %f) |%f|", velocity.x, velocity.y, velocity.z, glm::length(velocity)); } @@ -124,10 +187,64 @@ void PlayerMovementSystem::updateMovementControllers(double dt) if (isOnGround) { (bool)cPhysics["IsOnGround"] = false; 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"]; + + 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 @@ -150,81 +267,7 @@ void PlayerMovementSystem::updateMovementControllers(double dt) } } - // 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"; - } - } - } + // TODO: Animations } controller->Reset(); @@ -292,7 +335,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,11 +346,11 @@ 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)); @@ -315,11 +358,145 @@ bool PlayerMovementSystem::OnDoubleJump(Events::DoubleJump & e) } 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 player(m_World, e.Player); + if (!player.Valid()){// || !IsClient || player.ID == LocalPlayer.ID) { + return false; + } + +// auto entityFile = ResourceManager::Load("Schema/Entities/DashEffect.xml"); + // EntityWrapper dashEffect = entityFile->MergeInto(m_World); + EntityWrapper playerModel = player.FirstChildByName("PlayerModel"); + + for (auto& kv : m_PlayerInputControllers) { + EntityWrapper player = kv.first; + 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"]; + ((glm::vec4&)dashEffectModel["ExplosionEffect"]["EndColor"]).w = 0.f; + (double&)dashEffectModel["ExplosionEffect"]["ExplosionDuration"] = dashEffect["Lifetime"]["Lifetime"]; + (glm::vec3&)dashEffectModel["ExplosionEffect"]["ExplosionOrigin"] = glm::vec3(0, 1, 0) + (0.2f * controller->Movement()); + + + + + auto animationChildren = dashEffectModel.ChildrenWithComponent("Animation"); + + for (auto animationEntity : animationChildren) { + (bool&)animationEntity["Animation"]["Play"] = false; + } + */ + } + + } + } + return true; +} diff --git a/src/Game/Systems/PlayerSpawnSystem.cpp b/src/Game/Systems/PlayerSpawnSystem.cpp index e03a1778..03e3adb4 100644 --- a/src/Game/Systems/PlayerSpawnSystem.cpp +++ b/src/Game/Systems/PlayerSpawnSystem.cpp @@ -1,4 +1,5 @@ #include "Systems/PlayerSpawnSystem.h" +#include "Core/ELockMouse.h" PlayerSpawnSystem::PlayerSpawnSystem(SystemParams params) : System(params) @@ -10,7 +11,7 @@ PlayerSpawnSystem::PlayerSpawnSystem(SystemParams params) 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; + m_DbgConfigForceRespawn = m_ForcedRespawnTime > 0 && IsServer; } void PlayerSpawnSystem::Update(double dt) @@ -26,7 +27,21 @@ void PlayerSpawnSystem::Update(double dt) // Increase timer. double& timer = (double&)modeComponent["RespawnTime"]; timer += dt; - double maxRespawnTime = m_DbgConfigForceRespawn ? m_ForcedRespawnTime : (double)modeComponent["MaxRespawnTime"]; + if (m_DbgConfigForceRespawn) { + (double&)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; } @@ -45,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")) { @@ -54,37 +77,54 @@ 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) { + 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; + } continue; } } + // TODO: Choose a different spawner depending on class picked? + // Spawn the player! EntityWrapper player = SpawnerSystem::Spawn(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; } @@ -94,34 +134,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; @@ -156,18 +204,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; @@ -175,7 +213,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; } @@ -183,10 +221,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; @@ -195,6 +229,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..94674432 --- /dev/null +++ b/src/Game/Systems/ScoreScreenSystem.cpp @@ -0,0 +1,158 @@ +#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); +} + +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); + (int&)entity["ScoreScreen"]["TotalIdentities"] -= 1; + break; + } + for (auto it2 = m_DisconnectedIdentities.begin(); it2 != m_DisconnectedIdentities.end(); ++it2) { + if (ID == *it2) { + m_World->DeleteEntity(child.ID); + (int&)entity["ScoreScreen"]["TotalIdentities"] -= 1; + 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 + (int&)child["ScoreIdentity"]["Kills"] = it->second.Kills; + //Update Kills for child + (int&)child["ScoreIdentity"]["Deaths"] = it->second.Deaths; + //KD is not updated at the moment. + if (it->second.Deaths != 0) { + (double&)child["ScoreIdentity"]["KD"] = it->second.Kills/it->second.Deaths; + } + + //Update position for child + glm::vec3 offset = (glm::vec3)entity["ScoreScreen"]["Offset"]; + (glm::vec3&) 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"]; + (glm::vec3&) scoreIdentity["Transform"]["Position"] = offset * (float)newPosition; + auto cScoreIdentity = scoreIdentity["ScoreIdentity"]; + auto data = it->second; + + (std::string&)cScoreIdentity["Name"] = data.Name; + (int&)cScoreIdentity["ID"] = data.ID; + + m_World->SetParent(scoreIdentity.ID, entity.ID); + + (int&)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; +} diff --git a/src/Game/Systems/ServerListSystem.cpp b/src/Game/Systems/ServerListSystem.cpp new file mode 100644 index 00000000..ad575e3f --- /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(); + + (int&)cServerList["TotalIdentities"] = (int)e.Serverlist.size(); + for (int i = 0; i < e.Serverlist.size(); i++) { + //Create Identities for each server and place them on the right position. + EntityWrapper newIdentity = SpawnerSystem::Spawn(identitySpawner, identitySpawner); + EntityWrapper serverIdentityEntity = newIdentity.FirstChildByName("ServerIdentity"); + + glm::vec3 offset = (glm::vec3)serverListEntity["ServerList"]["Offset"]; + (glm::vec3&)serverIdentityEntity["Transform"]["Position"] = offset * (float)i; + + auto& cIdentity = serverIdentityEntity["ServerIdentity"]; + (std::string&)cIdentity["IP"] = e.Serverlist[i].Address; + (std::string&)cIdentity["ServerName"] = e.Serverlist[i].Name; + (int&)cIdentity["Port"] = e.Serverlist[i].Port; + (int&)cIdentity["PlayersConnected"] = e.Serverlist[i].PlayersConnected; + } + } + return 1; +} diff --git a/src/Game/Systems/SpawnerSystem.cpp b/src/Game/Systems/SpawnerSystem.cpp index 6500460f..282c958b 100644 --- a/src/Game/Systems/SpawnerSystem.cpp +++ b/src/Game/Systems/SpawnerSystem.cpp @@ -17,15 +17,17 @@ EntityWrapper SpawnerSystem::Spawn(EntityWrapper spawner, EntityWrapper parent / // 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); diff --git a/src/Game/Systems/SpectatorCameraSystem.cpp b/src/Game/Systems/SpectatorCameraSystem.cpp new file mode 100644 index 00000000..d1f2f1ce --- /dev/null +++ b/src/Game/Systems/SpectatorCameraSystem.cpp @@ -0,0 +1,90 @@ +#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); +} + +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); + } + } +} + +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) { + camName = "PickClassCamera"; + } 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; +} \ No newline at end of file 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..71218ef8 --- /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); + + std::string& 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..8c92b35b --- /dev/null +++ b/src/Game/Systems/Weapon/AssaultWeaponBehaviour.cpp @@ -0,0 +1,323 @@ +#include "Systems/Weapon/AssaultWeaponBehaviour.h" + +void AssaultWeaponBehaviour::UpdateComponent(EntityWrapper& entity, ComponentWrapper& cWeapon, double dt) +{ + double& fireCooldown = cWeapon["FireCooldown"]; + fireCooldown = glm::max(0.0, fireCooldown - dt); + + WeaponBehaviour::UpdateComponent(entity, cWeapon, dt); +} + +void AssaultWeaponBehaviour::UpdateWeapon(ComponentWrapper cWeapon, WeaponInfo& wi, double dt) +{ + // Start reloading automatically if at 0 mag ammo + int& magAmmo = cWeapon["MagazineAmmo"]; + if (m_ConfigAutoReload && magAmmo <= 0) { + OnReload(cWeapon, wi); + } + + // Only start reloading once we're done firing + bool& reloadQueued = cWeapon["ReloadQueued"]; + double& fireCooldown = cWeapon["FireCooldown"]; + bool& isReloading = cWeapon["IsReloading"]; + if (reloadQueued && fireCooldown <= 0) { + reloadQueued = fireCooldown; + isReloading = true; + } + + // Decrement reload timer + double& reloadTimer = cWeapon["ReloadTimer"]; + if (isReloading) { + reloadTimer = glm::max(0.0, reloadTimer - dt); + } + + // Handle reloading + if (isReloading && reloadTimer <= 0.0) { + int& magSize = cWeapon["MagazineSize"]; + int& ammo = cWeapon["Ammo"]; + + ammo = glm::max(0, ammo - (magSize - magAmmo)); + magAmmo = glm::min(magSize, ammo); + 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) { + float& currentTravel = cWeapon["CurrentTravel"]; + float& returnSpeed = cWeapon["ViewReturnSpeed"]; + if (currentTravel > 0) { + float change = returnSpeed * dt; + currentTravel = glm::max(0.f, currentTravel - change); + EntityWrapper camera = wi.Player.FirstChildByName("Camera"); + if (camera.Valid()) { + glm::vec3& cameraOrientation = camera["Transform"]["Orientation"]; + cameraOrientation.x -= change; + } + } + } + + // 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("MovementBlend"); + if (blend.Valid()) { + (double&)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) +{ + bool& reloadQueued = cWeapon["ReloadQueued"]; + bool& isReloading = cWeapon["IsReloading"]; + if (reloadQueued || isReloading) { + return; + } + + int& magAmmo = cWeapon["MagazineAmmo"]; + int& magSize = cWeapon["MagazineSize"]; + if (magAmmo >= magSize) { + return; + } + int& ammo = cWeapon["Ammo"]; + if (ammo <= 0) { + return; + } + + double reloadTime = cWeapon["ReloadTime"]; + double& reloadTimer = cWeapon["ReloadTimer"]; + + // Start reload + 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.EmitterID = wi.Player.ID; + e.FilePath = "Audio/weapon/Assault/AssaultWeaponReload.wav"; + m_EventBroker->Publish(e); +} + +void AssaultWeaponBehaviour::OnEquip(ComponentWrapper cWeapon, WeaponInfo& wi) +{ + cWeapon["FireCooldown"] = (double)cWeapon["EquipTime"]; +} + +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 + int& magAmmo = cWeapon["MagazineAmmo"]; + if (magAmmo <= 0) { + return; + } else { + magAmmo -= 1; + } + + // View punch + if (IsClient) { + EntityWrapper camera = wi.Player.FirstChildByName("Camera"); + if (camera.Valid()) { + glm::vec3& cameraOrientation = camera["Transform"]["Orientation"]; + float viewPunch = cWeapon["ViewPunch"]; + float maxTravelAngle = cWeapon["MaxTravelAngle"]; + float& currentTravel = cWeapon["CurrentTravel"]; + if (currentTravel < maxTravelAngle) { + float change = viewPunch; + if (currentTravel + change > maxTravelAngle) { + change = maxTravelAngle - currentTravel; + } + 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("WeaponMuzzle"); + if (tracerSpawner.Valid()) { + glm::vec3 origin = Transform::AbsolutePosition(tracerSpawner); + glm::vec3 direction = glm::quat(Transform::AbsoluteOrientationEuler(tracerSpawner)) * glm::vec3(0, 0, -1); + float distance = traceRayDistance(origin, direction); + EntityWrapper ray = SpawnerSystem::Spawn(tracerSpawner); + if (ray.Valid()) { + ((glm::vec3&)ray["Transform"]["Scale"]).z = distance; + } + } + + // 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.EmitterID = wi.Player.ID; + e.FilePath = "Audio/weapon/hitclick.wav"; + m_EventBroker->Publish(e); + } + } + + // 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.EmitterID = wi.Player.ID; + 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; +} 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..835b5378 100644 --- a/src/Game/Systems/Weapon/DefenderWeaponBehaviour.cpp +++ b/src/Game/Systems/Weapon/DefenderWeaponBehaviour.cpp @@ -2,48 +2,171 @@ void DefenderWeaponBehaviour::UpdateComponent(EntityWrapper& entity, ComponentWrapper& cWeapon, double dt) { - (double&)cWeapon["TimeSinceLastFire"] += dt; + double& fireCooldown = cWeapon["FireCooldown"]; + fireCooldown = glm::max(0.0, fireCooldown - dt); + WeaponBehaviour::UpdateComponent(entity, cWeapon, dt); } -void DefenderWeaponBehaviour::UpdateWeapon(WeaponInfo& wi, double dt) +void DefenderWeaponBehaviour::UpdateWeapon(ComponentWrapper cWeapon, WeaponInfo& wi, double dt) { - ComponentWrapper cWeapon = wi.GetComponent(); + // Decrement reload timer + double& 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 + int& magAmmo = cWeapon["MagazineAmmo"]; + if (m_ConfigAutoReload && magAmmo <= 0) { + OnReload(cWeapon, wi); + } + + // Handle reloading + bool& isReloading = cWeapon["IsReloading"]; + if (isReloading && reloadTimer <= 0.0) { + double reloadTime = cWeapon["ReloadTime"]; + int& magSize = cWeapon["MagazineSize"]; + int& ammo = cWeapon["Ammo"]; + if (magAmmo < magSize && ammo > 0) { + ammo -= 1; + magAmmo += 1; + reloadTimer = reloadTime; + Events::PlaySoundOnEntity e; + e.EmitterID = wi.Player.ID; + e.FilePath = "Audio/weapon/Zoom.wav"; + m_EventBroker->Publish(e); + } else { + isReloading = false; + playAnimationAndReturn(wi.FirstPersonEntity, "FinalBlend", "ReloadEnd"); + } + } + + // Restore view angle + if (IsClient) { + float& currentTravel = cWeapon["CurrentTravel"]; + float& returnSpeed = cWeapon["ViewReturnSpeed"]; + if (currentTravel > 0) { + float change = returnSpeed * dt; + currentTravel = glm::max(0.f, currentTravel - change); + EntityWrapper camera = wi.Player.FirstChildByName("Camera"); + if (camera.Valid()) { + glm::vec3& cameraOrientation = camera["Transform"]["Orientation"]; + cameraOrientation.x -= change; + } + } + } + + // 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) { + bool& isReloading = cWeapon["IsReloading"]; + if (isReloading) { + return; + } + + int& magAmmo = cWeapon["MagazineAmmo"]; + int& magSize = cWeapon["MagazineSize"]; + if (magAmmo >= magSize) { + return; + } + int& ammo = cWeapon["Ammo"]; + if (ammo <= 0) { + return; + } + + double reloadTime = cWeapon["ReloadTime"]; + double& reloadTimer = cWeapon["ReloadTimer"]; + + // Start reload + isReloading = true; + reloadTimer = reloadTime; + + // 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); + } +} + +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 (IsServer) { + SpawnerSystem::Spawn(attachment, attachment); + } + + if (IsClient) { + EntityWrapper root = wi.FirstPersonEntity; + if (root.Valid()) { + EntityWrapper animationNode = root.FirstChildByName("Shield"); + if (animationNode.Valid()) { + Events::AutoAnimationBlend eFireBlend; + eFireBlend.RootNode = root; + eFireBlend.NodeName = "Shield"; + eFireBlend.Restart = true; + eFireBlend.Start = true; + m_EventBroker->Publish(eFireBlend); + } + } + } } else { attachment.DeleteChildren(); + + 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); + } + } + } } } } @@ -51,17 +174,22 @@ bool DefenderWeaponBehaviour::OnInputCommand(WeaponInfo& wi, const Events::Input return false; } -bool DefenderWeaponBehaviour::OnSetCamera(const Events::SetCamera& e) +void DefenderWeaponBehaviour::fireShell(ComponentWrapper cWeapon, WeaponInfo& wi) { - m_CurrentCamera = e.CameraEntity; - return true; -} + cWeapon["FireCooldown"] = 60.0 / (double)cWeapon["RPM"]; -void DefenderWeaponBehaviour::fireShell(WeaponInfo& wi) -{ - ComponentWrapper cWeapon = wi.GetComponent(); + // Stop reloading + bool& isReloading = cWeapon["IsReloading"]; + isReloading = false; + + // Ammo + int& magAmmo = cWeapon["MagazineAmmo"]; + if (magAmmo <= 0) { + return; + } else { + magAmmo -= 1; + } - cWeapon["TimeSinceLastFire"] = 0.0; int numPellets = cWeapon["NumPellets"]; float spreadAngle = cWeapon["SpreadAngle"]; std::uniform_real_distribution randomSpreadAngle(-spreadAngle, spreadAngle); @@ -72,11 +200,29 @@ void DefenderWeaponBehaviour::fireShell(WeaponInfo& wi) 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; + // View punch + if (IsClient) { + EntityWrapper camera = wi.Player.FirstChildByName("Camera"); + if (camera.Valid()) { + glm::vec3& cameraOrientation = camera["Transform"]["Orientation"]; + float viewPunch = cWeapon["ViewPunch"]; + float maxTravelAngle = cWeapon["MaxTravelAngle"]; + float& currentTravel = cWeapon["CurrentTravel"]; + if (currentTravel < maxTravelAngle) { + float change = viewPunch; + if (currentTravel + change > maxTravelAngle) { + change = maxTravelAngle - currentTravel; + } + cameraOrientation.x += change; + currentTravel += change; + } + } + } + // Tracers EntityWrapper weaponModelEntity; if (wi.Player == LocalPlayer) { @@ -95,13 +241,21 @@ void DefenderWeaponBehaviour::fireShell(WeaponInfo& wi) orientation.x += angles.x; orientation.y += angles.y; glm::vec3 trajectory = direction * distance; - dealDamage(wi, direction, pelletDamage); + dealDamage(cWeapon, wi, direction, pelletDamage); } } + // Play animation + playAnimationAndReturn(wi.FirstPersonEntity, "FinalBlend", "Fire"); + + // Sound + Events::PlaySoundOnEntity e; + e.EmitterID = wi.Player.ID; + e.FilePath = "Audio/weapon/Blast.wav"; + m_EventBroker->Publish(e); } -void DefenderWeaponBehaviour::dealDamage(WeaponInfo& wi, glm::vec3 direction, double damage) +void DefenderWeaponBehaviour::dealDamage(ComponentWrapper cWeapon, WeaponInfo& wi, glm::vec3 direction, double damage) { // Only deal damage client side if (!IsClient) { @@ -160,16 +314,12 @@ void DefenderWeaponBehaviour::dealDamage(WeaponInfo& wi, glm::vec3 direction, do 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) diff --git a/src/Game/Systems/Weapon/SidearmWeaponBehaviour.cpp b/src/Game/Systems/Weapon/SidearmWeaponBehaviour.cpp new file mode 100644 index 00000000..cba3d5e8 --- /dev/null +++ b/src/Game/Systems/Weapon/SidearmWeaponBehaviour.cpp @@ -0,0 +1,77 @@ +#include "Systems/Weapon/SidearmWeaponBehaviour.h" + +void SidearmWeaponBehaviour::UpdateComponent(EntityWrapper& entity, ComponentWrapper& cWeapon, double dt) +{ + double& 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) +{ + 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::OnEquip(ComponentWrapper cWeapon, WeaponInfo& wi) +{ + cWeapon["FireCooldown"] = (double)cWeapon["EquipTime"]; +} + +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"]; + + // Get weapon model based on current person + EntityWrapper weaponModelEntity = getRelevantWeaponEntity(wi); + if (!weaponModelEntity.Valid()) { + return; + } + + // Tracer + EntityWrapper tracerSpawner = weaponModelEntity.FirstChildByName("WeaponMuzzle"); + if (tracerSpawner.Valid()) { + glm::vec3 origin = Transform::AbsolutePosition(tracerSpawner); + glm::vec3 direction = Transform::AbsoluteOrientation(tracerSpawner) * glm::vec3(0, 0, -1); + float distance = traceRayDistance(origin, direction); + EntityWrapper ray = SpawnerSystem::Spawn(tracerSpawner); + ((glm::vec3&)ray["Transform"]["Scale"]).z = (distance / 100.f); + } +} + +bool SidearmWeaponBehaviour::canFire(ComponentWrapper cWeapon) +{ + bool triggerHeld = cWeapon["TriggerHeld"]; + double& cooldown = cWeapon["FireCooldown"]; + // TODO: Ammo checks + return triggerHeld && cooldown <= 0.0; +} \ No newline at end of file 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/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/PickupSpawnTest.cpp b/src/Tests/PickupSpawnTest.cpp index 4acd897e..0af72883 100644 --- a/src/Tests/PickupSpawnTest.cpp +++ b/src/Tests/PickupSpawnTest.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/PickupSpawnTest.h b/src/Tests/PickupSpawnTest.h index b9d5483a..372b07cd 100644 --- a/src/Tests/PickupSpawnTest.h +++ b/src/Tests/PickupSpawnTest.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/PickupSpawnSystem.h"