Index: binaries/data/config/default.cfg =================================================================== --- binaries/data/config/default.cfg +++ binaries/data/config/default.cfg @@ -61,6 +61,8 @@ ; if false, actors won't be rendered but anything entity will be. renderactors = true +maxragdolls = -1 ; When enabled, limits the number of corpses to the number specified. + watereffects=true ; When disabled, force usage of the fixed pipeline water. This is faster, but really, really ugly. waterfancyeffects = false waterrealdepth = true Index: binaries/data/mods/public/gui/options/options.json =================================================================== --- binaries/data/mods/public/gui/options/options.json +++ binaries/data/mods/public/gui/options/options.json @@ -592,6 +592,14 @@ "tooltip": "Units and Structures can be part of multiple control groups. This is useful to keep control groups for distinct armies and a control group for the entire army simultaneously." } ] + }, + { + "type": "number", + "label": "Number of ragdolls", + "tooltip": "To save CPU workload, limits the number of corpses to display -1 is unlimited.", + "config": "maxragdolls", + "min": -1, + "max": 200 } ] } Index: binaries/data/mods/public/simulation/components/Health.js =================================================================== --- binaries/data/mods/public/simulation/components/Health.js +++ binaries/data/mods/public/simulation/components/Health.js @@ -323,7 +323,11 @@ if (resource) entCorpse = Engine.AddEntity("resource|" + templateName); else + { entCorpse = Engine.AddLocalEntity("corpse|" + templateName); + if(entCorpse == INVALID_ENTITY) + return; + } // Copy various parameters so it looks just like us. let cmpPositionCorpse = Engine.QueryInterface(entCorpse, IID_Position); Index: source/renderer/RenderingOptions.h =================================================================== --- source/renderer/RenderingOptions.h +++ source/renderer/RenderingOptions.h @@ -99,7 +99,7 @@ OPTION(PostProc, bool); OPTION(DisplayFrustum, bool); OPTION(DisplayShadowsFrustum, bool); - + OPTION(MaxRagDolls, int); OPTION(RenderActors, bool); #undef OPTION_DEFAULT_SETTER Index: source/renderer/RenderingOptions.cpp =================================================================== --- source/renderer/RenderingOptions.cpp +++ source/renderer/RenderingOptions.cpp @@ -110,7 +110,7 @@ CFG_GET_VAL("forcealphatest", m_ForceAlphaTest); CFG_GET_VAL("gpuskinning", m_GPUSkinning); - + CFG_GET_VAL("maxragdolls", m_MaxRagDolls); CFG_GET_VAL("renderactors", m_RenderActors); } Index: source/simulation2/Simulation2.cpp =================================================================== --- source/simulation2/Simulation2.cpp +++ source/simulation2/Simulation2.cpp @@ -43,6 +43,7 @@ #include "ps/Pyrogenesis.h" #include "ps/Util.h" #include "ps/XML/Xeromyces.h" +#include "renderer/RenderingOptions.h" #include @@ -687,7 +688,21 @@ entity_id_t CSimulation2::AddLocalEntity(const std::wstring& templateName) { - return m->m_ComponentManager.AddEntity(templateName, m->m_ComponentManager.AllocateNewLocalEntity()); + entity_id_t newEnt = INVALID_ENTITY; + bool isCorpse = templateName.find(L"corpse|") != std::string::npos; + if (isCorpse) + { + int maxCorpses = g_RenderingOptions.GetMaxRagDolls(); + if (maxCorpses != -1 && CComponentManager::m_Corpses.size() >= static_cast(maxCorpses)) + return newEnt; + + newEnt = m->m_ComponentManager.AllocateNewLocalEntity(); + CComponentManager::m_Corpses.push_back(newEnt); + } + else + newEnt = m->m_ComponentManager.AllocateNewLocalEntity(); + + return m->m_ComponentManager.AddEntity(templateName, newEnt); } void CSimulation2::DestroyEntity(entity_id_t ent) Index: source/simulation2/system/ComponentManager.h =================================================================== --- source/simulation2/system/ComponentManager.h +++ source/simulation2/system/ComponentManager.h @@ -80,6 +80,8 @@ void LoadComponentTypes(); + static std::vector m_Corpses; + /** * Load a script and execute it in a new function scope. * @param filename VFS path to load Index: source/simulation2/system/ComponentManager.cpp =================================================================== --- source/simulation2/system/ComponentManager.cpp +++ source/simulation2/system/ComponentManager.cpp @@ -24,6 +24,7 @@ #include "ps/Filesystem.h" #include "ps/Profile.h" #include "ps/scripting/JSInterface_VFS.h" +#include "renderer/RenderingOptions.h" #include "simulation2/components/ICmpTemplateManager.h" #include "simulation2/MessageTypes.h" #include "simulation2/system/DynamicSubscription.h" @@ -466,6 +467,8 @@ return (int)ent; } +std::vector CComponentManager::m_Corpses = std::vector(); + int CComponentManager::Script_AddLocalEntity(ScriptInterface::CxPrivate* pCxPrivate, const std::string& templateName) { CComponentManager* componentManager = static_cast (pCxPrivate->pCBData); @@ -473,9 +476,22 @@ std::wstring name(templateName.begin(), templateName.end()); // TODO: should validate the string to make sure it doesn't contain scary characters // that will let it access non-component-template files + entity_id_t newEnt = INVALID_ENTITY; + bool isCorpse = templateName.find("corpse|") != std::string::npos; + if (isCorpse) + { + int maxCorpses = g_RenderingOptions.GetMaxRagDolls(); + if (maxCorpses != -1 && m_Corpses.size() >= static_cast(maxCorpses)) + return newEnt; - entity_id_t ent = componentManager->AddEntity(name, componentManager->AllocateNewLocalEntity()); - return (int)ent; + newEnt = componentManager->AllocateNewLocalEntity(); + m_Corpses.push_back(newEnt); + } + else + newEnt = componentManager->AllocateNewLocalEntity(); + + + return static_cast(componentManager->AddEntity(name, newEnt)); } void CComponentManager::Script_DestroyEntity(ScriptInterface::CxPrivate* pCxPrivate, int ent) @@ -894,6 +910,10 @@ void CComponentManager::DestroyComponentsSoon(entity_id_t ent) { + std::vector< entity_id_t>::iterator it = std::find(m_Corpses.begin(), m_Corpses.end(), static_cast (ent)); + if (it != m_Corpses.end()) + m_Corpses.erase(it); + m_DestructionQueue.push_back(ent); }