stvoy-sp-sdk/game/bg_pangles.cpp

338 lines
11 KiB
C++
Raw Normal View History

2002-11-22 00:00:00 +00:00
// define GAME_INCLUDE so that g_public.h does not define the
// short, server-visible gclient_t and gentity_t structures,
// because we define the full size ones in this file
#define GAME_INCLUDE
#include "q_shared.h"
#include "g_shared.h"
#include "bg_local.h"
#include "anims.h"
extern pmove_t *pm;
extern pml_t pml;
extern void PM_SetAnim(pmove_t *pm,int setAnimParts,int anim,int setAnimFlags);
void BG_CalculateOffsetAngles( gentity_t *ent, usercmd_t *ucmd )
{
if ( !ent->client )
return;
//These are the values we can set that will lock the legs and torso in place
if(ucmd->forwardmove || ucmd->rightmove)
{//When moving, always face all parts toward angles
//FIXME: What about strafing?
ent->client->renderInfo.torsoYawLockMode = LM_NONE; // center to catch up with head
ent->client->renderInfo.torsoPitchLockMode = LM_NONE; // center to catch up with head
ent->client->renderInfo.legsYawLockMode = LM_NONE; // center to catch up with head
}
else
{
// if standing still, only point all in the same direction if go beyond swing tolerance
// allow yaw to drift a bit
ent->client->renderInfo.torsoYawLockMode = LM_SWING;
ent->client->renderInfo.torsoPitchLockMode = LM_SWING;
ent->client->renderInfo.legsYawLockMode = LM_SWING;
}
if(!ent->NPC)
{
return;
}
//Additional mods to angles based on lookMode, if any
switch( ent->NPC->lookMode )
{
case LT_FULLFACE:
//Turn every part to full face the angles
ent->client->renderInfo.torsoYawLockMode = LM_NONE; // center to catch up with head
ent->client->renderInfo.torsoPitchLockMode = LM_NONE; // center to catch up with head
ent->client->renderInfo.legsYawLockMode = LM_NONE; // center to catch up with head
return;
break;
case LT_AIMSWING:
//Turn torso and head to point, allow legs to swing
ent->client->renderInfo.torsoYawLockMode = LM_NONE; // center to catch up with head
ent->client->renderInfo.torsoPitchLockMode = LM_NONE; // center to catch up with head
ent->client->renderInfo.legsYawLockMode = LM_SWING; // center to catch up with head
return;
break;
case LT_AIM:
//Turn torso and head to point, clamp legs
ent->client->renderInfo.torsoYawLockMode = LM_NONE; // center to catch up with head
ent->client->renderInfo.torsoPitchLockMode = LM_NONE; // center to catch up with head
ent->client->renderInfo.legsYawLockMode = LM_CLAMP; // center to catch up with head
return;
break;
case LT_NORMAL:
//Turn all toward direction, allow soft swing
ent->client->renderInfo.torsoYawLockMode = LM_SWING; // center to catch up with head
ent->client->renderInfo.torsoPitchLockMode = LM_SWING; // center to catch up with head
ent->client->renderInfo.legsYawLockMode = LM_SWING; // center to catch up with head
return;
break;
case LT_AIMSOFT:
//lock legs, turn tosro to general head angles
ent->client->renderInfo.torsoYawLockMode = LM_SWING; // center to catch up with head
ent->client->renderInfo.torsoPitchLockMode = LM_SWING; // center to catch up with head
ent->client->renderInfo.legsYawLockMode = LM_CLAMP; // center to catch up with head
return;
break;
case LT_GLANCE://Turn head only if possible
ent->client->renderInfo.torsoYawLockMode = LM_CLAMP; // center to catch up with head
ent->client->renderInfo.torsoPitchLockMode = LM_CLAMP; // center to catch up with head
ent->client->renderInfo.legsYawLockMode = LM_CLAMP; // center to catch up with head
return;
break;
case LT_NONE:
default:
//use the bstate below
break;
}
switch((int)ent->NPC->behaviorState)
{
case BS_FACE://Completely Face a new direction
case BS_POINT_AND_SHOOT://Aim at enemy and fire
case BS_FACE_ENEMY://Aim at enemy, don't fire
case BS_RUN_AND_SHOOT:
case BS_HUNT_AND_KILL:
ent->client->renderInfo.torsoYawLockMode = LM_NONE; // center to catch up with head
ent->client->renderInfo.torsoPitchLockMode = LM_NONE; // center to catch up with head
ent->client->renderInfo.legsYawLockMode = LM_NONE; // center to catch up with head
break;
case BS_STAND_AND_SHOOT://Stay in one spot and shoot- duck when neccesary
case BS_STAND_GUARD://Wait around for an enemy
case BS_AIM:
//case BS_COVER://35: Watch your coverTarg and shoot any enemy around him, laying down supressing fire
//Only aim torso/head at facing
ent->client->renderInfo.legsYawLockMode = LM_CLAMP; //Keep legs facing if possible
break;
case BS_LOOK:
case BS_SAY://36: Turn to sayTarg, use talk anim, say your sayString (look up string in your sounds table), exit tempBState when sound finished (anim of mouth should be timed to length of sound as well)
//Only look at facing with head
ent->client->renderInfo.torsoYawLockMode = LM_CLAMP; //Keep torso facing if possible
ent->client->renderInfo.torsoPitchLockMode = LM_CLAMP; //Keep torso facing if possible
ent->client->renderInfo.legsYawLockMode = LM_CLAMP; //Keep legs facing if possible
break;
case BS_FORMATION://Maintain a formation
if(!ucmd->forwardmove && !ucmd->rightmove)
{//Just standing around
ent->client->renderInfo.legsYawLockMode = LM_CLAMP; //Keep legs facing if possible
}
if(!(ucmd->buttons & BUTTON_ATTACK))
{//Looking around, not shooting
ent->client->renderInfo.torsoYawLockMode = LM_SWING; //Keep torso facing if possible
ent->client->renderInfo.torsoPitchLockMode = LM_SWING; //Keep torso facing if possible
}
break;
case BS_EVADE_AND_SHOOT://Run from enemies, shoot them if they hit you
case BS_MOVE://move in one dir, face another...
//case BS_RETREAT://34: Back away while still engaging enemy
//Does this mean shoot in one dir and move in another?
//???
break;
default:
//No changes
break;
}
}
/*
================
PM_UpdateViewAngles
This can be used as another entry point when only the viewangles
are being updated isntead of a full move
//FIXME: Now that they pmove twice per think, they snap-look really fast
================
*/
void PM_UpdateViewAngles( playerState_t *ps, usercmd_t *cmd, gentity_t *gent )
{
short temp, pitchClampMin, pitchClampMax;
float pitchMin=-75, pitchMax=75, yawMin=0, yawMax=0; //just to shut up warnings
int i;
vec3_t start, end, tmins, tmaxs, right;
trace_t trace;
qboolean lockedYaw = qfalse;
if ( ps->pm_type == PM_INTERMISSION )
{
return; // no view changes at all
}
if ( ps->pm_type != PM_SPECTATOR && ps->stats[STAT_HEALTH] <= 0 )
{
return; // no view changes at all
}
if ( ps->eFlags & EF_NPC && gent != NULL && gent->client != NULL )
{
if(gent->client->renderInfo.renderFlags & RF_LOCKEDANGLE)
{
pitchMin = 0 - gent->client->renderInfo.headPitchRangeUp - gent->client->renderInfo.torsoPitchRangeUp;
pitchMax = gent->client->renderInfo.headPitchRangeDown + gent->client->renderInfo.torsoPitchRangeDown;
yawMin = 0 - gent->client->renderInfo.headYawRangeLeft - gent->client->renderInfo.torsoYawRangeLeft;
yawMax = gent->client->renderInfo.headYawRangeRight + gent->client->renderInfo.torsoYawRangeRight;
lockedYaw = qtrue;
}
else
{
pitchMin = -gent->client->renderInfo.headPitchRangeUp;
pitchMax = gent->client->renderInfo.headPitchRangeDown;
}
}
pitchClampMin = ANGLE2SHORT(pitchMin);
pitchClampMax = ANGLE2SHORT(pitchMax);
// circularly clamp the angles with deltas
for (i=0 ; i<3 ; i++)
{
temp = cmd->angles[i] + ps->delta_angles[i];
if ( i == PITCH )
{
//FIXME get this limit from the NPCs stats?
// don't let the player look up or down more than 90 degrees
if ( temp > pitchClampMax )
{
ps->delta_angles[i] = pitchClampMax - cmd->angles[i];
temp = pitchClampMax;
}
else if ( temp < pitchClampMin )
{
ps->delta_angles[i] = pitchClampMin - cmd->angles[i];
temp = pitchClampMin;
}
}
//FIXME: Are we losing precision here? Is this why it jitters?
ps->viewangles[i] = SHORT2ANGLE(temp);
if ( i == YAW && lockedYaw)
{
// don't let the player look left or right more than the clamp, if any
if ( AngleSubtract(ps->viewangles[i], gent->client->renderInfo.lockYaw) > yawMax )
{
ps->viewangles[i] = yawMax;
}
else if ( AngleSubtract(ps->viewangles[i], gent->client->renderInfo.lockYaw) < yawMin )
{
ps->viewangles[i] = yawMin;
}
}
}
if ( (cmd->buttons & BUTTON_USE) && cmd->rightmove != 0 && !cmd->forwardmove && cmd->upmove <= 0 )
{//Only lean if holding use button, strafing and not moving forward or back and not jumping
if ( gent )
{
int leanofs = 0;
vec3_t viewangles;
if ( cmd->rightmove > 0 )
{
if((pm->ps->legsAnim&~ANIM_TOGGLEBIT) != LEGS_LEAN_RIGHT1)
{
PM_SetAnim(pm, SETANIM_LEGS, LEGS_LEAN_RIGHT1, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD);
}
pm->ps->legsAnimTimer = 500;//Force it to hold the anim for at least half a sec
if ( ps->leanofs <= 28 )
{
leanofs = ps->leanofs + 4;
}
else
{
leanofs = 32;
}
}
else
{
if ( (pm->ps->legsAnim&~ANIM_TOGGLEBIT) != LEGS_LEAN_LEFT1 )
{
PM_SetAnim(pm, SETANIM_LEGS, LEGS_LEAN_LEFT1, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD);
}
pm->ps->legsAnimTimer = 500;//Force it to hold the anim for at least half a sec
if ( ps->leanofs >= -28 )
{
leanofs = ps->leanofs - 4;
}
else
{
leanofs = -32;
}
}
VectorCopy( ps->origin, start );
start[2] += ps->viewheight;
VectorCopy( ps->viewangles, viewangles );
viewangles[ROLL] = 0;
AngleVectors( ps->viewangles, NULL, right, NULL );
VectorNormalize( right );
right[2] = (leanofs<0)?0.25:-0.25;
VectorMA( start, leanofs, right, end );
VectorSet( tmins, -8, -8, -4 );
VectorSet( tmaxs, 8, 8, 4 );
//if we don't trace EVERY frame, can TURN while leaning and
//end up leaning into solid architecture (sigh)
gi.trace( &trace, start, tmins, tmaxs, end, gent->s.number, MASK_PLAYERSOLID );
ps->leanofs = floor((float)leanofs * trace.fraction);
ps->leanStopDebounceTime = 20;
}
}
else
{
if ( gent && (cmd->forwardmove || cmd->upmove > 0) )
{
if( ((pm->ps->legsAnim&~ANIM_TOGGLEBIT) == LEGS_LEAN_RIGHT1) ||
((pm->ps->legsAnim&~ANIM_TOGGLEBIT) == LEGS_LEAN_LEFT1) )
{
pm->ps->legsAnimTimer = 0;//Force it to stop the anim
}
}
if ( ps->leanofs > 0 )
{
//FIXME: play lean anim backwards?
ps->leanofs-=4;
if ( ps->leanofs < 0 )
{
ps->leanofs = 0;
}
}
else if ( ps->leanofs < 0 )
{
//FIXME: play lean anim backwards?
ps->leanofs+=4;
if ( ps->leanofs > 0 )
{
ps->leanofs = 0;
}
}
}
if ( ps->leanStopDebounceTime )
{
ps->leanStopDebounceTime -= 1;
cmd->rightmove = 0;
cmd->buttons &= ~BUTTON_USE;
}
}