diff --git a/cl_dll/ammo.cpp b/cl_dll/ammo.cpp index 988bd6fa..5f8a7fee 100644 --- a/cl_dll/ammo.cpp +++ b/cl_dll/ammo.cpp @@ -835,9 +835,6 @@ int CHudAmmo::Draw( float flTime ) // Draw Weapon Menu DrawWList( flTime ); - // Draw ammo pickup history - gHR.DrawAmmoHistory( flTime ); - if( !( m_iFlags & HUD_ACTIVE ) ) return 0; diff --git a/cl_dll/battery.cpp b/cl_dll/battery.cpp index 2f26057f..2b785d2b 100644 --- a/cl_dll/battery.cpp +++ b/cl_dll/battery.cpp @@ -25,6 +25,12 @@ #include #include +#define ARMOR_BAR_LEFT 40 +#define ARMOR_BAR_BOTTOM 96 + +#define ARMOR_BAR_WIDTH 20 +#define ARMOR_BAR_HEIGHT 150 + DECLARE_MESSAGE( m_Battery, Battery ) int CHudBattery::Init( void ) @@ -74,19 +80,29 @@ int CHudBattery::Draw( float flTime ) if( gHUD.m_iHideHUDDisplay & HIDEHUD_HEALTH ) return 1; + if( !( gHUD.m_iWeaponBits & ( 1 << ( WEAPON_SUIT ) ) ) ) + return 1; + int r, g, b, x, y, a; - wrect_t rc; + int iWidth, iHeight; - rc = *m_prc2; - rc.top += m_iHeight * ( (float)( 100 - ( min( 100,m_iBat ) ) ) * 0.01 ); // battery can go from 0 to 100 so * 0.01 goes from 0 to 1 + iWidth = ARMOR_BAR_WIDTH; + iHeight = ARMOR_BAR_HEIGHT; - UnpackRGB( r, g, b, RGB_YELLOWISH ); + x = ScreenWidth - ARMOR_BAR_LEFT; + y = ScreenHeight - ARMOR_BAR_BOTTOM - iHeight; - if( !( gHUD.m_iWeaponBits & ( 1 << ( WEAPON_SUIT ) ) ) ) - return 1; + // Draw empty transparent bar. + r = g = b = 255; + a = 16; + + FillRGBA( x, y, iWidth, iHeight, r, g, b, a ); + + // Draw armor level bar. + UnpackRGB( r, g, b, RGB_YELLOWISH ); // Has health changed? Flash the health # - if( m_fFade ) + /*if( m_fFade ) { if( m_fFade > FADE_TIME ) m_fFade = FADE_TIME; @@ -99,35 +115,15 @@ int CHudBattery::Draw( float flTime ) } // Fade the health number back to dim + a = MIN_ALPHA + ( m_fFade / FADE_TIME ) * 128; } - else + else*/ a = MIN_ALPHA; - ScaleColors( r, g, b, a ); - - int iOffset = ( m_prc1->bottom - m_prc1->top ) / 6; - - y = ScreenHeight - gHUD.m_iFontHeight - gHUD.m_iFontHeight / 2; - x = ScreenWidth / 5; - - // make sure we have the right sprite handles - if( !m_hSprite1 ) - m_hSprite1 = gHUD.GetSprite( gHUD.GetSpriteIndex( "suit_empty" ) ); - if( !m_hSprite2 ) - m_hSprite2 = gHUD.GetSprite( gHUD.GetSpriteIndex( "suit_full" ) ); - - SPR_Set( m_hSprite1, r, g, b ); - SPR_DrawAdditive( 0, x, y - iOffset, m_prc1 ); - - if( rc.bottom > rc.top ) - { - SPR_Set( m_hSprite2, r, g, b ); - SPR_DrawAdditive( 0, x, y - iOffset + ( rc.top - m_prc2->top ), &rc ); - } + iHeight = ( m_iBat * ARMOR_BAR_HEIGHT ) / 100; - x += ( m_prc1->right - m_prc1->left ); - x = gHUD.DrawHudNumber( x, y, DHN_3DIGITS | DHN_DRAWZERO, m_iBat, r, g, b ); + gEngfuncs.pfnFillRGBABlend( x, y + ( ARMOR_BAR_HEIGHT - iHeight ), ARMOR_BAR_WIDTH, iHeight, r, g, b, a ); return 1; } diff --git a/cl_dll/ev_hldm.cpp b/cl_dll/ev_hldm.cpp index 9787a839..8fb62786 100644 --- a/cl_dll/ev_hldm.cpp +++ b/cl_dll/ev_hldm.cpp @@ -70,6 +70,9 @@ void EV_TripmineFire( struct event_args_s *args ); void EV_SnarkFire( struct event_args_s *args ); void EV_TrainPitchAdjust( struct event_args_s *args ); + +void EV_FireAK47( struct event_args_s *args ); +void EV_FireMac10( struct event_args_s *args ); } #define VECTOR_CONE_1DEGREES Vector( 0.00873, 0.00873, 0.00873 ) @@ -257,6 +260,14 @@ char *EV_HLDM_DamageDecal( physent_t *pe ) return decalname; } +//===================== +// EV_WallPuffCallback +//===================== +void EV_WallPuffCallback( struct tempent_s *ent, float frametime, float currenttime ) +{ + ent->entity.angles = ent->entity.baseline.vuser1; +} + void EV_HLDM_GunshotDecalTrace( pmtrace_t *pTrace, char *decalName ) { int iRand; @@ -297,6 +308,35 @@ void EV_HLDM_GunshotDecalTrace( pmtrace_t *pTrace, char *decalName ) gEngfuncs.pEfxAPI->R_DecalShoot( gEngfuncs.pEfxAPI->Draw_DecalIndex( gEngfuncs.pEfxAPI->Draw_DecalIndexFromName( decalName ) ), gEngfuncs.pEventAPI->EV_IndexFromTrace( pTrace ), 0, pTrace->endpos, 0 ); + + // + // Spawn small smoke puffs at the trace end location. + // + int modelindex = gEngfuncs.pEventAPI->EV_FindModelIndex( "sprites/wallsmoke.spr" ); + Vector position = pTrace->endpos + pTrace->plane.normal * 2; + Vector velocity = pTrace->plane.normal * gEngfuncs.pfnRandomFloat( 8, 10 ); + + TEMPENTITY* pSmoke = gEngfuncs.pEfxAPI->R_TempSprite( + position, // position + velocity, // velocity + gEngfuncs.pfnRandomFloat( 30, 35 ) / 100, // scale + modelindex, // model index + kRenderNormal, // rendermode + kRenderFxNoDissipation, // renderfx + gEngfuncs.pfnRandomFloat( 0.25, 0.5 ), // alpha + 0.01, // life + FTENT_SPRCYCLE | FTENT_FADEOUT); // flags + + if( pSmoke ) + { + Vector angles; + VectorAngles( velocity, angles ); + + pSmoke->flags |= FTENT_CLIENTCUSTOM; + pSmoke->entity.curstate.framerate = 4; + pSmoke->entity.baseline.vuser1 = angles; + pSmoke->callback = EV_WallPuffCallback; + } } } } @@ -317,6 +357,12 @@ void EV_HLDM_DecalGunshot( pmtrace_t *pTrace, int iBulletType ) case BULLET_MONSTER_MP5: case BULLET_PLAYER_BUCKSHOT: case BULLET_PLAYER_357: + case BULLET_PLAYER_AK47: + case BULLET_MONSTER_AK47: + case BULLET_MONSTER_HVMG: + case BULLET_PLAYER_MAC10: + case BULLET_MONSTER_MAC10: + case BULLET_PLAYER_SNIPER: default: // smoke and decal EV_HLDM_GunshotDecalTrace( pTrace, EV_HLDM_DamageDecal( pe ) ); @@ -359,6 +405,10 @@ int EV_HLDM_CheckTracer( int idx, float *vecSrc, float *end, float *forward, flo case BULLET_MONSTER_MP5: case BULLET_MONSTER_9MM: case BULLET_MONSTER_12MM: + case BULLET_PLAYER_AK47: + case BULLET_MONSTER_AK47: + case BULLET_MONSTER_HVMG: + case BULLET_MONSTER_MAC10: default: EV_CreateTracer( vecTracerSrc, end ); break; @@ -435,6 +485,8 @@ void EV_HLDM_FireBullets( int idx, float *forward, float *right, float *up, int EV_HLDM_DecalGunshot( &tr, iBulletType ); break; case BULLET_PLAYER_MP5: + case BULLET_PLAYER_AK47: + case BULLET_PLAYER_MAC10: if( !tracer ) { EV_HLDM_PlayTextureSound( idx, &tr, vecSrc, vecEnd, iBulletType ); @@ -445,6 +497,7 @@ void EV_HLDM_FireBullets( int idx, float *forward, float *right, float *up, int EV_HLDM_DecalGunshot( &tr, iBulletType ); break; case BULLET_PLAYER_357: + case BULLET_PLAYER_SNIPER: EV_HLDM_PlayTextureSound( idx, &tr, vecSrc, vecEnd, iBulletType ); EV_HLDM_DecalGunshot( &tr, iBulletType ); break; @@ -1303,23 +1356,39 @@ void EV_FireCrossbow( event_args_t *args ) { int idx; vec3_t origin; + vec3_t angles; + vec3_t velocity; + + vec3_t vecSrc, vecAiming; + vec3_t up, right, forward; idx = args->entindex; VectorCopy( args->origin, origin ); + VectorCopy( args->angles, angles ); + VectorCopy( args->velocity, velocity ); - gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/xbow_fire1.wav", 1, ATTN_NORM, 0, 93 + gEngfuncs.pfnRandomLong( 0, 0xF ) ); - gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_ITEM, "weapons/xbow_reload1.wav", gEngfuncs.pfnRandomFloat( 0.95, 1.0 ), ATTN_NORM, 0, 93 + gEngfuncs.pfnRandomLong( 0, 0xF ) ); + AngleVectors( angles, forward, right, up ); - //Only play the weapon anims if I shot it. if( EV_IsLocal( idx ) ) { + // Add muzzle flash to current weapon model + EV_MuzzleFlash(); + if( args->iparam1 ) gEngfuncs.pEventAPI->EV_WeaponAnimation( CROSSBOW_FIRE1, 1 ); - else if ( args->iparam2 ) + else if( args->iparam2 ) gEngfuncs.pEventAPI->EV_WeaponAnimation( CROSSBOW_FIRE3, 1 ); V_PunchAxis( 0, -2.0 ); } + + gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/xbow_fire1.wav", 1, ATTN_NORM, 0, 93 + gEngfuncs.pfnRandomLong( 0, 0xF ) ); + + EV_GetGunPosition( args, vecSrc, origin ); + + VectorCopy( forward, vecAiming ); + + EV_HLDM_FireBullets( idx, forward, right, up, 1, vecSrc, vecAiming, 8192, BULLET_PLAYER_SNIPER, 0, 0, args->fparam1, args->fparam2 ); } //====================== // CROSSBOW END @@ -1743,3 +1812,163 @@ int EV_TFC_IsAllyTeam( int iTeam1, int iTeam2 ) { return 0; } + +//====================== +// AK47 START +//====================== +enum ak47_e +{ + AK47_LONGIDLE = 0, + AK47_IDLE1, + AK47_LAUNCH, + AK47_RELOAD, + AK47_DEPLOY, + AK47_FIRE1, + AK47_FIRE2, + AK47_FIRE3, +}; + +void EV_FireAK47( struct event_args_s *args ) +{ + int idx; + vec3_t origin; + vec3_t angles; + vec3_t velocity; + + vec3_t ShellVelocity; + vec3_t ShellOrigin; + int shell; + vec3_t vecSrc, vecAiming; + vec3_t up, right, forward; + float flSpread = 0.01; + + idx = args->entindex; + VectorCopy( args->origin, origin ); + VectorCopy( args->angles, angles ); + VectorCopy( args->velocity, velocity ); + + AngleVectors( angles, forward, right, up ); + + shell = gEngfuncs.pEventAPI->EV_FindModelIndex( "models/shell.mdl" );// brass shell + + if( EV_IsLocal( idx ) ) + { + // Add muzzle flash to current weapon model + EV_MuzzleFlash(); + gEngfuncs.pEventAPI->EV_WeaponAnimation( AK47_FIRE1 + gEngfuncs.pfnRandomLong( 0, 2 ), 2 ); + + V_PunchAxis(0, gEngfuncs.pfnRandomFloat( -2, 2 ) ); + } + + EV_GetDefaultShellInfo( args, origin, velocity, ShellVelocity, ShellOrigin, forward, right, up, 20, -12, 4 ); + + EV_EjectBrass( ShellOrigin, ShellVelocity, angles[YAW], shell, TE_BOUNCE_SHELL ); + + switch( gEngfuncs.pfnRandomLong( 0, 2 ) ) + { + case 0: + gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/ak1.wav", 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ) ); + break; + case 1: + gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/ak2.wav", 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ) ); + break; + case 2: + gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/ak3.wav", 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ) ); + break; + } + + EV_GetGunPosition( args, vecSrc, origin ); + VectorCopy( forward, vecAiming ); + + if( gEngfuncs.GetMaxClients() > 1 ) + { + EV_HLDM_FireBullets( idx, forward, right, up, 1, vecSrc, vecAiming, 8192, BULLET_PLAYER_AK47, 2, &tracerCount[idx - 1], args->fparam1, args->fparam2 ); + } + else + { + EV_HLDM_FireBullets( idx, forward, right, up, 1, vecSrc, vecAiming, 8192, BULLET_PLAYER_AK47, 2, &tracerCount[idx - 1], args->fparam1, args->fparam2 ); + } +} +//====================== +// AK47 END +//====================== + +//====================== +// MAC10 START +//====================== +enum mac10_e +{ + MAC10_LONGIDLE = 0, + MAC10_IDLE1, + MAC10_LAUNCH, + MAC10_RELOAD, + MAC10_DEPLOY, + MAC10_FIRE1, + MAC10_FIRE2, + MAC10_FIRE3, +}; + +void EV_FireMac10( struct event_args_s *args ) +{ + int idx; + vec3_t origin; + vec3_t angles; + vec3_t velocity; + + vec3_t ShellVelocity; + vec3_t ShellOrigin; + int shell; + vec3_t vecSrc, vecAiming; + vec3_t up, right, forward; + float flSpread = 0.01; + + idx = args->entindex; + VectorCopy( args->origin, origin ); + VectorCopy( args->angles, angles ); + VectorCopy( args->velocity, velocity ); + + AngleVectors( angles, forward, right, up ); + + shell = gEngfuncs.pEventAPI->EV_FindModelIndex( "models/shell.mdl" );// brass shell + + if( EV_IsLocal( idx ) ) + { + // Add muzzle flash to current weapon model + EV_MuzzleFlash(); + gEngfuncs.pEventAPI->EV_WeaponAnimation( MAC10_FIRE1 + gEngfuncs.pfnRandomLong( 0, 2 ), 2 ); + + V_PunchAxis( 0, gEngfuncs.pfnRandomFloat( -2, 2 ) ); + } + + EV_GetDefaultShellInfo( args, origin, velocity, ShellVelocity, ShellOrigin, forward, right, up, 20, -12, 4 ); + + EV_EjectBrass( ShellOrigin, ShellVelocity, angles[YAW], shell, TE_BOUNCE_SHELL ); + + switch( gEngfuncs.pfnRandomLong( 0, 2 ) ) + { + case 0: + gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/mac1.wav", 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ) ); + break; + case 1: + gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/mac2.wav", 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ) ); + break; + case 2: + gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/mac3.wav", 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ) ); + break; + } + + EV_GetGunPosition( args, vecSrc, origin ); + VectorCopy( forward, vecAiming ); + + if( gEngfuncs.GetMaxClients() > 1 ) + { + EV_HLDM_FireBullets( idx, forward, right, up, 1, vecSrc, vecAiming, 8192, BULLET_PLAYER_MAC10, 2, &tracerCount[idx - 1], args->fparam1, args->fparam2 ); + } + else + { + EV_HLDM_FireBullets( idx, forward, right, up, 1, vecSrc, vecAiming, 8192, BULLET_PLAYER_MAC10, 2, &tracerCount[idx - 1], args->fparam1, args->fparam2 ); + } +} +//====================== +// MAC10 END +//====================== diff --git a/cl_dll/ev_hldm.h b/cl_dll/ev_hldm.h index bff43b1e..49806a6f 100644 --- a/cl_dll/ev_hldm.h +++ b/cl_dll/ev_hldm.h @@ -17,10 +17,15 @@ typedef enum BULLET_PLAYER_357, // python BULLET_PLAYER_BUCKSHOT, // shotgun BULLET_PLAYER_CROWBAR, // crowbar swipe - + BULLET_PLAYER_AK47, + BULLET_PLAYER_MAC10, + BULLET_PLAYER_SNIPER, BULLET_MONSTER_9MM, BULLET_MONSTER_MP5, BULLET_MONSTER_12MM + BULLET_MONSTER_AK47, + BULLET_MONSTER_HVMG, + BULLET_MONSTER_MAC10, }Bullet; enum glock_e diff --git a/cl_dll/health.cpp b/cl_dll/health.cpp index d4979c35..396d8607 100644 --- a/cl_dll/health.cpp +++ b/cl_dll/health.cpp @@ -27,6 +27,12 @@ #include "parsemsg.h" #include +#define HEALTH_BAR_LEFT 68 +#define HEALTH_BAR_BOTTOM 96 + +#define HEALTH_BAR_WIDTH 20 +#define HEALTH_BAR_HEIGHT 150 + #include "mobility_int.h" DECLARE_MESSAGE( m_Health, Health ) @@ -178,64 +184,56 @@ void CHudHealth::GetPainColor( int &r, int &g, int &b ) int CHudHealth::Draw( float flTime ) { + if( ( gHUD.m_iHideHUDDisplay & HIDEHUD_HEALTH ) || gEngfuncs.IsSpectateOnly() ) + return 1; + + if( !( gHUD.m_iWeaponBits & ( 1 << ( WEAPON_SUIT ) ) ) ) + return 1; + int r, g, b; int a = 0, x, y; - int HealthWidth; + int iWidth, iHeight; - if( ( gHUD.m_iHideHUDDisplay & HIDEHUD_HEALTH ) || gEngfuncs.IsSpectateOnly() ) - return 1; + iWidth = HEALTH_BAR_WIDTH; + iHeight = HEALTH_BAR_HEIGHT; + + x = ScreenWidth - HEALTH_BAR_LEFT; + y = ScreenHeight - HEALTH_BAR_BOTTOM - iHeight; + + // Draw empty transparent bar. + r = g = b = 255; + a = 16; - if( !m_hSprite ) - m_hSprite = LoadSprite( PAIN_NAME ); + FillRGBA( x, y, iWidth, iHeight, r, g, b, a ); + + // Draw health level bar. + UnpackRGB( r, g, b, RGB_YELLOWISH ); // Has health changed? Flash the health # - if( m_fFade ) + /*if( m_fFade ) { + if( m_fFade > FADE_TIME ) + m_fFade = FADE_TIME; + m_fFade -= ( gHUD.m_flTimeDelta * 20 ); if( m_fFade <= 0 ) { - a = MIN_ALPHA; + a = 128; m_fFade = 0; } // Fade the health number back to dim + a = MIN_ALPHA + ( m_fFade / FADE_TIME ) * 128; } - else + else*/ a = MIN_ALPHA; - // If health is getting low, make it bright red - if( m_iHealth <= 15 ) - a = 255; - - GetPainColor( r, g, b ); - ScaleColors( r, g, b, a ); - - // Only draw health if we have the suit. - if( gHUD.m_iWeaponBits & ( 1 << ( WEAPON_SUIT ) ) ) - { - HealthWidth = gHUD.GetSpriteRect( gHUD.m_HUD_number_0 ).right - gHUD.GetSpriteRect( gHUD.m_HUD_number_0 ).left; - int CrossWidth = gHUD.GetSpriteRect( m_HUD_cross ).right - gHUD.GetSpriteRect( m_HUD_cross ).left; - - y = ScreenHeight - gHUD.m_iFontHeight - gHUD.m_iFontHeight / 2; - x = CrossWidth / 2; + iHeight = ( m_iHealth * HEALTH_BAR_HEIGHT ) / 100; - SPR_Set( gHUD.GetSprite( m_HUD_cross ), r, g, b ); - SPR_DrawAdditive( 0, x, y, &gHUD.GetSpriteRect( m_HUD_cross ) ); + gEngfuncs.pfnFillRGBABlend( x, y + ( HEALTH_BAR_HEIGHT - iHeight ), HEALTH_BAR_WIDTH, iHeight, r, g, b, a ); - x = CrossWidth + HealthWidth / 2; - - x = gHUD.DrawHudNumber( x, y, DHN_3DIGITS | DHN_DRAWZERO, m_iHealth, r, g, b ); - - x += HealthWidth / 2; - - int iHeight = gHUD.m_iFontHeight; - int iWidth = HealthWidth / 10; - FillRGBA( x, y, iWidth, iHeight, 255, 160, 0, a ); - } - - DrawDamage( flTime ); - return DrawPain( flTime ); + return 1; } void CHudHealth::CalcDamageDirection( vec3_t vecFrom ) diff --git a/cl_dll/hl/hl_events.cpp b/cl_dll/hl/hl_events.cpp index c79279dd..ad3d113b 100644 --- a/cl_dll/hl/hl_events.cpp +++ b/cl_dll/hl/hl_events.cpp @@ -40,6 +40,9 @@ void EV_TripmineFire( struct event_args_s *args ); void EV_SnarkFire( struct event_args_s *args ); void EV_TrainPitchAdjust( struct event_args_s *args ); + +void EV_FireAK47( struct event_args_s *args ); +void EV_FireMac10( struct event_args_s *args ); } /* @@ -76,4 +79,6 @@ void Game_HookEvents( void ) gEngfuncs.pfnHookEvent( "events/firehornet.sc", EV_HornetGunFire ); gEngfuncs.pfnHookEvent( "events/tripfire.sc", EV_TripmineFire ); gEngfuncs.pfnHookEvent( "events/snarkfire.sc", EV_SnarkFire ); + gEngfuncs.pfnHookEvent( "events/ak47.sc", EV_FireAK47 ); + gEngfuncs.pfnHookEvent( "events/mac10.sc", EV_FireMac10 ); } diff --git a/cl_dll/hl/hl_weapons.cpp b/cl_dll/hl/hl_weapons.cpp index 5a17e858..a3fecafc 100644 --- a/cl_dll/hl/hl_weapons.cpp +++ b/cl_dll/hl/hl_weapons.cpp @@ -55,19 +55,16 @@ vec3_t previousorigin; // HLDM Weapon placeholder entities. CGlock g_Glock; CCrowbar g_Crowbar; -CPython g_Python; CMP5 g_Mp5; CCrossbow g_Crossbow; CShotgun g_Shotgun; CRpg g_Rpg; -CGauss g_Gauss; -CEgon g_Egon; -CHgun g_HGun; CHandGrenade g_HandGren; CSatchel g_Satchel; CTripmine g_Tripmine; CSqueak g_Snark; - +CAK47 g_AK47; +CMac10 g_Mac10; /* ====================== AlertMessage @@ -625,18 +622,16 @@ void HUD_InitClientWeapons( void ) // Allocate slot(s) for each weapon that we are going to be predicting HUD_PrepEntity( &g_Glock, &player ); HUD_PrepEntity( &g_Crowbar, &player ); - HUD_PrepEntity( &g_Python, &player ); HUD_PrepEntity( &g_Mp5, &player ); HUD_PrepEntity( &g_Crossbow, &player ); HUD_PrepEntity( &g_Shotgun, &player ); HUD_PrepEntity( &g_Rpg, &player ); - HUD_PrepEntity( &g_Gauss, &player ); - HUD_PrepEntity( &g_Egon, &player ); - HUD_PrepEntity( &g_HGun, &player ); HUD_PrepEntity( &g_HandGren, &player ); HUD_PrepEntity( &g_Satchel, &player ); HUD_PrepEntity( &g_Tripmine, &player ); HUD_PrepEntity( &g_Snark, &player ); + HUD_PrepEntity( &g_AK47, &player ); + HUD_PrepEntity( &g_Mac10, &player ); } /* @@ -706,9 +701,6 @@ void HUD_WeaponsPostThink( local_state_s *from, local_state_s *to, usercmd_t *cm case WEAPON_GLOCK: pWeapon = &g_Glock; break; - case WEAPON_PYTHON: - pWeapon = &g_Python; - break; case WEAPON_MP5: pWeapon = &g_Mp5; break; @@ -721,15 +713,6 @@ void HUD_WeaponsPostThink( local_state_s *from, local_state_s *to, usercmd_t *cm case WEAPON_RPG: pWeapon = &g_Rpg; break; - case WEAPON_GAUSS: - pWeapon = &g_Gauss; - break; - case WEAPON_EGON: - pWeapon = &g_Egon; - break; - case WEAPON_HORNETGUN: - pWeapon = &g_HGun; - break; case WEAPON_HANDGRENADE: pWeapon = &g_HandGren; break; @@ -742,6 +725,12 @@ void HUD_WeaponsPostThink( local_state_s *from, local_state_s *to, usercmd_t *cm case WEAPON_SNARK: pWeapon = &g_Snark; break; + case WEAPON_AK47: + pWeapon = &g_AK47; + break; + case WEAPON_MAC10: + pWeapon = &g_Mac10; + break; } // Store pointer to our destination entity_state_t so we can get our origin, etc. from it @@ -851,6 +840,14 @@ void HUD_WeaponsPostThink( local_state_s *from, local_state_s *to, usercmd_t *cm ( (CRpg *)player.m_pActiveItem )->m_fSpotActive = (int)from->client.vuser2[1]; ( (CRpg *)player.m_pActiveItem )->m_cActiveRockets = (int)from->client.vuser2[2]; } + else if( player.m_pActiveItem->m_iId == WEAPON_AK47 ) + { + player.ammo_ak47 = (int)from->client.vuser2[1]; + } + else if( player.m_pActiveItem->m_iId == WEAPON_MAC10 ) + { + player.ammo_mac10 = (int)from->client.vuser2[1]; + } // Don't go firing anything if we have died. // Or if we don't have a weapon model deployed @@ -919,6 +916,14 @@ void HUD_WeaponsPostThink( local_state_s *from, local_state_s *to, usercmd_t *cm from->client.vuser2[1] = ( (CRpg *)player.m_pActiveItem)->m_fSpotActive; from->client.vuser2[2] = ( (CRpg *)player.m_pActiveItem)->m_cActiveRockets; } + else if( player.m_pActiveItem->m_iId == WEAPON_AK47 ) + { + from->client.vuser2[1] = player.ammo_ak47; + } + else if( player.m_pActiveItem->m_iId == WEAPON_MAC10 ) + { + from->client.vuser2[1] = player.ammo_mac10; + } // Make sure that weapon animation matches what the game .dll is telling us // over the wire ( fixes some animation glitches ) @@ -930,10 +935,6 @@ void HUD_WeaponsPostThink( local_state_s *from, local_state_s *to, usercmd_t *cm if( pWeapon == &g_Tripmine ) body = 0; - //Show laser sight/scope combo - if( pWeapon == &g_Python && bIsMultiplayer() ) - body = 1; - // Force a fixed anim down to viewmodel HUD_SendWeaponAnim( to->client.weaponanim, body, 1 ); } diff --git a/cl_dll/hud.h b/cl_dll/hud.h index ec236003..6f4ecdc8 100644 --- a/cl_dll/hud.h +++ b/cl_dll/hud.h @@ -20,7 +20,7 @@ // CHud handles the message, calculation, and drawing the HUD // -#define RGB_YELLOWISH 0x00FFA000 //255,160,0 +#define RGB_YELLOWISH 0x000080FF //0,128,255 #define RGB_REDISH 0x00FF1010 //255,160,0 #define RGB_GREENISH 0x0000A000 //0,160,0 diff --git a/dlls/agrunt.cpp b/dlls/agrunt.cpp index 97804f68..2c53e6a7 100644 --- a/dlls/agrunt.cpp +++ b/dlls/agrunt.cpp @@ -253,6 +253,9 @@ void CAGrunt::TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir { SpawnBlood( ptr->vecEndPos, BloodColor(), flDamage );// a little surface blood. TraceBleed( flDamage, vecDir, ptr, bitsDamageType ); + + // Spawn blood stream. + UTIL_BloodStream( ptr->vecEndPos, -vecDir, BloodColor(), RANDOM_LONG( 4, 5 ) * 10 ); } AddMultiDamage( pevAttacker, this, flDamage, bitsDamageType ); diff --git a/dlls/cbase.h b/dlls/cbase.h index 47ce7595..1400b5a8 100644 --- a/dlls/cbase.h +++ b/dlls/cbase.h @@ -340,6 +340,8 @@ public: int ammo_uranium; int ammo_hornets; int ammo_argrens; + int ammo_ak47; + int ammo_mac10; //Special stuff for grenades and satchels. float m_flStartThrow; float m_flReleaseThrow; diff --git a/dlls/client.cpp b/dlls/client.cpp index 21e5d810..7a20a6b1 100644 --- a/dlls/client.cpp +++ b/dlls/client.cpp @@ -52,6 +52,31 @@ extern int g_teamplay; void LinkUserMessages( void ); +static const char* g_pszTrainMaps[] = +{ + "t000", + "t001", + "t002", + "t003", + "t004", +}; + +BOOL IsHazardCourseLevel( const char* szMapName ) +{ + for( size_t i = 0; i < ARRAYSIZE( g_pszTrainMaps ); i++ ) + { + if( FStrEq( szMapName, g_pszTrainMaps[i] ) ) + return TRUE; + } + + return FALSE; +} + +BOOL IsCurrentLevelTraining( void ) +{ + return IsHazardCourseLevel( STRING( gpGlobals->mapname ) ); +} + /* * used by kill command and disconnect command * ROBIN: Moved here from player.cpp, to allow multiple player models @@ -787,6 +812,13 @@ void ClientPrecache( void ) if( giPrecacheGrunt ) UTIL_PrecacheOther( "monster_human_grunt" ); + + PRECACHE_SOUND( "player/pain/pain_arm.wav" ); + PRECACHE_SOUND( "player/pain/pain_chest.wav" ); + PRECACHE_SOUND( "player/pain/pain_head.wav" ); + PRECACHE_SOUND( "player/pain/pain_leg.wav" ); + PRECACHE_SOUND( "player/pain/pain_stomach.wav" ); + PRECACHE_SOUND( "player/pain/spout.wav" ); } /* @@ -1623,6 +1655,14 @@ void UpdateClientData( const struct edict_s *ent, int sendweapons, struct client cd->vuser2.y = ( (CRpg *)pl->m_pActiveItem )->m_fSpotActive; cd->vuser2.z = ( (CRpg *)pl->m_pActiveItem )->m_cActiveRockets; } + else if( pl->m_pActiveItem->m_iId == WEAPON_AK47 ) + { + cd->vuser2.y = pl->ammo_ak47; + } + else if( pl->m_pActiveItem->m_iId == WEAPON_MAC10 ) + { + cd->vuser2.y = pl->ammo_mac10; + } } } } diff --git a/dlls/combat.cpp b/dlls/combat.cpp index 3a59844f..6a4381b6 100644 --- a/dlls/combat.cpp +++ b/dlls/combat.cpp @@ -1336,6 +1336,9 @@ void CBaseMonster::TraceAttack( entvars_t *pevAttacker, float flDamage, Vector v SpawnBlood( ptr->vecEndPos, BloodColor(), flDamage );// a little surface blood. TraceBleed( flDamage, vecDir, ptr, bitsDamageType ); AddMultiDamage( pevAttacker, this, flDamage, bitsDamageType ); + + // Spawn blood stream. + UTIL_BloodStream( ptr->vecEndPos, -vecDir, ( BloodColor() == BLOOD_COLOR_RED ) ? 70 : BloodColor(), RANDOM_LONG( 4, 5 ) * 10 ); } } @@ -1402,6 +1405,9 @@ void CBaseEntity::FireBullets( ULONG cShots, Vector vecSrc, Vector vecDirShootin case BULLET_MONSTER_MP5: case BULLET_MONSTER_9MM: case BULLET_MONSTER_12MM: + case BULLET_MONSTER_AK47: + case BULLET_MONSTER_MAC10: + case BULLET_MONSTER_HVMG: default: MESSAGE_BEGIN( MSG_PAS, SVC_TEMPENTITY, vecTracerSrc ); WRITE_BYTE( TE_TRACER ); @@ -1459,6 +1465,24 @@ void CBaseEntity::FireBullets( ULONG cShots, Vector vecSrc, Vector vecDirShootin UTIL_DecalTrace( &tr, DECAL_GLASSBREAK1 + RANDOM_LONG( 0, 2 ) ); } + break; + case BULLET_MONSTER_AK47: + pEntity->TraceAttack( pevAttacker, gSkillData.monDmgMP5, vecDir, &tr, DMG_BULLET ); + + TEXTURETYPE_PlaySound( &tr, vecSrc, vecEnd, iBulletType ); + DecalGunshot( &tr, iBulletType ); + break; + case BULLET_MONSTER_HVMG: + pEntity->TraceAttack(pevAttacker, gSkillData.monDmgHvmg, vecDir, &tr, DMG_BULLET ); + + TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType); + DecalGunshot(&tr, iBulletType); + break; + case BULLET_MONSTER_MAC10: + pEntity->TraceAttack( pevAttacker, gSkillData.monDmgMac10, vecDir, &tr, DMG_BULLET ); + + TEXTURETYPE_PlaySound( &tr, vecSrc, vecEnd, iBulletType ); + DecalGunshot( &tr, iBulletType ); break; } } @@ -1544,6 +1568,15 @@ Vector CBaseEntity::FireBulletsPlayer( ULONG cShots, Vector vecSrc, Vector vecDi UTIL_DecalTrace( &tr, DECAL_GLASSBREAK1 + RANDOM_LONG( 0, 2 ) ); } + break; + case BULLET_PLAYER_AK47: + pEntity->TraceAttack( pevAttacker, gSkillData.plrDmgAK47, vecDir, &tr, DMG_BULLET ); + break; + case BULLET_PLAYER_MAC10: + pEntity->TraceAttack( pevAttacker, gSkillData.plrDmgMac10, vecDir, &tr, DMG_BULLET ); + break; + case BULLET_PLAYER_SNIPER: + pEntity->TraceAttack( pevAttacker, gSkillData.plrDmgCrossbowMonster, vecDir, &tr, DMG_BULLET ); break; } } diff --git a/dlls/crossbow.cpp b/dlls/crossbow.cpp index d34ad25d..c8e90df7 100644 --- a/dlls/crossbow.cpp +++ b/dlls/crossbow.cpp @@ -393,68 +393,57 @@ void CCrossbow::FireSniperBolt() void CCrossbow::FireBolt() { - TraceResult tr; - - if( m_iClip == 0 ) + // don't fire underwater + if( m_pPlayer->pev->waterlevel == 3 ) { PlayEmptySound(); + m_flNextPrimaryAttack = 0.15; return; } - m_pPlayer->m_iWeaponVolume = QUIET_GUN_VOLUME; + if( m_iClip <= 0 ) + { + if( !m_fFireOnEmpty ) + Reload(); + else + { + EMIT_SOUND( ENT( m_pPlayer->pev ), CHAN_WEAPON, "weapons/357_cock1.wav", 0.8, ATTN_NORM ); + m_flNextPrimaryAttack = 0.15; + } - m_iClip--; + return; + } - int flags; -#if defined( CLIENT_WEAPONS ) - flags = FEV_NOTHOST; -#else - flags = 0; -#endif + m_pPlayer->m_iWeaponVolume = LOUD_GUN_VOLUME; + m_pPlayer->m_iWeaponFlash = BRIGHT_GUN_FLASH; - PLAYBACK_EVENT_FULL( flags, m_pPlayer->edict(), m_usCrossbow, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, 0, 0, m_iClip, m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType], 0, 0 ); + m_iClip--; + + m_pPlayer->pev->effects = (int)( m_pPlayer->pev->effects ) | EF_MUZZLEFLASH; // player "shoot" animation m_pPlayer->SetAnimation( PLAYER_ATTACK1 ); - Vector anglesAim = m_pPlayer->pev->v_angle + m_pPlayer->pev->punchangle; - UTIL_MakeVectors( anglesAim ); + UTIL_MakeVectors( m_pPlayer->pev->v_angle + m_pPlayer->pev->punchangle ); - anglesAim.x = -anglesAim.x; - Vector vecSrc = m_pPlayer->GetGunPosition() - gpGlobals->v_up * 2; - Vector vecDir = gpGlobals->v_forward; + Vector vecSrc = m_pPlayer->GetGunPosition(); + Vector vecAiming = m_pPlayer->GetAutoaimVector( AUTOAIM_10DEGREES ); -#ifndef CLIENT_DLL - CCrossbowBolt *pBolt = CCrossbowBolt::BoltCreate(); - pBolt->pev->origin = vecSrc; - pBolt->pev->angles = anglesAim; - pBolt->pev->owner = m_pPlayer->edict(); + Vector vecDir; + vecDir = m_pPlayer->FireBulletsPlayer( 1, vecSrc, vecAiming, VECTOR_CONE_1DEGREES, 8192, BULLET_PLAYER_SNIPER, 0, 0, m_pPlayer->pev, m_pPlayer->random_seed ); - if( m_pPlayer->pev->waterlevel == 3 ) - { - pBolt->pev->velocity = vecDir * BOLT_WATER_VELOCITY; - pBolt->pev->speed = BOLT_WATER_VELOCITY; - } - else - { - pBolt->pev->velocity = vecDir * BOLT_AIR_VELOCITY; - pBolt->pev->speed = BOLT_AIR_VELOCITY; - } - pBolt->pev->avelocity.z = 10; + int flags; +#if defined( CLIENT_WEAPONS ) + flags = FEV_NOTHOST; +#else + flags = 0; #endif - if( !m_iClip && m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0 ) - // HEV suit - indicate out of ammo condition - m_pPlayer->SetSuitUpdate( "!HEV_AMO0", FALSE, 0 ); - - m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.75; + PLAYBACK_EVENT_FULL( flags, m_pPlayer->edict(), m_usCrossbow, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, vecDir.x, vecDir.y, m_iClip, m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType], 0, 0 ); - m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.75; + m_flNextPrimaryAttack = m_flNextSecondaryAttack = GetNextAttackDelay( 0.75 ); - if( m_iClip != 0 ) - m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 5.0; - else - m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 0.75; + m_flTimeWeaponIdle = UTIL_SharedRandomFloat( m_pPlayer->random_seed, 10, 15 ); } void CCrossbow::SecondaryAttack() diff --git a/dlls/eftd/ak47.cpp b/dlls/eftd/ak47.cpp new file mode 100644 index 00000000..795373e6 --- /dev/null +++ b/dlls/eftd/ak47.cpp @@ -0,0 +1,229 @@ +/*** +* +* Copyright (c) 1996-2001, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ + +#include "extdll.h" +#include "util.h" +#include "cbase.h" +#include "monsters.h" +#include "weapons.h" +#include "nodes.h" +#include "player.h" +#include "soundent.h" +#include "gamerules.h" + +enum ak47_e +{ + AK47_LONGIDLE = 0, + AK47_IDLE1, + AK47_LAUNCH, + AK47_RELOAD, + AK47_DEPLOY, + AK47_FIRE1, + AK47_FIRE2, + AK47_FIRE3, +}; + + +LINK_ENTITY_TO_CLASS(weapon_ak47, CAK47); + +void CAK47::Spawn() +{ + Precache(); + SET_MODEL(ENT(pev), "models/w_ak47.mdl"); + m_iId = WEAPON_AK47; + + m_iDefaultAmmo = AK47_DEFAULT_GIVE; + + FallInit();// get ready to fall down. +} + + +void CAK47::Precache(void) +{ + PRECACHE_MODEL("models/v_ak47.mdl"); + PRECACHE_MODEL("models/w_ak47.mdl"); + PRECACHE_MODEL("models/p_9mmAR.mdl"); + + m_iShell = PRECACHE_MODEL("models/shell.mdl");// brass shellTE_MODEL + + PRECACHE_MODEL("models/w_ak47clip.mdl"); + PRECACHE_SOUND("items/9mmclip1.wav"); + + PRECACHE_SOUND("items/akclipinsert1.wav"); + PRECACHE_SOUND("items/akcliprelease1.wav"); + + PRECACHE_SOUND("weapons/ak1.wav"); + PRECACHE_SOUND("weapons/ak2.wav"); + PRECACHE_SOUND("weapons/ak3.wav"); + + PRECACHE_SOUND("weapons/357_cock1.wav"); + + m_usAK47 = PRECACHE_EVENT(1, "events/ak47.sc"); +} + +int CAK47::GetItemInfo(ItemInfo *p) +{ + p->pszName = STRING(pev->classname); + p->pszAmmo1 = "ak47"; + p->iMaxAmmo1 = AK47_MAX_CARRY; + p->pszAmmo2 = NULL; + p->iMaxAmmo2 = -1; + p->iMaxClip = AK47_MAX_CLIP; + p->iSlot = 2; + p->iPosition = 3; + p->iFlags = 0; + p->iId = m_iId = WEAPON_AK47; + p->iWeight = AK47_WEIGHT; + + return 1; +} + +BOOL CAK47::Deploy() +{ + BOOL bResult = DefaultDeploy("models/v_ak47.mdl", "models/p_9mmAR.mdl", AK47_DEPLOY, "ak47"); + + if (bResult) + { + m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 1; + } + + return bResult; +} + + +void CAK47::PrimaryAttack() +{ + // don't fire underwater + if (m_pPlayer->pev->waterlevel == 3) + { + PlayEmptySound(); + m_flNextPrimaryAttack = 0.15; + return; + } + + if (m_iClip <= 0) + { + PlayEmptySound(); + m_flNextPrimaryAttack = 0.15; + return; + } + + m_pPlayer->m_iWeaponVolume = NORMAL_GUN_VOLUME; + m_pPlayer->m_iWeaponFlash = NORMAL_GUN_FLASH; + + m_iClip--; + + + m_pPlayer->pev->effects = (int)(m_pPlayer->pev->effects) | EF_MUZZLEFLASH; + + // player "shoot" animation + m_pPlayer->SetAnimation(PLAYER_ATTACK1); + + Vector vecSrc = m_pPlayer->GetGunPosition(); + Vector vecAiming = m_pPlayer->GetAutoaimVector(AUTOAIM_5DEGREES); + Vector vecDir; + Vector vecSpread; + + // Allow for higher accuracy when the player is crouching. + if (m_pPlayer->pev->flags & FL_DUCKING) + { + vecSpread = VECTOR_CONE_2DEGREES; + } + else + { + vecSpread = VECTOR_CONE_5DEGREES; + } + + // single player spread + vecDir = m_pPlayer->FireBulletsPlayer(1, vecSrc, vecAiming, vecSpread, 8192, BULLET_PLAYER_AK47, 2, 0, m_pPlayer->pev, m_pPlayer->random_seed); + + int flags; +#if defined( CLIENT_WEAPONS ) + flags = FEV_NOTHOST; +#else + flags = 0; +#endif + + PLAYBACK_EVENT_FULL(flags, m_pPlayer->edict(), m_usAK47, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, vecDir.x, vecDir.y, 0, 0, 0, 0); + + m_flNextPrimaryAttack = GetNextAttackDelay(0.1); + + if (m_flNextPrimaryAttack < UTIL_WeaponTimeBase()) + m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.1; + + m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + UTIL_SharedRandomFloat(m_pPlayer->random_seed, 10, 15); +} + +void CAK47::Reload(void) +{ + if (m_pPlayer->ammo_ak47 <= 0) + return; + + DefaultReload(AK47_MAX_CLIP, AK47_RELOAD, 2.8); +} + + +void CAK47::WeaponIdle(void) +{ + ResetEmptySound(); + + m_pPlayer->GetAutoaimVector(AUTOAIM_5DEGREES); + + if (m_flTimeWeaponIdle > UTIL_WeaponTimeBase()) + return; + + int iAnim; + switch (RANDOM_LONG(0, 1)) + { + case 0: + iAnim = AK47_LONGIDLE; + break; + + default: + case 1: + iAnim = AK47_IDLE1; + break; + } + + SendWeaponAnim(iAnim); + + m_flTimeWeaponIdle = UTIL_SharedRandomFloat(m_pPlayer->random_seed, 10, 15); // how long till we do this again. +} + + +class CAK47AmmoClip : public CBasePlayerAmmo +{ + void Spawn(void) + { + Precache(); + SET_MODEL(ENT(pev), "models/w_ak47clip.mdl"); + CBasePlayerAmmo::Spawn(); + } + void Precache(void) + { + PRECACHE_MODEL("models/w_ak47clip.mdl"); + PRECACHE_SOUND("items/9mmclip1.wav"); + } + BOOL AddAmmo(CBaseEntity *pOther) + { + int bResult = (pOther->GiveAmmo(AMMO_AK47_GIVE, "ak47", AK47_MAX_CARRY) != -1); + if (bResult) + { + EMIT_SOUND(ENT(pev), CHAN_ITEM, "items/9mmclip1.wav", 1, ATTN_NORM); + } + return bResult; + } +}; +LINK_ENTITY_TO_CLASS(ammo_ak47, CAK47AmmoClip); \ No newline at end of file diff --git a/dlls/eftd/diablo.cpp b/dlls/eftd/diablo.cpp new file mode 100644 index 00000000..0882b31b --- /dev/null +++ b/dlls/eftd/diablo.cpp @@ -0,0 +1,345 @@ +/*** +* +* Copyright (c) 1996-2001, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* This source code contains proprietary and confidential information of +* Valve LLC and its suppliers. Access to this code is restricted to +* persons who have executed a written SDK license with Valve. Any access, +* use or distribution of this code by or to any unlicensed person is illegal. +* +****/ + +// UNDONE: Don't flinch every time you get hit + +#include "extdll.h" +#include "util.h" +#include "cbase.h" +#include "monsters.h" +#include "schedule.h" + + +//========================================================= +// Monster's Anim Events Go Here +//========================================================= +#define DIABLO_AE_ATTACK_RIGHT 0x01 +#define DIABLO_AE_ATTACK_LEFT 0x02 +#define DIABLO_AE_ATTACK_BOTH 0x03 + +#define DIABLO_FLINCH_DELAY 2 // at most one flinch every n secs + +class CDiablo : public CBaseMonster +{ +public: + void Spawn(void); + void Precache(void); + void SetYawSpeed(void); + int Classify(void); + void HandleAnimEvent(MonsterEvent_t *pEvent); + int IgnoreConditions(void); + + float m_flNextFlinch; + + void PainSound(void); + void AlertSound(void); + void IdleSound(void); + void AttackSound(void); + + static const char *pAttackSounds[]; + static const char *pIdleSounds[]; + static const char *pAlertSounds[]; + static const char *pPainSounds[]; + static const char *pAttackHitSounds[]; + static const char *pAttackMissSounds[]; + + // No range attacks + BOOL CheckRangeAttack1(float flDot, float flDist) { return FALSE; } + BOOL CheckRangeAttack2(float flDot, float flDist) { return FALSE; } + int TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType); + + void SetActivity(Activity NewActivity); +}; + +LINK_ENTITY_TO_CLASS(monster_diablo, CDiablo); + +const char *CDiablo::pAttackHitSounds[] = +{ + "diablo/diablo_claw1.wav", + "diablo/diablo_claw2.wav", + "diablo/diablo_claw3.wav", +}; + +const char *CDiablo::pAttackMissSounds[] = +{ + "diablo/diablo_claw_miss1.wav", + "diablo/diablo_claw_miss2.wav", +}; + +const char *CDiablo::pAttackSounds[] = +{ + "diablo/diablo_attack1.wav", + "diablo/diablo_attack2.wav", +}; + +const char *CDiablo::pIdleSounds[] = +{ + "diablo/diablo_idle1.wav", + "diablo/diablo_idle2.wav", + "diablo/diablo_idle3.wav", +}; + +const char *CDiablo::pAlertSounds[] = +{ + "diablo/diablo_alert10.wav", + "diablo/diablo_alert20.wav", + "diablo/diablo_alert30.wav", +}; + +const char *CDiablo::pPainSounds[] = +{ + "diablo/diablo_pain1.wav", + "diablo/diablo_pain2.wav", +}; + +//========================================================= +// Classify - indicates this monster's place in the +// relationship table. +//========================================================= +int CDiablo::Classify(void) +{ + return CLASS_ALIEN_PREDATOR; +} + +//========================================================= +// SetYawSpeed - allows each sequence to have a different +// turn rate associated with it. +//========================================================= +void CDiablo::SetYawSpeed(void) +{ + int ys; + + ys = 140; // 120 + +#if 0 + switch (m_Activity) + { + } +#endif + + pev->yaw_speed = ys; +} + +int CDiablo::TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType) +{ + // Take 30% damage from bullets + if (bitsDamageType == DMG_BULLET) + { + Vector vecDir = pev->origin - (pevInflictor->absmin + pevInflictor->absmax) * 0.5; + vecDir = vecDir.Normalize(); + float flForce = DamageForce(flDamage); + pev->velocity = pev->velocity + vecDir * flForce; + flDamage *= 0.3; + } + + // HACK HACK -- until we fix this. + if (IsAlive()) + PainSound(); + return CBaseMonster::TakeDamage(pevInflictor, pevAttacker, flDamage, bitsDamageType); +} + +void CDiablo::PainSound(void) +{ + int pitch = 95 + RANDOM_LONG(0, 9); + + if (RANDOM_LONG(0, 5) < 2) + EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, RANDOM_SOUND_ARRAY(pPainSounds), 1.0, ATTN_NORM, 0, pitch); +} + +void CDiablo::AlertSound(void) +{ + int pitch = 95 + RANDOM_LONG(0, 9); + + EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, RANDOM_SOUND_ARRAY(pAlertSounds), 1.0, ATTN_NORM, 0, pitch); +} + +void CDiablo::IdleSound(void) +{ + int pitch = 100 + RANDOM_LONG(-5, 5); + + // Play a random idle sound + EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, RANDOM_SOUND_ARRAY(pIdleSounds), 1.0, ATTN_NORM, 0, pitch); +} + +void CDiablo::AttackSound(void) +{ + int pitch = 100 + RANDOM_LONG(-5, 5); + + // Play a random attack sound + EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, RANDOM_SOUND_ARRAY(pAttackSounds), 1.0, ATTN_NORM, 0, pitch); +} + + +//========================================================= +// HandleAnimEvent - catches the monster-specific messages +// that occur when tagged animation frames are played. +//========================================================= +void CDiablo::HandleAnimEvent(MonsterEvent_t *pEvent) +{ + switch (pEvent->event) + { + case DIABLO_AE_ATTACK_RIGHT: + { + // do stuff for this event. + // ALERT( at_console, "Slash right!\n" ); + CBaseEntity *pHurt = CheckTraceHullAttack(70, gSkillData.diabloDmgOneSlash, DMG_SLASH | DMG_NEVERGIB); + if (pHurt) + { + if (pHurt->pev->flags & (FL_MONSTER | FL_CLIENT)) + { + pHurt->pev->punchangle.z = -18; + pHurt->pev->punchangle.x = 5; + pHurt->pev->velocity = pHurt->pev->velocity - gpGlobals->v_right * 100; + } + // Play a random attack hit sound + EMIT_SOUND_DYN(ENT(pev), CHAN_WEAPON, RANDOM_SOUND_ARRAY(pAttackHitSounds), 1.0, ATTN_NORM, 0, 100 + RANDOM_LONG(-5, 5)); + } + else // Play a random attack miss sound + EMIT_SOUND_DYN(ENT(pev), CHAN_WEAPON, RANDOM_SOUND_ARRAY(pAttackMissSounds), 1.0, ATTN_NORM, 0, 100 + RANDOM_LONG(-5, 5)); + + if (RANDOM_LONG(0, 1)) + AttackSound(); + } + break; + + case DIABLO_AE_ATTACK_LEFT: + { + // do stuff for this event. + // ALERT( at_console, "Slash left!\n" ); + CBaseEntity *pHurt = CheckTraceHullAttack(70, gSkillData.diabloDmgOneSlash, DMG_SLASH | DMG_NEVERGIB); + if (pHurt) + { + if (pHurt->pev->flags & (FL_MONSTER | FL_CLIENT)) + { + pHurt->pev->punchangle.z = 18; + pHurt->pev->punchangle.x = 5; + pHurt->pev->velocity = pHurt->pev->velocity + gpGlobals->v_right * 100; + } + EMIT_SOUND_DYN(ENT(pev), CHAN_WEAPON, RANDOM_SOUND_ARRAY(pAttackHitSounds), 1.0, ATTN_NORM, 0, 100 + RANDOM_LONG(-5, 5)); + } + else + EMIT_SOUND_DYN(ENT(pev), CHAN_WEAPON, RANDOM_SOUND_ARRAY(pAttackMissSounds), 1.0, ATTN_NORM, 0, 100 + RANDOM_LONG(-5, 5)); + + if (RANDOM_LONG(0, 1)) + AttackSound(); + } + break; + + case DIABLO_AE_ATTACK_BOTH: + { + // do stuff for this event. + CBaseEntity *pHurt = CheckTraceHullAttack(70, gSkillData.diabloDmgBothSlash, DMG_SLASH | DMG_NEVERGIB); + if (pHurt) + { + if (pHurt->pev->flags & (FL_MONSTER | FL_CLIENT)) + { + pHurt->pev->punchangle.x = 5; + pHurt->pev->velocity = pHurt->pev->velocity + gpGlobals->v_forward * -100; + } + EMIT_SOUND_DYN(ENT(pev), CHAN_WEAPON, RANDOM_SOUND_ARRAY(pAttackHitSounds), 1.0, ATTN_NORM, 0, 100 + RANDOM_LONG(-5, 5)); + } + else + EMIT_SOUND_DYN(ENT(pev), CHAN_WEAPON, RANDOM_SOUND_ARRAY(pAttackMissSounds), 1.0, ATTN_NORM, 0, 100 + RANDOM_LONG(-5, 5)); + + if (RANDOM_LONG(0, 1)) + AttackSound(); + } + break; + + default: + CBaseMonster::HandleAnimEvent(pEvent); + break; + } +} + +//========================================================= +// Spawn +//========================================================= +void CDiablo::Spawn() +{ + Precache(); + + SET_MODEL(ENT(pev), "models/diablo.mdl"); + UTIL_SetSize(pev, VEC_HUMAN_HULL_MIN, VEC_HUMAN_HULL_MAX); + + pev->solid = SOLID_SLIDEBOX; + pev->movetype = MOVETYPE_STEP; + m_bloodColor = BLOOD_COLOR_RED; + pev->health = gSkillData.diabloHealth; + pev->view_ofs = VEC_VIEW;// position of the eyes relative to monster's origin. + m_flFieldOfView = 0.5;// indicates the width of this monster's forward view cone ( as a dotproduct result ) + m_MonsterState = MONSTERSTATE_NONE; + m_afCapability = bits_CAP_DOORS_GROUP; + + MonsterInit(); +} + +//========================================================= +// Precache - precaches all resources this monster needs +//========================================================= +void CDiablo::Precache() +{ + PRECACHE_MODEL("models/diablo.mdl"); + + PRECACHE_SOUND_ARRAY(pAttackHitSounds); + PRECACHE_SOUND_ARRAY(pAttackMissSounds); + PRECACHE_SOUND_ARRAY(pAttackSounds); + PRECACHE_SOUND_ARRAY(pIdleSounds); + PRECACHE_SOUND_ARRAY(pAlertSounds); + PRECACHE_SOUND_ARRAY(pPainSounds); +} + + +void CDiablo::SetActivity(Activity newActivity) +{ + if (m_MonsterState == MONSTERSTATE_COMBAT) + { + if (newActivity == ACT_WALK) + newActivity = ACT_RUN; + } + + CBaseMonster::SetActivity(newActivity); +} + +//========================================================= +// AI Schedules Specific to this monster +//========================================================= + + + +int CDiablo::IgnoreConditions(void) +{ + int iIgnore = CBaseMonster::IgnoreConditions(); + + if ((m_Activity == ACT_MELEE_ATTACK1) || (m_Activity == ACT_MELEE_ATTACK1)) + { +#if 0 + if (pev->health < 20) + iIgnore |= (bits_COND_LIGHT_DAMAGE | bits_COND_HEAVY_DAMAGE); + else +#endif + if (m_flNextFlinch >= gpGlobals->time) + iIgnore |= (bits_COND_LIGHT_DAMAGE | bits_COND_HEAVY_DAMAGE); + } + + if ((m_Activity == ACT_SMALL_FLINCH) || (m_Activity == ACT_BIG_FLINCH)) + { + if (m_flNextFlinch < gpGlobals->time) + m_flNextFlinch = gpGlobals->time + DIABLO_FLINCH_DELAY; + } + + return iIgnore; + +} \ No newline at end of file diff --git a/dlls/eftd/hassault.cpp b/dlls/eftd/hassault.cpp new file mode 100644 index 00000000..b8091e4a --- /dev/null +++ b/dlls/eftd/hassault.cpp @@ -0,0 +1,251 @@ +/*** +* +* Copyright (c) 1996-2001, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* This source code contains proprietary and confidential information of +* Valve LLC and its suppliers. Access to this code is restricted to +* persons who have executed a written SDK license with Valve. Any access, +* use or distribution of this code by or to any unlicensed person is illegal. +* +****/ + + +#include "extdll.h" +#include "plane.h" +#include "util.h" +#include "cbase.h" +#include "monsters.h" +#include "schedule.h" +#include "animation.h" +#include "weapons.h" +#include "soundent.h" +#include "effects.h" + +//========================================================= +// Monster's Anim Events Go Here +//========================================================= +#define HASSAULT_AE_BURST1 ( 1 ) +#define HASSAULT_AE_BURST2 ( 2 ) +#define HASSAULT_AE_BURST3 ( 3 ) +#define HASSAULT_AE_BURST4 ( 4 ) +#define HASSAULT_AE_BURST5 ( 5 ) +#define HASSAULT_AE_BURST6 ( 6 ) +#define HASSAULT_AE_BURST7 ( 7 ) +#define HASSAULT_AE_BURST8 ( 8 ) +#define HASSAULT_AE_BURST9 ( 9 ) +#define HASSAULT_AE_PAIN1 ( 10 ) +#define HASSAULT_AE_PAIN2 ( 11 ) + +class CHassault : public CBaseMonster +{ +public: + void Spawn(void); + void Precache(void); + void SetYawSpeed(void); + int Classify(void); + void HandleAnimEvent(MonsterEvent_t* pEvent); + + void DeathSound(void); + + BOOL CheckMeleeAttack1(float flDot, float flDist) { return FALSE; } + BOOL CheckMeleeAttack2(float flDot, float flDist) { return FALSE; } + BOOL CheckRangeAttack2(float flDot, float flDist) { return FALSE; } + + void Shoot(void); + + static const char *pDeathSounds[]; + static const char *pPainSounds[]; + static const char *pBurstSounds[]; + +private: + int m_iShell; +}; + +LINK_ENTITY_TO_CLASS(monster_hassault, CHassault); + +const char *CHassault::pPainSounds[] = +{ + "hgrunt/gr_pain1.wav", + "hgrunt/gr_pain2.wav", + "hgrunt/gr_pain3.wav", + "hgrunt/gr_pain4.wav", + "hgrunt/gr_pain5.wav", +}; + +const char *CHassault::pDeathSounds[] = +{ + "hgrunt/gr_die1.wav", + "hgrunt/gr_die2.wav", + "hgrunt/gr_die3.wav", +}; + +const char *CHassault::pBurstSounds[] = +{ + "hassault/hw_shoot1.wav", + "hassault/hw_shoot2.wav", + "hassault/hw_shoot3.wav", +}; + +//========================================================= +// SetYawSpeed - allows each sequence to have a different +// turn rate associated with it. +//========================================================= +void CHassault::SetYawSpeed(void) +{ + int ys; + + switch (m_Activity) + { + case ACT_IDLE: + ys = 150; + break; + case ACT_RUN: + case ACT_WALK: + ys = 180; + break; + case ACT_RANGE_ATTACK1: + ys = 120; + break; + case ACT_TURN_LEFT: + case ACT_TURN_RIGHT: + ys = 180; + break; + default: + ys = 90; + break; + } + + pev->yaw_speed = ys; +} + +//========================================================= +// HandleAnimEvent - catches the monster-specific messages +// that occur when tagged animation frames are played. +//========================================================= +void CHassault::HandleAnimEvent(MonsterEvent_t *pEvent) +{ + switch (pEvent->event) + { + case HASSAULT_AE_BURST1: + case HASSAULT_AE_BURST2: + case HASSAULT_AE_BURST3: + case HASSAULT_AE_BURST4: + case HASSAULT_AE_BURST5: + case HASSAULT_AE_BURST6: + case HASSAULT_AE_BURST7: + case HASSAULT_AE_BURST8: + case HASSAULT_AE_BURST9: + + Shoot(); + EMIT_SOUND(ENT(pev), CHAN_WEAPON, RANDOM_SOUND_ARRAY(pBurstSounds), 1, ATTN_NORM); + + break; + + case HASSAULT_AE_PAIN1: + case HASSAULT_AE_PAIN2: + EMIT_SOUND(ENT(pev), CHAN_VOICE, RANDOM_SOUND_ARRAY(pPainSounds), 1, ATTN_NORM); + break; + + default: + CBaseMonster::HandleAnimEvent(pEvent); + break; + } +} + + +//========================================================= +// Spawn +//========================================================= +void CHassault::Spawn() +{ + Precache(); + + SET_MODEL(ENT(pev), "models/hassault.mdl"); + UTIL_SetSize(pev, VEC_HUMAN_HULL_MIN, VEC_HUMAN_HULL_MAX); + + pev->solid = SOLID_SLIDEBOX; + pev->movetype = MOVETYPE_STEP; + m_bloodColor = BLOOD_COLOR_RED; + pev->effects = 0; + pev->health = gSkillData.hassaultHealth; + m_flFieldOfView = 0.2;// indicates the width of this monster's forward view cone ( as a dotproduct result ) + m_MonsterState = MONSTERSTATE_NONE; + + m_afCapability = bits_CAP_SQUAD | bits_CAP_TURN_HEAD | bits_CAP_DOORS_GROUP; + + m_HackedGunPos = Vector(0, 0, 55); + + m_cAmmoLoaded = 1; + ClearConditions(bits_COND_NO_AMMO_LOADED); + + MonsterInit(); +} + +//========================================================= +// Precache - precaches all resources this monster needs +//========================================================= +void CHassault::Precache() +{ + PRECACHE_MODEL("models/hassault.mdl"); + + PRECACHE_SOUND("hassault/hw_gun4.wav"); + + PRECACHE_SOUND_ARRAY(pPainSounds); + PRECACHE_SOUND_ARRAY(pDeathSounds); + PRECACHE_SOUND_ARRAY(pBurstSounds); + + PRECACHE_SOUND("hassault/hw_spin.wav"); + PRECACHE_SOUND("hassault/hw_spindown.wav"); + PRECACHE_SOUND("hassault/hw_spinup.wav"); + + m_iShell = PRECACHE_MODEL("models/shell.mdl");// brass shell +} + +//========================================================= +// Classify - indicates this monster's place in the +// relationship table. +//========================================================= +int CHassault::Classify(void) +{ + return CLASS_HUMAN_MILITARY; +} + +//========================================================= +// Shoot +//========================================================= +void CHassault::Shoot(void) +{ + if (m_hEnemy == NULL) + { + return; + } + + Vector vecShootOrigin = GetGunPosition(); + Vector vecShootDir = ShootAtEnemy(vecShootOrigin); + + UTIL_MakeVectors(pev->angles); + + Vector vecShellVelocity = gpGlobals->v_right * RANDOM_FLOAT(40, 90) + gpGlobals->v_up * RANDOM_FLOAT(75, 200) + gpGlobals->v_forward * RANDOM_FLOAT(-40, 40); + EjectBrass(vecShootOrigin - vecShootDir * 24, vecShellVelocity, pev->angles.y, m_iShell, TE_BOUNCE_SHELL); + FireBullets(1, vecShootOrigin, vecShootDir, VECTOR_CONE_15DEGREES, 2048, BULLET_MONSTER_HVMG); // shoot +-5 degrees + + pev->effects |= EF_MUZZLEFLASH; + + // m_cAmmoLoaded--;// take away a bullet! + + Vector angDir = UTIL_VecToAngles(vecShootDir); + SetBlending(0, angDir.x); +} + + +//========================================================= +// DeathSound +//========================================================= +void CHassault::DeathSound(void) +{ + EMIT_SOUND(ENT(pev), CHAN_VOICE, RANDOM_SOUND_ARRAY(pDeathSounds), 1, ATTN_IDLE); +} \ No newline at end of file diff --git a/dlls/eftd/mac10.cpp b/dlls/eftd/mac10.cpp new file mode 100644 index 00000000..207491fb --- /dev/null +++ b/dlls/eftd/mac10.cpp @@ -0,0 +1,229 @@ +/*** +* +* Copyright (c) 1996-2001, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ + +#include "extdll.h" +#include "util.h" +#include "cbase.h" +#include "monsters.h" +#include "weapons.h" +#include "nodes.h" +#include "player.h" +#include "soundent.h" +#include "gamerules.h" + +enum mac10_e +{ + MAC10_LONGIDLE = 0, + MAC10_IDLE1, + MAC10_LAUNCH, + MAC10_RELOAD, + MAC10_DEPLOY, + MAC10_FIRE1, + MAC10_FIRE2, + MAC10_FIRE3, +}; + + +LINK_ENTITY_TO_CLASS(weapon_mac10, CMac10); + +void CMac10::Spawn() +{ + Precache(); + SET_MODEL(ENT(pev), "models/w_mac10.mdl"); + m_iId = WEAPON_MAC10; + + m_iDefaultAmmo = MAC10_DEFAULT_GIVE; + + FallInit();// get ready to fall down. +} + + +void CMac10::Precache(void) +{ + PRECACHE_MODEL("models/v_mac10.mdl"); + PRECACHE_MODEL("models/w_mac10.mdl"); + PRECACHE_MODEL("models/p_9mmAR.mdl"); + + m_iShell = PRECACHE_MODEL("models/shell.mdl");// brass shellTE_MODEL + + PRECACHE_MODEL("models/w_mac10clip.mdl"); + PRECACHE_SOUND("items/9mmclip1.wav"); + + PRECACHE_SOUND("items/mac10clipinsert1.wav"); + PRECACHE_SOUND("items/mac10cliprelease1.wav"); + + PRECACHE_SOUND("weapons/mac1.wav"); + PRECACHE_SOUND("weapons/mac2.wav"); + PRECACHE_SOUND("weapons/mac3.wav"); + + PRECACHE_SOUND("weapons/357_cock1.wav"); + + m_usMac10 = PRECACHE_EVENT(1, "events/mac10.sc"); +} + +int CMac10::GetItemInfo(ItemInfo *p) +{ + p->pszName = STRING(pev->classname); + p->pszAmmo1 = "mac10"; + p->iMaxAmmo1 = MAC10_MAX_CARRY; + p->pszAmmo2 = NULL; + p->iMaxAmmo2 = -1; + p->iMaxClip = MAC10_MAX_CLIP; + p->iSlot = 1; + p->iPosition = 1; + p->iFlags = 0; + p->iId = m_iId = WEAPON_MAC10; + p->iWeight = MAC10_WEIGHT; + + return 1; +} + +BOOL CMac10::Deploy() +{ + BOOL bResult = DefaultDeploy("models/v_mac10.mdl", "models/p_9mmAR.mdl", MAC10_DEPLOY, "mac10"); + + if ( bResult ) + { + m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.8; + } + + return bResult; +} + + +void CMac10::PrimaryAttack() +{ + // don't fire underwater + if (m_pPlayer->pev->waterlevel == 3) + { + PlayEmptySound(); + m_flNextPrimaryAttack = 0.15; + return; + } + + if (m_iClip <= 0) + { + PlayEmptySound(); + m_flNextPrimaryAttack = 0.15; + return; + } + + m_pPlayer->m_iWeaponVolume = NORMAL_GUN_VOLUME; + m_pPlayer->m_iWeaponFlash = NORMAL_GUN_FLASH; + + m_iClip--; + + + m_pPlayer->pev->effects = (int)(m_pPlayer->pev->effects) | EF_MUZZLEFLASH; + + // player "shoot" animation + m_pPlayer->SetAnimation(PLAYER_ATTACK1); + + Vector vecSrc = m_pPlayer->GetGunPosition(); + Vector vecAiming = m_pPlayer->GetAutoaimVector(AUTOAIM_5DEGREES); + Vector vecDir; + Vector vecSpread; + + // Allow for higher accuracy when the player is crouching. + if (m_pPlayer->pev->flags & FL_DUCKING) + { + vecSpread = VECTOR_CONE_1DEGREES; + } + else + { + vecSpread = VECTOR_CONE_4DEGREES; + } + + // single player spread + vecDir = m_pPlayer->FireBulletsPlayer(1, vecSrc, vecAiming, vecSpread, 8192, BULLET_PLAYER_MAC10, 2, 0, m_pPlayer->pev, m_pPlayer->random_seed); + + int flags; +#if defined( CLIENT_WEAPONS ) + flags = FEV_NOTHOST; +#else + flags = 0; +#endif + + PLAYBACK_EVENT_FULL(flags, m_pPlayer->edict(), m_usMac10, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, vecDir.x, vecDir.y, 0, 0, 0, 0); + + m_flNextPrimaryAttack = GetNextAttackDelay(0.1); + + if (m_flNextPrimaryAttack < UTIL_WeaponTimeBase()) + m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.1; + + m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + UTIL_SharedRandomFloat(m_pPlayer->random_seed, 10, 15); +} + +void CMac10::Reload(void) +{ + if (m_pPlayer->ammo_mac10 <= 0) + return; + + DefaultReload(MAC10_MAX_CLIP, MAC10_RELOAD, 2.7); +} + + +void CMac10::WeaponIdle(void) +{ + ResetEmptySound(); + + m_pPlayer->GetAutoaimVector(AUTOAIM_5DEGREES); + + if (m_flTimeWeaponIdle > UTIL_WeaponTimeBase()) + return; + + int iAnim; + switch (RANDOM_LONG(0, 1)) + { + case 0: + iAnim = MAC10_LONGIDLE; + break; + + default: + case 1: + iAnim = MAC10_IDLE1; + break; + } + + SendWeaponAnim(iAnim); + + m_flTimeWeaponIdle = UTIL_SharedRandomFloat(m_pPlayer->random_seed, 10, 15); // how long till we do this again. +} + + +class CMac10AmmoClip : public CBasePlayerAmmo +{ + void Spawn(void) + { + Precache(); + SET_MODEL(ENT(pev), "models/w_mac10clip.mdl"); + CBasePlayerAmmo::Spawn(); + } + void Precache(void) + { + PRECACHE_MODEL("models/w_mac10clip.mdl"); + PRECACHE_SOUND("items/9mmclip1.wav"); + } + BOOL AddAmmo(CBaseEntity *pOther) + { + int bResult = (pOther->GiveAmmo(AMMO_MAC10_GIVE, "mac10", MAC10_MAX_CARRY) != -1); + if (bResult) + { + EMIT_SOUND(ENT(pev), CHAN_ITEM, "items/9mmclip1.wav", 1, ATTN_NORM); + } + return bResult; + } +}; +LINK_ENTITY_TO_CLASS(ammo_mac10, CMac10AmmoClip); \ No newline at end of file diff --git a/dlls/func_break.cpp b/dlls/func_break.cpp index 38b05f7b..c1d313ed 100644 --- a/dlls/func_break.cpp +++ b/dlls/func_break.cpp @@ -48,16 +48,16 @@ const char *CBreakable::pSpawnObjects[] = "ammo_buckshot", // 9 "weapon_crossbow", // 10 "ammo_crossbow", // 11 - "weapon_357", // 12 - "ammo_357", // 13 - "weapon_rpg", // 14 - "ammo_rpgclip", // 15 - "ammo_gaussclip", // 16 - "weapon_handgrenade", // 17 - "weapon_tripmine", // 18 - "weapon_satchel", // 19 - "weapon_snark", // 20 - "weapon_hornetgun", // 21 + "weapon_rpg", // 12 + "ammo_rpgclip", // 13 + "weapon_handgrenade", // 14 + "weapon_tripmine", // 15 + "weapon_satchel", // 16 + "weapon_snark", // 17 + "weapon_ak47", // 18 + "ammo_ak47", // 19 + "weapon_mac10", // 20 + "ammo_mac10", }; void CBreakable::KeyValue( KeyValueData* pkvd ) diff --git a/dlls/game.cpp b/dlls/game.cpp index 3aec1810..992e8482 100644 --- a/dlls/game.cpp +++ b/dlls/game.cpp @@ -439,6 +439,44 @@ cvar_t sk_player_leg1 = { "sk_player_leg1","1" }; cvar_t sk_player_leg2 = { "sk_player_leg2","1" }; cvar_t sk_player_leg3 = { "sk_player_leg3","1" }; +// Diablo +cvar_t sk_diablo_health1 = { "sk_diablo_health1", "0" }; +cvar_t sk_diablo_health2 = { "sk_diablo_health2", "0" }; +cvar_t sk_diablo_health3 = { "sk_diablo_health3", "0" }; + +cvar_t sk_diablo_dmg_one_slash1 = { "sk_diablo_dmg_one_slash1", "0" }; +cvar_t sk_diablo_dmg_one_slash2 = { "sk_diablo_dmg_one_slash2", "0" }; +cvar_t sk_diablo_dmg_one_slash3 = { "sk_diablo_dmg_one_slash3", "0" }; + +cvar_t sk_diablo_dmg_both_slash1 = { "sk_diablo_dmg_both_slash1", "0" }; +cvar_t sk_diablo_dmg_both_slash2 = { "sk_diablo_dmg_both_slash2", "0" }; +cvar_t sk_diablo_dmg_both_slash3 = { "sk_diablo_dmg_both_slash3", "0" }; + +// Hassault +cvar_t sk_hassault_health1 = { "sk_hassault_health1", "0" }; +cvar_t sk_hassault_health2 = { "sk_hassault_health2", "0" }; +cvar_t sk_hassault_health3 = { "sk_hassault_health3", "0" }; + +// AK47 Round +cvar_t sk_plr_ak47_bullet1 = { "sk_plr_ak47_bullet1", "0" }; +cvar_t sk_plr_ak47_bullet2 = { "sk_plr_ak47_bullet2", "0" }; +cvar_t sk_plr_ak47_bullet3 = { "sk_plr_ak47_bullet3", "0" }; + +// Mac10 Round +cvar_t sk_plr_mac10_bullet1 = { "sk_plr_mac10_bullet1", "0" }; +cvar_t sk_plr_mac10_bullet2 = { "sk_plr_mac10_bullet2", "0" }; +cvar_t sk_plr_mac10_bullet3 = { "sk_plr_mac10_bullet3", "0" }; + +// Heavy machine gun round +cvar_t sk_hvmg_bullet1 = { "sk_hvmg_bullet1", "0" }; +cvar_t sk_hvmg_bullet2 = { "sk_hvmg_bullet2", "0" }; +cvar_t sk_hvmg_bullet3 = { "sk_hvmg_bullet3", "0" }; + +// Grunt Mac10 +cvar_t sk_mac10_bullet1 = { "sk_mac10_bullet1", "0" }; +cvar_t sk_mac10_bullet2 = { "sk_mac10_bullet2", "0" }; +cvar_t sk_mac10_bullet3 = { "sk_mac10_bullet3", "0" }; + // END Cvars for Skill Level settings // Register your console variables here @@ -847,6 +885,45 @@ void GameDLLInit( void ) CVAR_REGISTER( &sk_player_leg1 ); CVAR_REGISTER( &sk_player_leg2 ); CVAR_REGISTER( &sk_player_leg3 ); + + // Diablo + CVAR_REGISTER( &sk_diablo_health1 ); + CVAR_REGISTER( &sk_diablo_health2 ); + CVAR_REGISTER( &sk_diablo_health3 ); + + CVAR_REGISTER( &sk_diablo_dmg_one_slash1 ); + CVAR_REGISTER( &sk_diablo_dmg_one_slash2 ); + CVAR_REGISTER( &sk_diablo_dmg_one_slash3 ); + + CVAR_REGISTER( &sk_diablo_dmg_both_slash1 ); + CVAR_REGISTER( &sk_diablo_dmg_both_slash2 ); + CVAR_REGISTER( &sk_diablo_dmg_both_slash3 ); + + // Hassault + CVAR_REGISTER( &sk_hassault_health1 ); + CVAR_REGISTER( &sk_hassault_health2 ); + CVAR_REGISTER( &sk_hassault_health3 ); + + // AK47 Round + CVAR_REGISTER( &sk_plr_ak47_bullet1 ); + CVAR_REGISTER( &sk_plr_ak47_bullet2 ); + CVAR_REGISTER( &sk_plr_ak47_bullet3 ); + + // Mac10 Round + CVAR_REGISTER( &sk_plr_mac10_bullet1 ); + CVAR_REGISTER( &sk_plr_mac10_bullet2 ); + CVAR_REGISTER( &sk_plr_mac10_bullet3 ); + + // Heavy machine gun round + CVAR_REGISTER( &sk_hvmg_bullet1 ); + CVAR_REGISTER( &sk_hvmg_bullet2 ); + CVAR_REGISTER( &sk_hvmg_bullet3 ); + + // Grunt Mac10 + CVAR_REGISTER( &sk_mac10_bullet1 ); + CVAR_REGISTER( &sk_mac10_bullet2 ); + CVAR_REGISTER( &sk_mac10_bullet3 ); + // END REGISTER CVARS FOR SKILL LEVEL STUFF SERVER_COMMAND( "exec skill.cfg\n" ); diff --git a/dlls/gamerules.cpp b/dlls/gamerules.cpp index f59788c4..c6482e78 100644 --- a/dlls/gamerules.cpp +++ b/dlls/gamerules.cpp @@ -301,6 +301,26 @@ void CGameRules::RefreshSkillData ( void ) gSkillData.plrStomach = GetSkillCvar( "sk_player_stomach" ); gSkillData.plrLeg = GetSkillCvar( "sk_player_leg" ); gSkillData.plrArm = GetSkillCvar( "sk_player_arm" ); + + // Diablo + gSkillData.diabloHealth = GetSkillCvar( "sk_diablo_health" ); + gSkillData.diabloDmgOneSlash = GetSkillCvar( "sk_diablo_dmg_one_slash" ); + gSkillData.diabloDmgBothSlash = GetSkillCvar( "sk_diablo_dmg_both_slash" ); + + // Hassault + gSkillData.hassaultHealth = GetSkillCvar( "sk_hassault_health" ); + + // AK47 Round + gSkillData.plrDmgAK47 = GetSkillCvar( "sk_plr_ak47_bullet" ); + + // Mac10 Round + gSkillData.plrDmgMac10 = GetSkillCvar( "sk_plr_mac10_bullet" ); + + // Heavy machine gun round + gSkillData.monDmgHvmg = GetSkillCvar( "sk_hvmg_bullet" ); + + // Grunt Mac10 + gSkillData.monDmgMac10 = GetSkillCvar( "sk_mac10_bullet" ); } //========================================================= diff --git a/dlls/glock.cpp b/dlls/glock.cpp index 1f4517e7..e4c16bb7 100644 --- a/dlls/glock.cpp +++ b/dlls/glock.cpp @@ -88,33 +88,70 @@ int CGlock::GetItemInfo( ItemInfo *p ) BOOL CGlock::Deploy() { - // pev->body = 1; - return DefaultDeploy( "models/v_9mmhandgun.mdl", "models/p_9mmhandgun.mdl", GLOCK_DRAW, "onehanded", /*UseDecrement() ? 1 : 0*/ 0 ); + BOOL bResult = DefaultDeploy( "models/v_9mmhandgun.mdl", "models/p_9mmhandgun.mdl", GLOCK_DRAW, "onehanded", /*UseDecrement() ? 1 : 0*/ 0 ); + + if( bResult ) + { + m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.85f; + m_fInAttack = 0; + } + + return bResult; +} + +void CGlock::Holster(int skiplocal /*= 0*/) +{ + m_fInReload = FALSE;// cancel any reload in progress. + + m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.5; + SendWeaponAnim( GLOCK_HOLSTER ); + + m_fInAttack = 0; } void CGlock::SecondaryAttack( void ) { - GlockFire( 0.1, 0.2, FALSE ); } void CGlock::PrimaryAttack( void ) { - GlockFire( 0.01, 0.3, TRUE ); + float flSpread; + + // Allow for higher accuracy when the player is crouching. + if( m_pPlayer->pev->flags & FL_DUCKING ) + { + flSpread = 0.00873; + } + else + { + flSpread = 0.03490; + } + + GlockFire( flSpread, 0.2, TRUE ); } void CGlock::GlockFire( float flSpread, float flCycleTime, BOOL fUseAutoAim ) { + // Do not allow attack unless primary attack key was released. + if( m_fInAttack ) + return; + if( m_iClip <= 0 ) { - if( m_fFireOnEmpty ) + if( !m_fFireOnEmpty ) + Reload(); + else { - PlayEmptySound(); - m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.2; + EMIT_SOUND( ENT( m_pPlayer->pev ), CHAN_WEAPON, "weapons/357_cock1.wav", 0.8, ATTN_NORM ); + m_flNextPrimaryAttack = GetNextAttackDelay( 0.2 ); } return; } + // Prevent from continuously refire. + m_fInAttack = 1; + m_iClip--; m_pPlayer->pev->effects = (int)( m_pPlayer->pev->effects ) | EF_MUZZLEFLASH; @@ -175,13 +212,16 @@ void CGlock::Reload( void ) int iResult; if( m_iClip == 0 ) - iResult = DefaultReload( 17, GLOCK_RELOAD, 1.5 ); + iResult = DefaultReload( GLOCK_MAX_CLIP, GLOCK_RELOAD, 2.2 ); else - iResult = DefaultReload( 17, GLOCK_RELOAD_NOT_EMPTY, 1.5 ); + iResult = DefaultReload( GLOCK_MAX_CLIP, GLOCK_RELOAD_NOT_EMPTY, 2.2 ); if( iResult ) { m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + UTIL_SharedRandomFloat( m_pPlayer->random_seed, 10, 15 ); + + // Unblock primary attack. + m_fInAttack = 0; } } @@ -191,6 +231,12 @@ void CGlock::WeaponIdle( void ) m_pPlayer->GetAutoaimVector( AUTOAIM_10DEGREES ); + // + // Unblock primary attack. + // This will only occur if players released primary attack key. + // + m_fInAttack = 0; + if( m_flTimeWeaponIdle > UTIL_WeaponTimeBase() ) return; @@ -203,18 +249,19 @@ void CGlock::WeaponIdle( void ) if( flRand <= 0.3 + 0 * 0.75 ) { iAnim = GLOCK_IDLE3; - m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 49.0 / 16; + m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 50.0 / 18.0; } else if( flRand <= 0.6 + 0 * 0.875 ) { iAnim = GLOCK_IDLE1; - m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 60.0 / 16.0; + m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 50.0 / 18.0; } else { iAnim = GLOCK_IDLE2; - m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 40.0 / 16.0; + m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 50.0 / 26.0; } + SendWeaponAnim( iAnim, 1 ); } } diff --git a/dlls/hgrunt.cpp b/dlls/hgrunt.cpp index 7b0eaa2c..8cd6378f 100644 --- a/dlls/hgrunt.cpp +++ b/dlls/hgrunt.cpp @@ -45,6 +45,8 @@ int g_fGruntQuestion; // true if an idle grunt asked a question. Cleared when extern DLL_GLOBAL int g_iSkillLevel; +BOOL IsCurrentLevelTraining( void ); + //========================================================= // monster-specific DEFINE's //========================================================= @@ -61,16 +63,22 @@ extern DLL_GLOBAL int g_iSkillLevel; #define HGRUNT_HANDGRENADE ( 1 << 1) #define HGRUNT_GRENADELAUNCHER ( 1 << 2) #define HGRUNT_SHOTGUN ( 1 << 3) - +#define HGRUNT_AK47 ( 1 << 0) +#define HGRUNT_MAC10 ( 1 << 3) #define HEAD_GROUP 1 #define HEAD_GRUNT 0 #define HEAD_COMMANDER 1 #define HEAD_SHOTGUN 2 #define HEAD_M203 3 +#define HEAD_ARCTIC 0 #define GUN_GROUP 2 #define GUN_MP5 0 #define GUN_SHOTGUN 1 #define GUN_NONE 2 +#define GUN_AK47 0 +#define GUN_MAC10 1 + +#define GF_SNOWGRUNT 1 //========================================================= // Monster's Anim Events Go Here @@ -140,7 +148,10 @@ public: void PainSound( void ); void IdleSound( void ); Vector GetGunPosition( void ); - void Shoot( void ); + void Shoot( Vector vecSpread, int iBulletType ); + void ShootMP5( Vector vecSpread ); + void ShootAK47( Vector vecSpread ); + void ShootMac10( Vector vecSpread ); void Shotgun( void ); void PrescheduleThink( void ); void GibMonster( void ); @@ -184,6 +195,10 @@ public: int m_iSentence; static const char *pGruntSentences[]; + + BOOL IsSnowGrunt() const; + + int m_iGruntFlags; }; LINK_ENTITY_TO_CLASS( monster_human_grunt, CHGrunt ) @@ -202,6 +217,7 @@ TYPEDESCRIPTION CHGrunt::m_SaveData[] = //DEFINE_FIELD( CShotgun, m_iBrassShell, FIELD_INTEGER ), //DEFINE_FIELD( CShotgun, m_iShotgunShell, FIELD_INTEGER ), DEFINE_FIELD( CHGrunt, m_iSentence, FIELD_INTEGER ), + DEFINE_FIELD( CHGrunt, m_iGruntFlags, FIELD_INTEGER ), }; IMPLEMENT_SAVERESTORE( CHGrunt, CSquadMonster ) @@ -285,13 +301,37 @@ void CHGrunt::GibMonster( void ) CBaseEntity *pGun; - if( FBitSet( pev->weapons, HGRUNT_SHOTGUN ) ) + if( !IsSnowGrunt() ) { - pGun = DropItem( "weapon_shotgun", vecGunPos, vecGunAngles ); + if( FBitSet( pev->weapons, HGRUNT_SHOTGUN ) ) + { + pGun = DropItem( "weapon_shotgun", vecGunPos, vecGunAngles ); + } + else + { + pGun = DropItem( "weapon_9mmAR", vecGunPos, vecGunAngles ); + } + + if( FBitSet( pev->weapons, HGRUNT_GRENADELAUNCHER ) ) + { + pGun = DropItem( "ammo_ARgrenades", vecGunPos, vecGunAngles ); + if( pGun ) + { + pGun->pev->velocity = Vector( RANDOM_FLOAT( -100, 100 ), RANDOM_FLOAT( -100, 100 ), RANDOM_FLOAT( 200, 300 ) ); + pGun->pev->avelocity = Vector( 0, RANDOM_FLOAT( 200, 400 ), 0 ); + } + } } else { - pGun = DropItem( "weapon_9mmAR", vecGunPos, vecGunAngles ); + if( FBitSet( pev->weapons, HGRUNT_MAC10 ) ) + { + pGun = DropItem( "weapon_mac10", vecGunPos, vecGunAngles ); + } + else + { + pGun = DropItem( "weapon_ak47", vecGunPos, vecGunAngles ); + } } if( pGun ) @@ -299,16 +339,6 @@ void CHGrunt::GibMonster( void ) pGun->pev->velocity = Vector( RANDOM_FLOAT( -100, 100 ), RANDOM_FLOAT( -100, 100 ), RANDOM_FLOAT( 200, 300 ) ); pGun->pev->avelocity = Vector( 0, RANDOM_FLOAT( 200, 400 ), 0 ); } - - if( FBitSet( pev->weapons, HGRUNT_GRENADELAUNCHER ) ) - { - pGun = DropItem( "ammo_ARgrenades", vecGunPos, vecGunAngles ); - if ( pGun ) - { - pGun->pev->velocity = Vector( RANDOM_FLOAT( -100, 100 ), RANDOM_FLOAT( -100, 100 ), RANDOM_FLOAT( 200, 300 ) ); - pGun->pev->avelocity = Vector( 0, RANDOM_FLOAT( 200, 400 ), 0 ); - } - } } CBaseMonster::GibMonster(); @@ -332,6 +362,9 @@ int CHGrunt::ISoundMask( void ) //========================================================= BOOL CHGrunt::FOkToSpeak( void ) { + if( IsCurrentLevelTraining() ) + return FALSE; + // if someone else is talking, don't speak if( gpGlobals->time <= CTalkMonster::g_talkWaitTime ) return FALSE; @@ -785,7 +818,7 @@ Vector CHGrunt::GetGunPosition() //========================================================= // Shoot //========================================================= -void CHGrunt::Shoot( void ) +void CHGrunt::Shoot( Vector vecSpread, int iBulletType ) { if( m_hEnemy == NULL ) { @@ -799,7 +832,7 @@ void CHGrunt::Shoot( void ) Vector vecShellVelocity = gpGlobals->v_right * RANDOM_FLOAT( 40, 90 ) + gpGlobals->v_up * RANDOM_FLOAT( 75, 200 ) + gpGlobals->v_forward * RANDOM_FLOAT( -40, 40 ); EjectBrass( vecShootOrigin - vecShootDir * 24, vecShellVelocity, pev->angles.y, m_iBrassShell, TE_BOUNCE_SHELL ); - FireBullets( 1, vecShootOrigin, vecShootDir, VECTOR_CONE_10DEGREES, 2048, BULLET_MONSTER_MP5 ); // shoot +-5 degrees + FireBullets( 1, vecShootOrigin, vecShootDir, vecSpread, 2048, iBulletType ); // shoot +-5 degrees pev->effects |= EF_MUZZLEFLASH; @@ -836,6 +869,47 @@ void CHGrunt::Shotgun( void ) SetBlending( 0, angDir.x ); } +void CHGrunt::ShootMP5( Vector vecSpread ) +{ + Shoot( vecSpread, BULLET_MONSTER_MP5 ); +} + +void CHGrunt::ShootAK47( Vector vecSpread ) +{ + Shoot( vecSpread, BULLET_MONSTER_AK47 ); + + switch( RANDOM_LONG( 0, 2 ) ) + { + case 0: + EMIT_SOUND( ENT( pev ), CHAN_WEAPON, "weapons/Hks1.wav", 1, ATTN_NORM ); + break; + case 1: + EMIT_SOUND( ENT( pev ), CHAN_WEAPON, "weapons/Hks2.wav", 1, ATTN_NORM ); + break; + case 2: + EMIT_SOUND( ENT( pev ), CHAN_WEAPON, "weapons/Hks3.wav", 1, ATTN_NORM ); + break; + } +} + +void CHGrunt::ShootMac10( Vector vecSpread ) +{ + Shoot( vecSpread, BULLET_MONSTER_MAC10 ); + + switch( RANDOM_LONG( 0, 2 ) ) + { + case 0: + EMIT_SOUND( ENT( pev ), CHAN_WEAPON, "weapons/mac1.wav", 1, ATTN_NORM ); + break; + case 1: + EMIT_SOUND( ENT( pev ), CHAN_WEAPON, "weapons/mac2.wav", 1, ATTN_NORM ); + break; + case 2: + EMIT_SOUND( ENT( pev ), CHAN_WEAPON, "weapons/mac3.wav", 1, ATTN_NORM ); + break; + } +} + //========================================================= // HandleAnimEvent - catches the monster-specific messages // that occur when tagged animation frames are played. @@ -858,18 +932,35 @@ void CHGrunt::HandleAnimEvent( MonsterEvent_t *pEvent ) SetBodygroup( GUN_GROUP, GUN_NONE ); // now spawn a gun. - if( FBitSet( pev->weapons, HGRUNT_SHOTGUN ) ) + + // Regular soldier model. + if( !IsSnowGrunt() ) { - DropItem( "weapon_shotgun", vecGunPos, vecGunAngles ); + // Shotgun. + if( FBitSet( pev->weapons, HGRUNT_SHOTGUN ) ) + { + DropItem( "weapon_shotgun", vecGunPos, vecGunAngles ); + } + else + { + DropItem( "weapon_9mmAR", vecGunPos, vecGunAngles ); + } + if( FBitSet( pev->weapons, HGRUNT_GRENADELAUNCHER ) ) + { + DropItem( "ammo_ARgrenades", BodyTarget( pev->origin ), vecGunAngles ); + } } + // Snow soldier model. else { - DropItem( "weapon_9mmAR", vecGunPos, vecGunAngles ); - } - - if( FBitSet( pev->weapons, HGRUNT_GRENADELAUNCHER ) ) - { - DropItem( "ammo_ARgrenades", BodyTarget( pev->origin ), vecGunAngles ); + if( FBitSet( pev->weapons, HGRUNT_MAC10 ) ) + { + DropItem( "weapon_mac10", vecGunPos, vecGunAngles ); + } + else + { + DropItem( "weapon_ak47", vecGunPos, vecGunAngles ); + } } } break; @@ -908,25 +999,45 @@ void CHGrunt::HandleAnimEvent( MonsterEvent_t *pEvent ) break; case HGRUNT_AE_BURST1: { - if( FBitSet( pev->weapons, HGRUNT_9MMAR ) ) + // Regular soldier model. + if( !IsSnowGrunt() ) { - Shoot(); - - // the first round of the three round burst plays the sound and puts a sound in the world sound list. - if( RANDOM_LONG( 0, 1 ) ) + // MP5 + if( FBitSet( pev->weapons, HGRUNT_9MMAR ) ) { - EMIT_SOUND( ENT( pev ), CHAN_WEAPON, "hgrunt/gr_mgun1.wav", 1, ATTN_NORM ); + ShootMP5( VECTOR_CONE_10DEGREES ); + + // the first round of the three round burst plays the sound and puts a sound in the world sound list. + if( RANDOM_LONG( 0, 1 ) ) + { + EMIT_SOUND( ENT( pev ), CHAN_WEAPON, "hgrunt/gr_mgun1.wav", 1, ATTN_NORM ); + } + else + { + EMIT_SOUND( ENT( pev ), CHAN_WEAPON, "hgrunt/gr_mgun2.wav", 1, ATTN_NORM ); + } } + // Shotgun else { - EMIT_SOUND( ENT( pev ), CHAN_WEAPON, "hgrunt/gr_mgun2.wav", 1, ATTN_NORM ); + Shotgun(); + + EMIT_SOUND( ENT( pev ), CHAN_WEAPON, "weapons/sbarrel1.wav", 1, ATTN_NORM ); } } + // Snow soldier model. else { - Shotgun(); - - EMIT_SOUND( ENT( pev ), CHAN_WEAPON, "weapons/sbarrel1.wav", 1, ATTN_NORM ); + // AK47 + if( FBitSet( pev->weapons, HGRUNT_AK47 ) ) + { + ShootAK47( VECTOR_CONE_10DEGREES ); + } + // Mac10 + else + { + ShootMac10( VECTOR_CONE_10DEGREES ); + } } CSoundEnt::InsertSound( bits_SOUND_COMBAT, pev->origin, 384, 0.3 ); @@ -934,7 +1045,26 @@ void CHGrunt::HandleAnimEvent( MonsterEvent_t *pEvent ) break; case HGRUNT_AE_BURST2: case HGRUNT_AE_BURST3: - Shoot(); + // Regular soldier model. + if( !IsSnowGrunt() ) + { + // MP5 + Shoot( VECTOR_CONE_10DEGREES, BULLET_MONSTER_MP5 ); + } + // Snow soldier model. + else + { + // AK47 + if( FBitSet( pev->weapons, HGRUNT_AK47 ) ) + { + ShootAK47( VECTOR_CONE_10DEGREES ); + } + // Mac10 + else + { + ShootMac10( VECTOR_CONE_10DEGREES ); + } + } break; case HGRUNT_AE_KICK: { @@ -972,7 +1102,19 @@ void CHGrunt::Spawn() { Precache(); - SET_MODEL( ENT( pev ), "models/hgrunt.mdl" ); + char* szModel = (char*)STRING( pev->model ); + if( !szModel || !*szModel ) + { + szModel = "models/hgrunt.mdl"; + pev->model = ALLOC_STRING( szModel ); + } + else if( !FStrEq( szModel, "models/hgrunt.mdl" ) ) + { + szModel = "models/hgruntsnow.mdl"; + pev->model = ALLOC_STRING( szModel ); + } + + SET_MODEL( ENT( pev ), szModel ); UTIL_SetSize( pev, VEC_HUMAN_HULL_MIN, VEC_HUMAN_HULL_MAX ); pev->solid = SOLID_SLIDEBOX; @@ -993,38 +1135,63 @@ void CHGrunt::Spawn() m_HackedGunPos = Vector( 0, 0, 55 ); - if( pev->weapons == 0 ) + m_iGruntFlags = 0; + + // Check to see if this is a regular or snow grunt model. + if( !FStrEq( STRING( pev->model ), "models/hgrunt.mdl" ) ) { - // initialize to original values - pev->weapons = HGRUNT_9MMAR | HGRUNT_HANDGRENADE; - // pev->weapons = HGRUNT_SHOTGUN; - // pev->weapons = HGRUNT_9MMAR | HGRUNT_GRENADELAUNCHER; + m_iGruntFlags |= GF_SNOWGRUNT; } - if( FBitSet( pev->weapons, HGRUNT_SHOTGUN ) ) + // Regular soldier model. + if( !IsSnowGrunt() ) { - SetBodygroup( GUN_GROUP, GUN_SHOTGUN ); - m_cClipSize = 8; + if( pev->weapons == 0 ) + { + // initialize to original values + pev->weapons = HGRUNT_9MMAR | HGRUNT_HANDGRENADE; + } + + if( FBitSet( pev->weapons, HGRUNT_SHOTGUN ) ) + { + SetBodygroup( GUN_GROUP, GUN_SHOTGUN ); + m_cClipSize = 8; + } + else + { + m_cClipSize = 27; + } + + if( FBitSet( pev->weapons, HGRUNT_SHOTGUN ) ) + { + SetBodygroup( HEAD_GROUP, HEAD_SHOTGUN ); + } + else if( FBitSet( pev->weapons, HGRUNT_GRENADELAUNCHER ) ) + { + SetBodygroup( HEAD_GROUP, HEAD_M203 ); + } } + // Snow grunt model. else { - m_cClipSize = GRUNT_CLIP_SIZE; - } - m_cAmmoLoaded = m_cClipSize; + if( pev->weapons == 0 ) + { + // initialize to original values + pev->weapons = HGRUNT_AK47 | HGRUNT_HANDGRENADE; + } - if( RANDOM_LONG( 0, 99 ) < 80 ) - pev->skin = 0; // light skin - else - pev->skin = 1; // dark skin + // Snow grunt weapons do not incorporate grenade launchers. + pev->weapons &= ~HGRUNT_GRENADELAUNCHER; - if( FBitSet( pev->weapons, HGRUNT_SHOTGUN ) ) - { - SetBodygroup( HEAD_GROUP, HEAD_SHOTGUN ); - } - else if( FBitSet( pev->weapons, HGRUNT_GRENADELAUNCHER ) ) - { - SetBodygroup( HEAD_GROUP, HEAD_M203 ); - pev->skin = 1; // alway dark skin + if( FBitSet( pev->weapons, HGRUNT_MAC10 ) ) + { + SetBodygroup( GUN_GROUP, GUN_MAC10 ); + } + + m_cClipSize = 27; + + // Only one arctic head available. + SetBodygroup( HEAD_GROUP, HEAD_ARCTIC ); } CTalkMonster::g_talkWaitTime = 0; @@ -1038,6 +1205,7 @@ void CHGrunt::Spawn() void CHGrunt::Precache() { PRECACHE_MODEL( "models/hgrunt.mdl" ); + PRECACHE_MODEL( "models/hgruntsnow.mdl" ); PRECACHE_SOUND( "hgrunt/gr_mgun1.wav" ); PRECACHE_SOUND( "hgrunt/gr_mgun2.wav" ); @@ -1060,6 +1228,14 @@ void CHGrunt::Precache() PRECACHE_SOUND( "zombie/claw_miss2.wav" );// because we use the basemonster SWIPE animation event + PRECACHE_SOUND( "weapons/Hks1.wav" ); + PRECACHE_SOUND( "weapons/Hks2.wav" ); + PRECACHE_SOUND( "weapons/Hks3.wav" ); + + PRECACHE_SOUND( "weapons/mac1.wav" ); + PRECACHE_SOUND( "weapons/mac2.wav" ); + PRECACHE_SOUND( "weapons/mac3.wav" ); + // get voice pitch if( RANDOM_LONG( 0, 1 ) ) m_voicePitch = 109 + RANDOM_LONG( 0, 7 ); @@ -1855,15 +2031,33 @@ void CHGrunt::SetActivity( Activity NewActivity ) } else { - if( m_fStanding ) + // Regular soldier model. + if( !IsSnowGrunt() ) { - // get aimable sequence - iSequence = LookupSequence( "standing_shotgun" ); + if( m_fStanding ) + { + // get aimable sequence + iSequence = LookupSequence( "standing_shotgun" ); + } + else + { + // get crouching shoot + iSequence = LookupSequence( "crouching_shotgun" ); + } } + // Snow soldier model. else { - // get crouching shoot - iSequence = LookupSequence( "crouching_shotgun" ); + if( m_fStanding ) + { + // get aimable sequence + iSequence = LookupSequence( "standing_mp5" ); + } + else + { + // get crouching shoot + iSequence = LookupSequence( "crouching_mp5" ); + } } } break; @@ -2339,6 +2533,11 @@ Schedule_t *CHGrunt::GetScheduleOfType( int Type ) } } +BOOL CHGrunt::IsSnowGrunt( void ) const +{ + return m_iGruntFlags & GF_SNOWGRUNT; +} + //========================================================= // CHGruntRepel - when triggered, spawns a monster_human_grunt // repelling down a line. diff --git a/dlls/items.cpp b/dlls/items.cpp index d9cc7871..a5526eb8 100644 --- a/dlls/items.cpp +++ b/dlls/items.cpp @@ -187,11 +187,6 @@ class CItemSuit : public CItem if( pPlayer->pev->weapons & ( 1<spawnflags & SF_SUIT_SHORTLOGON ) - EMIT_SOUND_SUIT( pPlayer->edict(), "!HEV_A0" ); // short version of suit logon, - else - EMIT_SOUND_SUIT( pPlayer->edict(), "!HEV_AAx" ); // long version of suit logon - pPlayer->pev->weapons |= ( 1 << WEAPON_SUIT ); return TRUE; } diff --git a/dlls/mp5.cpp b/dlls/mp5.cpp index 7d05d5e1..1447c700 100644 --- a/dlls/mp5.cpp +++ b/dlls/mp5.cpp @@ -54,6 +54,10 @@ void CMP5::Spawn() m_iDefaultAmmo = MP5_DEFAULT_GIVE; + m_fSpotActive = 1; +#ifndef CLIENT_DLL + m_pSpot = NULL; +#endif FallInit();// get ready to fall down. } @@ -84,6 +88,8 @@ void CMP5::Precache( void ) m_usMP5 = PRECACHE_EVENT( 1, "events/mp5.sc" ); m_usMP52 = PRECACHE_EVENT( 1, "events/mp52.sc" ); + + UTIL_PrecacheOther( "laser_spot" ); } int CMP5::GetItemInfo( ItemInfo *p ) @@ -117,7 +123,29 @@ int CMP5::AddToPlayer( CBasePlayer *pPlayer ) BOOL CMP5::Deploy() { - return DefaultDeploy( "models/v_9mmAR.mdl", "models/p_9mmAR.mdl", MP5_DEPLOY, "mp5" ); + BOOL bResult = DefaultDeploy( "models/v_9mmAR.mdl", "models/p_9mmAR.mdl", MP5_DEPLOY, "mp5" ); + + if( bResult ) + { + m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 1; + } + + return bResult; +} + +void CMP5::Holster( int skiplocal /*= 0*/ ) +{ + m_fInReload = FALSE;// cancel any reload in progress. + + m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.5; + +#ifndef CLIENT_DLL + if( m_pSpot ) + { + m_pSpot->Killed( NULL, GIB_NEVER ); + m_pSpot = NULL; + } +#endif } void CMP5::PrimaryAttack() @@ -150,21 +178,22 @@ void CMP5::PrimaryAttack() Vector vecSrc = m_pPlayer->GetGunPosition(); Vector vecAiming = m_pPlayer->GetAutoaimVector( AUTOAIM_5DEGREES ); Vector vecDir; -#ifdef CLIENT_DLL - if( !bIsMultiplayer() ) -#else - if( !g_pGameRules->IsMultiplayer() ) -#endif + + Vector vecSpread; + + // Allow for higher accuracy when the player is crouching. + if( m_pPlayer->pev->flags & FL_DUCKING ) { - // optimized multiplayer. Widened to make it easier to hit a moving player - vecDir = m_pPlayer->FireBulletsPlayer( 1, vecSrc, vecAiming, VECTOR_CONE_6DEGREES, 8192, BULLET_PLAYER_MP5, 2, 0, m_pPlayer->pev, m_pPlayer->random_seed ); + vecSpread = VECTOR_CONE_1DEGREES; } else { - // single player spread - vecDir = m_pPlayer->FireBulletsPlayer( 1, vecSrc, vecAiming, VECTOR_CONE_3DEGREES, 8192, BULLET_PLAYER_MP5, 2, 0, m_pPlayer->pev, m_pPlayer->random_seed ); + vecSpread = VECTOR_CONE_3DEGREES; } + // single player spread + vecDir = m_pPlayer->FireBulletsPlayer( 1, vecSrc, vecAiming, vecSpread, 8192, BULLET_PLAYER_MP5, 2, 0, m_pPlayer->pev, m_pPlayer->random_seed ); + int flags; #if defined( CLIENT_WEAPONS ) flags = FEV_NOTHOST; @@ -183,6 +212,8 @@ void CMP5::PrimaryAttack() m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.1; m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + UTIL_SharedRandomFloat( m_pPlayer->random_seed, 10, 15 ); + + UpdateSpot(); } void CMP5::SecondaryAttack( void ) @@ -234,6 +265,13 @@ void CMP5::SecondaryAttack( void ) if( !m_pPlayer->m_rgAmmo[m_iSecondaryAmmoType] ) // HEV suit - indicate out of ammo condition m_pPlayer->SetSuitUpdate( "!HEV_AMO0", FALSE, 0 ); + +#ifndef CLIENT_DLL + if( m_pSpot && m_fSpotActive ) + { + m_pSpot->Suspend( 1 ); + } +#endif } void CMP5::Reload( void ) @@ -241,11 +279,24 @@ void CMP5::Reload( void ) if( m_pPlayer->ammo_9mm <= 0 ) return; - DefaultReload( MP5_MAX_CLIP, MP5_RELOAD, 1.5 ); + int iResult = DefaultReload( MP5_MAX_CLIP, MP5_RELOAD, 3.0 ); + + if( iResult ) + { +#ifndef CLIENT_DLL + if( m_pSpot && m_fSpotActive ) + { + m_pSpot->Suspend( 3.0 ); + m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 3.0; + } +#endif + } } void CMP5::WeaponIdle( void ) { + UpdateSpot(); + ResetEmptySound(); m_pPlayer->GetAutoaimVector( AUTOAIM_5DEGREES ); @@ -270,6 +321,29 @@ void CMP5::WeaponIdle( void ) m_flTimeWeaponIdle = UTIL_SharedRandomFloat( m_pPlayer->random_seed, 10, 15 ); // how long till we do this again. } +void CMP5::UpdateSpot( void ) +{ +#ifndef CLIENT_DLL + if( m_fSpotActive ) + { + if( !m_pSpot ) + { + m_pSpot = CLaserSpot::CreateSpot(); + m_pSpot->pev->scale = 0.5; + } + + UTIL_MakeVectors( m_pPlayer->pev->v_angle ); + Vector vecSrc = m_pPlayer->GetGunPosition();; + Vector vecAiming = gpGlobals->v_forward; + + TraceResult tr; + UTIL_TraceLine( vecSrc, vecSrc + vecAiming * 8192, dont_ignore_monsters, ENT( m_pPlayer->pev ), &tr ); + + UTIL_SetOrigin( m_pSpot->pev, tr.vecEndPos ); + } +#endif +} + class CMP5AmmoClip : public CBasePlayerAmmo { void Spawn( void ) diff --git a/dlls/player.cpp b/dlls/player.cpp index 2f097072..b551b94f 100644 --- a/dlls/player.cpp +++ b/dlls/player.cpp @@ -408,6 +408,45 @@ void CBasePlayer::TraceAttack( entvars_t *pevAttacker, float flDamage, Vector ve SpawnBlood( ptr->vecEndPos, BloodColor(), flDamage );// a little surface blood. TraceBleed( flDamage, vecDir, ptr, bitsDamageType ); AddMultiDamage( pevAttacker, this, flDamage, bitsDamageType ); + + if( bitsDamageType & ( DMG_BLAST | DMG_SHOCK | DMG_SONIC | DMG_ENERGYBEAM ) ) + { + float flRand = RANDOM_FLOAT( 0, 1 ); + + // Blast damage always trigger pain sounds. + if( bitsDamageType & DMG_BLAST ) + flRand = 0; + + // + // 25% chances playing damage location based pain sound. + // + if( flRand <= 0.25 ) + { + switch( ptr->iHitgroup ) + { + case HITGROUP_HEAD: + EMIT_SOUND( ENT( pev ), CHAN_VOICE, "player/pain/pain_head.wav", 1, ATTN_NORM ); + break; + case HITGROUP_CHEST: + EMIT_SOUND( ENT( pev ), CHAN_VOICE, "player/pain/pain_chest.wav", 1, ATTN_NORM ); + break; + case HITGROUP_STOMACH: + EMIT_SOUND( ENT( pev ), CHAN_VOICE, "player/pain/pain_stomach.wav", 1, ATTN_NORM ); + break; + case HITGROUP_LEFTARM: + case HITGROUP_RIGHTARM: + EMIT_SOUND( ENT( pev ), CHAN_VOICE, "player/pain/pain_arm.wav", 1, ATTN_NORM ); + break; + case HITGROUP_LEFTLEG: + case HITGROUP_RIGHTLEG: + EMIT_SOUND( ENT( pev ), CHAN_VOICE, "player/pain/pain_leg.wav", 1, ATTN_NORM ); + break; + default: + EMIT_SOUND( ENT( pev ), CHAN_VOICE, "player/pain/spout.wav", 1, ATTN_NORM ); + break; + } + } + } } } @@ -421,6 +460,18 @@ void CBasePlayer::TraceAttack( entvars_t *pevAttacker, float flDamage, Vector ve #define ARMOR_RATIO 0.2 // Armor Takes 80% of the damage #define ARMOR_BONUS 0.5 // Each Point of Armor is work 1/x points of health +// Damage values for determine the amount of fade to apply. +#define DAMAGE_FADE_MIN 0 +#define DAMAGE_FADE_MAX 100 + +// Alpha value for damage hold. +#define DAMAGE_ALPHA_MIN 20 +#define DAMAGE_ALPHA_MAX 255 + +// Amount of time to hold fade effect. +#define DAMAGE_HOLD_MIN 0.5 +#define DAMAGE_HOLD_MAX 0.8 + int CBasePlayer::TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType ) { // have suit diagnose the problem - ie: report damage type @@ -482,6 +533,56 @@ int CBasePlayer::TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, fl flDamage = flNew; } + // Fade the screen. + if( flDamage > DAMAGE_FADE_MIN && !( bitsDamageType & ( DMG_DROWN ) ) ) + { + // ALERT( at_console, "Damage: %f\n", flDamage ); + + // if the damage amount is superior to our health, + // completely fade the screen. + if( flDamage >= pev->health ) + { + UTIL_ScreenFade( this, Vector( 128, 0, 0 ), 0.8f, 0, 255, FFADE_IN ); + } + else + { + float flDmg = flDamage; + + // Clamp damage fade amount. + if( flDmg > DAMAGE_FADE_MAX ) + flDmg = DAMAGE_FADE_MAX; + + // ALERT( at_console, "Resulting Damage: %f\n", flDmg ); + + // Calculate fade hold based on damage amount. + float fadehold; + fadehold = DAMAGE_HOLD_MIN + ( ( flDmg * ( DAMAGE_HOLD_MAX - DAMAGE_HOLD_MIN ) ) / DAMAGE_FADE_MAX ); + + // Clamp final fade hold value. + if( fadehold < DAMAGE_HOLD_MIN ) + fadehold = DAMAGE_HOLD_MIN; + else if( fadehold > DAMAGE_HOLD_MAX ) + fadehold = DAMAGE_HOLD_MAX; + + // ALERT( at_console, "Resulting fadehold: %f\n", fadehold ); + + // Calculate alpha based on damage amount. + int alpha; + alpha = DAMAGE_ALPHA_MIN + ( ( flDmg * ( DAMAGE_ALPHA_MAX - DAMAGE_ALPHA_MIN ) ) / DAMAGE_FADE_MAX ); + + // Clamp final alpha value. + if( alpha < DAMAGE_ALPHA_MIN ) + alpha = DAMAGE_ALPHA_MIN; + else if( alpha > DAMAGE_ALPHA_MAX ) + alpha = DAMAGE_ALPHA_MAX; + + // ALERT( at_console, "Resulting alpha: %d\n", alpha ); + + // Send screen fade. + UTIL_ScreenFade( this, Vector( 128, 0, 0 ), 0.8f, fadehold, alpha, FFADE_IN ); + } + } + // this cast to INT is critical!!! If a player ends up with 0.5 health, the engine will get that // as an int (zero) and think the player is dead! (this will incite a clientside screentilt, etc) fTookDamage = CBaseMonster::TakeDamage( pevInflictor, pevAttacker, (int)flDamage, bitsDamageType ); @@ -890,7 +991,7 @@ void CBasePlayer::Killed( entvars_t *pevAttacker, int iGib ) MESSAGE_END(); // UNDONE: Put this in, but add FFADE_PERMANENT and make fade time 8.8 instead of 4.12 - // UTIL_ScreenFade( edict(), Vector( 128, 0, 0 ), 6, 15, 255, FFADE_OUT | FFADE_MODULATE ); + UTIL_ScreenFade( this, Vector(128, 0, 0), 12, 15, 192, FFADE_OUT | FFADE_STAYOUT ); if( ( pev->health < -40 && iGib != GIB_NEVER ) || iGib == GIB_ALWAYS ) { @@ -1092,6 +1193,8 @@ void CBasePlayer::TabulateAmmo() ammo_rockets = AmmoInventory( GetAmmoIndex( "rockets" ) ); ammo_uranium = AmmoInventory( GetAmmoIndex( "uranium" ) ); ammo_hornets = AmmoInventory( GetAmmoIndex( "Hornets" ) ); + ammo_ak47 = AmmoInventory( GetAmmoIndex( "ak47" ) ); + ammo_mac10 = AmmoInventory( GetAmmoIndex( "mac10" ) ); } /* @@ -2194,76 +2297,6 @@ void CBasePlayer::SetSuitUpdate( char *name, int fgroup, int iNoRepeatTime ) // due to static channel design, etc. We don't play HEV sounds in multiplayer right now. return; } - - // if name == NULL, then clear out the queue - if( !name ) - { - for( i = 0; i < CSUITPLAYLIST; i++ ) - m_rgSuitPlayList[i] = 0; - return; - } - - // get sentence or group number - if( !fgroup ) - { - isentence = SENTENCEG_Lookup( name, NULL ); - if( isentence < 0 ) - return; - } - else - // mark group number as negative - isentence = -SENTENCEG_GetIndex( name ); - - // check norepeat list - this list lets us cancel - // the playback of words or sentences that have already - // been played within a certain time. - for( i = 0; i < CSUITNOREPEAT; i++ ) - { - if( isentence == m_rgiSuitNoRepeat[i] ) - { - // this sentence or group is already in - // the norepeat list - if( m_rgflSuitNoRepeatTime[i] < gpGlobals->time ) - { - // norepeat time has expired, clear it out - m_rgiSuitNoRepeat[i] = 0; - m_rgflSuitNoRepeatTime[i] = 0.0; - iempty = i; - break; - } - else - { - // don't play, still marked as norepeat - return; - } - } - // keep track of empty slot - if( !m_rgiSuitNoRepeat[i] ) - iempty = i; - } - - // sentence is not in norepeat list, save if norepeat time was given - if( iNoRepeatTime ) - { - if( iempty < 0 ) - iempty = RANDOM_LONG( 0, CSUITNOREPEAT - 1 ); // pick random slot to take over - m_rgiSuitNoRepeat[iempty] = isentence; - m_rgflSuitNoRepeatTime[iempty] = iNoRepeatTime + gpGlobals->time; - } - - // find empty spot in queue, or overwrite last spot - m_rgSuitPlayList[m_iSuitPlayNext++] = isentence; - if( m_iSuitPlayNext == CSUITPLAYLIST ) - m_iSuitPlayNext = 0; - - if( m_flSuitUpdate <= gpGlobals->time ) - { - if( m_flSuitUpdate == 0 ) - // play queue is empty, don't delay too long before playback - m_flSuitUpdate = gpGlobals->time + SUITFIRSTUPDATETIME; - else - m_flSuitUpdate = gpGlobals->time + SUITUPDATETIME; - } } /* @@ -3345,7 +3378,6 @@ void CBasePlayer::CheatImpulseCommands( int iImpulse ) } break; case 101: - gEvilImpulse101 = TRUE; GiveNamedItem( "item_suit" ); GiveNamedItem( "item_battery" ); GiveNamedItem( "weapon_crowbar" ); @@ -3358,20 +3390,18 @@ void CBasePlayer::CheatImpulseCommands( int iImpulse ) GiveNamedItem( "ammo_ARgrenades" ); GiveNamedItem( "weapon_handgrenade" ); GiveNamedItem( "weapon_tripmine" ); -#ifndef OEM_BUILD - GiveNamedItem( "weapon_357" ); - GiveNamedItem( "ammo_357" ); GiveNamedItem( "weapon_crossbow" ); GiveNamedItem( "ammo_crossbow" ); - GiveNamedItem( "weapon_egon" ); - GiveNamedItem( "weapon_gauss" ); - GiveNamedItem( "ammo_gaussclip" ); GiveNamedItem( "weapon_rpg" ); GiveNamedItem( "ammo_rpgclip" ); GiveNamedItem( "weapon_satchel" ); GiveNamedItem( "weapon_snark" ); - GiveNamedItem( "weapon_hornetgun" ); -#endif + + GiveNamedItem( "weapon_ak47" ); + GiveNamedItem( "ammo_ak47" ); + GiveNamedItem( "weapon_mac10" ); + GiveNamedItem( "ammo_mac10" ); + gEvilImpulse101 = FALSE; break; case 102: diff --git a/dlls/skill.h b/dlls/skill.h index 5e784bed..46bbdc59 100644 --- a/dlls/skill.h +++ b/dlls/skill.h @@ -133,6 +133,18 @@ struct skilldata_t float plrStomach; float plrLeg; float plrArm; + + float diabloHealth; + float diabloDmgOneSlash; + float diabloDmgBothSlash; + + float hassaultHealth; + + float plrDmgAK47; + float plrDmgMac10; + + float monDmgHvmg; + float monDmgMac10; }; extern DLL_GLOBAL skilldata_t gSkillData; diff --git a/dlls/weapons.cpp b/dlls/weapons.cpp index 3e2ef386..9bc47513 100644 --- a/dlls/weapons.cpp +++ b/dlls/weapons.cpp @@ -169,6 +169,12 @@ void DecalGunshot( TraceResult *pTrace, int iBulletType ) case BULLET_MONSTER_MP5: case BULLET_PLAYER_BUCKSHOT: case BULLET_PLAYER_357: + case BULLET_PLAYER_AK47: + case BULLET_MONSTER_AK47: + case BULLET_MONSTER_HVMG: + case BULLET_PLAYER_MAC10: + case BULLET_MONSTER_MAC10: + case BULLET_PLAYER_SNIPER: default: // smoke and decal UTIL_GunshotDecalTrace( pTrace, DamageDecal( pEntity, DMG_BULLET ) ); @@ -316,15 +322,6 @@ void W_Precache( void ) UTIL_PrecacheOther( "ammo_9mmAR" ); UTIL_PrecacheOther( "ammo_ARgrenades" ); -#if !defined( OEM_BUILD ) && !defined( HLDEMO_BUILD ) - // python - UTIL_PrecacheOtherWeapon( "weapon_357" ); - UTIL_PrecacheOther( "ammo_357" ); - - // gauss - UTIL_PrecacheOtherWeapon( "weapon_gauss" ); - UTIL_PrecacheOther( "ammo_gaussclip" ); - // rpg UTIL_PrecacheOtherWeapon( "weapon_rpg" ); UTIL_PrecacheOther( "ammo_rpgclip" ); @@ -333,24 +330,27 @@ void W_Precache( void ) UTIL_PrecacheOtherWeapon( "weapon_crossbow" ); UTIL_PrecacheOther( "ammo_crossbow" ); - // egon - UTIL_PrecacheOtherWeapon( "weapon_egon" ); -#endif // tripmine UTIL_PrecacheOtherWeapon( "weapon_tripmine" ); -#if !defined( OEM_BUILD ) && !defined( HLDEMO_BUILD ) + // satchel charge UTIL_PrecacheOtherWeapon( "weapon_satchel" ); -#endif + // hand grenade - UTIL_PrecacheOtherWeapon("weapon_handgrenade"); -#if !defined( OEM_BUILD ) && !defined( HLDEMO_BUILD ) + UTIL_PrecacheOtherWeapon( "weapon_handgrenade" ); + // squeak grenade UTIL_PrecacheOtherWeapon( "weapon_snark" ); - // hornetgun - UTIL_PrecacheOtherWeapon( "weapon_hornetgun" ); + // AK47 + UTIL_PrecacheOtherWeapon( "weapon_ak47" ); + UTIL_PrecacheOther( "ammo_ak47" ); + + // Mac10 + UTIL_PrecacheOtherWeapon( "weapon_mac10" ); + UTIL_PrecacheOther( "ammo_mac10" ); +#if !defined( OEM_BUILD ) && !defined( HLDEMO_BUILD ) if( g_pGameRules->IsDeathmatch() ) { UTIL_PrecacheOther( "weaponbox" );// container for dropped deathmatch weapons @@ -366,6 +366,9 @@ void W_Precache( void ) g_sModelIndexLaser = PRECACHE_MODEL( (char *)g_pModelNameLaser ); g_sModelIndexLaserDot = PRECACHE_MODEL( "sprites/laserdot.spr" ); + PRECACHE_MODEL( "sprites/wallsmoke.spr" ); + PRECACHE_MODEL( "sprites/groundsmoke.spr" ); + // used by explosions PRECACHE_MODEL( "models/grenade.mdl" ); PRECACHE_MODEL( "sprites/explode1.spr" ); @@ -1496,34 +1499,16 @@ TYPEDESCRIPTION CShotgun::m_SaveData[] = IMPLEMENT_SAVERESTORE( CShotgun, CBasePlayerWeapon ) -TYPEDESCRIPTION CGauss::m_SaveData[] = -{ - DEFINE_FIELD( CGauss, m_fInAttack, FIELD_INTEGER ), - //DEFINE_FIELD( CGauss, m_flStartCharge, FIELD_TIME ), - //DEFINE_FIELD( CGauss, m_flPlayAftershock, FIELD_TIME ), - //DEFINE_FIELD( CGauss, m_flNextAmmoBurn, FIELD_TIME ), - DEFINE_FIELD( CGauss, m_fPrimaryFire, FIELD_BOOLEAN ), -}; - -IMPLEMENT_SAVERESTORE( CGauss, CBasePlayerWeapon ) - -TYPEDESCRIPTION CEgon::m_SaveData[] = +TYPEDESCRIPTION CSatchel::m_SaveData[] = { - //DEFINE_FIELD( CEgon, m_pBeam, FIELD_CLASSPTR ), - //DEFINE_FIELD( CEgon, m_pNoise, FIELD_CLASSPTR ), - //DEFINE_FIELD( CEgon, m_pSprite, FIELD_CLASSPTR ), - DEFINE_FIELD( CEgon, m_shootTime, FIELD_TIME ), - DEFINE_FIELD( CEgon, m_fireState, FIELD_INTEGER ), - DEFINE_FIELD( CEgon, m_fireMode, FIELD_INTEGER ), - DEFINE_FIELD( CEgon, m_shakeTime, FIELD_TIME ), - DEFINE_FIELD( CEgon, m_flAmmoUseTime, FIELD_TIME ), + DEFINE_FIELD( CSatchel, m_chargeReady, FIELD_INTEGER ), }; -IMPLEMENT_SAVERESTORE( CEgon, CBasePlayerWeapon ) +IMPLEMENT_SAVERESTORE( CSatchel, CBasePlayerWeapon ) -TYPEDESCRIPTION CSatchel::m_SaveData[] = +TYPEDESCRIPTION CMP5::m_SaveData[] = { - DEFINE_FIELD( CSatchel, m_chargeReady, FIELD_INTEGER ), + DEFINE_FIELD( CMP5, m_fSpotActive, FIELD_INTEGER ), }; -IMPLEMENT_SAVERESTORE( CSatchel, CBasePlayerWeapon ) +IMPLEMENT_SAVERESTORE( CMP5, CBasePlayerWeapon ); diff --git a/dlls/weapons.h b/dlls/weapons.h index 5112254a..ad573491 100644 --- a/dlls/weapons.h +++ b/dlls/weapons.h @@ -61,22 +61,19 @@ public: #define ITEM_SECURITY 3 #define ITEM_BATTERY 4 -#define WEAPON_NONE 0 +#define WEAPON_NONE 0 #define WEAPON_CROWBAR 1 #define WEAPON_GLOCK 2 -#define WEAPON_PYTHON 3 -#define WEAPON_MP5 4 -#define WEAPON_CHAINGUN 5 -#define WEAPON_CROSSBOW 6 -#define WEAPON_SHOTGUN 7 -#define WEAPON_RPG 8 -#define WEAPON_GAUSS 9 -#define WEAPON_EGON 10 -#define WEAPON_HORNETGUN 11 -#define WEAPON_HANDGRENADE 12 -#define WEAPON_TRIPMINE 13 -#define WEAPON_SATCHEL 14 -#define WEAPON_SNARK 15 +#define WEAPON_MP5 3 +#define WEAPON_CROSSBOW 4 +#define WEAPON_SHOTGUN 5 +#define WEAPON_RPG 6 +#define WEAPON_HANDGRENADE 7 +#define WEAPON_TRIPMINE 8 +#define WEAPON_SATCHEL 9 +#define WEAPON_SNARK 10 +#define WEAPON_MAC10 11 +#define WEAPON_AK47 12 #define WEAPON_ALLWEAPONS (~(1<