mirror of https://github.com/FWGS/hlsdk-xash3d
Upload reverse-engineered Azure Sheep source code.
This commit is contained in:
parent
4078ca6ad8
commit
888483b5c4
|
@ -24,25 +24,11 @@ LOCAL_CFLAGS += -DCLIENT_DLL=1
|
|||
|
||||
SRCS=
|
||||
SRCS_C=
|
||||
SRCS+=../dlls/crossbow.cpp
|
||||
SRCS+=../dlls/crowbar.cpp
|
||||
SRCS+=../dlls/egon.cpp
|
||||
SRCS+=./ev_hldm.cpp
|
||||
SRCS+=../dlls/gauss.cpp
|
||||
SRCS+=../dlls/handgrenade.cpp
|
||||
SRCS+=./hl/hl_baseentity.cpp
|
||||
SRCS+=./hl/hl_events.cpp
|
||||
SRCS+=./hl/hl_objects.cpp
|
||||
SRCS+=./hl/hl_weapons.cpp
|
||||
SRCS+=../dlls/hornetgun.cpp
|
||||
SRCS+=../dlls/mp5.cpp
|
||||
SRCS+=../dlls/python.cpp
|
||||
SRCS+=../dlls/rpg.cpp
|
||||
SRCS+=../dlls/satchel.cpp
|
||||
SRCS+=../dlls/shotgun.cpp
|
||||
SRCS+=../dlls/squeakgrenade.cpp
|
||||
SRCS+=../dlls/tripmine.cpp
|
||||
SRCS+=../dlls/glock.cpp
|
||||
#SRCS+=../game_shared/voice_banmgr.cpp
|
||||
#SRCS+=../game_shared/voice_status.cpp
|
||||
SRCS+=./ammo.cpp
|
||||
|
@ -92,7 +78,7 @@ SRCS+=./input_xash3d.cpp
|
|||
SRCS+=./scoreboard.cpp
|
||||
SRCS+=./MOTD.cpp
|
||||
INCLUDES = -I../common -I. -I../game_shared -I../pm_shared -I../engine -I../dlls -I../utils/false_vgui/include
|
||||
DEFINES = -Wno-write-strings -DLINUX -D_LINUX -Dstricmp=strcasecmp -Dstrnicmp=strncasecmp -DCLIENT_WEAPONS -DCLIENT_DLL -w
|
||||
DEFINES = -Wno-write-strings -DLINUX -D_LINUX -Dstricmp=strcasecmp -Dstrnicmp=strncasecmp -DCLIENT_DLL -w
|
||||
|
||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/. \
|
||||
$(LOCAL_PATH)/../common \
|
||||
|
|
|
@ -25,31 +25,13 @@ project (CLDLL)
|
|||
|
||||
set (CLDLL_LIBRARY client)
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-write-strings -DLINUX -D_LINUX -Dstricmp=strcasecmp -D_strnicmp=strncasecmp -Dstrnicmp=strncasecmp -DCLIENT_WEAPONS -DCLIENT_DLL -w")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-write-strings -DLINUX -D_LINUX -Dstricmp=strcasecmp -D_strnicmp=strncasecmp -Dstrnicmp=strncasecmp -DCLIENT_DLL -w")
|
||||
if (GOLDSOURCE_SUPPORT)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DGOLDSOURCE_SUPPORT")
|
||||
endif()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS}")
|
||||
|
||||
set (CLDLL_SOURCES
|
||||
../dlls/crossbow.cpp
|
||||
../dlls/crowbar.cpp
|
||||
../dlls/egon.cpp
|
||||
../dlls/gauss.cpp
|
||||
../dlls/handgrenade.cpp
|
||||
../dlls/hornetgun.cpp
|
||||
../dlls/mp5.cpp
|
||||
../dlls/python.cpp
|
||||
../dlls/rpg.cpp
|
||||
../dlls/satchel.cpp
|
||||
../dlls/shotgun.cpp
|
||||
../dlls/squeakgrenade.cpp
|
||||
../dlls/tripmine.cpp
|
||||
../dlls/glock.cpp
|
||||
../dlls/asheep/beretta.cpp
|
||||
../dlls/asheep/m41a.cpp
|
||||
../dlls/asheep/poolstick.cpp
|
||||
../dlls/asheep/toad.cpp
|
||||
ev_hldm.cpp
|
||||
hl/hl_baseentity.cpp
|
||||
hl/hl_events.cpp
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#define AMMOHISTORY_H
|
||||
|
||||
// this is the max number of items in each bucket
|
||||
#define MAX_WEAPON_POSITIONS MAX_WEAPON_SLOTS
|
||||
#define MAX_WEAPON_POSITIONS MAX_WEAPON_SLOTS + 1
|
||||
|
||||
class WeaponsResource
|
||||
{
|
||||
|
|
|
@ -55,19 +55,9 @@ void EV_FireGlock2( struct event_args_s *args );
|
|||
void EV_FireShotGunSingle( struct event_args_s *args );
|
||||
void EV_FireShotGunDouble( struct event_args_s *args );
|
||||
void EV_FireMP5( struct event_args_s *args );
|
||||
void EV_FireMP52( struct event_args_s *args );
|
||||
void EV_FirePython( struct event_args_s *args );
|
||||
void EV_FireGauss( struct event_args_s *args );
|
||||
void EV_SpinGauss( struct event_args_s *args );
|
||||
void EV_Crowbar( struct event_args_s *args );
|
||||
void EV_FireCrossbow( struct event_args_s *args );
|
||||
void EV_FireCrossbow2( struct event_args_s *args );
|
||||
void EV_FireRpg( struct event_args_s *args );
|
||||
void EV_EgonFire( struct event_args_s *args );
|
||||
void EV_EgonStop( struct event_args_s *args );
|
||||
void EV_HornetGunFire( struct event_args_s *args );
|
||||
void EV_TripmineFire( struct event_args_s *args );
|
||||
void EV_SnarkFire( struct event_args_s *args );
|
||||
|
||||
//Begin Alex
|
||||
void EV_FireM41A( struct event_args_s *args );
|
||||
|
@ -402,28 +392,16 @@ void EV_HLDM_FireBullets( int idx, float *forward, float *right, float *up, int
|
|||
vec3_t vecDir, vecEnd;
|
||||
float x, y, z;
|
||||
|
||||
//We randomize for the Shotgun.
|
||||
if( iBulletType == BULLET_PLAYER_BUCKSHOT )
|
||||
{
|
||||
do{
|
||||
x = gEngfuncs.pfnRandomFloat( -0.5, 0.5 ) + gEngfuncs.pfnRandomFloat( -0.5, 0.5 );
|
||||
y = gEngfuncs.pfnRandomFloat( -0.5, 0.5 ) + gEngfuncs.pfnRandomFloat( -0.5, 0.5 );
|
||||
z = x * x + y * y;
|
||||
}while( z > 1 );
|
||||
do{
|
||||
x = gEngfuncs.pfnRandomFloat( -0.5, 0.5 ) + gEngfuncs.pfnRandomFloat( -0.5, 0.5 );
|
||||
y = gEngfuncs.pfnRandomFloat( -0.5, 0.5 ) + gEngfuncs.pfnRandomFloat( -0.5, 0.5 );
|
||||
z = x * x + y * y;
|
||||
}while( z > 1 );
|
||||
|
||||
for( i = 0 ; i < 3; i++ )
|
||||
{
|
||||
vecDir[i] = vecDirShooting[i] + x * flSpreadX * right[i] + y * flSpreadY * up [i];
|
||||
vecEnd[i] = vecSrc[i] + flDistance * vecDir[i];
|
||||
}
|
||||
}//But other guns already have their spread randomized in the synched spread.
|
||||
else
|
||||
for( i = 0 ; i < 3; i++ )
|
||||
{
|
||||
for( i = 0 ; i < 3; i++ )
|
||||
{
|
||||
vecDir[i] = vecDirShooting[i] + flSpreadX * right[i] + flSpreadY * up [i];
|
||||
vecEnd[i] = vecSrc[i] + flDistance * vecDir[i];
|
||||
}
|
||||
vecDir[i] = vecDirShooting[i] + x * flSpreadX * right[i] + y * flSpreadY * up [i];
|
||||
vecEnd[i] = vecSrc[i] + flDistance * vecDir[i];
|
||||
}
|
||||
|
||||
gEngfuncs.pEventAPI->EV_SetUpPlayerPrediction( false, true );
|
||||
|
@ -746,32 +724,6 @@ void EV_FireMP5( event_args_t *args )
|
|||
}
|
||||
}
|
||||
|
||||
// We only predict the animation and sound
|
||||
// The grenade is still launched from the server.
|
||||
void EV_FireMP52( event_args_t *args )
|
||||
{
|
||||
int idx;
|
||||
vec3_t origin;
|
||||
|
||||
idx = args->entindex;
|
||||
VectorCopy( args->origin, origin );
|
||||
|
||||
if( EV_IsLocal( idx ) )
|
||||
{
|
||||
gEngfuncs.pEventAPI->EV_WeaponAnimation( MP5_LAUNCH, 2 );
|
||||
V_PunchAxis( 0, -10 );
|
||||
}
|
||||
|
||||
switch( gEngfuncs.pfnRandomLong( 0, 1 ) )
|
||||
{
|
||||
case 0:
|
||||
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/glauncher.wav", 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ) );
|
||||
break;
|
||||
case 1:
|
||||
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/glauncher2.wav", 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
//======================
|
||||
// MP5 END
|
||||
//======================
|
||||
|
@ -1144,571 +1096,6 @@ void EV_FireGauss( event_args_t *args )
|
|||
// GAUSS END
|
||||
//======================
|
||||
|
||||
//======================
|
||||
// CROWBAR START
|
||||
//======================
|
||||
enum crowbar_e
|
||||
{
|
||||
CROWBAR_IDLE = 0,
|
||||
CROWBAR_DRAW,
|
||||
CROWBAR_HOLSTER,
|
||||
CROWBAR_ATTACK1HIT,
|
||||
CROWBAR_ATTACK1MISS,
|
||||
CROWBAR_ATTACK2MISS,
|
||||
CROWBAR_ATTACK2HIT,
|
||||
CROWBAR_ATTACK3MISS,
|
||||
#ifndef CROWBAR_IDLE_ANIM
|
||||
CROWBAR_ATTACK3HIT
|
||||
#else
|
||||
CROWBAR_ATTACK3HIT,
|
||||
CROWBAR_IDLE2,
|
||||
CROWBAR_IDLE3
|
||||
#endif
|
||||
};
|
||||
|
||||
int g_iSwing;
|
||||
|
||||
//Only predict the miss sounds, hit sounds are still played
|
||||
//server side, so players don't get the wrong idea.
|
||||
void EV_Crowbar( 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 ) )
|
||||
{
|
||||
switch( (g_iSwing++) % 3 )
|
||||
{
|
||||
case 0:
|
||||
gEngfuncs.pEventAPI->EV_WeaponAnimation( CROWBAR_ATTACK1MISS, 1 );
|
||||
break;
|
||||
case 1:
|
||||
gEngfuncs.pEventAPI->EV_WeaponAnimation( CROWBAR_ATTACK2MISS, 1 );
|
||||
break;
|
||||
case 2:
|
||||
gEngfuncs.pEventAPI->EV_WeaponAnimation( CROWBAR_ATTACK3MISS, 1 );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
//======================
|
||||
// CROWBAR END
|
||||
//======================
|
||||
|
||||
//======================
|
||||
// CROSSBOW START
|
||||
//======================
|
||||
enum crossbow_e
|
||||
{
|
||||
CROSSBOW_IDLE1 = 0, // full
|
||||
CROSSBOW_IDLE2, // empty
|
||||
CROSSBOW_FIDGET1, // full
|
||||
CROSSBOW_FIDGET2, // empty
|
||||
CROSSBOW_FIRE1, // full
|
||||
CROSSBOW_FIRE2, // reload
|
||||
CROSSBOW_FIRE3, // empty
|
||||
CROSSBOW_RELOAD, // from empty
|
||||
CROSSBOW_DRAW1, // full
|
||||
CROSSBOW_DRAW2, // empty
|
||||
CROSSBOW_HOLSTER1, // full
|
||||
CROSSBOW_HOLSTER2 // empty
|
||||
};
|
||||
|
||||
//=====================
|
||||
// EV_BoltCallback
|
||||
// This function is used to correct the origin and angles
|
||||
// of the bolt, so it looks like it's stuck on the wall.
|
||||
//=====================
|
||||
void EV_BoltCallback( struct tempent_s *ent, float frametime, float currenttime )
|
||||
{
|
||||
ent->entity.origin = ent->entity.baseline.vuser1;
|
||||
ent->entity.angles = ent->entity.baseline.vuser2;
|
||||
}
|
||||
|
||||
void EV_FireCrossbow2( event_args_t *args )
|
||||
{
|
||||
vec3_t vecSrc, vecEnd;
|
||||
vec3_t up, right, forward;
|
||||
pmtrace_t tr;
|
||||
|
||||
int idx;
|
||||
vec3_t origin;
|
||||
vec3_t angles;
|
||||
vec3_t velocity;
|
||||
|
||||
idx = args->entindex;
|
||||
VectorCopy( args->origin, origin );
|
||||
VectorCopy( args->angles, angles );
|
||||
|
||||
VectorCopy( args->velocity, velocity );
|
||||
|
||||
AngleVectors( angles, forward, right, up );
|
||||
|
||||
EV_GetGunPosition( args, vecSrc, origin );
|
||||
|
||||
VectorMA( vecSrc, 8192, forward, vecEnd );
|
||||
|
||||
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/xbow_fire1.wav", 1, ATTN_NORM, 0, 93 + gEngfuncs.pfnRandomLong( 0, 0xF ) );
|
||||
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_ITEM, "weapons/xbow_reload1.wav", gEngfuncs.pfnRandomFloat( 0.95, 1.0 ), ATTN_NORM, 0, 93 + gEngfuncs.pfnRandomLong( 0, 0xF ) );
|
||||
|
||||
if( EV_IsLocal( idx ) )
|
||||
{
|
||||
if( args->iparam1 )
|
||||
gEngfuncs.pEventAPI->EV_WeaponAnimation( CROSSBOW_FIRE1, 1 );
|
||||
else if( args->iparam2 )
|
||||
gEngfuncs.pEventAPI->EV_WeaponAnimation( CROSSBOW_FIRE3, 1 );
|
||||
}
|
||||
|
||||
// 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 );
|
||||
|
||||
//We hit something
|
||||
if( tr.fraction < 1.0 )
|
||||
{
|
||||
physent_t *pe = gEngfuncs.pEventAPI->EV_GetPhysent( tr.ent );
|
||||
|
||||
//Not the world, let's assume we hit something organic ( dog, cat, uncle joe, etc ).
|
||||
if( pe->solid != SOLID_BSP )
|
||||
{
|
||||
switch( gEngfuncs.pfnRandomLong( 0, 1 ) )
|
||||
{
|
||||
case 0:
|
||||
gEngfuncs.pEventAPI->EV_PlaySound( idx, tr.endpos, CHAN_BODY, "weapons/xbow_hitbod1.wav", 1, ATTN_NORM, 0, PITCH_NORM );
|
||||
break;
|
||||
case 1:
|
||||
gEngfuncs.pEventAPI->EV_PlaySound( idx, tr.endpos, CHAN_BODY, "weapons/xbow_hitbod2.wav", 1, ATTN_NORM, 0, PITCH_NORM );
|
||||
break;
|
||||
}
|
||||
}
|
||||
//Stick to world but don't stick to glass, it might break and leave the bolt floating. It can still stick to other non-transparent breakables though.
|
||||
else if( pe->rendermode == kRenderNormal )
|
||||
{
|
||||
gEngfuncs.pEventAPI->EV_PlaySound( 0, tr.endpos, CHAN_BODY, "weapons/xbow_hit1.wav", gEngfuncs.pfnRandomFloat( 0.95, 1.0 ), ATTN_NORM, 0, PITCH_NORM );
|
||||
|
||||
//Not underwater, do some sparks...
|
||||
if( gEngfuncs.PM_PointContents( tr.endpos, NULL ) != CONTENTS_WATER )
|
||||
gEngfuncs.pEfxAPI->R_SparkShower( tr.endpos );
|
||||
|
||||
vec3_t vBoltAngles;
|
||||
int iModelIndex = gEngfuncs.pEventAPI->EV_FindModelIndex( "models/crossbow_bolt.mdl" );
|
||||
|
||||
VectorAngles( forward, vBoltAngles );
|
||||
|
||||
TEMPENTITY *bolt = gEngfuncs.pEfxAPI->R_TempModel( tr.endpos - forward * 10, Vector( 0, 0, 0 ), vBoltAngles , 5, iModelIndex, TE_BOUNCE_NULL );
|
||||
|
||||
if( bolt )
|
||||
{
|
||||
bolt->flags |= ( FTENT_CLIENTCUSTOM ); //So it calls the callback function.
|
||||
bolt->entity.baseline.vuser1 = tr.endpos - forward * 10; // Pull out a little bit
|
||||
bolt->entity.baseline.vuser2 = vBoltAngles; //Look forward!
|
||||
bolt->callback = EV_BoltCallback; //So we can set the angles and origin back. (Stick the bolt to the wall)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gEngfuncs.pEventAPI->EV_PopPMStates();
|
||||
}
|
||||
|
||||
//TODO: Fully predict the fliying bolt.
|
||||
void EV_FireCrossbow( event_args_t *args )
|
||||
{
|
||||
int idx;
|
||||
vec3_t origin;
|
||||
|
||||
idx = args->entindex;
|
||||
VectorCopy( args->origin, origin );
|
||||
|
||||
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/xbow_fire1.wav", 1, ATTN_NORM, 0, 93 + gEngfuncs.pfnRandomLong( 0, 0xF ) );
|
||||
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_ITEM, "weapons/xbow_reload1.wav", gEngfuncs.pfnRandomFloat( 0.95, 1.0 ), ATTN_NORM, 0, 93 + gEngfuncs.pfnRandomLong( 0, 0xF ) );
|
||||
|
||||
//Only play the weapon anims if I shot it.
|
||||
if( EV_IsLocal( idx ) )
|
||||
{
|
||||
if( args->iparam1 )
|
||||
gEngfuncs.pEventAPI->EV_WeaponAnimation( CROSSBOW_FIRE1, 1 );
|
||||
else if ( args->iparam2 )
|
||||
gEngfuncs.pEventAPI->EV_WeaponAnimation( CROSSBOW_FIRE3, 1 );
|
||||
|
||||
V_PunchAxis( 0, -2.0 );
|
||||
}
|
||||
}
|
||||
//======================
|
||||
// CROSSBOW END
|
||||
//======================
|
||||
|
||||
//======================
|
||||
// RPG START
|
||||
//======================
|
||||
enum rpg_e
|
||||
{
|
||||
RPG_IDLE = 0,
|
||||
RPG_FIDGET,
|
||||
RPG_RELOAD, // to reload
|
||||
RPG_FIRE2, // to empty
|
||||
RPG_HOLSTER1, // loaded
|
||||
RPG_DRAW1, // loaded
|
||||
RPG_HOLSTER2, // unloaded
|
||||
RPG_DRAW_UL, // unloaded
|
||||
RPG_IDLE_UL, // unloaded idle
|
||||
RPG_FIDGET_UL // unloaded fidget
|
||||
};
|
||||
|
||||
void EV_FireRpg( event_args_t *args )
|
||||
{
|
||||
int idx;
|
||||
vec3_t origin;
|
||||
|
||||
idx = args->entindex;
|
||||
VectorCopy( args->origin, origin );
|
||||
|
||||
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/rocketfire1.wav", 0.9, ATTN_NORM, 0, PITCH_NORM );
|
||||
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_ITEM, "weapons/glauncher.wav", 0.7, ATTN_NORM, 0, PITCH_NORM );
|
||||
|
||||
//Only play the weapon anims if I shot it.
|
||||
if( EV_IsLocal( idx ) )
|
||||
{
|
||||
gEngfuncs.pEventAPI->EV_WeaponAnimation( RPG_FIRE2, 1 );
|
||||
|
||||
V_PunchAxis( 0, -5.0 );
|
||||
}
|
||||
}
|
||||
//======================
|
||||
// RPG END
|
||||
//======================
|
||||
|
||||
//======================
|
||||
// EGON END
|
||||
//======================
|
||||
enum egon_e
|
||||
{
|
||||
EGON_IDLE1 = 0,
|
||||
EGON_FIDGET1,
|
||||
EGON_ALTFIREON,
|
||||
EGON_ALTFIRECYCLE,
|
||||
EGON_ALTFIREOFF,
|
||||
EGON_FIRE1,
|
||||
EGON_FIRE2,
|
||||
EGON_FIRE3,
|
||||
EGON_FIRE4,
|
||||
EGON_DRAW,
|
||||
EGON_HOLSTER
|
||||
};
|
||||
|
||||
int g_fireAnims1[] = { EGON_FIRE1, EGON_FIRE2, EGON_FIRE3, EGON_FIRE4 };
|
||||
int g_fireAnims2[] = { EGON_ALTFIRECYCLE };
|
||||
|
||||
enum EGON_FIRESTATE
|
||||
{
|
||||
FIRE_OFF,
|
||||
FIRE_CHARGE
|
||||
};
|
||||
|
||||
enum EGON_FIREMODE
|
||||
{
|
||||
FIRE_NARROW,
|
||||
FIRE_WIDE
|
||||
};
|
||||
|
||||
#define EGON_PRIMARY_VOLUME 450
|
||||
#define EGON_BEAM_SPRITE "sprites/xbeam1.spr"
|
||||
#define EGON_FLARE_SPRITE "sprites/XSpark1.spr"
|
||||
#define EGON_SOUND_OFF "weapons/egon_off1.wav"
|
||||
#define EGON_SOUND_RUN "weapons/egon_run3.wav"
|
||||
#define EGON_SOUND_STARTUP "weapons/egon_windup2.wav"
|
||||
|
||||
#define ARRAYSIZE(p) ( sizeof(p) /sizeof(p[0]) )
|
||||
|
||||
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 there is any sound playing already, kill it. - Solokiller
|
||||
// This is necessary because multiple sounds can play on the same channel at the same time.
|
||||
// In some cases, more than 1 run sound plays when the egon stops firing, in which case only the earliest entry in the list is stopped.
|
||||
// This ensures no more than 1 of those is ever active at the same time.
|
||||
gEngfuncs.pEventAPI->EV_StopSound( idx, CHAN_STATIC, EGON_SOUND_RUN );
|
||||
|
||||
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 );
|
||||
|
||||
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 );
|
||||
|
||||
if( EV_IsLocal( idx ) )
|
||||
{
|
||||
if( pBeam )
|
||||
{
|
||||
pBeam->die = 0.0;
|
||||
pBeam = NULL;
|
||||
}
|
||||
|
||||
if( pBeam2 )
|
||||
{
|
||||
pBeam2->die = 0.0;
|
||||
pBeam2 = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
//======================
|
||||
// EGON END
|
||||
//======================
|
||||
|
||||
//======================
|
||||
// HORNET START
|
||||
//======================
|
||||
enum hgun_e
|
||||
{
|
||||
HGUN_IDLE1 = 0,
|
||||
HGUN_FIDGETSWAY,
|
||||
HGUN_FIDGETSHAKE,
|
||||
HGUN_DOWN,
|
||||
HGUN_UP,
|
||||
HGUN_SHOOT
|
||||
};
|
||||
|
||||
void EV_HornetGunFire( event_args_t *args )
|
||||
{
|
||||
int idx; //, iFireMode;
|
||||
vec3_t origin, angles, vecSrc, forward, right, up;
|
||||
|
||||
idx = args->entindex;
|
||||
VectorCopy( args->origin, origin );
|
||||
VectorCopy( args->angles, angles );
|
||||
//iFireMode = args->iparam1;
|
||||
|
||||
//Only play the weapon anims if I shot it.
|
||||
if( EV_IsLocal( idx ) )
|
||||
{
|
||||
V_PunchAxis( 0, gEngfuncs.pfnRandomLong( 0, 2 ) );
|
||||
gEngfuncs.pEventAPI->EV_WeaponAnimation( HGUN_SHOOT, 1 );
|
||||
}
|
||||
|
||||
switch( gEngfuncs.pfnRandomLong( 0, 2 ) )
|
||||
{
|
||||
case 0:
|
||||
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "agrunt/ag_fire1.wav", 1, ATTN_NORM, 0, 100 );
|
||||
break;
|
||||
case 1:
|
||||
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "agrunt/ag_fire2.wav", 1, ATTN_NORM, 0, 100 );
|
||||
break;
|
||||
case 2:
|
||||
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "agrunt/ag_fire3.wav", 1, ATTN_NORM, 0, 100 );
|
||||
break;
|
||||
}
|
||||
}
|
||||
//======================
|
||||
// HORNET END
|
||||
//======================
|
||||
|
||||
//======================
|
||||
// TRIPMINE START
|
||||
//======================
|
||||
enum tripmine_e
|
||||
{
|
||||
TRIPMINE_IDLE1 = 0,
|
||||
TRIPMINE_IDLE2,
|
||||
TRIPMINE_ARM1,
|
||||
TRIPMINE_ARM2,
|
||||
TRIPMINE_FIDGET,
|
||||
TRIPMINE_HOLSTER,
|
||||
TRIPMINE_DRAW,
|
||||
TRIPMINE_WORLD,
|
||||
TRIPMINE_GROUND
|
||||
};
|
||||
|
||||
//We only check if it's possible to put a trip mine
|
||||
//and if it is, then we play the animation. Server still places it.
|
||||
void EV_TripmineFire( event_args_t *args )
|
||||
{
|
||||
int idx;
|
||||
vec3_t vecSrc, angles, view_ofs, forward;
|
||||
pmtrace_t tr;
|
||||
|
||||
idx = args->entindex;
|
||||
VectorCopy( args->origin, vecSrc );
|
||||
VectorCopy( args->angles, angles );
|
||||
|
||||
AngleVectors( angles, forward, NULL, NULL );
|
||||
|
||||
if( !EV_IsLocal ( idx ) )
|
||||
return;
|
||||
|
||||
// Grab predicted result for local player
|
||||
gEngfuncs.pEventAPI->EV_LocalPlayerViewheight( view_ofs );
|
||||
|
||||
vecSrc = vecSrc + view_ofs;
|
||||
|
||||
// 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, vecSrc + forward * 128, PM_NORMAL, -1, &tr );
|
||||
|
||||
//Hit something solid
|
||||
if( tr.fraction < 1.0 )
|
||||
gEngfuncs.pEventAPI->EV_WeaponAnimation ( TRIPMINE_DRAW, 0 );
|
||||
|
||||
gEngfuncs.pEventAPI->EV_PopPMStates();
|
||||
}
|
||||
//======================
|
||||
// TRIPMINE END
|
||||
//======================
|
||||
|
||||
//======================
|
||||
// SQUEAK START
|
||||
//======================
|
||||
enum squeak_e
|
||||
{
|
||||
SQUEAK_IDLE1 = 0,
|
||||
SQUEAK_FIDGETFIT,
|
||||
SQUEAK_FIDGETNIP,
|
||||
SQUEAK_DOWN,
|
||||
SQUEAK_UP,
|
||||
SQUEAK_THROW
|
||||
};
|
||||
|
||||
#define VEC_HULL_MIN Vector( -16, -16, -36 )
|
||||
#define VEC_DUCK_HULL_MIN Vector( -16, -16, -18 )
|
||||
|
||||
void EV_SnarkFire( event_args_t *args )
|
||||
{
|
||||
int idx;
|
||||
vec3_t vecSrc, angles, view_ofs, forward;
|
||||
pmtrace_t tr;
|
||||
|
||||
idx = args->entindex;
|
||||
VectorCopy( args->origin, vecSrc );
|
||||
VectorCopy( args->angles, angles );
|
||||
|
||||
AngleVectors( angles, forward, NULL, NULL );
|
||||
|
||||
if( !EV_IsLocal ( idx ) )
|
||||
return;
|
||||
|
||||
if( args->ducking )
|
||||
vecSrc = vecSrc - ( VEC_HULL_MIN - VEC_DUCK_HULL_MIN );
|
||||
|
||||
// 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 + forward * 20, vecSrc + forward * 64, PM_NORMAL, -1, &tr );
|
||||
|
||||
//Find space to drop the thing.
|
||||
if( tr.allsolid == 0 && tr.startsolid == 0 && tr.fraction > 0.25 )
|
||||
gEngfuncs.pEventAPI->EV_WeaponAnimation( SQUEAK_THROW, 0 );
|
||||
|
||||
gEngfuncs.pEventAPI->EV_PopPMStates();
|
||||
}
|
||||
//======================
|
||||
// SQUEAK END
|
||||
//======================
|
||||
|
||||
void EV_TrainPitchAdjust( event_args_t *args )
|
||||
{
|
||||
int idx;
|
||||
|
@ -1899,7 +1286,8 @@ enum m41a_e
|
|||
M41A_DEPLOY,
|
||||
M41A_FIRE1,
|
||||
M41A_FIRE2,
|
||||
//M41A_FIRE3,
|
||||
M41A_FIRE3,
|
||||
M41A_HOLSTER
|
||||
};
|
||||
|
||||
void EV_FireM41A( event_args_t *args )
|
||||
|
@ -1929,7 +1317,7 @@ void EV_FireM41A( event_args_t *args )
|
|||
{
|
||||
// Add muzzle flash to current weapon model
|
||||
EV_MuzzleFlash();
|
||||
gEngfuncs.pEventAPI->EV_WeaponAnimation( M41A_FIRE1 + gEngfuncs.pfnRandomLong( 0, 1 ), 2 );
|
||||
gEngfuncs.pEventAPI->EV_WeaponAnimation( M41A_FIRE1 + gEngfuncs.pfnRandomLong( 0, 2 ), 2 );
|
||||
|
||||
V_PunchAxis( 0, gEngfuncs.pfnRandomFloat( -2, 2 ) );
|
||||
}
|
||||
|
@ -1938,15 +1326,7 @@ void EV_FireM41A( event_args_t *args )
|
|||
|
||||
EV_EjectBrass( ShellOrigin, ShellVelocity, angles[YAW], shell, TE_BOUNCE_SHELL );
|
||||
|
||||
switch( gEngfuncs.pfnRandomLong( 0, 1 ) )
|
||||
{
|
||||
case 0:
|
||||
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/m41ahks1.wav", 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ) );
|
||||
break;
|
||||
case 1:
|
||||
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/m41ahks2.wav", 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ) );
|
||||
break;
|
||||
}
|
||||
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/m41ahks1.wav", 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ) );
|
||||
|
||||
EV_GetGunPosition( args, vecSrc, origin );
|
||||
VectorCopy( forward, vecAiming );
|
||||
|
|
|
@ -231,7 +231,7 @@ int CHudHealth::Draw( float flTime )
|
|||
|
||||
int iHeight = gHUD.m_iFontHeight;
|
||||
int iWidth = HealthWidth / 10;
|
||||
FillRGBA( x, y, iWidth, iHeight, 255, 160, 0, a );
|
||||
FillRGBA( x, y, iWidth, iHeight, r, g, b, a );
|
||||
}
|
||||
|
||||
DrawDamage( flTime );
|
||||
|
|
|
@ -96,7 +96,7 @@ void CGrenade::Explode( TraceResult *, int ) { }
|
|||
void CGrenade::Killed( entvars_t *, int ) { }
|
||||
void CGrenade::Spawn( void ) { }
|
||||
CGrenade *CGrenade::ShootTimed( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity, float time ){ return 0; }
|
||||
CGrenade *CGrenade::ShootContact( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity ){ return 0; }
|
||||
CGrenade *CGrenade::ShootContact( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity, float flDmg ){ return 0; }
|
||||
void CGrenade::DetonateUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ){ }
|
||||
|
||||
void UTIL_Remove( CBaseEntity *pEntity ){ }
|
||||
|
|
|
@ -25,19 +25,9 @@ void EV_FireGlock2( struct event_args_s *args );
|
|||
void EV_FireShotGunSingle( struct event_args_s *args );
|
||||
void EV_FireShotGunDouble( struct event_args_s *args );
|
||||
void EV_FireMP5( struct event_args_s *args );
|
||||
void EV_FireMP52( struct event_args_s *args );
|
||||
void EV_FirePython( struct event_args_s *args );
|
||||
void EV_FireGauss( struct event_args_s *args );
|
||||
void EV_SpinGauss( struct event_args_s *args );
|
||||
void EV_Crowbar( struct event_args_s *args );
|
||||
void EV_FireCrossbow( struct event_args_s *args );
|
||||
void EV_FireCrossbow2( struct event_args_s *args );
|
||||
void EV_FireRpg( struct event_args_s *args );
|
||||
void EV_EgonFire( struct event_args_s *args );
|
||||
void EV_EgonStop( struct event_args_s *args );
|
||||
void EV_HornetGunFire( struct event_args_s *args );
|
||||
void EV_TripmineFire( struct event_args_s *args );
|
||||
void EV_SnarkFire( struct event_args_s *args );
|
||||
|
||||
void EV_TrainPitchAdjust( struct event_args_s *args );
|
||||
|
||||
|
@ -68,20 +58,10 @@ void Game_HookEvents( void )
|
|||
gEngfuncs.pfnHookEvent( "events/shotgun1.sc", EV_FireShotGunSingle );
|
||||
gEngfuncs.pfnHookEvent( "events/shotgun2.sc", EV_FireShotGunDouble );
|
||||
gEngfuncs.pfnHookEvent( "events/mp5.sc", EV_FireMP5 );
|
||||
gEngfuncs.pfnHookEvent( "events/mp52.sc", EV_FireMP52 );
|
||||
gEngfuncs.pfnHookEvent( "events/python.sc", EV_FirePython );
|
||||
gEngfuncs.pfnHookEvent( "events/gauss.sc", EV_FireGauss );
|
||||
gEngfuncs.pfnHookEvent( "events/gaussspin.sc", EV_SpinGauss );
|
||||
gEngfuncs.pfnHookEvent( "events/train.sc", EV_TrainPitchAdjust );
|
||||
gEngfuncs.pfnHookEvent( "events/crowbar.sc", EV_Crowbar );
|
||||
gEngfuncs.pfnHookEvent( "events/crossbow1.sc", EV_FireCrossbow );
|
||||
gEngfuncs.pfnHookEvent( "events/crossbow2.sc", EV_FireCrossbow2 );
|
||||
gEngfuncs.pfnHookEvent( "events/rpg.sc", EV_FireRpg );
|
||||
gEngfuncs.pfnHookEvent( "events/egon_fire.sc", EV_EgonFire );
|
||||
gEngfuncs.pfnHookEvent( "events/egon_stop.sc", EV_EgonStop );
|
||||
gEngfuncs.pfnHookEvent( "events/firehornet.sc", EV_HornetGunFire );
|
||||
gEngfuncs.pfnHookEvent( "events/tripfire.sc", EV_TripmineFire );
|
||||
gEngfuncs.pfnHookEvent( "events/snarkfire.sc", EV_SnarkFire );
|
||||
//begin Alex
|
||||
gEngfuncs.pfnHookEvent( "events/m41a.sc", EV_FireM41A );
|
||||
gEngfuncs.pfnHookEvent( "events/beretta1.sc", EV_FireBeretta1 );
|
||||
|
|
|
@ -27,54 +27,10 @@
|
|||
#include "entity_types.h"
|
||||
#include "r_efx.h"
|
||||
|
||||
extern BEAM *pBeam;
|
||||
extern BEAM *pBeam2;
|
||||
void HUD_GetLastOrg( float *org );
|
||||
|
||||
void UpdateBeams( void )
|
||||
{
|
||||
vec3_t forward, vecSrc, vecEnd, origin, angles, right, up;
|
||||
vec3_t view_ofs;
|
||||
pmtrace_t tr;
|
||||
cl_entity_t *pthisplayer = gEngfuncs.GetLocalPlayer();
|
||||
int idx = pthisplayer->index;
|
||||
|
||||
// Get our exact viewangles from engine
|
||||
gEngfuncs.GetViewAngles( (float *)angles );
|
||||
|
||||
// Determine our last predicted origin
|
||||
HUD_GetLastOrg( (float *)&origin );
|
||||
|
||||
AngleVectors( angles, forward, right, up );
|
||||
|
||||
VectorCopy( origin, vecSrc );
|
||||
|
||||
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();
|
||||
|
||||
if( pBeam )
|
||||
{
|
||||
pBeam->target = tr.endpos;
|
||||
pBeam->die = gEngfuncs.GetClientTime() + 0.1; // We keep it alive just a little bit forward in the future, just in case.
|
||||
}
|
||||
|
||||
if( pBeam2 )
|
||||
{
|
||||
pBeam2->target = tr.endpos;
|
||||
pBeam2->die = gEngfuncs.GetClientTime() + 0.1; // We keep it alive just a little bit forward in the future, just in case.
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -86,6 +42,4 @@ Add game specific, client-side objects here
|
|||
*/
|
||||
void Game_AddObjects( void )
|
||||
{
|
||||
if( pBeam && pBeam2 )
|
||||
UpdateBeams();
|
||||
}
|
||||
|
|
|
@ -52,28 +52,6 @@ int g_irunninggausspred = 0;
|
|||
|
||||
vec3_t previousorigin;
|
||||
|
||||
// HLDM Weapon placeholder entities.
|
||||
CGlock g_Glock;
|
||||
CCrowbar g_Crowbar;
|
||||
CPython g_Python;
|
||||
CMP5 g_Mp5;
|
||||
CCrossbow g_Crossbow;
|
||||
CShotgun g_Shotgun;
|
||||
CRpg g_Rpg;
|
||||
CGauss g_Gauss;
|
||||
CEgon g_Egon;
|
||||
CHgun g_HGun;
|
||||
CHandGrenade g_HandGren;
|
||||
CSatchel g_Satchel;
|
||||
CTripmine g_Tripmine;
|
||||
CSqueak g_Snark;
|
||||
//begin Alex
|
||||
CBeretta g_Beretta;
|
||||
CM41A g_M41A;
|
||||
CPoolstick g_Poolstick;
|
||||
CToad g_Toad;
|
||||
//end Alex
|
||||
|
||||
/*
|
||||
======================
|
||||
AlertMessage
|
||||
|
@ -606,28 +584,6 @@ void HUD_InitClientWeapons( void )
|
|||
|
||||
// Allocate a slot for the local player
|
||||
HUD_PrepEntity( &player, NULL );
|
||||
|
||||
// Allocate slot(s) for each weapon that we are going to be predicting
|
||||
HUD_PrepEntity( &g_Glock, &player );
|
||||
HUD_PrepEntity( &g_Crowbar, &player );
|
||||
HUD_PrepEntity( &g_Python, &player );
|
||||
HUD_PrepEntity( &g_Mp5, &player );
|
||||
HUD_PrepEntity( &g_Crossbow, &player );
|
||||
HUD_PrepEntity( &g_Shotgun, &player );
|
||||
HUD_PrepEntity( &g_Rpg, &player );
|
||||
HUD_PrepEntity( &g_Gauss, &player );
|
||||
HUD_PrepEntity( &g_Egon, &player );
|
||||
HUD_PrepEntity( &g_HGun, &player );
|
||||
HUD_PrepEntity( &g_HandGren, &player );
|
||||
HUD_PrepEntity( &g_Satchel, &player );
|
||||
HUD_PrepEntity( &g_Tripmine, &player );
|
||||
HUD_PrepEntity( &g_Snark, &player );
|
||||
//begin Alex
|
||||
HUD_PrepEntity( &g_M41A, &player );
|
||||
HUD_PrepEntity( &g_Beretta, &player );
|
||||
HUD_PrepEntity( &g_Toad, &player );
|
||||
HUD_PrepEntity( &g_Poolstick, &player );
|
||||
//end Alex
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -687,68 +643,6 @@ void HUD_WeaponsPostThink( local_state_s *from, local_state_s *to, usercmd_t *cm
|
|||
// Get current clock
|
||||
gpGlobals->time = time;
|
||||
|
||||
// Fill in data based on selected weapon
|
||||
// FIXME, make this a method in each weapon? where you pass in an entity_state_t *?
|
||||
switch( from->client.m_iId )
|
||||
{
|
||||
case WEAPON_CROWBAR:
|
||||
pWeapon = &g_Crowbar;
|
||||
break;
|
||||
case WEAPON_GLOCK:
|
||||
pWeapon = &g_Glock;
|
||||
break;
|
||||
case WEAPON_PYTHON:
|
||||
pWeapon = &g_Python;
|
||||
break;
|
||||
case WEAPON_MP5:
|
||||
pWeapon = &g_Mp5;
|
||||
break;
|
||||
case WEAPON_CROSSBOW:
|
||||
pWeapon = &g_Crossbow;
|
||||
break;
|
||||
case WEAPON_SHOTGUN:
|
||||
pWeapon = &g_Shotgun;
|
||||
break;
|
||||
case WEAPON_RPG:
|
||||
pWeapon = &g_Rpg;
|
||||
break;
|
||||
case WEAPON_GAUSS:
|
||||
pWeapon = &g_Gauss;
|
||||
break;
|
||||
case WEAPON_EGON:
|
||||
pWeapon = &g_Egon;
|
||||
break;
|
||||
case WEAPON_HORNETGUN:
|
||||
pWeapon = &g_HGun;
|
||||
break;
|
||||
case WEAPON_HANDGRENADE:
|
||||
pWeapon = &g_HandGren;
|
||||
break;
|
||||
case WEAPON_SATCHEL:
|
||||
pWeapon = &g_Satchel;
|
||||
break;
|
||||
case WEAPON_TRIPMINE:
|
||||
pWeapon = &g_Tripmine;
|
||||
break;
|
||||
case WEAPON_SNARK:
|
||||
pWeapon = &g_Snark;
|
||||
break;
|
||||
// begin Alex
|
||||
case WEAPON_M41A:
|
||||
pWeapon = &g_M41A;
|
||||
break;
|
||||
case WEAPON_BERETTA:
|
||||
pWeapon = &g_Beretta;
|
||||
break;
|
||||
case WEAPON_TOAD:
|
||||
pWeapon = &g_Toad;
|
||||
break;
|
||||
case WEAPON_POOLSTICK:
|
||||
pWeapon = &g_Poolstick;
|
||||
break;
|
||||
// end Alex
|
||||
}
|
||||
|
||||
// Store pointer to our destination entity_state_t so we can get our origin, etc. from it
|
||||
// for setting up events on the client
|
||||
g_finalstate = to;
|
||||
|
@ -792,11 +686,6 @@ void HUD_WeaponsPostThink( local_state_s *from, local_state_s *to, usercmd_t *cm
|
|||
pCurrent->m_flNextSecondaryAttack = pfrom->m_flNextSecondaryAttack;
|
||||
pCurrent->m_flTimeWeaponIdle = pfrom->m_flTimeWeaponIdle;
|
||||
pCurrent->pev->fuser1 = pfrom->fuser1;
|
||||
pCurrent->m_flStartThrow = pfrom->fuser2;
|
||||
pCurrent->m_flReleaseThrow = pfrom->fuser3;
|
||||
pCurrent->m_chargeReady = pfrom->iuser1;
|
||||
pCurrent->m_fInAttack = pfrom->iuser2;
|
||||
pCurrent->m_fireState = pfrom->iuser3;
|
||||
|
||||
pCurrent->m_iSecondaryAmmoType = (int)from->client.vuser3[2];
|
||||
pCurrent->m_iPrimaryAmmoType = (int)from->client.vuser4[0];
|
||||
|
@ -835,15 +724,6 @@ void HUD_WeaponsPostThink( local_state_s *from, local_state_s *to, usercmd_t *cm
|
|||
player.m_flNextAmmoBurn = from->client.fuser2;
|
||||
player.m_flAmmoStartCharge = from->client.fuser3;
|
||||
|
||||
//Stores all our ammo info, so the client side weapons can use them.
|
||||
player.ammo_9mm = (int)from->client.vuser1[0];
|
||||
player.ammo_357 = (int)from->client.vuser1[1];
|
||||
player.ammo_argrens = (int)from->client.vuser1[2];
|
||||
player.ammo_bolts = (int)from->client.ammo_nails; //is an int anyways...
|
||||
player.ammo_buckshot = (int)from->client.ammo_shells;
|
||||
player.ammo_uranium = (int)from->client.ammo_cells;
|
||||
player.ammo_hornets = (int)from->client.vuser2[0];
|
||||
player.ammo_rockets = (int)from->client.ammo_rockets;
|
||||
|
||||
// Point to current weapon object
|
||||
if( from->client.m_iId )
|
||||
|
@ -851,12 +731,6 @@ void HUD_WeaponsPostThink( local_state_s *from, local_state_s *to, usercmd_t *cm
|
|||
player.m_pActiveItem = g_pWpns[from->client.m_iId];
|
||||
}
|
||||
|
||||
if( player.m_pActiveItem->m_iId == WEAPON_RPG )
|
||||
{
|
||||
( (CRpg *)player.m_pActiveItem )->m_fSpotActive = (int)from->client.vuser2[1];
|
||||
( (CRpg *)player.m_pActiveItem )->m_cActiveRockets = (int)from->client.vuser2[2];
|
||||
}
|
||||
|
||||
// Don't go firing anything if we have died.
|
||||
// Or if we don't have a weapon model deployed
|
||||
if( ( player.pev->deadflag != ( DEAD_DISCARDBODY + 1 ) ) &&
|
||||
|
@ -908,37 +782,12 @@ void HUD_WeaponsPostThink( local_state_s *from, local_state_s *to, usercmd_t *cm
|
|||
to->client.fuser3 = player.m_flAmmoStartCharge;
|
||||
to->client.maxspeed = player.pev->maxspeed;
|
||||
|
||||
//HL Weapons
|
||||
to->client.vuser1[0] = player.ammo_9mm;
|
||||
to->client.vuser1[1] = player.ammo_357;
|
||||
to->client.vuser1[2] = player.ammo_argrens;
|
||||
|
||||
to->client.ammo_nails = player.ammo_bolts;
|
||||
to->client.ammo_shells = player.ammo_buckshot;
|
||||
to->client.ammo_cells = player.ammo_uranium;
|
||||
to->client.vuser2[0] = player.ammo_hornets;
|
||||
to->client.ammo_rockets = player.ammo_rockets;
|
||||
|
||||
if( player.m_pActiveItem->m_iId == WEAPON_RPG )
|
||||
{
|
||||
from->client.vuser2[1] = ( (CRpg *)player.m_pActiveItem)->m_fSpotActive;
|
||||
from->client.vuser2[2] = ( (CRpg *)player.m_pActiveItem)->m_cActiveRockets;
|
||||
}
|
||||
|
||||
// Make sure that weapon animation matches what the game .dll is telling us
|
||||
// over the wire ( fixes some animation glitches )
|
||||
if( g_runfuncs && ( HUD_GetWeaponAnim() != to->client.weaponanim ) )
|
||||
{
|
||||
int body = 2;
|
||||
|
||||
//Pop the model to body 0.
|
||||
if( pWeapon == &g_Tripmine )
|
||||
body = 0;
|
||||
|
||||
//Show laser sight/scope combo
|
||||
if( pWeapon == &g_Python && bIsMultiplayer() )
|
||||
body = 1;
|
||||
|
||||
// Force a fixed anim down to viewmodel
|
||||
HUD_SendWeaponAnim( to->client.weaponanim, body, 1 );
|
||||
}
|
||||
|
@ -963,11 +812,6 @@ void HUD_WeaponsPostThink( local_state_s *from, local_state_s *to, usercmd_t *cm
|
|||
pto->m_flNextSecondaryAttack = pCurrent->m_flNextSecondaryAttack;
|
||||
pto->m_flTimeWeaponIdle = pCurrent->m_flTimeWeaponIdle;
|
||||
pto->fuser1 = pCurrent->pev->fuser1;
|
||||
pto->fuser2 = pCurrent->m_flStartThrow;
|
||||
pto->fuser3 = pCurrent->m_flReleaseThrow;
|
||||
pto->iuser1 = pCurrent->m_chargeReady;
|
||||
pto->iuser2 = pCurrent->m_fInAttack;
|
||||
pto->iuser3 = pCurrent->m_fireState;
|
||||
|
||||
// Decrement weapon counters, server does this at same time ( during post think, after doing everything else )
|
||||
pto->m_flNextReload -= cmd->msec / 1000.0;
|
||||
|
|
|
@ -514,8 +514,8 @@ int CHud::MsgFunc_SetFOV( const char *pszName, int iSize, void *pbuf )
|
|||
int def_fov = CVAR_GET_FLOAT( "default_fov" );
|
||||
|
||||
//Weapon prediction already takes care of changing the fog. ( g_lastFOV ).
|
||||
if( cl_lw && cl_lw->value )
|
||||
return 1;
|
||||
//if( cl_lw && cl_lw->value )
|
||||
// return 1;
|
||||
|
||||
g_lastFOV = newfov;
|
||||
|
||||
|
|
|
@ -22,9 +22,9 @@
|
|||
#pragma once
|
||||
#ifndef HUD_H
|
||||
#define HUD_H
|
||||
#define RGB_YELLOWISH 0x00555EFF //85,94,255 Blue Azure Sheep hud
|
||||
#define RGB_YELLOWISH 0x004040FF //64,64,255 Blue Azure Sheep hud
|
||||
#define RGB_REDISH 0x00FF1010 //255,160,0
|
||||
#define RGB_GREENISH 0x0000A000 //0,160,0
|
||||
#define RGB_GREENISH 0x008080FF //128,128,255
|
||||
|
||||
#include "wrect.h"
|
||||
#include "cl_dll.h"
|
||||
|
|
|
@ -23,8 +23,6 @@
|
|||
|
||||
#define MAX_CLIENTS 32
|
||||
|
||||
extern BEAM *pBeam;
|
||||
extern BEAM *pBeam2;
|
||||
|
||||
/// USER-DEFINED SERVER MESSAGE HANDLERS
|
||||
|
||||
|
@ -69,9 +67,6 @@ void CHud::MsgFunc_InitHUD( const char *pszName, int iSize, void *pbuf )
|
|||
pList->p->InitHUDData();
|
||||
pList = pList->pNext;
|
||||
}
|
||||
|
||||
//Probably not a good place to put this.
|
||||
pBeam = pBeam2 = NULL;
|
||||
}
|
||||
|
||||
int CHud::MsgFunc_GameMode( const char *pszName, int iSize, void *pbuf )
|
||||
|
|
|
@ -13,7 +13,7 @@ ifeq ($(TARGET_ARCH_ABI),armeabi-v7a-hard)
|
|||
LOCAL_MODULE_FILENAME = libserver_hardfp
|
||||
endif
|
||||
|
||||
LOCAL_CFLAGS += -D_LINUX -DCLIENT_WEAPONS -Dstricmp=strcasecmp -Dstrnicmp=strncasecmp -D_snprintf=snprintf \
|
||||
LOCAL_CFLAGS += -D_LINUX -Dstricmp=strcasecmp -Dstrnicmp=strncasecmp -D_snprintf=snprintf \
|
||||
-fno-exceptions -DNO_VOICEGAMEMGR -w
|
||||
|
||||
LOCAL_CPPFLAGS := $(LOCAL_CFLAGS)
|
||||
|
@ -126,6 +126,24 @@ LOCAL_SRC_FILES := agrunt.cpp airtank.cpp \
|
|||
world.cpp \
|
||||
xen.cpp \
|
||||
zombie.cpp \
|
||||
asheep/panther.cpp \
|
||||
asheep/archer.cpp \
|
||||
asheep/barneyglock.cpp \
|
||||
asheep/barneyhg.cpp \
|
||||
asheep/barneymp5.cpp \
|
||||
asheep/barneyshotgun.cpp \
|
||||
asheep/barniel.cpp \
|
||||
asheep/beretta.cpp \
|
||||
asheep/bodypart.cpp \
|
||||
asheep/garbage.cpp \
|
||||
asheep/gordonnadrian.cpp \
|
||||
asheep/kate.cpp \
|
||||
asheep/kmedkit.cpp \
|
||||
asheep/m41a.cpp \
|
||||
asheep/poolstick.cpp \
|
||||
asheep/spforce.cpp \
|
||||
asheep/terror.cpp \
|
||||
asheep/toad.cpp \
|
||||
../pm_shared/pm_debug.c \
|
||||
../pm_shared/pm_math.c \
|
||||
../pm_shared/pm_shared.c
|
||||
|
|
|
@ -25,7 +25,7 @@ project (SVDLL)
|
|||
|
||||
set (SVDLL_LIBRARY server)
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_LINUX -DCLIENT_WEAPONS -Dstricmp=strcasecmp -Dstrnicmp=strncasecmp -D_snprintf=snprintf -D_vsnprintf=vsnprintf -fno-exceptions -w")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_LINUX -Dstricmp=strcasecmp -Dstrnicmp=strncasecmp -D_snprintf=snprintf -D_vsnprintf=vsnprintf -fno-exceptions -w")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS}")
|
||||
|
||||
set (SVDLL_SOURCES
|
||||
|
@ -128,14 +128,19 @@ set (SVDLL_SOURCES
|
|||
world.cpp
|
||||
xen.cpp
|
||||
zombie.cpp
|
||||
asheep/adrian.cpp
|
||||
asheep/alienpanther.cpp
|
||||
asheep/panther.cpp
|
||||
asheep/archer.cpp
|
||||
asheep/barneyglock.cpp
|
||||
asheep/barneyhg.cpp
|
||||
asheep/barneymp5.cpp
|
||||
asheep/barneyshotgun.cpp
|
||||
asheep/barniel.cpp
|
||||
asheep/beretta.cpp
|
||||
asheep/gordon.cpp
|
||||
asheep/hevbarn.cpp
|
||||
asheep/bodypart.cpp
|
||||
asheep/garbage.cpp
|
||||
asheep/gordonnadrian.cpp
|
||||
asheep/kate.cpp
|
||||
asheep/kmedkit.cpp
|
||||
asheep/m41a.cpp
|
||||
asheep/poolstick.cpp
|
||||
asheep/spforce.cpp
|
||||
|
|
|
@ -193,7 +193,7 @@ const char *CAGrunt::pAlertSounds[] =
|
|||
//=========================================================
|
||||
int CAGrunt::IRelationship( CBaseEntity *pTarget )
|
||||
{
|
||||
if( FClassnameIs( pTarget->pev, "monster_human_grunt" ) )
|
||||
if( FClassnameIs( pTarget->pev, "monster_human_grunt" ) || FClassnameIs( pTarget->pev, "monster_human_spforce" ) )
|
||||
{
|
||||
return R_NM;
|
||||
}
|
||||
|
@ -466,19 +466,6 @@ void CAGrunt::HandleAnimEvent( MonsterEvent_t *pEvent )
|
|||
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 )
|
||||
|
|
|
@ -167,7 +167,7 @@ void CApache::Precache( void )
|
|||
|
||||
PRECACHE_SOUND( "turret/tu_fire1.wav" );
|
||||
|
||||
PRECACHE_MODEL( "sprites/lgtning.spr" );
|
||||
// PRECACHE_MODEL( "sprites/lgtning.spr" );
|
||||
|
||||
m_iExplode = PRECACHE_MODEL( "sprites/fexplo.spr" );
|
||||
m_iBodyGibs = PRECACHE_MODEL( "models/metalplategibs_green.mdl" );
|
||||
|
|
|
@ -1,842 +0,0 @@
|
|||
/***
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
****/
|
||||
//=========================================================
|
||||
// monster template
|
||||
//=========================================================
|
||||
// UNDONE: Holster weapon?
|
||||
|
||||
#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 "weapons.h"
|
||||
#include "soundent.h"
|
||||
|
||||
//=========================================================
|
||||
// Monster's Anim Events Go Here
|
||||
//=========================================================
|
||||
// first flag is barney dying for scripted sequences?
|
||||
#define ADRIAN_AE_DRAW ( 2 )
|
||||
#define ADRIAN_AE_SHOOT ( 3 )
|
||||
#define ADRIAN_AE_HOLSTER ( 4 )
|
||||
|
||||
#define ADRIAN_BODY_GUNHOLSTERED 0
|
||||
#define ADRIAN_BODY_GUNDRAWN 1
|
||||
#define ADRIAN_BODY_GUNGONE 2
|
||||
|
||||
class CAdrian : public CTalkMonster
|
||||
{
|
||||
public:
|
||||
void Spawn( void );
|
||||
void Precache( void );
|
||||
void SetYawSpeed( void );
|
||||
int ISoundMask( void );
|
||||
void AdrianFirePistol( 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_adrian, CAdrian );
|
||||
|
||||
TYPEDESCRIPTION CAdrian::m_SaveData[] =
|
||||
{
|
||||
DEFINE_FIELD( CAdrian, m_fGunDrawn, FIELD_BOOLEAN ),
|
||||
DEFINE_FIELD( CAdrian, m_painTime, FIELD_TIME ),
|
||||
DEFINE_FIELD( CAdrian, m_checkAttackTime, FIELD_TIME ),
|
||||
DEFINE_FIELD( CAdrian, m_lastAttackCheck, FIELD_BOOLEAN ),
|
||||
DEFINE_FIELD( CAdrian, m_flPlayerDamage, FIELD_FLOAT ),
|
||||
};
|
||||
|
||||
IMPLEMENT_SAVERESTORE( CAdrian, CTalkMonster );
|
||||
|
||||
//=========================================================
|
||||
// AI Schedules Specific to this monster
|
||||
//=========================================================
|
||||
Task_t tlAdrFollow[] =
|
||||
{
|
||||
{ TASK_MOVE_TO_TARGET_RANGE,(float)128 }, // Move within 128 of target ent (client)
|
||||
{ TASK_SET_SCHEDULE, (float)SCHED_TARGET_FACE },
|
||||
};
|
||||
|
||||
Schedule_t slAdrFollow[] =
|
||||
{
|
||||
{
|
||||
tlAdrFollow,
|
||||
ARRAYSIZE ( tlAdrFollow ),
|
||||
bits_COND_NEW_ENEMY |
|
||||
bits_COND_LIGHT_DAMAGE |
|
||||
bits_COND_HEAVY_DAMAGE |
|
||||
bits_COND_HEAR_SOUND |
|
||||
bits_COND_PROVOKED,
|
||||
bits_SOUND_DANGER,
|
||||
"Follow"
|
||||
},
|
||||
};
|
||||
|
||||
//=========================================================
|
||||
// AdrianDraw- much better looking draw schedule for when
|
||||
// barney knows who he's gonna attack.
|
||||
//=========================================================
|
||||
Task_t tlAdrianEnemyDraw[] =
|
||||
{
|
||||
{ TASK_STOP_MOVING, 0 },
|
||||
{ TASK_FACE_ENEMY, 0 },
|
||||
{ TASK_PLAY_SEQUENCE_FACE_ENEMY, (float) ACT_ARM },
|
||||
};
|
||||
|
||||
Schedule_t slAdrianEnemyDraw[] =
|
||||
{
|
||||
{
|
||||
tlAdrianEnemyDraw,
|
||||
ARRAYSIZE ( tlAdrianEnemyDraw ),
|
||||
0,
|
||||
0,
|
||||
"Adrian Enemy Draw"
|
||||
}
|
||||
};
|
||||
|
||||
Task_t tlAdrFaceTarget[] =
|
||||
{
|
||||
{ TASK_SET_ACTIVITY, (float)ACT_IDLE },
|
||||
{ TASK_FACE_TARGET, (float)0 },
|
||||
{ TASK_SET_ACTIVITY, (float)ACT_IDLE },
|
||||
{ TASK_SET_SCHEDULE, (float)SCHED_TARGET_CHASE },
|
||||
};
|
||||
|
||||
Schedule_t slAdrFaceTarget[] =
|
||||
{
|
||||
{
|
||||
tlAdrFaceTarget,
|
||||
ARRAYSIZE ( tlAdrFaceTarget ),
|
||||
bits_COND_CLIENT_PUSH |
|
||||
bits_COND_NEW_ENEMY |
|
||||
bits_COND_LIGHT_DAMAGE |
|
||||
bits_COND_HEAVY_DAMAGE |
|
||||
bits_COND_HEAR_SOUND |
|
||||
bits_COND_PROVOKED,
|
||||
bits_SOUND_DANGER,
|
||||
"FaceTarget"
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
Task_t tlIdleAdrStand[] =
|
||||
{
|
||||
{ TASK_STOP_MOVING, 0 },
|
||||
{ TASK_SET_ACTIVITY, (float)ACT_IDLE },
|
||||
{ TASK_WAIT, (float)2 }, // repick IDLESTAND every two seconds.
|
||||
{ TASK_TLK_HEADRESET, (float)0 }, // reset head position
|
||||
};
|
||||
|
||||
Schedule_t slIdleAdrStand[] =
|
||||
{
|
||||
{
|
||||
tlIdleAdrStand,
|
||||
ARRAYSIZE ( tlIdleAdrStand ),
|
||||
bits_COND_NEW_ENEMY |
|
||||
bits_COND_LIGHT_DAMAGE |
|
||||
bits_COND_HEAVY_DAMAGE |
|
||||
bits_COND_HEAR_SOUND |
|
||||
bits_COND_SMELL |
|
||||
bits_COND_PROVOKED,
|
||||
|
||||
bits_SOUND_COMBAT |// sound flags - change these, and you'll break the talking code.
|
||||
//bits_SOUND_PLAYER |
|
||||
//bits_SOUND_WORLD |
|
||||
|
||||
bits_SOUND_DANGER |
|
||||
bits_SOUND_MEAT |// scents
|
||||
bits_SOUND_CARCASS |
|
||||
bits_SOUND_GARBAGE,
|
||||
"IdleStand"
|
||||
},
|
||||
};
|
||||
|
||||
DEFINE_CUSTOM_SCHEDULES( CAdrian )
|
||||
{
|
||||
slAdrFollow,
|
||||
slAdrianEnemyDraw,
|
||||
slAdrFaceTarget,
|
||||
slIdleAdrStand,
|
||||
};
|
||||
|
||||
|
||||
IMPLEMENT_CUSTOM_SCHEDULES( CAdrian, CTalkMonster );
|
||||
|
||||
void CAdrian :: StartTask( Task_t *pTask )
|
||||
{
|
||||
CTalkMonster::StartTask( pTask );
|
||||
}
|
||||
|
||||
void CAdrian :: RunTask( Task_t *pTask )
|
||||
{
|
||||
switch ( pTask->iTask )
|
||||
{
|
||||
case TASK_RANGE_ATTACK1:
|
||||
if (m_hEnemy != NULL && (m_hEnemy->IsPlayer()))
|
||||
{
|
||||
pev->framerate = 1.5;
|
||||
}
|
||||
CTalkMonster::RunTask( pTask );
|
||||
break;
|
||||
default:
|
||||
CTalkMonster::RunTask( pTask );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//=========================================================
|
||||
// ISoundMask - returns a bit mask indicating which types
|
||||
// of sounds this monster regards.
|
||||
//=========================================================
|
||||
int CAdrian :: ISoundMask ( void)
|
||||
{
|
||||
return bits_SOUND_WORLD |
|
||||
bits_SOUND_COMBAT |
|
||||
bits_SOUND_CARCASS |
|
||||
bits_SOUND_MEAT |
|
||||
bits_SOUND_GARBAGE |
|
||||
bits_SOUND_DANGER |
|
||||
bits_SOUND_PLAYER;
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// Classify - indicates this monster's place in the
|
||||
// relationship table.
|
||||
//=========================================================
|
||||
int CAdrian :: Classify ( void )
|
||||
{
|
||||
return CLASS_PLAYER_ALLY;
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// ALertSound - barney says "Freeze!"
|
||||
//=========================================================
|
||||
void CAdrian :: AlertSound( void )
|
||||
{
|
||||
if ( m_hEnemy != NULL )
|
||||
{
|
||||
if ( FOkToSpeak() )
|
||||
{
|
||||
PlaySentence( "BA_ATTACK", RANDOM_FLOAT(2.8, 3.2), VOL_NORM, ATTN_IDLE );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
//=========================================================
|
||||
// SetYawSpeed - allows each sequence to have a different
|
||||
// turn rate associated with it.
|
||||
//=========================================================
|
||||
void CAdrian :: SetYawSpeed ( void )
|
||||
{
|
||||
int ys;
|
||||
|
||||
ys = 0;
|
||||
|
||||
switch ( m_Activity )
|
||||
{
|
||||
case ACT_IDLE:
|
||||
ys = 70;
|
||||
break;
|
||||
case ACT_WALK:
|
||||
ys = 70;
|
||||
break;
|
||||
case ACT_RUN:
|
||||
ys = 90;
|
||||
break;
|
||||
default:
|
||||
ys = 70;
|
||||
break;
|
||||
}
|
||||
|
||||
pev->yaw_speed = ys;
|
||||
}
|
||||
|
||||
|
||||
//=========================================================
|
||||
// CheckRangeAttack1
|
||||
//=========================================================
|
||||
BOOL CAdrian :: CheckRangeAttack1 ( float flDot, float flDist )
|
||||
{
|
||||
if ( flDist <= 1024 && flDot >= 0.5 )
|
||||
{
|
||||
if ( gpGlobals->time > m_checkAttackTime )
|
||||
{
|
||||
TraceResult tr;
|
||||
|
||||
Vector shootOrigin = pev->origin + Vector( 0, 0, 55 );
|
||||
CBaseEntity *pEnemy = m_hEnemy;
|
||||
Vector shootTarget = ( (pEnemy->BodyTarget( shootOrigin ) - pEnemy->pev->origin) + m_vecEnemyLKP );
|
||||
UTIL_TraceLine( shootOrigin, shootTarget, dont_ignore_monsters, ENT(pev), &tr );
|
||||
m_checkAttackTime = gpGlobals->time + 1;
|
||||
if ( tr.flFraction == 1.0 || (tr.pHit != NULL && CBaseEntity::Instance(tr.pHit) == pEnemy) )
|
||||
m_lastAttackCheck = TRUE;
|
||||
else
|
||||
m_lastAttackCheck = FALSE;
|
||||
m_checkAttackTime = gpGlobals->time + 1.5;
|
||||
}
|
||||
return m_lastAttackCheck;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
//=========================================================
|
||||
// AdrianFirePistol - shoots one round from the pistol at
|
||||
// the enemy barney is facing.
|
||||
//=========================================================
|
||||
void CAdrian :: AdrianFirePistol ( void )
|
||||
{
|
||||
Vector vecShootOrigin;
|
||||
|
||||
UTIL_MakeVectors(pev->angles);
|
||||
vecShootOrigin = pev->origin + Vector( 0, 0, 55 );
|
||||
Vector vecShootDir = ShootAtEnemy( vecShootOrigin );
|
||||
|
||||
Vector angDir = UTIL_VecToAngles( vecShootDir );
|
||||
SetBlending( 0, angDir.x );
|
||||
pev->effects = EF_MUZZLEFLASH;
|
||||
|
||||
FireBullets(1, vecShootOrigin, vecShootDir, VECTOR_CONE_2DEGREES, 1024, BULLET_MONSTER_9MM );
|
||||
|
||||
int pitchShift = RANDOM_LONG( 0, 20 );
|
||||
|
||||
// Only shift about half the time
|
||||
if ( pitchShift > 10 )
|
||||
pitchShift = 0;
|
||||
else
|
||||
pitchShift -= 5;
|
||||
EMIT_SOUND_DYN( ENT(pev), CHAN_WEAPON, "barney/ba_attack2.wav", 1, ATTN_NORM, 0, 100 + pitchShift );
|
||||
|
||||
CSoundEnt::InsertSound ( bits_SOUND_COMBAT, pev->origin, 384, 0.3 );
|
||||
|
||||
// UNDONE: Reload?
|
||||
m_cAmmoLoaded--;// take away a bullet!
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// HandleAnimEvent - catches the monster-specific messages
|
||||
// that occur when tagged animation frames are played.
|
||||
//
|
||||
// Returns number of events handled, 0 if none.
|
||||
//=========================================================
|
||||
void CAdrian :: HandleAnimEvent( MonsterEvent_t *pEvent )
|
||||
{
|
||||
switch( pEvent->event )
|
||||
{
|
||||
case ADRIAN_AE_SHOOT:
|
||||
AdrianFirePistol();
|
||||
break;
|
||||
|
||||
case ADRIAN_AE_DRAW:
|
||||
// barney's bodygroup switches here so he can pull gun from holster
|
||||
pev->body = ADRIAN_BODY_GUNDRAWN;
|
||||
m_fGunDrawn = TRUE;
|
||||
break;
|
||||
|
||||
case ADRIAN_AE_HOLSTER:
|
||||
// change bodygroup to replace gun in holster
|
||||
pev->body = ADRIAN_BODY_GUNHOLSTERED;
|
||||
m_fGunDrawn = FALSE;
|
||||
break;
|
||||
|
||||
default:
|
||||
CTalkMonster::HandleAnimEvent( pEvent );
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// Spawn
|
||||
//=========================================================
|
||||
void CAdrian :: Spawn()
|
||||
{
|
||||
Precache( );
|
||||
|
||||
SET_MODEL(ENT(pev), "models/adrian.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.barneyHealth;
|
||||
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 npc will notice player and say hello
|
||||
m_MonsterState = MONSTERSTATE_NONE;
|
||||
|
||||
pev->body = 0; // gun in holster
|
||||
m_fGunDrawn = FALSE;
|
||||
|
||||
m_afCapability = bits_CAP_HEAR | bits_CAP_TURN_HEAD | bits_CAP_DOORS_GROUP;
|
||||
|
||||
MonsterInit();
|
||||
SetUse( &CAdrian::FollowerUse );
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// Precache - precaches all resources this monster needs
|
||||
//=========================================================
|
||||
void CAdrian :: Precache()
|
||||
{
|
||||
PRECACHE_MODEL("models/adrian.mdl");
|
||||
|
||||
PRECACHE_SOUND("barney/ba_attack1.wav" );
|
||||
PRECACHE_SOUND("barney/ba_attack2.wav" );
|
||||
|
||||
PRECACHE_SOUND("barney/ba_pain1.wav");
|
||||
PRECACHE_SOUND("barney/ba_pain2.wav");
|
||||
PRECACHE_SOUND("barney/ba_pain3.wav");
|
||||
|
||||
PRECACHE_SOUND("barney/ba_die1.wav");
|
||||
PRECACHE_SOUND("barney/ba_die2.wav");
|
||||
PRECACHE_SOUND("barney/ba_die3.wav");
|
||||
PRECACHE_SOUND("barney/ba_duty.wav");
|
||||
PRECACHE_SOUND("barney/ba_post.wav");
|
||||
PRECACHE_SOUND("barney/goon.wav");
|
||||
|
||||
// every new barney must call this, otherwise
|
||||
// when a level is loaded, nobody will talk (time is reset to 0)
|
||||
TalkInit();
|
||||
CTalkMonster::Precache();
|
||||
}
|
||||
|
||||
// Init talk data
|
||||
void CAdrian :: TalkInit()
|
||||
{
|
||||
|
||||
CTalkMonster::TalkInit();
|
||||
|
||||
// scientists speach group names (group names are in sentences.txt)
|
||||
|
||||
m_szGrp[TLK_ANSWER] = "BA_ANSWER";
|
||||
m_szGrp[TLK_QUESTION] = "BA_QUESTION";
|
||||
m_szGrp[TLK_IDLE] = "BA_IDLE";
|
||||
m_szGrp[TLK_STARE] = "BA_STARE";
|
||||
m_szGrp[TLK_USE] = "BA_OK";
|
||||
m_szGrp[TLK_UNUSE] = "BA_WAIT";
|
||||
m_szGrp[TLK_STOP] = "BA_STOP";
|
||||
|
||||
m_szGrp[TLK_NOSHOOT] = "BA_SCARED";
|
||||
m_szGrp[TLK_HELLO] = "BA_HELLO";
|
||||
|
||||
m_szGrp[TLK_PLHURT1] = "!BA_CUREA";
|
||||
m_szGrp[TLK_PLHURT2] = "!BA_CUREB";
|
||||
m_szGrp[TLK_PLHURT3] = "!BA_CUREC";
|
||||
|
||||
m_szGrp[TLK_PHELLO] = NULL; //"BA_PHELLO"; // UNDONE
|
||||
m_szGrp[TLK_PIDLE] = NULL; //"BA_PIDLE"; // UNDONE
|
||||
m_szGrp[TLK_PQUESTION] = "BA_PQUEST"; // UNDONE
|
||||
|
||||
m_szGrp[TLK_SMELL] = "BA_SMELL";
|
||||
|
||||
m_szGrp[TLK_WOUND] = "BA_WOUND";
|
||||
m_szGrp[TLK_MORTAL] = "BA_MORTAL";
|
||||
|
||||
// get voice for head - just one barney voice for now
|
||||
m_voicePitch = 100;
|
||||
}
|
||||
|
||||
|
||||
static BOOL IsFacing( entvars_t *pevTest, const Vector &reference )
|
||||
{
|
||||
Vector vecDir = (reference - pevTest->origin);
|
||||
vecDir.z = 0;
|
||||
vecDir = vecDir.Normalize();
|
||||
Vector forward, angle;
|
||||
angle = pevTest->v_angle;
|
||||
angle.x = 0;
|
||||
UTIL_MakeVectorsPrivate( angle, forward, NULL, NULL );
|
||||
// He's facing me, he meant it
|
||||
if ( DotProduct( forward, vecDir ) > 0.96 ) // +/- 15 degrees or so
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
int CAdrian :: TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType)
|
||||
{
|
||||
// make sure friends talk about it if player hurts talkmonsters...
|
||||
int ret = CTalkMonster::TakeDamage(pevInflictor, pevAttacker, flDamage, bitsDamageType);
|
||||
if ( !IsAlive() || pev->deadflag == DEAD_DYING )
|
||||
return ret;
|
||||
|
||||
if ( m_MonsterState != MONSTERSTATE_PRONE && (pevAttacker->flags & FL_CLIENT) )
|
||||
{
|
||||
m_flPlayerDamage += flDamage;
|
||||
|
||||
// This is a heurstic to determine if the player intended to harm me
|
||||
// If I have an enemy, we can't establish intent (may just be crossfire)
|
||||
if ( m_hEnemy == NULL )
|
||||
{
|
||||
// If the player was facing directly at me, or I'm already suspicious, get mad
|
||||
if ( (m_afMemory & bits_MEMORY_SUSPICIOUS) || IsFacing( pevAttacker, pev->origin ) )
|
||||
{
|
||||
// Alright, now I'm pissed!
|
||||
PlaySentence( "BA_MAD", 4, VOL_NORM, ATTN_NORM );
|
||||
|
||||
Remember( bits_MEMORY_PROVOKED );
|
||||
StopFollowing( TRUE );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Hey, be careful with that
|
||||
PlaySentence( "BA_SHOT", 4, VOL_NORM, ATTN_NORM );
|
||||
Remember( bits_MEMORY_SUSPICIOUS );
|
||||
}
|
||||
}
|
||||
else if ( !(m_hEnemy->IsPlayer()) && pev->deadflag == DEAD_NO )
|
||||
{
|
||||
PlaySentence( "BA_SHOT", 4, VOL_NORM, ATTN_NORM );
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
//=========================================================
|
||||
// PainSound
|
||||
//=========================================================
|
||||
void CAdrian :: PainSound ( void )
|
||||
{
|
||||
if (gpGlobals->time < m_painTime)
|
||||
return;
|
||||
|
||||
m_painTime = gpGlobals->time + RANDOM_FLOAT(0.5, 0.75);
|
||||
|
||||
switch (RANDOM_LONG(0,2))
|
||||
{
|
||||
case 0: EMIT_SOUND_DYN( ENT(pev), CHAN_VOICE, "barney/ba_pain1.wav", 1, ATTN_NORM, 0, GetVoicePitch()); break;
|
||||
case 1: EMIT_SOUND_DYN( ENT(pev), CHAN_VOICE, "barney/ba_pain2.wav", 1, ATTN_NORM, 0, GetVoicePitch()); break;
|
||||
case 2: EMIT_SOUND_DYN( ENT(pev), CHAN_VOICE, "barney/ba_pain3.wav", 1, ATTN_NORM, 0, GetVoicePitch()); break;
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// DeathSound
|
||||
//=========================================================
|
||||
void CAdrian :: DeathSound ( void )
|
||||
{
|
||||
switch (RANDOM_LONG(0,2))
|
||||
{
|
||||
case 0: EMIT_SOUND_DYN( ENT(pev), CHAN_VOICE, "barney/ba_die1.wav", 1, ATTN_NORM, 0, GetVoicePitch()); break;
|
||||
case 1: EMIT_SOUND_DYN( ENT(pev), CHAN_VOICE, "barney/ba_die2.wav", 1, ATTN_NORM, 0, GetVoicePitch()); break;
|
||||
case 2: EMIT_SOUND_DYN( ENT(pev), CHAN_VOICE, "barney/ba_die3.wav", 1, ATTN_NORM, 0, GetVoicePitch()); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CAdrian::TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType)
|
||||
{
|
||||
switch( ptr->iHitgroup)
|
||||
{
|
||||
case HITGROUP_CHEST:
|
||||
case HITGROUP_STOMACH:
|
||||
if (bitsDamageType & (DMG_BULLET | DMG_SLASH | DMG_BLAST))
|
||||
{
|
||||
flDamage = flDamage / 2;
|
||||
}
|
||||
break;
|
||||
case 10:
|
||||
if (bitsDamageType & (DMG_BULLET | DMG_SLASH | DMG_CLUB))
|
||||
{
|
||||
flDamage -= 20;
|
||||
if (flDamage <= 0)
|
||||
{
|
||||
UTIL_Ricochet( ptr->vecEndPos, 1.0 );
|
||||
flDamage = 0.01;
|
||||
}
|
||||
}
|
||||
// always a head shot
|
||||
ptr->iHitgroup = HITGROUP_HEAD;
|
||||
break;
|
||||
}
|
||||
|
||||
CTalkMonster::TraceAttack( pevAttacker, flDamage, vecDir, ptr, bitsDamageType );
|
||||
}
|
||||
|
||||
|
||||
void CAdrian::Killed( entvars_t *pevAttacker, int iGib )
|
||||
{
|
||||
if ( pev->body < ADRIAN_BODY_GUNGONE )
|
||||
{// drop the gun!
|
||||
Vector vecGunPos;
|
||||
Vector vecGunAngles;
|
||||
|
||||
pev->body = ADRIAN_BODY_GUNGONE;
|
||||
|
||||
GetAttachment( 0, vecGunPos, vecGunAngles );
|
||||
|
||||
CBaseEntity *pGun = DropItem( "weapon_barney9mmhg", vecGunPos, vecGunAngles );
|
||||
}
|
||||
|
||||
SetUse( NULL );
|
||||
CTalkMonster::Killed( pevAttacker, iGib );
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// AI Schedules Specific to this monster
|
||||
//=========================================================
|
||||
|
||||
Schedule_t* CAdrian :: GetScheduleOfType ( int Type )
|
||||
{
|
||||
Schedule_t *psched;
|
||||
|
||||
switch( Type )
|
||||
{
|
||||
case SCHED_ARM_WEAPON:
|
||||
if ( m_hEnemy != NULL )
|
||||
{
|
||||
// face enemy, then draw.
|
||||
return slAdrianEnemyDraw;
|
||||
}
|
||||
break;
|
||||
|
||||
// Hook these to make a looping schedule
|
||||
case SCHED_TARGET_FACE:
|
||||
// call base class default so that barney will talk
|
||||
// when 'used'
|
||||
psched = CTalkMonster::GetScheduleOfType(Type);
|
||||
|
||||
if (psched == slIdleStand)
|
||||
return slAdrFaceTarget; // override this for different target face behavior
|
||||
else
|
||||
return psched;
|
||||
|
||||
case SCHED_TARGET_CHASE:
|
||||
return slAdrFollow;
|
||||
|
||||
case SCHED_IDLE_STAND:
|
||||
// call base class default so that scientist will talk
|
||||
// when standing during idle
|
||||
psched = CTalkMonster::GetScheduleOfType(Type);
|
||||
|
||||
if (psched == slIdleStand)
|
||||
{
|
||||
// just look straight ahead.
|
||||
return slIdleAdrStand;
|
||||
}
|
||||
else
|
||||
return psched;
|
||||
}
|
||||
|
||||
return CTalkMonster::GetScheduleOfType( Type );
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// GetSchedule - Decides which type of schedule best suits
|
||||
// the monster's current state and conditions. Then calls
|
||||
// monster's member function to get a pointer to a schedule
|
||||
// of the proper type.
|
||||
//=========================================================
|
||||
Schedule_t *CAdrian :: GetSchedule ( void )
|
||||
{
|
||||
if ( HasConditions( bits_COND_HEAR_SOUND ) )
|
||||
{
|
||||
CSound *pSound;
|
||||
pSound = PBestSound();
|
||||
|
||||
ASSERT( pSound != NULL );
|
||||
if ( pSound && (pSound->m_iType & bits_SOUND_DANGER) )
|
||||
return GetScheduleOfType( SCHED_TAKE_COVER_FROM_BEST_SOUND );
|
||||
}
|
||||
if ( HasConditions( bits_COND_ENEMY_DEAD ) && FOkToSpeak() )
|
||||
{
|
||||
PlaySentence( "BA_KILL", 4, VOL_NORM, ATTN_NORM );
|
||||
}
|
||||
|
||||
switch( m_MonsterState )
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
// always act surprized with a new enemy
|
||||
if ( HasConditions( bits_COND_NEW_ENEMY ) && HasConditions( bits_COND_LIGHT_DAMAGE) )
|
||||
return GetScheduleOfType( SCHED_SMALL_FLINCH );
|
||||
|
||||
// wait for one schedule to draw gun
|
||||
if (!m_fGunDrawn )
|
||||
return GetScheduleOfType( SCHED_ARM_WEAPON );
|
||||
|
||||
if ( HasConditions( bits_COND_HEAVY_DAMAGE ) )
|
||||
return GetScheduleOfType( SCHED_TAKE_COVER_FROM_ENEMY );
|
||||
}
|
||||
break;
|
||||
|
||||
case MONSTERSTATE_ALERT:
|
||||
case MONSTERSTATE_IDLE:
|
||||
if ( HasConditions(bits_COND_LIGHT_DAMAGE | bits_COND_HEAVY_DAMAGE))
|
||||
{
|
||||
// flinch if hurt
|
||||
return GetScheduleOfType( SCHED_SMALL_FLINCH );
|
||||
}
|
||||
|
||||
if ( m_hEnemy == NULL && IsFollowing() )
|
||||
{
|
||||
if ( !m_hTargetEnt->IsAlive() )
|
||||
{
|
||||
// UNDONE: Comment about the recently dead player here?
|
||||
StopFollowing( FALSE );
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( HasConditions( bits_COND_CLIENT_PUSH ) )
|
||||
{
|
||||
return GetScheduleOfType( SCHED_MOVE_AWAY_FOLLOW );
|
||||
}
|
||||
return GetScheduleOfType( SCHED_TARGET_FACE );
|
||||
}
|
||||
}
|
||||
|
||||
if ( HasConditions( bits_COND_CLIENT_PUSH ) )
|
||||
{
|
||||
return GetScheduleOfType( SCHED_MOVE_AWAY );
|
||||
}
|
||||
|
||||
// try to say something about smells
|
||||
TrySmellTalk();
|
||||
break;
|
||||
}
|
||||
|
||||
return CTalkMonster::GetSchedule();
|
||||
}
|
||||
|
||||
MONSTERSTATE CAdrian :: GetIdealState ( void )
|
||||
{
|
||||
return CTalkMonster::GetIdealState();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CAdrian::DeclineFollowing( void )
|
||||
{
|
||||
PlaySentence( "BA_POK", 2, VOL_NORM, ATTN_NORM );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//=========================================================
|
||||
// DEAD ADRIAN PROP
|
||||
//
|
||||
// Designer selects a pose in worldcraft, 0 through num_poses-1
|
||||
// this value is added to what is selected as the 'first dead pose'
|
||||
// among the monster's normal animations. All dead poses must
|
||||
// appear sequentially in the model file. Be sure and set
|
||||
// the m_iFirstPose properly!
|
||||
//
|
||||
//=========================================================
|
||||
class CDeadAdrian : public CBaseMonster
|
||||
{
|
||||
public:
|
||||
void Spawn( void );
|
||||
int Classify ( void ) { return CLASS_PLAYER_ALLY; }
|
||||
|
||||
void KeyValue( KeyValueData *pkvd );
|
||||
|
||||
int m_iPose;// which sequence to display -- temporary, don't need to save
|
||||
static char *m_szPoses[3];
|
||||
};
|
||||
|
||||
char *CDeadAdrian::m_szPoses[] = { "lying_on_back", "lying_on_side", "lying_on_stomach" };
|
||||
|
||||
void CDeadAdrian::KeyValue( KeyValueData *pkvd )
|
||||
{
|
||||
if (FStrEq(pkvd->szKeyName, "pose"))
|
||||
{
|
||||
m_iPose = atoi(pkvd->szValue);
|
||||
pkvd->fHandled = TRUE;
|
||||
}
|
||||
else
|
||||
CBaseMonster::KeyValue( pkvd );
|
||||
}
|
||||
|
||||
LINK_ENTITY_TO_CLASS( monster_adrian_dead, CDeadAdrian );
|
||||
|
||||
//=========================================================
|
||||
// ********** DeadAdrian SPAWN **********
|
||||
//=========================================================
|
||||
void CDeadAdrian :: Spawn( )
|
||||
{
|
||||
PRECACHE_MODEL("models/adrian.mdl");
|
||||
SET_MODEL(ENT(pev), "models/adrian.mdl");
|
||||
|
||||
pev->effects = 0;
|
||||
pev->yaw_speed = 8;
|
||||
pev->sequence = 0;
|
||||
m_bloodColor = BLOOD_COLOR_RED;
|
||||
|
||||
pev->sequence = LookupSequence( m_szPoses[m_iPose] );
|
||||
if (pev->sequence == -1)
|
||||
{
|
||||
ALERT ( at_console, "Dead barney with bad pose\n" );
|
||||
}
|
||||
// Corpses have less health
|
||||
pev->health = 8;//gSkillData.barneyHealth;
|
||||
|
||||
MonsterInitDead();
|
||||
}
|
|
@ -1,866 +0,0 @@
|
|||
/***
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
****/
|
||||
//=========================================================
|
||||
// Alien panther monster
|
||||
//=========================================================
|
||||
|
||||
#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"
|
||||
|
||||
extern DLL_GLOBAL int g_iSkillLevel;
|
||||
|
||||
//=========================================================
|
||||
// Monster's Anim Events Go Here
|
||||
//=========================================================
|
||||
#define APANTHER_AE_CLAW ( 1 )
|
||||
#define APANTHER_AE_CLAWRAKE ( 2 )
|
||||
#define APANTHER_AE_ZAP_POWERUP ( 3 )
|
||||
#define APANTHER_AE_ZAP_SHOOT ( 4 )
|
||||
#define APANTHER_AE_ZAP_DONE ( 5 )
|
||||
|
||||
#define APANTHER_MAX_BEAMS 8
|
||||
|
||||
class CAlienPanther : 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[APANTHER_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_panther, CAlienPanther );
|
||||
|
||||
|
||||
TYPEDESCRIPTION CAlienPanther::m_SaveData[] =
|
||||
{
|
||||
DEFINE_FIELD( CAlienPanther, m_iBravery, FIELD_INTEGER ),
|
||||
|
||||
DEFINE_ARRAY( CAlienPanther, m_pBeam, FIELD_CLASSPTR, APANTHER_MAX_BEAMS ),
|
||||
DEFINE_FIELD( CAlienPanther, m_iBeams, FIELD_INTEGER ),
|
||||
DEFINE_FIELD( CAlienPanther, m_flNextAttack, FIELD_TIME ),
|
||||
|
||||
DEFINE_FIELD( CAlienPanther, m_voicePitch, FIELD_INTEGER ),
|
||||
|
||||
DEFINE_FIELD( CAlienPanther, m_hDead, FIELD_EHANDLE ),
|
||||
|
||||
};
|
||||
|
||||
IMPLEMENT_SAVERESTORE( CAlienPanther, CSquadMonster );
|
||||
|
||||
|
||||
|
||||
|
||||
const char *CAlienPanther::pAttackHitSounds[] =
|
||||
{
|
||||
"panther/pclaw_strike1.wav",
|
||||
"panther/pclaw_strike2.wav",
|
||||
"panther/pclaw_strike3.wav",
|
||||
};
|
||||
|
||||
const char *CAlienPanther::pAttackMissSounds[] =
|
||||
{
|
||||
"panther/pclaw_miss1.wav",
|
||||
"panther/pclaw_miss2.wav",
|
||||
};
|
||||
|
||||
const char *CAlienPanther::pPainSounds[] =
|
||||
{
|
||||
"panther/p_pain1.wav",
|
||||
"panther/p_pain2.wav",
|
||||
};
|
||||
|
||||
const char *CAlienPanther::pDeathSounds[] =
|
||||
{
|
||||
"panther/p_die1.wav",
|
||||
"panther/p_die2.wav",
|
||||
};
|
||||
|
||||
//=========================================================
|
||||
// Classify - indicates this monster's place in the
|
||||
// relationship table.
|
||||
//=========================================================
|
||||
int CAlienPanther :: Classify ( void )
|
||||
{
|
||||
return CLASS_ALIEN_MILITARY;
|
||||
}
|
||||
|
||||
|
||||
int CAlienPanther::IRelationship( CBaseEntity *pTarget )
|
||||
{
|
||||
if ( (pTarget->IsPlayer()) )
|
||||
if ( (pev->spawnflags & SF_MONSTER_WAIT_UNTIL_PROVOKED ) && ! (m_afMemory & bits_MEMORY_PROVOKED ))
|
||||
return R_NO;
|
||||
return CBaseMonster::IRelationship( pTarget );
|
||||
}
|
||||
|
||||
|
||||
void CAlienPanther :: CallForHelp( char *szClassname, float flDist, EHANDLE hEnemy, Vector &vecLocation )
|
||||
{
|
||||
// ALERT( at_aiconsole, "help " );
|
||||
|
||||
// skip ones not on my netname
|
||||
if ( FStringNull( pev->netname ))
|
||||
return;
|
||||
|
||||
CBaseEntity *pEntity = NULL;
|
||||
|
||||
while ((pEntity = UTIL_FindEntityByString( pEntity, "netname", STRING( pev->netname ))) != NULL)
|
||||
{
|
||||
float d = (pev->origin - pEntity->pev->origin).Length();
|
||||
if (d < flDist)
|
||||
{
|
||||
CBaseMonster *pMonster = pEntity->MyMonsterPointer( );
|
||||
if (pMonster)
|
||||
{
|
||||
pMonster->m_afMemory |= bits_MEMORY_PROVOKED;
|
||||
pMonster->PushEnemy( hEnemy, vecLocation );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//=========================================================
|
||||
// ALertSound - scream
|
||||
//=========================================================
|
||||
void CAlienPanther :: AlertSound( void )
|
||||
{
|
||||
if ( m_hEnemy != NULL )
|
||||
{
|
||||
SENTENCEG_PlayRndSz(ENT(pev), "SLV_ALERT", 0.85, ATTN_NORM, 0, m_voicePitch);
|
||||
|
||||
CallForHelp( "monster_alien_panther", 512, m_hEnemy, m_vecEnemyLKP );
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// IdleSound
|
||||
//=========================================================
|
||||
void CAlienPanther :: IdleSound( void )
|
||||
{
|
||||
if (RANDOM_LONG( 0, 2 ) == 0)
|
||||
{
|
||||
SENTENCEG_PlayRndSz(ENT(pev), "P_IDLE", 0.85, ATTN_NORM, 0, m_voicePitch);
|
||||
}
|
||||
|
||||
#if 0
|
||||
int side = RANDOM_LONG( 0, 1 ) * 2 - 1;
|
||||
|
||||
ClearBeams( );
|
||||
ArmBeam( side );
|
||||
|
||||
UTIL_MakeAimVectors( pev->angles );
|
||||
Vector vecSrc = pev->origin + gpGlobals->v_right * 2 * side;
|
||||
MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, vecSrc );
|
||||
WRITE_BYTE(TE_DLIGHT);
|
||||
WRITE_COORD(vecSrc.x); // X
|
||||
WRITE_COORD(vecSrc.y); // Y
|
||||
WRITE_COORD(vecSrc.z); // Z
|
||||
WRITE_BYTE( 8 ); // radius * 0.1
|
||||
WRITE_BYTE( 255 ); // r
|
||||
WRITE_BYTE( 180 ); // g
|
||||
WRITE_BYTE( 96 ); // b
|
||||
WRITE_BYTE( 10 ); // time * 10
|
||||
WRITE_BYTE( 0 ); // decay * 0.1
|
||||
MESSAGE_END( );
|
||||
|
||||
EMIT_SOUND_DYN( ENT(pev), CHAN_WEAPON, "panther/p_zap1.wav", 1, ATTN_NORM, 0, 100 );
|
||||
#endif
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// PainSound
|
||||
//=========================================================
|
||||
void CAlienPanther :: PainSound( void )
|
||||
{
|
||||
if (RANDOM_LONG( 0, 2 ) == 0)
|
||||
{
|
||||
EMIT_SOUND_DYN ( ENT(pev), CHAN_WEAPON, pPainSounds[ RANDOM_LONG(0,ARRAYSIZE(pPainSounds)-1) ], 1.0, ATTN_NORM, 0, m_voicePitch );
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// DieSound
|
||||
//=========================================================
|
||||
|
||||
void CAlienPanther :: DeathSound( void )
|
||||
{
|
||||
EMIT_SOUND_DYN ( ENT(pev), CHAN_WEAPON, pDeathSounds[ RANDOM_LONG(0,ARRAYSIZE(pDeathSounds)-1) ], 1.0, ATTN_NORM, 0, m_voicePitch );
|
||||
}
|
||||
|
||||
|
||||
//=========================================================
|
||||
// ISoundMask - returns a bit mask indicating which types
|
||||
// of sounds this monster regards.
|
||||
//=========================================================
|
||||
int CAlienPanther :: ISoundMask ( void)
|
||||
{
|
||||
return bits_SOUND_WORLD |
|
||||
bits_SOUND_COMBAT |
|
||||
bits_SOUND_DANGER |
|
||||
bits_SOUND_PLAYER;
|
||||
}
|
||||
|
||||
|
||||
void CAlienPanther::Killed( entvars_t *pevAttacker, int iGib )
|
||||
{
|
||||
ClearBeams( );
|
||||
CSquadMonster::Killed( pevAttacker, iGib );
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// SetYawSpeed - allows each sequence to have a different
|
||||
// turn rate associated with it.
|
||||
//=========================================================
|
||||
void CAlienPanther :: SetYawSpeed ( void )
|
||||
{
|
||||
int ys;
|
||||
|
||||
switch ( m_Activity )
|
||||
{
|
||||
case ACT_WALK:
|
||||
ys = 50;
|
||||
break;
|
||||
case ACT_RUN:
|
||||
ys = 70;
|
||||
break;
|
||||
case ACT_IDLE:
|
||||
ys = 50;
|
||||
break;
|
||||
default:
|
||||
ys = 90;
|
||||
break;
|
||||
}
|
||||
|
||||
pev->yaw_speed = ys;
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// HandleAnimEvent - catches the monster-specific messages
|
||||
// that occur when tagged animation frames are played.
|
||||
//
|
||||
// Returns number of events handled, 0 if none.
|
||||
//=========================================================
|
||||
void CAlienPanther :: HandleAnimEvent( MonsterEvent_t *pEvent )
|
||||
{
|
||||
// ALERT( at_console, "event %d : %f\n", pEvent->event, pev->frame );
|
||||
switch( pEvent->event )
|
||||
{
|
||||
case APANTHER_AE_CLAW:
|
||||
{
|
||||
// SOUND HERE!
|
||||
CBaseEntity *pHurt = CheckTraceHullAttack( 70, gSkillData.pantherDmgClaw, DMG_SLASH );
|
||||
if ( pHurt )
|
||||
{
|
||||
if ( pHurt->pev->flags & (FL_MONSTER|FL_CLIENT) )
|
||||
{
|
||||
pHurt->pev->punchangle.z = -18;
|
||||
pHurt->pev->punchangle.x = 5;
|
||||
}
|
||||
// Play a random attack hit sound
|
||||
EMIT_SOUND_DYN ( ENT(pev), CHAN_WEAPON, pAttackHitSounds[ RANDOM_LONG(0,ARRAYSIZE(pAttackHitSounds)-1) ], 1.0, ATTN_NORM, 0, m_voicePitch );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Play a random attack miss sound
|
||||
EMIT_SOUND_DYN ( ENT(pev), CHAN_WEAPON, pAttackMissSounds[ RANDOM_LONG(0,ARRAYSIZE(pAttackMissSounds)-1) ], 1.0, ATTN_NORM, 0, m_voicePitch );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case APANTHER_AE_CLAWRAKE:
|
||||
{
|
||||
CBaseEntity *pHurt = CheckTraceHullAttack( 70, gSkillData.pantherDmgClawRake, DMG_SLASH );
|
||||
if ( pHurt )
|
||||
{
|
||||
if ( pHurt->pev->flags & (FL_MONSTER|FL_CLIENT) )
|
||||
{
|
||||
pHurt->pev->punchangle.z = -18;
|
||||
pHurt->pev->punchangle.x = 5;
|
||||
}
|
||||
EMIT_SOUND_DYN ( ENT(pev), CHAN_WEAPON, pAttackHitSounds[ RANDOM_LONG(0,ARRAYSIZE(pAttackHitSounds)-1) ], 1.0, ATTN_NORM, 0, m_voicePitch );
|
||||
}
|
||||
else
|
||||
{
|
||||
EMIT_SOUND_DYN ( ENT(pev), CHAN_WEAPON, pAttackMissSounds[ RANDOM_LONG(0,ARRAYSIZE(pAttackMissSounds)-1) ], 1.0, ATTN_NORM, 0, m_voicePitch );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case APANTHER_AE_ZAP_POWERUP:
|
||||
{
|
||||
// speed up attack when on hard
|
||||
if (g_iSkillLevel == SKILL_HARD)
|
||||
pev->framerate = 1.5;
|
||||
|
||||
UTIL_MakeAimVectors( pev->angles );
|
||||
|
||||
if (m_iBeams == 0)
|
||||
{
|
||||
Vector vecSrc = pev->origin + gpGlobals->v_forward * 2;
|
||||
MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, vecSrc );
|
||||
WRITE_BYTE(TE_DLIGHT);
|
||||
WRITE_COORD(vecSrc.x); // X
|
||||
WRITE_COORD(vecSrc.y); // Y
|
||||
WRITE_COORD(vecSrc.z); // Z
|
||||
WRITE_BYTE( 12 ); // radius * 0.1
|
||||
WRITE_BYTE( 255 ); // r
|
||||
WRITE_BYTE( 180 ); // g
|
||||
WRITE_BYTE( 96 ); // b
|
||||
WRITE_BYTE( 20 / pev->framerate ); // time * 10
|
||||
WRITE_BYTE( 0 ); // decay * 0.1
|
||||
MESSAGE_END( );
|
||||
|
||||
}
|
||||
if (m_hDead != NULL)
|
||||
{
|
||||
WackBeam( -1, m_hDead );
|
||||
WackBeam( 1, m_hDead );
|
||||
}
|
||||
else
|
||||
{
|
||||
ArmBeam( -1 );
|
||||
ArmBeam( 1 );
|
||||
BeamGlow( );
|
||||
}
|
||||
|
||||
EMIT_SOUND_DYN( ENT(pev), CHAN_WEAPON, "panther/p_zap2.wav", 1, ATTN_NORM, 0, 100 + m_iBeams * 10 );
|
||||
pev->skin = m_iBeams / 2;
|
||||
}
|
||||
break;
|
||||
|
||||
case APANTHER_AE_ZAP_SHOOT:
|
||||
{
|
||||
ClearBeams( );
|
||||
|
||||
if (m_hDead != NULL)
|
||||
{
|
||||
Vector vecDest = m_hDead->pev->origin + Vector( 0, 0, 38 );
|
||||
TraceResult trace;
|
||||
UTIL_TraceHull( vecDest, vecDest, dont_ignore_monsters, human_hull, m_hDead->edict(), &trace );
|
||||
|
||||
if ( !trace.fStartSolid )
|
||||
{
|
||||
CBaseEntity *pNew = Create( "monster_alien_panther", m_hDead->pev->origin, m_hDead->pev->angles );
|
||||
CBaseMonster *pNewMonster = pNew->MyMonsterPointer( );
|
||||
pNew->pev->spawnflags |= 1;
|
||||
WackBeam( -1, pNew );
|
||||
WackBeam( 1, pNew );
|
||||
UTIL_Remove( m_hDead );
|
||||
EMIT_SOUND_DYN( ENT(pev), CHAN_WEAPON, "panther/p_shoot1.wav", 1, ATTN_NORM, 0, RANDOM_LONG( 130, 160 ) );
|
||||
|
||||
/*
|
||||
CBaseEntity *pEffect = Create( "test_effect", pNew->Center(), pev->angles );
|
||||
pEffect->Use( this, this, USE_ON, 1 );
|
||||
*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
ClearMultiDamage();
|
||||
|
||||
UTIL_MakeAimVectors( pev->angles );
|
||||
|
||||
ZapBeam( -1 );
|
||||
ZapBeam( 1 );
|
||||
|
||||
EMIT_SOUND_DYN( ENT(pev), CHAN_WEAPON, "panther/p_shoot1.wav", 1, ATTN_NORM, 0, RANDOM_LONG( 130, 160 ) );
|
||||
// STOP_SOUND( ENT(pev), CHAN_WEAPON, "debris/zap4.wav" );
|
||||
ApplyMultiDamage(pev, pev);
|
||||
|
||||
m_flNextAttack = gpGlobals->time + RANDOM_FLOAT( 0.5, 4.0 );
|
||||
}
|
||||
break;
|
||||
|
||||
case APANTHER_AE_ZAP_DONE:
|
||||
{
|
||||
ClearBeams( );
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
CSquadMonster::HandleAnimEvent( pEvent );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// CheckRangeAttack1 - normal beam attack
|
||||
//=========================================================
|
||||
BOOL CAlienPanther :: CheckRangeAttack1 ( float flDot, float flDist )
|
||||
{
|
||||
if (m_flNextAttack > gpGlobals->time)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return CSquadMonster::CheckRangeAttack1( flDot, flDist );
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// CheckRangeAttack2 - check bravery and try to resurect dead comrades
|
||||
//=========================================================
|
||||
BOOL CAlienPanther :: CheckRangeAttack2 ( float flDot, float flDist )
|
||||
{
|
||||
return FALSE;
|
||||
|
||||
if (m_flNextAttack > gpGlobals->time)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
m_hDead = NULL;
|
||||
m_iBravery = 0;
|
||||
|
||||
CBaseEntity *pEntity = NULL;
|
||||
while ((pEntity = UTIL_FindEntityByClassname( pEntity, "monster_alien_panther" )) != NULL)
|
||||
{
|
||||
TraceResult tr;
|
||||
|
||||
UTIL_TraceLine( EyePosition( ), pEntity->EyePosition( ), ignore_monsters, ENT(pev), &tr );
|
||||
if (tr.flFraction == 1.0 || tr.pHit == pEntity->edict())
|
||||
{
|
||||
if (pEntity->pev->deadflag == DEAD_DEAD)
|
||||
{
|
||||
float d = (pev->origin - pEntity->pev->origin).Length();
|
||||
if (d < flDist)
|
||||
{
|
||||
m_hDead = pEntity;
|
||||
flDist = d;
|
||||
}
|
||||
m_iBravery--;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_iBravery++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (m_hDead != NULL)
|
||||
return TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
//=========================================================
|
||||
// StartTask
|
||||
//=========================================================
|
||||
void CAlienPanther :: StartTask ( Task_t *pTask )
|
||||
{
|
||||
ClearBeams( );
|
||||
|
||||
CSquadMonster :: StartTask ( pTask );
|
||||
}
|
||||
|
||||
|
||||
//=========================================================
|
||||
// Spawn
|
||||
//=========================================================
|
||||
void CAlienPanther :: Spawn()
|
||||
{
|
||||
Precache( );
|
||||
|
||||
SET_MODEL(ENT(pev), "models/panther.mdl");
|
||||
UTIL_SetSize(pev, VEC_HUMAN_HULL_MIN, VEC_HUMAN_HULL_MAX);
|
||||
|
||||
pev->solid = SOLID_SLIDEBOX;
|
||||
pev->movetype = MOVETYPE_STEP;
|
||||
m_bloodColor = BLOOD_COLOR_GREEN;
|
||||
pev->effects = 0;
|
||||
pev->health = gSkillData.pantherHealth;
|
||||
pev->view_ofs = Vector ( 0, 0, 64 );// 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 CAlienPanther :: Precache()
|
||||
{
|
||||
int i;
|
||||
|
||||
PRECACHE_MODEL("models/panther.mdl");
|
||||
PRECACHE_MODEL("sprites/lgtning.spr");
|
||||
PRECACHE_SOUND("panther/p_zap1.wav");
|
||||
PRECACHE_SOUND("panther/p_zap2.wav");
|
||||
PRECACHE_SOUND("panther/p_electro1.wav");
|
||||
PRECACHE_SOUND("panther/p_shoot1.wav");
|
||||
PRECACHE_SOUND("panther/p_pain1.wav");
|
||||
PRECACHE_SOUND("panther/p_pain2.wav");
|
||||
PRECACHE_SOUND("panther/p_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" );
|
||||
}
|
||||
|
||||
|
||||
//=========================================================
|
||||
// TakeDamage - get provoked when injured
|
||||
//=========================================================
|
||||
|
||||
int CAlienPanther :: TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType)
|
||||
{
|
||||
// don't slash one of your own
|
||||
if ((bitsDamageType & DMG_SLASH) && pevAttacker && IRelationship( Instance(pevAttacker) ) < R_DL)
|
||||
return 0;
|
||||
|
||||
m_afMemory |= bits_MEMORY_PROVOKED;
|
||||
return CSquadMonster::TakeDamage(pevInflictor, pevAttacker, flDamage, bitsDamageType);
|
||||
}
|
||||
|
||||
|
||||
void CAlienPanther::TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType)
|
||||
{
|
||||
if (bitsDamageType & DMG_SHOCK)
|
||||
return;
|
||||
|
||||
CSquadMonster::TraceAttack( pevAttacker, flDamage, vecDir, ptr, bitsDamageType );
|
||||
}
|
||||
|
||||
|
||||
//=========================================================
|
||||
// AI Schedules Specific to this monster
|
||||
//=========================================================
|
||||
|
||||
|
||||
|
||||
// primary range attack
|
||||
Task_t tlPantherAttack1[] =
|
||||
{
|
||||
{ TASK_STOP_MOVING, 0 },
|
||||
{ TASK_FACE_IDEAL, (float)0 },
|
||||
{ TASK_RANGE_ATTACK1, (float)0 },
|
||||
};
|
||||
|
||||
Schedule_t slPantherAttack1[] =
|
||||
{
|
||||
{
|
||||
tlPantherAttack1,
|
||||
ARRAYSIZE ( tlPantherAttack1 ),
|
||||
bits_COND_CAN_MELEE_ATTACK1 |
|
||||
bits_COND_HEAR_SOUND |
|
||||
bits_COND_HEAVY_DAMAGE,
|
||||
|
||||
bits_SOUND_DANGER,
|
||||
"Panther Range Attack1"
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
DEFINE_CUSTOM_SCHEDULES( CAlienPanther )
|
||||
{
|
||||
slPantherAttack1,
|
||||
};
|
||||
|
||||
IMPLEMENT_CUSTOM_SCHEDULES( CAlienPanther, CSquadMonster );
|
||||
|
||||
|
||||
//=========================================================
|
||||
//=========================================================
|
||||
Schedule_t *CAlienPanther :: GetSchedule( void )
|
||||
{
|
||||
ClearBeams( );
|
||||
|
||||
/*
|
||||
if (pev->spawnflags)
|
||||
{
|
||||
pev->spawnflags = 0;
|
||||
return GetScheduleOfType( SCHED_RELOAD );
|
||||
}
|
||||
*/
|
||||
|
||||
if ( HasConditions( bits_COND_HEAR_SOUND ) )
|
||||
{
|
||||
CSound *pSound;
|
||||
pSound = PBestSound();
|
||||
|
||||
ASSERT( pSound != NULL );
|
||||
|
||||
if ( pSound && (pSound->m_iType & bits_SOUND_DANGER) )
|
||||
return GetScheduleOfType( SCHED_TAKE_COVER_FROM_BEST_SOUND );
|
||||
if ( pSound->m_iType & bits_SOUND_COMBAT )
|
||||
m_afMemory |= bits_MEMORY_PROVOKED;
|
||||
}
|
||||
|
||||
switch (m_MonsterState)
|
||||
{
|
||||
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 (pev->health < 20 || m_iBravery < 0)
|
||||
{
|
||||
if (!HasConditions( bits_COND_CAN_MELEE_ATTACK1 ))
|
||||
{
|
||||
m_failSchedule = SCHED_CHASE_ENEMY;
|
||||
if (HasConditions( bits_COND_LIGHT_DAMAGE | bits_COND_HEAVY_DAMAGE))
|
||||
{
|
||||
return GetScheduleOfType( SCHED_TAKE_COVER_FROM_ENEMY );
|
||||
}
|
||||
if ( HasConditions ( bits_COND_SEE_ENEMY ) && HasConditions ( bits_COND_ENEMY_FACING_ME ) )
|
||||
{
|
||||
// ALERT( at_console, "exposed\n");
|
||||
return GetScheduleOfType( SCHED_TAKE_COVER_FROM_ENEMY );
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return CSquadMonster::GetSchedule( );
|
||||
}
|
||||
|
||||
|
||||
Schedule_t *CAlienPanther :: GetScheduleOfType ( int Type )
|
||||
{
|
||||
switch ( Type )
|
||||
{
|
||||
case SCHED_FAIL:
|
||||
if (HasConditions( bits_COND_CAN_MELEE_ATTACK1 ))
|
||||
{
|
||||
return CSquadMonster :: GetScheduleOfType( SCHED_MELEE_ATTACK1 ); ;
|
||||
}
|
||||
break;
|
||||
case SCHED_RANGE_ATTACK1:
|
||||
return slPantherAttack1;
|
||||
case SCHED_RANGE_ATTACK2:
|
||||
return slPantherAttack1;
|
||||
}
|
||||
return CSquadMonster :: GetScheduleOfType( Type );
|
||||
}
|
||||
|
||||
|
||||
//=========================================================
|
||||
// ArmBeam - small beam from arm to nearby geometry
|
||||
//=========================================================
|
||||
|
||||
void CAlienPanther :: ArmBeam( int side )
|
||||
{
|
||||
TraceResult tr;
|
||||
float flDist = 1.0;
|
||||
|
||||
if (m_iBeams >= APANTHER_MAX_BEAMS)
|
||||
return;
|
||||
|
||||
UTIL_MakeAimVectors( pev->angles );
|
||||
Vector vecSrc = pev->origin + gpGlobals->v_up * 36 + gpGlobals->v_right * side * 16 + gpGlobals->v_forward * 32;
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
Vector vecAim = gpGlobals->v_right * side * RANDOM_FLOAT( 0, 1 ) + gpGlobals->v_up * RANDOM_FLOAT( -1, 1 );
|
||||
TraceResult tr1;
|
||||
UTIL_TraceLine ( vecSrc, vecSrc + vecAim * 512, dont_ignore_monsters, ENT( pev ), &tr1);
|
||||
if (flDist > tr1.flFraction)
|
||||
{
|
||||
tr = tr1;
|
||||
flDist = tr.flFraction;
|
||||
}
|
||||
}
|
||||
|
||||
// Couldn't find anything close enough
|
||||
if ( flDist == 1.0 )
|
||||
return;
|
||||
|
||||
DecalGunshot( &tr, BULLET_PLAYER_CROWBAR );
|
||||
|
||||
m_pBeam[m_iBeams] = CBeam::BeamCreate( "sprites/lgtning.spr", 30 );
|
||||
if (!m_pBeam[m_iBeams])
|
||||
return;
|
||||
|
||||
m_pBeam[m_iBeams]->PointEntInit( tr.vecEndPos, entindex( ) );
|
||||
m_pBeam[m_iBeams]->SetEndAttachment( side < 0 ? 2 : 1 );
|
||||
// m_pBeam[m_iBeams]->SetColor( 180, 255, 96 );
|
||||
m_pBeam[m_iBeams]->SetColor( 255, 0, 20 );//edit Alex
|
||||
m_pBeam[m_iBeams]->SetBrightness( 64 );
|
||||
m_pBeam[m_iBeams]->SetNoise( 80 );
|
||||
m_iBeams++;
|
||||
}
|
||||
|
||||
|
||||
//=========================================================
|
||||
// BeamGlow - brighten all beams
|
||||
//=========================================================
|
||||
void CAlienPanther :: BeamGlow( )
|
||||
{
|
||||
int b = m_iBeams * 32;
|
||||
if (b > 255)
|
||||
b = 255;
|
||||
|
||||
for (int i = 0; i < m_iBeams; i++)
|
||||
{
|
||||
if (m_pBeam[i]->GetBrightness() != 255)
|
||||
{
|
||||
m_pBeam[i]->SetBrightness( b );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//=========================================================
|
||||
// WackBeam - regenerate dead colleagues
|
||||
//=========================================================
|
||||
void CAlienPanther :: WackBeam( int side, CBaseEntity *pEntity )
|
||||
{
|
||||
Vector vecDest;
|
||||
float flDist = 1.0;
|
||||
|
||||
if (m_iBeams >= APANTHER_MAX_BEAMS)
|
||||
return;
|
||||
|
||||
if (pEntity == NULL)
|
||||
return;
|
||||
|
||||
m_pBeam[m_iBeams] = CBeam::BeamCreate( "sprites/lgtning.spr", 30 );
|
||||
if (!m_pBeam[m_iBeams])
|
||||
return;
|
||||
|
||||
m_pBeam[m_iBeams]->PointEntInit( pEntity->Center(), entindex( ) );
|
||||
m_pBeam[m_iBeams]->SetEndAttachment( side < 0 ? 2 : 1 );
|
||||
m_pBeam[m_iBeams]->SetColor( 255, 0, 20 );
|
||||
m_pBeam[m_iBeams]->SetBrightness( 255 );
|
||||
m_pBeam[m_iBeams]->SetNoise( 80 );
|
||||
m_iBeams++;
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// ZapBeam - heavy damage directly forward
|
||||
//=========================================================
|
||||
void CAlienPanther :: ZapBeam( int side )
|
||||
{
|
||||
Vector vecSrc, vecAim;
|
||||
TraceResult tr;
|
||||
CBaseEntity *pEntity;
|
||||
|
||||
if (m_iBeams >= APANTHER_MAX_BEAMS)
|
||||
return;
|
||||
|
||||
vecSrc = pev->origin + gpGlobals->v_up * 36;
|
||||
vecAim = ShootAtEnemy( vecSrc );
|
||||
float deflection = 0.01;
|
||||
vecAim = vecAim + side * gpGlobals->v_right * RANDOM_FLOAT( 0, deflection ) + gpGlobals->v_up * RANDOM_FLOAT( -deflection, deflection );
|
||||
UTIL_TraceLine ( vecSrc, vecSrc + vecAim * 1024, dont_ignore_monsters, ENT( pev ), &tr);
|
||||
|
||||
m_pBeam[m_iBeams] = CBeam::BeamCreate( "sprites/lgtning.spr", 50 );
|
||||
if (!m_pBeam[m_iBeams])
|
||||
return;
|
||||
|
||||
m_pBeam[m_iBeams]->PointEntInit( tr.vecEndPos, entindex( ) );
|
||||
m_pBeam[m_iBeams]->SetEndAttachment( side < 0 ? 2 : 1 );
|
||||
m_pBeam[m_iBeams]->SetColor( 255, 0, 20 );//modified Alex, was (180, 255, 96)
|
||||
m_pBeam[m_iBeams]->SetBrightness( 255 );
|
||||
m_pBeam[m_iBeams]->SetNoise( 20 );
|
||||
m_iBeams++;
|
||||
|
||||
pEntity = CBaseEntity::Instance(tr.pHit);
|
||||
if (pEntity != NULL && pEntity->pev->takedamage)
|
||||
{
|
||||
pEntity->TraceAttack( pev, gSkillData.pantherDmgZap, vecAim, &tr, DMG_SHOCK );
|
||||
}
|
||||
UTIL_EmitAmbientSound( ENT(pev), tr.vecEndPos, "panther/p_electro1.wav", 0.5, ATTN_NORM, 0, RANDOM_LONG( 140, 160 ) );
|
||||
}
|
||||
|
||||
|
||||
//=========================================================
|
||||
// ClearBeams - remove all beams
|
||||
//=========================================================
|
||||
void CAlienPanther :: ClearBeams( )
|
||||
{
|
||||
for (int i = 0; i < APANTHER_MAX_BEAMS; i++)
|
||||
{
|
||||
if (m_pBeam[i])
|
||||
{
|
||||
UTIL_Remove( m_pBeam[i] );
|
||||
m_pBeam[i] = NULL;
|
||||
}
|
||||
}
|
||||
m_iBeams = 0;
|
||||
pev->skin = 0;
|
||||
|
||||
STOP_SOUND( ENT(pev), CHAN_WEAPON, "panther/p_zap1.wav" );
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,78 @@
|
|||
/***
|
||||
*
|
||||
* 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 "extdll.h"
|
||||
#include "util.h"
|
||||
#include "cbase.h"
|
||||
#include "monsters.h"
|
||||
#include "weapons.h"
|
||||
#include "nodes.h"
|
||||
#include "player.h"
|
||||
|
||||
enum barneyglock_e
|
||||
{
|
||||
BARNEYGLOCK_IDLE1 = 0,
|
||||
BARNEYGLOCK_IDLE2,
|
||||
BARNEYGLOCK_IDLE3,
|
||||
BARNEYGLOCK_SHOOT,
|
||||
BARNEYGLOCK_SHOOT_EMPTY,
|
||||
BARNEYGLOCK_RELOAD,
|
||||
BARNEYGLOCK_RELOAD_NOT_EMPTY,
|
||||
BARNEYGLOCK_DRAW,
|
||||
BARNEYGLOCK_HOLSTER,
|
||||
BARNEYGLOCK_ADD_SILENCER
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS( weapon_barney9mmhg, CBarneyGlock )
|
||||
|
||||
void CBarneyGlock::Spawn()
|
||||
{
|
||||
Precache();
|
||||
m_iId = WEAPON_BARNEYGLOCK;
|
||||
SET_MODEL( ENT( pev ), "models/w_9mmhandgun.mdl" );
|
||||
|
||||
m_iDefaultAmmo = GLOCK_DEFAULT_GIVE;
|
||||
|
||||
FallInit();// get ready to fall down.
|
||||
}
|
||||
|
||||
void CBarneyGlock::Precache( void )
|
||||
{
|
||||
PRECACHE_MODEL( "models/v_barney9mmhg.mdl" );
|
||||
CGlock::Precache();
|
||||
}
|
||||
|
||||
int CBarneyGlock::GetItemInfo( ItemInfo *p )
|
||||
{
|
||||
p->pszName = STRING( pev->classname );
|
||||
p->pszAmmo1 = "9mm";
|
||||
p->iMaxAmmo1 = _9MM_MAX_CARRY;
|
||||
p->pszAmmo2 = NULL;
|
||||
p->iMaxAmmo2 = -1;
|
||||
p->iMaxClip = GLOCK_MAX_CLIP;
|
||||
p->iSlot = 1;
|
||||
p->iPosition = 1;
|
||||
p->iFlags = 0;
|
||||
p->iId = m_iId = WEAPON_BARNEYGLOCK;
|
||||
p->iWeight = GLOCK_WEIGHT;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
BOOL CBarneyGlock::Deploy()
|
||||
{
|
||||
// pev->body = 1;
|
||||
return DefaultDeploy( "models/v_barney9mmhg.mdl", "models/p_9mmhandgun.mdl", BARNEYGLOCK_DRAW, "onehanded", /*UseDecrement() ? 1 : 0*/ 0 );
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
/***
|
||||
*
|
||||
* 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 "extdll.h"
|
||||
#include "util.h"
|
||||
#include "cbase.h"
|
||||
#include "monsters.h"
|
||||
#include "weapons.h"
|
||||
#include "nodes.h"
|
||||
#include "player.h"
|
||||
|
||||
#define HANDGRENADE_PRIMARY_VOLUME 450
|
||||
|
||||
enum barneyhandgrenade_e
|
||||
{
|
||||
BARNEYHANDGRENADE_IDLE = 0,
|
||||
BARNEYHANDGRENADE_FIDGET,
|
||||
BARNEYHANDGRENADE_PINPULL,
|
||||
BARNEYHANDGRENADE_THROW1, // toss
|
||||
BARNEYHANDGRENADE_THROW2, // medium
|
||||
BARNEYHANDGRENADE_THROW3, // hard
|
||||
BARNEYHANDGRENADE_HOLSTER,
|
||||
BARNEYHANDGRENADE_DRAW
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS( weapon_barneyhandgrenade, CBarneyHandGrenade )
|
||||
|
||||
void CBarneyHandGrenade::Spawn()
|
||||
{
|
||||
Precache();
|
||||
m_iId = WEAPON_BARNEYHANDGRENADE;
|
||||
SET_MODEL( ENT( pev ), "models/w_grenade.mdl" );
|
||||
|
||||
#ifndef CLIENT_DLL
|
||||
pev->dmg = gSkillData.plrDmgHandGrenade;
|
||||
#endif
|
||||
m_iDefaultAmmo = HANDGRENADE_DEFAULT_GIVE;
|
||||
|
||||
FallInit();// get ready to fall down.
|
||||
}
|
||||
|
||||
void CBarneyHandGrenade::Precache( void )
|
||||
{
|
||||
PRECACHE_MODEL( "models/v_barneygrenade.mdl" );
|
||||
CHandGrenade::Precache();
|
||||
}
|
||||
|
||||
int CBarneyHandGrenade::GetItemInfo( ItemInfo *p )
|
||||
{
|
||||
p->pszName = STRING( pev->classname );
|
||||
p->pszAmmo1 = "Hand Grenade";
|
||||
p->iMaxAmmo1 = HANDGRENADE_MAX_CARRY;
|
||||
p->pszAmmo2 = NULL;
|
||||
p->iMaxAmmo2 = -1;
|
||||
p->iMaxClip = WEAPON_NOCLIP;
|
||||
p->iSlot = 4;
|
||||
p->iPosition = 1;
|
||||
p->iId = m_iId = WEAPON_BARNEYHANDGRENADE;
|
||||
p->iWeight = HANDGRENADE_WEIGHT;
|
||||
p->iFlags = ITEM_FLAG_LIMITINWORLD | ITEM_FLAG_EXHAUSTIBLE;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
BOOL CBarneyHandGrenade::Deploy()
|
||||
{
|
||||
m_flReleaseThrow = -1;
|
||||
return DefaultDeploy( "models/v_barneygrenade.mdl", "models/p_grenade.mdl", BARNEYHANDGRENADE_DRAW, "crowbar" );
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
/***
|
||||
*
|
||||
* 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 "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 barneymp5_e
|
||||
{
|
||||
BARNEYMP5_LONGIDLE = 0,
|
||||
BARNEYMP5_IDLE1,
|
||||
BARNEYMP5_LAUNCH,
|
||||
BARNEYMP5_RELOAD,
|
||||
BARNEYMP5_DEPLOY,
|
||||
BARNEYMP5_FIRE1,
|
||||
BARNEYMP5_FIRE2,
|
||||
BARNEYMP5_FIRE3,
|
||||
BARNEYMP5_HOLSTER
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS( weapon_barney9mmar, CBarneyMP5 )
|
||||
|
||||
void CBarneyMP5::Spawn()
|
||||
{
|
||||
Precache();
|
||||
SET_MODEL( ENT( pev ), "models/w_9mmAR.mdl" );
|
||||
m_iId = WEAPON_BARNEYMP5;
|
||||
|
||||
m_iDefaultAmmo = MP5_DEFAULT_GIVE;
|
||||
|
||||
FallInit();// get ready to fall down.
|
||||
}
|
||||
|
||||
void CBarneyMP5::Precache( void )
|
||||
{
|
||||
PRECACHE_MODEL( "models/v_barney9mmar.mdl" );
|
||||
CMP5::Precache();
|
||||
}
|
||||
|
||||
int CBarneyMP5::GetItemInfo( ItemInfo *p )
|
||||
{
|
||||
p->pszName = STRING( pev->classname );
|
||||
p->pszAmmo1 = "9mm";
|
||||
p->iMaxAmmo1 = _9MM_MAX_CARRY;
|
||||
p->pszAmmo2 = "ARgrenades";
|
||||
p->iMaxAmmo2 = M203_GRENADE_MAX_CARRY;
|
||||
p->iMaxClip = MP5_MAX_CLIP;
|
||||
p->iSlot = 2;
|
||||
p->iPosition = 1;
|
||||
p->iFlags = 0;
|
||||
p->iId = m_iId = WEAPON_BARNEYMP5;
|
||||
p->iWeight = MP5_WEIGHT;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
BOOL CBarneyMP5::Deploy()
|
||||
{
|
||||
return DefaultDeploy( "models/v_barney9mmar.mdl", "models/p_9mmAR.mdl", BARNEYMP5_DEPLOY, "barneymp5" );
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
/***
|
||||
*
|
||||
* 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 "extdll.h"
|
||||
#include "util.h"
|
||||
#include "cbase.h"
|
||||
#include "monsters.h"
|
||||
#include "weapons.h"
|
||||
#include "nodes.h"
|
||||
#include "player.h"
|
||||
#include "gamerules.h"
|
||||
|
||||
// special deathmatch shotgun spreads
|
||||
#define VECTOR_CONE_DM_SHOTGUN Vector( 0.08716, 0.04362, 0.00 )// 10 degrees by 5 degrees
|
||||
#define VECTOR_CONE_DM_DOUBLESHOTGUN Vector( 0.17365, 0.04362, 0.00 ) // 20 degrees by 5 degrees
|
||||
|
||||
enum barneyshotgun_e
|
||||
{
|
||||
BARNEYSHOTGUN_IDLE = 0,
|
||||
BARNEYSHOTGUN_FIRE,
|
||||
BARNEYSHOTGUN_FIRE2,
|
||||
BARNEYSHOTGUN_RELOAD,
|
||||
BARNEYSHOTGUN_PUMP,
|
||||
BARNEYSHOTGUN_START_RELOAD,
|
||||
BARNEYSHOTGUN_DRAW,
|
||||
BARNEYSHOTGUN_HOLSTER,
|
||||
BARNEYSHOTGUN_IDLE4,
|
||||
BARNEYSHOTGUN_IDLE_DEEP
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS( weapon_barneyshotgun, CBarneyShotgun )
|
||||
|
||||
void CBarneyShotgun::Spawn()
|
||||
{
|
||||
Precache();
|
||||
m_iId = WEAPON_BARNEYSHOTGUN;
|
||||
SET_MODEL( ENT( pev ), "models/w_shotgun.mdl" );
|
||||
|
||||
m_iDefaultAmmo = SHOTGUN_DEFAULT_GIVE;
|
||||
|
||||
FallInit();// get ready to fall
|
||||
}
|
||||
|
||||
void CBarneyShotgun::Precache( void )
|
||||
{
|
||||
PRECACHE_MODEL( "models/v_barneyshotgun.mdl" );
|
||||
CShotgun::Precache();
|
||||
}
|
||||
|
||||
int CBarneyShotgun::GetItemInfo( ItemInfo *p )
|
||||
{
|
||||
p->pszName = STRING( pev->classname );
|
||||
p->pszAmmo1 = "buckshot";
|
||||
p->iMaxAmmo1 = BUCKSHOT_MAX_CARRY;
|
||||
p->pszAmmo2 = NULL;
|
||||
p->iMaxAmmo2 = -1;
|
||||
p->iMaxClip = SHOTGUN_MAX_CLIP;
|
||||
p->iSlot = 2;
|
||||
p->iPosition = 3;
|
||||
p->iFlags = 0;
|
||||
p->iId = m_iId = WEAPON_BARNEYSHOTGUN;
|
||||
p->iWeight = SHOTGUN_WEIGHT;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
BOOL CBarneyShotgun::Deploy()
|
||||
{
|
||||
return DefaultDeploy( "models/v_barneyshotgun.mdl", "models/p_shotgun.mdl", BARNEYSHOTGUN_DRAW, "shotgun" );
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
|
||||
* 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.
|
||||
|
@ -27,324 +27,67 @@
|
|||
#include "scripted.h"
|
||||
#include "weapons.h"
|
||||
#include "soundent.h"
|
||||
#include "barney.h"
|
||||
|
||||
//=========================================================
|
||||
// Monster's Anim Events Go Here
|
||||
//=========================================================
|
||||
// first flag is barniel dying for scripted sequences?
|
||||
#define BARNIEL_AE_DRAW ( 2 )
|
||||
#define BARNIEL_AE_SHOOT ( 3 )
|
||||
#define BARNIEL_AE_HOLSTER ( 4 )
|
||||
// first flag is barney dying for scripted sequences?
|
||||
|
||||
#define BARNIEL_BODY_GUNHOLSTERED 0
|
||||
#define BARNIEL_BODY_GUNDRAWN 1
|
||||
#define BARNIEL_BODY_GUNGONE 2
|
||||
|
||||
class CBarniel : public CTalkMonster
|
||||
class CBarniel : public CBarney
|
||||
{
|
||||
public:
|
||||
void Spawn( void );
|
||||
void Precache( void );
|
||||
void SetYawSpeed( void );
|
||||
int ISoundMask( void );
|
||||
void BarnielFirePistol( 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 );
|
||||
void Spawn( void );
|
||||
void Precache( void );
|
||||
void BarneyFirePistol( void );
|
||||
void AlertSound( void );
|
||||
CBaseEntity* CheckTraceHullAttack( float flDist, int iDamage, int iDmgType );
|
||||
int TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType);
|
||||
|
||||
// Override these to set behavior
|
||||
Schedule_t *GetScheduleOfType ( int Type );
|
||||
Schedule_t *GetSchedule ( void );
|
||||
MONSTERSTATE GetIdealState ( void );
|
||||
void DeclineFollowing( void );
|
||||
|
||||
void DeathSound( void );
|
||||
void PainSound( void );
|
||||
|
||||
void TalkInit( void );
|
||||
// Override these to set behavior
|
||||
Schedule_t *GetSchedule( 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[];
|
||||
void DeathSound( void );
|
||||
void PainSound( void );
|
||||
|
||||
BOOL m_fGunDrawn;
|
||||
float m_painTime;
|
||||
float m_checkAttackTime;
|
||||
BOOL m_lastAttackCheck;
|
||||
void TalkInit( void );
|
||||
|
||||
// UNDONE: What is this for? It isn't used?
|
||||
float m_flPlayerDamage;// how much pain has the player inflicted on me?
|
||||
|
||||
CUSTOM_SCHEDULES;
|
||||
int m_iCombatState;
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS( monster_barniel, CBarniel );
|
||||
LINK_ENTITY_TO_CLASS( monster_barniel, CBarniel )
|
||||
|
||||
TYPEDESCRIPTION CBarniel::m_SaveData[] =
|
||||
{
|
||||
DEFINE_FIELD( CBarniel, m_fGunDrawn, FIELD_BOOLEAN ),
|
||||
DEFINE_FIELD( CBarniel, m_painTime, FIELD_TIME ),
|
||||
DEFINE_FIELD( CBarniel, m_checkAttackTime, FIELD_TIME ),
|
||||
DEFINE_FIELD( CBarniel, m_lastAttackCheck, FIELD_BOOLEAN ),
|
||||
DEFINE_FIELD( CBarniel, m_flPlayerDamage, FIELD_FLOAT ),
|
||||
};
|
||||
|
||||
IMPLEMENT_SAVERESTORE( CBarniel, CTalkMonster );
|
||||
extern Schedule_t slBaFollow[];
|
||||
extern Schedule_t slBarneyEnemyDraw[];
|
||||
extern Schedule_t slBaFaceTarget[];
|
||||
extern Schedule_t slIdleBaStand[];
|
||||
extern Schedule_t slGruntHideReload[];
|
||||
|
||||
//=========================================================
|
||||
// AI Schedules Specific to this monster
|
||||
// ALertSound - barney says "Freeze!"
|
||||
//=========================================================
|
||||
Task_t tlBa1Follow[] =
|
||||
{
|
||||
{ TASK_MOVE_TO_TARGET_RANGE,(float)128 }, // Move within 128 of target ent (client)
|
||||
{ TASK_SET_SCHEDULE, (float)SCHED_TARGET_FACE },
|
||||
};
|
||||
|
||||
Schedule_t slBa1Follow[] =
|
||||
void CBarniel::AlertSound( void )
|
||||
{
|
||||
if( m_hEnemy != 0 )
|
||||
{
|
||||
tlBa1Follow,
|
||||
ARRAYSIZE ( tlBa1Follow ),
|
||||
bits_COND_NEW_ENEMY |
|
||||
bits_COND_LIGHT_DAMAGE |
|
||||
bits_COND_HEAVY_DAMAGE |
|
||||
bits_COND_HEAR_SOUND |
|
||||
bits_COND_PROVOKED,
|
||||
bits_SOUND_DANGER,
|
||||
"Follow"
|
||||
},
|
||||
};
|
||||
|
||||
//=========================================================
|
||||
// BarnielDraw- much better looking draw schedule for when
|
||||
// barniel knows who he's gonna attack.
|
||||
//=========================================================
|
||||
Task_t tlBarnielEnemyDraw[] =
|
||||
{
|
||||
{ TASK_STOP_MOVING, 0 },
|
||||
{ TASK_FACE_ENEMY, 0 },
|
||||
{ TASK_PLAY_SEQUENCE_FACE_ENEMY, (float) ACT_ARM },
|
||||
};
|
||||
|
||||
Schedule_t slBarnielEnemyDraw[] =
|
||||
{
|
||||
{
|
||||
tlBarnielEnemyDraw,
|
||||
ARRAYSIZE ( tlBarnielEnemyDraw ),
|
||||
0,
|
||||
0,
|
||||
"Barniel Enemy Draw"
|
||||
}
|
||||
};
|
||||
|
||||
Task_t tlBa1FaceTarget[] =
|
||||
{
|
||||
{ TASK_SET_ACTIVITY, (float)ACT_IDLE },
|
||||
{ TASK_FACE_TARGET, (float)0 },
|
||||
{ TASK_SET_ACTIVITY, (float)ACT_IDLE },
|
||||
{ TASK_SET_SCHEDULE, (float)SCHED_TARGET_CHASE },
|
||||
};
|
||||
|
||||
Schedule_t slBa1FaceTarget[] =
|
||||
{
|
||||
{
|
||||
tlBa1FaceTarget,
|
||||
ARRAYSIZE ( tlBa1FaceTarget ),
|
||||
bits_COND_CLIENT_PUSH |
|
||||
bits_COND_NEW_ENEMY |
|
||||
bits_COND_LIGHT_DAMAGE |
|
||||
bits_COND_HEAVY_DAMAGE |
|
||||
bits_COND_HEAR_SOUND |
|
||||
bits_COND_PROVOKED,
|
||||
bits_SOUND_DANGER,
|
||||
"FaceTarget"
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
Task_t tlIdleBa1Stand[] =
|
||||
{
|
||||
{ TASK_STOP_MOVING, 0 },
|
||||
{ TASK_SET_ACTIVITY, (float)ACT_IDLE },
|
||||
{ TASK_WAIT, (float)2 }, // repick IDLESTAND every two seconds.
|
||||
{ TASK_TLK_HEADRESET, (float)0 }, // reset head position
|
||||
};
|
||||
|
||||
Schedule_t slIdleBa1Stand[] =
|
||||
{
|
||||
{
|
||||
tlIdleBa1Stand,
|
||||
ARRAYSIZE ( tlIdleBa1Stand ),
|
||||
bits_COND_NEW_ENEMY |
|
||||
bits_COND_LIGHT_DAMAGE |
|
||||
bits_COND_HEAVY_DAMAGE |
|
||||
bits_COND_HEAR_SOUND |
|
||||
bits_COND_SMELL |
|
||||
bits_COND_PROVOKED,
|
||||
|
||||
bits_SOUND_COMBAT |// sound flags - change these, and you'll break the talking code.
|
||||
//bits_SOUND_PLAYER |
|
||||
//bits_SOUND_WORLD |
|
||||
|
||||
bits_SOUND_DANGER |
|
||||
bits_SOUND_MEAT |// scents
|
||||
bits_SOUND_CARCASS |
|
||||
bits_SOUND_GARBAGE,
|
||||
"IdleStand"
|
||||
},
|
||||
};
|
||||
|
||||
DEFINE_CUSTOM_SCHEDULES( CBarniel )
|
||||
{
|
||||
slBa1Follow,
|
||||
slBarnielEnemyDraw,
|
||||
slBa1FaceTarget,
|
||||
slIdleBa1Stand,
|
||||
};
|
||||
|
||||
|
||||
IMPLEMENT_CUSTOM_SCHEDULES( CBarniel, CTalkMonster );
|
||||
|
||||
void CBarniel :: StartTask( Task_t *pTask )
|
||||
{
|
||||
CTalkMonster::StartTask( pTask );
|
||||
}
|
||||
|
||||
void CBarniel :: RunTask( Task_t *pTask )
|
||||
{
|
||||
switch ( pTask->iTask )
|
||||
{
|
||||
case TASK_RANGE_ATTACK1:
|
||||
if (m_hEnemy != NULL && (m_hEnemy->IsPlayer()))
|
||||
if( FOkToSpeak() )
|
||||
{
|
||||
pev->framerate = 1.5;
|
||||
}
|
||||
CTalkMonster::RunTask( pTask );
|
||||
break;
|
||||
default:
|
||||
CTalkMonster::RunTask( pTask );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//=========================================================
|
||||
// ISoundMask - returns a bit mask indicating which types
|
||||
// of sounds this monster regards.
|
||||
//=========================================================
|
||||
int CBarniel :: ISoundMask ( void)
|
||||
{
|
||||
return bits_SOUND_WORLD |
|
||||
bits_SOUND_COMBAT |
|
||||
bits_SOUND_CARCASS |
|
||||
bits_SOUND_MEAT |
|
||||
bits_SOUND_GARBAGE |
|
||||
bits_SOUND_DANGER |
|
||||
bits_SOUND_PLAYER;
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// Classify - indicates this monster's place in the
|
||||
// relationship table.
|
||||
//=========================================================
|
||||
int CBarniel :: Classify ( void )
|
||||
{
|
||||
return CLASS_PLAYER_ALLY;
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// ALertSound - barniel says "Freeze!"
|
||||
//=========================================================
|
||||
void CBarniel :: AlertSound( void )
|
||||
{
|
||||
if ( m_hEnemy != NULL )
|
||||
{
|
||||
if ( FOkToSpeak() )
|
||||
{
|
||||
PlaySentence( "BN_ATTACK", RANDOM_FLOAT(2.8, 3.2), VOL_NORM, ATTN_IDLE );
|
||||
PlaySentence( "BN_ATTACK", RANDOM_FLOAT( 2.8, 3.2 ), VOL_NORM, ATTN_IDLE );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
//=========================================================
|
||||
// SetYawSpeed - allows each sequence to have a different
|
||||
// turn rate associated with it.
|
||||
//=========================================================
|
||||
void CBarniel :: SetYawSpeed ( void )
|
||||
{
|
||||
int ys;
|
||||
|
||||
ys = 0;
|
||||
|
||||
switch ( m_Activity )
|
||||
{
|
||||
case ACT_IDLE:
|
||||
ys = 70;
|
||||
break;
|
||||
case ACT_WALK:
|
||||
ys = 70;
|
||||
break;
|
||||
case ACT_RUN:
|
||||
ys = 90;
|
||||
break;
|
||||
default:
|
||||
ys = 70;
|
||||
break;
|
||||
}
|
||||
|
||||
pev->yaw_speed = ys;
|
||||
}
|
||||
|
||||
|
||||
//=========================================================
|
||||
// CheckRangeAttack1
|
||||
// BarneyFirePistol - shoots one round from the pistol at
|
||||
// the enemy barney is facing.
|
||||
//=========================================================
|
||||
BOOL CBarniel :: CheckRangeAttack1 ( float flDot, float flDist )
|
||||
{
|
||||
if ( flDist <= 1024 && flDot >= 0.5 )
|
||||
{
|
||||
if ( gpGlobals->time > m_checkAttackTime )
|
||||
{
|
||||
TraceResult tr;
|
||||
|
||||
Vector shootOrigin = pev->origin + Vector( 0, 0, 55 );
|
||||
CBaseEntity *pEnemy = m_hEnemy;
|
||||
Vector shootTarget = ( (pEnemy->BodyTarget( shootOrigin ) - pEnemy->pev->origin) + m_vecEnemyLKP );
|
||||
UTIL_TraceLine( shootOrigin, shootTarget, dont_ignore_monsters, ENT(pev), &tr );
|
||||
m_checkAttackTime = gpGlobals->time + 1;
|
||||
if ( tr.flFraction == 1.0 || (tr.pHit != NULL && CBaseEntity::Instance(tr.pHit) == pEnemy) )
|
||||
m_lastAttackCheck = TRUE;
|
||||
else
|
||||
m_lastAttackCheck = FALSE;
|
||||
m_checkAttackTime = gpGlobals->time + 1.5;
|
||||
}
|
||||
return m_lastAttackCheck;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
//=========================================================
|
||||
// BarnielFirePistol - shoots one round from the pistol at
|
||||
// the enemy barniel is facing.
|
||||
//=========================================================
|
||||
void CBarniel :: BarnielFirePistol ( void )
|
||||
void CBarniel::BarneyFirePistol( void )
|
||||
{
|
||||
Vector vecShootOrigin;
|
||||
|
||||
UTIL_MakeVectors(pev->angles);
|
||||
UTIL_MakeVectors( pev->angles );
|
||||
vecShootOrigin = pev->origin + Vector( 0, 0, 55 );
|
||||
Vector vecShootDir = ShootAtEnemy( vecShootOrigin );
|
||||
|
||||
|
@ -352,177 +95,144 @@ void CBarniel :: BarnielFirePistol ( void )
|
|||
SetBlending( 0, angDir.x );
|
||||
pev->effects = EF_MUZZLEFLASH;
|
||||
|
||||
FireBullets(1, vecShootOrigin, vecShootDir, VECTOR_CONE_2DEGREES, 1024, BULLET_MONSTER_9MM );
|
||||
|
||||
FireBullets( 1, vecShootOrigin, vecShootDir, VECTOR_CONE_2DEGREES, 1024, BULLET_MONSTER_9MM );
|
||||
|
||||
int pitchShift = RANDOM_LONG( 0, 20 );
|
||||
|
||||
// Only shift about half the time
|
||||
if ( pitchShift > 10 )
|
||||
if( pitchShift > 10 )
|
||||
pitchShift = 0;
|
||||
else
|
||||
pitchShift -= 5;
|
||||
EMIT_SOUND_DYN( ENT(pev), CHAN_WEAPON, "barniel/bn_attack2.wav", 1, ATTN_NORM, 0, 100 + pitchShift );
|
||||
EMIT_SOUND_DYN( ENT( pev ), CHAN_WEAPON, "barniel/bn_attack2.wav", 1, ATTN_NORM, 0, 100 + pitchShift );
|
||||
|
||||
CSoundEnt::InsertSound ( bits_SOUND_COMBAT, pev->origin, 384, 0.3 );
|
||||
CSoundEnt::InsertSound( bits_SOUND_COMBAT, pev->origin, 384, 0.3 );
|
||||
|
||||
// UNDONE: Reload?
|
||||
m_cAmmoLoaded--;// take away a bullet!
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// HandleAnimEvent - catches the monster-specific messages
|
||||
// that occur when tagged animation frames are played.
|
||||
//
|
||||
// Returns number of events handled, 0 if none.
|
||||
//=========================================================
|
||||
void CBarniel :: HandleAnimEvent( MonsterEvent_t *pEvent )
|
||||
{
|
||||
switch( pEvent->event )
|
||||
{
|
||||
case BARNIEL_AE_SHOOT:
|
||||
BarnielFirePistol();
|
||||
break;
|
||||
|
||||
case BARNIEL_AE_DRAW:
|
||||
// barniel's bodygroup switches here so he can pull gun from holster
|
||||
pev->body = BARNIEL_BODY_GUNDRAWN;
|
||||
m_fGunDrawn = TRUE;
|
||||
break;
|
||||
|
||||
case BARNIEL_AE_HOLSTER:
|
||||
// change bodygroup to replace gun in holster
|
||||
pev->body = BARNIEL_BODY_GUNHOLSTERED;
|
||||
m_fGunDrawn = FALSE;
|
||||
break;
|
||||
|
||||
default:
|
||||
CTalkMonster::HandleAnimEvent( pEvent );
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// Spawn
|
||||
//=========================================================
|
||||
void CBarniel :: Spawn()
|
||||
void CBarniel::Spawn()
|
||||
{
|
||||
Precache( );
|
||||
Precache();
|
||||
SET_MODEL( ENT( pev ), "models/barniel.mdl" );
|
||||
UTIL_SetSize( pev, VEC_HUMAN_HULL_MIN, VEC_HUMAN_HULL_MAX );
|
||||
|
||||
SET_MODEL(ENT(pev), "models/barniel.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.barneyHealth;
|
||||
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 npc will notice player and say hello
|
||||
m_MonsterState = MONSTERSTATE_NONE;
|
||||
|
||||
pev->solid = SOLID_SLIDEBOX;
|
||||
pev->movetype = MOVETYPE_STEP;
|
||||
m_bloodColor = BLOOD_COLOR_RED;
|
||||
pev->health = gSkillData.barneyHealth;
|
||||
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 npc will notice player and say hello
|
||||
m_MonsterState = MONSTERSTATE_NONE;
|
||||
pev->body = 0; // gun in holster
|
||||
m_fGunDrawn = FALSE;
|
||||
|
||||
pev->body = 0; // gun in holster
|
||||
m_fGunDrawn = FALSE;
|
||||
m_afCapability = bits_CAP_HEAR | bits_CAP_TURN_HEAD | bits_CAP_DOORS_GROUP;
|
||||
|
||||
m_afCapability = bits_CAP_HEAR | bits_CAP_TURN_HEAD | bits_CAP_DOORS_GROUP;
|
||||
m_cAmmoLoaded = GLOCK_MAX_CLIP;
|
||||
|
||||
m_iCombatState = -1;
|
||||
|
||||
MonsterInit();
|
||||
SetUse( &CBarniel::FollowerUse );
|
||||
SetUse( &CTalkMonster::FollowerUse );
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// Precache - precaches all resources this monster needs
|
||||
//=========================================================
|
||||
void CBarniel :: Precache()
|
||||
void CBarniel::Precache()
|
||||
{
|
||||
PRECACHE_MODEL("models/barniel.mdl");
|
||||
PRECACHE_MODEL( "models/barniel.mdl" );
|
||||
|
||||
PRECACHE_SOUND("barniel/bn_attack1.wav" );
|
||||
PRECACHE_SOUND("barniel/bn_attack2.wav" );
|
||||
PRECACHE_SOUND( "barniel/bn_attack1.wav" );
|
||||
PRECACHE_SOUND( "barniel/bn_attack2.wav" );
|
||||
|
||||
PRECACHE_SOUND("barniel/bn_pain1.wav");
|
||||
//PRECACHE_SOUND("barniel/bn_pain2.wav");
|
||||
//PRECACHE_SOUND("barniel/bn_pain3.wav");
|
||||
PRECACHE_SOUND( "barniel/bn_pain1.wav" );
|
||||
|
||||
PRECACHE_SOUND("barniel/bn_die1.wav");
|
||||
//PRECACHE_SOUND("barniel/bn_die2.wav");
|
||||
//PRECACHE_SOUND("barniel/bn_die3.wav");
|
||||
|
||||
// every new barniel must call this, otherwise
|
||||
PRECACHE_SOUND( "barniel/bn_die1.wav" );
|
||||
|
||||
PRECACHE_SOUND( "weapons/reload3.wav" );
|
||||
|
||||
// every new barney must call this, otherwise
|
||||
// when a level is loaded, nobody will talk (time is reset to 0)
|
||||
TalkInit();
|
||||
CTalkMonster::Precache();
|
||||
}
|
||||
|
||||
// Init talk data
|
||||
void CBarniel :: TalkInit()
|
||||
void CBarniel::TalkInit()
|
||||
{
|
||||
|
||||
CTalkMonster::TalkInit();
|
||||
|
||||
// scientists speach group names (group names are in sentences.txt)
|
||||
|
||||
m_szGrp[TLK_ANSWER] = "BN_ANSWER";
|
||||
m_szGrp[TLK_ANSWER] = "BN_ANSWER";
|
||||
m_szGrp[TLK_QUESTION] = "BN_QUESTION";
|
||||
m_szGrp[TLK_IDLE] = "BN_IDLE";
|
||||
m_szGrp[TLK_STARE] = "BN_STARE";
|
||||
m_szGrp[TLK_USE] = "BN_OK";
|
||||
m_szGrp[TLK_UNUSE] = "BN_WAIT";
|
||||
m_szGrp[TLK_STOP] = "BN_STOP";
|
||||
m_szGrp[TLK_IDLE] = "BN_IDLE";
|
||||
m_szGrp[TLK_STARE] = "BN_STARE";
|
||||
m_szGrp[TLK_USE] = "BN_OK";
|
||||
m_szGrp[TLK_UNUSE] = "BN_WAIT";
|
||||
m_szGrp[TLK_STOP] = "BN_STOP";
|
||||
|
||||
m_szGrp[TLK_NOSHOOT] = "BN_SCARED";
|
||||
m_szGrp[TLK_HELLO] = "BN_HELLO";
|
||||
m_szGrp[TLK_NOSHOOT] = "BN_SCARED";
|
||||
m_szGrp[TLK_HELLO] = "BN_HELLO";
|
||||
|
||||
m_szGrp[TLK_PLHURT1] = "!BN_CUREA";
|
||||
m_szGrp[TLK_PLHURT2] = "!BN_CUREB";
|
||||
m_szGrp[TLK_PLHURT3] = "!BN_CUREC";
|
||||
m_szGrp[TLK_PLHURT1] = "!BN_CUREA";
|
||||
m_szGrp[TLK_PLHURT2] = "!BN_CUREB";
|
||||
m_szGrp[TLK_PLHURT3] = "!BN_CUREC";
|
||||
|
||||
m_szGrp[TLK_PHELLO] = NULL; //"BN_PHELLO"; // UNDONE
|
||||
m_szGrp[TLK_PIDLE] = NULL; //"BN_PIDLE"; // UNDONE
|
||||
m_szGrp[TLK_PHELLO] = "BN_PHELLO"; // UNDONE
|
||||
m_szGrp[TLK_PIDLE] = "BN_PIDLE"; // UNDONE
|
||||
m_szGrp[TLK_PQUESTION] = "BN_PQUEST"; // UNDONE
|
||||
|
||||
m_szGrp[TLK_SMELL] = "BN_SMELL";
|
||||
|
||||
m_szGrp[TLK_WOUND] = "BN_WOUND";
|
||||
m_szGrp[TLK_MORTAL] = "BN_MORTAL";
|
||||
m_szGrp[TLK_SMELL] = "BN_SMELL";
|
||||
|
||||
// get voice for head - just one barniel voice for now
|
||||
m_szGrp[TLK_WOUND] = "BN_WOUND";
|
||||
m_szGrp[TLK_MORTAL] = "BN_MORTAL";
|
||||
|
||||
// get voice for head - just one barney voice for now
|
||||
m_voicePitch = 100;
|
||||
}
|
||||
|
||||
|
||||
static BOOL IsFacing( entvars_t *pevTest, const Vector &reference )
|
||||
{
|
||||
Vector vecDir = (reference - pevTest->origin);
|
||||
Vector vecDir = reference - pevTest->origin;
|
||||
vecDir.z = 0;
|
||||
vecDir = vecDir.Normalize();
|
||||
Vector forward, angle;
|
||||
angle = pevTest->v_angle;
|
||||
angle.x = 0;
|
||||
UTIL_MakeVectorsPrivate( angle, forward, NULL, NULL );
|
||||
|
||||
// He's facing me, he meant it
|
||||
if ( DotProduct( forward, vecDir ) > 0.96 ) // +/- 15 degrees or so
|
||||
if( DotProduct( forward, vecDir ) > 0.96 ) // +/- 15 degrees or so
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
int CBarniel :: TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType)
|
||||
int CBarniel::TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType )
|
||||
{
|
||||
// make sure friends talk about it if player hurts talkmonsters...
|
||||
int ret = CTalkMonster::TakeDamage(pevInflictor, pevAttacker, flDamage, bitsDamageType);
|
||||
if ( !IsAlive() || pev->deadflag == DEAD_DYING )
|
||||
int ret = CTalkMonster::TakeDamage( pevInflictor, pevAttacker, flDamage, bitsDamageType );
|
||||
if( !IsAlive() || pev->deadflag == DEAD_DYING )
|
||||
return ret;
|
||||
|
||||
if ( m_MonsterState != MONSTERSTATE_PRONE && (pevAttacker->flags & FL_CLIENT) )
|
||||
if( m_MonsterState != MONSTERSTATE_PRONE && ( pevAttacker->flags & FL_CLIENT ) )
|
||||
{
|
||||
m_flPlayerDamage += flDamage;
|
||||
|
||||
// This is a heurstic to determine if the player intended to harm me
|
||||
// If I have an enemy, we can't establish intent (may just be crossfire)
|
||||
if ( m_hEnemy == NULL )
|
||||
if( m_hEnemy == 0 )
|
||||
{
|
||||
// If the player was facing directly at me, or I'm already suspicious, get mad
|
||||
if ( (m_afMemory & bits_MEMORY_SUSPICIOUS) || IsFacing( pevAttacker, pev->origin ) )
|
||||
if( ( m_afMemory & bits_MEMORY_SUSPICIOUS ) || IsFacing( pevAttacker, pev->origin ) )
|
||||
{
|
||||
// Alright, now I'm pissed!
|
||||
PlaySentence( "BN_MAD", 4, VOL_NORM, ATTN_NORM );
|
||||
|
@ -537,7 +247,7 @@ int CBarniel :: TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, flo
|
|||
Remember( bits_MEMORY_SUSPICIOUS );
|
||||
}
|
||||
}
|
||||
else if ( !(m_hEnemy->IsPlayer()) && pev->deadflag == DEAD_NO )
|
||||
else if( !( m_hEnemy->IsPlayer()) && pev->deadflag == DEAD_NO )
|
||||
{
|
||||
PlaySentence( "BN_SHOT", 4, VOL_NORM, ATTN_NORM );
|
||||
}
|
||||
|
@ -546,128 +256,25 @@ int CBarniel :: TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, flo
|
|||
return ret;
|
||||
}
|
||||
|
||||
|
||||
//=========================================================
|
||||
// PainSound
|
||||
//=========================================================
|
||||
void CBarniel :: PainSound ( void )
|
||||
void CBarniel::PainSound( void )
|
||||
{
|
||||
if (gpGlobals->time < m_painTime)
|
||||
if( gpGlobals->time < m_painTime )
|
||||
return;
|
||||
|
||||
m_painTime = gpGlobals->time + RANDOM_FLOAT(0.5, 0.75);
|
||||
|
||||
m_painTime = gpGlobals->time + RANDOM_FLOAT( 0.5, 0.75 );
|
||||
|
||||
EMIT_SOUND_DYN( ENT(pev), CHAN_VOICE, "barniel/bn_pain1.wav", 1, ATTN_NORM, 0, GetVoicePitch());
|
||||
|
||||
EMIT_SOUND_DYN( ENT( pev ), CHAN_VOICE, "barniel/bn_pain1.wav", 1, ATTN_NORM, 0, GetVoicePitch() );
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// DeathSound
|
||||
//=========================================================
|
||||
void CBarniel :: DeathSound ( void )
|
||||
void CBarniel::DeathSound( void )
|
||||
{
|
||||
|
||||
EMIT_SOUND_DYN( ENT(pev), CHAN_VOICE, "barniel/bn_die1.wav", 1, ATTN_NORM, 0, GetVoicePitch());
|
||||
|
||||
}
|
||||
|
||||
|
||||
void CBarniel::TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType)
|
||||
{
|
||||
switch( ptr->iHitgroup)
|
||||
{
|
||||
case HITGROUP_CHEST:
|
||||
case HITGROUP_STOMACH:
|
||||
if (bitsDamageType & (DMG_BULLET | DMG_SLASH | DMG_BLAST))
|
||||
{
|
||||
flDamage = flDamage / 2;
|
||||
}
|
||||
break;
|
||||
case 10:
|
||||
if (bitsDamageType & (DMG_BULLET | DMG_SLASH | DMG_CLUB))
|
||||
{
|
||||
flDamage -= 20;
|
||||
if (flDamage <= 0)
|
||||
{
|
||||
UTIL_Ricochet( ptr->vecEndPos, 1.0 );
|
||||
flDamage = 0.01;
|
||||
}
|
||||
}
|
||||
// always a head shot
|
||||
ptr->iHitgroup = HITGROUP_HEAD;
|
||||
break;
|
||||
}
|
||||
|
||||
CTalkMonster::TraceAttack( pevAttacker, flDamage, vecDir, ptr, bitsDamageType );
|
||||
}
|
||||
|
||||
|
||||
void CBarniel::Killed( entvars_t *pevAttacker, int iGib )
|
||||
{
|
||||
if ( pev->body < BARNIEL_BODY_GUNGONE )
|
||||
{// drop the gun!
|
||||
Vector vecGunPos;
|
||||
Vector vecGunAngles;
|
||||
|
||||
pev->body = BARNIEL_BODY_GUNGONE;
|
||||
|
||||
GetAttachment( 0, vecGunPos, vecGunAngles );
|
||||
|
||||
CBaseEntity *pGun = DropItem( "weapon_barney9mmhg", vecGunPos, vecGunAngles );
|
||||
}
|
||||
|
||||
SetUse( NULL );
|
||||
CTalkMonster::Killed( pevAttacker, iGib );
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// AI Schedules Specific to this monster
|
||||
//=========================================================
|
||||
|
||||
Schedule_t* CBarniel :: GetScheduleOfType ( int Type )
|
||||
{
|
||||
Schedule_t *psched;
|
||||
|
||||
switch( Type )
|
||||
{
|
||||
case SCHED_ARM_WEAPON:
|
||||
if ( m_hEnemy != NULL )
|
||||
{
|
||||
// face enemy, then draw.
|
||||
return slBarnielEnemyDraw;
|
||||
}
|
||||
break;
|
||||
|
||||
// Hook these to make a looping schedule
|
||||
case SCHED_TARGET_FACE:
|
||||
// call base class default so that barniel will talk
|
||||
// when 'used'
|
||||
psched = CTalkMonster::GetScheduleOfType(Type);
|
||||
|
||||
if (psched == slIdleStand)
|
||||
return slBa1FaceTarget; // override this for different target face behavior
|
||||
else
|
||||
return psched;
|
||||
|
||||
case SCHED_TARGET_CHASE:
|
||||
return slBa1Follow;
|
||||
|
||||
case SCHED_IDLE_STAND:
|
||||
// call base class default so that scientist will talk
|
||||
// when standing during idle
|
||||
psched = CTalkMonster::GetScheduleOfType(Type);
|
||||
|
||||
if (psched == slIdleStand)
|
||||
{
|
||||
// just look straight ahead.
|
||||
return slIdleBa1Stand;
|
||||
}
|
||||
else
|
||||
return psched;
|
||||
}
|
||||
|
||||
return CTalkMonster::GetScheduleOfType( Type );
|
||||
EMIT_SOUND_DYN( ENT( pev ), CHAN_VOICE, "barniel/bn_die1.wav", 1, ATTN_NORM, 0, GetVoicePitch() );
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
|
@ -676,18 +283,18 @@ Schedule_t* CBarniel :: GetScheduleOfType ( int Type )
|
|||
// monster's member function to get a pointer to a schedule
|
||||
// of the proper type.
|
||||
//=========================================================
|
||||
Schedule_t *CBarniel :: GetSchedule ( void )
|
||||
Schedule_t *CBarniel::GetSchedule( void )
|
||||
{
|
||||
if ( HasConditions( bits_COND_HEAR_SOUND ) )
|
||||
if( HasConditions( bits_COND_HEAR_SOUND ) )
|
||||
{
|
||||
CSound *pSound;
|
||||
pSound = PBestSound();
|
||||
|
||||
ASSERT( pSound != NULL );
|
||||
if ( pSound && (pSound->m_iType & bits_SOUND_DANGER) )
|
||||
if( pSound && (pSound->m_iType & bits_SOUND_DANGER) )
|
||||
return GetScheduleOfType( SCHED_TAKE_COVER_FROM_BEST_SOUND );
|
||||
}
|
||||
if ( HasConditions( bits_COND_ENEMY_DEAD ) && FOkToSpeak() )
|
||||
if( HasConditions( bits_COND_ENEMY_DEAD ) && FOkToSpeak() )
|
||||
{
|
||||
PlaySentence( "BN_KILL", 4, VOL_NORM, ATTN_NORM );
|
||||
}
|
||||
|
@ -696,37 +303,39 @@ Schedule_t *CBarniel :: GetSchedule ( void )
|
|||
{
|
||||
case MONSTERSTATE_COMBAT:
|
||||
{
|
||||
// dead enemy
|
||||
if ( HasConditions( bits_COND_ENEMY_DEAD ) )
|
||||
// dead enemy
|
||||
if( HasConditions( bits_COND_ENEMY_DEAD ) )
|
||||
{
|
||||
// call base class, all code to handle dead enemies is centralized there.
|
||||
return CBaseMonster :: GetSchedule();
|
||||
return CBaseMonster::GetSchedule();
|
||||
}
|
||||
|
||||
// always act surprized with a new enemy
|
||||
if ( HasConditions( bits_COND_NEW_ENEMY ) && HasConditions( bits_COND_LIGHT_DAMAGE) )
|
||||
if( HasConditions( bits_COND_NEW_ENEMY ) && HasConditions( bits_COND_LIGHT_DAMAGE ) )
|
||||
return GetScheduleOfType( SCHED_SMALL_FLINCH );
|
||||
|
||||
|
||||
// wait for one schedule to draw gun
|
||||
if (!m_fGunDrawn )
|
||||
if( !m_fGunDrawn )
|
||||
return GetScheduleOfType( SCHED_ARM_WEAPON );
|
||||
|
||||
if ( HasConditions( bits_COND_HEAVY_DAMAGE ) )
|
||||
if( HasConditions( bits_COND_HEAVY_DAMAGE ) )
|
||||
return GetScheduleOfType( SCHED_TAKE_COVER_FROM_ENEMY );
|
||||
|
||||
if( HasConditions( bits_COND_NO_AMMO_LOADED ) )
|
||||
return GetScheduleOfType( SCHED_BARNEY_COVER_AND_RELOAD );
|
||||
}
|
||||
break;
|
||||
|
||||
case MONSTERSTATE_ALERT:
|
||||
case MONSTERSTATE_IDLE:
|
||||
if ( HasConditions(bits_COND_LIGHT_DAMAGE | bits_COND_HEAVY_DAMAGE))
|
||||
if( HasConditions( bits_COND_LIGHT_DAMAGE | bits_COND_HEAVY_DAMAGE ) )
|
||||
{
|
||||
// flinch if hurt
|
||||
return GetScheduleOfType( SCHED_SMALL_FLINCH );
|
||||
}
|
||||
|
||||
if ( m_hEnemy == NULL && IsFollowing() )
|
||||
if( m_hEnemy == 0 && IsFollowing() )
|
||||
{
|
||||
if ( !m_hTargetEnt->IsAlive() )
|
||||
if( !m_hTargetEnt->IsAlive() )
|
||||
{
|
||||
// UNDONE: Comment about the recently dead player here?
|
||||
StopFollowing( FALSE );
|
||||
|
@ -734,7 +343,7 @@ Schedule_t *CBarniel :: GetSchedule ( void )
|
|||
}
|
||||
else
|
||||
{
|
||||
if ( HasConditions( bits_COND_CLIENT_PUSH ) )
|
||||
if( HasConditions( bits_COND_CLIENT_PUSH ) )
|
||||
{
|
||||
return GetScheduleOfType( SCHED_MOVE_AWAY_FOLLOW );
|
||||
}
|
||||
|
@ -742,7 +351,7 @@ Schedule_t *CBarniel :: GetSchedule ( void )
|
|||
}
|
||||
}
|
||||
|
||||
if ( HasConditions( bits_COND_CLIENT_PUSH ) )
|
||||
if( HasConditions( bits_COND_CLIENT_PUSH ) )
|
||||
{
|
||||
return GetScheduleOfType( SCHED_MOVE_AWAY );
|
||||
}
|
||||
|
@ -750,86 +359,14 @@ Schedule_t *CBarniel :: GetSchedule ( void )
|
|||
// try to say something about smells
|
||||
TrySmellTalk();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return CTalkMonster::GetSchedule();
|
||||
}
|
||||
|
||||
MONSTERSTATE CBarniel :: GetIdealState ( void )
|
||||
{
|
||||
return CTalkMonster::GetIdealState();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CBarniel::DeclineFollowing( void )
|
||||
{
|
||||
PlaySentence( "BN_POK", 2, VOL_NORM, ATTN_NORM );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//=========================================================
|
||||
// DEAD BARNIEL PROP
|
||||
//
|
||||
// Designer selects a pose in worldcraft, 0 through num_poses-1
|
||||
// this value is added to what is selected as the 'first dead pose'
|
||||
// among the monster's normal animations. All dead poses must
|
||||
// appear sequentially in the model file. Be sure and set
|
||||
// the m_iFirstPose properly!
|
||||
//
|
||||
//=========================================================
|
||||
class CDeadBarniel : public CBaseMonster
|
||||
{
|
||||
public:
|
||||
void Spawn( void );
|
||||
int Classify ( void ) { return CLASS_PLAYER_ALLY; }
|
||||
|
||||
void KeyValue( KeyValueData *pkvd );
|
||||
|
||||
int m_iPose;// which sequence to display -- temporary, don't need to save
|
||||
static char *m_szPoses[3];
|
||||
};
|
||||
|
||||
char *CDeadBarniel::m_szPoses[] = { "lying_on_back", "lying_on_side", "lying_on_stomach" };
|
||||
|
||||
void CDeadBarniel::KeyValue( KeyValueData *pkvd )
|
||||
{
|
||||
if (FStrEq(pkvd->szKeyName, "pose"))
|
||||
{
|
||||
m_iPose = atoi(pkvd->szValue);
|
||||
pkvd->fHandled = TRUE;
|
||||
}
|
||||
else
|
||||
CBaseMonster::KeyValue( pkvd );
|
||||
}
|
||||
|
||||
LINK_ENTITY_TO_CLASS( monster_barniel_dead, CDeadBarniel );
|
||||
|
||||
//=========================================================
|
||||
// ********** DeadBarniel SPAWN **********
|
||||
//=========================================================
|
||||
void CDeadBarniel :: Spawn( )
|
||||
{
|
||||
PRECACHE_MODEL("models/barniel.mdl");
|
||||
SET_MODEL(ENT(pev), "models/barniel.mdl");
|
||||
|
||||
pev->effects = 0;
|
||||
pev->yaw_speed = 8;
|
||||
pev->sequence = 0;
|
||||
m_bloodColor = BLOOD_COLOR_RED;
|
||||
|
||||
pev->sequence = LookupSequence( m_szPoses[m_iPose] );
|
||||
if (pev->sequence == -1)
|
||||
{
|
||||
ALERT ( at_console, "Dead barniel with bad pose\n" );
|
||||
}
|
||||
// Corpses have less health
|
||||
pev->health = 8;//gSkillData.barnielHealth;
|
||||
|
||||
MonsterInitDead();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -94,6 +94,11 @@ BOOL CBeretta::Deploy( )
|
|||
return DefaultDeploy( "models/v_9mmberetta.mdl", "models/p_9mmberetta.mdl", BERETTA_DRAW, "onehanded", /*UseDecrement() ? 1 : 0*/ 0 );
|
||||
}
|
||||
|
||||
void CBeretta::Holster( int skiplocal /* = 0 */ )
|
||||
{
|
||||
DefaultHolster( BERETTA_HOLSTER, 1.2 );
|
||||
}
|
||||
|
||||
void CBeretta::SecondaryAttack( void )
|
||||
{
|
||||
BerettaFire( 0.1, 0.2, FALSE );
|
||||
|
@ -106,12 +111,18 @@ void CBeretta::PrimaryAttack( void )
|
|||
|
||||
void CBeretta::BerettaFire( float flSpread , float flCycleTime, BOOL fUseAutoAim )
|
||||
{
|
||||
if( m_pPlayer->m_bIsHolster )
|
||||
{
|
||||
WeaponIdle();
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_iClip <= 0)
|
||||
{
|
||||
if (m_fFireOnEmpty)
|
||||
{
|
||||
PlayEmptySound();
|
||||
m_flNextPrimaryAttack = GetNextAttackDelay(0.2);
|
||||
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.2f;
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -162,7 +173,7 @@ void CBeretta::BerettaFire( float flSpread , float flCycleTime, BOOL fUseAutoAim
|
|||
|
||||
PLAYBACK_EVENT_FULL( flags, m_pPlayer->edict(), fUseAutoAim ? m_usFireBeretta1 : m_usFireBeretta2, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, vecDir.x, vecDir.y, 0, 0, ( m_iClip == 0 ) ? 1 : 0, 0 );
|
||||
|
||||
m_flNextPrimaryAttack = m_flNextSecondaryAttack = GetNextAttackDelay(flCycleTime);
|
||||
m_flNextPrimaryAttack = m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + flCycleTime;
|
||||
|
||||
if (!m_iClip && m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0)
|
||||
// HEV suit - indicate out of ammo condition
|
||||
|
@ -174,15 +185,21 @@ void CBeretta::BerettaFire( float flSpread , float flCycleTime, BOOL fUseAutoAim
|
|||
|
||||
void CBeretta::Reload( void )
|
||||
{
|
||||
if ( m_pPlayer->ammo_9mm <= 0 )
|
||||
return;
|
||||
if( m_pPlayer->m_bIsHolster )
|
||||
{
|
||||
WeaponIdle();
|
||||
return;
|
||||
}
|
||||
|
||||
if( m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0 || m_iClip == BERETTA_MAX_CLIP )
|
||||
return;
|
||||
|
||||
int iResult;
|
||||
|
||||
if (m_iClip == 0)
|
||||
iResult = DefaultReload( 17, BERETTA_RELOAD, 1.5 );
|
||||
iResult = DefaultReload( BERETTA_MAX_CLIP, BERETTA_RELOAD, 1.5 );
|
||||
else
|
||||
iResult = DefaultReload( 17, BERETTA_RELOAD_NOT_EMPTY, 1.5 );
|
||||
iResult = DefaultReload( BERETTA_MAX_CLIP, BERETTA_RELOAD_NOT_EMPTY, 1.5 );
|
||||
|
||||
if (iResult)
|
||||
{
|
||||
|
@ -190,11 +207,19 @@ void CBeretta::Reload( void )
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CBeretta::WeaponIdle( void )
|
||||
{
|
||||
ResetEmptySound( );
|
||||
if( m_pPlayer->m_bIsHolster )
|
||||
{
|
||||
if( m_flTimeWeaponIdle <= UTIL_WeaponTimeBase() )
|
||||
{
|
||||
m_pPlayer->m_bIsHolster = FALSE;
|
||||
Deploy();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
ResetEmptySound();
|
||||
|
||||
m_pPlayer->GetAutoaimVector( AUTOAIM_10DEGREES );
|
||||
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
/***
|
||||
*
|
||||
* 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 "basemonster.h"
|
||||
|
||||
#define SF_BODYPART_RANDOMYAW (1U << 3)
|
||||
|
||||
class CBodyPart : public CBaseMonster
|
||||
{
|
||||
public:
|
||||
void Spawn();
|
||||
void Precache();
|
||||
int Classify();
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS( monster_bodypart, CBodyPart )
|
||||
|
||||
int CBodyPart::Classify()
|
||||
{
|
||||
return CLASS_INSECT;
|
||||
}
|
||||
|
||||
void CBodyPart::Spawn()
|
||||
{
|
||||
Precache();
|
||||
SET_MODEL( ENT( pev ), STRING( pev->model ) );
|
||||
|
||||
pev->movetype = MOVETYPE_NONE;
|
||||
pev->solid = SOLID_NOT;
|
||||
|
||||
m_bloodColor = BLOOD_COLOR_RED;
|
||||
m_MonsterState = MONSTERSTATE_NONE;
|
||||
|
||||
pev->health = 80000; // !!!
|
||||
pev->takedamage = DAMAGE_NO;
|
||||
pev->deadflag = DEAD_DEAD;
|
||||
pev->effects = 0;
|
||||
pev->sequence = 0;
|
||||
|
||||
if( FBitSet( pev->spawnflags, SF_BODYPART_RANDOMYAW ) )
|
||||
{
|
||||
pev->angles = Vector( 0, RANDOM_LONG( 0, 360 ), 0 );
|
||||
}
|
||||
}
|
||||
|
||||
void CBodyPart::Precache()
|
||||
{
|
||||
int iRand;
|
||||
|
||||
switch( pev->body )
|
||||
{
|
||||
default:
|
||||
case 0:
|
||||
iRand = RANDOM_LONG( 0, 8 );
|
||||
if( iRand == 8 )
|
||||
{
|
||||
pev->model = MAKE_STRING( "models/gib_hgrunt.mdl" );
|
||||
pev->body = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
pev->model = MAKE_STRING( "models/hgibs.mdl" );
|
||||
pev->body = ( iRand == 7 ) ? RANDOM_LONG( 7, 10 ) : iRand;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
pev->model = MAKE_STRING( "models/hgibs.mdl" );
|
||||
iRand = RANDOM_LONG( 0, 7 );
|
||||
pev->body = ( iRand == 7 ) ? RANDOM_LONG( 7, 10 ) : iRand;
|
||||
break;
|
||||
case 2:
|
||||
pev->model = MAKE_STRING( "models/gib_hgrunt.mdl" );
|
||||
pev->body = 0;
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
case 8:
|
||||
case 9:
|
||||
case 10:
|
||||
case 11:
|
||||
case 12:
|
||||
case 13:
|
||||
pev->model = MAKE_STRING( "models/hgibs.mdl" );
|
||||
pev->body -= 3;
|
||||
break;
|
||||
}
|
||||
PRECACHE_MODEL( STRING( pev->model ) );
|
||||
}
|
|
@ -0,0 +1,186 @@
|
|||
/***
|
||||
*
|
||||
* 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 "basemonster.h"
|
||||
|
||||
#define SF_GARBAGE_RANDOMYAW (1U << 3)
|
||||
|
||||
// garbage's bodygroups
|
||||
#define STRAINEDPAPER1 0
|
||||
#define STRAINEDPAPER2 1
|
||||
#define STRAINEDPAPER3 2
|
||||
#define GLASS 4
|
||||
#define SANDWICH 5
|
||||
#define APPLE 6
|
||||
#define BANANA 7
|
||||
#define MAGAZINE 8
|
||||
#define BROWNPAPER 9
|
||||
#define BLUECAN 11
|
||||
|
||||
class CGarbage : public CBaseMonster
|
||||
{
|
||||
public:
|
||||
void Spawn();
|
||||
void Precache();
|
||||
int Classify();
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS( monster_garbage, CGarbage )
|
||||
|
||||
int CGarbage::Classify()
|
||||
{
|
||||
return CLASS_INSECT;
|
||||
}
|
||||
|
||||
void CGarbage::Spawn()
|
||||
{
|
||||
Precache();
|
||||
SET_MODEL( ENT( pev ), STRING( pev->model ) );
|
||||
|
||||
pev->movetype = MOVETYPE_NONE;
|
||||
pev->solid = SOLID_NOT;
|
||||
|
||||
m_bloodColor = DONT_BLEED;
|
||||
m_MonsterState = MONSTERSTATE_NONE;
|
||||
|
||||
pev->health = 80000; // !!!
|
||||
pev->takedamage = DAMAGE_NO;
|
||||
pev->deadflag = DEAD_DEAD;
|
||||
pev->effects = 0;
|
||||
pev->sequence = 0;
|
||||
|
||||
if( FBitSet( pev->spawnflags, SF_GARBAGE_RANDOMYAW ) )
|
||||
{
|
||||
pev->angles = Vector( 0, RANDOM_LONG( 0, 360 ), 0 );
|
||||
}
|
||||
}
|
||||
|
||||
void CGarbage::Precache()
|
||||
{
|
||||
int iRand;
|
||||
|
||||
switch( pev->body )
|
||||
{
|
||||
default:
|
||||
case 0:
|
||||
iRand = RANDOM_LONG( 0, 8 );
|
||||
pev->model = MAKE_STRING( "models/garbagegibs.mdl" );
|
||||
switch( iRand )
|
||||
{
|
||||
case 1:
|
||||
pev->body = STRAINEDPAPER1;
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
pev->body = STRAINEDPAPER2;
|
||||
break;
|
||||
case 4:
|
||||
pev->body = GLASS;
|
||||
break;
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
pev->body = iRand + 1;
|
||||
break;
|
||||
default:
|
||||
pev->body = BROWNPAPER;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
pev->body = RANDOM_LONG( 0, 2 );
|
||||
pev->model = MAKE_STRING( "models/garbagegibs.mdl" );
|
||||
break;
|
||||
case 2:
|
||||
iRand = RANDOM_LONG( 4, 8 );
|
||||
if( iRand == 8 )
|
||||
{
|
||||
if( RANDOM_LONG( 0, 1 ) )
|
||||
{
|
||||
pev->model = MAKE_STRING( "models/garbagegibs.mdl" );
|
||||
pev->body = 11;
|
||||
}
|
||||
else
|
||||
{
|
||||
pev->model = MAKE_STRING( "models/can.mdl" );
|
||||
pev->body = 0;
|
||||
pev->skin = RANDOM_LONG( 0, 5 );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pev->model = MAKE_STRING( "models/garbagegibs.mdl" );
|
||||
pev->body = iRand;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
pev->model = MAKE_STRING( "models/garbagegibs.mdl" );
|
||||
pev->body = RANDOM_LONG( 8, 9 );
|
||||
break;
|
||||
case 4:
|
||||
iRand = RANDOM_LONG( 0, 6 );
|
||||
if( iRand == 6 )
|
||||
{
|
||||
pev->model = MAKE_STRING( "models/garbagegibs.mdl" );
|
||||
pev->body = BLUECAN;
|
||||
}
|
||||
else
|
||||
{
|
||||
pev->model = MAKE_STRING( "models/can.mdl" );
|
||||
pev->body = 0;
|
||||
pev->skin = iRand;
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
pev->model = MAKE_STRING( "models/garbagegibs.mdl" );
|
||||
pev->body = STRAINEDPAPER1;
|
||||
break;
|
||||
case 6:
|
||||
case 7:
|
||||
pev->model = MAKE_STRING( "models/garbagegibs.mdl" );
|
||||
pev->body = STRAINEDPAPER2;
|
||||
break;
|
||||
case 8:
|
||||
case 9:
|
||||
case 10:
|
||||
case 11:
|
||||
pev->model = MAKE_STRING( "models/garbagegibs.mdl" );
|
||||
pev->body -= 4;
|
||||
break;
|
||||
case 12:
|
||||
case 13:
|
||||
case 14:
|
||||
case 15:
|
||||
case 16:
|
||||
case 17:
|
||||
pev->model = MAKE_STRING( "models/can.mdl" );
|
||||
pev->skin = pev->body - 12;
|
||||
pev->body = 0;
|
||||
break;
|
||||
case 18:
|
||||
pev->model = MAKE_STRING( "models/garbagegibs.mdl" );
|
||||
pev->body = BLUECAN;
|
||||
break;
|
||||
case 19:
|
||||
case 20:
|
||||
pev->model = MAKE_STRING( "models/garbagegibs.mdl" );
|
||||
pev->body -= 11;
|
||||
break;
|
||||
}
|
||||
PRECACHE_MODEL( STRING( pev->model ) );
|
||||
}
|
|
@ -1,844 +0,0 @@
|
|||
/***
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
****/
|
||||
//=========================================================
|
||||
// monster template
|
||||
//=========================================================
|
||||
// UNDONE: Holster weapon?
|
||||
|
||||
#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 "weapons.h"
|
||||
#include "soundent.h"
|
||||
|
||||
//=========================================================
|
||||
// Monster's Anim Events Go Here
|
||||
//=========================================================
|
||||
// first flag is barney dying for scripted sequences?
|
||||
#define GORDON_AE_DRAW ( 2 )
|
||||
#define GORDON_AE_SHOOT ( 3 )
|
||||
#define GORDON_AE_HOLSTER ( 4 )
|
||||
|
||||
#define GORDON_BODY_GUNHOLSTERED 0
|
||||
#define GORDON_BODY_GUNDRAWN 1
|
||||
#define GORDON_BODY_GUNGONE 2
|
||||
|
||||
class CGordon : public CTalkMonster
|
||||
{
|
||||
public:
|
||||
void Spawn( void );
|
||||
void Precache( void );
|
||||
void SetYawSpeed( void );
|
||||
int ISoundMask( void );
|
||||
void GordonFirePistol( 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_gordon, CGordon );
|
||||
|
||||
TYPEDESCRIPTION CGordon::m_SaveData[] =
|
||||
{
|
||||
DEFINE_FIELD( CGordon, m_fGunDrawn, FIELD_BOOLEAN ),
|
||||
DEFINE_FIELD( CGordon, m_painTime, FIELD_TIME ),
|
||||
DEFINE_FIELD( CGordon, m_checkAttackTime, FIELD_TIME ),
|
||||
DEFINE_FIELD( CGordon, m_lastAttackCheck, FIELD_BOOLEAN ),
|
||||
DEFINE_FIELD( CGordon, m_flPlayerDamage, FIELD_FLOAT ),
|
||||
};
|
||||
|
||||
IMPLEMENT_SAVERESTORE( CGordon, CTalkMonster );
|
||||
|
||||
//=========================================================
|
||||
// AI Schedules Specific to this monster
|
||||
//=========================================================
|
||||
Task_t tlGoFollow[] =
|
||||
{
|
||||
{ TASK_MOVE_TO_TARGET_RANGE,(float)128 }, // Move within 128 of target ent (client)
|
||||
{ TASK_SET_SCHEDULE, (float)SCHED_TARGET_FACE },
|
||||
};
|
||||
|
||||
Schedule_t slGoFollow[] =
|
||||
{
|
||||
{
|
||||
tlGoFollow,
|
||||
ARRAYSIZE ( tlGoFollow ),
|
||||
bits_COND_NEW_ENEMY |
|
||||
bits_COND_LIGHT_DAMAGE |
|
||||
bits_COND_HEAVY_DAMAGE |
|
||||
bits_COND_HEAR_SOUND |
|
||||
bits_COND_PROVOKED,
|
||||
bits_SOUND_DANGER,
|
||||
"Follow"
|
||||
},
|
||||
};
|
||||
|
||||
//=========================================================
|
||||
// GordonDraw- much better looking draw schedule for when
|
||||
// barney knows who he's gonna attack.
|
||||
//=========================================================
|
||||
Task_t tlGordonEnemyDraw[] =
|
||||
{
|
||||
{ TASK_STOP_MOVING, 0 },
|
||||
{ TASK_FACE_ENEMY, 0 },
|
||||
{ TASK_PLAY_SEQUENCE_FACE_ENEMY, (float) ACT_ARM },
|
||||
};
|
||||
|
||||
Schedule_t slGordonEnemyDraw[] =
|
||||
{
|
||||
{
|
||||
tlGordonEnemyDraw,
|
||||
ARRAYSIZE ( tlGordonEnemyDraw ),
|
||||
0,
|
||||
0,
|
||||
"Gordon Enemy Draw"
|
||||
}
|
||||
};
|
||||
|
||||
Task_t tlGoFaceTarget[] =
|
||||
{
|
||||
{ TASK_SET_ACTIVITY, (float)ACT_IDLE },
|
||||
{ TASK_FACE_TARGET, (float)0 },
|
||||
{ TASK_SET_ACTIVITY, (float)ACT_IDLE },
|
||||
{ TASK_SET_SCHEDULE, (float)SCHED_TARGET_CHASE },
|
||||
};
|
||||
|
||||
Schedule_t slGoFaceTarget[] =
|
||||
{
|
||||
{
|
||||
tlGoFaceTarget,
|
||||
ARRAYSIZE ( tlGoFaceTarget ),
|
||||
bits_COND_CLIENT_PUSH |
|
||||
bits_COND_NEW_ENEMY |
|
||||
bits_COND_LIGHT_DAMAGE |
|
||||
bits_COND_HEAVY_DAMAGE |
|
||||
bits_COND_HEAR_SOUND |
|
||||
bits_COND_PROVOKED,
|
||||
bits_SOUND_DANGER,
|
||||
"FaceTarget"
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
Task_t tlIdleGoStand[] =
|
||||
{
|
||||
{ TASK_STOP_MOVING, 0 },
|
||||
{ TASK_SET_ACTIVITY, (float)ACT_IDLE },
|
||||
{ TASK_WAIT, (float)2 }, // repick IDLESTAND every two seconds.
|
||||
{ TASK_TLK_HEADRESET, (float)0 }, // reset head position
|
||||
};
|
||||
|
||||
Schedule_t slIdleGoStand[] =
|
||||
{
|
||||
{
|
||||
tlIdleGoStand,
|
||||
ARRAYSIZE ( tlIdleGoStand ),
|
||||
bits_COND_NEW_ENEMY |
|
||||
bits_COND_LIGHT_DAMAGE |
|
||||
bits_COND_HEAVY_DAMAGE |
|
||||
bits_COND_HEAR_SOUND |
|
||||
bits_COND_SMELL |
|
||||
bits_COND_PROVOKED,
|
||||
|
||||
bits_SOUND_COMBAT |// sound flags - change these, and you'll break the talking code.
|
||||
//bits_SOUND_PLAYER |
|
||||
//bits_SOUND_WORLD |
|
||||
|
||||
bits_SOUND_DANGER |
|
||||
bits_SOUND_MEAT |// scents
|
||||
bits_SOUND_CARCASS |
|
||||
bits_SOUND_GARBAGE,
|
||||
"IdleStand"
|
||||
},
|
||||
};
|
||||
|
||||
DEFINE_CUSTOM_SCHEDULES( CGordon )
|
||||
{
|
||||
slGoFollow,
|
||||
slGordonEnemyDraw,
|
||||
slGoFaceTarget,
|
||||
slIdleGoStand,
|
||||
};
|
||||
|
||||
|
||||
IMPLEMENT_CUSTOM_SCHEDULES( CGordon, CTalkMonster );
|
||||
|
||||
void CGordon :: StartTask( Task_t *pTask )
|
||||
{
|
||||
CTalkMonster::StartTask( pTask );
|
||||
}
|
||||
|
||||
void CGordon :: RunTask( Task_t *pTask )
|
||||
{
|
||||
switch ( pTask->iTask )
|
||||
{
|
||||
case TASK_RANGE_ATTACK1:
|
||||
if (m_hEnemy != NULL && (m_hEnemy->IsPlayer()))
|
||||
{
|
||||
pev->framerate = 1.5;
|
||||
}
|
||||
CTalkMonster::RunTask( pTask );
|
||||
break;
|
||||
default:
|
||||
CTalkMonster::RunTask( pTask );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//=========================================================
|
||||
// ISoundMask - returns a bit mask indicating which types
|
||||
// of sounds this monster regards.
|
||||
//=========================================================
|
||||
int CGordon :: ISoundMask ( void)
|
||||
{
|
||||
return bits_SOUND_WORLD |
|
||||
bits_SOUND_COMBAT |
|
||||
bits_SOUND_CARCASS |
|
||||
bits_SOUND_MEAT |
|
||||
bits_SOUND_GARBAGE |
|
||||
bits_SOUND_DANGER |
|
||||
bits_SOUND_PLAYER;
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// Classify - indicates this monster's place in the
|
||||
// relationship table.
|
||||
//=========================================================
|
||||
int CGordon :: Classify ( void )
|
||||
{
|
||||
return CLASS_PLAYER_ALLY;
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// ALertSound - barney says "Freeze!"
|
||||
//=========================================================
|
||||
void CGordon :: AlertSound( void )
|
||||
{
|
||||
if ( m_hEnemy != NULL )
|
||||
{
|
||||
if ( FOkToSpeak() )
|
||||
{
|
||||
PlaySentence( "GO_ATTACK", RANDOM_FLOAT(2.8, 3.2), VOL_NORM, ATTN_IDLE );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
//=========================================================
|
||||
// SetYawSpeed - allows each sequence to have a different
|
||||
// turn rate associated with it.
|
||||
//=========================================================
|
||||
void CGordon :: SetYawSpeed ( void )
|
||||
{
|
||||
int ys;
|
||||
|
||||
ys = 0;
|
||||
|
||||
switch ( m_Activity )
|
||||
{
|
||||
case ACT_IDLE:
|
||||
ys = 70;
|
||||
break;
|
||||
case ACT_WALK:
|
||||
ys = 70;
|
||||
break;
|
||||
case ACT_RUN:
|
||||
ys = 90;
|
||||
break;
|
||||
default:
|
||||
ys = 70;
|
||||
break;
|
||||
}
|
||||
|
||||
pev->yaw_speed = ys;
|
||||
}
|
||||
|
||||
|
||||
//=========================================================
|
||||
// CheckRangeAttack1
|
||||
//=========================================================
|
||||
BOOL CGordon :: CheckRangeAttack1 ( float flDot, float flDist )
|
||||
{
|
||||
if ( flDist <= 1024 && flDot >= 0.5 )
|
||||
{
|
||||
if ( gpGlobals->time > m_checkAttackTime )
|
||||
{
|
||||
TraceResult tr;
|
||||
|
||||
Vector shootOrigin = pev->origin + Vector( 0, 0, 55 );
|
||||
CBaseEntity *pEnemy = m_hEnemy;
|
||||
Vector shootTarget = ( (pEnemy->BodyTarget( shootOrigin ) - pEnemy->pev->origin) + m_vecEnemyLKP );
|
||||
UTIL_TraceLine( shootOrigin, shootTarget, dont_ignore_monsters, ENT(pev), &tr );
|
||||
m_checkAttackTime = gpGlobals->time + 1;
|
||||
if ( tr.flFraction == 1.0 || (tr.pHit != NULL && CBaseEntity::Instance(tr.pHit) == pEnemy) )
|
||||
m_lastAttackCheck = TRUE;
|
||||
else
|
||||
m_lastAttackCheck = FALSE;
|
||||
m_checkAttackTime = gpGlobals->time + 1.5;
|
||||
}
|
||||
return m_lastAttackCheck;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
//=========================================================
|
||||
// GordonFirePistol - shoots one round from the pistol at
|
||||
// the enemy barney is facing.
|
||||
//=========================================================
|
||||
void CGordon :: GordonFirePistol ( void )
|
||||
{
|
||||
Vector vecShootOrigin;
|
||||
|
||||
UTIL_MakeVectors(pev->angles);
|
||||
vecShootOrigin = pev->origin + Vector( 0, 0, 55 );
|
||||
Vector vecShootDir = ShootAtEnemy( vecShootOrigin );
|
||||
|
||||
Vector angDir = UTIL_VecToAngles( vecShootDir );
|
||||
SetBlending( 0, angDir.x );
|
||||
pev->effects = EF_MUZZLEFLASH;
|
||||
|
||||
FireBullets(1, vecShootOrigin, vecShootDir, VECTOR_CONE_2DEGREES, 1024, BULLET_MONSTER_9MM );
|
||||
|
||||
int pitchShift = RANDOM_LONG( 0, 20 );
|
||||
|
||||
// Only shift about half the time
|
||||
if ( pitchShift > 10 )
|
||||
pitchShift = 0;
|
||||
else
|
||||
pitchShift -= 5;
|
||||
EMIT_SOUND_DYN( ENT(pev), CHAN_WEAPON, "gordon/go_attack2.wav", 1, ATTN_NORM, 0, 100 + pitchShift );
|
||||
|
||||
CSoundEnt::InsertSound ( bits_SOUND_COMBAT, pev->origin, 384, 0.3 );
|
||||
|
||||
// UNDONE: Reload?
|
||||
m_cAmmoLoaded--;// take away a bullet!
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// HandleAnimEvent - catches the monster-specific messages
|
||||
// that occur when tagged animation frames are played.
|
||||
//
|
||||
// Returns number of events handled, 0 if none.
|
||||
//=========================================================
|
||||
void CGordon :: HandleAnimEvent( MonsterEvent_t *pEvent )
|
||||
{
|
||||
switch( pEvent->event )
|
||||
{
|
||||
case GORDON_AE_SHOOT:
|
||||
GordonFirePistol();
|
||||
break;
|
||||
|
||||
case GORDON_AE_DRAW:
|
||||
// barney's bodygroup switches here so he can pull gun from holster
|
||||
pev->body = GORDON_BODY_GUNDRAWN;
|
||||
m_fGunDrawn = TRUE;
|
||||
break;
|
||||
|
||||
case GORDON_AE_HOLSTER:
|
||||
// change bodygroup to replace gun in holster
|
||||
pev->body = GORDON_BODY_GUNHOLSTERED;
|
||||
m_fGunDrawn = FALSE;
|
||||
break;
|
||||
|
||||
default:
|
||||
CTalkMonster::HandleAnimEvent( pEvent );
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// Spawn
|
||||
//=========================================================
|
||||
void CGordon :: Spawn()
|
||||
{
|
||||
Precache( );
|
||||
|
||||
SET_MODEL(ENT(pev), "models/freeman.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.barneyHealth;
|
||||
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 npc will notice player and say hello
|
||||
m_MonsterState = MONSTERSTATE_NONE;
|
||||
|
||||
pev->body = 0; // gun in holster
|
||||
m_fGunDrawn = FALSE;
|
||||
|
||||
m_afCapability = bits_CAP_HEAR | bits_CAP_TURN_HEAD | bits_CAP_DOORS_GROUP;
|
||||
|
||||
MonsterInit();
|
||||
SetUse( &CGordon::FollowerUse );
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// Precache - precaches all resources this monster needs
|
||||
//=========================================================
|
||||
void CGordon :: Precache()
|
||||
{
|
||||
PRECACHE_MODEL("models/freeman.mdl");
|
||||
|
||||
PRECACHE_SOUND("gordon/go_attack1.wav" );
|
||||
PRECACHE_SOUND("gordon/go_attack2.wav" );
|
||||
|
||||
PRECACHE_SOUND("gordon/go_pain1.wav");
|
||||
PRECACHE_SOUND("gordon/go_pain2.wav");
|
||||
PRECACHE_SOUND("gordon/go_pain3.wav");
|
||||
|
||||
PRECACHE_SOUND("gordon/go_die1.wav");
|
||||
PRECACHE_SOUND("gordon/go_die2.wav");
|
||||
PRECACHE_SOUND("gordon/go_die3.wav");
|
||||
PRECACHE_SOUND("gordon/go_duty.wav");
|
||||
PRECACHE_SOUND("gordon/go_post.wav");
|
||||
//PRECACHE_SOUND("gordon/goon.wav");
|
||||
|
||||
// every new barney must call this, otherwise
|
||||
// when a level is loaded, nobody will talk (time is reset to 0)
|
||||
TalkInit();
|
||||
CTalkMonster::Precache();
|
||||
}
|
||||
|
||||
// Init talk data
|
||||
void CGordon :: TalkInit()
|
||||
{
|
||||
|
||||
CTalkMonster::TalkInit();
|
||||
|
||||
// scientists speach group names (group names are in sentences.txt)
|
||||
|
||||
m_szGrp[TLK_ANSWER] = "GO_ANSWER";
|
||||
m_szGrp[TLK_QUESTION] = "GO_QUESTION";
|
||||
m_szGrp[TLK_IDLE] = "GO_IDLE";
|
||||
m_szGrp[TLK_STARE] = "GO_STARE";
|
||||
m_szGrp[TLK_USE] = "GO_OK";
|
||||
m_szGrp[TLK_UNUSE] = "GO_WAIT";
|
||||
m_szGrp[TLK_STOP] = "GO_STOP";
|
||||
|
||||
m_szGrp[TLK_NOSHOOT] = "GO_SCARED";
|
||||
m_szGrp[TLK_HELLO] = "GO_HELLO";
|
||||
|
||||
m_szGrp[TLK_PLHURT1] = "!BA_CUREA";
|
||||
m_szGrp[TLK_PLHURT2] = "!BA_CUREB";
|
||||
m_szGrp[TLK_PLHURT3] = "!BA_CUREC";
|
||||
|
||||
m_szGrp[TLK_PHELLO] = NULL; //"GO_PHELLO"; // UNDONE
|
||||
m_szGrp[TLK_PIDLE] = NULL; //"GO_PIDLE"; // UNDONE
|
||||
m_szGrp[TLK_PQUESTION] = "GO_PQUEST"; // UNDONE
|
||||
|
||||
m_szGrp[TLK_SMELL] = "GO_SMELL";
|
||||
|
||||
m_szGrp[TLK_WOUND] = "GO_WOUND";
|
||||
m_szGrp[TLK_MORTAL] = "GO_MORTAL";
|
||||
|
||||
// get voice for head - just one barney voice for now
|
||||
m_voicePitch = 100;
|
||||
}
|
||||
|
||||
|
||||
static BOOL IsFacing( entvars_t *pevTest, const Vector &reference )
|
||||
{
|
||||
Vector vecDir = (reference - pevTest->origin);
|
||||
vecDir.z = 0;
|
||||
vecDir = vecDir.Normalize();
|
||||
Vector forward, angle;
|
||||
angle = pevTest->v_angle;
|
||||
angle.x = 0;
|
||||
UTIL_MakeVectorsPrivate( angle, forward, NULL, NULL );
|
||||
// He's facing me, he meant it
|
||||
if ( DotProduct( forward, vecDir ) > 0.96 ) // +/- 15 degrees or so
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
int CGordon :: TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType)
|
||||
{
|
||||
// make sure friends talk about it if player hurts talkmonsters...
|
||||
int ret = CTalkMonster::TakeDamage(pevInflictor, pevAttacker, flDamage, bitsDamageType);
|
||||
if ( !IsAlive() || pev->deadflag == DEAD_DYING )
|
||||
return ret;
|
||||
|
||||
if ( m_MonsterState != MONSTERSTATE_PRONE && (pevAttacker->flags & FL_CLIENT) )
|
||||
{
|
||||
m_flPlayerDamage += flDamage;
|
||||
|
||||
// This is a heurstic to determine if the player intended to harm me
|
||||
// If I have an enemy, we can't establish intent (may just be crossfire)
|
||||
if ( m_hEnemy == NULL )
|
||||
{
|
||||
// If the player was facing directly at me, or I'm already suspicious, get mad
|
||||
if ( (m_afMemory & bits_MEMORY_SUSPICIOUS) || IsFacing( pevAttacker, pev->origin ) )
|
||||
{
|
||||
// Alright, now I'm pissed!
|
||||
PlaySentence( "GO_MAD", 4, VOL_NORM, ATTN_NORM );
|
||||
|
||||
Remember( bits_MEMORY_PROVOKED );
|
||||
StopFollowing( TRUE );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Hey, be careful with that
|
||||
PlaySentence( "GO_SHOT", 4, VOL_NORM, ATTN_NORM );
|
||||
Remember( bits_MEMORY_SUSPICIOUS );
|
||||
}
|
||||
}
|
||||
else if ( !(m_hEnemy->IsPlayer()) && pev->deadflag == DEAD_NO )
|
||||
{
|
||||
PlaySentence( "GO_SHOT", 4, VOL_NORM, ATTN_NORM );
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
//=========================================================
|
||||
// PainSound
|
||||
//=========================================================
|
||||
void CGordon :: PainSound ( void )
|
||||
{
|
||||
if (gpGlobals->time < m_painTime)
|
||||
return;
|
||||
|
||||
m_painTime = gpGlobals->time + RANDOM_FLOAT(0.5, 0.75);
|
||||
|
||||
switch (RANDOM_LONG(0,2))
|
||||
{
|
||||
case 0: EMIT_SOUND_DYN( ENT(pev), CHAN_VOICE, "gordon/go_pain1.wav", 1, ATTN_NORM, 0, GetVoicePitch()); break;
|
||||
case 1: EMIT_SOUND_DYN( ENT(pev), CHAN_VOICE, "gordon/go_pain2.wav", 1, ATTN_NORM, 0, GetVoicePitch()); break;
|
||||
case 2: EMIT_SOUND_DYN( ENT(pev), CHAN_VOICE, "gordon/go_pain3.wav", 1, ATTN_NORM, 0, GetVoicePitch()); break;
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// DeathSound
|
||||
//=========================================================
|
||||
void CGordon :: DeathSound ( void )
|
||||
{
|
||||
switch (RANDOM_LONG(0,2))
|
||||
{
|
||||
case 0: EMIT_SOUND_DYN( ENT(pev), CHAN_VOICE, "gordon/go_die1.wav", 1, ATTN_NORM, 0, GetVoicePitch()); break;
|
||||
case 1: EMIT_SOUND_DYN( ENT(pev), CHAN_VOICE, "gordon/go_die2.wav", 1, ATTN_NORM, 0, GetVoicePitch()); break;
|
||||
case 2: EMIT_SOUND_DYN( ENT(pev), CHAN_VOICE, "gordon/go_die3.wav", 1, ATTN_NORM, 0, GetVoicePitch()); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CGordon::TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType)
|
||||
{
|
||||
switch( ptr->iHitgroup)
|
||||
{
|
||||
case HITGROUP_CHEST:
|
||||
case HITGROUP_STOMACH:
|
||||
if (bitsDamageType & (DMG_BULLET | DMG_SLASH | DMG_BLAST))
|
||||
{
|
||||
flDamage = flDamage / 2;
|
||||
}
|
||||
break;
|
||||
case 10:
|
||||
if (bitsDamageType & (DMG_BULLET | DMG_SLASH | DMG_CLUB))
|
||||
{
|
||||
flDamage -= 20;
|
||||
if (flDamage <= 0)
|
||||
{
|
||||
UTIL_Ricochet( ptr->vecEndPos, 1.0 );
|
||||
flDamage = 0.01;
|
||||
}
|
||||
}
|
||||
// always a head shot
|
||||
ptr->iHitgroup = HITGROUP_HEAD;
|
||||
break;
|
||||
}
|
||||
|
||||
CTalkMonster::TraceAttack( pevAttacker, flDamage, vecDir, ptr, bitsDamageType );
|
||||
}
|
||||
|
||||
|
||||
void CGordon::Killed( entvars_t *pevAttacker, int iGib )
|
||||
{
|
||||
if ( pev->body < GORDON_BODY_GUNGONE )
|
||||
{// drop the gun!
|
||||
Vector vecGunPos;
|
||||
Vector vecGunAngles;
|
||||
|
||||
pev->body = GORDON_BODY_GUNGONE;
|
||||
|
||||
GetAttachment( 0, vecGunPos, vecGunAngles );
|
||||
|
||||
CBaseEntity *pGun = DropItem( "weapon_barney9mmhg", vecGunPos, vecGunAngles );
|
||||
}
|
||||
|
||||
SetUse( NULL );
|
||||
CTalkMonster::Killed( pevAttacker, iGib );
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// AI Schedules Specific to this monster
|
||||
//=========================================================
|
||||
|
||||
Schedule_t* CGordon :: GetScheduleOfType ( int Type )
|
||||
{
|
||||
Schedule_t *psched;
|
||||
|
||||
switch( Type )
|
||||
{
|
||||
case SCHED_ARM_WEAPON:
|
||||
if ( m_hEnemy != NULL )
|
||||
{
|
||||
// face enemy, then draw.
|
||||
return slGordonEnemyDraw;
|
||||
}
|
||||
break;
|
||||
|
||||
// Hook these to make a looping schedule
|
||||
case SCHED_TARGET_FACE:
|
||||
// call base class default so that barney will talk
|
||||
// when 'used'
|
||||
psched = CTalkMonster::GetScheduleOfType(Type);
|
||||
|
||||
if (psched == slIdleStand)
|
||||
return slGoFaceTarget; // override this for different target face behavior
|
||||
else
|
||||
return psched;
|
||||
|
||||
case SCHED_TARGET_CHASE:
|
||||
return slGoFollow;
|
||||
|
||||
case SCHED_IDLE_STAND:
|
||||
// call base class default so that scientist will talk
|
||||
// when standing during idle
|
||||
psched = CTalkMonster::GetScheduleOfType(Type);
|
||||
|
||||
if (psched == slIdleStand)
|
||||
{
|
||||
// just look straight ahead.
|
||||
return slIdleGoStand;
|
||||
}
|
||||
else
|
||||
return psched;
|
||||
}
|
||||
|
||||
return CTalkMonster::GetScheduleOfType( Type );
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// GetSchedule - Decides which type of schedule best suits
|
||||
// the monster's current state and conditions. Then calls
|
||||
// monster's member function to get a pointer to a schedule
|
||||
// of the proper type.
|
||||
//=========================================================
|
||||
Schedule_t *CGordon :: GetSchedule ( void )
|
||||
{
|
||||
if ( HasConditions( bits_COND_HEAR_SOUND ) )
|
||||
{
|
||||
CSound *pSound;
|
||||
pSound = PBestSound();
|
||||
|
||||
ASSERT( pSound != NULL );
|
||||
if ( pSound && (pSound->m_iType & bits_SOUND_DANGER) )
|
||||
return GetScheduleOfType( SCHED_TAKE_COVER_FROM_BEST_SOUND );
|
||||
}
|
||||
if ( HasConditions( bits_COND_ENEMY_DEAD ) && FOkToSpeak() )
|
||||
{
|
||||
PlaySentence( "GO_KILL", 4, VOL_NORM, ATTN_NORM );
|
||||
}
|
||||
|
||||
switch( m_MonsterState )
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
// always act surprized with a new enemy
|
||||
if ( HasConditions( bits_COND_NEW_ENEMY ) && HasConditions( bits_COND_LIGHT_DAMAGE) )
|
||||
return GetScheduleOfType( SCHED_SMALL_FLINCH );
|
||||
|
||||
// wait for one schedule to draw gun
|
||||
if (!m_fGunDrawn )
|
||||
return GetScheduleOfType( SCHED_ARM_WEAPON );
|
||||
|
||||
if ( HasConditions( bits_COND_HEAVY_DAMAGE ) )
|
||||
return GetScheduleOfType( SCHED_TAKE_COVER_FROM_ENEMY );
|
||||
}
|
||||
break;
|
||||
|
||||
case MONSTERSTATE_ALERT:
|
||||
case MONSTERSTATE_IDLE:
|
||||
if ( HasConditions(bits_COND_LIGHT_DAMAGE | bits_COND_HEAVY_DAMAGE))
|
||||
{
|
||||
// flinch if hurt
|
||||
return GetScheduleOfType( SCHED_SMALL_FLINCH );
|
||||
}
|
||||
|
||||
if ( m_hEnemy == NULL && IsFollowing() )
|
||||
{
|
||||
if ( !m_hTargetEnt->IsAlive() )
|
||||
{
|
||||
// UNDONE: Comment about the recently dead player here?
|
||||
StopFollowing( FALSE );
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( HasConditions( bits_COND_CLIENT_PUSH ) )
|
||||
{
|
||||
return GetScheduleOfType( SCHED_MOVE_AWAY_FOLLOW );
|
||||
}
|
||||
return GetScheduleOfType( SCHED_TARGET_FACE );
|
||||
}
|
||||
}
|
||||
|
||||
if ( HasConditions( bits_COND_CLIENT_PUSH ) )
|
||||
{
|
||||
return GetScheduleOfType( SCHED_MOVE_AWAY );
|
||||
}
|
||||
|
||||
// try to say something about smells
|
||||
TrySmellTalk();
|
||||
break;
|
||||
}
|
||||
|
||||
return CTalkMonster::GetSchedule();
|
||||
}
|
||||
|
||||
MONSTERSTATE CGordon :: GetIdealState ( void )
|
||||
{
|
||||
return CTalkMonster::GetIdealState();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CGordon::DeclineFollowing( void )
|
||||
{
|
||||
PlaySentence( "GO_POK", 2, VOL_NORM, ATTN_NORM );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//=========================================================
|
||||
// DEAD GORDON PROP
|
||||
//
|
||||
// Designer selects a pose in worldcraft, 0 through num_poses-1
|
||||
// this value is added to what is selected as the 'first dead pose'
|
||||
// among the monster's normal animations. All dead poses must
|
||||
// appear sequentially in the model file. Be sure and set
|
||||
// the m_iFirstPose properly!
|
||||
//
|
||||
//=========================================================
|
||||
class CDeadGordon : public CBaseMonster
|
||||
{
|
||||
public:
|
||||
void Spawn( void );
|
||||
int Classify ( void ) { return CLASS_PLAYER_ALLY; }
|
||||
|
||||
void KeyValue( KeyValueData *pkvd );
|
||||
|
||||
int m_iPose;// which sequence to display -- temporary, don't need to save
|
||||
static char *m_szPoses[3];
|
||||
};
|
||||
|
||||
char *CDeadGordon::m_szPoses[] = { "lying_on_back", "lying_on_side", "lying_on_stomach" };
|
||||
|
||||
void CDeadGordon::KeyValue( KeyValueData *pkvd )
|
||||
{
|
||||
if (FStrEq(pkvd->szKeyName, "pose"))
|
||||
{
|
||||
m_iPose = atoi(pkvd->szValue);
|
||||
pkvd->fHandled = TRUE;
|
||||
}
|
||||
else
|
||||
CBaseMonster::KeyValue( pkvd );
|
||||
}
|
||||
|
||||
LINK_ENTITY_TO_CLASS( monster_gordon_dead, CDeadGordon );
|
||||
|
||||
//=========================================================
|
||||
// ********** DeadGordon SPAWN **********
|
||||
//=========================================================
|
||||
void CDeadGordon :: Spawn( )
|
||||
{
|
||||
PRECACHE_MODEL("models/freeman.mdl");
|
||||
SET_MODEL(ENT(pev), "models/freeman.mdl");
|
||||
|
||||
pev->effects = 0;
|
||||
pev->yaw_speed = 8;
|
||||
pev->sequence = 0;
|
||||
m_bloodColor = BLOOD_COLOR_RED;
|
||||
|
||||
pev->sequence = LookupSequence( m_szPoses[m_iPose] );
|
||||
if (pev->sequence == -1)
|
||||
{
|
||||
ALERT ( at_console, "Dead barney with bad pose\n" );
|
||||
}
|
||||
// Corpses have less health
|
||||
pev->health = 8;//gSkillData.barneyHealth;
|
||||
|
||||
MonsterInitDead();
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,495 @@
|
|||
/***
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
****/
|
||||
//=========================================================
|
||||
// monster template
|
||||
//=========================================================
|
||||
// UNDONE: Holster weapon?
|
||||
|
||||
#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 "weapons.h"
|
||||
#include "soundent.h"
|
||||
#include "barney.h"
|
||||
|
||||
//=========================================================
|
||||
// Monster's Anim Events Go Here
|
||||
//=========================================================
|
||||
// first flag is barney dying for scripted sequences?
|
||||
|
||||
class CGordon : public CBarney
|
||||
{
|
||||
public:
|
||||
void Spawn( void );
|
||||
void Precache( void );
|
||||
void BarneyFirePistol( void );
|
||||
void AlertSound( void );
|
||||
BOOL CheckMeleeAttack1( float flDot, float flDist );
|
||||
void HandleAnimEvent( MonsterEvent_t *pEvent );
|
||||
int IRelationship( CBaseEntity *pTarget );
|
||||
CBaseEntity* AdrianCheckTraceHullAttack( float flDist, int iDamage, int iDmgType );
|
||||
int TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType);
|
||||
|
||||
void DeclineFollowing( void );
|
||||
|
||||
// Override these to set behavior
|
||||
Schedule_t *GetSchedule( void );
|
||||
|
||||
void DeathSound( void );
|
||||
void PainSound( void );
|
||||
|
||||
void TalkInit( void );
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS( monster_gordon, CGordon )
|
||||
LINK_ENTITY_TO_CLASS( monster_adrian, CGordon )
|
||||
|
||||
extern Schedule_t slBaFollow[];
|
||||
extern Schedule_t slBarneyEnemyDraw[];
|
||||
extern Schedule_t slBaFaceTarget[];
|
||||
extern Schedule_t slIdleBaStand[];
|
||||
extern Schedule_t slGruntHideReload[];
|
||||
|
||||
//=========================================================
|
||||
// ALertSound - barney says "Freeze!"
|
||||
//=========================================================
|
||||
void CGordon::AlertSound( void )
|
||||
{
|
||||
if( m_hEnemy != 0 )
|
||||
{
|
||||
if( FOkToSpeak() )
|
||||
{
|
||||
PlaySentence( "GO_ATTACK", RANDOM_FLOAT( 2.8, 3.2 ), VOL_NORM, ATTN_IDLE );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int CGordon::IRelationship( CBaseEntity *pTarget )
|
||||
{
|
||||
if( FClassnameIs( pev, "monster_adrian" ) && FClassnameIs( pTarget->pev, "monster_human_grunt" ) )
|
||||
{
|
||||
return R_AL;
|
||||
}
|
||||
|
||||
return CTalkMonster::IRelationship( pTarget );
|
||||
}
|
||||
|
||||
CBaseEntity* CGordon::AdrianCheckTraceHullAttack( float flDist, int iDamage, int iDmgType )
|
||||
{
|
||||
TraceResult tr;
|
||||
|
||||
UTIL_MakeVectors( pev->angles );
|
||||
|
||||
Vector vecStart = pev->origin;
|
||||
vecStart.z += pev->size.z * 0.5;
|
||||
Vector vecEnd = vecStart + ( gpGlobals->v_forward * flDist );
|
||||
|
||||
UTIL_TraceHull( vecStart, vecEnd, dont_ignore_monsters, head_hull, ENT( pev ), &tr );
|
||||
|
||||
if( tr.pHit )
|
||||
return CBaseEntity::Instance( tr.pHit );
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BOOL CGordon::CheckMeleeAttack1( float flDot, float flDist )
|
||||
{
|
||||
CBaseMonster *pEnemy = 0;
|
||||
|
||||
if( m_hEnemy != 0 )
|
||||
{
|
||||
pEnemy = m_hEnemy->MyMonsterPointer();
|
||||
|
||||
if( !pEnemy )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if( flDist <= 64 && flDot >= 0.7 &&
|
||||
pEnemy->Classify() != CLASS_ALIEN_BIOWEAPON &&
|
||||
pEnemy->Classify() != CLASS_PLAYER_BIOWEAPON )
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// BarneyFirePistol - shoots one round from the pistol at
|
||||
// the enemy barney is facing.
|
||||
//=========================================================
|
||||
void CGordon::BarneyFirePistol( void )
|
||||
{
|
||||
Vector vecShootOrigin;
|
||||
|
||||
UTIL_MakeVectors( pev->angles );
|
||||
vecShootOrigin = pev->origin + Vector( 0, 0, 55 );
|
||||
Vector vecShootDir = ShootAtEnemy( vecShootOrigin );
|
||||
|
||||
Vector angDir = UTIL_VecToAngles( vecShootDir );
|
||||
SetBlending( 0, angDir.x );
|
||||
pev->effects = EF_MUZZLEFLASH;
|
||||
|
||||
FireBullets( 1, vecShootOrigin, vecShootDir, VECTOR_CONE_2DEGREES, 1024, BULLET_MONSTER_9MM );
|
||||
|
||||
int pitchShift = RANDOM_LONG( 0, 20 );
|
||||
|
||||
// Only shift about half the time
|
||||
if( pitchShift > 10 )
|
||||
pitchShift = 0;
|
||||
else
|
||||
pitchShift -= 5;
|
||||
EMIT_SOUND_DYN( ENT( pev ), CHAN_WEAPON, "gordon/go_attack2.wav", 1, ATTN_NORM, 0, 100 + pitchShift );
|
||||
|
||||
CSoundEnt::InsertSound( bits_SOUND_COMBAT, pev->origin, 384, 0.3 );
|
||||
|
||||
// UNDONE: Reload?
|
||||
m_cAmmoLoaded--;// take away a bullet!
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// HandleAnimEvent - catches the monster-specific messages
|
||||
// that occur when tagged animation frames are played.
|
||||
//
|
||||
// Returns number of events handled, 0 if none.
|
||||
//=========================================================
|
||||
void CGordon::HandleAnimEvent( MonsterEvent_t *pEvent )
|
||||
{
|
||||
CBaseEntity *pHurt;
|
||||
switch( pEvent->event )
|
||||
{
|
||||
case BARNEY_AE_KICK:
|
||||
pHurt = AdrianCheckTraceHullAttack( 70, 0, DMG_GENERIC );
|
||||
if( pHurt )
|
||||
{
|
||||
EMIT_SOUND_DYN( ENT( pev ), CHAN_VOICE, "common/kick.wav", 1, ATTN_NORM, 0, PITCH_NORM );
|
||||
|
||||
UTIL_MakeVectors( pev->angles );
|
||||
|
||||
pHurt->pev->punchangle.x = 5;
|
||||
pHurt->pev->velocity = pHurt->pev->velocity - gpGlobals->v_forward * 100 + gpGlobals->v_up * 50;
|
||||
pHurt->TakeDamage( pev, pev, gSkillData.hgruntDmgKick, DMG_CLUB );
|
||||
}
|
||||
break;
|
||||
default:
|
||||
CBarney::HandleAnimEvent( pEvent );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// Spawn
|
||||
//=========================================================
|
||||
void CGordon::Spawn()
|
||||
{
|
||||
Precache();
|
||||
|
||||
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_RED;
|
||||
pev->health = gSkillData.kateHealth;
|
||||
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 npc will notice player and say hello
|
||||
m_MonsterState = MONSTERSTATE_NONE;
|
||||
|
||||
pev->body = 0; // gun in holster
|
||||
m_fGunDrawn = FALSE;
|
||||
|
||||
m_afCapability = bits_CAP_HEAR | bits_CAP_TURN_HEAD | bits_CAP_DOORS_GROUP;
|
||||
|
||||
m_cAmmoLoaded = GLOCK_MAX_CLIP;
|
||||
|
||||
MonsterInit();
|
||||
SetUse( &CTalkMonster::FollowerUse );
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// Precache - precaches all resources this monster needs
|
||||
//=========================================================
|
||||
void CGordon::Precache()
|
||||
{
|
||||
if( FClassnameIs( pev, "monster_adrian" ) )
|
||||
pev->model = MAKE_STRING( "models/adrian.mdl" );
|
||||
else
|
||||
pev->model = MAKE_STRING( "models/freeman.mdl" );
|
||||
|
||||
PRECACHE_MODEL( STRING( pev->model ) );
|
||||
|
||||
PRECACHE_SOUND( "gordon/go_attack1.wav" );
|
||||
PRECACHE_SOUND( "gordon/go_attack2.wav" );
|
||||
|
||||
PRECACHE_SOUND( "gordon/go_pain1.wav" );
|
||||
PRECACHE_SOUND( "gordon/go_pain2.wav" );
|
||||
PRECACHE_SOUND( "gordon/go_pain3.wav" );
|
||||
|
||||
PRECACHE_SOUND( "gordon/go_die1.wav" );
|
||||
PRECACHE_SOUND( "gordon/go_die2.wav" );
|
||||
PRECACHE_SOUND( "gordon/go_die3.wav" );
|
||||
|
||||
PRECACHE_SOUND( "weapons/reload3.wav" );
|
||||
|
||||
PRECACHE_SOUND( "zombie/claw_miss1.wav" );
|
||||
PRECACHE_SOUND( "zombie/claw_miss2.wav" );
|
||||
PRECACHE_SOUND( "common/kick.wav" );
|
||||
|
||||
// every new barney must call this, otherwise
|
||||
// when a level is loaded, nobody will talk (time is reset to 0)
|
||||
TalkInit();
|
||||
CTalkMonster::Precache();
|
||||
}
|
||||
|
||||
// Init talk data
|
||||
void CGordon::TalkInit()
|
||||
{
|
||||
CTalkMonster::TalkInit();
|
||||
|
||||
// scientists speach group names (group names are in sentences.txt)
|
||||
m_szGrp[TLK_ANSWER] = "GO_ANSWER";
|
||||
m_szGrp[TLK_QUESTION] = "GO_QUESTION";
|
||||
m_szGrp[TLK_IDLE] = "GO_IDLE";
|
||||
m_szGrp[TLK_STARE] = "GO_STARE";
|
||||
m_szGrp[TLK_USE] = "GO_OK";
|
||||
m_szGrp[TLK_UNUSE] = "GO_WAIT";
|
||||
m_szGrp[TLK_STOP] = "GO_STOP";
|
||||
|
||||
m_szGrp[TLK_NOSHOOT] = "GO_SCARED";
|
||||
m_szGrp[TLK_HELLO] = "GO_HELLO";
|
||||
|
||||
m_szGrp[TLK_PLHURT1] = "!HM_CUREA";
|
||||
m_szGrp[TLK_PLHURT2] = "!HM_CUREB";
|
||||
m_szGrp[TLK_PLHURT3] = "!HM_CUREC";
|
||||
|
||||
m_szGrp[TLK_PHELLO] = NULL; //"GO_PHELLO"; // UNDONE
|
||||
m_szGrp[TLK_PIDLE] = NULL; //"GO_PIDLE"; // UNDONE
|
||||
m_szGrp[TLK_PQUESTION] = "GO_PQUEST"; // UNDONE
|
||||
|
||||
m_szGrp[TLK_SMELL] = "GO_SMELL";
|
||||
|
||||
m_szGrp[TLK_WOUND] = "GO_WOUND";
|
||||
m_szGrp[TLK_MORTAL] = "GO_MORTAL";
|
||||
|
||||
// get voice for head - just one barney voice for now
|
||||
if( FClassnameIs( pev, "monster_adrian" ) )
|
||||
m_voicePitch = 95;
|
||||
else
|
||||
m_voicePitch = 100;
|
||||
}
|
||||
|
||||
static BOOL IsFacing( entvars_t *pevTest, const Vector &reference )
|
||||
{
|
||||
Vector vecDir = reference - pevTest->origin;
|
||||
vecDir.z = 0;
|
||||
vecDir = vecDir.Normalize();
|
||||
Vector forward, angle;
|
||||
angle = pevTest->v_angle;
|
||||
angle.x = 0;
|
||||
UTIL_MakeVectorsPrivate( angle, forward, NULL, NULL );
|
||||
|
||||
// He's facing me, he meant it
|
||||
if( DotProduct( forward, vecDir ) > 0.96 ) // +/- 15 degrees or so
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int CGordon::TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType )
|
||||
{
|
||||
// make sure friends talk about it if player hurts talkmonsters...
|
||||
int ret = CTalkMonster::TakeDamage( pevInflictor, pevAttacker, flDamage, bitsDamageType );
|
||||
if( !IsAlive() || pev->deadflag == DEAD_DYING )
|
||||
return ret;
|
||||
|
||||
if( m_MonsterState != MONSTERSTATE_PRONE && ( pevAttacker->flags & FL_CLIENT ) )
|
||||
{
|
||||
m_flPlayerDamage += flDamage;
|
||||
|
||||
// This is a heurstic to determine if the player intended to harm me
|
||||
// If I have an enemy, we can't establish intent (may just be crossfire)
|
||||
if( m_hEnemy == 0 )
|
||||
{
|
||||
// If the player was facing directly at me, or I'm already suspicious, get mad
|
||||
if( ( m_afMemory & bits_MEMORY_SUSPICIOUS ) || IsFacing( pevAttacker, pev->origin ) )
|
||||
{
|
||||
// Alright, now I'm pissed!
|
||||
PlaySentence( "GO_MAD", 4, VOL_NORM, ATTN_NORM );
|
||||
|
||||
Remember( bits_MEMORY_PROVOKED );
|
||||
StopFollowing( TRUE );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Hey, be careful with that
|
||||
PlaySentence( "GO_SHOT", 4, VOL_NORM, ATTN_NORM );
|
||||
Remember( bits_MEMORY_SUSPICIOUS );
|
||||
}
|
||||
}
|
||||
else if( !( m_hEnemy->IsPlayer()) && pev->deadflag == DEAD_NO )
|
||||
{
|
||||
PlaySentence( "GO_SHOT", 4, VOL_NORM, ATTN_NORM );
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// PainSound
|
||||
//=========================================================
|
||||
void CGordon::PainSound( void )
|
||||
{
|
||||
if( gpGlobals->time < m_painTime )
|
||||
return;
|
||||
|
||||
m_painTime = gpGlobals->time + RANDOM_FLOAT( 0.5, 0.75 );
|
||||
|
||||
switch( RANDOM_LONG( 0, 2 ) )
|
||||
{
|
||||
case 0:
|
||||
EMIT_SOUND_DYN( ENT( pev ), CHAN_VOICE, "gordon/go_pain1.wav", 1, ATTN_NORM, 0, GetVoicePitch() );
|
||||
break;
|
||||
case 1:
|
||||
EMIT_SOUND_DYN( ENT( pev ), CHAN_VOICE, "gordon/go_pain2.wav", 1, ATTN_NORM, 0, GetVoicePitch() );
|
||||
break;
|
||||
case 2:
|
||||
EMIT_SOUND_DYN( ENT( pev ), CHAN_VOICE, "gordon/go_pain3.wav", 1, ATTN_NORM, 0, GetVoicePitch() );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// DeathSound
|
||||
//=========================================================
|
||||
void CGordon::DeathSound( void )
|
||||
{
|
||||
switch( RANDOM_LONG( 0, 2 ) )
|
||||
{
|
||||
case 0:
|
||||
EMIT_SOUND_DYN( ENT( pev ), CHAN_VOICE, "gordon/go_die1.wav", 1, ATTN_NORM, 0, GetVoicePitch() );
|
||||
break;
|
||||
case 1:
|
||||
EMIT_SOUND_DYN( ENT( pev ), CHAN_VOICE, "gordon/go_die2.wav", 1, ATTN_NORM, 0, GetVoicePitch() );
|
||||
break;
|
||||
case 2:
|
||||
EMIT_SOUND_DYN( ENT( pev ), CHAN_VOICE, "gordon/go_die3.wav", 1, ATTN_NORM, 0, GetVoicePitch() );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// GetSchedule - Decides which type of schedule best suits
|
||||
// the monster's current state and conditions. Then calls
|
||||
// monster's member function to get a pointer to a schedule
|
||||
// of the proper type.
|
||||
//=========================================================
|
||||
Schedule_t *CGordon::GetSchedule( void )
|
||||
{
|
||||
if( HasConditions( bits_COND_HEAR_SOUND ) )
|
||||
{
|
||||
CSound *pSound;
|
||||
pSound = PBestSound();
|
||||
|
||||
ASSERT( pSound != NULL );
|
||||
if( pSound && (pSound->m_iType & bits_SOUND_DANGER) )
|
||||
return GetScheduleOfType( SCHED_TAKE_COVER_FROM_BEST_SOUND );
|
||||
}
|
||||
if( HasConditions( bits_COND_ENEMY_DEAD ) && FOkToSpeak() )
|
||||
{
|
||||
PlaySentence( "GO_KILL", 4, VOL_NORM, ATTN_NORM );
|
||||
}
|
||||
|
||||
switch( m_MonsterState )
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
// always act surprized with a new enemy
|
||||
if( HasConditions( bits_COND_NEW_ENEMY ) && HasConditions( bits_COND_LIGHT_DAMAGE ) )
|
||||
return GetScheduleOfType( SCHED_SMALL_FLINCH );
|
||||
|
||||
// wait for one schedule to draw gun
|
||||
if( !m_fGunDrawn )
|
||||
return GetScheduleOfType( SCHED_ARM_WEAPON );
|
||||
|
||||
if( HasConditions( bits_COND_HEAVY_DAMAGE ) )
|
||||
return GetScheduleOfType( SCHED_TAKE_COVER_FROM_ENEMY );
|
||||
|
||||
if( HasConditions( bits_COND_CAN_MELEE_ATTACK1 ) )
|
||||
return GetScheduleOfType( SCHED_MELEE_ATTACK1 );
|
||||
|
||||
if( HasConditions( bits_COND_NO_AMMO_LOADED ) )
|
||||
return GetScheduleOfType( SCHED_BARNEY_COVER_AND_RELOAD );
|
||||
}
|
||||
break;
|
||||
case MONSTERSTATE_ALERT:
|
||||
case MONSTERSTATE_IDLE:
|
||||
if( HasConditions( bits_COND_LIGHT_DAMAGE | bits_COND_HEAVY_DAMAGE ) )
|
||||
{
|
||||
// flinch if hurt
|
||||
return GetScheduleOfType( SCHED_SMALL_FLINCH );
|
||||
}
|
||||
|
||||
if( m_hEnemy == 0 && IsFollowing() )
|
||||
{
|
||||
if( !m_hTargetEnt->IsAlive() )
|
||||
{
|
||||
// UNDONE: Comment about the recently dead player here?
|
||||
StopFollowing( FALSE );
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( HasConditions( bits_COND_CLIENT_PUSH ) )
|
||||
{
|
||||
return GetScheduleOfType( SCHED_MOVE_AWAY_FOLLOW );
|
||||
}
|
||||
return GetScheduleOfType( SCHED_TARGET_FACE );
|
||||
}
|
||||
}
|
||||
|
||||
if( HasConditions( bits_COND_CLIENT_PUSH ) )
|
||||
{
|
||||
return GetScheduleOfType( SCHED_MOVE_AWAY );
|
||||
}
|
||||
|
||||
// try to say something about smells
|
||||
TrySmellTalk();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return CTalkMonster::GetSchedule();
|
||||
}
|
||||
|
||||
void CGordon::DeclineFollowing( void )
|
||||
{
|
||||
PlaySentence( "GO_POK", 2, VOL_NORM, ATTN_NORM );
|
||||
}
|
|
@ -1,839 +0,0 @@
|
|||
/***
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
****/
|
||||
//=========================================================
|
||||
// monster template
|
||||
//=========================================================
|
||||
// UNDONE: Holster weapon?
|
||||
|
||||
#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 "weapons.h"
|
||||
#include "soundent.h"
|
||||
|
||||
//=========================================================
|
||||
// Monster's Anim Events Go Here
|
||||
//=========================================================
|
||||
// first flag is hevbarn dying for scripted sequences?
|
||||
#define HEVBARN_AE_DRAW ( 2 )
|
||||
#define HEVBARN_AE_SHOOT ( 3 )
|
||||
#define HEVBARN_AE_HOLSTER ( 4 )
|
||||
|
||||
#define HEVBARN_BODY_GUNHOLSTERED 0
|
||||
#define HEVBARN_BODY_GUNDRAWN 1
|
||||
#define HEVBARN_BODY_GUNGONE 2
|
||||
|
||||
class CHevbarn : public CTalkMonster
|
||||
{
|
||||
public:
|
||||
void Spawn( void );
|
||||
void Precache( void );
|
||||
void SetYawSpeed( void );
|
||||
int ISoundMask( void );
|
||||
void HevbarnFirePistol( 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_hevbarn, CHevbarn );
|
||||
|
||||
TYPEDESCRIPTION CHevbarn::m_SaveData[] =
|
||||
{
|
||||
DEFINE_FIELD( CHevbarn, m_fGunDrawn, FIELD_BOOLEAN ),
|
||||
DEFINE_FIELD( CHevbarn, m_painTime, FIELD_TIME ),
|
||||
DEFINE_FIELD( CHevbarn, m_checkAttackTime, FIELD_TIME ),
|
||||
DEFINE_FIELD( CHevbarn, m_lastAttackCheck, FIELD_BOOLEAN ),
|
||||
DEFINE_FIELD( CHevbarn, m_flPlayerDamage, FIELD_FLOAT ),
|
||||
};
|
||||
|
||||
IMPLEMENT_SAVERESTORE( CHevbarn, CTalkMonster );
|
||||
|
||||
//=========================================================
|
||||
// AI Schedules Specific to this monster
|
||||
//=========================================================
|
||||
Task_t tlHvBaFollow[] =
|
||||
{
|
||||
{ TASK_MOVE_TO_TARGET_RANGE,(float)128 }, // Move within 128 of target ent (client)
|
||||
{ TASK_SET_SCHEDULE, (float)SCHED_TARGET_FACE },
|
||||
};
|
||||
|
||||
Schedule_t slHvBaFollow[] =
|
||||
{
|
||||
{
|
||||
tlHvBaFollow,
|
||||
ARRAYSIZE ( tlHvBaFollow ),
|
||||
bits_COND_NEW_ENEMY |
|
||||
bits_COND_LIGHT_DAMAGE |
|
||||
bits_COND_HEAVY_DAMAGE |
|
||||
bits_COND_HEAR_SOUND |
|
||||
bits_COND_PROVOKED,
|
||||
bits_SOUND_DANGER,
|
||||
"Follow"
|
||||
},
|
||||
};
|
||||
|
||||
//=========================================================
|
||||
// HevbarnDraw- much better looking draw schedule for when
|
||||
// hevbarn knows who he's gonna attack.
|
||||
//=========================================================
|
||||
Task_t tlHevbarnEnemyDraw[] =
|
||||
{
|
||||
{ TASK_STOP_MOVING, 0 },
|
||||
{ TASK_FACE_ENEMY, 0 },
|
||||
{ TASK_PLAY_SEQUENCE_FACE_ENEMY, (float) ACT_ARM },
|
||||
};
|
||||
|
||||
Schedule_t slHevbarnEnemyDraw[] =
|
||||
{
|
||||
{
|
||||
tlHevbarnEnemyDraw,
|
||||
ARRAYSIZE ( tlHevbarnEnemyDraw ),
|
||||
0,
|
||||
0,
|
||||
"Hevbarn Enemy Draw"
|
||||
}
|
||||
};
|
||||
|
||||
Task_t tlHvBaFaceTarget[] =
|
||||
{
|
||||
{ TASK_SET_ACTIVITY, (float)ACT_IDLE },
|
||||
{ TASK_FACE_TARGET, (float)0 },
|
||||
{ TASK_SET_ACTIVITY, (float)ACT_IDLE },
|
||||
{ TASK_SET_SCHEDULE, (float)SCHED_TARGET_CHASE },
|
||||
};
|
||||
|
||||
Schedule_t slHvBaFaceTarget[] =
|
||||
{
|
||||
{
|
||||
tlHvBaFaceTarget,
|
||||
ARRAYSIZE ( tlHvBaFaceTarget ),
|
||||
bits_COND_CLIENT_PUSH |
|
||||
bits_COND_NEW_ENEMY |
|
||||
bits_COND_LIGHT_DAMAGE |
|
||||
bits_COND_HEAVY_DAMAGE |
|
||||
bits_COND_HEAR_SOUND |
|
||||
bits_COND_PROVOKED,
|
||||
bits_SOUND_DANGER,
|
||||
"FaceTarget"
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
Task_t tlIdleHvBaStand[] =
|
||||
{
|
||||
{ TASK_STOP_MOVING, 0 },
|
||||
{ TASK_SET_ACTIVITY, (float)ACT_IDLE },
|
||||
{ TASK_WAIT, (float)2 }, // repick IDLESTAND every two seconds.
|
||||
{ TASK_TLK_HEADRESET, (float)0 }, // reset head position
|
||||
};
|
||||
|
||||
Schedule_t slIdleHvBaStand[] =
|
||||
{
|
||||
{
|
||||
tlIdleHvBaStand,
|
||||
ARRAYSIZE ( tlIdleHvBaStand ),
|
||||
bits_COND_NEW_ENEMY |
|
||||
bits_COND_LIGHT_DAMAGE |
|
||||
bits_COND_HEAVY_DAMAGE |
|
||||
bits_COND_HEAR_SOUND |
|
||||
bits_COND_SMELL |
|
||||
bits_COND_PROVOKED,
|
||||
|
||||
bits_SOUND_COMBAT |// sound flags - change these, and you'll break the talking code.
|
||||
//bits_SOUND_PLAYER |
|
||||
//bits_SOUND_WORLD |
|
||||
|
||||
bits_SOUND_DANGER |
|
||||
bits_SOUND_MEAT |// scents
|
||||
bits_SOUND_CARCASS |
|
||||
bits_SOUND_GARBAGE,
|
||||
"IdleStand"
|
||||
},
|
||||
};
|
||||
|
||||
DEFINE_CUSTOM_SCHEDULES( CHevbarn )
|
||||
{
|
||||
slHvBaFollow,
|
||||
slHevbarnEnemyDraw,
|
||||
slHvBaFaceTarget,
|
||||
slIdleHvBaStand,
|
||||
};
|
||||
|
||||
|
||||
IMPLEMENT_CUSTOM_SCHEDULES( CHevbarn, CTalkMonster );
|
||||
|
||||
void CHevbarn :: StartTask( Task_t *pTask )
|
||||
{
|
||||
CTalkMonster::StartTask( pTask );
|
||||
}
|
||||
|
||||
void CHevbarn :: RunTask( Task_t *pTask )
|
||||
{
|
||||
switch ( pTask->iTask )
|
||||
{
|
||||
case TASK_RANGE_ATTACK1:
|
||||
if (m_hEnemy != NULL && (m_hEnemy->IsPlayer()))
|
||||
{
|
||||
pev->framerate = 1.5;
|
||||
}
|
||||
CTalkMonster::RunTask( pTask );
|
||||
break;
|
||||
default:
|
||||
CTalkMonster::RunTask( pTask );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//=========================================================
|
||||
// ISoundMask - returns a bit mask indicating which types
|
||||
// of sounds this monster regards.
|
||||
//=========================================================
|
||||
int CHevbarn :: ISoundMask ( void)
|
||||
{
|
||||
return bits_SOUND_WORLD |
|
||||
bits_SOUND_COMBAT |
|
||||
bits_SOUND_CARCASS |
|
||||
bits_SOUND_MEAT |
|
||||
bits_SOUND_GARBAGE |
|
||||
bits_SOUND_DANGER |
|
||||
bits_SOUND_PLAYER;
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// Classify - indicates this monster's place in the
|
||||
// relationship table.
|
||||
//=========================================================
|
||||
int CHevbarn :: Classify ( void )
|
||||
{
|
||||
return CLASS_PLAYER_ALLY;
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// ALertSound - hevbarn says "Freeze!"
|
||||
//=========================================================
|
||||
void CHevbarn :: AlertSound( void )
|
||||
{
|
||||
if ( m_hEnemy != NULL )
|
||||
{
|
||||
if ( FOkToSpeak() )
|
||||
{
|
||||
PlaySentence( "BA_ATTACK", RANDOM_FLOAT(2.8, 3.2), VOL_NORM, ATTN_IDLE );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
//=========================================================
|
||||
// SetYawSpeed - allows each sequence to have a different
|
||||
// turn rate associated with it.
|
||||
//=========================================================
|
||||
void CHevbarn :: SetYawSpeed ( void )
|
||||
{
|
||||
int ys;
|
||||
|
||||
ys = 0;
|
||||
|
||||
switch ( m_Activity )
|
||||
{
|
||||
case ACT_IDLE:
|
||||
ys = 70;
|
||||
break;
|
||||
case ACT_WALK:
|
||||
ys = 70;
|
||||
break;
|
||||
case ACT_RUN:
|
||||
ys = 90;
|
||||
break;
|
||||
default:
|
||||
ys = 70;
|
||||
break;
|
||||
}
|
||||
|
||||
pev->yaw_speed = ys;
|
||||
}
|
||||
|
||||
|
||||
//=========================================================
|
||||
// CheckRangeAttack1
|
||||
//=========================================================
|
||||
BOOL CHevbarn :: CheckRangeAttack1 ( float flDot, float flDist )
|
||||
{
|
||||
if ( flDist <= 1024 && flDot >= 0.5 )
|
||||
{
|
||||
if ( gpGlobals->time > m_checkAttackTime )
|
||||
{
|
||||
TraceResult tr;
|
||||
|
||||
Vector shootOrigin = pev->origin + Vector( 0, 0, 55 );
|
||||
CBaseEntity *pEnemy = m_hEnemy;
|
||||
Vector shootTarget = ( (pEnemy->BodyTarget( shootOrigin ) - pEnemy->pev->origin) + m_vecEnemyLKP );
|
||||
UTIL_TraceLine( shootOrigin, shootTarget, dont_ignore_monsters, ENT(pev), &tr );
|
||||
m_checkAttackTime = gpGlobals->time + 1;
|
||||
if ( tr.flFraction == 1.0 || (tr.pHit != NULL && CBaseEntity::Instance(tr.pHit) == pEnemy) )
|
||||
m_lastAttackCheck = TRUE;
|
||||
else
|
||||
m_lastAttackCheck = FALSE;
|
||||
m_checkAttackTime = gpGlobals->time + 1.5;
|
||||
}
|
||||
return m_lastAttackCheck;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
//=========================================================
|
||||
// HevbarnFirePistol - shoots one round from the pistol at
|
||||
// the enemy hevbarn is facing.
|
||||
//=========================================================
|
||||
void CHevbarn :: HevbarnFirePistol ( void )
|
||||
{
|
||||
Vector vecShootOrigin;
|
||||
|
||||
UTIL_MakeVectors(pev->angles);
|
||||
vecShootOrigin = pev->origin + Vector( 0, 0, 55 );
|
||||
Vector vecShootDir = ShootAtEnemy( vecShootOrigin );
|
||||
|
||||
Vector angDir = UTIL_VecToAngles( vecShootDir );
|
||||
SetBlending( 0, angDir.x );
|
||||
pev->effects = EF_MUZZLEFLASH;
|
||||
|
||||
FireBullets(1, vecShootOrigin, vecShootDir, VECTOR_CONE_2DEGREES, 1024, BULLET_MONSTER_9MM );
|
||||
|
||||
int pitchShift = RANDOM_LONG( 0, 20 );
|
||||
|
||||
// Only shift about half the time
|
||||
if ( pitchShift > 10 )
|
||||
pitchShift = 0;
|
||||
else
|
||||
pitchShift -= 5;
|
||||
EMIT_SOUND_DYN( ENT(pev), CHAN_WEAPON, "barney/ba_attack2.wav", 1, ATTN_NORM, 0, 100 + pitchShift );
|
||||
|
||||
CSoundEnt::InsertSound ( bits_SOUND_COMBAT, pev->origin, 384, 0.3 );
|
||||
|
||||
// UNDONE: Reload?
|
||||
m_cAmmoLoaded--;// take away a bullet!
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// HandleAnimEvent - catches the monster-specific messages
|
||||
// that occur when tagged animation frames are played.
|
||||
//
|
||||
// Returns number of events handled, 0 if none.
|
||||
//=========================================================
|
||||
void CHevbarn :: HandleAnimEvent( MonsterEvent_t *pEvent )
|
||||
{
|
||||
switch( pEvent->event )
|
||||
{
|
||||
case HEVBARN_AE_SHOOT:
|
||||
HevbarnFirePistol();
|
||||
break;
|
||||
|
||||
case HEVBARN_AE_DRAW:
|
||||
// hevbarn's bodygroup switches here so he can pull gun from holster
|
||||
pev->body = HEVBARN_BODY_GUNDRAWN;
|
||||
m_fGunDrawn = TRUE;
|
||||
break;
|
||||
|
||||
case HEVBARN_AE_HOLSTER:
|
||||
// change bodygroup to replace gun in holster
|
||||
pev->body = HEVBARN_BODY_GUNHOLSTERED;
|
||||
m_fGunDrawn = FALSE;
|
||||
break;
|
||||
|
||||
default:
|
||||
CTalkMonster::HandleAnimEvent( pEvent );
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// Spawn
|
||||
//=========================================================
|
||||
void CHevbarn :: Spawn()
|
||||
{
|
||||
Precache( );
|
||||
|
||||
SET_MODEL(ENT(pev), "models/hev_barney.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.barneyHealth;
|
||||
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 npc will notice player and say hello
|
||||
m_MonsterState = MONSTERSTATE_NONE;
|
||||
|
||||
pev->body = 0; // gun in holster
|
||||
m_fGunDrawn = FALSE;
|
||||
|
||||
m_afCapability = bits_CAP_HEAR | bits_CAP_TURN_HEAD | bits_CAP_DOORS_GROUP;
|
||||
|
||||
MonsterInit();
|
||||
SetUse( &CHevbarn::FollowerUse );
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// Precache - precaches all resources this monster needs
|
||||
//=========================================================
|
||||
void CHevbarn :: Precache()
|
||||
{
|
||||
PRECACHE_MODEL("models/hev_barney.mdl");
|
||||
|
||||
PRECACHE_SOUND("barney/ba_attack1.wav" );
|
||||
PRECACHE_SOUND("barney/ba_attack2.wav" );
|
||||
|
||||
PRECACHE_SOUND("barney/ba_pain1.wav");
|
||||
PRECACHE_SOUND("barney/ba_pain2.wav");
|
||||
PRECACHE_SOUND("barney/ba_pain3.wav");
|
||||
|
||||
PRECACHE_SOUND("barney/ba_die1.wav");
|
||||
PRECACHE_SOUND("barney/ba_die2.wav");
|
||||
PRECACHE_SOUND("barney/ba_die3.wav");
|
||||
|
||||
// every new hevbarn must call this, otherwise
|
||||
// when a level is loaded, nobody will talk (time is reset to 0)
|
||||
TalkInit();
|
||||
CTalkMonster::Precache();
|
||||
}
|
||||
|
||||
// Init talk data
|
||||
void CHevbarn :: TalkInit()
|
||||
{
|
||||
|
||||
CTalkMonster::TalkInit();
|
||||
|
||||
// scientists speach group names (group names are in sentences.txt)
|
||||
|
||||
m_szGrp[TLK_ANSWER] = "BA_ANSWER";
|
||||
m_szGrp[TLK_QUESTION] = "BA_QUESTION";
|
||||
m_szGrp[TLK_IDLE] = "BA_IDLE";
|
||||
m_szGrp[TLK_STARE] = "BA_STARE";
|
||||
m_szGrp[TLK_USE] = "BA_OK";
|
||||
m_szGrp[TLK_UNUSE] = "BA_WAIT";
|
||||
m_szGrp[TLK_STOP] = "BA_STOP";
|
||||
|
||||
m_szGrp[TLK_NOSHOOT] = "BA_SCARED";
|
||||
m_szGrp[TLK_HELLO] = "BA_HELLO";
|
||||
|
||||
m_szGrp[TLK_PLHURT1] = "!BA_CUREA";
|
||||
m_szGrp[TLK_PLHURT2] = "!BA_CUREB";
|
||||
m_szGrp[TLK_PLHURT3] = "!BA_CUREC";
|
||||
|
||||
m_szGrp[TLK_PHELLO] = NULL; //"BA_PHELLO"; // UNDONE
|
||||
m_szGrp[TLK_PIDLE] = NULL; //"BA_PIDLE"; // UNDONE
|
||||
m_szGrp[TLK_PQUESTION] = "BA_PQUEST"; // UNDONE
|
||||
|
||||
m_szGrp[TLK_SMELL] = "BA_SMELL";
|
||||
|
||||
m_szGrp[TLK_WOUND] = "BA_WOUND";
|
||||
m_szGrp[TLK_MORTAL] = "BA_MORTAL";
|
||||
|
||||
// get voice for head - just one hevbarn voice for now
|
||||
m_voicePitch = 100;
|
||||
}
|
||||
|
||||
|
||||
static BOOL IsFacing( entvars_t *pevTest, const Vector &reference )
|
||||
{
|
||||
Vector vecDir = (reference - pevTest->origin);
|
||||
vecDir.z = 0;
|
||||
vecDir = vecDir.Normalize();
|
||||
Vector forward, angle;
|
||||
angle = pevTest->v_angle;
|
||||
angle.x = 0;
|
||||
UTIL_MakeVectorsPrivate( angle, forward, NULL, NULL );
|
||||
// He's facing me, he meant it
|
||||
if ( DotProduct( forward, vecDir ) > 0.96 ) // +/- 15 degrees or so
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
int CHevbarn :: TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType)
|
||||
{
|
||||
// make sure friends talk about it if player hurts talkmonsters...
|
||||
int ret = CTalkMonster::TakeDamage(pevInflictor, pevAttacker, flDamage, bitsDamageType);
|
||||
if ( !IsAlive() || pev->deadflag == DEAD_DYING )
|
||||
return ret;
|
||||
|
||||
if ( m_MonsterState != MONSTERSTATE_PRONE && (pevAttacker->flags & FL_CLIENT) )
|
||||
{
|
||||
m_flPlayerDamage += flDamage;
|
||||
|
||||
// This is a heurstic to determine if the player intended to harm me
|
||||
// If I have an enemy, we can't establish intent (may just be crossfire)
|
||||
if ( m_hEnemy == NULL )
|
||||
{
|
||||
// If the player was facing directly at me, or I'm already suspicious, get mad
|
||||
if ( (m_afMemory & bits_MEMORY_SUSPICIOUS) || IsFacing( pevAttacker, pev->origin ) )
|
||||
{
|
||||
// Alright, now I'm pissed!
|
||||
PlaySentence( "BA_MAD", 4, VOL_NORM, ATTN_NORM );
|
||||
|
||||
Remember( bits_MEMORY_PROVOKED );
|
||||
StopFollowing( TRUE );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Hey, be careful with that
|
||||
PlaySentence( "BA_SHOT", 4, VOL_NORM, ATTN_NORM );
|
||||
Remember( bits_MEMORY_SUSPICIOUS );
|
||||
}
|
||||
}
|
||||
else if ( !(m_hEnemy->IsPlayer()) && pev->deadflag == DEAD_NO )
|
||||
{
|
||||
PlaySentence( "BA_SHOT", 4, VOL_NORM, ATTN_NORM );
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
//=========================================================
|
||||
// PainSound
|
||||
//=========================================================
|
||||
void CHevbarn :: PainSound ( void )
|
||||
{
|
||||
if (gpGlobals->time < m_painTime)
|
||||
return;
|
||||
|
||||
m_painTime = gpGlobals->time + RANDOM_FLOAT(0.5, 0.75);
|
||||
|
||||
switch (RANDOM_LONG(0,2))
|
||||
{
|
||||
case 0: EMIT_SOUND_DYN( ENT(pev), CHAN_VOICE, "barney/ba_pain1.wav", 1, ATTN_NORM, 0, GetVoicePitch()); break;
|
||||
case 1: EMIT_SOUND_DYN( ENT(pev), CHAN_VOICE, "barney/ba_pain2.wav", 1, ATTN_NORM, 0, GetVoicePitch()); break;
|
||||
case 2: EMIT_SOUND_DYN( ENT(pev), CHAN_VOICE, "barney/ba_pain3.wav", 1, ATTN_NORM, 0, GetVoicePitch()); break;
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// DeathSound
|
||||
//=========================================================
|
||||
void CHevbarn :: DeathSound ( void )
|
||||
{
|
||||
switch (RANDOM_LONG(0,2))
|
||||
{
|
||||
case 0: EMIT_SOUND_DYN( ENT(pev), CHAN_VOICE, "barney/ba_die1.wav", 1, ATTN_NORM, 0, GetVoicePitch()); break;
|
||||
case 1: EMIT_SOUND_DYN( ENT(pev), CHAN_VOICE, "barney/ba_die2.wav", 1, ATTN_NORM, 0, GetVoicePitch()); break;
|
||||
case 2: EMIT_SOUND_DYN( ENT(pev), CHAN_VOICE, "barney/ba_die3.wav", 1, ATTN_NORM, 0, GetVoicePitch()); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CHevbarn::TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType)
|
||||
{
|
||||
switch( ptr->iHitgroup)
|
||||
{
|
||||
case HITGROUP_CHEST:
|
||||
case HITGROUP_STOMACH:
|
||||
if (bitsDamageType & (DMG_BULLET | DMG_SLASH | DMG_BLAST))
|
||||
{
|
||||
flDamage = flDamage / 2;
|
||||
}
|
||||
break;
|
||||
case 10:
|
||||
if (bitsDamageType & (DMG_BULLET | DMG_SLASH | DMG_CLUB))
|
||||
{
|
||||
flDamage -= 20;
|
||||
if (flDamage <= 0)
|
||||
{
|
||||
UTIL_Ricochet( ptr->vecEndPos, 1.0 );
|
||||
flDamage = 0.01;
|
||||
}
|
||||
}
|
||||
// always a head shot
|
||||
ptr->iHitgroup = HITGROUP_HEAD;
|
||||
break;
|
||||
}
|
||||
|
||||
CTalkMonster::TraceAttack( pevAttacker, flDamage, vecDir, ptr, bitsDamageType );
|
||||
}
|
||||
|
||||
|
||||
void CHevbarn::Killed( entvars_t *pevAttacker, int iGib )
|
||||
{
|
||||
if ( pev->body < HEVBARN_BODY_GUNGONE )
|
||||
{// drop the gun!
|
||||
Vector vecGunPos;
|
||||
Vector vecGunAngles;
|
||||
|
||||
pev->body = HEVBARN_BODY_GUNGONE;
|
||||
|
||||
GetAttachment( 0, vecGunPos, vecGunAngles );
|
||||
|
||||
CBaseEntity *pGun = DropItem( "weapon_barney9mmhg", vecGunPos, vecGunAngles );
|
||||
}
|
||||
|
||||
SetUse( NULL );
|
||||
CTalkMonster::Killed( pevAttacker, iGib );
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// AI Schedules Specific to this monster
|
||||
//=========================================================
|
||||
|
||||
Schedule_t* CHevbarn :: GetScheduleOfType ( int Type )
|
||||
{
|
||||
Schedule_t *psched;
|
||||
|
||||
switch( Type )
|
||||
{
|
||||
case SCHED_ARM_WEAPON:
|
||||
if ( m_hEnemy != NULL )
|
||||
{
|
||||
// face enemy, then draw.
|
||||
return slHevbarnEnemyDraw;
|
||||
}
|
||||
break;
|
||||
|
||||
// Hook these to make a looping schedule
|
||||
case SCHED_TARGET_FACE:
|
||||
// call base class default so that hevbarn will talk
|
||||
// when 'used'
|
||||
psched = CTalkMonster::GetScheduleOfType(Type);
|
||||
|
||||
if (psched == slIdleStand)
|
||||
return slHvBaFaceTarget; // override this for different target face behavior
|
||||
else
|
||||
return psched;
|
||||
|
||||
case SCHED_TARGET_CHASE:
|
||||
return slHvBaFollow;
|
||||
|
||||
case SCHED_IDLE_STAND:
|
||||
// call base class default so that scientist will talk
|
||||
// when standing during idle
|
||||
psched = CTalkMonster::GetScheduleOfType(Type);
|
||||
|
||||
if (psched == slIdleStand)
|
||||
{
|
||||
// just look straight ahead.
|
||||
return slIdleHvBaStand;
|
||||
}
|
||||
else
|
||||
return psched;
|
||||
}
|
||||
|
||||
return CTalkMonster::GetScheduleOfType( Type );
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// GetSchedule - Decides which type of schedule best suits
|
||||
// the monster's current state and conditions. Then calls
|
||||
// monster's member function to get a pointer to a schedule
|
||||
// of the proper type.
|
||||
//=========================================================
|
||||
Schedule_t *CHevbarn :: GetSchedule ( void )
|
||||
{
|
||||
if ( HasConditions( bits_COND_HEAR_SOUND ) )
|
||||
{
|
||||
CSound *pSound;
|
||||
pSound = PBestSound();
|
||||
|
||||
ASSERT( pSound != NULL );
|
||||
if ( pSound && (pSound->m_iType & bits_SOUND_DANGER) )
|
||||
return GetScheduleOfType( SCHED_TAKE_COVER_FROM_BEST_SOUND );
|
||||
}
|
||||
if ( HasConditions( bits_COND_ENEMY_DEAD ) && FOkToSpeak() )
|
||||
{
|
||||
PlaySentence( "BA_KILL", 4, VOL_NORM, ATTN_NORM );
|
||||
}
|
||||
|
||||
switch( m_MonsterState )
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
// always act surprized with a new enemy
|
||||
if ( HasConditions( bits_COND_NEW_ENEMY ) && HasConditions( bits_COND_LIGHT_DAMAGE) )
|
||||
return GetScheduleOfType( SCHED_SMALL_FLINCH );
|
||||
|
||||
// wait for one schedule to draw gun
|
||||
if (!m_fGunDrawn )
|
||||
return GetScheduleOfType( SCHED_ARM_WEAPON );
|
||||
|
||||
if ( HasConditions( bits_COND_HEAVY_DAMAGE ) )
|
||||
return GetScheduleOfType( SCHED_TAKE_COVER_FROM_ENEMY );
|
||||
}
|
||||
break;
|
||||
|
||||
case MONSTERSTATE_ALERT:
|
||||
case MONSTERSTATE_IDLE:
|
||||
if ( HasConditions(bits_COND_LIGHT_DAMAGE | bits_COND_HEAVY_DAMAGE))
|
||||
{
|
||||
// flinch if hurt
|
||||
return GetScheduleOfType( SCHED_SMALL_FLINCH );
|
||||
}
|
||||
|
||||
if ( m_hEnemy == NULL && IsFollowing() )
|
||||
{
|
||||
if ( !m_hTargetEnt->IsAlive() )
|
||||
{
|
||||
// UNDONE: Comment about the recently dead player here?
|
||||
StopFollowing( FALSE );
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( HasConditions( bits_COND_CLIENT_PUSH ) )
|
||||
{
|
||||
return GetScheduleOfType( SCHED_MOVE_AWAY_FOLLOW );
|
||||
}
|
||||
return GetScheduleOfType( SCHED_TARGET_FACE );
|
||||
}
|
||||
}
|
||||
|
||||
if ( HasConditions( bits_COND_CLIENT_PUSH ) )
|
||||
{
|
||||
return GetScheduleOfType( SCHED_MOVE_AWAY );
|
||||
}
|
||||
|
||||
// try to say something about smells
|
||||
TrySmellTalk();
|
||||
break;
|
||||
}
|
||||
|
||||
return CTalkMonster::GetSchedule();
|
||||
}
|
||||
|
||||
MONSTERSTATE CHevbarn :: GetIdealState ( void )
|
||||
{
|
||||
return CTalkMonster::GetIdealState();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CHevbarn::DeclineFollowing( void )
|
||||
{
|
||||
PlaySentence( "BA_POK", 2, VOL_NORM, ATTN_NORM );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//=========================================================
|
||||
// DEAD HEVBARN PROP
|
||||
//
|
||||
// Designer selects a pose in worldcraft, 0 through num_poses-1
|
||||
// this value is added to what is selected as the 'first dead pose'
|
||||
// among the monster's normal animations. All dead poses must
|
||||
// appear sequentially in the model file. Be sure and set
|
||||
// the m_iFirstPose properly!
|
||||
//
|
||||
//=========================================================
|
||||
class CDeadHevbarn : public CBaseMonster
|
||||
{
|
||||
public:
|
||||
void Spawn( void );
|
||||
int Classify ( void ) { return CLASS_PLAYER_ALLY; }
|
||||
|
||||
void KeyValue( KeyValueData *pkvd );
|
||||
|
||||
int m_iPose;// which sequence to display -- temporary, don't need to save
|
||||
static char *m_szPoses[3];
|
||||
};
|
||||
|
||||
char *CDeadHevbarn::m_szPoses[] = { "lying_on_back", "lying_on_side", "lying_on_stomach" };
|
||||
|
||||
void CDeadHevbarn::KeyValue( KeyValueData *pkvd )
|
||||
{
|
||||
if (FStrEq(pkvd->szKeyName, "pose"))
|
||||
{
|
||||
m_iPose = atoi(pkvd->szValue);
|
||||
pkvd->fHandled = TRUE;
|
||||
}
|
||||
else
|
||||
CBaseMonster::KeyValue( pkvd );
|
||||
}
|
||||
|
||||
LINK_ENTITY_TO_CLASS( monster_hevbarn_dead, CDeadHevbarn );
|
||||
|
||||
//=========================================================
|
||||
// ********** DeadHevbarn SPAWN **********
|
||||
//=========================================================
|
||||
void CDeadHevbarn :: Spawn( )
|
||||
{
|
||||
PRECACHE_MODEL("models/hev_barney.mdl");
|
||||
SET_MODEL(ENT(pev), "models/hev_barney.mdl");
|
||||
|
||||
pev->effects = 0;
|
||||
pev->yaw_speed = 8;
|
||||
pev->sequence = 0;
|
||||
m_bloodColor = BLOOD_COLOR_RED;
|
||||
|
||||
pev->sequence = LookupSequence( m_szPoses[m_iPose] );
|
||||
if (pev->sequence == -1)
|
||||
{
|
||||
ALERT ( at_console, "Dead hevbarn with bad pose\n" );
|
||||
}
|
||||
// Corpses have less health
|
||||
pev->health = 8;//gSkillData.hevbarnHealth;
|
||||
|
||||
MonsterInitDead();
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,368 @@
|
|||
/***
|
||||
*
|
||||
* 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 "extdll.h"
|
||||
#include "util.h"
|
||||
#include "cbase.h"
|
||||
#include "monsters.h"
|
||||
#include "weapons.h"
|
||||
#include "nodes.h"
|
||||
#include "player.h"
|
||||
#include "gamerules.h"
|
||||
|
||||
#define CROWBAR_BODYHIT_VOLUME 128
|
||||
#define CROWBAR_WALLHIT_VOLUME 512
|
||||
|
||||
LINK_ENTITY_TO_CLASS( weapon_kmedkit, CKMedKit )
|
||||
|
||||
enum kmedkit_e
|
||||
{
|
||||
KMEDKIT_IDLE1 = 0,
|
||||
KMEDKIT_IDLE2,
|
||||
KMEDKIT_LONGIDLE,
|
||||
KMEDKIT_LONGUSE,
|
||||
KMEDKIT_SHORTUSE,
|
||||
KMEDKIT_HOLSTER,
|
||||
KMEDKIT_DEPLOY
|
||||
};
|
||||
|
||||
void CKMedKit::Spawn()
|
||||
{
|
||||
Precache();
|
||||
m_iId = WEAPON_KMEDKIT;
|
||||
SET_MODEL( ENT( pev ), "models/w_kmedkit.mdl" );
|
||||
m_iDefaultAmmo = KMEDKIT_DEFAULT_GIVE;
|
||||
|
||||
FallInit();// get ready to fall down.
|
||||
}
|
||||
|
||||
void CKMedKit::Precache( void )
|
||||
{
|
||||
PRECACHE_MODEL( "models/v_kmedkit.mdl" );
|
||||
PRECACHE_MODEL( "models/w_kmedkit.mdl" );
|
||||
PRECACHE_MODEL( "models/p_kmedkit.mdl" );
|
||||
PRECACHE_SOUND( "weapons/kmedkit_miss.wav" );
|
||||
PRECACHE_SOUND( "weapons/kmedkit_heal.wav" );
|
||||
}
|
||||
|
||||
int CKMedKit::GetItemInfo( ItemInfo *p )
|
||||
{
|
||||
p->pszName = STRING( pev->classname );
|
||||
p->pszAmmo1 = "katemedickit";
|
||||
p->iMaxAmmo1 = KMEDKIT_MAX_CARRY;
|
||||
p->pszAmmo2 = NULL;
|
||||
p->iMaxAmmo2 = -1;
|
||||
p->iMaxClip = WEAPON_NOCLIP;
|
||||
p->iSlot = 0;
|
||||
p->iPosition = 2;
|
||||
p->iId = WEAPON_KMEDKIT;
|
||||
p->iWeight = KMEDKIT_WEIGHT;
|
||||
p->iFlags = ITEM_FLAG_SELECTONEMPTY | ITEM_FLAG_NOAUTORELOAD | ITEM_FLAG_NOAUTOSWITCHEMPTY;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CKMedKit::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 CKMedKit::Deploy()
|
||||
{
|
||||
return DefaultDeploy( "models/v_kmedkit.mdl", "models/p_kmedkit.mdl", KMEDKIT_DEPLOY, "kmedkit" );
|
||||
}
|
||||
|
||||
void CKMedKit::Holster( int skiplocal /* = 0 */ )
|
||||
{
|
||||
DefaultHolster( KMEDKIT_HOLSTER, 0.5 );
|
||||
}
|
||||
|
||||
extern void FindHullIntersection( const Vector &vecSrc, TraceResult &tr, float *mins, float *maxs, edict_t *pEntity );
|
||||
/*
|
||||
void FindHullIntersection( const Vector &vecSrc, TraceResult &tr, float *mins, float *maxs, edict_t *pEntity )
|
||||
{
|
||||
int i, j, k;
|
||||
float distance;
|
||||
float *minmaxs[2] = {mins, maxs};
|
||||
TraceResult tmpTrace;
|
||||
Vector vecHullEnd = tr.vecEndPos;
|
||||
Vector vecEnd;
|
||||
|
||||
distance = 1e6f;
|
||||
|
||||
vecHullEnd = vecSrc + ( ( vecHullEnd - vecSrc ) * 2 );
|
||||
UTIL_TraceLine( vecSrc, vecHullEnd, dont_ignore_monsters, pEntity, &tmpTrace );
|
||||
if( tmpTrace.flFraction < 1.0 )
|
||||
{
|
||||
tr = tmpTrace;
|
||||
return;
|
||||
}
|
||||
|
||||
for( i = 0; i < 2; i++ )
|
||||
{
|
||||
for( j = 0; j < 2; j++ )
|
||||
{
|
||||
for( k = 0; k < 2; k++ )
|
||||
{
|
||||
vecEnd.x = vecHullEnd.x + minmaxs[i][0];
|
||||
vecEnd.y = vecHullEnd.y + minmaxs[j][1];
|
||||
vecEnd.z = vecHullEnd.z + minmaxs[k][2];
|
||||
|
||||
UTIL_TraceLine( vecSrc, vecEnd, dont_ignore_monsters, pEntity, &tmpTrace );
|
||||
if( tmpTrace.flFraction < 1.0 )
|
||||
{
|
||||
float thisDistance = ( tmpTrace.vecEndPos - vecSrc ).Length();
|
||||
if( thisDistance < distance )
|
||||
{
|
||||
tr = tmpTrace;
|
||||
distance = thisDistance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
void CKMedKit::PrimaryAttack()
|
||||
{
|
||||
if( m_pPlayer->m_bIsHolster )
|
||||
{
|
||||
WeaponIdle();
|
||||
return;
|
||||
}
|
||||
|
||||
if( m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] > 0 )
|
||||
{
|
||||
UseMedkit( 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
EMIT_SOUND_DYN( ENT( m_pPlayer->pev ), CHAN_ITEM, "weapons/kmedkit_miss.wav", 1, ATTN_NORM, 0, 94 + RANDOM_LONG( 0, 15 ) );
|
||||
m_flNextPrimaryAttack = gpGlobals->time + 0.5f;
|
||||
m_flNextSecondaryAttack = gpGlobals->time + 0.1f;
|
||||
}
|
||||
}
|
||||
|
||||
void CKMedKit::SecondaryAttack()
|
||||
{
|
||||
if( m_pPlayer->m_bIsHolster )
|
||||
{
|
||||
WeaponIdle();
|
||||
return;
|
||||
}
|
||||
|
||||
if( m_flNextPrimaryAttack <= UTIL_WeaponTimeBase() )
|
||||
UseMedkit( 2 );
|
||||
}
|
||||
|
||||
void CKMedKit::UseMedkit( int fMode )
|
||||
{
|
||||
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
|
||||
|
||||
// player "shoot" animation
|
||||
m_pPlayer->SetAnimation( PLAYER_ATTACK1 );
|
||||
|
||||
if( tr.flFraction < 1.0 )
|
||||
{
|
||||
CBaseEntity *pEntity = CBaseEntity::Instance( tr.pHit );
|
||||
if( pEntity )
|
||||
{
|
||||
if( FClassnameIs( ENT( pEntity->pev ), "monster_kate" ) )
|
||||
{
|
||||
if( fMode == 2 )
|
||||
{
|
||||
if( !m_bIsStateChanged )
|
||||
{
|
||||
m_bIsStateChanged = TRUE;
|
||||
m_iState = 0;
|
||||
m_iKateHealth = pEntity->pev->health;
|
||||
|
||||
SendWeaponAnim( KMEDKIT_LONGUSE, 0 );
|
||||
|
||||
SetThink( &CKMedKit::SayKateHealth );
|
||||
pev->nextthink = gpGlobals->time + 0.1f;
|
||||
|
||||
m_flTimeWeaponIdle = gpGlobals->time + 2.4f;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( pEntity->pev->health == gSkillData.kateHealth || pEntity->pev->dmg )
|
||||
goto miss;
|
||||
|
||||
SendWeaponAnim( KMEDKIT_SHORTUSE, 0 );
|
||||
m_flTimeWeaponIdle = gpGlobals->time + 1.1f;
|
||||
|
||||
pEntity->pev->health = gSkillData.healthkitCapacity + pEntity->pev->health;
|
||||
if( pEntity->pev->health > gSkillData.kateHealth )
|
||||
pEntity->pev->health = gSkillData.kateHealth;
|
||||
|
||||
SetThink( &CKMedKit::SayKateHealth );
|
||||
pev->nextthink = gpGlobals->time + 1.5f;
|
||||
|
||||
m_bIsStateChanged = TRUE;
|
||||
m_iState = 1;
|
||||
m_iKateHealth = pEntity->pev->health;
|
||||
|
||||
--m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType];
|
||||
EMIT_SOUND( ENT( m_pPlayer->pev ), CHAN_WEAPON, "weapons/kmedkit_heal.wav", 1, ATTN_NORM );
|
||||
}
|
||||
m_flNextPrimaryAttack = m_flNextSecondaryAttack = gpGlobals->time + 100.0f;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
miss:
|
||||
// miss
|
||||
m_flNextPrimaryAttack = m_flNextSecondaryAttack = gpGlobals->time + 0.5f;
|
||||
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + UTIL_SharedRandomFloat( m_pPlayer->random_seed, 10, 15 );
|
||||
|
||||
// player "shoot" animation
|
||||
m_pPlayer->SetAnimation( PLAYER_ATTACK1 );
|
||||
|
||||
SendWeaponAnim( KMEDKIT_IDLE1, 0 );
|
||||
EMIT_SOUND_DYN( ENT( m_pPlayer->pev ), CHAN_WEAPON, "weapons/kmedkit_miss.wav", 1, ATTN_NORM, 0, 94 + RANDOM_LONG( 0, 15 ) );
|
||||
}
|
||||
|
||||
void CKMedKit::SayKateHealth()
|
||||
{
|
||||
if( m_bIsStateChanged )
|
||||
{
|
||||
char szSentence[64];
|
||||
const char *pszSentence;
|
||||
|
||||
switch( m_iState )
|
||||
{
|
||||
case 0:
|
||||
pszSentence = "!KA_HEALTHST1";
|
||||
++m_iState;
|
||||
pev->nextthink = gpGlobals->time + 1.8f;
|
||||
break;
|
||||
case 1:
|
||||
pszSentence = "!KA_HEALTHST2";
|
||||
++m_iState;
|
||||
pev->nextthink = gpGlobals->time + 2.0f;
|
||||
break;
|
||||
case 2:
|
||||
UTIL_ShowKateHealth( m_iKateHealth );
|
||||
if( m_iKateHealth < 100 )
|
||||
{
|
||||
if( m_iKateHealth >= 20 )
|
||||
{
|
||||
sprintf( szSentence, "!KA_HEALTH%d0", m_iKateHealth / 10 );
|
||||
pszSentence = szSentence;
|
||||
pev->nextthink = gpGlobals->time + 1.5f;
|
||||
++m_iState;
|
||||
if( m_iKateHealth % 10 == 0 )
|
||||
++m_iState;
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf( szSentence, "!KA_HEALTH%d", m_iKateHealth );
|
||||
pszSentence = szSentence;
|
||||
pev->nextthink = gpGlobals->time + 1.6f;
|
||||
m_iState += 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pszSentence = "!KA_HEALTH00";
|
||||
pev->nextthink = gpGlobals->time + 1.2f;
|
||||
m_iState += 2;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
sprintf( szSentence, "!KA_HEALTH%d", m_iKateHealth % 10 );
|
||||
pszSentence = szSentence;
|
||||
pev->nextthink = gpGlobals->time + 1.0f;
|
||||
++m_iState;
|
||||
break;
|
||||
case 4:
|
||||
pszSentence = "!KA_HEALTHED";
|
||||
pev->nextthink = gpGlobals->time + 1.0f;
|
||||
++m_iState;
|
||||
break;
|
||||
case 5:
|
||||
m_bIsStateChanged = FALSE;
|
||||
m_flNextPrimaryAttack = m_flNextSecondaryAttack = m_flTimeWeaponIdle = gpGlobals->time + 0.1f;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
EMIT_SOUND_SUIT( m_pPlayer->edict(), pszSentence );
|
||||
}
|
||||
}
|
||||
|
||||
void CKMedKit::WeaponIdle()
|
||||
{
|
||||
if( m_pPlayer->m_bIsHolster )
|
||||
{
|
||||
if( m_flTimeWeaponIdle <= UTIL_WeaponTimeBase() )
|
||||
{
|
||||
m_pPlayer->m_bIsHolster = FALSE;
|
||||
Deploy();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if( m_flTimeWeaponIdle < UTIL_WeaponTimeBase() )
|
||||
{
|
||||
int iAnim, iRand = RANDOM_LONG( 0, 2 );
|
||||
if( iRand == 0 )
|
||||
{
|
||||
iAnim = KMEDKIT_LONGIDLE;
|
||||
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 2.7f;
|
||||
}
|
||||
else if( iRand == 1 )
|
||||
{
|
||||
iAnim = KMEDKIT_IDLE2;
|
||||
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 1.3f;
|
||||
}
|
||||
else
|
||||
{
|
||||
iAnim = KMEDKIT_IDLE1;
|
||||
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + UTIL_SharedRandomFloat( m_pPlayer->random_seed, 10, 15 );
|
||||
}
|
||||
SendWeaponAnim( iAnim );
|
||||
}
|
||||
}
|
|
@ -32,11 +32,11 @@ enum m41a_e
|
|||
M41A_DEPLOY,
|
||||
M41A_FIRE1,
|
||||
M41A_FIRE2,
|
||||
//M41A_FIRE3,
|
||||
M41A_FIRE3,
|
||||
M41A_HOLSTER
|
||||
};
|
||||
|
||||
|
||||
|
||||
LINK_ENTITY_TO_CLASS( weapon_9mmm41a, CM41A );
|
||||
|
||||
//=========================================================
|
||||
|
@ -76,15 +76,13 @@ void CM41A::Precache( void )
|
|||
PRECACHE_SOUND("items/cliprelease1.wav");
|
||||
|
||||
PRECACHE_SOUND ("weapons/m41ahks1.wav");// H to the K
|
||||
PRECACHE_SOUND ("weapons/m41ahks2.wav");// H to the K
|
||||
|
||||
PRECACHE_SOUND( "weapons/m41aglauncher.wav" );
|
||||
PRECACHE_SOUND( "weapons/m41aglauncher2.wav" );
|
||||
|
||||
PRECACHE_SOUND ("weapons/357_cock1.wav");
|
||||
|
||||
m_usM41A = PRECACHE_EVENT( 1, "events/M41A.sc" );
|
||||
m_usM41A2 = PRECACHE_EVENT( 1, "events/M41A.sc" );
|
||||
m_usM41A = PRECACHE_EVENT( 1, "events/m41a.sc" );
|
||||
}
|
||||
|
||||
int CM41A::GetItemInfo(ItemInfo *p)
|
||||
|
@ -96,10 +94,10 @@ int CM41A::GetItemInfo(ItemInfo *p)
|
|||
p->iMaxAmmo2 = M203_GRENADE_MAX_CARRY;
|
||||
p->iMaxClip = MP5_MAX_CLIP;
|
||||
p->iSlot = 2;
|
||||
p->iPosition = 3;
|
||||
p->iPosition = 5;
|
||||
p->iFlags = 0;
|
||||
p->iId = m_iId = WEAPON_M41A;
|
||||
p->iWeight = MP5_WEIGHT;
|
||||
p->iWeight = M41A_WEIGHT;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -121,21 +119,31 @@ BOOL CM41A::Deploy( )
|
|||
return DefaultDeploy( "models/v_9mmm41a.mdl", "models/p_9mmm41a.mdl", M41A_DEPLOY, "M41A" );
|
||||
}
|
||||
|
||||
void CM41A::Holster( int skiplocal /* = 0 */ )
|
||||
{
|
||||
DefaultHolster( M41A_HOLSTER, 0.9 );
|
||||
}
|
||||
|
||||
void CM41A::PrimaryAttack()
|
||||
{
|
||||
if( m_pPlayer->m_bIsHolster )
|
||||
{
|
||||
WeaponIdle();
|
||||
return;
|
||||
}
|
||||
|
||||
// don't fire underwater
|
||||
if (m_pPlayer->pev->waterlevel == 3)
|
||||
{
|
||||
PlayEmptySound( );
|
||||
m_flNextPrimaryAttack = 0.15;
|
||||
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.15;
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_iClip <= 0)
|
||||
{
|
||||
PlayEmptySound();
|
||||
m_flNextPrimaryAttack = 0.15;
|
||||
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.15;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -161,12 +169,12 @@ void CM41A::PrimaryAttack()
|
|||
#endif
|
||||
{
|
||||
// optimized multiplayer. Widened to make it easier to hit a moving player
|
||||
vecDir = m_pPlayer->FireBulletsPlayer( 4, vecSrc, vecAiming, VECTOR_CONE_2DEGREES, 8192, BULLET_PLAYER_M41A, 2, 0, m_pPlayer->pev, m_pPlayer->random_seed );
|
||||
vecDir = m_pPlayer->FireBulletsPlayer( 1, vecSrc, vecAiming, VECTOR_CONE_6DEGREES, 8192, BULLET_PLAYER_M41A, 2, 0, m_pPlayer->pev, m_pPlayer->random_seed );
|
||||
}
|
||||
else
|
||||
{
|
||||
// single player spread
|
||||
vecDir = m_pPlayer->FireBulletsPlayer( 4, vecSrc, vecAiming, VECTOR_CONE_1DEGREES, 8192, BULLET_PLAYER_M41A, 2, 0, m_pPlayer->pev, m_pPlayer->random_seed );
|
||||
vecDir = m_pPlayer->FireBulletsPlayer( 1, vecSrc, vecAiming, VECTOR_CONE_3DEGREES, 8192, BULLET_PLAYER_M41A, 2, 0, m_pPlayer->pev, m_pPlayer->random_seed );
|
||||
}
|
||||
|
||||
int flags;
|
||||
|
@ -182,7 +190,7 @@ void CM41A::PrimaryAttack()
|
|||
// HEV suit - indicate out of ammo condition
|
||||
m_pPlayer->SetSuitUpdate("!HEV_AMO0", FALSE, 0);
|
||||
|
||||
m_flNextPrimaryAttack = GetNextAttackDelay(0.1);
|
||||
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.1;
|
||||
|
||||
if ( m_flNextPrimaryAttack < UTIL_WeaponTimeBase() )
|
||||
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.1;
|
||||
|
@ -194,11 +202,17 @@ void CM41A::PrimaryAttack()
|
|||
|
||||
void CM41A::SecondaryAttack( void )
|
||||
{
|
||||
if( m_pPlayer->m_bIsHolster )
|
||||
{
|
||||
WeaponIdle();
|
||||
return;
|
||||
}
|
||||
|
||||
// don't fire underwater
|
||||
if (m_pPlayer->pev->waterlevel == 3)
|
||||
{
|
||||
PlayEmptySound( );
|
||||
m_flNextPrimaryAttack = 0.15;
|
||||
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.15;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -216,45 +230,59 @@ void CM41A::SecondaryAttack( void )
|
|||
|
||||
m_pPlayer->m_rgAmmo[m_iSecondaryAmmoType]--;
|
||||
|
||||
SendWeaponAnim( M41A_LAUNCH );
|
||||
|
||||
// player "shoot" animation
|
||||
m_pPlayer->SetAnimation( PLAYER_ATTACK1 );
|
||||
|
||||
// play this sound through BODY channel so we can hear it if player didn't stop firing MP3
|
||||
EMIT_SOUND( ENT( m_pPlayer->pev ), CHAN_WEAPON, RANDOM_LONG( 0, 1 ) ? "weapons/m41aglauncher.wav" : "weapons/m41aglauncher2.wav", 0.8, ATTN_NORM );
|
||||
|
||||
UTIL_MakeVectors( m_pPlayer->pev->v_angle + m_pPlayer->pev->punchangle );
|
||||
|
||||
// we don't add in player velocity anymore.
|
||||
CGrenade::ShootContact( m_pPlayer->pev,
|
||||
m_pPlayer->pev->origin + m_pPlayer->pev->view_ofs + gpGlobals->v_forward * 16,
|
||||
gpGlobals->v_forward * 800 );
|
||||
gpGlobals->v_forward * 800, gSkillData.plrDmgM41AGrenade );
|
||||
|
||||
int flags;
|
||||
#if defined( CLIENT_WEAPONS )
|
||||
flags = FEV_NOTHOST;
|
||||
#else
|
||||
flags = 0;
|
||||
#endif
|
||||
|
||||
PLAYBACK_EVENT( flags, m_pPlayer->edict(), m_usM41A2 );
|
||||
|
||||
m_flNextPrimaryAttack = GetNextAttackDelay(1);
|
||||
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 1;
|
||||
m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 1;
|
||||
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 5;// idle pretty soon after shooting.
|
||||
|
||||
if (!m_pPlayer->m_rgAmmo[m_iSecondaryAmmoType])
|
||||
// HEV suit - indicate out of ammo condition
|
||||
m_pPlayer->SetSuitUpdate("!HEV_AMO0", FALSE, 0);
|
||||
|
||||
m_pPlayer->pev->punchangle.x -= 10;
|
||||
}
|
||||
|
||||
void CM41A::Reload( void )
|
||||
{
|
||||
if ( m_pPlayer->ammo_9mm <= 0 )
|
||||
if( m_pPlayer->m_bIsHolster )
|
||||
{
|
||||
WeaponIdle();
|
||||
return;
|
||||
}
|
||||
|
||||
if( m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0 || m_iClip == MP5_MAX_CLIP )
|
||||
return;
|
||||
|
||||
DefaultReload( MP5_MAX_CLIP, M41A_RELOAD, 1.5 );
|
||||
DefaultReload( MP5_MAX_CLIP, M41A_RELOAD, 2.0 );
|
||||
}
|
||||
|
||||
|
||||
void CM41A::WeaponIdle( void )
|
||||
{
|
||||
if( m_pPlayer->m_bIsHolster )
|
||||
{
|
||||
if( m_flTimeWeaponIdle <= UTIL_WeaponTimeBase() )
|
||||
{
|
||||
m_pPlayer->m_bIsHolster = FALSE;
|
||||
Deploy();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
ResetEmptySound( );
|
||||
|
||||
m_pPlayer->GetAutoaimVector( AUTOAIM_5DEGREES );
|
||||
|
@ -280,3 +308,8 @@ void CM41A::WeaponIdle( void )
|
|||
m_flTimeWeaponIdle = UTIL_SharedRandomFloat( m_pPlayer->random_seed, 10, 15 ); // how long till we do this again.
|
||||
}
|
||||
|
||||
BOOL CM41A::IsUseable()
|
||||
{
|
||||
//Can be used if the player has AR grenades. - Solokiller
|
||||
return CBasePlayerWeapon::IsUseable() || m_pPlayer->m_rgAmmo[m_iSecondaryAmmoType] > 0;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,517 @@
|
|||
/***
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
****/
|
||||
//=========================================================
|
||||
// Alien slave monster
|
||||
//=========================================================
|
||||
|
||||
#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 CPanther : public CISlave
|
||||
{
|
||||
public:
|
||||
void Spawn( void );
|
||||
void Precache( void );
|
||||
void HandleAnimEvent( MonsterEvent_t *pEvent );
|
||||
void TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType);
|
||||
|
||||
void DeathSound( void );
|
||||
void PainSound( void );
|
||||
void AlertSound( void );
|
||||
void IdleSound( void );
|
||||
|
||||
void ClearBeams();
|
||||
void ArmBeam( int side );
|
||||
void WackBeam( int side, CBaseEntity *pEntity );
|
||||
void ZapBeam( int side );
|
||||
|
||||
static const char *pAttackHitSounds[];
|
||||
static const char *pAttackMissSounds[];
|
||||
static const char *pPainSounds[];
|
||||
static const char *pDeathSounds[];
|
||||
static const char *pIdleSounds[];
|
||||
static const char *pAlertSounds[];
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS( monster_alien_panther, CPanther )
|
||||
|
||||
const char *CPanther::pAttackHitSounds[] =
|
||||
{
|
||||
"panther/pclaw_strike1.wav",
|
||||
"panther/pclaw_strike2.wav",
|
||||
"panther/pclaw_strike3.wav",
|
||||
};
|
||||
|
||||
const char *CPanther::pAttackMissSounds[] =
|
||||
{
|
||||
"panther/pclaw_miss1.wav",
|
||||
"panther/pclaw_miss2.wav",
|
||||
};
|
||||
|
||||
const char *CPanther::pPainSounds[] =
|
||||
{
|
||||
"panther/p_pain1.wav",
|
||||
"panther/p_pain2.wav",
|
||||
};
|
||||
|
||||
const char *CPanther::pDeathSounds[] =
|
||||
{
|
||||
"panther/p_die1.wav",
|
||||
"panther/p_die2.wav",
|
||||
};
|
||||
|
||||
const char *CPanther::pIdleSounds[] =
|
||||
{
|
||||
"panther/p_idle1.wav",
|
||||
"panther/p_idle2.wav",
|
||||
};
|
||||
|
||||
const char *CPanther::pAlertSounds[] =
|
||||
{
|
||||
"panther/p_alert1.wav",
|
||||
"panther/p_alert2.wav",
|
||||
};
|
||||
|
||||
//=========================================================
|
||||
// ALertSound - scream
|
||||
//=========================================================
|
||||
void CPanther::AlertSound( void )
|
||||
{
|
||||
if( m_hEnemy != 0 )
|
||||
{
|
||||
EMIT_SOUND_DYN( ENT( pev ), CHAN_WEAPON, pAlertSounds[RANDOM_LONG( 0, ARRAYSIZE( pDeathSounds ) - 1 )], 1.0, ATTN_NORM, 0, m_voicePitch );
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// IdleSound
|
||||
//=========================================================
|
||||
void CPanther::IdleSound( void )
|
||||
{
|
||||
if( RANDOM_LONG( 0, 2 ) == 0 )
|
||||
{
|
||||
EMIT_SOUND_DYN( ENT( pev ), CHAN_WEAPON, pIdleSounds[RANDOM_LONG( 0, ARRAYSIZE( pDeathSounds ) - 1 )], 1.0, ATTN_NORM, 0, m_voicePitch );
|
||||
}
|
||||
#if 0
|
||||
int side = RANDOM_LONG( 0, 1 ) * 2 - 1;
|
||||
|
||||
ClearBeams();
|
||||
ArmBeam( side );
|
||||
|
||||
UTIL_MakeAimVectors( pev->angles );
|
||||
Vector vecSrc = pev->origin + gpGlobals->v_right * 2 * side;
|
||||
MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, vecSrc );
|
||||
WRITE_BYTE( TE_DLIGHT );
|
||||
WRITE_COORD( vecSrc.x ); // X
|
||||
WRITE_COORD( vecSrc.y ); // Y
|
||||
WRITE_COORD( vecSrc.z ); // Z
|
||||
WRITE_BYTE( 8 ); // radius * 0.1
|
||||
WRITE_BYTE( 255 ); // r
|
||||
WRITE_BYTE( 180 ); // g
|
||||
WRITE_BYTE( 96 ); // b
|
||||
WRITE_BYTE( 10 ); // time * 10
|
||||
WRITE_BYTE( 0 ); // decay * 0.1
|
||||
MESSAGE_END();
|
||||
|
||||
EMIT_SOUND_DYN( ENT( pev ), CHAN_WEAPON, "debris/zap1.wav", 1, ATTN_NORM, 0, 100 );
|
||||
#endif
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// PainSound
|
||||
//=========================================================
|
||||
void CPanther::PainSound( void )
|
||||
{
|
||||
if( RANDOM_LONG( 0, 2 ) == 0 )
|
||||
{
|
||||
EMIT_SOUND_DYN( ENT( pev ), CHAN_WEAPON, pPainSounds[RANDOM_LONG( 0, ARRAYSIZE( pPainSounds ) - 1 )], 1.0, ATTN_NORM, 0, m_voicePitch );
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// DieSound
|
||||
//=========================================================
|
||||
void CPanther::DeathSound( void )
|
||||
{
|
||||
EMIT_SOUND_DYN( ENT( pev ), CHAN_WEAPON, pDeathSounds[RANDOM_LONG( 0, ARRAYSIZE( pDeathSounds ) - 1 )], 1.0, ATTN_NORM, 0, m_voicePitch );
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// HandleAnimEvent - catches the monster-specific messages
|
||||
// that occur when tagged animation frames are played.
|
||||
//
|
||||
// Returns number of events handled, 0 if none.
|
||||
//=========================================================
|
||||
void CPanther::HandleAnimEvent( MonsterEvent_t *pEvent )
|
||||
{
|
||||
// ALERT( at_console, "event %d : %f\n", pEvent->event, pev->frame );
|
||||
switch( pEvent->event )
|
||||
{
|
||||
case ISLAVE_AE_CLAW:
|
||||
{
|
||||
// SOUND HERE!
|
||||
CBaseEntity *pHurt = CheckTraceHullAttack( 70, gSkillData.pantherDmgClaw, DMG_SLASH );
|
||||
if( pHurt )
|
||||
{
|
||||
if( pHurt->pev->flags & ( FL_MONSTER | FL_CLIENT ) )
|
||||
{
|
||||
pHurt->pev->punchangle.z = -18;
|
||||
pHurt->pev->punchangle.x = 5;
|
||||
}
|
||||
// Play a random attack hit sound
|
||||
EMIT_SOUND_DYN( ENT( pev ), CHAN_WEAPON, pAttackHitSounds[RANDOM_LONG( 0, ARRAYSIZE( pAttackHitSounds ) - 1 )], 1.0, ATTN_NORM, 0, m_voicePitch );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Play a random attack miss sound
|
||||
EMIT_SOUND_DYN( ENT( pev ), CHAN_WEAPON, pAttackMissSounds[RANDOM_LONG( 0, ARRAYSIZE( pAttackMissSounds ) - 1 )], 1.0, ATTN_NORM, 0, m_voicePitch );
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ISLAVE_AE_CLAWRAKE:
|
||||
{
|
||||
CBaseEntity *pHurt = CheckTraceHullAttack( 70, gSkillData.pantherDmgClawRake, DMG_SLASH );
|
||||
if( pHurt )
|
||||
{
|
||||
if( pHurt->pev->flags & ( FL_MONSTER | FL_CLIENT ) )
|
||||
{
|
||||
pHurt->pev->punchangle.z = -18;
|
||||
pHurt->pev->punchangle.x = 5;
|
||||
}
|
||||
EMIT_SOUND_DYN( ENT( pev ), CHAN_WEAPON, pAttackHitSounds[RANDOM_LONG( 0, ARRAYSIZE( pAttackHitSounds ) - 1 )], 1.0, ATTN_NORM, 0, m_voicePitch );
|
||||
}
|
||||
else
|
||||
{
|
||||
EMIT_SOUND_DYN( ENT(pev), CHAN_WEAPON, pAttackMissSounds[RANDOM_LONG( 0, ARRAYSIZE( pAttackMissSounds ) - 1 )], 1.0, ATTN_NORM, 0, m_voicePitch );
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ISLAVE_AE_ZAP_POWERUP:
|
||||
{
|
||||
// speed up attack when on hard
|
||||
if( g_iSkillLevel == SKILL_HARD )
|
||||
pev->framerate = 1.5;
|
||||
|
||||
UTIL_MakeAimVectors( pev->angles );
|
||||
|
||||
if( m_iBeams == 0 )
|
||||
{
|
||||
Vector vecSrc = pev->origin + gpGlobals->v_forward * 2;
|
||||
|
||||
MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, vecSrc );
|
||||
WRITE_BYTE( TE_DLIGHT );
|
||||
WRITE_COORD( vecSrc.x ); // X
|
||||
WRITE_COORD( vecSrc.y ); // Y
|
||||
WRITE_COORD( vecSrc.z ); // Z
|
||||
WRITE_BYTE( 12 ); // radius * 0.1
|
||||
WRITE_BYTE( 192 ); // r
|
||||
WRITE_BYTE( 64 ); // g
|
||||
WRITE_BYTE( 8 ); // b
|
||||
WRITE_BYTE( 20 / pev->framerate ); // time * 10
|
||||
WRITE_BYTE( 0 ); // decay * 0.1
|
||||
MESSAGE_END();
|
||||
}
|
||||
if( m_hDead != 0 )
|
||||
{
|
||||
WackBeam( -1, m_hDead );
|
||||
WackBeam( 1, m_hDead );
|
||||
}
|
||||
else
|
||||
{
|
||||
ArmBeam( -1 );
|
||||
ArmBeam( 1 );
|
||||
BeamGlow();
|
||||
}
|
||||
|
||||
EMIT_SOUND_DYN( ENT( pev ), CHAN_WEAPON, "panther/p_zap2.wav", 1, ATTN_NORM, 0, 100 + m_iBeams * 10 );
|
||||
pev->skin = m_iBeams / 2;
|
||||
}
|
||||
break;
|
||||
case ISLAVE_AE_ZAP_SHOOT:
|
||||
{
|
||||
ClearBeams();
|
||||
|
||||
if( m_hDead != 0 )
|
||||
{
|
||||
Vector vecDest = m_hDead->pev->origin + Vector( 0, 0, 38 );
|
||||
TraceResult trace;
|
||||
UTIL_TraceHull( vecDest, vecDest, dont_ignore_monsters, human_hull, m_hDead->edict(), &trace );
|
||||
|
||||
if( !trace.fStartSolid )
|
||||
{
|
||||
CBaseEntity *pNew = Create( STRING( pev->classname ), m_hDead->pev->origin, m_hDead->pev->angles );
|
||||
//CBaseMonster *pNewMonster = pNew->MyMonsterPointer();
|
||||
pNew->pev->spawnflags |= 1;
|
||||
WackBeam( -1, pNew );
|
||||
WackBeam( 1, pNew );
|
||||
UTIL_Remove( m_hDead );
|
||||
EMIT_SOUND_DYN( ENT( pev ), CHAN_WEAPON, "panther/p_shoot1.wav", 1, ATTN_NORM, 0, RANDOM_LONG( 130, 160 ) );
|
||||
/*
|
||||
CBaseEntity *pEffect = Create( "test_effect", pNew->Center(), pev->angles );
|
||||
pEffect->Use( this, this, USE_ON, 1 );
|
||||
*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
ClearMultiDamage();
|
||||
|
||||
UTIL_MakeAimVectors( pev->angles );
|
||||
|
||||
ZapBeam( -1 );
|
||||
ZapBeam( 1 );
|
||||
|
||||
EMIT_SOUND_DYN( ENT( pev ), CHAN_WEAPON, "panther/p_shoot1.wav", 1, ATTN_NORM, 0, RANDOM_LONG( 130, 160 ) );
|
||||
// STOP_SOUND( ENT( pev ), CHAN_WEAPON, "panther/p_zap2.wav" );
|
||||
ApplyMultiDamage( pev, pev );
|
||||
|
||||
m_flNextAttack = gpGlobals->time + RANDOM_FLOAT( 0.5, 4.0 );
|
||||
}
|
||||
break;
|
||||
case ISLAVE_AE_ZAP_DONE:
|
||||
{
|
||||
ClearBeams();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
CSquadMonster::HandleAnimEvent( pEvent );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// Spawn
|
||||
//=========================================================
|
||||
void CPanther::Spawn()
|
||||
{
|
||||
Precache();
|
||||
|
||||
SET_MODEL( ENT( pev ), "models/panther.mdl" );
|
||||
|
||||
UTIL_SetSize( pev, Vector( -32, -32, 0 ), Vector( 32, 32, 64 ) );
|
||||
|
||||
pev->solid = SOLID_SLIDEBOX;
|
||||
pev->movetype = MOVETYPE_STEP;
|
||||
pev->effects = 0;
|
||||
pev->health = gSkillData.pantherHealth;
|
||||
m_bloodColor = BLOOD_COLOR_GREEN;
|
||||
m_voicePitch = RANDOM_LONG( 85, 110 );
|
||||
pev->view_ofs = Vector( 0, 0, 80 );// 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;
|
||||
|
||||
MonsterInit();
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// Precache - precaches all resources this monster needs
|
||||
//=========================================================
|
||||
void CPanther::Precache()
|
||||
{
|
||||
size_t i;
|
||||
|
||||
PRECACHE_MODEL( "models/panther.mdl" );
|
||||
PRECACHE_SOUND( "panther/p_zap1.wav" );
|
||||
PRECACHE_SOUND( "panther/p_zap2.wav" );
|
||||
PRECACHE_SOUND( "panther/p_electro1.wav" );
|
||||
PRECACHE_SOUND( "panther/p_shoot1.wav" );
|
||||
PRECACHE_SOUND( "panther/p_pain2.wav" );
|
||||
PRECACHE_SOUND( "panther/p_headbite.wav" );
|
||||
PRECACHE_SOUND( "panther/pclaw_miss1.wav" );
|
||||
|
||||
for( i = 0; i < ARRAYSIZE( pAttackHitSounds ); i++ )
|
||||
PRECACHE_SOUND( pAttackHitSounds[i] );
|
||||
|
||||
for( i = 0; i < ARRAYSIZE( pAttackMissSounds ); i++ )
|
||||
PRECACHE_SOUND( pAttackMissSounds[i] );
|
||||
|
||||
for( i = 0; i < ARRAYSIZE( pPainSounds ); i++ )
|
||||
PRECACHE_SOUND( pIdleSounds[i] );
|
||||
|
||||
for( i = 0; i < ARRAYSIZE( pPainSounds ); i++ )
|
||||
PRECACHE_SOUND( pAlertSounds[i] );
|
||||
|
||||
for( i = 0; i < ARRAYSIZE( pPainSounds ); i++ )
|
||||
PRECACHE_SOUND( pPainSounds[i] );
|
||||
|
||||
for( i = 0; i < ARRAYSIZE( pDeathSounds ); i++ )
|
||||
PRECACHE_SOUND( pDeathSounds[i] );
|
||||
|
||||
UTIL_PrecacheOther( "test_effect" );
|
||||
}
|
||||
|
||||
void CPanther::TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType )
|
||||
{
|
||||
if( bitsDamageType & DMG_SHOCK )
|
||||
return;
|
||||
|
||||
if( ptr->iHitgroup != HITGROUP_HEAD )
|
||||
{
|
||||
if( bitsDamageType & ( DMG_BULLET | DMG_SLASH | DMG_CLUB ) )
|
||||
{
|
||||
UTIL_Ricochet( ptr->vecEndPos, 1.0 );
|
||||
flDamage = 0.01;
|
||||
}
|
||||
}
|
||||
|
||||
CSquadMonster::TraceAttack( pevAttacker, flDamage, vecDir, ptr, bitsDamageType );
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// ArmBeam - small beam from arm to nearby geometry
|
||||
//=========================================================
|
||||
void CPanther::ArmBeam( int side )
|
||||
{
|
||||
TraceResult tr;
|
||||
int r, g, b;
|
||||
float flDist = 1.0;
|
||||
|
||||
if( m_iBeams >= ISLAVE_MAX_BEAMS )
|
||||
return;
|
||||
|
||||
UTIL_MakeAimVectors( pev->angles );
|
||||
Vector vecSrc = pev->origin + gpGlobals->v_up * 36 + gpGlobals->v_right * side * 16 + gpGlobals->v_forward * 32;
|
||||
|
||||
for( int i = 0; i < 3; i++ )
|
||||
{
|
||||
Vector vecAim = gpGlobals->v_right * side * RANDOM_FLOAT( 0, 1 ) + gpGlobals->v_up * RANDOM_FLOAT( -1, 1 );
|
||||
TraceResult tr1;
|
||||
UTIL_TraceLine( vecSrc, vecSrc + vecAim * 512, dont_ignore_monsters, ENT( pev ), &tr1 );
|
||||
if( flDist > tr1.flFraction )
|
||||
{
|
||||
tr = tr1;
|
||||
flDist = tr.flFraction;
|
||||
}
|
||||
}
|
||||
|
||||
// Couldn't find anything close enough
|
||||
if( flDist == 1.0 )
|
||||
return;
|
||||
|
||||
DecalGunshot( &tr, BULLET_PLAYER_CROWBAR );
|
||||
|
||||
m_pBeam[m_iBeams] = CBeam::BeamCreate( "sprites/lgtning.spr", 30 );
|
||||
if( !m_pBeam[m_iBeams] )
|
||||
return;
|
||||
|
||||
m_pBeam[m_iBeams]->PointEntInit( tr.vecEndPos, entindex() );
|
||||
m_pBeam[m_iBeams]->SetEndAttachment( side < 0 ? 2 : 1 );
|
||||
// m_pBeam[m_iBeams]->SetColor( 180, 255, 96 );
|
||||
|
||||
r = 192, g = 64, b = 8;
|
||||
|
||||
m_pBeam[m_iBeams]->SetColor( r, g, b );
|
||||
m_pBeam[m_iBeams]->SetBrightness( 64 );
|
||||
m_pBeam[m_iBeams]->SetNoise( 80 );
|
||||
m_iBeams++;
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// WackBeam - regenerate dead colleagues
|
||||
//=========================================================
|
||||
void CPanther::WackBeam( int side, CBaseEntity *pEntity )
|
||||
{
|
||||
//Vector vecDest;
|
||||
//float flDist = 1.0;
|
||||
int r, g, b;
|
||||
|
||||
if( m_iBeams >= ISLAVE_MAX_BEAMS )
|
||||
return;
|
||||
|
||||
if( pEntity == NULL )
|
||||
return;
|
||||
|
||||
m_pBeam[m_iBeams] = CBeam::BeamCreate( "sprites/lgtning.spr", 30 );
|
||||
if( !m_pBeam[m_iBeams] )
|
||||
return;
|
||||
|
||||
m_pBeam[m_iBeams]->PointEntInit( pEntity->Center(), entindex() );
|
||||
m_pBeam[m_iBeams]->SetEndAttachment( side < 0 ? 2 : 1 );
|
||||
|
||||
r = 192, g = 64, b = 8;
|
||||
|
||||
m_pBeam[m_iBeams]->SetColor( r, g, b );
|
||||
m_pBeam[m_iBeams]->SetBrightness( 255 );
|
||||
m_pBeam[m_iBeams]->SetNoise( 80 );
|
||||
m_iBeams++;
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// ZapBeam - heavy damage directly forward
|
||||
//=========================================================
|
||||
void CPanther::ZapBeam( int side )
|
||||
{
|
||||
Vector vecSrc, vecAim;
|
||||
int r, g, b;
|
||||
TraceResult tr;
|
||||
CBaseEntity *pEntity;
|
||||
|
||||
if( m_iBeams >= ISLAVE_MAX_BEAMS )
|
||||
return;
|
||||
|
||||
vecSrc = pev->origin + gpGlobals->v_up * 36;
|
||||
vecAim = ShootAtEnemy( vecSrc );
|
||||
float deflection = 0.01;
|
||||
vecAim = vecAim + side * gpGlobals->v_right * RANDOM_FLOAT( 0, deflection ) + gpGlobals->v_up * RANDOM_FLOAT( -deflection, deflection );
|
||||
UTIL_TraceLine( vecSrc, vecSrc + vecAim * 1024, dont_ignore_monsters, ENT( pev ), &tr );
|
||||
|
||||
m_pBeam[m_iBeams] = CBeam::BeamCreate( "sprites/lgtning.spr", 50 );
|
||||
if( !m_pBeam[m_iBeams] )
|
||||
return;
|
||||
|
||||
m_pBeam[m_iBeams]->PointEntInit( tr.vecEndPos, entindex() );
|
||||
m_pBeam[m_iBeams]->SetEndAttachment( side < 0 ? 2 : 1 );
|
||||
|
||||
r = 192, g = 64, b = 8;
|
||||
|
||||
m_pBeam[m_iBeams]->SetColor( r, g, b );
|
||||
m_pBeam[m_iBeams]->SetBrightness( 255 );
|
||||
m_pBeam[m_iBeams]->SetNoise( 20 );
|
||||
m_iBeams++;
|
||||
|
||||
pEntity = CBaseEntity::Instance( tr.pHit );
|
||||
if( pEntity != NULL && pEntity->pev->takedamage )
|
||||
{
|
||||
pEntity->TraceAttack( pev, gSkillData.pantherDmgZap, vecAim, &tr, DMG_SHOCK );
|
||||
}
|
||||
UTIL_EmitAmbientSound( ENT( pev ), tr.vecEndPos, "panther/p_electro1.wav", 0.5, ATTN_NORM, 0, RANDOM_LONG( 140, 160 ) );
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// ClearBeams - remove all beams
|
||||
//=========================================================
|
||||
void CPanther::ClearBeams()
|
||||
{
|
||||
for( int i = 0; i < ISLAVE_MAX_BEAMS; i++ )
|
||||
{
|
||||
if( m_pBeam[i] )
|
||||
{
|
||||
UTIL_Remove( m_pBeam[i] );
|
||||
m_pBeam[i] = NULL;
|
||||
}
|
||||
}
|
||||
m_iBeams = 0;
|
||||
pev->skin = 0;
|
||||
|
||||
STOP_SOUND( ENT( pev ), CHAN_WEAPON, "panther/p_zap2.wav" );
|
||||
}
|
|
@ -26,8 +26,7 @@
|
|||
#define POOLSTICK_BODYHIT_VOLUME 128
|
||||
#define POOLSTICK_WALLHIT_VOLUME 512
|
||||
|
||||
LINK_ENTITY_TO_CLASS( weapon_poolstick, CPoolstick );
|
||||
|
||||
LINK_ENTITY_TO_CLASS( weapon_poolstick, CPoolstick )
|
||||
|
||||
|
||||
enum poolstick_e {
|
||||
|
@ -39,7 +38,9 @@ enum poolstick_e {
|
|||
POOLSTICK_ATTACK2MISS,
|
||||
POOLSTICK_ATTACK2HIT,
|
||||
POOLSTICK_ATTACK3MISS,
|
||||
POOLSTICK_ATTACK3HIT
|
||||
POOLSTICK_ATTACK3HIT,
|
||||
POOLSTICK_IDLE2,
|
||||
POOLSTICK_IDLE3
|
||||
};
|
||||
|
||||
|
||||
|
@ -65,8 +66,6 @@ void CPoolstick::Precache( void )
|
|||
PRECACHE_SOUND("weapons/pstk_hitbod2.wav");
|
||||
PRECACHE_SOUND("weapons/pstk_hitbod3.wav");
|
||||
PRECACHE_SOUND("weapons/pstk_miss1.wav");
|
||||
|
||||
m_usPoolstick = PRECACHE_EVENT ( 1, "events/crowbar.sc" );
|
||||
}
|
||||
|
||||
int CPoolstick::GetItemInfo(ItemInfo *p)
|
||||
|
@ -78,7 +77,7 @@ int CPoolstick::GetItemInfo(ItemInfo *p)
|
|||
p->iMaxAmmo2 = -1;
|
||||
p->iMaxClip = WEAPON_NOCLIP;
|
||||
p->iSlot = 0;
|
||||
p->iPosition = 2;
|
||||
p->iPosition = 1;
|
||||
p->iId = WEAPON_POOLSTICK;
|
||||
p->iWeight = CROWBAR_WEIGHT;
|
||||
return 1;
|
||||
|
@ -93,12 +92,11 @@ BOOL CPoolstick::Deploy( )
|
|||
|
||||
void CPoolstick::Holster( int skiplocal /* = 0 */ )
|
||||
{
|
||||
m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.5;
|
||||
SendWeaponAnim( POOLSTICK_HOLSTER );
|
||||
DefaultHolster( POOLSTICK_HOLSTER, 0.7 );
|
||||
}
|
||||
|
||||
|
||||
void FindHullIntersection2( const Vector &vecSrc, TraceResult &tr, float *mins, float *maxs, edict_t *pEntity )
|
||||
extern void FindHullIntersection( const Vector &vecSrc, TraceResult &tr, float *mins, float *maxs, edict_t *pEntity );
|
||||
/*void FindHullIntersection( const Vector &vecSrc, TraceResult &tr, float *mins, float *maxs, edict_t *pEntity )
|
||||
{
|
||||
int i, j, k;
|
||||
float distance;
|
||||
|
@ -141,10 +139,16 @@ void FindHullIntersection2( const Vector &vecSrc, TraceResult &tr, float *mins,
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
void CPoolstick::PrimaryAttack()
|
||||
{
|
||||
if( m_pPlayer->m_bIsHolster )
|
||||
{
|
||||
WeaponIdle();
|
||||
return;
|
||||
}
|
||||
|
||||
if (! Swing( 1 ))
|
||||
{
|
||||
SetThink( &CPoolstick::SwingAgain );
|
||||
|
@ -187,31 +191,40 @@ int CPoolstick::Swing( int fFirst )
|
|||
// This is and approximation of the "best" intersection
|
||||
CBaseEntity *pHit = CBaseEntity::Instance( tr.pHit );
|
||||
if ( !pHit || pHit->IsBSPModel() )
|
||||
FindHullIntersection2( vecSrc, tr, VEC_DUCK_HULL_MIN, VEC_DUCK_HULL_MAX, m_pPlayer->edict() );
|
||||
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_usPoolstick,
|
||||
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.5);
|
||||
|
||||
switch( ( m_iSwing++ ) % 3 )
|
||||
{
|
||||
case 0:
|
||||
SendWeaponAnim( POOLSTICK_ATTACK1MISS );
|
||||
break;
|
||||
case 1:
|
||||
SendWeaponAnim( POOLSTICK_ATTACK2MISS );
|
||||
break;
|
||||
case 2:
|
||||
SendWeaponAnim( POOLSTICK_ATTACK3MISS );
|
||||
break;
|
||||
}
|
||||
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.5;
|
||||
EMIT_SOUND_DYN( ENT( m_pPlayer->pev ), CHAN_WEAPON, "weapons/pstk_miss1.wav", 1, ATTN_NORM, 0, 94 + RANDOM_LONG( 0, 0xF ) );
|
||||
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + UTIL_SharedRandomFloat( m_pPlayer->random_seed, 10, 15 );
|
||||
|
||||
// player "shoot" animation
|
||||
m_pPlayer->SetAnimation( PLAYER_ATTACK1 );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch( ((m_iSwing++) % 2) + 1 )
|
||||
switch( (m_iSwing++) % 3)
|
||||
{
|
||||
case 0:
|
||||
SendWeaponAnim( POOLSTICK_ATTACK1HIT ); break;
|
||||
|
@ -224,7 +237,6 @@ int CPoolstick::Swing( int fFirst )
|
|||
// player "shoot" animation
|
||||
m_pPlayer->SetAnimation( PLAYER_ATTACK1 );
|
||||
|
||||
#ifndef CLIENT_DLL
|
||||
|
||||
// hit
|
||||
fDidHit = TRUE;
|
||||
|
@ -303,14 +315,49 @@ int CPoolstick::Swing( int fFirst )
|
|||
}
|
||||
|
||||
m_pPlayer->m_iWeaponVolume = flVol * POOLSTICK_WALLHIT_VOLUME;
|
||||
#endif
|
||||
m_flNextPrimaryAttack = GetNextAttackDelay(0.25);
|
||||
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.25;
|
||||
|
||||
SetThink( &CPoolstick::Smack );
|
||||
pev->nextthink = UTIL_WeaponTimeBase() + 0.2;
|
||||
|
||||
|
||||
}
|
||||
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + UTIL_SharedRandomFloat( m_pPlayer->random_seed, 10, 15 );
|
||||
return fDidHit;
|
||||
}
|
||||
|
||||
void CPoolstick::WeaponIdle()
|
||||
{
|
||||
if( m_pPlayer->m_bIsHolster )
|
||||
{
|
||||
if( m_flTimeWeaponIdle <= UTIL_WeaponTimeBase() )
|
||||
{
|
||||
m_pPlayer->m_bIsHolster = FALSE;
|
||||
Deploy();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if( m_flTimeWeaponIdle < UTIL_WeaponTimeBase() )
|
||||
{
|
||||
int iAnim;
|
||||
float flRand = UTIL_SharedRandomFloat( m_pPlayer->random_seed, 0, 1 );
|
||||
if( flRand > 0.9 )
|
||||
{
|
||||
iAnim = POOLSTICK_IDLE2;
|
||||
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 160.0 / 30.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( flRand > 0.5 )
|
||||
{
|
||||
iAnim = POOLSTICK_IDLE;
|
||||
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 70.0 / 30.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
iAnim = POOLSTICK_IDLE3;
|
||||
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 160.0 / 30.0;
|
||||
}
|
||||
}
|
||||
SendWeaponAnim( iAnim );
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -28,11 +28,12 @@ enum w_toad_e {
|
|||
WTOAD_IDLE1 = 0,
|
||||
WTOAD_FIDGET,
|
||||
WTOAD_JUMP,
|
||||
WTOAD_RUN,
|
||||
WTOAD_RUN
|
||||
};
|
||||
|
||||
enum toad_e {
|
||||
TOAD_IDLE1 = 0,
|
||||
TOAD_IDLE2,
|
||||
TOAD_FIDGETFIT,
|
||||
TOAD_FIDGETNIP,
|
||||
TOAD_DOWN,
|
||||
|
@ -41,7 +42,6 @@ enum toad_e {
|
|||
};
|
||||
|
||||
#ifndef CLIENT_DLL
|
||||
|
||||
class CToadGrenade : public CGrenade
|
||||
{
|
||||
void Spawn( void );
|
||||
|
@ -51,7 +51,7 @@ class CToadGrenade : public CGrenade
|
|||
void EXPORT HuntThink( void );
|
||||
int BloodColor( void ) { return BLOOD_COLOR_YELLOW; }
|
||||
void Killed( entvars_t *pevAttacker, int iGib );
|
||||
// void GibMonster( void );
|
||||
void GibMonster( void );
|
||||
|
||||
virtual int Save( CSave &save );
|
||||
virtual int Restore( CRestore &restore );
|
||||
|
@ -70,6 +70,7 @@ class CToadGrenade : public CGrenade
|
|||
int m_iMyClass;
|
||||
};
|
||||
|
||||
extern int gEvilImpulse101;
|
||||
float CToadGrenade::m_flNextBounceSoundTime = 0;
|
||||
|
||||
LINK_ENTITY_TO_CLASS( monster_toad, CToadGrenade );
|
||||
|
@ -150,7 +151,7 @@ void CToadGrenade::Precache( void )
|
|||
{
|
||||
PRECACHE_MODEL("models/w_toad.mdl");
|
||||
PRECACHE_SOUND("toad/toad_blast1.wav");
|
||||
// PRECACHE_SOUND("common/bodysplat.wav");
|
||||
PRECACHE_SOUND("common/bodysplat.wav");
|
||||
PRECACHE_SOUND("toad/toad_die1.wav");
|
||||
PRECACHE_SOUND("toad/toad_hunt1.wav");
|
||||
PRECACHE_SOUND("toad/toad_hunt2.wav");
|
||||
|
@ -173,7 +174,7 @@ void CToadGrenade :: Killed( entvars_t *pevAttacker, int iGib )
|
|||
pev->takedamage = DAMAGE_NO;
|
||||
|
||||
// play squeek blast
|
||||
EMIT_SOUND_DYN(ENT(pev), CHAN_ITEM, "squeek/toad_blast1.wav", 1, 0.5, 0, PITCH_NORM);
|
||||
EMIT_SOUND_DYN(ENT(pev), CHAN_ITEM, "toad/toad_blast1.wav", 1, 0.5, 0, PITCH_NORM);
|
||||
|
||||
CSoundEnt::InsertSound ( bits_SOUND_COMBAT, pev->origin, SMALL_EXPLOSION_VOLUME, 3.0 );
|
||||
|
||||
|
@ -191,10 +192,10 @@ void CToadGrenade :: Killed( entvars_t *pevAttacker, int iGib )
|
|||
CBaseMonster :: Killed( pevAttacker, GIB_ALWAYS );
|
||||
}
|
||||
|
||||
/* void CToadGrenade :: GibMonster( void )
|
||||
void CToadGrenade :: GibMonster( void )
|
||||
{
|
||||
EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "common/bodysplat.wav", 0.75, ATTN_NORM, 0, 200);
|
||||
} */
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -232,7 +233,7 @@ void CToadGrenade::HuntThink( void )
|
|||
pev->velocity = pev->velocity * 0.9;
|
||||
pev->velocity.z += 8.0;
|
||||
}
|
||||
else if (pev->movetype = MOVETYPE_FLY)
|
||||
else if (pev->movetype == MOVETYPE_FLY)
|
||||
{
|
||||
pev->movetype = MOVETYPE_BOUNCE;
|
||||
}
|
||||
|
@ -263,7 +264,7 @@ void CToadGrenade::HuntThink( void )
|
|||
// squeek if it's about time blow up
|
||||
if ((m_flDie - gpGlobals->time <= 0.5) && (m_flDie - gpGlobals->time >= 0.3))
|
||||
{
|
||||
EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "squeek/toad_die1.wav", 1, ATTN_NORM, 0, 100 + RANDOM_LONG(0,0x3F));
|
||||
EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "toad/toad_die1.wav", 1, ATTN_NORM, 0, 100 + RANDOM_LONG(0,0x3F));
|
||||
CSoundEnt::InsertSound ( bits_SOUND_COMBAT, pev->origin, 256, 0.25 );
|
||||
}
|
||||
|
||||
|
@ -364,7 +365,7 @@ void CToadGrenade::SuperBounceTouch( CBaseEntity *pOther )
|
|||
// m_flDie += 2.0; // add more life
|
||||
|
||||
// make bite sound
|
||||
EMIT_SOUND_DYN(ENT(pev), CHAN_WEAPON, "squeek/toad_deploy1.wav", 1.0, ATTN_NORM, 0, (int)flpitch);
|
||||
EMIT_SOUND_DYN(ENT(pev), CHAN_WEAPON, "toad/toad_deploy1.wav", 1.0, ATTN_NORM, 0, (int)flpitch);
|
||||
m_flNextAttack = gpGlobals->time + 0.5;
|
||||
}
|
||||
}
|
||||
|
@ -422,25 +423,28 @@ void CToad::Spawn( )
|
|||
|
||||
FallInit();//get ready to fall down.
|
||||
|
||||
m_iDefaultAmmo = SNARK_DEFAULT_GIVE;
|
||||
m_iDefaultAmmo = TOAD_DEFAULT_GIVE;
|
||||
|
||||
pev->sequence = 1;
|
||||
pev->animtime = gpGlobals->time;
|
||||
pev->framerate = 1.0;
|
||||
|
||||
SetThink( &CToad::ToadIdle );
|
||||
pev->nextthink = gpGlobals->time + 0.2f;
|
||||
m_flNextTrace = 0;
|
||||
m_flNextHunt = 0;
|
||||
m_flDie = 0;
|
||||
}
|
||||
|
||||
|
||||
void CToad::Precache( void )
|
||||
{
|
||||
PRECACHE_MODEL("models/toad_nest.mdl");
|
||||
PRECACHE_MODEL("models/toad_nestt.mdl");
|
||||
PRECACHE_MODEL("models/v_toad.mdl");
|
||||
PRECACHE_MODEL("models/p_toad.mdl");
|
||||
PRECACHE_SOUND("toad/toad_hunt2.wav");
|
||||
PRECACHE_SOUND("toad/toad_hunt3.wav");
|
||||
UTIL_PrecacheOther("monster_toad");
|
||||
|
||||
m_usToadFire = PRECACHE_EVENT ( 1, "events/snarkfire.sc" );
|
||||
}
|
||||
|
||||
|
||||
|
@ -453,7 +457,7 @@ int CToad::GetItemInfo(ItemInfo *p)
|
|||
p->iMaxAmmo2 = -1;
|
||||
p->iMaxClip = WEAPON_NOCLIP;
|
||||
p->iSlot = 4;
|
||||
p->iPosition = 4;
|
||||
p->iPosition = 5;
|
||||
p->iId = m_iId = WEAPON_TOAD;
|
||||
p->iWeight = SNARK_WEIGHT;
|
||||
p->iFlags = ITEM_FLAG_LIMITINWORLD | ITEM_FLAG_EXHAUSTIBLE;
|
||||
|
@ -465,16 +469,20 @@ int CToad::GetItemInfo(ItemInfo *p)
|
|||
|
||||
BOOL CToad::Deploy( )
|
||||
{
|
||||
// play hunt sound
|
||||
float flRndSound = RANDOM_FLOAT ( 0 , 1 );
|
||||
if( !gEvilImpulse101 )
|
||||
{
|
||||
// play hunt sound
|
||||
float flRndSound = RANDOM_FLOAT( 0, 1 );
|
||||
|
||||
if ( flRndSound <= 0.5 )
|
||||
EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "toad/toad_hunt2.wav", 1, ATTN_NORM, 0, 100);
|
||||
else
|
||||
EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "toad/toad_hunt3.wav", 1, ATTN_NORM, 0, 100);
|
||||
if ( flRndSound <= 0.5 )
|
||||
EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "toad/toad_hunt2.wav", 1, ATTN_NORM, 0, 100);
|
||||
else
|
||||
EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "toad/toad_hunt3.wav", 1, ATTN_NORM, 0, 100);
|
||||
|
||||
m_pPlayer->m_iWeaponVolume = QUIET_GUN_VOLUME;
|
||||
m_pPlayer->m_iWeaponVolume = QUIET_GUN_VOLUME;
|
||||
}
|
||||
|
||||
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 1.1;
|
||||
return DefaultDeploy( "models/v_toad.mdl", "models/p_toad.mdl", TOAD_UP, "toad" );
|
||||
}
|
||||
|
||||
|
@ -491,13 +499,19 @@ void CToad::Holster( int skiplocal /* = 0 */ )
|
|||
return;
|
||||
}
|
||||
|
||||
SendWeaponAnim( TOAD_DOWN );
|
||||
DefaultHolster( TOAD_DOWN, 1.5 );
|
||||
EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_WEAPON, "common/null.wav", 1.0, ATTN_NORM);
|
||||
}
|
||||
|
||||
|
||||
void CToad::PrimaryAttack()
|
||||
{
|
||||
if( m_pPlayer->m_bIsHolster )
|
||||
{
|
||||
WeaponIdle();
|
||||
return;
|
||||
}
|
||||
|
||||
if ( m_pPlayer->m_rgAmmo[ m_iPrimaryAmmoType ] )
|
||||
{
|
||||
UTIL_MakeVectors( m_pPlayer->pev->v_angle );
|
||||
|
@ -515,17 +529,10 @@ void CToad::PrimaryAttack()
|
|||
// find place to toss monster
|
||||
UTIL_TraceLine( trace_origin + gpGlobals->v_forward * 20, trace_origin + gpGlobals->v_forward * 64, dont_ignore_monsters, NULL, &tr );
|
||||
|
||||
int flags;
|
||||
#ifdef CLIENT_WEAPONS
|
||||
flags = FEV_NOTHOST;
|
||||
#else
|
||||
flags = 0;
|
||||
#endif
|
||||
|
||||
PLAYBACK_EVENT_FULL( flags, m_pPlayer->edict(), m_usToadFire, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, 0, 0, 0, 0 );
|
||||
|
||||
if ( tr.fAllSolid == 0 && tr.fStartSolid == 0 && tr.flFraction > 0.25 )
|
||||
{
|
||||
SendWeaponAnim( TOAD_THROW );
|
||||
|
||||
// player "shoot" animation
|
||||
m_pPlayer->SetAnimation( PLAYER_ATTACK1 );
|
||||
|
||||
|
@ -557,12 +564,26 @@ void CToad::PrimaryAttack()
|
|||
|
||||
void CToad::SecondaryAttack( void )
|
||||
{
|
||||
|
||||
if( m_pPlayer->m_bIsHolster )
|
||||
{
|
||||
WeaponIdle();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CToad::WeaponIdle( void )
|
||||
{
|
||||
if( m_pPlayer->m_bIsHolster )
|
||||
{
|
||||
if( m_flTimeWeaponIdle <= UTIL_WeaponTimeBase() )
|
||||
{
|
||||
m_pPlayer->m_bIsHolster = FALSE;
|
||||
Deploy();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if ( m_flTimeWeaponIdle > UTIL_WeaponTimeBase() )
|
||||
return;
|
||||
|
||||
|
@ -581,24 +602,130 @@ void CToad::WeaponIdle( void )
|
|||
return;
|
||||
}
|
||||
|
||||
int iAnim;
|
||||
float flRand = UTIL_SharedRandomFloat( m_pPlayer->random_seed, 0, 1 );
|
||||
if (flRand <= 0.75)
|
||||
{
|
||||
iAnim = TOAD_IDLE1;
|
||||
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 30.0 / 16 * (2);
|
||||
}
|
||||
else if (flRand <= 0.875)
|
||||
int iAnim, iRand = RANDOM_LONG( 0, 5 );
|
||||
switch( iRand )
|
||||
{
|
||||
case 0:
|
||||
iAnim = TOAD_IDLE2;
|
||||
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 2.2f;
|
||||
break;
|
||||
case 1:
|
||||
iAnim = TOAD_FIDGETFIT;
|
||||
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 70.0 / 16.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 2.18f;
|
||||
break;
|
||||
case 2:
|
||||
iAnim = TOAD_FIDGETNIP;
|
||||
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 80.0 / 16.0;
|
||||
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 2.9f;
|
||||
break;
|
||||
default:
|
||||
iAnim = TOAD_IDLE1;
|
||||
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 2.2f;
|
||||
break;
|
||||
}
|
||||
SendWeaponAnim( iAnim );
|
||||
}
|
||||
|
||||
void CToad::ToadIdle()
|
||||
{
|
||||
int i;
|
||||
float flDist;
|
||||
CBaseEntity *pPlayer = UTIL_PlayerByIndex( 1 );
|
||||
|
||||
if( !pPlayer )
|
||||
return;
|
||||
|
||||
flDist = ( pPlayer->Center() - this->Center() ).Length();
|
||||
if( !pPlayer->FVisible( this ) || flDist >= 256.0f )
|
||||
{
|
||||
if( pev->sequence != 1 )
|
||||
{
|
||||
pev->sequence = 1;
|
||||
pev->framerate = 0.5;
|
||||
ResetSequenceInfo();
|
||||
}
|
||||
|
||||
if( !RANDOM_LONG( 0, 10 ) )
|
||||
HuntSound( true );
|
||||
pev->nextthink = gpGlobals->time + 0.2f;
|
||||
return;
|
||||
}
|
||||
|
||||
if( flDist >= 50.0f )
|
||||
{
|
||||
TraceResult tr;
|
||||
|
||||
m_flDie = 1;
|
||||
pev->movetype = MOVETYPE_STEP;
|
||||
StudioFrameAdvance( 0.0 );
|
||||
if( pev->sequence != 1 )
|
||||
{
|
||||
if( m_flNextTrace <= gpGlobals->time )
|
||||
{
|
||||
Vector vecSrc, vecEnd;
|
||||
Vector vecDist2D = ( Center() - pPlayer->Center() ).Normalize();
|
||||
vecDist2D.z = 0;
|
||||
m_posNext = pev->origin + vecDist2D * 128;
|
||||
vecSrc = EyePosition();
|
||||
vecEnd = vecSrc + vecDist2D * 68;
|
||||
UTIL_TraceLine( vecSrc, vecEnd, ignore_monsters, 0, &tr );
|
||||
|
||||
if( tr.flFraction < 1.0f )
|
||||
{
|
||||
Vector vecDist, vecForward, vecAngle;
|
||||
vecDist = ( EyePosition() - tr.vecEndPos ).Normalize();
|
||||
vecAngle = Vector( 0, UTIL_AngleMod( UTIL_VecToAngles( vecDist ).y ) + 195.0f, 0 );
|
||||
UTIL_MakeVectorsPrivate( vecAngle, vecForward, 0, 0 );
|
||||
m_posNext = pev->origin - vecForward * 128;
|
||||
}
|
||||
m_flNextTrace = gpGlobals->time + 0.5f;
|
||||
}
|
||||
Vector newPos = m_posNext - Center();
|
||||
newPos.z = 0;
|
||||
pev->angles = UTIL_VecToAngles( newPos );
|
||||
UTIL_MoveToOrigin( ENT( pev ), newPos * 256.0f, 200.0f / m_flGroundSpeed, MOVE_STRAFE );
|
||||
HuntSound( false );
|
||||
pev->nextthink = gpGlobals->time + 0.2f;
|
||||
return;
|
||||
}
|
||||
pev->sequence = 0;
|
||||
pev->frame = 0;
|
||||
ResetSequenceInfo();
|
||||
pev->framerate = 3.0;
|
||||
HuntSound( true );
|
||||
pev->nextthink = gpGlobals->time + 0.2f;
|
||||
return;
|
||||
}
|
||||
|
||||
if( m_flDie == 1 )
|
||||
{
|
||||
for( i = 0; i < m_iDefaultAmmo; i++ )
|
||||
( (CBasePlayer*)pPlayer )->GiveNamedItem( "weapon_toad" );
|
||||
SetThink( &CBaseEntity::SUB_Remove );
|
||||
pev->nextthink = gpGlobals->time + 0.1f;
|
||||
}
|
||||
}
|
||||
|
||||
void CToad::HuntSound( bool force )
|
||||
{
|
||||
const char *pszSound;
|
||||
|
||||
if( ( m_flNextHunt <= gpGlobals->time ) || force )
|
||||
{
|
||||
int iRand = RANDOM_LONG( 0, 2 );
|
||||
if( iRand == 2 )
|
||||
{
|
||||
pszSound = "toad/toad_hunt3.wav";
|
||||
}
|
||||
else if( iRand == 1 )
|
||||
{
|
||||
pszSound = "toad/toad_hunt2.wav";
|
||||
}
|
||||
else
|
||||
{
|
||||
pszSound = "toad/toad_hunt1.wav";
|
||||
}
|
||||
EMIT_SOUND( ENT( pev ), CHAN_VOICE, pszSound, RANDOM_FLOAT( 0.5, 0.8 ), ATTN_NORM );
|
||||
m_flNextHunt = gpGlobals->time + RANDOM_FLOAT( 3.0, 4.0 );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
151
dlls/barney.cpp
151
dlls/barney.cpp
|
@ -27,68 +27,11 @@
|
|||
#include "scripted.h"
|
||||
#include "weapons.h"
|
||||
#include "soundent.h"
|
||||
|
||||
//=========================================================
|
||||
// Monster's Anim Events Go Here
|
||||
//=========================================================
|
||||
// first flag is barney dying for scripted sequences?
|
||||
#define BARNEY_AE_DRAW ( 2 )
|
||||
#define BARNEY_AE_SHOOT ( 3 )
|
||||
#define BARNEY_AE_HOLSTER ( 4 )
|
||||
|
||||
#define BARNEY_BODY_GUNHOLSTERED 0
|
||||
#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
|
||||
};
|
||||
#include "barney.h"
|
||||
|
||||
LINK_ENTITY_TO_CLASS( monster_barney, CBarney )
|
||||
LINK_ENTITY_TO_CLASS( monster_hevbarn, CBarney )
|
||||
LINK_ENTITY_TO_CLASS( monster_myself, CBarney )
|
||||
|
||||
TYPEDESCRIPTION CBarney::m_SaveData[] =
|
||||
{
|
||||
|
@ -174,6 +117,7 @@ Schedule_t slBaFaceTarget[] =
|
|||
Task_t tlIdleBaStand[] =
|
||||
{
|
||||
{ TASK_STOP_MOVING, 0 },
|
||||
{ TASK_SET_ACTIVITY, (float)ACT_DISARM },
|
||||
{ TASK_SET_ACTIVITY, (float)ACT_IDLE },
|
||||
{ TASK_WAIT, (float)2 }, // repick IDLESTAND every two seconds.
|
||||
{ TASK_TLK_HEADRESET, (float)0 }, // reset head position
|
||||
|
@ -201,12 +145,15 @@ Schedule_t slIdleBaStand[] =
|
|||
},
|
||||
};
|
||||
|
||||
extern Schedule_t slGruntHideReload[];
|
||||
|
||||
DEFINE_CUSTOM_SCHEDULES( CBarney )
|
||||
{
|
||||
slBaFollow,
|
||||
slBarneyEnemyDraw,
|
||||
slBaFaceTarget,
|
||||
slIdleBaStand,
|
||||
slGruntHideReload
|
||||
};
|
||||
|
||||
IMPLEMENT_CUSTOM_SCHEDULES( CBarney, CTalkMonster )
|
||||
|
@ -370,6 +317,11 @@ void CBarney::HandleAnimEvent( MonsterEvent_t *pEvent )
|
|||
{
|
||||
switch( pEvent->event )
|
||||
{
|
||||
case BARNEY_AE_RELOAD:
|
||||
EMIT_SOUND_DYN( ENT( pev ), CHAN_WEAPON, "weapons/reload3.wav", 1, ATTN_NORM, 0, 100 );
|
||||
m_cAmmoLoaded = GLOCK_MAX_CLIP;
|
||||
ClearConditions( bits_COND_NO_AMMO_LOADED );
|
||||
break;
|
||||
case BARNEY_AE_SHOOT:
|
||||
BarneyFirePistol();
|
||||
break;
|
||||
|
@ -395,22 +347,27 @@ void CBarney::Spawn()
|
|||
{
|
||||
Precache();
|
||||
|
||||
SET_MODEL( ENT( pev ), "models/barney.mdl" );
|
||||
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_RED;
|
||||
pev->health = gSkillData.barneyHealth;
|
||||
if( FClassnameIs( pev, "monster_hevbarn" ) )
|
||||
pev->health = gSkillData.barneyHealth * 1.5;
|
||||
else
|
||||
pev->health = gSkillData.barneyHealth;
|
||||
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 npc will notice player and say hello
|
||||
m_MonsterState = MONSTERSTATE_NONE;
|
||||
|
||||
pev->body = 0; // gun in holster
|
||||
pev->body = FBitSet( pev->spawnflags, SF_BARNEY_CARDS_BARNEY ) ? BARNEY_BODY_GUNDRAWN : BARNEY_BODY_GUNHOLSTERED;
|
||||
m_fGunDrawn = FALSE;
|
||||
|
||||
m_afCapability = bits_CAP_HEAR | bits_CAP_TURN_HEAD | bits_CAP_DOORS_GROUP;
|
||||
|
||||
m_cAmmoLoaded = GLOCK_MAX_CLIP;
|
||||
|
||||
MonsterInit();
|
||||
SetUse( &CTalkMonster::FollowerUse );
|
||||
}
|
||||
|
@ -420,7 +377,18 @@ void CBarney::Spawn()
|
|||
//=========================================================
|
||||
void CBarney::Precache()
|
||||
{
|
||||
PRECACHE_MODEL( "models/barney.mdl" );
|
||||
if( FClassnameIs( pev, "monster_myself" ) )
|
||||
pev->model = MAKE_STRING( "models/myself.mdl" );
|
||||
else if( FClassnameIs( pev, "monster_hevbarn" ) )
|
||||
pev->model = MAKE_STRING( "models/hev_barney.mdl" );
|
||||
else if( pev->spawnflags & SF_BARNEY_LAZY_BARNEY )
|
||||
pev->model = MAKE_STRING( "models/lazybarney.mdl" );
|
||||
else if( pev->spawnflags & SF_BARNEY_CARDS_BARNEY )
|
||||
pev->model = MAKE_STRING( "models/cardsbarney.mdl" );
|
||||
else
|
||||
pev->model = MAKE_STRING( "models/barney.mdl" );
|
||||
|
||||
PRECACHE_MODEL( STRING( pev->model ) );
|
||||
|
||||
PRECACHE_SOUND( "barney/ba_attack1.wav" );
|
||||
PRECACHE_SOUND( "barney/ba_attack2.wav" );
|
||||
|
@ -433,6 +401,8 @@ void CBarney::Precache()
|
|||
PRECACHE_SOUND( "barney/ba_die2.wav" );
|
||||
PRECACHE_SOUND( "barney/ba_die3.wav" );
|
||||
|
||||
PRECACHE_SOUND( "weapons/reload3.wav" );
|
||||
|
||||
// every new barney must call this, otherwise
|
||||
// when a level is loaded, nobody will talk (time is reset to 0)
|
||||
TalkInit();
|
||||
|
@ -460,8 +430,8 @@ void CBarney::TalkInit()
|
|||
m_szGrp[TLK_PLHURT2] = "!BA_CUREB";
|
||||
m_szGrp[TLK_PLHURT3] = "!BA_CUREC";
|
||||
|
||||
m_szGrp[TLK_PHELLO] = NULL; //"BA_PHELLO"; // UNDONE
|
||||
m_szGrp[TLK_PIDLE] = NULL; //"BA_PIDLE"; // UNDONE
|
||||
m_szGrp[TLK_PHELLO] = "BA_PHELLO"; // UNDONE
|
||||
m_szGrp[TLK_PIDLE] = "BA_PIDLE"; // UNDONE
|
||||
m_szGrp[TLK_PQUESTION] = "BA_PQUEST"; // UNDONE
|
||||
|
||||
m_szGrp[TLK_SMELL] = "BA_SMELL";
|
||||
|
@ -473,6 +443,18 @@ void CBarney::TalkInit()
|
|||
m_voicePitch = 100;
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// CheckAmmo - overridden for the barney because he actually
|
||||
// uses ammo! (base class doesn't)
|
||||
//=========================================================
|
||||
void CBarney::CheckAmmo( void )
|
||||
{
|
||||
if( m_cAmmoLoaded <= 0 )
|
||||
{
|
||||
SetConditions( bits_COND_NO_AMMO_LOADED );
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL IsFacing( entvars_t *pevTest, const Vector &reference )
|
||||
{
|
||||
Vector vecDir = reference - pevTest->origin;
|
||||
|
@ -611,12 +593,17 @@ void CBarney::Killed( entvars_t *pevAttacker, int iGib )
|
|||
// drop the gun!
|
||||
Vector vecGunPos;
|
||||
Vector vecGunAngles;
|
||||
const char *pszName;
|
||||
|
||||
pev->body = BARNEY_BODY_GUNGONE;
|
||||
|
||||
GetAttachment( 0, vecGunPos, vecGunAngles );
|
||||
|
||||
DropItem( "weapon_barney9mmhg", vecGunPos, vecGunAngles ); // edit Alex, in Azure Sheep entity is named another way
|
||||
if( FBitSet( pev->spawnflags, SF_BARNEY_HAVESUIT ) )
|
||||
pszName = "weapon_9mmhandgun";
|
||||
else
|
||||
pszName = "weapon_barney9mmhg";
|
||||
DropItem( pszName, vecGunPos, vecGunAngles );
|
||||
}
|
||||
|
||||
SetUse( NULL );
|
||||
|
@ -632,6 +619,8 @@ Schedule_t *CBarney::GetScheduleOfType( int Type )
|
|||
|
||||
switch( Type )
|
||||
{
|
||||
case SCHED_BARNEY_COVER_AND_RELOAD:
|
||||
return slGruntHideReload;
|
||||
case SCHED_ARM_WEAPON:
|
||||
if( m_hEnemy != 0 )
|
||||
{
|
||||
|
@ -711,6 +700,9 @@ Schedule_t *CBarney::GetSchedule( void )
|
|||
|
||||
if( HasConditions( bits_COND_HEAVY_DAMAGE ) )
|
||||
return GetScheduleOfType( SCHED_TAKE_COVER_FROM_ENEMY );
|
||||
|
||||
if( HasConditions( bits_COND_NO_AMMO_LOADED ) )
|
||||
return GetScheduleOfType( SCHED_BARNEY_COVER_AND_RELOAD );
|
||||
}
|
||||
break;
|
||||
case MONSTERSTATE_ALERT:
|
||||
|
@ -800,14 +792,35 @@ void CDeadBarney::KeyValue( KeyValueData *pkvd )
|
|||
}
|
||||
|
||||
LINK_ENTITY_TO_CLASS( monster_barney_dead, CDeadBarney )
|
||||
LINK_ENTITY_TO_CLASS( monster_hevbarn_dead, CDeadBarney )
|
||||
LINK_ENTITY_TO_CLASS( monster_myself_dead, CDeadBarney )
|
||||
LINK_ENTITY_TO_CLASS( monster_barniel_dead, CDeadBarney )
|
||||
LINK_ENTITY_TO_CLASS( monster_adrian_dead, CDeadBarney )
|
||||
LINK_ENTITY_TO_CLASS( monster_gordon_dead, CDeadBarney )
|
||||
LINK_ENTITY_TO_CLASS( monster_kate_dead, CDeadBarney )
|
||||
|
||||
//=========================================================
|
||||
// ********** DeadBarney SPAWN **********
|
||||
//=========================================================
|
||||
void CDeadBarney::Spawn()
|
||||
{
|
||||
PRECACHE_MODEL( "models/barney.mdl" );
|
||||
SET_MODEL( ENT( pev ), "models/barney.mdl" );
|
||||
if( FClassnameIs( pev, "monster_adrian_dead" ) )
|
||||
pev->model = MAKE_STRING( "models/adrian.mdl" );
|
||||
else if( FClassnameIs( pev, "monster_gordon_dead" ) )
|
||||
pev->model = MAKE_STRING( "models/gordon.mdl" );
|
||||
else if( FClassnameIs( pev, "monster_barniel_dead" ) )
|
||||
pev->model = MAKE_STRING( "models/barniel.mdl" );
|
||||
else if( FClassnameIs( pev, "monster_kate_dead" ) )
|
||||
pev->model = MAKE_STRING( "models/kate.mdl" );
|
||||
else if( FClassnameIs( pev, "monster_myself_dead" ) )
|
||||
pev->model = MAKE_STRING( "models/myself.mdl" );
|
||||
else if( FClassnameIs( pev, "monster_hevbarn_dead" ) )
|
||||
pev->model = MAKE_STRING( "models/hev_barney.mdl" );
|
||||
else
|
||||
pev->model = MAKE_STRING( "models/barney.mdl" );
|
||||
|
||||
PRECACHE_MODEL( STRING( pev->model ) );
|
||||
SET_MODEL( ENT( pev ), STRING( pev->model ) );
|
||||
|
||||
pev->effects = 0;
|
||||
pev->yaw_speed = 8;
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
/***
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
****/
|
||||
//=========================================================
|
||||
// monster template
|
||||
//=========================================================
|
||||
#ifndef BARNEY_H
|
||||
#define BARNEY_H
|
||||
|
||||
//=========================================================
|
||||
// Monster's Anim Events Go Here
|
||||
//=========================================================
|
||||
// first flag is barney dying for scripted sequences?
|
||||
#define BARNEY_AE_DRAW ( 2 )
|
||||
#define BARNEY_AE_SHOOT ( 3 )
|
||||
#define BARNEY_AE_HOLSTER ( 4 )
|
||||
#define BARNEY_AE_RELOAD ( 5 )
|
||||
#define BARNEY_AE_KICK ( 6 )
|
||||
|
||||
#define BARNEY_BODY_GUNHOLSTERED 0
|
||||
#define BARNEY_BODY_GUNDRAWN 1
|
||||
#define BARNEY_BODY_GUNGONE 2
|
||||
|
||||
#define SF_BARNEY_HAVESUIT 8
|
||||
#define SF_BARNEY_LAZY_BARNEY 32
|
||||
#define SF_BARNEY_CARDS_BARNEY 64
|
||||
|
||||
enum
|
||||
{
|
||||
SCHED_BARNEY_COVER_AND_RELOAD = LAST_COMMON_SCHEDULE + 1
|
||||
};
|
||||
|
||||
//=========================================================
|
||||
// CBarney
|
||||
//=========================================================
|
||||
class CBarney : public CTalkMonster
|
||||
{
|
||||
public:
|
||||
virtual void Spawn( void );
|
||||
virtual void Precache( void );
|
||||
void SetYawSpeed( void );
|
||||
int ISoundMask( void );
|
||||
virtual void BarneyFirePistol( void );
|
||||
virtual void AlertSound( void );
|
||||
int Classify( void );
|
||||
virtual 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 );
|
||||
|
||||
virtual void DeclineFollowing( void );
|
||||
|
||||
// Override these to set behavior
|
||||
Schedule_t *GetScheduleOfType( int Type );
|
||||
virtual Schedule_t *GetSchedule( void );
|
||||
MONSTERSTATE GetIdealState( void );
|
||||
|
||||
virtual void DeathSound( void );
|
||||
virtual void PainSound( void );
|
||||
|
||||
virtual void TalkInit( void );
|
||||
void CheckAmmo( void );
|
||||
virtual void TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType);
|
||||
virtual 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
|
||||
};
|
||||
#endif
|
18
dlls/cbase.h
18
dlls/cbase.h
|
@ -333,24 +333,6 @@ public:
|
|||
|
||||
virtual BOOL FVisible( CBaseEntity *pEntity );
|
||||
virtual BOOL FVisible( const Vector &vecOrigin );
|
||||
|
||||
//We use this variables to store each ammo count.
|
||||
int ammo_9mm;
|
||||
int ammo_357;
|
||||
int ammo_bolts;
|
||||
int ammo_buckshot;
|
||||
int ammo_rockets;
|
||||
int ammo_uranium;
|
||||
int ammo_hornets;
|
||||
int ammo_argrens;
|
||||
//Special stuff for grenades and satchels.
|
||||
float m_flStartThrow;
|
||||
float m_flReleaseThrow;
|
||||
int m_chargeReady;
|
||||
int m_fInAttack;
|
||||
|
||||
enum EGON_FIRESTATE { FIRE_OFF, FIRE_CHARGE };
|
||||
int m_fireState;
|
||||
};
|
||||
|
||||
// Ugly technique to override base member functions
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
#define MAX_WEAPON_SLOTS 5 // hud item selection slots
|
||||
#define MAX_ITEM_TYPES 6 // hud item selection slots
|
||||
|
||||
#define MAX_ITEMS 5 // hard coded item types
|
||||
#define MAX_ITEMS 6 // hard coded item types
|
||||
|
||||
#define HIDEHUD_WEAPONS ( 1<<0 )
|
||||
#define HIDEHUD_FLASHLIGHT ( 1<<1 )
|
||||
|
|
|
@ -302,8 +302,14 @@ void CBaseMonster::GibMonster( void )
|
|||
|
||||
EMIT_SOUND( ENT( pev ), CHAN_WEAPON, "common/bodysplat.wav", 1, ATTN_NORM );
|
||||
|
||||
if( FClassnameIs( pev, "monster_exp_alien_slave" ) )
|
||||
{
|
||||
if( CVAR_GET_FLOAT( "violence_hgibs" ) != 0 )
|
||||
CGib::SpawnRandomGibs( pev, 4, 1 );
|
||||
gibbed = TRUE;
|
||||
}
|
||||
// only humans throw skulls !!!UNDONE - eventually monsters will have their own sets of gibs
|
||||
if( HasHumanGibs() )
|
||||
else if( HasHumanGibs() )
|
||||
{
|
||||
if( CVAR_GET_FLOAT( "violence_hgibs" ) != 0 ) // Only the player will ever get here
|
||||
{
|
||||
|
@ -1536,6 +1542,12 @@ 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_M41A:
|
||||
pEntity->TraceAttack( pevAttacker, gSkillData.plrDmgM41A, vecDir, &tr, DMG_BULLET );
|
||||
break;
|
||||
case BULLET_PLAYER_BERETTA:
|
||||
pEntity->TraceAttack( pevAttacker, gSkillData.plrDmgBeretta, vecDir, &tr, DMG_BULLET );
|
||||
break;
|
||||
case BULLET_NONE: // FIX
|
||||
pEntity->TraceAttack( pevAttacker, 50, vecDir, &tr, DMG_CLUB );
|
||||
TEXTURETYPE_PlaySound( &tr, vecSrc, vecEnd, iBulletType );
|
||||
|
|
|
@ -291,9 +291,6 @@ void CCrossbow::Precache( void )
|
|||
PRECACHE_SOUND( "weapons/xbow_reload1.wav" );
|
||||
|
||||
UTIL_PrecacheOther( "crossbow_bolt" );
|
||||
|
||||
m_usCrossbow = PRECACHE_EVENT( 1, "events/crossbow1.sc" );
|
||||
m_usCrossbow2 = PRECACHE_EVENT( 1, "events/crossbow2.sc" );
|
||||
}
|
||||
|
||||
int CCrossbow::GetItemInfo( ItemInfo *p )
|
||||
|
@ -305,7 +302,7 @@ int CCrossbow::GetItemInfo( ItemInfo *p )
|
|||
p->iMaxAmmo2 = -1;
|
||||
p->iMaxClip = CROSSBOW_MAX_CLIP;
|
||||
p->iSlot = 2;
|
||||
p->iPosition = 2;
|
||||
p->iPosition = 4;
|
||||
p->iId = WEAPON_CROSSBOW;
|
||||
p->iFlags = 0;
|
||||
p->iWeight = CROSSBOW_WEIGHT;
|
||||
|
@ -321,22 +318,25 @@ BOOL CCrossbow::Deploy()
|
|||
|
||||
void CCrossbow::Holster( int skiplocal /* = 0 */ )
|
||||
{
|
||||
m_fInReload = FALSE;// cancel any reload in progress.
|
||||
|
||||
if( m_fInZoom )
|
||||
{
|
||||
SecondaryAttack();
|
||||
}
|
||||
|
||||
m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.5;
|
||||
if( m_iClip )
|
||||
SendWeaponAnim( CROSSBOW_HOLSTER1 );
|
||||
DefaultHolster( CROSSBOW_HOLSTER1, 0.7 );
|
||||
else
|
||||
SendWeaponAnim( CROSSBOW_HOLSTER2 );
|
||||
DefaultHolster( CROSSBOW_HOLSTER2, 0.7 );
|
||||
}
|
||||
|
||||
void CCrossbow::PrimaryAttack( void )
|
||||
{
|
||||
if( m_pPlayer->m_bIsHolster )
|
||||
{
|
||||
WeaponIdle();
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
if( m_fInZoom && bIsMultiplayer() )
|
||||
#else
|
||||
|
@ -353,7 +353,7 @@ void CCrossbow::PrimaryAttack( void )
|
|||
// this function only gets called in multiplayer
|
||||
void CCrossbow::FireSniperBolt()
|
||||
{
|
||||
m_flNextPrimaryAttack = GetNextAttackDelay( 0.75 );
|
||||
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.75;
|
||||
|
||||
if( m_iClip == 0 )
|
||||
{
|
||||
|
@ -366,14 +366,16 @@ void CCrossbow::FireSniperBolt()
|
|||
m_pPlayer->m_iWeaponVolume = QUIET_GUN_VOLUME;
|
||||
m_iClip--;
|
||||
|
||||
int flags;
|
||||
#if defined( CLIENT_WEAPONS )
|
||||
flags = FEV_NOTHOST;
|
||||
#else
|
||||
flags = 0;
|
||||
#endif
|
||||
|
||||
PLAYBACK_EVENT_FULL( flags, m_pPlayer->edict(), m_usCrossbow2, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, 0, 0, m_iClip, m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType], 0, 0 );
|
||||
EMIT_SOUND_DYN( ENT( m_pPlayer->pev ), CHAN_WEAPON, "weapons/xbow_fire1.wav", RANDOM_FLOAT( 0.95, 1.0 ), ATTN_NORM, 0, 93 + RANDOM_LONG( 0, 0xF ) );
|
||||
if( m_iClip )
|
||||
{
|
||||
EMIT_SOUND_DYN( ENT( m_pPlayer->pev ), CHAN_ITEM, "weapons/xbow_reload1.wav", RANDOM_FLOAT( 0.95, 1.0 ), ATTN_NORM, 0, 93 + RANDOM_LONG( 0, 0xF ) );
|
||||
SendWeaponAnim( CROSSBOW_FIRE1 );
|
||||
}
|
||||
else if( m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] == 0 )
|
||||
{
|
||||
SendWeaponAnim( CROSSBOW_FIRE3 );
|
||||
}
|
||||
|
||||
// player "shoot" animation
|
||||
m_pPlayer->SetAnimation( PLAYER_ATTACK1 );
|
||||
|
@ -388,10 +390,38 @@ void CCrossbow::FireSniperBolt()
|
|||
#ifndef CLIENT_DLL
|
||||
if( tr.pHit->v.takedamage )
|
||||
{
|
||||
EMIT_SOUND( tr.pHit, CHAN_BODY, RANDOM_LONG( 0, 1 ) ? "weapons/xbow_hitbod2.wav" : "weapons/xbow_hitbod1.wav", 1, ATTN_NORM );
|
||||
ClearMultiDamage();
|
||||
CBaseEntity::Instance( tr.pHit )->TraceAttack( m_pPlayer->pev, 120, vecDir, &tr, DMG_BULLET | DMG_NEVERGIB );
|
||||
ApplyMultiDamage( pev, m_pPlayer->pev );
|
||||
}
|
||||
else
|
||||
{
|
||||
// create a bolt
|
||||
CCrossbowBolt *pBolt = CCrossbowBolt::BoltCreate();
|
||||
pBolt->pev->origin = tr.vecEndPos - vecDir * 10;
|
||||
pBolt->pev->angles = UTIL_VecToAngles( vecDir );
|
||||
pBolt->pev->solid = SOLID_NOT;
|
||||
pBolt->SetTouch( NULL );
|
||||
pBolt->SetThink( &CBaseEntity::SUB_Remove );
|
||||
|
||||
EMIT_SOUND( pBolt->edict(), CHAN_WEAPON, "weapons/xbow_hit1.wav", RANDOM_FLOAT( 0.95, 1.0 ), ATTN_NORM );
|
||||
|
||||
if( UTIL_PointContents( tr.vecEndPos ) != CONTENTS_WATER )
|
||||
{
|
||||
UTIL_Sparks( tr.vecEndPos );
|
||||
}
|
||||
|
||||
if( FClassnameIs( tr.pHit, "worldspawn" ) )
|
||||
{
|
||||
// let the bolt sit around for a while if it hit static architecture
|
||||
pBolt->pev->nextthink = gpGlobals->time + 5.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
pBolt->pev->nextthink = gpGlobals->time;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -409,14 +439,15 @@ void CCrossbow::FireBolt()
|
|||
|
||||
m_iClip--;
|
||||
|
||||
int flags;
|
||||
#if defined( CLIENT_WEAPONS )
|
||||
flags = FEV_NOTHOST;
|
||||
#else
|
||||
flags = 0;
|
||||
#endif
|
||||
|
||||
PLAYBACK_EVENT_FULL( flags, m_pPlayer->edict(), m_usCrossbow, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, 0, 0, m_iClip, m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType], 0, 0 );
|
||||
if( m_iClip )
|
||||
{
|
||||
EMIT_SOUND_DYN( ENT( m_pPlayer->pev ), CHAN_ITEM, "weapons/xbow_reload1.wav", RANDOM_FLOAT( 0.95, 1.0 ), ATTN_NORM, 0, 93 + RANDOM_LONG( 0, 0xF ) );
|
||||
SendWeaponAnim( CROSSBOW_FIRE1 );
|
||||
}
|
||||
else if( m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] == 0 )
|
||||
{
|
||||
SendWeaponAnim( CROSSBOW_FIRE3 );
|
||||
}
|
||||
|
||||
// player "shoot" animation
|
||||
m_pPlayer->SetAnimation( PLAYER_ATTACK1 );
|
||||
|
@ -452,7 +483,7 @@ void CCrossbow::FireBolt()
|
|||
// HEV suit - indicate out of ammo condition
|
||||
m_pPlayer->SetSuitUpdate( "!HEV_AMO0", FALSE, 0 );
|
||||
|
||||
m_flNextPrimaryAttack = GetNextAttackDelay( 0.75 );
|
||||
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.75;
|
||||
|
||||
m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.75;
|
||||
|
||||
|
@ -460,10 +491,18 @@ void CCrossbow::FireBolt()
|
|||
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 5.0;
|
||||
else
|
||||
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 0.75;
|
||||
|
||||
m_pPlayer->pev->punchangle.x -= 2;
|
||||
}
|
||||
|
||||
void CCrossbow::SecondaryAttack()
|
||||
{
|
||||
if( m_pPlayer->m_bIsHolster )
|
||||
{
|
||||
WeaponIdle();
|
||||
return;
|
||||
}
|
||||
|
||||
if( m_pPlayer->pev->fov != 0 )
|
||||
{
|
||||
m_pPlayer->pev->fov = m_pPlayer->m_iFOV = 0; // 0 means reset to default fov
|
||||
|
@ -481,6 +520,12 @@ void CCrossbow::SecondaryAttack()
|
|||
|
||||
void CCrossbow::Reload( void )
|
||||
{
|
||||
if( m_pPlayer->m_bIsHolster )
|
||||
{
|
||||
WeaponIdle();
|
||||
return;
|
||||
}
|
||||
|
||||
if( m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0 || m_iClip == CROSSBOW_MAX_CLIP )
|
||||
return;
|
||||
|
||||
|
@ -497,6 +542,16 @@ void CCrossbow::Reload( void )
|
|||
|
||||
void CCrossbow::WeaponIdle( void )
|
||||
{
|
||||
if( m_pPlayer->m_bIsHolster )
|
||||
{
|
||||
if( m_flTimeWeaponIdle <= UTIL_WeaponTimeBase() )
|
||||
{
|
||||
m_pPlayer->m_bIsHolster = FALSE;
|
||||
Deploy();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
m_pPlayer->GetAutoaimVector( AUTOAIM_2DEGREES ); // get the autoaim vector but ignore it; used for autoaim crosshair in DM
|
||||
|
||||
ResetEmptySound();
|
||||
|
|
|
@ -37,13 +37,9 @@ enum crowbar_e
|
|||
CROWBAR_ATTACK2MISS,
|
||||
CROWBAR_ATTACK2HIT,
|
||||
CROWBAR_ATTACK3MISS,
|
||||
#ifndef CROWBAR_IDLE_ANIM
|
||||
CROWBAR_ATTACK3HIT
|
||||
#else
|
||||
CROWBAR_ATTACK3HIT,
|
||||
CROWBAR_IDLE2,
|
||||
CROWBAR_IDLE3
|
||||
#endif
|
||||
};
|
||||
|
||||
void CCrowbar::Spawn()
|
||||
|
@ -67,8 +63,6 @@ void CCrowbar::Precache( void )
|
|||
PRECACHE_SOUND( "weapons/cbar_hitbod2.wav" );
|
||||
PRECACHE_SOUND( "weapons/cbar_hitbod3.wav" );
|
||||
PRECACHE_SOUND( "weapons/cbar_miss1.wav" );
|
||||
|
||||
m_usCrowbar = PRECACHE_EVENT( 1, "events/crowbar.sc" );
|
||||
}
|
||||
|
||||
int CCrowbar::GetItemInfo( ItemInfo *p )
|
||||
|
@ -105,8 +99,7 @@ BOOL CCrowbar::Deploy()
|
|||
|
||||
void CCrowbar::Holster( int skiplocal /* = 0 */ )
|
||||
{
|
||||
m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.5;
|
||||
SendWeaponAnim( CROWBAR_HOLSTER );
|
||||
DefaultHolster( CROWBAR_HOLSTER, 0.7 );
|
||||
}
|
||||
|
||||
void FindHullIntersection( const Vector &vecSrc, TraceResult &tr, float *mins, float *maxs, edict_t *pEntity )
|
||||
|
@ -155,6 +148,12 @@ void FindHullIntersection( const Vector &vecSrc, TraceResult &tr, float *mins, f
|
|||
|
||||
void CCrowbar::PrimaryAttack()
|
||||
{
|
||||
if( m_pPlayer->m_bIsHolster )
|
||||
{
|
||||
WeaponIdle();
|
||||
return;
|
||||
}
|
||||
|
||||
if( !Swing( 1 ) )
|
||||
{
|
||||
#ifndef CLIENT_DLL
|
||||
|
@ -201,29 +200,33 @@ int CCrowbar::Swing( int fFirst )
|
|||
}
|
||||
}
|
||||
#endif
|
||||
if( fFirst )
|
||||
{
|
||||
PLAYBACK_EVENT_FULL( FEV_NOTHOST, m_pPlayer->edict(), m_usCrowbar,
|
||||
0.0, (float *)&g_vecZero, (float *)&g_vecZero, 0, 0, 0,
|
||||
0, 0, 0 );
|
||||
}
|
||||
|
||||
if( tr.flFraction >= 1.0 )
|
||||
{
|
||||
if( fFirst )
|
||||
{
|
||||
// miss
|
||||
m_flNextPrimaryAttack = GetNextAttackDelay( 0.5 );
|
||||
#ifdef CROWBAR_IDLE_ANIM
|
||||
switch( ( m_iSwing++ ) % 3 )
|
||||
{
|
||||
case 0:
|
||||
SendWeaponAnim( CROWBAR_ATTACK1MISS );
|
||||
break;
|
||||
case 1:
|
||||
SendWeaponAnim( CROWBAR_ATTACK2MISS );
|
||||
break;
|
||||
case 2:
|
||||
SendWeaponAnim( CROWBAR_ATTACK3MISS );
|
||||
break;
|
||||
}
|
||||
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.5;
|
||||
EMIT_SOUND_DYN( ENT( m_pPlayer->pev ), CHAN_WEAPON, "weapons/cbar_miss1.wav", 1, ATTN_NORM, 0, 94 + RANDOM_LONG( 0, 0xF ) );
|
||||
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + UTIL_SharedRandomFloat( m_pPlayer->random_seed, 10, 15 );
|
||||
#endif
|
||||
// player "shoot" animation
|
||||
m_pPlayer->SetAnimation( PLAYER_ATTACK1 );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch( ( ( m_iSwing++ ) % 2 ) + 1 )
|
||||
switch( ( m_iSwing++ ) % 3 )
|
||||
{
|
||||
case 0:
|
||||
SendWeaponAnim( CROWBAR_ATTACK1HIT );
|
||||
|
@ -330,17 +333,26 @@ int CCrowbar::Swing( int fFirst )
|
|||
SetThink( &CCrowbar::Smack );
|
||||
pev->nextthink = UTIL_WeaponTimeBase() + 0.2;
|
||||
#endif
|
||||
m_flNextPrimaryAttack = GetNextAttackDelay( 0.25 );
|
||||
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.25;
|
||||
}
|
||||
#ifdef CROWBAR_IDLE_ANIM
|
||||
|
||||
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + UTIL_SharedRandomFloat( m_pPlayer->random_seed, 10, 15 );
|
||||
#endif
|
||||
|
||||
return fDidHit;
|
||||
}
|
||||
|
||||
#ifdef CROWBAR_IDLE_ANIM
|
||||
void CCrowbar::WeaponIdle( void )
|
||||
{
|
||||
if( m_pPlayer->m_bIsHolster )
|
||||
{
|
||||
if( m_flTimeWeaponIdle <= UTIL_WeaponTimeBase() )
|
||||
{
|
||||
m_pPlayer->m_bIsHolster = FALSE;
|
||||
Deploy();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if( m_flTimeWeaponIdle < UTIL_WeaponTimeBase() )
|
||||
{
|
||||
int iAnim;
|
||||
|
@ -366,4 +378,3 @@ void CCrowbar::WeaponIdle( void )
|
|||
SendWeaponAnim( iAnim );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
108
dlls/effects.cpp
108
dlls/effects.cpp
|
@ -1569,7 +1569,7 @@ void CTestEffect::Spawn( void )
|
|||
|
||||
void CTestEffect::Precache( void )
|
||||
{
|
||||
PRECACHE_MODEL( "sprites/lgtning.spr" );
|
||||
// PRECACHE_MODEL( "sprites/lgtning.spr" );
|
||||
}
|
||||
|
||||
void CTestEffect::TestThink( void )
|
||||
|
@ -2233,3 +2233,109 @@ void CItemSoda::CanTouch( CBaseEntity *pOther )
|
|||
SetThink( &CBaseEntity::SUB_Remove );
|
||||
pev->nextthink = gpGlobals->time;
|
||||
}
|
||||
|
||||
class CEnvPawnEffect : public CPointEntity
|
||||
{
|
||||
public:
|
||||
int Save( CSave &save );
|
||||
int Restore( CRestore &restore );
|
||||
static TYPEDESCRIPTION m_SaveData[];
|
||||
|
||||
void Spawn( void );
|
||||
void Precache( void );
|
||||
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
|
||||
void KeyValue( KeyValueData *pkvd );
|
||||
private:
|
||||
int m_iLightRad;
|
||||
//int m_iLightingModelIndex;
|
||||
int m_iSpawnType;
|
||||
int m_iBeamCount;
|
||||
float m_flSpriteScale;
|
||||
float m_flSpawnSoundRad;
|
||||
float m_flSpawnVol;
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS( env_spawnereffect, CEnvPawnEffect )
|
||||
|
||||
TYPEDESCRIPTION CEnvPawnEffect::m_SaveData[] =
|
||||
{
|
||||
DEFINE_FIELD( CEnvPawnEffect, m_iLightRad, FIELD_INTEGER ),
|
||||
DEFINE_FIELD( CEnvPawnEffect, m_iSpawnType, FIELD_INTEGER ),
|
||||
DEFINE_FIELD( CEnvPawnEffect, m_iBeamCount, FIELD_INTEGER ),
|
||||
DEFINE_FIELD( CEnvPawnEffect, m_flSpriteScale, FIELD_FLOAT ),
|
||||
DEFINE_FIELD( CEnvPawnEffect, m_flSpawnSoundRad, FIELD_FLOAT ),
|
||||
DEFINE_FIELD( CEnvPawnEffect, m_flSpawnVol, FIELD_FLOAT ),
|
||||
};
|
||||
|
||||
IMPLEMENT_SAVERESTORE( CEnvPawnEffect, CPointEntity )
|
||||
|
||||
void CEnvPawnEffect::Spawn()
|
||||
{
|
||||
Precache();
|
||||
pev->solid = SOLID_NOT;
|
||||
pev->movetype = MOVETYPE_NONE;
|
||||
}
|
||||
|
||||
void CEnvPawnEffect::Precache()
|
||||
{
|
||||
PRECACHE_SOUND( "ambience/spawnsnd.wav" );
|
||||
PRECACHE_MODEL( "sprites/xflare1.spr" );
|
||||
PRECACHE_MODEL( "sprites/fexplo1.spr" );
|
||||
}
|
||||
|
||||
void CEnvPawnEffect::KeyValue( KeyValueData *pkvd )
|
||||
{
|
||||
if( FStrEq( pkvd->szKeyName, "spawntype" ) )
|
||||
{
|
||||
m_iSpawnType = atoi( pkvd->szValue );
|
||||
pkvd->fHandled = TRUE;
|
||||
}
|
||||
else if( FStrEq( pkvd->szKeyName, "beamcount" ) )
|
||||
{
|
||||
m_iBeamCount = atoi( pkvd->szValue );
|
||||
pkvd->fHandled = TRUE;
|
||||
}
|
||||
else if( FStrEq( pkvd->szKeyName, "spritescale" ) )
|
||||
{
|
||||
m_flSpriteScale = atof( pkvd->szValue );
|
||||
pkvd->fHandled = TRUE;
|
||||
}
|
||||
else if( FStrEq( pkvd->szKeyName, "spawnsoundrad" ) )
|
||||
{
|
||||
switch( atoi( pkvd->szValue ) )
|
||||
{
|
||||
case 3:
|
||||
m_flSpawnSoundRad = ATTN_NONE;
|
||||
break;
|
||||
case 2:
|
||||
m_flSpawnSoundRad = ATTN_NORM;
|
||||
break;
|
||||
case 1:
|
||||
m_flSpawnSoundRad = ATTN_IDLE;
|
||||
break;
|
||||
default:
|
||||
m_flSpawnSoundRad = ATTN_STATIC;
|
||||
break;
|
||||
}
|
||||
pkvd->fHandled = TRUE;
|
||||
}
|
||||
else if( FStrEq( pkvd->szKeyName, "spawnvol" ) )
|
||||
{
|
||||
m_flSpawnVol = atof( pkvd->szValue );
|
||||
pkvd->fHandled = TRUE;
|
||||
}
|
||||
else if( FStrEq( pkvd->szKeyName, "lightrad" ) )
|
||||
{
|
||||
m_iLightRad = atoi( pkvd->szValue );
|
||||
pkvd->fHandled = TRUE;
|
||||
}
|
||||
else
|
||||
pkvd->fHandled = FALSE;
|
||||
}
|
||||
|
||||
void CEnvPawnEffect::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
|
||||
{
|
||||
UTIL_CreateWarpball( ENT( pev ), pev->origin, m_flSpawnVol, m_flSpawnSoundRad, m_iBeamCount, m_iSpawnType, m_flSpriteScale, m_iLightRad );
|
||||
SetThink( &CBaseEntity::SUB_Remove );
|
||||
pev->nextthink = gpGlobals->time;
|
||||
}
|
||||
|
|
|
@ -51,6 +51,9 @@ enum egon_e {
|
|||
|
||||
LINK_ENTITY_TO_CLASS( weapon_egon, CEgon )
|
||||
|
||||
int CEgon::g_fireAnims1[] = { EGON_FIRE1, EGON_FIRE2, EGON_FIRE3, EGON_FIRE4 };
|
||||
int CEgon::g_fireAnims2[] = { EGON_ALTFIRECYCLE };
|
||||
|
||||
void CEgon::Spawn()
|
||||
{
|
||||
Precache();
|
||||
|
@ -79,15 +82,12 @@ void CEgon::Precache( void )
|
|||
PRECACHE_MODEL( EGON_FLARE_SPRITE );
|
||||
|
||||
PRECACHE_SOUND( "weapons/357_cock1.wav" );
|
||||
|
||||
m_usEgonFire = PRECACHE_EVENT( 1, "events/egon_fire.sc" );
|
||||
m_usEgonStop = PRECACHE_EVENT( 1, "events/egon_stop.sc" );
|
||||
}
|
||||
|
||||
BOOL CEgon::Deploy( void )
|
||||
{
|
||||
m_deployed = FALSE;
|
||||
m_fireState = FIRE_OFF;
|
||||
// m_fireState = FIRE_OFF;
|
||||
return DefaultDeploy( "models/v_egon.mdl", "models/p_egon.mdl", EGON_DRAW, "egon" );
|
||||
}
|
||||
|
||||
|
@ -105,9 +105,7 @@ int CEgon::AddToPlayer( CBasePlayer *pPlayer )
|
|||
|
||||
void CEgon::Holster( int skiplocal /* = 0 */ )
|
||||
{
|
||||
m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.5;
|
||||
SendWeaponAnim( EGON_HOLSTER );
|
||||
|
||||
DefaultHolster( EGON_HOLSTER, 0.7 );
|
||||
EndAttack();
|
||||
}
|
||||
|
||||
|
@ -162,7 +160,7 @@ void CEgon::Attack( void )
|
|||
// don't fire underwater
|
||||
if( m_pPlayer->pev->waterlevel == 3 )
|
||||
{
|
||||
if( m_fireState != FIRE_OFF || m_pBeam )
|
||||
if( m_pBeam )
|
||||
{
|
||||
EndAttack();
|
||||
}
|
||||
|
@ -197,13 +195,21 @@ void CEgon::Attack( void )
|
|||
|
||||
m_flAmmoUseTime = gpGlobals->time;// start using ammo ASAP.
|
||||
|
||||
PLAYBACK_EVENT_FULL( flags, m_pPlayer->edict(), m_usEgonFire, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, m_fireState, m_fireMode, 1, 0 );
|
||||
|
||||
SendWeaponAnim( g_fireAnims1[ RANDOM_LONG( 0, ARRAYSIZE( g_fireAnims1 ) - 1 ) ] );
|
||||
m_shakeTime = 0;
|
||||
|
||||
m_pPlayer->m_iWeaponVolume = EGON_PRIMARY_VOLUME;
|
||||
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 0.1;
|
||||
pev->fuser1 = UTIL_WeaponTimeBase() + 2;
|
||||
m_shootTime = gpGlobals->time + 2;
|
||||
|
||||
if( m_fireMode == FIRE_WIDE )
|
||||
{
|
||||
EMIT_SOUND_DYN( ENT( m_pPlayer->pev ), CHAN_WEAPON, EGON_SOUND_STARTUP, 0.98, ATTN_NORM, 0, 125 );
|
||||
}
|
||||
else
|
||||
{
|
||||
EMIT_SOUND_DYN( ENT( m_pPlayer->pev ), CHAN_WEAPON, EGON_SOUND_STARTUP, 0.9, ATTN_NORM, 0, 100 );
|
||||
}
|
||||
|
||||
pev->dmgtime = gpGlobals->time + GetPulseInterval();
|
||||
m_fireState = FIRE_CHARGE;
|
||||
|
@ -214,15 +220,23 @@ void CEgon::Attack( void )
|
|||
Fire( vecSrc, vecAiming );
|
||||
m_pPlayer->m_iWeaponVolume = EGON_PRIMARY_VOLUME;
|
||||
|
||||
if( pev->fuser1 <= UTIL_WeaponTimeBase() )
|
||||
if( m_shootTime != 0 && gpGlobals->time > m_shootTime )
|
||||
{
|
||||
PLAYBACK_EVENT_FULL( flags, m_pPlayer->edict(), m_usEgonFire, 0, (float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, m_fireState, m_fireMode, 0, 0 );
|
||||
pev->fuser1 = 1000;
|
||||
if( m_fireMode == FIRE_WIDE )
|
||||
{
|
||||
EMIT_SOUND_DYN( ENT( m_pPlayer->pev ), CHAN_STATIC, EGON_SOUND_RUN, 0.98, ATTN_NORM, 0, 125 );
|
||||
}
|
||||
else
|
||||
{
|
||||
EMIT_SOUND_DYN( ENT( m_pPlayer->pev ), CHAN_STATIC, EGON_SOUND_RUN, 0.9, ATTN_NORM, 0, 100 );
|
||||
}
|
||||
m_shootTime = 0;
|
||||
}
|
||||
|
||||
if( !HasAmmo() )
|
||||
{
|
||||
EndAttack();
|
||||
m_fireState = FIRE_OFF;
|
||||
m_flNextPrimaryAttack = m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 1.0;
|
||||
}
|
||||
break;
|
||||
|
@ -232,6 +246,12 @@ void CEgon::Attack( void )
|
|||
|
||||
void CEgon::PrimaryAttack( void )
|
||||
{
|
||||
if( m_pPlayer->m_bIsHolster )
|
||||
{
|
||||
WeaponIdle();
|
||||
return;
|
||||
}
|
||||
|
||||
m_fireMode = FIRE_WIDE;
|
||||
Attack();
|
||||
}
|
||||
|
@ -407,8 +427,8 @@ void CEgon::CreateEffect( void )
|
|||
m_pBeam->SetFlags( BEAM_FSINE );
|
||||
m_pBeam->SetEndAttachment( 1 );
|
||||
m_pBeam->pev->spawnflags |= SF_BEAM_TEMPORARY; // Flag these to be destroyed on save/restore or level transition
|
||||
m_pBeam->pev->flags |= FL_SKIPLOCALHOST;
|
||||
m_pBeam->pev->owner = m_pPlayer->edict();
|
||||
// m_pBeam->pev->flags |= FL_SKIPLOCALHOST;
|
||||
// m_pBeam->pev->owner = m_pPlayer->edict();
|
||||
|
||||
m_pNoise = CBeam::BeamCreate( EGON_BEAM_SPRITE, 55 );
|
||||
m_pNoise->PointEntInit( pev->origin, m_pPlayer->entindex() );
|
||||
|
@ -416,15 +436,15 @@ void CEgon::CreateEffect( void )
|
|||
m_pNoise->SetBrightness( 100 );
|
||||
m_pNoise->SetEndAttachment( 1 );
|
||||
m_pNoise->pev->spawnflags |= SF_BEAM_TEMPORARY;
|
||||
m_pNoise->pev->flags |= FL_SKIPLOCALHOST;
|
||||
m_pNoise->pev->owner = m_pPlayer->edict();
|
||||
// m_pNoise->pev->flags |= FL_SKIPLOCALHOST;
|
||||
// m_pNoise->pev->owner = m_pPlayer->edict();
|
||||
|
||||
m_pSprite = CSprite::SpriteCreate( EGON_FLARE_SPRITE, pev->origin, FALSE );
|
||||
m_pSprite->pev->scale = 1.0;
|
||||
m_pSprite->SetTransparency( kRenderGlow, 255, 255, 255, 255, kRenderFxNoDissipation );
|
||||
m_pSprite->pev->spawnflags |= SF_SPRITE_TEMPORARY;
|
||||
m_pSprite->pev->flags |= FL_SKIPLOCALHOST;
|
||||
m_pSprite->pev->owner = m_pPlayer->edict();
|
||||
// m_pSprite->pev->flags |= FL_SKIPLOCALHOST;
|
||||
// m_pSprite->pev->owner = m_pPlayer->edict();
|
||||
|
||||
if( m_fireMode == FIRE_WIDE )
|
||||
{
|
||||
|
@ -470,6 +490,16 @@ void CEgon::DestroyEffect( void )
|
|||
|
||||
void CEgon::WeaponIdle( void )
|
||||
{
|
||||
if( m_pPlayer->m_bIsHolster )
|
||||
{
|
||||
if( m_flTimeWeaponIdle <= UTIL_WeaponTimeBase() )
|
||||
{
|
||||
m_pPlayer->m_bIsHolster = FALSE;
|
||||
Deploy();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
ResetEmptySound();
|
||||
|
||||
if( m_flTimeWeaponIdle > UTIL_WeaponTimeBase() )
|
||||
|
@ -499,16 +529,11 @@ void CEgon::WeaponIdle( void )
|
|||
|
||||
void CEgon::EndAttack( void )
|
||||
{
|
||||
bool bMakeNoise = false;
|
||||
|
||||
if( m_fireState != FIRE_OFF ) //Checking the button just in case!.
|
||||
bMakeNoise = true;
|
||||
|
||||
PLAYBACK_EVENT_FULL( FEV_GLOBAL | FEV_RELIABLE, m_pPlayer->edict(), m_usEgonStop, 0, (float *)&m_pPlayer->pev->origin, (float *)&m_pPlayer->pev->angles, 0.0, 0.0, bMakeNoise, 0, 0, 0 );
|
||||
|
||||
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 2.0;
|
||||
m_flNextPrimaryAttack = m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.5;
|
||||
|
||||
STOP_SOUND( ENT( m_pPlayer->pev ), CHAN_STATIC, EGON_SOUND_RUN );
|
||||
EMIT_SOUND_DYN( ENT( m_pPlayer->pev ), CHAN_WEAPON, EGON_SOUND_OFF, 0.98, ATTN_NORM, 0, 100 );
|
||||
m_fireState = FIRE_OFF;
|
||||
|
||||
DestroyEffect();
|
||||
|
|
|
@ -138,21 +138,24 @@ BOOL CGauss::Deploy()
|
|||
|
||||
void CGauss::Holster( int skiplocal /* = 0 */ )
|
||||
{
|
||||
PLAYBACK_EVENT_FULL( FEV_RELIABLE | FEV_GLOBAL, m_pPlayer->edict(), m_usGaussFire, 0.01, (float *)&m_pPlayer->pev->origin, (float *)&m_pPlayer->pev->angles, 0.0, 0.0, 0, 0, 0, 1 );
|
||||
|
||||
m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.5;
|
||||
|
||||
SendWeaponAnim( GAUSS_HOLSTER );
|
||||
DefaultHolster( GAUSS_HOLSTER, 0.9 );
|
||||
m_fInAttack = 0;
|
||||
EMIT_SOUND( ENT( m_pPlayer->pev ), CHAN_WEAPON, "common/null.wav", 1.0, ATTN_NORM );
|
||||
}
|
||||
|
||||
void CGauss::PrimaryAttack()
|
||||
{
|
||||
if( m_pPlayer->m_bIsHolster )
|
||||
{
|
||||
WeaponIdle();
|
||||
return;
|
||||
}
|
||||
|
||||
// don't fire underwater
|
||||
if( m_pPlayer->pev->waterlevel == 3 )
|
||||
{
|
||||
PlayEmptySound();
|
||||
m_flNextSecondaryAttack = m_flNextPrimaryAttack = GetNextAttackDelay( 0.15 );
|
||||
m_flNextSecondaryAttack = m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.15;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -176,6 +179,12 @@ void CGauss::PrimaryAttack()
|
|||
|
||||
void CGauss::SecondaryAttack()
|
||||
{
|
||||
if( m_pPlayer->m_bIsHolster )
|
||||
{
|
||||
WeaponIdle();
|
||||
return;
|
||||
}
|
||||
|
||||
// don't fire underwater
|
||||
if( m_pPlayer->pev->waterlevel == 3 )
|
||||
{
|
||||
|
@ -190,7 +199,7 @@ void CGauss::SecondaryAttack()
|
|||
PlayEmptySound();
|
||||
}
|
||||
|
||||
m_flNextSecondaryAttack = m_flNextPrimaryAttack = GetNextAttackDelay( 0.5 );
|
||||
m_flNextSecondaryAttack = m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.5;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -217,7 +226,7 @@ void CGauss::SecondaryAttack()
|
|||
m_pPlayer->m_flStartCharge = gpGlobals->time;
|
||||
m_pPlayer->m_flAmmoStartCharge = UTIL_WeaponTimeBase() + GetFullChargeTime();
|
||||
|
||||
PLAYBACK_EVENT_FULL( FEV_NOTHOST, m_pPlayer->edict(), m_usGaussSpin, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, 110, 0, 0, 0 );
|
||||
PLAYBACK_EVENT_FULL( 0, m_pPlayer->edict(), m_usGaussSpin, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, 110, 0, 0, 0 );
|
||||
|
||||
m_iSoundState = SND_CHANGE_PITCH;
|
||||
}
|
||||
|
@ -281,7 +290,7 @@ void CGauss::SecondaryAttack()
|
|||
if( m_iSoundState == 0 )
|
||||
ALERT( at_console, "sound state %d\n", m_iSoundState );
|
||||
|
||||
PLAYBACK_EVENT_FULL( FEV_NOTHOST, m_pPlayer->edict(), m_usGaussSpin, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, pitch, 0, ( m_iSoundState == SND_CHANGE_PITCH ) ? 1 : 0, 0 );
|
||||
PLAYBACK_EVENT_FULL( 0, m_pPlayer->edict(), m_usGaussSpin, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, pitch, 0, ( m_iSoundState == SND_CHANGE_PITCH ) ? 1 : 0, 0 );
|
||||
|
||||
m_iSoundState = SND_CHANGE_PITCH; // hack for going through level transitions
|
||||
|
||||
|
@ -389,13 +398,13 @@ void CGauss::Fire( Vector vecOrigSrc, Vector vecDir, float flDamage )
|
|||
g_irunninggausspred = true;
|
||||
#endif
|
||||
// The main firing event is sent unreliably so it won't be delayed.
|
||||
PLAYBACK_EVENT_FULL( FEV_NOTHOST, m_pPlayer->edict(), m_usGaussFire, 0.0, (float *)&m_pPlayer->pev->origin, (float *)&m_pPlayer->pev->angles, flDamage, 0.0, 0, 0, m_fPrimaryFire ? 1 : 0, 0 );
|
||||
PLAYBACK_EVENT_FULL( 0, m_pPlayer->edict(), m_usGaussFire, 0.0, (float *)&m_pPlayer->pev->origin, (float *)&m_pPlayer->pev->angles, flDamage, 0.0, 0, 0, m_fPrimaryFire ? 1 : 0, 0 );
|
||||
|
||||
// This reliable event is used to stop the spinning sound
|
||||
// It's delayed by a fraction of second to make sure it is delayed by 1 frame on the client
|
||||
// It's sent reliably anyway, which could lead to other delays
|
||||
|
||||
PLAYBACK_EVENT_FULL( FEV_NOTHOST | FEV_RELIABLE, m_pPlayer->edict(), m_usGaussFire, 0.01, (float *)&m_pPlayer->pev->origin, (float *)&m_pPlayer->pev->angles, 0.0, 0.0, 0, 0, 0, 1 );
|
||||
PLAYBACK_EVENT_FULL( FEV_RELIABLE, m_pPlayer->edict(), m_usGaussFire, 0.01, (float *)&m_pPlayer->pev->origin, (float *)&m_pPlayer->pev->angles, 0.0, 0.0, 0, 0, 0, 1 );
|
||||
|
||||
/*ALERT( at_console, "%f %f %f\n%f %f %f\n",
|
||||
vecSrc.x, vecSrc.y, vecSrc.z,
|
||||
|
@ -545,6 +554,16 @@ void CGauss::Fire( Vector vecOrigSrc, Vector vecDir, float flDamage )
|
|||
|
||||
void CGauss::WeaponIdle( void )
|
||||
{
|
||||
if( m_pPlayer->m_bIsHolster )
|
||||
{
|
||||
if( m_flTimeWeaponIdle <= UTIL_WeaponTimeBase() )
|
||||
{
|
||||
m_pPlayer->m_bIsHolster = FALSE;
|
||||
Deploy();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
ResetEmptySound();
|
||||
|
||||
// play aftershock static discharge
|
||||
|
|
|
@ -20,10 +20,11 @@
|
|||
#include "cbase.h"
|
||||
#include "monsters.h"
|
||||
#include "schedule.h"
|
||||
#include "weapons.h"
|
||||
|
||||
// For holograms, make them not solid so the player can walk through them
|
||||
#define SF_GENERICMONSTER_NOTSOLID 4
|
||||
|
||||
#define SF_GENERICMONSTER_DONTBLEED 8
|
||||
//=========================================================
|
||||
// Monster's Anim Events Go Here
|
||||
//=========================================================
|
||||
|
@ -37,6 +38,8 @@ public:
|
|||
int Classify( void );
|
||||
void HandleAnimEvent( MonsterEvent_t *pEvent );
|
||||
int ISoundMask( void );
|
||||
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 );
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS( monster_generic, CGenericMonster )
|
||||
|
@ -112,8 +115,16 @@ void CGenericMonster::Spawn()
|
|||
|
||||
pev->solid = SOLID_SLIDEBOX;
|
||||
pev->movetype = MOVETYPE_STEP;
|
||||
m_bloodColor = BLOOD_COLOR_RED;
|
||||
pev->health = 8;
|
||||
if( pev->spawnflags & SF_GENERICMONSTER_DONTBLEED )
|
||||
{
|
||||
m_bloodColor = DONT_BLEED;
|
||||
pev->health = 100;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_bloodColor = BLOOD_COLOR_RED;
|
||||
pev->health = 8;
|
||||
}
|
||||
m_flFieldOfView = 0.5;// indicates the width of this monster's forward view cone ( as a dotproduct result )
|
||||
m_MonsterState = MONSTERSTATE_NONE;
|
||||
|
||||
|
@ -134,6 +145,38 @@ void CGenericMonster::Precache()
|
|||
PRECACHE_MODEL( STRING( pev->model ) );
|
||||
}
|
||||
|
||||
void CGenericMonster::TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType )
|
||||
{
|
||||
if( pev->spawnflags & SF_GENERICMONSTER_DONTBLEED )
|
||||
{
|
||||
UTIL_Ricochet( ptr->vecEndPos, 1.0f );
|
||||
AddMultiDamage( pevAttacker, this, flDamage, bitsDamageType );
|
||||
return;
|
||||
}
|
||||
|
||||
CBaseMonster::TraceAttack( pevAttacker, flDamage, vecDir, ptr, bitsDamageType );
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// AI Schedules Specific to this monster
|
||||
//=========================================================
|
||||
int CGenericMonster::TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType )
|
||||
{
|
||||
if( pev->spawnflags & SF_GENERICMONSTER_DONTBLEED )
|
||||
{
|
||||
pev->health = pev->max_health / 2; // always trigger the 50% damage aitrigger
|
||||
|
||||
if( flDamage > 0 )
|
||||
{
|
||||
SetConditions( bits_COND_LIGHT_DAMAGE );
|
||||
}
|
||||
|
||||
if( flDamage >= 20 )
|
||||
{
|
||||
SetConditions( bits_COND_HEAVY_DAMAGE );
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return CBaseMonster::TakeDamage( pevInflictor, pevAttacker, flDamage, bitsDamageType );
|
||||
}
|
||||
|
|
|
@ -356,7 +356,7 @@ void CGrenade::Spawn( void )
|
|||
m_fRegisteredSound = FALSE;
|
||||
}
|
||||
|
||||
CGrenade *CGrenade::ShootContact( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity )
|
||||
CGrenade *CGrenade::ShootContact( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity, float flDmg )
|
||||
{
|
||||
CGrenade *pGrenade = GetClassPtr( (CGrenade *)NULL );
|
||||
pGrenade->Spawn();
|
||||
|
@ -377,7 +377,7 @@ CGrenade *CGrenade::ShootContact( entvars_t *pevOwner, Vector vecStart, Vector v
|
|||
// Explode on contact
|
||||
pGrenade->SetTouch( &CGrenade::ExplodeTouch );
|
||||
|
||||
pGrenade->pev->dmg = gSkillData.plrDmgM203Grenade;
|
||||
pGrenade->pev->dmg = flDmg;
|
||||
|
||||
return pGrenade;
|
||||
}
|
||||
|
|
|
@ -37,10 +37,10 @@ enum glock_e
|
|||
|
||||
LINK_ENTITY_TO_CLASS( weapon_glock, CGlock )
|
||||
LINK_ENTITY_TO_CLASS( weapon_9mmhandgun, CGlock )
|
||||
LINK_ENTITY_TO_CLASS( weapon_barney9mmnh, CGlock )
|
||||
|
||||
void CGlock::Spawn()
|
||||
{
|
||||
pev->classname = MAKE_STRING( "weapon_barney9mmhg" ); // hack to allow for old names
|
||||
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" );
|
||||
|
@ -52,7 +52,7 @@ void CGlock::Spawn()
|
|||
|
||||
void CGlock::Precache( void )
|
||||
{
|
||||
PRECACHE_MODEL( "models/v_barney9mmhg.mdl" );
|
||||
PRECACHE_MODEL( "models/v_9mmhandgun.mdl" );
|
||||
PRECACHE_MODEL( "models/w_9mmhandgun.mdl" );
|
||||
PRECACHE_MODEL( "models/p_9mmhandgun.mdl" );
|
||||
|
||||
|
@ -101,7 +101,12 @@ int CGlock::AddToPlayer( CBasePlayer *pPlayer )
|
|||
BOOL CGlock::Deploy()
|
||||
{
|
||||
// pev->body = 1;
|
||||
return DefaultDeploy( "models/v_barney9mmhg.mdl", "models/p_9mmhandgun.mdl", GLOCK_DRAW, "onehanded", /*UseDecrement() ? 1 : 0*/ 0 );
|
||||
return DefaultDeploy( "models/v_9mmhandgun.mdl", "models/p_9mmhandgun.mdl", GLOCK_DRAW, "onehanded", /*UseDecrement() ? 1 : 0*/ 0 );
|
||||
}
|
||||
|
||||
void CGlock::Holster( int skiplocal /* = 0 */ )
|
||||
{
|
||||
DefaultHolster( GLOCK_HOLSTER, 1.2 );
|
||||
}
|
||||
|
||||
void CGlock::SecondaryAttack( void )
|
||||
|
@ -116,12 +121,18 @@ void CGlock::PrimaryAttack( void )
|
|||
|
||||
void CGlock::GlockFire( float flSpread, float flCycleTime, BOOL fUseAutoAim )
|
||||
{
|
||||
if( m_pPlayer->m_bIsHolster )
|
||||
{
|
||||
WeaponIdle();
|
||||
return;
|
||||
}
|
||||
|
||||
if( m_iClip <= 0 )
|
||||
{
|
||||
if( m_fFireOnEmpty )
|
||||
{
|
||||
PlayEmptySound();
|
||||
m_flNextPrimaryAttack = GetNextAttackDelay( 0.2 );
|
||||
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.2;
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -170,7 +181,7 @@ void CGlock::GlockFire( float flSpread, float flCycleTime, BOOL fUseAutoAim )
|
|||
|
||||
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 );
|
||||
|
||||
m_flNextPrimaryAttack = m_flNextSecondaryAttack = GetNextAttackDelay( flCycleTime );
|
||||
m_flNextPrimaryAttack = m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + flCycleTime;
|
||||
|
||||
if( !m_iClip && m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0 )
|
||||
// HEV suit - indicate out of ammo condition
|
||||
|
@ -181,6 +192,12 @@ void CGlock::GlockFire( float flSpread, float flCycleTime, BOOL fUseAutoAim )
|
|||
|
||||
void CGlock::Reload( void )
|
||||
{
|
||||
if( m_pPlayer->m_bIsHolster )
|
||||
{
|
||||
WeaponIdle();
|
||||
return;
|
||||
}
|
||||
|
||||
if( m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0 || m_iClip == GLOCK_MAX_CLIP )
|
||||
return;
|
||||
|
||||
|
@ -199,6 +216,16 @@ void CGlock::Reload( void )
|
|||
|
||||
void CGlock::WeaponIdle( void )
|
||||
{
|
||||
if( m_pPlayer->m_bIsHolster )
|
||||
{
|
||||
if( m_flTimeWeaponIdle <= UTIL_WeaponTimeBase() )
|
||||
{
|
||||
m_pPlayer->m_bIsHolster = FALSE;
|
||||
Deploy();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
ResetEmptySound();
|
||||
|
||||
m_pPlayer->GetAutoaimVector( AUTOAIM_10DEGREES );
|
||||
|
|
|
@ -47,6 +47,7 @@ public:
|
|||
int m_iJuice;
|
||||
int m_iOn; // 0 = off, 1 = startup, 2 = going
|
||||
float m_flSoundTime;
|
||||
float m_flMessageTime;
|
||||
};
|
||||
|
||||
TYPEDESCRIPTION CRecharge::m_SaveData[] =
|
||||
|
@ -104,8 +105,14 @@ void CRecharge::Precache()
|
|||
|
||||
void CRecharge::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
|
||||
{
|
||||
// Make sure that we have a caller
|
||||
if( !pActivator )
|
||||
return;
|
||||
|
||||
m_hActivator = pActivator;
|
||||
|
||||
// if it's not a player, ignore
|
||||
if( !FClassnameIs( pActivator->pev, "player" ) )
|
||||
if( !m_hActivator->IsPlayer() )
|
||||
return;
|
||||
|
||||
// if there is no juice left, turn it off
|
||||
|
@ -116,13 +123,19 @@ void CRecharge::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE use
|
|||
}
|
||||
|
||||
// if the player doesn't have the suit, or there is no juice left, make the deny noise
|
||||
if( ( m_iJuice <= 0 ) || ( !( pActivator->pev->weapons & ( 1 << WEAPON_SUIT ) ) ) )
|
||||
if( ( m_iJuice <= 0 ) || ( !( m_hActivator->pev->weapons & ( 1 << WEAPON_SUIT ) ) || !UTIL_HasSuit( m_hActivator ) ) )
|
||||
{
|
||||
if( m_flSoundTime <= gpGlobals->time )
|
||||
{
|
||||
m_flSoundTime = gpGlobals->time + 0.62;
|
||||
EMIT_SOUND( ENT( pev ), CHAN_ITEM, "items/suitchargeno1.wav", 0.85, ATTN_NORM );
|
||||
}
|
||||
|
||||
if( !UTIL_HasSuit( m_hActivator ) && m_flMessageTime < gpGlobals->time )
|
||||
{
|
||||
m_flMessageTime = gpGlobals->time + 4.0f;
|
||||
UTIL_ShowMessageAll( "NOHEVRECHARGE" );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -133,16 +146,6 @@ void CRecharge::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE use
|
|||
if( m_flNextCharge >= gpGlobals->time )
|
||||
return;
|
||||
|
||||
// Make sure that we have a caller
|
||||
if( !pActivator )
|
||||
return;
|
||||
|
||||
m_hActivator = pActivator;
|
||||
|
||||
//only recharge the player
|
||||
if( !m_hActivator->IsPlayer() )
|
||||
return;
|
||||
|
||||
// Play the on sound or the looping charging sound
|
||||
if( !m_iOn )
|
||||
{
|
||||
|
|
|
@ -36,7 +36,6 @@ enum handgrenade_e
|
|||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS( weapon_handgrenade, CHandGrenade )
|
||||
LINK_ENTITY_TO_CLASS( weapon_barneyhandgrenade, CHandGrenade ) // edit for Azure Sheep
|
||||
|
||||
void CHandGrenade::Spawn()
|
||||
{
|
||||
|
@ -54,8 +53,8 @@ void CHandGrenade::Spawn()
|
|||
|
||||
void CHandGrenade::Precache( void )
|
||||
{
|
||||
PRECACHE_MODEL( "models/v_grenade.mdl" );
|
||||
PRECACHE_MODEL( "models/w_grenade.mdl" );
|
||||
PRECACHE_MODEL( "models/v_barneygrenade.mdl" );
|
||||
PRECACHE_MODEL( "models/p_grenade.mdl" );
|
||||
}
|
||||
|
||||
|
@ -79,7 +78,7 @@ int CHandGrenade::GetItemInfo( ItemInfo *p )
|
|||
BOOL CHandGrenade::Deploy()
|
||||
{
|
||||
m_flReleaseThrow = -1;
|
||||
return DefaultDeploy( "models/v_barneygrenade.mdl", "models/p_grenade.mdl", HANDGRENADE_DRAW, "crowbar" );
|
||||
return DefaultDeploy( "models/v_grenade.mdl", "models/p_grenade.mdl", HANDGRENADE_DRAW, "crowbar" );
|
||||
}
|
||||
|
||||
BOOL CHandGrenade::CanHolster( void )
|
||||
|
@ -90,11 +89,9 @@ BOOL CHandGrenade::CanHolster( void )
|
|||
|
||||
void CHandGrenade::Holster( int skiplocal /* = 0 */ )
|
||||
{
|
||||
m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.5;
|
||||
|
||||
if( m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] )
|
||||
{
|
||||
SendWeaponAnim( HANDGRENADE_HOLSTER );
|
||||
DefaultHolster( HANDGRENADE_HOLSTER, 0.7 );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -114,6 +111,12 @@ void CHandGrenade::Holster( int skiplocal /* = 0 */ )
|
|||
|
||||
void CHandGrenade::PrimaryAttack()
|
||||
{
|
||||
if( m_pPlayer->m_bIsHolster )
|
||||
{
|
||||
WeaponIdle();
|
||||
return;
|
||||
}
|
||||
|
||||
if( !m_flStartThrow && m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] > 0 )
|
||||
{
|
||||
m_flStartThrow = gpGlobals->time;
|
||||
|
@ -126,6 +129,16 @@ void CHandGrenade::PrimaryAttack()
|
|||
|
||||
void CHandGrenade::WeaponIdle( void )
|
||||
{
|
||||
if( m_pPlayer->m_bIsHolster )
|
||||
{
|
||||
if( m_flTimeWeaponIdle <= UTIL_WeaponTimeBase() )
|
||||
{
|
||||
m_pPlayer->m_bIsHolster = FALSE;
|
||||
Deploy();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if( m_flReleaseThrow == 0 && m_flStartThrow )
|
||||
m_flReleaseThrow = gpGlobals->time;
|
||||
|
||||
|
@ -176,7 +189,7 @@ void CHandGrenade::WeaponIdle( void )
|
|||
|
||||
m_flReleaseThrow = 0;
|
||||
m_flStartThrow = 0;
|
||||
m_flNextPrimaryAttack = GetNextAttackDelay( 0.5 );
|
||||
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.5;
|
||||
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 0.5;
|
||||
|
||||
m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]--;
|
||||
|
@ -186,7 +199,7 @@ void CHandGrenade::WeaponIdle( void )
|
|||
// just threw last grenade
|
||||
// set attack times in the future, and weapon idle in the future so we can see the whole throw
|
||||
// animation, weapon idle will automatically retire the weapon for us.
|
||||
m_flTimeWeaponIdle = m_flNextSecondaryAttack = m_flNextPrimaryAttack = GetNextAttackDelay( 0.5 );// ensure that the animation can finish playing
|
||||
m_flTimeWeaponIdle = m_flNextSecondaryAttack = m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.5;// ensure that the animation can finish playing
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
/***
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
****/
|
||||
class CHeadCrab : public CBaseMonster
|
||||
{
|
||||
public:
|
||||
virtual void Spawn( void );
|
||||
virtual void Precache( void );
|
||||
void RunTask ( Task_t *pTask );
|
||||
virtual 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 );
|
||||
void PrescheduleThink( void );
|
||||
virtual int Classify( void );
|
||||
virtual 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[];
|
||||
};
|
|
@ -60,10 +60,13 @@ void CHealthKit::Precache( void )
|
|||
{
|
||||
PRECACHE_MODEL( "models/w_medkit.mdl" );
|
||||
PRECACHE_SOUND( "items/smallmedkit1.wav" );
|
||||
PRECACHE_SOUND( "items/smallmedkit3.wav" );
|
||||
}
|
||||
|
||||
BOOL CHealthKit::MyTouch( CBasePlayer *pPlayer )
|
||||
{
|
||||
const char *pszSound;
|
||||
|
||||
if( pPlayer->pev->deadflag != DEAD_NO )
|
||||
{
|
||||
return FALSE;
|
||||
|
@ -75,7 +78,12 @@ BOOL CHealthKit::MyTouch( CBasePlayer *pPlayer )
|
|||
WRITE_STRING( STRING( pev->classname ) );
|
||||
MESSAGE_END();
|
||||
|
||||
EMIT_SOUND( ENT( pPlayer->pev ), CHAN_ITEM, "items/smallmedkit1.wav", 1, ATTN_NORM );
|
||||
if( UTIL_HasSuit( pPlayer ) )
|
||||
pszSound = "items/smallmedkit1.wav";
|
||||
else
|
||||
pszSound = "items/smallmedkit3.wav";
|
||||
|
||||
EMIT_SOUND( ENT( pPlayer->pev ), CHAN_ITEM, pszSound, 1, ATTN_NORM );
|
||||
|
||||
if( g_pGameRules->ItemShouldRespawn( this ) )
|
||||
{
|
||||
|
@ -168,10 +176,13 @@ void CWallHealth::Precache()
|
|||
PRECACHE_SOUND( "items/medshot4.wav" );
|
||||
PRECACHE_SOUND( "items/medshotno1.wav" );
|
||||
PRECACHE_SOUND( "items/medcharge4.wav" );
|
||||
PRECACHE_SOUND( "items/medcharge5.wav" );
|
||||
}
|
||||
|
||||
void CWallHealth::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
|
||||
{
|
||||
const char *pszSound;
|
||||
|
||||
// Make sure that we have a caller
|
||||
if( !pActivator )
|
||||
return;
|
||||
|
@ -214,7 +225,11 @@ void CWallHealth::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE u
|
|||
if( ( m_iOn == 1 ) && ( m_flSoundTime <= gpGlobals->time ) )
|
||||
{
|
||||
m_iOn++;
|
||||
EMIT_SOUND( ENT( pev ), CHAN_STATIC, "items/medcharge4.wav", 1.0, ATTN_NORM );
|
||||
if( UTIL_HasSuit( pActivator ) )
|
||||
pszSound = "items/medcharge4.wav";
|
||||
else
|
||||
pszSound = "items/medcharge5.wav";
|
||||
EMIT_SOUND( ENT( pev ), CHAN_STATIC, pszSound, 1.0, ATTN_NORM );
|
||||
}
|
||||
|
||||
// charge the player
|
||||
|
@ -239,7 +254,10 @@ void CWallHealth::Off( void )
|
|||
{
|
||||
// Stop looping sound.
|
||||
if( m_iOn > 1 )
|
||||
{
|
||||
STOP_SOUND( ENT( pev ), CHAN_STATIC, "items/medcharge4.wav" );
|
||||
STOP_SOUND( ENT( pev ), CHAN_STATIC, "items/medcharge5.wav" );
|
||||
}
|
||||
|
||||
m_iOn = 0;
|
||||
|
||||
|
|
158
dlls/hgrunt.cpp
158
dlls/hgrunt.cpp
|
@ -40,6 +40,7 @@
|
|||
#include "soundent.h"
|
||||
#include "effects.h"
|
||||
#include "customentity.h"
|
||||
#include "hgrunt.h"
|
||||
|
||||
int g_fGruntQuestion; // true if an idle grunt asked a question. Cleared when someone answers.
|
||||
|
||||
|
@ -72,6 +73,9 @@ extern DLL_GLOBAL int g_iSkillLevel;
|
|||
#define GUN_SHOTGUN 1
|
||||
#define GUN_NONE 2
|
||||
|
||||
#define SF_BARNEY_HAVESUIT ( 1 << 3 )
|
||||
#define SF_FRIENDLY_GRUNT ( 1 << 6 )
|
||||
|
||||
//=========================================================
|
||||
// Monster's Anim Events Go Here
|
||||
//=========================================================
|
||||
|
@ -119,73 +123,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[] =
|
||||
|
@ -217,18 +154,6 @@ const char *CHGrunt::pGruntSentences[] =
|
|||
"HG_TAUNT", // say rude things
|
||||
};
|
||||
|
||||
typedef enum
|
||||
{
|
||||
HGRUNT_SENT_NONE = -1,
|
||||
HGRUNT_SENT_GREN = 0,
|
||||
HGRUNT_SENT_ALERT,
|
||||
HGRUNT_SENT_MONSTER,
|
||||
HGRUNT_SENT_COVER,
|
||||
HGRUNT_SENT_THROW,
|
||||
HGRUNT_SENT_CHARGE,
|
||||
HGRUNT_SENT_TAUNT
|
||||
} HGRUNT_SENTENCE_TYPES;
|
||||
|
||||
//=========================================================
|
||||
// Speak Sentence - say your cued up sentence.
|
||||
//
|
||||
|
@ -266,10 +191,40 @@ int CHGrunt::IRelationship( CBaseEntity *pTarget )
|
|||
{
|
||||
return R_NM;
|
||||
}
|
||||
|
||||
else if( FClassnameIs( pTarget->pev, "monster_human_spforce" ) )
|
||||
{
|
||||
return R_HT;
|
||||
}
|
||||
else if( FClassnameIs( pTarget->pev, "monster_adrian" ) )
|
||||
{
|
||||
return R_AL;
|
||||
}
|
||||
else if( FBitSet( pev->spawnflags, SF_FRIENDLY_GRUNT )
|
||||
&& pTarget->IsPlayer()
|
||||
&& IsNotProvoked() )
|
||||
{
|
||||
return R_AL;
|
||||
}
|
||||
|
||||
return CSquadMonster::IRelationship( pTarget );
|
||||
}
|
||||
|
||||
BOOL CHGrunt::IsNotProvoked()
|
||||
{
|
||||
CBaseEntity *pEntity = UTIL_FindEntityByTargetname( 0, "adrianmm" );
|
||||
if( pEntity )
|
||||
return !FBitSet( m_afMemory,bits_MEMORY_PROVOKED );
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void CHGrunt::Provoke()
|
||||
{
|
||||
CBaseEntity *pEntity = UTIL_FindEntityByTargetname( 0, "adrianmm" );
|
||||
if( pEntity )
|
||||
SetBits( m_afMemory,bits_MEMORY_PROVOKED );
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// GibMonster - make gun fly through the air.
|
||||
//=========================================================
|
||||
|
@ -284,16 +239,26 @@ void CHGrunt::GibMonster( void )
|
|||
GetAttachment( 0, vecGunPos, vecGunAngles );
|
||||
|
||||
CBaseEntity *pGun;
|
||||
const char *pszWeapon;
|
||||
|
||||
if( FBitSet( pev->weapons, HGRUNT_SHOTGUN ) )
|
||||
{
|
||||
pGun = DropItem( "weapon_shotgun", vecGunPos, vecGunAngles );
|
||||
if( FBitSet( pev->spawnflags, SF_BARNEY_HAVESUIT ) )
|
||||
pszWeapon = "weapon_shotgun";
|
||||
else
|
||||
pszWeapon = "weapon_barneyshotgun";
|
||||
}
|
||||
else if( FBitSet( pev->spawnflags, SF_BARNEY_HAVESUIT ) )
|
||||
{
|
||||
pszWeapon = "weapon_9mmAR";
|
||||
}
|
||||
else
|
||||
{
|
||||
pGun = DropItem( "weapon_9mmAR", vecGunPos, vecGunAngles );
|
||||
pszWeapon = "weapon_barney9mmar";
|
||||
}
|
||||
|
||||
pGun = DropItem( pszWeapon, vecGunPos, vecGunAngles );
|
||||
|
||||
if( pGun )
|
||||
{
|
||||
pGun->pev->velocity = Vector( RANDOM_FLOAT( -100, 100 ), RANDOM_FLOAT( -100, 100 ), RANDOM_FLOAT( 200, 300 ) );
|
||||
|
@ -627,6 +592,15 @@ void CHGrunt::TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir
|
|||
//=========================================================
|
||||
int CHGrunt::TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType )
|
||||
{
|
||||
if( FBitSet( pev->spawnflags, SF_FRIENDLY_GRUNT )
|
||||
&& pev->movetype != MOVETYPE_FLY
|
||||
&& FBitSet( pevAttacker->flags, EF_DIMLIGHT )
|
||||
&& m_hEnemy == 0 )
|
||||
{
|
||||
SENTENCEG_PlayRndSz( ENT( pev ), "HG_ALERT", HGRUNT_SENTENCE_VOLUME, GRUNT_ATTN, 0, m_voicePitch );
|
||||
Provoke();
|
||||
}
|
||||
|
||||
Forget( bits_MEMORY_INCOVER );
|
||||
|
||||
return CSquadMonster::TakeDamage( pevInflictor, pevAttacker, flDamage, bitsDamageType );
|
||||
|
@ -851,6 +825,7 @@ void CHGrunt::HandleAnimEvent( MonsterEvent_t *pEvent )
|
|||
{
|
||||
Vector vecGunPos;
|
||||
Vector vecGunAngles;
|
||||
const char *pszWeapon;
|
||||
|
||||
GetAttachment( 0, vecGunPos, vecGunAngles );
|
||||
|
||||
|
@ -860,13 +835,22 @@ void CHGrunt::HandleAnimEvent( MonsterEvent_t *pEvent )
|
|||
// now spawn a gun.
|
||||
if( FBitSet( pev->weapons, HGRUNT_SHOTGUN ) )
|
||||
{
|
||||
DropItem( "weapon_shotgun", vecGunPos, vecGunAngles );
|
||||
if( FBitSet( pev->spawnflags, SF_BARNEY_HAVESUIT ) )
|
||||
pszWeapon = "weapon_shotgun";
|
||||
else
|
||||
pszWeapon = "weapon_barneyshotgun";
|
||||
}
|
||||
else if( FBitSet( pev->spawnflags, SF_BARNEY_HAVESUIT ) )
|
||||
{
|
||||
pszWeapon = "weapon_9mmAR";
|
||||
}
|
||||
else
|
||||
{
|
||||
DropItem( "weapon_9mmAR", vecGunPos, vecGunAngles );
|
||||
pszWeapon = "weapon_barney9mmar";
|
||||
}
|
||||
|
||||
DropItem( pszWeapon, vecGunPos, vecGunAngles );
|
||||
|
||||
if( FBitSet( pev->weapons, HGRUNT_GRENADELAUNCHER ) )
|
||||
{
|
||||
DropItem( "ammo_ARgrenades", BodyTarget( pev->origin ), vecGunAngles );
|
||||
|
@ -892,7 +876,7 @@ void CHGrunt::HandleAnimEvent( MonsterEvent_t *pEvent )
|
|||
case HGRUNT_AE_GREN_LAUNCH:
|
||||
{
|
||||
EMIT_SOUND( ENT( pev ), CHAN_WEAPON, "weapons/glauncher.wav", 0.8, ATTN_NORM );
|
||||
CGrenade::ShootContact( pev, GetGunPosition(), m_vecTossVelocity );
|
||||
CGrenade::ShootContact( pev, GetGunPosition(), m_vecTossVelocity, gSkillData.plrDmgM203Grenade );
|
||||
m_fThrowGrenade = FALSE;
|
||||
if( g_iSkillLevel == SKILL_HARD )
|
||||
m_flNextGrenadeCheck = gpGlobals->time + RANDOM_FLOAT( 2, 5 );// wait a random amount of time before shooting again
|
||||
|
@ -943,6 +927,7 @@ void CHGrunt::HandleAnimEvent( MonsterEvent_t *pEvent )
|
|||
if( pHurt )
|
||||
{
|
||||
// SOUND HERE!
|
||||
EMIT_SOUND( ENT(pev), CHAN_WEAPON, "common/kick.wav", 1, ATTN_NORM );
|
||||
UTIL_MakeVectors( pev->angles );
|
||||
pHurt->pev->punchangle.x = 15;
|
||||
pHurt->pev->velocity = pHurt->pev->velocity + gpGlobals->v_forward * 100 + gpGlobals->v_up * 50;
|
||||
|
@ -1061,6 +1046,8 @@ void CHGrunt::Precache()
|
|||
|
||||
PRECACHE_SOUND( "zombie/claw_miss2.wav" );// because we use the basemonster SWIPE animation event
|
||||
|
||||
PRECACHE_SOUND( "common/kick.wav" );
|
||||
|
||||
// get voice pitch
|
||||
if( RANDOM_LONG( 0, 1 ) )
|
||||
m_voicePitch = 109 + RANDOM_LONG( 0, 7 );
|
||||
|
@ -1801,7 +1788,6 @@ Schedule_t slGruntRepelLand[] =
|
|||
},
|
||||
};
|
||||
|
||||
|
||||
DEFINE_CUSTOM_SCHEDULES( CHGrunt )
|
||||
{
|
||||
slGruntFail,
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
/***
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
****/
|
||||
//=========================================================
|
||||
// hgrunt
|
||||
//=========================================================
|
||||
|
||||
typedef enum
|
||||
{
|
||||
HGRUNT_SENT_NONE = -1,
|
||||
HGRUNT_SENT_GREN = 0,
|
||||
HGRUNT_SENT_ALERT,
|
||||
HGRUNT_SENT_MONSTER,
|
||||
HGRUNT_SENT_COVER,
|
||||
HGRUNT_SENT_THROW,
|
||||
HGRUNT_SENT_CHARGE,
|
||||
HGRUNT_SENT_TAUNT
|
||||
} HGRUNT_SENTENCE_TYPES;
|
||||
|
||||
class CHGrunt : public CSquadMonster
|
||||
{
|
||||
public:
|
||||
virtual void Spawn( void );
|
||||
virtual void Precache( void );
|
||||
void SetYawSpeed( void );
|
||||
int Classify( void );
|
||||
int ISoundMask( void );
|
||||
virtual 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 );
|
||||
virtual void IdleSound( void );
|
||||
Vector GetGunPosition( void );
|
||||
virtual void Shoot( void );
|
||||
virtual void Shotgun( void );
|
||||
void PrescheduleThink( void );
|
||||
virtual void GibMonster( void );
|
||||
virtual void SpeakSentence( void );
|
||||
|
||||
int Save( CSave &save );
|
||||
int Restore( CRestore &restore );
|
||||
|
||||
CBaseEntity *Kick( void );
|
||||
virtual Schedule_t *GetSchedule( void );
|
||||
virtual Schedule_t *GetScheduleOfType( int Type );
|
||||
void TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType);
|
||||
virtual int TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType );
|
||||
|
||||
virtual int IRelationship( CBaseEntity *pTarget );
|
||||
|
||||
BOOL FOkToSpeak( void );
|
||||
void JustSpoke( void );
|
||||
BOOL IsNotProvoked();
|
||||
void Provoke();
|
||||
|
||||
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[];
|
||||
};
|
|
@ -99,6 +99,19 @@ void CHornet::Spawn( void )
|
|||
if( !pSoundEnt )
|
||||
pSoundEnt = edict();
|
||||
|
||||
switch( RANDOM_LONG( 0, 2 ) )
|
||||
{
|
||||
case 0:
|
||||
EMIT_SOUND( pSoundEnt, CHAN_WEAPON, "agrunt/ag_fire1.wav", 1, ATTN_NORM );
|
||||
break;
|
||||
case 1:
|
||||
EMIT_SOUND( pSoundEnt, CHAN_WEAPON, "agrunt/ag_fire2.wav", 1, ATTN_NORM );
|
||||
break;
|
||||
case 2:
|
||||
EMIT_SOUND( pSoundEnt, CHAN_WEAPON, "agrunt/ag_fire3.wav", 1, ATTN_NORM );
|
||||
break;
|
||||
}
|
||||
|
||||
if( !FNullEnt( pev->owner ) && ( pev->owner->v.flags & FL_CLIENT ) )
|
||||
{
|
||||
pev->dmg = gSkillData.plrDmgHornet;
|
||||
|
|
|
@ -65,8 +65,6 @@ void CHgun::Precache( void )
|
|||
PRECACHE_MODEL( "models/w_hgun.mdl" );
|
||||
PRECACHE_MODEL( "models/p_hgun.mdl" );
|
||||
|
||||
m_usHornetFire = PRECACHE_EVENT( 1, "events/firehornet.sc" );
|
||||
|
||||
UTIL_PrecacheOther( "hornet" );
|
||||
}
|
||||
|
||||
|
@ -113,8 +111,7 @@ BOOL CHgun::Deploy()
|
|||
|
||||
void CHgun::Holster( int skiplocal /* = 0 */ )
|
||||
{
|
||||
m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.5;
|
||||
SendWeaponAnim( HGUN_DOWN );
|
||||
DefaultHolster( HGUN_DOWN, 1.3 );
|
||||
|
||||
//!!!HACKHACK - can't select hornetgun if it's empty! no way to get ammo for it, either.
|
||||
if( !m_pPlayer->m_rgAmmo[PrimaryAmmoIndex()] )
|
||||
|
@ -125,6 +122,11 @@ void CHgun::Holster( int skiplocal /* = 0 */ )
|
|||
|
||||
void CHgun::PrimaryAttack()
|
||||
{
|
||||
if( m_pPlayer->m_bIsHolster )
|
||||
{
|
||||
WeaponIdle();
|
||||
return;
|
||||
}
|
||||
Reload();
|
||||
|
||||
if(m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0)
|
||||
|
@ -144,13 +146,7 @@ void CHgun::PrimaryAttack()
|
|||
m_pPlayer->m_iWeaponVolume = QUIET_GUN_VOLUME;
|
||||
m_pPlayer->m_iWeaponFlash = DIM_GUN_FLASH;
|
||||
|
||||
int flags;
|
||||
#if defined( CLIENT_WEAPONS )
|
||||
flags = FEV_NOTHOST;
|
||||
#else
|
||||
flags = 0;
|
||||
#endif
|
||||
PLAYBACK_EVENT_FULL( flags, m_pPlayer->edict(), m_usHornetFire, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, FIREMODE_TRACK, 0, 0, 0 );
|
||||
SendWeaponAnim( HGUN_SHOOT );
|
||||
|
||||
// player "shoot" animation
|
||||
m_pPlayer->SetAnimation( PLAYER_ATTACK1 );
|
||||
|
@ -167,6 +163,11 @@ void CHgun::PrimaryAttack()
|
|||
|
||||
void CHgun::SecondaryAttack( void )
|
||||
{
|
||||
if( m_pPlayer->m_bIsHolster )
|
||||
{
|
||||
WeaponIdle();
|
||||
return;
|
||||
}
|
||||
Reload();
|
||||
|
||||
if( m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0 )
|
||||
|
@ -175,7 +176,6 @@ void CHgun::SecondaryAttack( void )
|
|||
}
|
||||
|
||||
//Wouldn't be a bad idea to completely predict these, since they fly so fast...
|
||||
#ifndef CLIENT_DLL
|
||||
CBaseEntity *pHornet;
|
||||
Vector vecSrc;
|
||||
|
||||
|
@ -223,29 +223,30 @@ void CHgun::SecondaryAttack( void )
|
|||
|
||||
pHornet->SetThink( &CHornet::StartDart );
|
||||
|
||||
m_flRechargeTime = gpGlobals->time + 0.5;
|
||||
#endif
|
||||
int flags;
|
||||
#if defined( CLIENT_WEAPONS )
|
||||
flags = FEV_NOTHOST;
|
||||
#else
|
||||
flags = 0;
|
||||
#endif
|
||||
PLAYBACK_EVENT_FULL( flags, m_pPlayer->edict(), m_usHornetFire, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, FIREMODE_FAST, 0, 0, 0 );
|
||||
|
||||
m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]--;
|
||||
m_pPlayer->m_iWeaponVolume = NORMAL_GUN_VOLUME;
|
||||
m_pPlayer->m_iWeaponFlash = DIM_GUN_FLASH;
|
||||
|
||||
m_flRechargeTime = gpGlobals->time + 0.5;
|
||||
|
||||
SendWeaponAnim( HGUN_SHOOT );
|
||||
|
||||
// player "shoot" animation
|
||||
m_pPlayer->SetAnimation( PLAYER_ATTACK1 );
|
||||
|
||||
m_flNextPrimaryAttack = m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.1;
|
||||
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + UTIL_SharedRandomFloat( m_pPlayer->random_seed, 10, 15 );
|
||||
m_pPlayer->pev->punchangle.x = RANDOM_FLOAT( 0, 2 );
|
||||
}
|
||||
|
||||
void CHgun::Reload( void )
|
||||
{
|
||||
if( m_pPlayer->m_bIsHolster )
|
||||
{
|
||||
WeaponIdle();
|
||||
return;
|
||||
}
|
||||
|
||||
if( m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] >= HORNET_MAX_CARRY )
|
||||
return;
|
||||
|
||||
|
@ -258,6 +259,16 @@ void CHgun::Reload( void )
|
|||
|
||||
void CHgun::WeaponIdle( void )
|
||||
{
|
||||
if( m_pPlayer->m_bIsHolster )
|
||||
{
|
||||
if( m_flTimeWeaponIdle <= UTIL_WeaponTimeBase() )
|
||||
{
|
||||
m_pPlayer->m_bIsHolster = FALSE;
|
||||
Deploy();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
Reload();
|
||||
|
||||
if( m_flTimeWeaponIdle > UTIL_WeaponTimeBase() )
|
||||
|
|
|
@ -29,97 +29,7 @@
|
|||
#include "animation.h"
|
||||
#include "effects.h"
|
||||
#include "weapons.h"
|
||||
|
||||
#define SEARCH_RETRY 16
|
||||
|
||||
#define ICHTHYOSAUR_SPEED 150
|
||||
|
||||
extern CGraph WorldGraph;
|
||||
|
||||
#define EYE_MAD 0
|
||||
#define EYE_BASE 1
|
||||
#define EYE_CLOSED 2
|
||||
#define EYE_BACK 3
|
||||
#define EYE_LOOK 4
|
||||
|
||||
//=========================================================
|
||||
// Monster's Anim Events Go Here
|
||||
//=========================================================
|
||||
|
||||
// UNDONE: Save/restore here
|
||||
class CIchthyosaur : public CFlyingMonster
|
||||
{
|
||||
public:
|
||||
void Spawn( void );
|
||||
void Precache( void );
|
||||
void SetYawSpeed( void );
|
||||
int Classify( void );
|
||||
void HandleAnimEvent( MonsterEvent_t *pEvent );
|
||||
CUSTOM_SCHEDULES
|
||||
|
||||
int Save( CSave &save );
|
||||
int Restore( CRestore &restore );
|
||||
static TYPEDESCRIPTION m_SaveData[];
|
||||
|
||||
Schedule_t *GetSchedule( void );
|
||||
Schedule_t *GetScheduleOfType ( int Type );
|
||||
|
||||
void Killed( entvars_t *pevAttacker, int iGib );
|
||||
void BecomeDead( void );
|
||||
|
||||
void EXPORT CombatUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
|
||||
void EXPORT BiteTouch( CBaseEntity *pOther );
|
||||
|
||||
void StartTask( Task_t *pTask );
|
||||
void RunTask( Task_t *pTask );
|
||||
|
||||
BOOL CheckMeleeAttack1( float flDot, float flDist );
|
||||
BOOL CheckRangeAttack1( float flDot, float flDist );
|
||||
|
||||
float ChangeYaw( int speed );
|
||||
Activity GetStoppedActivity( void );
|
||||
|
||||
void Move( float flInterval );
|
||||
void MoveExecute( CBaseEntity *pTargetEnt, const Vector &vecDir, float flInterval );
|
||||
void MonsterThink( void );
|
||||
void Stop( void );
|
||||
void Swim( void );
|
||||
Vector DoProbe(const Vector &Probe );
|
||||
|
||||
float VectorToPitch( const Vector &vec );
|
||||
float FlPitchDiff( void );
|
||||
float ChangePitch( int speed );
|
||||
|
||||
Vector m_SaveVelocity;
|
||||
float m_idealDist;
|
||||
|
||||
float m_flBlink;
|
||||
|
||||
float m_flEnemyTouched;
|
||||
BOOL m_bOnAttack;
|
||||
|
||||
float m_flMaxSpeed;
|
||||
float m_flMinSpeed;
|
||||
float m_flMaxDist;
|
||||
|
||||
CBeam *m_pBeam;
|
||||
|
||||
float m_flNextAlert;
|
||||
|
||||
static const char *pIdleSounds[];
|
||||
static const char *pAlertSounds[];
|
||||
static const char *pAttackSounds[];
|
||||
static const char *pBiteSounds[];
|
||||
static const char *pDieSounds[];
|
||||
static const char *pPainSounds[];
|
||||
|
||||
void IdleSound( void );
|
||||
void AlertSound( void );
|
||||
void AttackSound( void );
|
||||
void BiteSound( void );
|
||||
void DeathSound( void );
|
||||
void PainSound( void );
|
||||
};
|
||||
#include "ichthyosaur.h"
|
||||
|
||||
LINK_ENTITY_TO_CLASS( monster_ichthyosaur, CIchthyosaur )
|
||||
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
/***
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
****/
|
||||
//=========================================================
|
||||
// icthyosaur - evin, satan fish monster
|
||||
//=========================================================
|
||||
|
||||
#define SEARCH_RETRY 16
|
||||
|
||||
#define ICHTHYOSAUR_SPEED 150
|
||||
|
||||
extern CGraph WorldGraph;
|
||||
|
||||
#define EYE_MAD 0
|
||||
#define EYE_BASE 1
|
||||
#define EYE_CLOSED 2
|
||||
#define EYE_BACK 3
|
||||
#define EYE_LOOK 4
|
||||
|
||||
//=========================================================
|
||||
// Monster's Anim Events Go Here
|
||||
//=========================================================
|
||||
|
||||
// UNDONE: Save/restore here
|
||||
class CIchthyosaur : public CFlyingMonster
|
||||
{
|
||||
public:
|
||||
virtual void Spawn( void );
|
||||
virtual void Precache( void );
|
||||
void SetYawSpeed( void );
|
||||
int Classify( void );
|
||||
virtual void HandleAnimEvent( MonsterEvent_t *pEvent );
|
||||
CUSTOM_SCHEDULES
|
||||
|
||||
int Save( CSave &save );
|
||||
int Restore( CRestore &restore );
|
||||
static TYPEDESCRIPTION m_SaveData[];
|
||||
|
||||
virtual Schedule_t *GetSchedule( void );
|
||||
Schedule_t *GetScheduleOfType ( int Type );
|
||||
|
||||
void Killed( entvars_t *pevAttacker, int iGib );
|
||||
void BecomeDead( void );
|
||||
|
||||
void EXPORT CombatUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
|
||||
void EXPORT BiteTouch( CBaseEntity *pOther );
|
||||
|
||||
virtual void StartTask( Task_t *pTask );
|
||||
void RunTask( Task_t *pTask );
|
||||
|
||||
BOOL CheckMeleeAttack1( float flDot, float flDist );
|
||||
BOOL CheckRangeAttack1( float flDot, float flDist );
|
||||
|
||||
float ChangeYaw( int speed );
|
||||
Activity GetStoppedActivity( void );
|
||||
|
||||
void Move( float flInterval );
|
||||
void MoveExecute( CBaseEntity *pTargetEnt, const Vector &vecDir, float flInterval );
|
||||
virtual void MonsterThink( void );
|
||||
virtual void Stop( void );
|
||||
virtual void Swim( void );
|
||||
Vector DoProbe(const Vector &Probe );
|
||||
|
||||
float VectorToPitch( const Vector &vec );
|
||||
float FlPitchDiff( void );
|
||||
float ChangePitch( int speed );
|
||||
|
||||
Vector m_SaveVelocity;
|
||||
float m_idealDist;
|
||||
|
||||
float m_flBlink;
|
||||
|
||||
float m_flEnemyTouched;
|
||||
BOOL m_bOnAttack;
|
||||
|
||||
float m_flMaxSpeed;
|
||||
float m_flMinSpeed;
|
||||
float m_flMaxDist;
|
||||
|
||||
CBeam *m_pBeam;
|
||||
|
||||
float m_flNextAlert;
|
||||
|
||||
static const char *pIdleSounds[];
|
||||
static const char *pAlertSounds[];
|
||||
static const char *pAttackSounds[];
|
||||
static const char *pBiteSounds[];
|
||||
static const char *pDieSounds[];
|
||||
static const char *pPainSounds[];
|
||||
|
||||
virtual void IdleSound( void );
|
||||
virtual void AlertSound( void );
|
||||
virtual void AttackSound( void );
|
||||
virtual void BiteSound( void );
|
||||
virtual void DeathSound( void );
|
||||
virtual void PainSound( void );
|
||||
};
|
128
dlls/islave.cpp
128
dlls/islave.cpp
|
@ -25,75 +25,7 @@
|
|||
#include "effects.h"
|
||||
#include "weapons.h"
|
||||
#include "soundent.h"
|
||||
|
||||
extern DLL_GLOBAL int g_iSkillLevel;
|
||||
|
||||
//=========================================================
|
||||
// Monster's Anim Events Go Here
|
||||
//=========================================================
|
||||
#define ISLAVE_AE_CLAW ( 1 )
|
||||
#define ISLAVE_AE_CLAWRAKE ( 2 )
|
||||
#define ISLAVE_AE_ZAP_POWERUP ( 3 )
|
||||
#define ISLAVE_AE_ZAP_SHOOT ( 4 )
|
||||
#define ISLAVE_AE_ZAP_DONE ( 5 )
|
||||
|
||||
#define ISLAVE_MAX_BEAMS 8
|
||||
|
||||
class CISlave : public CSquadMonster
|
||||
{
|
||||
public:
|
||||
void Spawn( void );
|
||||
void Precache( void );
|
||||
void UpdateOnRemove();
|
||||
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( const 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[];
|
||||
};
|
||||
#include "islave.h"
|
||||
|
||||
LINK_ENTITY_TO_CLASS( monster_alien_slave, CISlave )
|
||||
LINK_ENTITY_TO_CLASS( monster_exp_alien_slave, CISlave )//new Azure Sheep vortigaunt
|
||||
|
@ -191,7 +123,7 @@ void CISlave::AlertSound( void )
|
|||
{
|
||||
SENTENCEG_PlayRndSz( ENT( pev ), "SLV_ALERT", 0.85, ATTN_NORM, 0, m_voicePitch );
|
||||
|
||||
CallForHelp( "monster_alien_slave", 512, m_hEnemy, m_vecEnemyLKP );
|
||||
CallForHelp( STRING( pev->classname ), 512, m_hEnemy, m_vecEnemyLKP );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -353,16 +285,23 @@ void CISlave::HandleAnimEvent( MonsterEvent_t *pEvent )
|
|||
|
||||
if( m_iBeams == 0 )
|
||||
{
|
||||
int r, g, b;
|
||||
Vector vecSrc = pev->origin + gpGlobals->v_forward * 2;
|
||||
|
||||
if( FClassnameIs( pev, "monster_exp_alien_slave" ) )
|
||||
r = 255, g = 128, b = 255;
|
||||
else
|
||||
r = 255, g = 180, b = 96;
|
||||
|
||||
MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, vecSrc );
|
||||
WRITE_BYTE( TE_DLIGHT );
|
||||
WRITE_COORD( vecSrc.x ); // X
|
||||
WRITE_COORD( vecSrc.y ); // Y
|
||||
WRITE_COORD( vecSrc.z ); // Z
|
||||
WRITE_BYTE( 12 ); // radius * 0.1
|
||||
WRITE_BYTE( 255 ); // r
|
||||
WRITE_BYTE( 180 ); // g
|
||||
WRITE_BYTE( 96 ); // b
|
||||
WRITE_BYTE( r ); // r
|
||||
WRITE_BYTE( g ); // g
|
||||
WRITE_BYTE( b ); // b
|
||||
WRITE_BYTE( 20 / pev->framerate ); // time * 10
|
||||
WRITE_BYTE( 0 ); // decay * 0.1
|
||||
MESSAGE_END();
|
||||
|
@ -395,7 +334,7 @@ void CISlave::HandleAnimEvent( MonsterEvent_t *pEvent )
|
|||
|
||||
if( !trace.fStartSolid )
|
||||
{
|
||||
CBaseEntity *pNew = Create( "monster_alien_slave", m_hDead->pev->origin, m_hDead->pev->angles );
|
||||
CBaseEntity *pNew = Create( STRING( pev->classname ), m_hDead->pev->origin, m_hDead->pev->angles );
|
||||
//CBaseMonster *pNewMonster = pNew->MyMonsterPointer();
|
||||
pNew->pev->spawnflags |= 1;
|
||||
WackBeam( -1, pNew );
|
||||
|
@ -463,7 +402,7 @@ BOOL CISlave::CheckRangeAttack2( float flDot, float flDist )
|
|||
m_iBravery = 0;
|
||||
|
||||
CBaseEntity *pEntity = NULL;
|
||||
while( ( pEntity = UTIL_FindEntityByClassname( pEntity, "monster_alien_slave" ) ) != NULL )
|
||||
while( ( pEntity = UTIL_FindEntityByClassname( pEntity, STRING( pev->classname ) ) ) != NULL )
|
||||
{
|
||||
TraceResult tr;
|
||||
|
||||
|
@ -510,15 +449,21 @@ void CISlave::Spawn()
|
|||
Precache();
|
||||
|
||||
if( FClassnameIs( pev, "monster_exp_alien_slave" ) )
|
||||
{
|
||||
SET_MODEL( ENT( pev ), "models/sslave.mdl" );
|
||||
m_bloodColor = BLOOD_COLOR_RED;
|
||||
m_voicePitch = RANDOM_LONG( 110, 120 );
|
||||
}
|
||||
else
|
||||
{
|
||||
SET_MODEL( ENT( pev ), "models/islave.mdl" );
|
||||
|
||||
m_bloodColor = BLOOD_COLOR_GREEN;
|
||||
m_voicePitch = RANDOM_LONG( 85, 110 );
|
||||
}
|
||||
UTIL_SetSize( pev, VEC_HUMAN_HULL_MIN, VEC_HUMAN_HULL_MAX );
|
||||
|
||||
pev->solid = SOLID_SLIDEBOX;
|
||||
pev->movetype = MOVETYPE_STEP;
|
||||
m_bloodColor = BLOOD_COLOR_GREEN;
|
||||
pev->effects = 0;
|
||||
pev->health = gSkillData.slaveHealth;
|
||||
pev->view_ofs = Vector( 0, 0, 64 );// position of the eyes relative to monster's origin.
|
||||
|
@ -526,8 +471,6 @@ void CISlave::Spawn()
|
|||
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();
|
||||
}
|
||||
|
||||
|
@ -708,6 +651,7 @@ Schedule_t *CISlave::GetScheduleOfType( int Type )
|
|||
void CISlave::ArmBeam( int side )
|
||||
{
|
||||
TraceResult tr;
|
||||
int r, g, b;
|
||||
float flDist = 1.0;
|
||||
|
||||
if( m_iBeams >= ISLAVE_MAX_BEAMS )
|
||||
|
@ -741,7 +685,13 @@ void CISlave::ArmBeam( int side )
|
|||
m_pBeam[m_iBeams]->PointEntInit( tr.vecEndPos, entindex() );
|
||||
m_pBeam[m_iBeams]->SetEndAttachment( side < 0 ? 2 : 1 );
|
||||
// m_pBeam[m_iBeams]->SetColor( 180, 255, 96 );
|
||||
m_pBeam[m_iBeams]->SetColor( 96, 128, 16 );
|
||||
|
||||
if( FClassnameIs( pev, "monster_exp_alien_slave" ) )
|
||||
r = 255, g = 128, b = 255;
|
||||
else
|
||||
r = 96, g = 128, b = 16;
|
||||
|
||||
m_pBeam[m_iBeams]->SetColor( r, g, b );
|
||||
m_pBeam[m_iBeams]->SetBrightness( 64 );
|
||||
m_pBeam[m_iBeams]->SetNoise( 80 );
|
||||
m_iBeams++;
|
||||
|
@ -772,6 +722,7 @@ void CISlave::WackBeam( int side, CBaseEntity *pEntity )
|
|||
{
|
||||
//Vector vecDest;
|
||||
//float flDist = 1.0;
|
||||
int r, g, b;
|
||||
|
||||
if( m_iBeams >= ISLAVE_MAX_BEAMS )
|
||||
return;
|
||||
|
@ -785,7 +736,13 @@ void CISlave::WackBeam( int side, CBaseEntity *pEntity )
|
|||
|
||||
m_pBeam[m_iBeams]->PointEntInit( pEntity->Center(), entindex() );
|
||||
m_pBeam[m_iBeams]->SetEndAttachment( side < 0 ? 2 : 1 );
|
||||
m_pBeam[m_iBeams]->SetColor( 180, 255, 96 );
|
||||
|
||||
if( FClassnameIs( pev, "monster_exp_alien_slave" ) )
|
||||
r = 255, g = 128, b = 255;
|
||||
else
|
||||
r = 180, g = 255, b = 96;
|
||||
|
||||
m_pBeam[m_iBeams]->SetColor( r, g, b );
|
||||
m_pBeam[m_iBeams]->SetBrightness( 255 );
|
||||
m_pBeam[m_iBeams]->SetNoise( 80 );
|
||||
m_iBeams++;
|
||||
|
@ -797,6 +754,7 @@ void CISlave::WackBeam( int side, CBaseEntity *pEntity )
|
|||
void CISlave::ZapBeam( int side )
|
||||
{
|
||||
Vector vecSrc, vecAim;
|
||||
int r, g, b;
|
||||
TraceResult tr;
|
||||
CBaseEntity *pEntity;
|
||||
|
||||
|
@ -815,7 +773,13 @@ void CISlave::ZapBeam( int side )
|
|||
|
||||
m_pBeam[m_iBeams]->PointEntInit( tr.vecEndPos, entindex() );
|
||||
m_pBeam[m_iBeams]->SetEndAttachment( side < 0 ? 2 : 1 );
|
||||
m_pBeam[m_iBeams]->SetColor( 180, 255, 96 );
|
||||
|
||||
if( FClassnameIs( pev, "monster_exp_alien_slave" ) )
|
||||
r = 255, g = 128, b = 255;
|
||||
else
|
||||
r = 180, g = 255, b = 96;
|
||||
|
||||
m_pBeam[m_iBeams]->SetColor( r, g, b );
|
||||
m_pBeam[m_iBeams]->SetBrightness( 255 );
|
||||
m_pBeam[m_iBeams]->SetNoise( 20 );
|
||||
m_iBeams++;
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
/***
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
****/
|
||||
//=========================================================
|
||||
// Alien slave monster
|
||||
//=========================================================
|
||||
#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"
|
||||
|
||||
extern DLL_GLOBAL int g_iSkillLevel;
|
||||
|
||||
//=========================================================
|
||||
// Monster's Anim Events Go Here
|
||||
//=========================================================
|
||||
#define ISLAVE_AE_CLAW ( 1 )
|
||||
#define ISLAVE_AE_CLAWRAKE ( 2 )
|
||||
#define ISLAVE_AE_ZAP_POWERUP ( 3 )
|
||||
#define ISLAVE_AE_ZAP_SHOOT ( 4 )
|
||||
#define ISLAVE_AE_ZAP_DONE ( 5 )
|
||||
|
||||
#define ISLAVE_MAX_BEAMS 8
|
||||
|
||||
class CISlave : public CSquadMonster
|
||||
{
|
||||
public:
|
||||
void Spawn( void );
|
||||
void Precache( void );
|
||||
void UpdateOnRemove();
|
||||
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( const 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[];
|
||||
|
||||
virtual void ClearBeams();
|
||||
virtual void ArmBeam( int side );
|
||||
virtual 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[];
|
||||
};
|
|
@ -174,7 +174,40 @@ void CItem::Materialize( void )
|
|||
class CItemSuit : public CItem
|
||||
{
|
||||
void Spawn( void )
|
||||
{
|
||||
{
|
||||
Precache();
|
||||
SET_MODEL( ENT( pev ), "models/w_blue_suit.mdl" );
|
||||
CItem::Spawn();
|
||||
}
|
||||
void Precache( void )
|
||||
{
|
||||
PRECACHE_MODEL( "models/w_blue_suit.mdl" );
|
||||
}
|
||||
BOOL MyTouch( CBasePlayer *pPlayer )
|
||||
{
|
||||
if( !FBitSet( pPlayer->pev->weapons, 1 << WEAPON_SUIT ) )
|
||||
pPlayer->pev->weapons |= ( 1 << WEAPON_SUIT );
|
||||
|
||||
pPlayer->m_bHaveSuit = TRUE;
|
||||
|
||||
if( gEvilImpulse101 )
|
||||
return TRUE;
|
||||
|
||||
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
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS( item_suit, CItemSuit )
|
||||
|
||||
class CItemArmor : public CItem
|
||||
{
|
||||
void Spawn( void )
|
||||
{
|
||||
Precache();
|
||||
SET_MODEL( ENT( pev ), "models/w_suit.mdl" );
|
||||
CItem::Spawn();
|
||||
|
@ -182,25 +215,24 @@ class CItemSuit : public CItem
|
|||
void Precache( void )
|
||||
{
|
||||
PRECACHE_MODEL( "models/w_suit.mdl" );
|
||||
PRECACHE_SOUND( "armor/pickup.wav" );
|
||||
}
|
||||
BOOL MyTouch( CBasePlayer *pPlayer )
|
||||
{
|
||||
if( pPlayer->pev->weapons & ( 1<<WEAPON_SUIT ) )
|
||||
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
|
||||
EMIT_SOUND( pPlayer->edict(), CHAN_ITEM, "armor/pickup.wav", 1, ATTN_NORM );
|
||||
|
||||
pPlayer->pev->armorvalue += gSkillData.batteryCapacity;
|
||||
pPlayer->pev->armorvalue = Q_min( pPlayer->pev->armorvalue, MAX_NORMAL_BATTERY );
|
||||
|
||||
pPlayer->pev->weapons |= ( 1 << WEAPON_SUIT );
|
||||
return TRUE;
|
||||
}
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS( item_suit, CItemSuit )
|
||||
//begin Alex
|
||||
LINK_ENTITY_TO_CLASS( item_armor, CItemSuit ) // for Azure Sheep
|
||||
LINK_ENTITY_TO_CLASS( item_armor, CItemArmor ) // for Azure Sheep
|
||||
//end Alex
|
||||
|
||||
class CItemBattery : public CItem
|
||||
|
@ -215,6 +247,7 @@ class CItemBattery : public CItem
|
|||
{
|
||||
PRECACHE_MODEL( "models/w_battery.mdl" );
|
||||
PRECACHE_SOUND( "items/gunpickup2.wav" );
|
||||
PRECACHE_SOUND( "barney/nope.wav" );
|
||||
}
|
||||
BOOL MyTouch( CBasePlayer *pPlayer )
|
||||
{
|
||||
|
@ -224,7 +257,7 @@ class CItemBattery : public CItem
|
|||
}
|
||||
|
||||
if( ( pPlayer->pev->armorvalue < MAX_NORMAL_BATTERY ) &&
|
||||
( pPlayer->pev->weapons & ( 1 << WEAPON_SUIT ) ) )
|
||||
( pPlayer->pev->weapons & ( 1 << WEAPON_SUIT ) ) && pPlayer->m_bHaveSuit )
|
||||
{
|
||||
int pct;
|
||||
char szcharge[64];
|
||||
|
@ -238,6 +271,9 @@ class CItemBattery : public CItem
|
|||
WRITE_STRING( STRING( pev->classname ) );
|
||||
MESSAGE_END();
|
||||
|
||||
if( gEvilImpulse101 )
|
||||
return TRUE;
|
||||
|
||||
// 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 );
|
||||
|
@ -251,8 +287,15 @@ class CItemBattery : public CItem
|
|||
pPlayer->SetSuitUpdate( szcharge, FALSE, SUIT_NEXT_IN_30SEC);
|
||||
return TRUE;
|
||||
}
|
||||
else if( NextMessageTime < gpGlobals->time && !pPlayer->m_bHaveSuit )
|
||||
{
|
||||
EMIT_SOUND( pPlayer->edict(), CHAN_ITEM, "barney/nope.wav", 1, ATTN_NORM );
|
||||
UTIL_ShowMessageAll( "NOHEVBATTERY" );
|
||||
NextMessageTime < gpGlobals->time + 4.0;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
float NextMessageTime;
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS( item_battery, CItemBattery )
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#define SF_MONSTERMAKER_START_ON 1 // start active ( if has targetname )
|
||||
#define SF_MONSTERMAKER_CYCLIC 4 // drop one monster every time fired.
|
||||
#define SF_MONSTERMAKER_MONSTERCLIP 8 // Children are blocked by monsterclip
|
||||
#define SF_MONSTERMAKER_WARPBALL 16 // Children are made by warpball
|
||||
|
||||
//=========================================================
|
||||
// MonsterMaker - this ent creates monsters during the game.
|
||||
|
@ -51,7 +52,7 @@ public:
|
|||
string_t m_iszMonsterClassname;// classname of the monster(s) that will be created.
|
||||
|
||||
int m_cNumMonsters;// max number of monsters this ent can create
|
||||
|
||||
|
||||
int m_cLiveChildren;// how many monsters made by this monster maker that are currently alive
|
||||
int m_iMaxLiveChildren;// max number of monsters that this maker may have out at one time.
|
||||
|
||||
|
@ -59,6 +60,12 @@ public:
|
|||
|
||||
BOOL m_fActive;
|
||||
BOOL m_fFadeChildren;// should we make the children fadeout?
|
||||
|
||||
int m_iSpawnType;
|
||||
int m_iBeamCount;
|
||||
float m_flSpriteScale;
|
||||
float m_flSpawnSoundRad;
|
||||
float m_flSpawnVol;
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS( monstermaker, CMonsterMaker )
|
||||
|
@ -72,6 +79,11 @@ TYPEDESCRIPTION CMonsterMaker::m_SaveData[] =
|
|||
DEFINE_FIELD( CMonsterMaker, m_iMaxLiveChildren, FIELD_INTEGER ),
|
||||
DEFINE_FIELD( CMonsterMaker, m_fActive, FIELD_BOOLEAN ),
|
||||
DEFINE_FIELD( CMonsterMaker, m_fFadeChildren, FIELD_BOOLEAN ),
|
||||
DEFINE_FIELD( CMonsterMaker, m_iSpawnType, FIELD_INTEGER ),
|
||||
DEFINE_FIELD( CMonsterMaker, m_iBeamCount, FIELD_INTEGER ),
|
||||
DEFINE_FIELD( CMonsterMaker, m_flSpriteScale, FIELD_FLOAT ),
|
||||
DEFINE_FIELD( CMonsterMaker, m_flSpawnSoundRad, FIELD_FLOAT ),
|
||||
DEFINE_FIELD( CMonsterMaker, m_flSpawnVol, FIELD_FLOAT ),
|
||||
};
|
||||
|
||||
IMPLEMENT_SAVERESTORE( CMonsterMaker, CBaseMonster )
|
||||
|
@ -93,7 +105,45 @@ void CMonsterMaker::KeyValue( KeyValueData *pkvd )
|
|||
m_iszMonsterClassname = ALLOC_STRING( pkvd->szValue );
|
||||
pkvd->fHandled = TRUE;
|
||||
}
|
||||
else
|
||||
else if( FStrEq( pkvd->szKeyName, "spawntype" ) )
|
||||
{
|
||||
m_iSpawnType = atoi( pkvd->szValue );
|
||||
pkvd->fHandled = TRUE;
|
||||
}
|
||||
else if( FStrEq( pkvd->szKeyName, "beamcount" ) )
|
||||
{
|
||||
m_iBeamCount = atoi( pkvd->szValue );
|
||||
pkvd->fHandled = TRUE;
|
||||
}
|
||||
else if( FStrEq( pkvd->szKeyName, "spritescale" ) )
|
||||
{
|
||||
m_flSpriteScale = atof( pkvd->szValue );
|
||||
pkvd->fHandled = TRUE;
|
||||
}
|
||||
else if( FStrEq( pkvd->szKeyName, "spawnsoundrad" ) )
|
||||
{
|
||||
switch( atoi( pkvd->szValue ) )
|
||||
{
|
||||
case 3:
|
||||
m_flSpawnSoundRad = ATTN_NONE;
|
||||
break;
|
||||
case 2:
|
||||
m_flSpawnSoundRad = ATTN_NORM;
|
||||
break;
|
||||
case 1:
|
||||
m_flSpawnSoundRad = ATTN_IDLE;
|
||||
break;
|
||||
default:
|
||||
m_flSpawnSoundRad = ATTN_STATIC;
|
||||
break;
|
||||
}
|
||||
pkvd->fHandled = TRUE;
|
||||
}
|
||||
else if( FStrEq( pkvd->szKeyName, "spawnvol" ) )
|
||||
{
|
||||
m_flSpawnVol = atof( pkvd->szValue );
|
||||
pkvd->fHandled = TRUE;
|
||||
}
|
||||
CBaseMonster::KeyValue( pkvd );
|
||||
}
|
||||
|
||||
|
@ -149,6 +199,9 @@ void CMonsterMaker::Spawn()
|
|||
|
||||
void CMonsterMaker::Precache( void )
|
||||
{
|
||||
if( FBitSet( pev->spawnflags, SF_MONSTERMAKER_WARPBALL ) )
|
||||
UTIL_PrecacheOther( "env_spawnereffect" );
|
||||
|
||||
CBaseMonster::Precache();
|
||||
|
||||
UTIL_PrecacheOther( STRING( m_iszMonsterClassname ) );
|
||||
|
@ -208,6 +261,10 @@ void CMonsterMaker::MakeMonster( void )
|
|||
pevCreate = VARS( pent );
|
||||
pevCreate->origin = pev->origin;
|
||||
pevCreate->angles = pev->angles;
|
||||
|
||||
if( FBitSet( pev->spawnflags, SF_MONSTERMAKER_WARPBALL ) )
|
||||
pevCreate->origin.z -= 16;
|
||||
|
||||
SetBits( pevCreate->spawnflags, SF_MONSTER_FALL_TO_GROUND );
|
||||
|
||||
// Children hit monsterclip brushes
|
||||
|
@ -223,6 +280,22 @@ void CMonsterMaker::MakeMonster( void )
|
|||
pevCreate->targetname = pev->netname;
|
||||
}
|
||||
|
||||
if( FBitSet( pev->spawnflags, SF_MONSTERMAKER_WARPBALL ) )
|
||||
{
|
||||
int iLightRad;
|
||||
float height = ( pevCreate->absmax.z - pevCreate->absmin.z ) * 0.5f;
|
||||
|
||||
if( FClassnameIs( pevCreate, "monster_alien_slave" )
|
||||
|| FClassnameIs( pevCreate, "monster_exp_alien_slave" ) )
|
||||
iLightRad = 24;
|
||||
else if( FClassnameIs( pevCreate, "monster_alien_grunt" ))
|
||||
iLightRad = 32;
|
||||
else
|
||||
iLightRad = pevCreate->size.z / 3;
|
||||
|
||||
UTIL_CreateWarpball( ENT( pevCreate ), pevCreate->origin + Vector( 0, 0, height ), m_flSpawnVol, m_flSpawnSoundRad, m_iBeamCount, m_iSpawnType, m_flSpriteScale, iLightRad );
|
||||
}
|
||||
|
||||
m_cLiveChildren++;// count this monster
|
||||
m_cNumMonsters--;
|
||||
|
||||
|
|
|
@ -111,7 +111,7 @@ void CFuncMortarField::Precache( void )
|
|||
{
|
||||
PRECACHE_SOUND( "weapons/mortar.wav" );
|
||||
PRECACHE_SOUND( "weapons/mortarhit.wav" );
|
||||
PRECACHE_MODEL( "sprites/lgtning.spr" );
|
||||
//PRECACHE_MODEL( "sprites/lgtning.spr" );
|
||||
}
|
||||
|
||||
// If connected to a table, then use the table controllers, else hit where the trigger is.
|
||||
|
|
72
dlls/mp5.cpp
72
dlls/mp5.cpp
|
@ -32,12 +32,12 @@ enum mp5_e
|
|||
MP5_DEPLOY,
|
||||
MP5_FIRE1,
|
||||
MP5_FIRE2,
|
||||
MP5_FIRE3
|
||||
MP5_FIRE3,
|
||||
MP5_HOLSTER
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS( weapon_mp5, CMP5 )
|
||||
LINK_ENTITY_TO_CLASS( weapon_9mmAR, CMP5 )
|
||||
LINK_ENTITY_TO_CLASS( weapon_barney9mmar, CMP5 )
|
||||
|
||||
//=========================================================
|
||||
//=========================================================
|
||||
|
@ -48,7 +48,7 @@ int CMP5::SecondaryAmmoIndex( void )
|
|||
|
||||
void CMP5::Spawn()
|
||||
{
|
||||
pev->classname = MAKE_STRING( "weapon_barney9mmar" ); // hack to allow for old names
|
||||
pev->classname = MAKE_STRING( "weapon_9mmAR" ); // hack to allow for old names
|
||||
Precache();
|
||||
SET_MODEL( ENT( pev ), "models/w_9mmAR.mdl" );
|
||||
m_iId = WEAPON_MP5;
|
||||
|
@ -60,7 +60,7 @@ void CMP5::Spawn()
|
|||
|
||||
void CMP5::Precache( void )
|
||||
{
|
||||
PRECACHE_MODEL( "models/v_barney9mmar.mdl" );
|
||||
PRECACHE_MODEL( "models/v_9mmAR.mdl" );
|
||||
PRECACHE_MODEL( "models/w_9mmAR.mdl" );
|
||||
PRECACHE_MODEL( "models/p_9mmAR.mdl" );
|
||||
|
||||
|
@ -84,7 +84,7 @@ void CMP5::Precache( void )
|
|||
PRECACHE_SOUND( "weapons/357_cock1.wav" );
|
||||
|
||||
m_usMP5 = PRECACHE_EVENT( 1, "events/mp5.sc" );
|
||||
m_usMP52 = PRECACHE_EVENT( 1, "events/mp52.sc" );
|
||||
// m_usMP52 = PRECACHE_EVENT( 1, "events/mp52.sc" );
|
||||
}
|
||||
|
||||
int CMP5::GetItemInfo( ItemInfo *p )
|
||||
|
@ -118,23 +118,34 @@ int CMP5::AddToPlayer( CBasePlayer *pPlayer )
|
|||
|
||||
BOOL CMP5::Deploy()
|
||||
{
|
||||
return DefaultDeploy( "models/v_barney9mmAR.mdl", "models/p_9mmAR.mdl", MP5_DEPLOY, "mp5" );
|
||||
return DefaultDeploy( "models/v_9mmAR.mdl", "models/p_9mmAR.mdl", MP5_DEPLOY, "mp5" );
|
||||
}
|
||||
|
||||
void CMP5::Holster( int skiplocal /* = 0 */ )
|
||||
{
|
||||
DefaultHolster( MP5_HOLSTER, 0.9 );
|
||||
}
|
||||
|
||||
void CMP5::PrimaryAttack()
|
||||
{
|
||||
if( m_pPlayer->m_bIsHolster )
|
||||
{
|
||||
WeaponIdle();
|
||||
return;
|
||||
}
|
||||
|
||||
// don't fire underwater
|
||||
if( m_pPlayer->pev->waterlevel == 3 )
|
||||
{
|
||||
PlayEmptySound();
|
||||
m_flNextPrimaryAttack = 0.15;
|
||||
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.15;
|
||||
return;
|
||||
}
|
||||
|
||||
if( m_iClip <= 0 )
|
||||
{
|
||||
PlayEmptySound();
|
||||
m_flNextPrimaryAttack = 0.15;
|
||||
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.15;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -178,7 +189,7 @@ void CMP5::PrimaryAttack()
|
|||
// HEV suit - indicate out of ammo condition
|
||||
m_pPlayer->SetSuitUpdate( "!HEV_AMO0", FALSE, 0 );
|
||||
|
||||
m_flNextPrimaryAttack = GetNextAttackDelay( 0.1 );
|
||||
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.1;
|
||||
|
||||
if( m_flNextPrimaryAttack < UTIL_WeaponTimeBase() )
|
||||
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.1;
|
||||
|
@ -188,11 +199,17 @@ void CMP5::PrimaryAttack()
|
|||
|
||||
void CMP5::SecondaryAttack( void )
|
||||
{
|
||||
if( m_pPlayer->m_bIsHolster )
|
||||
{
|
||||
WeaponIdle();
|
||||
return;
|
||||
}
|
||||
|
||||
// don't fire underwater
|
||||
if( m_pPlayer->pev->waterlevel == 3 )
|
||||
{
|
||||
PlayEmptySound( );
|
||||
m_flNextPrimaryAttack = 0.15;
|
||||
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.15;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -210,35 +227,40 @@ void CMP5::SecondaryAttack( void )
|
|||
|
||||
m_pPlayer->m_rgAmmo[m_iSecondaryAmmoType]--;
|
||||
|
||||
SendWeaponAnim( MP5_LAUNCH );
|
||||
|
||||
// player "shoot" animation
|
||||
m_pPlayer->SetAnimation( PLAYER_ATTACK1 );
|
||||
|
||||
// play this sound through BODY channel so we can hear it if player didn't stop firing MP3
|
||||
EMIT_SOUND( ENT( m_pPlayer->pev ), CHAN_WEAPON, RANDOM_LONG( 0, 1 ) ? "weapons/glauncher.wav" : "weapons/glauncher2.wav", 0.8, ATTN_NORM );
|
||||
|
||||
UTIL_MakeVectors( m_pPlayer->pev->v_angle + m_pPlayer->pev->punchangle );
|
||||
|
||||
// we don't add in player velocity anymore.
|
||||
CGrenade::ShootContact( m_pPlayer->pev,
|
||||
m_pPlayer->pev->origin + m_pPlayer->pev->view_ofs + gpGlobals->v_forward * 16,
|
||||
gpGlobals->v_forward * 800 );
|
||||
gpGlobals->v_forward * 800, gSkillData.plrDmgM203Grenade );
|
||||
|
||||
int flags;
|
||||
#if defined( CLIENT_WEAPONS )
|
||||
flags = FEV_NOTHOST;
|
||||
#else
|
||||
flags = 0;
|
||||
#endif
|
||||
PLAYBACK_EVENT( flags, m_pPlayer->edict(), m_usMP52 );
|
||||
|
||||
m_flNextPrimaryAttack = GetNextAttackDelay( 1 );
|
||||
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 1;
|
||||
m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 1;
|
||||
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 5;// idle pretty soon after shooting.
|
||||
|
||||
if( !m_pPlayer->m_rgAmmo[m_iSecondaryAmmoType] )
|
||||
// HEV suit - indicate out of ammo condition
|
||||
m_pPlayer->SetSuitUpdate( "!HEV_AMO0", FALSE, 0 );
|
||||
|
||||
m_pPlayer->pev->punchangle.x -= 10;
|
||||
}
|
||||
|
||||
void CMP5::Reload( void )
|
||||
{
|
||||
if( m_pPlayer->m_bIsHolster )
|
||||
{
|
||||
WeaponIdle();
|
||||
return;
|
||||
}
|
||||
|
||||
if( m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0 || m_iClip == MP5_MAX_CLIP )
|
||||
return;
|
||||
|
||||
|
@ -247,6 +269,16 @@ void CMP5::Reload( void )
|
|||
|
||||
void CMP5::WeaponIdle( void )
|
||||
{
|
||||
if( m_pPlayer->m_bIsHolster )
|
||||
{
|
||||
if( m_flTimeWeaponIdle <= UTIL_WeaponTimeBase() )
|
||||
{
|
||||
m_pPlayer->m_bIsHolster = FALSE;
|
||||
Deploy();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
ResetEmptySound();
|
||||
|
||||
m_pPlayer->GetAutoaimVector( AUTOAIM_5DEGREES );
|
||||
|
|
|
@ -146,13 +146,13 @@ void CHalfLifeMultiplay::RefreshSkillData( void )
|
|||
gSkillData.plrDmgCrowbar = 25;
|
||||
|
||||
// Poolstick
|
||||
gSkillData.plrDmgPoolstick = 10;//Alex
|
||||
gSkillData.plrDmgPoolstick = 12;//Alex
|
||||
|
||||
// Glock Round
|
||||
gSkillData.plrDmg9MM = 12;
|
||||
|
||||
// Beretta Round
|
||||
gSkillData.plrDmgBeretta = 10;
|
||||
gSkillData.plrDmgBeretta = 14;
|
||||
|
||||
// 357 Round
|
||||
gSkillData.plrDmg357 = 40;
|
||||
|
@ -161,7 +161,7 @@ void CHalfLifeMultiplay::RefreshSkillData( void )
|
|||
gSkillData.plrDmgMP5 = 12;
|
||||
|
||||
// M41A Round
|
||||
gSkillData.plrDmgM41A = 8;
|
||||
gSkillData.plrDmgM41A = 14;
|
||||
|
||||
// M41A M203 grenade
|
||||
gSkillData.plrDmgM41AGrenade = 105;
|
||||
|
|
|
@ -331,7 +331,7 @@ void CNihilanth::Spawn( void )
|
|||
void CNihilanth::Precache( void )
|
||||
{
|
||||
PRECACHE_MODEL( "models/nihilanth.mdl" );
|
||||
PRECACHE_MODEL( "sprites/lgtning.spr" );
|
||||
// PRECACHE_MODEL( "sprites/lgtning.spr" );
|
||||
UTIL_PrecacheOther( "nihilanth_energy_ball" );
|
||||
UTIL_PrecacheOther( "monster_alien_controller" );
|
||||
UTIL_PrecacheOther( "monster_alien_slave" );
|
||||
|
|
|
@ -1053,17 +1053,18 @@ void CFuncTrackTrain::StopSound( void )
|
|||
// if sound playing, stop it
|
||||
if( m_soundPlaying && pev->noise )
|
||||
{
|
||||
unsigned short us_encode;
|
||||
/* unsigned short us_encode;
|
||||
unsigned short us_sound = ( (unsigned short)( m_sounds ) & 0x0007 ) << 12;
|
||||
|
||||
us_encode = us_sound;
|
||||
|
||||
PLAYBACK_EVENT_FULL( FEV_RELIABLE | FEV_UPDATE, edict(), m_usAdjustPitch, 0.0,
|
||||
(float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, us_encode, 0, 1, 0 );
|
||||
/*
|
||||
(float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, us_encode, 0, 1, 0 );*/
|
||||
|
||||
STOP_SOUND( ENT( pev ), CHAN_STATIC, STRING( pev->noise ) );
|
||||
*/
|
||||
EMIT_SOUND_DYN( ENT( pev ), CHAN_ITEM, "plats/ttrain_brake1.wav", m_flVolume, ATTN_NORM, 0, 100 );
|
||||
|
||||
if( m_sounds < 7 && !FBitSet( pev->spawnflags, SF_TRACKTRAIN_CAR ) )
|
||||
EMIT_SOUND_DYN( ENT( pev ), CHAN_ITEM, "plats/ttrain_brake1.wav", m_flVolume, ATTN_NORM, 0, 100 );
|
||||
}
|
||||
|
||||
m_soundPlaying = 0;
|
||||
|
@ -1079,26 +1080,34 @@ void CFuncTrackTrain::UpdateSound( void )
|
|||
if( !pev->noise )
|
||||
return;
|
||||
|
||||
flpitch = TRAIN_STARTPITCH + ( fabs( pev->speed ) * ( TRAIN_MAXPITCH - TRAIN_STARTPITCH ) / TRAIN_MAXSPEED );
|
||||
if( m_sounds > 7 && m_sounds <= 10 )
|
||||
{
|
||||
flpitch = PITCH_NORM;
|
||||
}
|
||||
else
|
||||
{
|
||||
flpitch = TRAIN_STARTPITCH + ( fabs( pev->speed ) * ( TRAIN_MAXPITCH - TRAIN_STARTPITCH ) / TRAIN_MAXSPEED );
|
||||
}
|
||||
|
||||
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 );
|
||||
if( m_sounds < 7 && !FBitSet( pev->spawnflags, SF_TRACKTRAIN_CAR ) )
|
||||
EMIT_SOUND_DYN( ENT( pev ), CHAN_ITEM, "plats/ttrain_start1.wav", m_flVolume, ATTN_NORM, 0, 100 );
|
||||
EMIT_SOUND_DYN( ENT( pev ), CHAN_STATIC, STRING( pev->noise ), m_flVolume, ATTN_NORM, 0, (int)flpitch );
|
||||
m_soundPlaying = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
|
||||
// update pitch
|
||||
EMIT_SOUND_DYN( ENT( pev ), CHAN_STATIC, STRING( pev->noise ), m_flVolume, ATTN_NORM, SND_CHANGE_PITCH, (int)flpitch );
|
||||
*/
|
||||
|
||||
// volume 0.0 - 1.0 - 6 bits
|
||||
// m_sounds 3 bits
|
||||
// flpitch = 6 bits
|
||||
// 15 bits total
|
||||
|
||||
/*
|
||||
unsigned short us_encode;
|
||||
unsigned short us_sound = ( ( unsigned short )( m_sounds ) & 0x0007 ) << 12;
|
||||
unsigned short us_pitch = ( ( unsigned short )( flpitch / 10.0 ) & 0x003f ) << 6;
|
||||
|
@ -1107,7 +1116,7 @@ void CFuncTrackTrain::UpdateSound( void )
|
|||
us_encode = us_sound | us_pitch | us_volume;
|
||||
|
||||
PLAYBACK_EVENT_FULL( FEV_RELIABLE | FEV_UPDATE, edict(), m_usAdjustPitch, 0.0,
|
||||
(float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, us_encode, 0, 0, 0 );
|
||||
(float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, us_encode, 0, 0, 0 );*/
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1500,6 +1509,18 @@ void CFuncTrackTrain::Precache( void )
|
|||
case 6:
|
||||
pszSound = "plats/ttrain7.wav";
|
||||
break;
|
||||
case 7:
|
||||
pszSound = "plats/theli1.wav";
|
||||
break;
|
||||
case 8:
|
||||
pszSound = "ambience/cardrive2.wav";
|
||||
break;
|
||||
case 9:
|
||||
pszSound = "ambience/jeep_start.wav";
|
||||
break;
|
||||
case 10:
|
||||
pszSound = "ambience/jeep_drive.wav";
|
||||
break;
|
||||
}
|
||||
|
||||
if( pszSound )
|
||||
|
|
110
dlls/player.cpp
110
dlls/player.cpp
|
@ -119,6 +119,8 @@ TYPEDESCRIPTION CBasePlayer::m_playerSaveData[] =
|
|||
DEFINE_FIELD( CBasePlayer, m_iHideHUD, FIELD_INTEGER ),
|
||||
DEFINE_FIELD( CBasePlayer, m_iFOV, FIELD_INTEGER ),
|
||||
|
||||
DEFINE_FIELD( CBasePlayer, m_bHaveSuit, FIELD_BOOLEAN ),
|
||||
DEFINE_FIELD( CBasePlayer, m_bIsHolster, FIELD_BOOLEAN ),
|
||||
//DEFINE_FIELD( CBasePlayer, m_fDeadTime, FIELD_FLOAT ), // only used in multiplayer games
|
||||
//DEFINE_FIELD( CBasePlayer, m_fGameHUDInitialized, FIELD_INTEGER ), // only used in multiplayer games
|
||||
//DEFINE_FIELD( CBasePlayer, m_flStopExtraSoundTime, FIELD_TIME ),
|
||||
|
@ -356,7 +358,10 @@ void CBasePlayer::DeathSound( void )
|
|||
}
|
||||
|
||||
// play one of the suit death alarms
|
||||
EMIT_GROUPNAME_SUIT( ENT( pev ), "HEV_DEAD" );
|
||||
if( m_bHaveSuit )
|
||||
EMIT_GROUPNAME_SUIT( ENT( pev ), "HEV_DEAD" );
|
||||
else
|
||||
EMIT_GROUPNAME_SUIT( ENT( pev ), "HEV_NHEVDEAD" );
|
||||
}
|
||||
|
||||
// override takehealth
|
||||
|
@ -785,7 +790,8 @@ void CBasePlayer::RemoveAllItems( BOOL removeSuit )
|
|||
if( m_pActiveItem )
|
||||
{
|
||||
ResetAutoaim();
|
||||
m_pActiveItem->Holster();
|
||||
Holster();
|
||||
m_bIsHolster = FALSE;
|
||||
m_pActiveItem = NULL;
|
||||
}
|
||||
|
||||
|
@ -849,8 +855,7 @@ void CBasePlayer::Killed( entvars_t *pevAttacker, int iGib )
|
|||
CSound *pSound;
|
||||
|
||||
// Holster weapon immediately, to allow it to cleanup
|
||||
if( m_pActiveItem )
|
||||
m_pActiveItem->Holster();
|
||||
Holster();
|
||||
|
||||
g_pGameRules->PlayerKilled( this, pevAttacker, g_pevLastInflictor );
|
||||
|
||||
|
@ -1087,25 +1092,6 @@ void CBasePlayer::SetAnimation( PLAYER_ANIM playerAnim )
|
|||
ResetSequenceInfo();
|
||||
}
|
||||
|
||||
/*
|
||||
===========
|
||||
TabulateAmmo
|
||||
This function is used to find and store
|
||||
all the ammo we have into the ammo vars.
|
||||
============
|
||||
*/
|
||||
void CBasePlayer::TabulateAmmo()
|
||||
{
|
||||
ammo_9mm = AmmoInventory( GetAmmoIndex( "9mm" ) );
|
||||
ammo_357 = AmmoInventory( GetAmmoIndex( "357" ) );
|
||||
ammo_argrens = AmmoInventory( GetAmmoIndex( "ARgrenades" ) );
|
||||
ammo_bolts = AmmoInventory( GetAmmoIndex( "bolts" ) );
|
||||
ammo_buckshot = AmmoInventory( GetAmmoIndex( "buckshot" ) );
|
||||
ammo_rockets = AmmoInventory( GetAmmoIndex( "rockets" ) );
|
||||
ammo_uranium = AmmoInventory( GetAmmoIndex( "uranium" ) );
|
||||
ammo_hornets = AmmoInventory( GetAmmoIndex( "Hornets" ) );
|
||||
}
|
||||
|
||||
/*
|
||||
===========
|
||||
WaterMove
|
||||
|
@ -1394,8 +1380,7 @@ void CBasePlayer::StartObserver( Vector vecPosition, Vector vecViewAngle )
|
|||
MESSAGE_END();
|
||||
|
||||
// Holster weapon immediately, to allow it to cleanup
|
||||
if( m_pActiveItem )
|
||||
m_pActiveItem->Holster();
|
||||
Holster();
|
||||
|
||||
if( m_pTank != 0 )
|
||||
m_pTank->Use( this, this, USE_OFF, 0 );
|
||||
|
@ -2815,6 +2800,8 @@ void CBasePlayer::Spawn( void )
|
|||
m_flgeigerDelay = gpGlobals->time + 2.0; // wait a few seconds until user-defined message registrations
|
||||
// are recieved by all clients
|
||||
|
||||
m_bIsHolster = FALSE;
|
||||
m_bHaveSuit = FALSE;
|
||||
m_flTimeStepSound = 0;
|
||||
m_iStepLeft = 0;
|
||||
m_flFieldOfView = 0.5;// some monsters use this to determine whether or not the player is looking at them.
|
||||
|
@ -2996,6 +2983,15 @@ int CBasePlayer::Restore( CRestore &restore )
|
|||
return status;
|
||||
}
|
||||
|
||||
void CBasePlayer::Holster()
|
||||
{
|
||||
if( m_pActiveItem )
|
||||
{
|
||||
m_pActiveItem->Holster();
|
||||
m_bIsHolster = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
void CBasePlayer::SelectNextItem( int iItem )
|
||||
{
|
||||
CBasePlayerItem *pItem;
|
||||
|
@ -3028,14 +3024,11 @@ void CBasePlayer::SelectNextItem( int iItem )
|
|||
ResetAutoaim();
|
||||
|
||||
// FIX, this needs to queue them up and delay
|
||||
if( m_pActiveItem )
|
||||
{
|
||||
m_pActiveItem->Holster();
|
||||
}
|
||||
Holster();
|
||||
|
||||
m_pActiveItem = pItem;
|
||||
|
||||
if( m_pActiveItem )
|
||||
if( !m_bIsHolster )
|
||||
{
|
||||
m_pActiveItem->Deploy();
|
||||
m_pActiveItem->UpdateItemInfo();
|
||||
|
@ -3076,13 +3069,12 @@ void CBasePlayer::SelectItem( const char *pstr )
|
|||
ResetAutoaim();
|
||||
|
||||
// FIX, this needs to queue them up and delay
|
||||
if( m_pActiveItem )
|
||||
m_pActiveItem->Holster();
|
||||
Holster();
|
||||
|
||||
m_pLastItem = m_pActiveItem;
|
||||
m_pActiveItem = pItem;
|
||||
|
||||
if( m_pActiveItem )
|
||||
if( !m_bIsHolster )
|
||||
{
|
||||
m_pActiveItem->Deploy();
|
||||
m_pActiveItem->UpdateItemInfo();
|
||||
|
@ -3104,12 +3096,12 @@ void CBasePlayer::SelectLastItem( void )
|
|||
ResetAutoaim();
|
||||
|
||||
// FIX, this needs to queue them up and delay
|
||||
if( m_pActiveItem )
|
||||
m_pActiveItem->Holster();
|
||||
Holster();
|
||||
|
||||
CBasePlayerItem *pTemp = m_pActiveItem;
|
||||
m_pActiveItem = m_pLastItem;
|
||||
m_pLastItem = pTemp;
|
||||
|
||||
m_pActiveItem->Deploy();
|
||||
m_pActiveItem->UpdateItemInfo();
|
||||
}
|
||||
|
@ -3443,20 +3435,47 @@ void CBasePlayer::CheatImpulseCommands( int iImpulse )
|
|||
Create( "monster_human_grunt", pev->origin + gpGlobals->v_forward * 128, pev->angles );
|
||||
}
|
||||
break;
|
||||
case 77:
|
||||
pEntity = UTIL_FindEntityByTargetname( 0, "katemm" );
|
||||
if( pEntity )
|
||||
{
|
||||
FireTargets( STRING( pEntity->pev->message ), this, this, USE_TOGGLE, 0 );
|
||||
ALERT( at_console, "impulse 77: Kate spawned!\n" );
|
||||
}
|
||||
else
|
||||
ALERT( at_console, "impulse 77: Didn't find Kate spawner!\n" );
|
||||
break;
|
||||
case 78:
|
||||
pEntity = UTIL_FindEntityByTargetname( 0, "katemmspw" );
|
||||
if( pEntity )
|
||||
UTIL_ShowKateHealth( pEntity->pev->health );
|
||||
else
|
||||
ALERT( at_console, "impulse 78: Didn't find Kate (katemm)!\n" );
|
||||
break;
|
||||
case 101:
|
||||
ALERT( at_console, "Cheater...\n" );
|
||||
gEvilImpulse101 = TRUE;
|
||||
GiveNamedItem( "item_suit" );
|
||||
GiveNamedItem( "item_battery" );
|
||||
GiveNamedItem( "weapon_crowbar" );
|
||||
GiveNamedItem( "weapon_barney9mmhg" ); // Alex for new 9mm handgun
|
||||
GiveNamedItem( "weapon_9mmhandgun" );
|
||||
GiveNamedItem( "weapon_beretta" );
|
||||
GiveNamedItem( "ammo_9mmclip" );
|
||||
GiveNamedItem( "weapon_barneyshotgun" ); // Alex for new shotgun
|
||||
GiveNamedItem( "weapon_shotgun" );
|
||||
GiveNamedItem( "ammo_buckshot" );
|
||||
GiveNamedItem( "weapon_barney9mmar" ); // Alex for new 9mm ar
|
||||
GiveNamedItem( "weapon_9mmAR" );
|
||||
GiveNamedItem( "weapon_9mmm41a" );
|
||||
GiveNamedItem( "ammo_9mmAR" );
|
||||
GiveNamedItem( "ammo_ARgrenades" );
|
||||
GiveNamedItem( "weapon_barneyhandgrenade" ); // Alex for new handgrenade
|
||||
GiveNamedItem( "weapon_handgrenade" );
|
||||
GiveNamedItem( "weapon_tripmine" );
|
||||
GiveNamedItem( "weapon_barney9mmhg" );
|
||||
GiveNamedItem( "weapon_barneyshotgun" );
|
||||
GiveNamedItem( "weapon_barney9mmar" );
|
||||
GiveNamedItem( "weapon_barneyhandgrenade" );
|
||||
GiveNamedItem( "weapon_poolstick" );
|
||||
GiveNamedItem( "weapon_toad" );
|
||||
GiveNamedItem( "weapon_kmedkit" );
|
||||
#ifndef OEM_BUILD
|
||||
GiveNamedItem( "weapon_357" );
|
||||
GiveNamedItem( "ammo_357" );
|
||||
|
@ -3610,7 +3629,7 @@ int CBasePlayer::AddPlayerItem( CBasePlayerItem *pItem )
|
|||
|
||||
// ugly hack to update clip w/o an update clip message
|
||||
pInsert->UpdateItemInfo();
|
||||
if( m_pActiveItem )
|
||||
if( !m_bIsHolster )
|
||||
m_pActiveItem->UpdateItemInfo();
|
||||
|
||||
pItem->Kill();
|
||||
|
@ -3660,6 +3679,7 @@ int CBasePlayer::RemovePlayerItem( CBasePlayerItem *pItem, bool bCallHolster )
|
|||
if( bCallHolster )
|
||||
pItem->Holster();
|
||||
m_pActiveItem = NULL;
|
||||
m_bIsHolster = FALSE;
|
||||
pev->viewmodel = 0;
|
||||
pev->weaponmodel = 0;
|
||||
}
|
||||
|
@ -3729,8 +3749,6 @@ int CBasePlayer::GiveAmmo( int iCount, const char *szName, int iMax )
|
|||
MESSAGE_END();
|
||||
}
|
||||
|
||||
TabulateAmmo();
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
|
@ -4556,13 +4574,11 @@ BOOL CBasePlayer::SwitchWeapon( CBasePlayerItem *pWeapon )
|
|||
|
||||
ResetAutoaim();
|
||||
|
||||
if( m_pActiveItem )
|
||||
{
|
||||
m_pActiveItem->Holster();
|
||||
}
|
||||
Holster();
|
||||
|
||||
m_pActiveItem = pWeapon;
|
||||
pWeapon->Deploy();
|
||||
if( !m_bIsHolster )
|
||||
pWeapon->Deploy();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
@ -305,8 +305,6 @@ public:
|
|||
void SetCustomDecalFrames( int nFrames );
|
||||
int GetCustomDecalFrames( void );
|
||||
|
||||
void TabulateAmmo( void );
|
||||
|
||||
Vector m_vecLastViewAngles;
|
||||
|
||||
float m_flStartCharge;
|
||||
|
@ -325,6 +323,9 @@ public:
|
|||
|
||||
float m_flNextChatTime;
|
||||
|
||||
void Holster();
|
||||
BOOL m_bHaveSuit;
|
||||
BOOL m_bIsHolster;
|
||||
bool m_bSentBhopcap; // If false, the player just joined and needs a bhopcap message.
|
||||
};
|
||||
|
||||
|
|
|
@ -82,7 +82,7 @@ void CPlayerMonster :: HandleAnimEvent( MonsterEvent_t *pEvent )
|
|||
//=========================================================
|
||||
int CPlayerMonster::ISoundMask( void )
|
||||
{
|
||||
return NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
|
|
|
@ -47,7 +47,7 @@ int CPython::GetItemInfo( ItemInfo *p )
|
|||
p->iMaxClip = PYTHON_MAX_CLIP;
|
||||
p->iFlags = 0;
|
||||
p->iSlot = 1;
|
||||
p->iPosition = 1;
|
||||
p->iPosition = 3;
|
||||
p->iId = m_iId = WEAPON_PYTHON;
|
||||
p->iWeight = PYTHON_WEIGHT;
|
||||
|
||||
|
@ -116,20 +116,20 @@ BOOL CPython::Deploy()
|
|||
|
||||
void CPython::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_WeaponTimeBase() + UTIL_SharedRandomFloat( m_pPlayer->random_seed, 10, 15 );
|
||||
SendWeaponAnim( PYTHON_HOLSTER );
|
||||
DefaultHolster( PYTHON_HOLSTER, 1.0 );
|
||||
}
|
||||
|
||||
void CPython::SecondaryAttack( void )
|
||||
{
|
||||
if( m_pPlayer->m_bIsHolster )
|
||||
{
|
||||
WeaponIdle();
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
if( !bIsMultiplayer() )
|
||||
#else
|
||||
|
@ -155,11 +155,17 @@ void CPython::SecondaryAttack( void )
|
|||
|
||||
void CPython::PrimaryAttack()
|
||||
{
|
||||
if( m_pPlayer->m_bIsHolster )
|
||||
{
|
||||
WeaponIdle();
|
||||
return;
|
||||
}
|
||||
|
||||
// don't fire underwater
|
||||
if( m_pPlayer->pev->waterlevel == 3 )
|
||||
{
|
||||
PlayEmptySound();
|
||||
m_flNextPrimaryAttack = 0.15;
|
||||
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.15;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -170,7 +176,7 @@ void CPython::PrimaryAttack()
|
|||
else
|
||||
{
|
||||
PlayEmptySound();
|
||||
m_flNextPrimaryAttack = 0.15;
|
||||
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.15;
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -206,12 +212,18 @@ void CPython::PrimaryAttack()
|
|||
// HEV suit - indicate out of ammo condition
|
||||
m_pPlayer->SetSuitUpdate( "!HEV_AMO0", FALSE, 0 );
|
||||
|
||||
m_flNextPrimaryAttack = 0.75;
|
||||
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.75;
|
||||
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + UTIL_SharedRandomFloat( m_pPlayer->random_seed, 10, 15 );
|
||||
}
|
||||
|
||||
void CPython::Reload( void )
|
||||
{
|
||||
if( m_pPlayer->m_bIsHolster )
|
||||
{
|
||||
WeaponIdle();
|
||||
return;
|
||||
}
|
||||
|
||||
if( m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0 || m_iClip == PYTHON_MAX_CLIP )
|
||||
return;
|
||||
|
||||
|
@ -229,12 +241,22 @@ void CPython::Reload( void )
|
|||
#endif
|
||||
if( DefaultReload( PYTHON_MAX_CLIP, PYTHON_RELOAD, 2.0, bUseScope ) )
|
||||
{
|
||||
m_flSoundDelay = 1.5;
|
||||
m_flSoundDelay = UTIL_WeaponTimeBase() + 1.5;
|
||||
}
|
||||
}
|
||||
|
||||
void CPython::WeaponIdle( void )
|
||||
{
|
||||
if( m_pPlayer->m_bIsHolster )
|
||||
{
|
||||
if( m_flTimeWeaponIdle <= UTIL_WeaponTimeBase() )
|
||||
{
|
||||
m_pPlayer->m_bIsHolster = FALSE;
|
||||
Deploy();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
ResetEmptySound();
|
||||
|
||||
m_pPlayer->GetAutoaimVector( AUTOAIM_10DEGREES );
|
||||
|
|
226
dlls/rat.cpp
226
dlls/rat.cpp
|
@ -21,48 +21,77 @@
|
|||
#include "cbase.h"
|
||||
#include "monsters.h"
|
||||
#include "schedule.h"
|
||||
#include "headcrab.h"
|
||||
#include "game.h"
|
||||
|
||||
//=========================================================
|
||||
// Monster's Anim Events Go Here
|
||||
//=========================================================
|
||||
#define RAT_AE_JUMPATTACK ( 2 )
|
||||
|
||||
class CRat : public CBaseMonster
|
||||
class CRat : public CHeadCrab
|
||||
{
|
||||
public:
|
||||
void Spawn( void );
|
||||
void Precache( void );
|
||||
void SetYawSpeed( void );
|
||||
int Classify( void );
|
||||
|
||||
void HandleAnimEvent( MonsterEvent_t *pEvent );
|
||||
void EXPORT RatLeapTouch( CBaseEntity *pOther );
|
||||
void StartTask( Task_t *pTask );
|
||||
|
||||
void PainSound( void );
|
||||
void DeathSound( void );
|
||||
void IdleSound( void );
|
||||
void AlertSound( void );
|
||||
|
||||
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_rat, CRat )
|
||||
|
||||
const char *CRat::pIdleSounds[] =
|
||||
{
|
||||
"rat/rat_idle.wav"
|
||||
};
|
||||
|
||||
const char *CRat::pAlertSounds[] =
|
||||
{
|
||||
"rat/rat_alert.wav"
|
||||
};
|
||||
|
||||
const char *CRat::pPainSounds[] =
|
||||
{
|
||||
"rat/rat_pain.wav"
|
||||
};
|
||||
|
||||
const char *CRat::pAttackSounds[] =
|
||||
{
|
||||
"rat/rat_attack.wav"
|
||||
};
|
||||
|
||||
const char *CRat::pDeathSounds[] =
|
||||
{
|
||||
"rat/rat_die.wav"
|
||||
};
|
||||
|
||||
const char *CRat::pBiteSounds[] =
|
||||
{
|
||||
"rat/rat_headbite.wav"
|
||||
};
|
||||
|
||||
//=========================================================
|
||||
// Classify - indicates this monster's place in the
|
||||
// relationship table.
|
||||
//=========================================================
|
||||
int CRat::Classify( void )
|
||||
{
|
||||
return CLASS_INSECT;
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// SetYawSpeed - allows each sequence to have a different
|
||||
// turn rate associated with it.
|
||||
//=========================================================
|
||||
void CRat::SetYawSpeed( void )
|
||||
{
|
||||
int ys;
|
||||
|
||||
switch( m_Activity )
|
||||
{
|
||||
case ACT_IDLE:
|
||||
default:
|
||||
ys = 45;
|
||||
break;
|
||||
}
|
||||
|
||||
pev->yaw_speed = ys;
|
||||
return CLASS_HUMAN_MILITARY;
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
|
@ -73,7 +102,10 @@ void CRat::Spawn()
|
|||
Precache();
|
||||
|
||||
SET_MODEL( ENT( pev ), "models/bigrat.mdl" );
|
||||
UTIL_SetSize( pev, Vector( 0, 0, 0 ), Vector( 0, 0, 0 ) );
|
||||
if( !strncmp( STRING( gpGlobals->mapname ), "asmap", 5 ) )
|
||||
UTIL_SetSize( pev, Vector( -12, -12, 0 ), Vector( 12, 12, 24 ) );
|
||||
else
|
||||
UTIL_SetSize( pev, g_vecZero, g_vecZero );
|
||||
|
||||
pev->solid = SOLID_SLIDEBOX;
|
||||
pev->movetype = MOVETYPE_STEP;
|
||||
|
@ -91,9 +123,157 @@ void CRat::Spawn()
|
|||
//=========================================================
|
||||
void CRat::Precache()
|
||||
{
|
||||
PRECACHE_SOUND_ARRAY( pIdleSounds );
|
||||
PRECACHE_SOUND_ARRAY( pAlertSounds );
|
||||
PRECACHE_SOUND_ARRAY( pPainSounds );
|
||||
PRECACHE_SOUND_ARRAY( pAttackSounds );
|
||||
PRECACHE_SOUND_ARRAY( pDeathSounds );
|
||||
PRECACHE_SOUND_ARRAY( pBiteSounds );
|
||||
|
||||
PRECACHE_MODEL( "models/bigrat.mdl" );
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// HandleAnimEvent - catches the monster-specific messages
|
||||
// that occur when tagged animation frames are played.
|
||||
//=========================================================
|
||||
void CRat::HandleAnimEvent( MonsterEvent_t *pEvent )
|
||||
{
|
||||
switch( pEvent->event )
|
||||
{
|
||||
case RAT_AE_JUMPATTACK:
|
||||
{
|
||||
ClearBits( pev->flags, FL_ONGROUND );
|
||||
|
||||
UTIL_SetOrigin( pev, pev->origin + Vector( 0, 0, 1 ) );// take him off ground so engine doesn't instantly reset onground
|
||||
UTIL_MakeVectors( pev->angles );
|
||||
|
||||
Vector vecJumpDir;
|
||||
if( m_hEnemy != 0 )
|
||||
{
|
||||
float gravity = g_psv_gravity->value;
|
||||
if( gravity <= 1 )
|
||||
gravity = 1;
|
||||
|
||||
// How fast does the headcrab need to travel to reach that height given gravity?
|
||||
float height = m_hEnemy->pev->origin.z + m_hEnemy->pev->view_ofs.z - pev->origin.z;
|
||||
if( height < 16 )
|
||||
height = 16;
|
||||
float speed = sqrt( 2 * gravity * height );
|
||||
float time = speed / gravity;
|
||||
|
||||
// Scale the sideways velocity to get there at the right time
|
||||
vecJumpDir = m_hEnemy->pev->origin + m_hEnemy->pev->view_ofs - pev->origin;
|
||||
vecJumpDir = vecJumpDir * ( 1.0 / time );
|
||||
|
||||
// Speed to offset gravity at the desired height
|
||||
vecJumpDir.z = speed;
|
||||
|
||||
// Don't jump too far/fast
|
||||
float distance = vecJumpDir.Length();
|
||||
|
||||
if( distance > 650 )
|
||||
{
|
||||
vecJumpDir = vecJumpDir * ( 650.0 / distance );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// jump hop, don't care where
|
||||
vecJumpDir = Vector( gpGlobals->v_forward.x, gpGlobals->v_forward.y, gpGlobals->v_up.z ) * 350;
|
||||
}
|
||||
|
||||
EMIT_SOUND_DYN( edict(), CHAN_VOICE, pAttackSounds[0], GetSoundVolue(), ATTN_IDLE, 0, GetVoicePitch() );
|
||||
|
||||
pev->velocity = vecJumpDir;
|
||||
m_flNextAttack = gpGlobals->time + 2;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
CBaseMonster::HandleAnimEvent( pEvent );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// LeapTouch - this is the rat's touch function when it
|
||||
// is in the air
|
||||
//=========================================================
|
||||
void CRat::RatLeapTouch( 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 CRat::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( &CRat::RatLeapTouch );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
CBaseMonster::StartTask( pTask );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// IdleSound
|
||||
//=========================================================
|
||||
void CRat::IdleSound( void )
|
||||
{
|
||||
EMIT_SOUND_DYN( edict(), CHAN_VOICE, RANDOM_SOUND_ARRAY( pIdleSounds ), GetSoundVolue(), ATTN_IDLE, 0, GetVoicePitch() );
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// AlertSound
|
||||
//=========================================================
|
||||
void CRat::AlertSound( void )
|
||||
{
|
||||
EMIT_SOUND_DYN( edict(), CHAN_VOICE, RANDOM_SOUND_ARRAY( pAlertSounds ), GetSoundVolue(), ATTN_IDLE, 0, GetVoicePitch() );
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// AlertSound
|
||||
//=========================================================
|
||||
void CRat::PainSound( void )
|
||||
{
|
||||
EMIT_SOUND_DYN( edict(), CHAN_VOICE, RANDOM_SOUND_ARRAY( pPainSounds ), GetSoundVolue(), ATTN_IDLE, 0, GetVoicePitch() );
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// DeathSound
|
||||
//=========================================================
|
||||
void CRat::DeathSound( void )
|
||||
{
|
||||
EMIT_SOUND_DYN( edict(), CHAN_VOICE, RANDOM_SOUND_ARRAY( pDeathSounds ), GetSoundVolue(), ATTN_IDLE, 0, GetVoicePitch() );
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// AI Schedules Specific to this monster
|
||||
//=========================================================
|
||||
|
|
50
dlls/rpg.cpp
50
dlls/rpg.cpp
|
@ -281,6 +281,12 @@ void CRpgRocket::FollowThink( void )
|
|||
|
||||
void CRpg::Reload( void )
|
||||
{
|
||||
if( m_pPlayer->m_bIsHolster )
|
||||
{
|
||||
WeaponIdle();
|
||||
return;
|
||||
}
|
||||
|
||||
int iResult = 0;
|
||||
|
||||
// don't bother with any of this if don't need to reload.
|
||||
|
@ -297,7 +303,7 @@ void CRpg::Reload( void )
|
|||
// Set the next attack time into the future so that WeaponIdle will get called more often
|
||||
// than reload, allowing the RPG LTD to be updated
|
||||
|
||||
m_flNextPrimaryAttack = GetNextAttackDelay( 0.5 );
|
||||
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.5;
|
||||
|
||||
if( m_cActiveRockets && m_fSpotActive )
|
||||
{
|
||||
|
@ -360,7 +366,7 @@ void CRpg::Precache( void )
|
|||
PRECACHE_SOUND( "weapons/rocketfire1.wav" );
|
||||
PRECACHE_SOUND( "weapons/glauncher.wav" ); // alternative fire sound
|
||||
|
||||
m_usRpg = PRECACHE_EVENT( 1, "events/rpg.sc" );
|
||||
//m_usRpg = PRECACHE_EVENT( 1, "events/rpg.sc" );
|
||||
}
|
||||
|
||||
int CRpg::GetItemInfo( ItemInfo *p )
|
||||
|
@ -415,12 +421,10 @@ BOOL CRpg::CanHolster( void )
|
|||
|
||||
void CRpg::Holster( int skiplocal /* = 0 */ )
|
||||
{
|
||||
m_fInReload = FALSE;// cancel any reload in progress.
|
||||
|
||||
m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.5;
|
||||
|
||||
SendWeaponAnim( RPG_HOLSTER1 );
|
||||
|
||||
if( m_iClip )
|
||||
DefaultHolster( RPG_HOLSTER1, 0.8 );
|
||||
else
|
||||
DefaultHolster( RPG_HOLSTER2, 0.8 );
|
||||
#ifndef CLIENT_DLL
|
||||
if( m_pSpot )
|
||||
{
|
||||
|
@ -432,12 +436,20 @@ void CRpg::Holster( int skiplocal /* = 0 */ )
|
|||
|
||||
void CRpg::PrimaryAttack()
|
||||
{
|
||||
if( m_pPlayer->m_bIsHolster )
|
||||
{
|
||||
WeaponIdle();
|
||||
return;
|
||||
}
|
||||
|
||||
if( m_iClip )
|
||||
{
|
||||
m_pPlayer->m_iWeaponVolume = LOUD_GUN_VOLUME;
|
||||
m_pPlayer->m_iWeaponFlash = BRIGHT_GUN_FLASH;
|
||||
|
||||
#ifndef CLIENT_DLL
|
||||
SendWeaponAnim( RPG_FIRE2 );
|
||||
|
||||
// player "shoot" animation
|
||||
m_pPlayer->SetAnimation( PLAYER_ATTACK1 );
|
||||
|
||||
|
@ -459,12 +471,14 @@ void CRpg::PrimaryAttack()
|
|||
#else
|
||||
flags = 0;
|
||||
#endif
|
||||
PLAYBACK_EVENT( flags, m_pPlayer->edict(), m_usRpg );
|
||||
EMIT_SOUND( ENT( m_pPlayer->pev ), CHAN_WEAPON, "weapons/rocketfire1.wav", 0.9, ATTN_NORM );
|
||||
EMIT_SOUND( ENT( m_pPlayer->pev ), CHAN_ITEM, "weapons/glauncher.wav", 0.7, ATTN_NORM );
|
||||
|
||||
m_iClip--;
|
||||
|
||||
m_flNextPrimaryAttack = GetNextAttackDelay( 1.5 );
|
||||
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 1.5;
|
||||
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 1.5;
|
||||
m_pPlayer->pev->punchangle.x -= 5;
|
||||
|
||||
ResetEmptySound();
|
||||
}
|
||||
|
@ -478,6 +492,12 @@ void CRpg::PrimaryAttack()
|
|||
|
||||
void CRpg::SecondaryAttack()
|
||||
{
|
||||
if( m_pPlayer->m_bIsHolster )
|
||||
{
|
||||
WeaponIdle();
|
||||
return;
|
||||
}
|
||||
|
||||
m_fSpotActive = !m_fSpotActive;
|
||||
|
||||
#ifndef CLIENT_DLL
|
||||
|
@ -492,6 +512,16 @@ void CRpg::SecondaryAttack()
|
|||
|
||||
void CRpg::WeaponIdle( void )
|
||||
{
|
||||
if( m_pPlayer->m_bIsHolster )
|
||||
{
|
||||
if( m_flTimeWeaponIdle <= UTIL_WeaponTimeBase() )
|
||||
{
|
||||
m_pPlayer->m_bIsHolster = FALSE;
|
||||
Deploy();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateSpot();
|
||||
|
||||
if( m_flTimeWeaponIdle > UTIL_WeaponTimeBase() )
|
||||
|
|
|
@ -258,7 +258,7 @@ int CSatchel::GetItemInfo( ItemInfo *p )
|
|||
p->iMaxAmmo2 = -1;
|
||||
p->iMaxClip = WEAPON_NOCLIP;
|
||||
p->iSlot = 4;
|
||||
p->iPosition = 1;
|
||||
p->iPosition = 2;
|
||||
p->iFlags = ITEM_FLAG_SELECTONEMPTY | ITEM_FLAG_LIMITINWORLD | ITEM_FLAG_EXHAUSTIBLE;
|
||||
p->iId = m_iId = WEAPON_SATCHEL;
|
||||
p->iWeight = SATCHEL_WEIGHT;
|
||||
|
@ -305,15 +305,13 @@ BOOL CSatchel::Deploy()
|
|||
|
||||
void CSatchel::Holster( int skiplocal /* = 0 */ )
|
||||
{
|
||||
m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.5;
|
||||
|
||||
if( m_chargeReady )
|
||||
{
|
||||
SendWeaponAnim( SATCHEL_RADIO_HOLSTER );
|
||||
DefaultHolster( SATCHEL_RADIO_HOLSTER, 0.7 );
|
||||
}
|
||||
else
|
||||
{
|
||||
SendWeaponAnim( SATCHEL_DROP );
|
||||
DefaultHolster( SATCHEL_DROP, 0.7 );
|
||||
}
|
||||
EMIT_SOUND( ENT( m_pPlayer->pev ), CHAN_WEAPON, "common/null.wav", 1.0, ATTN_NORM );
|
||||
|
||||
|
@ -326,6 +324,12 @@ void CSatchel::Holster( int skiplocal /* = 0 */ )
|
|||
|
||||
void CSatchel::PrimaryAttack()
|
||||
{
|
||||
if( m_pPlayer->m_bIsHolster )
|
||||
{
|
||||
WeaponIdle();
|
||||
return;
|
||||
}
|
||||
|
||||
switch( m_chargeReady )
|
||||
{
|
||||
case SATCHEL_IDLE:
|
||||
|
@ -353,7 +357,7 @@ void CSatchel::PrimaryAttack()
|
|||
}
|
||||
|
||||
m_chargeReady = SATCHEL_RELOAD;
|
||||
m_flNextPrimaryAttack = GetNextAttackDelay( 0.5 );
|
||||
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.5;
|
||||
m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.5;
|
||||
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 0.5;
|
||||
break;
|
||||
|
@ -366,6 +370,12 @@ void CSatchel::PrimaryAttack()
|
|||
|
||||
void CSatchel::SecondaryAttack( void )
|
||||
{
|
||||
if( m_pPlayer->m_bIsHolster )
|
||||
{
|
||||
WeaponIdle();
|
||||
return;
|
||||
}
|
||||
|
||||
if( m_chargeReady != SATCHEL_RELOAD )
|
||||
{
|
||||
Throw();
|
||||
|
@ -400,13 +410,23 @@ void CSatchel::Throw( void )
|
|||
|
||||
m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]--;
|
||||
|
||||
m_flNextPrimaryAttack = GetNextAttackDelay( 1.0 );
|
||||
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 1.0;
|
||||
m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
void CSatchel::WeaponIdle( void )
|
||||
{
|
||||
if( m_pPlayer->m_bIsHolster )
|
||||
{
|
||||
if( m_flTimeWeaponIdle <= UTIL_WeaponTimeBase() )
|
||||
{
|
||||
m_pPlayer->m_bIsHolster = FALSE;
|
||||
Deploy();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if( m_flTimeWeaponIdle > UTIL_WeaponTimeBase() )
|
||||
return;
|
||||
|
||||
|
@ -441,7 +461,7 @@ void CSatchel::WeaponIdle( void )
|
|||
// use tripmine animations
|
||||
strcpy( m_pPlayer->m_szAnimExtention, "trip" );
|
||||
|
||||
m_flNextPrimaryAttack = GetNextAttackDelay( 0.5 );
|
||||
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.5;
|
||||
m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.5;
|
||||
m_chargeReady = SATCHEL_IDLE;
|
||||
break;
|
||||
|
|
|
@ -442,13 +442,19 @@ Activity CScientist::GetStoppedActivity( void )
|
|||
|
||||
void CScientist::StartTask( Task_t *pTask )
|
||||
{
|
||||
const char *pszSentence;
|
||||
|
||||
switch( pTask->iTask )
|
||||
{
|
||||
case TASK_SAY_HEAL:
|
||||
//if( FOkToSpeak() )
|
||||
Talk( 2 );
|
||||
m_hTalkTarget = m_hTargetEnt;
|
||||
PlaySentence( "SC_HEAL", 2, VOL_NORM, ATTN_IDLE );
|
||||
if( FClassnameIs( pev, "monster_worker" ) )
|
||||
pszSentence = "WK_HEAL";
|
||||
else
|
||||
pszSentence = "SC_HEAL";
|
||||
PlaySentence( pszSentence, 2, VOL_NORM, ATTN_IDLE );
|
||||
TaskComplete();
|
||||
break;
|
||||
case TASK_SCREAM:
|
||||
|
@ -469,9 +475,18 @@ void CScientist::StartTask( Task_t *pTask )
|
|||
//The enemy can be null here. - Solokiller
|
||||
//Discovered while testing the barnacle grapple on headcrabs with scientists in view.
|
||||
if( m_hEnemy != 0 && m_hEnemy->IsPlayer() )
|
||||
PlaySentence( "SC_PLFEAR", 5, VOL_NORM, ATTN_NORM );
|
||||
{
|
||||
if( FClassnameIs( pev, "monster_worker" ) )
|
||||
pszSentence = "WK_PLFEAR";
|
||||
else
|
||||
pszSentence = "SC_PLFEAR";
|
||||
}
|
||||
else if( FClassnameIs( pev, "monster_worker" ) )
|
||||
pszSentence = "WK_FEAR";
|
||||
else
|
||||
PlaySentence( "SC_FEAR", 5, VOL_NORM, ATTN_NORM );
|
||||
pszSentence = "SC_FEAR";
|
||||
|
||||
PlaySentence( pszSentence, 5, VOL_NORM, ATTN_NORM );
|
||||
}
|
||||
TaskComplete();
|
||||
break;
|
||||
|
@ -639,10 +654,7 @@ void CScientist::HandleAnimEvent( MonsterEvent_t *pEvent )
|
|||
void CScientist::Spawn( void )
|
||||
{
|
||||
Precache();
|
||||
if( FClassnameIs( pev, "monster_worker" ) )
|
||||
SET_MODEL( ENT( pev ), "models/gus.mdl" );
|
||||
else
|
||||
SET_MODEL( ENT( pev ), "models/scientist.mdl" );
|
||||
SET_MODEL( ENT( pev ), STRING( pev->model ) );
|
||||
|
||||
UTIL_SetSize( pev, VEC_HUMAN_HULL_MIN, VEC_HUMAN_HULL_MAX );
|
||||
|
||||
|
@ -661,15 +673,18 @@ void CScientist::Spawn( void )
|
|||
// White hands
|
||||
pev->skin = 0;
|
||||
|
||||
if( pev->body == -1 )
|
||||
if( !FClassnameIs( pev, "monster_worker" ) )
|
||||
{
|
||||
// -1 chooses a random head
|
||||
pev->body = RANDOM_LONG( 0, NUM_SCIENTIST_HEADS - 1 );// pick a head, any head
|
||||
}
|
||||
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;
|
||||
// Luther is black, make his hands black
|
||||
if( pev->body == HEAD_LUTHER )
|
||||
pev->skin = 1;
|
||||
}
|
||||
|
||||
MonsterInit();
|
||||
SetUse( &CTalkMonster::FollowerUse );
|
||||
|
@ -681,10 +696,10 @@ void CScientist::Spawn( void )
|
|||
void CScientist::Precache( void )
|
||||
{
|
||||
if( FClassnameIs( pev, "monster_worker" ) )
|
||||
PRECACHE_MODEL( "models/gus.mdl" );
|
||||
pev->model = MAKE_STRING( "models/gus.mdl" );
|
||||
else
|
||||
PRECACHE_MODEL( "models/scientist.mdl" );
|
||||
|
||||
pev->model = MAKE_STRING( "models/scientist.mdl" );
|
||||
PRECACHE_MODEL( STRING( pev->model ) );
|
||||
PRECACHE_SOUND( "scientist/sci_pain1.wav" );
|
||||
PRECACHE_SOUND( "scientist/sci_pain2.wav" );
|
||||
PRECACHE_SOUND( "scientist/sci_pain3.wav" );
|
||||
|
@ -711,45 +726,73 @@ void CScientist::TalkInit()
|
|||
|
||||
// scientists speach group names (group names are in sentences.txt)
|
||||
|
||||
m_szGrp[TLK_ANSWER] = "SC_ANSWER";
|
||||
m_szGrp[TLK_QUESTION] = "SC_QUESTION";
|
||||
m_szGrp[TLK_IDLE] = "SC_IDLE";
|
||||
m_szGrp[TLK_STARE] = "SC_STARE";
|
||||
m_szGrp[TLK_USE] = "SC_OK";
|
||||
m_szGrp[TLK_UNUSE] = "SC_WAIT";
|
||||
m_szGrp[TLK_STOP] = "SC_STOP";
|
||||
m_szGrp[TLK_NOSHOOT] = "SC_SCARED";
|
||||
m_szGrp[TLK_HELLO] = "SC_HELLO";
|
||||
if( FClassnameIs( pev, "monster_worker" ) )
|
||||
{
|
||||
m_szGrp[TLK_ANSWER] = "WK_ANSWER";
|
||||
m_szGrp[TLK_QUESTION] = "WK_QUESTION";
|
||||
m_szGrp[TLK_IDLE] = "WK_IDLE";
|
||||
m_szGrp[TLK_STARE] = "WK_STARE";
|
||||
m_szGrp[TLK_USE] = "WK_OK";
|
||||
m_szGrp[TLK_UNUSE] = "WK_WAIT";
|
||||
m_szGrp[TLK_STOP] = "WK_STOP";
|
||||
m_szGrp[TLK_NOSHOOT] = "WK_SCARED";
|
||||
m_szGrp[TLK_HELLO] = "WK_HELLO";
|
||||
|
||||
m_szGrp[TLK_PLHURT1] = "!SC_CUREA";
|
||||
m_szGrp[TLK_PLHURT2] = "!SC_CUREB";
|
||||
m_szGrp[TLK_PLHURT3] = "!SC_CUREC";
|
||||
m_szGrp[TLK_PLHURT1] = "!WK_CUREA";
|
||||
m_szGrp[TLK_PLHURT2] = "!WK_CUREB";
|
||||
m_szGrp[TLK_PLHURT3] = "!WK_CUREC";
|
||||
|
||||
m_szGrp[TLK_SMELL] = "WK_SMELL";
|
||||
|
||||
m_szGrp[TLK_WOUND] = "WK_WOUND";
|
||||
m_szGrp[TLK_MORTAL] = "WK_MORTAL";
|
||||
|
||||
m_voicePitch = 90;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_szGrp[TLK_ANSWER] = "SC_ANSWER";
|
||||
m_szGrp[TLK_QUESTION] = "SC_QUESTION";
|
||||
m_szGrp[TLK_IDLE] = "SC_IDLE";
|
||||
m_szGrp[TLK_STARE] = "SC_STARE";
|
||||
m_szGrp[TLK_USE] = "SC_OK";
|
||||
m_szGrp[TLK_UNUSE] = "SC_WAIT";
|
||||
m_szGrp[TLK_STOP] = "SC_STOP";
|
||||
m_szGrp[TLK_NOSHOOT] = "SC_SCARED";
|
||||
m_szGrp[TLK_HELLO] = "SC_HELLO";
|
||||
|
||||
m_szGrp[TLK_PLHURT1] = "!SC_CUREA";
|
||||
m_szGrp[TLK_PLHURT2] = "!SC_CUREB";
|
||||
m_szGrp[TLK_PLHURT3] = "!SC_CUREC";
|
||||
|
||||
m_szGrp[TLK_SMELL] = "SC_SMELL";
|
||||
|
||||
m_szGrp[TLK_WOUND] = "SC_WOUND";
|
||||
m_szGrp[TLK_MORTAL] = "SC_MORTAL";
|
||||
|
||||
// get voice for head
|
||||
switch( pev->body % 3 )
|
||||
{
|
||||
default:
|
||||
case HEAD_GLASSES:
|
||||
m_voicePitch = 105;
|
||||
break; //glasses
|
||||
case HEAD_EINSTEIN:
|
||||
m_voicePitch = 100;
|
||||
break; //einstein
|
||||
case HEAD_LUTHER:
|
||||
m_voicePitch = 95;
|
||||
break; //luther
|
||||
case HEAD_SLICK:
|
||||
m_voicePitch = 100;
|
||||
break; //slick
|
||||
}
|
||||
}
|
||||
|
||||
m_szGrp[TLK_PHELLO] = "SC_PHELLO";
|
||||
m_szGrp[TLK_PIDLE] = "SC_PIDLE";
|
||||
m_szGrp[TLK_PQUESTION] = "SC_PQUEST";
|
||||
m_szGrp[TLK_SMELL] = "SC_SMELL";
|
||||
|
||||
m_szGrp[TLK_WOUND] = "SC_WOUND";
|
||||
m_szGrp[TLK_MORTAL] = "SC_MORTAL";
|
||||
|
||||
// get voice for head
|
||||
switch( pev->body % 3 )
|
||||
{
|
||||
default:
|
||||
case HEAD_GLASSES:
|
||||
m_voicePitch = 105;
|
||||
break; //glasses
|
||||
case HEAD_EINSTEIN:
|
||||
m_voicePitch = 100;
|
||||
break; //einstein
|
||||
case HEAD_LUTHER:
|
||||
m_voicePitch = 95;
|
||||
break; //luther
|
||||
case HEAD_SLICK:
|
||||
m_voicePitch = 100;
|
||||
break; //slick
|
||||
}
|
||||
}
|
||||
|
||||
int CScientist::TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType )
|
||||
|
@ -1139,15 +1182,13 @@ LINK_ENTITY_TO_CLASS( monster_scientist_dead, CDeadScientist )
|
|||
void CDeadScientist::Spawn()
|
||||
{
|
||||
if( FClassnameIs( pev, "monster_worker" ) )
|
||||
{
|
||||
PRECACHE_MODEL( "models/gus.mdl" );
|
||||
SET_MODEL( ENT( pev ), "models/gus.mdl" );
|
||||
}
|
||||
pev->model = MAKE_STRING( "models/construction.mdl" );
|
||||
else
|
||||
{
|
||||
PRECACHE_MODEL( "models/scientist.mdl" );
|
||||
SET_MODEL( ENT( pev ), "models/scientist.mdl" );
|
||||
}
|
||||
pev->model = MAKE_STRING( "models/scientist.mdl" );
|
||||
|
||||
PRECACHE_MODEL( STRING( pev->model ) );
|
||||
SET_MODEL( ENT( pev ), STRING( pev->model ) );
|
||||
|
||||
pev->effects = 0;
|
||||
pev->sequence = 0;
|
||||
|
||||
|
@ -1156,17 +1197,20 @@ void CDeadScientist::Spawn()
|
|||
|
||||
m_bloodColor = BLOOD_COLOR_RED;
|
||||
|
||||
if( pev->body == -1 )
|
||||
{
|
||||
// -1 chooses a random head
|
||||
pev->body = RANDOM_LONG( 0, NUM_SCIENTIST_HEADS - 1 );// pick a head, any head
|
||||
}
|
||||
pev->skin = 0;
|
||||
|
||||
// Luther is black, make his hands black
|
||||
if( pev->body == HEAD_LUTHER )
|
||||
pev->skin = 1;
|
||||
else
|
||||
pev->skin = 0;
|
||||
if( !FClassnameIs( pev, "monster_worker" ) )
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
pev->sequence = LookupSequence( m_szPoses[m_iPose] );
|
||||
if( pev->sequence == -1 )
|
||||
|
|
|
@ -41,7 +41,6 @@ enum shotgun_e
|
|||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS( weapon_shotgun, CShotgun )
|
||||
LINK_ENTITY_TO_CLASS( weapon_barneyshotgun, CShotgun )
|
||||
|
||||
void CShotgun::Spawn()
|
||||
{
|
||||
|
@ -56,7 +55,7 @@ void CShotgun::Spawn()
|
|||
|
||||
void CShotgun::Precache( void )
|
||||
{
|
||||
PRECACHE_MODEL( "models/v_barneyshotgun.mdl" );
|
||||
PRECACHE_MODEL( "models/v_shotgun.mdl" );
|
||||
PRECACHE_MODEL( "models/w_shotgun.mdl" );
|
||||
PRECACHE_MODEL( "models/p_shotgun.mdl" );
|
||||
|
||||
|
@ -101,7 +100,7 @@ int CShotgun::GetItemInfo( ItemInfo *p )
|
|||
p->iMaxAmmo2 = -1;
|
||||
p->iMaxClip = SHOTGUN_MAX_CLIP;
|
||||
p->iSlot = 2;
|
||||
p->iPosition = 1;
|
||||
p->iPosition = 2;
|
||||
p->iFlags = 0;
|
||||
p->iId = m_iId = WEAPON_SHOTGUN;
|
||||
p->iWeight = SHOTGUN_WEIGHT;
|
||||
|
@ -111,16 +110,27 @@ int CShotgun::GetItemInfo( ItemInfo *p )
|
|||
|
||||
BOOL CShotgun::Deploy()
|
||||
{
|
||||
return DefaultDeploy( "models/v_barneyshotgun.mdl", "models/p_shotgun.mdl", SHOTGUN_DRAW, "shotgun" );
|
||||
return DefaultDeploy( "models/v_shotgun.mdl", "models/p_shotgun.mdl", SHOTGUN_DRAW, "shotgun" );
|
||||
}
|
||||
|
||||
void CShotgun::Holster( int skiplocal /* = 0 */ )
|
||||
{
|
||||
DefaultHolster( SHOTGUN_HOLSTER, 0.4 );
|
||||
}
|
||||
|
||||
void CShotgun::PrimaryAttack()
|
||||
{
|
||||
if( m_pPlayer->m_bIsHolster )
|
||||
{
|
||||
WeaponIdle();
|
||||
return;
|
||||
}
|
||||
|
||||
// don't fire underwater
|
||||
if( m_pPlayer->pev->waterlevel == 3 )
|
||||
{
|
||||
PlayEmptySound();
|
||||
m_flNextPrimaryAttack = GetNextAttackDelay( 0.15 );
|
||||
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.15;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -176,7 +186,7 @@ void CShotgun::PrimaryAttack()
|
|||
//if( m_iClip != 0 )
|
||||
m_flPumpTime = gpGlobals->time + 0.5;
|
||||
|
||||
m_flNextPrimaryAttack = GetNextAttackDelay( 0.75 );
|
||||
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.75;
|
||||
m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.75;
|
||||
if( m_iClip != 0 )
|
||||
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 5.0;
|
||||
|
@ -187,11 +197,17 @@ void CShotgun::PrimaryAttack()
|
|||
|
||||
void CShotgun::SecondaryAttack( void )
|
||||
{
|
||||
if( m_pPlayer->m_bIsHolster )
|
||||
{
|
||||
WeaponIdle();
|
||||
return;
|
||||
}
|
||||
|
||||
// don't fire underwater
|
||||
if( m_pPlayer->pev->waterlevel == 3 )
|
||||
{
|
||||
PlayEmptySound();
|
||||
m_flNextPrimaryAttack = GetNextAttackDelay( 0.15 );
|
||||
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.15;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -247,18 +263,24 @@ void CShotgun::SecondaryAttack( void )
|
|||
//if( m_iClip != 0 )
|
||||
m_flPumpTime = gpGlobals->time + 0.95;
|
||||
|
||||
m_flNextPrimaryAttack = GetNextAttackDelay( 1.5 );
|
||||
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 1.5;
|
||||
m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 1.5;
|
||||
if( m_iClip != 0 )
|
||||
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 6.0;
|
||||
else
|
||||
m_flTimeWeaponIdle = 1.5;
|
||||
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 1.5;
|
||||
|
||||
m_fInSpecialReload = 0;
|
||||
}
|
||||
|
||||
void CShotgun::Reload( void )
|
||||
{
|
||||
if( m_pPlayer->m_bIsHolster )
|
||||
{
|
||||
WeaponIdle();
|
||||
return;
|
||||
}
|
||||
|
||||
if( m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0 || m_iClip == SHOTGUN_MAX_CLIP )
|
||||
return;
|
||||
|
||||
|
@ -273,7 +295,7 @@ void CShotgun::Reload( void )
|
|||
m_fInSpecialReload = 1;
|
||||
m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.6;
|
||||
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 0.6;
|
||||
m_flNextPrimaryAttack = GetNextAttackDelay( 1.0 );
|
||||
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 1.0;
|
||||
m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 1.0;
|
||||
return;
|
||||
}
|
||||
|
@ -315,6 +337,16 @@ void CShotgun::WeaponTick()
|
|||
|
||||
void CShotgun::WeaponIdle( void )
|
||||
{
|
||||
if( m_pPlayer->m_bIsHolster )
|
||||
{
|
||||
if( m_flTimeWeaponIdle <= UTIL_WeaponTimeBase() )
|
||||
{
|
||||
m_pPlayer->m_bIsHolster = FALSE;
|
||||
Deploy();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
ResetEmptySound();
|
||||
|
||||
m_pPlayer->GetAutoaimVector( AUTOAIM_5DEGREES );
|
||||
|
|
|
@ -936,6 +936,8 @@ void CEnvSound::Think( void )
|
|||
{
|
||||
if( flRange < pPlayer->m_flSndRange || pPlayer->m_flSndRange == 0 )
|
||||
{
|
||||
ALERT( at_console, "env_sound: set to %d - %s \n", (int)m_flRoomtype, UTIL_GetSoundRoomTypeName( m_flRoomtype ) );
|
||||
|
||||
// new entity is closer to player, so it wins.
|
||||
pPlayer->m_pentSndLast = ENT( pev );
|
||||
pPlayer->m_flSndRoomtype = m_flRoomtype;
|
||||
|
@ -979,81 +981,6 @@ void CEnvSound::Spawn()
|
|||
// spread think times
|
||||
pev->nextthink = gpGlobals->time + RANDOM_FLOAT( 0.0, 0.5 );
|
||||
}
|
||||
|
||||
//=====================
|
||||
//LRC - trigger_sound
|
||||
//=====================
|
||||
class CTriggerSound : public CBaseDelay
|
||||
{
|
||||
public:
|
||||
void KeyValue( KeyValueData* pkvd );
|
||||
void Spawn( void );
|
||||
void Touch( CBaseEntity *pOther );
|
||||
|
||||
virtual int Save( CSave &save );
|
||||
virtual int Restore( CRestore &restore );
|
||||
static TYPEDESCRIPTION m_SaveData[];
|
||||
virtual int ObjectCaps( void ) { return CBaseDelay :: ObjectCaps() & ~FCAP_ACROSS_TRANSITION; }
|
||||
|
||||
float m_flRoomtype;
|
||||
string_t m_iszMaster;
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS( trigger_sound, CTriggerSound );
|
||||
TYPEDESCRIPTION CTriggerSound::m_SaveData[] =
|
||||
{
|
||||
DEFINE_FIELD( CTriggerSound, m_flRoomtype, FIELD_FLOAT ),
|
||||
DEFINE_FIELD( CTriggerSound, m_iszMaster, FIELD_FLOAT ),
|
||||
};
|
||||
|
||||
IMPLEMENT_SAVERESTORE( CTriggerSound, CBaseDelay );
|
||||
|
||||
void CTriggerSound::KeyValue( KeyValueData *pkvd )
|
||||
{
|
||||
if( FStrEq( pkvd->szKeyName, "roomtype" ) )
|
||||
{
|
||||
m_flRoomtype = atof( pkvd->szValue );
|
||||
pkvd->fHandled = TRUE;
|
||||
}
|
||||
else if ( FStrEq(pkvd->szKeyName, "master" ) )
|
||||
{
|
||||
m_iszMaster = ALLOC_STRING( pkvd->szValue );
|
||||
pkvd->fHandled = TRUE;
|
||||
}
|
||||
else
|
||||
CBaseEntity::KeyValue( pkvd );
|
||||
}
|
||||
|
||||
void CTriggerSound::Touch( CBaseEntity *pOther )
|
||||
{
|
||||
if( !UTIL_IsMasterTriggered( m_iszMaster, pOther ) ) return;
|
||||
|
||||
if( pOther->IsPlayer() )
|
||||
{
|
||||
CBasePlayer *pPlayer = (CBasePlayer*)pOther;
|
||||
if( pPlayer->m_pentSndLast != this->edict() )
|
||||
{
|
||||
pPlayer->m_pentSndLast = ENT( pev );
|
||||
pPlayer->m_flSndRoomtype = m_flRoomtype;
|
||||
pPlayer->m_flSndRange = 0;
|
||||
|
||||
MESSAGE_BEGIN( MSG_ONE, SVC_ROOMTYPE, NULL, pPlayer->edict() ); // use the magic #1 for "one client"
|
||||
WRITE_SHORT( (short)m_flRoomtype ); // sequence number
|
||||
MESSAGE_END();
|
||||
|
||||
SUB_UseTargets( pPlayer, USE_TOGGLE, 0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CTriggerSound::Spawn()
|
||||
{
|
||||
pev->solid = SOLID_TRIGGER;
|
||||
pev->movetype = MOVETYPE_NONE;
|
||||
SET_MODEL( ENT( pev ), STRING( pev->model ) ); // set size and link into world
|
||||
SetBits( pev->effects, EF_NODRAW );
|
||||
}
|
||||
|
||||
// ==================== SENTENCE GROUPS, UTILITY FUNCTIONS ======================================
|
||||
|
||||
#define CSENTENCE_LRU_MAX 32 // max number of elements per sentence group
|
||||
|
@ -1067,7 +994,7 @@ typedef struct sentenceg
|
|||
unsigned char rgblru[CSENTENCE_LRU_MAX];
|
||||
} SENTENCEG;
|
||||
|
||||
#define CSENTENCEG_MAX 500 // max number of sentence groups
|
||||
#define CSENTENCEG_MAX 210 // max number of sentence groups
|
||||
// globals
|
||||
|
||||
SENTENCEG rgsentenceg[CSENTENCEG_MAX];
|
||||
|
@ -1481,6 +1408,9 @@ void EMIT_SOUND_DYN( edict_t *entity, int channel, const char *sample, float vol
|
|||
|
||||
void EMIT_SOUND_SUIT( edict_t *entity, const char *sample )
|
||||
{
|
||||
if( !UTIL_HasSuit( CBaseEntity::Instance( entity ) ) )
|
||||
return;
|
||||
|
||||
float fvol;
|
||||
int pitch = PITCH_NORM;
|
||||
|
||||
|
@ -1809,7 +1739,7 @@ float TEXTURETYPE_PlaySound( TraceResult *ptr, Vector vecSrc, Vector vecEnd, in
|
|||
cnt = 3;
|
||||
break;
|
||||
case CHAR_TEX_FLESH:
|
||||
if( iBulletType == BULLET_PLAYER_CROWBAR )
|
||||
if( iBulletType == BULLET_PLAYER_CROWBAR || iBulletType == BULLET_PLAYER_POOLSTICK )
|
||||
return 0.0; // crowbar already makes this sound
|
||||
fvol = 1.0;
|
||||
fvolbar = 0.2;
|
||||
|
|
|
@ -433,7 +433,7 @@ void CSqueak::Precache( void )
|
|||
PRECACHE_SOUND( "squeek/sqk_hunt3.wav" );
|
||||
UTIL_PrecacheOther( "monster_snark" );
|
||||
|
||||
m_usSnarkFire = PRECACHE_EVENT( 1, "events/snarkfire.sc" );
|
||||
// m_usSnarkFire = PRECACHE_EVENT( 1, "events/snarkfire.sc" );
|
||||
}
|
||||
|
||||
int CSqueak::GetItemInfo( ItemInfo *p )
|
||||
|
@ -445,7 +445,7 @@ int CSqueak::GetItemInfo( ItemInfo *p )
|
|||
p->iMaxAmmo2 = -1;
|
||||
p->iMaxClip = WEAPON_NOCLIP;
|
||||
p->iSlot = 4;
|
||||
p->iPosition = 3;
|
||||
p->iPosition = 4;
|
||||
p->iId = m_iId = WEAPON_SNARK;
|
||||
p->iWeight = SNARK_WEIGHT;
|
||||
p->iFlags = ITEM_FLAG_LIMITINWORLD | ITEM_FLAG_EXHAUSTIBLE;
|
||||
|
@ -470,8 +470,6 @@ BOOL CSqueak::Deploy()
|
|||
|
||||
void CSqueak::Holster( int skiplocal /* = 0 */ )
|
||||
{
|
||||
m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.5;
|
||||
|
||||
if( !m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] )
|
||||
{
|
||||
m_pPlayer->pev->weapons &= ~( 1 << WEAPON_SNARK );
|
||||
|
@ -479,12 +477,18 @@ void CSqueak::Holster( int skiplocal /* = 0 */ )
|
|||
return;
|
||||
}
|
||||
|
||||
SendWeaponAnim( SQUEAK_DOWN );
|
||||
DefaultHolster( SQUEAK_DOWN, 1.5 );
|
||||
EMIT_SOUND( ENT( m_pPlayer->pev ), CHAN_WEAPON, "common/null.wav", 1.0, ATTN_NORM );
|
||||
}
|
||||
|
||||
void CSqueak::PrimaryAttack()
|
||||
{
|
||||
if( m_pPlayer->m_bIsHolster )
|
||||
{
|
||||
WeaponIdle();
|
||||
return;
|
||||
}
|
||||
|
||||
if( m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] )
|
||||
{
|
||||
UTIL_MakeVectors( m_pPlayer->pev->v_angle );
|
||||
|
@ -502,16 +506,10 @@ void CSqueak::PrimaryAttack()
|
|||
// find place to toss monster
|
||||
UTIL_TraceLine( trace_origin + gpGlobals->v_forward * 20, trace_origin + gpGlobals->v_forward * 64, dont_ignore_monsters, NULL, &tr );
|
||||
|
||||
int flags;
|
||||
#ifdef CLIENT_WEAPONS
|
||||
flags = FEV_NOTHOST;
|
||||
#else
|
||||
flags = 0;
|
||||
#endif
|
||||
PLAYBACK_EVENT_FULL( flags, m_pPlayer->edict(), m_usSnarkFire, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, 0, 0, 0, 0 );
|
||||
|
||||
if( tr.fAllSolid == 0 && tr.fStartSolid == 0 && tr.flFraction > 0.25 )
|
||||
{
|
||||
SendWeaponAnim( SQUEAK_THROW );
|
||||
|
||||
// player "shoot" animation
|
||||
m_pPlayer->SetAnimation( PLAYER_ATTACK1 );
|
||||
#ifndef CLIENT_DLL
|
||||
|
@ -532,7 +530,7 @@ void CSqueak::PrimaryAttack()
|
|||
|
||||
m_fJustThrown = 1;
|
||||
|
||||
m_flNextPrimaryAttack = GetNextAttackDelay( 0.3 );
|
||||
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.3;
|
||||
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 1.0;
|
||||
}
|
||||
}
|
||||
|
@ -540,11 +538,25 @@ void CSqueak::PrimaryAttack()
|
|||
|
||||
void CSqueak::SecondaryAttack( void )
|
||||
{
|
||||
|
||||
if( m_pPlayer->m_bIsHolster )
|
||||
{
|
||||
WeaponIdle();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void CSqueak::WeaponIdle( void )
|
||||
{
|
||||
if( m_pPlayer->m_bIsHolster )
|
||||
{
|
||||
if( m_flTimeWeaponIdle <= UTIL_WeaponTimeBase() )
|
||||
{
|
||||
m_pPlayer->m_bIsHolster = FALSE;
|
||||
Deploy();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if( m_flTimeWeaponIdle > UTIL_WeaponTimeBase() )
|
||||
return;
|
||||
|
||||
|
|
|
@ -59,7 +59,10 @@ const char *CTalkMonster::m_szFriends[TLK_CFRIENDS] =
|
|||
"monster_barniel",
|
||||
"monster_hevbarn",
|
||||
"monster_kate",
|
||||
"monster_worker"
|
||||
"monster_worker",
|
||||
"monster_myself",
|
||||
"monster_gordon",
|
||||
"monster_adrian"
|
||||
};
|
||||
|
||||
//=========================================================
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
#define bit_saidHeard (1<<6)
|
||||
#define bit_saidSmelled (1<<7)
|
||||
|
||||
#define TLK_CFRIENDS 7
|
||||
#define TLK_CFRIENDS 10
|
||||
|
||||
typedef enum
|
||||
{
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#define SF_TRACKTRAIN_NOCONTROL 0x0002
|
||||
#define SF_TRACKTRAIN_FORWARDONLY 0x0004
|
||||
#define SF_TRACKTRAIN_PASSABLE 0x0008
|
||||
#define SF_TRACKTRAIN_CAR 0x0010
|
||||
|
||||
// Spawnflag for CPathTrack
|
||||
#define SF_PATH_DISABLED 0x00000001
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "saverestore.h"
|
||||
#include "trains.h" // trigger_camera has train functionality
|
||||
#include "gamerules.h"
|
||||
#include "skill.h"
|
||||
|
||||
#define SF_TRIGGER_PUSH_START_OFF 2//spawnflag that makes trigger_push spawn turned OFF
|
||||
#define SF_TRIGGER_HURT_TARGETONCE 1// Only fire hurt target once
|
||||
|
@ -1095,8 +1096,15 @@ void CBaseTrigger::MultiTouch( CBaseEntity *pOther )
|
|||
|
||||
pevToucher = pOther->pev;
|
||||
|
||||
if( FBitSet( pev->spawnflags, SF_TRIGGER_KATEONLY ) )
|
||||
{
|
||||
if( FClassnameIs( pevToucher, "monster_kate" ) )
|
||||
{
|
||||
ActivateMultiTrigger( pOther );
|
||||
}
|
||||
}
|
||||
// Only touch clients, monsters, or pushables (depending on flags)
|
||||
if( ( ( pevToucher->flags & FL_CLIENT ) && !( pev->spawnflags & SF_TRIGGER_NOCLIENTS ) ) ||
|
||||
else if( ( ( pevToucher->flags & FL_CLIENT ) && !( pev->spawnflags & SF_TRIGGER_NOCLIENTS ) ) ||
|
||||
( ( pevToucher->flags & FL_MONSTER ) && (pev->spawnflags & SF_TRIGGER_ALLOWMONSTERS ) ) ||
|
||||
( ( pev->spawnflags & SF_TRIGGER_PUSHABLES ) && FClassnameIs( pevToucher,"func_pushable" ) ) )
|
||||
{
|
||||
|
@ -2381,3 +2389,169 @@ void CTriggerCamera::Move()
|
|||
float fraction = 2 * gpGlobals->frametime;
|
||||
pev->velocity = ( ( pev->movedir * pev->speed ) * fraction ) + ( pev->velocity * ( 1 - fraction ) );
|
||||
}
|
||||
|
||||
class CTriggerDie : public CBaseTrigger
|
||||
{
|
||||
public:
|
||||
void KeyValue( KeyValueData *pkvd );
|
||||
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
|
||||
|
||||
int Save( CSave &save );
|
||||
int Restore( CRestore &restore );
|
||||
|
||||
static TYPEDESCRIPTION m_SaveData[];
|
||||
|
||||
private:
|
||||
string_t m_szMonsterName;
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS( trigger_die, CTriggerDie )
|
||||
|
||||
TYPEDESCRIPTION CTriggerDie::m_SaveData[] =
|
||||
{
|
||||
DEFINE_FIELD( CTriggerDie, m_szMonsterName, FIELD_STRING ),
|
||||
};
|
||||
|
||||
IMPLEMENT_SAVERESTORE( CTriggerDie, CBaseTrigger )
|
||||
|
||||
void CTriggerDie::KeyValue( KeyValueData *pkvd )
|
||||
{
|
||||
if( FStrEq( pkvd->szKeyName, "monstername" ) )
|
||||
{
|
||||
m_szMonsterName = ALLOC_STRING( pkvd->szValue );
|
||||
pkvd->fHandled = TRUE;
|
||||
}
|
||||
else
|
||||
CBaseTrigger::KeyValue( pkvd );
|
||||
}
|
||||
|
||||
void CTriggerDie::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
|
||||
{
|
||||
CBaseEntity *pEntity = UTIL_FindEntityByTargetname( 0, STRING( m_szMonsterName ) );
|
||||
if( pEntity )
|
||||
{
|
||||
float flDmg = pEntity->pev->health + 1.0f;
|
||||
pEntity->TakeDamage( pev, pev, flDmg, 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
ALERT( at_console, "trigger_die: didn't find monster!\n" );
|
||||
}
|
||||
}
|
||||
|
||||
class CTriggerLoadHazard : public CBaseTrigger
|
||||
{
|
||||
public:
|
||||
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS( trigger_loadhazard, CTriggerLoadHazard )
|
||||
|
||||
void CTriggerLoadHazard::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
|
||||
{
|
||||
if( pActivator && pActivator->IsPlayer() )
|
||||
{
|
||||
ALERT( at_console, "trigger_loadhazard: loading t0a0 - Hazard Course\n" );
|
||||
CHANGE_LEVEL( "t0a0", 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
ALERT( at_console, "trigger_loadhazard: not player activate\n" );
|
||||
}
|
||||
}
|
||||
|
||||
class CTriggerKateHealth : public CBaseTrigger
|
||||
{
|
||||
public:
|
||||
void KeyValue( KeyValueData *pkvd );
|
||||
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
|
||||
|
||||
int Save( CSave &save );
|
||||
int Restore( CRestore &restore );
|
||||
|
||||
static TYPEDESCRIPTION m_SaveData[];
|
||||
|
||||
private:
|
||||
string_t m_szKateName;
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS( trigger_katehealth, CTriggerKateHealth )
|
||||
|
||||
TYPEDESCRIPTION CTriggerKateHealth::m_SaveData[] =
|
||||
{
|
||||
DEFINE_FIELD( CTriggerKateHealth, m_szKateName, FIELD_STRING ),
|
||||
};
|
||||
|
||||
IMPLEMENT_SAVERESTORE( CTriggerKateHealth, CBaseTrigger )
|
||||
|
||||
void CTriggerKateHealth::KeyValue( KeyValueData *pkvd )
|
||||
{
|
||||
if( FStrEq( pkvd->szKeyName, "katename" ) )
|
||||
{
|
||||
m_szKateName = ALLOC_STRING( pkvd->szValue );
|
||||
pkvd->fHandled = TRUE;
|
||||
}
|
||||
else
|
||||
CBaseTrigger::KeyValue( pkvd );
|
||||
}
|
||||
|
||||
void CTriggerKateHealth::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
|
||||
{
|
||||
CBaseEntity *pEntity = UTIL_FindEntityByTargetname( 0, STRING( m_szKateName ) );
|
||||
if( pEntity )
|
||||
{
|
||||
ALERT( at_console, "trigger_katehealth: Kate health before: %f\n", pEntity->pev->health );
|
||||
pEntity->pev->health = gSkillData.kateHealth;
|
||||
ALERT( at_console, "trigger_katehealth: Kate health after: %f\n", pEntity->pev->health );
|
||||
}
|
||||
else
|
||||
{
|
||||
ALERT( at_console, "trigger_katehealth: didn't find kate!\n" );
|
||||
}
|
||||
}
|
||||
|
||||
class CTriggerSound : public CBaseTrigger
|
||||
{
|
||||
public:
|
||||
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
|
||||
void Touch( CBaseEntity *pOther );
|
||||
void ChangeSoundRoom( float roomtype, float range );
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS( trigger_sound, CTriggerSound )
|
||||
|
||||
void CTriggerSound::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
|
||||
{
|
||||
ChangeSoundRoom( pev->health, 64.0f );
|
||||
}
|
||||
|
||||
void CTriggerSound::Touch( CBaseEntity *pOther )
|
||||
{
|
||||
if( pOther->IsPlayer() )
|
||||
ChangeSoundRoom( pev->health, 64.0f );
|
||||
}
|
||||
|
||||
void CTriggerSound::ChangeSoundRoom( float roomtype, float range )
|
||||
{
|
||||
CBasePlayer *pPlayer = (CBasePlayer *)UTIL_FindEntityByClassname( 0, "player" );
|
||||
if( pPlayer->m_flSndRoomtype != roomtype )
|
||||
{
|
||||
if( pPlayer->pev->waterlevel == 3 )
|
||||
{
|
||||
ALERT( at_console, "trigger_sound: underwater not setting to %d - %s\n", (int)roomtype, UTIL_GetSoundRoomTypeName( roomtype ) );
|
||||
pPlayer->m_flSndRoomtype = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
pPlayer->m_pentSndLast = ENT( pev );
|
||||
pPlayer->m_flSndRoomtype = roomtype;
|
||||
pPlayer->m_flSndRange = range;
|
||||
|
||||
ALERT( at_console, "trigger_sound: set to %d - %s \n", (int)roomtype, UTIL_GetSoundRoomTypeName( roomtype ) );
|
||||
|
||||
MESSAGE_BEGIN( MSG_ONE, SVC_ROOMTYPE, 0, pPlayer->edict() ); // use the magic #1 for "one client"
|
||||
WRITE_SHORT( (short)roomtype ); // sequence number
|
||||
MESSAGE_END();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -384,7 +384,7 @@ void CTripmine::Precache( void )
|
|||
PRECACHE_MODEL( "models/p_tripmine.mdl" );
|
||||
UTIL_PrecacheOther( "monster_tripmine" );
|
||||
|
||||
m_usTripFire = PRECACHE_EVENT( 1, "events/tripfire.sc" );
|
||||
//m_usTripFire = PRECACHE_EVENT( 1, "events/tripfire.sc" );
|
||||
}
|
||||
|
||||
int CTripmine::GetItemInfo( ItemInfo *p )
|
||||
|
@ -396,7 +396,7 @@ int CTripmine::GetItemInfo( ItemInfo *p )
|
|||
p->iMaxAmmo2 = -1;
|
||||
p->iMaxClip = WEAPON_NOCLIP;
|
||||
p->iSlot = 4;
|
||||
p->iPosition = 2;
|
||||
p->iPosition = 3;
|
||||
p->iId = m_iId = WEAPON_TRIPMINE;
|
||||
p->iWeight = TRIPMINE_WEIGHT;
|
||||
p->iFlags = ITEM_FLAG_LIMITINWORLD | ITEM_FLAG_EXHAUSTIBLE;
|
||||
|
@ -421,12 +421,18 @@ void CTripmine::Holster( int skiplocal /* = 0 */ )
|
|||
DestroyItem();
|
||||
}
|
||||
|
||||
SendWeaponAnim( TRIPMINE_HOLSTER );
|
||||
DefaultHolster( TRIPMINE_HOLSTER, 0.7 );
|
||||
EMIT_SOUND( ENT( m_pPlayer->pev ), CHAN_WEAPON, "common/null.wav", 1.0, ATTN_NORM );
|
||||
}
|
||||
|
||||
void CTripmine::PrimaryAttack( void )
|
||||
{
|
||||
if( m_pPlayer->m_bIsHolster )
|
||||
{
|
||||
WeaponIdle();
|
||||
return;
|
||||
}
|
||||
|
||||
if( m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0 )
|
||||
return;
|
||||
|
||||
|
@ -438,14 +444,6 @@ void CTripmine::PrimaryAttack( void )
|
|||
|
||||
UTIL_TraceLine( vecSrc, vecSrc + vecAiming * 128, dont_ignore_monsters, ENT( m_pPlayer->pev ), &tr );
|
||||
|
||||
int flags;
|
||||
#ifdef CLIENT_WEAPONS
|
||||
flags = FEV_NOTHOST;
|
||||
#else
|
||||
flags = 0;
|
||||
#endif
|
||||
PLAYBACK_EVENT_FULL( flags, m_pPlayer->edict(), m_usTripFire, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, 0, 0, 0, 0 );
|
||||
|
||||
if( tr.flFraction < 1.0 )
|
||||
{
|
||||
CBaseEntity *pEntity = CBaseEntity::Instance( tr.pHit );
|
||||
|
@ -477,12 +475,22 @@ void CTripmine::PrimaryAttack( void )
|
|||
|
||||
}*/
|
||||
|
||||
m_flNextPrimaryAttack = GetNextAttackDelay( 0.3 );
|
||||
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.3;
|
||||
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + UTIL_SharedRandomFloat( m_pPlayer->random_seed, 10, 15 );
|
||||
}
|
||||
|
||||
void CTripmine::WeaponIdle( void )
|
||||
{
|
||||
if( m_pPlayer->m_bIsHolster )
|
||||
{
|
||||
if( m_flTimeWeaponIdle <= UTIL_WeaponTimeBase() )
|
||||
{
|
||||
m_pPlayer->m_bIsHolster = FALSE;
|
||||
Deploy();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if( m_flTimeWeaponIdle > UTIL_WeaponTimeBase() )
|
||||
return;
|
||||
|
||||
|
|
203
dlls/util.cpp
203
dlls/util.cpp
|
@ -30,6 +30,209 @@
|
|||
#include "player.h"
|
||||
#include "weapons.h"
|
||||
#include "gamerules.h"
|
||||
#include "soundent.h"
|
||||
|
||||
void UTIL_CreateWarpball( edict_t *ent, Vector vecSrc, float spawnVol, float spawnSoundRad, int beamCount, int spawnType, float spriteScale, int lightRad )
|
||||
{
|
||||
Vector vecBeamColor, vecFlareColor, vecExpColor, vecDir, vecEnd;
|
||||
TraceResult tr;
|
||||
|
||||
if( spawnType == 1 )
|
||||
{
|
||||
vecBeamColor = Vector( 255, 128, 255 );
|
||||
vecFlareColor = vecBeamColor;
|
||||
vecExpColor = Vector( 128, 0, 128 );
|
||||
}
|
||||
else
|
||||
{
|
||||
vecBeamColor = Vector( 197, 243, 169 );
|
||||
vecFlareColor = Vector( 77, 210, 130 );
|
||||
vecExpColor = Vector( 184, 250, 214 );
|
||||
}
|
||||
|
||||
if( beamCount < 1 )
|
||||
beamCount = 16;
|
||||
|
||||
if( spriteScale <= 0.0f )
|
||||
spriteScale = 1.0f;
|
||||
|
||||
if( spawnSoundRad != ATTN_NONE
|
||||
&& spawnSoundRad != ATTN_NORM
|
||||
&& spawnSoundRad != ATTN_IDLE
|
||||
&& spawnSoundRad != ATTN_STATIC )
|
||||
spawnSoundRad = ATTN_NORM;
|
||||
|
||||
if( spawnVol <= 0.0f || spawnVol > 1.0f )
|
||||
spawnVol = 1.0f;
|
||||
|
||||
if( lightRad <= 0 )
|
||||
lightRad = 24;
|
||||
|
||||
UTIL_EmitAmbientSound( ent, vecSrc, "ambience/spawnsnd.wav", spawnVol, spawnSoundRad, 0, PITCH_NORM );
|
||||
CSoundEnt::InsertSound( bits_SOUND_COMBAT, vecSrc, 384, 0.3 );
|
||||
|
||||
while( beamCount > 0 )
|
||||
{
|
||||
vecDir = Vector( RANDOM_LONG( -1.0f, 1.0f ), RANDOM_LONG( -1.0f, 1.0f ), RANDOM_LONG( -1.0f, 1.0f ) );
|
||||
vecDir = vecDir.Normalize();
|
||||
UTIL_TraceLine( vecSrc, vecSrc + vecDir * 1024, ignore_monsters, ent, &tr );
|
||||
|
||||
vecEnd = tr.vecEndPos;
|
||||
if( ( vecEnd - vecSrc ).Length() >= ( 1024 * 0.1f ) && tr.flFraction != 1.0 )
|
||||
{
|
||||
MESSAGE_BEGIN( MSG_BROADCAST, SVC_TEMPENTITY );
|
||||
WRITE_BYTE( TE_BEAMPOINTS );
|
||||
WRITE_COORD( vecSrc.x );
|
||||
WRITE_COORD( vecSrc.y );
|
||||
WRITE_COORD( vecSrc.z );
|
||||
WRITE_COORD( vecEnd.x );
|
||||
WRITE_COORD( vecEnd.y );
|
||||
WRITE_COORD( vecEnd.z );
|
||||
WRITE_SHORT( g_sModelIndexLightning );
|
||||
WRITE_BYTE( RANDOM_LONG( 0, 3 ) );
|
||||
WRITE_BYTE( 10 );
|
||||
WRITE_BYTE( 8 );
|
||||
WRITE_BYTE( 18 );
|
||||
WRITE_BYTE( 65 );
|
||||
WRITE_BYTE( vecBeamColor.x );
|
||||
WRITE_BYTE( vecBeamColor.y );
|
||||
WRITE_BYTE( vecBeamColor.z );
|
||||
WRITE_BYTE( 150 );
|
||||
WRITE_BYTE( 35 );
|
||||
MESSAGE_END();
|
||||
}
|
||||
--beamCount;
|
||||
}
|
||||
|
||||
MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, vecSrc );
|
||||
WRITE_BYTE( TE_DLIGHT );
|
||||
WRITE_COORD( vecSrc.x ); // X
|
||||
WRITE_COORD( vecSrc.y ); // Y
|
||||
WRITE_COORD( vecSrc.z ); // Z
|
||||
WRITE_BYTE( lightRad ); // radius * 0.1
|
||||
WRITE_BYTE( vecFlareColor.x ); // r
|
||||
WRITE_BYTE( vecFlareColor.y ); // g
|
||||
WRITE_BYTE( vecFlareColor.z ); // b
|
||||
WRITE_BYTE( 16 ); // time * 10
|
||||
WRITE_BYTE( 0 ); // decay * 0.1
|
||||
MESSAGE_END();
|
||||
|
||||
UTIL_CreateSprite( "sprites/xflare1.spr", vecSrc, vecFlareColor, spriteScale );
|
||||
UTIL_CreateSprite( "sprites/fexplo1.spr", vecSrc, vecExpColor, spriteScale );
|
||||
}
|
||||
|
||||
void UTIL_CreateSprite( const char *spriteName, Vector origin, Vector color, float scale )
|
||||
{
|
||||
CSprite *pSprite = CSprite::SpriteCreate( spriteName, origin, TRUE );
|
||||
pSprite->AnimateAndDie( 10 );
|
||||
pSprite->SetTransparency( kRenderTransAdd, color.x, color.y, color.z, 255, kRenderFxNoDissipation );
|
||||
pSprite->SetScale( scale );
|
||||
}
|
||||
|
||||
bool UTIL_HasSuit( CBaseEntity *pEntity )
|
||||
{
|
||||
return ( (CBasePlayer*)pEntity )->m_bHaveSuit;
|
||||
}
|
||||
|
||||
void UTIL_ShowKateHealth( int health )
|
||||
{
|
||||
hudtextparms_t textParams;
|
||||
char msg[32];
|
||||
|
||||
textParams.channel = 1;
|
||||
textParams.x = 0.03f;
|
||||
textParams.y = 0.9f;
|
||||
textParams.effect = 0;
|
||||
if( health > 40 )
|
||||
{
|
||||
textParams.a1 = 100;
|
||||
textParams.r1 = 64;
|
||||
textParams.g1 = 64;
|
||||
textParams.b1 = 255;
|
||||
}
|
||||
else
|
||||
{
|
||||
textParams.a1 = 0;
|
||||
textParams.r1 = 255;
|
||||
textParams.g1 = 0;
|
||||
textParams.b1 = 0;
|
||||
}
|
||||
|
||||
textParams.fadeinTime = 0.0f;
|
||||
textParams.fadeoutTime = 0.5f;
|
||||
textParams.holdTime = 3.0f;
|
||||
textParams.fxTime = 0.25f;
|
||||
|
||||
sprintf( msg, "Kate's health: %d", health );
|
||||
UTIL_HudMessageAll( textParams, msg );
|
||||
}
|
||||
|
||||
const char *UTIL_GetSoundRoomTypeName( int number )
|
||||
{
|
||||
switch( number )
|
||||
{
|
||||
case 0:
|
||||
return "Normal (off)";
|
||||
case 1:
|
||||
return "Generic";
|
||||
case 2:
|
||||
return "Metal Small";
|
||||
case 3:
|
||||
return "Metal Medium";
|
||||
case 4:
|
||||
return "Metal Large";
|
||||
case 5:
|
||||
return "Tunnel Small";
|
||||
case 6:
|
||||
return "Tunnel Medium";
|
||||
case 7:
|
||||
return "Tunnel Large";
|
||||
case 8:
|
||||
return "Chamber Small";
|
||||
case 9:
|
||||
return "Chamber Medium";
|
||||
case 10:
|
||||
return "Chamber Large";
|
||||
case 11:
|
||||
return "Bright Small";
|
||||
case 12:
|
||||
return "Bright Medium";
|
||||
case 13:
|
||||
return "Bright Large";
|
||||
case 14:
|
||||
return "Water 1";
|
||||
case 15:
|
||||
return "Water 2";
|
||||
case 16:
|
||||
return "Water 3";
|
||||
case 17:
|
||||
return "Concrete Small";
|
||||
case 18:
|
||||
return "Concrete Medium";
|
||||
case 19:
|
||||
return "Concrete Large";
|
||||
case 20:
|
||||
return "Big 1";
|
||||
case 21:
|
||||
return "Big 2";
|
||||
case 22:
|
||||
return "Big 3";
|
||||
case 23:
|
||||
return "Cavern Small";
|
||||
case 24:
|
||||
return "Cavern Medium";
|
||||
case 25:
|
||||
return "Cavern Large";
|
||||
case 26:
|
||||
return "Pipe Medium";
|
||||
case 27:
|
||||
return "Pipe Small";
|
||||
case 28:
|
||||
return "Pipe Big?";
|
||||
default:
|
||||
return "????";
|
||||
}
|
||||
}
|
||||
|
||||
float UTIL_WeaponTimeBase( void )
|
||||
{
|
||||
|
|
|
@ -471,6 +471,7 @@ extern DLL_GLOBAL int g_Language;
|
|||
#define SF_TRIGGER_ALLOWMONSTERS 1// monsters allowed to fire this trigger
|
||||
#define SF_TRIGGER_NOCLIENTS 2// players not allowed to fire this trigger
|
||||
#define SF_TRIGGER_PUSHABLES 4// only pushables can fire this trigger
|
||||
#define SF_TRIGGER_KATEONLY 8
|
||||
|
||||
// func breakable
|
||||
#define SF_BREAK_TRIGGER_ONLY 1// may only be broken by trigger
|
||||
|
@ -578,4 +579,9 @@ int UTIL_SharedRandomLong( unsigned int seed, int low, int high );
|
|||
float UTIL_SharedRandomFloat( unsigned int seed, float low, float high );
|
||||
|
||||
float UTIL_WeaponTimeBase( void );
|
||||
const char *UTIL_GetSoundRoomTypeName( int number );
|
||||
void UTIL_CreateWarpball( edict_t *ent, Vector vecSrc, float spawnVol, float spawnSoundRad, int beamCount, int spawnType, float spriteScale, int lightRad );
|
||||
bool UTIL_HasSuit( CBaseEntity *pEntity );
|
||||
void UTIL_ShowKateHealth( int health );
|
||||
void UTIL_CreateSprite( const char *spriteName, Vector origin, Vector color, float scale );
|
||||
#endif // UTIL_H
|
||||
|
|
|
@ -45,6 +45,7 @@ DLL_GLOBAL short g_sModelIndexWExplosion;// holds the index for the underwater e
|
|||
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_sModelIndexLightning;// holds the sprite index for lightning
|
||||
|
||||
ItemInfo CBasePlayerItem::ItemInfoArray[MAX_WEAPONS];
|
||||
AmmoInfo CBasePlayerItem::AmmoInfoArray[MAX_AMMO_SLOTS];
|
||||
|
@ -168,9 +169,9 @@ void DecalGunshot( TraceResult *pTrace, int iBulletType )
|
|||
case BULLET_PLAYER_MP5:
|
||||
case BULLET_MONSTER_MP5:
|
||||
case BULLET_PLAYER_BUCKSHOT:
|
||||
case BULLET_PLAYER_BERETTA:
|
||||
case BULLET_PLAYER_357:
|
||||
case BULLET_PLAYER_M41A: // Alex
|
||||
case BULLET_MONSTER_M41A: // Alex
|
||||
default:
|
||||
// smoke and decal
|
||||
UTIL_GunshotDecalTrace( pTrace, DamageDecal( pEntity, DMG_BULLET ) );
|
||||
|
@ -180,6 +181,7 @@ void DecalGunshot( TraceResult *pTrace, int iBulletType )
|
|||
UTIL_GunshotDecalTrace( pTrace, DamageDecal( pEntity, DMG_BULLET ) );
|
||||
break;
|
||||
case BULLET_PLAYER_CROWBAR:
|
||||
case BULLET_PLAYER_POOLSTICK:
|
||||
// wall decal
|
||||
UTIL_DecalTrace( pTrace, DamageDecal( pEntity, DMG_CLUB ) );
|
||||
break;
|
||||
|
@ -296,6 +298,7 @@ void W_Precache( void )
|
|||
// custom items...
|
||||
|
||||
// common world objects
|
||||
UTIL_PrecacheOther( "item_armor" );
|
||||
UTIL_PrecacheOther( "item_suit" );
|
||||
UTIL_PrecacheOther( "item_healthkit" );
|
||||
UTIL_PrecacheOther( "item_battery" );
|
||||
|
@ -322,6 +325,12 @@ void W_Precache( void )
|
|||
UTIL_PrecacheOther( "ammo_9mmAR" );
|
||||
UTIL_PrecacheOther( "ammo_ARgrenades" );
|
||||
|
||||
// Weapons with Barney's hands.
|
||||
UTIL_PrecacheOtherWeapon( "weapon_barney9mmhg" );
|
||||
UTIL_PrecacheOtherWeapon( "weapon_barneyshotgun" );
|
||||
UTIL_PrecacheOtherWeapon( "weapon_barneyhandgrenade" );
|
||||
UTIL_PrecacheOtherWeapon( "weapon_barney9mmar" );
|
||||
|
||||
// begin Alex
|
||||
// m41a
|
||||
UTIL_PrecacheOtherWeapon( "weapon_9mmm41a" );
|
||||
|
@ -368,6 +377,9 @@ void W_Precache( void )
|
|||
// toad
|
||||
UTIL_PrecacheOtherWeapon( "weapon_toad" ); // Alex
|
||||
|
||||
// Kate's medickit
|
||||
UTIL_PrecacheOtherWeapon( "weapon_kmedkit" );
|
||||
|
||||
// hornetgun
|
||||
UTIL_PrecacheOtherWeapon( "weapon_hornetgun" );
|
||||
|
||||
|
@ -385,6 +397,7 @@ void W_Precache( void )
|
|||
|
||||
g_sModelIndexLaser = PRECACHE_MODEL( g_pModelNameLaser );
|
||||
g_sModelIndexLaserDot = PRECACHE_MODEL( "sprites/laserdot.spr" );
|
||||
g_sModelIndexLightning = PRECACHE_MODEL( "sprites/lgtning.spr" );
|
||||
|
||||
// used by explosions
|
||||
PRECACHE_MODEL( "models/grenade.mdl" );
|
||||
|
@ -629,16 +642,14 @@ void CBasePlayerWeapon::ItemPostFrame( void )
|
|||
m_iClip += j;
|
||||
m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] -= j;
|
||||
|
||||
m_pPlayer->TabulateAmmo();
|
||||
|
||||
m_fInReload = FALSE;
|
||||
}
|
||||
|
||||
if( !(m_pPlayer->pev->button & IN_ATTACK ) )
|
||||
/* 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()] )
|
||||
|
@ -646,7 +657,6 @@ void CBasePlayerWeapon::ItemPostFrame( void )
|
|||
m_fFireOnEmpty = TRUE;
|
||||
}
|
||||
|
||||
m_pPlayer->TabulateAmmo();
|
||||
SecondaryAttack();
|
||||
m_pPlayer->pev->button &= ~IN_ATTACK2;
|
||||
}
|
||||
|
@ -657,7 +667,6 @@ void CBasePlayerWeapon::ItemPostFrame( void )
|
|||
m_fFireOnEmpty = TRUE;
|
||||
}
|
||||
|
||||
m_pPlayer->TabulateAmmo();
|
||||
PrimaryAttack();
|
||||
}
|
||||
else if( m_pPlayer->pev->button & IN_RELOAD && iMaxClip() != WEAPON_NOCLIP && !m_fInReload )
|
||||
|
@ -962,7 +971,6 @@ BOOL CBasePlayerWeapon::DefaultDeploy( const char *szViewModel, const char *szWe
|
|||
if( !CanDeploy() )
|
||||
return FALSE;
|
||||
|
||||
m_pPlayer->TabulateAmmo();
|
||||
m_pPlayer->pev->viewmodel = MAKE_STRING( szViewModel );
|
||||
m_pPlayer->pev->weaponmodel = MAKE_STRING( szWeaponModel );
|
||||
strcpy( m_pPlayer->m_szAnimExtention, szAnimExt );
|
||||
|
@ -970,11 +978,19 @@ BOOL CBasePlayerWeapon::DefaultDeploy( const char *szViewModel, const char *szWe
|
|||
|
||||
m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.5;
|
||||
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 1.0;
|
||||
m_flLastFireTime = 0.0f;
|
||||
// m_flLastFireTime = 0.0f;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void CBasePlayerWeapon::DefaultHolster( int iAnim, float fDelay )
|
||||
{
|
||||
m_fInReload = FALSE;
|
||||
SendWeaponAnim( iAnim );
|
||||
m_flNextPrimaryAttack = m_flNextSecondaryAttack = m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + fDelay;
|
||||
m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + fDelay;
|
||||
}
|
||||
|
||||
BOOL CBasePlayerWeapon::DefaultReload( int iClipSize, int iAnim, float fDelay, int body )
|
||||
{
|
||||
if( m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0 )
|
||||
|
@ -1644,3 +1660,12 @@ TYPEDESCRIPTION CSatchel::m_SaveData[] =
|
|||
};
|
||||
|
||||
IMPLEMENT_SAVERESTORE( CSatchel, CBasePlayerWeapon )
|
||||
|
||||
TYPEDESCRIPTION CKMedKit::m_SaveData[] =
|
||||
{
|
||||
DEFINE_FIELD( CKMedKit, m_bIsStateChanged, FIELD_BOOLEAN ),
|
||||
DEFINE_FIELD( CKMedKit, m_iState, FIELD_INTEGER ),
|
||||
DEFINE_FIELD( CKMedKit, m_iKateHealth, FIELD_INTEGER ),
|
||||
};
|
||||
|
||||
IMPLEMENT_SAVERESTORE( CKMedKit, CBasePlayerWeapon )
|
||||
|
|
136
dlls/weapons.h
136
dlls/weapons.h
|
@ -32,7 +32,7 @@ public:
|
|||
typedef enum { SATCHEL_DETONATE = 0, SATCHEL_RELEASE } SATCHELCODE;
|
||||
|
||||
static CGrenade *ShootTimed( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity, float time );
|
||||
static CGrenade *ShootContact( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity );
|
||||
static CGrenade *ShootContact( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity, float flDmg );
|
||||
static CGrenade *ShootSatchelCharge( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity );
|
||||
static void UseSatchelCharges( entvars_t *pevOwner, SATCHELCODE code );
|
||||
|
||||
|
@ -80,11 +80,15 @@ public:
|
|||
#define WEAPON_SNARK 15
|
||||
//begin Alex
|
||||
#define WEAPON_M41A 16
|
||||
#define WEAPON_BERETTA 17
|
||||
#define WEAPON_POOLSTICK 18
|
||||
#define WEAPON_TOAD 19
|
||||
#define WEAPON_KMEDKIT 20
|
||||
#define WEAPON_TOAD 17
|
||||
#define WEAPON_BERETTA 18
|
||||
#define WEAPON_POOLSTICK 19
|
||||
//end Alex
|
||||
#define WEAPON_BARNEYGLOCK 20
|
||||
#define WEAPON_BARNEYMP5 21
|
||||
#define WEAPON_BARNEYHANDGRENADE 22
|
||||
#define WEAPON_BARNEYSHOTGUN 23
|
||||
#define WEAPON_KMEDKIT 24
|
||||
|
||||
#define WEAPON_ALLWEAPONS (~(1<<WEAPON_SUIT))
|
||||
|
||||
|
@ -109,8 +113,9 @@ public:
|
|||
#define SNARK_WEIGHT 5
|
||||
#define SATCHEL_WEIGHT -10
|
||||
#define TRIPMINE_WEIGHT -10
|
||||
#define TOAD_WEIGHT 10 // Alex
|
||||
#define KMEDKIT_WEIGHT 10 // Alex
|
||||
#define TOAD_WEIGHT 8 // Alex
|
||||
#define KMEDKIT_WEIGHT 0 // Alex
|
||||
#define M41A_WEIGHT 18
|
||||
|
||||
// weapon clip/carry ammo capacities
|
||||
#define URANIUM_MAX_CARRY 100
|
||||
|
@ -125,8 +130,8 @@ public:
|
|||
#define SNARK_MAX_CARRY 15
|
||||
#define HORNET_MAX_CARRY 8
|
||||
#define M203_GRENADE_MAX_CARRY 10
|
||||
#define TOAD_MAX_CARRY 250 // Alex
|
||||
#define KMEDKIT_MAX_CARRY 250 // Alex
|
||||
#define TOAD_MAX_CARRY 12 // Alex
|
||||
#define KMEDKIT_MAX_CARRY 3 // Alex
|
||||
|
||||
// the maximum amount of ammo each weapon's clip can hold
|
||||
#define WEAPON_NOCLIP -1
|
||||
|
@ -147,7 +152,7 @@ public:
|
|||
#define TRIPMINE_MAX_CLIP WEAPON_NOCLIP
|
||||
#define SNARK_MAX_CLIP WEAPON_NOCLIP
|
||||
#define BERETTA_MAX_CLIP 15
|
||||
#define KMEDKIT_MAX_CLIP 1
|
||||
#define KMEDKIT_MAX_CLIP WEAPON_NOCLIP
|
||||
|
||||
// the default amount of ammo that comes with each gun when it spawns
|
||||
#define GLOCK_DEFAULT_GIVE 17
|
||||
|
@ -167,6 +172,7 @@ public:
|
|||
#define HIVEHAND_DEFAULT_GIVE 8
|
||||
#define BERETTA_DEFAULT_GIVE 15 // Alex
|
||||
#define KMEDKIT_DEFAULT_GIVE 1 // Alex
|
||||
#define TOAD_DEFAULT_GIVE 1
|
||||
|
||||
// The amount of ammo given to a player by an ammo item.
|
||||
#define AMMO_URANIUMBOX_GIVE 20
|
||||
|
@ -197,7 +203,6 @@ typedef enum
|
|||
BULLET_MONSTER_9MM,
|
||||
BULLET_MONSTER_MP5,
|
||||
BULLET_MONSTER_12MM,
|
||||
BULLET_MONSTER_M41A // M41A
|
||||
} Bullet;
|
||||
|
||||
#define ITEM_FLAG_SELECTONEMPTY 1
|
||||
|
@ -331,6 +336,7 @@ public:
|
|||
virtual BOOL CanDeploy( void );
|
||||
virtual BOOL IsUseable( void );
|
||||
BOOL DefaultDeploy( const char *szViewModel, const char *szWeaponModel, int iAnim, const char *szAnimExt, int skiplocal = 0, int body = 0 );
|
||||
void DefaultHolster( int iAnim, float fDelay );
|
||||
int DefaultReload( int iClipSize, int iAnim, float fDelay, int body = 0 );
|
||||
|
||||
virtual void ItemPostFrame( void ); // called each frame by the player PostThink
|
||||
|
@ -394,6 +400,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_sModelIndexLightning;// holds the sprite index for lightning
|
||||
|
||||
extern void ClearMultiDamage(void);
|
||||
extern void ApplyMultiDamage(entvars_t* pevInflictor, entvars_t* pevAttacker );
|
||||
|
@ -490,6 +497,7 @@ public:
|
|||
void SecondaryAttack( void );
|
||||
void GlockFire( float flSpread, float flCycleTime, BOOL fUseAutoAim );
|
||||
BOOL Deploy( void );
|
||||
void Holster( int skiplocal = 0 );
|
||||
void Reload( void );
|
||||
void WeaponIdle( void );
|
||||
|
||||
|
@ -502,7 +510,7 @@ public:
|
|||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
//private:
|
||||
int m_iShell;
|
||||
|
||||
unsigned short m_usFireGlock1;
|
||||
|
@ -524,9 +532,8 @@ public:
|
|||
int Swing( int fFirst );
|
||||
BOOL Deploy( void );
|
||||
void Holster( int skiplocal = 0 );
|
||||
#ifdef CROWBAR_IDLE_ANIM
|
||||
void WeaponIdle();
|
||||
#endif
|
||||
|
||||
int m_iSwing;
|
||||
TraceResult m_trHit;
|
||||
|
||||
|
@ -539,7 +546,6 @@ public:
|
|||
#endif
|
||||
}
|
||||
private:
|
||||
unsigned short m_usCrowbar;
|
||||
};
|
||||
|
||||
class CPython : public CBasePlayerWeapon
|
||||
|
@ -586,6 +592,7 @@ public:
|
|||
void SecondaryAttack( void );
|
||||
int SecondaryAmmoIndex( void );
|
||||
BOOL Deploy( void );
|
||||
void Holster( int skiplocal = 0 );
|
||||
void Reload( void );
|
||||
void WeaponIdle( void );
|
||||
BOOL IsUseable();
|
||||
|
@ -603,7 +610,6 @@ public:
|
|||
|
||||
private:
|
||||
unsigned short m_usMP5;
|
||||
unsigned short m_usMP52;
|
||||
};
|
||||
|
||||
class CCrossbow : public CBasePlayerWeapon
|
||||
|
@ -636,8 +642,6 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
unsigned short m_usCrossbow;
|
||||
unsigned short m_usCrossbow2;
|
||||
};
|
||||
|
||||
class CShotgun : public CBasePlayerWeapon
|
||||
|
@ -657,6 +661,7 @@ public:
|
|||
void PrimaryAttack( void );
|
||||
void SecondaryAttack( void );
|
||||
BOOL Deploy( );
|
||||
void Holster( int skiplocal = 0 );
|
||||
void Reload( void );
|
||||
void WeaponTick();
|
||||
void WeaponIdle( void );
|
||||
|
@ -732,7 +737,6 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
unsigned short m_usRpg;
|
||||
};
|
||||
|
||||
class CRpgRocket : public CGrenade
|
||||
|
@ -777,6 +781,7 @@ public:
|
|||
void StartFire( void );
|
||||
void Fire( Vector vecOrigSrc, Vector vecDirShooting, float flDamage );
|
||||
float GetFullChargeTime( void );
|
||||
int m_fInAttack;
|
||||
int m_iBalls;
|
||||
int m_iGlow;
|
||||
int m_iBeam;
|
||||
|
@ -838,6 +843,9 @@ public:
|
|||
|
||||
void UseAmmo( int count );
|
||||
|
||||
static int g_fireAnims1[];
|
||||
static int g_fireAnims2[];
|
||||
enum EGON_FIRESTATE { FIRE_OFF, FIRE_CHARGE };
|
||||
enum EGON_FIREMODE { FIRE_NARROW, FIRE_WIDE};
|
||||
|
||||
CBeam *m_pBeam;
|
||||
|
@ -859,11 +867,10 @@ private:
|
|||
#ifndef CLIENT_DLL
|
||||
float m_shootTime;
|
||||
#endif
|
||||
EGON_FIRESTATE m_fireState;
|
||||
EGON_FIREMODE m_fireMode;
|
||||
float m_shakeTime;
|
||||
BOOL m_deployed;
|
||||
|
||||
unsigned short m_usEgonFire;
|
||||
};
|
||||
|
||||
class CHgun : public CBasePlayerWeapon
|
||||
|
@ -902,7 +909,6 @@ public:
|
|||
#endif
|
||||
}
|
||||
private:
|
||||
unsigned short m_usHornetFire;
|
||||
};
|
||||
|
||||
class CHandGrenade : public CBasePlayerWeapon
|
||||
|
@ -927,6 +933,8 @@ public:
|
|||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
float m_flStartThrow;
|
||||
float m_flReleaseThrow;
|
||||
};
|
||||
|
||||
class CSatchel : public CBasePlayerWeapon
|
||||
|
@ -961,6 +969,8 @@ public:
|
|||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
private:
|
||||
int m_chargeReady;
|
||||
};
|
||||
|
||||
class CTripmine : public CBasePlayerWeapon
|
||||
|
@ -992,7 +1002,6 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
unsigned short m_usTripFire;
|
||||
};
|
||||
|
||||
class CSqueak : public CBasePlayerWeapon
|
||||
|
@ -1020,24 +1029,38 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
unsigned short m_usSnarkFire;
|
||||
};
|
||||
|
||||
// Added by Alex
|
||||
class CKMedkit : public CBasePlayerWeapon
|
||||
class CKMedKit : 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 iItemSlot( void ) { return 1; }
|
||||
int GetItemInfo(ItemInfo *p);
|
||||
|
||||
int AddToPlayer( CBasePlayer *pPlayer );
|
||||
void Holster( int skiplocal /* = 0 */ );
|
||||
void PrimaryAttack( void );
|
||||
void SecondaryAttack( void );
|
||||
void KMedkitFire( float flSpread, float flCycleTime, BOOL fUseAutoAim );
|
||||
void UseMedkit( int fMode );
|
||||
void EXPORT SayKateHealth();
|
||||
BOOL Deploy( void );
|
||||
void Reload( void );
|
||||
void WeaponIdle( void );
|
||||
BOOL IsUseable()
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
BOOL CanDeploy()
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
virtual BOOL UseDecrement( void )
|
||||
{
|
||||
|
@ -1049,8 +1072,9 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
|
||||
unsigned short m_usUseKMedkit;
|
||||
BOOL m_bIsStateChanged;
|
||||
int m_iState;
|
||||
int m_iKateHealth;
|
||||
};
|
||||
// end
|
||||
|
||||
|
@ -1069,6 +1093,7 @@ public:
|
|||
BOOL Deploy( void );
|
||||
void Reload( void );
|
||||
void WeaponIdle( void );
|
||||
void Holster( int skiplocal /* = 0 */ );
|
||||
|
||||
virtual BOOL UseDecrement( void )
|
||||
{
|
||||
|
@ -1101,6 +1126,8 @@ public:
|
|||
int Swing( int fFirst );
|
||||
BOOL Deploy( void );
|
||||
void Holster( int skiplocal = 0 );
|
||||
void WeaponIdle();
|
||||
|
||||
int m_iSwing;
|
||||
TraceResult m_trHit;
|
||||
|
||||
|
@ -1113,7 +1140,6 @@ public:
|
|||
#endif
|
||||
}
|
||||
private:
|
||||
unsigned short m_usPoolstick;
|
||||
};
|
||||
// Alex end
|
||||
// Added by Alex
|
||||
|
@ -1125,6 +1151,7 @@ public:
|
|||
int iItemSlot( void ) { return 3; }
|
||||
int GetItemInfo(ItemInfo *p);
|
||||
int AddToPlayer( CBasePlayer *pPlayer );
|
||||
void Holster( int skiplocal /* = 0 */ );
|
||||
|
||||
void PrimaryAttack( void );
|
||||
void SecondaryAttack( void );
|
||||
|
@ -1132,6 +1159,8 @@ public:
|
|||
BOOL Deploy( void );
|
||||
void Reload( void );
|
||||
void WeaponIdle( void );
|
||||
BOOL IsUseable();
|
||||
|
||||
float m_flNextAnimTime;
|
||||
int m_iShell;
|
||||
|
||||
|
@ -1146,7 +1175,6 @@ public:
|
|||
|
||||
private:
|
||||
unsigned short m_usM41A;
|
||||
unsigned short m_usM41A2;
|
||||
};
|
||||
// end
|
||||
// alex
|
||||
|
@ -1157,6 +1185,8 @@ public:
|
|||
void Precache( void );
|
||||
int iItemSlot( void ) { return 5; }
|
||||
int GetItemInfo(ItemInfo *p);
|
||||
void EXPORT ToadIdle();
|
||||
void HuntSound( bool force );
|
||||
|
||||
void PrimaryAttack( void );
|
||||
void SecondaryAttack( void );
|
||||
|
@ -1173,9 +1203,47 @@ public:
|
|||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned short m_usToadFire;
|
||||
Vector m_posNext;
|
||||
float m_flNextTrace;
|
||||
float m_flNextHunt;
|
||||
float m_flDie;
|
||||
};
|
||||
// alex
|
||||
|
||||
class CBarneyGlock : public CGlock
|
||||
{
|
||||
public:
|
||||
void Spawn();
|
||||
void Precache();
|
||||
int GetItemInfo( ItemInfo *p );
|
||||
BOOL Deploy();
|
||||
};
|
||||
|
||||
class CBarneyShotgun : public CShotgun
|
||||
{
|
||||
public:
|
||||
void Spawn();
|
||||
void Precache();
|
||||
int GetItemInfo( ItemInfo *p );
|
||||
BOOL Deploy();
|
||||
};
|
||||
|
||||
class CBarneyMP5 : public CMP5
|
||||
{
|
||||
public:
|
||||
void Spawn();
|
||||
void Precache();
|
||||
int GetItemInfo( ItemInfo *p );
|
||||
BOOL Deploy();
|
||||
};
|
||||
|
||||
class CBarneyHandGrenade : public CHandGrenade
|
||||
{
|
||||
public:
|
||||
void Spawn();
|
||||
void Precache();
|
||||
int GetItemInfo( ItemInfo *p );
|
||||
BOOL Deploy();
|
||||
};
|
||||
#endif // WEAPONS_H
|
||||
|
|
|
@ -266,17 +266,17 @@ void CZombie::HandleAnimEvent( MonsterEvent_t *pEvent )
|
|||
void CZombie::Spawn()
|
||||
{
|
||||
Precache();
|
||||
if( FClassnameIs( pev, "monster_zombie" ) )
|
||||
SET_MODEL( ENT( pev ), "models/zombie.mdl" );
|
||||
else
|
||||
SET_MODEL( ENT( pev ), "models/zbarnie.mdl" );
|
||||
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;
|
||||
pev->health = gSkillData.zombieHealth;
|
||||
if( FClassnameIs( pev, "monster_zombie" ) )
|
||||
pev->health = gSkillData.zombieHealth;
|
||||
else
|
||||
pev->health = gSkillData.zombieHealth * 1.25;
|
||||
pev->view_ofs = VEC_VIEW;// position of the eyes relative to monster's origin.
|
||||
m_flFieldOfView = 0.5;// indicates the width of this monster's forward view cone ( as a dotproduct result )
|
||||
m_MonsterState = MONSTERSTATE_NONE;
|
||||
|
@ -293,9 +293,11 @@ void CZombie::Precache()
|
|||
size_t i;
|
||||
|
||||
if( FClassnameIs( pev, "monster_zombie" ) )
|
||||
PRECACHE_MODEL( "models/zombie.mdl" );
|
||||
pev->model = MAKE_STRING( "models/zombie.mdl" );
|
||||
else
|
||||
PRECACHE_MODEL( "models/zbarnie.mdl" );
|
||||
pev->model = MAKE_STRING( "models/zbarney.mdl" );
|
||||
|
||||
PRECACHE_MODEL( STRING( pev->model ) );
|
||||
|
||||
for( i = 0; i < ARRAYSIZE( pAttackHitSounds ); i++ )
|
||||
PRECACHE_SOUND( pAttackHitSounds[i] );
|
||||
|
|
Loading…
Reference in New Issue