2
0
mirror of https://github.com/FWGS/hlsdk-xash3d synced 2024-11-29 21:40:32 +01:00
hlsdk-xash3d/dlls/animating.cpp

312 lines
8.7 KiB
C++
Raw Normal View History

2016-06-04 15:24:23 +02:00
/***
*
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
*
* This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved.
*
* Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from
* Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC.
*
****/
/*
===== monsters.cpp ========================================================
Monster-related utility code
*/
#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "animation.h"
#include "saverestore.h"
2016-07-31 15:48:50 +02:00
TYPEDESCRIPTION CBaseAnimating::m_SaveData[] =
2016-06-04 15:24:23 +02:00
{
DEFINE_FIELD( CBaseMonster, m_flFrameRate, FIELD_FLOAT ),
DEFINE_FIELD( CBaseMonster, m_flGroundSpeed, FIELD_FLOAT ),
DEFINE_FIELD( CBaseMonster, m_flLastEventCheck, FIELD_TIME ),
DEFINE_FIELD( CBaseMonster, m_fSequenceFinished, FIELD_BOOLEAN ),
DEFINE_FIELD( CBaseMonster, m_fSequenceLoops, FIELD_BOOLEAN ),
};
IMPLEMENT_SAVERESTORE( CBaseAnimating, CBaseDelay )
2016-06-04 15:24:23 +02:00
//=========================================================
// StudioFrameAdvance - advance the animation frame up to the current time
// if an flInterval is passed in, only advance animation that number of seconds
//=========================================================
2016-07-31 15:48:50 +02:00
float CBaseAnimating::StudioFrameAdvance( float flInterval )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
if( flInterval == 0.0 )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
flInterval = gpGlobals->time - pev->animtime;
if( flInterval <= 0.001 )
2016-06-04 15:24:23 +02:00
{
pev->animtime = gpGlobals->time;
return 0.0;
}
}
2016-07-31 15:48:50 +02:00
if( !pev->animtime )
2016-06-04 15:24:23 +02:00
flInterval = 0.0;
2016-07-31 15:48:50 +02:00
2016-06-04 15:24:23 +02:00
pev->frame += flInterval * m_flFrameRate * pev->framerate;
pev->animtime = gpGlobals->time;
2016-07-31 15:48:50 +02:00
if( pev->frame < 0.0 || pev->frame >= 256.0 )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
if( m_fSequenceLoops )
pev->frame -= (int)( pev->frame / 256.0 ) * 256.0;
2016-06-04 15:24:23 +02:00
else
2016-07-31 15:48:50 +02:00
pev->frame = ( pev->frame < 0.0 ) ? 0 : 255;
2016-06-04 15:24:23 +02:00
m_fSequenceFinished = TRUE; // just in case it wasn't caught in GetEvents
}
return flInterval;
}
//=========================================================
// LookupActivity
//=========================================================
2016-07-31 15:48:50 +02:00
int CBaseAnimating::LookupActivity( int activity )
2016-06-04 15:24:23 +02:00
{
ASSERT( activity != 0 );
2016-07-31 15:48:50 +02:00
void *pmodel = GET_MODEL_PTR( ENT( pev ) );
2016-06-04 15:24:23 +02:00
return ::LookupActivity( pmodel, pev, activity );
}
//=========================================================
// LookupActivityHeaviest
//
// Get activity with highest 'weight'
//
//=========================================================
2016-07-31 15:48:50 +02:00
int CBaseAnimating::LookupActivityHeaviest( int activity )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
void *pmodel = GET_MODEL_PTR( ENT( pev ) );
2016-06-04 15:24:23 +02:00
return ::LookupActivityHeaviest( pmodel, pev, activity );
}
//=========================================================
//=========================================================
2016-07-31 15:48:50 +02:00
int CBaseAnimating::LookupSequence( const char *label )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
void *pmodel = GET_MODEL_PTR( ENT( pev ) );
2016-06-04 15:24:23 +02:00
return ::LookupSequence( pmodel, label );
}
//=========================================================
//=========================================================
2016-07-31 15:48:50 +02:00
void CBaseAnimating::ResetSequenceInfo()
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
void *pmodel = GET_MODEL_PTR( ENT( pev ) );
2016-06-04 15:24:23 +02:00
GetSequenceInfo( pmodel, pev, &m_flFrameRate, &m_flGroundSpeed );
2016-07-31 15:48:50 +02:00
m_fSequenceLoops = ( ( GetSequenceFlags() & STUDIO_LOOPING ) != 0 );
2016-06-04 15:24:23 +02:00
pev->animtime = gpGlobals->time;
pev->framerate = 1.0;
m_fSequenceFinished = FALSE;
m_flLastEventCheck = gpGlobals->time;
}
//=========================================================
//=========================================================
2016-07-31 15:48:50 +02:00
BOOL CBaseAnimating::GetSequenceFlags()
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
void *pmodel = GET_MODEL_PTR( ENT( pev ) );
2016-06-04 15:24:23 +02:00
return ::GetSequenceFlags( pmodel, pev );
}
//=========================================================
// DispatchAnimEvents
//=========================================================
2016-07-31 15:48:50 +02:00
void CBaseAnimating::DispatchAnimEvents( float flInterval )
2016-06-04 15:24:23 +02:00
{
MonsterEvent_t event;
2016-07-31 15:48:50 +02:00
void *pmodel = GET_MODEL_PTR( ENT( pev ) );
2016-06-04 15:24:23 +02:00
2016-07-31 15:48:50 +02:00
if( !pmodel )
2016-06-04 15:24:23 +02:00
{
ALERT( at_aiconsole, "Gibbed monster is thinking!\n" );
return;
}
// FIXME: I have to do this or some events get missed, and this is probably causing the problem below
flInterval = 0.1;
// FIX: this still sometimes hits events twice
2016-07-31 15:48:50 +02:00
float flStart = pev->frame + ( m_flLastEventCheck - pev->animtime ) * m_flFrameRate * pev->framerate;
2016-06-04 15:24:23 +02:00
float flEnd = pev->frame + flInterval * m_flFrameRate * pev->framerate;
m_flLastEventCheck = pev->animtime + flInterval;
m_fSequenceFinished = FALSE;
2016-07-31 15:48:50 +02:00
if( flEnd >= 256 || flEnd <= 0.0 )
2016-06-04 15:24:23 +02:00
m_fSequenceFinished = TRUE;
int index = 0;
2016-07-31 15:48:50 +02:00
while( ( index = GetAnimationEvent( pmodel, pev, &event, flStart, flEnd, index ) ) != 0 )
2016-06-04 15:24:23 +02:00
{
HandleAnimEvent( &event );
}
}
//=========================================================
//=========================================================
2016-07-31 15:48:50 +02:00
float CBaseAnimating::SetBoneController( int iController, float flValue )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
void *pmodel = GET_MODEL_PTR( ENT( pev ) );
2016-06-04 15:24:23 +02:00
return SetController( pmodel, pev, iController, flValue );
}
//=========================================================
//=========================================================
2016-07-31 15:48:50 +02:00
void CBaseAnimating::InitBoneControllers( void )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
void *pmodel = GET_MODEL_PTR( ENT( pev ) );
2016-06-04 15:24:23 +02:00
SetController( pmodel, pev, 0, 0.0 );
SetController( pmodel, pev, 1, 0.0 );
SetController( pmodel, pev, 2, 0.0 );
SetController( pmodel, pev, 3, 0.0 );
}
//=========================================================
//=========================================================
2016-07-31 15:48:50 +02:00
float CBaseAnimating::SetBlending( int iBlender, float flValue )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
void *pmodel = GET_MODEL_PTR( ENT( pev ) );
2016-06-04 15:24:23 +02:00
return ::SetBlending( pmodel, pev, iBlender, flValue );
}
//=========================================================
//=========================================================
2016-07-31 15:48:50 +02:00
void CBaseAnimating::GetBonePosition( int iBone, Vector &origin, Vector &angles )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
GET_BONE_POSITION( ENT( pev ), iBone, origin, angles );
2016-06-04 15:24:23 +02:00
}
//=========================================================
//=========================================================
2016-07-31 15:48:50 +02:00
void CBaseAnimating::GetAttachment( int iAttachment, Vector &origin, Vector &angles )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
GET_ATTACHMENT( ENT( pev ), iAttachment, origin, angles );
2016-06-04 15:24:23 +02:00
}
//=========================================================
//=========================================================
2016-07-31 15:48:50 +02:00
int CBaseAnimating::FindTransition( int iEndingSequence, int iGoalSequence, int *piDir )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
void *pmodel = GET_MODEL_PTR( ENT( pev ) );
if( piDir == NULL )
2016-06-04 15:24:23 +02:00
{
int iDir;
int sequence = ::FindTransition( pmodel, iEndingSequence, iGoalSequence, &iDir );
2016-07-31 15:48:50 +02:00
if( iDir != 1 )
2016-06-04 15:24:23 +02:00
return -1;
else
return sequence;
}
return ::FindTransition( pmodel, iEndingSequence, iGoalSequence, piDir );
}
//=========================================================
//=========================================================
2016-07-31 15:48:50 +02:00
void CBaseAnimating::GetAutomovement( Vector &origin, Vector &angles, float flInterval )
2016-06-04 15:24:23 +02:00
{
}
2016-07-31 15:48:50 +02:00
void CBaseAnimating::SetBodygroup( int iGroup, int iValue )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
::SetBodygroup( GET_MODEL_PTR( ENT( pev ) ), pev, iGroup, iValue );
2016-06-04 15:24:23 +02:00
}
2016-07-31 15:48:50 +02:00
int CBaseAnimating::GetBodygroup( int iGroup )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
return ::GetBodygroup( GET_MODEL_PTR( ENT( pev ) ), pev, iGroup );
2016-06-04 15:24:23 +02:00
}
2016-07-31 15:48:50 +02:00
int CBaseAnimating::ExtractBbox( int sequence, float *mins, float *maxs )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
return ::ExtractBbox( GET_MODEL_PTR( ENT( pev ) ), sequence, mins, maxs );
2016-06-04 15:24:23 +02:00
}
//=========================================================
//=========================================================
2016-07-31 15:48:50 +02:00
void CBaseAnimating::SetSequenceBox( void )
2016-06-04 15:24:23 +02:00
{
Vector mins, maxs;
// Get sequence bbox
2016-07-31 15:48:50 +02:00
if( ExtractBbox( pev->sequence, mins, maxs ) )
2016-06-04 15:24:23 +02:00
{
// expand box for rotation
// find min / max for rotations
2016-07-31 15:48:50 +02:00
float yaw = pev->angles.y * ( M_PI / 180.0 );
2016-06-04 15:24:23 +02:00
Vector xvector, yvector;
2016-07-31 15:48:50 +02:00
xvector.x = cos( yaw );
xvector.y = sin( yaw );
yvector.x = -sin( yaw );
yvector.y = cos( yaw );
2016-06-04 15:24:23 +02:00
Vector bounds[2];
bounds[0] = mins;
bounds[1] = maxs;
2016-07-31 15:48:50 +02:00
2016-06-04 15:24:23 +02:00
Vector rmin( 9999, 9999, 9999 );
Vector rmax( -9999, -9999, -9999 );
Vector base, transformed;
2016-07-31 15:48:50 +02:00
for( int i = 0; i <= 1; i++ )
2016-06-04 15:24:23 +02:00
{
base.x = bounds[i].x;
2016-07-31 15:48:50 +02:00
for( int j = 0; j <= 1; j++ )
2016-06-04 15:24:23 +02:00
{
base.y = bounds[j].y;
2016-07-31 15:48:50 +02:00
for( int k = 0; k <= 1; k++ )
2016-06-04 15:24:23 +02:00
{
base.z = bounds[k].z;
2016-07-31 15:48:50 +02:00
// transform the point
transformed.x = xvector.x * base.x + yvector.x * base.y;
transformed.y = xvector.y * base.x + yvector.y * base.y;
2016-06-04 15:24:23 +02:00
transformed.z = base.z;
2016-07-31 15:48:50 +02:00
if( transformed.x < rmin.x )
2016-06-04 15:24:23 +02:00
rmin.x = transformed.x;
2016-07-31 15:48:50 +02:00
if( transformed.x > rmax.x )
2016-06-04 15:24:23 +02:00
rmax.x = transformed.x;
2016-07-31 15:48:50 +02:00
if( transformed.y < rmin.y )
2016-06-04 15:24:23 +02:00
rmin.y = transformed.y;
2016-07-31 15:48:50 +02:00
if( transformed.y > rmax.y )
2016-06-04 15:24:23 +02:00
rmax.y = transformed.y;
2016-07-31 15:48:50 +02:00
if( transformed.z < rmin.z )
2016-06-04 15:24:23 +02:00
rmin.z = transformed.z;
2016-07-31 15:48:50 +02:00
if( transformed.z > rmax.z )
2016-06-04 15:24:23 +02:00
rmax.z = transformed.z;
}
}
}
rmin.z = 0;
rmax.z = rmin.z + 1;
UTIL_SetSize( pev, rmin, rmax );
}
}