summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cgame/cg_local.h7
-rw-r--r--src/cgame/cg_view.c35
-rw-r--r--src/cgame/cg_weapons.c25
-rw-r--r--src/game/bg_misc.c29
-rw-r--r--src/game/bg_pmove.c103
-rw-r--r--src/game/bg_public.h61
-rw-r--r--src/game/g_active.c30
-rw-r--r--src/game/g_client.c6
-rw-r--r--src/game/g_combat.c11
-rw-r--r--src/game/g_local.h4
-rw-r--r--src/game/g_main.c5
-rw-r--r--src/game/g_weapon.c110
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;