/* ===== hs_model.cpp ======================================================== Half-Screwed Model Entites, or how we don't have to worry and rely on brushes and broken, laggy maps anymore. Phew. NOTE: I ripped this from Cycler. so It's not me, man. */ #include "extdll.h" #include "util.h" #include "cbase.h" #include "monsters.h" #include "animation.h" #include "weapons.h" #include "player.h" #define TEMP_FOR_SCREEN_SHOTS #ifdef TEMP_FOR_SCREEN_SHOTS //=================================================== class CHSModel : public CBaseMonster { public: void GeneriCHSModelSpawn(char *szModel, Vector vecMin, Vector vecMax); virtual int ObjectCaps( void ) { return (CBaseEntity :: ObjectCaps() | FCAP_IMPULSE_USE); } void Spawn( void ); void Think( void ); // Don't treat as a live target virtual BOOL IsAlive( void ) { return FALSE; } virtual int Save( CSave &save ); virtual int Restore( CRestore &restore ); static TYPEDESCRIPTION m_SaveData[]; int m_animate; }; TYPEDESCRIPTION CHSModel::m_SaveData[] = { DEFINE_FIELD( CHSModel, m_animate, FIELD_INTEGER ), }; IMPLEMENT_SAVERESTORE( CHSModel, CBaseMonster ); // // we should get rid of all the other cyclers and replace them with this. // class CGeneriCHSModel : public CHSModel { public: void Spawn( void ) { GeneriCHSModelSpawn( (char *)STRING(pev->model), Vector(-16, -16, 0), Vector(16, 16, 72) ); } }; LINK_ENTITY_TO_CLASS( hs_model, CGeneriCHSModel ); // Cycler member functions void CHSModel :: GeneriCHSModelSpawn(char *szModel, Vector vecMin, Vector vecMax) { if (!szModel || !*szModel) { ALERT(at_error, "cycler at %.0f %.0f %0.f missing modelname", pev->origin.x, pev->origin.y, pev->origin.z ); REMOVE_ENTITY(ENT(pev)); return; } pev->classname = MAKE_STRING("cycler"); PRECACHE_MODEL( szModel ); SET_MODEL(ENT(pev), szModel); CHSModel::Spawn( ); UTIL_SetSize(pev, vecMin, vecMax); } void CHSModel :: Spawn( ) { InitBoneControllers(); pev->solid = SOLID_SLIDEBOX; pev->movetype = MOVETYPE_NONE; pev->takedamage = DAMAGE_NO; pev->effects = 0; pev->health = 8675309;// no cycler should die pev->yaw_speed = 5; pev->ideal_yaw = pev->angles.y; ChangeYaw( 360 ); m_flFrameRate = 75; m_flGroundSpeed = 0; pev->nextthink += 1.0; ResetSequenceInfo( ); if (pev->sequence != 0 || pev->frame != 0) { m_animate = 0; pev->framerate = 0; } else { m_animate = 1; } } // // cycler think // void CHSModel :: Think( void ) { pev->nextthink = gpGlobals->time + 0.1; if (m_animate) { StudioFrameAdvance ( ); } if (m_fSequenceFinished && !m_fSequenceLoops) { // ResetSequenceInfo(); // hack to avoid reloading model every frame pev->animtime = gpGlobals->time; pev->framerate = 1.0; m_fSequenceFinished = FALSE; m_flLastEventCheck = gpGlobals->time; pev->frame = 0; if (!m_animate) pev->framerate = 0.0; // FIX: don't reset framerate } } #endif class CHSModelSprite : public CBaseEntity { public: void Spawn( void ); void Think( void ); void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); virtual int ObjectCaps( void ) { return (CBaseEntity :: ObjectCaps() | FCAP_DONT_SAVE | FCAP_IMPULSE_USE); } virtual int TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType ); void Animate( float frames ); virtual int Save( CSave &save ); virtual int Restore( CRestore &restore ); static TYPEDESCRIPTION m_SaveData[]; inline int ShouldAnimate( void ) { return m_animate && m_maxFrame > 1.0; } int m_animate; float m_lastTime; float m_maxFrame; }; LINK_ENTITY_TO_CLASS( hs_sprite, CHSModelSprite ); TYPEDESCRIPTION CHSModelSprite::m_SaveData[] = { DEFINE_FIELD( CHSModelSprite, m_animate, FIELD_INTEGER ), DEFINE_FIELD( CHSModelSprite, m_lastTime, FIELD_TIME ), DEFINE_FIELD( CHSModelSprite, m_maxFrame, FIELD_FLOAT ), }; IMPLEMENT_SAVERESTORE( CHSModelSprite, CBaseEntity ); void CHSModelSprite::Spawn( void ) { pev->solid = SOLID_SLIDEBOX; pev->movetype = MOVETYPE_NONE; pev->takedamage = DAMAGE_NO; pev->effects = 0; pev->frame = 0; pev->nextthink = gpGlobals->time + 0.1; m_animate = 1; m_lastTime = gpGlobals->time; PRECACHE_MODEL( (char *)STRING(pev->model) ); SET_MODEL( ENT(pev), STRING(pev->model) ); m_maxFrame = (float) MODEL_FRAMES( pev->modelindex ) - 1; } void CHSModelSprite::Think( void ) { if ( ShouldAnimate() ) Animate( pev->framerate * (gpGlobals->time - m_lastTime) ); pev->nextthink = gpGlobals->time + 0.1; m_lastTime = gpGlobals->time; } void CHSModelSprite::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) { m_animate = !m_animate; ALERT( at_console, "Sprite: %s\n", STRING(pev->model) ); } int CHSModelSprite::TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType ) { if ( m_maxFrame > 1.0 ) { Animate( 1.0 ); } return 1; } void CHSModelSprite::Animate( float frames ) { pev->frame += frames; if ( m_maxFrame > 0 ) pev->frame = fmod( pev->frame, m_maxFrame ); }