summaryrefslogtreecommitdiff
path: root/src/game
diff options
context:
space:
mode:
authorPaweł Redman <pawel.redman@gmail.com>2015-06-29 00:52:09 +0200
committerPaweł Redman <pawel.redman@gmail.com>2015-06-29 16:40:28 +0200
commit0918eb3bcdefd0d6ee4bd573b761454c99f032f6 (patch)
treedd1bd0bfe5348ad3b4860f11b7d3dcbb6db9ca3c /src/game
parent93d2e4414ee25e417ee0d2ca0248448002ea4d5b (diff)
Initial implementation of new grenades.
Diffstat (limited to 'src/game')
-rw-r--r--src/game/bg_misc.c42
-rw-r--r--src/game/bg_pmove.c135
-rw-r--r--src/game/bg_public.h12
-rw-r--r--src/game/g_active.c9
-rw-r--r--src/game/g_client.c2
-rw-r--r--src/game/g_cmds.c81
-rw-r--r--src/game/g_combat.c15
-rw-r--r--src/game/g_local.h3
-rw-r--r--src/game/g_missile.c4
-rw-r--r--src/game/g_team.c2
-rw-r--r--src/game/g_weapon.c26
-rw-r--r--src/game/tremulous.h8
12 files changed, 269 insertions, 70 deletions
diff --git a/src/game/bg_misc.c b/src/game/bg_misc.c
index ff158bb..b5bd305 100644
--- a/src/game/bg_misc.c
+++ b/src/game/bg_misc.c
@@ -3190,8 +3190,7 @@ static const weaponAttributes_t bg_weapons[ ] =
qfalse, //qboolean longRanged;
TEAM_ALIENS //team_t team;
},
-
- {
+ {
WP_BLASTER, //int weaponNum;
0, //int price;
STAGE_GE_1, //int stages
@@ -3507,11 +3506,11 @@ static const weaponAttributes_t bg_weapons[ ] =
},
{
WP_GRENADE, //int weaponNum;
- GRENADE_PRICE, //int price;
- STAGE_GE_3, //int stages
- SLOT_NONE, //int slots;
+ 0, //int price;
+ STAGE_GE_1, //int stages
+ 0, //int slots;
"grenade", //char *weaponName;
- "Grenade", //char *humanName;
+ "[yenade]Grenades", //char *humanName;
"",
1, //int maxAmmo;
0, //int maxClips;
@@ -3838,7 +3837,7 @@ static const upgradeAttributes_t bg_upgrades[ ] =
STAGE_GE_4, //int stages
SLOT_NONE, //int slots;
"gren", //char *upgradeName;
- "[yenade]Explosive Grenade", //char *humanName;
+ "[yenade]Grenade", //char *humanName;
"A small incendinary device ideal for damaging tightly packed "
"alien structures. Has a five second timer.",
0,
@@ -4101,7 +4100,12 @@ char *eventnames[ ] =
"EV_MGTURRET_SPINUP", // trigger a sound
"EV_RPTUSE_SOUND", // trigger a sound
"EV_LEV2_ZAP",
- "EV_ACIDBOMB_BOUNCE"
+ "EV_ACIDBOMB_BOUNCE",
+ "EV_ROCKETL_PRIME",
+ "EV_WARP_ENTER",
+ "EV_WARP_EXIT",
+ "EV_GRENADE_PRIME",
+ "EV_GRENADE_TICK"
};
/*
@@ -4382,8 +4386,9 @@ Does the player hold a weapon?
*/
qboolean BG_InventoryContainsWeapon( int weapon, int stats[ ] )
{
- // humans always have a blaster
- if( stats[ STAT_TEAM ] == TEAM_HUMANS && weapon == WP_BLASTER )
+ // humans always have a blaster and a grenade thrower
+ if( stats[ STAT_TEAM ] == TEAM_HUMANS &&
+ ( weapon == WP_BLASTER || weapon == WP_GRENADE ) )
return qtrue;
return ( stats[ STAT_WEAPON ] == weapon );
@@ -4400,8 +4405,12 @@ int BG_SlotsForInventory( int stats[ ] )
int i, slot, slots;
slots = BG_Weapon( stats[ STAT_WEAPON ] )->slots;
+
if( stats[ STAT_TEAM ] == TEAM_HUMANS )
- slots |= BG_Weapon( WP_BLASTER )->slots;
+ {
+ slots |= BG_Weapon( WP_BLASTER )->slots |
+ BG_Weapon( WP_GRENADE )->slots;
+ }
for( i = UP_NONE; i < UP_NUM_UPGRADES; i++ )
{
@@ -4653,6 +4662,12 @@ qboolean BG_PlayerCanChangeWeapon( playerState_t *ps )
ps->stats[ STAT_MISC ] > LCANNON_CHARGE_TIME_MIN )
return qfalse;
+ if( ps->weapon == WP_GRENADE &&
+ ps->stats[ STAT_MISC ] > 0 )
+ {
+ return qfalse;
+ }
+
return ps->weaponTime <= 0 || ps->weaponstate != WEAPON_FIRING;
}
@@ -5101,6 +5116,11 @@ weapon_t BG_PrimaryWeapon( int stats[ ] )
if( BG_InventoryContainsWeapon( WP_BLASTER, stats ) )
return WP_BLASTER;
+ if( BG_InventoryContainsWeapon( WP_GRENADE, stats ) )
+ {
+ return WP_GRENADE;
+ }
+
return WP_NONE;
}
diff --git a/src/game/bg_pmove.c b/src/game/bg_pmove.c
index 4fd73f1..f8f8a69 100644
--- a/src/game/bg_pmove.c
+++ b/src/game/bg_pmove.c
@@ -2861,9 +2861,10 @@ static void PM_BeginWeaponChange( int weapon )
if( pm->ps->weaponstate == WEAPON_DROPPING )
return;
- // prevent storing a primed rocket launcher
- if( pm->ps->weapon == WP_ROCKET_LAUNCHER &&
- pm->ps->stats[ STAT_MISC ] > 0 )
+ // prevent storing a primed rocket launcher or grenade
+ if( ( pm->ps->weapon == WP_ROCKET_LAUNCHER ||
+ pm->ps->weapon == WP_GRENADE ) &&
+ pm->ps->stats[ STAT_MISC ] > 0 )
return;
// cancel a reload
@@ -2932,9 +2933,17 @@ static void PM_TorsoAnimation( void )
if( !( pm->ps->persistant[ PERS_STATE ] & PS_NONSEGMODEL ) )
{
if( pm->ps->weapon == WP_BLASTER )
+ {
PM_ContinueTorsoAnim( TORSO_STAND2 );
+ }
+ else if( pm->ps->weapon == WP_GRENADE )
+ {
+ PM_ContinueTorsoAnim( TORSO_STAND3 );
+ }
else
+ {
PM_ContinueTorsoAnim( TORSO_STAND );
+ }
}
PM_ContinueWeaponAnim( WANIM_IDLE );
@@ -3104,6 +3113,32 @@ static void PM_Weapon( void )
}
}
+ if( pm->ps->weapon == WP_GRENADE )
+ {
+ if( !pm->ps->weaponTime &&
+ pm->ps->stats[ STAT_GRENADES ] > 0 &&
+ ( ( pm->cmd.buttons & BUTTON_ATTACK ) ||
+ pm->ps->stats[ STAT_MISC ] > 0 ) )
+ {
+ int old_time;
+
+ old_time = pm->ps->stats[ STAT_MISC ];
+
+ if( old_time == 0 )
+ {
+ PM_AddEvent( EV_GRENADE_PRIME );
+ }
+
+ pm->ps->stats[ STAT_MISC ] += pml.msec;
+
+ if( pm->ps->stats[ STAT_MISC ] < GRENADE_FUSE_TIME &&
+ old_time / 1000 < pm->ps->stats[ STAT_MISC ] / 1000 )
+ {
+ PM_AddEvent( EV_GRENADE_TICK );
+ }
+ }
+ }
+
// don't allow attack until all buttons are up
if( pm->ps->pm_flags & PMF_RESPAWNED )
return;
@@ -3200,7 +3235,9 @@ static void PM_Weapon( void )
else minAmmo = 1;
// check for out of ammo
- if( pm->ps->ammo < minAmmo && !pm->ps->clips && !BG_Weapon( pm->ps->weapon )->infiniteAmmo )
+ if( ( pm->ps->weapon != WP_GRENADE && pm->ps->ammo < minAmmo &&
+ !pm->ps->clips && !BG_Weapon( pm->ps->weapon )->infiniteAmmo ) ||
+ ( pm->ps->weapon == WP_GRENADE && pm->ps->stats[ STAT_GRENADES ] <= 0 ) )
{
if( attack1 || ( BG_Weapon( pm->ps->weapon )->hasAltMode && attack2 ) || ( BG_Weapon( pm->ps->weapon )->hasThirdMode && attack3 ) )
{
@@ -3345,6 +3382,36 @@ static void PM_Weapon( void )
return;
}
+ case WP_GRENADE:
+ if( attack1 || pm->ps->stats[ STAT_MISC ] == 0 )
+ {
+ pm->ps->weaponTime = 0;
+
+ if( pm->ps->stats[ STAT_MISC ] < GRENADE_FUSE_TIME )
+ {
+ pm->ps->weaponstate = WEAPON_READY;
+ return;
+ }
+ }
+
+ if( pm->ps->stats[ STAT_MISC ] > GRENADE_TIME_MIN )
+ {
+ attack1 = qtrue;
+ }
+ else if( pm->ps->stats[ STAT_MISC ] > 0 )
+ {
+ pm->ps->weaponTime = 0;
+ pm->ps->weaponstate = WEAPON_READY;
+ return;
+ }
+ else
+ {
+ pm->ps->weaponTime = 0;
+ pm->ps->weaponstate = WEAPON_READY;
+ return;
+ }
+ break;
+
default:
if( !attack1 && !attack2 && !attack3 )
{
@@ -3462,7 +3529,11 @@ static void PM_Weapon( void )
//FIXME: this should be an option in the client weapon.cfg
switch( pm->ps->weapon )
{
-
+ case WP_GRENADE:
+ PM_StartTorsoAnim( TORSO_ATTACK3 );
+ PM_StartWeaponAnim( WANIM_ATTACK1 );
+ break;
+
case WP_BLASTER:
PM_StartTorsoAnim( TORSO_ATTACK2 );
PM_StartWeaponAnim( WANIM_ATTACK1 );
@@ -3544,27 +3615,39 @@ static void PM_Weapon( void )
( pm->ps->weapon == WP_ALEVEL4 && attack3 )||
( pm->ps->weapon == WP_ALEVEL5 && attack3 ))
{
- switch( pm->ps->weapon ) {
- case WP_MASS_DRIVER:
- if( attack3 ) {
- pm->ps->ammo -= 7;
- if( pm->ps->ammo < 7 ) pm->ps->ammo += 1;
- } else pm->ps->ammo--;
- break;
- case WP_LUCIFER_CANNON:
- if( attack1 && !attack2 ) {
- pm->ps->ammo -= ( pm->ps->stats[ STAT_MISC ] * LCANNON_CHARGE_AMMO +
- LCANNON_CHARGE_TIME_MAX - 1 ) / LCANNON_CHARGE_TIME_MAX;
- } else pm->ps->ammo--;
- break;
- case WP_LAS_GUN:
- if( attack2 ) {
- pm->ps->ammo -= 25;
- } else pm->ps->ammo--;
- break;
- default:
- pm->ps->ammo--;
- break;
+ switch( pm->ps->weapon )
+ {
+ case WP_LUCIFER_CANNON:
+ if( attack1 && !attack2 )
+ {
+ pm->ps->ammo -=
+ ( pm->ps->stats[ STAT_MISC ] * LCANNON_CHARGE_AMMO +
+ LCANNON_CHARGE_TIME_MAX - 1 ) / LCANNON_CHARGE_TIME_MAX;
+ }
+ else
+ {
+ pm->ps->ammo--;
+ }
+ break;
+
+ case WP_LAS_GUN:
+ if( attack2 )
+ {
+ pm->ps->ammo -= 25;
+ }
+ else
+ {
+ pm->ps->ammo--;
+ }
+ break;
+
+ case WP_GRENADE:
+ pm->ps->stats[ STAT_GRENADES ]--;
+ break;
+
+ default:
+ pm->ps->ammo--;
+ break;
}
// Stay on the safe side
diff --git a/src/game/bg_public.h b/src/game/bg_public.h
index b0c1213..f377739 100644
--- a/src/game/bg_public.h
+++ b/src/game/bg_public.h
@@ -243,8 +243,10 @@ typedef enum
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 3 more
+ STAT_VIEWLOCK, // direction to lock the view in
+ STAT_GRENADES,
+ STAT_BUILD_TIMER
+ // netcode has space for 1 more
} statIndex_t;
#define SCA_WALLCLIMBER 0x00000001
@@ -569,7 +571,9 @@ typedef enum
EV_ACIDBOMB_BOUNCE,
EV_ROCKETL_PRIME,
EV_WARP_ENTER,
- EV_WARP_EXIT
+ EV_WARP_EXIT,
+ EV_GRENADE_PRIME,
+ EV_GRENADE_TICK
} entity_event_t;
typedef enum
@@ -659,10 +663,12 @@ typedef enum
TORSO_GESTURE,
TORSO_ATTACK,
TORSO_ATTACK2,
+ TORSO_ATTACK3,
TORSO_DROP,
TORSO_RAISE,
TORSO_STAND,
TORSO_STAND2,
+ TORSO_STAND3,
LEGS_WALKCR,
LEGS_WALK,
LEGS_RUN,
diff --git a/src/game/g_active.c b/src/game/g_active.c
index b3df37b..c1a473d 100644
--- a/src/game/g_active.c
+++ b/src/game/g_active.c
@@ -579,6 +579,7 @@ void SpectatorThink( gentity_t *ent, usercmd_t *ucmd )
client->ps.speed = client->pers.flySpeed;
client->ps.stats[ STAT_STAMINA ] = 0;
client->ps.stats[ STAT_MISC ] = 0;
+ client->ps.stats[ STAT_BUILD_TIMER ] = 0;
client->ps.stats[ STAT_BUILDABLE ] = BA_NONE;
client->ps.stats[ STAT_CLASS ] = PCL_NONE;
client->ps.weapon = WP_NONE;
@@ -778,11 +779,11 @@ void ClientTimerActions( gentity_t *ent, int msec )
BG_InventoryContainsWeapon( WP_HBUILD, client->ps.stats ) )
{
// Update build timer
- if( client->ps.stats[ STAT_MISC ] > 0 )
- client->ps.stats[ STAT_MISC ] -= 100;
+ if( client->ps.stats[ STAT_BUILD_TIMER ] > 0 )
+ client->ps.stats[ STAT_BUILD_TIMER ] -= 100;
- if( client->ps.stats[ STAT_MISC ] < 0 )
- client->ps.stats[ STAT_MISC ] = 0;
+ if( client->ps.stats[ STAT_BUILD_TIMER ] < 0 )
+ client->ps.stats[ STAT_BUILD_TIMER ] = 0;
}
switch( weapon )
diff --git a/src/game/g_client.c b/src/game/g_client.c
index ccf65e8..4fd2bb8 100644
--- a/src/game/g_client.c
+++ b/src/game/g_client.c
@@ -1554,7 +1554,7 @@ void ClientSpawn( gentity_t *ent, gentity_t *spawn, vec3_t origin, vec3_t angles
{
spawn_angles[ YAW ] += 180.0f;
AngleNormalize360( spawn_angles[ YAW ] );
-
+
//
G_Sound( ent, CHAN_VOICE, G_SoundIndex( "sound/buildables/human/spawn1.wav" ) );
}
diff --git a/src/game/g_cmds.c b/src/game/g_cmds.c
index 2b7b105..de0090b 100644
--- a/src/game/g_cmds.c
+++ b/src/game/g_cmds.c
@@ -449,7 +449,7 @@ void Cmd_Give_f( gentity_t *ent )
{
ADMP( "usage: give [what]\n" );
ADMP( "usage: valid choices are: all, health, funds [amount], stamina, "
- "ammo\n" );
+ "ammo, grenades\n" );
return;
}
@@ -488,18 +488,32 @@ void Cmd_Give_f( gentity_t *ent )
if( give_all || Q_stricmp( name, "stamina" ) == 0 )
ent->client->ps.stats[ STAT_STAMINA ] = STAMINA_MAX;
+ if( give_all || Q_stricmp( name, "grenades" ) == 0 )
+ {
+ ent->client->ps.stats[ STAT_GRENADES ] = GRENADE_MAX;
+ }
+
if( give_all || Q_stricmp( name, "ammo" ) == 0 )
{
gclient_t *client = ent->client;
+ int weapon;
if( client->ps.weapon != WP_ALEVEL3_UPG &&
BG_Weapon( client->ps.weapon )->infiniteAmmo )
return;
- client->ps.ammo = BG_Weapon( client->ps.weapon )->maxAmmo;
- client->ps.clips = BG_Weapon( client->ps.weapon )->maxClips;
+ weapon = BG_PrimaryWeapon( client->ps.stats );
+
+ if( weapon == WP_BLASTER ||
+ weapon == WP_GRENADE )
+ {
+ return;
+ }
+
+ client->ps.ammo = BG_Weapon( weapon )->maxAmmo;
+ client->ps.clips = BG_Weapon( weapon )->maxClips;
- if( BG_Weapon( client->ps.weapon )->usesEnergy &&
+ if( BG_Weapon( weapon )->usesEnergy &&
BG_InventoryContainsUpgrade( UP_BATTPACK, client->ps.stats ) )
client->ps.ammo = (int)( (float)client->ps.ammo * BATTPACK_MODIFIER );
}
@@ -1777,7 +1791,7 @@ void Cmd_Class_f( gentity_t *ent )
if( ent->client->sess.spectatorState == SPECTATOR_NOT &&
( currentClass == PCL_ALIEN_BUILDER0 ||
currentClass == PCL_ALIEN_BUILDER0_UPG ) &&
- ent->client->ps.stats[ STAT_MISC ] > 0 )
+ ent->client->ps.stats[ STAT_BUILD_TIMER ] > 0 )
{
G_TriggerMenu( ent->client->ps.clientNum, MN_A_EVOLVEBUILDTIMER );
return;
@@ -1925,7 +1939,7 @@ void Cmd_Destroy_f( gentity_t *ent )
( ent->client->pers.teamSelection == TEAM_HUMANS &&
!G_FindPower( traceEnt, qtrue ) ) )
{
- if( ent->client->ps.stats[ STAT_MISC ] > 0 )
+ if( ent->client->ps.stats[ STAT_BUILD_TIMER ] > 0 )
{
G_AddEvent( ent, EV_BUILD_DELAY, ent->client->ps.clientNum );
return;
@@ -1950,7 +1964,7 @@ void Cmd_Destroy_f( gentity_t *ent )
{
if( !g_cheats.integer ) // add a bit to the build timer
{
- ent->client->ps.stats[ STAT_MISC ] +=
+ ent->client->ps.stats[ STAT_BUILD_TIMER ] +=
BG_Buildable( traceEnt->s.modelindex )->buildTime / 4;
}
G_Damage( traceEnt, ent, ent, forward, tr.endpos,
@@ -1978,7 +1992,8 @@ void Cmd_ActivateItem_f( gentity_t *ent )
// "weapon" aliased to whatever weapon you have
if( !Q_stricmp( "weapon", s ) )
{
- if( ent->client->ps.weapon == WP_BLASTER &&
+ if( ( ent->client->ps.weapon == WP_BLASTER ||
+ ent->client->ps.weapon == WP_GRENADE ) &&
BG_PlayerCanChangeWeapon( &ent->client->ps ) )
G_ForceWeaponChange( ent, WP_NONE );
return;
@@ -1987,6 +2002,13 @@ void Cmd_ActivateItem_f( gentity_t *ent )
upgrade = BG_UpgradeByName( s )->number;
weapon = BG_WeaponByName( s )->number;
+ // for backward compatibility
+ if( upgrade == UP_GRENADE )
+ {
+ upgrade = UP_NONE;
+ weapon = WP_GRENADE;
+ }
+
if( upgrade != UP_NONE && BG_InventoryContainsUpgrade( upgrade, ent->client->ps.stats ) )
BG_ActivateUpgrade( upgrade, ent->client->ps.stats );
else if( weapon != WP_NONE &&
@@ -2045,7 +2067,8 @@ void Cmd_ToggleItem_f( gentity_t *ent )
//special case to allow switching between
//the blaster and the primary weapon
- if( ent->client->ps.weapon != WP_BLASTER )
+ if( ent->client->ps.weapon != WP_BLASTER &&
+ ent->client->ps.weapon != WP_GRENADE )
weapon = WP_BLASTER;
else
weapon = WP_NONE;
@@ -2211,6 +2234,12 @@ void Cmd_Buy_f( gentity_t *ent )
return;
}
+ if( upgrade == UP_GRENADE && ent->client->ps.stats[ STAT_GRENADES ] >= GRENADE_MAX )
+ {
+ trap_SendServerCommand( ent-g_entities, "print \"You can't carry any more grenades\n\"" );
+ return;
+ }
+
if( upgrade == UP_AMMO )
G_GiveClientMaxAmmo( ent, energyOnly );
else
@@ -2230,8 +2259,16 @@ void Cmd_Buy_f( gentity_t *ent )
ent->client->ps.eFlags ^= EF_TELEPORT_BIT;
}
- //add to inventory
- BG_AddUpgradeToInventory( upgrade, ent->client->ps.stats );
+ //UP_GRENADE isn't actually an upgrade, it's ammo for WP_GRENADE
+ if( upgrade == UP_GRENADE )
+ {
+ ent->client->ps.stats[ STAT_GRENADES ]++;
+ }
+ else
+ {
+ //add to inventory
+ BG_AddUpgradeToInventory( upgrade, ent->client->ps.stats );
+ }
}
if( upgrade == UP_BATTPACK )
@@ -2294,7 +2331,7 @@ void Cmd_Sell_f( gentity_t *ent )
if( BG_InventoryContainsWeapon( weapon, ent->client->ps.stats ) )
{
//guard against selling the HBUILD weapons exploit
- if( weapon == WP_HBUILD && ent->client->ps.stats[ STAT_MISC ] > 0 )
+ if( weapon == WP_HBUILD && ent->client->ps.stats[ STAT_BUILD_TIMER ] > 0 )
{
G_TriggerMenu( ent->client->ps.clientNum, MN_H_ARMOURYBUILDTIMER );
return;
@@ -2320,8 +2357,18 @@ void Cmd_Sell_f( gentity_t *ent )
trap_SendServerCommand( ent-g_entities, "print \"You can't sell this item\n\"" );
return;
}
+
+ //UP_GRENADE is not an actual upgrade, it's ammo for WP_GRENADE
+ if( upgrade == UP_GRENADE )
+ {
+ if( ent->client->ps.stats[ STAT_GRENADES ] > 0 )
+ {
+ ent->client->ps.stats[ STAT_GRENADES ]--;
+ G_AddCreditToClient( ent->client, (short)BG_Upgrade( upgrade )->price, qfalse );
+ }
+ }
//remove upgrade if carried
- if( BG_InventoryContainsUpgrade( upgrade, ent->client->ps.stats ) )
+ else if( BG_InventoryContainsUpgrade( upgrade, ent->client->ps.stats ) )
{
// shouldn't really need to test for this, but just to be safe
if( upgrade == UP_BATTLESUIT )
@@ -2413,6 +2460,14 @@ void Cmd_Sell_f( gentity_t *ent )
G_AddCreditToClient( ent->client, (short)BG_Upgrade( i )->price, qfalse );
}
}
+
+ if( ent->client->ps.stats[ STAT_GRENADES ] > 0 )
+ {
+ G_AddCreditToClient( ent->client,
+ ent->client->ps.stats[ STAT_GRENADES ] *
+ (short)BG_Upgrade( UP_GRENADE )->price, qfalse );
+ ent->client->ps.stats[ STAT_GRENADES ] = 0;
+ }
}
else
G_TriggerMenu( ent->client->ps.clientNum, MN_H_UNKNOWNITEM );
diff --git a/src/game/g_combat.c b/src/game/g_combat.c
index bfe0de9..397bde0 100644
--- a/src/game/g_combat.c
+++ b/src/game/g_combat.c
@@ -432,6 +432,21 @@ void player_die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int
if( level.intermissiontime )
return;
+ if( self->client->ps.weapon == WP_GRENADE &&
+ self->client->ps.stats[ STAT_MISC ] > 0 )
+ {
+ int fuse_left;
+
+ fuse_left = GRENADE_FUSE_TIME - self->client->ps.stats[ STAT_MISC ];
+
+ if( fuse_left < 0 )
+ {
+ fuse_left = 0;
+ }
+
+ launch_grenade( self, self->s.origin, vec3_origin, fuse_left );
+ }
+
self->client->ps.pm_type = PM_DEAD;
self->suicideTime = 0;
diff --git a/src/game/g_local.h b/src/game/g_local.h
index c1cde73..c968642 100644
--- a/src/game/g_local.h
+++ b/src/game/g_local.h
@@ -1011,8 +1011,7 @@ gentity_t *fire_bounceBall( gentity_t *self, vec3_t start, vec3_t dir );
gentity_t *fire_bounceBall2( gentity_t *self, vec3_t start, vec3_t dir, int weapon, int dmg, int mod, int speed, int radius );
gentity_t *fire_bounceBall3( gentity_t *self, vec3_t start, vec3_t dir, int weapon, int dmg, int mod, int speed, int radius );
gentity_t *fire_hive( gentity_t *self, vec3_t start, vec3_t dir );
-gentity_t *launch_grenade( gentity_t *self, vec3_t start, vec3_t dir );
-gentity_t *launch_grenade_flames( gentity_t *self, vec3_t start, vec3_t dir );
+gentity_t *launch_grenade( gentity_t *self, vec3_t start, vec3_t dir, int fuse_time );
gentity_t *launch_shield( gentity_t *self, vec3_t start, vec3_t dir );
gentity_t *launch_saw( gentity_t *self, vec3_t start, vec3_t dir );
gentity_t *fire_md2( gentity_t *self, vec3_t start, vec3_t dir );
diff --git a/src/game/g_missile.c b/src/game/g_missile.c
index 5dd9725..8d7a93c 100644
--- a/src/game/g_missile.c
+++ b/src/game/g_missile.c
@@ -695,7 +695,7 @@ gentity_t *fire_rocket( gentity_t *self, vec3_t start, vec3_t dir )
launch_grenade
=================
*/
-gentity_t *launch_grenade( gentity_t *self, vec3_t start, vec3_t dir )
+gentity_t *launch_grenade( gentity_t *self, vec3_t start, vec3_t dir, int fuse_time )
{
gentity_t *bolt;
@@ -703,7 +703,7 @@ gentity_t *launch_grenade( gentity_t *self, vec3_t start, vec3_t dir )
bolt = G_Spawn( );
bolt->classname = "grenade";
bolt->pointAgainstWorld = qfalse;
- bolt->nextthink = level.time + 5000;
+ bolt->nextthink = level.time + fuse_time;
bolt->think = G_ExplodeMissile;
bolt->s.eType = ET_MISSILE;
bolt->r.svFlags = SVF_USE_CURRENT_ORIGIN;
diff --git a/src/game/g_team.c b/src/game/g_team.c
index f92936f..ad0873c 100644
--- a/src/game/g_team.c
+++ b/src/game/g_team.c
@@ -302,7 +302,7 @@ void G_BalanceTeams( void )
// Refund all weapons and equipment before team change
for( i = WP_NONE+1; i < WP_NUM_WEAPONS; ++i )
{
- if ( i == WP_HBUILD && ent->client->ps.stats[ STAT_MISC ] > 0 )
+ if ( i == WP_HBUILD && ent->client->ps.stats[ STAT_BUILD_TIMER ] > 0 )
continue;
if (BG_InventoryContainsWeapon( i, ent->client->ps.stats ) && BG_Weapon( i )->purchasable )
{
diff --git a/src/game/g_weapon.c b/src/game/g_weapon.c
index 0925973..265358a 100644
--- a/src/game/g_weapon.c
+++ b/src/game/g_weapon.c
@@ -80,7 +80,12 @@ void G_GiveClientMaxAmmo( gentity_t *ent, qboolean buyingEnergyAmmo )
for( i = WP_NONE + 1; i < WP_NUM_WEAPONS; i++ )
{
qboolean energyWeapon;
-
+
+ if( i == WP_GRENADE )
+ {
+ continue;
+ }
+
energyWeapon = BG_Weapon( i )->usesEnergy;
if( !BG_InventoryContainsWeapon( i, ent->client->ps.stats ) ||
BG_Weapon( i )->infiniteAmmo ||
@@ -626,9 +631,20 @@ GRENADE
void throwGrenade( gentity_t *ent )
{
+ int fuse_left;
+
G_CombatStats_Fire( ent, CSW_GRENADE, GRENADE_DAMAGE );
- launch_grenade( ent, muzzle, forward );
+ fuse_left = GRENADE_FUSE_TIME - ent->client->ps.stats[ STAT_MISC ];
+
+ if( fuse_left < 0 )
+ {
+ fuse_left = 0;
+ }
+
+ launch_grenade( ent, muzzle, forward, fuse_left );
+
+ ent->client->ps.stats[ STAT_MISC ] = 0;
}
/*
@@ -937,7 +953,7 @@ void CheckCkitRepair( gentity_t *ent )
int bHealth;
if( ent->client->ps.weaponTime > 0 ||
- ent->client->ps.stats[ STAT_MISC ] > 0 )
+ ent->client->ps.stats[ STAT_BUILD_TIMER ] > 0 )
return;
BG_GetClientViewOrigin( &ent->client->ps, viewOrigin );
@@ -997,7 +1013,7 @@ void buildFire( gentity_t *ent, dynMenu_t menu )
if( buildable > BA_NONE )
{
- if( ent->client->ps.stats[ STAT_MISC ] > 0 )
+ if( ent->client->ps.stats[ STAT_BUILD_TIMER ] > 0 )
{
G_AddEvent( ent, EV_BUILD_DELAY, ent->client->ps.clientNum );
return;
@@ -1007,7 +1023,7 @@ void buildFire( gentity_t *ent, dynMenu_t menu )
{
if( !g_cheats.integer )
{
- ent->client->ps.stats[ STAT_MISC ] +=
+ ent->client->ps.stats[ STAT_BUILD_TIMER ] +=
BG_Buildable( buildable )->buildTime;
}
diff --git a/src/game/tremulous.h b/src/game/tremulous.h
index 3262b55..9a7a8c8 100644
--- a/src/game/tremulous.h
+++ b/src/game/tremulous.h
@@ -357,11 +357,15 @@ TREMULOUS EDGE MOD SRC FILE
#define PAINSAW_BLADERANGE 100.0f
#define GRENADE_PRICE 200
-#define GRENADE_REPEAT 0
+#define GRENADE_MAX 3
+#define GRENADE_REPEAT 500
#define GRENADE_K_SCALE 1.0f
-#define GRENADE_DAMAGE HDM(340)
+#define GRENADE_DAMAGE HDM(200)
#define GRENADE_RANGE 192.0f
#define GRENADE_SPEED 700.0f
+#define GRENADE_TIME_MIN 500
+#define GRENADE_TIME_WARN 1500
+#define GRENADE_FUSE_TIME 3000
#define SHOTGUN_PRICE 150
#define SHOTGUN_SHELLS 8