Paranoia2/dlls/movewith.cpp
2020-08-31 19:50:41 +03:00

692 lines
25 KiB
C++

#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_debug, "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_debug, "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_debug, "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_debug,"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_debug,"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;
}