diff --git a/code/cgame/cg_commands.cpp b/code/cgame/cg_commands.cpp index 205ac529..de8636c0 100644 --- a/code/cgame/cg_commands.cpp +++ b/code/cgame/cg_commands.cpp @@ -2706,8 +2706,7 @@ void ClientGameCommandManager::DeleteEmitters(dtiki_t *tiki) for (i = m_emitters.NumObjects(); i > 0; i--) { spawnthing = m_emitters.ObjectAt(i); if (spawnthing->cgd.tiki == tiki) { - m_emitters.RemoveObjectAt(i); - delete spawnthing; + FreeSpawnthing(spawnthing); } } } @@ -4538,28 +4537,6 @@ bool ClientGameCommandManager::GetTagPositionAndOrientation(str tagname, orienta return ClientGameCommandManager::GetTagPositionAndOrientation(tagnum, new_or); } -//=============== -// FreeAllTempModels -//=============== -void ClientGameCommandManager::FreeAllTempModels(void) -{ - ctempmodel_t *p, *next; - - // Go through all the temp models and run the physics if necessary, - // then add them to the ref - p = m_active_tempmodels.prev; - for (; p != &m_active_tempmodels; p = next) { - // grab next now, so if the local entity is freed we still have it - next = p->prev; - FreeTempModel(p); - } -} - -void ClientGameCommandManager::FreeSomeTempModels(void) -{ - // FIXME: unimplemented -} - //=============== // FreeAllEmitters //=============== @@ -4576,6 +4553,9 @@ void CG_RestartCommandManager() commandManager.FreeAllTempModels(); } +//================= +// CG_CleanUpTempModels +//================= void CG_CleanUpTempModels() { commandManager.FreeSomeTempModels(); diff --git a/code/cgame/cg_commands.h b/code/cgame/cg_commands.h index 24f16a72..7c9a9a60 100644 --- a/code/cgame/cg_commands.h +++ b/code/cgame/cg_commands.h @@ -952,6 +952,7 @@ public: void InitializeEmitters(void); void RemoveClientEntity(int number, dtiki_t *tiki, centity_t *cent, ctempmodel_t *p = NULL); void ClearSwipes(void); + void FreeSpawnthing(spawnthing_t* sp); void ResetTempModels(void); void SpawnTempModel(int count, spawnthing_t *sp); diff --git a/code/cgame/cg_local.h b/code/cgame/cg_local.h index 3e9b5b70..273e22b7 100644 --- a/code/cgame/cg_local.h +++ b/code/cgame/cg_local.h @@ -533,6 +533,8 @@ extern "C" { // cg_tempmodels.cpp // extern cvar_t *cg_showtempmodels; + extern cvar_t *cg_max_tempmodels; + extern cvar_t *cg_reserve_tempmodels; extern cvar_t *cg_detail; extern cvar_t *cg_effectdetail; extern cvar_t *cg_effect_physicsrate; diff --git a/code/cgame/cg_tempmodels.cpp b/code/cgame/cg_tempmodels.cpp index 4fac5ac2..4f9add91 100644 --- a/code/cgame/cg_tempmodels.cpp +++ b/code/cgame/cg_tempmodels.cpp @@ -28,6 +28,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "tiki.h" cvar_t *cg_showtempmodels; +cvar_t *cg_max_tempmodels; +cvar_t *cg_reserve_tempmodels; cvar_t *cg_detail; cvar_t *cg_effectdetail; cvar_t *cg_effect_physicsrate; @@ -86,6 +88,83 @@ void ClientGameCommandManager::FreeTempModel(ctempmodel_t *p) m_free_tempmodels = p; } +//=============== +// FreeAllTempModels +//=============== +void ClientGameCommandManager::FreeAllTempModels(void) +{ + ctempmodel_t *p, *next; + + // Go through all the temp models and run the physics if necessary, + // then add them to the ref + p = m_active_tempmodels.prev; + for (; p != &m_active_tempmodels; p = next) { + // grab next now, so if the local entity is freed we still have it + next = p->prev; + FreeTempModel(p); + } +} + +//=============== +// FreeSomeTempModels +//=============== +void ClientGameCommandManager::FreeSomeTempModels(void) +{ + ctempmodel_t* model; + int count = 0; + unsigned int i; + unsigned int numToFree; + + if (!m_free_tempmodels) { + return; + } + + for (model = m_active_tempmodels.prev; model != &m_active_tempmodels; model = model->prev) { + count++; + } + + if (cg_reserve_tempmodels->integer <= (cg_max_tempmodels->integer - count)) { + // nothing to free + return; + } + + numToFree = cg_reserve_tempmodels->integer - (cg_max_tempmodels->integer - count); + + for (i = 0; i < numToFree; i++) { + FreeTempModel(m_active_tempmodels.prev); + } +} + +//=============== +// FreeSpawnthing +//=============== +void ClientGameCommandManager::FreeSpawnthing(spawnthing_t* sp) +{ + ctempmodel_t* model; + ctempmodel_t* prev; + + if (sp->numtempmodels) { + for (model = m_active_tempmodels.prev; model != &m_active_tempmodels; model = prev) { + prev = model->prev; + + if (model->m_spawnthing == sp) { + FreeTempModel(model); + } + } + } else { + m_emitters.RemoveObject(sp); + + if (sp == m_spawnthing) { + m_spawnthing = NULL; + } + + delete sp; + } +} + +//=============== +// ResetTempModels +//=============== void ClientGameCommandManager::ResetTempModels(void) { // Go through all the active tempmodels and free them @@ -128,9 +207,23 @@ void ClientGameCommandManager::InitializeTempModels(void) void ClientGameCommandManager::InitializeTempModelCvars(void) { cg_showtempmodels = cgi.Cvar_Get("cg_showtempmodels", "0", 0); - cg_detail = cgi.Cvar_Get("detail", "1", 1); - cg_effectdetail = cgi.Cvar_Get("cg_effectdetail", "0.2", 1); - cg_effect_physicsrate = cgi.Cvar_Get("cg_effect_physicsrate", "10", 1); + cg_detail = cgi.Cvar_Get("detail", "1", CVAR_ARCHIVE); + cg_effectdetail = cgi.Cvar_Get("cg_effectdetail", "0.2", CVAR_ARCHIVE); + cg_effect_physicsrate = cgi.Cvar_Get("cg_effect_physicsrate", "10", CVAR_ARCHIVE); + cg_max_tempmodels = cgi.Cvar_Get("cg_max_tempmodels", "1100", CVAR_ARCHIVE); + cg_reserve_tempmodels = cgi.Cvar_Get("cg_reserve_tempmodels", "200", CVAR_ARCHIVE); + + if (cg_max_tempmodels->integer > MAX_TEMPMODELS) { + // 2.40 sets the integer value directly rather than calling Cvar_Set() + //cg_max_tempmodels->integer = MAX_TEMPMODELS + cgi.Cvar_Set("cg_max_tempmodels", va("%i", MAX_TEMPMODELS)); + } + + if (cg_reserve_tempmodels->integer * 5 > cg_max_tempmodels->integer) { + // 2.40 sets the integer value directly rather than calling Cvar_Set() + //cg_reserve_tempmodels->integer = cg_max_tempmodels->integer / 5; + cgi.Cvar_Set("cg_reserve_tempmodels", va("%i", cg_max_tempmodels->integer / 5)); + } } //===============