diff options
-rw-r--r-- | src/cgame/cg_event.c | 10 | ||||
-rw-r--r-- | src/cgame/cg_view.c | 16 | ||||
-rw-r--r-- | src/cgame/cg_weapons.c | 6 | ||||
-rw-r--r-- | src/game/bg_misc.c | 223 | ||||
-rw-r--r-- | src/game/bg_pmove.c | 32 | ||||
-rw-r--r-- | src/game/bg_public.h | 24 | ||||
-rw-r--r-- | src/game/g_active.c | 21 | ||||
-rw-r--r-- | src/game/g_buildable.c | 2 | ||||
-rw-r--r-- | src/game/g_client.c | 175 | ||||
-rw-r--r-- | src/game/g_cmds.c | 61 | ||||
-rw-r--r-- | src/game/g_local.h | 8 | ||||
-rw-r--r-- | src/game/g_main.c | 3 |
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 = ¢->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 |