diff --git a/dlls/animation.cpp b/dlls/animation.cpp index 4bdbff4e8c..a50dd01b1c 100644 --- a/dlls/animation.cpp +++ b/dlls/animation.cpp @@ -528,3 +528,32 @@ int GetBodygroup( void *pmodel, entvars_t *pev, int iGroup ) return iCurrent; } + +int GetBodyCount( void *pmodel ) +{ + studiohdr_t *pstudiohdr = (studiohdr_t *)pmodel; + if( !pstudiohdr ) + return 0; + + int bodiesNum = 1; + mstudiobodyparts_t *pbodypart = (mstudiobodyparts_t *)( (byte *)pstudiohdr + pstudiohdr->bodypartindex ); + + for (int j=0; jnumbodyparts; ++j) + { + bodiesNum = bodiesNum * pbodypart[j].nummodels; + } + return bodiesNum; +} + +int GetBodygroupNumModels(void *pmodel , int iGroup) +{ + studiohdr_t *pstudiohdr = (studiohdr_t *)pmodel; + if( !pstudiohdr ) + return 0; + + if( iGroup > pstudiohdr->numbodyparts ) + return 0; + + mstudiobodyparts_t *pbodypart = (mstudiobodyparts_t *)( (byte *)pstudiohdr + pstudiohdr->bodypartindex ) + iGroup; + return pbodypart->nummodels; +} diff --git a/dlls/animation.h b/dlls/animation.h index 28d4c096ec..584ec859a1 100644 --- a/dlls/animation.h +++ b/dlls/animation.h @@ -39,6 +39,8 @@ void SequencePrecache( void *pmodel, const char *pSequenceName ); int FindTransition( void *pmodel, int iEndingAnim, int iGoalAnim, int *piDir ); void SetBodygroup( void *pmodel, entvars_t *pev, int iGroup, int iValue ); int GetBodygroup( void *pmodel, entvars_t *pev, int iGroup ); +int GetBodyCount( void *pmodel ); +int GetBodygroupNumModels( void *pmodel, int iGroup ); int GetAnimationEvent(void *pmodel, entvars_t *pev, MonsterEvent_t *pMonsterEvent, float flStart, float flEnd, int index, int& latestAnimEventFrame , int minAnimEventFrame); int ExtractBbox( void *pmodel, int sequence, float *mins, float *maxs ); diff --git a/dlls/game.cpp b/dlls/game.cpp index d1ed18f124..856ef7f2e7 100644 --- a/dlls/game.cpp +++ b/dlls/game.cpp @@ -62,7 +62,6 @@ ModFeatures::ModFeatures() shockroach_racex_classify = false; scientist_random_heads = 4; - scientist_total_heads = FEATURE_OPFOR_SPECIFIC ? 6 : scientist_random_heads; vortigaunt_coil_attack = true; vortigaunt_idle_effects = false; @@ -141,7 +140,6 @@ bool ModFeatures::SetValue(const char *key, const char *value) } KeyValueDefinition integers[] = { - KEY_VALUE_DEF(scientist_total_heads), KEY_VALUE_DEF(scientist_random_heads), }; diff --git a/dlls/game.h b/dlls/game.h index 1175aade9f..02c603c528 100644 --- a/dlls/game.h +++ b/dlls/game.h @@ -67,7 +67,6 @@ struct ModFeatures bool racex_dislike_alien_monsters; bool shockroach_racex_classify; - int scientist_total_heads; int scientist_random_heads; bool vortigaunt_coil_attack; diff --git a/dlls/scientist.cpp b/dlls/scientist.cpp index 9a4a9808db..b71d986a31 100644 --- a/dlls/scientist.cpp +++ b/dlls/scientist.cpp @@ -82,6 +82,7 @@ class CScientist : public CTalkMonster int GetDefaultVoicePitch(); void Spawn( void ); void Precache( void ); + void CalcTotalHeadCount(); void SetYawSpeed( void ); int DefaultClassify( void ); @@ -135,7 +136,7 @@ class CScientist : public CTalkMonster return g_modFeatures.scientist_random_heads; } virtual int TotalHeadCount() { - return g_modFeatures.scientist_total_heads; + return m_totalHeadCount > 0 ? m_totalHeadCount : 4; } bool NeedleIsEquiped() { return pev->body >= TotalHeadCount(); @@ -153,6 +154,9 @@ class CScientist : public CTalkMonster float m_painTime; float m_healTime; float m_fearTime; + + // Don't save + int m_totalHeadCount; }; LINK_ENTITY_TO_CLASS( monster_scientist, CScientist ) @@ -768,6 +772,7 @@ int CScientist::GetDefaultVoicePitch() void CScientist::Spawn() { SciSpawnHelper("models/scientist.mdl", gSkillData.scientistHealth); + CalcTotalHeadCount(); // White hands pev->skin = 0; @@ -795,6 +800,17 @@ void CScientist::Precache( void ) CTalkMonster::Precache(); RegisterTalkMonster(); RegisterMedic(); + + CalcTotalHeadCount(); +} + +void CScientist::CalcTotalHeadCount() +{ + if (pev->modelindex) + { + // Divide by 2 to account for body variants with the needle + m_totalHeadCount = GetBodyCount( GET_MODEL_PTR(ENT(pev)) ) / 2; + } } void CScientist::PrecacheSounds() @@ -1343,6 +1359,7 @@ void CSittingScientist::SciSpawnHelper(const char* modelName) void CSittingScientist::Spawn( ) { SciSpawnHelper("models/scientist.mdl"); + CalcTotalHeadCount(); // Luther is black, make his hands black if ( pev->body == HEAD_LUTHER ) pev->skin = 1; @@ -1353,6 +1370,7 @@ void CSittingScientist::Precache( void ) m_baseSequence = LookupSequence( "sitlookleft" ); TalkInit(); RegisterTalkMonster(false); + CalcTotalHeadCount(); } //========================================================= @@ -1521,6 +1539,21 @@ int CSittingScientist::FIdleSpeak( void ) class CCleansuitScientist : public CScientist { public: + int GetDefaultVoicePitch() + { + switch( pev->body ) + { + default: + case HEAD_GLASSES: + return 105; + case HEAD_EINSTEIN: + return 100; + case HEAD_LUTHER: + return 95; + case HEAD_SLICK: + return 100; + } + } void Spawn(); void Precache(); bool IsEnabledInMod() { return g_modFeatures.IsMonsterEnabled("cleansuit_scientist"); } @@ -1634,6 +1667,7 @@ void CRosenberg::Spawn() SciSpawnHelper("models/scientist_rosenberg.mdl", gSkillData.scientistHealth * 2); #else SciSpawnHelper("models/scientist.mdl", gSkillData.scientistHealth * 2); + CalcTotalHeadCount(); pev->body = 3; #endif TalkMonsterInit(); @@ -1645,6 +1679,7 @@ void CRosenberg::Precache() PrecacheMyModel("models/scientist_rosenberg.mdl"); #else PrecacheMyModel("models/scientist.mdl"); + CalcTotalHeadCount(); #endif PRECACHE_SOUND( "rosenberg/ro_pain0.wav" ); PRECACHE_SOUND( "rosenberg/ro_pain1.wav" ); diff --git a/features/featureful_server.cfg b/features/featureful_server.cfg index b01e7042a9..42ec541ed1 100644 --- a/features/featureful_server.cfg +++ b/features/featureful_server.cfg @@ -71,9 +71,6 @@ shockroach_racex_classify false // SCIENTISTS ///////// -// Total scientist head count. Used when calculating the right body state (with or without needle on). Set it to 6 for Opposing Force scientist model. -scientist_total_heads 4 - // Scientist head count used for randomizing when body is set to -1 scientist_random_heads 4