|
You can download complete source for the smoke grenade here:
SmokeGrenade.cpp. You might want to
have the source open in a window next to this page to refer to
as you read.
Difficulty rating: easy. This relies heavily on existing Halflife
grenade code and has almost nothing original.
This smoke grenade works like the other Halflife grenades and satchel
charges. It has two pieces: the weapon object that players can pick up
and hold, and the thrown grenade object. The first inherits from
CBasePlayerWeapon and appears in player inventory. The second inherits
from CBaseMonster and is an in-game entity independent of the player.
It tumbles until its timer runs out, then detonates.
Here's the first class:
class CSmokeGrenade : public CBasePlayerWeapon
{
public:
void Spawn( void );
void Precache( void );
int iItemSlot( void ) { return 5; }
int GetItemInfo(ItemInfo *p);
void PrimaryAttack( void );
BOOL Deploy( void );
BOOL CanHolster( void );
void Holster( void );
void WeaponIdle( void );
float m_flStartThrow;
float m_flReleaseThrow;
};
LINK_ENTITY_TO_CLASS( weapon_smokegrenade, CSmokeGrenade );
This class declaration looks just like all the other weapons you've
ever written, with the addition of two variables. We need to keep track
of when we started throwing the grenade, because that's when it's primed.
And then we keep track of the fact that we've released the throw, so we
can follow through on the throw animation and take out another grenade.
The LINK_ENTITY line allows you to add smoke grenades to your maps using
the name "weapon_smokegrenade".
Spawn()
Called when a grenade pickup appears in the world. Sets the model
and number to be given to the player who picks it up.
Precache()
Tells the server to precache the models and sounds used by the weapon.
iItemSlot()
Which HUD slot this weapon appears in.
GetItemInfo()
Fills out a struct with weapon info to send to the client. The client
uses the information to display your weapon in the HUD weapon selector.
PrimaryAttack()
Pulls the pin and goes into the windup to throw. Fastball or curve?
Deploy()
Takes out the grenade and announces its models to the world.
CanHolster()
You can't holster a primed grenade.
Holster()
Puts the grenades away and takes out another weapon. If the player
has no more grenades, removes the weapon from the list of available
weapons. This part might look odd, but it's because grenades don't
work like guns. Guns stick around but are just unselectable without
ammo. Grenades vanish from the player's weapon list entirely when
the player runs out of "ammo".
WeaponIdle()
The exciting stuff begins here, where the player actually throws the
grenade. Scan down to about line 180, a few lines into WeaponIdle().
Here, we set up the vectors for the throw by looking at where the player
is facing and how fast the player is moving. We set the detonation time
two seconds into the future. Then we actually throw on line 202:
CSmoker::ShootTimed( m_pPlayer->pev, vecSrc, vecThrow, time);
This spawns a CSmoker object and sends it on its way, leaving the player
free to take out another weapon or throw another grenade.
Here is the declaration of the class that actually spews the smoke. It
inherits from class CGrenade, which in turn inherits from class
CBaseMonster. You can find the original grenade monster declared in
weapons.h and implemented in ggrenade.cpp. Like other Halflife monsters,
it has think routines that are called repeatedly as time passes. This
is how we implement the timed explosion.
class CSmoker : public CGrenade
{
public:
void Spawn( void );
static CSmoker *ShootTimed( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity, float time );
void BounceTouch( CBaseEntity *pOther );
void TumbleThink( void );
void SmokeThink(void);
void SputterOut(void);
virtual void BounceSound( void );
virtual int BloodColor( void ) { return DONT_BLEED; }
virtual void Killed( entvars_t *pevAttacker, int iGib );
BOOL m_Detonated;
BOOL m_fRegisteredSound;
float m_SmokeTime;
};
LINK_ENTITY_TO_CLASS( smoking_grenade, CSmoker);
ShootTimed() creates a smoker and throws it out into the world. The
smoker calls TumbleThink() while it's waiting to blow. Then when its
timer expires, it switches to SmokeThink() and starts spewing. (It's fun
to hold this grenade for a second before throwing-- it'll detonate in
the air and smoke as it flies.) As a final touch, it emits a small smoke
cloud and leaves a dark stain behind in SputterOut().
The animation action is all in SmokeThink(). Take a look. First it checks
to see if we've finished smoking. If so, we stop making noise and sputter
out. Otherwise, we make a hissing sound and animate a big smoke sprite.
Try changing the size of the smoke cloud or changing the sprite used.
There are several sprites in the basic HalfLife pak file that work
pretty well.
At the top of the file are some #defines for parameters you might want
to tweak. Current C++ practice is to make these consts and put them in
your class definition, but I've left them as #defines.
| WEAPON_SMOKEGRENADE 19 |
Just make sure this doesn't collide with your mod's other weapons. |
| SMOKETIME 16 |
Time it spends smoking. |
| SMOKEG_FIRE_DELAY 2.0 |
Time from priming to detonation. |
| SMOKEG_SLOT 4 |
Slot 4 is where standard HL puts its grenades. |
| SMOKEG_POSITION 4 |
Make sure this doesn't collide with other weapons in the slot. |
| SMOKEG_WEIGHT 25 |
If your mod uses weights, set this. |
SMOKEG_MODEL_1STPERSON "models/v_grenade.mdl"
SMOKEG_MODEL_3RDPERSON "models/p_grenade.mdl"
SMOKEG_MODEL_WORLD "models/w_grenade.mdl" |
Your mod's modelers will make replacements for these,
which are the standard Halflife grenade models. |
SMOKEG_SOUND_VOLUME 0.25
SMOKEG_BODYHIT_VOLUME 128
SMOKEG_WALLHIT_VOLUME 512 |
Adjust the volume parameters to suit your custom sound effects. |
| SMOKEG_DEFAULT_GIVE 5 |
How many are in a grenade pickup. |
| SMOKEG_CLIPSIZE 1 |
Leave at 1. |
| SMOKEG_MAX_AMMO 10 |
The maximum number a player can carry. |
In your mod's sprites directory, create a file named
weapon_smokegrenade.txt. Paste into it the generic HalfLife
grenade info:
6
weapon 320 320hud1 160 0 80 20
weapon_s 320 320hud1 160 20 80 20
ammo 320 320hud2 36 34 18 18
weapon 640 640hud3 0 0 170 45
weapon_s 640 640hud6 0 0 170 45
ammo 640 640hud7 48 96 24 24
This smoke grenade uses the existing HL grenade model and a smoke
sprite already in the game. You'll want to create your own models
and sprite. And you might want to write a volume effect for the smoke
instead of using a 2D sprite. Other variations include doing a small
amount of damage every second to somebody standing in the smoke cloud.
Or making them cough and screw up their aim for a few seconds after
smoke exposure.
|