forked from FWGS/Paranoia2
692 lines
25 KiB
C++
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;
|
|
}
|