Merge @malortie's patches for "They Hunger".

This commit is contained in:
Night Owl 2016-10-09 04:07:37 +05:00
parent 21317e7da3
commit c6916f1ec2
81 changed files with 9135 additions and 1077 deletions

100
cl_dll/Hunger/zoom.cpp Normal file
View File

@ -0,0 +1,100 @@
/***
*
* Copyright (c) 1996-2002, 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 "hud.h"
#include "cl_util.h"
#include "parsemsg.h"
#include "ammohistory.h"
#include <string.h>
#include <stdio.h>
DECLARE_MESSAGE(m_Zoom, Zoom)
int CHudZoom::Init(void)
{
m_fOn = 0;
m_pWeapon = NULL;
HOOK_MESSAGE(Zoom);
m_iFlags |= HUD_ACTIVE;
gHUD.AddHudElem(this);
return 1;
};
void CHudZoom::Reset(void)
{
m_fOn = 0;
}
int CHudZoom::VidInit(void)
{
m_pWeapon = NULL;
return 1;
};
int CHudZoom::MsgFunc_Zoom(const char *pszName, int iSize, void *pbuf)
{
int iId;
BEGIN_READ(pbuf, iSize);
m_fOn = READ_BYTE();
iId = READ_BYTE();
WEAPON* pWeapon = gWR.GetWeapon(iId);
if (pWeapon)
{
m_pWeapon = pWeapon;
}
return 1;
}
int CHudZoom::Draw(float flTime)
{
if (gHUD.m_iHideHUDDisplay & HIDEHUD_ALL)
return 1;
if (!m_fOn)
{
if (m_pWeapon)
{
SetCrosshair(m_pWeapon->hCrosshair, m_pWeapon->rcCrosshair, 255, 0, 0);
}
}
else
{
int r, g, b, a;
r = b = 0;
g = 128;
a = 192;
ScaleColors(r, g, b, a);
FillRGBA(0, 0, ScreenWidth, ScreenHeight, r, g, b, a);
if (m_pWeapon)
{
SetCrosshair(m_pWeapon->hZoomedCrosshair, m_pWeapon->rcZoomedCrosshair, 255, 0, 0);
}
}
return 1;
}

View File

@ -28,6 +28,8 @@
#include "ammohistory.h"
extern bool bIsMultiplayer( void );
WEAPON *gpActiveSel; // NULL means off, 1 means just the menu bar, otherwise
// this points to the active weapon menu item
WEAPON *gpLastSel; // Last weapon menu selection
@ -542,8 +544,17 @@ int CHudAmmo::MsgFunc_HideWeapon( const char *pszName, int iSize, void *pbuf )
}
else
{
if ( m_pWeapon )
SetCrosshair( m_pWeapon->hCrosshair, m_pWeapon->rcCrosshair, 255, 255, 255 );
if( m_pWeapon )
{
if( bIsMultiplayer() )
{
SetCrosshair( m_pWeapon->hCrosshair, m_pWeapon->rcCrosshair, 255, 255, 255 );
}
else
{
SetCrosshair( m_pWeapon->hCrosshair, m_pWeapon->rcCrosshair, 255, 0, 0 );
}
}
}
return 1;
@ -608,18 +619,53 @@ int CHudAmmo::MsgFunc_CurWeapon( const char *pszName, int iSize, void *pbuf )
{
// normal crosshairs
if( fOnTarget && m_pWeapon->hAutoaim )
SetCrosshair( m_pWeapon->hAutoaim, m_pWeapon->rcAutoaim, 255, 255, 255 );
{
if( bIsMultiplayer() )
{
SetCrosshair( m_pWeapon->hAutoaim, m_pWeapon->rcAutoaim, 255, 255, 255 );
}
else
{
SetCrosshair( m_pWeapon->hAutoaim, m_pWeapon->rcAutoaim, 255, 0, 0 );
}
}
else
SetCrosshair( m_pWeapon->hCrosshair, m_pWeapon->rcCrosshair, 255, 255, 255 );
{
if( bIsMultiplayer() )
{
SetCrosshair( m_pWeapon->hCrosshair, m_pWeapon->rcCrosshair, 255, 255, 255 );
}
else
{
SetCrosshair( m_pWeapon->hCrosshair, m_pWeapon->rcCrosshair, 255, 0, 0 );
}
}
}
else
{
// zoomed crosshairs
if( fOnTarget && m_pWeapon->hZoomedAutoaim )
SetCrosshair( m_pWeapon->hZoomedAutoaim, m_pWeapon->rcZoomedAutoaim, 255, 255, 255 );
{
if( bIsMultiplayer() )
{
SetCrosshair( m_pWeapon->hZoomedAutoaim, m_pWeapon->rcZoomedAutoaim, 255, 255, 255);
}
else
{
SetCrosshair( m_pWeapon->hZoomedAutoaim, m_pWeapon->rcZoomedAutoaim, 255, 0, 0);
}
}
else
SetCrosshair( m_pWeapon->hZoomedCrosshair, m_pWeapon->rcZoomedCrosshair, 255, 255, 255 );
{
if( bIsMultiplayer() )
{
SetCrosshair( m_pWeapon->hZoomedCrosshair, m_pWeapon->rcZoomedCrosshair, 255, 255, 255 );
}
else
{
SetCrosshair( m_pWeapon->hZoomedCrosshair, m_pWeapon->rcZoomedCrosshair, 255, 0, 0 );
}
}
}
m_fFade = 200.0f; //!!!
@ -859,7 +905,14 @@ int CHudAmmo::Draw( float flTime )
if( m_fFade > 0 )
m_fFade -= ( gHUD.m_flTimeDelta * 20 );
UnpackRGB( r, g, b, RGB_YELLOWISH );
if( bIsMultiplayer() )
{
UnpackRGB( r, g, b, RGB_YELLOWISH );
}
else
{
UnpackRGB( r, g, b, RGB_REDISH );
}
ScaleColors( r, g, b, a );
@ -887,7 +940,14 @@ int CHudAmmo::Draw( float flTime )
x += AmmoWidth / 2;
UnpackRGB( r,g,b, RGB_YELLOWISH );
if( bIsMultiplayer() )
{
UnpackRGB( r, g, b, RGB_YELLOWISH );
}
else
{
UnpackRGB( r, g, b, RGB_REDISH );
}
// draw the | bar
FillRGBA( x, y, iBarWidth, gHUD.m_iFontHeight, r, g, b, a );
@ -957,7 +1017,7 @@ int DrawBar( int x, int y, int width, int height, float f )
width -= w;
}
UnpackRGB( r, g, b, RGB_YELLOWISH );
UnpackRGB( r, g, b, RGB_REDISH );
FillRGBA( x, y, width, height, r, g, b, 128 );

View File

@ -71,63 +71,5 @@ int CHudBattery::MsgFunc_Battery( const char *pszName, int iSize, void *pbuf )
int CHudBattery::Draw( float flTime )
{
if( gHUD.m_iHideHUDDisplay & HIDEHUD_HEALTH )
return 1;
int r, g, b, x, y, a;
wrect_t rc;
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
UnpackRGB( r, g, b, RGB_YELLOWISH );
if( !( gHUD.m_iWeaponBits & ( 1 << ( WEAPON_SUIT ) ) ) )
return 1;
// Has health changed? Flash the health #
if( m_fFade )
{
if( m_fFade > FADE_TIME )
m_fFade = FADE_TIME;
m_fFade -= ( gHUD.m_flTimeDelta * 20 );
if( m_fFade <= 0 )
{
a = 128;
m_fFade = 0;
}
// Fade the health number back to dim
a = MIN_ALPHA + ( m_fFade / FADE_TIME ) * 128;
}
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 );
}
x += ( m_prc1->right - m_prc1->left );
x = gHUD.DrawHudNumber( x, y, DHN_3DIGITS | DHN_DRAWZERO, m_iBat, r, g, b );
return 1;
}

View File

@ -70,6 +70,16 @@ 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_Shovel( struct event_args_s *args );
void EV_Spanner( struct event_args_s *args );
void EV_Medkit( struct event_args_s *args );
void EV_FireAP9( struct event_args_s *args );
void EV_FireChaingun1( struct event_args_s *args );
void EV_FireChaingun2( struct event_args_s *args );
void EV_FireSniper( struct event_args_s *args );
void EV_FireSniper2( struct event_args_s *args );
void EV_FireTaurus( struct event_args_s *args );
}
#define VECTOR_CONE_1DEGREES Vector( 0.00873, 0.00873, 0.00873 )
@ -317,6 +327,10 @@ void EV_HLDM_DecalGunshot( pmtrace_t *pTrace, int iBulletType )
case BULLET_MONSTER_MP5:
case BULLET_PLAYER_BUCKSHOT:
case BULLET_PLAYER_357:
case BULLET_PLAYER_AP9:
case BULLET_PLAYER_CHAINGUN:
case BULLET_PLAYER_SNIPER:
case BULLET_PLAYER_TAURUS:
default:
// smoke and decal
EV_HLDM_GunshotDecalTrace( pTrace, EV_HLDM_DamageDecal( pe ) );
@ -448,6 +462,21 @@ void EV_HLDM_FireBullets( int idx, float *forward, float *right, float *up, int
EV_HLDM_PlayTextureSound( idx, &tr, vecSrc, vecEnd, iBulletType );
EV_HLDM_DecalGunshot( &tr, iBulletType );
break;
case BULLET_PLAYER_AP9:
EV_HLDM_PlayTextureSound( idx, &tr, vecSrc, vecEnd, iBulletType );
EV_HLDM_DecalGunshot( &tr, iBulletType );
break;
case BULLET_PLAYER_CHAINGUN:
EV_HLDM_DecalGunshot( &tr, iBulletType );
break;
case BULLET_PLAYER_SNIPER:
EV_HLDM_PlayTextureSound( idx, &tr, vecSrc, vecEnd, iBulletType );
EV_HLDM_DecalGunshot( &tr, iBulletType );
break;
case BULLET_PLAYER_TAURUS:
EV_HLDM_PlayTextureSound( idx, &tr, vecSrc, vecEnd, iBulletType );
EV_HLDM_DecalGunshot( &tr, iBulletType );
break;
}
}
@ -464,7 +493,9 @@ void EV_FireGlock1( event_args_t *args )
vec3_t origin;
vec3_t angles;
vec3_t velocity;
int body;
int empty;
int silencerOn;
vec3_t ShellVelocity;
vec3_t ShellOrigin;
@ -477,24 +508,44 @@ void EV_FireGlock1( event_args_t *args )
VectorCopy( args->angles, angles );
VectorCopy( args->velocity, velocity );
body = args->iparam1;
empty = args->bparam1;
silencerOn = args->bparam2;
AngleVectors( angles, forward, right, up );
shell = gEngfuncs.pEventAPI->EV_FindModelIndex( "models/shell.mdl" );// brass shell
if( EV_IsLocal( idx ) )
{
EV_MuzzleFlash();
gEngfuncs.pEventAPI->EV_WeaponAnimation( empty ? GLOCK_SHOOT_EMPTY : GLOCK_SHOOT, 2 );
if( !silencerOn )
EV_MuzzleFlash();
gEngfuncs.pEventAPI->EV_WeaponAnimation( empty ? GLOCK_SHOOT_EMPTY : GLOCK_SHOOT, body );
V_PunchAxis( 0, -2.0 );
}
EV_GetDefaultShellInfo( args, origin, velocity, ShellVelocity, ShellOrigin, forward, right, up, 20, -12, 4 );
EV_EjectBrass( ShellOrigin, ShellVelocity, angles[YAW], shell, TE_BOUNCE_SHELL );
EV_EjectBrass( ShellOrigin, ShellVelocity, angles[ YAW ], shell, TE_BOUNCE_SHELL );
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/pl_gun3.wav", gEngfuncs.pfnRandomFloat( 0.92, 1.0 ), ATTN_NORM, 0, 98 + gEngfuncs.pfnRandomLong( 0, 3 ) );
if( !silencerOn )
{
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/pl_gun3.wav", gEngfuncs.pfnRandomFloat( 0.92, 1.0 ), ATTN_NORM, 0, 98 + gEngfuncs.pfnRandomLong( 0, 3 ) );
}
else
{
switch( gEngfuncs.pfnRandomLong( 0, 1 ) )
{
case 0:
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/pl_gun1.wav", gEngfuncs.pfnRandomFloat( 0.8, 0.9 ), ATTN_NORM, 0, PITCH_NORM );
break;
case 1:
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/pl_gun2.wav", gEngfuncs.pfnRandomFloat( 0.8, 0.9 ), ATTN_NORM, 0, PITCH_NORM );
break;
}
}
EV_GetGunPosition( args, vecSrc, origin );
@ -505,47 +556,11 @@ void EV_FireGlock1( event_args_t *args )
void EV_FireGlock2( event_args_t *args )
{
int idx;
vec3_t origin;
vec3_t angles;
vec3_t velocity;
cl_entity_t *viewent = gEngfuncs.GetViewModel();
if( !viewent )
return;
vec3_t ShellVelocity;
vec3_t ShellOrigin;
int shell;
vec3_t vecSrc, vecAiming;
vec3_t vecSpread;
vec3_t up, right, forward;
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( GLOCK_SHOOT, 2 );
V_PunchAxis( 0, -2.0 );
}
EV_GetDefaultShellInfo( args, origin, velocity, ShellVelocity, ShellOrigin, forward, right, up, 20, -12, 4 );
EV_EjectBrass ( ShellOrigin, ShellVelocity, angles[YAW], shell, TE_BOUNCE_SHELL );
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/pl_gun3.wav", gEngfuncs.pfnRandomFloat( 0.92, 1.0 ), ATTN_NORM, 0, 98 + gEngfuncs.pfnRandomLong( 0, 3 ) );
EV_GetGunPosition( args, vecSrc, origin );
VectorCopy( forward, vecAiming );
EV_HLDM_FireBullets( idx, forward, right, up, 1, vecSrc, vecAiming, 8192, BULLET_PLAYER_9MM, 0, &tracerCount[idx - 1], args->fparam1, args->fparam2 );
viewent->curstate.body = args->iparam1;
}
//======================
// GLOCK END
@ -1411,114 +1426,23 @@ BEAM *pBeam;
BEAM *pBeam2;
void EV_EgonFire( event_args_t *args )
{
int idx, iFireState, iFireMode;
vec3_t origin;
idx = args->entindex;
VectorCopy( args->origin, origin );
iFireState = args->iparam1;
iFireMode = args->iparam2;
int iStartup = args->bparam1;
if( iStartup )
{
if( iFireMode == FIRE_WIDE )
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, EGON_SOUND_STARTUP, 0.98, ATTN_NORM, 0, 125 );
else
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, EGON_SOUND_STARTUP, 0.9, ATTN_NORM, 0, 100 );
}
else
{
if( iFireMode == FIRE_WIDE )
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_STATIC, EGON_SOUND_RUN, 0.98, ATTN_NORM, 0, 125 );
else
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_STATIC, EGON_SOUND_RUN, 0.9, ATTN_NORM, 0, 100 );
}
//Only play the weapon anims if I shot it.
if( EV_IsLocal( idx ) )
gEngfuncs.pEventAPI->EV_WeaponAnimation ( g_fireAnims1[gEngfuncs.pfnRandomLong( 0, 3 )], 1 );
if( iStartup == 1 && EV_IsLocal( idx ) && !pBeam && !pBeam2 && cl_lw->value ) //Adrian: Added the cl_lw check for those lital people that hate weapon prediction.
{
vec3_t vecSrc, vecEnd, angles, forward, right, up;
pmtrace_t tr;
cl_entity_t *pl = gEngfuncs.GetEntityByIndex( idx );
if( pl )
{
VectorCopy( gHUD.m_vecAngles, angles );
AngleVectors( angles, forward, right, up );
EV_GetGunPosition( args, vecSrc, pl->origin );
VectorMA( vecSrc, 2048, forward, vecEnd );
gEngfuncs.pEventAPI->EV_SetUpPlayerPrediction( false, true );
// Store off the old count
gEngfuncs.pEventAPI->EV_PushPMStates();
// Now add in all of the players.
gEngfuncs.pEventAPI->EV_SetSolidPlayers( idx - 1 );
gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc, vecEnd, PM_STUDIO_BOX, -1, &tr );
gEngfuncs.pEventAPI->EV_PopPMStates();
int iBeamModelIndex = gEngfuncs.pEventAPI->EV_FindModelIndex( EGON_BEAM_SPRITE );
float r = 50.0f;
float g = 50.0f;
float b = 125.0f;
if( IEngineStudio.IsHardware() )
{
r /= 100.0f;
g /= 100.0f;
}
pBeam = gEngfuncs.pEfxAPI->R_BeamEntPoint( idx | 0x1000, tr.endpos, iBeamModelIndex, 99999, 3.5, 0.2, 0.7, 55, 0, 0, r, g, b );
if( pBeam )
pBeam->flags |= ( FBEAM_SINENOISE );
pBeam2 = gEngfuncs.pEfxAPI->R_BeamEntPoint( idx | 0x1000, tr.endpos, iBeamModelIndex, 99999, 5.0, 0.08, 0.7, 25, 0, 0, r, g, b );
}
}
}
void EV_EgonStop( event_args_t *args )
{
int idx;
vec3_t origin;
idx = args->entindex;
VectorCopy( args->origin, origin );
// Play fire sound.
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/flmfire2.wav", 1, ATTN_NORM, 0, 98 + gEngfuncs.pfnRandomLong( 0, 0x04 ) );
gEngfuncs.pEventAPI->EV_StopSound( idx, CHAN_STATIC, EGON_SOUND_RUN );
if( args->iparam1 )
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, EGON_SOUND_OFF, 0.98, ATTN_NORM, 0, 100 );
//Only play the weapon anims if I shot it.
if( EV_IsLocal( idx ) )
{
if( pBeam )
{
pBeam->die = 0.0;
pBeam = NULL;
}
gEngfuncs.pEventAPI->EV_WeaponAnimation( g_fireAnims1[gEngfuncs.pfnRandomLong( 0, 3 )], 1 );
}
if( pBeam2 )
{
pBeam2->die = 0.0;
pBeam2 = NULL;
}
}
void EV_EgonStop( event_args_t *args )
{
}
//======================
// EGON END
@ -1743,3 +1667,421 @@ int EV_TFC_IsAllyTeam( int iTeam1, int iTeam2 )
{
return 0;
}
//======================
// SHOVEL START
//======================
enum shovel_e
{
SHOVEL_IDLE = 0,
SHOVEL_DRAW,
SHOVEL_HOLSTER,
SHOVEL_ATTACK1HIT,
SHOVEL_ATTACK1MISS,
SHOVEL_ATTACK2MISS,
SHOVEL_ATTACK2HIT,
SHOVEL_ATTACK3MISS,
SHOVEL_ATTACK3HIT,
SHOVEL_IDLE2,
SHOVEL_IDLE3
};
//Only predict the miss sounds, hit sounds are still played
//server side, so players don't get the wrong idea.
void EV_Shovel( event_args_t *args )
{
int idx;
vec3_t origin;
vec3_t angles;
vec3_t velocity;
idx = args->entindex;
VectorCopy( args->origin, origin );
//Play Swing sound
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/cbar_miss1.wav", 1, ATTN_NORM, 0, PITCH_NORM );
if( EV_IsLocal( idx ) )
{
gEngfuncs.pEventAPI->EV_WeaponAnimation( SHOVEL_ATTACK1MISS, 1 );
switch( ( g_iSwing++ ) % 3 )
{
case 0:
gEngfuncs.pEventAPI->EV_WeaponAnimation( SHOVEL_ATTACK1MISS, 1 );
break;
case 1:
gEngfuncs.pEventAPI->EV_WeaponAnimation( SHOVEL_ATTACK2MISS, 1 );
break;
case 2:
gEngfuncs.pEventAPI->EV_WeaponAnimation( SHOVEL_ATTACK3MISS, 1 );
break;
}
}
}
//======================
// SHOVEL END
//======================
//======================
// SPANNER START
//======================
enum spanner_e
{
SPANNER_IDLE = 0,
SPANNER_ATTACK1,
SPANNER_ATTACK2,
SPANNER_USE,
SPANNER_DRAW,
SPANNER_HOLSTER
};
//Only predict the miss sounds, hit sounds are still played
//server side, so players don't get the wrong idea.
void EV_Spanner( event_args_t *args )
{
int idx;
vec3_t origin;
vec3_t angles;
vec3_t velocity;
idx = args->entindex;
VectorCopy( args->origin, origin );
//Play Swing sound
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/cbar_miss1.wav", 1, ATTN_NORM, 0, PITCH_NORM );
if( EV_IsLocal( idx ) )
{
gEngfuncs.pEventAPI->EV_WeaponAnimation( SPANNER_ATTACK1, 1 );
switch( ( g_iSwing++ ) % 2 )
{
case 0:
gEngfuncs.pEventAPI->EV_WeaponAnimation( SPANNER_ATTACK1, 1 );
break;
case 1:
gEngfuncs.pEventAPI->EV_WeaponAnimation( SPANNER_ATTACK2, 1 );
break;
}
}
}
//======================
// SPANNER END
//======================
//======================
// AP9 START
//======================
enum ap9_e
{
AP9_IDLE = 0,
AP9_RELOAD,
AP9_DRAW,
AP9_SHOOT1,
AP9_SHOOT2,
AP9_SHOOT3
};
void EV_FireAP9( event_args_t *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;
int burstShot = args->bparam1;
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( AP9_SHOOT1 + gEngfuncs.pfnRandomLong( 0, 2 ), 1 );
int punch = !burstShot ? 2 : 1;
V_PunchAxis( 0, gEngfuncs.pfnRandomFloat( -punch, punch ) );
}
EV_GetDefaultShellInfo( args, origin, velocity, ShellVelocity, ShellOrigin, forward, right, up, 20, -12, 4 );
EV_EjectBrass( ShellOrigin, ShellVelocity, angles[ YAW ], shell, TE_BOUNCE_SHELL );
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/ap9_fire.wav", 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ) );
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_AP9, 2, &tracerCount[idx-1], args->fparam1, args->fparam2 );
}
else
{
EV_HLDM_FireBullets( idx, forward, right, up, 1, vecSrc, vecAiming, 8192, BULLET_PLAYER_AP9, 2, &tracerCount[idx-1], args->fparam1, args->fparam2 );
}
}
//======================
// AP9 END
//======================
//======================
// TAURUS START
//======================
enum taurus_e
{
TAURUS_IDLE1 = 0,
TAURUS_IDLE2,
TAURUS_IDLE3,
TAURUS_SHOOT,
TAURUS_SHOOT2,
TAURUS_SHOOT3,
TAURUS_SHOOT_EMPTY,
TAURUS_RELOAD,
TAURUS_RELOAD2,
TAURUS_DRAW,
TAURUS_DRAW2
};
void EV_FireTaurus( 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 );
AngleVectors( angles, forward, right, up );
if( EV_IsLocal( idx ) )
{
EV_MuzzleFlash();
gEngfuncs.pEventAPI->EV_WeaponAnimation( TAURUS_SHOOT + gEngfuncs.pfnRandomLong( 0, 2 ), 1 );
V_PunchAxis( 0, -2.0 );
}
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/tau_fire.wav", gEngfuncs.pfnRandomFloat(0.92, 1.0), ATTN_NORM, 0, 98 + gEngfuncs.pfnRandomLong( 0, 3 ) );
EV_GetGunPosition( args, vecSrc, origin );
VectorCopy( forward, vecAiming );
EV_HLDM_FireBullets( idx, forward, right, up, 1, vecSrc, vecAiming, 8192, BULLET_PLAYER_TAURUS, 0, 0, args->fparam1, args->fparam2 );
}
//======================
// TAURUS END
//======================
//======================
// SNIPER START
//======================
extern vec3_t ev_punchangle;
void EV_FireSniper( event_args_t *args )
{
int idx;
vec3_t origin;
vec3_t angles;
vec3_t velocity;
int activity;
vec3_t vecSrc, vecAiming;
vec3_t up, right, forward;
idx = args->entindex;
VectorCopy( args->origin, origin );
VectorCopy( args->angles, angles );
VectorCopy( args->velocity, velocity );
activity = args->iparam1;
AngleVectors( angles, forward, right, up);
if( EV_IsLocal( idx ) )
{
// Add muzzle flash to current weapon model
EV_MuzzleFlash();
gEngfuncs.pEventAPI->EV_WeaponAnimation( activity, 1 );
// Substract additional pitch from already exisiting one.
float pitch = ev_punchangle[PITCH];
pitch -= 4;
// Send punch angle.
V_PunchAxis( 0, pitch );
}
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/sniper.wav", gEngfuncs.pfnRandomFloat( 0.8, 0.9 ), ATTN_NORM, 0, PITCH_NORM );
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 );
}
//======================
// SNIPER END
//======================
//======================
// SNIPER2 START
//======================
void EV_FireSniper2( event_args_t *args )
{
}
//======================
// SNIPER2 END
//======================
//======================
// CHAINGUN START
//======================
enum chaingun_e
{
CHAINGUN_IDLE = 0,
CHAINGUN_IDLE2,
CHAINGUN_SPINUP,
CHAINGUN_SPINDOWN,
CHAINGUN_FIRE,
CHAINGUN_DRAW,
CHAINGUN_HOLSTER
};
void EV_FireChaingun1( event_args_t *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;
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( CHAINGUN_FIRE, 1 );
V_PunchAxis( 0, gEngfuncs.pfnRandomFloat( -1, 1 ) );
}
EV_GetDefaultShellInfo( args, origin, velocity, ShellVelocity, ShellOrigin, forward, right, up, 20, -12, 4 );
EV_EjectBrass( ShellOrigin, ShellVelocity, angles[ YAW ], shell, TE_BOUNCE_SHELL );
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/asscan2.wav", 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ) );
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_CHAINGUN, 2, &tracerCount[idx - 1], args->fparam1, args->fparam2 );
}
else
{
EV_HLDM_FireBullets( idx, forward, right, up, 1, vecSrc, vecAiming, 8192, BULLET_PLAYER_CHAINGUN, 2, &tracerCount[idx - 1], args->fparam1, args->fparam2 );
}
}
extern cvar_t *cl_forwardspeed;
extern cvar_t *cl_backspeed;
extern cvar_t *cl_sidespeed;
void EV_FireChaingun2( event_args_t *args )
{
static float default_forwardspeed = cl_forwardspeed->value;
static float default_backspeed = cl_backspeed->value;
static float default_sidespeed = cl_sidespeed->value;
// Toggle speed.
int idx;
int firing;
idx = args->entindex;
firing = args->bparam1;
if( firing )
{
cl_forwardspeed->value = 100;
cl_backspeed->value = 100;
cl_sidespeed->value = 100;
}
else
{
cl_forwardspeed->value = default_forwardspeed;
cl_backspeed->value = default_backspeed;
cl_sidespeed->value = default_sidespeed;
}
}
//======================
// CHAINGUN END
//======================
//======================
// MEDKIT START
//======================
enum medkit_e
{
MEDKIT_IDLE = 0,
MEDKIT_LONGIDLE,
MEDKIT_LONGUSE,
MEDKIT_SHORTUSE,
MEDKIT_HOLSTER,
MEDKIT_DRAW
};
//Only predict the miss sounds, hit sounds are still played
//server side, so players don't get the wrong idea.
void EV_Medkit( event_args_t *args )
{
int idx;
idx = args->entindex;
if( EV_IsLocal( idx ) )
{
gEngfuncs.pEventAPI->EV_WeaponAnimation( MEDKIT_LONGUSE, 1 );
}
}
//======================
// MEDKIT END
//======================

View File

@ -17,7 +17,10 @@ typedef enum
BULLET_PLAYER_357, // python
BULLET_PLAYER_BUCKSHOT, // shotgun
BULLET_PLAYER_CROWBAR, // crowbar swipe
BULLET_PLAYER_AP9,
BULLET_PLAYER_CHAINGUN,
BULLET_PLAYER_SNIPER,
BULLET_PLAYER_TAURUS,
BULLET_MONSTER_9MM,
BULLET_MONSTER_MP5,
BULLET_MONSTER_12MM

View File

@ -25,6 +25,8 @@
#include <string.h>
#include <stdio.h>
extern bool bIsMultiplayer( void );
DECLARE_MESSAGE( m_Flash, FlashBat )
DECLARE_MESSAGE( m_Flash, Flashlight )
@ -114,10 +116,17 @@ int CHudFlashlight::Draw( float flTime )
else
a = MIN_ALPHA;
if( m_flBat < 0.20 )
UnpackRGB( r,g,b, RGB_REDISH );
if( bIsMultiplayer() )
{
if( m_flBat < 0.20 )
UnpackRGB( r, g, b, RGB_REDISH );
else
UnpackRGB( r, g, b, RGB_YELLOWISH );
}
else
UnpackRGB( r,g,b, RGB_YELLOWISH );
{
UnpackRGB( r, g, b, RGB_REDISH );
}
ScaleColors( r, g, b, a );

View File

@ -29,6 +29,8 @@
#include "mobility_int.h"
extern bool bIsMultiplayer( void );
DECLARE_MESSAGE( m_Health, Health )
DECLARE_MESSAGE( m_Health, Damage )
@ -165,7 +167,14 @@ void CHudHealth::GetPainColor( int &r, int &g, int &b )
#else
if( m_iHealth > 25 )
{
UnpackRGB( r, g, b, RGB_YELLOWISH );
if( bIsMultiplayer() )
{
UnpackRGB( r, g, b, RGB_YELLOWISH );
}
else
{
UnpackRGB( r, g, b, RGB_REDISH );
}
}
else
{
@ -226,12 +235,6 @@ int CHudHealth::Draw( float flTime )
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 );
@ -379,6 +382,15 @@ int CHudHealth::DrawDamage( float flTime )
if( !m_bitsDamage )
return 1;
if( bIsMultiplayer() )
{
UnpackRGB( r, g, b, RGB_YELLOWISH );
}
else
{
UnpackRGB( r, g, b, RGB_REDISH );
}
UnpackRGB( r, g, b, RGB_YELLOWISH );
a = (int)( fabs( sin( flTime * 2 ) ) * 256.0 );

View File

@ -98,6 +98,10 @@ CGrenade *CGrenade::ShootTimed( entvars_t *pevOwner, Vector vecStart, Vector vec
CGrenade *CGrenade::ShootContact( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity ){ return 0; }
void CGrenade::DetonateUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ){ }
// CTnt Stubs
void CTnt::Spawn( void ) { }
CGrenade *CTnt::ShootTimed( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity, float time ){ return 0; }
void UTIL_Remove( CBaseEntity *pEntity ){ }
struct skilldata_t gSkillData;
void UTIL_SetSize( entvars_t *pev, const Vector &vecMin, const Vector &vecMax ){ }
@ -314,6 +318,7 @@ int CBasePlayerItem::Restore( class CRestore & ) { return 1; }
int CBasePlayerItem::Save( class CSave & ) { return 1; }
int CBasePlayerWeapon::Restore( class CRestore & ) { return 1; }
int CBasePlayerWeapon::Save( class CSave & ) { return 1; }
float CBasePlayerWeapon::GetNextAttackDelay( float flTime ) { return flTime; }
void CBasePlayerItem::SetObjectCollisionBox( void ) { }
void CBasePlayerItem::FallInit( void ) { }
void CBasePlayerItem::FallThink( void ) { }

View File

@ -40,6 +40,16 @@ 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_Shovel( struct event_args_s *args );
void EV_Spanner( struct event_args_s *args );
void EV_Medkit( struct event_args_s *args );
void EV_FireAP9( struct event_args_s *args );
void EV_FireChaingun1( struct event_args_s *args );
void EV_FireChaingun2( struct event_args_s *args );
void EV_FireSniper( struct event_args_s *args );
void EV_FireSniper2( struct event_args_s *args );
void EV_FireTaurus( struct event_args_s *args );
}
/*
@ -76,4 +86,14 @@ 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/shovel.sc", EV_Shovel );
gEngfuncs.pfnHookEvent( "events/spanner.sc", EV_Spanner );
gEngfuncs.pfnHookEvent( "events/medkit.sc", EV_Medkit );
gEngfuncs.pfnHookEvent( "events/ap9.sc", EV_FireAP9 );
gEngfuncs.pfnHookEvent( "events/chaingun1.sc", EV_FireChaingun1 );
gEngfuncs.pfnHookEvent( "events/chaingun2.sc", EV_FireChaingun2 );
gEngfuncs.pfnHookEvent( "events/sniper.sc", EV_FireSniper );
gEngfuncs.pfnHookEvent( "events/sniper2.sc", EV_FireSniper2 );
gEngfuncs.pfnHookEvent( "events/taurus.sc", EV_FireTaurus );
}

View File

@ -68,6 +68,15 @@ CSatchel g_Satchel;
CTripmine g_Tripmine;
CSqueak g_Snark;
CShovel g_Shovel;
CSpanner g_Spanner;
CAP9 g_AP9;
CTaurus g_Taurus;
CHKG36 g_HKG36;
CEinar1 g_Einar1;
CChaingun g_Chaingun;
CMedkit g_Medkit;
/*
======================
AlertMessage
@ -637,6 +646,14 @@ void HUD_InitClientWeapons( void )
HUD_PrepEntity( &g_Satchel, &player );
HUD_PrepEntity( &g_Tripmine, &player );
HUD_PrepEntity( &g_Snark, &player );
HUD_PrepEntity( &g_Shovel, &player );
HUD_PrepEntity( &g_Spanner, &player );
HUD_PrepEntity( &g_AP9, &player );
HUD_PrepEntity( &g_Taurus, &player );
HUD_PrepEntity( &g_HKG36, &player );
HUD_PrepEntity( &g_Einar1, &player );
HUD_PrepEntity( &g_Chaingun, &player );
HUD_PrepEntity( &g_Medkit, &player );
}
/*
@ -742,6 +759,30 @@ void HUD_WeaponsPostThink( local_state_s *from, local_state_s *to, usercmd_t *cm
case WEAPON_SNARK:
pWeapon = &g_Snark;
break;
case WEAPON_SHOVEL:
pWeapon = &g_Shovel;
break;
case WEAPON_SPANNER:
pWeapon = &g_Spanner;
break;
case WEAPON_AP9:
pWeapon = &g_AP9;
break;
case WEAPON_TAURUS:
pWeapon = &g_Taurus;
break;
case WEAPON_HKG36:
pWeapon = &g_HKG36;
break;
case WEAPON_EINAR1:
pWeapon = &g_Einar1;
break;
case WEAPON_CHAINGUN:
pWeapon = &g_Chaingun;
break;
case WEAPON_MEDKIT:
pWeapon = &g_Medkit;
break;
}
// Store pointer to our destination entity_state_t so we can get our origin, etc. from it
@ -851,6 +892,18 @@ 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_AP9 )
{
player.ammo_ap9 = (int)from->client.vuser1[1];
}
else if( player.m_pActiveItem->m_iId == WEAPON_TAURUS )
{
player.ammo_taurus = (int)from->client.vuser1[1];
}
else if( player.m_pActiveItem->m_iId == WEAPON_EINAR1 || player.m_pActiveItem->m_iId == WEAPON_HKG36 )
{
player.ammo_sniper = (int)from->client.vuser1[1];
}
// Don't go firing anything if we have died.
// Or if we don't have a weapon model deployed
@ -919,6 +972,18 @@ 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_AP9 )
{
from->client.vuser1[1] = player.ammo_ap9;
}
else if( player.m_pActiveItem->m_iId == WEAPON_TAURUS )
{
from->client.vuser1[1] = player.ammo_taurus;
}
else if( player.m_pActiveItem->m_iId == WEAPON_EINAR1 || player.m_pActiveItem->m_iId == WEAPON_HKG36 )
{
from->client.vuser1[1] = player.ammo_sniper;
}
// Make sure that weapon animation matches what the game .dll is telling us
// over the wire ( fixes some animation glitches )
@ -934,6 +999,9 @@ void HUD_WeaponsPostThink( local_state_s *from, local_state_s *to, usercmd_t *cm
if( pWeapon == &g_Python && bIsMultiplayer() )
body = 1;
if( pWeapon == &g_Glock && ( (CGlock*)pWeapon )->m_fSilencerOn )
body = 1;
// Force a fixed anim down to viewmodel
HUD_SendWeaponAnim( to->client.weaponanim, body, 1 );
}

View File

@ -227,6 +227,7 @@ void CHud::Init( void )
m_AmmoSecondary.Init();
m_TextMessage.Init();
m_StatusIcons.Init();
m_Zoom.Init();
m_MOTD.Init();
m_Scoreboard.Init();
@ -396,6 +397,7 @@ void CHud::VidInit( void )
m_AmmoSecondary.VidInit();
m_TextMessage.VidInit();
m_StatusIcons.VidInit();
m_Zoom.VidInit();
m_Scoreboard.VidInit();
m_MOTD.VidInit();
}

View File

@ -556,6 +556,24 @@ private:
icon_sprite_t m_IconList[MAX_ICONSPRITES];
};
//
//-----------------------------------------------------
//
class CHudZoom : public CHudBase
{
public:
int Init( void );
int VidInit( void );
int Draw( float flTime );
void Reset( void );
int MsgFunc_Zoom( const char *pszName, int iSize, void *pbuf );
private:
int m_fOn;
WEAPON* m_pWeapon;
};
//
//-----------------------------------------------------
//
@ -631,6 +649,7 @@ public:
CHudAmmoSecondary m_AmmoSecondary;
CHudTextMessage m_TextMessage;
CHudStatusIcons m_StatusIcons;
CHudZoom m_Zoom;
CHudScoreboard m_Scoreboard;
CHudMOTD m_MOTD;

View File

@ -24,6 +24,8 @@
#include <stdio.h>
#include "parsemsg.h"
extern bool bIsMultiplayer( void );
DECLARE_MESSAGE( m_Train, Train )
int CHudTrain::Init( void )
@ -53,7 +55,15 @@ int CHudTrain::Draw( float fTime )
{
int r, g, b, x, y;
UnpackRGB( r, g, b, RGB_YELLOWISH );
if( bIsMultiplayer() )
{
UnpackRGB( r, g, b, RGB_YELLOWISH );
}
else
{
UnpackRGB( r, g, b, RGB_REDISH );
}
SPR_Set( m_hSprite, r, g, b );
// This should show up to the right and part way up the armor number

View File

@ -1324,6 +1324,15 @@ int V_FindViewModelByWeaponModel( int weaponindex )
{ "models/p_tripmine.mdl", "models/v_tripmine.mdl" },
{ "models/p_satchel_radio.mdl", "models/v_satchel_radio.mdl" },
{ "models/p_satchel.mdl", "models/v_satchel.mdl" },
{ "models/p_ap9.mdl", "models/v_ap9.mdl" },
{ "models/p_hkg36.mdl", "models/v_hkg36.mdl" },
{ "models/p_shovel.mdl", "models/v_shovel.mdl" },
{ "models/p_sniper.mdl", "models/v_tfc_sniper.mdl" },
{ "models/p_spanner.mdl", "models/v_tfc_spanner.mdl" },
{ "models/p_taurus.mdl", "models/v_taurus.mdl" },
{ "models/p_tfac.mdl", "models/v_tfac.mdl" },
{ "models/p_tfc_medkit.mdl", "models/v_tfc_medkit.mdl" },
{ "models/p_tnt.mdl", "models/v_tnt.mdl" },
{ NULL, NULL }
};

277
dlls/Hunger/ap9.cpp Normal file
View File

@ -0,0 +1,277 @@
/***
*
* 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 ap9_e
{
AP9_IDLE = 0,
AP9_RELOAD,
AP9_DRAW,
AP9_SHOOT1,
AP9_SHOOT2,
AP9_SHOOT3,
};
LINK_ENTITY_TO_CLASS(weapon_th_ap9, CAP9);
void CAP9::Spawn()
{
Precache();
SET_MODEL(ENT(pev), "models/w_ap9.mdl");
m_iId = WEAPON_AP9;
m_iDefaultAmmo = AP9_DEFAULT_GIVE;
m_iBurstShots = 0;
FallInit();// get ready to fall down.
}
void CAP9::Precache(void)
{
PRECACHE_MODEL("models/v_ap9.mdl");
PRECACHE_MODEL("models/w_ap9.mdl");
PRECACHE_MODEL("models/p_ap9.mdl");
m_iShell = PRECACHE_MODEL("models/shell.mdl");// brass shellTE_MODEL
PRECACHE_MODEL("models/w_ap9clip.mdl");
PRECACHE_SOUND("items/9mmclip1.wav");
PRECACHE_SOUND("weapons/ap9_bolt.wav");
PRECACHE_SOUND("weapons/ap9_clipin.wav");
PRECACHE_SOUND("weapons/ap9_clipout.wav");
PRECACHE_SOUND("weapons/ap9_fire.wav");
PRECACHE_SOUND("weapons/357_cock1.wav");
m_usFireAP9 = PRECACHE_EVENT(1, "events/ap9.sc");
}
int CAP9::GetItemInfo(ItemInfo *p)
{
p->pszName = STRING(pev->classname);
p->pszAmmo1 = "ap9";
p->iMaxAmmo1 = AP9_MAX_CARRY;
p->pszAmmo2 = NULL;
p->iMaxAmmo2 = -1;
p->iMaxClip = AP9_MAX_CLIP;
p->iSlot = 1;
p->iPosition = 2;
p->iFlags = 0;
p->iId = m_iId = WEAPON_AP9;
p->iWeight = AP9_WEIGHT;
return 1;
}
int CAP9::AddToPlayer(CBasePlayer *pPlayer)
{
if (CBasePlayerWeapon::AddToPlayer(pPlayer))
{
MESSAGE_BEGIN(MSG_ONE, gmsgWeapPickup, NULL, pPlayer->pev);
WRITE_BYTE(m_iId);
MESSAGE_END();
return TRUE;
}
return FALSE;
}
BOOL CAP9::Deploy()
{
BOOL bResult = DefaultDeploy("models/v_ap9.mdl", "models/p_ap9.mdl", AP9_DRAW, "ap9");
if (bResult)
{
m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.7;
}
return bResult;
}
void CAP9::PrimaryAttack(void)
{
m_fInAttack = 0;
AP9Fire(0.03, 0.13, TRUE, FALSE);
}
void CAP9::SecondaryAttack(void)
{
if (m_fInAttack != 0)
return;
m_fInAttack = 1;
m_iBurstShots = 0;
m_flNextPrimaryAttack = m_flNextSecondaryAttack = GetNextAttackDelay(2.0);
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() - 0.1;
}
void CAP9::AP9Fire(float flSpread, float flCycleTime, BOOL fUseAutoAim, BOOL fBurstShot)
{
if (m_iClip <= 0)
{
if (m_fFireOnEmpty)
{
PlayEmptySound();
m_flNextPrimaryAttack = GetNextAttackDelay(0.2);
}
return;
}
m_iClip--;
m_pPlayer->pev->effects = (int)(m_pPlayer->pev->effects) | EF_MUZZLEFLASH;
int flags;
#if defined( CLIENT_WEAPONS )
flags = FEV_NOTHOST;
#else
flags = 0;
#endif
// player "shoot" animation
m_pPlayer->SetAnimation( PLAYER_ATTACK1 );
// silenced
if (pev->body == 1)
{
m_pPlayer->m_iWeaponVolume = QUIET_GUN_VOLUME;
m_pPlayer->m_iWeaponFlash = DIM_GUN_FLASH;
}
else
{
// non-silenced
m_pPlayer->m_iWeaponVolume = NORMAL_GUN_VOLUME;
m_pPlayer->m_iWeaponFlash = NORMAL_GUN_FLASH;
}
Vector vecSrc = m_pPlayer->GetGunPosition( );
Vector vecAiming;
if ( fUseAutoAim )
{
vecAiming = m_pPlayer->GetAutoaimVector( AUTOAIM_10DEGREES );
}
else
{
vecAiming = gpGlobals->v_forward;
}
Vector vecDir;
vecDir = m_pPlayer->FireBulletsPlayer( 1, vecSrc, vecAiming, Vector( flSpread, flSpread, flSpread ), 8192, BULLET_PLAYER_AP9, 0, 0, m_pPlayer->pev, m_pPlayer->random_seed );
PLAYBACK_EVENT_FULL(flags, m_pPlayer->edict(), m_usFireAP9, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, vecDir.x, vecDir.y, 0, 0, fBurstShot, 0);
m_flNextPrimaryAttack = m_flNextSecondaryAttack = GetNextAttackDelay(flCycleTime);
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + UTIL_SharedRandomFloat( m_pPlayer->random_seed, 10, 15 );
}
void CAP9::Reload(void)
{
if (m_pPlayer->ammo_ap9 <= 0)
return;
int iResult = DefaultReload(AP9_MAX_CLIP, AP9_RELOAD, 2.9);
if (iResult)
{
m_fInAttack = 0;
m_iBurstShots = 0;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + UTIL_SharedRandomFloat(m_pPlayer->random_seed, 10, 15);
}
}
void CAP9::WeaponIdle(void)
{
ResetEmptySound();
m_pPlayer->GetAutoaimVector(AUTOAIM_5DEGREES);
if (m_flTimeWeaponIdle > UTIL_WeaponTimeBase())
return;
if (m_fInAttack != 0)
{
if (m_iBurstShots < 3 && m_iClip > 0)
{
AP9Fire(0.01, 0.05, FALSE, TRUE);
m_iBurstShots++;
m_flNextPrimaryAttack = m_flNextSecondaryAttack = GetNextAttackDelay(2.0f);
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 0.05;
}
else
{
m_fInAttack = 0;
m_iBurstShots = 0;
m_flNextPrimaryAttack = m_flNextSecondaryAttack = GetNextAttackDelay(0.5f);
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + UTIL_SharedRandomFloat(m_pPlayer->random_seed, 10, 15);
}
}
else
{
SendWeaponAnim(AP9_IDLE);
m_flTimeWeaponIdle = UTIL_SharedRandomFloat(m_pPlayer->random_seed, 10, 15); // how long till we do this again.
}
}
class CAP9Ammo : public CBasePlayerAmmo
{
void Spawn(void)
{
Precache();
SET_MODEL(ENT(pev), "models/w_ap9clip.mdl");
CBasePlayerAmmo::Spawn();
}
void Precache(void)
{
PRECACHE_MODEL("models/w_ap9clip.mdl");
PRECACHE_SOUND("items/9mmclip1.wav");
}
BOOL AddAmmo(CBaseEntity *pOther)
{
int bResult = (pOther->GiveAmmo(AMMO_AP9_GIVE, "ap9", AP9_MAX_CARRY) != -1);
if (bResult)
{
EMIT_SOUND(ENT(pev), CHAN_ITEM, "items/9mmclip1.wav", 1, ATTN_NORM);
}
return bResult;
}
};
LINK_ENTITY_TO_CLASS(ammo_th_ap9, CAP9Ammo);

173
dlls/Hunger/babykelly.cpp Normal file
View File

@ -0,0 +1,173 @@
/***
*
* 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 "util.h"
#include "cbase.h"
#include "monsters.h"
#include "squadmonster.h"
#include "schedule.h"
#include "effects.h"
#include "weapons.h"
#include "soundent.h"
#include "islave.h"
class CBabyKelly : public CISlave
{
public:
void Spawn(void);
void Precache(void);
void DeathSound(void);
void PainSound(void);
void AlertSound(void);
void IdleSound(void);
static const char *pAttackHitSounds[];
static const char *pAttackMissSounds[];
static const char *pPainSounds[];
static const char *pDeathSounds[];
};
LINK_ENTITY_TO_CLASS(monster_th_babykelly, CBabyKelly);
const char *CBabyKelly::pAttackHitSounds[] =
{
"zombie/claw_strike1.wav",
"zombie/claw_strike2.wav",
"zombie/claw_strike3.wav",
};
const char *CBabyKelly::pAttackMissSounds[] =
{
"zombie/claw_miss1.wav",
"zombie/claw_miss2.wav",
};
const char *CBabyKelly::pPainSounds[] =
{
"aslave/slv_pain1.wav",
"aslave/slv_pain2.wav",
};
const char *CBabyKelly::pDeathSounds[] =
{
"aslave/slv_die1.wav",
"aslave/slv_die2.wav",
};
//=========================================================
// ALertSound - scream
//=========================================================
void CBabyKelly::AlertSound(void)
{
if (m_hEnemy != NULL)
{
SENTENCEG_PlayRndSz(ENT(pev), "BKL_ALERT", 0.85, ATTN_NORM, 0, m_voicePitch);
CallForHelp("monster_alien_slave", 512, m_hEnemy, m_vecEnemyLKP);
}
}
//=========================================================
// IdleSound
//=========================================================
void CBabyKelly::IdleSound(void)
{
if (RANDOM_LONG(0, 2) == 0)
{
SENTENCEG_PlayRndSz(ENT(pev), "BKL_IDLE", 0.85, ATTN_NORM, 0, m_voicePitch);
}
}
//=========================================================
// PainSound
//=========================================================
void CBabyKelly::PainSound(void)
{
if (RANDOM_LONG(0, 2) == 0)
{
EMIT_SOUND_DYN(ENT(pev), CHAN_WEAPON, RANDOM_SOUND_ARRAY(pPainSounds), 1.0, ATTN_NORM, 0, m_voicePitch);
}
}
//=========================================================
// DieSound
//=========================================================
void CBabyKelly::DeathSound(void)
{
EMIT_SOUND_DYN(ENT(pev), CHAN_WEAPON, RANDOM_SOUND_ARRAY(pDeathSounds), 1.0, ATTN_NORM, 0, m_voicePitch);
}
//=========================================================
// Spawn
//=========================================================
void CBabyKelly::Spawn()
{
Precache();
SET_MODEL(ENT(pev), "models/babykelly.mdl");
UTIL_SetSize(pev, VEC_HUMAN_HULL_MIN, VEC_HUMAN_HULL_MAX);
pev->solid = SOLID_SLIDEBOX;
pev->movetype = MOVETYPE_STEP;
m_bloodColor = DONT_BLEED;
pev->effects = 0;
pev->health = gSkillData.slaveHealth;
pev->view_ofs = Vector(0, 0, 32);// position of the eyes relative to monster's origin.
m_flFieldOfView = VIEW_FIELD_WIDE; // NOTE: we need a wide field of view so npc will notice player and say hello
m_MonsterState = MONSTERSTATE_NONE;
m_afCapability = bits_CAP_HEAR | bits_CAP_TURN_HEAD | bits_CAP_RANGE_ATTACK2 | bits_CAP_DOORS_GROUP;
m_voicePitch = RANDOM_LONG(85, 110);
MonsterInit();
}
//=========================================================
// Precache - precaches all resources this monster needs
//=========================================================
void CBabyKelly::Precache()
{
int i;
PRECACHE_MODEL("models/babykelly.mdl");
PRECACHE_MODEL("sprites/lgtning.spr");
PRECACHE_SOUND("debris/zap1.wav");
PRECACHE_SOUND("debris/zap4.wav");
PRECACHE_SOUND("weapons/electro4.wav");
PRECACHE_SOUND("hassault/hw_shoot1.wav");
PRECACHE_SOUND("zombie/zo_pain2.wav");
PRECACHE_SOUND("headcrab/hc_headbite.wav");
PRECACHE_SOUND("weapons/cbar_miss1.wav");
for (i = 0; i < ARRAYSIZE(pAttackHitSounds); i++)
PRECACHE_SOUND((char *)pAttackHitSounds[i]);
for (i = 0; i < ARRAYSIZE(pAttackMissSounds); i++)
PRECACHE_SOUND((char *)pAttackMissSounds[i]);
for (i = 0; i < ARRAYSIZE(pPainSounds); i++)
PRECACHE_SOUND((char *)pPainSounds[i]);
for (i = 0; i < ARRAYSIZE(pDeathSounds); i++)
PRECACHE_SOUND((char *)pDeathSounds[i]);
UTIL_PrecacheOther("test_effect");
}

150
dlls/Hunger/boss.cpp Normal file
View File

@ -0,0 +1,150 @@
/***
*
* 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 "util.h"
#include "cbase.h"
#include "monsters.h"
#include "weapons.h"
#include "nodes.h"
#include "effects.h"
#include "apache.h"
#define SF_WAITFORTRIGGER (0x04 | 0x40) // UNDONE: Fix!
#define SF_NOWRECKAGE 0x08
class CBoss : public CApache
{
public:
void Spawn(void);
void Precache(void);
BOOL FireGun(void);
};
LINK_ENTITY_TO_CLASS(monster_th_boss, CBoss);
void CBoss::Spawn(void)
{
Precache( );
// motor
pev->movetype = MOVETYPE_FLY;
pev->solid = SOLID_BBOX;
SET_MODEL(ENT(pev), "models/boss.mdl");
UTIL_SetSize( pev, Vector( -32, -32, -64 ), Vector( 32, 32, 0 ) );
UTIL_SetOrigin( pev, pev->origin );
pev->flags |= FL_MONSTER;
pev->takedamage = DAMAGE_AIM;
pev->health = gSkillData.bossHealth;
m_flFieldOfView = -0.707; // 270 degrees
pev->sequence = 0;
ResetSequenceInfo( );
pev->frame = RANDOM_LONG(0, 0xFF);
InitBoneControllers();
if (pev->spawnflags & SF_WAITFORTRIGGER)
{
SetUse(&CBoss::StartupUse);
}
else
{
SetThink(&CBoss::HuntThink);
SetTouch(&CBoss::FlyTouch);
pev->nextthink = gpGlobals->time + 1.0;
}
m_iRockets = 0;
}
void CBoss::Precache(void)
{
PRECACHE_MODEL("models/boss.mdl");
PRECACHE_SOUND("apache/ap_rotor1.wav");
PRECACHE_SOUND("apache/ap_rotor2.wav");
PRECACHE_SOUND("apache/ap_rotor3.wav");
PRECACHE_SOUND("apache/ap_whine1.wav");
PRECACHE_SOUND("weapons/mortarhit.wav");
m_iSpriteTexture = PRECACHE_MODEL( "sprites/white.spr" );
PRECACHE_SOUND("turret/tu_fire1.wav");
PRECACHE_MODEL("sprites/lgtning.spr");
m_iExplode = PRECACHE_MODEL( "sprites/fexplo.spr" );
m_iBodyGibs = PRECACHE_MODEL( "models/metalplategibs_green.mdl" );
}
BOOL CBoss::FireGun()
{
UTIL_MakeAimVectors( pev->angles );
Vector posGun, angGun;
GetAttachment( 1, posGun, angGun );
Vector vecTarget = (m_posTarget - posGun).Normalize( );
Vector vecOut;
vecOut.x = DotProduct( -gpGlobals->v_right, vecTarget );
vecOut.y = -DotProduct( gpGlobals->v_forward, vecTarget );
vecOut.z = DotProduct( gpGlobals->v_up, vecTarget );
Vector angles = UTIL_VecToAngles (vecOut);
angles.x = -angles.x;
if (angles.y > 180)
angles.y = angles.y - 360;
if (angles.y < -180)
angles.y = angles.y + 360;
if (angles.x > 180)
angles.x = angles.x - 360;
if (angles.x < -180)
angles.x = angles.x + 360;
if (angles.x > m_angGun.x)
m_angGun.x = min( angles.x, m_angGun.x + 12 );
if (angles.x < m_angGun.x)
m_angGun.x = max( angles.x, m_angGun.x - 12 );
if (angles.y > m_angGun.y)
m_angGun.y = min( angles.y, m_angGun.y + 12 );
if (angles.y < m_angGun.y)
m_angGun.y = max( angles.y, m_angGun.y - 12 );
m_angGun.y = SetBoneController( 0, m_angGun.y );
m_angGun.x = SetBoneController( 1, m_angGun.x );
Vector posBarrel, angBarrel;
GetAttachment( 0, posBarrel, angBarrel );
Vector vecGun = (posBarrel - posGun).Normalize( );
if (DotProduct( vecGun, vecTarget ) > 0.98)
{
FireBullets( 1, posGun, vecGun, VECTOR_CONE_4DEGREES, 8192, BULLET_MONSTER_12MM, 1 );
EMIT_SOUND(ENT(pev), CHAN_WEAPON, "turret/tu_fire1.wav", 1, 0.3);
return TRUE;
}
return FALSE;
}

396
dlls/Hunger/chaingun.cpp Normal file
View File

@ -0,0 +1,396 @@
/***
*
* 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 "gamerules.h"
enum chaingun_e {
CHAINGUN_IDLE = 0,
CHAINGUN_IDLE2,
CHAINGUN_SPINUP,
CHAINGUN_SPINDOWN,
CHAINGUN_FIRE,
CHAINGUN_DRAW,
CHAINGUN_HOLSTER,
};
LINK_ENTITY_TO_CLASS(weapon_th_chaingun, CChaingun);
void CChaingun::Spawn()
{
Precache();
m_iId = WEAPON_CHAINGUN;
SET_MODEL(ENT(pev), "models/w_tfac.mdl");
m_iDefaultAmmo = CHAINGUN_DEFAULT_GIVE;
m_fInAttack = 0;
m_fInSpecialReload = 0;
FallInit();// get ready to fall down.
}
void CChaingun::Precache(void)
{
PRECACHE_MODEL("models/v_tfac.mdl");
PRECACHE_MODEL("models/w_tfac.mdl");
PRECACHE_MODEL("models/p_tfac.mdl");
m_iShell = PRECACHE_MODEL("models/shell.mdl");// brass shell
PRECACHE_SOUND("items/9mmclip1.wav");
PRECACHE_SOUND("weapons/reload3.wav");
PRECACHE_SOUND("weapons/asscan1.wav");
PRECACHE_SOUND("weapons/asscan2.wav");
PRECACHE_SOUND("weapons/asscan3.wav");
PRECACHE_SOUND("weapons/asscan4.wav");
m_usFireChaingun1 = PRECACHE_EVENT(1, "events/chaingun1.sc");
m_usFireChaingun2 = PRECACHE_EVENT(1, "events/chaingun2.sc");
}
int CChaingun::GetItemInfo(ItemInfo *p)
{
p->pszName = STRING(pev->classname);
p->pszAmmo1 = "9mm";
p->iMaxAmmo1 = _9MM_MAX_CARRY;
p->pszAmmo2 = NULL;
p->iMaxAmmo2 = -1;
p->iMaxClip = CHAINGUN_MAX_CLIP;
p->iSlot = 3;
p->iPosition = 3;
p->iFlags = 0;
p->iId = m_iId = WEAPON_CHAINGUN;
p->iWeight = CHAINGUN_WEIGHT;
return 1;
}
BOOL CChaingun::Deploy()
{
// pev->body = 1;
return DefaultDeploy("models/v_tfac.mdl", "models/p_tfac.mdl", CHAINGUN_DRAW, "chaingun", UseDecrement());
}
void CChaingun::Holster(int skiplocal /*= 0*/)
{
m_fInReload = FALSE;
m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 1.0;
m_flTimeWeaponIdle = UTIL_SharedRandomFloat(m_pPlayer->random_seed, 10, 15);
SendWeaponAnim(CHAINGUN_HOLSTER);
// Stop chaingun sounds.
StopSounds();
m_fInAttack = 0;
m_fInSpecialReload = 0;
}
void CChaingun::PrimaryAttack(void)
{
// Don't fire while in reload.
if (m_fInSpecialReload != 0)
{
WeaponIdle();
return;
}
// don't fire underwater
if (m_pPlayer->pev->waterlevel == 3)
{
if (m_fInAttack != 0)
{
// spin down
SpinDown();
m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 1;
}
else
{
PlayEmptySound();
}
m_flNextSecondaryAttack = m_flNextPrimaryAttack = GetNextAttackDelay(0.5);
return;
}
if (m_iClip <= 0)
{
Reload();
if (m_iClip == 0)
PlayEmptySound();
return;
}
if (m_fInAttack == 0)
{
// Spin up
SpinUp();
}
else if (m_fInAttack == 1)
{
if (m_flTimeWeaponIdle < UTIL_WeaponTimeBase())
{
// fire
SendWeaponAnim(CHAINGUN_FIRE);
m_fInAttack = 2;
}
}
else
{
// Spin
Spin();
}
m_fInSpecialReload = 0;
}
void CChaingun::SecondaryAttack(void)
{
WeaponIdle();
}
void CChaingun::Reload(void)
{
if (m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0 || m_iClip == CHAINGUN_MAX_CLIP)
return;
// don't reload until recoil is done
if (m_flNextPrimaryAttack > UTIL_WeaponTimeBase())
return;
if (m_fInAttack != 0)
return;
// Stop sounds.
StopSounds();
// Stop spin up or firing.
m_fInAttack = 0;
// Restore player speed.
PLAYBACK_EVENT_FULL(0, m_pPlayer->edict(), m_usFireChaingun2, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, 0, 0, FALSE, 0);
// check to see if we're ready to reload
if (m_fInSpecialReload == 0)
{
SendWeaponAnim(CHAINGUN_HOLSTER);
m_fInSpecialReload = 1;
m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.5;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 0.6;
m_flNextPrimaryAttack = GetNextAttackDelay(0.6);
m_flNextSecondaryAttack = GetNextAttackDelay(1.5);
return;
}
else if (m_fInSpecialReload == 1)
{
if (m_flTimeWeaponIdle > UTIL_WeaponTimeBase())
return;
// was waiting for gun to move to side
m_fInSpecialReload = 2;
EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/reload3.wav", 1, ATTN_NORM, 0, 85 + RANDOM_LONG(0, 0x1f));
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 0.8;
}
else
{
if ( DefaultReload(SNIPER_MAX_CLIP, CHAINGUN_DRAW, 0.53 ))
{
m_fInSpecialReload = 3;
m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() - 0.1;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 0.5;
}
}
}
void CChaingun::WeaponIdle(void)
{
ResetEmptySound();
m_pPlayer->GetAutoaimVector(AUTOAIM_10DEGREES);
if (m_flTimeWeaponIdle > UTIL_WeaponTimeBase())
return;
if (m_fInAttack != 0)
{
// Spin down
SpinDown();
m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 1;
}
else
{
if (m_iClip == 0 && m_fInSpecialReload == 0 && m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType])
{
Reload();
}
else if (m_fInSpecialReload != 0)
{
if (m_iClip != CHAINGUN_MAX_CLIP && m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType])
{
Reload();
}
else
{
m_fInSpecialReload = 0;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 1.5;
m_flNextPrimaryAttack = m_flNextSecondaryAttack = GetNextAttackDelay(0.0);
}
}
else
{
int iAnim;
float flRand = UTIL_SharedRandomFloat(m_pPlayer->random_seed, 0, 1);
if (flRand <= 0.5)
{
iAnim = CHAINGUN_IDLE;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + (41.0 / 10.0);
}
else
{
iAnim = CHAINGUN_IDLE2;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + (51.0 / 10.0);
}
SendWeaponAnim(iAnim);
}
}
}
BOOL CChaingun::ShouldWeaponIdle(void)
{
return m_iClip == 0 || m_fInSpecialReload != 0;
}
void CChaingun::SpinUp(void)
{
// spin up
m_pPlayer->m_iWeaponVolume = QUIET_GUN_VOLUME;
SendWeaponAnim(CHAINGUN_SPINUP);
// Slowdown player.
PLAYBACK_EVENT_FULL(0, m_pPlayer->edict(), m_usFireChaingun2, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, 0, 0, TRUE, 0);
m_fInAttack = 1;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 0.5;
EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/asscan1.wav", 1.0, ATTN_NORM, 0, 80 + RANDOM_LONG(0, 0x3f));
}
void CChaingun::SpinDown(void)
{
// Spin down
m_pPlayer->m_iWeaponVolume = QUIET_GUN_VOLUME;
SendWeaponAnim(CHAINGUN_SPINDOWN);
// Restore player speed.
PLAYBACK_EVENT_FULL(0, m_pPlayer->edict(), m_usFireChaingun2, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, 0, 0, FALSE, 0);
EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/asscan3.wav", 1.0, ATTN_NORM, 0, 80 + RANDOM_LONG(0, 0x3f));
m_fInAttack = 0;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 2.0;
}
void CChaingun::Spin(void)
{
// out of ammo!
if (m_iClip <= 0)
{
// Spin down
SpinDown();
m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 1;
return;
}
m_fInAttack = 2;
// Spin sound.
EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/asscan4.wav", 0.8, ATTN_NORM);
#ifdef CLIENT_DLL
if (!bIsMultiplayer())
#else
if (!g_pGameRules->IsMultiplayer())
#endif
{
// single player spread
Fire(0.1, 0.1, FALSE);
}
else
{
// optimized multiplayer. Widened to make it easier to hit a moving player
Fire(0.2, 0.1, FALSE);
}
}
void CChaingun::Fire(float flSpread, float flCycleTime, BOOL fUseAutoAim)
{
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;
vecDir = m_pPlayer->FireBulletsPlayer(1, vecSrc, vecAiming, Vector(flSpread, flSpread, flSpread), 8192, BULLET_PLAYER_CHAINGUN, 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_usFireChaingun1, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, vecDir.x, vecDir.y, 0, 0, 0, 0);
m_flNextPrimaryAttack = GetNextAttackDelay(flCycleTime);
if (m_flNextPrimaryAttack < UTIL_WeaponTimeBase())
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + flCycleTime;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 0.1;
}
void CChaingun::StopSounds(void)
{
STOP_SOUND(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/asscan1.wav");
STOP_SOUND(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/asscan2.wav");
STOP_SOUND(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/asscan3.wav");
STOP_SOUND(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/asscan4.wav");
}

169
dlls/Hunger/chicken.cpp Normal file
View File

@ -0,0 +1,169 @@
/***
*
* 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 "util.h"
#include "cbase.h"
#include "monsters.h"
#include "schedule.h"
#include "game.h"
#include "headcrab.h"
class CChicken : public CHeadCrab
{
public:
void Spawn(void);
void Precache(void);
void StartTask(Task_t *pTask);
void PainSound(void);
void DeathSound(void);
void IdleSound(void);
void AlertSound(void);
void AttackSound(void);
static const char *pIdleSounds[];
static const char *pAlertSounds[];
static const char *pPainSounds[];
static const char *pAttackSounds[];
static const char *pDeathSounds[];
};
LINK_ENTITY_TO_CLASS(monster_th_chicken, CChicken);
const char *CChicken::pIdleSounds[] =
{
"chicken/ch_idle1.wav",
"chicken/ch_idle2.wav",
};
const char *CChicken::pAlertSounds[] =
{
"chicken/ch_alert1.wav",
"chicken/ch_alert1.wav",
};
const char *CChicken::pPainSounds[] =
{
"chicken/ch_pain1.wav",
"chicken/ch_pain2.wav",
};
const char *CChicken::pAttackSounds[] =
{
"chicken/ch_attack1.wav",
"chicken/ch_attack2.wav",
};
const char *CChicken::pDeathSounds[] =
{
"chicken/ch_die1.wav",
"chicken/ch_die2.wav",
};
//=========================================================
// Spawn
//=========================================================
void CChicken::Spawn()
{
Precache();
SET_MODEL(ENT(pev), "models/chicken.mdl");
UTIL_SetSize(pev, Vector(-12, -12, 0), Vector(12, 12, 24));
pev->solid = SOLID_SLIDEBOX;
pev->movetype = MOVETYPE_STEP;
m_bloodColor = BLOOD_COLOR_RED;
pev->effects = 0;
pev->health = gSkillData.headcrabHealth;
pev->view_ofs = Vector(0, 0, 20);// position of the eyes relative to monster's origin.
pev->yaw_speed = 5;//!!! should we put this in the monster's changeanim function since turn rates may vary with state/anim?
m_flFieldOfView = 0.5;// indicates the width of this monster's forward view cone ( as a dotproduct result )
m_MonsterState = MONSTERSTATE_NONE;
MonsterInit();
}
//=========================================================
// Precache - precaches all resources this monster needs
//=========================================================
void CChicken::Precache()
{
PRECACHE_SOUND_ARRAY(pIdleSounds);
PRECACHE_SOUND_ARRAY(pAlertSounds);
PRECACHE_SOUND_ARRAY(pPainSounds);
PRECACHE_SOUND_ARRAY(pAttackSounds);
PRECACHE_SOUND_ARRAY(pDeathSounds);
PRECACHE_MODEL("models/chicken.mdl");
}
void CChicken::StartTask(Task_t *pTask)
{
m_iTaskStatus = TASKSTATUS_RUNNING;
switch (pTask->iTask)
{
case TASK_RANGE_ATTACK1:
{
EMIT_SOUND_DYN(edict(), CHAN_WEAPON, pAttackSounds[0], GetSoundVolue(), ATTN_IDLE, 0, GetVoicePitch());
m_IdealActivity = ACT_RANGE_ATTACK1;
SetTouch(&CHeadCrab::LeapTouch);
break;
}
default:
{
CHeadCrab::StartTask(pTask);
}
}
}
//=========================================================
// IdleSound
//=========================================================
void CChicken::IdleSound(void)
{
EMIT_SOUND_DYN(edict(), CHAN_VOICE, RANDOM_SOUND_ARRAY(pIdleSounds), GetSoundVolue(), ATTN_IDLE, 0, GetVoicePitch());
}
//=========================================================
// AlertSound
//=========================================================
void CChicken::AlertSound(void)
{
EMIT_SOUND_DYN(edict(), CHAN_VOICE, RANDOM_SOUND_ARRAY(pAlertSounds), GetSoundVolue(), ATTN_IDLE, 0, GetVoicePitch());
}
//=========================================================
// PainSound
//=========================================================
void CChicken::PainSound(void)
{
EMIT_SOUND_DYN(edict(), CHAN_VOICE, RANDOM_SOUND_ARRAY(pPainSounds), GetSoundVolue(), ATTN_IDLE, 0, GetVoicePitch());
}
//=========================================================
// DeathSound
//=========================================================
void CChicken::DeathSound(void)
{
EMIT_SOUND_DYN(edict(), CHAN_VOICE, RANDOM_SOUND_ARRAY(pDeathSounds), GetSoundVolue(), ATTN_IDLE, 0, GetVoicePitch());
}
//=========================================================
// AttackSound
//=========================================================
void CChicken::AttackSound(void)
{
EMIT_SOUND_DYN(edict(), CHAN_VOICE, RANDOM_SOUND_ARRAY(pAttackSounds), GetSoundVolue(), ATTN_IDLE, 0, GetVoicePitch());
}

187
dlls/Hunger/civilian.cpp Normal file
View File

@ -0,0 +1,187 @@
/***
*
* 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 "util.h"
#include "cbase.h"
#include "monsters.h"
#include "talkmonster.h"
#include "schedule.h"
#include "defaultai.h"
#include "scripted.h"
#include "animation.h"
#include "soundent.h"
#include "scientist.h"
#define NUM_CIVILIAN_HEADS 5 // four heads available for civilian model
enum { HEAD_GLASSES = 0, HEAD_FRANKLIN = 1, HEAD_ECHELON_OFFICER = 2, HEAD_SLICK = 3, HEAD_ORDELY = 4, };
class CCivilian : public CScientist
{
public:
void Spawn(void);
void Precache(void);
};
LINK_ENTITY_TO_CLASS(einar_civ, CCivilian);
//=========================================================
// Spawn
//=========================================================
void CCivilian::Spawn(void)
{
Precache( );
SET_MODEL(ENT(pev), "models/civ.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.scientistHealth;
pev->view_ofs = Vector ( 0, 0, 50 );// position of the eyes relative to monster's origin.
m_flFieldOfView = VIEW_FIELD_WIDE; // NOTE: we need a wide field of view so scientists will notice player and say hello
m_MonsterState = MONSTERSTATE_NONE;
// m_flDistTooFar = 256.0;
m_afCapability = bits_CAP_HEAR | bits_CAP_TURN_HEAD | bits_CAP_OPEN_DOORS | bits_CAP_AUTO_DOORS | bits_CAP_USE;
if ( pev->body == -1 )
{// -1 chooses a random head
pev->body = RANDOM_LONG(0, NUM_CIVILIAN_HEADS-1);// pick a head, any head
}
MonsterInit();
SetUse( &CCivilian::FollowerUse );
}
//=========================================================
// Precache - precaches all resources this monster needs
//=========================================================
void CCivilian :: Precache( void )
{
PRECACHE_MODEL("models/civ.mdl");
PRECACHE_SOUND("scientist/sci_pain1.wav");
PRECACHE_SOUND("scientist/sci_pain2.wav");
PRECACHE_SOUND("scientist/sci_pain3.wav");
PRECACHE_SOUND("scientist/sci_pain4.wav");
PRECACHE_SOUND("scientist/sci_pain5.wav");
// every new civilian must call this, otherwise
// when a level is loaded, nobody will talk (time is reset to 0)
TalkInit();
CTalkMonster::Precache();
}
//=========================================================
// Dead Civilian PROP
//=========================================================
class CDeadCivilian : public CDeadScientist
{
public:
void Spawn(void);
};
LINK_ENTITY_TO_CLASS(einar_civ_dead, CDeadCivilian);
//
// ********** DeadCivilian SPAWN **********
//
void CDeadCivilian::Spawn()
{
PRECACHE_MODEL("models/civ.mdl");
SET_MODEL(ENT(pev), "models/civ.mdl");
pev->effects = 0;
pev->sequence = 0;
// Corpses have less health
pev->health = 8;//gSkillData.scientistHealth;
m_bloodColor = BLOOD_COLOR_RED;
if (pev->body == -1)
{// -1 chooses a random head
pev->body = RANDOM_LONG(0, NUM_CIVILIAN_HEADS - 1);// pick a head, any head
}
pev->sequence = LookupSequence(m_szPoses[m_iPose]);
if (pev->sequence == -1)
{
ALERT(at_console, "Dead civilian with bad pose\n");
}
// pev->skin += 2; // use bloody skin -- UNDONE: Turn this back on when we have a bloody skin again!
MonsterInitDead();
}
//=========================================================
// Sitting Civilian PROP
//=========================================================
class CSittingCivilian : public CSittingScientist
{
public:
void Spawn(void);
void Precache(void);
};
LINK_ENTITY_TO_CLASS(einar_civ_sit, CSittingCivilian);
//
// ********** Civilian SPAWN **********
//
void CSittingCivilian::Spawn()
{
PRECACHE_MODEL("models/civ.mdl");
SET_MODEL(ENT(pev), "models/civ.mdl");
Precache();
InitBoneControllers();
UTIL_SetSize(pev, Vector(-14, -14, 0), Vector(14, 14, 36));
pev->solid = SOLID_SLIDEBOX;
pev->movetype = MOVETYPE_STEP;
pev->effects = 0;
pev->health = 50;
m_bloodColor = BLOOD_COLOR_RED;
m_flFieldOfView = VIEW_FIELD_WIDE; // indicates the width of this monster's forward view cone ( as a dotproduct result )
m_afCapability = bits_CAP_HEAR | bits_CAP_TURN_HEAD;
SetBits(pev->spawnflags, SF_MONSTER_PREDISASTER); // predisaster only!
if (pev->body == -1)
{// -1 chooses a random head
pev->body = RANDOM_LONG(0, NUM_CIVILIAN_HEADS - 1);// pick a head, any head
}
m_baseSequence = LookupSequence("sitlookleft");
pev->sequence = m_baseSequence + RANDOM_LONG(0, 4);
ResetSequenceInfo();
SetThink(&CSittingCivilian::SittingThink);
pev->nextthink = gpGlobals->time + 0.1;
DROP_TO_FLOOR(ENT(pev));
}
void CSittingCivilian::Precache(void)
{
m_baseSequence = LookupSequence("sitlookleft");
TalkInit();
}

View File

@ -0,0 +1,538 @@
/***
*
* 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 "squadmonster.h"
#include "weapons.h"
#include "talkmonster.h"
#include "soundent.h"
#include "effects.h"
#include "customentity.h"
#include "hgrunt.h"
#include "hornet.h"
#define FRANKLIN_MELEE_DIST 100
int iFranklinMuzzleFlash;
//=========================================================
// monster-specific DEFINE's
//=========================================================
#define GRUNT_CLIP_SIZE 36 // how many bullets in a clip? - NOTE: 3 round burst sound, so keep as 3 * x!
#define GRUNT_VOL 0.35 // volume of grunt sounds
#define GRUNT_ATTN ATTN_NORM // attenutation of grunt sentences
#define HGRUNT_LIMP_HEALTH 20
#define HGRUNT_DMG_HEADSHOT ( DMG_BULLET | DMG_CLUB ) // damage types that can kill a grunt with a single headshot.
#define HGRUNT_NUM_HEADS 2 // how many grunt heads are there?
#define HGRUNT_MINIMUM_HEADSHOT_DAMAGE 15 // must do at least this much damage in one shot to head to score a headshot kill
#define HGRUNT_SENTENCE_VOLUME (float)0.35 // volume of grunt sentences
#define HGRUNT_9MMAR ( 1 << 0)
#define HGRUNT_HANDGRENADE ( 1 << 1)
#define HGRUNT_GRENADELAUNCHER ( 1 << 2)
#define HGRUNT_SHOTGUN ( 1 << 3)
#define HEAD_GROUP 1
#define HEAD_GRUNT 0
#define HEAD_COMMANDER 1
#define HEAD_SHOTGUN 2
#define HEAD_M203 3
#define GUN_GROUP 2
#define GUN_MP5 0
#define GUN_SHOTGUN 1
#define GUN_NONE 2
//=========================================================
// Monster's Anim Events Go Here
//=========================================================
#define HGRUNT_AE_RELOAD ( 2 )
#define HGRUNT_AE_KICK ( 3 )
#define HGRUNT_AE_BURST1 ( 4 )
#define HGRUNT_AE_BURST2 ( 5 )
#define HGRUNT_AE_BURST3 ( 6 )
#define HGRUNT_AE_GREN_TOSS ( 7 )
#define HGRUNT_AE_GREN_LAUNCH ( 8 )
#define HGRUNT_AE_GREN_DROP ( 9 )
#define HGRUNT_AE_CAUGHT_ENEMY ( 10) // grunt established sight with an enemy (player only) that had previously eluded the squad.
#define HGRUNT_AE_DROP_GUN ( 11) // grunt (probably dead) is dropping his mp5.
class CCyberFranklin : public CHGrunt
{
public:
void Spawn(void);
void Precache(void);
int Classify(void);
void HandleAnimEvent(MonsterEvent_t *pEvent);
BOOL CheckMeleeAttack1(float flDot, float flDist);
BOOL CheckRangeAttack1(float flDot, float flDist);
BOOL CheckRangeAttack2(float flDot, float flDist) { return FALSE; }
void CheckAmmo(void) { }
void SetActivity(Activity NewActivity);
void StartTask(Task_t *pTask);
void AlertSound(void);
void DeathSound(void);
void PainSound(void);
void AttackSound(void);
void IdleSound(void) { }
Vector GetGunPosition(void);
void Shoot(void);
virtual int Save( CSave &save );
virtual int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
BOOL m_fCanHornetAttack;
float m_flNextHornetAttackCheck;
static const char *pAttackHitSounds[];
static const char *pAttackMissSounds[];
static const char *pAttackSounds[];
static const char *pDieSounds[];
static const char *pPainSounds[];
static const char *pIdleSounds[];
static const char *pAlertSounds[];
};
LINK_ENTITY_TO_CLASS(monster_th_cyberfranklin, CCyberFranklin);
TYPEDESCRIPTION CCyberFranklin::m_SaveData[] =
{
DEFINE_FIELD(CCyberFranklin, m_fCanHornetAttack, FIELD_BOOLEAN),
DEFINE_FIELD(CCyberFranklin, m_flNextHornetAttackCheck, FIELD_TIME),
};
IMPLEMENT_SAVERESTORE(CCyberFranklin, CHGrunt);
const char *CCyberFranklin::pAttackHitSounds[] =
{
"zombie/claw_strike1.wav",
"zombie/claw_strike2.wav",
"zombie/claw_strike3.wav",
};
const char *CCyberFranklin::pAttackMissSounds[] =
{
"zombie/claw_miss1.wav",
"zombie/claw_miss2.wav",
};
const char *CCyberFranklin::pAttackSounds[] =
{
"franklin/attack1.wav",
};
const char *CCyberFranklin::pDieSounds[] =
{
"franklin/death1.wav",
"franklin/death2.wav",
"franklin/death3.wav",
};
const char *CCyberFranklin::pPainSounds[] =
{
"franklin/pain1.wav",
"franklin/pain2.wav",
};
const char *CCyberFranklin::pAlertSounds[] =
{
"franklin/alert1.wav",
};
//=========================================================
// CheckMeleeAttack1
//=========================================================
BOOL CCyberFranklin::CheckMeleeAttack1(float flDot, float flDist)
{
CBaseMonster *pEnemy;
if (m_hEnemy != NULL)
{
pEnemy = m_hEnemy->MyMonsterPointer();
if (!pEnemy)
{
return FALSE;
}
}
if (flDist <= 72 && flDot >= 0.7 &&
pEnemy->Classify() != CLASS_ALIEN_BIOWEAPON &&
pEnemy->Classify() != CLASS_PLAYER_BIOWEAPON)
{
return TRUE;
}
return FALSE;
}
//=========================================================
// CheckRangeAttack1
//
// !!!LATER - we may want to load balance this. Several
// tracelines are done, so we may not want to do this every
// server frame. Definitely not while firing.
//=========================================================
BOOL CCyberFranklin :: CheckRangeAttack1 ( float flDot, float flDist )
{
if ( gpGlobals->time < m_flNextHornetAttackCheck )
{
return m_fCanHornetAttack;
}
if (HasConditions(bits_COND_SEE_ENEMY) && flDist >= FRANKLIN_MELEE_DIST && flDist <= 1024 && flDot >= 0.5 && NoFriendlyFire())
{
TraceResult tr;
Vector vecArmPos, vecArmDir;
// verify that a shot fired from the gun will hit the enemy before the world.
// !!!LATER - we may wish to do something different for projectile weapons as opposed to instant-hit
UTIL_MakeVectors( pev->angles );
GetAttachment( 0, vecArmPos, vecArmDir );
// UTIL_TraceLine( vecArmPos, vecArmPos + gpGlobals->v_forward * 256, ignore_monsters, ENT(pev), &tr);
UTIL_TraceLine( vecArmPos, m_hEnemy->BodyTarget(vecArmPos), dont_ignore_monsters, ENT(pev), &tr);
if ( tr.flFraction == 1.0 || tr.pHit == m_hEnemy->edict() )
{
m_flNextHornetAttackCheck = gpGlobals->time + RANDOM_FLOAT( 2, 5 );
m_fCanHornetAttack = TRUE;
return m_fCanHornetAttack;
}
}
m_flNextHornetAttackCheck = gpGlobals->time + 0.2;// don't check for half second if this check wasn't successful
m_fCanHornetAttack = FALSE;
return m_fCanHornetAttack;
}
//=========================================================
// DieSound
//=========================================================
void CCyberFranklin::DeathSound(void)
{
EMIT_SOUND(ENT(pev), CHAN_VOICE, RANDOM_SOUND_ARRAY(pDieSounds), 1.0, ATTN_NORM);
}
//=========================================================
// AlertSound
//=========================================================
void CCyberFranklin::AlertSound(void)
{
EMIT_SOUND(ENT(pev), CHAN_VOICE, RANDOM_SOUND_ARRAY(pAlertSounds), 1.0, ATTN_NORM);
}
//=========================================================
// AttackSound
//=========================================================
void CCyberFranklin::AttackSound(void)
{
EMIT_SOUND(ENT(pev), CHAN_VOICE, RANDOM_SOUND_ARRAY(pAttackSounds), 1.0, ATTN_NORM);
}
//=========================================================
// PainSound
//=========================================================
void CCyberFranklin::PainSound(void)
{
if (m_flNextPainTime > gpGlobals->time)
{
return;
}
m_flNextPainTime = gpGlobals->time + 0.6;
EMIT_SOUND(ENT(pev), CHAN_VOICE, RANDOM_SOUND_ARRAY(pPainSounds), 1.0, ATTN_NORM);
}
//=========================================================
// Classify - indicates this monster's place in the
// relationship table.
//=========================================================
int CCyberFranklin::Classify(void)
{
return CLASS_ALIEN_MONSTER;
}
//=========================================================
// GetGunPosition return the end of the barrel
//=========================================================
Vector CCyberFranklin::GetGunPosition()
{
return pev->origin + Vector(0, 0, 48);
}
//=========================================================
// Shoot
//=========================================================
void CCyberFranklin::Shoot(void)
{
// m_vecEnemyLKP should be center of enemy body
Vector vecArmPos, vecArmDir;
Vector vecDirToEnemy;
Vector angDir;
if (HasConditions( bits_COND_SEE_ENEMY))
{
vecDirToEnemy = ( ( m_vecEnemyLKP ) - pev->origin );
angDir = UTIL_VecToAngles( vecDirToEnemy );
vecDirToEnemy = vecDirToEnemy.Normalize();
}
else
{
angDir = pev->angles;
UTIL_MakeAimVectors( angDir );
vecDirToEnemy = gpGlobals->v_forward;
}
pev->effects = EF_MUZZLEFLASH;
// make angles +-180
if (angDir.x > 180)
{
angDir.x = angDir.x - 360;
}
SetBlending( 0, angDir.x );
GetAttachment( 0, vecArmPos, vecArmDir );
vecArmPos = vecArmPos + vecDirToEnemy * 32;
MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, vecArmPos );
WRITE_BYTE( TE_SPRITE );
WRITE_COORD( vecArmPos.x ); // pos
WRITE_COORD( vecArmPos.y );
WRITE_COORD( vecArmPos.z );
WRITE_SHORT( iFranklinMuzzleFlash ); // model
WRITE_BYTE( 6 ); // size * 10
WRITE_BYTE( 128 ); // brightness
MESSAGE_END();
CBaseEntity *pHornet = CBaseEntity::Create( "hornet", vecArmPos, UTIL_VecToAngles( vecDirToEnemy ), edict() );
UTIL_MakeVectors ( pHornet->pev->angles );
pHornet->pev->velocity = gpGlobals->v_forward * 300;
switch ( RANDOM_LONG ( 0 , 2 ) )
{
case 0: EMIT_SOUND_DYN ( ENT(pev), CHAN_WEAPON, "agrunt/ag_fire1.wav", 1.0, ATTN_NORM, 0, 100 ); break;
case 1: EMIT_SOUND_DYN ( ENT(pev), CHAN_WEAPON, "agrunt/ag_fire2.wav", 1.0, ATTN_NORM, 0, 100 ); break;
case 2: EMIT_SOUND_DYN ( ENT(pev), CHAN_WEAPON, "agrunt/ag_fire3.wav", 1.0, ATTN_NORM, 0, 100 ); break;
}
CBaseMonster *pHornetMonster = pHornet->MyMonsterPointer();
if ( pHornetMonster )
{
pHornetMonster->m_hEnemy = m_hEnemy;
}
}
//=========================================================
// HandleAnimEvent - catches the monster-specific messages
// that occur when tagged animation frames are played.
//=========================================================
void CCyberFranklin::HandleAnimEvent(MonsterEvent_t *pEvent)
{
switch( pEvent->event )
{
case HGRUNT_AE_DROP_GUN:
case HGRUNT_AE_RELOAD:
case HGRUNT_AE_GREN_TOSS:
case HGRUNT_AE_GREN_LAUNCH:
case HGRUNT_AE_GREN_DROP:
break;
case HGRUNT_AE_BURST1:
case HGRUNT_AE_BURST2:
case HGRUNT_AE_BURST3:
Shoot();
break;
case HGRUNT_AE_KICK:
{
CBaseEntity *pHurt = Kick();
if ( pHurt )
{
// SOUND HERE!
UTIL_MakeVectors( pev->angles );
if (pHurt->pev->flags & (FL_MONSTER | FL_CLIENT))
{
pHurt->pev->punchangle.x = 15;
}
pHurt->pev->velocity = pHurt->pev->velocity + gpGlobals->v_forward * 100 + gpGlobals->v_up * 50;
pHurt->TakeDamage( pev, pev, gSkillData.hgruntDmgKick, DMG_CLUB );
// 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));
}
break;
default:
CHGrunt::HandleAnimEvent( pEvent );
break;
}
}
//=========================================================
// Spawn
//=========================================================
void CCyberFranklin::Spawn()
{
Precache();
SET_MODEL(ENT(pev), "models/franklin2.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.cyberfranklinHealth;
m_flFieldOfView = 0.2;// indicates the width of this monster's forward view cone ( as a dotproduct result )
m_MonsterState = MONSTERSTATE_NONE;
m_flNextGrenadeCheck = gpGlobals->time + 1;
m_flNextPainTime = gpGlobals->time;
m_iSentence = -1;
m_afCapability = bits_CAP_SQUAD | bits_CAP_TURN_HEAD | bits_CAP_DOORS_GROUP;
m_fEnemyEluded = FALSE;
m_fFirstEncounter = TRUE;// this is true when the grunt spawns, because he hasn't encountered an enemy yet.
m_HackedGunPos = Vector(24, 64, 48);
pev->weapons = HGRUNT_9MMAR;
m_cClipSize = HORNETGUN_MAX_CLIP;
m_cAmmoLoaded = m_cClipSize;
pev->body = 0;
pev->skin = 0;
CTalkMonster::g_talkWaitTime = 0;
MonsterInit();
m_afCapability &= ~bits_CAP_RANGE_ATTACK2;
ClearConditions(bits_COND_NO_AMMO_LOADED);
}
//=========================================================
// Precache - precaches all resources this monster needs
//=========================================================
void CCyberFranklin::Precache()
{
PRECACHE_MODEL("models/franklin2.mdl");
PRECACHE_SOUND_ARRAY(pAttackHitSounds);
PRECACHE_SOUND_ARRAY(pAttackMissSounds);
PRECACHE_SOUND_ARRAY(pDieSounds);
PRECACHE_SOUND_ARRAY(pPainSounds);
PRECACHE_SOUND_ARRAY(pAttackSounds);
PRECACHE_SOUND_ARRAY(pAlertSounds);
PRECACHE_SOUND("franklin/franklin_step.wav");
PRECACHE_SOUND("hassault/hw_shoot1.wav");
iFranklinMuzzleFlash = PRECACHE_MODEL("sprites/muz4.spr");
UTIL_PrecacheOther("hornet");
m_voicePitch = 100;
}
//=========================================================
// SetActivity
//=========================================================
void CCyberFranklin::SetActivity(Activity NewActivity)
{
int iSequence = ACTIVITY_NOT_AVAILABLE;
void *pmodel = GET_MODEL_PTR(ENT(pev));
switch (NewActivity)
{
case ACT_RANGE_ATTACK1:
{
// get crouching shoot
iSequence = LookupSequence("crouching_mp5");
}
break;
default:
CHGrunt::SetActivity(NewActivity);
return;
}
m_Activity = NewActivity; // Go ahead and set this so it doesn't keep trying when the anim is not present
// Set to the desired anim, or default anim if the desired is not present
if (iSequence > ACTIVITY_NOT_AVAILABLE)
{
if (pev->sequence != iSequence || !m_fSequenceLoops)
{
pev->frame = 0;
}
pev->sequence = iSequence; // Set to the reset anim (if it's there)
ResetSequenceInfo();
SetYawSpeed();
}
else
{
// Not available try to get default anim
ALERT(at_console, "%s has no sequence for act:%d\n", STRING(pev->classname), NewActivity);
pev->sequence = 0; // Set to the reset anim (if it's there)
}
}
//=========================================================
// start task
//=========================================================
void CCyberFranklin::StartTask(Task_t *pTask)
{
m_iTaskStatus = TASKSTATUS_RUNNING;
switch (pTask->iTask)
{
case TASK_MELEE_ATTACK1:
AttackSound();
CHGrunt::StartTask(pTask);
break;
default:
CHGrunt::StartTask(pTask);
break;
}
}

99
dlls/Hunger/flame.cpp Normal file
View File

@ -0,0 +1,99 @@
/***
*
* 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 "util.h"
#include "cbase.h"
#include "monsters.h"
#include "schedule.h"
#include "nodes.h"
#include "effects.h"
#include "decals.h"
#include "soundent.h"
#include "game.h"
#include "flame.h"
#include "weapons.h"
LINK_ENTITY_TO_CLASS(flame, CFlame);
TYPEDESCRIPTION CFlame::m_SaveData[] =
{
DEFINE_FIELD(CFlame, m_maxFrame, FIELD_INTEGER),
};
IMPLEMENT_SAVERESTORE(CFlame, CBaseEntity);
void CFlame::Spawn(void)
{
pev->movetype = MOVETYPE_FLY;
pev->solid = SOLID_BBOX;
pev->rendermode = kRenderTransAlpha;
pev->renderamt = 255;
pev->effects = EF_DIMLIGHT;
SET_MODEL(ENT(pev), "sprites/fthrow.spr");
pev->frame = 0;
pev->scale = RANDOM_FLOAT(0.9f, 1.1f);
pev->dmg = gSkillData.plrDmgFlame;
UTIL_SetSize(pev, Vector(0, 0, 0), Vector(0, 0, 0));
m_maxFrame = (float)MODEL_FRAMES(pev->modelindex) - 1;
}
void CFlame::Animate(void)
{
pev->nextthink = gpGlobals->time + 0.1;
pev->frame += 2;
if (pev->frame)
{
if (pev->frame > m_maxFrame)
{
pev->frame = m_maxFrame;
SetThink(&CFlame::SUB_Remove);
pev->nextthink = gpGlobals->time;
}
}
}
void CFlame::Shoot(entvars_t *pevOwner, Vector vecStart, Vector vecVelocity)
{
CFlame *pFlame = GetClassPtr((CFlame *)NULL);
pFlame->Spawn();
UTIL_SetOrigin(pFlame->pev, vecStart);
pFlame->pev->velocity = vecVelocity;
pFlame->pev->owner = ENT(pevOwner);
pFlame->pev->flags |= EF_BRIGHTLIGHT; // Required to make flame glow.
pFlame->SetThink(&CFlame::Animate);
pFlame->pev->nextthink = gpGlobals->time + 0.1;
}
void CFlame::Touch(CBaseEntity *pOther)
{
if (pOther->pev->takedamage)
{
pOther->TakeDamage(pev, pev, pev->dmg, DMG_BURN | DMG_NEVERGIB);
SpawnBlood(pev->origin, pOther->BloodColor(), pev->dmg);
}
SetThink(&CFlame::SUB_Remove);
pev->nextthink = gpGlobals->time;
}

38
dlls/Hunger/flame.h Normal file
View File

@ -0,0 +1,38 @@
/***
*
* 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.
*
****/
#ifndef FLAME_H
#define FLAME_H
//=========================================================
// Flamethrower flame entity
//=========================================================
class CFlame : public CBaseEntity
{
public:
void Spawn(void);
static void Shoot(entvars_t *pevOwner, Vector vecStart, Vector vecVelocity);
void Touch(CBaseEntity *pOther);
void EXPORT Animate(void);
virtual int Save(CSave &save);
virtual int Restore(CRestore &restore);
static TYPEDESCRIPTION m_SaveData[];
int m_maxFrame;
};
#endif // FLAME_H

137
dlls/Hunger/hand.cpp Normal file
View File

@ -0,0 +1,137 @@
/***
*
* 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 "util.h"
#include "cbase.h"
#include "monsters.h"
#include "schedule.h"
#include "game.h"
#include "headcrab.h"
class CHand : public CHeadCrab
{
public:
void Spawn(void);
void Precache(void);
void StartTask(Task_t *pTask);
void EXPORT LeapTouch(CBaseEntity *pOther);
void PainSound(void) { }
void DeathSound(void) { }
void IdleSound(void) { }
void AlertSound(void) { }
void AttackSound(void) { }
static const char *pAttackSounds[];
static const char *pBiteSounds[];
};
LINK_ENTITY_TO_CLASS(einar_hand, CHand);
const char *CHand::pAttackSounds[] =
{
"thehand/hnd_attack1.wav",
};
const char *CHand::pBiteSounds[] =
{
"thehand/hnd_headbite.wav",
};
//=========================================================
// Spawn
//=========================================================
void CHand::Spawn()
{
Precache();
SET_MODEL(ENT(pev), "models/thehand.mdl");
UTIL_SetSize(pev, Vector(-12, -12, 0), Vector(12, 12, 24));
pev->solid = SOLID_SLIDEBOX;
pev->movetype = MOVETYPE_STEP;
m_bloodColor = BLOOD_COLOR_RED;
pev->effects = 0;
pev->health = gSkillData.headcrabHealth;
pev->view_ofs = Vector(0, 0, 20);// position of the eyes relative to monster's origin.
pev->yaw_speed = 5;//!!! should we put this in the monster's changeanim function since turn rates may vary with state/anim?
m_flFieldOfView = 0.5;// indicates the width of this monster's forward view cone ( as a dotproduct result )
m_MonsterState = MONSTERSTATE_NONE;
MonsterInit();
}
//=========================================================
// Precache - precaches all resources this monster needs
//=========================================================
void CHand::Precache()
{
PRECACHE_MODEL("models/thehand.mdl");
PRECACHE_SOUND_ARRAY(pAttackSounds);
PRECACHE_SOUND_ARRAY(pBiteSounds);
PRECACHE_SOUND("headcrab/hc_attack1.wav");
PRECACHE_SOUND("headcrab/hc_attack2.wav");
PRECACHE_SOUND("headcrab/hc_attack3.wav");
}
//=========================================================
// LeapTouch - this is the hand's touch function when it
// is in the air
//=========================================================
void CHand::LeapTouch(CBaseEntity *pOther)
{
if (!pOther->pev->takedamage)
{
return;
}
if (pOther->Classify() == Classify())
{
return;
}
// Don't hit if back on ground
if (!FBitSet(pev->flags, FL_ONGROUND))
{
EMIT_SOUND_DYN(edict(), CHAN_WEAPON, RANDOM_SOUND_ARRAY(pBiteSounds), GetSoundVolue(), ATTN_IDLE, 0, GetVoicePitch());
pOther->TakeDamage(pev, pev, GetDamageAmount(), DMG_SLASH);
}
SetTouch(NULL);
}
void CHand::StartTask(Task_t *pTask)
{
m_iTaskStatus = TASKSTATUS_RUNNING;
switch (pTask->iTask)
{
case TASK_RANGE_ATTACK1:
{
EMIT_SOUND_DYN(edict(), CHAN_WEAPON, pAttackSounds[0], GetSoundVolue(), ATTN_IDLE, 0, GetVoicePitch());
m_IdealActivity = ACT_RANGE_ATTACK1;
SetTouch(&CHand::LeapTouch);
break;
}
default:
{
CHeadCrab::StartTask(pTask);
}
}
}

126
dlls/Hunger/hkg36.cpp Normal file
View File

@ -0,0 +1,126 @@
/***
*
* 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 "weapons.h"
#include "monsters.h"
#include "player.h"
#include "gamerules.h"
enum hkg36_e {
HKG36_IDLE = 0,
HKG36_RELOAD,
HKG36_DRAW,
HKG36_SHOOT1,
};
LINK_ENTITY_TO_CLASS(weapon_th_sniper, CHKG36);
int CHKG36::GetPrimaryAttackActivity(void)
{
return HKG36_SHOOT1;
}
int CHKG36::GetZoomedAttackActivity(void)
{
return HKG36_SHOOT1;
}
int CHKG36::GetItemInfo(ItemInfo *p)
{
p->pszName = STRING(pev->classname);
p->pszAmmo1 = "sniper";
p->iMaxAmmo1 = SNIPER_MAX_CARRY;
p->pszAmmo2 = NULL;
p->iMaxAmmo2 = -1;
p->iMaxClip = SNIPER_MAX_CLIP;
p->iFlags = 0;
p->iSlot = 2;
p->iPosition = 3;
p->iId = m_iId = WEAPON_HKG36;
p->iWeight = SNIPER_WEIGHT;
return 1;
}
void CHKG36::Spawn()
{
Precache();
m_iId = WEAPON_HKG36;
SET_MODEL(ENT(pev), "models/w_hkg36.mdl");
m_iDefaultAmmo = SNIPER_DEFAULT_GIVE;
FallInit();// get ready to fall down.
}
void CHKG36::Precache(void)
{
PRECACHE_MODEL("models/v_hkg36.mdl");
PRECACHE_MODEL("models/w_hkg36.mdl");
PRECACHE_MODEL("models/p_hkg36.mdl");
PRECACHE_MODEL("models/w_antidote.mdl");
PRECACHE_SOUND("items/9mmclip1.wav");
PRECACHE_SOUND("weapons/sniper.wav");
PRECACHE_SOUND("weapons/ap9_bolt.wav");
PRECACHE_SOUND("weapons/ap9_clipin.wav");
PRECACHE_SOUND("weapons/ap9_clipout.wav");
PRECACHE_SOUND("weapons/357_cock1.wav");
m_usFireSniper = PRECACHE_EVENT(1, "events/sniper.sc");
}
BOOL CHKG36::Deploy()
{
BOOL bResult = DefaultDeploy("models/v_hkg36.mdl", "models/p_hkg36.mdl", HKG36_DRAW, "hkg36", UseDecrement());
if ( bResult )
{
m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 1.0;
}
return bResult;
}
void CHKG36::Reload(void)
{
if (m_pPlayer->ammo_sniper <= 0)
return;
int iResult = DefaultReload(SNIPER_MAX_CLIP, HKG36_RELOAD, 3.8);
if (iResult)
{
CSniper::Reload();
}
}
void CHKG36::WeaponIdle(void)
{
CSniper::WeaponIdle();
if (m_flTimeWeaponIdle > UTIL_WeaponTimeBase())
return;
m_flTimeWeaponIdle = 17.0 / 30.0;
SendWeaponAnim(HKG36_IDLE, UseDecrement());
}

169
dlls/Hunger/medkit.cpp Normal file
View File

@ -0,0 +1,169 @@
/***
*
* 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"
enum medkit_e {
MEDKIT_IDLE = 0,
MEDKIT_LONGIDLE,
MEDKIT_LONGUSE,
MEDKIT_SHORTUSE,
MEDKIT_HOLSTER,
MEDKIT_DRAW,
};
LINK_ENTITY_TO_CLASS(weapon_th_medkit, CMedkit);
void CMedkit::Spawn()
{
Precache();
m_iId = WEAPON_MEDKIT;
SET_MODEL(ENT(pev), "models/w_tfc_medkit.mdl");
m_iDefaultAmmo = MEDKIT_DEFAULT_GIVE;
m_flSoundDelay = 0;
FallInit();// get ready to fall down.
}
void CMedkit::Precache(void)
{
PRECACHE_MODEL("models/v_tfc_medkit.mdl");
PRECACHE_MODEL("models/w_tfc_medkit.mdl");
PRECACHE_MODEL("models/p_tfc_medkit.mdl");
PRECACHE_SOUND("items/9mmclip1.wav");
PRECACHE_SOUND("items/medshot4.wav");
PRECACHE_SOUND("items/medshotno1.wav");
m_usMedkit = PRECACHE_EVENT(1, "events/medkit.sc");
}
int CMedkit::GetItemInfo(ItemInfo *p)
{
p->pszName = STRING(pev->classname);
p->pszAmmo1 = "Hornets";
p->iMaxAmmo1 = MEDKIT_MAX_CARRY;
p->pszAmmo2 = NULL;
p->iMaxAmmo2 = -1;
p->iMaxClip = WEAPON_NOCLIP;
p->iSlot = 4;
p->iPosition = 4;
p->iId = m_iId = WEAPON_MEDKIT;
p->iWeight = MEDKIT_WEIGHT;
p->iFlags = ITEM_FLAG_LIMITINWORLD | ITEM_FLAG_EXHAUSTIBLE;
return 1;
}
BOOL CMedkit::Deploy()
{
m_flSoundDelay = 0;
return DefaultDeploy("models/v_tfc_medkit.mdl", "models/p_tfc_medkit.mdl", MEDKIT_DRAW, "medkit");
}
void CMedkit::Holster(int skiplocal /*= 0*/)
{
m_flSoundDelay = 0;
m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.5;
SendWeaponAnim(MEDKIT_HOLSTER);
}
void CMedkit::PrimaryAttack(void)
{
if (m_pPlayer->pev->health >= m_pPlayer->pev->max_health)
return;
if (m_pPlayer->ammo_hornets <= 0)
{
PlayEmptySound();
m_flNextPrimaryAttack = 1.0;
return;
}
PLAYBACK_EVENT(0, m_pPlayer->edict(), m_usMedkit);
m_flNextPrimaryAttack = GetNextAttackDelay(2.4);
if (m_flNextPrimaryAttack < UTIL_WeaponTimeBase())
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 2.4;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + UTIL_SharedRandomFloat(m_pPlayer->random_seed, 10, 15);
m_flSoundDelay = gpGlobals->time + (38.0 / 30.0);
}
void CMedkit::WeaponIdle(void)
{
ResetEmptySound();
m_pPlayer->GetAutoaimVector(AUTOAIM_10DEGREES);
if (m_flSoundDelay != 0 && m_flSoundDelay <= gpGlobals->time)
{
// player "shoot" animation
m_pPlayer->SetAnimation(PLAYER_ATTACK1);
if ( m_pPlayer->TakeHealth(gSkillData.medkitHeal, DMG_GENERIC) )
{
m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]--;
}
EMIT_SOUND_DYN(ENT(pev), CHAN_WEAPON, "items/medshot4.wav", 1.0, ATTN_NORM, 0, RANDOM_LONG(90, 100));
m_flSoundDelay = 0;
}
if (m_flTimeWeaponIdle > UTIL_WeaponTimeBase())
return;
int iAnim;
float flRand = UTIL_SharedRandomFloat(m_pPlayer->random_seed, 0.0, 1.0);
if (flRand <= 0.75)
{
iAnim = MEDKIT_LONGIDLE;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 72.0 / 30.0;
}
else
{
iAnim = MEDKIT_IDLE;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 36.0 / 30.0;
}
SendWeaponAnim(iAnim, 1);
}
BOOL CMedkit::PlayEmptySound(void)
{
if (m_iPlayEmptySound)
{
EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_WEAPON, "items/medshotno1.wav", 0.8, ATTN_NORM);
m_iPlayEmptySound = 0;
return 0;
}
return 0;
}

213
dlls/Hunger/megasquid.cpp Normal file
View File

@ -0,0 +1,213 @@
/***
*
* 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 "util.h"
#include "cbase.h"
#include "monsters.h"
#include "schedule.h"
#include "nodes.h"
#include "effects.h"
#include "decals.h"
#include "soundent.h"
#include "game.h"
#include "bullsquid.h"
extern int iSquidSpitSprite;
//=========================================================
// Monster's Anim Events Go Here
//=========================================================
#define MSQUID_AE_SPIT ( 1 )
#define MSQUID_AE_BITE ( 2 )
#define MSQUID_AE_BLINK ( 3 )
#define MSQUID_AE_TAILWHIP ( 4 )
#define MSQUID_AE_HOP ( 5 )
#define MSQUID_AE_THROW ( 6 )
class CMegasquid : public CBullsquid
{
public:
void Spawn(void);
void Precache(void);
void HandleAnimEvent(MonsterEvent_t *pEvent);
BOOL CheckMeleeAttack1(float flDot, float flDist) { return FALSE; }
BOOL CheckMeleeAttack2(float flDot, float flDist);
};
LINK_ENTITY_TO_CLASS(monster_th_megasquid, CMegasquid);
//=========================================================
// Spawn
//=========================================================
void CMegasquid::Spawn()
{
Precache();
SET_MODEL(ENT(pev), "models/megasquid.mdl");
UTIL_SetSize(pev, Vector(-160, -160, 0), Vector(160, 160, 256));
pev->solid = SOLID_SLIDEBOX;
pev->movetype = MOVETYPE_STEP;
m_bloodColor = BLOOD_COLOR_RED;
pev->effects = 0;
pev->health = gSkillData.megasquidHealth;
m_flFieldOfView = 0.2;// indicates the width of this monster's forward view cone ( as a dotproduct result )
m_MonsterState = MONSTERSTATE_NONE;
m_fCanThreatDisplay = FALSE;
m_flNextSpitTime = gpGlobals->time;
pev->view_ofs = Vector(0, 0, 128);
MonsterInit();
// Remove tail whip attack.
m_afCapability &= ~bits_CAP_MELEE_ATTACK1;
}
//=========================================================
// Precache - precaches all resources this monster needs
//=========================================================
void CMegasquid::Precache()
{
CBullsquid::Precache();
PRECACHE_MODEL("models/megasquid.mdl");
}
//=========================================================
// CheckMeleeAttack2 - bullsquid is a big guy, so has a longer
// melee range than most monsters. This is the bite attack.
// this attack will not be performed if the tailwhip attack
// is valid.
//=========================================================
BOOL CMegasquid::CheckMeleeAttack2(float flDot, float flDist)
{
if (flDist <= 200 && flDot >= 0.7) // The player & bullsquid can be as much as their bboxes
{ // apart (48 * sqrt(3)) and he can still attack (85 is a little more than 48*sqrt(3))
return TRUE;
}
return FALSE;
}
//=========================================================
// HandleAnimEvent - catches the monster-specific messages
// that occur when tagged animation frames are played.
//=========================================================
void CMegasquid::HandleAnimEvent(MonsterEvent_t *pEvent)
{
switch (pEvent->event)
{
case MSQUID_AE_SPIT:
{
Vector vecSpitOffset;
Vector vecSpitDir;
UTIL_MakeVectors ( pev->angles );
// !!!HACKHACK - the spot at which the spit originates (in front of the mouth) was measured in 3ds and hardcoded here.
// we should be able to read the position of bones at runtime for this info.
vecSpitOffset = ( gpGlobals->v_right * 40 + gpGlobals->v_forward * 185 + gpGlobals->v_up * 115 ); // 8 37 23
vecSpitOffset = ( pev->origin + vecSpitOffset );
vecSpitDir = ( ( m_hEnemy->pev->origin + m_hEnemy->pev->view_ofs ) - vecSpitOffset ).Normalize();
vecSpitDir.x += RANDOM_FLOAT( -0.05, 0.05 );
vecSpitDir.y += RANDOM_FLOAT( -0.05, 0.05 );
vecSpitDir.z += RANDOM_FLOAT( -0.05, 0 );
// do stuff for this event.
AttackSound();
// spew the spittle temporary ents.
MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, vecSpitOffset );
WRITE_BYTE( TE_SPRITE_SPRAY );
WRITE_COORD( vecSpitOffset.x); // pos
WRITE_COORD( vecSpitOffset.y);
WRITE_COORD( vecSpitOffset.z);
WRITE_COORD( vecSpitDir.x); // dir
WRITE_COORD( vecSpitDir.y);
WRITE_COORD( vecSpitDir.z);
WRITE_SHORT( iSquidSpitSprite ); // model
WRITE_BYTE ( 15 ); // count
WRITE_BYTE ( 210 ); // speed
WRITE_BYTE ( 25 ); // noise ( client will divide by 100 )
MESSAGE_END();
CSquidSpit::Shoot( pev, vecSpitOffset, vecSpitDir * 900 );
}
break;
case MSQUID_AE_BITE:
{
// SOUND HERE!
CBaseEntity *pHurt = CheckTraceHullAttack(220, gSkillData.bullsquidDmgBite, DMG_SLASH);
if (pHurt)
{
//pHurt->pev->punchangle.z = -15;
//pHurt->pev->punchangle.x = -45;
pHurt->pev->velocity = pHurt->pev->velocity - gpGlobals->v_forward * 100;
pHurt->pev->velocity = pHurt->pev->velocity + gpGlobals->v_up * 100;
}
}
break;
case MSQUID_AE_THROW:
{
int iPitch;
// squid throws its prey IF the prey is a client.
CBaseEntity *pHurt = CheckTraceHullAttack(220, 0, 0);
if (pHurt)
{
// croonchy bite sound
iPitch = RANDOM_FLOAT(90, 110);
switch (RANDOM_LONG(0, 1))
{
case 0:
EMIT_SOUND_DYN(ENT(pev), CHAN_WEAPON, "bullchicken/bc_bite2.wav", 1, ATTN_NORM, 0, iPitch);
break;
case 1:
EMIT_SOUND_DYN(ENT(pev), CHAN_WEAPON, "bullchicken/bc_bite3.wav", 1, ATTN_NORM, 0, iPitch);
break;
}
//pHurt->pev->punchangle.x = RANDOM_LONG(0,34) - 5;
//pHurt->pev->punchangle.z = RANDOM_LONG(0,49) - 25;
//pHurt->pev->punchangle.y = RANDOM_LONG(0,89) - 45;
// screeshake transforms the viewmodel as well as the viewangle. No problems with seeing the ends of the viewmodels.
UTIL_ScreenShake(pHurt->pev->origin, 25.0, 1.5, 0.7, 2);
if (pHurt->IsPlayer())
{
UTIL_MakeVectors(pev->angles);
pHurt->pev->velocity = pHurt->pev->velocity + gpGlobals->v_forward * 300 + gpGlobals->v_up * 300;
}
}
}
break;
default:
CBullsquid::HandleAnimEvent(pEvent);
}
}

284
dlls/Hunger/shovel.cpp Normal file
View File

@ -0,0 +1,284 @@
/***
*
* 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 "gamerules.h"
#define SHOVEL_BODYHIT_VOLUME 128
#define SHOVEL_WALLHIT_VOLUME 512
void FindHullIntersection(const Vector &vecSrc, TraceResult &tr, float *mins, float *maxs, edict_t *pEntity);
LINK_ENTITY_TO_CLASS(weapon_th_shovel, CShovel);
enum shovel_e {
SHOVEL_IDLE = 0,
SHOVEL_DRAW,
SHOVEL_HOLSTER,
SHOVEL_ATTACK1HIT,
SHOVEL_ATTACK1MISS,
SHOVEL_ATTACK2MISS,
SHOVEL_ATTACK2HIT,
SHOVEL_ATTACK3MISS,
SHOVEL_ATTACK3HIT,
SHOVEL_IDLE2,
SHOVEL_IDLE3,
};
void CShovel::Spawn()
{
Precache();
m_iId = WEAPON_SHOVEL;
SET_MODEL(ENT(pev), "models/w_shovel.mdl");
m_iClip = -1;
FallInit();// get ready to fall down.
}
void CShovel::Precache(void)
{
PRECACHE_MODEL("models/v_shovel.mdl");
PRECACHE_MODEL("models/w_shovel.mdl");
PRECACHE_MODEL("models/p_shovel.mdl");
PRECACHE_SOUND("weapons/cbar_hit1.wav");
PRECACHE_SOUND("weapons/cbar_hit2.wav");
PRECACHE_SOUND("weapons/cbar_hitbod1.wav");
PRECACHE_SOUND("weapons/cbar_hitbod2.wav");
PRECACHE_SOUND("weapons/cbar_hitbod3.wav");
PRECACHE_SOUND("weapons/cbar_miss1.wav");
PRECACHE_SOUND("kelly/cbar_hitkelly1.wav");
PRECACHE_SOUND("kelly/cbar_hitkelly2.wav");
PRECACHE_SOUND("kelly/cbar_hitkelly3.wav");
m_usShovel = PRECACHE_EVENT(1, "events/shovel.sc");
}
int CShovel::GetItemInfo(ItemInfo *p)
{
p->pszName = STRING(pev->classname);
p->pszAmmo1 = NULL;
p->iMaxAmmo1 = -1;
p->pszAmmo2 = NULL;
p->iMaxAmmo2 = -1;
p->iMaxClip = WEAPON_NOCLIP;
p->iSlot = 0;
p->iPosition = 1;
p->iId = WEAPON_SHOVEL;
p->iWeight = SHOVEL_WEIGHT;
return 1;
}
BOOL CShovel::Deploy()
{
return DefaultDeploy("models/v_shovel.mdl", "models/p_shovel.mdl", SHOVEL_DRAW, "shovel");
}
void CShovel::Holster(int skiplocal /* = 0 */)
{
m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.5;
SendWeaponAnim(SHOVEL_HOLSTER);
}
void CShovel::PrimaryAttack()
{
if (!Swing(1))
{
SetThink(&CShovel::SwingAgain);
pev->nextthink = gpGlobals->time + 0.1;
}
}
int CShovel::Swing(int fFirst)
{
int fDidHit = FALSE;
TraceResult tr;
UTIL_MakeVectors(m_pPlayer->pev->v_angle);
Vector vecSrc = m_pPlayer->GetGunPosition();
Vector vecEnd = vecSrc + gpGlobals->v_forward * 32;
UTIL_TraceLine(vecSrc, vecEnd, dont_ignore_monsters, ENT(m_pPlayer->pev), &tr);
#ifndef CLIENT_DLL
if (tr.flFraction >= 1.0)
{
UTIL_TraceHull(vecSrc, vecEnd, dont_ignore_monsters, head_hull, ENT(m_pPlayer->pev), &tr);
if (tr.flFraction < 1.0)
{
// Calculate the point of intersection of the line (or hull) and the object we hit
// This is and approximation of the "best" intersection
CBaseEntity *pHit = CBaseEntity::Instance(tr.pHit);
if (!pHit || pHit->IsBSPModel())
FindHullIntersection(vecSrc, tr, VEC_DUCK_HULL_MIN, VEC_DUCK_HULL_MAX, m_pPlayer->edict());
vecEnd = tr.vecEndPos; // This is the point on the actual surface (the hull could have hit space)
}
}
#endif
PLAYBACK_EVENT_FULL(FEV_NOTHOST, m_pPlayer->edict(), m_usShovel,
0.0, (float *)&g_vecZero, (float *)&g_vecZero, 0, 0, 0,
0.0, 0, 0.0);
if (tr.flFraction >= 1.0)
{
if (fFirst)
{
// miss
m_flNextPrimaryAttack = GetNextAttackDelay(0.56); // 0.5
// player "shoot" animation
m_pPlayer->SetAnimation(PLAYER_ATTACK1);
}
}
else
{
// switch (((m_iSwing++) % 2) + 1)
switch (RANDOM_LONG(0, 2))
{
case 0:
SendWeaponAnim(SHOVEL_ATTACK1MISS); break;
case 1:
SendWeaponAnim(SHOVEL_ATTACK2MISS); break;
case 2:
SendWeaponAnim(SHOVEL_ATTACK3MISS); break;
}
// player "shoot" animation
m_pPlayer->SetAnimation(PLAYER_ATTACK1);
#ifndef CLIENT_DLL
// hit
fDidHit = TRUE;
CBaseEntity *pEntity = CBaseEntity::Instance(tr.pHit);
ClearMultiDamage();
if ((m_flNextPrimaryAttack + 1 < UTIL_WeaponTimeBase()) || g_pGameRules->IsMultiplayer())
{
// first swing does full damage
pEntity->TraceAttack(m_pPlayer->pev, gSkillData.plrDmgShovel, gpGlobals->v_forward, &tr, DMG_CLUB);
}
else
{
// subsequent swings do half
pEntity->TraceAttack(m_pPlayer->pev, gSkillData.plrDmgShovel / 2, gpGlobals->v_forward, &tr, DMG_CLUB);
}
ApplyMultiDamage(m_pPlayer->pev, m_pPlayer->pev);
// play thwack, smack, or dong sound
float flVol = 1.0;
int fHitWorld = TRUE;
if (pEntity)
{
if (pEntity->Classify() != CLASS_NONE && pEntity->Classify() != CLASS_MACHINE)
{
// Skeletons make different hit sounds.
if (pEntity->Classify() == CLASS_SKELETON)
{
// play thwack or smack sound
switch (RANDOM_LONG(0, 2))
{
case 0:
EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_ITEM, "kelly/cbar_hitkelly1.wav", 1, ATTN_NORM); break;
case 1:
EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_ITEM, "kelly/cbar_hitkelly2.wav", 1, ATTN_NORM); break;
case 2:
EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_ITEM, "kelly/cbar_hitkelly3.wav", 1, ATTN_NORM); break;
}
}
else
{
// play thwack or smack sound
switch (RANDOM_LONG(0, 2))
{
case 0:
EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/cbar_hitbod1.wav", 1, ATTN_NORM); break;
case 1:
EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/cbar_hitbod2.wav", 1, ATTN_NORM); break;
case 2:
EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/cbar_hitbod3.wav", 1, ATTN_NORM); break;
}
}
m_pPlayer->m_iWeaponVolume = SHOVEL_BODYHIT_VOLUME;
if (!pEntity->IsAlive())
return TRUE;
else
flVol = 0.1;
fHitWorld = FALSE;
}
}
// play texture hit sound
// UNDONE: Calculate the correct point of intersection when we hit with the hull instead of the line
if (fHitWorld)
{
float fvolbar = TEXTURETYPE_PlaySound(&tr, vecSrc, vecSrc + (vecEnd - vecSrc) * 2, BULLET_PLAYER_CROWBAR);
if (g_pGameRules->IsMultiplayer())
{
// override the volume here, cause we don't play texture sounds in multiplayer,
// and fvolbar is going to be 0 from the above call.
fvolbar = 1;
}
// also play crowbar strike
switch (RANDOM_LONG(0, 1))
{
case 0:
EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/cbar_hit1.wav", fvolbar, ATTN_NORM, 0, 98 + RANDOM_LONG(0, 3));
break;
case 1:
EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/cbar_hit2.wav", fvolbar, ATTN_NORM, 0, 98 + RANDOM_LONG(0, 3));
break;
}
// delay the decal a bit
m_trHit = tr;
}
m_pPlayer->m_iWeaponVolume = flVol * SHOVEL_WALLHIT_VOLUME;
#endif
m_flNextPrimaryAttack = GetNextAttackDelay(0.26); // 0.25
SetThink(&CShovel::Smack);
pev->nextthink = UTIL_WeaponTimeBase() + 0.2;
}
return fDidHit;
}

207
dlls/Hunger/sniper.cpp Normal file
View File

@ -0,0 +1,207 @@
/***
*
* 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 "weapons.h"
#include "monsters.h"
#include "player.h"
#include "gamerules.h"
extern int gmsgZoom;
int CSniper::AddToPlayer(CBasePlayer *pPlayer)
{
if (CBasePlayerWeapon::AddToPlayer(pPlayer))
{
MESSAGE_BEGIN(MSG_ONE, gmsgWeapPickup, NULL, pPlayer->pev);
WRITE_BYTE(m_iId);
MESSAGE_END();
return TRUE;
}
return FALSE;
}
void CSniper::Holster(int skiplocal /* = 0 */)
{
m_fInReload = FALSE;// cancel any reload in progress.
if (m_fInZoom)
{
SecondaryAttack();
}
m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 1.0;
m_flTimeWeaponIdle = UTIL_SharedRandomFloat(m_pPlayer->random_seed, 10, 15);
}
void CSniper::SniperFire(float flSpread, float flCycleTime, BOOL fUseAutoAim, int iActivity)
{
// don't fire underwater
if (m_pPlayer->pev->waterlevel == 3)
{
PlayEmptySound();
m_flNextPrimaryAttack = 0.15;
return;
}
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;
}
return;
}
m_pPlayer->m_iWeaponVolume = LOUD_GUN_VOLUME;
m_pPlayer->m_iWeaponFlash = BRIGHT_GUN_FLASH;
m_iClip--;
m_pPlayer->pev->effects = (int)(m_pPlayer->pev->effects) | EF_MUZZLEFLASH;
// player "shoot" animation
m_pPlayer->SetAnimation(PLAYER_ATTACK1);
UTIL_MakeVectors(m_pPlayer->pev->v_angle + m_pPlayer->pev->punchangle);
Vector vecSrc = m_pPlayer->GetGunPosition();
Vector vecAiming;
if (fUseAutoAim)
{
vecAiming = m_pPlayer->GetAutoaimVector(AUTOAIM_10DEGREES);
}
else
{
vecAiming = gpGlobals->v_forward;
}
Vector vecDir;
vecDir = m_pPlayer->FireBulletsPlayer(1, vecSrc, vecAiming, Vector(flSpread, flSpread, flSpread), 8192, BULLET_PLAYER_SNIPER, 0, 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_usFireSniper, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, vecDir.x, vecDir.y, iActivity, 0, 0, 0);
m_flNextPrimaryAttack = m_flNextSecondaryAttack = GetNextAttackDelay(flCycleTime);
m_flNextPrimaryAttack = m_flNextSecondaryAttack = GetNextAttackDelay(flCycleTime);
if (m_flNextPrimaryAttack < UTIL_WeaponTimeBase())
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + flCycleTime;
if (m_flNextSecondaryAttack < UTIL_WeaponTimeBase())
m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + flCycleTime;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + UTIL_SharedRandomFloat(m_pPlayer->random_seed, 10, 15);
}
void CSniper::SecondaryAttack(void)
{
ToggleZoom();
m_flNextPrimaryAttack = m_flNextSecondaryAttack = GetNextAttackDelay(0.5);
}
void CSniper::PrimaryAttack()
{
BOOL fUseAutoAim;
int iAnim;
float flSpread;
float flCycleTime;
fUseAutoAim = TRUE;
iAnim = m_fInZoom ? GetZoomedAttackActivity() : GetPrimaryAttackActivity();
flSpread = m_fInZoom ? 0.01 : 0.03;
flCycleTime = m_fInZoom ? 0.7 : 0.1;
SniperFire(flSpread, flCycleTime, fUseAutoAim, iAnim);
}
void CSniper::Reload(void)
{
if (m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0)
return;
if (m_fInZoom)
{
SetZoomState(FALSE);
}
}
void CSniper::WeaponIdle(void)
{
ResetEmptySound();
m_pPlayer->GetAutoaimVector(AUTOAIM_10DEGREES);
}
void CSniper::SetZoomState(BOOL bState)
{
m_fInZoom = bState;
m_pPlayer->pev->fov = m_pPlayer->m_iFOV = bState ? 40 : 0; // 0 means reset to default fov
#ifndef CLIENT_DLL
// Toggle Zoom HUD.
MESSAGE_BEGIN(MSG_ONE, gmsgZoom, NULL, m_pPlayer->pev);
WRITE_BYTE( bState );
WRITE_BYTE( m_iId );
MESSAGE_END();
#endif
}
void CSniper::ToggleZoom(void)
{
SetZoomState(!m_fInZoom);
}
class CSniperAmmo : public CBasePlayerAmmo
{
void Spawn(void)
{
Precache();
SET_MODEL(ENT(pev), "models/w_antidote.mdl");
CBasePlayerAmmo::Spawn();
}
void Precache(void)
{
PRECACHE_MODEL("models/w_antidote.mdl");
PRECACHE_SOUND("items/9mmclip1.wav");
}
BOOL AddAmmo(CBaseEntity *pOther)
{
if (pOther->GiveAmmo(AMMO_SNIPER_GIVE, "sniper", SNIPER_MAX_CARRY) != -1)
{
EMIT_SOUND(ENT(pev), CHAN_ITEM, "items/9mmclip1.wav", 1, ATTN_NORM);
return TRUE;
}
return FALSE;
}
};
LINK_ENTITY_TO_CLASS(ammo_th_sniper, CSniperAmmo);
LINK_ENTITY_TO_CLASS(ammo_einar1, CSniperAmmo);

275
dlls/Hunger/spanner.cpp Normal file
View File

@ -0,0 +1,275 @@
/***
*
* 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 "gamerules.h"
#define SPANNER_BODYHIT_VOLUME 128
#define SPANNER_WALLHIT_VOLUME 512
void FindHullIntersection(const Vector &vecSrc, TraceResult &tr, float *mins, float *maxs, edict_t *pEntity);
LINK_ENTITY_TO_CLASS(weapon_th_spanner, CSpanner);
enum spanner_e {
SPANNER_IDLE = 0,
SPANNER_ATTACK1,
SPANNER_ATTACK2,
SPANNER_USE,
SPANNER_DRAW,
SPANNER_HOLSTER,
};
void CSpanner::Spawn()
{
Precache();
m_iId = WEAPON_SPANNER;
SET_MODEL(ENT(pev), "models/backpack.mdl");
m_iClip = -1;
FallInit();// get ready to fall down.
}
void CSpanner::Precache(void)
{
PRECACHE_MODEL("models/v_tfc_spanner.mdl");
PRECACHE_MODEL("models/backpack.mdl");
PRECACHE_MODEL("models/p_spanner.mdl");
PRECACHE_SOUND("weapons/cbar_hit1.wav");
PRECACHE_SOUND("weapons/cbar_hit2.wav");
PRECACHE_SOUND("weapons/cbar_hitbod1.wav");
PRECACHE_SOUND("weapons/cbar_hitbod2.wav");
PRECACHE_SOUND("weapons/cbar_hitbod3.wav");
PRECACHE_SOUND("weapons/cbar_miss1.wav");
PRECACHE_SOUND("kelly/cbar_hitkelly1.wav");
PRECACHE_SOUND("kelly/cbar_hitkelly2.wav");
PRECACHE_SOUND("kelly/cbar_hitkelly3.wav");
m_usSpanner = PRECACHE_EVENT(1, "events/spanner.sc");
}
int CSpanner::GetItemInfo(ItemInfo *p)
{
p->pszName = STRING(pev->classname);
p->pszAmmo1 = NULL;
p->iMaxAmmo1 = -1;
p->pszAmmo2 = NULL;
p->iMaxAmmo2 = -1;
p->iMaxClip = WEAPON_NOCLIP;
p->iSlot = 0;
p->iPosition = 2;
p->iId = WEAPON_SPANNER;
p->iWeight = SPANNER_WEIGHT;
return 1;
}
BOOL CSpanner::Deploy()
{
return DefaultDeploy("models/v_tfc_spanner.mdl", "models/p_spanner.mdl", SPANNER_DRAW, "spanner");
}
void CSpanner::Holster(int skiplocal /* = 0 */)
{
m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.5;
SendWeaponAnim(SPANNER_HOLSTER);
}
void CSpanner::PrimaryAttack()
{
if (!Swing(1))
{
SetThink(&CSpanner::SwingAgain);
pev->nextthink = gpGlobals->time + 0.1;
}
}
int CSpanner::Swing(int fFirst)
{
int fDidHit = FALSE;
TraceResult tr;
UTIL_MakeVectors(m_pPlayer->pev->v_angle);
Vector vecSrc = m_pPlayer->GetGunPosition();
Vector vecEnd = vecSrc + gpGlobals->v_forward * 32;
UTIL_TraceLine(vecSrc, vecEnd, dont_ignore_monsters, ENT(m_pPlayer->pev), &tr);
#ifndef CLIENT_DLL
if (tr.flFraction >= 1.0)
{
UTIL_TraceHull(vecSrc, vecEnd, dont_ignore_monsters, head_hull, ENT(m_pPlayer->pev), &tr);
if (tr.flFraction < 1.0)
{
// Calculate the point of intersection of the line (or hull) and the object we hit
// This is and approximation of the "best" intersection
CBaseEntity *pHit = CBaseEntity::Instance(tr.pHit);
if (!pHit || pHit->IsBSPModel())
FindHullIntersection(vecSrc, tr, VEC_DUCK_HULL_MIN, VEC_DUCK_HULL_MAX, m_pPlayer->edict());
vecEnd = tr.vecEndPos; // This is the point on the actual surface (the hull could have hit space)
}
}
#endif
PLAYBACK_EVENT_FULL(FEV_NOTHOST, m_pPlayer->edict(), m_usSpanner,
0.0, (float *)&g_vecZero, (float *)&g_vecZero, 0, 0, 0,
0.0, 0, 0.0);
if (tr.flFraction >= 1.0)
{
if (fFirst)
{
// miss
m_flNextPrimaryAttack = GetNextAttackDelay(0.38); // 0.5
// player "shoot" animation
m_pPlayer->SetAnimation(PLAYER_ATTACK1);
}
}
else
{
switch ((m_iSwing++) % 2)
{
case 0:
SendWeaponAnim(SPANNER_ATTACK1); break;
case 1:
SendWeaponAnim(SPANNER_ATTACK2); break;
}
// player "shoot" animation
m_pPlayer->SetAnimation(PLAYER_ATTACK1);
#ifndef CLIENT_DLL
// hit
fDidHit = TRUE;
CBaseEntity *pEntity = CBaseEntity::Instance(tr.pHit);
ClearMultiDamage();
if ((m_flNextPrimaryAttack + 1 < UTIL_WeaponTimeBase()) || g_pGameRules->IsMultiplayer())
{
// first swing does full damage
pEntity->TraceAttack(m_pPlayer->pev, gSkillData.plrDmgSpanner, gpGlobals->v_forward, &tr, DMG_CLUB);
}
else
{
// subsequent swings do half
pEntity->TraceAttack(m_pPlayer->pev, gSkillData.plrDmgSpanner / 2, gpGlobals->v_forward, &tr, DMG_CLUB);
}
ApplyMultiDamage(m_pPlayer->pev, m_pPlayer->pev);
// play thwack, smack, or dong sound
float flVol = 1.0;
int fHitWorld = TRUE;
if (pEntity)
{
if (pEntity->Classify() != CLASS_NONE && pEntity->Classify() != CLASS_MACHINE)
{
// Skeletons make different hit sounds.
if (pEntity->Classify() == CLASS_SKELETON)
{
// play thwack or smack sound
switch (RANDOM_LONG(0, 2))
{
case 0:
EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_ITEM, "kelly/cbar_hitkelly1.wav", 1, ATTN_NORM); break;
case 1:
EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_ITEM, "kelly/cbar_hitkelly2.wav", 1, ATTN_NORM); break;
case 2:
EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_ITEM, "kelly/cbar_hitkelly3.wav", 1, ATTN_NORM); break;
}
}
else
{
// play thwack or smack sound
switch (RANDOM_LONG(0, 2))
{
case 0:
EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/cbar_hitbod1.wav", 1, ATTN_NORM); break;
case 1:
EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/cbar_hitbod2.wav", 1, ATTN_NORM); break;
case 2:
EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/cbar_hitbod3.wav", 1, ATTN_NORM); break;
}
}
m_pPlayer->m_iWeaponVolume = SPANNER_BODYHIT_VOLUME;
if (!pEntity->IsAlive())
return TRUE;
else
flVol = 0.1;
fHitWorld = FALSE;
}
}
// play texture hit sound
// UNDONE: Calculate the correct point of intersection when we hit with the hull instead of the line
if (fHitWorld)
{
float fvolbar = TEXTURETYPE_PlaySound(&tr, vecSrc, vecSrc + (vecEnd - vecSrc) * 2, BULLET_PLAYER_CROWBAR);
if (g_pGameRules->IsMultiplayer())
{
// override the volume here, cause we don't play texture sounds in multiplayer,
// and fvolbar is going to be 0 from the above call.
fvolbar = 1;
}
// also play crowbar strike
switch (RANDOM_LONG(0, 1))
{
case 0:
EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/cbar_hit1.wav", fvolbar, ATTN_NORM, 0, 98 + RANDOM_LONG(0, 3));
break;
case 1:
EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/cbar_hit2.wav", fvolbar, ATTN_NORM, 0, 98 + RANDOM_LONG(0, 3));
break;
}
// delay the decal a bit
m_trHit = tr;
}
m_pPlayer->m_iWeaponVolume = flVol * SPANNER_WALLHIT_VOLUME;
#endif
m_flNextPrimaryAttack = GetNextAttackDelay(0.2); // 0.25
SetThink(&CSpanner::Smack);
pev->nextthink = UTIL_WeaponTimeBase() + 0.2;
}
return fDidHit;
}

224
dlls/Hunger/taurus.cpp Normal file
View File

@ -0,0 +1,224 @@
/***
*
* 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"
enum taurus_e {
TAURUS_IDLE1 = 0,
TAURUS_IDLE2,
TAURUS_IDLE3,
TAURUS_SHOOT,
TAURUS_SHOOT2,
TAURUS_SHOOT3,
TAURUS_SHOOT_EMPTY,
TAURUS_RELOAD,
TAURUS_RELOAD2,
TAURUS_DRAW,
TAURUS_DRAW2,
};
LINK_ENTITY_TO_CLASS(weapon_th_taurus, CTaurus);
void CTaurus::Spawn()
{
Precache();
m_iId = WEAPON_TAURUS;
SET_MODEL(ENT(pev), "models/w_taurus.mdl");
m_iDefaultAmmo = TAURUS_DEFAULT_GIVE;
FallInit();// get ready to fall down.
}
void CTaurus::Precache(void)
{
PRECACHE_MODEL("models/v_taurus.mdl");
PRECACHE_MODEL("models/w_taurus.mdl");
PRECACHE_MODEL("models/p_taurus.mdl");
m_iShell = PRECACHE_MODEL("models/shell.mdl");// brass shell
PRECACHE_SOUND("items/9mmclip1.wav");
PRECACHE_SOUND("weapons/tau_back.wav");
PRECACHE_SOUND("weapons/tau_clipin.wav");
PRECACHE_SOUND("weapons/tau_clipout.wav");
PRECACHE_SOUND("weapons/tau_fire.wav");
PRECACHE_SOUND("weapons/tau_release.wav");
m_usFireTaurus = PRECACHE_EVENT(1, "events/taurus.sc");
}
int CTaurus::GetItemInfo(ItemInfo *p)
{
p->pszName = STRING(pev->classname);
p->pszAmmo1 = "taurus";
p->iMaxAmmo1 = TAURUS_MAX_CARRY;
p->pszAmmo2 = NULL;
p->iMaxAmmo2 = -1;
p->iMaxClip = TAURUS_MAX_CLIP;
p->iSlot = 1;
p->iPosition = 3;
p->iFlags = 0;
p->iId = m_iId = WEAPON_TAURUS;
p->iWeight = TAURUS_WEIGHT;
return 1;
}
BOOL CTaurus::Deploy()
{
return DefaultDeploy("models/v_taurus.mdl", "models/p_taurus.mdl", TAURUS_DRAW2, "taurus", 0);
}
void CTaurus::PrimaryAttack(void)
{
if (m_iClip <= 0)
{
if (m_fFireOnEmpty)
{
PlayEmptySound();
m_flNextPrimaryAttack = GetNextAttackDelay(0.28);
}
return;
}
m_iClip--;
m_pPlayer->pev->effects = (int)(m_pPlayer->pev->effects) | EF_MUZZLEFLASH;
int flags;
#if defined( CLIENT_WEAPONS )
flags = FEV_NOTHOST;
#else
flags = 0;
#endif
// player "shoot" animation
m_pPlayer->SetAnimation(PLAYER_ATTACK1);
// silenced
if (pev->body == 1)
{
m_pPlayer->m_iWeaponVolume = QUIET_GUN_VOLUME;
m_pPlayer->m_iWeaponFlash = DIM_GUN_FLASH;
}
else
{
// non-silenced
m_pPlayer->m_iWeaponVolume = NORMAL_GUN_VOLUME;
m_pPlayer->m_iWeaponFlash = NORMAL_GUN_FLASH;
}
Vector vecSrc = m_pPlayer->GetGunPosition();
Vector vecAiming = m_pPlayer->GetAutoaimVector(AUTOAIM_10DEGREES);
Vector vecDir;
vecDir = m_pPlayer->FireBulletsPlayer(1, vecSrc, vecAiming, VECTOR_CONE_3DEGREES, 8192, BULLET_PLAYER_TAURUS, 0, 0, m_pPlayer->pev, m_pPlayer->random_seed);
PLAYBACK_EVENT_FULL(flags, m_pPlayer->edict(), m_usFireTaurus, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, vecDir.x, vecDir.y, 0, 0, 0, 0);
m_flNextPrimaryAttack = GetNextAttackDelay(0.28);
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + UTIL_SharedRandomFloat(m_pPlayer->random_seed, 10, 15);
}
void CTaurus::Reload(void)
{
if (m_pPlayer->ammo_taurus <= 0)
return;
int iResult = DefaultReload(TAURUS_MAX_CLIP, TAURUS_RELOAD2, 2.0);
if (iResult)
{
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + UTIL_SharedRandomFloat(m_pPlayer->random_seed, 10, 15);
}
}
void CTaurus::WeaponIdle(void)
{
ResetEmptySound();
m_pPlayer->GetAutoaimVector(AUTOAIM_10DEGREES);
if (m_flTimeWeaponIdle > UTIL_WeaponTimeBase())
return;
// only idle if the slid isn't back
if (m_iClip != 0)
{
int iAnim;
float flRand = UTIL_SharedRandomFloat(m_pPlayer->random_seed, 0.0, 1.0);
if (flRand <= 0.3 + 0 * 0.75)
{
iAnim = TAURUS_IDLE3;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 46.0 / 18.0;
}
else if (flRand <= 0.6 + 0 * 0.875)
{
iAnim = TAURUS_IDLE1;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 46.0 / 16.0;
}
else
{
iAnim = TAURUS_IDLE2;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 46.0 / 20.0;
}
SendWeaponAnim(iAnim, 1);
}
}
class CTaurusAmmo : public CBasePlayerAmmo
{
void Spawn(void)
{
Precache();
SET_MODEL(ENT(pev), "models/w_taurusclip.mdl");
CBasePlayerAmmo::Spawn();
}
void Precache(void)
{
PRECACHE_MODEL("models/w_taurusclip.mdl");
PRECACHE_SOUND("items/9mmclip1.wav");
}
BOOL AddAmmo(CBaseEntity *pOther)
{
if (pOther->GiveAmmo(AMMO_TAURUS_GIVE, "taurus", TAURUS_MAX_CARRY) != -1)
{
EMIT_SOUND(ENT(pev), CHAN_ITEM, "items/9mmclip1.wav", 1, ATTN_NORM);
return TRUE;
}
return FALSE;
}
};
LINK_ENTITY_TO_CLASS(ammo_th_taurus, CTaurusAmmo);

82
dlls/Hunger/tnt.cpp Normal file
View File

@ -0,0 +1,82 @@
/***
*
* 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.
*
****/
/*
===== generic grenade.cpp ========================================================
*/
#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "monsters.h"
#include "weapons.h"
#include "nodes.h"
#include "soundent.h"
#include "decals.h"
LINK_ENTITY_TO_CLASS(tnt, CTnt);
void CTnt::Spawn(void)
{
pev->movetype = MOVETYPE_BOUNCE;
pev->solid = SOLID_BBOX;
SET_MODEL(ENT(pev), "models/w_tnt.mdl");
UTIL_SetSize(pev, Vector(0, 0, 0), Vector(0, 0, 0));
pev->dmg = 100;
m_fRegisteredSound = FALSE;
}
CGrenade * CTnt::ShootTimed(entvars_t *pevOwner, Vector vecStart, Vector vecVelocity, float time)
{
CTnt *pTnt = GetClassPtr((CTnt *)NULL);
pTnt->Spawn();
UTIL_SetOrigin(pTnt->pev, vecStart);
pTnt->pev->velocity = vecVelocity;
pTnt->pev->angles = UTIL_VecToAngles(pTnt->pev->velocity);
pTnt->pev->owner = ENT(pevOwner);
pTnt->SetTouch(&CTnt::BounceTouch); // Bounce if touched
// Take one second off of the desired detonation time and set the think to PreDetonate. PreDetonate
// will insert a DANGER sound into the world sound list and delay detonation for one second so that
// the grenade explodes after the exact amount of time specified in the call to ShootTimed().
pTnt->pev->dmgtime = gpGlobals->time + time;
pTnt->SetThink(&CTnt::TumbleThink);
pTnt->pev->nextthink = gpGlobals->time + 0.1;
if (time < 0.1)
{
pTnt->pev->nextthink = gpGlobals->time;
pTnt->pev->velocity = Vector(0, 0, 0);
}
pTnt->pev->sequence = RANDOM_LONG(3, 6);
pTnt->pev->framerate = 1.0;
// Tumble through the air
// pTnt->pev->avelocity.x = -400;
pTnt->pev->gravity = 0.5;
pTnt->pev->friction = 0.8;
SET_MODEL(ENT(pTnt->pev), "models/w_tnt.mdl");
pTnt->pev->dmg = 100;
return pTnt;
}

View File

@ -0,0 +1,236 @@
/***
*
* 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 "weapons.h"
#include "monsters.h"
#include "player.h"
#include "gamerules.h"
enum einar1_e {
EINAR1_IDLE = 0,
EINAR1_AIM,
EINAR1_FIRE,
EINAR1_DRAW,
EINAR1_HOLSTER,
EINAR1_AUTOIDLE,
EINAR1_AUTOFIRE,
EINAR1_AUTODRAW,
EINAR1_AUTOHOLSTER,
};
LINK_ENTITY_TO_CLASS(weapon_einar1, CEinar1);
int CEinar1::GetPrimaryAttackActivity(void)
{
return EINAR1_AUTOFIRE;
}
int CEinar1::GetZoomedAttackActivity(void)
{
return EINAR1_FIRE;
}
int CEinar1::GetItemInfo(ItemInfo *p)
{
p->pszName = STRING(pev->classname);
p->pszAmmo1 = "sniper";
p->iMaxAmmo1 = SNIPER_MAX_CARRY;
p->pszAmmo2 = NULL;
p->iMaxAmmo2 = -1;
p->iMaxClip = SNIPER_MAX_CLIP;
p->iFlags = 0;
p->iSlot = 2;
p->iPosition = 4;
p->iId = m_iId = WEAPON_EINAR1;
p->iWeight = SNIPER_WEIGHT;
return 1;
}
void CEinar1::Spawn()
{
Precache();
m_iId = WEAPON_EINAR1;
SET_MODEL(ENT(pev), "models/w_isotopebox.mdl");
m_iDefaultAmmo = SNIPER_DEFAULT_GIVE;
m_fInZoom = FALSE;
m_fInAttack = 0;
m_fInSpecialReload = 0;
FallInit();// get ready to fall down.
}
void CEinar1::Precache(void)
{
PRECACHE_MODEL("models/v_tfc_sniper.mdl");
PRECACHE_MODEL("models/w_isotopebox.mdl");
PRECACHE_MODEL("models/p_sniper.mdl");
PRECACHE_MODEL("models/w_antidote.mdl");
PRECACHE_SOUND("items/9mmclip1.wav");
PRECACHE_SOUND("weapons/sniper.wav");
PRECACHE_SOUND("weapons/reload3.wav");
PRECACHE_SOUND("weapons/357_cock1.wav");
m_usFireSniper = PRECACHE_EVENT(1, "events/sniper.sc");
}
BOOL CEinar1::Deploy()
{
return DefaultDeploy("models/v_tfc_sniper.mdl", "models/p_sniper.mdl", EINAR1_AUTODRAW, "einar1");
}
void CEinar1::Holster(int skiplocal /* = 0 */)
{
CSniper::Holster(skiplocal);
m_fInZoom = FALSE;
m_fInAttack = 0;
m_fInSpecialReload = 0;
SendWeaponAnim( EINAR1_AUTOHOLSTER );
}
void CEinar1::PrimaryAttack()
{
if (m_fInSpecialReload != 0)
return;
CSniper::PrimaryAttack();
m_fInAttack = 1;
m_fInSpecialReload = 0;
}
void CEinar1::SecondaryAttack(void)
{
if (m_fInSpecialReload != 0)
return;
CSniper::SecondaryAttack();
m_flNextPrimaryAttack = GetNextAttackDelay(1);
m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 1;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 5; // idle pretty soon after shooting.
m_fInAttack = 1;
m_fInSpecialReload = 0;
}
void CEinar1::Reload(void)
{
if (m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0 || m_iClip == SNIPER_MAX_CLIP)
return;
// don't reload until recoil is done
if (m_flNextPrimaryAttack > UTIL_WeaponTimeBase())
return;
if (m_fInZoom)
{
SetZoomState(FALSE);
}
// check to see if we're ready to reload
if (m_fInSpecialReload == 0)
{
SendWeaponAnim(EINAR1_AUTOHOLSTER);
m_fInSpecialReload = 1;
m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.0; // 0.5
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 0.6;
m_flNextPrimaryAttack = GetNextAttackDelay(0.6);
m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 1.5;
return;
}
else if (m_fInSpecialReload == 1)
{
if (m_flTimeWeaponIdle > UTIL_WeaponTimeBase())
return;
// was waiting for gun to move to side
m_fInSpecialReload = 2;
EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/reload3.wav", 1, ATTN_NORM, 0, 85 + RANDOM_LONG(0, 0x1f));
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 0.8;
}
else
{
DefaultReload( SNIPER_MAX_CLIP, EINAR1_AUTODRAW, 0.5);
m_fInSpecialReload = 0;
}
}
void CEinar1::WeaponIdle(void)
{
CSniper::WeaponIdle();
if (m_fInSpecialReload == 0 && m_fInAttack == 1 && (gpGlobals->time - m_flLastFireTime) > 0.1f)
{
SendWeaponAnim(m_fInZoom ? EINAR1_IDLE : EINAR1_AUTOIDLE);
m_fInAttack = 0;
}
if (m_flTimeWeaponIdle > UTIL_WeaponTimeBase())
return;
if (m_iClip == 0 && m_fInSpecialReload == 0 && m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType])
{
Reload();
}
else if (m_fInSpecialReload != 0)
{
if (m_iClip != SNIPER_MAX_CLIP && m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType])
{
Reload();
}
else
{
m_fInSpecialReload = 0;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 1.5;
}
}
else if (m_fInSpecialReload == 0)
{
int iAnim;
if (m_fInZoom)
{
iAnim = EINAR1_IDLE;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + (31.0 / 10.0);
}
else
{
iAnim = EINAR1_AUTOIDLE;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + (31.0 / 15.0);
}
SendWeaponAnim(iAnim, UseDecrement());
}
}
BOOL CEinar1::ShouldWeaponIdle(void)
{
return (m_iClip == 0) || (m_fInSpecialReload != 0);
}

397
dlls/Hunger/zombiebull.cpp Normal file
View File

@ -0,0 +1,397 @@
/***
*
* 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.
*
****/
//=========================================================
// bullsquid - big, spotty tentacle-mouthed meanie.
//=========================================================
#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "monsters.h"
#include "schedule.h"
#include "nodes.h"
#include "effects.h"
#include "decals.h"
#include "soundent.h"
#include "game.h"
#include "bullsquid.h"
//=========================================================
// Monster's Anim Events Go Here
//=========================================================
#define ZBULL_AE_SPIT ( 1 )
#define ZBULL_AE_BITE ( 2 )
#define ZBULL_AE_BLINK ( 3 )
#define ZBULL_AE_TAILWHIP ( 4 )
#define ZBULL_AE_HOP ( 5 )
#define ZBULL_AE_THROW ( 6 )
class CZombieBull : public CBullsquid
{
public:
void Spawn(void);
void Precache(void);
int Classify(void);
void HandleAnimEvent(MonsterEvent_t *pEvent);
void IdleSound(void);
void PainSound(void);
void DeathSound(void);
void AlertSound(void);
void AttackSound(void);
void BiteSound(void);
void StartTask(Task_t *pTask);
BOOL CheckMeleeAttack1(float flDot, float flDist);
BOOL CheckMeleeAttack2(float flDot, float flDist);
BOOL CheckRangeAttack1(float flDot, float flDist) { return FALSE; }
Schedule_t *GetSchedule(void);
static const char *pAttackSounds[];
static const char *pBiteSounds[];
static const char *pIdleSounds[];
static const char *pAlertSounds[];
static const char *pPainSounds[];
static const char *pDeathSounds[];
};
LINK_ENTITY_TO_CLASS(monster_th_zombiebull, CZombieBull);
const char *CZombieBull::pAttackSounds[] =
{
"bull/bu_whip1.wav",
"bull/bu_whip2.wav",
"bull/bu_whip3.wav",
};
const char *CZombieBull::pBiteSounds[] =
{
"bull/bu_gore1.wav",
"bull/bu_gore2.wav",
"bull/bu_gore3.wav",
};
const char *CZombieBull::pIdleSounds[] =
{
"bull/bu_idle1.wav",
"bull/bu_idle2.wav",
"bull/bu_idle3.wav",
};
const char *CZombieBull::pAlertSounds[] =
{
"bull/bu_alert1.wav",
"bull/bu_alert2.wav",
"bull/bu_alert3.wav",
"bull/bu_alert4.wav",
};
const char *CZombieBull::pPainSounds[] =
{
"bull/bu_pain1.wav",
"bull/bu_pain2.wav",
"bull/bu_pain3.wav",
};
const char *CZombieBull::pDeathSounds[] =
{
"bull/bu_die1.wav",
"bull/bu_die2.wav",
"bull/bu_die3.wav",
};
//=========================================================
// Classify - indicates this monster's place in the
// relationship table.
//=========================================================
int CZombieBull::Classify(void)
{
return CLASS_ALIEN_MONSTER;
}
//=========================================================
// CheckMeleeAttack1 - bullsquid is a big guy, so has a longer
// melee range than most monsters. This is the tailwhip attack
//=========================================================
BOOL CZombieBull::CheckMeleeAttack1(float flDot, float flDist)
{
if (m_hEnemy->pev->health <= gSkillData.bullsquidDmgWhip && flDist <= 95 && flDot >= 0.7)
{
return TRUE;
}
return FALSE;
}
//=========================================================
// CheckMeleeAttack2 - bullsquid is a big guy, so has a longer
// melee range than most monsters. This is the bite attack.
// this attack will not be performed if the tailwhip attack
// is valid.
//=========================================================
BOOL CZombieBull::CheckMeleeAttack2(float flDot, float flDist)
{
if (flDist <= 95 && flDot >= 0.7 && !HasConditions(bits_COND_CAN_MELEE_ATTACK1))
{
return TRUE;
}
return FALSE;
}
//=========================================================
// IdleSound
//=========================================================
void CZombieBull::IdleSound(void)
{
EMIT_SOUND(ENT(pev), CHAN_VOICE, RANDOM_SOUND_ARRAY(pIdleSounds), 1, ATTN_NORM);
}
//=========================================================
// PainSound
//=========================================================
void CZombieBull::PainSound(void)
{
EMIT_SOUND(ENT(pev), CHAN_VOICE, RANDOM_SOUND_ARRAY(pPainSounds), 1, ATTN_NORM);
}
//=========================================================
// AlertSound
//=========================================================
void CZombieBull::AlertSound(void)
{
EMIT_SOUND(ENT(pev), CHAN_VOICE, RANDOM_SOUND_ARRAY(pAlertSounds), 1, ATTN_NORM);
}
//=========================================================
// HandleAnimEvent - catches the monster-specific messages
// that occur when tagged animation frames are played.
//=========================================================
void CZombieBull::HandleAnimEvent(MonsterEvent_t *pEvent)
{
switch (pEvent->event)
{
case ZBULL_AE_BITE:
{
// SOUND HERE!
CBaseEntity *pHurt = CheckTraceHullAttack(90, gSkillData.zombiebullDmgBite, DMG_SLASH);
if (pHurt)
{
pHurt->pev->velocity = pHurt->pev->velocity + gpGlobals->v_forward * 400;
}
else
{
//
// Search for human repels.
//
CBaseEntity *pEntity = NULL;
// iterate on all entities in the vicinity.
while ((pEntity = UTIL_FindEntityInSphere(pEntity, pev->origin, 128)) != NULL)
{
if (pEntity->pev->takedamage != DAMAGE_NO)
{
if (FClassnameIs(pEntity->pev, "monster_hgrunt_repel"))
{
pEntity->TakeDamage(pev, pev, gSkillData.zombiebullDmgBite, DMG_SLASH | DMG_ALWAYSGIB);
}
}
}
}
}
break;
case ZBULL_AE_TAILWHIP:
{
// croonchy bite sound
BiteSound();
CBaseEntity *pHurt = CheckTraceHullAttack(90, gSkillData.zombiebullDmgWhip, DMG_SLASH | DMG_ALWAYSGIB);
if (pHurt)
{
pHurt->pev->punchangle.z = -20;
pHurt->pev->punchangle.x = 20;
pHurt->pev->velocity = pHurt->pev->velocity + gpGlobals->v_right * 16;
}
}
break;
case ZBULL_AE_THROW:
{
// squid throws its prey IF the prey is a client.
CBaseEntity *pHurt = CheckTraceHullAttack(90, 0, 0);
if (pHurt)
{
// screeshake transforms the viewmodel as well as the viewangle. No problems with seeing the ends of the viewmodels.
UTIL_ScreenShake(pHurt->pev->origin, 25.0, 1.5, 0.7, 2);
}
}
break;
case ZBULL_AE_BLINK:
break;
default:
CBullsquid::HandleAnimEvent(pEvent);
}
}
//=========================================================
// Spawn
//=========================================================
void CZombieBull::Spawn()
{
Precache();
SET_MODEL(ENT(pev), "models/zombiebull.mdl");
UTIL_SetSize(pev, Vector(-32, -32, 0), Vector(32, 32, 64));
pev->solid = SOLID_SLIDEBOX;
pev->movetype = MOVETYPE_STEP;
m_bloodColor = BLOOD_COLOR_RED;
pev->effects = 0;
pev->health = gSkillData.zombiebullHealth;
m_flFieldOfView = 0.2;// indicates the width of this monster's forward view cone ( as a dotproduct result )
m_MonsterState = MONSTERSTATE_NONE;
m_fCanThreatDisplay = FALSE;
MonsterInit();
}
//=========================================================
// Precache - precaches all resources this monster needs
//=========================================================
void CZombieBull::Precache()
{
PRECACHE_MODEL("models/zombiebull.mdl");
PRECACHE_SOUND("zombie/claw_miss2.wav");// because we use the basemonster SWIPE animation event
PRECACHE_SOUND_ARRAY(pAttackSounds);
PRECACHE_SOUND_ARRAY(pBiteSounds);
PRECACHE_SOUND_ARRAY(pIdleSounds);
PRECACHE_SOUND_ARRAY(pAlertSounds);
PRECACHE_SOUND_ARRAY(pPainSounds);
PRECACHE_SOUND_ARRAY(pDeathSounds);
PRECACHE_SOUND("bull/bu_paw1.wav");
PRECACHE_SOUND("bull/bu_runstep1.wav");
PRECACHE_SOUND("bull/bu_runstep2.wav");
PRECACHE_SOUND("bull/bu_walkstep1.wav");
PRECACHE_SOUND("bull/bu_walkstep2.wav");
}
//=========================================================
// DeathSound
//=========================================================
void CZombieBull::DeathSound(void)
{
EMIT_SOUND(ENT(pev), CHAN_VOICE, RANDOM_SOUND_ARRAY(pDeathSounds), 1, ATTN_NORM);
}
//=========================================================
// AttackSound
//=========================================================
void CZombieBull::AttackSound(void)
{
EMIT_SOUND(ENT(pev), CHAN_VOICE, RANDOM_SOUND_ARRAY(pAttackSounds), 1, ATTN_NORM);
}
//=========================================================
// BiteSound
//=========================================================
void CZombieBull::BiteSound(void)
{
EMIT_SOUND(ENT(pev), CHAN_VOICE, RANDOM_SOUND_ARRAY(pBiteSounds), 1, ATTN_NORM);
}
//=========================================================
// GetSchedule
//=========================================================
Schedule_t *CZombieBull::GetSchedule(void)
{
switch (m_MonsterState)
{
case MONSTERSTATE_ALERT:
return CBaseMonster::GetSchedule();
case MONSTERSTATE_COMBAT:
{
// dead enemy
if (HasConditions(bits_COND_ENEMY_DEAD))
{
// call base class, all code to handle dead enemies is centralized there.
return CBaseMonster::GetSchedule();
}
if (HasConditions(bits_COND_NEW_ENEMY))
{
return GetScheduleOfType(SCHED_WAKE_ANGRY);
}
if (HasConditions(bits_COND_CAN_MELEE_ATTACK1))
{
return GetScheduleOfType(SCHED_MELEE_ATTACK1);
}
if (HasConditions(bits_COND_CAN_MELEE_ATTACK2))
{
return GetScheduleOfType(SCHED_MELEE_ATTACK2);
}
return GetScheduleOfType(SCHED_CHASE_ENEMY);
break;
}
}
return CBaseMonster::GetSchedule();
}
//=========================================================
// Start task - selects the correct activity and performs
// any necessary calculations to start the next task on the
// schedule. OVERRIDDEN for bullsquid because it needs to
// know explicitly when the last attempt to chase the enemy
// failed, since that impacts its attack choices.
//=========================================================
void CZombieBull::StartTask(Task_t *pTask)
{
m_iTaskStatus = TASKSTATUS_RUNNING;
switch (pTask->iTask)
{
case TASK_MELEE_ATTACK2:
{
AttackSound();
CBaseMonster::StartTask(pTask);
break;
}
default:
{
CBullsquid::StartTask(pTask);
break;
}
}
}

View File

@ -25,6 +25,7 @@
#include "weapons.h"
#include "soundent.h"
#include "hornet.h"
#include "hgrunt.h"
//=========================================================
// monster-specific schedule types
@ -193,11 +194,6 @@ const char *CAGrunt::pAlertSounds[] =
//=========================================================
int CAGrunt::IRelationship( CBaseEntity *pTarget )
{
if( FClassnameIs( pTarget->pev, "monster_human_grunt" ) )
{
return R_NM;
}
return CSquadMonster::IRelationship( pTarget );
}
@ -214,46 +210,8 @@ int CAGrunt::ISoundMask( void )
//=========================================================
void CAGrunt::TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType )
{
if( ptr->iHitgroup == 10 && ( bitsDamageType & ( DMG_BULLET | DMG_SLASH | DMG_CLUB ) ) )
{
// hit armor
if( pev->dmgtime != gpGlobals->time || ( RANDOM_LONG( 0, 10 ) < 1 ) )
{
UTIL_Ricochet( ptr->vecEndPos, RANDOM_FLOAT( 1, 2 ) );
pev->dmgtime = gpGlobals->time;
}
if( RANDOM_LONG( 0, 1 ) == 0 )
{
Vector vecTracerDir = vecDir;
vecTracerDir.x += RANDOM_FLOAT( -0.3, 0.3 );
vecTracerDir.y += RANDOM_FLOAT( -0.3, 0.3 );
vecTracerDir.z += RANDOM_FLOAT( -0.3, 0.3 );
vecTracerDir = vecTracerDir * -512;
MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, ptr->vecEndPos );
WRITE_BYTE( TE_TRACER );
WRITE_COORD( ptr->vecEndPos.x );
WRITE_COORD( ptr->vecEndPos.y );
WRITE_COORD( ptr->vecEndPos.z );
WRITE_COORD( vecTracerDir.x );
WRITE_COORD( vecTracerDir.y );
WRITE_COORD( vecTracerDir.z );
MESSAGE_END();
}
flDamage -= 20;
if( flDamage <= 0 )
flDamage = 0.1;// don't hurt the monster much, but allow bits_COND_LIGHT_DAMAGE to be generated
}
else
{
SpawnBlood( ptr->vecEndPos, BloodColor(), flDamage );// a little surface blood.
TraceBleed( flDamage, vecDir, ptr, bitsDamageType );
}
SpawnBlood( ptr->vecEndPos, BloodColor(), flDamage ); // a little surface blood.
TraceBleed( flDamage, vecDir, ptr, bitsDamageType );
AddMultiDamage( pevAttacker, this, flDamage, bitsDamageType );
}
@ -263,7 +221,7 @@ void CAGrunt::TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir
//=========================================================
void CAGrunt::StopTalking( void )
{
m_flNextWordTime = m_flNextSpeakTime = gpGlobals->time + 10 + RANDOM_LONG( 0, 10 );
m_flNextWordTime = m_flNextSpeakTime = gpGlobals->time + 50 + RANDOM_LONG( 0, 10 );
}
//=========================================================
@ -322,7 +280,7 @@ void CAGrunt::PrescheduleThink( void )
}
else
{
m_flNextWordTime = gpGlobals->time + RANDOM_FLOAT( 0.5, 1 );
m_flNextWordTime = gpGlobals->time + RANDOM_FLOAT( 20, 25 );
}
}
}
@ -492,10 +450,10 @@ void CAGrunt::HandleAnimEvent( MonsterEvent_t *pEvent )
{
// left foot
case 0:
EMIT_SOUND_DYN( ENT( pev ), CHAN_BODY, "player/pl_ladder2.wav", 1, ATTN_NORM, 0, 70 );
EMIT_SOUND_DYN( ENT( pev ), CHAN_BODY, "zork/leftfoot2.wav", 1, ATTN_NORM, 0, 70 );
break;
case 1:
EMIT_SOUND_DYN( ENT( pev ), CHAN_BODY, "player/pl_ladder4.wav", 1, ATTN_NORM, 0, 70 );
EMIT_SOUND_DYN( ENT( pev ), CHAN_BODY, "zork/leftfoot4.wav", 1, ATTN_NORM, 0, 70 );
break;
}
break;
@ -504,10 +462,10 @@ void CAGrunt::HandleAnimEvent( MonsterEvent_t *pEvent )
switch( RANDOM_LONG( 0, 1 ) )
{
case 0:
EMIT_SOUND_DYN( ENT( pev ), CHAN_BODY, "player/pl_ladder1.wav", 1, ATTN_NORM, 0, 70 );
EMIT_SOUND_DYN( ENT( pev ), CHAN_BODY, "zork/leftfoot1.wav", 1, ATTN_NORM, 0, 70 );
break;
case 1:
EMIT_SOUND_DYN( ENT( pev ), CHAN_BODY, "player/pl_ladder3.wav", 1, ATTN_NORM, 0 ,70);
EMIT_SOUND_DYN( ENT( pev ), CHAN_BODY, "zork/leftfoot3.wav", 1, ATTN_NORM, 0 ,70);
break;
}
break;
@ -588,7 +546,7 @@ void CAGrunt::Spawn()
pev->solid = SOLID_SLIDEBOX;
pev->movetype = MOVETYPE_STEP;
m_bloodColor = BLOOD_COLOR_GREEN;
m_bloodColor = BLOOD_COLOR_RED;
pev->effects = 0;
pev->health = gSkillData.agruntHealth;
m_flFieldOfView = 0.2;// indicates the width of this monster's forward view cone ( as a dotproduct result )
@ -598,7 +556,7 @@ void CAGrunt::Spawn()
m_HackedGunPos = Vector( 24, 64, 48 );
m_flNextSpeakTime = m_flNextWordTime = gpGlobals->time + 10 + RANDOM_LONG( 0, 10 );
m_flNextSpeakTime = m_flNextWordTime = gpGlobals->time + 50 + RANDOM_LONG( 0, 10 );
MonsterInit();
}
@ -638,6 +596,12 @@ void CAGrunt::Precache()
iAgruntMuzzleFlash = PRECACHE_MODEL( "sprites/muz4.spr" );
UTIL_PrecacheOther( "hornet" );
PRECACHE_SOUND( "zork/leftfoot2.wav" );
PRECACHE_SOUND( "zork/leftfoot4.wav" );
PRECACHE_SOUND( "zork/rightfoot1.wav" );
PRECACHE_SOUND( "zork/rightfoot3.wav" );
}
//=========================================================
@ -925,34 +889,7 @@ BOOL CAGrunt::CheckMeleeAttack1( float flDot, float flDist )
//=========================================================
BOOL CAGrunt::CheckRangeAttack1( float flDot, float flDist )
{
if( gpGlobals->time < m_flNextHornetAttackCheck )
{
return m_fCanHornetAttack;
}
if( HasConditions( bits_COND_SEE_ENEMY ) && flDist >= AGRUNT_MELEE_DIST && flDist <= 1024 && flDot >= 0.5 && NoFriendlyFire() )
{
TraceResult tr;
Vector vecArmPos, vecArmDir;
// verify that a shot fired from the gun will hit the enemy before the world.
// !!!LATER - we may wish to do something different for projectile weapons as opposed to instant-hit
UTIL_MakeVectors( pev->angles );
GetAttachment( 0, vecArmPos, vecArmDir );
//UTIL_TraceLine( vecArmPos, vecArmPos + gpGlobals->v_forward * 256, ignore_monsters, ENT( pev ), &tr );
UTIL_TraceLine( vecArmPos, m_hEnemy->BodyTarget( vecArmPos ), dont_ignore_monsters, ENT( pev ), &tr );
if( tr.flFraction == 1.0 || tr.pHit == m_hEnemy->edict() )
{
m_flNextHornetAttackCheck = gpGlobals->time + RANDOM_FLOAT( 2, 5 );
m_fCanHornetAttack = TRUE;
return m_fCanHornetAttack;
}
}
m_flNextHornetAttackCheck = gpGlobals->time + 0.2;// don't check for half second if this check wasn't successful
m_fCanHornetAttack = FALSE;
return m_fCanHornetAttack;
return FALSE;
}
//=========================================================

View File

@ -21,74 +21,13 @@
#include "weapons.h"
#include "nodes.h"
#include "effects.h"
#include "apache.h"
extern DLL_GLOBAL int g_iSkillLevel;
#define SF_WAITFORTRIGGER (0x04 | 0x40) // UNDONE: Fix!
#define SF_NOWRECKAGE 0x08
class CApache : public CBaseMonster
{
int Save( CSave &save );
int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
void Spawn( void );
void Precache( void );
int Classify( void ) { return CLASS_HUMAN_MILITARY; };
int BloodColor( void ) { return DONT_BLEED; }
void Killed( entvars_t *pevAttacker, int iGib );
void GibMonster( void );
void SetObjectCollisionBox( void )
{
pev->absmin = pev->origin + Vector( -300, -300, -172 );
pev->absmax = pev->origin + Vector( 300, 300, 8 );
}
void EXPORT HuntThink( void );
void EXPORT FlyTouch( CBaseEntity *pOther );
void EXPORT CrashTouch( CBaseEntity *pOther );
void EXPORT DyingThink( void );
void EXPORT StartupUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
void EXPORT NullThink( void );
void ShowDamage( void );
void Flight( void );
void FireRocket( void );
BOOL FireGun( void );
int TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType );
void TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType );
int m_iRockets;
float m_flForce;
float m_flNextRocket;
Vector m_vecTarget;
Vector m_posTarget;
Vector m_vecDesired;
Vector m_posDesired;
Vector m_vecGoal;
Vector m_angGun;
float m_flLastSeen;
float m_flPrevSeen;
int m_iSoundState; // don't save this
int m_iSpriteTexture;
int m_iExplode;
int m_iBodyGibs;
float m_flGoalSpeed;
int m_iDoSmokePuff;
CBeam *m_pBeam;
};
LINK_ENTITY_TO_CLASS( monster_apache, CApache )
TYPEDESCRIPTION CApache::m_SaveData[] =
@ -122,7 +61,7 @@ void CApache::Spawn( void )
pev->movetype = MOVETYPE_FLY;
pev->solid = SOLID_BBOX;
SET_MODEL( ENT( pev ), "models/apache.mdl" );
SET_MODEL( ENT( pev ), (char*)STRING( pev->model ) );
UTIL_SetSize( pev, Vector( -32, -32, -64 ), Vector( 32, 32, 0 ) );
UTIL_SetOrigin( pev, pev->origin );
@ -154,7 +93,8 @@ void CApache::Spawn( void )
void CApache::Precache( void )
{
PRECACHE_MODEL( "models/apache.mdl" );
PRECACHE_MODEL( "models/apache2.mdl" );
PRECACHE_MODEL( "models/huey_apache.mdl" );
PRECACHE_SOUND( "apache/ap_rotor1.wav" );
PRECACHE_SOUND( "apache/ap_rotor2.wav" );
@ -397,6 +337,14 @@ void CApache::DyingThink( void )
WRITE_BYTE( BREAK_METAL );
MESSAGE_END();
//
// AI Trigger target on death.
//
if( m_iTriggerCondition == AITRIGGER_DEATH && !FStringNull( m_iszTriggerTarget ) )
{
FireTargets( STRING( m_iszTriggerTarget ), this, this, USE_TOGGLE, 0 );
m_iTriggerCondition = AITRIGGER_NONE;
}
SetThink( &CBaseEntity::SUB_Remove );
pev->nextthink = gpGlobals->time + 0.1;
}
@ -915,8 +863,8 @@ void CApache::TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir
}
else
{
// do half damage in the body
// AddMultiDamage( pevAttacker, this, flDamage / 2.0, bitsDamageType );
// do tenth damage in the body
AddMultiDamage( pevAttacker, this, flDamage / 10.0, bitsDamageType );
UTIL_Ricochet( ptr->vecEndPos, 2.0 );
}
}

81
dlls/apache.h Normal file
View File

@ -0,0 +1,81 @@
/***
*
* 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.
*
****/
#ifndef APACHE_H
#define APACHE_H
class CApache : public CBaseMonster
{
public:
int Save( CSave &save );
int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
void Spawn( void );
void Precache( void );
int Classify( void ) { return CLASS_HUMAN_MILITARY; };
int BloodColor( void ) { return DONT_BLEED; }
void Killed( entvars_t *pevAttacker, int iGib );
void GibMonster( void );
void SetObjectCollisionBox( void )
{
pev->absmin = pev->origin + Vector( -300, -300, -172);
pev->absmax = pev->origin + Vector(300, 300, 8);
}
void EXPORT HuntThink( void );
void EXPORT FlyTouch( CBaseEntity *pOther );
void EXPORT CrashTouch( CBaseEntity *pOther );
void EXPORT DyingThink( void );
void EXPORT StartupUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
void EXPORT NullThink( void );
void ShowDamage( void );
void Flight( void );
void FireRocket( void );
virtual BOOL FireGun( void );
int TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType );
void TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType);
int m_iRockets;
float m_flForce;
float m_flNextRocket;
Vector m_vecTarget;
Vector m_posTarget;
Vector m_vecDesired;
Vector m_posDesired;
Vector m_vecGoal;
Vector m_angGun;
float m_flLastSeen;
float m_flPrevSeen;
int m_iSoundState; // don't save this
int m_iSpriteTexture;
int m_iExplode;
int m_iBodyGibs;
float m_flGoalSpeed;
int m_iDoSmokePuff;
CBeam *m_pBeam;
};
#endif // APACHE_H

View File

@ -27,6 +27,25 @@
#include "scripted.h"
#include "weapons.h"
#include "soundent.h"
#include "barney.h"
//
// Barney special flags
//
#define BF_ZOMBIECOP 1
//
// Barney skins
//
enum
{
SKIN_NORMAL_COP = 0,
SKIN_ZOMBIE_COP_YOUNG,
SKIN_ZOMBIE_COP_OLD,
SKIN_ASYLUM_GUARD,
SKIN_ZOMBIE_ASYLUM_GUARD
};
//=========================================================
// Monster's Anim Events Go Here
@ -40,54 +59,6 @@
#define BARNEY_BODY_GUNDRAWN 1
#define BARNEY_BODY_GUNGONE 2
class CBarney : public CTalkMonster
{
public:
void Spawn( void );
void Precache( void );
void SetYawSpeed( void );
int ISoundMask( void );
void BarneyFirePistol( void );
void AlertSound( void );
int Classify( void );
void HandleAnimEvent( MonsterEvent_t *pEvent );
void RunTask( Task_t *pTask );
void StartTask( Task_t *pTask );
virtual int ObjectCaps( void ) { return CTalkMonster :: ObjectCaps() | FCAP_IMPULSE_USE; }
int TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType);
BOOL CheckRangeAttack1( float flDot, float flDist );
void DeclineFollowing( void );
// Override these to set behavior
Schedule_t *GetScheduleOfType( int Type );
Schedule_t *GetSchedule( void );
MONSTERSTATE GetIdealState( void );
void DeathSound( void );
void PainSound( void );
void TalkInit( void );
void TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType);
void Killed( entvars_t *pevAttacker, int iGib );
virtual int Save( CSave &save );
virtual int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
BOOL m_fGunDrawn;
float m_painTime;
float m_checkAttackTime;
BOOL m_lastAttackCheck;
// UNDONE: What is this for? It isn't used?
float m_flPlayerDamage;// how much pain has the player inflicted on me?
CUSTOM_SCHEDULES
};
LINK_ENTITY_TO_CLASS( monster_barney, CBarney )
TYPEDESCRIPTION CBarney::m_SaveData[] =
@ -97,6 +68,7 @@ TYPEDESCRIPTION CBarney::m_SaveData[] =
DEFINE_FIELD( CBarney, m_checkAttackTime, FIELD_TIME ),
DEFINE_FIELD( CBarney, m_lastAttackCheck, FIELD_BOOLEAN ),
DEFINE_FIELD( CBarney, m_flPlayerDamage, FIELD_FLOAT ),
DEFINE_FIELD( CBarney, m_iBarneyFlags, FIELD_INTEGER ),
};
IMPLEMENT_SAVERESTORE( CBarney, CTalkMonster )
@ -254,6 +226,9 @@ int CBarney::ISoundMask( void)
//=========================================================
int CBarney::Classify( void )
{
if( IsZombieCop() )
return CLASS_ALIEN_MONSTER;
return CLASS_PLAYER_ALLY;
}
@ -343,7 +318,21 @@ void CBarney::BarneyFirePistol( void )
SetBlending( 0, angDir.x );
pev->effects = EF_MUZZLEFLASH;
FireBullets( 1, vecShootOrigin, vecShootDir, VECTOR_CONE_2DEGREES, 1024, BULLET_MONSTER_9MM );
Vector vecSpread;
if( m_hEnemy == NULL || !m_hEnemy->IsPlayer() )
{
// Higher chance to hit target.
vecSpread = VECTOR_CONE_2DEGREES;
}
else
{
// Allow barney to miss player to avoid too much accuracy.
vecSpread = VECTOR_CONE_6DEGREES;
}
// Fire bullet.
FireBullets( 1, vecShootOrigin, vecShootDir, vecSpread, 1024, BULLET_MONSTER_9MM );
int pitchShift = RANDOM_LONG( 0, 20 );
@ -395,7 +384,12 @@ void CBarney::Spawn()
{
Precache();
SET_MODEL( ENT( pev ), "models/barney.mdl" );
char* szModel = (char*)STRING( pev->model );
if( !szModel || !*szModel )
{
szModel = "models/barney.mdl";
}
SET_MODEL( ENT( pev ), szModel );
UTIL_SetSize( pev, VEC_HUMAN_HULL_MIN, VEC_HUMAN_HULL_MAX );
pev->solid = SOLID_SLIDEBOX;
@ -413,6 +407,56 @@ void CBarney::Spawn()
MonsterInit();
SetUse( &CTalkMonster::FollowerUse );
// Cops use a lower voice pitch.
m_voicePitch = RANDOM_LONG( 95, 96 );
m_iBarneyFlags = 0;
// If this is a zombie cop.
if( pev->spawnflags & SF_MONSTER_ZOMBIECOP )
{
m_iBarneyFlags |= BF_ZOMBIECOP;
// Convert to zombie skin.
switch( pev->skin )
{
// Regular zombie skin.
case SKIN_NORMAL_COP:
pev->skin = SKIN_ZOMBIE_COP_YOUNG + RANDOM_LONG( 0, 1 );
break;
// Zombie asylum guard.
case SKIN_ASYLUM_GUARD:
pev->skin = SKIN_ZOMBIE_ASYLUM_GUARD;
break;
default:
break;
}
}
else
{
// Convert to normal skin.
switch( pev->skin )
{
// Young/old skin.
case SKIN_ZOMBIE_COP_YOUNG:
case SKIN_ZOMBIE_COP_OLD:
pev->skin = SKIN_NORMAL_COP;
break;
// Asylum guard.
case SKIN_ZOMBIE_ASYLUM_GUARD:
pev->skin = SKIN_ASYLUM_GUARD;
break;
default:
break;
}
}
// Prevent zombie cops from being 'used'.
if( IsZombieCop() )
{
SetUse( NULL );
}
}
//=========================================================
@ -421,6 +465,7 @@ void CBarney::Spawn()
void CBarney::Precache()
{
PRECACHE_MODEL( "models/barney.mdl" );
PRECACHE_MODEL( "models/pilot.mdl" );
PRECACHE_SOUND( "barney/ba_attack1.wav" );
PRECACHE_SOUND( "barney/ba_attack2.wav" );
@ -498,6 +543,10 @@ int CBarney::TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float
if( !IsAlive() || pev->deadflag == DEAD_DYING )
return ret;
// Do not speak about players harming me if I am a zombie.
if( IsZombieCop() )
return ret;
if( m_MonsterState != MONSTERSTATE_PRONE && ( pevAttacker->flags & FL_CLIENT ) )
{
m_flPlayerDamage += flDamage;
@ -580,7 +629,7 @@ void CBarney::TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir
{
case HITGROUP_CHEST:
case HITGROUP_STOMACH:
if (bitsDamageType & ( DMG_BULLET | DMG_SLASH | DMG_BLAST ) )
if( ( bitsDamageType & ( DMG_BULLET | DMG_SLASH | DMG_BLAST ) )&& HasKevlar() )
{
flDamage = flDamage / 2;
}
@ -764,6 +813,54 @@ void CBarney::DeclineFollowing( void )
PlaySentence( "BA_POK", 2, VOL_NORM, ATTN_NORM );
}
//=========================================================
// IdleRespond
// Respond to a previous question
//=========================================================
void CBarney::IdleRespond( void )
{
if( IsZombieCop() )
return;
CTalkMonster::IdleRespond();
}
int CBarney::FOkToSpeak( void )
{
if( IsZombieCop() )
return FALSE;
return CTalkMonster::FOkToSpeak();
}
BOOL CBarney::IsZombieCop( void ) const
{
return ( m_iBarneyFlags & BF_ZOMBIECOP );
}
BOOL CBarney::HasKevlar() const
{
return pev->skin == SKIN_ASYLUM_GUARD || pev->skin == SKIN_ZOMBIE_ASYLUM_GUARD;
}
//=========================================================
// Only called by monstermaker.
// Used to fix up Barney skin.
//=========================================================
void CBarney::FixupBarneySkin( BOOL bZombieCop )
{
if( bZombieCop )
{
// Map they21
//
// This Barney should attack players but use regular skin.
if( FStrEq( STRING( gpGlobals->mapname ), "they21" ) && FStrEq( STRING( pev->targetname ), "discoverer" ) )
{
pev->skin = SKIN_NORMAL_COP;
}
}
}
//=========================================================
// DEAD BARNEY PROP
//

79
dlls/barney.h Normal file
View File

@ -0,0 +1,79 @@
/***
*
* 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.
*
****/
#ifndef BARNEY_H
#define BARNEY_H
#include "talkmonster.h"
class CBarney : public CTalkMonster
{
public:
void Spawn(void);
void Precache(void);
void SetYawSpeed(void);
int ISoundMask(void);
void BarneyFirePistol(void);
void AlertSound(void);
int Classify(void);
void HandleAnimEvent(MonsterEvent_t *pEvent);
void RunTask(Task_t *pTask);
void StartTask(Task_t *pTask);
virtual int ObjectCaps(void) { return CTalkMonster::ObjectCaps() | FCAP_IMPULSE_USE; }
int TakeDamage(entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType);
BOOL CheckRangeAttack1(float flDot, float flDist);
void DeclineFollowing(void);
// Override these to set behavior
Schedule_t *GetScheduleOfType(int Type);
Schedule_t *GetSchedule(void);
MONSTERSTATE GetIdealState(void);
void DeathSound(void);
void PainSound(void);
void TalkInit(void);
void TraceAttack(entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType);
void Killed(entvars_t *pevAttacker, int iGib);
virtual int Save(CSave &save);
virtual int Restore(CRestore &restore);
static TYPEDESCRIPTION m_SaveData[];
BOOL m_fGunDrawn;
float m_painTime;
float m_checkAttackTime;
BOOL m_lastAttackCheck;
// UNDONE: What is this for? It isn't used?
float m_flPlayerDamage;// how much pain has the player inflicted on me?
CUSTOM_SCHEDULES;
void IdleRespond(void);
int FOkToSpeak(void);
BOOL IsZombieCop() const;
BOOL HasKevlar() const;
void FixupBarneySkin( BOOL bZombieCop );
int m_iBarneyFlags;
};
#endif // BARNEY_H

View File

@ -26,51 +26,12 @@
#include "decals.h"
#include "soundent.h"
#include "game.h"
#include "bullsquid.h"
#define SQUID_SPRINT_DIST 256 // how close the squid has to get before starting to sprint and refusing to swerve
int iSquidSpitSprite;
//=========================================================
// monster-specific schedule types
//=========================================================
enum
{
SCHED_SQUID_HURTHOP = LAST_COMMON_SCHEDULE + 1,
SCHED_SQUID_SMELLFOOD,
SCHED_SQUID_SEECRAB,
SCHED_SQUID_EAT,
SCHED_SQUID_SNIFF_AND_EAT,
SCHED_SQUID_WALLOW
};
//=========================================================
// monster-specific tasks
//=========================================================
enum
{
TASK_SQUID_HOPTURN = LAST_COMMON_TASK + 1
};
//=========================================================
// Bullsquid's spit projectile
//=========================================================
class CSquidSpit : public CBaseEntity
{
public:
void Spawn( void );
static void Shoot( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity );
void Touch( CBaseEntity *pOther );
void EXPORT Animate( void );
virtual int Save( CSave &save );
virtual int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
int m_maxFrame;
};
LINK_ENTITY_TO_CLASS( squidspit, CSquidSpit )
TYPEDESCRIPTION CSquidSpit::m_SaveData[] =
@ -89,7 +50,7 @@ void CSquidSpit::Spawn( void )
pev->rendermode = kRenderTransAlpha;
pev->renderamt = 255;
SET_MODEL( ENT( pev ), "sprites/bigspit.spr" );
SET_MODEL( ENT( pev ), "sprites/redbspit.spr" );
pev->frame = 0;
pev->scale = 0.5;
@ -184,46 +145,6 @@ void CSquidSpit::Touch( CBaseEntity *pOther )
#define BSQUID_AE_HOP ( 5 )
#define BSQUID_AE_THROW ( 6 )
class CBullsquid : public CBaseMonster
{
public:
void Spawn( void );
void Precache( void );
void SetYawSpeed( void );
int ISoundMask( void );
int Classify( void );
void HandleAnimEvent( MonsterEvent_t *pEvent );
void IdleSound( void );
void PainSound( void );
void DeathSound( void );
void AlertSound( void );
void AttackSound( void );
void StartTask( Task_t *pTask );
void RunTask( Task_t *pTask );
BOOL CheckMeleeAttack1( float flDot, float flDist );
BOOL CheckMeleeAttack2( float flDot, float flDist );
BOOL CheckRangeAttack1( float flDot, float flDist );
void RunAI( void );
BOOL FValidateHintType( short sHint );
Schedule_t *GetSchedule( void );
Schedule_t *GetScheduleOfType( int Type );
int TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType );
int IRelationship( CBaseEntity *pTarget );
int IgnoreConditions( void );
MONSTERSTATE GetIdealState( void );
int Save( CSave &save );
int Restore( CRestore &restore );
CUSTOM_SCHEDULES
static TYPEDESCRIPTION m_SaveData[];
BOOL m_fCanThreatDisplay;// this is so the squid only does the "I see a headcrab!" dance one time.
float m_flLastHurtTime;// we keep track of this, because if something hurts a squid, it will forget about its love of headcrabs for a while.
float m_flNextSpitTime;// last time the bullsquid used the spit attack.
};
LINK_ENTITY_TO_CLASS( monster_bullchicken, CBullsquid )
TYPEDESCRIPTION CBullsquid::m_SaveData[] =
@ -692,9 +613,9 @@ void CBullsquid::Precache()
{
PRECACHE_MODEL( "models/bullsquid.mdl" );
PRECACHE_MODEL( "sprites/bigspit.spr" );// spit projectile.
PRECACHE_MODEL( "sprites/redbspit.spr" );// spit projectile.
iSquidSpitSprite = PRECACHE_MODEL( "sprites/tinyspit.spr" );// client side spittle.
iSquidSpitSprite = PRECACHE_MODEL( "sprites/redtspit.spr" );// client side spittle.
PRECACHE_SOUND( "zombie/claw_miss2.wav" );// because we use the basemonster SWIPE animation event

98
dlls/bullsquid.h Normal file
View File

@ -0,0 +1,98 @@
/***
*
* 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.
*
****/
#ifndef BULLSQUID_H
#define BULLSQUID_H
//=========================================================
// monster-specific schedule types
//=========================================================
enum
{
SCHED_SQUID_HURTHOP = LAST_COMMON_SCHEDULE + 1,
SCHED_SQUID_SMELLFOOD,
SCHED_SQUID_SEECRAB,
SCHED_SQUID_EAT,
SCHED_SQUID_SNIFF_AND_EAT,
SCHED_SQUID_WALLOW,
};
//=========================================================
// monster-specific tasks
//=========================================================
enum
{
TASK_SQUID_HOPTURN = LAST_COMMON_TASK + 1,
};
//=========================================================
// Bullsquid's spit projectile
//=========================================================
class CSquidSpit : public CBaseEntity
{
public:
void Spawn( void );
static void Shoot( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity );
void Touch( CBaseEntity *pOther );
void EXPORT Animate( void );
virtual int Save( CSave &save );
virtual int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
int m_maxFrame;
};
class CBullsquid : public CBaseMonster
{
public:
void Spawn( void );
void Precache( void );
void SetYawSpeed( void );
int ISoundMask( void );
int Classify ( void );
void HandleAnimEvent( MonsterEvent_t *pEvent );
void IdleSound( void );
void PainSound( void );
void DeathSound( void );
void AlertSound ( void );
void AttackSound( void );
void StartTask ( Task_t *pTask );
void RunTask ( Task_t *pTask );
BOOL CheckMeleeAttack1 ( float flDot, float flDist );
BOOL CheckMeleeAttack2 ( float flDot, float flDist );
BOOL CheckRangeAttack1 ( float flDot, float flDist );
void RunAI( void );
BOOL FValidateHintType ( short sHint );
Schedule_t *GetSchedule( void );
Schedule_t *GetScheduleOfType ( int Type );
int TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType );
int IRelationship ( CBaseEntity *pTarget );
int IgnoreConditions ( void );
MONSTERSTATE GetIdealState ( void );
int Save( CSave &save );
int Restore( CRestore &restore );
CUSTOM_SCHEDULES;
static TYPEDESCRIPTION m_SaveData[];
BOOL m_fCanThreatDisplay;// this is so the squid only does the "I see a headcrab!" dance one time.
float m_flLastHurtTime;// we keep track of this, because if something hurts a squid, it will forget about its love of headcrabs for a while.
float m_flNextSpitTime;// last time the bullsquid used the spit attack.
};
#endif // BULLSQUID_H

View File

@ -101,6 +101,7 @@ typedef void(CBaseEntity::*USEPTR)( CBaseEntity *pActivator, CBaseEntity *pCalle
#define CLASS_PLAYER_ALLY 11
#define CLASS_PLAYER_BIOWEAPON 12 // hornets and snarks.launched by players
#define CLASS_ALIEN_BIOWEAPON 13 // hornets and snarks.launched by the alien menace
#define CLASS_SKELETON 14
#define CLASS_BARNACLE 99 // special because no one pays attention to it, and it eats a wide cross-section of creatures.
class CBaseEntity;
@ -340,6 +341,10 @@ public:
int ammo_uranium;
int ammo_hornets;
int ammo_argrens;
int ammo_ap9;
int ammo_taurus;
int ammo_sniper;
//Special stuff for grenades and satchels.
float m_flStartThrow;
float m_flReleaseThrow;

View File

@ -748,6 +748,8 @@ void ClientPrecache( void )
PRECACHE_SOUND( "debris/wood3.wav" );
PRECACHE_SOUND( "plats/train_use1.wav" ); // use a train
PRECACHE_SOUND( "plats/train_use2.wav" );
PRECACHE_SOUND( "plats/train_use6.wav" );
PRECACHE_SOUND( "buttons/spark5.wav" ); // hit computer texture
PRECACHE_SOUND( "buttons/spark6.wav" );
@ -787,6 +789,8 @@ void ClientPrecache( void )
if( giPrecacheGrunt )
UTIL_PrecacheOther( "monster_human_grunt" );
UTIL_PrecacheOther( "monster_th_cyberfranklin" );
}
/*
@ -1623,6 +1627,18 @@ 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_AP9 )
{
cd->vuser2.y = pl->ammo_ap9;
}
else if( pl->m_pActiveItem->m_iId == WEAPON_TAURUS )
{
cd->vuser2.y = pl->ammo_taurus;
}
else if( pl->m_pActiveItem->m_iId == WEAPON_EINAR1 || pl->m_pActiveItem->m_iId == WEAPON_HKG36 )
{
cd->vuser2.y = pl->ammo_sniper;
}
}
}
}

View File

@ -1535,6 +1535,18 @@ Vector CBaseEntity::FireBulletsPlayer( ULONG cShots, Vector vecSrc, Vector vecDi
case BULLET_PLAYER_357:
pEntity->TraceAttack( pevAttacker, gSkillData.plrDmg357, vecDir, &tr, DMG_BULLET );
break;
case BULLET_PLAYER_AP9:
pEntity->TraceAttack( pevAttacker, gSkillData.plrDmgAP9, vecDir, &tr, DMG_BULLET );
break;
case BULLET_PLAYER_CHAINGUN:
pEntity->TraceAttack( pevAttacker, gSkillData.plrDmgMP5, vecDir, &tr, DMG_BULLET );
break;
case BULLET_PLAYER_SNIPER:
pEntity->TraceAttack( pevAttacker, gSkillData.plrDmgSniper, vecDir, &tr, DMG_BULLET );
break;
case BULLET_PLAYER_TAURUS:
pEntity->TraceAttack( pevAttacker, gSkillData.plrDmgTaurus, vecDir, &tr, DMG_BULLET );
break;
case BULLET_NONE: // FIX
pEntity->TraceAttack( pevAttacker, 50, vecDir, &tr, DMG_CLUB );
TEXTURETYPE_PlaySound( &tr, vecSrc, vecEnd, iBulletType );

View File

@ -62,6 +62,9 @@ void CCrowbar::Precache( void )
PRECACHE_SOUND( "weapons/cbar_hitbod2.wav" );
PRECACHE_SOUND( "weapons/cbar_hitbod3.wav" );
PRECACHE_SOUND( "weapons/cbar_miss1.wav" );
PRECACHE_SOUND( "kelly/cbar_hitkelly1.wav" );
PRECACHE_SOUND( "kelly/cbar_hitkelly2.wav" );
PRECACHE_SOUND( "kelly/cbar_hitkelly3.wav" );
m_usCrowbar = PRECACHE_EVENT( 1, "events/crowbar.sc" );
}
@ -242,19 +245,40 @@ int CCrowbar::Swing( int fFirst )
{
if( pEntity->Classify() != CLASS_NONE && pEntity->Classify() != CLASS_MACHINE )
{
// play thwack or smack sound
switch( RANDOM_LONG( 0, 2 ) )
// Skeletons make different hit sounds.
if( pEntity->Classify() == CLASS_SKELETON )
{
case 0:
EMIT_SOUND( ENT( m_pPlayer->pev ), CHAN_ITEM, "weapons/cbar_hitbod1.wav", 1, ATTN_NORM );
break;
case 1:
EMIT_SOUND( ENT( m_pPlayer->pev ), CHAN_ITEM, "weapons/cbar_hitbod2.wav", 1, ATTN_NORM );
break;
case 2:
EMIT_SOUND( ENT( m_pPlayer->pev ), CHAN_ITEM, "weapons/cbar_hitbod3.wav", 1, ATTN_NORM );
break;
// play thwack or smack sound
switch( RANDOM_LONG( 0, 2 ) )
{
case 0:
EMIT_SOUND( ENT( m_pPlayer->pev ), CHAN_ITEM, "kelly/cbar_hitkelly1.wav", 1, ATTN_NORM );
break;
case 1:
EMIT_SOUND( ENT( m_pPlayer->pev ), CHAN_ITEM, "kelly/cbar_hitkelly2.wav", 1, ATTN_NORM );
break;
case 2:
EMIT_SOUND( ENT( m_pPlayer->pev ), CHAN_ITEM, "kelly/cbar_hitkelly3.wav", 1, ATTN_NORM );
break;
}
}
else
{
// play thwack or smack sound
switch( RANDOM_LONG( 0, 2 ) )
{
case 0:
EMIT_SOUND( ENT( m_pPlayer->pev ), CHAN_ITEM, "weapons/cbar_hitbod1.wav", 1, ATTN_NORM );
break;
case 1:
EMIT_SOUND( ENT( m_pPlayer->pev ), CHAN_ITEM, "weapons/cbar_hitbod2.wav", 1, ATTN_NORM );
break;
case 2:
EMIT_SOUND( ENT( m_pPlayer->pev ), CHAN_ITEM, "weapons/cbar_hitbod3.wav", 1, ATTN_NORM );
break;
}
}
m_pPlayer->m_iWeaponVolume = CROWBAR_BODYHIT_VOLUME;
if( !pEntity->IsAlive() )
return TRUE;

View File

@ -24,6 +24,7 @@
#include "effects.h"
#include "customentity.h"
#include "gamerules.h"
#include "flame.h"
#define EGON_PRIMARY_VOLUME 450
#define EGON_BEAM_SPRITE "sprites/xbeam1.spr"
@ -80,6 +81,10 @@ void CEgon::Precache( void )
PRECACHE_SOUND( "weapons/357_cock1.wav" );
PRECACHE_SOUND( "weapons/flmfire2.wav" );
UTIL_PrecacheOther( "flame" );
m_usEgonFire = PRECACHE_EVENT( 1, "events/egon_fire.sc" );
m_usEgonStop = PRECACHE_EVENT( 1, "events/egon_stop.sc" );
}
@ -232,8 +237,59 @@ void CEgon::Attack( void )
void CEgon::PrimaryAttack( void )
{
m_fireMode = FIRE_WIDE;
Attack();
// don't fire underwater
if( m_pPlayer->pev->waterlevel == 3 )
{
PlayEmptySound();
m_flNextPrimaryAttack = m_flNextSecondaryAttack = GetNextAttackDelay( 0.2 );
return;
}
if( !HasAmmo() )
{
m_flNextPrimaryAttack = m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.25;
PlayEmptySound();
return;
}
m_pPlayer->m_iWeaponVolume = EGON_PRIMARY_VOLUME;
// player "shoot" animation
m_pPlayer->SetAnimation( PLAYER_ATTACK1 );
UseAmmo( 1 );
int flags;
#if defined( CLIENT_WEAPONS )
flags = FEV_NOTHOST;
#else
flags = 0;
#endif
PLAYBACK_EVENT_FULL( flags, m_pPlayer->edict(), m_usEgonFire, 0, (float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, 0, 0, 0, 0 );
#ifndef CLIENT_DLL
Vector position, velocity;
Vector forward, right, up;
UTIL_MakeVectors( m_pPlayer->pev->v_angle + m_pPlayer->pev->punchangle );
forward = gpGlobals->v_forward;
right = gpGlobals->v_right;
up = gpGlobals->v_up;
position = m_pPlayer->pev->origin + m_pPlayer->pev->view_ofs;
position = position + forward * 16;
position = position + right * RANDOM_FLOAT( 4, 6 );
position = position + up * RANDOM_FLOAT( 1, 2 );
velocity = forward * 400;
velocity = velocity + right * ( RANDOM_LONG(0, 1 ) ? 16 : -16 );
velocity = velocity + up * ( RANDOM_LONG( 0, 1 ) ? 16 : -8 );
CFlame::Shoot( m_pPlayer->pev, position, velocity );
#endif
m_flNextPrimaryAttack = m_flNextSecondaryAttack = GetNextAttackDelay( 0.2f );
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 0.1;
}
void CEgon::Fire( const Vector &vecOrigSrc, const Vector &vecDir )
@ -475,9 +531,6 @@ void CEgon::WeaponIdle( void )
if( m_flTimeWeaponIdle > UTIL_WeaponTimeBase() )
return;
if( m_fireState != FIRE_OFF )
EndAttack();
int iAnim;
float flRand = RANDOM_FLOAT( 0, 1 );
@ -519,13 +572,13 @@ class CEgonAmmo : public CBasePlayerAmmo
void Spawn( void )
{
Precache();
SET_MODEL( ENT( pev ), "models/w_chainammo.mdl" );
SET_MODEL( ENT( pev ), "models/w_gas.mdl" );
CBasePlayerAmmo::Spawn();
}
void Precache( void )
{
PRECACHE_MODEL( "models/w_chainammo.mdl" );
PRECACHE_MODEL( "models/w_gas.mdl" );
PRECACHE_SOUND( "items/9mmclip1.wav" );
}

View File

@ -58,6 +58,18 @@ const char *CBreakable::pSpawnObjects[] =
"weapon_satchel", // 19
"weapon_snark", // 20
"weapon_hornetgun", // 21
"weapon_einar1", // 22
"ammo_th_sniper", // 23
"weapon_th_spanner", // 24
"weapon_th_ap9", // 25
"ammo_th_ap9", // 26
"weapon_th_shovel", // 27
"weapon_th_taurus", // 28
"ammo_th_taurus", // 29
"weapon_th_chaingun", // 30
"weapon_th_medkit", // 31
"weapon_th_sniper", // 32
"ammo_th_sniper", // 33
};
void CBreakable::KeyValue( KeyValueData* pkvd )

View File

@ -439,6 +439,84 @@ 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" };
// MONSTERS
// Baby Kelly
cvar_t sk_babykelly_health1 = { "sk_babykelly_health1", "0" };
cvar_t sk_babykelly_health2 = { "sk_babykelly_health2", "0" };
cvar_t sk_babykelly_health3 = { "sk_babykelly_health3", "0" };
// Boss
cvar_t sk_boss_health1 = { "sk_boss_health1", "0" };
cvar_t sk_boss_health2 = { "sk_boss_health2", "0" };
cvar_t sk_boss_health3 = { "sk_boss_health3", "0" };
cvar_t sk_cyberfranklin_health1 = { "sk_cyberfranklin_health1", "0" };
cvar_t sk_cyberfranklin_health2 = { "sk_cyberfranklin_health2", "0" };
cvar_t sk_cyberfranklin_health3 = { "sk_cyberfranklin_health3", "0" };
// Houndeye
cvar_t sk_houndeye_dmg_bite1 = { "sk_houndeye_dmg_bite1", "0" };
cvar_t sk_houndeye_dmg_bite2 = { "sk_houndeye_dmg_bite2", "0" };
cvar_t sk_houndeye_dmg_bite3 = { "sk_houndeye_dmg_bite3", "0" };
// Megasquid
cvar_t sk_megasquid_health1 = { "sk_megasquid_health1", "0" };
cvar_t sk_megasquid_health2 = { "sk_megasquid_health2", "0" };
cvar_t sk_megasquid_health3 = { "sk_megasquid_health3", "0" };
// Zombie bull
cvar_t sk_zombiebull_health1 = { "sk_zombiebull_health1", "0" };
cvar_t sk_zombiebull_health2 = { "sk_zombiebull_health2", "0" };
cvar_t sk_zombiebull_health3 = { "sk_zombiebull_health3", "0" };
cvar_t sk_zombiebull_dmg_bite1 = { "sk_zombiebull_dmg_bite1", "0" };
cvar_t sk_zombiebull_dmg_bite2 = { "sk_zombiebull_dmg_bite2", "0" };
cvar_t sk_zombiebull_dmg_bite3 = { "sk_zombiebull_dmg_bite3", "0" };
cvar_t sk_zombiebull_dmg_whip1 = { "sk_zombiebull_dmg_whip1", "0" };
cvar_t sk_zombiebull_dmg_whip2 = { "sk_zombiebull_dmg_whip2", "0" };
cvar_t sk_zombiebull_dmg_whip3 = { "sk_zombiebull_dmg_whip3", "0" };
// PLAYER WEAPONS
// Shovel
cvar_t sk_plr_shovel1 = { "sk_plr_shovel1", "0" };
cvar_t sk_plr_shovel2 = { "sk_plr_shovel2", "0" };
cvar_t sk_plr_shovel3 = { "sk_plr_shovel3", "0" };
// Spanner
cvar_t sk_plr_spanner1 = { "sk_plr_spanner1", "0" };
cvar_t sk_plr_spanner2 = { "sk_plr_spanner2", "0" };
cvar_t sk_plr_spanner3 = { "sk_plr_spanner3", "0" };
// AP9 Round
cvar_t sk_plr_ap9_bullet1 = { "sk_plr_ap9_bullet1", "0" };
cvar_t sk_plr_ap9_bullet2 = { "sk_plr_ap9_bullet2", "0" };
cvar_t sk_plr_ap9_bullet3 = { "sk_plr_ap9_bullet3", "0" };
// Taurus Round
cvar_t sk_plr_taurus_bullet1 = { "sk_plr_taurus_bullet1", "0" };
cvar_t sk_plr_taurus_bullet2 = { "sk_plr_taurus_bullet2", "0" };
cvar_t sk_plr_taurus_bullet3 = { "sk_plr_taurus_bullet3", "0" };
// Sniper Round
cvar_t sk_plr_sniper_bullet1 = { "sk_plr_sniper_bullet1", "0" };
cvar_t sk_plr_sniper_bullet2 = { "sk_plr_sniper_bullet2", "0" };
cvar_t sk_plr_sniper_bullet3 = { "sk_plr_sniper_bullet3", "0" };
// Flamethrower
cvar_t sk_plr_flame1 = { "sk_plr_flame1", "0" };
cvar_t sk_plr_flame2 = { "sk_plr_flame2", "0" };
cvar_t sk_plr_flame3 = { "sk_plr_flame3", "0" };
// HEALTH/SUIT CHARGE DISTRIBUTION
// Medkit
cvar_t sk_medkit1 = { "sk_medkit1", "0" };
cvar_t sk_medkit2 = { "sk_medkit2", "0" };
cvar_t sk_medkit3 = { "sk_medkit3", "0" };
// END Cvars for Skill Level settings
// Register your console variables here
@ -847,6 +925,86 @@ void GameDLLInit( void )
CVAR_REGISTER( &sk_player_leg1 );
CVAR_REGISTER( &sk_player_leg2 );
CVAR_REGISTER( &sk_player_leg3 );
// MONSTERS
// Baby Kelly
CVAR_REGISTER( &sk_babykelly_health1 );
CVAR_REGISTER( &sk_babykelly_health2 );
CVAR_REGISTER( &sk_babykelly_health3 );
// Boss
CVAR_REGISTER( &sk_boss_health1 );
CVAR_REGISTER( &sk_boss_health2 );
CVAR_REGISTER( &sk_boss_health3 );
// Cyber Franklin
CVAR_REGISTER( &sk_cyberfranklin_health1 );
CVAR_REGISTER( &sk_cyberfranklin_health2 );
CVAR_REGISTER( &sk_cyberfranklin_health3 );
// Houndeye
CVAR_REGISTER( &sk_houndeye_dmg_bite1 );
CVAR_REGISTER( &sk_houndeye_dmg_bite2 );
CVAR_REGISTER( &sk_houndeye_dmg_bite3 );
// Megasquid
CVAR_REGISTER( &sk_megasquid_health1 );
CVAR_REGISTER( &sk_megasquid_health2 );
CVAR_REGISTER( &sk_megasquid_health3 );
// Zombie bull
CVAR_REGISTER( &sk_zombiebull_health1 );
CVAR_REGISTER( &sk_zombiebull_health2 );
CVAR_REGISTER( &sk_zombiebull_health3 );
CVAR_REGISTER( &sk_zombiebull_dmg_bite1 );
CVAR_REGISTER( &sk_zombiebull_dmg_bite2 );
CVAR_REGISTER( &sk_zombiebull_dmg_bite3 );
CVAR_REGISTER( &sk_zombiebull_dmg_whip1 );
CVAR_REGISTER( &sk_zombiebull_dmg_whip2 );
CVAR_REGISTER( &sk_zombiebull_dmg_whip3 );
// PLAYER WEAPONS
// Shovel
CVAR_REGISTER( &sk_plr_shovel1 );
CVAR_REGISTER( &sk_plr_shovel2 );
CVAR_REGISTER( &sk_plr_shovel3 );
// Spanner
CVAR_REGISTER( &sk_plr_spanner1 );
CVAR_REGISTER( &sk_plr_spanner2 );
CVAR_REGISTER( &sk_plr_spanner3 );
// AP9 Round
CVAR_REGISTER( &sk_plr_ap9_bullet1 );
CVAR_REGISTER( &sk_plr_ap9_bullet2 );
CVAR_REGISTER( &sk_plr_ap9_bullet3 );
// Taurus Round
CVAR_REGISTER( &sk_plr_taurus_bullet1 );
CVAR_REGISTER( &sk_plr_taurus_bullet2 );
CVAR_REGISTER( &sk_plr_taurus_bullet3 );
// Sniper Round
CVAR_REGISTER( &sk_plr_sniper_bullet1 );
CVAR_REGISTER( &sk_plr_sniper_bullet2 );
CVAR_REGISTER( &sk_plr_sniper_bullet3 );
// Flamethrower
CVAR_REGISTER( &sk_plr_flame1 );
CVAR_REGISTER( &sk_plr_flame2 );
CVAR_REGISTER( &sk_plr_flame3 );
// HEALTH/SUIT CHARGE DISTRIBUTION
// Medkit
CVAR_REGISTER( &sk_medkit1 );
CVAR_REGISTER( &sk_medkit2 );
CVAR_REGISTER( &sk_medkit3 );
// END REGISTER CVARS FOR SKILL LEVEL STUFF
SERVER_COMMAND( "exec skill.cfg\n" );

View File

@ -301,6 +301,53 @@ void CGameRules::RefreshSkillData ( void )
gSkillData.plrStomach = GetSkillCvar( "sk_player_stomach" );
gSkillData.plrLeg = GetSkillCvar( "sk_player_leg" );
gSkillData.plrArm = GetSkillCvar( "sk_player_arm" );
// MONSTERS
// Baby kelly
gSkillData.babykellyhealth = GetSkillCvar( "sk_babykelly_health" );
// Boss
gSkillData.bossHealth = GetSkillCvar( "sk_boss_health" );
// Cyber Franklin
gSkillData.cyberfranklinHealth = GetSkillCvar( "sk_cyberfranklin_health" );
// Houndeye
gSkillData.houndeyeDmgBite = GetSkillCvar( "sk_houndeye_dmg_bite" );
// Megasquid
gSkillData.megasquidHealth = GetSkillCvar( "sk_megasquid_health" );
// Zombie bull
gSkillData.zombiebullHealth = GetSkillCvar( "sk_zombiebull_health" );
gSkillData.zombiebullDmgBite = GetSkillCvar( "sk_zombiebull_dmg_bite" );
gSkillData.zombiebullDmgWhip = GetSkillCvar( "sk_zombiebull_dmg_whip" );
// PLAYER WEAPONS
// Shovel
gSkillData.plrDmgShovel = GetSkillCvar( "sk_plr_shovel" );
// Spanner
gSkillData.plrDmgSpanner = GetSkillCvar( "sk_plr_spanner" );
// AP9 Round
gSkillData.plrDmgAP9 = GetSkillCvar( "sk_plr_ap9_bullet" );
// Taurus Round
gSkillData.plrDmgTaurus = GetSkillCvar( "sk_plr_taurus_bullet" );
// Sniper Round
gSkillData.plrDmgSniper = GetSkillCvar( "sk_plr_sniper_bullet" );
// Flamethrower
gSkillData.plrDmgFlame = GetSkillCvar( "sk_plr_flame" );
// HEALTH/CHARGE
// Medkit
gSkillData.medkitHeal = GetSkillCvar( "sk_medkit" );
}
//=========================================================

View File

@ -21,6 +21,13 @@
#include "nodes.h"
#include "player.h"
#define GLOCK_MODEL_DEFAULT "models/w_9mmhandgun.mdl"
#define GLOCK_MODEL_SILENCER "models/w_silencer.mdl"
#define SILENCER_GROUP 2
#define SILENCER_OFF 0
#define SILENCER_ON 1
enum glock_e
{
GLOCK_IDLE1 = 0,
@ -43,7 +50,17 @@ void CGlock::Spawn()
pev->classname = MAKE_STRING( "weapon_9mmhandgun" ); // hack to allow for old names
Precache();
m_iId = WEAPON_GLOCK;
SET_MODEL( ENT( pev ), "models/w_9mmhandgun.mdl" );
char* szModel = NULL;
if( pev->body == SILENCER_ON )
szModel = GLOCK_MODEL_SILENCER;
else
szModel = GLOCK_MODEL_DEFAULT;
SET_MODEL( ENT( pev ), szModel );
// Always put the silencer on, for now.
m_fSilencerOn = TRUE;
m_iDefaultAmmo = GLOCK_DEFAULT_GIVE;
@ -54,6 +71,7 @@ void CGlock::Precache( void )
{
PRECACHE_MODEL( "models/v_9mmhandgun.mdl" );
PRECACHE_MODEL( "models/w_9mmhandgun.mdl" );
PRECACHE_MODEL( "models/w_silencer.mdl" );
PRECACHE_MODEL( "models/p_9mmhandgun.mdl" );
m_iShell = PRECACHE_MODEL( "models/shell.mdl" );// brass shell
@ -88,18 +106,66 @@ 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 );
#ifdef CLIENT_DLL
pev->body = 1;
#endif
return DefaultDeploy( "models/v_9mmhandgun.mdl", "models/p_9mmhandgun.mdl", GLOCK_DRAW, "onehanded", UseDecrement(), pev->body );
}
void CGlock::Holster( int skiplocal /*= 0*/ )
{
m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.5;
SendWeaponAnim( GLOCK_HOLSTER );
m_fInAttack = 0;
}
BOOL CGlock::ShouldWeaponIdle( void )
{
return m_fInAttack != 0;
}
void CGlock::SecondaryAttack( void )
{
GlockFire( 0.1, 0.2, FALSE );
if( m_fInAttack != 0 )
return;
if( !m_fSilencerOn )
{
// Add silencer.
m_fInAttack = 1;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 1.0;
SendWeaponAnim( GLOCK_HOLSTER, 1, SILENCER_OFF );
m_flNextPrimaryAttack = m_flNextSecondaryAttack = GetNextAttackDelay( 2.0 );
}
else
{
// Remove silencer.
m_fInAttack = 2;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 2.4; // 3.3
SendWeaponAnim( GLOCK_ADD_SILENCER, 1, SILENCER_ON );
m_flNextPrimaryAttack = m_flNextSecondaryAttack = GetNextAttackDelay( 3.4 );
}
}
void CGlock::PrimaryAttack( void )
{
GlockFire( 0.01, 0.3, TRUE );
if( m_fInAttack != 0 )
return;
if( m_fSilencerOn )
{
GlockFire( 0.01, 0.3, TRUE );
}
else
{
GlockFire( 0.1, 0.2, FALSE );
}
}
void CGlock::GlockFire( float flSpread, float flCycleTime, BOOL fUseAutoAim )
@ -156,7 +222,9 @@ void CGlock::GlockFire( float flSpread, float flCycleTime, BOOL fUseAutoAim )
Vector vecDir;
vecDir = m_pPlayer->FireBulletsPlayer( 1, vecSrc, vecAiming, Vector( flSpread, flSpread, flSpread ), 8192, BULLET_PLAYER_9MM, 0, 0, m_pPlayer->pev, m_pPlayer->random_seed );
PLAYBACK_EVENT_FULL( flags, m_pPlayer->edict(), fUseAutoAim ? m_usFireGlock1 : m_usFireGlock2, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, vecDir.x, vecDir.y, 0, 0, ( m_iClip == 0 ) ? 1 : 0, 0 );
int body = m_fSilencerOn ? SILENCER_ON : SILENCER_OFF;
PLAYBACK_EVENT_FULL( flags, m_pPlayer->edict(), m_usFireGlock1, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, vecDir.x, vecDir.y, body, 0, ( m_iClip == 0 ) ? 1 : 0, m_fSilencerOn );
m_flNextPrimaryAttack = m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + flCycleTime;
@ -170,17 +238,21 @@ void CGlock::GlockFire( float flSpread, float flCycleTime, BOOL fUseAutoAim )
void CGlock::Reload( void )
{
if( m_pPlayer->ammo_9mm <= 0 )
return;
return;
int body = m_fSilencerOn ? SILENCER_ON : SILENCER_OFF;
int iResult;
if( m_iClip == 0 )
iResult = DefaultReload( 17, GLOCK_RELOAD, 1.5 );
iResult = DefaultReload( GLOCK_MAX_CLIP, GLOCK_RELOAD, 1.5, body );
else
iResult = DefaultReload( 17, GLOCK_RELOAD_NOT_EMPTY, 1.5 );
iResult = DefaultReload( GLOCK_MAX_CLIP, GLOCK_RELOAD_NOT_EMPTY, 1.5, body );
if( iResult )
{
m_fInAttack = 0;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + UTIL_SharedRandomFloat( m_pPlayer->random_seed, 10, 15 );
}
}
@ -194,28 +266,51 @@ void CGlock::WeaponIdle( void )
if( m_flTimeWeaponIdle > UTIL_WeaponTimeBase() )
return;
// only idle if the slid isn't back
if( m_iClip != 0 )
if( m_fInAttack != 0 )
{
int iAnim;
float flRand = UTIL_SharedRandomFloat( m_pPlayer->random_seed, 0.0, 1.0 );
if( m_fInAttack == 1 )
{
m_fSilencerOn = TRUE;
}
else if( m_fInAttack == 2 )
{
m_fSilencerOn = FALSE;
}
if( flRand <= 0.3 + 0 * 0.75 )
int body = m_fSilencerOn ? SILENCER_ON : SILENCER_OFF;
SendWeaponAnim( GLOCK_DRAW, UseDecrement(), body );
m_fInAttack = 0;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 1.0;
}
else
{
// only idle if the slid isn't back
if( m_iClip != 0 )
{
iAnim = GLOCK_IDLE3;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 49.0 / 16;
int iAnim;
float flRand = UTIL_SharedRandomFloat( m_pPlayer->random_seed, 0.0, 1.0 );
if( flRand <= 0.3 + 0 * 0.75 )
{
iAnim = GLOCK_IDLE3;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 49.0 / 16;
}
else if( flRand <= 0.6 + 0 * 0.875 )
{
iAnim = GLOCK_IDLE1;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 60.0 / 16.0;
}
else
{
iAnim = GLOCK_IDLE2;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 40.0 / 16.0;
}
SendWeaponAnim( iAnim, 1, m_fSilencerOn ? 1 : 0 );
}
else if( flRand <= 0.6 + 0 * 0.875 )
{
iAnim = GLOCK_IDLE1;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 60.0 / 16.0;
}
else
{
iAnim = GLOCK_IDLE2;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 40.0 / 16.0;
}
SendWeaponAnim( iAnim, 1 );
}
}

View File

@ -41,7 +41,7 @@ void CHandGrenade::Spawn()
{
Precache();
m_iId = WEAPON_HANDGRENADE;
SET_MODEL( ENT( pev ), "models/w_grenade.mdl" );
SET_MODEL( ENT( pev ), "models/w_tnt.mdl" );
#ifndef CLIENT_DLL
pev->dmg = gSkillData.plrDmgHandGrenade;
@ -53,9 +53,9 @@ void CHandGrenade::Spawn()
void CHandGrenade::Precache( void )
{
PRECACHE_MODEL( "models/w_grenade.mdl" );
PRECACHE_MODEL( "models/v_grenade.mdl" );
PRECACHE_MODEL( "models/p_grenade.mdl" );
PRECACHE_MODEL( "models/w_tnt.mdl" );
PRECACHE_MODEL( "models/v_tnt.mdl" );
PRECACHE_MODEL( "models/p_tnt.mdl" );
}
int CHandGrenade::GetItemInfo( ItemInfo *p )
@ -78,7 +78,7 @@ int CHandGrenade::GetItemInfo( ItemInfo *p )
BOOL CHandGrenade::Deploy()
{
m_flReleaseThrow = -1;
return DefaultDeploy( "models/v_grenade.mdl", "models/p_grenade.mdl", HANDGRENADE_DRAW, "crowbar" );
return DefaultDeploy( "models/v_tnt.mdl", "models/p_tnt.mdl", HANDGRENADE_DRAW, "crowbar" );
}
BOOL CHandGrenade::CanHolster( void )
@ -150,7 +150,7 @@ void CHandGrenade::WeaponIdle( void )
if( time < 0 )
time = 0;
CGrenade::ShootTimed( m_pPlayer->pev, vecSrc, vecThrow, time );
CTnt::ShootTimed( m_pPlayer->pev, vecSrc, vecThrow, time );
if( flVel < 500 )
{

View File

@ -22,6 +22,7 @@
#include "monsters.h"
#include "schedule.h"
#include "game.h"
#include "headcrab.h"
//=========================================================
// Monster's Anim Events Go Here
@ -70,43 +71,6 @@ Schedule_t slHCRangeAttack1Fast[] =
},
};
class CHeadCrab : public CBaseMonster
{
public:
void Spawn( void );
void Precache( void );
void RunTask ( Task_t *pTask );
void StartTask ( Task_t *pTask );
void SetYawSpeed ( void );
void EXPORT LeapTouch ( CBaseEntity *pOther );
Vector Center( void );
Vector BodyTarget( const Vector &posSrc );
void PainSound( void );
void DeathSound( void );
void IdleSound( void );
void AlertSound( void );
void PrescheduleThink( void );
int Classify ( void );
void HandleAnimEvent( MonsterEvent_t *pEvent );
BOOL CheckRangeAttack1 ( float flDot, float flDist );
BOOL CheckRangeAttack2 ( float flDot, float flDist );
int TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType );
virtual float GetDamageAmount( void ) { return gSkillData.headcrabDmgBite; }
virtual int GetVoicePitch( void ) { return 100; }
virtual float GetSoundVolue( void ) { return 1.0; }
Schedule_t* GetScheduleOfType ( int Type );
CUSTOM_SCHEDULES
static const char *pIdleSounds[];
static const char *pAlertSounds[];
static const char *pPainSounds[];
static const char *pAttackSounds[];
static const char *pDeathSounds[];
static const char *pBiteSounds[];
};
LINK_ENTITY_TO_CLASS( monster_headcrab, CHeadCrab )
DEFINE_CUSTOM_SCHEDULES( CHeadCrab )
@ -260,9 +224,7 @@ void CHeadCrab::HandleAnimEvent( MonsterEvent_t *pEvent )
vecJumpDir = Vector( gpGlobals->v_forward.x, gpGlobals->v_forward.y, gpGlobals->v_up.z ) * 350;
}
int iSound = RANDOM_LONG(0,2);
if( iSound != 0 )
EMIT_SOUND_DYN( edict(), CHAN_VOICE, pAttackSounds[iSound], GetSoundVolue(), ATTN_IDLE, 0, GetVoicePitch() );
AttackSound();
pev->velocity = vecJumpDir;
m_flNextAttack = gpGlobals->time + 2;
@ -286,7 +248,7 @@ void CHeadCrab::Spawn()
pev->solid = SOLID_SLIDEBOX;
pev->movetype = MOVETYPE_STEP;
m_bloodColor = BLOOD_COLOR_GREEN;
m_bloodColor = BLOOD_COLOR_RED;
pev->effects = 0;
pev->health = gSkillData.headcrabHealth;
pev->view_ofs = Vector( 0, 0, 20 );// position of the eyes relative to monster's origin.
@ -467,6 +429,16 @@ void CHeadCrab::DeathSound( void )
EMIT_SOUND_DYN( edict(), CHAN_VOICE, RANDOM_SOUND_ARRAY( pDeathSounds ), GetSoundVolue(), ATTN_IDLE, 0, GetVoicePitch() );
}
//=========================================================
// AttackSound
//=========================================================
void CHeadCrab::AttackSound( void )
{
int iSound = RANDOM_LONG(0, 2);
if( iSound != 0 )
EMIT_SOUND_DYN( edict(), CHAN_VOICE, pAttackSounds[iSound], GetSoundVolue(), ATTN_IDLE, 0, GetVoicePitch() );
}
Schedule_t *CHeadCrab::GetScheduleOfType( int Type )
{
switch( Type )

56
dlls/headcrab.h Normal file
View File

@ -0,0 +1,56 @@
/***
*
* 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.
*
****/
#ifndef HEADCRAB_H
#define HEADCRAB_H
class CHeadCrab : public CBaseMonster
{
public:
void Spawn( void );
void Precache( void );
void RunTask ( Task_t *pTask );
void StartTask ( Task_t *pTask );
void SetYawSpeed ( void );
void EXPORT LeapTouch ( CBaseEntity *pOther );
Vector Center( void );
Vector BodyTarget( const Vector &posSrc );
virtual void PainSound( void );
virtual void DeathSound( void );
virtual void IdleSound( void );
virtual void AlertSound( void );
virtual void AttackSound( void );
void PrescheduleThink( void );
int Classify ( void );
void HandleAnimEvent( MonsterEvent_t *pEvent );
BOOL CheckRangeAttack1 ( float flDot, float flDist );
BOOL CheckRangeAttack2 ( float flDot, float flDist );
int TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType );
virtual float GetDamageAmount( void ) { return gSkillData.headcrabDmgBite; }
virtual int GetVoicePitch( void ) { return 100; }
virtual float GetSoundVolue( void ) { return 1.0; }
Schedule_t* GetScheduleOfType ( int Type );
CUSTOM_SCHEDULES;
static const char *pIdleSounds[];
static const char *pAlertSounds[];
static const char *pPainSounds[];
static const char *pAttackSounds[];
static const char *pDeathSounds[];
static const char *pBiteSounds[];
};
#endif // HEADCRAB_H

View File

@ -40,6 +40,12 @@
#include "soundent.h"
#include "effects.h"
#include "customentity.h"
#include "hgrunt.h"
//
// Spawn flags
//
#define SF_HGRUNT_ZSOLDIER 64
int g_fGruntQuestion; // true if an idle grunt asked a question. Cleared when someone answers.
@ -71,6 +77,9 @@ extern DLL_GLOBAL int g_iSkillLevel;
#define GUN_MP5 0
#define GUN_SHOTGUN 1
#define GUN_NONE 2
#define PARACHUTE_GROUP 3
#define PARACHUTE_OFF 0
#define PARACHUTE_ON 1
//=========================================================
// Monster's Anim Events Go Here
@ -119,73 +128,6 @@ enum
//=========================================================
#define bits_COND_GRUNT_NOFIRE ( bits_COND_SPECIAL1 )
class CHGrunt : public CSquadMonster
{
public:
void Spawn( void );
void Precache( void );
void SetYawSpeed( void );
int Classify( void );
int ISoundMask( void );
void HandleAnimEvent( MonsterEvent_t *pEvent );
BOOL FCanCheckAttacks( void );
BOOL CheckMeleeAttack1( float flDot, float flDist );
BOOL CheckRangeAttack1( float flDot, float flDist );
BOOL CheckRangeAttack2( float flDot, float flDist );
void CheckAmmo( void );
void SetActivity( Activity NewActivity );
void StartTask( Task_t *pTask );
void RunTask( Task_t *pTask );
void DeathSound( void );
void PainSound( void );
void IdleSound( void );
Vector GetGunPosition( void );
void Shoot( void );
void Shotgun( void );
void PrescheduleThink( void );
void GibMonster( void );
void SpeakSentence( void );
int Save( CSave &save );
int Restore( CRestore &restore );
CBaseEntity *Kick( void );
Schedule_t *GetSchedule( void );
Schedule_t *GetScheduleOfType( int Type );
void TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType);
int TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType );
int IRelationship( CBaseEntity *pTarget );
BOOL FOkToSpeak( void );
void JustSpoke( void );
CUSTOM_SCHEDULES
static TYPEDESCRIPTION m_SaveData[];
// checking the feasibility of a grenade toss is kind of costly, so we do it every couple of seconds,
// not every server frame.
float m_flNextGrenadeCheck;
float m_flNextPainTime;
float m_flLastEnemySightTime;
Vector m_vecTossVelocity;
BOOL m_fThrowGrenade;
BOOL m_fStanding;
BOOL m_fFirstEncounter;// only put on the handsign show in the squad's first encounter.
int m_cClipSize;
int m_voicePitch;
int m_iBrassShell;
int m_iShotgunShell;
int m_iSentence;
static const char *pGruntSentences[];
};
LINK_ENTITY_TO_CLASS( monster_human_grunt, CHGrunt )
TYPEDESCRIPTION CHGrunt::m_SaveData[] =
@ -202,6 +144,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 )
@ -332,6 +275,10 @@ int CHGrunt::ISoundMask( void )
//=========================================================
BOOL CHGrunt::FOkToSpeak( void )
{
// Zombie soldiers do not speak.
if( IsZombieSoldier() )
return FALSE;
// if someone else is talking, don't speak
if( gpGlobals->time <= CTalkMonster::g_talkWaitTime )
return FALSE;
@ -632,6 +579,19 @@ int CHGrunt::TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float
return CSquadMonster::TakeDamage( pevInflictor, pevAttacker, flDamage, bitsDamageType );
}
void CHGrunt::Killed( entvars_t *pevAttacker, int iGib )
{
//
// If a grunt is killed while using a parachute, update
// bodygroup to make it invisible.
//
if( GetBodygroup( PARACHUTE_GROUP ) == PARACHUTE_ON )
{
SetBodygroup( PARACHUTE_GROUP, PARACHUTE_OFF );
}
CSquadMonster::Killed( pevAttacker, iGib );
}
//=========================================================
// SetYawSpeed - allows each sequence to have a different
// turn rate associated with it.
@ -741,6 +701,9 @@ void CHGrunt::CheckAmmo( void )
//=========================================================
int CHGrunt::Classify( void )
{
if( IsZombieSoldier() )
return CLASS_ALIEN_MONSTER;
return CLASS_HUMAN_MILITARY;
}
@ -972,7 +935,33 @@ void CHGrunt::Spawn()
{
Precache();
SET_MODEL( ENT( pev ), "models/hgrunt.mdl" );
m_iGruntFlags = 0;
// Check if this is a zombie soldier.
if( pev->spawnflags & SF_HGRUNT_ZSOLDIER )
{
m_iGruntFlags |= GF_ZSOLDIER;
}
char* szModel = (char*)STRING( pev->model );
// If this is a zombie soldier with a regular grunt model,
// switch to appropriate model.
if( IsZombieSoldier() && !FStrEq( szModel, "models/zgrunt.mdl" ) )
{
szModel = "models/zgrunt.mdl";
pev->model = ALLOC_STRING( szModel );
}
else
{
// Pick regular grunt model.
szModel = "models/hgrunt.mdl";
pev->model = ALLOC_STRING( szModel );
}
// Set new model.
SET_MODEL( ENT( pev ), (char*)STRING( pev->model ) );
UTIL_SetSize( pev, VEC_HUMAN_HULL_MIN, VEC_HUMAN_HULL_MAX );
pev->solid = SOLID_SLIDEBOX;
@ -1038,6 +1027,7 @@ void CHGrunt::Spawn()
void CHGrunt::Precache()
{
PRECACHE_MODEL( "models/hgrunt.mdl" );
PRECACHE_MODEL( "models/zgrunt.mdl" );
PRECACHE_SOUND( "hgrunt/gr_mgun1.wav" );
PRECACHE_SOUND( "hgrunt/gr_mgun2.wav" );
@ -1203,6 +1193,11 @@ void CHGrunt::DeathSound( void )
}
}
BOOL CHGrunt::IsZombieSoldier( void ) const
{
return ( m_iGruntFlags & GF_ZSOLDIER );
}
//=========================================================
// AI Schedules Specific to this monster
//=========================================================
@ -1910,6 +1905,17 @@ void CHGrunt::SetActivity( Activity NewActivity )
}
iSequence = LookupActivity( NewActivity );
break;
case ACT_LAND:
//
// If a grunt landed using a parachute, update
// bodygroup to make it invisible.
//
if( GetBodygroup( PARACHUTE_GROUP ) == PARACHUTE_ON )
{
SetBodygroup( PARACHUTE_GROUP, PARACHUTE_OFF );
}
iSequence = LookupActivity( NewActivity );
break;
default:
iSequence = LookupActivity( NewActivity );
break;
@ -2212,13 +2218,31 @@ Schedule_t *CHGrunt::GetScheduleOfType( int Type )
}
else
{
if( RANDOM_LONG( 0, 1 ) )
// Zombie soldiers cannot use grenades.
if( IsZombieSoldier() )
{
return &slGruntTakeCover[0];
}
else
{
return &slGruntGrenadeCover[0];
// Regular cover.
if( RANDOM_LONG( 0, 1 ) )
{
return &slGruntTakeCover[0];
}
else
{
if( !FClassnameIs( pev,"monster_th_cyberfranklin" ) )
{
// Regular grenade cover.
return &slGruntGrenadeCover[0];
}
else
{
// Prevent Cyber franklin from dropping grenades down.
return &slGruntTakeCover[0];
}
}
}
}
}
@ -2343,15 +2367,7 @@ Schedule_t *CHGrunt::GetScheduleOfType( int Type )
// CHGruntRepel - when triggered, spawns a monster_human_grunt
// repelling down a line.
//=========================================================
class CHGruntRepel : public CBaseMonster
{
public:
void Spawn( void );
void Precache( void );
void EXPORT RepelUse ( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
int m_iSpriteTexture; // Don't save, precache
};
#define SF_REPEL_PARACHUTE 32
LINK_ENTITY_TO_CLASS( monster_grunt_repel, CHGruntRepel )
@ -2386,6 +2402,23 @@ void CHGruntRepel::RepelUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_
// UNDONE: position?
pGrunt->m_vecLastPosition = tr.vecEndPos;
//
// Fix trigger condition targets.
//
pGrunt->m_iszTriggerTarget = m_iszTriggerTarget;
pGrunt->m_iTriggerCondition = m_iTriggerCondition;
// If this is a parachuted grunt, set parachute
// bodygroup visible.
if( pev->spawnflags & SF_REPEL_PARACHUTE )
{
pGrunt->SetBodygroup( PARACHUTE_GROUP, PARACHUTE_ON );
// Do not spawn beam. Return.
UTIL_Remove( this );
return;
}
CBeam *pBeam = CBeam::BeamCreate( "sprites/rope.spr", 10 );
pBeam->PointEntInit( pev->origin + Vector( 0, 0, 112 ), pGrunt->entindex() );
pBeam->SetFlags( BEAM_FSOLID );
@ -2399,18 +2432,6 @@ void CHGruntRepel::RepelUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_
//=========================================================
// DEAD HGRUNT PROP
//=========================================================
class CDeadHGrunt : public CBaseMonster
{
public:
void Spawn( void );
int Classify( void ) { return CLASS_HUMAN_MILITARY; }
void KeyValue( KeyValueData *pkvd );
int m_iPose;// which sequence to display -- temporary, don't need to save
static char *m_szPoses[3];
};
char *CDeadHGrunt::m_szPoses[] = { "deadstomach", "deadside", "deadsitting" };
void CDeadHGrunt::KeyValue( KeyValueData *pkvd )
@ -2432,7 +2453,28 @@ LINK_ENTITY_TO_CLASS( monster_hgrunt_dead, CDeadHGrunt )
void CDeadHGrunt::Spawn( void )
{
PRECACHE_MODEL( "models/hgrunt.mdl" );
SET_MODEL( ENT( pev ), "models/hgrunt.mdl" );
PRECACHE_MODEL( "models/zgrunt.mdl" );
char* szModel = (char*)STRING( pev->model );
//
// Pick regular grunt model.
//
if( !szModel || !*szModel )
{
szModel = "models/hgrunt.mdl";
pev->model = ALLOC_STRING( szModel );
}
// If this is a zombie soldier with a regular grunt model,
// switch to appropriate model.
else if( ( pev->spawnflags & SF_HGRUNT_ZSOLDIER ) && !FStrEq( szModel, "models/zgrunt.mdl" ) )
{
szModel = "models/zgrunt.mdl";
pev->model = ALLOC_STRING( szModel );
}
// Set new model.
SET_MODEL( ENT( pev ), (char*)STRING( pev->model ) )
pev->effects = 0;
pev->yaw_speed = 8;

124
dlls/hgrunt.h Normal file
View File

@ -0,0 +1,124 @@
/***
*
* 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.
*
****/
#ifndef HGRUNT_H
#define HGRUNT_H
//
// Special Grunt flags
//
#define GF_ZSOLDIER 1
class CHGrunt : public CSquadMonster
{
public:
void Spawn( void );
void Precache( void );
void SetYawSpeed ( void );
int Classify ( void );
int ISoundMask ( void );
void HandleAnimEvent( MonsterEvent_t *pEvent );
BOOL FCanCheckAttacks ( void );
BOOL CheckMeleeAttack1 ( float flDot, float flDist );
BOOL CheckRangeAttack1 ( float flDot, float flDist );
BOOL CheckRangeAttack2 ( float flDot, float flDist );
void CheckAmmo ( void );
void SetActivity ( Activity NewActivity );
void StartTask ( Task_t *pTask );
void RunTask ( Task_t *pTask );
void DeathSound( void );
void PainSound( void );
void IdleSound ( void );
Vector GetGunPosition( void );
void Shoot ( void );
void Shotgun ( void );
void PrescheduleThink ( void );
void GibMonster( void );
void SpeakSentence( void );
int Save( CSave &save );
int Restore( CRestore &restore );
CBaseEntity *Kick( void );
Schedule_t *GetSchedule( void );
Schedule_t *GetScheduleOfType ( int Type );
void TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType);
int TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType );
void Killed(entvars_t *pevAttacker, int iGib);
int IRelationship ( CBaseEntity *pTarget );
BOOL FOkToSpeak( void );
void JustSpoke( void );
CUSTOM_SCHEDULES;
static TYPEDESCRIPTION m_SaveData[];
// checking the feasibility of a grenade toss is kind of costly, so we do it every couple of seconds,
// not every server frame.
float m_flNextGrenadeCheck;
float m_flNextPainTime;
float m_flLastEnemySightTime;
Vector m_vecTossVelocity;
BOOL m_fThrowGrenade;
BOOL m_fStanding;
BOOL m_fFirstEncounter;// only put on the handsign show in the squad's first encounter.
int m_cClipSize;
int m_voicePitch;
int m_iBrassShell;
int m_iShotgunShell;
int m_iSentence;
static const char *pGruntSentences[];
BOOL IsZombieSoldier() const;
int m_iGruntFlags;
};
//=========================================================
// CHGruntRepel - when triggered, spawns a monster_human_grunt
// repelling down a line.
//=========================================================
class CHGruntRepel : public CBaseMonster
{
public:
void Spawn(void);
void Precache(void);
void EXPORT RepelUse(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value);
int m_iSpriteTexture; // Don't save, precache
};
//=========================================================
// DEAD HGRUNT PROP
//=========================================================
class CDeadHGrunt : public CBaseMonster
{
public:
void Spawn(void);
int Classify(void) { return CLASS_HUMAN_MILITARY; }
void KeyValue(KeyValueData *pkvd);
int m_iPose;// which sequence to display -- temporary, don't need to save
static char *m_szPoses[3];
};
#endif // HGRUNT_H

View File

@ -223,18 +223,18 @@ old colors
switch( m_iHornetType )
{
case HORNET_TYPE_RED:
WRITE_BYTE( 179 ); // r, g, b
WRITE_BYTE( 39 ); // r, g, b
WRITE_BYTE( 14 ); // r, g, b
WRITE_BYTE( 255 ); // r, g, b
WRITE_BYTE( 0 ); // r, g, b
WRITE_BYTE( 255 ); // r, g, b
break;
case HORNET_TYPE_ORANGE:
WRITE_BYTE( 255 ); // r, g, b
WRITE_BYTE( 128 ); // r, g, b
WRITE_BYTE( 0 ); // r, g, b
WRITE_BYTE( 255 ); // r, g, b
WRITE_BYTE( 255 ); // r, g, b
break;
}
WRITE_BYTE( 128 ); // brightness
WRITE_BYTE( 0 ); // brightness
MESSAGE_END();
}

View File

@ -32,7 +32,7 @@ extern CGraph WorldGraph;
// houndeye does 20 points of damage spread over a sphere 384 units in diameter, and each additional
// squad member increases the BASE damage by 110%, per the spec.
#define HOUNDEYE_MAX_SQUAD_SIZE 4
#define HOUNDEYE_MAX_ATTACK_RADIUS 384
#define HOUNDEYE_MAX_ATTACK_RADIUS 96
#define HOUNDEYE_SQUAD_BONUS (float)1.1
#define HOUNDEYE_EYE_FRAMES 4 // how many different switchable maps for the eye
@ -277,7 +277,23 @@ void CHoundeye::HandleAnimEvent( MonsterEvent_t *pEvent )
WarnSound();
break;
case HOUND_AE_STARTATTACK:
WarmUpSound();
{
// SOUND HERE!
CBaseEntity *pHurt = CheckTraceHullAttack( 80, gSkillData.houndeyeDmgBite, DMG_SLASH );
if( pHurt )
{
if( pHurt->pev->flags & ( FL_CLIENT | FL_MONSTER ) )
{
pHurt->pev->punchangle.x = 2;
}
pHurt->pev->velocity = pHurt->pev->velocity - gpGlobals->v_forward * 16;
pHurt->pev->velocity = pHurt->pev->velocity + gpGlobals->v_up * 8;
}
WarmUpSound();
}
break;
case HOUND_AE_HOPBACK:
{
@ -290,8 +306,6 @@ void CHoundeye::HandleAnimEvent( MonsterEvent_t *pEvent )
break;
}
case HOUND_AE_THUMP:
// emit the shockwaves
SonicAttack();
break;
case HOUND_AE_ANGERSOUND1:
EMIT_SOUND( ENT( pev ), CHAN_VOICE, "houndeye/he_pain3.wav", 1, ATTN_NORM );
@ -323,7 +337,7 @@ void CHoundeye::Spawn()
pev->solid = SOLID_SLIDEBOX;
pev->movetype = MOVETYPE_STEP;
m_bloodColor = BLOOD_COLOR_YELLOW;
m_bloodColor = BLOOD_COLOR_RED;
pev->effects = 0;
pev->health = gSkillData.houndeyeHealth;
pev->yaw_speed = 5;//!!! should we put this in the monster's changeanim function since turn rates may vary with state/anim?
@ -365,6 +379,7 @@ void CHoundeye::Precache()
PRECACHE_SOUND( "houndeye/he_pain5.wav" );
PRECACHE_SOUND( "houndeye/he_attack1.wav" );
PRECACHE_SOUND( "houndeye/he_attack2.wav" );
PRECACHE_SOUND( "houndeye/he_attack3.wav" );
PRECACHE_SOUND( "houndeye/he_blast1.wav" );
@ -398,7 +413,7 @@ void CHoundeye::IdleSound( void )
//=========================================================
void CHoundeye::WarmUpSound( void )
{
switch( RANDOM_LONG( 0, 1 ) )
switch( RANDOM_LONG( 0, 2 ) )
{
case 0:
EMIT_SOUND( ENT( pev ), CHAN_WEAPON, "houndeye/he_attack1.wav", 0.7, ATTN_NORM );
@ -406,6 +421,9 @@ void CHoundeye::WarmUpSound( void )
case 1:
EMIT_SOUND( ENT( pev ), CHAN_WEAPON, "houndeye/he_attack3.wav", 0.7, ATTN_NORM );
break;
case 2:
EMIT_SOUND( ENT( pev ), CHAN_WEAPON, "houndeye/he_attack2.wav", 0.7, ATTN_NORM );
break;
}
}

View File

@ -471,7 +471,7 @@ void CIchthyosaur::Spawn()
pev->solid = SOLID_BBOX;
pev->movetype = MOVETYPE_FLY;
m_bloodColor = BLOOD_COLOR_GREEN;
m_bloodColor = BLOOD_COLOR_RED;
pev->health = gSkillData.ichthyosaurHealth;
pev->view_ofs = Vector( 0, 0, 16 );
m_flFieldOfView = VIEW_FIELD_WIDE;

View File

@ -25,6 +25,7 @@
#include "effects.h"
#include "weapons.h"
#include "soundent.h"
#include "islave.h"
extern DLL_GLOBAL int g_iSkillLevel;
@ -39,61 +40,6 @@ extern DLL_GLOBAL int g_iSkillLevel;
#define ISLAVE_MAX_BEAMS 8
class CISlave : public CSquadMonster
{
public:
void Spawn( void );
void Precache( void );
void SetYawSpeed( void );
int ISoundMask( void );
int Classify( void );
int IRelationship( CBaseEntity *pTarget );
void HandleAnimEvent( MonsterEvent_t *pEvent );
BOOL CheckRangeAttack1( float flDot, float flDist );
BOOL CheckRangeAttack2( float flDot, float flDist );
void CallForHelp( char *szClassname, float flDist, EHANDLE hEnemy, Vector &vecLocation );
void TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType );
int TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType );
void DeathSound( void );
void PainSound( void );
void AlertSound( void );
void IdleSound( void );
void Killed( entvars_t *pevAttacker, int iGib );
void StartTask( Task_t *pTask );
Schedule_t *GetSchedule( void );
Schedule_t *GetScheduleOfType( int Type );
CUSTOM_SCHEDULES
int Save( CSave &save );
int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
void ClearBeams();
void ArmBeam( int side );
void WackBeam( int side, CBaseEntity *pEntity );
void ZapBeam( int side );
void BeamGlow( void );
int m_iBravery;
CBeam *m_pBeam[ISLAVE_MAX_BEAMS];
int m_iBeams;
float m_flNextAttack;
int m_voicePitch;
EHANDLE m_hDead;
static const char *pAttackHitSounds[];
static const char *pAttackMissSounds[];
static const char *pPainSounds[];
static const char *pDeathSounds[];
};
LINK_ENTITY_TO_CLASS( monster_alien_slave, CISlave )
LINK_ENTITY_TO_CLASS( monster_vortigaunt, CISlave )
@ -144,7 +90,7 @@ const char *CISlave::pDeathSounds[] =
//=========================================================
int CISlave::Classify( void )
{
return CLASS_ALIEN_MILITARY;
return CLASS_SKELETON;
}
int CISlave::IRelationship( CBaseEntity *pTarget )
@ -512,7 +458,7 @@ void CISlave::Spawn()
pev->solid = SOLID_SLIDEBOX;
pev->movetype = MOVETYPE_STEP;
m_bloodColor = BLOOD_COLOR_GREEN;
m_bloodColor = DONT_BLEED;
pev->effects = 0;
pev->health = gSkillData.slaveHealth;
pev->view_ofs = Vector( 0, 0, 64 );// position of the eyes relative to monster's origin.

76
dlls/islave.h Normal file
View File

@ -0,0 +1,76 @@
/***
*
* 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.
*
****/
#ifndef ISLAVE_H
#define ISLAVE_H
#define ISLAVE_MAX_BEAMS 8
class CISlave : public CSquadMonster
{
public:
void Spawn( void );
void Precache( void );
void SetYawSpeed( void );
int ISoundMask( void );
int Classify ( void );
int IRelationship( CBaseEntity *pTarget );
void HandleAnimEvent( MonsterEvent_t *pEvent );
BOOL CheckRangeAttack1 ( float flDot, float flDist );
BOOL CheckRangeAttack2 ( float flDot, float flDist );
void CallForHelp( char *szClassname, float flDist, EHANDLE hEnemy, Vector &vecLocation );
void TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType);
int TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType);
void DeathSound( void );
void PainSound( void );
void AlertSound( void );
void IdleSound( void );
void Killed( entvars_t *pevAttacker, int iGib );
BOOL ShouldGibMonster(int iGib) { return FALSE; }
void StartTask ( Task_t *pTask );
Schedule_t *GetSchedule( void );
Schedule_t *GetScheduleOfType ( int Type );
CUSTOM_SCHEDULES;
int Save( CSave &save );
int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
void ClearBeams( );
void ArmBeam( int side );
void WackBeam( int side, CBaseEntity *pEntity );
void ZapBeam( int side );
void BeamGlow( void );
int m_iBravery;
CBeam *m_pBeam[ISLAVE_MAX_BEAMS];
int m_iBeams;
float m_flNextAttack;
int m_voicePitch;
EHANDLE m_hDead;
static const char *pAttackHitSounds[];
static const char *pAttackMissSounds[];
static const char *pPainSounds[];
static const char *pDeathSounds[];
};
#endif // ISLAVE_H

View File

@ -184,14 +184,6 @@ class CItemSuit : public CItem
}
BOOL MyTouch( CBasePlayer *pPlayer )
{
if( pPlayer->pev->weapons & ( 1<<WEAPON_SUIT ) )
return FALSE;
if( pev->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;
}
@ -214,39 +206,6 @@ class CItemBattery : public CItem
}
BOOL MyTouch( CBasePlayer *pPlayer )
{
if( pPlayer->pev->deadflag != DEAD_NO )
{
return FALSE;
}
if( ( pPlayer->pev->armorvalue < MAX_NORMAL_BATTERY ) &&
( pPlayer->pev->weapons & ( 1 << WEAPON_SUIT ) ) )
{
int pct;
char szcharge[64];
pPlayer->pev->armorvalue += gSkillData.batteryCapacity;
pPlayer->pev->armorvalue = min( pPlayer->pev->armorvalue, MAX_NORMAL_BATTERY );
EMIT_SOUND( pPlayer->edict(), CHAN_ITEM, "items/gunpickup2.wav", 1, ATTN_NORM );
MESSAGE_BEGIN( MSG_ONE, gmsgItemPickup, NULL, pPlayer->pev );
WRITE_STRING( STRING( pev->classname ) );
MESSAGE_END();
// Suit reports new power level
// For some reason this wasn't working in release build -- round it.
pct = (int)( (float)( pPlayer->pev->armorvalue * 100.0 ) * ( 1.0 / MAX_NORMAL_BATTERY ) + 0.5 );
pct = ( pct / 5 );
if( pct > 0 )
pct--;
sprintf( szcharge,"!HEV_%1dP", pct );
//EMIT_SOUND_SUIT( ENT( pev ), szcharge );
pPlayer->SetSuitUpdate( szcharge, FALSE, SUIT_NEXT_IN_30SEC);
return TRUE;
}
return FALSE;
}
};

View File

@ -22,6 +22,7 @@
#include "cbase.h"
#include "monsters.h"
#include "saverestore.h"
#include "barney.h"
// Monstermaker spawnflags
#define SF_MONSTERMAKER_START_ON 1 // start active ( if has targetname )
@ -214,6 +215,18 @@ void CMonsterMaker::MakeMonster( void )
if( pev->spawnflags & SF_MONSTERMAKER_MONSTERCLIP )
SetBits( pevCreate->spawnflags, SF_MONSTER_HITMONSTERCLIP );
// Override monster blood color.
if( pev->spawnflags & SF_MONSTER_REDBLOOD )
SetBits( pevCreate->spawnflags, SF_MONSTER_REDBLOOD );
// Override monster relationship.
if( pev->spawnflags & SF_MONSTER_ZOMBIECOP )
SetBits( pevCreate->spawnflags, SF_MONSTER_ZOMBIECOP );
// Override monster framerate.
if( pev->spawnflags & SF_MONSTER_FASTZOMBIEMODE )
SetBits( pevCreate->spawnflags, SF_MONSTER_FASTZOMBIEMODE );
DispatchSpawn( ENT( pevCreate ) );
pevCreate->owner = edict();
@ -223,6 +236,10 @@ void CMonsterMaker::MakeMonster( void )
pevCreate->targetname = pev->netname;
}
CBarney* pBarney = (CBarney*)CBaseEntity::Instance( pevCreate );
if( pBarney )
pBarney->FixupBarneySkin( ( pev->spawnflags & SF_MONSTER_ZOMBIECOP ) ? TRUE : FALSE );
m_cLiveChildren++;// count this monster
m_cNumMonsters--;

View File

@ -2015,6 +2015,9 @@ void CBaseMonster::MonsterInit( void )
// set eye position
SetEyePosition();
if( pev->spawnflags & SF_MONSTER_REDBLOOD )
m_bloodColor = BLOOD_COLOR_RED;
SetThink( &CBaseMonster::MonsterInitThink );
pev->nextthink = gpGlobals->time + 0.1;
SetUse( &CBaseMonster::MonsterUse );
@ -2164,22 +2167,23 @@ int CBaseMonster::TaskIsRunning( void )
//=========================================================
int CBaseMonster::IRelationship( CBaseEntity *pTarget )
{
static int iEnemy[14][14] =
{ // NONE MACH PLYR HPASS HMIL AMIL APASS AMONST APREY APRED INSECT PLRALY PBWPN ABWPN
/*NONE*/ { R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO, R_NO, R_NO },
/*MACHINE*/ { R_NO ,R_NO ,R_DL ,R_DL ,R_NO ,R_DL ,R_DL ,R_DL ,R_DL ,R_DL ,R_NO ,R_DL, R_DL, R_DL },
/*PLAYER*/ { R_NO ,R_DL ,R_NO ,R_NO ,R_DL ,R_DL ,R_DL ,R_DL ,R_DL ,R_DL ,R_NO ,R_NO, R_DL, R_DL },
/*HUMANPASSIVE*/{ R_NO ,R_NO ,R_AL ,R_AL ,R_HT ,R_FR ,R_NO ,R_HT ,R_DL ,R_FR ,R_NO ,R_AL, R_NO, R_NO },
/*HUMANMILITAR*/{ R_NO ,R_NO ,R_HT ,R_DL ,R_NO ,R_HT ,R_DL ,R_DL ,R_DL ,R_DL ,R_NO ,R_HT, R_NO, R_NO },
/*ALIENMILITAR*/{ R_NO ,R_DL ,R_HT ,R_DL ,R_HT ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_DL, R_NO, R_NO },
/*ALIENPASSIVE*/{ R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO, R_NO, R_NO },
/*ALIENMONSTER*/{ R_NO ,R_DL ,R_DL ,R_DL ,R_DL ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_DL, R_NO, R_NO },
/*ALIENPREY */{ R_NO ,R_NO ,R_DL ,R_DL ,R_DL ,R_NO ,R_NO ,R_NO ,R_NO ,R_FR ,R_NO ,R_DL, R_NO, R_NO },
/*ALIENPREDATO*/{ R_NO ,R_NO ,R_DL ,R_DL ,R_DL ,R_NO ,R_NO ,R_NO ,R_HT ,R_DL ,R_NO ,R_DL, R_NO, R_NO },
/*INSECT*/ { R_FR ,R_FR ,R_FR ,R_FR ,R_FR ,R_NO ,R_FR ,R_FR ,R_FR ,R_FR ,R_NO ,R_FR, R_NO, R_NO },
/*PLAYERALLY*/ { R_NO ,R_DL ,R_AL ,R_AL ,R_DL ,R_DL ,R_DL ,R_DL ,R_DL ,R_DL ,R_NO ,R_NO, R_NO, R_NO },
/*PBIOWEAPON*/ { R_NO ,R_NO ,R_DL ,R_DL ,R_DL ,R_DL ,R_DL ,R_DL ,R_DL ,R_DL ,R_NO ,R_DL, R_NO, R_DL },
/*ABIOWEAPON*/ { R_NO ,R_NO ,R_DL ,R_DL ,R_DL ,R_AL ,R_NO ,R_DL ,R_DL ,R_NO ,R_NO ,R_DL, R_DL, R_NO }
static int iEnemy[15][15] =
{ // NONE MACH PLYR HPASS HMIL AMIL APASS AMONST APREY APRED INSECT PLRALY PBWPN ABWPN SKELETON
/*NONE*/ { R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO, R_NO, R_NO, R_NO },
/*MACHINE*/ { R_NO ,R_NO ,R_DL ,R_DL ,R_NO ,R_DL ,R_DL ,R_DL ,R_DL ,R_DL ,R_NO ,R_DL, R_DL, R_DL, R_DL },
/*PLAYER*/ { R_NO ,R_DL ,R_NO ,R_NO ,R_DL ,R_DL ,R_DL ,R_DL ,R_DL ,R_DL ,R_NO ,R_NO, R_DL, R_DL, R_DL },
/*HUMANPASSIVE*/{ R_NO ,R_NO ,R_AL ,R_AL ,R_HT ,R_FR ,R_NO ,R_HT ,R_DL ,R_FR ,R_NO ,R_AL, R_NO, R_NO, R_HT },
/*HUMANMILITAR*/{ R_NO ,R_NO ,R_HT ,R_DL ,R_NO ,R_HT ,R_DL ,R_DL ,R_DL ,R_DL ,R_NO ,R_HT, R_NO, R_NO, R_DL },
/*ALIENMILITAR*/{ R_NO ,R_DL ,R_HT ,R_DL ,R_HT ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_DL, R_NO, R_NO, R_NO },
/*ALIENPASSIVE*/{ R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO, R_NO, R_NO, R_NO },
/*ALIENMONSTER*/{ R_NO ,R_DL ,R_DL ,R_DL ,R_DL ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_DL, R_NO, R_NO, R_NO },
/*ALIENPREY */{ R_NO ,R_NO ,R_DL ,R_DL ,R_DL ,R_NO ,R_NO ,R_NO ,R_NO ,R_FR ,R_NO ,R_DL, R_NO, R_NO, R_NO },
/*ALIENPREDATO*/{ R_NO ,R_NO ,R_DL ,R_DL ,R_DL ,R_NO ,R_NO ,R_NO ,R_HT ,R_DL ,R_NO ,R_DL, R_NO, R_NO, R_NO },
/*INSECT*/ { R_FR ,R_FR ,R_FR ,R_FR ,R_FR ,R_NO ,R_FR ,R_FR ,R_FR ,R_FR ,R_NO ,R_FR, R_NO, R_NO, R_FR },
/*PLAYERALLY*/ { R_NO ,R_DL ,R_AL ,R_AL ,R_DL ,R_DL ,R_DL ,R_DL ,R_DL ,R_DL ,R_NO ,R_NO, R_NO, R_NO, R_DL },
/*PBIOWEAPON*/ { R_NO ,R_NO ,R_DL ,R_DL ,R_DL ,R_DL ,R_DL ,R_DL ,R_DL ,R_DL ,R_NO ,R_DL, R_NO, R_DL, R_DL },
/*ABIOWEAPON*/ { R_NO ,R_NO ,R_DL ,R_DL ,R_DL ,R_AL ,R_NO ,R_DL ,R_DL ,R_NO ,R_NO ,R_DL, R_DL, R_NO, R_DL },
/*SKELETON*/ { R_NO ,R_DL ,R_DL ,R_DL ,R_DL ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_DL, R_NO, R_NO, R_NO }
};
return iEnemy[Classify()][pTarget->Classify()];

View File

@ -45,11 +45,12 @@
#define SF_MONSTER_HITMONSTERCLIP 4
// 8
#define SF_MONSTER_PRISONER 16 // monster won't attack anyone, no one will attacke him.
// 32
// 64
#define SF_MONSTER_REDBLOOD 32
#define SF_MONSTER_ZOMBIECOP 64
#define SF_MONSTER_WAIT_FOR_SCRIPT 128 //spawnflag that makes monsters wait to check for attacking until the script is done or they've been attacked
#define SF_MONSTER_PREDISASTER 256 //this is a predisaster scientist or barney. Influences how they speak.
#define SF_MONSTER_FADECORPSE 512 // Fade out corpse after death
#define SF_MONSTER_FASTZOMBIEMODE 1024
#define SF_MONSTER_FALL_TO_GROUND 0x80000000
// specialty spawnflags

View File

@ -1063,7 +1063,17 @@ void CFuncTrackTrain::StopSound( void )
/*
STOP_SOUND( ENT( pev ), CHAN_STATIC, (char*)STRING( pev->noise ) );
*/
EMIT_SOUND_DYN( ENT( pev ), CHAN_ITEM, "plats/ttrain_brake1.wav", m_flVolume, ATTN_NORM, 0, 100 );
char *brake = "plats/ttrain_brake1.wav";
if( UseCustomSounds() )
{
if( IsCar() )
brake = "plats/ttrain_brake2.wav";
else if( IsTrain() )
brake = "plats/ttrain_brake6.wav";
}
EMIT_SOUND_DYN( ENT( pev ), CHAN_ITEM, brake, m_flVolume, ATTN_NORM, 0, 100 );
}
m_soundPlaying = 0;
@ -1084,7 +1094,17 @@ void CFuncTrackTrain::UpdateSound( void )
if( !m_soundPlaying )
{
// play startup sound for train
EMIT_SOUND_DYN( ENT( pev ), CHAN_ITEM, "plats/ttrain_start1.wav", m_flVolume, ATTN_NORM, 0, 100 );
char *start = "plats/ttrain_start1.wav";
if( UseCustomSounds() )
{
if( IsCar() )
start = "plats/ttrain_start2.wav";
else if( IsTrain() )
start = "plats/ttrain_start6.wav";
}
EMIT_SOUND_DYN( ENT( pev ), CHAN_ITEM, start, m_flVolume, ATTN_NORM, 0, 100 );
EMIT_SOUND_DYN( ENT( pev ), CHAN_STATIC, (char*)STRING( pev->noise ), m_flVolume, ATTN_NORM, 0, (int)flpitch );
m_soundPlaying = 1;
}
@ -1509,9 +1529,30 @@ void CFuncTrackTrain::Precache( void )
PRECACHE_SOUND( "plats/ttrain_brake1.wav" );
PRECACHE_SOUND( "plats/ttrain_start1.wav" );
PRECACHE_SOUND( "plats/ttrain_brake2.wav" );
PRECACHE_SOUND( "plats/ttrain_start2.wav" );
PRECACHE_SOUND( "plats/ttrain_brake6.wav" );
PRECACHE_SOUND( "plats/ttrain_start6.wav" );
m_usAdjustPitch = PRECACHE_EVENT( 1, "events/train.sc" );
}
BOOL CFuncTrackTrain::UseCustomSounds( void ) const
{
return ( pev->spawnflags & SF_TRACKTRAIN_TH_SOUNDS );
}
BOOL CFuncTrackTrain::IsCar( void ) const
{
return FStrEq( STRING( pev->noise ), "plats/ttrain2.wav" );
}
BOOL CFuncTrackTrain::IsTrain(void) const
{
return FStrEq( STRING( pev->noise ), "plats/ttrain6.wav" );
}
// This class defines the volume of space that the player must stand in to control the train
class CFuncTrainControls : public CBaseEntity
{

View File

@ -184,6 +184,8 @@ int gmsgTeamNames = 0;
int gmsgStatusText = 0;
int gmsgStatusValue = 0;
int gmsgZoom = 0;
void LinkUserMessages( void )
{
// Already taken care of?
@ -228,6 +230,8 @@ void LinkUserMessages( void )
gmsgStatusText = REG_USER_MSG( "StatusText", -1 );
gmsgStatusValue = REG_USER_MSG( "StatusValue", 3 );
gmsgZoom = REG_USER_MSG( "Zoom", 2 );
}
LINK_ENTITY_TO_CLASS( player, CBasePlayer )
@ -1092,6 +1096,9 @@ void CBasePlayer::TabulateAmmo()
ammo_rockets = AmmoInventory( GetAmmoIndex( "rockets" ) );
ammo_uranium = AmmoInventory( GetAmmoIndex( "uranium" ) );
ammo_hornets = AmmoInventory( GetAmmoIndex( "Hornets" ) );
ammo_ap9 = AmmoInventory( GetAmmoIndex( "ap9" ) );
ammo_taurus = AmmoInventory( GetAmmoIndex( "taurus" ) );
ammo_sniper = AmmoInventory( GetAmmoIndex( "sniper" ) );
}
/*
@ -1411,7 +1418,19 @@ void CBasePlayer::PlayerUse( void )
m_afPhysicsFlags |= PFLAG_ONTRAIN;
m_iTrain = TrainSpeed( pTrain->pev->speed, pTrain->pev->impulse );
m_iTrain |= TRAIN_NEW;
EMIT_SOUND( ENT( pev ), CHAN_ITEM, "plats/train_use1.wav", 0.8, ATTN_NORM );
char* usesound = "plats/train_use1.wav";
CFuncTrackTrain* pTrackTrain = (CFuncTrackTrain*)pTrain;
if pTrackTrain && pTrackTrain->UseCustomSounds() )
{
if( pTrackTrain->IsCar() )
usesound = "plats/train_use2.wav";
else if( pTrackTrain->IsTrain() )
usesound = "plats/train_use6.wav";
}
EMIT_SOUND( ENT( pev ), CHAN_ITEM, usesound, 0.8, ATTN_NORM );
return;
}
}
@ -2181,89 +2200,6 @@ void CBasePlayer::CheckSuitUpdate()
void CBasePlayer::SetSuitUpdate( char *name, int fgroup, int iNoRepeatTime )
{
int i;
int isentence;
int iempty = -1;
// Ignore suit updates if no suit
if( !( pev->weapons & ( 1 << WEAPON_SUIT ) ) )
return;
if( g_pGameRules->IsMultiplayer() )
{
// 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;
}
}
/*
@ -3347,7 +3283,6 @@ void CBasePlayer::CheatImpulseCommands( int iImpulse )
case 101:
gEvilImpulse101 = TRUE;
GiveNamedItem( "item_suit" );
GiveNamedItem( "item_battery" );
GiveNamedItem( "weapon_crowbar" );
GiveNamedItem( "weapon_9mmhandgun" );
GiveNamedItem( "ammo_9mmclip" );
@ -3370,8 +3305,19 @@ void CBasePlayer::CheatImpulseCommands( int iImpulse )
GiveNamedItem( "ammo_rpgclip" );
GiveNamedItem( "weapon_satchel" );
GiveNamedItem( "weapon_snark" );
GiveNamedItem( "weapon_hornetgun" );
#endif
GiveNamedItem( "weapon_th_ap9" );
GiveNamedItem( "ammo_th_ap9" );
GiveNamedItem( "weapon_th_chaingun" );
GiveNamedItem( "weapon_th_medkit" );
GiveNamedItem( "weapon_th_shovel" );
GiveNamedItem( "weapon_einar1" );
GiveNamedItem( "weapon_th_sniper" );
GiveNamedItem( "ammo_th_sniper" );
GiveNamedItem( "weapon_th_spanner" );
GiveNamedItem( "weapon_th_taurus" );
GiveNamedItem( "ammo_th_taurus" );
gEvilImpulse101 = FALSE;
break;
case 102:

View File

@ -75,6 +75,8 @@ void CPython::Spawn()
m_iDefaultAmmo = PYTHON_DEFAULT_GIVE;
m_flSoundDelay = 0;
FallInit();// get ready to fall down.
}
@ -227,9 +229,11 @@ void CPython::Reload( void )
#else
bUseScope = g_pGameRules->IsMultiplayer();
#endif
if( DefaultReload( 6, PYTHON_RELOAD, 2.0, bUseScope ) )
int iResult = DefaultReload( PYTHON_MAX_CLIP, PYTHON_RELOAD, 2.0, bUseScope );
if( iResult )
{
m_flSoundDelay = 1.5;
m_flSoundDelay = gpGlobals->time + 1.5;
}
}
@ -240,7 +244,7 @@ void CPython::WeaponIdle( void )
m_pPlayer->GetAutoaimVector( AUTOAIM_10DEGREES );
// ALERT( at_console, "%.2f\n", gpGlobals->time - m_flSoundDelay );
if( m_flSoundDelay != 0 && m_flSoundDelay <= UTIL_WeaponTimeBase() )
if( m_flSoundDelay != 0 && ( m_flSoundDelay <= UTIL_WeaponTimeBase() || m_flSoundDelay <= gpGlobals->time ) )
{
EMIT_SOUND( ENT( m_pPlayer->pev ), CHAN_WEAPON, "weapons/357_reload1.wav", RANDOM_FLOAT( 0.8, 0.9 ), ATTN_NORM );
m_flSoundDelay = 0;

View File

@ -26,6 +26,7 @@
#include "scripted.h"
#include "animation.h"
#include "soundent.h"
#include "scientist.h"
#define NUM_SCIENTIST_HEADS 4 // four heads available for scientist model
@ -37,6 +38,16 @@ enum
HEAD_SLICK = 3
};
#define NUM_SCIENTIST_SKINS 4
enum
{
SKIN_GLASSES = 0,
SKIN_DOCTOR = 1,
SKIN_PREIST = 2,
SKIN_PATIENT = 3
};
enum
{
SCHED_HIDE = LAST_TALKMONSTER_SCHEDULE + 1,
@ -68,56 +79,6 @@ enum
//=======================================================
// Scientist
//=======================================================
class CScientist : public CTalkMonster
{
public:
void Spawn( void );
void Precache( void );
void SetYawSpeed( void );
int Classify( void );
void HandleAnimEvent( MonsterEvent_t *pEvent );
void RunTask( Task_t *pTask );
void StartTask( Task_t *pTask );
int ObjectCaps( void ) { return CTalkMonster::ObjectCaps() | FCAP_IMPULSE_USE; }
int TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType );
virtual int FriendNumber( int arrayNumber );
void SetActivity( Activity newActivity );
Activity GetStoppedActivity( void );
int ISoundMask( void );
void DeclineFollowing( void );
float CoverRadius( void ) { return 1200; } // Need more room for cover because scientists want to get far away!
BOOL DisregardEnemy( CBaseEntity *pEnemy ) { return !pEnemy->IsAlive() || ( gpGlobals->time - m_fearTime ) > 15; }
BOOL CanHeal( void );
void Heal( void );
void Scream( void );
// Override these to set behavior
Schedule_t *GetScheduleOfType( int Type );
Schedule_t *GetSchedule( void );
MONSTERSTATE GetIdealState( void );
void DeathSound( void );
void PainSound( void );
void TalkInit( void );
void Killed( entvars_t *pevAttacker, int iGib );
virtual int Save( CSave &save );
virtual int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
CUSTOM_SCHEDULES
private:
float m_painTime;
float m_healTime;
float m_fearTime;
};
LINK_ENTITY_TO_CLASS( monster_scientist, CScientist )
TYPEDESCRIPTION CScientist::m_SaveData[] =
@ -651,19 +612,12 @@ void CScientist::Spawn( void )
m_afCapability = bits_CAP_HEAR | bits_CAP_TURN_HEAD | bits_CAP_OPEN_DOORS | bits_CAP_AUTO_DOORS | bits_CAP_USE;
// White hands
pev->skin = 0;
if( pev->body == -1 )
{
// -1 chooses a random head
pev->body = RANDOM_LONG( 0, NUM_SCIENTIST_HEADS - 1 );// pick a head, any head
}
// Luther is black, make his hands black
if( pev->body == HEAD_LUTHER )
pev->skin = 1;
MonsterInit();
SetUse( &CTalkMonster::FollowerUse );
}
@ -1050,10 +1004,7 @@ MONSTERSTATE CScientist::GetIdealState( void )
BOOL CScientist::CanHeal( void )
{
if( ( m_healTime > gpGlobals->time ) || ( m_hTargetEnt == NULL ) || ( m_hTargetEnt->pev->health > ( m_hTargetEnt->pev->max_health * 0.5 ) ) )
return FALSE;
return TRUE;
return FALSE;
}
void CScientist::Heal( void )
@ -1082,20 +1033,6 @@ int CScientist::FriendNumber( int arrayNumber )
//=========================================================
// Dead Scientist PROP
//=========================================================
class CDeadScientist : public CBaseMonster
{
public:
void Spawn( void );
int Classify( void )
{
return CLASS_HUMAN_PASSIVE;
}
void KeyValue( KeyValueData *pkvd );
int m_iPose;// which sequence to display
static char *m_szPoses[7];
};
char *CDeadScientist::m_szPoses[] =
{
"lying_on_back",
@ -1141,12 +1078,6 @@ void CDeadScientist::Spawn()
pev->body = RANDOM_LONG( 0, NUM_SCIENTIST_HEADS - 1 );// pick a head, any head
}
// Luther is black, make his hands black
if( pev->body == HEAD_LUTHER )
pev->skin = 1;
else
pev->skin = 0;
pev->sequence = LookupSequence( m_szPoses[m_iPose] );
if( pev->sequence == -1 )
{
@ -1160,27 +1091,6 @@ void CDeadScientist::Spawn()
//=========================================================
// Sitting Scientist PROP
//=========================================================
class CSittingScientist : public CScientist // kdb: changed from public CBaseMonster so he can speak
{
public:
void Spawn( void );
void Precache( void );
void EXPORT SittingThink( void );
int Classify( void );
virtual int Save( CSave &save );
virtual int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
virtual void SetAnswerQuestion( CTalkMonster *pSpeaker );
int FriendNumber( int arrayNumber );
int FIdleSpeak( void );
int m_baseSequence;
int m_headTurn;
float m_flResponseDelay;
};
LINK_ENTITY_TO_CLASS( monster_sitting_scientist, CSittingScientist )
TYPEDESCRIPTION CSittingScientist::m_SaveData[] =
@ -1232,10 +1142,6 @@ void CSittingScientist::Spawn()
pev->body = RANDOM_LONG( 0, NUM_SCIENTIST_HEADS - 1 );// pick a head, any head
}
// Luther is black, make his hands black
if( pev->body == HEAD_LUTHER )
pev->skin = 1;
m_baseSequence = LookupSequence( "sitlookleft" );
pev->sequence = m_baseSequence + RANDOM_LONG( 0, 4 );
ResetSequenceInfo();

110
dlls/scientist.h Normal file
View File

@ -0,0 +1,110 @@
/***
*
* 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.
*
****/
#ifndef SCIENTIST_H
#define SCIENTIST_H
//=======================================================
// Scientist
//=======================================================
class CScientist : public CTalkMonster
{
public:
void Spawn( void );
void Precache( void );
void SetYawSpeed( void );
int Classify ( void );
void HandleAnimEvent( MonsterEvent_t *pEvent );
void RunTask( Task_t *pTask );
void StartTask( Task_t *pTask );
int ObjectCaps( void ) { return CTalkMonster :: ObjectCaps() | FCAP_IMPULSE_USE; }
int TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType);
virtual int FriendNumber( int arrayNumber );
void SetActivity ( Activity newActivity );
Activity GetStoppedActivity( void );
int ISoundMask( void );
void DeclineFollowing( void );
float CoverRadius( void ) { return 1200; } // Need more room for cover because scientists want to get far away!
BOOL DisregardEnemy( CBaseEntity *pEnemy ) { return !pEnemy->IsAlive() || (gpGlobals->time - m_fearTime) > 15; }
BOOL CanHeal( void );
void Heal( void );
void Scream( void );
// Override these to set behavior
Schedule_t *GetScheduleOfType ( int Type );
Schedule_t *GetSchedule ( void );
MONSTERSTATE GetIdealState ( void );
void DeathSound( void );
void PainSound( void );
void TalkInit( void );
void Killed( entvars_t *pevAttacker, int iGib );
virtual int Save( CSave &save );
virtual int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
CUSTOM_SCHEDULES;
private:
float m_painTime;
float m_healTime;
float m_fearTime;
};
//=========================================================
// Dead Scientist PROP
//=========================================================
class CDeadScientist : public CBaseMonster
{
public:
void Spawn(void);
int Classify(void) { return CLASS_HUMAN_PASSIVE; }
void KeyValue(KeyValueData *pkvd);
int m_iPose;// which sequence to display
static char *m_szPoses[7];
};
//=========================================================
// Sitting Scientist PROP
//=========================================================
class CSittingScientist : public CScientist // kdb: changed from public CBaseMonster so he can speak
{
public:
void Spawn(void);
void Precache(void);
void EXPORT SittingThink(void);
int Classify(void);
virtual int Save(CSave &save);
virtual int Restore(CRestore &restore);
static TYPEDESCRIPTION m_SaveData[];
virtual void SetAnswerQuestion(CTalkMonster *pSpeaker);
int FriendNumber(int arrayNumber);
int FIdleSpeak(void);
int m_baseSequence;
int m_headTurn;
float m_flResponseDelay;
};
#endif // SCIENTIST_H

View File

@ -133,6 +133,32 @@ struct skilldata_t
float plrStomach;
float plrLeg;
float plrArm;
// Monster Health & Damage
float babykellyhealth;
float bossHealth;
float cyberfranklinHealth;
float houndeyeDmgBite;
float megasquidHealth;
float zombiebullHealth;
float zombiebullDmgBite;
float zombiebullDmgWhip;
// health/suit charge
float medkitHeal;
// Player Weapons
float plrDmgShovel;
float plrDmgSpanner;
float plrDmgAP9;
float plrDmgTaurus;
float plrDmgSniper;
float plrDmgFlame;
};
extern DLL_GLOBAL skilldata_t gSkillData;

View File

@ -19,6 +19,8 @@
#define SF_SQUADMONSTER_LEADER 32
#define SF_SQUADMONSTER_NOZAP 256
#define bits_NO_SLOT 0
// HUMAN GRUNT SLOTS

View File

@ -50,7 +50,7 @@ class CSqueakGrenade : public CGrenade
int Classify( void );
void EXPORT SuperBounceTouch( CBaseEntity *pOther );
void EXPORT HuntThink( void );
int BloodColor( void ) { return BLOOD_COLOR_YELLOW; }
int BloodColor( void ) { return BLOOD_COLOR_RED; }
void Killed( entvars_t *pevAttacker, int iGib );
void GibMonster( void );

View File

@ -23,6 +23,7 @@
#include "scripted.h"
#include "soundent.h"
#include "animation.h"
#include "barney.h"
//=========================================================
// Talking monster base class
@ -644,6 +645,10 @@ CBaseEntity *CTalkMonster::EnumFriends( CBaseEntity *pPrevious, int listNumber,
void CTalkMonster::AlertFriends( void )
{
// Do not alert friends if this is a zombie cop.
if( FClassnameIs( pev, "monster_barney" ) && ( (CBarney*)this )->IsZombieCop() )
return;
CBaseEntity *pFriend = NULL;
int i;
@ -653,7 +658,7 @@ void CTalkMonster::AlertFriends( void )
while( ( pFriend = EnumFriends( pFriend, i, TRUE ) ) )
{
CBaseMonster *pMonster = pFriend->MyMonsterPointer();
if( pMonster->IsAlive() )
if( pMonster->IsAlive() && pMonster->Classify() == Classify() )
{
// don't provoke a friend that's playing a death animation. They're a goner
pMonster->m_afMemory |= bits_MEMORY_PROVOKED;
@ -1147,9 +1152,13 @@ int CTalkMonster::TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, f
// if player damaged this entity, have other friends talk about it
if( pevAttacker && m_MonsterState != MONSTERSTATE_PRONE && FBitSet( pevAttacker->flags, FL_CLIENT ) )
{
// Do not tell friends to stop shooting if this is a zombie cop.
if( FClassnameIs( pev, "monster_barney" ) && ( (CBarney*)this )->IsZombieCop() )
return CBaseMonster::TakeDamage( pevInflictor, pevAttacker, flDamage, bitsDamageType );
CBaseEntity *pFriend = FindNearestFriend( FALSE );
if( pFriend && pFriend->IsAlive() )
if( pFriend && pFriend->IsAlive() && pFriend->Classify() == Classify() )
{
// only if not dead or dying!
CTalkMonster *pTalkMonster = (CTalkMonster *)pFriend;
@ -1190,8 +1199,12 @@ Schedule_t *CTalkMonster::GetScheduleOfType( int Type )
{
//SENTENCEG_PlayRndSz( ENT( pev ), m_szGrp[TLK_WOUND], 1.0, ATTN_IDLE, 0, GetVoicePitch() );
//CTalkMonster::g_talkWaitTime = gpGlobals->time + RANDOM_FLOAT( 2.8, 3.2 );
PlaySentence( m_szGrp[TLK_WOUND], RANDOM_FLOAT( 2.8, 3.2 ), VOL_NORM, ATTN_IDLE );
SetBits( m_bitsSaid, bit_saidWoundLight );
if( FWoundSpeak() )
{
SetBits( m_bitsSaid, bit_saidWoundLight );
}
return slIdleStand;
}
// sustained heavy wounds?
@ -1199,8 +1212,12 @@ Schedule_t *CTalkMonster::GetScheduleOfType( int Type )
{
//SENTENCEG_PlayRndSz( ENT( pev ), m_szGrp[TLK_MORTAL], 1.0, ATTN_IDLE, 0, GetVoicePitch() );
//CTalkMonster::g_talkWaitTime = gpGlobals->time + RANDOM_FLOAT( 2.8, 3.2 );
PlaySentence( m_szGrp[TLK_MORTAL], RANDOM_FLOAT( 2.8, 3.2 ), VOL_NORM, ATTN_IDLE );
SetBits( m_bitsSaid, bit_saidWoundHeavy );
if( FMortalSpeak() )
{
SetBits( m_bitsSaid, bit_saidWoundHeavy );
}
return slIdleStand;
}
@ -1407,3 +1424,24 @@ void CTalkMonster::Precache( void )
if( m_iszUnUse )
m_szGrp[TLK_UNUSE] = STRING( m_iszUnUse );
}
int CTalkMonster::FWoundSpeak( void )
{
if( !FOkToSpeak() )
return FALSE;
PlaySentence( m_szGrp[TLK_WOUND], RANDOM_FLOAT( 2.8, 3.2 ), VOL_NORM, ATTN_IDLE );
return TRUE;
}
int CTalkMonster::FMortalSpeak( void )
{
if( !FOkToSpeak() )
return FALSE;
PlaySentence( m_szGrp[TLK_MORTAL], RANDOM_FLOAT( 2.8, 3.2 ), VOL_NORM, ATTN_IDLE );
return TRUE;
}

View File

@ -123,12 +123,14 @@ public:
// Conversations / communication
int GetVoicePitch( void );
void IdleRespond( void );
virtual void IdleRespond( void );
int FIdleSpeak( void );
int FIdleStare( void );
int FIdleHello( void );
void IdleHeadTurn( Vector &vecFriend );
int FOkToSpeak( void );
virtual int FOkToSpeak( void );
int FWoundSpeak( void );
int FMortalSpeak( void );
void TrySmellTalk( void );
CBaseEntity *EnumFriends( CBaseEntity *pentPrevious, int listNumber, BOOL bTrace );
void AlertFriends( void );

1267
dlls/time Normal file

File diff suppressed because it is too large Load Diff

View File

@ -20,6 +20,7 @@
#define SF_TRACKTRAIN_NOCONTROL 0x0002
#define SF_TRACKTRAIN_FORWARDONLY 0x0004
#define SF_TRACKTRAIN_PASSABLE 0x0008
#define SF_TRACKTRAIN_TH_SOUNDS 0x0020
// Spawnflag for CPathTrack
#define SF_PATH_DISABLED 0x00000001
@ -118,6 +119,10 @@ public:
float m_flBank;
float m_oldSpeed;
BOOL UseCustomSounds( void ) const;
BOOL IsCar( void ) const;
BOOL IsTrain( void ) const;
private:
unsigned short m_usAdjustPitch;
};

View File

@ -46,6 +46,8 @@ DLL_GLOBAL short g_sModelIndexBubbles;// holds the index for the bubbles model
DLL_GLOBAL short g_sModelIndexBloodDrop;// holds the sprite index for the initial blood
DLL_GLOBAL short g_sModelIndexBloodSpray;// holds the sprite index for splattered blood
DLL_GLOBAL short g_sModelIndexFThrow; // holds the index for the flamethrower
ItemInfo CBasePlayerItem::ItemInfoArray[MAX_WEAPONS];
AmmoInfo CBasePlayerItem::AmmoInfoArray[MAX_AMMO_SLOTS];
@ -169,6 +171,10 @@ void DecalGunshot( TraceResult *pTrace, int iBulletType )
case BULLET_MONSTER_MP5:
case BULLET_PLAYER_BUCKSHOT:
case BULLET_PLAYER_357:
case BULLET_PLAYER_AP9:
case BULLET_PLAYER_CHAINGUN:
case BULLET_PLAYER_SNIPER:
case BULLET_PLAYER_TAURUS:
default:
// smoke and decal
UTIL_GunshotDecalTrace( pTrace, DamageDecal( pEntity, DMG_BULLET ) );
@ -347,10 +353,33 @@ void W_Precache( void )
#if !defined( OEM_BUILD ) && !defined( HLDEMO_BUILD )
// squeak grenade
UTIL_PrecacheOtherWeapon( "weapon_snark" );
#endif
// ap9
UTIL_PrecacheOtherWeapon( "weapon_th_ap9" );
UTIL_PrecacheOther( "ammo_th_ap9" );
// hornetgun
UTIL_PrecacheOtherWeapon( "weapon_hornetgun" );
// chaingun
UTIL_PrecacheOtherWeapon( "weapon_th_chaingun" );
// medkit
UTIL_PrecacheOtherWeapon( "weapon_th_medkit" );
// shovel
UTIL_PrecacheOtherWeapon( "weapon_th_shovel" );
// sniper
UTIL_PrecacheOtherWeapon( "weapon_einar1" );
UTIL_PrecacheOtherWeapon( "weapon_th_sniper" );
UTIL_PrecacheOther( "ammo_th_sniper" );
// spanner
UTIL_PrecacheOtherWeapon( "weapon_th_spanner" );
// taurus
UTIL_PrecacheOtherWeapon( "weapon_th_taurus" );
UTIL_PrecacheOther( "ammo_th_taurus" );
#if !defined( OEM_BUILD ) && !defined( HLDEMO_BUILD )
if( g_pGameRules->IsDeathmatch() )
{
UTIL_PrecacheOther( "weaponbox" );// container for dropped deathmatch weapons
@ -366,6 +395,8 @@ void W_Precache( void )
g_sModelIndexLaser = PRECACHE_MODEL( (char *)g_pModelNameLaser );
g_sModelIndexLaserDot = PRECACHE_MODEL( "sprites/laserdot.spr" );
g_sModelIndexFThrow = PRECACHE_MODEL( "sprites/fthrow.spr" );
// used by explosions
PRECACHE_MODEL( "models/grenade.mdl" );
PRECACHE_MODEL( "sprites/explode1.spr" );
@ -382,6 +413,9 @@ void W_Precache( void )
PRECACHE_SOUND( "weapons/bullet_hit2.wav" ); // hit by bullet
PRECACHE_SOUND( "items/weapondrop1.wav" );// weapon falls to the ground
// Precached here since hand grenade no longer precaches it.
PRECACHE_MODEL( "models/w_grenade.mdl" );
}
TYPEDESCRIPTION CBasePlayerItem::m_SaveData[] =
@ -612,6 +646,11 @@ void CBasePlayerWeapon::ItemPostFrame( void )
m_fInReload = FALSE;
}
if( !( m_pPlayer->pev->button & IN_ATTACK ) )
{
m_flLastFireTime = 0.0f;
}
if( ( m_pPlayer->pev->button & IN_ATTACK2 ) && CanAttack( m_flNextSecondaryAttack, gpGlobals->time, UseDecrement() ) )
{
if( pszAmmo2() && !m_pPlayer->m_rgAmmo[SecondaryAmmoIndex()] )
@ -943,6 +982,7 @@ BOOL CBasePlayerWeapon::DefaultDeploy( char *szViewModel, char *szWeaponModel, i
m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.5;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 1.0;
m_flLastFireTime = 0.0f;
return TRUE;
}
@ -1130,6 +1170,37 @@ void CBasePlayerWeapon::RetireWeapon( void )
g_pGameRules->GetNextBestWeapon( m_pPlayer, this );
}
/=========================================================================
// GetNextAttackDelay - An accurate way of calcualting the next attack time.
//=========================================================================
float CBasePlayerWeapon::GetNextAttackDelay( float delay )
{
if( m_flLastFireTime == 0 || m_flNextPrimaryAttack == -1 )
{
// At this point, we are assuming that the client has stopped firing
// and we are going to reset our book keeping variables.
m_flLastFireTime = gpGlobals->time;
m_flPrevPrimaryAttack = delay;
}
// calculate the time between this shot and the previous
float flTimeBetweenFires = gpGlobals->time - m_flLastFireTime;
float flCreep = 0.0f;
if( flTimeBetweenFires > 0 )
flCreep = flTimeBetweenFires - m_flPrevPrimaryAttack; // postive or negative
// save the last fire time
m_flLastFireTime = gpGlobals->time;
float flNextAttack = UTIL_WeaponTimeBase() + delay - flCreep;
// we need to remember what the m_flNextPrimaryAttack time is set to for each shot,
// store it as m_flPrevPrimaryAttack.
m_flPrevPrimaryAttack = flNextAttack - UTIL_WeaponTimeBase();
//char szMsg[256];
//_snprintf( szMsg, sizeof(szMsg), "next attack time: %0.4f\n", gpGlobals->time + flNextAttack );
//OutputDebugString( szMsg );
return flNextAttack;
}
//*********************************************************
// weaponbox code:
//*********************************************************
@ -1527,3 +1598,40 @@ TYPEDESCRIPTION CSatchel::m_SaveData[] =
};
IMPLEMENT_SAVERESTORE( CSatchel, CBasePlayerWeapon )
TYPEDESCRIPTION CGlock::m_SaveData[] =
{
DEFINE_FIELD( CGlock, m_fSilencerOn, FIELD_BOOLEAN ),
};
IMPLEMENT_SAVERESTORE( CGlock, CBasePlayerWeapon );
TYPEDESCRIPTION CPython::m_SaveData[] =
{
DEFINE_FIELD( CPython, m_flSoundDelay, FIELD_TIME ),
};
IMPLEMENT_SAVERESTORE( CPython, CBasePlayerWeapon );
TYPEDESCRIPTION CAP9::m_SaveData[] =
{
DEFINE_FIELD( CAP9, m_iBurstShots, FIELD_INTEGER ),
};
IMPLEMENT_SAVERESTORE( CAP9, CBasePlayerWeapon );
TYPEDESCRIPTION CSniper::m_SaveData[] =
{
DEFINE_FIELD( CSniper, m_fInZoom, FIELD_BOOLEAN ),
};
IMPLEMENT_SAVERESTORE( CSniper, CBasePlayerWeapon )
#if 0
TYPEDESCRIPTION CEinar1::m_SaveData[] =
{
DEFINE_FIELD( CEinar1, m_fInZoom, FIELD_BOOLEAN ),
};
IMPLEMENT_SAVERESTORE( CEinar1, CBasePlayerWeapon )
#endif

View File

@ -55,6 +55,15 @@ public:
BOOL m_fRegisteredSound;// whether or not this grenade has issued its DANGER sound to the world sound list yet.
};
// Timed Tnt
class CTnt : public CGrenade
{
public:
void Spawn( void );
static CGrenade *ShootTimed( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity, float time );
};
// constant items
#define ITEM_HEALTHKIT 1
#define ITEM_ANTIDOTE 2
@ -77,6 +86,13 @@ public:
#define WEAPON_TRIPMINE 13
#define WEAPON_SATCHEL 14
#define WEAPON_SNARK 15
#define WEAPON_SHOVEL 16
#define WEAPON_SPANNER 17
#define WEAPON_AP9 18
#define WEAPON_TAURUS 19
#define WEAPON_EINAR1 20
#define WEAPON_HKG36 21
#define WEAPON_MEDKIT 22
#define WEAPON_ALLWEAPONS (~(1<<WEAPON_SUIT))
@ -101,6 +117,13 @@ public:
#define SNARK_WEIGHT 5
#define SATCHEL_WEIGHT -10
#define TRIPMINE_WEIGHT -10
#define SHOVEL_WEIGHT 0
#define SPANNER_WEIGHT 0
#define AP9_WEIGHT 10
#define TAURUS_WEIGHT 10
#define SNIPER_WEIGHT 10
#define CHAINGUN_WEIGHT 20
#define MEDKIT_WEIGHT -1
// weapon clip/carry ammo capacities
#define URANIUM_MAX_CARRY 100
@ -115,6 +138,11 @@ public:
#define SNARK_MAX_CARRY 15
#define HORNET_MAX_CARRY 8
#define M203_GRENADE_MAX_CARRY 10
#define AP9_MAX_CARRY 200
#define TAURUS_MAX_CARRY 80
#define SNIPER_MAX_CARRY 50
#define CHAINGUN_MAX_CARRY 200
#define MEDKIT_MAX_CARRY 12
// the maximum amount of ammo each weapon's clip can hold
#define WEAPON_NOCLIP -1
@ -134,6 +162,11 @@ public:
#define SATCHEL_MAX_CLIP WEAPON_NOCLIP
#define TRIPMINE_MAX_CLIP WEAPON_NOCLIP
#define SNARK_MAX_CLIP WEAPON_NOCLIP
#define AP9_MAX_CLIP 40
#define TAURUS_MAX_CLIP 10
#define SNIPER_MAX_CLIP 5
#define CHAINGUN_MAX_CLIP 100
#define MEDKIT_MAX_CLIP WEAPON_NOCLIP
// the default amount of ammo that comes with each gun when it spawns
#define GLOCK_DEFAULT_GIVE 17
@ -151,6 +184,11 @@ public:
#define TRIPMINE_DEFAULT_GIVE 1
#define SNARK_DEFAULT_GIVE 5
#define HIVEHAND_DEFAULT_GIVE 8
#define AP9_DEFAULT_GIVE 40
#define TAURUS_DEFAULT_GIVE 10
#define SNIPER_DEFAULT_GIVE 5
#define CHAINGUN_DEFAULT_GIVE 100
#define MEDKIT_DEFAULT_GIVE 12
// The amount of ammo given to a player by an ammo item.
#define AMMO_URANIUMBOX_GIVE 20
@ -164,6 +202,10 @@ public:
#define AMMO_RPGCLIP_GIVE RPG_MAX_CLIP
#define AMMO_URANIUMBOX_GIVE 20
#define AMMO_SNARKBOX_GIVE 5
#define AMMO_AP9_GIVE AP9_MAX_CLIP
#define AMMO_TAURUS_GIVE TAURUS_MAX_CLIP
#define AMMO_SNIPER_GIVE SNIPER_MAX_CLIP
#define AMMO_CHAINGUN_GIVE CHAINGUN_MAX_CLIP
// bullet types
typedef enum
@ -174,7 +216,10 @@ typedef enum
BULLET_PLAYER_357, // python
BULLET_PLAYER_BUCKSHOT, // shotgun
BULLET_PLAYER_CROWBAR, // crowbar swipe
BULLET_PLAYER_AP9,
BULLET_PLAYER_CHAINGUN,
BULLET_PLAYER_SNIPER,
BULLET_PLAYER_TAURUS,
BULLET_MONSTER_9MM,
BULLET_MONSTER_MP5,
BULLET_MONSTER_12MM
@ -331,6 +376,7 @@ public:
void PrintState( void );
virtual CBasePlayerItem *GetWeaponPtr( void ) { return (CBasePlayerItem *)this; };
float GetNextAttackDelay( float delay );
float m_flPumpTime;
int m_fInSpecialReload; // Are we in the middle of a reload for the shotguns
@ -345,6 +391,10 @@ public:
int m_fInReload; // Are we in the middle of a reload;
int m_iDefaultAmmo;// how much ammo you get when you pick up this weapon as placed by a level designer.
// hle time creep vars
float m_flPrevPrimaryAttack;
float m_flLastFireTime;
};
class CBasePlayerAmmo : public CBaseEntity
@ -368,6 +418,7 @@ extern DLL_GLOBAL short g_sModelIndexWExplosion;// holds the index for the under
extern DLL_GLOBAL short g_sModelIndexBubbles;// holds the index for the bubbles model
extern DLL_GLOBAL short g_sModelIndexBloodDrop;// holds the sprite index for blood drops
extern DLL_GLOBAL short g_sModelIndexBloodSpray;// holds the sprite index for blood spray (bigger)
extern DLL_GLOBAL short g_sModelIndexFThrow;// holds the index for the flamethrower
extern void ClearMultiDamage(void);
extern void ApplyMultiDamage(entvars_t* pevInflictor, entvars_t* pevAttacker );
@ -475,6 +526,16 @@ public:
#endif
}
void Holster( int skiplocal = 0 );
BOOL ShouldWeaponIdle( void );
#ifndef CLIENT_DLL
int Save( CSave &save );
int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
#endif
BOOL m_fSilencerOn;
private:
int m_iShell;
@ -525,6 +586,11 @@ public:
void Holster( int skiplocal = 0 );
void Reload( void );
void WeaponIdle( void );
#ifndef CLIENT_DLL
int Save( CSave &save );
int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
#endif
float m_flSoundDelay;
BOOL m_fInZoom;// don't save this.
@ -982,4 +1048,298 @@ public:
private:
unsigned short m_usSnarkFire;
};
class CShovel : public CCrowbar
{
public:
void Spawn( void );
void Precache( void );
int GetItemInfo(ItemInfo *p);
void PrimaryAttack( void );
int Swing( int fFirst );
BOOL Deploy( void );
void Holster( int skiplocal = 0 );
private:
unsigned short m_usShovel;
};
class CSpanner : public CCrowbar
{
public:
void Spawn(void);
void Precache(void);
int GetItemInfo(ItemInfo *p);
void PrimaryAttack(void);
int Swing(int fFirst);
BOOL Deploy(void);
void Holster(int skiplocal = 0);
private:
unsigned short m_usSpanner;
};
class CAP9 : public CBasePlayerWeapon
{
public:
#ifndef CLIENT_DLL
int Save(CSave &save);
int Restore(CRestore &restore);
static TYPEDESCRIPTION m_SaveData[];
#endif
void Spawn(void);
void Precache(void);
int iItemSlot(void) { return 2; }
int GetItemInfo(ItemInfo *p);
int AddToPlayer(CBasePlayer *pPlayer);
void PrimaryAttack(void);
void SecondaryAttack(void);
void AP9Fire(float flSpread, float flCycleTime, BOOL fUseAutoAim, BOOL fBurstShot);
BOOL Deploy(void);
void Reload(void);
void WeaponIdle(void);
BOOL ShouldWeaponIdle(void) { return TRUE; }
int m_iShell;
virtual BOOL UseDecrement(void)
{
#if defined( CLIENT_WEAPONS )
return TRUE;
#else
return FALSE;
#endif
}
int m_iBurstShots;
private:
unsigned short m_usFireAP9;
};
class CTaurus : public CGlock
{
public:
void Spawn( void );
void Precache( void );
int GetItemInfo(ItemInfo *p);
void PrimaryAttack( void );
void SecondaryAttack( void ) {}
BOOL Deploy( void );
void Reload( void );
void WeaponIdle( void );
private:
int m_iShell;
unsigned short m_usFireTaurus;
};
class CSniper : public CBasePlayerWeapon
{
public:
#ifndef CLIENT_DLL
int Save(CSave &save);
int Restore(CRestore &restore);
static TYPEDESCRIPTION m_SaveData[];
#endif
virtual int GetPrimaryAttackActivity(void) = 0;
virtual int GetZoomedAttackActivity(void) = 0;
int iItemSlot(void) { return 3; }
int AddToPlayer(CBasePlayer *pPlayer);
void PrimaryAttack(void);
void SecondaryAttack(void);
void SniperFire(float flSpread, float flCycleTime, BOOL fUseAutoAim, int iActivity);
void Holster(int skiplocal = 0);
void Reload(void);
void WeaponIdle(void);
virtual BOOL UseDecrement(void)
{
#if defined( CLIENT_WEAPONS )
return TRUE;
#else
return FALSE;
#endif
}
void SetZoomState(BOOL bState);
void ToggleZoom(void);
BOOL m_fInZoom;
protected:
unsigned short m_usFireSniper;
};
class CHKG36 : public CSniper
{
public:
void Spawn(void);
void Precache(void);
int GetItemInfo(ItemInfo *p);
BOOL Deploy(void);
void Reload(void);
void WeaponIdle(void);
int GetPrimaryAttackActivity(void);
int GetZoomedAttackActivity(void);
};
#if 0
class CEinar1 : public CSniper
{
public:
void Spawn(void);
void Precache(void);
int GetItemInfo(ItemInfo *p);
void PrimaryAttack(void);
void SecondaryAttack(void);
BOOL Deploy(void);
void Holster(int skiplocal = 0);
void Reload(void);
void WeaponIdle(void);
BOOL ShouldWeaponIdle(void);
int GetPrimaryAttackActivity(void);
int GetZoomedAttackActivity(void);
private:
unsigned short m_usFireSniper2;
};
#endif
#if 0
class CEinar1 : public CBasePlayerWeapon
{
public:
#ifndef CLIENT_DLL
int Save(CSave &save);
int Restore(CRestore &restore);
static TYPEDESCRIPTION m_SaveData[];
#endif
void Spawn(void);
void Precache(void);
int GetItemInfo(ItemInfo *p);
int iItemSlot(void) { return 3; }
int AddToPlayer(CBasePlayer *pPlayer);
void PrimaryAttack(void);
void SecondaryAttack(void);
BOOL Deploy(void);
void Holster(int skiplocal = 0);
void Reload(void);
void WeaponIdle(void);
BOOL ShouldWeaponIdle(void);
virtual BOOL UseDecrement(void)
{
#if defined( CLIENT_WEAPONS )
return TRUE;
#else
return FALSE;
#endif
}
void SetZoomState(BOOL bState);
void ToggleZoom(void);
BOOL m_fInZoom;
private:
unsigned short m_usFireSniper;
unsigned short m_usFireSniper2;
};
#endif
#if 1
class CEinar1 : public CSniper
{
public:
void Spawn(void);
void Precache(void);
int GetItemInfo(ItemInfo *p);
void PrimaryAttack(void);
void SecondaryAttack(void);
BOOL Deploy(void);
void Holster(int skiplocal = 0);
void Reload(void);
void WeaponIdle(void);
BOOL ShouldWeaponIdle(void);
int GetPrimaryAttackActivity(void);
int GetZoomedAttackActivity(void);
};
#endif
class CChaingun : public CBasePlayerWeapon
{
public:
void Spawn(void);
void Precache(void);
int iItemSlot(void) { return 4; }
int GetItemInfo(ItemInfo *p);
void PrimaryAttack(void);
void SecondaryAttack(void);
BOOL Deploy(void);
void Holster(int skiplocal = 0);
void Reload(void);
void WeaponIdle(void);
BOOL ShouldWeaponIdle(void);
virtual BOOL UseDecrement(void)
{
#if defined( CLIENT_WEAPONS )
return TRUE;
#else
return FALSE;
#endif
}
void SpinUp(void);
void SpinDown(void);
void Spin(void);
void Fire(float flSpread, float flCycleTime, BOOL fUseAutoAim);
void StopSounds(void);
private:
int m_iShell;
unsigned short m_usFireChaingun1;
unsigned short m_usFireChaingun2;
};
class CMedkit : public CBasePlayerWeapon
{
public:
void Spawn(void);
void Precache(void);
int iItemSlot(void) { return 5; }
int GetItemInfo(ItemInfo *p);
void PrimaryAttack(void);
BOOL Deploy(void);
void Holster(int skiplocal = 0);
void WeaponIdle(void);
BOOL PlayEmptySound(void);
BOOL ShouldWeaponIdle(void) { return TRUE; }
virtual BOOL UseDecrement(void)
{
#if defined( CLIENT_WEAPONS )
return TRUE;
#else
return FALSE;
#endif
}
float m_flSoundDelay;
private:
unsigned short m_usMedkit;
};
#endif // WEAPONS_H

View File

@ -617,20 +617,6 @@ void CWorld::Precache( void )
// g-cont. moved here to right restore global WaveHeight on save\restore level
CVAR_SET_FLOAT( "sv_wateramp", pev->scale );
if( pev->netname )
{
ALERT( at_aiconsole, "Chapter title: %s\n", STRING( pev->netname ) );
CBaseEntity *pEntity = CBaseEntity::Create( "env_message", g_vecZero, g_vecZero, NULL );
if( pEntity )
{
pEntity->SetThink( &CBaseEntity::SUB_CallUseToggle );
pEntity->pev->message = pev->netname;
pev->netname = 0;
pEntity->pev->nextthink = gpGlobals->time + 0.3;
pEntity->pev->spawnflags = SF_MESSAGE_ONCE;
}
}
if( pev->spawnflags & SF_WORLD_DARK )
CVAR_SET_FLOAT( "v_dark", 1.0 );
else

View File

@ -23,6 +23,58 @@
#include "cbase.h"
#include "monsters.h"
#include "schedule.h"
#include "zombie.h"
//
// Spawn Flags
//
#define SF_ZOMBIE_FASTMODE 1024
#define NUM_ZOMBIE1_BODIES 11
#define NUM_ZOMBIE2_BODIES 6
#define NUM_ZOMBIE3_BODIES 5
enum
{
ZOMBIE1_FUNERAL = 0,
ZOMBIE1_FUNERAL_HEADLESS,
ZOMBIE1_CIVILIAN,
ZOMBIE1_CIVILIAN_HEADLESS,
ZOMBIE1_COP,
ZOMBIE1_FEMALE,
ZOMBIE1_BIOHAZARD_SUIT,
ZOMBIE1_ECHELON_OFFICER,
ZOMBIE1_EINSTEIN,
ZOMBIE1_DOCTOR,
ZOMBIE1_PATIENT
};
enum
{
ZOMBIE2_COP_HEADOPEN = 0,
ZOMBIE2_COP_CROWBAR,
ZOMBIE2_DOCTOR,
ZOMBIE2_DOCTOR_BUTCHER,
ZOMBIE2_DOCTOR_SHOTGUN,
ZOMBIE2_CIVILIAN_CHEST_GUN
};
enum
{
ZOMBIE3_NEIL = 0,
ZOMBIE3_BROOM,
ZOMBIE3_OLD,
ZOMBIE3_MECHANIC,
ZOMBIE3_HAMMER
};
enum
{
LPZOMBIE_STANDARD = 0,
LPZOMBIE_COP,
LPZOMBIE_BURNT,
LPZOMBIE_FLESH
};
//=========================================================
// Monster's Anim Events Go Here
@ -33,37 +85,14 @@
#define ZOMBIE_FLINCH_DELAY 2 // at most one flinch every n secs
class CZombie : public CBaseMonster
LINK_ENTITY_TO_CLASS( monster_zombie, CZombie )
TYPEDESCRIPTION CZombie::m_SaveData[] =
{
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 );
DEFINE_FIELD( CZombie, m_iZombieFlags, FIELD_INTEGER ),
};
LINK_ENTITY_TO_CLASS( monster_zombie, CZombie )
IMPLEMENT_SAVERESTORE( CZombie, CBaseMonster )
const char *CZombie::pAttackHitSounds[] =
{
@ -105,6 +134,135 @@ const char *CZombie::pPainSounds[] =
"zombie/zo_pain2.wav",
};
const char *CZombie::pCopAttackSounds[] =
{
"zombiecop/zo_attack1.wav",
"zombiecop/zo_attack2.wav",
};
const char *CZombie::pCopIdleSounds[] =
{
"zombiecop/zo_idle1.wav",
"zombiecop/zo_idle2.wav",
"zombiecop/zo_idle3.wav",
"zombiecop/zo_idle4.wav",
};
const char *CZombie::pCopAlertSounds[] =
{
"zombiecop/zo_alert10.wav",
"zombiecop/zo_alert20.wav",
"zombiecop/zo_alert30.wav",
};
const char *CZombie::pCopPainSounds[] =
{
"zombiecop/zo_pain1.wav",
"zombiecop/zo_pain2.wav",
};
const char *CZombie::pFemaleAttackSounds[] =
{
"zfemale/zo_attack1.wav",
"zfemale/zo_attack2.wav",
};
const char *CZombie::pFemaleIdleSounds[] =
{
"zfemale/zo_idle1.wav",
"zfemale/zo_idle2.wav",
"zfemale/zo_idle3.wav",
"zfemale/zo_idle4.wav",
};
const char *CZombie::pFemaleAlertSounds[] =
{
"zfemale/zo_alert10.wav",
"zfemale/zo_alert20.wav",
"zfemale/zo_alert30.wav",
};
const char *CZombie::pFemalePainSounds[] =
{
"zfemale/zo_pain1.wav",
"zfemale/zo_pain2.wav",
};
const char *CZombie::pNurseAttackSounds[] =
{
"znurse/zo_attack1.wav",
"znurse/zo_attack2.wav",
};
const char *CZombie::pNurseIdleSounds[] =
{
"znurse/zo_idle1.wav",
"znurse/zo_idle2.wav",
"znurse/zo_idle3.wav",
"znurse/zo_idle4.wav",
};
const char *CZombie::pNurseAlertSounds[] =
{
"znurse/zo_alert10.wav",
"znurse/zo_alert20.wav",
"znurse/zo_alert30.wav",
};
const char *CZombie::pNursePainSounds[] =
{
"znurse/zo_pain1.wav",
"znurse/zo_pain2.wav",
};
const char *CZombie::pNewAttackSounds[] =
{
"zombienew/zo_attack1.wav",
"zombienew/zo_attack2.wav",
};
const char *CZombie::pNewIdleSounds[] =
{
"zombienew/zo_idle1.wav",
"zombienew/zo_idle2.wav",
"zombienew/zo_idle3.wav",
"zombienew/zo_idle4.wav",
};
const char *CZombie::pNewAlertSounds[] =
{
"zombienew/zo_alert10.wav",
"zombienew/zo_alert20.wav",
"zombienew/zo_alert30.wav",
};
const char *CZombie::pNewPainSounds[] =
{
"zombienew/zo_pain1.wav",
"zombienew/zo_pain2.wav",
"zombienew/zo_pain3.wav",
};
BOOL CZombie::IsFemale() const
{
return ( m_iZombieFlags & ZF_FEMALE );
}
BOOL CZombie::IsNurse() const
{
return ( m_iZombieFlags & ZF_NURSE );
}
BOOL CZombie::IsCop() const
{
return ( m_iZombieFlags & ZF_COP );
}
BOOL CZombie::UseNewSounds() const
{
return ( m_iZombieFlags & ZF_NEWSOUNDS );
}
//=========================================================
// Classify - indicates this monster's place in the
// relationship table.
@ -151,31 +309,146 @@ int CZombie::TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float
void CZombie::PainSound( void )
{
int pitch = 95 + RANDOM_LONG( 0, 9 );
if( RANDOM_LONG( 0, 5 ) < 2 )
EMIT_SOUND_DYN( ENT( pev ), CHAN_VOICE, pPainSounds[RANDOM_LONG( 0, ARRAYSIZE( pPainSounds ) - 1 )], 1.0, ATTN_NORM, 0, pitch );
{
int pitch = 95 + RANDOM_LONG( 0, 9 );
if( IsFemale() )
{
if( IsNurse() )
{
EMIT_SOUND_DYN( ENT( pev ), CHAN_VOICE, pNursePainSounds[RANDOM_LONG( 0, ARRAYSIZE( pNursePainSounds) - 1 )], 1.0, ATTN_NORM, 0, pitch );
}
else
{
EMIT_SOUND_DYN( ENT( pev ), CHAN_VOICE, pFemalePainSounds[RANDOM_LONG( 0, ARRAYSIZE( pFemalePainSounds ) - 1 )], 1.0, ATTN_NORM, 0, pitch );
}
}
else
{
if( IsCop() )
{
EMIT_SOUND_DYN( ENT( pev ), CHAN_VOICE, pCopPainSounds[RANDOM_LONG( 0, ARRAYSIZE( pCopPainSounds ) - 1 )], 1.0, ATTN_NORM, 0, pitch );
}
else
{
if( UseNewSounds() )
{
EMIT_SOUND_DYN( ENT( pev ), CHAN_VOICE, pNewPainSounds[RANDOM_LONG( 0, ARRAYSIZE( pNewPainSounds ) - 1 )], 1.0, ATTN_NORM, 0, pitch );
}
else
{
EMIT_SOUND_DYN( ENT( pev ), CHAN_VOICE, pPainSounds[RANDOM_LONG( 0, ARRAYSIZE( pPainSounds ) - 1 )], 1.0, ATTN_NORM, 0, pitch );
}
}
}
}
}
void CZombie::AlertSound( void )
{
int pitch = 95 + RANDOM_LONG( 0, 9 );
EMIT_SOUND_DYN( ENT( pev ), CHAN_VOICE, pAlertSounds[ RANDOM_LONG( 0, ARRAYSIZE( pAlertSounds ) - 1 )], 1.0, ATTN_NORM, 0, pitch );
if( IsFemale() )
{
if( IsNurse() )
{
EMIT_SOUND_DYN( ENT( pev ), CHAN_VOICE, pNurseAlertSounds[RANDOM_LONG( 0, ARRAYSIZE( pNurseAlertSounds ) - 1 )], 1.0, ATTN_NORM, 0, pitch );
}
else
{
EMIT_SOUND_DYN( ENT( pev ), CHAN_VOICE, pFemaleAlertSounds[RANDOM_LONG( 0, ARRAYSIZE( pFemaleAlertSounds ) - 1 )], 1.0, ATTN_NORM, 0, pitch );
}
}
else
{
if( IsCop() )
{
EMIT_SOUND_DYN( ENT( pev ), CHAN_VOICE, pCopAlertSounds[RANDOM_LONG(0, ARRAYSIZE(pCopAlertSounds) - 1)], 1.0, ATTN_NORM, 0, pitch);
}
else
{
if( UseNewSounds() )
{
EMIT_SOUND_DYN( ENT( pev ), CHAN_VOICE, pNewAlertSounds[RANDOM_LONG( 0, ARRAYSIZE( pNewAlertSounds ) - 1 )], 1.0, ATTN_NORM, 0, pitch );
}
else
{
EMIT_SOUND_DYN( ENT( pev ), CHAN_VOICE, pAlertSounds[RANDOM_LONG( 0, ARRAYSIZE( pAlertSounds ) - 1 )], 1.0, ATTN_NORM, 0, pitch );
}
}
}
}
void CZombie::IdleSound( void )
{
int pitch = 95 + RANDOM_LONG( 0, 9 );
// Play a random idle sound
EMIT_SOUND_DYN( ENT( pev ), CHAN_VOICE, pIdleSounds[RANDOM_LONG( 0, ARRAYSIZE( pIdleSounds ) -1 )], 1.0, ATTN_NORM, 0, 100 + RANDOM_LONG( -5, 5 ) );
if( IsFemale() )
{
if( IsNurse() )
{
EMIT_SOUND_DYN( ENT( pev ), CHAN_VOICE, pNurseIdleSounds[RANDOM_LONG( 0, ARRAYSIZE( pNurseIdleSounds ) - 1 )], 1.0, ATTN_NORM, 0, pitch );
}
else
{
EMIT_SOUND_DYN( ENT( pev ), CHAN_VOICE, pFemaleIdleSounds[RANDOM_LONG( 0, ARRAYSIZE( pFemaleIdleSounds ) - 1 )], 1.0, ATTN_NORM, 0, pitch );
}
}
else
{
if( IsCop() )
{
EMIT_SOUND_DYN( ENT( pev ), CHAN_VOICE, pCopIdleSounds[RANDOM_LONG(0, ARRAYSIZE(pCopIdleSounds) - 1)], 1.0, ATTN_NORM, 0, pitch);
}
else
{
if( UseNewSounds() )
{
EMIT_SOUND_DYN( ENT( pev ), CHAN_VOICE, pNewIdleSounds[RANDOM_LONG( 0, ARRAYSIZE( pNewIdleSounds ) - 1 )], 1.0, ATTN_NORM, 0, pitch );
}
else
{
EMIT_SOUND_DYN( ENT( pev ), CHAN_VOICE, pIdleSounds[RANDOM_LONG( 0, ARRAYSIZE( pIdleSounds ) - 1 )], 1.0, ATTN_NORM, 0, pitch );
}
}
}
}
void CZombie::AttackSound( void )
{
int pitch = 100 + RANDOM_LONG( -5, 5 );
// Play a random attack sound
EMIT_SOUND_DYN( ENT( pev ), CHAN_VOICE, pAttackSounds[RANDOM_LONG( 0, ARRAYSIZE( pAttackSounds ) - 1 )], 1.0, ATTN_NORM, 0, 100 + RANDOM_LONG( -5, 5 ) );
if( IsFemale() )
{
if( IsNurse() )
{
EMIT_SOUND_DYN( ENT( pev ), CHAN_VOICE, pNurseAttackSounds[RANDOM_LONG( 0, ARRAYSIZE( pNurseAttackSounds ) - 1 )], 1.0, ATTN_NORM, 0, pitch );
}
else
{
EMIT_SOUND_DYN( ENT( pev ), CHAN_VOICE, pFemaleAttackSounds[RANDOM_LONG( 0, ARRAYSIZE( pFemaleAttackSounds ) - 1 )], 1.0, ATTN_NORM, 0, pitch );
}
}
else
{
if( IsCop() )
{
EMIT_SOUND_DYN( ENT( pev ), CHAN_VOICE, pCopAttackSounds[RANDOM_LONG( 0, ARRAYSIZE( pCopAttackSounds ) - 1 )], 1.0, ATTN_NORM, 0, pitch );
}
else
{
if( UseNewSounds() )
{
EMIT_SOUND_DYN( ENT( pev ), CHAN_VOICE, pNewAttackSounds[RANDOM_LONG( 0, ARRAYSIZE( pNewAttackSounds ) - 1 )], 1.0, ATTN_NORM, 0, pitch );
}
else
{
EMIT_SOUND_DYN( ENT( pev ), CHAN_VOICE, pAttackSounds[RANDOM_LONG( 0, ARRAYSIZE( pAttackSounds ) - 1 )], 1.0, ATTN_NORM, 0, pitch );
}
}
}
}
//=========================================================
@ -264,12 +537,19 @@ void CZombie::Spawn()
{
Precache();
SET_MODEL( ENT(pev), "models/zombie.mdl" );
char* szModel = (char*)STRING( pev->model );
if( !szModel || !*szModel )
{
szModel = "models/zombie.mdl";
pev->model = ALLOC_STRING( szModel );
}
SET_MODEL( ENT( pev ), STRING( pev->model ) );
UTIL_SetSize( pev, VEC_HUMAN_HULL_MIN, VEC_HUMAN_HULL_MAX );
pev->solid = SOLID_SLIDEBOX;
pev->movetype = MOVETYPE_STEP;
m_bloodColor = BLOOD_COLOR_GREEN;
m_bloodColor = BLOOD_COLOR_RED;
pev->health = gSkillData.zombieHealth;
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 )
@ -277,6 +557,76 @@ void CZombie::Spawn()
m_afCapability = bits_CAP_DOORS_GROUP;
MonsterInit();
m_iZombieFlags = 0;
if( FStrEq( STRING( pev->model ), "models/zombie.mdl" ) )
{
switch( pev->body )
{
case ZOMBIE1_COP:
m_iZombieFlags |= ZF_COP;
break;
case ZOMBIE1_FEMALE:
m_iZombieFlags |= ZF_FEMALE;
break;
default:
break;
}
}
else if( FStrEq( STRING( pev->model ), "models/zombie2.mdl" ) )
{
switch( pev->body )
{
case ZOMBIE2_COP_HEADOPEN:
case ZOMBIE2_COP_CROWBAR:
m_iZombieFlags |= ZF_COP;
break;
default:
break;
}
}
else if( FStrEq( STRING( pev->model ), "models/zombie3.mdl" ) )
{
// Third zombie model always use new sounds.
m_iZombieFlags |= ZF_NEWSOUNDS;
switch( pev->body )
{
case ZOMBIE3_BROOM:
m_iZombieFlags |= ZF_FEMALE;
break;
default:
break;
}
}
else if( FStrEq( STRING( pev->model ), "models/nursezombie.mdl" ) )
{
m_iZombieFlags |= ( ZF_FEMALE | ZF_NURSE );
}
else if( FStrEq( STRING( pev->model ), "models/lpzombie.mdl" ) ) // Special zombie type with few polygons.
{
// Low polygon zombie model always use new sounds.
m_iZombieFlags |= ZF_NEWSOUNDS;
switch( pev->skin )
{
case LPZOMBIE_COP:
m_iZombieFlags |= ZF_COP;
break;
case LPZOMBIE_FLESH:
// Unable to differentiate genders so set this flag randomly.
if( RANDOM_LONG( 0, 1 ) )
m_iZombieFlags |= ZF_FEMALE;
break;
default:
break;
}
}
else
{
ALERT( at_warning, "Unsupported zombie model %s\n", STRING( pev->model ) );
}
}
//=========================================================
@ -287,6 +637,10 @@ void CZombie::Precache()
int i;
PRECACHE_MODEL( "models/zombie.mdl" );
PRECACHE_MODEL( "models/zombie2.mdl" );
PRECACHE_MODEL( "models/zombie3.mdl" );
PRECACHE_MODEL( "models/nursezombie.mdl" );
PRECACHE_MODEL( "models/lpzombie.mdl" );
for( i = 0; i < ARRAYSIZE( pAttackHitSounds ); i++ )
PRECACHE_SOUND( (char *)pAttackHitSounds[i] );
@ -305,6 +659,26 @@ void CZombie::Precache()
for( i = 0; i < ARRAYSIZE( pPainSounds ); i++ )
PRECACHE_SOUND( (char *)pPainSounds[i] );
PRECACHE_SOUND_ARRAY( pCopAttackSounds );
PRECACHE_SOUND_ARRAY( pCopIdleSounds );
PRECACHE_SOUND_ARRAY( pCopAlertSounds );
PRECACHE_SOUND_ARRAY( pCopPainSounds );
PRECACHE_SOUND_ARRAY( pFemaleAttackSounds );
PRECACHE_SOUND_ARRAY( pFemaleIdleSounds );
PRECACHE_SOUND_ARRAY( pFemaleAlertSounds );
PRECACHE_SOUND_ARRAY( pFemalePainSounds );
PRECACHE_SOUND_ARRAY( pNurseAttackSounds );
PRECACHE_SOUND_ARRAY( pNurseIdleSounds );
PRECACHE_SOUND_ARRAY( pNurseAlertSounds );
PRECACHE_SOUND_ARRAY( pNursePainSounds );
PRECACHE_SOUND_ARRAY( pNewAttackSounds );
PRECACHE_SOUND_ARRAY( pNewIdleSounds );
PRECACHE_SOUND_ARRAY( pNewAlertSounds );
PRECACHE_SOUND_ARRAY( pNewPainSounds );
}
//=========================================================
@ -334,3 +708,21 @@ int CZombie::IgnoreConditions( void )
return iIgnore;
}
//========================================================
// RunAI - overridden for zombie because there are things
// that need to be checked every think.
//========================================================
void CZombie::RunAI( void )
{
// first, do base class stuff
CBaseMonster::RunAI();
if( pev->spawnflags & SF_ZOMBIE_FASTMODE )
{
if( m_Activity == ACT_WALK || m_Activity == ACT_RUN )
{
pev->framerate = 1.5;
}
}
}

89
dlls/zombie.h Normal file
View File

@ -0,0 +1,89 @@
/***
*
* 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.
*
****/
#ifndef ZOMBIE_H
#define ZOMBIE_H
//
// Zombie Flags
//
#define ZF_FEMALE 1
#define ZF_NURSE 2
#define ZF_COP 4
#define ZF_NEWSOUNDS 8
class CZombie : 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 );
int Save(CSave &save);
int Restore(CRestore &restore);
static TYPEDESCRIPTION m_SaveData[];
void RunAI(void);
BOOL IsFemale() const;
BOOL IsNurse() const;
BOOL IsCop() const;
BOOL UseNewSounds() const;
static const char *pCopAttackSounds[];
static const char *pCopIdleSounds[];
static const char *pCopAlertSounds[];
static const char *pCopPainSounds[];
static const char *pFemaleAttackSounds[];
static const char *pFemaleIdleSounds[];
static const char *pFemaleAlertSounds[];
static const char *pFemalePainSounds[];
static const char *pNurseAttackSounds[];
static const char *pNurseIdleSounds[];
static const char *pNurseAlertSounds[];
static const char *pNursePainSounds[];
static const char *pNewAttackSounds[];
static const char *pNewIdleSounds[];
static const char *pNewAlertSounds[];
static const char *pNewPainSounds[];
int m_iZombieFlags;
};
#endif // ZOMBIE_H