codemp/game/bg_slidemove.c File Reference

#include "q_shared.h"
#include "bg_public.h"
#include "bg_local.h"
#include "../namespace_begin.h"
#include "../namespace_end.h"

Go to the source code of this file.

Defines

#define MAX_IMPACT_TURN_ANGLE   45.0f
#define MAX_CLIP_PLANES   5

Functions

qboolean BG_UnrestrainedPitchRoll (playerState_t *ps, Vehicle_t *pVeh)
void trap_FX_PlayEffectID (int id, vec3_t org, vec3_t fwd, int vol, int rad)
void PM_SetPMViewAngle (playerState_t *ps, vec3_t angle, usercmd_t *ucmd)
void PM_VehicleImpact (bgEntity_t *pEnt, trace_t *trace)
qboolean PM_GroundSlideOkay (float zNormal)
qboolean PM_SlideMove (qboolean gravity)
void PM_StepSlideMove (qboolean gravity)

Variables

bgEntity_tpm_entSelf
bgEntity_tpm_entVeh


Define Documentation

#define MAX_CLIP_PLANES   5
 

Definition at line 628 of file bg_slidemove.c.

Referenced by PM_SlideMove().

#define MAX_IMPACT_TURN_ANGLE   45.0f
 

Definition at line 47 of file bg_slidemove.c.

Referenced by PM_VehicleImpact().


Function Documentation

qboolean BG_UnrestrainedPitchRoll playerState_t ps,
Vehicle_t pVeh
 

Definition at line 7785 of file bg_pmove.c.

07786 {
07787         if ( bg_fighterAltControl.integer
07788                 && ps->clientNum < MAX_CLIENTS //real client
07789                 && ps->m_iVehicleNum//in a vehicle
07790                 && pVeh //valid vehicle data pointer
07791                 && pVeh->m_pVehicleInfo//valid vehicle info
07792                 && pVeh->m_pVehicleInfo->type == VH_FIGHTER )//fighter
07793                 //FIXME: specify per vehicle instead of assuming true for all fighters
07794                 //FIXME: map/server setting?
07795         {//can roll and pitch without limitation!
07796                 return qtrue;
07797         }
07798         return qfalse;
07799 }

qboolean PM_GroundSlideOkay float  zNormal  ) 
 

Definition at line 554 of file bg_slidemove.c.

References BG_InReboundJump(), BOTH_FORCELONGLEAP_ATTACK, BOTH_FORCELONGLEAP_LAND, BOTH_FORCELONGLEAP_START, BOTH_FORCEWALLRUNFLIP_START, BOTH_WALL_RUN_LEFT, BOTH_WALL_RUN_LEFT_STOP, BOTH_WALL_RUN_RIGHT, BOTH_WALL_RUN_RIGHT_STOP, playerState_s::legsAnim, pm, pmove_t::ps, qboolean, qfalse, qtrue, and playerState_s::velocity.

Referenced by PM_SlideMove().

00555 {
00556         if ( zNormal > 0 )
00557         {
00558                 if ( pm->ps->velocity[2] > 0 )
00559                 {
00560                         if ( pm->ps->legsAnim == BOTH_WALL_RUN_RIGHT
00561                                 || pm->ps->legsAnim == BOTH_WALL_RUN_LEFT 
00562                                 || pm->ps->legsAnim == BOTH_WALL_RUN_RIGHT_STOP
00563                                 || pm->ps->legsAnim == BOTH_WALL_RUN_LEFT_STOP 
00564                                 || pm->ps->legsAnim == BOTH_FORCEWALLRUNFLIP_START 
00565                                 || pm->ps->legsAnim == BOTH_FORCELONGLEAP_START
00566                                 || pm->ps->legsAnim == BOTH_FORCELONGLEAP_ATTACK
00567                                 || pm->ps->legsAnim == BOTH_FORCELONGLEAP_LAND
00568                                 || BG_InReboundJump( pm->ps->legsAnim ))
00569                         {
00570                                 return qfalse;
00571                         }
00572                 }
00573         }
00574         return qtrue;
00575 }

void PM_SetPMViewAngle playerState_t ps,
vec3_t  angle,
usercmd_t ucmd
 

Definition at line 1342 of file bg_pmove.c.

References ANGLE2SHORT, usercmd_s::angles, playerState_s::delta_angles, playerState_t, ucmd, usercmd_t, vec3_t, VectorCopy, and playerState_s::viewangles.

Referenced by PM_AdjustAngleForWallJump(), PM_AdjustAngleForWallRun(), PM_AdjustAngleForWallRunUp(), PM_AdjustAnglesForWallRunUpFlipAlt(), PM_VehFaceHyperspacePoint(), PM_VehForcedTurning(), PM_VehicleViewAngles(), and PmoveSingle().

01343 {
01344         int                     i;
01345 
01346         for (i=0 ; i<3 ; i++)
01347         { // set the delta angle
01348                 int             cmdAngle;
01349 
01350                 cmdAngle = ANGLE2SHORT(angle[i]);
01351                 ps->delta_angles[i] = cmdAngle - ucmd->angles[i];
01352         }
01353         VectorCopy (angle, ps->viewangles);
01354 }

qboolean PM_SlideMove qboolean  gravity  ) 
 

Definition at line 629 of file bg_slidemove.c.

References trace_t::allsolid, bgEntity_t, CLASS_VEHICLE, playerState_s::clientNum, DotProduct, trace_t::endpos, trace_t::entityNum, ET_NPC, entityState_s::eType, trace_t::fraction, pml_t::frametime, playerState_s::gravity, pml_t::groundPlane, pml_t::groundTrace, pml_t::impactSpeed, bgEntity_s::m_pVehicle, MAX_CLIENTS, MAX_CLIP_PLANES, pmove_t::maxs, pmove_t::mins, cplane_s::normal, entityState_s::NPC_class, playerState_s::origin, OVERCLIP, trace_t::plane, pm, PM_AddTouchEnt(), PM_ClipVelocity(), pm_entSelf, playerState_s::pm_flags, PM_GroundSlideOkay(), playerState_s::pm_time, PM_VehicleImpact(), PMF_STUCK_TO_WALL, pml, pmove_t::ps, qboolean, qtrue, bgEntity_s::s, pmove_t::trace, pmove_t::tracemask, vec3_t, VectorAdd, VectorClear, VectorCopy, VectorMA, VectorNormalize(), VectorNormalize2(), VectorScale, and playerState_s::velocity.

Referenced by PM_StepSlideMove().

00629                                                  {
00630         int                     bumpcount, numbumps;
00631         vec3_t          dir;
00632         float           d;
00633         int                     numplanes;
00634         vec3_t          normal, planes[MAX_CLIP_PLANES];
00635         vec3_t          primal_velocity;
00636         vec3_t          clipVelocity;
00637         int                     i, j, k;
00638         trace_t trace;
00639         vec3_t          end;
00640         float           time_left;
00641         float           into;
00642         vec3_t          endVelocity;
00643         vec3_t          endClipVelocity;
00644         //qboolean      damageSelf = qtrue;
00645         
00646         numbumps = 4;
00647 
00648         VectorCopy (pm->ps->velocity, primal_velocity);
00649 
00650         if ( gravity ) {
00651                 VectorCopy( pm->ps->velocity, endVelocity );
00652                 endVelocity[2] -= pm->ps->gravity * pml.frametime;
00653                 pm->ps->velocity[2] = ( pm->ps->velocity[2] + endVelocity[2] ) * 0.5;
00654                 primal_velocity[2] = endVelocity[2];
00655                 if ( pml.groundPlane ) {
00656                         if ( PM_GroundSlideOkay( pml.groundTrace.plane.normal[2] ) )
00657                         {// slide along the ground plane
00658                                 PM_ClipVelocity (pm->ps->velocity, pml.groundTrace.plane.normal, 
00659                                         pm->ps->velocity, OVERCLIP );
00660                         }
00661                 }
00662         }
00663 
00664         time_left = pml.frametime;
00665 
00666         // never turn against the ground plane
00667         if ( pml.groundPlane ) {
00668                 numplanes = 1;
00669                 VectorCopy( pml.groundTrace.plane.normal, planes[0] );
00670                 if ( !PM_GroundSlideOkay( planes[0][2] ) )
00671                 {
00672                         planes[0][2] = 0;
00673                         VectorNormalize( planes[0] );
00674                 }
00675         } else {
00676                 numplanes = 0;
00677         }
00678 
00679         // never turn against original velocity
00680         VectorNormalize2( pm->ps->velocity, planes[numplanes] );
00681         numplanes++;
00682 
00683         for ( bumpcount=0 ; bumpcount < numbumps ; bumpcount++ ) {
00684 
00685                 // calculate position we are trying to move to
00686                 VectorMA( pm->ps->origin, time_left, pm->ps->velocity, end );
00687 
00688                 // see if we can make it there
00689                 pm->trace ( &trace, pm->ps->origin, pm->mins, pm->maxs, end, pm->ps->clientNum, pm->tracemask);
00690 
00691                 if (trace.allsolid) {
00692                         // entity is completely trapped in another solid
00693                         pm->ps->velocity[2] = 0;        // don't build up falling damage, but allow sideways acceleration
00694                         return qtrue;
00695                 }
00696 
00697                 if (trace.fraction > 0) {
00698                         // actually covered some distance
00699                         VectorCopy (trace.endpos, pm->ps->origin);
00700                 }
00701 
00702                 if (trace.fraction == 1) {
00703                          break;         // moved the entire distance
00704                 }
00705 
00706                 // save entity for contact
00707                 PM_AddTouchEnt( trace.entityNum );
00708 
00709                 if (pm->ps->clientNum >= MAX_CLIENTS)
00710                 {
00711                         bgEntity_t *pEnt = pm_entSelf;
00712 
00713                         if (pEnt && pEnt->s.eType == ET_NPC && pEnt->s.NPC_class == CLASS_VEHICLE &&
00714                                 pEnt->m_pVehicle)
00715                         { //do vehicle impact stuff then
00716                                 PM_VehicleImpact(pEnt, &trace);
00717                         }
00718                 }
00719 #ifdef QAGAME
00720                 else
00721                 {
00722                         if ( PM_ClientImpact( &trace ) )
00723                         {
00724                                 continue;
00725                         }
00726                 }
00727 #endif
00728 
00729                 time_left -= time_left * trace.fraction;
00730 
00731                 if (numplanes >= MAX_CLIP_PLANES) {
00732                         // this shouldn't really happen
00733                         VectorClear( pm->ps->velocity );
00734                         return qtrue;
00735                 }
00736 
00737                 VectorCopy( trace.plane.normal, normal );
00738 
00739                 if ( !PM_GroundSlideOkay( normal[2] ) )
00740                 {//wall-running
00741                         //never push up off a sloped wall
00742                         normal[2] = 0;
00743                         VectorNormalize( normal );
00744                 }
00745                 //
00746                 // if this is the same plane we hit before, nudge velocity
00747                 // out along it, which fixes some epsilon issues with
00748                 // non-axial planes
00749                 //
00750                 if ( !(pm->ps->pm_flags&PMF_STUCK_TO_WALL) )
00751                 {//no sliding if stuck to wall!
00752                         for ( i = 0 ; i < numplanes ; i++ ) {
00753                                 if ( VectorCompare( normal, planes[i] ) ) {//DotProduct( normal, planes[i] ) > 0.99 ) {
00754                                         VectorAdd( normal, pm->ps->velocity, pm->ps->velocity );
00755                                         break;
00756                                 }
00757                         }
00758                         if ( i < numplanes ) {
00759                                 continue;
00760                         }
00761                 }
00762                 VectorCopy (normal, planes[numplanes]);
00763                 numplanes++;
00764 
00765                 //
00766                 // modify velocity so it parallels all of the clip planes
00767                 //
00768 
00769                 // find a plane that it enters
00770                 for ( i = 0 ; i < numplanes ; i++ ) {
00771                         into = DotProduct( pm->ps->velocity, planes[i] );
00772                         if ( into >= 0.1 ) {
00773                                 continue;               // move doesn't interact with the plane
00774                         }
00775 
00776                         // see how hard we are hitting things
00777                         if ( -into > pml.impactSpeed ) {
00778                                 pml.impactSpeed = -into;
00779                         }
00780 
00781                         // slide along the plane
00782                         PM_ClipVelocity (pm->ps->velocity, planes[i], clipVelocity, OVERCLIP );
00783 
00784                         // slide along the plane
00785                         PM_ClipVelocity (endVelocity, planes[i], endClipVelocity, OVERCLIP );
00786 
00787                         // see if there is a second plane that the new move enters
00788                         for ( j = 0 ; j < numplanes ; j++ ) {
00789                                 if ( j == i ) {
00790                                         continue;
00791                                 }
00792                                 if ( DotProduct( clipVelocity, planes[j] ) >= 0.1 ) {
00793                                         continue;               // move doesn't interact with the plane
00794                                 }
00795 
00796                                 // try clipping the move to the plane
00797                                 PM_ClipVelocity( clipVelocity, planes[j], clipVelocity, OVERCLIP );
00798                                 PM_ClipVelocity( endClipVelocity, planes[j], endClipVelocity, OVERCLIP );
00799 
00800                                 // see if it goes back into the first clip plane
00801                                 if ( DotProduct( clipVelocity, planes[i] ) >= 0 ) {
00802                                         continue;
00803                                 }
00804 
00805                                 // slide the original velocity along the crease
00806                                 CrossProduct (planes[i], planes[j], dir);
00807                                 VectorNormalize( dir );
00808                                 d = DotProduct( dir, pm->ps->velocity );
00809                                 VectorScale( dir, d, clipVelocity );
00810 
00811                                 CrossProduct (planes[i], planes[j], dir);
00812                                 VectorNormalize( dir );
00813                                 d = DotProduct( dir, endVelocity );
00814                                 VectorScale( dir, d, endClipVelocity );
00815 
00816                                 // see if there is a third plane the the new move enters
00817                                 for ( k = 0 ; k < numplanes ; k++ ) {
00818                                         if ( k == i || k == j ) {
00819                                                 continue;
00820                                         }
00821                                         if ( DotProduct( clipVelocity, planes[k] ) >= 0.1 ) {
00822                                                 continue;               // move doesn't interact with the plane
00823                                         }
00824 
00825                                         // stop dead at a triple plane interaction
00826                                         VectorClear( pm->ps->velocity );
00827                                         return qtrue;
00828                                 }
00829                         }
00830 
00831                         // if we have fixed all interactions, try another move
00832                         VectorCopy( clipVelocity, pm->ps->velocity );
00833                         VectorCopy( endClipVelocity, endVelocity );
00834                         break;
00835                 }
00836         }
00837 
00838         if ( gravity ) {
00839                 VectorCopy( endVelocity, pm->ps->velocity );
00840         }
00841 
00842         // don't change velocity if in a timer (FIXME: is this correct?)
00843         if ( pm->ps->pm_time ) {
00844                 VectorCopy( primal_velocity, pm->ps->velocity );
00845         }
00846 
00847         return ( bumpcount != 0 );
00848 }

void PM_StepSlideMove qboolean  gravity  ) 
 

Definition at line 856 of file bg_slidemove.c.

References trace_t::allsolid, BG_InReboundHold(), bgEntity_t, c_pmove, CLASS_ATST, CLASS_RANCOR, CLASS_VEHICLE, playerState_s::clientNum, Com_Printf(), pmove_t::debugLevel, DotProduct, trace_t::endpos, trace_t::entityNum, EV_STEP_12, EV_STEP_16, EV_STEP_4, EV_STEP_8, trace_t::fraction, vehicleInfo_t::hoverHeight, playerState_s::legsAnim, bgEntity_s::m_pVehicle, Vehicle_s::m_pVehicleInfo, MAX_CLIENTS, pmove_t::maxs, MIN_WALK_NORMAL, pmove_t::mins, cplane_s::normal, entityState_s::NPC_class, playerState_s::origin, OVERCLIP, trace_t::plane, pm, PM_AddEvent(), PM_ClipVelocity(), pm_entSelf, PM_SlideMove(), pmove_t::ps, qboolean, qfalse, qtrue, bgEntity_s::s, STEPSIZE, pmove_t::stepSlideFix, pmove_t::trace, pmove_t::tracemask, vehicleInfo_t::type, vec3_t, VectorCopy, VectorNormalize(), VectorSet, VectorSubtract, playerState_s::velocity, and VH_WALKER.

00856                                           { 
00857         vec3_t          start_o, start_v;
00858         vec3_t          down_o, down_v;
00859         trace_t         trace;
00860 //      float           down_dist, up_dist;
00861 //      vec3_t          delta, delta2;
00862         vec3_t          up, down;
00863         float           stepSize;
00864         qboolean        isGiant = qfalse;
00865         bgEntity_t      *pEnt;
00866         qboolean skipStep = qfalse;
00867 
00868         VectorCopy (pm->ps->origin, start_o);
00869         VectorCopy (pm->ps->velocity, start_v);
00870 
00871         if ( BG_InReboundHold( pm->ps->legsAnim ) )
00872         {
00873                 gravity = qfalse;
00874         }
00875 
00876         if ( PM_SlideMove( gravity ) == 0 ) {
00877                 return;         // we got exactly where we wanted to go first try       
00878         }
00879 
00880         pEnt = pm_entSelf;
00881 
00882         if (pm->ps->clientNum >= MAX_CLIENTS)
00883         {
00884                 if (pEnt && pEnt->s.NPC_class == CLASS_VEHICLE &&
00885                         pEnt->m_pVehicle && pEnt->m_pVehicle->m_pVehicleInfo->hoverHeight > 0)
00886                 {
00887                         return;
00888                 }
00889         }
00890 
00891         VectorCopy(start_o, down);
00892         down[2] -= STEPSIZE;
00893         pm->trace (&trace, start_o, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask);
00894         VectorSet(up, 0, 0, 1);
00895         // never step up when you still have up velocity
00896         if ( pm->ps->velocity[2] > 0 && (trace.fraction == 1.0 ||
00897                                                                                 DotProduct(trace.plane.normal, up) < 0.7))
00898         {
00899                 return;
00900         }
00901 
00902         VectorCopy (pm->ps->origin, down_o);
00903         VectorCopy (pm->ps->velocity, down_v);
00904 
00905         VectorCopy (start_o, up);
00906 
00907         if (pm->ps->clientNum >= MAX_CLIENTS)
00908         {
00909                 // apply ground friction, even if on ladder
00910                 if (pEnt &&
00911                         pEnt->s.NPC_class == CLASS_ATST ||
00912                                 (pEnt->s.NPC_class == CLASS_VEHICLE &&
00913                                         pEnt->m_pVehicle &&
00914                                         pEnt->m_pVehicle->m_pVehicleInfo->type == VH_WALKER)
00915                         )
00916                 {//AT-STs can step high
00917                         up[2] += 66.0f;
00918                         isGiant = qtrue;
00919                 }
00920                 else if ( pEnt && pEnt->s.NPC_class == CLASS_RANCOR )
00921                 {//also can step up high
00922                         up[2] += 64.0f;
00923                         isGiant = qtrue;
00924                 }
00925                 else
00926                 {
00927                         up[2] += STEPSIZE;
00928                 }
00929         }
00930         else
00931         {
00932                 up[2] += STEPSIZE;
00933         }
00934 
00935         // test the player position if they were a stepheight higher
00936         pm->trace (&trace, start_o, pm->mins, pm->maxs, up, pm->ps->clientNum, pm->tracemask);
00937         if ( trace.allsolid ) {
00938                 if ( pm->debugLevel ) {
00939                         Com_Printf("%i:bend can't step\n", c_pmove);
00940                 }
00941                 return;         // can't step up
00942         }
00943 
00944         stepSize = trace.endpos[2] - start_o[2];
00945         // try slidemove from this position
00946         VectorCopy (trace.endpos, pm->ps->origin);
00947         VectorCopy (start_v, pm->ps->velocity);
00948 
00949         PM_SlideMove( gravity );
00950 
00951         // push down the final amount
00952         VectorCopy (pm->ps->origin, down);
00953         down[2] -= stepSize;
00954         pm->trace (&trace, pm->ps->origin, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask);
00955 
00956         if ( pm->stepSlideFix )
00957         {
00958                 if ( pm->ps->clientNum < MAX_CLIENTS
00959                         && trace.plane.normal[2] < MIN_WALK_NORMAL )
00960                 {//normal players cannot step up slopes that are too steep to walk on!
00961                         vec3_t stepVec;
00962                         //okay, the step up ends on a slope that it too steep to step up onto,
00963                         //BUT:
00964                         //If the step looks like this:
00965                         //  (B)\__
00966                         //        \_____(A)
00967                         //Then it might still be okay, so we figure out the slope of the entire move
00968                         //from (A) to (B) and if that slope is walk-upabble, then it's okay
00969                         VectorSubtract( trace.endpos, down_o, stepVec );
00970                         VectorNormalize( stepVec ); 
00971                         if ( stepVec[2] > (1.0f-MIN_WALK_NORMAL) )
00972                         {
00973                                 skipStep = qtrue;
00974                         }
00975                 }
00976         }
00977 
00978         if ( !trace.allsolid 
00979                 && !skipStep ) //normal players cannot step up slopes that are too steep to walk on!
00980         { 
00981                 if ( pm->ps->clientNum >= MAX_CLIENTS//NPC
00982                         && isGiant 
00983                         && trace.entityNum < MAX_CLIENTS
00984                         && pEnt 
00985                         && pEnt->s.NPC_class == CLASS_RANCOR )
00986                 {//Rancor don't step on clients
00987                         if ( pm->stepSlideFix )
00988                         {
00989                                 VectorCopy (down_o, pm->ps->origin);
00990                                 VectorCopy (down_v, pm->ps->velocity);
00991                         }
00992                         else
00993                         {
00994                                 VectorCopy (start_o, pm->ps->origin);
00995                                 VectorCopy (start_v, pm->ps->velocity);
00996                         }
00997                 }
00998                 /*
00999                 else if ( pm->ps->clientNum >= MAX_CLIENTS//NPC
01000                         && isGiant 
01001                         && trace.entityNum < MAX_CLIENTS
01002                         && pEnt 
01003                         && pEnt->s.NPC_class == CLASS_ATST 
01004                         && OnSameTeam( pEnt, traceEnt) )
01005                 {//NPC AT-ST's don't step up on allies
01006                         VectorCopy (start_o, pm->ps->origin);
01007                         VectorCopy (start_v, pm->ps->velocity);
01008                 }
01009                 */
01010                 else
01011                 {
01012                         VectorCopy (trace.endpos, pm->ps->origin);
01013                         if ( pm->stepSlideFix )
01014                         {
01015                                 if ( trace.fraction < 1.0 ) {
01016                                         PM_ClipVelocity( pm->ps->velocity, trace.plane.normal, pm->ps->velocity, OVERCLIP );
01017                                 }
01018                         }
01019                 }
01020         }
01021         else
01022         {
01023                 if ( pm->stepSlideFix )
01024                 {
01025                         VectorCopy (down_o, pm->ps->origin);
01026                         VectorCopy (down_v, pm->ps->velocity);
01027                 }
01028         }
01029         if ( !pm->stepSlideFix )
01030         {
01031                 if ( trace.fraction < 1.0 ) {
01032                         PM_ClipVelocity( pm->ps->velocity, trace.plane.normal, pm->ps->velocity, OVERCLIP );
01033                 }
01034         }
01035 
01036 #if 0
01037         // if the down trace can trace back to the original position directly, don't step
01038         pm->trace( &trace, pm->ps->origin, pm->mins, pm->maxs, start_o, pm->ps->clientNum, pm->tracemask);
01039         if ( trace.fraction == 1.0 ) {
01040                 // use the original move
01041                 VectorCopy (down_o, pm->ps->origin);
01042                 VectorCopy (down_v, pm->ps->velocity);
01043                 if ( pm->debugLevel ) {
01044                         Com_Printf("%i:bend\n", c_pmove);
01045                 }
01046         } else 
01047 #endif
01048         {
01049                 // use the step move
01050                 float   delta;
01051 
01052                 delta = pm->ps->origin[2] - start_o[2];
01053                 if ( delta > 2 ) {
01054                         if ( delta < 7 ) {
01055                                 PM_AddEvent( EV_STEP_4 );
01056                         } else if ( delta < 11 ) {
01057                                 PM_AddEvent( EV_STEP_8 );
01058                         } else if ( delta < 15 ) {
01059                                 PM_AddEvent( EV_STEP_12 );
01060                         } else {
01061                                 PM_AddEvent( EV_STEP_16 );
01062                         }
01063                 }
01064                 if ( pm->debugLevel ) {
01065                         Com_Printf("%i:stepped\n", c_pmove);
01066                 }
01067         }
01068 }

void PM_VehicleImpact bgEntity_t pEnt,
trace_t trace
 

Definition at line 48 of file bg_slidemove.c.

References AngleNormalize180(), AnglesSubtract(), AngleVectors(), entityState_s::apos, BG_KnockDownable(), bgEntity_t, entityShared_t::bmodel, CLASS_VEHICLE, gentity_s::classname, gentity_s::client, pmove_t::cmd, DAMAGE_NO_ARMOR, DotProduct, trace_t::entityNum, ENTITYNUM_WORLD, ET_MISSILE, ET_MOVER, ET_NPC, ET_PLAYER, ET_TERRAIN, entityState_s::eType, EV_PLAY_EFFECT_ID, fabs(), FighterIsLanded(), trace_t::fraction, pml_t::frametime, G_AddEvent(), G_CanBeEnemy(), G_Damage(), g_entities, gentity_t, HANDEXTEND_KNOCKDOWN, vehicleInfo_t::iImpactFX, gentity_s::inuse, level, Vehicle_s::m_fTimeModifier, Vehicle_s::m_iHitDebounce, Vehicle_s::m_iLastImpactDmg, Vehicle_s::m_iRemovedSurfaces, Vehicle_s::m_LandTrace, Vehicle_s::m_pParentEntity, Vehicle_s::m_pPilot, bgEntity_s::m_pVehicle, Vehicle_s::m_pVehicleInfo, Vehicle_s::m_ulFlags, Vehicle_s::m_vFullAngleVelocity, Vehicle_s::m_vOrientation, vehicleInfo_t::mass, MAX_CLIENTS, MAX_IMPACT_TURN_ANGLE, MIN_LANDING_SLOPE, MIN_LANDING_SPEED, MOD_FALLING, MOD_MELEE, cplane_s::normal, entityState_s::NPC_class, NULL, entityState_s::number, entityState_s::origin, playerState_s::origin, playerState_s::otherKiller, playerState_s::otherKillerTime, entityState_s::owner, entityShared_t::ownerNum, PITCH, trace_t::plane, pm, PM_BGEntForNum(), pml, gclient_s::ps, pmove_t::ps, Q_stricmp(), qboolean, qfalse, qtrue, gentity_s::r, ROLL, bgEntity_s::s, gentity_s::s, usercmd_s::serverTime, entityState_s::solid, SOLID_BMODEL, gentity_s::spawnflags, entityState_s::speed, playerState_s::speed, vehicleInfo_t::surfDestruction, level_locals_t::time, vehicleInfo_t::toughness, TR_STATIONARY, trap_FX_PlayEffectID(), trajectory_t::trType, vehicleInfo_t::type, vec3_origin, vec3_t, vectoangles(), VectorAdd, VectorCopy, VectorNormalize(), VectorNormalize2(), VectorScale, VectorSubtract, VEH_CRASHING, Vehicle_t, playerState_s::velocity, VH_FIGHTER, VH_SPEEDER, and YAW.

Referenced by PM_SlideMove().

00049 {
00050         // See if the vehicle has crashed into the ground.
00051         Vehicle_t *pSelfVeh = pEnt->m_pVehicle;
00052         float magnitude = VectorLength( pm->ps->velocity ) * pSelfVeh->m_pVehicleInfo->mass / 50.0f;
00053         qboolean forceSurfDestruction = qfalse;
00054 #ifdef QAGAME
00055         gentity_t *hitEnt = trace!=NULL?&g_entities[trace->entityNum]:NULL;
00056 
00057         if (!hitEnt || 
00058                 (pSelfVeh && pSelfVeh->m_pPilot &&
00059                 hitEnt && hitEnt->s.eType == ET_MISSILE && hitEnt->inuse &&
00060                 hitEnt->r.ownerNum == pSelfVeh->m_pPilot->s.number)
00061                 )
00062         { 
00063                 return;
00064         }
00065 
00066         if ( pSelfVeh//I have a vehicle struct
00067                 && pSelfVeh->m_iRemovedSurfaces )//vehicle has bits removed
00068         {//spiralling to our deaths, explode on any solid impact
00069                 if ( hitEnt->s.NPC_class == CLASS_VEHICLE )
00070                 {//hit another vehicle, explode!
00071                         //Give credit to whoever got me into this death spiral state
00072                         gentity_t *parent = (gentity_t *)pSelfVeh->m_pParentEntity;
00073                         gentity_t *killer = NULL;
00074                         if (parent->client->ps.otherKiller < ENTITYNUM_WORLD &&
00075                                 parent->client->ps.otherKillerTime > level.time)
00076                         {
00077                                 gentity_t *potentialKiller = &g_entities[parent->client->ps.otherKiller];
00078 
00079                                 if (potentialKiller->inuse && potentialKiller->client)
00080                                 { //he's valid I guess
00081                                         killer = potentialKiller;
00082                                 }
00083                         }
00084                         //FIXME: damage hitEnt, some, too?  Our explosion should hurt them some, but...
00085                         G_Damage( (gentity_t *)pEnt, killer, killer, NULL, pm->ps->origin, 999999, DAMAGE_NO_ARMOR, MOD_FALLING );//FIXME: MOD_IMPACT
00086                         return;
00087                 }
00088                 else if ( !VectorCompare( trace->plane.normal, vec3_origin )
00089                         && (trace->entityNum == ENTITYNUM_WORLD || hitEnt->r.bmodel ) )
00090                 {//have a valid hit plane and we hit a solid brush
00091                         vec3_t  moveDir;
00092                         float   impactDot;
00093                         VectorCopy( pm->ps->velocity, moveDir );
00094                         VectorNormalize( moveDir );
00095                         impactDot = DotProduct( moveDir, trace->plane.normal );
00096                         if ( impactDot <= -0.7f )//hit rather head-on and hard
00097                         {// Just DIE now
00098                                 //Give credit to whoever got me into this death spiral state
00099                                 gentity_t *parent = (gentity_t *)pSelfVeh->m_pParentEntity;
00100                                 gentity_t *killer = NULL;
00101                                 if (parent->client->ps.otherKiller < ENTITYNUM_WORLD &&
00102                                         parent->client->ps.otherKillerTime > level.time)
00103                                 {
00104                                         gentity_t *potentialKiller = &g_entities[parent->client->ps.otherKiller];
00105 
00106                                         if (potentialKiller->inuse && potentialKiller->client)
00107                                         { //he's valid I guess
00108                                                 killer = potentialKiller;
00109                                         }
00110                                 }
00111                                 G_Damage( (gentity_t *)pEnt, killer, killer, NULL, pm->ps->origin, 999999, DAMAGE_NO_ARMOR, MOD_FALLING );//FIXME: MOD_IMPACT
00112                                 return;
00113                         }
00114                 }
00115         }
00116         
00117         if ( trace->entityNum < ENTITYNUM_WORLD
00118                 && hitEnt->s.eType == ET_MOVER
00119                 && hitEnt->s.apos.trType != TR_STATIONARY//rotating
00120                 && (hitEnt->spawnflags&16) //IMPACT
00121                 && Q_stricmp( "func_rotating", hitEnt->classname ) == 0 )
00122         {//hit a func_rotating that is supposed to destroy anything it touches!
00123                 //guarantee the hit will happen, thereby taking off a piece of the ship
00124                 forceSurfDestruction = qtrue;
00125         }
00126         else if ( (fabs(pm->ps->velocity[0])+fabs(pm->ps->velocity[1])) < 100.0f
00127                 && pm->ps->velocity[2] > -100.0f )
00128 #else
00129         if ( (fabs(pm->ps->velocity[0])+fabs(pm->ps->velocity[1])) < 100.0f
00130                 && pm->ps->velocity[2] > -100.0f )
00131 #endif
00132                 /*
00133         if ( (pSelfVeh->m_ulFlags&VEH_GEARSOPEN) 
00134                 && trace->plane.normal[2] > 0.7f
00135                 && fabs(pSelfVeh->m_vOrientation[PITCH]) < 0.2f
00136                 && fabs(pSelfVeh->m_vOrientation[ROLL]) < 0.2f )*/
00137         {//we're landing, we're cool
00138                 //FIXME: some sort of landing "thump", not the impactFX
00139                 /*
00140                 if ( pSelfVeh->m_pVehicleInfo->iImpactFX )
00141                 {
00142                         vec3_t up = {0,0,1};
00143 #ifdef QAGAME
00144                         G_PlayEffectID( pSelfVeh->m_pVehicleInfo->iImpactFX, pm->ps->origin, up );
00145 #else
00146                         trap_FX_PlayEffectID( pSelfVeh->m_pVehicleInfo->iImpactFX, pm->ps->origin, up, -1, -1 );
00147 #endif
00148                 }
00149                 */
00150                 //this was annoying me -rww
00151                 //FIXME: this shouldn't even be getting called when the vehicle is at rest!
00152 #ifdef QAGAME
00153                 if (hitEnt && (hitEnt->s.eType == ET_PLAYER || hitEnt->s.eType == ET_NPC) && pSelfVeh->m_pVehicleInfo->type == VH_FIGHTER)
00154                 { //always smack players
00155                 }
00156                 else
00157 #endif
00158                 {
00159                         return;
00160                 }
00161         }
00162         if ( pSelfVeh &&
00163                 (pSelfVeh->m_pVehicleInfo->type == VH_SPEEDER || pSelfVeh->m_pVehicleInfo->type == VH_FIGHTER) && //this is kind of weird on tauntauns and atst's..
00164                 (magnitude >= 100||forceSurfDestruction) )
00165         {
00166                 if ( pEnt->m_pVehicle->m_iHitDebounce < pm->cmd.serverTime 
00167                         || forceSurfDestruction )
00168                 {//a bit of a hack, may conflict with getting shot, but...
00169                         //FIXME: impact sound and effect should be gotten from g_vehicleInfo...?
00170                         //FIXME: should pass in trace.endpos and trace.plane.normal
00171                         vec3_t  vehUp;
00172 #ifndef QAGAME
00173                         bgEntity_t *hitEnt;
00174 #endif
00175 
00176                         if ( trace && !pSelfVeh->m_iRemovedSurfaces && !forceSurfDestruction )
00177                         {
00178                                 qboolean turnFromImpact = qfalse, turnHitEnt = qfalse;
00179                                 float l = pm->ps->speed*0.5f;
00180                                 vec3_t  bounceDir;
00181 #ifndef QAGAME
00182                                 bgEntity_t *hitEnt = PM_BGEntForNum(trace->entityNum);
00183 #endif
00184                                 if ( (trace->entityNum == ENTITYNUM_WORLD || hitEnt->s.solid == SOLID_BMODEL)//bounce off any brush
00185                                          && !VectorCompare(trace->plane.normal, vec3_origin) )//have a valid plane to bounce off of
00186                                 { //bounce off in the opposite direction of the impact
00187                                         if (pSelfVeh->m_pVehicleInfo->type == VH_SPEEDER)
00188                                         {
00189                                                 pm->ps->speed *= pml.frametime;
00190                                                 VectorCopy(trace->plane.normal, bounceDir);
00191                                         }
00192                                         else if ( trace->plane.normal[2] >= MIN_LANDING_SLOPE//flat enough to land on
00193                                                 && pSelfVeh->m_LandTrace.fraction < 1.0f //ground present
00194                                                 && pm->ps->speed <= MIN_LANDING_SPEED )
00195                                         {//could land here, don't bounce off, in fact, return altogether!
00196                                                 return;
00197                                         }
00198                                         else
00199                                         {
00200                                                 if (pSelfVeh->m_pVehicleInfo->type == VH_FIGHTER)
00201                                                 {
00202                                                         turnFromImpact = qtrue;
00203                                                 }
00204                                                 VectorCopy(trace->plane.normal, bounceDir);
00205                                         }
00206                                 }
00207                                 else if ( pSelfVeh->m_pVehicleInfo->type == VH_FIGHTER )
00208                                 {//check for impact with another fighter
00209 #ifndef QAGAME
00210                                         bgEntity_t *hitEnt = PM_BGEntForNum(trace->entityNum);
00211 #endif
00212                                         if ( hitEnt->s.NPC_class == CLASS_VEHICLE
00213                                                 && hitEnt->m_pVehicle 
00214                                                 && hitEnt->m_pVehicle->m_pVehicleInfo
00215                                                 && hitEnt->m_pVehicle->m_pVehicleInfo->type == VH_FIGHTER )
00216                                         {//two vehicles hit each other, turn away from the impact
00217                                                 turnFromImpact = qtrue;
00218                                                 turnHitEnt = qtrue;
00219 #ifndef QAGAME
00220                                                 VectorSubtract( pm->ps->origin, hitEnt->s.origin, bounceDir );
00221 #else
00222                                                 VectorSubtract( pm->ps->origin, hitEnt->r.currentOrigin, bounceDir );
00223 #endif
00224                                                 VectorNormalize( bounceDir );
00225                                         }
00226                                 }
00227                                 if ( turnFromImpact )
00228                                 {//bounce off impact surf and turn away
00229                                         vec3_t  pushDir={0}, turnAwayAngles, turnDelta;
00230                                         float   turnStrength, pitchTurnStrength, yawTurnStrength;
00231                                         vec3_t  moveDir;
00232                                         float bounceDot, turnDivider;
00233                                         //bounce
00234                                         if ( !turnHitEnt )
00235                                         {//hit wall
00236                                                 VectorScale(bounceDir, (pm->ps->speed*0.25f/pSelfVeh->m_pVehicleInfo->mass), pushDir);
00237                                         }
00238                                         else
00239                                         {//hit another fighter
00240 #ifndef QAGAME
00241                                                 VectorScale( bounceDir, (pm->ps->speed+hitEnt->s.speed)*0.5f, bounceDir );
00242 #else
00243                                                 if ( hitEnt->client )
00244                                                 {
00245                                                         VectorScale( bounceDir, (pm->ps->speed+hitEnt->client->ps.speed)*0.5f, pushDir );
00246                                                 }
00247                                                 else
00248                                                 {
00249                                                         VectorScale( bounceDir, (pm->ps->speed+hitEnt->s.speed)*0.5f, pushDir );
00250                                                 }
00251 #endif
00252                                                 VectorScale(pushDir, (l/pSelfVeh->m_pVehicleInfo->mass), pushDir);
00253                                                 VectorScale(pushDir, 0.1f, pushDir);
00254                                         }
00255                                         VectorNormalize2( pm->ps->velocity, moveDir );
00256                                         bounceDot = DotProduct( moveDir, bounceDir )*-1;
00257                                         if ( bounceDot < 0.1f )
00258                                         {
00259                                                 bounceDot = 0.1f;
00260                                         }
00261                                         VectorScale( pushDir, bounceDot, pushDir );
00262                                         VectorAdd(pm->ps->velocity, pushDir, pm->ps->velocity);
00263                                         //turn
00264                                         turnDivider = (pSelfVeh->m_pVehicleInfo->mass/400.0f);
00265                                         if ( turnHitEnt )
00266                                         {//don't turn as much when hit another ship
00267                                                 turnDivider *= 4.0f;
00268                                         }
00269                                         if ( turnDivider < 0.5f )
00270                                         {
00271                                                 turnDivider = 0.5f;
00272                                         }
00273                                         turnStrength = (magnitude/2000.0f);
00274                                         if ( turnStrength < 0.1f )
00275                                         {
00276                                                 turnStrength = 0.1f;
00277                                         }
00278                                         else if ( turnStrength > 2.0f )
00279                                         {
00280                                                 turnStrength = 2.0f;
00281                                         }
00282                                         //get the angles we are going to turn towards
00283                                         vectoangles( bounceDir, turnAwayAngles );
00284                                         //get the delta from our current angles to those new angles
00285                                         AnglesSubtract( turnAwayAngles, pSelfVeh->m_vOrientation, turnDelta );
00286                                         //now do pitch
00287                                         if ( !bounceDir[2] )
00288                                         {//shouldn't be any pitch
00289                                         }
00290                                         else
00291                                         {
00292                                                 pitchTurnStrength = turnStrength*turnDelta[PITCH];
00293                                                 if ( pitchTurnStrength > MAX_IMPACT_TURN_ANGLE )
00294                                                 {
00295                                                         pitchTurnStrength = MAX_IMPACT_TURN_ANGLE;
00296                                                 }
00297                                                 else if ( pitchTurnStrength < -MAX_IMPACT_TURN_ANGLE )
00298                                                 {
00299                                                         pitchTurnStrength = -MAX_IMPACT_TURN_ANGLE;
00300                                                 }
00301                                                 //pSelfVeh->m_vOrientation[PITCH] = AngleNormalize180(pSelfVeh->m_vOrientation[PITCH]+pitchTurnStrength/turnDivider*pSelfVeh->m_fTimeModifier);
00302                                                 pSelfVeh->m_vFullAngleVelocity[PITCH] = AngleNormalize180(pSelfVeh->m_vOrientation[PITCH]+pitchTurnStrength/turnDivider*pSelfVeh->m_fTimeModifier);
00303                                         }
00304                                         //now do yaw
00305                                         if ( !bounceDir[0] 
00306                                                 && !bounceDir[1] )
00307                                         {//shouldn't be any yaw
00308                                         }
00309                                         else
00310                                         {
00311                                                 yawTurnStrength = turnStrength*turnDelta[YAW];
00312                                                 if ( yawTurnStrength > MAX_IMPACT_TURN_ANGLE )
00313                                                 {
00314                                                         yawTurnStrength = MAX_IMPACT_TURN_ANGLE;
00315                                                 }
00316                                                 else if ( yawTurnStrength < -MAX_IMPACT_TURN_ANGLE )
00317                                                 {
00318                                                         yawTurnStrength = -MAX_IMPACT_TURN_ANGLE;
00319                                                 }
00320                                                 //pSelfVeh->m_vOrientation[ROLL] = AngleNormalize180(pSelfVeh->m_vOrientation[ROLL]-yawTurnStrength/turnDivider*pSelfVeh->m_fTimeModifier);
00321                                                 pSelfVeh->m_vFullAngleVelocity[ROLL] = AngleNormalize180(pSelfVeh->m_vOrientation[ROLL]-yawTurnStrength/turnDivider*pSelfVeh->m_fTimeModifier);
00322                                         }
00323                                         /*
00324                                         PM_SetPMViewAngle(pm->ps, pSelfVeh->m_vOrientation, &pSelfVeh->m_ucmd);
00325                                         if ( pm_entVeh )
00326                                         {//I'm a vehicle, so pm_entVeh is actually my pilot
00327                                                 bgEntity_t *pilot = pm_entVeh;
00328                                                 if ( !BG_UnrestrainedPitchRoll( pilot->playerState, pSelfVeh ) )
00329                                                 {
00330                                                         //set the rider's viewangles to the vehicle's viewangles
00331                                                         PM_SetPMViewAngle(pilot->playerState, pSelfVeh->m_vOrientation, &pSelfVeh->m_ucmd);
00332                                                 }
00333                                         }
00334                                         */
00335 #ifdef QAGAME//server-side, turn the guy we hit away from us, too
00336                                         if ( turnHitEnt//make the other guy turn and get pushed
00337                                                 && hitEnt->client //must be a valid client
00338                                                 && !FighterIsLanded( hitEnt->m_pVehicle, &hitEnt->client->ps )//but not if landed
00339                                                 && !(hitEnt->spawnflags&2) )//and not if suspended
00340                                         {
00341                                                 l = hitEnt->client->ps.speed;
00342                                                 //now bounce *them* away and turn them
00343                                                 //flip the bounceDir
00344                                                 VectorScale( bounceDir, -1, bounceDir );
00345                                                 //do bounce
00346                                                 VectorScale( bounceDir, (pm->ps->speed+l)*0.5f, pushDir );
00347                                                 VectorScale(pushDir, (l*0.5f/hitEnt->m_pVehicle->m_pVehicleInfo->mass), pushDir);
00348                                                 VectorNormalize2( hitEnt->client->ps.velocity, moveDir );
00349                                                 bounceDot = DotProduct( moveDir, bounceDir )*-1;
00350                                                 if ( bounceDot < 0.1f )
00351                                                 {
00352                                                         bounceDot = 0.1f;
00353                                                 }
00354                                                 VectorScale( pushDir, bounceDot, pushDir );
00355                                                 VectorAdd(hitEnt->client->ps.velocity, pushDir, hitEnt->client->ps.velocity);
00356                                                 //turn
00357                                                 turnDivider = (hitEnt->m_pVehicle->m_pVehicleInfo->mass/400.0f);
00358                                                 if ( turnHitEnt )
00359                                                 {//don't turn as much when hit another ship
00360                                                         turnDivider *= 4.0f;
00361                                                 }
00362                                                 if ( turnDivider < 0.5f )
00363                                                 {
00364                                                         turnDivider = 0.5f;
00365                                                 }
00366                                                 //get the angles we are going to turn towards
00367                                                 vectoangles( bounceDir, turnAwayAngles );
00368                                                 //get the delta from our current angles to those new angles
00369                                                 AnglesSubtract( turnAwayAngles, hitEnt->m_pVehicle->m_vOrientation, turnDelta );
00370                                                 //now do pitch
00371                                                 if ( !bounceDir[2] )
00372                                                 {//shouldn't be any pitch
00373                                                 }
00374                                                 else
00375                                                 {
00376                                                         pitchTurnStrength = turnStrength*turnDelta[PITCH];
00377                                                         if ( pitchTurnStrength > MAX_IMPACT_TURN_ANGLE )
00378                                                         {
00379                                                                 pitchTurnStrength = MAX_IMPACT_TURN_ANGLE;
00380                                                         }
00381                                                         else if ( pitchTurnStrength < -MAX_IMPACT_TURN_ANGLE )
00382                                                         {
00383                                                                 pitchTurnStrength = -MAX_IMPACT_TURN_ANGLE;
00384                                                         }
00385                                                         //hitEnt->m_pVehicle->m_vOrientation[PITCH] = AngleNormalize180(hitEnt->m_pVehicle->m_vOrientation[PITCH]+pitchTurnStrength/turnDivider*pSelfVeh->m_fTimeModifier);
00386                                                         hitEnt->m_pVehicle->m_vFullAngleVelocity[PITCH] = AngleNormalize180(hitEnt->m_pVehicle->m_vOrientation[PITCH]+pitchTurnStrength/turnDivider*pSelfVeh->m_fTimeModifier);
00387                                                 }
00388                                                 //now do yaw
00389                                                 if ( !bounceDir[0] 
00390                                                         && !bounceDir[1] )
00391                                                 {//shouldn't be any yaw
00392                                                 }
00393                                                 else
00394                                                 {
00395                                                         yawTurnStrength = turnStrength*turnDelta[YAW];
00396                                                         if ( yawTurnStrength > MAX_IMPACT_TURN_ANGLE )
00397                                                         {
00398                                                                 yawTurnStrength = MAX_IMPACT_TURN_ANGLE;
00399                                                         }
00400                                                         else if ( yawTurnStrength < -MAX_IMPACT_TURN_ANGLE )
00401                                                         {
00402                                                                 yawTurnStrength = -MAX_IMPACT_TURN_ANGLE;
00403                                                         }
00404                                                         //hitEnt->m_pVehicle->m_vOrientation[ROLL] = AngleNormalize180(hitEnt->m_pVehicle->m_vOrientation[ROLL]-yawTurnStrength/turnDivider*pSelfVeh->m_fTimeModifier);
00405                                                         hitEnt->m_pVehicle->m_vFullAngleVelocity[ROLL] = AngleNormalize180(hitEnt->m_pVehicle->m_vOrientation[ROLL]-yawTurnStrength/turnDivider*pSelfVeh->m_fTimeModifier);
00406                                                 }
00407                                                 //NOTE: will these angle changes stick or will they be stomped 
00408                                                 //              when the vehicle goes through its own update and re-grabs 
00409                                                 //              its angles from its pilot...?  Should we do a 
00410                                                 //              SetClientViewAngles on the pilot?
00411                                                 /*
00412                                                 SetClientViewAngle( hitEnt, hitEnt->m_pVehicle->m_vOrientation );
00413                                                 if ( hitEnt->m_pVehicle->m_pPilot 
00414                                                         && ((gentity_t *)hitEnt->m_pVehicle->m_pPilot)->client )
00415                                                 {
00416                                                         SetClientViewAngle( (gentity_t *)hitEnt->m_pVehicle->m_pPilot, hitEnt->m_pVehicle->m_vOrientation );
00417                                                 }
00418                                                 */
00419                                         }
00420 #endif
00421                                 }
00422                         }
00423 
00424 #ifdef QAGAME
00425                         if (!hitEnt)
00426                         {
00427                                 return;
00428                         }
00429 
00430                         AngleVectors( pSelfVeh->m_vOrientation, NULL, NULL, vehUp );
00431                         if ( pSelfVeh->m_pVehicleInfo->iImpactFX )
00432                         {
00433                                 //G_PlayEffectID( pSelfVeh->m_pVehicleInfo->iImpactFX, pm->ps->origin, vehUp );
00434                                 //tempent use bad!
00435                                 G_AddEvent((gentity_t *)pEnt, EV_PLAY_EFFECT_ID, pSelfVeh->m_pVehicleInfo->iImpactFX);
00436                         }
00437                         pEnt->m_pVehicle->m_iHitDebounce = pm->cmd.serverTime + 200;
00438                         magnitude /= pSelfVeh->m_pVehicleInfo->toughness * 50.0f; 
00439 
00440                         if (hitEnt && (hitEnt->s.eType != ET_TERRAIN || !(hitEnt->spawnflags & 1) || pSelfVeh->m_pVehicleInfo->type == VH_FIGHTER))
00441                         { //don't damage the vehicle from terrain that doesn't want to damage vehicles
00442                                 if (pSelfVeh->m_pVehicleInfo->type == VH_FIGHTER)
00443                                 { //increase the damage...
00444                                         float mult = (pSelfVeh->m_vOrientation[PITCH]*0.1f);
00445                                         if (mult < 1.0f)
00446                                         {
00447                                                 mult = 1.0f;
00448                                         }
00449                                         if (hitEnt->inuse && hitEnt->takedamage)
00450                                         { //if the other guy takes damage, don't hurt us a lot for ramming him
00451                                                 //unless it's a vehicle, then we get 1.5 times damage
00452                                                 if (hitEnt->s.eType == ET_NPC &&
00453                                                         hitEnt->s.NPC_class == CLASS_VEHICLE &&
00454                                                         hitEnt->m_pVehicle)
00455                                                 {
00456                                                         mult = 1.5f;
00457                                                 }
00458                                                 else
00459                                                 {
00460                                                         mult = 0.5f;
00461                                                 }
00462                                         }
00463 
00464                                         magnitude *= mult;
00465                                 }
00466                                 pSelfVeh->m_iLastImpactDmg = magnitude;
00467                                 //FIXME: what about proper death credit to the guy who shot you down?
00468                                 //FIXME: actually damage part of the ship that impacted?
00469                                 G_Damage( (gentity_t *)pEnt, NULL, NULL, NULL, pm->ps->origin, magnitude*5, DAMAGE_NO_ARMOR, MOD_FALLING );//FIXME: MOD_IMPACT
00470 
00471                                 if (pSelfVeh->m_pVehicleInfo->surfDestruction)
00472                                 {
00473                                         G_FlyVehicleSurfaceDestruction((gentity_t *)pEnt, trace, magnitude, forceSurfDestruction );
00474                                 }
00475 
00476                                 pSelfVeh->m_ulFlags |= VEH_CRASHING;
00477                         }
00478 
00479                         if (hitEnt &&
00480                                 hitEnt->inuse &&
00481                                 hitEnt->takedamage)
00482                         { //damage this guy because we hit him
00483                                 float pmult = 1.0f;
00484                                 int finalD;
00485                                 gentity_t *attackEnt;
00486 
00487                                 if ( (hitEnt->s.eType == ET_PLAYER && hitEnt->s.number < MAX_CLIENTS) ||
00488                                          (hitEnt->s.eType == ET_NPC && hitEnt->s.NPC_class != CLASS_VEHICLE) )
00489                                 { //probably a humanoid, or something
00490                                         if (pSelfVeh->m_pVehicleInfo->type == VH_FIGHTER)
00491                                         { //player die good.. if me fighter
00492                                                 pmult = 2000.0f;
00493                                         }
00494                                         else
00495                                         {
00496                                                 pmult = 40.0f;
00497                                         }
00498 
00499                                         if (hitEnt->client &&
00500                                                 BG_KnockDownable(&hitEnt->client->ps) &&
00501                                                 G_CanBeEnemy((gentity_t *)pEnt, hitEnt))
00502                                         { //smash!
00503                                                 if (hitEnt->client->ps.forceHandExtend != HANDEXTEND_KNOCKDOWN)
00504                                                 {
00505                                                         hitEnt->client->ps.forceHandExtend = HANDEXTEND_KNOCKDOWN;
00506                                                         hitEnt->client->ps.forceHandExtendTime = pm->cmd.serverTime + 1100;
00507                                                         hitEnt->client->ps.forceDodgeAnim = 0; //this toggles between 1 and 0, when it's 1 we should play the get up anim
00508                                                 }
00509 
00510                                                 hitEnt->client->ps.otherKiller = pEnt->s.number;
00511                                                 hitEnt->client->ps.otherKillerTime = pm->cmd.serverTime + 5000;
00512                                                 hitEnt->client->ps.otherKillerDebounceTime = pm->cmd.serverTime + 100;
00513 
00514                                                 //add my velocity into his to force him along in the correct direction from impact
00515                                                 VectorAdd(hitEnt->client->ps.velocity, pm->ps->velocity, hitEnt->client->ps.velocity);
00516                                                 //upward thrust
00517                                                 hitEnt->client->ps.velocity[2] += 200.0f;
00518                                         }
00519                                 }
00520 
00521                                 if (pSelfVeh->m_pPilot)
00522                                 {
00523                                         attackEnt = (gentity_t *)pSelfVeh->m_pPilot;
00524                                 }
00525                                 else
00526                                 {
00527                                         attackEnt = (gentity_t *)pEnt;
00528                                 }
00529 
00530                                 finalD = magnitude*pmult;
00531                                 if (finalD < 1)
00532                                 {
00533                                         finalD = 1;
00534                                 }
00535                                 G_Damage( hitEnt, attackEnt, attackEnt, NULL, pm->ps->origin, finalD, 0, MOD_MELEE );//FIXME: MOD_IMPACT
00536                         }
00537 #else   //this is gonna result in "double effects" for the client doing the prediction.
00538                 //it doesn't look bad though. could just use predicted events, but I'm too lazy.
00539                         hitEnt = PM_BGEntForNum(trace->entityNum);
00540 
00541                         if (!hitEnt || hitEnt->s.owner != pEnt->s.number)
00542                         { //don't hit your own missiles!
00543                                 AngleVectors( pSelfVeh->m_vOrientation, NULL, NULL, vehUp );
00544                                 pEnt->m_pVehicle->m_iHitDebounce = pm->cmd.serverTime + 200;
00545                                 trap_FX_PlayEffectID( pSelfVeh->m_pVehicleInfo->iImpactFX, pm->ps->origin, vehUp, -1, -1 );
00546 
00547                                 pSelfVeh->m_ulFlags |= VEH_CRASHING;
00548                         }
00549 #endif
00550                 }
00551         }
00552 }

void trap_FX_PlayEffectID int  id,
vec3_t  org,
vec3_t  fwd,
int  vol,
int  rad
 

Definition at line 637 of file cg_syscalls.c.

References CG_FX_PLAY_EFFECT_ID, and vec3_t.

Referenced by CG_AddPlayerWeapon(), CG_AddSaberBlade(), CG_Disintegration(), CG_EntityEvent(), CG_G2SaberEffects(), CG_MiscModelExplosion(), CG_MissileHitPlayer(), CG_MissileHitWall(), CG_Player(), CG_PlayerAnimEventDo(), CG_ROFF_NotetrackCallback(), CG_SaberCompWork(), CG_VehicleWeaponImpact(), FX_BlasterAltFireThink(), FX_BlasterProjectileThink(), FX_BlasterWeaponHitPlayer(), FX_BlasterWeaponHitWall(), FX_BowcasterAltProjectileThink(), FX_BowcasterHitPlayer(), FX_BowcasterHitWall(), FX_BowcasterProjectileThink(), FX_BryarAltHitPlayer(), FX_BryarAltHitWall(), FX_BryarAltProjectileThink(), FX_BryarHitPlayer(), FX_BryarHitWall(), FX_BryarProjectileThink(), FX_ConcussionHitPlayer(), FX_ConcussionHitWall(), FX_ConcussionProjectileThink(), FX_DEMP2_HitPlayer(), FX_DEMP2_HitWall(), FX_DEMP2_ProjectileThink(), FX_DisruptorAltHit(), FX_DisruptorAltMiss(), FX_DisruptorHitPlayer(), FX_DisruptorHitWall(), FX_FlechetteAltProjectileThink(), FX_FlechetteProjectileThink(), FX_FlechetteWeaponHitPlayer(), FX_FlechetteWeaponHitWall(), FX_ForceDrained(), FX_RepeaterAltHitPlayer(), FX_RepeaterAltHitWall(), FX_RepeaterAltProjectileThink(), FX_RepeaterHitPlayer(), FX_RepeaterHitWall(), FX_RepeaterProjectileThink(), FX_RocketAltProjectileThink(), FX_RocketHitPlayer(), FX_RocketHitWall(), FX_RocketProjectileThink(), FX_TurretHitPlayer(), FX_TurretHitWall(), FX_TurretProjectileThink(), PM_VehicleImpact(), and TurretClientRun().

00638 {
00639         syscall( CG_FX_PLAY_EFFECT_ID, id, org, fwd, vol, rad );
00640 }


Variable Documentation

bgEntity_t* pm_entSelf
 

Definition at line 33 of file bg_slidemove.c.

Referenced by BG_AdjustClientSpeed(), PM_AdjustAttackStates(), PM_HoverTrace(), PM_SetSpecialMoveValues(), PM_SlideMove(), PM_StepSlideMove(), and PmoveSingle().

bgEntity_t* pm_entVeh
 

Definition at line 34 of file bg_slidemove.c.

Referenced by PM_AdjustAttackStates(), PM_UpdateViewAngles(), PM_VehicleWeaponAnimate(), and PmoveSingle().