|
|
|
New Code Old Code This is my first tutorial, so I would like it if you contact me, telling me what I did completely wrong and what is realy cool! This tutorial is about how to create a Shotgun with two types of ammo (slugs and buckshot). I included the slugs in a way, that you can still shoot with both barrels. I wrote this tutorial especially for people who want to have weapons with two types of ammo , but want to use a clip in both cases.(Another idea might be a MP5 with normal and HE ammo) Read this(the comments explain the important changes) and then replace shotgun.cpp with it: // BEGIN SHOTGUN.CPP /*******3Mode shotgun******* * Copyright 1999 Dr.Death * ***************************/ // essential weapon includes #include "extdll.h" #include "util.h" #include "cbase.h" #include "monsters.h" #include "weapons.h" #include "nodes.h" #include "player.h" #include "gamerules.h" // special deathmatch shotgun spreads #define VECTOR_CONE_DM_SHOTGUN Vector( 0.08716, 0.04362, 0.00 )// 10 degrees by 5 degrees #define VECTOR_CONE_DM_DOUBLESHOTGUN Vector( 0.17365, 0.04362, 0.00 ) // 20 degrees by 5 degrees enum shotgun_e { SHOTGUN_IDLE = 0, SHOTGUN_FIRE, SHOTGUN_FIRE2, SHOTGUN_RELOAD, SHOTGUN_PUMP, SHOTGUN_START_RELOAD, SHOTGUN_DRAW, SHOTGUN_HOLSTER, SHOTGUN_IDLE4, SHOTGUN_IDLE_DEEP }; class CShotgun : public CBasePlayerWeapon { public: int Save( CSave &save ); int Restore( CRestore &restore ); static TYPEDESCRIPTION m_SaveData[]; void Spawn( void ); void Precache( void ); int iItemSlot( ) { return 3; } int GetItemInfo(ItemInfo *p); int AddToPlayer( CBasePlayer *pPlayer ); void PrimaryAttack( void ); void SecondaryAttack( void ); BOOL Deploy( ); void Reload( void ); void WeaponIdle( void ); int m_fInReload; float m_flNextReload; int m_iShell; float m_flPumpTime; // New additions to CShotgun void SingleBarrelShot(); // use this if in slug or single barrel shot mode void DoubleBarrelShot(); // use this if in double barrel int m_iShotgunMode; // we have to use an int not a bool because we have 3 modes int m_iOldClip; // I don't have to use a member but i did }; LINK_ENTITY_TO_CLASS( weapon_shotgun, CShotgun ); TYPEDESCRIPTION CShotgun::m_SaveData[] = { DEFINE_FIELD( CShotgun, m_flNextReload, FIELD_TIME ), DEFINE_FIELD( CShotgun, m_fInReload, FIELD_INTEGER ), DEFINE_FIELD( CShotgun, m_flNextReload, FIELD_TIME ), // DEFINE_FIELD( CShotgun, m_iShell, FIELD_INTEGER ), DEFINE_FIELD( CShotgun, m_flPumpTime, FIELD_TIME ), }; IMPLEMENT_SAVERESTORE( CShotgun, CBasePlayerWeapon ); void CShotgun::Spawn( ) { Precache( ); m_iId = WEAPON_SHOTGUN; SET_MODEL(ENT(pev), "models/w_shotgun.mdl"); m_iDefaultAmmo = SHOTGUN_DEFAULT_GIVE; FallInit();// get ready to fall } void CShotgun::Precache( void ) { PRECACHE_MODEL("models/v_shotgun.mdl"); PRECACHE_MODEL("models/w_shotgun.mdl"); PRECACHE_MODEL("models/p_shotgun.mdl"); m_iShell = PRECACHE_MODEL ("models/shotgunshell.mdl");// shotgun shell PRECACHE_SOUND("items/9mmclip1.wav"); PRECACHE_SOUND ("weapons/dbarrel1.wav");//shotgun PRECACHE_SOUND ("weapons/sbarrel1.wav");//shotgun PRECACHE_SOUND ("weapons/reload1.wav"); // shotgun reload PRECACHE_SOUND ("weapons/reload3.wav"); // shotgun reload PRECACHE_SOUND ("weapons/357_cock1.wav"); // gun empty sound PRECACHE_SOUND ("weapons/scock1.wav"); // cock gun } int CShotgun::AddToPlayer( CBasePlayer *pPlayer ) { if ( CBasePlayerWeapon::AddToPlayer( pPlayer ) ) { MESSAGE_BEGIN( MSG_ONE, gmsgWeapPickup, NULL, pPlayer->pev ); WRITE_BYTE( m_iId ); MESSAGE_END(); m_iShotgunMode = 0; // we don't want a shotgun without declared mode return TRUE; } return FALSE; } int CShotgun::GetItemInfo(ItemInfo *p) { p->pszName = STRING(pev->classname); p->pszAmmo1 = "buckshot"; p->iMaxAmmo1 = BUCKSHOT_MAX_CARRY; // you might want to replace this by 62 p->pszAmmo2 = "slugs"; // new slug ammo type p->iMaxAmmo2 = BUCKSHOT_MAX_CARRY; // you might want to replace this by 62 p->iMaxClip = SHOTGUN_MAX_CLIP; p->iSlot = 2; p->iPosition = 1; p->iFlags = 0; p->iId = m_iId = WEAPON_SHOTGUN; p->iWeight = SHOTGUN_WEIGHT; return 1; } BOOL CShotgun::Deploy( ) { return DefaultDeploy( "models/v_shotgun.mdl", "models/p_shotgun.mdl", SHOTGUN_DRAW, "shotgun" ); } void CShotgun::PrimaryAttack() { // chose the right shooting mode if( m_iShotgunMode == 0 ) { SingleBarrelShot(); } else if( m_iShotgunMode == 1 ) { DoubleBarrelShot(); } else { SingleBarrelShot(); } } void CShotgun::SecondaryAttack( void ) { // this is important because this is the ammo type switching part if(m_iShotgunMode == 0 ) // check what mode we are in { m_iShotgunMode = 1; //Change mode to 1 i.E. Buckshot/Double Barrel SendWeaponAnim( SHOTGUN_PUMP ); // show this animation so that we now that we changed the mode EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/scock1.wav", 1, ATTN_NORM, 0, 95 + RANDOM_LONG(0,0x1f)); } else if(m_iShotgunMode == 1 ) { m_iShotgunMode = 2; m_iOldClip = m_iClip; //Change to Slugs // this is important m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] += m_iOldClip; //put old clip back into the ammo reservoir if(m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] > BUCKSHOT_MAX_CARRY) m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] = BUCKSHOT_MAX_CARRY; // just to make sure that we don't have to much ammo m_iClip = 0; //set clip to 0 weapon will reload automatically(if you don't now how this works look at the weaponidle function SendWeaponAnim( SHOTGUN_PUMP ); //same as before EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/scock1.wav", 1, ATTN_NORM, 0, 95 + RANDOM_LONG(0,0x1f)); } else { m_iShotgunMode = 0; // same as before only the other way round m_iOldClip = m_iClip; m_pPlayer->m_rgAmmo[m_iSecondaryAmmoType] += m_iOldClip; if(m_pPlayer->m_rgAmmo[m_iSecondaryAmmoType] > BUCKSHOT_MAX_CARRY) m_pPlayer->m_rgAmmo[m_iSecondaryAmmoType] = BUCKSHOT_MAX_CARRY; m_iClip = 0; SendWeaponAnim( SHOTGUN_PUMP ); EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/scock1.wav", 1, ATTN_NORM, 0, 95 + RANDOM_LONG(0,0x1f)); } m_flNextPrimaryAttack = gpGlobals->time + 0.75; m_flNextSecondaryAttack = gpGlobals->time + 0.75; // we have to declare this or else we will be changing modes 10 times a second } void CShotgun::SingleBarrelShot() { // don't fire underwater if (m_pPlayer->pev->waterlevel == 3) { PlayEmptySound( ); m_flNextPrimaryAttack = gpGlobals->time + 0.15; return; } if (m_iClip < 0) { Reload( );//Modified reload function to use up the right ammo type chek it out ! if (m_iClip == 0) PlayEmptySound( ); return; } m_pPlayer->m_iWeaponVolume = LOUD_GUN_VOLUME; m_pPlayer->m_iWeaponFlash = NORMAL_GUN_FLASH; m_iClip--; m_pPlayer->pev->effects = (int)(m_pPlayer->pev->effects) | EF_MUZZLEFLASH; SendWeaponAnim( SHOTGUN_FIRE ); // player "shoot" animation m_pPlayer->SetAnimation( PLAYER_ATTACK1 ); UTIL_MakeVectors( m_pPlayer->pev->v_angle + m_pPlayer->pev->punchangle ); Vector vecShellVelocity = m_pPlayer->pev->velocity + gpGlobals->v_right * RANDOM_FLOAT(50,70) + gpGlobals->v_up * RANDOM_FLOAT(100,150) + gpGlobals->v_forward * 25; EjectBrass ( m_pPlayer->pev->origin + m_pPlayer->pev->view_ofs + gpGlobals->v_up * -12 + gpGlobals->v_forward * 20 + gpGlobals->v_right * 4 , vecShellVelocity, pev->angles.y, m_iShell, TE_BOUNCE_SHOTSHELL); EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/sbarrel1.wav", RANDOM_FLOAT(0.95, 1.0), ATTN_NORM, 0, 93 + RANDOM_LONG(0,0x1f)); Vector vecSrc = m_pPlayer->GetGunPosition( ); Vector vecAiming = m_pPlayer->GetAutoaimVector( AUTOAIM_10DEGREES ); if( m_iShotgunMode == 0 ) { m_pPlayer->FireBullets( 12, vecSrc, vecAiming, VECTOR_CONE_DM_SHOTGUN, 1536, BULLET_PLAYER_BUCKSHOT, 0 ); // Using more bullets to make shotgun cooler } else { m_pPlayer->FireBullets( 1, vecSrc, vecAiming, VECTOR_CONE_8DEGREES, 2048, BULLET_PLAYER_SLUGS, 0 ); // should perhaps lower the cone size // fire a slug } if( m_iShotgunMode == 0 ) { if (!m_iClip && m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] < 0) // HEV suit - indicate out of ammo condition m_pPlayer->SetSuitUpdate("!HEV_AMO0", FALSE, 0); if (m_iClip != 0) m_flPumpTime = gpGlobals->time + 0.5; } else // this is just a little bit diffrent { if (!m_iClip && m_pPlayer->m_rgAmmo[m_iSecondaryAmmoType] < 0) // HEV suit - indicate out of ammo condition m_pPlayer->SetSuitUpdate("!HEV_AMO0", FALSE, 0); if (m_iClip != 0) m_flPumpTime = gpGlobals->time + 0.5; } m_flNextPrimaryAttack = gpGlobals->time + 0.75; m_flNextSecondaryAttack = gpGlobals->time + 0.75; if (m_iClip != 0) m_flTimeWeaponIdle = gpGlobals->time + 5.0; else m_flTimeWeaponIdle = 0.75; m_fInReload = 0; m_pPlayer->pev->punchangle.x -= 5; } void CShotgun::DoubleBarrelShot() // this is the same as the old SecondaryFire( void ) { // don't fire underwater if (m_pPlayer->pev->waterlevel == 3) { PlayEmptySound( ); m_flNextPrimaryAttack = gpGlobals->time + 0.15; return; } if (m_iClip < 1) { Reload( ); PlayEmptySound( ); return; } m_pPlayer->m_iWeaponVolume = LOUD_GUN_VOLUME; m_pPlayer->m_iWeaponFlash = BRIGHT_GUN_FLASH; m_iClip -= 2; m_pPlayer->pev->effects = (int)(m_pPlayer->pev->effects) | EF_MUZZLEFLASH; SendWeaponAnim( SHOTGUN_FIRE2 ); // player "shoot" animation m_pPlayer->SetAnimation( PLAYER_ATTACK1 ); UTIL_MakeVectors( m_pPlayer->pev->v_angle + m_pPlayer->pev->punchangle ); Vector vecShellVelocity = m_pPlayer->pev->velocity + gpGlobals->v_right * RANDOM_FLOAT(50,70) + gpGlobals->v_up * RANDOM_FLOAT(100,150) + gpGlobals->v_forward * 25; EjectBrass ( m_pPlayer->pev->origin + m_pPlayer->pev->view_ofs + gpGlobals->v_up * -12 + gpGlobals->v_forward * 20 + gpGlobals->v_right * 4 , vecShellVelocity, pev->angles.y, m_iShell, TE_BOUNCE_SHOTSHELL); vecShellVelocity = m_pPlayer->pev->velocity + gpGlobals->v_right * RANDOM_FLOAT(50,70) + gpGlobals->v_up * RANDOM_FLOAT(100,150) + gpGlobals->v_forward * 25; EjectBrass ( m_pPlayer->pev->origin + m_pPlayer->pev->view_ofs + gpGlobals->v_up * -12 + gpGlobals->v_forward * 20 + gpGlobals->v_right * 4 , vecShellVelocity, pev->angles.y, m_iShell, TE_BOUNCE_SHOTSHELL); EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/dbarrel1.wav", RANDOM_FLOAT(0.98, 1.0), ATTN_NORM, 0, 85 + RANDOM_LONG(0,0x1f)); Vector vecSrc = m_pPlayer->GetGunPosition( ); Vector vecAiming = m_pPlayer->GetAutoaimVector( AUTOAIM_10DEGREES ); m_pPlayer->FireBullets( 24, vecSrc, vecAiming, VECTOR_CONE_DM_DOUBLESHOTGUN, 1536, BULLET_PLAYER_BUCKSHOT, 0 ); // Slugs should only have single fire //m_pPlayer->FireBullets( 2, vecSrc, vecAiming, VECTOR_CONE_5DEGREES, 2048, BULLET_PLAYER_SLUGS, 0 ); if (!m_iClip && m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] < 0) // HEV suit - indicate out of ammo condition m_pPlayer->SetSuitUpdate("!HEV_AMO0", FALSE, 0); if (m_iClip != 0) m_flPumpTime = gpGlobals->time + 0.95; m_flNextPrimaryAttack = gpGlobals->time + 1.5; m_flNextSecondaryAttack = gpGlobals->time + 1.5; if (m_iClip != 0) m_flTimeWeaponIdle = gpGlobals->time + 6.0; else m_flTimeWeaponIdle = 1.5; m_fInReload = 0; m_pPlayer->pev->punchangle.x -= 10; } void CShotgun::Reload( void ) { if(m_iShotgunMode == 0 || m_iShotgunMode == 1) // we do want to check the right ammo values { if (m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] < 0 || m_iClip == SHOTGUN_MAX_CLIP) return; } else { if (m_pPlayer->m_rgAmmo[m_iSecondaryAmmoType] < 0 || m_iClip == SHOTGUN_MAX_CLIP) return; } if (m_flNextReload > gpGlobals->time) return; // don't reload until recoil is done if (m_flNextPrimaryAttack > gpGlobals->time) return; // check to see if we're ready to reload if (m_fInReload == 0) { SendWeaponAnim( SHOTGUN_START_RELOAD ); m_fInReload = 1; m_pPlayer->m_flNextAttack = gpGlobals->time + 0.6; m_flTimeWeaponIdle = gpGlobals->time + 0.6; m_flNextPrimaryAttack = gpGlobals->time + 1.0; m_flNextSecondaryAttack = gpGlobals->time + 1.0; return; } else if (m_fInReload == 1) { if (m_flTimeWeaponIdle > gpGlobals->time) return; // was waiting for gun to move to side m_fInReload = 2; if (RANDOM_LONG(0,1)) EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/reload1.wav", 1, ATTN_NORM, 0, 85 + RANDOM_LONG(0,0x1f)); else EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/reload3.wav", 1, ATTN_NORM, 0, 85 + RANDOM_LONG(0,0x1f)); SendWeaponAnim( SHOTGUN_RELOAD ); m_flNextReload = gpGlobals->time + 0.5; m_flTimeWeaponIdle = gpGlobals->time + 0.5; } else { // Add them to the clip m_iClip += 1; if(m_iShotgunMode == 0 || m_iShotgunMode == 1) // we don't want to use up buckshot if we fire slugs { m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] -= 1; } else { m_pPlayer->m_rgAmmo[m_iSecondaryAmmoType] -= 1; } m_fInReload = 1; } } void CShotgun::WeaponIdle( void ) { if(m_iShotgunMode == 0 || m_iShotgunMode == 1) // we need this because we would check the wrong values if didn't use this { ResetEmptySound( ); m_pPlayer->GetAutoaimVector( AUTOAIM_10DEGREES ); if (m_flPumpTime && m_flPumpTime time) { // play pumping sound EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/scock1.wav", 1, ATTN_NORM, 0, 95 + RANDOM_LONG(0,0x1f)); m_flPumpTime = 0; } if (m_flTimeWeaponIdle time) { if (m_iClip == 0 && m_fInReload == 0 && m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]) { Reload( ); } else if (m_fInReload != 0) { if (m_iClip != 8 && m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]) { Reload( ); } else { // reload debounce has timed out SendWeaponAnim( SHOTGUN_PUMP ); // play cocking sound EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/scock1.wav", 1, ATTN_NORM, 0, 95 + RANDOM_LONG(0,0x1f)); m_fInReload = 0; m_flTimeWeaponIdle = gpGlobals->time + 1.5; } } else { int iAnim; float flRand = RANDOM_FLOAT(0, 1); if (flRand < 0.8) { iAnim = SHOTGUN_IDLE_DEEP; m_flTimeWeaponIdle = gpGlobals->time + (60.0/12.0);// * RANDOM_LONG(2, 5); } else if (flRand < 0.95) { iAnim = SHOTGUN_IDLE; m_flTimeWeaponIdle = gpGlobals->time + (20.0/9.0); } else { iAnim = SHOTGUN_IDLE4; m_flTimeWeaponIdle = gpGlobals->time + (20.0/9.0); } SendWeaponAnim( iAnim ); } } } else // same as before but replaced Primary by Secondary and vice versa { ResetEmptySound( ); m_pPlayer->GetAutoaimVector( AUTOAIM_10DEGREES ); if (m_flPumpTime && m_flPumpTime time) { // play pumping sound EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/scock1.wav", 1, ATTN_NORM, 0, 95 + RANDOM_LONG(0,0x1f)); m_flPumpTime = 0; } if (m_flTimeWeaponIdle time) { if (m_iClip == 0 && m_fInReload == 0 && m_pPlayer->m_rgAmmo[m_iSecondaryAmmoType]) { Reload( ); } else if (m_fInReload != 0) { if (m_iClip != 8 && m_pPlayer->m_rgAmmo[m_iSecondaryAmmoType]) { Reload( ); } else { // reload debounce has timed out SendWeaponAnim( SHOTGUN_PUMP ); // play cocking sound EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/scock1.wav", 1, ATTN_NORM, 0, 95 + RANDOM_LONG(0,0x1f)); m_fInReload = 0; m_flTimeWeaponIdle = gpGlobals->time + 1.5; } } else { int iAnim; float flRand = RANDOM_FLOAT(0, 1); if (flRand < 0.8) { iAnim = SHOTGUN_IDLE_DEEP; m_flTimeWeaponIdle = gpGlobals->time + (60.0/12.0);// * RANDOM_LONG(2, 5); } else if (flRand < 0.95) { iAnim = SHOTGUN_IDLE; m_flTimeWeaponIdle = gpGlobals->time + (20.0/9.0); } else { iAnim = SHOTGUN_IDLE4; m_flTimeWeaponIdle = gpGlobals->time + (20.0/9.0); } SendWeaponAnim( iAnim ); } } } } class CShotgunAmmo : public CBasePlayerAmmo { void Spawn( void ) { Precache( ); SET_MODEL(ENT(pev), "models/w_shotbox.mdl"); CBasePlayerAmmo::Spawn( ); } void Precache( void ) { PRECACHE_MODEL ("models/w_shotbox.mdl"); PRECACHE_SOUND("items/9mmclip1.wav"); } BOOL AddAmmo( CBaseEntity *pOther ) { if (pOther->GiveAmmo( AMMO_BUCKSHOTBOX_GIVE, "buckshot", BUCKSHOT_MAX_CARRY ) != -1) { EMIT_SOUND(ENT(pev), CHAN_ITEM, "items/9mmclip1.wav", 1, ATTN_NORM); return TRUE; } return FALSE; } }; LINK_ENTITY_TO_CLASS( ammo_buckshot, CShotgunAmmo ); class CShotgunSlugs : public CBasePlayerAmmo // this is the slug ammo { void Spawn( void ) { Precache( ); SET_MODEL(ENT(pev), "models/w_shotbox.mdl"); // you should use a custom model CBasePlayerAmmo::Spawn( ); } void Precache( void ) // won't work if we don't precache { PRECACHE_MODEL ("models/w_shotbox.mdl"); PRECACHE_SOUND("items/9mmclip1.wav"); } BOOL AddAmmo( CBaseEntity *pOther ) { if (pOther->GiveAmmo( AMMO_BUCKSHOTBOX_GIVE, "slugs", BUCKSHOT_MAX_CARRY ) != -1) // give us the ammo { EMIT_SOUND(ENT(pev), CHAN_ITEM, "items/9mmclip1.wav", 1, ATTN_NORM); return TRUE; } return FALSE; } }; LINK_ENTITY_TO_CLASS( ammo_slugs, CShotgunSlugs ); //END SHOTGUN.CPP Now we have to make some minor changes to combat.cpp , weapons.cpp and weapons.h These are the changes to combat.cpp: ------------------------------------ Add this after line 1494: case BULLET_PLAYER_SLUGS: // make distance based! pEntity->TraceAttack(pevAttacker, 30, vecDir, &tr, DMG_BULLET); if ( !tracer ) { // TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType); DecalGunshot( &tr, iBulletType ); } break; ------------------------------------ These are the changes to weapons.cpp: ------------------------------------- Add this after line 178 ( directly after BULLET_PLAYER_BUCKSHOT: ): case BULLET_PLAYER_SLUGS: ------------------------------------- These are the changes to weapons.h: ----------------------------------- In line 173 you will find this: typedef enum { BULLET_NONE = 0, BULLET_PLAYER_9MM, // glock BULLET_PLAYER_MP5, // mp5 BULLET_PLAYER_357, // python BULLET_PLAYER_BUCKSHOT, // shotgun BULLET_PLAYER_CROWBAR, // crowbar swipe BULLET_MONSTER_9MM, BULLET_MONSTER_MP5, BULLET_MONSTER_12MM, } Bullet; Replace it with this: typedef enum { BULLET_NONE = 0, BULLET_PLAYER_9MM, // glock BULLET_PLAYER_MP5, // mp5 BULLET_PLAYER_357, // python BULLET_PLAYER_BUCKSHOT, // shotgun BULLET_PLAYER_CROWBAR, // crowbar swipe BULLET_MONSTER_9MM, BULLET_MONSTER_MP5, BULLET_MONSTER_12MM, BULLET_PLAYER_SLUGS, } Bullet; ------------------------------------ Now compile and run (don't forget liblist.gam) Thats it ! We have now created a Shotgun w/ slugs ! But if you want to have better ammo display in the HUD you still have to make some changes. (You will find out how to do this in the smokegrenade tutorial that you can find in the Half-Life Programming Zone) This is the end of my first tutorial and perhaps I will make some more! And if you liked it tell me PS: To have a "blast those guys to hell" MP-5 Just replace line 198 with this: m_pPlayer->FireBullets(8, vecSrc, vecAiming, VECTOR_CONE_6DEGREES, 8192, BULLET_PLAYER_MP5, 4 );
Any questions or suggestions should be sent to me:
muellerroemer@planet-interkom.de