diff options
-rw-r--r-- | src/cgame/cg_draw.c | 73 | ||||
-rw-r--r-- | src/cgame/cg_tutorial.c | 11 | ||||
-rw-r--r-- | src/cgame/cg_view.c | 12 | ||||
-rw-r--r-- | src/game/bg_pmove.c | 62 | ||||
-rw-r--r-- | src/game/bg_public.h | 3 | ||||
-rw-r--r-- | src/game/g_active.c | 22 | ||||
-rw-r--r-- | src/game/g_buildable.c | 9 | ||||
-rw-r--r-- | src/game/g_client.c | 2 | ||||
-rw-r--r-- | src/game/g_cmds.c | 5 | ||||
-rw-r--r-- | src/game/tremulous.h | 14 |
10 files changed, 207 insertions, 6 deletions
diff --git a/src/cgame/cg_draw.c b/src/cgame/cg_draw.c index 570276b..0af9839 100644 --- a/src/cgame/cg_draw.c +++ b/src/cgame/cg_draw.c @@ -375,10 +375,34 @@ static void CG_DrawPlayerStamina( int ownerDraw, rectDef_t *rect, vec4_t backColor, vec4_t foreColor, qhandle_t shader ) { + playerState_t *ps = &cg.snap->ps; + float stamina = ps->stats[ STAT_STAMINA ]; + float maxStaminaBy3 = (float)STAMINA_MAX / 3.0f; float progress; vec4_t color; - progress = 0.0f; + switch( ownerDraw ) + { + case CG_PLAYER_STAMINA_1: + progress = ( stamina - 2 * (int)maxStaminaBy3 ) / maxStaminaBy3; + break; + case CG_PLAYER_STAMINA_2: + progress = ( stamina - (int)maxStaminaBy3 ) / maxStaminaBy3; + break; + case CG_PLAYER_STAMINA_3: + progress = stamina / maxStaminaBy3; + break; + case CG_PLAYER_STAMINA_4: + progress = ( stamina + STAMINA_MAX ) / STAMINA_MAX; + break; + default: + return; + } + + if( progress > 1.0f ) + progress = 1.0f; + else if( progress < 0.0f ) + progress = 0.0f; Vector4Lerp( progress, backColor, foreColor, color ); @@ -395,9 +419,25 @@ CG_DrawPlayerStaminaBolt static void CG_DrawPlayerStaminaBolt( rectDef_t *rect, vec4_t backColor, vec4_t foreColor, qhandle_t shader ) { + float stamina = cg.snap->ps.stats[ STAT_STAMINA ]; vec4_t color; - Vector4Copy( backColor, color ); + if( cg.predictedPlayerState.stats[ STAT_STATE ] & SS_SPEEDBOOST ) + { + if( stamina >= 0 ) + Vector4Lerp( ( sin( cg.time / 150.0f ) + 1 ) / 2, + backColor, foreColor, color ); + else + Vector4Lerp( ( sin( cg.time / 2000.0f ) + 1 ) / 2, + backColor, foreColor, color ); + } + else + { + if( stamina < 0 ) + Vector4Copy( backColor, color ); + else + Vector4Copy( foreColor, color ); + } trap_R_SetColor( color ); CG_DrawPic( rect->x, rect->y, rect->w, rect->h, shader ); @@ -3420,6 +3460,31 @@ void CG_RunMenuScript( char **args ) } //END TA UI + +/* +================ +CG_DrawLighting + +================ +*/ +static void CG_DrawLighting( void ) +{ + // centity_t *cent; + + // cent = &cg_entities[ cg.snap->ps.clientNum ]; + + //fade to black if stamina is low + if( ( cg.snap->ps.stats[ STAT_STAMINA ] < STAMINA_BLACKOUT_LEVEL ) && + ( cg.snap->ps.stats[ STAT_TEAM ] == TEAM_HUMANS ) ) + { + vec4_t black = { 0, 0, 0, 0 }; + black[ 3 ] = 1.0 - ( (float)( cg.snap->ps.stats[ STAT_STAMINA ] + 1000 ) / 200.0f ); + trap_R_SetColor( black ); + CG_DrawPic( 0, 0, 640, 480, cgs.media.whiteShader ); + trap_R_SetColor( NULL ); + } +} + /* =============================================================================== @@ -4097,6 +4162,10 @@ static void CG_Draw2D( void ) if( cg.levelShot ) return; + // fading to black if stamina runs out + // (only 2D that can't be disabled) + CG_DrawLighting( ); + if( cg_draw2D.integer == 0 ) return; diff --git a/src/cgame/cg_tutorial.c b/src/cgame/cg_tutorial.c index d2f01b3..d36ecac 100644 --- a/src/cgame/cg_tutorial.c +++ b/src/cgame/cg_tutorial.c @@ -514,6 +514,17 @@ static void CG_HumanText( char *text, playerState_t *ps ) BG_Upgrade( UP_MEDKIT )->humanName ) ); } + if( ps->stats[ STAT_STAMINA ] <= STAMINA_BLACKOUT_LEVEL ) + { + Q_strcat( text, MAX_TUTORIAL_TEXT, + "You are blacking out. Stop sprinting to recover stamina\n" ); + } + else if( ps->stats[ STAT_STAMINA ] <= STAMINA_SLOW_LEVEL ) + { + Q_strcat( text, MAX_TUTORIAL_TEXT, + "Your stamina is low. Stop sprinting to recover\n" ); + } + switch( cg.nearUsableBuildable ) { case BA_H_ARMOURY: diff --git a/src/cgame/cg_view.c b/src/cgame/cg_view.c index 333e421..1221fe9 100644 --- a/src/cgame/cg_view.c +++ b/src/cgame/cg_view.c @@ -809,6 +809,18 @@ void CG_OffsetFirstPersonView( void ) cg.predictedPlayerState.pm_type == PM_JETPACK ) ) { angles[PITCH] += cg.bobfracsin * bob2 * 0.5; + + // heavy breathing effects //FIXME: sound + if( cg.predictedPlayerState.stats[ STAT_STAMINA ] < STAMINA_BREATHING_LEVEL ) + { + float deltaBreath = ( cg.predictedPlayerState.stats[ STAT_STAMINA ] - + STAMINA_BREATHING_LEVEL ) / -250.0; + float deltaAngle = cos( (float)cg.time/150.0 ) * deltaBreath; + + deltaAngle += ( deltaAngle < 0 ? -deltaAngle : deltaAngle ) * 0.5; + + angles[ PITCH ] -= deltaAngle; + } } //=================================== diff --git a/src/game/bg_pmove.c b/src/game/bg_pmove.c index 63b67fa..ecdaccf 100644 --- a/src/game/bg_pmove.c +++ b/src/game/bg_pmove.c @@ -406,6 +406,57 @@ static float PM_CmdScale( usercmd_t *cmd ) if( pm->ps->stats[ STAT_TEAM ] == TEAM_HUMANS && pm->ps->pm_type == PM_NORMAL ) { + qboolean wasSprinting; + qboolean sprint; + wasSprinting = sprint = pm->ps->stats[ STAT_STATE ] & SS_SPEEDBOOST; + + if( pm->ps->persistant[ PERS_STATE ] & PS_SPRINTTOGGLE ) + { + if( cmd->buttons & BUTTON_SPRINT && + !( pm->ps->pm_flags & PMF_SPRINTHELD ) ) + { + sprint = !sprint; + pm->ps->pm_flags |= PMF_SPRINTHELD; + } + else if( pm->ps->pm_flags & PMF_SPRINTHELD && + !( cmd->buttons & BUTTON_SPRINT ) ) + pm->ps->pm_flags &= ~PMF_SPRINTHELD; + } + else + sprint = cmd->buttons & BUTTON_SPRINT; + + if( sprint ) + pm->ps->stats[ STAT_STATE ] |= SS_SPEEDBOOST; + else if( wasSprinting && !sprint ) + pm->ps->stats[ STAT_STATE ] &= ~SS_SPEEDBOOST; + + // Walk overrides sprint. We keep the state that we want to be sprinting + // (above), but don't apply the modifier, and in g_active we skip taking + // the stamina too. + if( sprint && !( cmd->buttons & BUTTON_WALKING ) ) + modifier *= HUMAN_SPRINT_MODIFIER; + else + modifier *= HUMAN_JOG_MODIFIER; + + if( cmd->forwardmove < 0 ) + { + //can't run backwards + modifier *= HUMAN_BACK_MODIFIER; + } + else if( cmd->rightmove ) + { + //can't move that fast sideways + modifier *= HUMAN_SIDE_MODIFIER; + } + + //must have have stamina to jump + if( pm->ps->stats[ STAT_STAMINA ] < STAMINA_SLOW_LEVEL + STAMINA_JUMP_TAKE ) + cmd->upmove = 0; + + //slow down once stamina depletes + if( pm->ps->stats[ STAT_STAMINA ] <= STAMINA_SLOW_LEVEL ) + modifier *= (float)( pm->ps->stats[ STAT_STAMINA ] + STAMINA_MAX ) / (float)(STAMINA_SLOW_LEVEL + STAMINA_MAX); + if( pm->ps->stats[ STAT_STATE ] & SS_CREEPSLOWED ) { if( BG_InventoryContainsUpgrade( UP_LIGHTARMOUR, pm->ps->stats ) || @@ -906,6 +957,10 @@ static qboolean PM_CheckJump( void ) pm->ps->stats[ STAT_MISC ] > 0 ) return qfalse; + if( ( pm->ps->stats[ STAT_TEAM ] == TEAM_HUMANS ) && + ( pm->ps->stats[ STAT_STAMINA ] < STAMINA_SLOW_LEVEL + STAMINA_JUMP_TAKE ) ) + return qfalse; + //no bunny hopping off a dodge if( pm->ps->stats[ STAT_TEAM ] == TEAM_HUMANS && pm->ps->pm_time ) @@ -944,6 +999,10 @@ static qboolean PM_CheckJump( void ) pml.walking = qfalse; pm->ps->pm_flags |= PMF_JUMP_HELD; + // take some stamina off + if( pm->ps->stats[ STAT_TEAM ] == TEAM_HUMANS ) + pm->ps->stats[ STAT_STAMINA ] -= STAMINA_JUMP_TAKE; + pm->ps->groundEntityNum = ENTITYNUM_NONE; // jump away from wall @@ -2748,6 +2807,9 @@ static void PM_Footsteps( void ) bobmove *= BG_Class( pm->ps->stats[ STAT_CLASS ] )->bobCycle; + if( pm->ps->stats[ STAT_STATE ] & SS_SPEEDBOOST ) + bobmove *= HUMAN_SPRINT_MODIFIER; + // check for footstep / splash sounds old = pm->ps->bobCycle; pm->ps->bobCycle = (int)( old + bobmove * pml.msec ) & 255; diff --git a/src/game/bg_public.h b/src/game/bg_public.h index 61da2f7..1e9d23c 100644 --- a/src/game/bg_public.h +++ b/src/game/bg_public.h @@ -224,12 +224,13 @@ typedef enum STAT_MAX_HEALTH,// health / armor limit, changable by handicap STAT_CLASS, // player class (for aliens AND humans) STAT_TEAM, // player team + STAT_STAMINA, // stamina (human only) STAT_STATE, // client states e.g. wall climbing STAT_MISC, // for uh...misc stuff (pounce, trample, lcannon) STAT_BUILDABLE, // which ghost model to display for building STAT_FALLDIST, // the distance the player fell STAT_VIEWLOCK // direction to lock the view in - // netcode has space for 4 more + // netcode has space for 3 more } statIndex_t; #define SCA_WALLCLIMBER 0x00000001 diff --git a/src/game/g_active.c b/src/game/g_active.c index 2bf6400..0c84f57 100644 --- a/src/game/g_active.c +++ b/src/game/g_active.c @@ -631,6 +631,7 @@ void SpectatorThink( gentity_t *ent, usercmd_t *ucmd ) client->ps.pm_flags |= PMF_QUEUED; client->ps.speed = client->pers.flySpeed; + client->ps.stats[ STAT_STAMINA ] = 0; client->ps.stats[ STAT_MISC ] = 0; client->ps.stats[ STAT_BUILDABLE ] = BA_NONE; client->ps.stats[ STAT_CLASS ] = PCL_NONE; @@ -806,10 +807,26 @@ void ClientTimerActions( gentity_t *ent, int msec ) client->ps.stats[ STAT_STATE ] &= ~SS_INVI; } - // Regenerate health if we have got a Biokit + // Restore or subtract stamina + if( stopped || client->ps.pm_type == PM_JETPACK ) + client->ps.stats[ STAT_STAMINA ] += STAMINA_STOP_RESTORE; + else if( ( client->ps.stats[ STAT_STATE ] & SS_SPEEDBOOST ) && + !( client->buttons & BUTTON_WALKING ) ) // walk overrides sprint + client->ps.stats[ STAT_STAMINA ] -= STAMINA_SPRINT_TAKE; + else if( walking || crouched ) + client->ps.stats[ STAT_STAMINA ] += STAMINA_WALK_RESTORE; + + // Check stamina limits + if( client->ps.stats[ STAT_STAMINA ] > STAMINA_MAX ) + client->ps.stats[ STAT_STAMINA ] = STAMINA_MAX; + else if( client->ps.stats[ STAT_STAMINA ] < -STAMINA_MAX ) + client->ps.stats[ STAT_STAMINA ] = -STAMINA_MAX; + + // Regenerate health and stamina if we have got a Biokit if( BG_InventoryContainsUpgrade( UP_BIOKIT, client->ps.stats ) ) { int rate_health = BIOKIT_HEALTH_RATE; + int rate_stamina = BIOKIT_STAMINA_RATE; if( ent->nextRegenTime < level.time && ent->health > 0 && rate_health > 0 && ent->health < client->ps.stats[ STAT_MAX_HEALTH ] ) @@ -823,6 +840,9 @@ void ClientTimerActions( gentity_t *ent, int msec ) ent->nextRegenTime = level.time + 5000/rate_health; ent->client->alreadyRegenerated = qtrue; } + + if( client->ps.stats[ STAT_STAMINA ] + rate_stamina <= STAMINA_MAX ) + client->ps.stats[ STAT_STAMINA ] += rate_stamina; } if( weapon == WP_ABUILD || diff --git a/src/game/g_buildable.c b/src/game/g_buildable.c index fa66979..21f5424 100644 --- a/src/game/g_buildable.c +++ b/src/game/g_buildable.c @@ -2830,7 +2830,8 @@ void HMedistat_Think( gentity_t *self ) if( player->client && player->client->ps.stats[ STAT_TEAM ] == TEAM_HUMANS ) { - if( player->health < player->client->ps.stats[ STAT_MAX_HEALTH ] && + if( ( player->health < player->client->ps.stats[ STAT_MAX_HEALTH ] || + player->client->ps.stats[ STAT_STAMINA ] < STAMINA_MAX ) && PM_Live( player->client->ps.pm_type ) ) { self->enemy = player; @@ -2860,6 +2861,12 @@ void HMedistat_Think( gentity_t *self ) } else if( self->enemy && self->enemy->client ) //heal! { + if( self->enemy->client->ps.stats[ STAT_STAMINA ] < STAMINA_MAX ) + self->enemy->client->ps.stats[ STAT_STAMINA ] += STAMINA_MEDISTAT_RESTORE; + + if( self->enemy->client->ps.stats[ STAT_STAMINA ] > STAMINA_MAX ) + self->enemy->client->ps.stats[ STAT_STAMINA ] = STAMINA_MAX; + self->enemy->health++; //if they're completely healed, give them a medkit diff --git a/src/game/g_client.c b/src/game/g_client.c index bfb79b9..896a7fc 100644 --- a/src/game/g_client.c +++ b/src/game/g_client.c @@ -1505,6 +1505,8 @@ void ClientSpawn( gentity_t *ent, gentity_t *spawn, vec3_t origin, vec3_t angles for( i = 0; i < MAX_CLIENTS; i++ ) ent->credits[ i ] = 0; + client->ps.stats[ STAT_STAMINA ] = STAMINA_MAX; + G_SetOrigin( ent, spawn_origin ); VectorCopy( spawn_origin, client->ps.origin ); diff --git a/src/game/g_cmds.c b/src/game/g_cmds.c index 74dea71..f3cada7 100644 --- a/src/game/g_cmds.c +++ b/src/game/g_cmds.c @@ -450,7 +450,7 @@ void Cmd_Give_f( gentity_t *ent ) if( trap_Argc( ) < 2 ) { ADMP( "usage: give [what]\n" ); - ADMP( "usage: valid choices are: all, health, funds [amount], " + ADMP( "usage: valid choices are: all, health, funds [amount], stamina, " "poison, gas, ammo\n" ); return; } @@ -487,6 +487,9 @@ void Cmd_Give_f( gentity_t *ent ) G_AddCreditToClient( ent->client, (short)credits, qtrue ); } + if( give_all || Q_stricmp( name, "stamina" ) == 0 ) + ent->client->ps.stats[ STAT_STAMINA ] = STAMINA_MAX; + if( Q_stricmp( name, "poison" ) == 0 ) { if( ent->client->pers.teamSelection == TEAM_HUMANS ) diff --git a/src/game/tremulous.h b/src/game/tremulous.h index 3db55f9..229e4ea 100644 --- a/src/game/tremulous.h +++ b/src/game/tremulous.h @@ -324,7 +324,21 @@ TREMULOUS EDGE MOD SRC FILE * HUMAN */ +#define HUMAN_SPRINT_MODIFIER 1.28f +#define HUMAN_JOG_MODIFIER 1.1f +#define HUMAN_BACK_MODIFIER 0.8f +#define HUMAN_SIDE_MODIFIER 0.9f #define HUMAN_LAND_FRICTION 3.0f +#define STAMINA_STOP_RESTORE 20 +#define STAMINA_WALK_RESTORE 15 +#define STAMINA_MEDISTAT_RESTORE 30 +#define STAMINA_SPRINT_TAKE 8 +#define STAMINA_JUMP_TAKE 250 +#define STAMINA_DODGE_TAKE 250 +#define STAMINA_MAX 1200 +#define STAMINA_BREATHING_LEVEL 0 +#define STAMINA_SLOW_LEVEL -500 +#define STAMINA_BLACKOUT_LEVEL -800 #define HUMAN_SPAWN_REPEAT_TIME 11000 #define HUMAN_REGEN_DAMAGE_TIME 2000 //msec since damage before dcc repairs #define HUMAN_MAX_CREDITS 2000 |