diff options
-rw-r--r-- | src/cgame/cg_local.h | 7 | ||||
-rw-r--r-- | src/cgame/cg_view.c | 35 | ||||
-rw-r--r-- | src/cgame/cg_weapons.c | 25 | ||||
-rw-r--r-- | src/game/bg_misc.c | 29 | ||||
-rw-r--r-- | src/game/bg_pmove.c | 103 | ||||
-rw-r--r-- | src/game/bg_public.h | 61 | ||||
-rw-r--r-- | src/game/g_active.c | 30 | ||||
-rw-r--r-- | src/game/g_client.c | 6 | ||||
-rw-r--r-- | src/game/g_combat.c | 11 | ||||
-rw-r--r-- | src/game/g_local.h | 4 | ||||
-rw-r--r-- | src/game/g_main.c | 5 | ||||
-rw-r--r-- | src/game/g_weapon.c | 110 |
12 files changed, 366 insertions, 60 deletions
diff --git a/src/cgame/cg_local.h b/src/cgame/cg_local.h index ce615221..c66ce5fe 100644 --- a/src/cgame/cg_local.h +++ b/src/cgame/cg_local.h @@ -631,8 +631,11 @@ typedef struct { char testModelName[MAX_QPATH]; qboolean testGun; - int spawnTime; //TA: fovwarp - + int spawnTime; //TA: fovwarp + int weapon1Time; //TA: time when BUTTON_ATTACK went t->f f->t + int weapon2Time; //TA: time when BUTTON_ATTACK2 went t->f f->t + qboolean weapon1Firing; + qboolean weapon2Firing; } cg_t; diff --git a/src/cgame/cg_view.c b/src/cgame/cg_view.c index 712e5422..aad94541 100644 --- a/src/cgame/cg_view.c +++ b/src/cgame/cg_view.c @@ -244,8 +244,8 @@ static void CG_OffsetThirdPersonView( void ) { // if dead, look at killer if ( cg.predictedPlayerState.stats[STAT_HEALTH] <= 0 ) { - focusAngles[YAW] = cg.predictedPlayerState.stats[STAT_DEAD_YAW]; - cg.refdefViewAngles[YAW] = cg.predictedPlayerState.stats[STAT_DEAD_YAW]; + focusAngles[YAW] = cg.predictedPlayerState.generic1; + cg.refdefViewAngles[YAW] = cg.predictedPlayerState.generic1; } //if ( focusAngles[PITCH] > 45 ) { @@ -346,7 +346,7 @@ static void CG_OffsetFirstPersonView( void ) { if ( cg.snap->ps.stats[STAT_HEALTH] <= 0 ) { angles[ROLL] = 40; angles[PITCH] = -15; - angles[YAW] = cg.snap->ps.stats[STAT_DEAD_YAW]; + angles[YAW] = cg.snap->ps.generic1; origin[2] += cg.predictedPlayerState.viewheight; return; } @@ -407,6 +407,28 @@ static void CG_OffsetFirstPersonView( void ) { angles[ROLL] += delta; } + //provide some feedback for pouncing + if( cg.predictedPlayerState.weapon == WP_POUNCE ) + { + if( cg.predictedPlayerState.stats[ STAT_MISC ] > 0 ) + { + float fraction1, fraction2; + vec3_t forward; + + AngleVectors( angles, forward, NULL, NULL ); + VectorNormalize( forward ); + + fraction1 = (float)( cg.time - cg.weapon2Time ) / POUNCE_TIME; + + if( fraction1 > 1.0f ) + fraction1 = 1.0f; + + fraction2 = -sin( fraction1 * M_PI / 2 ); + + VectorMA( origin, 15*fraction2, forward, origin ); + } + } + //TA: this *feels* more realisitic for humans if( cg.predictedPlayerState.stats[ STAT_PTEAM ] == PTE_HUMANS ) { @@ -458,10 +480,13 @@ static void CG_OffsetFirstPersonView( void ) { // add fall height delta = cg.time - cg.landTime; - if ( delta < LAND_DEFLECT_TIME ) { + if( delta < LAND_DEFLECT_TIME ) + { f = delta / LAND_DEFLECT_TIME; cg.refdef.vieworg[2] += cg.landChange * f; - } else if ( delta < LAND_DEFLECT_TIME + LAND_RETURN_TIME ) { + } + else if( delta < LAND_DEFLECT_TIME + LAND_RETURN_TIME ) + { delta -= LAND_DEFLECT_TIME; f = 1.0 - ( delta / LAND_RETURN_TIME ); cg.refdef.vieworg[2] += cg.landChange * f; diff --git a/src/cgame/cg_weapons.c b/src/cgame/cg_weapons.c index 74a1ef6a..a53336f9 100644 --- a/src/cgame/cg_weapons.c +++ b/src/cgame/cg_weapons.c @@ -601,6 +601,11 @@ void CG_RegisterWeapon( int weaponNum ) { weaponInfo->flashSound[0] = trap_S_RegisterSound( "sound/weapons/melee/fstatck.wav", qfalse ); break; + case WP_POUNCE: + MAKERGB( weaponInfo->flashDlightColor, 0, 0, 0 ); + weaponInfo->flashSound[0] = trap_S_RegisterSound( "sound/weapons/melee/fstatck.wav", qfalse ); + break; + case WP_DBUILD: case WP_HBUILD: case WP_SCANNER: @@ -941,19 +946,35 @@ void CG_AddPlayerWeapon( refEntity_t *parent, playerState_t *ps, centity_t *cent if ( ps ) { if ( cg.predictedPlayerState.weapon == WP_RAILGUN - && cg.predictedPlayerState.weaponstate == WEAPON_FIRING ) { + && cg.predictedPlayerState.weaponstate == WEAPON_FIRING ) + { float f; f = (float)cg.predictedPlayerState.weaponTime / 1500; gun.shaderRGBA[1] = 0; gun.shaderRGBA[0] = gun.shaderRGBA[2] = 255 * ( 1.0 - f ); - } else { + } + else + { gun.shaderRGBA[0] = 255; gun.shaderRGBA[1] = 255; gun.shaderRGBA[2] = 255; gun.shaderRGBA[3] = 255; } + + //set weapon[1/2]Time when respective buttons change state + if( cg.weapon1Firing != ( cg.predictedPlayerState.eFlags & EF_FIRING ) ) + { + cg.weapon1Time = cg.time; + cg.weapon1Firing = ( cg.predictedPlayerState.eFlags & EF_FIRING ); + } + + if( cg.weapon2Firing != ( cg.predictedPlayerState.eFlags & EF_FIRING2 ) ) + { + cg.weapon2Time = cg.time; + cg.weapon2Firing = ( cg.predictedPlayerState.eFlags & EF_FIRING2 ); + } } gun.hModel = weapon->weaponModel; diff --git a/src/game/bg_misc.c b/src/game/bg_misc.c index dbe72df1..66ae1fe8 100644 --- a/src/game/bg_misc.c +++ b/src/game/bg_misc.c @@ -242,6 +242,22 @@ gitem_t bg_itemlist[] = "" }, +/*QUAKED weapon_pounce (.3 .3 1) (-16 -16 -16) (16 16 16) suspended +*/ + { + "weapon_pounce", + "sound/misc/w_pkup.wav", + { "models/weapons2/gauntlet/gauntlet.md3", + 0, 0, 0}, + "icons/iconw_gauntlet", + "Claw and Pounce", + 0, + IT_WEAPON, + WP_POUNCE, + "", + "" + }, + /*QUAKED weapon_abuild (.3 .3 1) (-16 -16 -16) (16 16 16) suspended */ { @@ -2617,6 +2633,18 @@ weaponAttributes_t bg_weapons[ ] = qtrue }, { + WP_POUNCE, + 100, + SLOT_WEAPON, + "pounce", + "Claw and pounce", + 0, + 0, + 0, + qfalse, + qfalse + }, + { WP_SCANNER, 100, SLOT_WEAPON, @@ -3705,6 +3733,7 @@ qboolean BG_infiniteAmmo( int weapon ) { case WP_VENOM: case WP_GRABANDCSAW: + case WP_POUNCE: case WP_DBUILD: case WP_HBUILD: case WP_SCANNER: diff --git a/src/game/bg_pmove.c b/src/game/bg_pmove.c index 85890e97..97e81461 100644 --- a/src/game/bg_pmove.c +++ b/src/game/bg_pmove.c @@ -422,12 +422,6 @@ static float PM_CmdScale( usercmd_t *cmd ) { modifier *= 0.75; } - //cap stamina - if( pm->ps->stats[ STAT_STAMINA ] > 1000 ) - pm->ps->stats[ STAT_STAMINA ] = 1000; - if( pm->ps->stats[ STAT_STAMINA ] < -1000 ) - pm->ps->stats[ STAT_STAMINA ] = -1000; - //must have +ve stamina to jump if( pm->ps->stats[ STAT_STAMINA ] < 0 ) cmd->upmove = 0; @@ -509,11 +503,57 @@ static void PM_SetMovementDir( void ) { /* ============= +PM_CheckPounce +============= +*/ +static qboolean PM_CheckPounce( void ) +{ + vec3_t forward; + + if( pm->ps->weapon != WP_POUNCE ) + return qfalse; + + if( pm->cmd.buttons & BUTTON_ATTACK2 ) + { + pm->ps->pm_flags &= ~PMF_POUNCE; + return qfalse; + } + + if( pm->ps->pm_flags & PMF_POUNCE ) + return qfalse; + + if( pm->ps->stats[ STAT_MISC ] == 0 ) + return qfalse; + + pml.groundPlane = qfalse; // jumping away + pml.walking = qfalse; + + pm->ps->pm_flags |= PMF_POUNCE; + + pm->ps->groundEntityNum = ENTITYNUM_NONE; + + AngleVectors( pm->ps->viewangles, forward, NULL, NULL ); + VectorMA( pm->ps->velocity, pm->ps->stats[ STAT_MISC ], forward, pm->ps->velocity ); + pm->ps->velocity[ 2 ] += JUMP_VELOCITY / 2; + + PM_AddEvent( EV_JUMP ); + + return qtrue; +} + +/* +============= PM_CheckJump ============= */ -static qboolean PM_CheckJump( void ) { - if( !BG_ClassHasAbility( pm->ps->stats[ STAT_PCLASS ], SCA_CANJUMP ) ) return qfalse; +static qboolean PM_CheckJump( void ) +{ + if( !BG_ClassHasAbility( pm->ps->stats[ STAT_PCLASS ], SCA_CANJUMP ) ) + return qfalse; + + //can't jump and pounce charge at the same time + if( pm->ps->weapon == WP_POUNCE && pm->ps->stats[ STAT_MISC ] > 0 ) + return qfalse; if( ( pm->ps->stats[ STAT_PTEAM ] == PTE_HUMANS ) && ( pm->ps->stats[ STAT_STAMINA ] < 0 ) ) @@ -873,7 +913,7 @@ static void PM_ClimbMove( void ) { } - if ( PM_CheckJump () ) { + if ( PM_CheckJump( ) || PM_CheckPounce( ) ) { // jumped away if ( pm->waterlevel > 1 ) { PM_WaterMove(); @@ -995,7 +1035,7 @@ static void PM_WalkMove( void ) { } - if ( PM_CheckJump () ) { + if( PM_CheckJump( ) || PM_CheckPounce( ) ) { // jumped away if ( pm->waterlevel > 1 ) { PM_WaterMove(); @@ -2307,9 +2347,19 @@ static void PM_Weapon( void ) } break; + case WP_POUNCE: + if( !pm->autoWeaponHit[ pm->ps->weapon ] && + !( pm->cmd.buttons & ( BUTTON_ATTACK | BUTTON_ATTACK2 ) ) ) + { + pm->ps->weaponTime = 0; + pm->ps->weaponstate = WEAPON_READY; + return; + } + break; + default: // check for fire - if ( !( pm->cmd.buttons & ( BUTTON_ATTACK | BUTTON_ATTACK2 ) ) ) + if( !( pm->cmd.buttons & ( BUTTON_ATTACK | BUTTON_ATTACK2 ) ) ) { pm->ps->weaponTime = 0; pm->ps->weaponstate = WEAPON_READY; @@ -2333,6 +2383,24 @@ static void PM_Weapon( void ) } else if( pm->cmd.buttons & BUTTON_ATTACK ) PM_AddEvent( EV_FIRE_WEAPON ); + + //TA: yuck hack + if( pm->autoWeaponHit[ pm->ps->weapon ] ) + { + switch( pm->ps->weapon ) + { + case WP_VENOM: + PM_AddEvent( EV_FIRE_WEAPON ); + break; + + case WP_POUNCE: + PM_AddEvent( EV_FIRE_WEAPON2 ); + break; + + default: + break; + } + } PM_StartTorsoAnim( TORSO_ATTACK ); @@ -2387,6 +2455,9 @@ static void PM_Weapon( void ) case WP_GRABANDCSAW: addTime = 50; break; + case WP_POUNCE: + addTime = 750; + break; case WP_DBUILD: addTime = 1000; break; @@ -2636,14 +2707,16 @@ void PmoveSingle (pmove_t *pmove) // set the firing flag for continuous beam weapons if ( !(pm->ps->pm_flags & PMF_RESPAWNED) && pm->ps->pm_type != PM_INTERMISSION - && ( pm->cmd.buttons & BUTTON_ATTACK ) && ( ammo > 0 || clips > 0 ) ) + && ( pm->cmd.buttons & BUTTON_ATTACK ) + && ( ( ammo > 0 || clips > 0 ) || BG_infiniteAmmo( pm->ps->weapon ) ) ) pm->ps->eFlags |= EF_FIRING; else pm->ps->eFlags &= ~EF_FIRING; // set the firing flag for continuous beam weapons if ( !(pm->ps->pm_flags & PMF_RESPAWNED) && pm->ps->pm_type != PM_INTERMISSION - && ( pm->cmd.buttons & BUTTON_ATTACK2 ) && ( ammo > 0 || clips > 0 ) ) + && ( pm->cmd.buttons & BUTTON_ATTACK2 ) + && ( ( ammo > 0 || clips > 0 ) || BG_infiniteAmmo( pm->ps->weapon ) ) ) pm->ps->eFlags |= EF_FIRING2; else pm->ps->eFlags &= ~EF_FIRING2; @@ -2687,9 +2760,9 @@ void PmoveSingle (pmove_t *pmove) 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); } + AngleVectors( wcl[ pm->ps->clientNum ].nonSvangles, pml.forward, pml.right, pml.up ); else - { AngleVectors (pm->ps->viewangles, pml.forward, pml.right, pml.up); } + AngleVectors( pm->ps->viewangles, pml.forward, pml.right, pml.up ); if ( pm->cmd.upmove < 10 ) { // not holding jump diff --git a/src/game/bg_public.h b/src/game/bg_public.h index 16c9d29d..37a6d367 100644 --- a/src/game/bg_public.h +++ b/src/game/bg_public.h @@ -28,31 +28,34 @@ // because games can change separately from the main system version, we need a // second version that must match between game and cgame -#define GAME_VERSION "baseq3-1" +#define GAME_VERSION "baseq3-1" -#define DEFAULT_GRAVITY 800 -#define GIB_HEALTH -40 -#define ARMOR_PROTECTION 0.66 +#define DEFAULT_GRAVITY 800 +#define GIB_HEALTH -40 +#define ARMOR_PROTECTION 0.66 -#define MAX_ITEMS 256 +#define MAX_ITEMS 256 -#define RANK_TIED_FLAG 0x4000 +#define RANK_TIED_FLAG 0x4000 #define DEFAULT_SHOTGUN_SPREAD 700 -#define DEFAULT_SHOTGUN_COUNT 11 +#define DEFAULT_SHOTGUN_COUNT 11 -#define ITEM_RADIUS 15 // item sizes are needed for client side pickup detection +#define ITEM_RADIUS 15 // item sizes are needed for client side pickup detection -#define LIGHTNING_RANGE 768 +#define LIGHTNING_RANGE 768 -#define SCORE_NOT_PRESENT -9999 // for the CS_SCORES[12] when only one player is present +#define SCORE_NOT_PRESENT -9999 // for the CS_SCORES[12] when only one player is present -#define VOTE_TIME 30000 // 30 seconds before vote times out +#define VOTE_TIME 30000 // 30 seconds before vote times out -#define MINS_Z -24 -#define DEFAULT_VIEWHEIGHT 26 -#define CROUCH_VIEWHEIGHT 12 -#define DEAD_VIEWHEIGHT -16 +#define MINS_Z -24 +#define DEFAULT_VIEWHEIGHT 26 +#define CROUCH_VIEWHEIGHT 12 +#define DEAD_VIEWHEIGHT -16 + +#define MAX_POUNCE_SPEED 750 +#define POUNCE_TIME 1000.0f // // config strings are a general means of communicating variable length strings @@ -82,6 +85,7 @@ #define CS_FLAGSTATUS 23 // string indicating flag status in CTF #define CS_SHADERSTATE 24 #define CS_BOTINFO 25 +#define CS_CLIENTS_READY 26 //TA: following suggestion in STAT_ enum STAT_CLIENTS_READY becomes a configstring #define CS_ITEMS 27 // string of 0's and 1's that tell which items are present @@ -153,19 +157,20 @@ typedef enum { } weaponstate_t; // pmove->pm_flags -#define PMF_DUCKED 1 -#define PMF_JUMP_HELD 2 +#define PMF_DUCKED 1 +#define PMF_JUMP_HELD 2 #define PMF_BACKWARDS_JUMP 8 // go into backwards land -#define PMF_BACKWARDS_RUN 16 // coast down to backwards run -#define PMF_TIME_LAND 32 // pm_time is time before rejump +#define PMF_BACKWARDS_RUN 16 // coast down to backwards run +#define PMF_TIME_LAND 32 // pm_time is time before rejump #define PMF_TIME_KNOCKBACK 64 // pm_time is an air-accelerate only time #define PMF_TIME_WATERJUMP 256 // pm_time is waterjump -#define PMF_RESPAWNED 512 // clear after attack and jump buttons come up -#define PMF_USE_ITEM_HELD 1024 -#define PMF_GRAPPLE_PULL 2048 // pull towards grapple location -#define PMF_FOLLOW 4096 // spectate following another player -#define PMF_SCOREBOARD 8192 // spectate as a scoreboard -#define PMF_INVULEXPAND 16384 // invulnerability sphere set to full size +#define PMF_RESPAWNED 512 // clear after attack and jump buttons come up +#define PMF_USE_ITEM_HELD 1024 +#define PMF_GRAPPLE_PULL 2048 // pull towards grapple location +#define PMF_FOLLOW 4096 // spectate following another player +#define PMF_SCOREBOARD 8192 // spectate as a scoreboard +#define PMF_INVULEXPAND 16384 // invulnerability sphere set to full size +#define PMF_POUNCE 32768 //TA: keep track of pouncing #define PMF_ALL_TIMES (PMF_TIME_WATERJUMP|PMF_TIME_LAND|PMF_TIME_KNOCKBACK) @@ -221,14 +226,13 @@ typedef enum { STAT_WEAPONS, // 16 bit fields STAT_WEAPONS2, //TA: another 16 bits to push the max weapon count up STAT_ARMOR, - STAT_DEAD_YAW, // look this direction when dead (FIXME: get rid of?) - STAT_CLIENTS_READY, // bit mask of clients wishing to exit the intermission (FIXME: configstring?) STAT_MAX_HEALTH, // health / armor limit, changable by handicap STAT_PCLASS, //TA: player class (for droids AND humans) STAT_PTEAM, //TA: player team STAT_STAMINA, //TA: stamina (human only) STAT_STATE, //TA: client states e.g. wall climbing - STAT_CREDIT //TA: human credit + STAT_CREDIT, //TA: human credit + STAT_MISC //TA: for uh...misc stuff } statIndex_t; #define SCA_WALLCLIMBER 1 @@ -335,6 +339,7 @@ typedef enum { WP_GRAPPLING_HOOK, WP_VENOM, WP_GRABANDCSAW, + WP_POUNCE, WP_HBUILD, WP_DBUILD, WP_SCANNER, diff --git a/src/game/g_active.c b/src/game/g_active.c index 86dd5148..685ff10c 100644 --- a/src/game/g_active.c +++ b/src/game/g_active.c @@ -469,12 +469,34 @@ void ClientTimerActions( gentity_t *ent, int msec ) client->ps.stats[ STAT_STAMINA ] = 1000; } + //client is poisoned if( client->ps.stats[ STAT_STATE ] & SS_POISONED ) { int damage = ( level.time - client->lastPoisonTime ) / 100; G_Damage( ent, NULL, NULL, NULL, NULL, damage, 0, MOD_VENOM ); } + + //client is charging up for a pounce + if( client->ps.weapon == WP_POUNCE ) + { + if( client->ps.stats[ STAT_MISC ] < MAX_POUNCE_SPEED && ucmd->buttons & BUTTON_ATTACK2 ) + { + client->ps.stats[ STAT_MISC ] += ( 100.0f / POUNCE_TIME ) * MAX_POUNCE_SPEED; + client->allowedToPounce = qtrue; + } + + if( !( ucmd->buttons & BUTTON_ATTACK2 ) ) + { + if( client->ps.stats[ STAT_MISC ] > 0 ) + client->pouncePayload = client->ps.stats[ STAT_MISC ]; + + client->ps.stats[ STAT_MISC ] = 0; + } + + if( client->ps.stats[ STAT_MISC ] > MAX_POUNCE_SPEED ) + client->ps.stats[ STAT_MISC ] = MAX_POUNCE_SPEED; + } } while( client->time1000 >= 1000 ) @@ -770,6 +792,10 @@ void ClientThink_real( gentity_t *ent ) { // set speed client->ps.speed = g_speed.value * BG_FindSpeedForClass( client->ps.stats[ STAT_PCLASS ] ); + //TA: slow player if charging up for a pounce + if( client->ps.weapon == WP_POUNCE && ucmd->buttons & BUTTON_ATTACK2 ) + client->ps.speed *= 0.75; + //TA: slow player if standing in creep for ( i = 1, creepNode = g_entities + i; i < level.num_entities; i++, creepNode++ ) { @@ -858,6 +884,10 @@ void ClientThink_real( gentity_t *ent ) { } break; + case WP_POUNCE: + pm.autoWeaponHit[ WP_POUNCE ] = CheckPounceAttack( ent ); + break; + default: break; } diff --git a/src/game/g_client.c b/src/game/g_client.c index 440b5652..262d7914 100644 --- a/src/game/g_client.c +++ b/src/game/g_client.c @@ -1389,10 +1389,14 @@ void ClientSpawn( gentity_t *ent, gentity_t *spawn ) { break; case PCL_D_O_LEV11: - case PCL_D_O_LEV12: BG_packWeapon( WP_GRABANDCSAW, client->ps.stats ); BG_packAmmoArray( WP_GRABANDCSAW, client->ps.ammo, client->ps.powerups, 0, 0, 0 ); break; + + case PCL_D_O_LEV12: + BG_packWeapon( WP_POUNCE, client->ps.stats ); + BG_packAmmoArray( WP_POUNCE, client->ps.ammo, client->ps.powerups, 0, 0, 0 ); + break; case PCL_D_D_BASE: case PCL_D_D_LEV11: diff --git a/src/game/g_combat.c b/src/game/g_combat.c index 605c8364..7788d2e5 100644 --- a/src/game/g_combat.c +++ b/src/game/g_combat.c @@ -175,16 +175,17 @@ void LookAtKiller( gentity_t *self, gentity_t *inflictor, gentity_t *attacker ) vec3_t dir; vec3_t angles; - if ( attacker && attacker != self ) { + if ( attacker && attacker != self ) VectorSubtract (attacker->s.pos.trBase, self->s.pos.trBase, dir); - } else if ( inflictor && inflictor != self ) { + else if ( inflictor && inflictor != self ) VectorSubtract (inflictor->s.pos.trBase, self->s.pos.trBase, dir); - } else { - self->client->ps.stats[STAT_DEAD_YAW] = self->s.angles[YAW]; + else + { + self->client->ps.generic1 = self->s.angles[YAW]; return; } - self->client->ps.stats[STAT_DEAD_YAW] = vectoyaw ( dir ); + self->client->ps.generic1 = vectoyaw ( dir ); angles[YAW] = vectoyaw ( dir ); angles[PITCH] = 0; diff --git a/src/game/g_local.h b/src/game/g_local.h index 2d285131..e1736309 100644 --- a/src/game/g_local.h +++ b/src/game/g_local.h @@ -341,6 +341,9 @@ struct gclient_s { int lastPoisonTime; int lastGrabTime; //TA: yuck yuck hack urgh + + int pouncePayload; //TA: amount of damage pounce attack will do + qboolean allowedToPounce; }; #define MAX_LOCDAMAGE_TEXT 8192 @@ -632,6 +635,7 @@ void CalcMuzzlePoint( gentity_t *ent, vec3_t forward, vec3_t right, vec3_t up, v void SnapVectorTowards( vec3_t v, vec3_t to ); qboolean CheckVenomAttack( gentity_t *ent ); qboolean CheckGrabAttack( gentity_t *ent ); +qboolean CheckPounceAttack( gentity_t *ent ); void Weapon_HookFree (gentity_t *ent); void Weapon_HookThink (gentity_t *ent); diff --git a/src/game/g_main.c b/src/game/g_main.c index d340e3c7..12c39e80 100644 --- a/src/game/g_main.c +++ b/src/game/g_main.c @@ -1300,13 +1300,14 @@ void CheckIntermissionExit( void ) { // copy the readyMask to each player's stats so // it can be displayed on the scoreboard - for (i=0 ; i< g_maxclients.integer ; i++) { +/* for (i=0 ; i< g_maxclients.integer ; i++) { cl = level.clients + i; if ( cl->pers.connected != CON_CONNECTED ) { continue; } cl->ps.stats[STAT_CLIENTS_READY] = readyMask; - } + }*/ + trap_SetConfigstring( CS_CLIENTS_READY, va( "%d", readyMask ) ); // never exit in less than five seconds if ( level.time < level.intermissiontime + 5000 ) { diff --git a/src/game/g_weapon.c b/src/game/g_weapon.c index 1179ce3e..93e98e01 100644 --- a/src/game/g_weapon.c +++ b/src/game/g_weapon.c @@ -796,6 +796,110 @@ qboolean CheckGrabAttack( gentity_t *ent ) return qtrue; } +/* +====================================================================== + +CLAW AND POUNCE + +====================================================================== +*/ + +/* +=============== +Weapon_Claw_Fire +=============== +*/ +void Weapon_Claw_Fire( gentity_t *ent ) +{ + trace_t tr; + vec3_t end; + gentity_t *tent; + gentity_t *traceEnt; + + // set aiming directions + AngleVectors (ent->client->ps.viewangles, forward, right, up); + + CalcMuzzlePoint( ent, forward, right, up, muzzle ); + + VectorMA( muzzle, 32, forward, end ); + + trap_Trace( &tr, muzzle, NULL, NULL, end, ent->s.number, MASK_SHOT ); + if ( tr.surfaceFlags & SURF_NOIMPACT ) + return; + + traceEnt = &g_entities[ tr.entityNum ]; + + // send blood impact + if ( traceEnt->takedamage && traceEnt->client ) + { + tent = G_TempEntity( tr.endpos, EV_MISSILE_HIT ); + tent->s.otherEntityNum = traceEnt->s.number; + tent->s.eventParm = DirToByte( tr.plane.normal ); + tent->s.weapon = ent->s.weapon; + } + + if ( traceEnt->takedamage ) + G_Damage( traceEnt, ent, ent, forward, tr.endpos, 50, DAMAGE_NO_KNOCKBACK, MOD_VENOM ); +} + +/* +=============== +CheckPounceAttack +=============== +*/ +qboolean CheckPounceAttack( gentity_t *ent ) +{ + trace_t tr; + vec3_t end; + gentity_t *tent; + gentity_t *traceEnt; + int damage; + + if( !ent->client->allowedToPounce ) + return qfalse; + + if( ent->client->ps.groundEntityNum != ENTITYNUM_NONE ) + return qfalse; + + // set aiming directions + AngleVectors (ent->client->ps.viewangles, forward, right, up); + + CalcMuzzlePoint( ent, forward, right, up, muzzle ); + + VectorMA (muzzle, 32, forward, end); + + trap_Trace (&tr, muzzle, NULL, NULL, end, ent->s.number, MASK_SHOT); + + //miss + if( tr.fraction >= 1.0 ) + return qfalse; + + if ( tr.surfaceFlags & SURF_NOIMPACT ) + return qfalse; + + traceEnt = &g_entities[ tr.entityNum ]; + + // send blood impact + if ( traceEnt->takedamage && traceEnt->client ) + { + tent = G_TempEntity( tr.endpos, EV_MISSILE_HIT ); + tent->s.otherEntityNum = traceEnt->s.number; + tent->s.eventParm = DirToByte( tr.plane.normal ); + tent->s.weapon = ent->s.weapon; + } + + if( !traceEnt->takedamage) + return qfalse; + + damage = (int)( (float)ent->client->pouncePayload / ( MAX_POUNCE_SPEED / 100.0f ) ); + + G_Damage( traceEnt, ent, ent, forward, tr.endpos, damage, DAMAGE_NO_KNOCKBACK, MOD_VENOM ); + + ent->client->allowedToPounce = qfalse; + + return qtrue; +} + //====================================================================== /* @@ -915,6 +1019,9 @@ void FireWeapon2( gentity_t *ent ) case WP_GRABANDCSAW: Weapon_Grab_Fire( ent ); break; + case WP_POUNCE: + //Weapon_Claw_Fire( ent ); + break; case WP_DBUILD: Weapon_Abuild_Fire( ent ); break; @@ -992,6 +1099,9 @@ void FireWeapon( gentity_t *ent ) case WP_GRABANDCSAW: Weapon_CSaw_Fire( ent ); break; + case WP_POUNCE: + Weapon_Claw_Fire( ent ); + break; case WP_DBUILD: Weapon_Abuild_Fire( ent ); break; |