# include "extdll.h"
# include "util.h"
# include "cbase.h"
# include "movewith.h"
# include "saverestore.h"
# include "player.h"
CWorld * g_pWorld = NULL ; //LRC
BOOL g_doingDesired = FALSE ; //LRC - marks whether the Desired functions are currently
// being processed.
void UTIL_AddToAssistList ( CBaseEntity * pEnt )
{
// ALERT(at_console, "Add %s \"%s\" to AssistList\n", STRING(pEnt->pev->classname), STRING(pEnt->pev->targetname));
if ( pEnt - > m_pAssistLink )
{
// ALERT(at_console, "Ignored AddToAssistList for %s \"%s\"\n", STRING(pEnt->pev->classname), STRING(pEnt->pev->targetname));
return ; // is pEnt already in the body of the list?
}
if ( ! g_pWorld )
{
ALERT ( at_console , " AddToAssistList %s \" %s \" has no AssistList! \n " , STRING ( pEnt - > pev - > classname ) , STRING ( pEnt - > pev - > targetname ) ) ;
return ;
}
CBaseEntity * pListMember = g_pWorld ;
// find the last entry in the list...
while ( pListMember - > m_pAssistLink ! = NULL )
pListMember = pListMember - > m_pAssistLink ;
if ( pListMember = = pEnt )
{
// ALERT(at_console, "(end)Ignored AddToAssistList for %s \"%s\"\n", STRING(pEnt->pev->classname), STRING(pEnt->pev->targetname));
return ; // pEnt is the last entry in the list.
}
pListMember - > m_pAssistLink = pEnt ; // it's not in the list already, so add pEnt to the list.
// int count = 0;
// for (pListMember = g_pWorld->m_pAssistLink; pListMember; pListMember = pListMember->m_pAssistLink)
// {
// count++;
// }
// ALERT(at_console, "Added %s \"%s\" to AssistList, length now %d\n", STRING(pEnt->pev->classname), STRING(pEnt->pev->targetname), count);
}
void HandlePostAssist ( CBaseEntity * pEnt )
{
if ( pEnt - > m_iLFlags & LF_POSTASSISTVEL )
{
// ALERT(at_console, "RestoreVel %s: orign %f %f %f, velocity was %f %f %f, back to %f %f %f\n",
// STRING(pEnt->pev->targetname),
// pEnt->pev->origin.x, pEnt->pev->origin.y, pEnt->pev->origin.z,
// pEnt->pev->velocity.x, pEnt->pev->velocity.y, pEnt->pev->velocity.z,
// pEnt->m_vecPostAssistVel.x, pEnt->m_vecPostAssistVel.y, pEnt->m_vecPostAssistVel.z
// );
pEnt - > pev - > velocity = pEnt - > m_vecPostAssistVel ;
pEnt - > m_vecPostAssistVel = g_vecZero ;
pEnt - > m_iLFlags & = ~ LF_POSTASSISTVEL ;
}
if ( pEnt - > m_iLFlags & LF_POSTASSISTAVEL )
{
// ALERT(at_console, "RestoreVel %s: orign %f %f %f, velocity was %f %f %f, back to %f %f %f\n",
// STRING(pEnt->pev->targetname),
// pEnt->pev->origin.x, pEnt->pev->origin.y, pEnt->pev->origin.z,
// pEnt->pev->velocity.x, pEnt->pev->velocity.y, pEnt->pev->velocity.z,
// pEnt->m_vecPostAssistVel.x, pEnt->m_vecPostAssistVel.y, pEnt->m_vecPostAssistVel.z
// );
pEnt - > pev - > avelocity = pEnt - > m_vecPostAssistAVel ;
pEnt - > m_vecPostAssistAVel = g_vecZero ;
pEnt - > m_iLFlags & = ~ LF_POSTASSISTAVEL ;
}
CBaseEntity * pChild ;
for ( pChild = pEnt - > m_pChildMoveWith ; pChild ! = NULL ; pChild = pChild - > m_pSiblingMoveWith )
HandlePostAssist ( pChild ) ;
}
// returns 0 if no desired settings needed, else returns 1
int ApplyDesiredSettings ( CBaseEntity * pListMember )
{
if ( pListMember - > m_iLFlags & LF_DODESIRED )
{
pListMember - > m_iLFlags & = ~ LF_DODESIRED ;
}
else
{
// don't need to apply any desired settings for this entity.
return 0 ;
}
// ALERT(at_console, "ApplyDesiredSettings for %s \"%s\", pevnt %f, ltime %f, mfnt %f, mpevnt %f, %f\n", STRING(pListMember->pev->classname), STRING(pListMember->pev->targetname), pListMember->pev->nextthink, pListMember->pev->ltime, pListMember->m_fNextThink, pListMember->m_fPevNextThink, pListMember->pev->origin.x);
if ( pListMember - > m_iLFlags & LF_DESIRED_ACTION )
{
pListMember - > m_iLFlags & = ~ LF_DESIRED_ACTION ;
pListMember - > DesiredAction ( ) ;
}
if ( pListMember - > m_iLFlags & LF_DESIRED_INFO )
{
pListMember - > m_iLFlags & = ~ LF_DESIRED_INFO ;
ALERT ( at_console , " DesiredInfo: pos %f %f %f, vel %f %f %f. Child pos %f %f %f, vel %f %f %f \n \n " , pListMember - > pev - > origin . x , pListMember - > pev - > origin . y , pListMember - > pev - > origin . z , pListMember - > pev - > velocity . x , pListMember - > pev - > velocity . y , pListMember - > pev - > velocity . z , pListMember - > m_pChildMoveWith - > pev - > origin . x , pListMember - > m_pChildMoveWith - > pev - > origin . y , pListMember - > m_pChildMoveWith - > pev - > origin . z , pListMember - > m_pChildMoveWith - > pev - > velocity . x , pListMember - > m_pChildMoveWith - > pev - > velocity . y , pListMember - > m_pChildMoveWith - > pev - > velocity . z ) ;
}
if ( pListMember - > m_iLFlags & LF_DESIRED_POSTASSIST )
{
pListMember - > m_iLFlags & = ~ LF_DESIRED_POSTASSIST ;
HandlePostAssist ( pListMember ) ;
}
if ( pListMember - > m_iLFlags & LF_DESIRED_THINK )
{
pListMember - > m_iLFlags & = ~ LF_DESIRED_THINK ;
//ALERT(at_console, "DesiredThink %s\n", STRING(pListMember->pev->targetname));
pListMember - > Think ( ) ;
}
return 1 ;
}
void AssistChildren ( CBaseEntity * pEnt , Vector vecAdjustVel , Vector vecAdjustAVel )
{
CBaseEntity * pChild ;
for ( pChild = pEnt - > m_pChildMoveWith ; pChild ! = NULL ; pChild = pChild - > m_pSiblingMoveWith )
{
if ( ! ( pChild - > m_iLFlags & LF_POSTASSISTVEL ) )
{
pChild - > m_vecPostAssistVel = pChild - > pev - > velocity ;
pChild - > m_iLFlags | = LF_POSTASSISTVEL ;
}
if ( ! ( pChild - > m_iLFlags & LF_POSTASSISTAVEL ) )
{
pChild - > m_vecPostAssistAVel = pChild - > pev - > avelocity ;
pChild - > m_iLFlags | = LF_POSTASSISTAVEL ;
}
pChild - > pev - > velocity = pChild - > pev - > velocity - vecAdjustVel ; // (pChild->pev->velocity - pEnt->m_vecPostAssistVel) + pEnt->m_vecPostAssistVel*fFraction;
pChild - > pev - > avelocity = pChild - > pev - > avelocity - vecAdjustAVel ; // (pChild->pev->avelocity - pEnt->m_vecPostAssistAVel) + pEnt->m_vecPostAssistAVel*fFraction;
//ALERT(at_console, "AssistChild %s: origin %f %f %f, old vel %f %f %f. fraction %f, new vel %f %f %f, dest %f %f %f\n", STRING(pChild->pev->targetname), pChild->pev->origin.x, pChild->pev->origin.y, pChild->pev->origin.z, pChild->m_vecPostAssistVel.x, pChild->m_vecPostAssistVel.y, pChild->m_vecPostAssistVel.z, fFraction, pChild->pev->velocity.x, pChild->pev->velocity.y, pChild->pev->velocity.z, pChild->pev->origin.x + pChild->pev->velocity.x*gpGlobals->frametime, pChild->pev->origin.y + pChild->pev->velocity.y*gpGlobals->frametime, pChild->pev->origin.z + pChild->pev->velocity.z*gpGlobals->frametime );
//ALERT(at_console, "AssistChild %s: origin %f %f %f. velocity was %f %f %f, now %f %f %f\n", STRING(pChild->pev->targetname), pChild->pev->origin.x, pChild->pev->origin.y, pChild->pev->origin.z, pChild->m_vecPostAssistVel.x, pChild->m_vecPostAssistVel.y, pChild->m_vecPostAssistVel.z, pChild->pev->velocity.x, pChild->pev->velocity.y, pChild->pev->velocity.z);
AssistChildren ( pChild , vecAdjustVel , vecAdjustAVel ) ;
}
}
// pEnt is a PUSH entity. Before physics is applied in a frame, we need to assist:
// 1) this entity, if it will stop moving this turn but its parent will continue.
// 2) this entity's PUSH children, if 1) was applied.
// 3) this entity's non-PUSH children, if this entity will stop moving this turn.
//
// returns 0 if the entity wasn't flagged for DoAssist.
int TryAssistEntity ( CBaseEntity * pEnt )
{
if ( gpGlobals - > frametime = = 0 )
{
// ALERT(at_console, "frametime 0, don't assist\n");
return 0 ;
}
// not flagged as needing assistance?
if ( ! ( pEnt - > m_iLFlags & LF_DOASSIST ) )
return 0 ;
// ALERT(at_console, "AssistList: %s\n", STRING(pEnt->pev->classname));
if ( pEnt - > m_fNextThink < = 0 )
{
// ALERT(at_console, "Cancelling assist for %s, %f\n", STRING(pEnt->pev->targetname), pEnt->pev->origin.x);
pEnt - > m_iLFlags & = ~ LF_DOASSIST ;
return 0 ; // the think has been cancelled. Oh well...
}
// ALERT(at_console, "Assist, mfNT %f, pevNT %f\n", pEnt->m_fNextThink, pEnt->pev->nextthink);
// pEnt->ThinkCorrection();
// a fraction of the current velocity. (the part of it that the engine should see.)
float fFraction = 0 ;
// is this the frame when the entity will stop?
if ( pEnt - > pev - > movetype = = MOVETYPE_PUSH )
{
if ( pEnt - > m_fNextThink < = pEnt - > pev - > ltime + gpGlobals - > frametime )
fFraction = ( pEnt - > m_fNextThink - pEnt - > pev - > ltime ) / gpGlobals - > frametime ;
}
else if ( pEnt - > m_fNextThink < = gpGlobals - > time + gpGlobals - > frametime )
{
fFraction = ( pEnt - > m_fNextThink - gpGlobals - > time ) / gpGlobals - > frametime ;
// ALERT(at_console, "Setting fFraction\n");
}
if ( fFraction )
{
// ALERT(at_console, "Assisting %s \"%s\", %f <= %f + %f\n", STRING(pEnt->pev->classname), STRING(pEnt->pev->targetname), pEnt->m_fNextThink, pEnt->pev->ltime, gpGlobals->frametime);
if ( pEnt - > m_iLFlags & LF_CORRECTSPEED )
{
if ( ! ( pEnt - > m_iLFlags & LF_POSTASSISTVEL ) )
{
pEnt - > m_vecPostAssistVel = pEnt - > pev - > velocity ;
pEnt - > m_iLFlags | = LF_POSTASSISTVEL ;
}
if ( ! ( pEnt - > m_iLFlags & LF_POSTASSISTAVEL ) )
{
pEnt - > m_vecPostAssistAVel = pEnt - > pev - > avelocity ;
pEnt - > m_iLFlags | = LF_POSTASSISTAVEL ;
}
Vector vecVelTemp = pEnt - > pev - > velocity ;
Vector vecAVelTemp = pEnt - > pev - > avelocity ;
if ( pEnt - > m_pMoveWith )
{
pEnt - > pev - > velocity = ( pEnt - > pev - > velocity - pEnt - > m_pMoveWith - > pev - > velocity ) * fFraction + pEnt - > m_pMoveWith - > pev - > velocity ;
pEnt - > pev - > avelocity = ( pEnt - > pev - > avelocity - pEnt - > m_pMoveWith - > pev - > avelocity ) * fFraction + pEnt - > m_pMoveWith - > pev - > avelocity ;
}
else
{
pEnt - > pev - > velocity = pEnt - > pev - > velocity * fFraction ;
pEnt - > pev - > avelocity = pEnt - > pev - > avelocity * fFraction ;
}
//ALERT(at_console, "Assist %s: origin %f %f %f, old vel %f %f %f. fraction %f, new vel %f %f %f, dest %f %f %f\n", STRING(pEnt->pev->targetname), pEnt->pev->origin.x, pEnt->pev->origin.y, pEnt->pev->origin.z, pEnt->m_vecPostAssistVel.x, pEnt->m_vecPostAssistVel.y, pEnt->m_vecPostAssistVel.z, fFraction, pEnt->pev->velocity.x, pEnt->pev->velocity.y, pEnt->pev->velocity.z, pEnt->pev->origin.x + pEnt->pev->velocity.x*gpGlobals->frametime, pEnt->pev->origin.y + pEnt->pev->velocity.y*gpGlobals->frametime, pEnt->pev->origin.z + pEnt->pev->velocity.z*gpGlobals->frametime);
AssistChildren ( pEnt , vecVelTemp - pEnt - > pev - > velocity , vecAVelTemp - pEnt - > pev - > avelocity ) ;
UTIL_DesiredPostAssist ( pEnt ) ;
}
UTIL_DesiredThink ( pEnt ) ;
// ALERT(at_console, "Assist sets DesiredThink for %s\n", STRING(pEnt->pev->classname));
pEnt - > m_iLFlags & = ~ LF_DOASSIST ;
}
#if 0
else
{
// float fLeft = (pEnt->m_fNextThink - pEnt->pev->ltime);
// ALERT(at_console, "NoAssist: origin %f %f %f, ontrack %f %f %f, mfNT %f, should be %f\n", pEnt->pev->origin.x, pEnt->pev->origin.y, pEnt->pev->origin.z, pEnt->pev->origin.x + pEnt->pev->velocity.x*fLeft, pEnt->pev->origin.y + pEnt->pev->velocity.y*fLeft, pEnt->pev->origin.z + pEnt->pev->velocity.z*fLeft, pEnt->m_fNextThink, ((int)(pEnt->pev->origin.x+pEnt->pev->velocity.x*fLeft)-pEnt->pev->origin.x)/pEnt->pev->velocity.x+pEnt->pev->ltime);
static Vector staticPos ;
static float staticLtime ;
static float staticGtime ;
static float staticFtime ;
// ALERT(at_console, "No assist %s; diff %f %f %f, ediff %f %f %f, ltdiff %f, gtdiff %f, ftime %f, nthink %f, mfNT %f\n",
// STRING(pEnt->pev->targetname),
// pEnt->pev->origin.x - staticPos.x, pEnt->pev->origin.y - staticPos.y, pEnt->pev->origin.z - staticPos.z,
// pEnt->pev->velocity.x*staticFtime, pEnt->pev->velocity.y*staticFtime, pEnt->pev->velocity.z*staticFtime,
// pEnt->pev->ltime - staticLtime, gpGlobals->time - staticGtime, gpGlobals->frametime,
// pEnt->pev->nextthink, pEnt->m_fNextThink
// );
staticPos = pEnt - > pev - > origin ;
staticLtime = pEnt - > pev - > ltime ;
staticGtime = gpGlobals - > time ;
staticFtime = gpGlobals - > frametime ;
}
# endif
// ALERT(at_console, "TryAssist %s \"%s\", lflags %f, pevnt %f, ltime %f, mfnt %f, mpevnt %f, %f\n", STRING(pEnt->pev->classname), STRING(pEnt->pev->targetname), pEnt->m_iLFlags, pEnt->pev->nextthink, pEnt->pev->ltime, pEnt->m_fNextThink, pEnt->m_fPevNextThink, pEnt->pev->origin.x);
// ALERT(at_console, "TryAssist %s \"%s\", pevnt %f, ltime %f, mfnt %f, mpevnt %f, lfl %d, %f\n", STRING(pEnt->pev->classname), STRING(pEnt->pev->targetname), pEnt->pev->nextthink, pEnt->pev->ltime, pEnt->m_fNextThink, pEnt->m_fPevNextThink, pEnt->m_iLFlags, pEnt->pev->origin.x);
return 1 ;
}
// called every frame, by StartFrame
void CheckAssistList ( void )
{
CBaseEntity * pListMember ;
if ( ! g_pWorld )
{
ALERT ( at_error , " CheckAssistList has no AssistList! \n " ) ;
return ;
}
int count = 0 ;
for ( pListMember = g_pWorld ; pListMember ; pListMember = pListMember - > m_pAssistLink )
{
if ( pListMember - > m_iLFlags & LF_DOASSIST )
count + + ;
}
// if (count)
// ALERT(at_console, "CheckAssistList begins, length is %d\n", count);
count = 0 ;
pListMember = g_pWorld ;
while ( pListMember - > m_pAssistLink ) // handle the remaining entries in the list
{
TryAssistEntity ( pListMember - > m_pAssistLink ) ;
if ( ! ( pListMember - > m_pAssistLink - > m_iLFlags & LF_ASSISTLIST ) )
{
// ALERT(at_console, "Removing %s \"%s\" from assistList\n", STRING(pListMember->m_pAssistLink->pev->classname), STRING(pListMember->m_pAssistLink->pev->targetname));
CBaseEntity * pTemp = pListMember - > m_pAssistLink ;
pListMember - > m_pAssistLink = pListMember - > m_pAssistLink - > m_pAssistLink ;
pTemp - > m_pAssistLink = NULL ;
}
else
{
pListMember = pListMember - > m_pAssistLink ;
}
}
// if (count)
// ALERT(at_console, "CheckAssistList complete, %d ents checked\n", count);
}
// called every frame, by PostThink
void CheckDesiredList ( void )
{
CBaseEntity * pListMember ;
int loopbreaker = 1000 ; //assume this is the max. number of entities which will use DesiredList in any one frame
// BOOL liststart = FALSE;
if ( g_doingDesired )
ALERT ( at_console , " CheckDesiredList: doingDesired is already set!? \n " ) ;
g_doingDesired = TRUE ;
if ( ! g_pWorld )
{
ALERT ( at_console , " CheckDesiredList has no AssistList! \n " ) ;
return ;
}
pListMember = g_pWorld ;
CBaseEntity * pNext ;
// int count = 0;
// int all = 0;
// for (pListMember = g_pWorld->m_pAssistLink; pListMember; pListMember = pListMember->m_pAssistLink)
// {
// all++;
// if (pListMember->m_iLFlags & LF_DODESIRED)
// count++;
// }
// if (count)
// ALERT(at_console, "CheckDesiredList begins, length is %d, total %d\n", count, all);
// count = 0;
pListMember = g_pWorld - > m_pAssistLink ;
while ( pListMember )
{
// cache this, in case ApplyDesiredSettings does a SUB_Remove.
pNext = pListMember - > m_pAssistLink ;
ApplyDesiredSettings ( pListMember ) ;
pListMember = pNext ;
loopbreaker - - ;
if ( loopbreaker < = 0 )
{
ALERT ( at_error , " Infinite(?) loop in DesiredList! " ) ;
break ;
}
}
// if (count)
// ALERT(at_console, "CheckDesiredList complete, %d ents checked\n", count);
// if (liststart) ALERT(at_console, "-- DesiredList ends\n");
g_doingDesired = FALSE ;
}
void UTIL_MarkForAssist ( CBaseEntity * pEnt , BOOL correctSpeed )
{
pEnt - > m_iLFlags | = LF_DOASSIST ;
if ( correctSpeed )
pEnt - > m_iLFlags | = LF_CORRECTSPEED ;
else
pEnt - > m_iLFlags & = ~ LF_CORRECTSPEED ;
UTIL_AddToAssistList ( pEnt ) ;
}
void UTIL_MarkForDesired ( CBaseEntity * pEnt )
{
pEnt - > m_iLFlags | = LF_DODESIRED ;
if ( g_doingDesired )
{
//ALERT(at_console, "doingDesired is true, start immediately\n");
ApplyDesiredSettings ( pEnt ) ;
return ;
}
UTIL_AddToAssistList ( pEnt ) ;
}
void UTIL_DesiredAction ( CBaseEntity * pEnt )
{
pEnt - > m_iLFlags | = LF_DESIRED_ACTION ;
UTIL_MarkForDesired ( pEnt ) ;
}
void UTIL_DesiredInfo ( CBaseEntity * pEnt )
{
pEnt - > m_iLFlags | = LF_DESIRED_INFO ;
UTIL_MarkForDesired ( pEnt ) ;
}
void UTIL_DesiredPostAssist ( CBaseEntity * pEnt )
{
pEnt - > m_iLFlags | = LF_DESIRED_POSTASSIST ;
UTIL_MarkForDesired ( pEnt ) ;
}
void UTIL_DesiredThink ( CBaseEntity * pEnt )
{
// ALERT(at_console, "Setting DesiredThink %s\n", STRING(pEnt->pev->targetname));
pEnt - > m_iLFlags | = LF_DESIRED_THINK ;
pEnt - > DontThink ( ) ;
UTIL_MarkForDesired ( pEnt ) ;
}
// LRC- change the origin to the given position, and bring any movewiths along too.
void UTIL_AssignOrigin ( CBaseEntity * pEntity , const Vector vecOrigin )
{
UTIL_AssignOrigin ( pEntity , vecOrigin , TRUE ) ;
}
// LRC- bInitiator is true if this is being called directly, rather than because pEntity is moving with something else.
void UTIL_AssignOrigin ( CBaseEntity * pEntity , const Vector vecOrigin , BOOL bInitiator )
{
// ALERT(at_console, "AssignOrigin before %f, after %f\n", pEntity->pev->origin.x, vecOrigin.x);
Vector vecDiff = vecOrigin - pEntity - > pev - > origin ;
if ( vecDiff . Length ( ) > 0.01 & & CVAR_GET_FLOAT ( " sohl_mwdebug " ) )
ALERT ( at_console , " AssignOrigin %s %s: (%f %f %f) goes to (%f %f %f) \n " , STRING ( pEntity - > pev - > classname ) , STRING ( pEntity - > pev - > targetname ) , pEntity - > pev - > origin . x , pEntity - > pev - > origin . y , pEntity - > pev - > origin . z , vecOrigin . x , vecOrigin . y , vecOrigin . z ) ;
// UTIL_SetDesiredPos(pEntity, vecOrigin);
// pEntity->pev->origin = vecOrigin;
UTIL_SetOrigin ( pEntity , vecOrigin ) ;
// if (pEntity->m_vecDesiredVel != g_vecZero)
// {
// pEntity->pev->velocity = pEntity->m_vecDesiredVel;
// }
if ( bInitiator & & pEntity - > m_pMoveWith )
{
// UTIL_DesiredMWOffset( pEntity );
// if (pEntity->m_vecMoveWithOffset != (pEntity->pev->origin - pEntity->m_pMoveWith->pev->origin))
// ALERT(at_console, "Changing MWOffset for %s \"%s\"\n", STRING(pEntity->pev->classname), STRING(pEntity->pev->targetname));
pEntity - > m_vecMoveWithOffset = pEntity - > pev - > origin - pEntity - > m_pMoveWith - > pev - > origin ;
// ALERT(at_console,"set m_vecMoveWithOffset = %f %f %f\n",pEntity->m_vecMoveWithOffset.x,pEntity->m_vecMoveWithOffset.y,pEntity->m_vecMoveWithOffset.z);
}
if ( pEntity - > m_pChildMoveWith ) // now I've moved pEntity, does anything else have to move with it?
{
CBaseEntity * pChild = pEntity - > m_pChildMoveWith ;
// if (vecDiff != g_vecZero)
// {
Vector vecTemp ;
while ( pChild )
{
//ALERT(at_console," pre: parent origin is (%f %f %f), child origin is (%f %f %f)\n",
// pEntity->pev->origin.x,pEntity->pev->origin.y,pEntity->pev->origin.z,
// pChild->pev->origin.x,pChild->pev->origin.y,pChild->pev->origin.z
//);
if ( pChild - > pev - > movetype ! = MOVETYPE_PUSH | | pChild - > pev - > velocity = = pEntity - > pev - > velocity ) // if the child isn't moving under its own power
{
UTIL_AssignOrigin ( pChild , vecOrigin + pChild - > m_vecMoveWithOffset , FALSE ) ;
// ALERT(at_console,"used m_vecMoveWithOffset based on %f %f %f to set %f %f %f\n",pEntity->pev->origin.x,pEntity->pev->origin.y,pEntity->pev->origin.z,pChild->pev->origin.x,pChild->pev->origin.y,pChild->pev->origin.z);
}
else
{
vecTemp = vecDiff + pChild - > pev - > origin ;
UTIL_AssignOrigin ( pChild , vecTemp , FALSE ) ;
}
//ALERT(at_console," child origin becomes (%f %f %f)\n",pChild->pev->origin.x,pChild->pev->origin.y,pChild->pev->origin.z);
//ALERT(at_console,"ent %p has sibling %p\n",pChild,pChild->m_pSiblingMoveWith);
pChild = pChild - > m_pSiblingMoveWith ;
}
// }
}
}
void UTIL_SetAngles ( CBaseEntity * pEntity , const Vector vecAngles )
{
UTIL_SetAngles ( pEntity , vecAngles , TRUE ) ;
}
void UTIL_SetAngles ( CBaseEntity * pEntity , const Vector vecAngles , BOOL bInitiator )
{
Vector vecDiff = vecAngles - pEntity - > pev - > angles ;
if ( vecDiff . Length ( ) > 0.01 & & CVAR_GET_FLOAT ( " sohl_mwdebug " ) )
ALERT ( at_console , " SetAngles %s %s: (%f %f %f) goes to (%f %f %f) \n " , STRING ( pEntity - > pev - > classname ) , STRING ( pEntity - > pev - > targetname ) , pEntity - > pev - > angles . x , pEntity - > pev - > angles . y , pEntity - > pev - > angles . z , vecAngles . x , vecAngles . y , vecAngles . z ) ;
// UTIL_SetDesiredAngles(pEntity, vecAngles);
pEntity - > pev - > angles = vecAngles ;
if ( bInitiator & & pEntity - > m_pMoveWith )
{
pEntity - > m_vecRotWithOffset = vecAngles - pEntity - > m_pMoveWith - > pev - > angles ;
}
if ( pEntity - > m_pChildMoveWith ) // now I've moved pEntity, does anything else have to move with it?
{
CBaseEntity * pChild = pEntity - > m_pChildMoveWith ;
Vector vecTemp ;
while ( pChild )
{
if ( pChild - > pev - > avelocity = = pEntity - > pev - > avelocity ) // if the child isn't turning under its own power
{
UTIL_SetAngles ( pChild , vecAngles + pChild - > m_vecRotWithOffset , FALSE ) ;
}
else
{
vecTemp = vecDiff + pChild - > pev - > angles ;
UTIL_SetAngles ( pChild , vecTemp , FALSE ) ;
}
//ALERT(at_console," child origin becomes (%f %f %f)\n",pChild->pev->origin.x,pChild->pev->origin.y,pChild->pev->origin.z);
//ALERT(at_console,"ent %p has sibling %p\n",pChild,pChild->m_pSiblingMoveWith);
pChild = pChild - > m_pSiblingMoveWith ;
}
}
}
//LRC- an arbitrary limit. If this number is exceeded we assume there's an infinite loop, and abort.
# define MAX_MOVEWITH_DEPTH 100
//LRC- for use in supporting movewith. Tell the entity that whatever it's moving with is about to change velocity.
// loopbreaker is there to prevent the game from hanging...
void UTIL_SetMoveWithVelocity ( CBaseEntity * pEnt , const Vector vecSet , int loopbreaker )
{
if ( loopbreaker < = 0 )
{
ALERT ( at_error , " Infinite child list for MoveWith! " ) ;
return ;
}
if ( ! pEnt - > m_pMoveWith )
{
ALERT ( at_error , " SetMoveWithVelocity: no MoveWith entity!? \n " ) ;
return ;
}
Vector vecNew ;
// if (pEnt->pev->movetype == MOVETYPE_PUSH)
// {
// float fFraction =
vecNew = ( pEnt - > pev - > velocity - pEnt - > m_pMoveWith - > pev - > velocity ) + vecSet ;
// }
// else
// vecNew = vecSet; // lazy assumption: non-push entities don't move on their own.
// ALERT(at_console,"SetMoveWithVelocity: %s changes to (%f %f %f) (based on %f %f %f)\n",
// STRING(pEnt->pev->classname), vecNew.x, vecNew.y, vecNew.z,
// pEnt->m_pMoveWith->pev->velocity.x, pEnt->m_pMoveWith->pev->velocity.y, pEnt->m_pMoveWith->pev->velocity.z
// );
// ALERT(at_console,"SMWV: %s is sent (%f,%f,%f) - goes from (%f,%f,%f) to (%f,%f,%f)\n",
// STRING(pEnt->pev->targetname), vecSet.x, vecSet.y, vecSet.z,
// pEnt->pev->velocity.x, pEnt->pev->velocity.y, pEnt->pev->velocity.z,
// vecNew.x, vecNew.y, vecNew.z
// );
//LRC- velocity is ignored on entities that aren't thinking! (Aargh...)
// if (fThinkTime)
// {
// UTIL_DesiredNextThink( pEnt, fThinkTime );
// }
// else if (pEnt->pev->nextthink < 1)
// {
// UTIL_DesiredNextThink( pEnt, 1E6 );
// //pEnt->pev->nextthink = gpGlobals->time + 1E6;
// }
if ( pEnt - > m_pChildMoveWith )
{
CBaseEntity * pMoving = pEnt - > m_pChildMoveWith ;
int sloopbreaker = MAX_MOVEWITH_DEPTH ; // to prevent the game hanging...
while ( pMoving )
{
UTIL_SetMoveWithVelocity ( pMoving , vecNew , loopbreaker - 1 ) ;
pMoving = pMoving - > m_pSiblingMoveWith ;
sloopbreaker - - ;
if ( sloopbreaker < = 0 )
{
ALERT ( at_error , " SetMoveWithVelocity: Infinite sibling list for MoveWith! " ) ;
break ;
}
}
}
// if (bImmediate)
pEnt - > pev - > velocity = vecNew ;
// else
// UTIL_SetDesiredVel(pEnt, vecNew);
}
//LRC
void UTIL_SetVelocity ( CBaseEntity * pEnt , const Vector vecSet )
{
Vector vecNew ;
if ( pEnt - > m_pMoveWith )
vecNew = vecSet + pEnt - > m_pMoveWith - > pev - > velocity ;
else
vecNew = vecSet ;
// ALERT(at_console,"SetV: %s is sent (%f,%f,%f) - goes from (%f,%f,%f) to (%f,%f,%f)\n",
// STRING(pEnt->pev->targetname), vecSet.x, vecSet.y, vecSet.z,
// pEnt->pev->velocity.x, pEnt->pev->velocity.y, pEnt->pev->velocity.z,
// vecNew.x, vecNew.y, vecNew.z
// );
if ( pEnt - > m_pChildMoveWith )
{
CBaseEntity * pMoving = pEnt - > m_pChildMoveWith ;
int sloopbreaker = MAX_MOVEWITH_DEPTH ; // LRC - to save us from infinite loops
while ( pMoving )
{
UTIL_SetMoveWithVelocity ( pMoving , vecNew , MAX_MOVEWITH_DEPTH ) ;
pMoving = pMoving - > m_pSiblingMoveWith ;
sloopbreaker - - ;
if ( sloopbreaker < = 0 )
{
ALERT ( at_error , " SetVelocity: Infinite sibling list for MoveWith! \n " ) ;
break ;
}
}
}
pEnt - > pev - > velocity = vecNew ;
}
//LRC - one more MoveWith utility. This one's for the simple version of RotWith.
void UTIL_SetMoveWithAvelocity ( CBaseEntity * pEnt , const Vector vecSet , int loopbreaker )
{
if ( loopbreaker < = 0 )
{
ALERT ( at_error , " Infinite child list for MoveWith! " ) ;
return ;
}
if ( ! pEnt - > m_pMoveWith )
{
ALERT ( at_error , " SetMoveWithAvelocity: no MoveWith entity!? \n " ) ;
return ;
}
Vector vecNew = ( pEnt - > pev - > avelocity - pEnt - > m_pMoveWith - > pev - > avelocity ) + vecSet ;
// ALERT(at_console, "Setting Child AVelocity %f %f %f, was %f %f %f mw %f %f %f\n", vecNew.x, vecNew.y, vecNew.z, pEnt->pev->avelocity.x, pEnt->pev->avelocity.y, pEnt->pev->avelocity.z, pEnt->m_pMoveWith->pev->avelocity.x, pEnt->m_pMoveWith->pev->avelocity.y, pEnt->m_pMoveWith->pev->avelocity.z);
if ( pEnt - > m_pChildMoveWith )
{
CBaseEntity * pMoving = pEnt - > m_pChildMoveWith ;
int sloopbreaker = MAX_MOVEWITH_DEPTH ; // to prevent the game hanging...
while ( pMoving )
{
UTIL_SetMoveWithAvelocity ( pMoving , vecNew , loopbreaker - 1 ) ;
pMoving = pMoving - > m_pSiblingMoveWith ;
sloopbreaker - - ;
if ( sloopbreaker < = 0 )
{
ALERT ( at_error , " SetMoveWithVelocity: Infinite sibling list for MoveWith! " ) ;
break ;
}
}
}
//UTIL_SetDesiredAvelocity(pEnt, vecNew);
pEnt - > pev - > avelocity = vecNew ;
}
void UTIL_SetAvelocity ( CBaseEntity * pEnt , const Vector vecSet )
{
Vector vecNew ;
if ( pEnt - > m_pMoveWith )
vecNew = vecSet + pEnt - > m_pMoveWith - > pev - > avelocity ;
else
vecNew = vecSet ;
// ALERT(at_console, "Setting AVelocity %f %f %f\n", vecNew.x, vecNew.y, vecNew.z);
if ( pEnt - > m_pChildMoveWith )
{
CBaseEntity * pMoving = pEnt - > m_pChildMoveWith ;
int sloopbreaker = MAX_MOVEWITH_DEPTH ; // LRC - to save us from infinite loops
while ( pMoving )
{
UTIL_SetMoveWithAvelocity ( pMoving , vecNew , MAX_MOVEWITH_DEPTH ) ;
pMoving = pMoving - > m_pSiblingMoveWith ;
sloopbreaker - - ;
if ( sloopbreaker < = 0 )
{
ALERT ( at_error , " SetAvelocity: Infinite sibling list for MoveWith! \n " ) ;
break ;
}
}
}
//UTIL_SetDesiredAvelocity(pEnt, vecNew);
pEnt - > pev - > avelocity = vecNew ;
}