summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cgame/cg_event.c10
-rw-r--r--src/cgame/cg_view.c16
-rw-r--r--src/cgame/cg_weapons.c6
-rw-r--r--src/game/bg_misc.c223
-rw-r--r--src/game/bg_pmove.c32
-rw-r--r--src/game/bg_public.h24
-rw-r--r--src/game/g_active.c21
-rw-r--r--src/game/g_buildable.c2
-rw-r--r--src/game/g_client.c175
-rw-r--r--src/game/g_cmds.c61
-rw-r--r--src/game/g_local.h8
-rw-r--r--src/game/g_main.c3
12 files changed, 377 insertions, 204 deletions
diff --git a/src/cgame/cg_event.c b/src/cgame/cg_event.c
index d5f30cb4..c8a3fab2 100644
--- a/src/cgame/cg_event.c
+++ b/src/cgame/cg_event.c
@@ -464,14 +464,14 @@ also called by CG_CheckPlayerstateEvents
#define DEBUGNAME(x) if(cg_debugEvents.integer){CG_Printf(x"\n");}
void CG_EntityEvent( centity_t *cent, vec3_t position ) {
entityState_t *es;
- int event;
- vec3_t dir;
+ int event;
+ vec3_t dir;
const char *s;
- int clientNum;
+ int clientNum;
clientInfo_t *ci;
- int steptime;
+ int steptime;
- BG_unpackAttributes( NULL, NULL, &steptime, cg.predictedPlayerState.stats );
+ steptime = BG_FindSteptimeForClass( cg.predictedPlayerState.stats[ STAT_PCLASS ] );
es = &cent->currentState;
event = es->event & ~EV_EVENT_BITS;
diff --git a/src/cgame/cg_view.c b/src/cgame/cg_view.c
index 7dabda68..d8401334 100644
--- a/src/cgame/cg_view.c
+++ b/src/cgame/cg_view.c
@@ -307,7 +307,7 @@ static void CG_StepOffset( void ) {
int timeDelta;
int steptime;
- BG_unpackAttributes( NULL, NULL, &steptime, cg.predictedPlayerState.stats );
+ steptime = BG_FindSteptimeForClass( cg.predictedPlayerState.stats[ STAT_PCLASS ] );
// smooth out stair climbing
timeDelta = cg.time - cg.stepTime;
@@ -331,9 +331,9 @@ static void CG_OffsetFirstPersonView( void ) {
float delta;
float speed;
float f;
- vec3_t predictedVelocity;
+ vec3_t predictedVelocity;
int timeDelta;
- int bob2;
+ float bob2;
if ( cg.snap->ps.pm_type == PM_INTERMISSION ) {
return;
@@ -389,17 +389,17 @@ static void CG_OffsetFirstPersonView( void ) {
// add angles based on bob
//TA: bob amount is class dependant
- BG_unpackAttributes( NULL, &bob2, NULL, cg.predictedPlayerState.stats );
+ bob2 = BG_FindBobForClass( cg.predictedPlayerState.stats[ STAT_PCLASS ] );
if( bob2 != 0 )
{
// make sure the bob is visible even at low speeds
speed = cg.xyspeed > 200 ? cg.xyspeed : 200;
- delta = cg.bobfracsin * ( bob2 / 1000.0 ) * speed;
+ delta = cg.bobfracsin * ( bob2 ) * speed;
if (cg.predictedPlayerState.pm_flags & PMF_DUCKED)
delta *= 3; // crouching
angles[PITCH] += delta;
- delta = cg.bobfracsin * ( bob2 / 1000.0 ) * speed;
+ delta = cg.bobfracsin * ( bob2 ) * speed;
if (cg.predictedPlayerState.pm_flags & PMF_DUCKED)
delta *= 3; // crouching accentuates roll
if (cg.bobcycle & 1)
@@ -530,7 +530,7 @@ static int CG_CalcFov( void ) {
int a;
float b;
- BG_unpackAttributes( &attribFov, NULL, NULL, cg.predictedPlayerState.stats );
+ attribFov = BG_FindFovForClass( cg.predictedPlayerState.stats[ STAT_PCLASS ] );
if ( cg.predictedPlayerState.pm_type == PM_INTERMISSION ) {
// if in intermission, use a fixed value
@@ -555,7 +555,7 @@ static int CG_CalcFov( void ) {
zoomFov = attribFov;
//TA: only do all the zoom stuff if the client CAN zoom
- if( cg.predictedPlayerState.stats[ STAT_ABILITIES ] & SCA_CANZOOM )
+ if( BG_ClassHasAbility( cg.predictedPlayerState.stats[ STAT_PCLASS ], SCA_CANZOOM ) )
{
if ( cg.zoomed )
{
diff --git a/src/cgame/cg_weapons.c b/src/cgame/cg_weapons.c
index 777271c3..15992501 100644
--- a/src/cgame/cg_weapons.c
+++ b/src/cgame/cg_weapons.c
@@ -692,7 +692,7 @@ static void CG_CalculateWeaponPosition( vec3_t origin, vec3_t angles ) {
float scale;
int delta;
float fracsin;
- int bob;
+ float bob;
VectorCopy( cg.refdef.vieworg, origin );
VectorCopy( cg.refdefViewAngles, angles );
@@ -706,7 +706,7 @@ static void CG_CalculateWeaponPosition( vec3_t origin, vec3_t angles ) {
// gun angles from bobbing
//TA: bob amount is class dependant
- BG_unpackAttributes( NULL, &bob, NULL, cg.predictedPlayerState.stats );
+ bob = BG_FindBobForClass( cg.predictedPlayerState.stats[ STAT_PCLASS ] );
if( bob != 0 )
{
angles[ROLL] += scale * cg.bobfracsin * 0.005;
@@ -715,7 +715,7 @@ static void CG_CalculateWeaponPosition( vec3_t origin, vec3_t angles ) {
}
// drop the weapon when landing
- if( !( cg.predictedPlayerState.stats[ STAT_ABILITIES ] & SCA_NOWEAPONDRIFT ) )
+ if( !BG_ClassHasAbility( cg.predictedPlayerState.stats[ STAT_PCLASS ], SCA_NOWEAPONDRIFT ) )
{
delta = cg.time - cg.landTime;
if ( delta < LAND_DEFLECT_TIME )
diff --git a/src/game/bg_misc.c b/src/game/bg_misc.c
index 4db19a08..762f38f5 100644
--- a/src/game/bg_misc.c
+++ b/src/game/bg_misc.c
@@ -900,7 +900,15 @@ classAttributes_t bg_classList[ ] =
{ 15, 15, 15 },
{ -15, -15, -4 },
{ 15, 15, 4 },
- 4, 4
+ 4, 4,
+ 25,
+ 0,
+ SCA_WALLCLIMBER|SCA_CANJUMP|SCA_NOWEAPONDRIFT,
+ 140,
+ 0.0f,
+ 25,
+ 2.0f,
+ 5.0f
},
{
PCL_D_D_BASE,
@@ -911,7 +919,15 @@ classAttributes_t bg_classList[ ] =
{ 15, 15 ,15 },
{ -15, -15, -4 },
{ 15, 15, 4 },
- 4, 4
+ 4, 4,
+ 50,
+ 0,
+ SCA_WALLCLIMBER|SCA_CANJUMP|SCA_NOWEAPONDRIFT,
+ 160,
+ 0.0f,
+ 25,
+ 1.5f,
+ 3.0f
},
{
PCL_D_B_BASE,
@@ -922,7 +938,15 @@ classAttributes_t bg_classList[ ] =
{ 15, 15, 20 },
{ -15, -15, -4 },
{ 15, 15, 4 },
- 12, 12
+ 12, 12,
+ 50,
+ 50,
+ SCA_TAKESFALLDAMAGE,
+ 80,
+ 0.015f,
+ 350,
+ 0.5f,
+ 1.0f
},
{
PCL_H_BASE,
@@ -933,7 +957,15 @@ classAttributes_t bg_classList[ ] =
{ 15, 15, 16 },
{ -15, -15, -4 },
{ 15, 15, 4 },
- 26, 12
+ 26, 12,
+ 100,
+ 50,
+ SCA_TAKESFALLDAMAGE|SCA_CANJUMP,
+ 90,
+ 0.002f,
+ 200,
+ 1.0f,
+ 1.0f
}
};
@@ -1036,6 +1068,171 @@ void BG_FindViewheightForClass( int pclass, int *viewheight, int *cViewheight )
*cViewheight = bg_classList[ 0 ].crouchViewheight;
}
+/*
+==============
+BG_FindHealthForClass
+==============
+*/
+int BG_FindHealthForClass( int pclass )
+{
+ int i;
+
+ for( i = 0; i < bg_numPclasses; i++ )
+ {
+ if( bg_classList[ i ].classNum == pclass )
+ {
+ return bg_classList[ i ].health;
+ }
+ }
+
+ return 100;
+}
+
+/*
+==============
+BG_FindArmorForClass
+==============
+*/
+int BG_FindArmorForClass( int pclass )
+{
+ int i;
+
+ for( i = 0; i < bg_numPclasses; i++ )
+ {
+ if( bg_classList[ i ].classNum == pclass )
+ {
+ return bg_classList[ i ].armor;
+ }
+ }
+
+ return 0;
+}
+
+/*
+==============
+BG_FindFovForClass
+==============
+*/
+int BG_FindFovForClass( int pclass )
+{
+ int i;
+
+ for( i = 0; i < bg_numPclasses; i++ )
+ {
+ if( bg_classList[ i ].classNum == pclass )
+ {
+ return bg_classList[ i ].fov;
+ }
+ }
+
+ return 90;
+}
+
+/*
+==============
+BG_FindBobForClass
+==============
+*/
+float BG_FindBobForClass( int pclass )
+{
+ int i;
+
+ for( i = 0; i < bg_numPclasses; i++ )
+ {
+ if( bg_classList[ i ].classNum == pclass )
+ {
+ return bg_classList[ i ].bob;
+ }
+ }
+
+ return 0.002;
+}
+
+/*
+==============
+BG_FindSpeedForClass
+==============
+*/
+float BG_FindSpeedForClass( int pclass )
+{
+ int i;
+
+ for( i = 0; i < bg_numPclasses; i++ )
+ {
+ if( bg_classList[ i ].classNum == pclass )
+ {
+ return bg_classList[ i ].speed;
+ }
+ }
+
+ return 1.0;
+}
+
+/*
+==============
+BG_FindStickyForClass
+==============
+*/
+float BG_FindStickyForClass( int pclass )
+{
+ int i;
+
+ for( i = 0; i < bg_numPclasses; i++ )
+ {
+ if( bg_classList[ i ].classNum == pclass )
+ {
+ return bg_classList[ i ].sticky;
+ }
+ }
+
+ return 1.0;
+}
+
+/*
+==============
+BG_FindSteptimeForClass
+==============
+*/
+int BG_FindSteptimeForClass( int pclass )
+{
+ int i;
+
+ for( i = 0; i < bg_numPclasses; i++ )
+ {
+ if( bg_classList[ i ].classNum == pclass )
+ {
+ return bg_classList[ i ].steptime;
+ }
+ }
+
+ return 200;
+}
+
+
+/*
+==============
+BG_ClassHasAbility
+==============
+*/
+qboolean BG_ClassHasAbility( int pclass, int ability )
+{
+ int i;
+
+ for( i = 0; i < bg_numPclasses; i++ )
+ {
+ if( bg_classList[ i ].classNum == pclass )
+ {
+ return ( bg_classList[ i ].abilities & ability );
+ }
+ }
+
+ //hack to get CANJUMP when a spectator
+ if( ability == SCA_CANJUMP )
+ return qtrue;
+ else
+ return qfalse;
+}
+
/*
==============
@@ -1836,21 +2033,3 @@ qboolean BG_activated( int item, int stats[ ] )
return( stats[ STAT_ACTIVEITEMS ] & ( 1 << item ) );
}
-//TA: set attributes in array
-void BG_packAttributes( int fov, int bob, int steptime, int stats[ ] )
-{
- stats[ STAT_ATTRIBS ] = ( ( (int)( (float)fov/10.0 ) & 0x1F ) << 10 ) | ( ( bob & 0x1F ) << 5 ) | ( (int)( (float)steptime/25.0 ) & 0x1F );
-}
-
-//TA: get attributes from array
-void BG_unpackAttributes( int *fov, int *bob, int *steptime, int stats[ ] )
-{
- if( fov != NULL )
- *fov = ( ( stats[ STAT_ATTRIBS ] >> 10 ) & 0x1F ) * 10;
-
- if( bob != NULL )
- *bob = ( stats[ STAT_ATTRIBS ] >> 5 ) & 0x1F;
-
- if( steptime != NULL )
- *steptime = ( stats[ STAT_ATTRIBS ] & 0x1F ) * 25;
-}
diff --git a/src/game/bg_pmove.c b/src/game/bg_pmove.c
index a2e0bc51..40915b22 100644
--- a/src/game/bg_pmove.c
+++ b/src/game/bg_pmove.c
@@ -298,17 +298,11 @@ static void PM_Friction( void ) {
if ( pm->waterlevel <= 1 ) {
if ( pml.walking && !(pml.groundTrace.surfaceFlags & SURF_SLICK) ) {
// if getting knocked back, no friction
- if ( ! (pm->ps->pm_flags & PMF_TIME_KNOCKBACK) ) {
- if( ( pm->ps->stats[ STAT_PTEAM ] == PTE_DROIDS ) &&
- ( pm->ps->stats[ STAT_PCLASS ] == PCL_D_O_BASE ) )
- {
- control = speed < pm_stopspeed*5 ? pm_stopspeed*5 : speed;
- }
- else
- {
- control = speed < pm_stopspeed ? pm_stopspeed : speed;
- }
+ if ( ! (pm->ps->pm_flags & PMF_TIME_KNOCKBACK) )
+ {
+ float sticky = BG_FindStickyForClass( pm->ps->stats[ STAT_PCLASS ] );
+ control = speed < pm_stopspeed*sticky ? pm_stopspeed*sticky : speed;
drop += control*pm_friction*pml.frametime;
}
}
@@ -440,7 +434,7 @@ static float PM_CmdScale( usercmd_t *cmd ) {
modifier *= (float)( pm->ps->stats[ STAT_STAMINA ] + 1000 ) / 500.0f;
}
- if( !( pm->ps->stats[ STAT_ABILITIES ] & SCA_CANJUMP ) )
+ if( !BG_ClassHasAbility( pm->ps->stats[ STAT_PCLASS ], SCA_CANJUMP ) )
cmd->upmove = 0;
max = abs( cmd->forwardmove );
@@ -454,7 +448,7 @@ static float PM_CmdScale( usercmd_t *cmd ) {
return 0;
}
- if( ( pm->ps->stats[ STAT_ABILITIES ] & SCA_WALLCLIMBER ) &&
+ if( BG_ClassHasAbility( pm->ps->stats[ STAT_PCLASS ], SCA_WALLCLIMBER ) &&
( pm->ps->stats[ STAT_STATE ] & SS_WALLCLIMBING ) )
{
total = sqrt( cmd->forwardmove * cmd->forwardmove + cmd->rightmove * cmd->rightmove );
@@ -516,7 +510,7 @@ PM_CheckJump
=============
*/
static qboolean PM_CheckJump( void ) {
- if( !( pm->ps->stats[ STAT_ABILITIES ] & SCA_CANJUMP ) ) return qfalse;
+ if( !BG_ClassHasAbility( pm->ps->stats[ STAT_PCLASS ], SCA_CANJUMP ) ) return qfalse;
if( ( pm->ps->stats[ STAT_PTEAM ] == PTE_HUMANS ) &&
( pm->ps->stats[ STAT_STAMINA ] < 0 ) )
@@ -1661,7 +1655,7 @@ static void PM_GroundTrace( void ) {
trace_t trace;
float srotAngle;
- if( ( pm->ps->stats[ STAT_ABILITIES ] & SCA_WALLCLIMBER ) && ( pm->cmd.upmove < 0 ) )
+ if( BG_ClassHasAbility( pm->ps->stats[ STAT_PCLASS ], SCA_WALLCLIMBER ) && ( pm->cmd.upmove < 0 ) )
{
PM_GroundClimbTrace( );
return;
@@ -1777,7 +1771,7 @@ static void PM_GroundTrace( void ) {
Com_Printf("%i:Land\n", c_pmove);
}
- if( pm->ps->stats[ STAT_ABILITIES ] & SCA_TAKESFALLDAMAGE )
+ if( BG_ClassHasAbility( pm->ps->stats[ STAT_PCLASS ], SCA_TAKESFALLDAMAGE ) )
PM_CrashLand();
// don't do landing time if we were just going down a slope
@@ -1924,7 +1918,7 @@ static void PM_Footsteps( void ) {
// calculate speed and cycle to be used for
// all cyclic walking effects
//
- if( ( pm->ps->stats[STAT_ABILITIES] & SCA_WALLCLIMBER ) && ( pml.groundPlane ) )
+ if( BG_ClassHasAbility( pm->ps->stats[ STAT_PCLASS ], SCA_WALLCLIMBER ) && ( pml.groundPlane ) )
{
pm->xyspeed = sqrt( pm->ps->velocity[0] * pm->ps->velocity[0]
+ pm->ps->velocity[1] * pm->ps->velocity[1]
@@ -2505,7 +2499,7 @@ void PM_UpdateViewAngles( playerState_t *ps, const usercmd_t *cmd ) {
}
//if we're a wall climber.. and we're climbing rotate the axis
- if( ( pm->ps->stats[ STAT_ABILITIES ] & SCA_WALLCLIMBER ) &&
+ if( BG_ClassHasAbility( pm->ps->stats[ STAT_PCLASS ], SCA_WALLCLIMBER ) &&
( pm->ps->stats[ STAT_STATE ] & SS_WALLCLIMBING ) &&
( VectorLength( xNormal ) != 0 ) )
{
@@ -2655,7 +2649,7 @@ void PmoveSingle (pmove_t *pmove)
pml.frametime = pml.msec * 0.001;
- if( ( pm->ps->stats[ STAT_ABILITIES ] & SCA_WALLCLIMBER ) &&
+ if( BG_ClassHasAbility( pm->ps->stats[ STAT_PCLASS ], SCA_WALLCLIMBER ) &&
( pm->ps->stats[ STAT_STATE ] & SS_WALLCLIMBING ) )
{ AngleVectors ( wcl[ pm->ps->clientNum ].nonSvangles, pml.forward, pml.right, pml.up); }
else
@@ -2733,7 +2727,7 @@ void PmoveSingle (pmove_t *pmove)
// swimming
PM_WaterMove();
} else if ( pml.walking ) {
- if( ( pm->ps->stats[ STAT_ABILITIES ] & SCA_WALLCLIMBER ) &&
+ if( BG_ClassHasAbility( pm->ps->stats[ STAT_PCLASS ], SCA_WALLCLIMBER ) &&
( pm->ps->stats[ STAT_STATE ] & SS_WALLCLIMBING ) )
PM_ClimbMove(); //TA: walking on any surface
else
diff --git a/src/game/bg_public.h b/src/game/bg_public.h
index a9c61caf..ab40ae77 100644
--- a/src/game/bg_public.h
+++ b/src/game/bg_public.h
@@ -240,8 +240,6 @@ typedef enum {
STAT_MAX_HEALTH, // health / armor limit, changable by handicap
STAT_PCLASS, //TA: player class (for droids AND humans)
STAT_PTEAM, //TA: player team
- STAT_ABILITIES, //TA: client abilities (based on class)
- STAT_ATTRIBS,
STAT_STAMINA, //TA: stamina (human only)
STAT_STATE //TA: client states e.g. wall climbing
} statIndex_t;
@@ -707,6 +705,14 @@ typedef struct
vec3_t deadMaxs;
int viewheight;
int crouchViewheight;
+ int health;
+ int armor;
+ int abilities;
+ int fov;
+ float bob;
+ int steptime;
+ float speed;
+ float sticky;
} classAttributes_t;
@@ -722,9 +728,17 @@ gitem_t *BG_FindItemForPowerup( powerup_t pw );
gitem_t *BG_FindItemForHoldable( holdable_t pw );
//TA:
-char *BG_FindModelNameForClass( int pclass );
-void BG_FindBBoxForClass( int pclass, vec3_t mins, vec3_t maxs, vec3_t cmaxs, vec3_t dmins, vec3_t dmaxs );
-void BG_FindViewheightForClass( int pclass, int *viewheight, int *cViewheight );
+char *BG_FindModelNameForClass( int pclass );
+void BG_FindBBoxForClass( int pclass, vec3_t mins, vec3_t maxs, vec3_t cmaxs, vec3_t dmins, vec3_t dmaxs );
+void BG_FindViewheightForClass( int pclass, int *viewheight, int *cViewheight );
+int BG_FindHealthForClass( int pclass );
+int BG_FindArmorForClass( int pclass );
+int BG_FindFovForClass( int pclass );
+float BG_FindBobForClass( int pclass );
+float BG_FindSpeedForClass( int pclass );
+float BG_FindStickyForClass( int pclass );
+int BG_FindSteptimeForClass( int pclass );
+qboolean BG_ClassHasAbility( int pclass, int ability );
#define ITEM_INDEX(x) ((x)-bg_itemlist)
qboolean BG_CanItemBeGrabbed( int gametype, const entityState_t *ent, const playerState_t *ps );
diff --git a/src/game/g_active.c b/src/game/g_active.c
index e2215014..0cf4f644 100644
--- a/src/game/g_active.c
+++ b/src/game/g_active.c
@@ -921,21 +921,18 @@ void ClientThink_real( gentity_t *ent ) {
//TA: look for MCU infront of player
if( ( client->buttons & BUTTON_GETFLAG ) && !( client->oldbuttons & BUTTON_GETFLAG ) )
{
- if( client->pers.pteam == PTE_HUMANS )
- {
- trace_t mcu;
- vec3_t view, point;
- gentity_t *traceEnt;
+ trace_t trace;
+ vec3_t view, point;
+ gentity_t *traceEnt;
- AngleVectors( client->ps.viewangles, view, NULL, NULL );
- VectorMA( client->ps.origin, 200, view, point );
- trap_Trace( &mcu, client->ps.origin, NULL, NULL, point, ent->s.number, MASK_SHOT );
+ AngleVectors( client->ps.viewangles, view, NULL, NULL );
+ VectorMA( client->ps.origin, 200, view, point );
+ trap_Trace( &trace, client->ps.origin, NULL, NULL, point, ent->s.number, MASK_SHOT );
- traceEnt = &g_entities[ mcu.entityNum ];
+ traceEnt = &g_entities[ trace.entityNum ];
- if( traceEnt->use )
- traceEnt->use( traceEnt, ent, ent ); //other and activator are the same in this context
- }
+ if( traceEnt->use )
+ traceEnt->use( traceEnt, ent, ent ); //other and activator are the same in this context
}
// check for respawning
diff --git a/src/game/g_buildable.c b/src/game/g_buildable.c
index 455c74b9..cb35b4c6 100644
--- a/src/game/g_buildable.c
+++ b/src/game/g_buildable.c
@@ -220,6 +220,8 @@ Called when a human activates an MCU
*/
void HMCU_Activate( gentity_t *self, gentity_t *other, gentity_t *activator )
{
+ if( activator->client->ps.stats[ STAT_PTEAM ] != PTE_HUMANS ) return;
+
G_AddPredictableEvent( activator, EV_MENU, MN_MCU );
}
diff --git a/src/game/g_client.c b/src/game/g_client.c
index 5d6479c7..89dd7ded 100644
--- a/src/game/g_client.c
+++ b/src/game/g_client.c
@@ -510,25 +510,6 @@ BODYQUE
=======================================================================
*/
-#if BODY_QUEUE_SIZE
-/*
-===============
-InitBodyQue
-===============
-*/
-void InitBodyQue (void) {
- int i;
- gentity_t *ent;
-
- level.bodyQueIndex = 0;
- for (i=0; i<BODY_QUEUE_SIZE ; i++) {
- ent = G_Spawn();
- ent->classname = "bodyque";
- ent->neverFree = qtrue;
- level.bodyQue[i] = ent;
- }
-}
-#endif
/*
=============
@@ -548,15 +529,31 @@ void BodySink( gentity_t *ent ) {
ent->s.pos.trBase[2] -= 1;
}
+
+
+/*
+================
+InfestBody
+
+Called when a droid infests a body
+================
+*/
+void InfestBody( gentity_t *self, gentity_t *other, gentity_t *activator )
+{
+ if( activator->client->ps.stats[ STAT_PTEAM ] != PTE_DROIDS ) return;
+
+ G_AddPredictableEvent( activator, EV_MENU, MN_DROID );
+}
+
/*
=============
-CopyToBodyQue
+SpawnCorpse
A player is respawning, so make an entity that looks
just like the existing corpse to leave behind.
=============
*/
-void CopyToBodyQue( gentity_t *ent ) {
+void SpawnCorpse( gentity_t *ent ) {
gentity_t *body;
int contents;
vec3_t origin, dest;
@@ -573,7 +570,12 @@ void CopyToBodyQue( gentity_t *ent ) {
}
body = G_Spawn( );
- body->classname = "corpse";
+
+ if( ent->client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS )
+ body->classname = "humanCorpse";
+ else
+ body->classname = "droidCorpse";
+
body->s = ent->s;
body->r.s = body->s;
body->s.eFlags = EF_DEAD;
@@ -584,6 +586,9 @@ void CopyToBodyQue( gentity_t *ent ) {
body->r.contents = CONTENTS_BODY;
body->clipmask = MASK_PLAYERSOLID;
body->s.clientNum = ent->client->ps.stats[ STAT_PCLASS ];
+
+ if( ent->client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS )
+ body->use = InfestBody;
switch ( body->s.legsAnim & ~ANIM_TOGGLEBIT ) {
case BOTH_DEATH1:
@@ -669,12 +674,12 @@ respawn
void respawn( gentity_t *ent ) {
gentity_t *tent;
- CopyToBodyQue (ent);
+ SpawnCorpse( ent );
//TA: Clients can't respawn - they must go thru the class cmd
- ClientSpawn(ent);
+ ClientSpawn( ent, NULL );
- //FIXME: need different spawn/respawn functions for different teams
+ //FIXME: need different spawn effects for different teams
// add a teleportation effect
//tent = G_TempEntity( ent->client->ps.origin, EV_PLAYER_TELEPORT_IN );
@@ -1124,7 +1129,7 @@ void ClientBegin( int clientNum ) {
// locate ent at a spawn point
- ClientSpawn( ent );
+ ClientSpawn( ent, NULL );
if ( client->sess.sessionTeam != TEAM_SPECTATOR ) {
// send event
@@ -1150,7 +1155,7 @@ after the first ClientBegin, and after each respawn
Initializes all non-persistant parts of playerState
============
*/
-void ClientSpawn(gentity_t *ent) {
+void ClientSpawn( gentity_t *ent, gentity_t *spawn ) {
int index;
vec3_t spawn_origin, spawn_angles;
gclient_t *client;
@@ -1199,13 +1204,32 @@ void ClientSpawn(gentity_t *ent) {
}
else
{
- // don't spawn near existing origin if possible
- spawnPoint = SelectTremulousSpawnPoint( teamLocal, spawn_origin, spawn_angles );
+ if( spawn != NULL )
+ {
+ vec3_t bodyMaxs;
+ vec3_t classMins;
+ vec3_t up = { 0, 0, 1 };
+
+ VectorCopy ( spawn->s.pos.trBase, spawn_origin );
+ VectorCopy ( spawn->s.angles, spawn_angles );
+
+ BG_FindBBoxForClass( spawn->s.clientNum, NULL, NULL, NULL, NULL, bodyMaxs );
+ BG_FindBBoxForClass( ent->client->pers.pclass, classMins, NULL, NULL, NULL, NULL );
- if( spawnPoint == NULL )
+ spawn_origin[ 2 ] += 64;
+ G_AddEvent( spawn, EV_GIB_DROID, DirToByte( up ) );
+ spawn->freeAfterEvent = qtrue;
+ }
+ else
{
- trap_SendServerCommand( ent-g_entities, va("print \"No suitable spawns available\n\"" ) );
- return;
+ // don't spawn near existing origin if possible
+ spawnPoint = SelectTremulousSpawnPoint( teamLocal, spawn_origin, spawn_angles );
+
+ if( spawnPoint == NULL )
+ {
+ trap_SendServerCommand( ent-g_entities, va("print \"No suitable spawns available\n\"" ) );
+ return;
+ }
}
}
client->pers.teamState.state = TEAM_ACTIVE;
@@ -1279,81 +1303,35 @@ void ClientSpawn(gentity_t *ent) {
client->ps.stats[ STAT_WEAPONS ] = 0;
client->ps.stats[ STAT_WEAPONS2 ] = 0;
+ client->ps.eFlags = flags;
+ client->ps.clientNum = index;
+
+ VectorCopy (playerMins, ent->r.mins);
+ VectorCopy (playerMaxs, ent->r.maxs);
+
+ client->pers.maxHealth = client->ps.stats[ STAT_MAX_HEALTH ] = BG_FindHealthForClass( ent->client->pers.pclass );
+ client->ps.stats[ STAT_ARMOR ] = BG_FindArmorForClass( ent->client->pers.pclass );
+ client->classSpeed = BG_FindSpeedForClass( ent->client->pers.pclass );
+
// clear entity values
switch( ent->client->pers.pclass )
{
case PCL_D_B_BASE:
- client->pers.maxHealth = 50;
- client->ps.stats[STAT_MAX_HEALTH] = 50;
- client->ps.stats[STAT_ARMOR] = 50;
-
- client->ps.eFlags = flags;
-
- VectorCopy (playerMins, ent->r.mins);
- VectorCopy (playerMaxs, ent->r.maxs);
-
- client->ps.clientNum = index;
-
BG_packWeapon( WP_ABUILD, client->ps.stats );
BG_packAmmoArray( WP_ABUILD, client->ps.ammo, client->ps.powerups, 0, 0, 0 );
-
- client->ps.stats[ STAT_ABILITIES ] |= SCA_TAKESFALLDAMAGE;
- BG_packAttributes( 80, 15, 350, client->ps.stats );
- client->classSpeed = 0.5;
break;
case PCL_D_O_BASE:
- client->pers.maxHealth = 25;
- client->ps.stats[STAT_MAX_HEALTH] = 25;
- client->ps.eFlags = flags;
-
- VectorCopy (playerMins, ent->r.mins);
- VectorCopy (playerMaxs, ent->r.maxs);
-
- client->ps.clientNum = index;
-
BG_packWeapon( WP_VENOM, client->ps.stats );
BG_packAmmoArray( WP_VENOM, client->ps.ammo, client->ps.powerups, 0, 0, 0 );
-
- client->ps.stats[ STAT_ABILITIES ] |= SCA_WALLCLIMBER;
- client->ps.stats[ STAT_ABILITIES ] |= SCA_CANJUMP;
- client->ps.stats[ STAT_ABILITIES ] |= SCA_NOWEAPONDRIFT;
- BG_packAttributes( 140, 0, 25, client->ps.stats );
- client->classSpeed = 2.0;
break;
case PCL_D_D_BASE:
- client->pers.maxHealth = 50;
- client->ps.stats[STAT_MAX_HEALTH] = 50;
- client->ps.eFlags = flags;
-
- VectorCopy (playerMins, ent->r.mins);
- VectorCopy (playerMaxs, ent->r.maxs);
-
- client->ps.clientNum = index;
-
BG_packWeapon( WP_VENOM, client->ps.stats );
BG_packAmmoArray( WP_VENOM, client->ps.ammo, client->ps.powerups, 0, 0, 0 );
-
- client->ps.stats[ STAT_ABILITIES ] |= SCA_WALLCLIMBER;
- client->ps.stats[ STAT_ABILITIES ] |= SCA_CANJUMP;
- client->ps.stats[ STAT_ABILITIES ] |= SCA_NOWEAPONDRIFT;
- BG_packAttributes( 160, 0, 25, client->ps.stats );
- client->classSpeed = 1.5;
break;
case PCL_H_BASE:
- client->pers.maxHealth = 100;
- client->ps.stats[STAT_MAX_HEALTH] = 100;
- client->ps.stats[STAT_ARMOR] = 50;
-
- client->ps.eFlags = flags;
-
- VectorCopy (playerMins, ent->r.mins);
- VectorCopy (playerMaxs, ent->r.maxs);
-
- client->ps.clientNum = index;
-
if( client->pers.pitem == WP_MACHINEGUN )
{
BG_packWeapon( WP_MACHINEGUN, client->ps.stats );
@@ -1364,23 +1342,10 @@ void ClientSpawn(gentity_t *ent) {
BG_packWeapon( WP_HBUILD, client->ps.stats );
BG_packAmmoArray( WP_HBUILD, client->ps.ammo, client->ps.powerups, 0, 0, 0 );
}
-
- client->ps.stats[ STAT_ABILITIES ] |= SCA_TAKESFALLDAMAGE;
- client->ps.stats[ STAT_ABILITIES ] |= SCA_CANJUMP;
- BG_packAttributes( 90, 2, 200, client->ps.stats );
- client->classSpeed = 1.0;
break;
//eventually remove this case (or report an error) when all classes implemented
default:
- client->ps.stats[STAT_MAX_HEALTH] = client->pers.maxHealth;
- client->ps.eFlags = flags;
-
- VectorCopy (playerMins, ent->r.mins);
- VectorCopy (playerMaxs, ent->r.maxs);
-
- client->ps.clientNum = index;
-
BG_packWeapon( WP_MACHINEGUN, client->ps.stats );
BG_packAmmoArray( WP_MACHINEGUN, client->ps.ammo, client->ps.powerups, 100, 0, 0 );
@@ -1388,19 +1353,11 @@ void ClientSpawn(gentity_t *ent) {
BG_packAmmoArray( WP_GAUNTLET, client->ps.ammo, client->ps.powerups, 0, 0, 0 );
BG_packAmmoArray( WP_GRAPPLING_HOOK, client->ps.ammo, client->ps.powerups, 0, 0, 0 );
-
- client->ps.stats[ STAT_ABILITIES ] |= SCA_TAKESFALLDAMAGE;
- client->ps.stats[ STAT_ABILITIES ] |= SCA_CANZOOM;
- client->ps.stats[ STAT_ABILITIES ] |= SCA_CANJUMP;
- BG_packAttributes( 90, 2, 200, client->ps.stats );
- client->classSpeed = 1.0;
-
}
ent->client->ps.stats[ STAT_PCLASS ] = ent->client->pers.pclass;
ent->client->ps.stats[ STAT_PTEAM ] = ent->client->pers.pteam;
-
// health will count down towards max_health
ent->health = client->ps.stats[STAT_HEALTH] = client->ps.stats[STAT_MAX_HEALTH]; //* 1.25;
diff --git a/src/game/g_cmds.c b/src/game/g_cmds.c
index 1bdb9f59..1b2c2be0 100644
--- a/src/game/g_cmds.c
+++ b/src/game/g_cmds.c
@@ -622,7 +622,7 @@ void Cmd_Team_f( gentity_t *ent ) {
if( oldTeam != ent->client->pers.pteam )
{
ent->client->pers.pclass = 0;
- ClientSpawn( ent );
+ ClientSpawn( ent, NULL );
}
//FIXME: put some team change broadcast code here.
@@ -1544,6 +1544,10 @@ void Cmd_Class_f( gentity_t *ent )
char s[ MAX_TOKEN_CHARS ];
qboolean dontSpawn = qfalse;
int clientNum;
+ gentity_t *body, *victim;
+ vec3_t distance;
+ int length = 4096;
+ int i;
clientNum = ent->client - level.clients;
trap_Argv( 1, s, sizeof( s ) );
@@ -1556,9 +1560,48 @@ void Cmd_Class_f( gentity_t *ent )
if( ent->client->pers.pteam == PTE_DROIDS )
{
- if( ent->client->pers.pclass != 0 )
+ if( ent->client->pers.pclass )
{
- trap_SendServerCommand( ent-g_entities, va("print \"You must be dead to use the class command\n\"" ) );
+ for ( i = 1, body = g_entities + i; i < level.num_entities; i++, body++ )
+ {
+ if( !Q_stricmp( body->classname, "humanCorpse" ) )
+ {
+ VectorSubtract( ent->s.pos.trBase, body->s.origin, distance );
+ if( VectorLength( distance ) <= length )
+ {
+ length = VectorLength( distance );
+ victim = body;
+ }
+ }
+ }
+
+ if( length <= 200 )
+ {
+ if( !Q_stricmp(s, "0") )
+ ent->client->pers.pclass = PCL_D_B_BASE;
+ else if( !Q_stricmp(s, "1") )
+ ent->client->pers.pclass = PCL_D_O_BASE;
+ else if( !Q_stricmp(s, "2") )
+ ent->client->pers.pclass = PCL_D_D_BASE;
+ else
+ {
+ trap_SendServerCommand( ent-g_entities, va("print \"Unknown class\n\"" ) );
+ dontSpawn = qtrue;
+ }
+
+ if( !dontSpawn )
+ {
+ ent->client->sess.sessionTeam = TEAM_FREE;
+ ClientUserinfoChanged( clientNum );
+ ClientSpawn( ent, victim );
+ }
+ }
+
+ return;
+ }
+ else if( ent->client->pers.pclass != 0 )
+ {
+ trap_SendServerCommand( ent-g_entities, va("print \"You must be dead to spawn from a bioegg\n\"" ) );
return;
}
@@ -1576,12 +1619,9 @@ void Cmd_Class_f( gentity_t *ent )
if( !dontSpawn )
{
- if( ent->client->torch != NULL )
- Cmd_TorchOff_f( ent );
-
ent->client->sess.sessionTeam = TEAM_FREE;
ClientUserinfoChanged( clientNum );
- ClientSpawn( ent );
+ ClientSpawn( ent, NULL );
}
}
else if( ent->client->pers.pteam == PTE_HUMANS )
@@ -1599,18 +1639,15 @@ void Cmd_Class_f( gentity_t *ent )
else if( !Q_stricmp( s, "1" ) )
ent->client->pers.pitem = WP_HBUILD;
- if( ent->client->torch != NULL )
- Cmd_TorchOff_f( ent );
-
ent->client->sess.sessionTeam = TEAM_FREE;
ClientUserinfoChanged( clientNum );
- ClientSpawn( ent );
+ ClientSpawn( ent, NULL );
}
else if( ent->client->pers.pteam == PTE_NONE )
{
ent->client->pers.pclass = 0;
ent->client->sess.sessionTeam = TEAM_FREE;
- ClientSpawn( ent );
+ ClientSpawn( ent, NULL );
trap_SendServerCommand( ent-g_entities, va("print \"Join a team first\n\"" ) );
}
else
diff --git a/src/game/g_local.h b/src/game/g_local.h
index b7e02177..1ddc628e 100644
--- a/src/game/g_local.h
+++ b/src/game/g_local.h
@@ -35,8 +35,6 @@
// the "gameversion" client command will print this plus compile date
#define GAMEVERSION "baseq3"
-#define BODY_QUEUE_SIZE 8
-
#define INFINITE 1000000
#define FRAMETIME 100 // msec
@@ -409,8 +407,6 @@ typedef struct {
qboolean locationLinked; // target_locations get linked
gentity_t *locationHead; // head of the location list
- int bodyQueIndex; // dead bodies
- gentity_t *bodyQue[BODY_QUEUE_SIZE];
//TA: extra stuff:
int numDroidSpawns;
@@ -574,13 +570,13 @@ int TeamLeader( int team );
team_t PickTeam( int ignoreClientNum );
void SetClientViewAngle( gentity_t *ent, vec3_t angle );
gentity_t *SelectSpawnPoint ( vec3_t avoidPoint, vec3_t origin, vec3_t angles );
-void CopyToBodyQue( gentity_t *ent );
+void SpawnCorpse( gentity_t *ent );
void respawn (gentity_t *ent);
void BeginIntermission (void);
void InitClientPersistant (gclient_t *client);
void InitClientResp (gclient_t *client);
void InitBodyQue (void);
-void ClientSpawn( gentity_t *ent );
+void ClientSpawn( gentity_t *ent, gentity_t *spawn );
void player_die (gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int damage, int mod);
void AddScore( gentity_t *ent, int score );
diff --git a/src/game/g_main.c b/src/game/g_main.c
index cf82e34d..8f39f4fb 100644
--- a/src/game/g_main.c
+++ b/src/game/g_main.c
@@ -460,9 +460,6 @@ void G_InitGame( int levelTime, int randomSeed, int restart ) {
trap_LocateGameData( level.gentities, level.num_entities, sizeof( gentity_t ),
&level.clients[0].ps, sizeof( level.clients[0] ) );
- // reserve some spots for dead player bodies
- InitBodyQue();
-
ClearRegisteredItems();
// parse the key/value pairs and spawn gentities