Remove files with ~

This commit is contained in:
RAINBOW2000 2017-01-22 18:53:24 +03:00
parent 8c1c6cefa2
commit 6608fb78d5
14 changed files with 0 additions and 7276 deletions

View File

@ -1,153 +0,0 @@
#HLSDK server Android port
#Copyright (c) nicknekit
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := server
include $(XASH3D_CONFIG)
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 \
-fno-exceptions -DNO_VOICEGAMEMGR -w
LOCAL_CPPFLAGS := $(LOCAL_CFLAGS) -frtti
LOCAL_C_INCLUDES := $(SDL_PATH)/include \
$(LOCAL_PATH)/. \
$(LOCAL_PATH)/wpn_shared \
$(LOCAL_PATH)/../common \
$(LOCAL_PATH)/../engine/common \
$(LOCAL_PATH)/../engine \
$(LOCAL_PATH)/../public \
$(LOCAL_PATH)/../pm_shared \
$(LOCAL_PATH)/../game_shared
LOCAL_SRC_FILES := agrunt.cpp airtank.cpp \
bonewheel.cpp \
sawnoff.cpp \
cross.cpp
pepsigun.cpp \
needle.cpp \
katana.cpp \
evilsci.cpp \
sniper.cpp \
glock2.cpp \
mariozombie.cpp \
megachav.cpp \
pink_panthera.cpp \
shrek.cpp \
skeleton.cpp \
skrillex.cpp \
superchav.cpp \
terror.cpp \
zombozo.cpp \
aflock.cpp \
animating.cpp \
animation.cpp \
apache.cpp \
barnacle.cpp \
barney.cpp \
bigmomma.cpp \
bloater.cpp \
bmodels.cpp \
bullsquid.cpp \
buttons.cpp \
cbase.cpp \
client.cpp \
combat.cpp \
controller.cpp \
crossbow.cpp \
crowbar.cpp \
defaultai.cpp \
doors.cpp \
effects.cpp \
egon.cpp \
explode.cpp \
flyingmonster.cpp \
func_break.cpp \
func_tank.cpp \
game.cpp \
gamerules.cpp \
gargantua.cpp \
gauss.cpp \
genericmonster.cpp \
ggrenade.cpp \
globals.cpp \
glock.cpp \
gman.cpp \
h_ai.cpp \
h_battery.cpp \
h_cycler.cpp \
h_cine.cpp \
h_export.cpp \
handgrenade.cpp \
hassassin.cpp \
headcrab.cpp \
healthkit.cpp \
hgrunt.cpp \
hornet.cpp \
hornetgun.cpp \
houndeye.cpp \
ichthyosaur.cpp \
islave.cpp \
items.cpp \
leech.cpp \
lights.cpp \
maprules.cpp \
monstermaker.cpp \
monsters.cpp \
monsterstate.cpp \
mortar.cpp \
mp5.cpp \
multiplay_gamerules.cpp \
nihilanth.cpp \
nodes.cpp \
osprey.cpp \
pathcorner.cpp \
plane.cpp \
plats.cpp \
player.cpp \
python.cpp \
rat.cpp \
roach.cpp \
rpg.cpp \
satchel.cpp \
schedule.cpp \
scientist.cpp \
scripted.cpp \
shotgun.cpp \
singleplay_gamerules.cpp \
skill.cpp \
sound.cpp \
soundent.cpp \
spectator.cpp \
squadmonster.cpp \
squeakgrenade.cpp \
subs.cpp \
talkmonster.cpp \
teamplay_gamerules.cpp \
tentacle.cpp \
tempmonster.cpp \
triggers.cpp \
tripmine.cpp \
turret.cpp \
util.cpp \
weapons.cpp \
world.cpp \
xen.cpp \
zombie.cpp \
rock.cpp \
../pm_shared/pm_debug.c \
../pm_shared/pm_math.c \
../pm_shared/pm_shared.c
# ../game_shared/voice_gamemgr.cpp
LOCAL_LDLIBS := -llog
include $(BUILD_SHARED_LIBRARY)

View File

@ -1,733 +0,0 @@
/***
*
* 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"
//=========================================================
// Monster's Anim Events Go Here
//=========================================================
// first flag is barney dying for scripted sequences?
#define BIGSMOKE_AE_DRAW ( 2 )
#define BIGSMOKE_AE_SHOOT ( 3 )
#define BIGSMOKE_AE_HOLSTER ( 4 )
#define BIGSMOKE_BODY_GUNHOLSTERED 0
#define BIGSMOKE_BODY_GUNDRAWN 1
#define BIGSMOKE_BODY_GUNGONE 2
class CBigSmoke : public CTalkMonster
{
public:
void Spawn( void );
void Precache( void );
void SetYawSpeed( void );
int ISoundMask( void );
void BigSmokeFirePistol( 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_big_smoke, CBigSmoke )
TYPEDESCRIPTION CBigSmoke::m_SaveData[] =
{
DEFINE_FIELD( CBigSmoke, m_fGunDrawn, FIELD_BOOLEAN ),
DEFINE_FIELD( CBigSmoke, m_painTime, FIELD_TIME ),
DEFINE_FIELD( CBigSmoke, m_checkAttackTime, FIELD_TIME ),
DEFINE_FIELD( CBigSmoke, m_lastAttackCheck, FIELD_BOOLEAN ),
DEFINE_FIELD( CBigSmoke, m_flPlayerDamage, FIELD_FLOAT ),
};
IMPLEMENT_SAVERESTORE( CBigSmoke, CTalkMonster )
//=========================================================
// AI Schedules Specific to this monster
//=========================================================
Task_t tlBsFollow[] =
{
{ TASK_MOVE_TO_TARGET_RANGE, (float)128 }, // Move within 128 of target ent (client)
{ TASK_SET_SCHEDULE, (float)SCHED_TARGET_FACE },
};
Schedule_t slBsFollow[] =
{
{
tlBsFollow,
ARRAYSIZE( tlBsFollow ),
bits_COND_NEW_ENEMY |
bits_COND_LIGHT_DAMAGE |
bits_COND_HEAVY_DAMAGE |
bits_COND_HEAR_SOUND |
bits_COND_PROVOKED,
bits_SOUND_DANGER,
"Follow"
},
};
//=========================================================
// BarneyDraw - much better looking draw schedule for when
// barney knows who he's gonna attack.
//=========================================================
Task_t tlBigSmokeEnemyDraw[] =
{
{ TASK_STOP_MOVING, 0 },
{ TASK_FACE_ENEMY, 0 },
{ TASK_PLAY_SEQUENCE_FACE_ENEMY, (float) ACT_ARM },
};
Schedule_t slBigSmokeEnemyDraw[] =
{
{
tlBigSmokeEnemyDraw,
ARRAYSIZE( tlBigSmokeEnemyDraw ),
0,
0,
"BigSmoke Enemy Draw"
}
};
Task_t tlBsFaceTarget[] =
{
{ 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 slBsFaceTarget[] =
{
{
tlBsFaceTarget,
ARRAYSIZE( tlBsFaceTarget ),
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 tlIdleBsStand[] =
{
{ 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 slIdleBsStand[] =
{
{
tlIdleBsStand,
ARRAYSIZE( tlIdleBsStand ),
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( CBigSmoke )
{
slBsFollow,
slBigSmokeEnemyDraw,
slBsFaceTarget,
slIdleBsStand,
};
IMPLEMENT_CUSTOM_SCHEDULES( CBigSmoke, CTalkMonster )
void CBigSmoke::StartTask( Task_t *pTask )
{
CTalkMonster::StartTask( pTask );
}
void CBigSmoke::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 CBigSmoke::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 CBigSmoke::Classify( void )
{
return CLASS_PLAYER_ALLY;
}
//=========================================================
// ALertSound - barney says "Freeze!"
//=========================================================
void CBigSmoke::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 CBigSmoke::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 CBigSmoke::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;
}
//=========================================================
// BarneyFirePistol - shoots one round from the pistol at
// the enemy barney is facing.
//=========================================================
void CBigSmoke::BigSmokeFirePistol( 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, "BigSmoke/fire1.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 CBigSmoke::HandleAnimEvent( MonsterEvent_t *pEvent )
{
switch( pEvent->event )
{
case BIGSMOKE_AE_SHOOT:
BigSmokeFirePistol();
break;
case BIGSMOKE_AE_DRAW:
// barney's bodygroup switches here so he can pull gun from holster
pev->body = BIGSMOKE_BODY_GUNDRAWN;
m_fGunDrawn = TRUE;
break;
case BIGSMOKE_AE_HOLSTER:
// change bodygroup to replace gun in holster
pev->body = BIGSMOKE_BODY_GUNHOLSTERED;
m_fGunDrawn = FALSE;
break;
default:
CTalkMonster::HandleAnimEvent( pEvent );
}
}
//=========================================================
// Spawn
//=========================================================
void CBigSmoke::Spawn()
{
Precache();
SET_MODEL( ENT( pev ), "models/bigsmoke.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 = 350;
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( &CTalkMonster::FollowerUse );
}
//=========================================================
// Precache - precaches all resources this monster needs
//=========================================================
void CBigSmoke::Precache()
{
PRECACHE_MODEL( "models/bigsmoke.mdl" );
PRECACHE_SOUND( "bigsmoke/fire1.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 CBigSmoke::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 CBigSmoke::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 CBarney::PainSound( void )
{
if( gpGlobals->time < m_painTime )
return;
m_painTime = gpGlobals->time + RANDOM_FLOAT( 0.5, 0.75 );
}
//=========================================================
// DeathSound
//=========================================================
void CBarney::DeathSound( void )
{
}
void CBarney::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 CBarney::Killed( entvars_t *pevAttacker, int iGib )
{
if( pev->body < BARNEY_BODY_GUNGONE )
{
// drop the gun!
Vector vecGunPos;
Vector vecGunAngles;
pev->body = BIGSMOKE_BODY_GUNGONE;
GetAttachment( 0, vecGunPos, vecGunAngles );
CBaseEntity *pGun = DropItem( "weapon_9mmhandgun", vecGunPos, vecGunAngles );
}
SetUse( NULL );
CTalkMonster::Killed( pevAttacker, iGib );
}
//=========================================================
// AI Schedules Specific to this monster
//=========================================================
Schedule_t *CBigSmoke::GetScheduleOfType( int Type )
{
Schedule_t *psched;
switch( Type )
{
case SCHED_ARM_WEAPON:
if( m_hEnemy != NULL )
{
// face enemy, then draw.
return slBigSmokeEnemyDraw;
}
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 slBaFaceTarget; // override this for different target face behavior
else
return psched;
case SCHED_TARGET_CHASE:
return slBaFollow;
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 slIdleBaStand;
}
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 *CBigSmoke::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;
default:
break;
}
return CTalkMonster::GetSchedule();
}
MONSTERSTATE CBigSmoke::GetIdealState( void )
{
return CTalkMonster::GetIdealState();
}
void CBigSmoke::DeclineFollowing( void )
{
PlaySentence( "BA_POK", 2, VOL_NORM, ATTN_NORM );
}

View File

@ -1,658 +0,0 @@
/***
*
* 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 "squadmonster.h"
//=========================================================
// Monster's Anim Events Go Here
//=========================================================
// first flag is barney dying for scripted sequences?
#define BIGSMOKE_AE_DRAW ( 2 )
#define BIGSMOKE_AE_SHOOT ( 3 )
#define BIGSMOKE_AE_HOLSTER ( 4 )
#define BIGSMOKE_BODY_GUNHOLSTERED 0
#define BIGSMOKE_BODY_GUNDRAWN 1
#define BIGSMOKE_BODY_GUNGONE 2
class CBigSmoke : public CSquadMonster
{
public:
void Spawn( void );
void Precache( void );
void SetYawSpeed( void );
int ISoundMask( void );
void BigSmokeFirePistol( void );
void AlertSound( void );
int Classify( void );
void HandleAnimEvent( MonsterEvent_t *pEvent );
void RunTask( Task_t *pTask );
void StartTask( Task_t *pTask );
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 );
static TYPEDESCRIPTION m_SaveData[];
virtual int Save( CSave &save );
virtual int Restore( CRestore &restore );
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_big_smoke, CBigSmoke )
TYPEDESCRIPTION CBigSmoke::m_SaveData[] =
{
DEFINE_FIELD( CBigSmoke, m_fGunDrawn, FIELD_BOOLEAN ),
DEFINE_FIELD( CBigSmoke, m_painTime, FIELD_TIME ),
DEFINE_FIELD( CBigSmoke, m_checkAttackTime, FIELD_TIME ),
DEFINE_FIELD( CBigSmoke, m_lastAttackCheck, FIELD_BOOLEAN ),
DEFINE_FIELD( CBigSmoke, m_flPlayerDamage, FIELD_FLOAT ),
};
IMPLEMENT_SAVERESTORE( CBigSmoke, CSquadMonster )
//=========================================================
// AI Schedules Specific to this monster
//=====
Task_t tlBsFollow[] =
{
{ TASK_MOVE_TO_TARGET_RANGE, (float)128 }, // Move within 128 of target ent (client)
{ TASK_SET_SCHEDULE, (float)SCHED_TARGET_FACE },
};
Schedule_t slBsFollow[] =
{
{
tlBsFollow,
ARRAYSIZE( tlBsFollow ),
bits_COND_NEW_ENEMY |
bits_COND_LIGHT_DAMAGE |
bits_COND_HEAVY_DAMAGE |
bits_COND_HEAR_SOUND |
bits_COND_PROVOKED,
bits_SOUND_DANGER,
"Follow"
},
};
//=========================================================
// BarneyDraw - much better looking draw schedule for when
// barney knows who he's gonna attack.
//=========================================================
Task_t tlBigSmokeEnemyDraw[] =
{
{ TASK_STOP_MOVING, 0 },
{ TASK_FACE_ENEMY, 0 },
{ TASK_PLAY_SEQUENCE_FACE_ENEMY, (float) ACT_ARM },
};
Schedule_t slBigSmokeEnemyDraw[] =
{
{
tlBigSmokeEnemyDraw,
ARRAYSIZE( tlBigSmokeEnemyDraw ),
0,
0,
"BigSmoke Enemy Draw"
}
};
Task_t tlBsFaceTarget[] =
{
{ 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 slBsFaceTarget[] =
{
{
tlBsFaceTarget,
ARRAYSIZE( tlBsFaceTarget ),
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 tlIdleBsStand[] =
{
{ 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 slIdleBsStand[] =
{
{
tlIdleBsStand,
ARRAYSIZE( tlIdleBsStand ),
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( CBigSmoke )
{
slBsFollow,
slBigSmokeEnemyDraw,
slBsFaceTarget,
slIdleBsStand,
};
IMPLEMENT_CUSTOM_SCHEDULES( CBigSmoke, CSquadMonster )
void CBigSmoke::StartTask( Task_t *pTask )
{
CSquadMonster::StartTask( pTask );
}
void CBigSmoke::RunTask( Task_t *pTask )
{
switch( pTask->iTask )
{
case TASK_RANGE_ATTACK1:
if( m_hEnemy != NULL && ( m_hEnemy->IsPlayer() ) )
{
pev->framerate = 1.5;
}
CSquadMonster::RunTask( pTask );
break;
default:
CSquadMonster::RunTask( pTask );
break;
}
}
//=========================================================
// ISoundMask - returns a bit mask indicating which types
// of sounds this monster regards.
//=========================================================
int CBigSmoke::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 CBigSmoke::Classify( void )
{
return CLASS_PLAYER_ALLY;
}
//=========================================================
// ALertSound - barney says "Freeze!"
//=========================================================
void CBigSmoke::AlertSound( void )
{
}
//=========================================================
// SetYawSpeed - allows each sequence to have a different
// turn rate associated with it.
//=========================================================
void CBigSmoke::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 CBigSmoke::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;
}
//=========================================================
// BarneyFirePistol - shoots one round from the pistol at
// the enemy barney is facing.
//=========================================================
void CBigSmoke::BigSmokeFirePistol( 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, "BigSmoke/fire1.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 CBigSmoke::HandleAnimEvent( MonsterEvent_t *pEvent )
{
switch( pEvent->event )
{
case BIGSMOKE_AE_SHOOT:
BigSmokeFirePistol();
break;
case BIGSMOKE_AE_DRAW:
// barney's bodygroup switches here so he can pull gun from holster
pev->body = BIGSMOKE_BODY_GUNDRAWN;
m_fGunDrawn = TRUE;
break;
case BIGSMOKE_AE_HOLSTER:
// change bodygroup to replace gun in holster
pev->body = BIGSMOKE_BODY_GUNHOLSTERED;
m_fGunDrawn = FALSE;
break;
default:
CSquadMonster::HandleAnimEvent( pEvent );
}
}
//=========================================================
// Spawn
//=========================================================
void CBigSmoke::Spawn()
{
Precache();
SET_MODEL( ENT( pev ), "models/bigsmoke.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 = 350;
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();
}
//=========================================================
// Precache - precaches all resources this monster needs
//=========================================================
void CBigSmoke::Precache()
{
PRECACHE_MODEL( "models/bigsmoke.mdl" );
PRECACHE_SOUND( "bigsmoke/fire1.wav" );
CSquadMonster::Precache();
}
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 CBigSmoke::TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType )
{
// make sure friends talk about it if player hurts talkmonsters...
int ret = CSquadMonster::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 ) )
{
}
else
{
}
}
else if( !( m_hEnemy->IsPlayer()) && pev->deadflag == DEAD_NO )
{
}
}
return ret;
}
//=========================================================
// PainSound
//=========================================================
void CBigSmoke::PainSound( void )
{
if( gpGlobals->time < m_painTime )
return;
m_painTime = gpGlobals->time + RANDOM_FLOAT( 0.5, 0.75 );
}
//=========================================================
// DeathSound
//=========================================================
void CBigSmoke::DeathSound( void )
{
}
void CBigSmoke::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;
}
CSquadMonster::TraceAttack( pevAttacker, flDamage, vecDir, ptr, bitsDamageType );
}
void CBigSmoke::Killed( entvars_t *pevAttacker, int iGib )
{
if( pev->body < BIGSMOKE_BODY_GUNGONE )
{
// drop the gun!
Vector vecGunPos;
Vector vecGunAngles;
pev->body = BIGSMOKE_BODY_GUNGONE;
GetAttachment( 0, vecGunPos, vecGunAngles );
CBaseEntity *pGun = DropItem( "weapon_9mmhandgun", vecGunPos, vecGunAngles );
}
SetUse( NULL );
CSquadMonster::Killed( pevAttacker, iGib );
}
//=========================================================
// AI Schedules Specific to this monster
//=========================================================
Schedule_t *CBigSmoke::GetScheduleOfType( int Type )
{
Schedule_t *psched;
switch( Type )
{
case SCHED_ARM_WEAPON:
if( m_hEnemy != NULL )
{
// face enemy, then draw.
return slBigSmokeEnemyDraw;
}
break;
// Hook these to make a looping schedule
case SCHED_TARGET_FACE:
// call base class default so that barney will talk
// when 'used'
psched = CSquadMonster::GetScheduleOfType( Type );
if( psched == slIdleStand )
return slBsFaceTarget; // override this for different target face behavior
else
return psched;
case SCHED_TARGET_CHASE:
return slBsFollow;
case SCHED_IDLE_STAND:
// call base class default so that scientist will talk
// when standing during idle
psched = CSquadMonster::GetScheduleOfType( Type );
if( psched == slIdleStand )
{
// just look straight ahead.
return slIdleBaStand;
}
else
return psched;
}
return CSquadMonster::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 *CBigSmoke::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 );
}
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( HasConditions( bits_COND_CLIENT_PUSH ) )
{
return GetScheduleOfType( SCHED_MOVE_AWAY );
}
break;
default:
break;
}
return CSquadMonster::GetSchedule();
}
MONSTERSTATE CBigSmoke::GetIdealState( void )
{
return CSquadMonster::GetIdealState();
}
void CBigSmoke::DeclineFollowing( void )
{
PlaySentence( "BA_POK", 2, VOL_NORM, ATTN_NORM );
}

View File

@ -1,455 +0,0 @@
#if !defined( OEM_BUILD ) && !defined( HLDEMO_BUILD )
#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "monsters.h"
#include "weapons.h"
#include "nodes.h"
#include "player.h"
#include "gamerules.h"
#ifndef CLIENT_DLL
#define BOLT_AIR_VELOCITY 1300
#define BOLT_WATER_VELOCITY 1300
// UNDONE: Save/restore this? Don't forget to set classname and LINK_ENTITY_TO_CLASS()
//
// OVERLOADS SOME ENTVARS:
//
// speed - the ideal magnitude of my velocity
class CCrowbar2Bolt : public CBaseEntity
{
void Spawn( void );
void Precache( void );
int Classify( void );
void EXPORT BubbleThink( void );
void EXPORT BoltTouch( CBaseEntity *pOther );
void EXPORT ExplodeThink( void );
int m_iTrail;
public:
static CCrowbar2Bolt *BoltCreate( void );
};
LINK_ENTITY_TO_CLASS( crowbar2_bolt, CCrowbar2Bolt )
CCrowbar2Bolt *CCrowbar2Bolt::BoltCreate( void )
{
// Create a new entity with CCrossbowBolt private data
CCrowbar2Bolt *pBolt = GetClassPtr( (CCrowbar2Bolt *)NULL );
pBolt->pev->classname = MAKE_STRING( "crossbow_bolt" ); // g-cont. enable save\restore
pBolt->Spawn();
return pBolt;
}
void CCrowbar2Bolt::Spawn()
{
Precache();
pev->movetype = MOVETYPE_FLY;
pev->solid = SOLID_BBOX;
pev->gravity = 300;
SET_MODEL( ENT( pev ), "models/w_hammer.mdl" );
UTIL_SetOrigin( pev, pev->origin );
UTIL_SetSize( pev, Vector( 0, 0, 0 ), Vector( 0, 0, 0 ) );
SetTouch( &CCrowbar2Bolt::BoltTouch );
SetThink( &CCrowbar2Bolt::BubbleThink );
pev->nextthink = gpGlobals->time + 0.2;
}
void CCrowbar2Bolt::Precache()
{
PRECACHE_MODEL( "models/w_hammer.mdl" );
PRECACHE_SOUND( "weapons/hammer_hitbod1.wav" );
PRECACHE_SOUND( "weapons/hammer_hitbod2.wav" );
PRECACHE_SOUND( "weapons/g_bounce2.wav" );
PRECACHE_SOUND( "fvox/beep.wav" );
m_iTrail = PRECACHE_MODEL( "sprites/streak.spr" );
}
int CCrowbar2Bolt::Classify( void )
{
return CLASS_NONE;
}
void CCrowbar2Bolt::BoltTouch( CBaseEntity *pOther )
{
SetTouch( NULL );
SetThink( NULL );
if( pOther->pev->takedamage )
{
TraceResult tr = UTIL_GetGlobalTrace();
entvars_t *pevOwner;
pevOwner = VARS( pev->owner );
// UNDONE: this needs to call TraceAttack instead
ClearMultiDamage();
if( pOther->IsPlayer() )
{
pOther->TraceAttack( pevOwner, 259, pev->velocity.Normalize(), &tr, DMG_ALWAYSGIB );
}
else
{
pOther->TraceAttack( pevOwner, 259, pev->velocity.Normalize(), &tr, DMG_BULLET | DMG_ALWAYSGIB );
}
ApplyMultiDamage( pev, pevOwner );
pev->velocity = Vector( 0, 0, 0 );
// play body "thwack" sound
switch( RANDOM_LONG( 0, 1 ) )
{
case 0:
EMIT_SOUND( ENT( pev ), CHAN_BODY, "weapons/hammer_hitbod.wav", 1, ATTN_NORM );
break;
case 1:
EMIT_SOUND( ENT( pev ), CHAN_BODY, "weapons/hammer_hitbod.wav", 1, ATTN_NORM );
break;
}
if( !g_pGameRules->IsMultiplayer() )
{
Killed( pev, GIB_ALWAYS );
}
}
else
{
EMIT_SOUND_DYN( ENT( pev ), CHAN_BODY, "weapons/hammer_hit.wav", RANDOM_FLOAT( 0.95, 1.0 ), ATTN_NORM, 0, 98 + RANDOM_LONG( 0, 7 ) );
SetThink( &CBaseEntity::SUB_Remove );
pev->nextthink = gpGlobals->time;// this will get changed below if the bolt is allowed to stick in what it hit.
if( FClassnameIs( pOther->pev, "worldspawn" ) )
{
// if what we hit is static architecture, can stay around for a while.
Vector vecDir = pev->velocity.Normalize();
UTIL_SetOrigin( pev, pev->origin - vecDir * 12 );
pev->angles = UTIL_VecToAngles( vecDir );
pev->solid = SOLID_NOT;
pev->movetype = MOVETYPE_FLY;
pev->velocity = Vector( 0, 0, 0 );
pev->avelocity.z = 180;
pev->angles.z = RANDOM_LONG( 180,360 );
pev->nextthink = gpGlobals->time + 10.0;
}
else if( pOther->pev->movetype == MOVETYPE_PUSH || pOther->pev->movetype == MOVETYPE_PUSHSTEP )
{
Vector vecDir = pev->velocity.Normalize();
UTIL_SetOrigin( pev, pev->origin - vecDir * 12 );
pev->angles = UTIL_VecToAngles( vecDir );
pev->solid = SOLID_NOT;
pev->velocity = Vector( 0, 0, 0 );
pev->avelocity.z = 0;
pev->angles.z = RANDOM_LONG( 0, 180 );
pev->nextthink = gpGlobals->time + 10.0;
}
if( UTIL_PointContents( pev->origin ) != CONTENTS_WATER )
{
UTIL_Sparks( pev->origin );
}
}
}
void CCrowbar2Bolt::BubbleThink( void )
{
pev->nextthink = gpGlobals->time + 0.1;
if( pev->waterlevel == 0 )
return;
UTIL_BubbleTrail( pev->origin - pev->velocity * 0.1, pev->origin, 1 );
}
void CCrowbar2Bolt::ExplodeThink( void )
{
int iContents = UTIL_PointContents( pev->origin );
int iScale;
pev->dmg = 40;
iScale = 10;
MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, pev->origin );
WRITE_BYTE( TE_EXPLOSION );
WRITE_COORD( pev->origin.x );
WRITE_COORD( pev->origin.y );
WRITE_COORD( pev->origin.z );
if( iContents != CONTENTS_WATER )
{
WRITE_SHORT( g_sModelIndexFireball );
}
else
{
WRITE_SHORT( g_sModelIndexWExplosion );
}
WRITE_BYTE( iScale ); // scale * 10
WRITE_BYTE( 15 ); // framerate
WRITE_BYTE( TE_EXPLFLAG_NONE );
MESSAGE_END();
entvars_t *pevOwner;
if( pev->owner )
pevOwner = VARS( pev->owner );
else
pevOwner = NULL;
pev->owner = NULL; // can't traceline attack owner if this is set
::RadiusDamage( pev->origin, pev, pevOwner, pev->dmg, 128, CLASS_NONE, DMG_BLAST | DMG_ALWAYSGIB );
UTIL_Remove( this );
}
#endif
enum crowbar_e
{
CROSSBOW_IDLE = 0,
CROSSBOW_DRAW,
CROSSBOW_HOLSTER,
CROSSBOW_ATTACK1HIT
};
LINK_ENTITY_TO_CLASS( weapon_hammer, CCrowbar2 )
void CCrowbar2::Spawn()
{
Precache();
m_iId = WEAPON_HAMMER;
SET_MODEL( ENT( pev ), "models/w_hammer.mdl" );
m_iDefaultAmmo = -1;
FallInit();// get ready to fall down.
}
int CCrowbar2::AddToPlayer( CBasePlayer *pPlayer )
{
if( CBasePlayerWeapon::AddToPlayer( pPlayer ) )
{
MESSAGE_BEGIN( MSG_ONE, gmsgWeapPickup, NULL, pPlayer->pev );
WRITE_BYTE( m_iId );
MESSAGE_END();
return TRUE;
}
return FALSE;
}
void CCrowbar2::Precache( void )
{
PRECACHE_MODEL( "models/w_hammer.mdl" );
PRECACHE_MODEL( "models/v_hammer.mdl" );
PRECACHE_MODEL( "models/p_hammer.mdl" );
PRECACHE_SOUND( "g_bounce2.wav" );
UTIL_PrecacheOther( "crossbow2_bolt" );
m_usCrossbow12 = PRECACHE_EVENT( 1, "events/crowbar.sc" );
m_usCrossbow22 = PRECACHE_EVENT( 1, "events/crowbar.sc" );
}
int CCrowbar2::GetItemInfo( ItemInfo *p )
{
p->pszName = STRING( pev->classname );
p->pszAmmo1 = NULL;
p->iMaxAmmo1 = -1;
p->pszAmmo2 = NULL;
p->iMaxAmmo2 = -1;
p->iMaxClip = -1;
p->iSlot = 0;
p->iPosition = 4;
p->iId = WEAPON_HAMMER;
p->iFlags = 0;
p->iWeight = -10;
return 1;
}
BOOL CCrowbar2::Deploy()
{
if( m_iClip )
return DefaultDeploy( "models/v_hammer.mdl", "models/p_hammer.mdl", CROSSBOW_DRAW, "bow" );
return DefaultDeploy( "models/v_hammer.mdl", "models/p_hammer.mdl", CROSSBOW_DRAW, "bow" );
}
void CCrowbar2::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_HOLSTER );
}
}
void CCrowbar2::PrimaryAttack( void )
{
#ifdef CLIENT_DLL
if( m_fInZoom && bIsMultiplayer() )
#else
if( m_fInZoom && g_pGameRules->IsMultiplayer() )
#endif
{
FireSniperBolt();
return;
}
FireBolt();
}
// this function only gets called in multiplayer
void CCrowbar2::FireSniperBolt()
{
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.35;
TraceResult tr;
m_pPlayer->m_iWeaponVolume = QUIET_GUN_VOLUME;
int flags;
#if defined( CLIENT_WEAPONS )
flags = FEV_NOTHOST;
#else
flags = 0;
#endif
PLAYBACK_EVENT_FULL( flags, m_pPlayer->edict(), m_usCrossbow22, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, 0, 0, m_iClip, m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType], 0, 0 );
// player "shoot" animation
m_pPlayer->SetAnimation( PLAYER_ATTACK1 );
Vector anglesAim = m_pPlayer->pev->v_angle + m_pPlayer->pev->punchangle;
UTIL_MakeVectors( anglesAim );
Vector vecSrc = m_pPlayer->GetGunPosition() - gpGlobals->v_up * 2;
Vector vecDir = gpGlobals->v_forward;
UTIL_TraceLine( vecSrc, vecSrc + vecDir * 8192, dont_ignore_monsters, m_pPlayer->edict(), &tr );
#ifndef CLIENT_DLL
if( tr.pHit->v.takedamage )
{
ClearMultiDamage();
CBaseEntity::Instance( tr.pHit )->TraceAttack( m_pPlayer->pev, 120, vecDir, &tr, DMG_BULLET | DMG_ALWAYSGIB );
ApplyMultiDamage( pev, m_pPlayer->pev );
}
#endif
}
void CCrowbar2::FireBolt()
{
TraceResult tr;
m_pPlayer->m_iWeaponVolume = QUIET_GUN_VOLUME;
int flags;
#if defined( CLIENT_WEAPONS )
flags = FEV_NOTHOST;
#else
flags = 0;
#endif
PLAYBACK_EVENT_FULL( flags, m_pPlayer->edict(), m_usCrossbow12, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, 0, 0, m_iClip, m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType], 0, 0 );
// player "shoot" animation
m_pPlayer->SetAnimation( PLAYER_ATTACK1 );
Vector anglesAim = m_pPlayer->pev->v_angle + m_pPlayer->pev->punchangle;
UTIL_MakeVectors( anglesAim );
anglesAim.x = -anglesAim.x;
Vector vecSrc = m_pPlayer->GetGunPosition() - gpGlobals->v_up * 2;
Vector vecDir = gpGlobals->v_forward;
#ifndef CLIENT_DLL
CCrowbar2Bolt *pBolt = CCrowbar2Bolt::BoltCreate();
pBolt->pev->origin = vecSrc;
pBolt->pev->angles = anglesAim;
pBolt->pev->owner = m_pPlayer->edict();
if( m_pPlayer->pev->waterlevel == 3 )
{
pBolt->pev->velocity = vecDir * BOLT_WATER_VELOCITY;
pBolt->pev->speed = BOLT_WATER_VELOCITY;
}
else
{
pBolt->pev->velocity = vecDir * BOLT_AIR_VELOCITY;
pBolt->pev->speed = BOLT_AIR_VELOCITY;
}
pBolt->pev->avelocity.z = 10;
#endif
if( !m_iClip && m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0 )
// HEV suit - indicate out of ammo condition
m_pPlayer->SetSuitUpdate( "!HEV_AMO0", FALSE, 0 );
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.35;
m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.35;
if( m_iClip != 0 )
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 5.0;
else
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 0.75;
}
void CCrowbar2::WeaponIdle( void )
{
m_pPlayer->GetAutoaimVector( AUTOAIM_2DEGREES ); // get the autoaim vector but ignore it; used for autoaim crosshair in DM
ResetEmptySound();
if( m_flTimeWeaponIdle < UTIL_WeaponTimeBase() )
{
float flRand = UTIL_SharedRandomFloat( m_pPlayer->random_seed, 0, 1 );
if( flRand <= 0.75 )
{
if( m_iClip )
{
SendWeaponAnim( CROSSBOW_IDLE );
}
else
{
SendWeaponAnim( CROSSBOW_IDLE );
}
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + UTIL_SharedRandomFloat( m_pPlayer->random_seed, 10, 15 );
}
else
{
if( m_iClip )
{
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 90.0 / 30.0;
}
else
{
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 80.0 / 30.0;
}
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + UTIL_SharedRandomFloat( m_pPlayer->random_seed, 10, 15 );
}
}
}
#endif

View File

@ -1,332 +0,0 @@
/***
*
* 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_crowbar, CCrowbar )
enum gauss_e
{
CROWBAR_IDLE = 0,
CROWBAR_DRAW,
CROWBAR_HOLSTER,
CROWBAR_ATTACK1HIT,
CROWBAR_ATTACK1MISS,
CROWBAR_ATTACK2MISS,
CROWBAR_ATTACK2HIT,
CROWBAR_ATTACK3MISS,
CROWBAR_ATTACK3HIT,
CROWBAR_TAUNT
};
void CCrowbar::Spawn( )
{
Precache();
m_iId = WEAPON_CROWBAR;
SET_MODEL( ENT( pev ), "models/w_crowbar.mdl" );
m_iClip = -1;
FallInit();// get ready to fall down.
}
void CCrowbar::Precache( void )
{
PRECACHE_MODEL( "models/v_crowbar.mdl" );
PRECACHE_MODEL( "models/w_crowbar.mdl" );
PRECACHE_MODEL( "models/p_crowbar.mdl" );
PRECACHE_SOUND( "weapons/cbar_hit1.wav" );
PRECACHE_SOUND( "weapons/cbar_hit2.wav" );
PRECACHE_SOUND( "weapons/cbar_hitbod1.wav" );
PRECACHE_SOUND( "weapons/cbar_hitbod2.wav" );
PRECACHE_SOUND( "weapons/cbar_hitbod3.wav" );
PRECACHE_SOUND( "weapons/cbar_miss1.wav" );
PRECACHE_SOUND( "taunts/taunt1.wav" );
PRECACHE_SOUND( "taunts/taunt2.wav" );
PRECACHE_SOUND( "taunts/taunt3.wav" );
PRECACHE_SOUND( "taunts/taunt4.wav" );
m_usCrowbar = PRECACHE_EVENT( 1, "events/crowbar.sc" );
}
int CCrowbar::GetItemInfo( ItemInfo *p )
{
p->pszName = STRING( pev->classname );
p->pszAmmo1 = NULL;
p->iMaxAmmo1 = -1;
p->pszAmmo2 = NULL;
p->iMaxAmmo2 = -1;
p->iMaxClip = WEAPON_NOCLIP;
p->iSlot = 0;
p->iPosition = 0;
p->iId = WEAPON_CROWBAR;
p->iWeight = CROWBAR_WEIGHT;
return 1;
}
BOOL CCrowbar::Deploy()
{
return DefaultDeploy( "models/v_crowbar.mdl", "models/p_crowbar.mdl", CROWBAR_DRAW, "crowbar" );
}
void CCrowbar::Holster( int skiplocal /* = 0 */ )
{
m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.5;
SendWeaponAnim( CROWBAR_HOLSTER );
}
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 CCrowbar::PrimaryAttack()
{
if( !Swing( 1 ) )
{
SetThink( &CCrowbar::SwingAgain );
pev->nextthink = gpGlobals->time + 0.1;
}
}
void CCrowbar::SecondaryAttack( void )
{
SendWeaponAnim( CROWBAR_TAUNT );
switch( RANDOM_LONG( 0, 3 ) )
{
case 0:
EMIT_SOUND( ENT( m_pPlayer->pev ), CHAN_ITEM, "taunts/taunt1.wav", 1, ATTN_NORM );
break;
case 1:
EMIT_SOUND( ENT( m_pPlayer->pev ), CHAN_ITEM, "taunts/taunt2.wav", 1, ATTN_NORM );
break;
case 2:
EMIT_SOUND( ENT( m_pPlayer->pev ), CHAN_ITEM, "taunts/taunt3.wav", 1, ATTN_NORM );
break;
case 3:
EMIT_SOUND( ENT( m_pPlayer->pev ), CHAN_ITEM, "taunts/taunt4.wav", 1, ATTN_NORM );
break;
};
pev->nextthink = gpGlobals->time + 2;
}
void CCrowbar::Smack()
{
DecalGunshot( &m_trHit, BULLET_PLAYER_CROWBAR );
}
void CCrowbar::SwingAgain( void )
{
Swing( 0 );
}
int CCrowbar::Swing( int fFirst )
{
int fDidHit = FALSE;
TraceResult tr;
UTIL_MakeVectors( m_pPlayer->pev->v_angle );
Vector vecSrc = m_pPlayer->GetGunPosition();
Vector vecEnd = vecSrc + gpGlobals->v_forward * 32;
UTIL_TraceLine( vecSrc, vecEnd, dont_ignore_monsters, ENT( m_pPlayer->pev ), &tr );
#ifndef CLIENT_DLL
if( tr.flFraction >= 1.0 )
{
UTIL_TraceHull( vecSrc, vecEnd, dont_ignore_monsters, head_hull, ENT( m_pPlayer->pev ), &tr );
if( tr.flFraction < 1.0 )
{
// Calculate the point of intersection of the line (or hull) and the object we hit
// This is and approximation of the "best" intersection
CBaseEntity *pHit = CBaseEntity::Instance( tr.pHit );
if( !pHit || pHit->IsBSPModel() )
FindHullIntersection( vecSrc, tr, VEC_DUCK_HULL_MIN, VEC_DUCK_HULL_MAX, m_pPlayer->edict() );
vecEnd = tr.vecEndPos; // This is the point on the actual surface (the hull could have hit space)
}
}
#endif
PLAYBACK_EVENT_FULL( FEV_NOTHOST, m_pPlayer->edict(), m_usCrowbar,
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 = UTIL_WeaponTimeBase() + 0.5;
// player "shoot" animation
m_pPlayer->SetAnimation( PLAYER_ATTACK1 );
}
}
else
{
switch( ( ( m_iSwing++ ) % 2 ) + 1 )
{
case 0:
SendWeaponAnim( CROWBAR_ATTACK1HIT );
break;
case 1:
SendWeaponAnim( CROWBAR_ATTACK2HIT );
break;
case 2:
SendWeaponAnim( CROWBAR_ATTACK3HIT );
break;
}
// player "shoot" animation
m_pPlayer->SetAnimation( PLAYER_ATTACK1 );
#ifndef CLIENT_DLL
// hit
fDidHit = TRUE;
CBaseEntity *pEntity = CBaseEntity::Instance( tr.pHit );
ClearMultiDamage();
if( ( m_flNextPrimaryAttack + 1 < UTIL_WeaponTimeBase() ) || g_pGameRules->IsMultiplayer() )
{
// first swing does full damage
pEntity->TraceAttack( m_pPlayer->pev, gSkillData.plrDmgCrowbar, gpGlobals->v_forward, &tr, DMG_CLUB );
}
else
{
// subsequent swings do half
pEntity->TraceAttack( m_pPlayer->pev, gSkillData.plrDmgCrowbar / 2, gpGlobals->v_forward, &tr, DMG_CLUB );
}
ApplyMultiDamage( m_pPlayer->pev, m_pPlayer->pev );
// play thwack, smack, or dong sound
float flVol = 1.0;
int fHitWorld = TRUE;
if( pEntity )
{
if( pEntity->Classify() != CLASS_NONE && pEntity->Classify() != CLASS_MACHINE )
{
// play thwack or smack sound
switch( RANDOM_LONG( 0, 2 ) )
{
case 0:
EMIT_SOUND( ENT( m_pPlayer->pev ), CHAN_ITEM, "weapons/cbar_hitbod1.wav", 1, ATTN_NORM );
break;
case 1:
EMIT_SOUND( ENT( m_pPlayer->pev ), CHAN_ITEM, "weapons/cbar_hitbod2.wav", 1, ATTN_NORM );
break;
case 2:
EMIT_SOUND( ENT( m_pPlayer->pev ), CHAN_ITEM, "weapons/cbar_hitbod3.wav", 1, ATTN_NORM );
break;
}
m_pPlayer->m_iWeaponVolume = CROWBAR_BODYHIT_VOLUME;
if( !pEntity->IsAlive() )
return TRUE;
else
flVol = 0.1;
fHitWorld = FALSE;
}
}
// play texture hit sound
// UNDONE: Calculate the correct point of intersection when we hit with the hull instead of the line
if( fHitWorld )
{
float fvolbar = TEXTURETYPE_PlaySound( &tr, vecSrc, vecSrc + ( vecEnd - vecSrc ) * 2, BULLET_PLAYER_CROWBAR );
if( g_pGameRules->IsMultiplayer() )
{
// override the volume here, cause we don't play texture sounds in multiplayer,
// and fvolbar is going to be 0 from the above call.
fvolbar = 1;
}
// also play crowbar strike
switch( RANDOM_LONG( 0, 1 ) )
{
case 0:
EMIT_SOUND_DYN( ENT( m_pPlayer->pev ), CHAN_ITEM, "weapons/cbar_hit1.wav", fvolbar, ATTN_NORM, 0, 98 + RANDOM_LONG( 0, 3 ) );
break;
case 1:
EMIT_SOUND_DYN( ENT( m_pPlayer->pev ), CHAN_ITEM, "weapons/cbar_hit2.wav", fvolbar, ATTN_NORM, 0, 98 + RANDOM_LONG( 0, 3 ) );
break;
}
// delay the decal a bit
m_trHit = tr;
}
m_pPlayer->m_iWeaponVolume = flVol * CROWBAR_WALLHIT_VOLUME;
#endif
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.25;
SetThink( &CCrowbar::Smack );
pev->nextthink = UTIL_WeaponTimeBase() + 0.2;
}
return fDidHit;
}

View File

@ -1,585 +0,0 @@
/***
*
* 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.
*
****/
/*
===== generic grenade.cpp ========================================================
*/
#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "monsters.h"
#include "weapons.h"
#include "nodes.h"
#include "soundent.h"
#include "decals.h"
//===================grenade
LINK_ENTITY_TO_CLASS( grenade, CGrenade )
// Grenades flagged with this will be triggered when the owner calls detonateSatchelCharges
#define SF_DETONATE 0x0001
//
// Grenade Explode
//
void CGrenade::Explode( Vector vecSrc, Vector vecAim )
{
TraceResult tr;
UTIL_TraceLine( pev->origin, pev->origin + Vector( 0, 0, -32 ), ignore_monsters, ENT( pev ), & tr );
Explode( &tr, DMG_BLAST );
}
// UNDONE: temporary scorching for PreAlpha - find a less sleazy permenant solution.
void CGrenade::Explode( TraceResult *pTrace, int bitsDamageType )
{
float flRndSound;// sound randomizer
pev->model = iStringNull;//invisible
pev->solid = SOLID_NOT;// intangible
pev->takedamage = DAMAGE_NO;
// Pull out of the wall a bit
if( pTrace->flFraction != 1.0 )
{
pev->origin = pTrace->vecEndPos + ( pTrace->vecPlaneNormal * ( pev->dmg - 24 ) * 0.6 );
}
int iContents = UTIL_PointContents( pev->origin );
MESSAGE_BEGIN( MSG_PAS, SVC_TEMPENTITY, pev->origin );
WRITE_BYTE( TE_EXPLOSION ); // This makes a dynamic light and the explosion sprites/sound
WRITE_COORD( pev->origin.x ); // Send to PAS because of the sound
WRITE_COORD( pev->origin.y );
WRITE_COORD( pev->origin.z );
if( iContents != CONTENTS_WATER )
{
WRITE_SHORT( g_sModelIndexFireball );
}
else
{
WRITE_SHORT( g_sModelIndexWExplosion );
}
WRITE_BYTE( ( pev->dmg - 50 ) * .60 ); // scale * 10
WRITE_BYTE( 15 ); // framerate
WRITE_BYTE( TE_EXPLFLAG_NONE );
MESSAGE_END();
CSoundEnt::InsertSound( bits_SOUND_COMBAT, pev->origin, NORMAL_EXPLOSION_VOLUME, 3.0 );
entvars_t *pevOwner;
if( pev->owner )
pevOwner = VARS( pev->owner );
else
pevOwner = NULL;
pev->owner = NULL; // can't traceline attack owner if this is set
RadiusDamage( pev, pevOwner, pev->dmg, CLASS_NONE, bitsDamageType );
if( RANDOM_FLOAT( 0, 1 ) < 0.5 )
{
UTIL_DecalTrace( pTrace, DECAL_SCORCH1 );
}
else
{
UTIL_DecalTrace( pTrace, DECAL_SCORCH2 );
}
flRndSound = RANDOM_FLOAT( 0, 1 );
switch( RANDOM_LONG( 0, 2 ) )
{
case 0:
EMIT_SOUND( ENT( pev ), CHAN_VOICE, "weapons/debris1.wav", 0.55, ATTN_NORM );
break;
case 1:
EMIT_SOUND( ENT( pev ), CHAN_VOICE, "weapons/debris2.wav", 0.55, ATTN_NORM );
break;
case 2:
EMIT_SOUND( ENT( pev ), CHAN_VOICE, "weapons/debris3.wav", 0.55, ATTN_NORM );
break;
}
pev->effects |= EF_NODRAW;
SetThink( &CGrenade::Smoke );
pev->velocity = g_vecZero;
pev->nextthink = gpGlobals->time + 0.3;
if( iContents != CONTENTS_WATER )
{
int sparkCount = RANDOM_LONG( 0, 3 );
for( int i = 0; i < sparkCount; i++ )
Create( "spark_shower", pev->origin, pTrace->vecPlaneNormal, NULL );
}
}
void CGrenade::Smoke( void )
{
if( UTIL_PointContents( pev->origin ) == CONTENTS_WATER )
{
UTIL_Bubbles( pev->origin - Vector( 64, 64, 64 ), pev->origin + Vector( 64, 64, 64 ), 100 );
}
else
{
MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, pev->origin );
WRITE_BYTE( TE_SMOKE );
WRITE_COORD( pev->origin.x );
WRITE_COORD( pev->origin.y );
WRITE_COORD( pev->origin.z );
WRITE_SHORT( g_sModelIndexSmoke );
WRITE_BYTE( ( pev->dmg - 50 ) * 0.80 ); // scale * 10
WRITE_BYTE( 12 ); // framerate
MESSAGE_END();
}
UTIL_Remove( this );
}
void CGrenade::Killed( entvars_t *pevAttacker, int iGib )
{
Detonate();
}
// Timed grenade, this think is called when time runs out.
void CGrenade::DetonateUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
SetThink( &CGrenade::Detonate );
pev->nextthink = gpGlobals->time;
}
void CGrenade::PreDetonate( void )
{
CSoundEnt::InsertSound ( bits_SOUND_DANGER, pev->origin, 400, 0.3 );
SetThink( &CGrenade::Detonate );
pev->nextthink = gpGlobals->time + 1;
}
void CGrenade::Detonate( void )
{
TraceResult tr;
Vector vecSpot;// trace starts here!
vecSpot = pev->origin + Vector( 0, 0, 8 );
UTIL_TraceLine( vecSpot, vecSpot + Vector( 0, 0, -40 ), ignore_monsters, ENT(pev), &tr );
Explode( &tr, DMG_BLAST );
}
//
// Contact grenade, explode when it touches something
//
void CGrenade::ExplodeTouch( CBaseEntity *pOther )
{
TraceResult tr;
Vector vecSpot;// trace starts here!
pev->enemy = pOther->edict();
vecSpot = pev->origin - pev->velocity.Normalize() * 32;
UTIL_TraceLine( vecSpot, vecSpot + pev->velocity.Normalize() * 64, ignore_monsters, ENT( pev ), &tr );
Explode( &tr, DMG_BLAST );
}
void CGrenade::DangerSoundThink( void )
{
if( !IsInWorld() )
{
UTIL_Remove( this );
return;
}
CSoundEnt::InsertSound ( bits_SOUND_DANGER, pev->origin + pev->velocity * 0.5, pev->velocity.Length(), 0.2 );
pev->nextthink = gpGlobals->time + 0.2;
if( pev->waterlevel != 0 )
{
pev->velocity = pev->velocity * 0.5;
}
}
void CGrenade::BounceTouch( CBaseEntity *pOther )
{
// don't hit the guy that launched this grenade
if( pOther->edict() == pev->owner )
return;
// only do damage if we're moving fairly fast
if( m_flNextAttack < gpGlobals->time && pev->velocity.Length() > 100 )
{
entvars_t *pevOwner = VARS( pev->owner );
if( pevOwner )
{
TraceResult tr = UTIL_GetGlobalTrace();
ClearMultiDamage();
pOther->TraceAttack( pevOwner, 1, gpGlobals->v_forward, &tr, DMG_CLUB );
ApplyMultiDamage( pev, pevOwner );
}
m_flNextAttack = gpGlobals->time + 1.0; // debounce
}
Vector vecTestVelocity;
// pev->avelocity = Vector( 300, 300, 300 );
// this is my heuristic for modulating the grenade velocity because grenades dropped purely vertical
// or thrown very far tend to slow down too quickly for me to always catch just by testing velocity.
// trimming the Z velocity a bit seems to help quite a bit.
vecTestVelocity = pev->velocity;
vecTestVelocity.z *= 0.45;
if( !m_fRegisteredSound && vecTestVelocity.Length() <= 60 )
{
//ALERT( at_console, "Grenade Registered!: %f\n", vecTestVelocity.Length() );
// grenade is moving really slow. It's probably very close to where it will ultimately stop moving.
// go ahead and emit the danger sound.
// register a radius louder than the explosion, so we make sure everyone gets out of the way
CSoundEnt::InsertSound( bits_SOUND_DANGER, pev->origin, pev->dmg / 0.4, 0.3 );
m_fRegisteredSound = TRUE;
}
if( pev->flags & FL_ONGROUND )
{
// add a bit of static friction
pev->velocity = pev->velocity * 0.8;
pev->sequence = RANDOM_LONG( 1, 1 );
}
else
{
// play bounce sound
BounceSound();
}
pev->framerate = pev->velocity.Length() / 200.0;
if( pev->framerate > 1.0 )
pev->framerate = 1;
else if( pev->framerate < 0.5 )
pev->framerate = 0;
}
void CGrenade::SlideTouch( CBaseEntity *pOther )
{
// don't hit the guy that launched this grenade
if( pOther->edict() == pev->owner )
return;
// pev->avelocity = Vector( 300, 300, 300 );
if( pev->flags & FL_ONGROUND )
{
// add a bit of static friction
pev->velocity = pev->velocity * 0.95;
if( pev->velocity.x != 0 || pev->velocity.y != 0 )
{
// maintain sliding sound
}
}
else
{
BounceSound();
}
}
void CGrenade::BounceSound( void )
{
switch( RANDOM_LONG( 0, 2 ) )
{
case 0:
EMIT_SOUND( ENT( pev ), CHAN_VOICE, "weapons/grenade_hit1.wav", 0.25, ATTN_NORM );
break;
case 1:
EMIT_SOUND( ENT( pev ), CHAN_VOICE, "weapons/grenade_hit2.wav", 0.25, ATTN_NORM );
break;
case 2:
EMIT_SOUND( ENT( pev ), CHAN_VOICE, "weapons/grenade_hit3.wav", 0.25, ATTN_NORM );
break;
}
}
void CGrenade::TumbleThink( void )
{
if( !IsInWorld() )
{
UTIL_Remove( this );
return;
}
StudioFrameAdvance();
pev->nextthink = gpGlobals->time + 0.1;
if( pev->dmgtime - 1 < gpGlobals->time )
{
CSoundEnt::InsertSound( bits_SOUND_DANGER, pev->origin + pev->velocity * ( pev->dmgtime - gpGlobals->time ), 400, 0.1 );
}
if( pev->dmgtime <= gpGlobals->time )
{
SetThink( &CGrenade::Detonate );
}
if( pev->waterlevel != 0 )
{
pev->velocity = pev->velocity * 0.5;
pev->framerate = 0.2;
}
}
void CGrenade::Spawn( void )
{
pev->movetype = MOVETYPE_BOUNCE;
pev->classname = MAKE_STRING( "grenade" );
pev->solid = SOLID_BBOX;
SET_MODEL( ENT( pev ), "models/grenade.mdl" );
UTIL_SetSize( pev, Vector( 0, 0, 0 ), Vector( 0, 0, 0 ) );
pev->dmg = 100;
m_fRegisteredSound = FALSE;
}
CGrenade *CGrenade::ShootContact( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity )
{
CGrenade *pGrenade = GetClassPtr( (CGrenade *)NULL );
pGrenade->Spawn();
// contact grenades arc lower
pGrenade->pev->gravity = 0.5;// lower gravity since grenade is aerodynamic and engine doesn't know it.
UTIL_SetOrigin( pGrenade->pev, vecStart );
pGrenade->pev->velocity = vecVelocity;
pGrenade->pev->angles = UTIL_VecToAngles( pGrenade->pev->velocity );
pGrenade->pev->owner = ENT( pevOwner );
// make monsters afaid of it while in the air
pGrenade->SetThink( &CGrenade::DangerSoundThink );
pGrenade->pev->nextthink = gpGlobals->time;
// Tumble in air
pGrenade->pev->avelocity.x = RANDOM_FLOAT( -100, -500 );
// Explode on contact
pGrenade->SetTouch( &CGrenade::ExplodeTouch );
pGrenade->pev->dmg = gSkillData.plrDmgM203Grenade;
return pGrenade;
}
CGrenade *CGrenadeRock::ShootTimed( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity, float time )
{
CGrenade *pGrenade = GetClassPtr( (CGrenade *)NULL );
pGrenade->Spawn();
UTIL_SetOrigin( pGrenade->pev, vecStart );
pGrenade->pev->velocity = vecVelocity;
pGrenade->pev->angles = UTIL_VecToAngles( pGrenade->pev->velocity );
pGrenade->pev->owner = ENT( pevOwner );
pGrenade->SetTouch( &CGrenadeRock::BounceTouch ); // Bounce if touched
// Take one second off of the desired detonation time and set the think to PreDetonate. PreDetonate
// will insert a DANGER sound into the world sound list and delay detonation for one second so that
// the grenade explodes after the exact amount of time specified in the call to ShootTimed().
pGrenade->pev->dmgtime = gpGlobals->time + time;
pGrenade->SetThink( &CGrenade::TumbleThink );
pGrenade->pev->nextthink = gpGlobals->time + 0.1;
if( time < 0.1 )
{
pGrenade->pev->nextthink = gpGlobals->time;
pGrenade->pev->velocity = Vector( 0, 0, 0 );
}
pGrenade->pev->sequence = RANDOM_LONG( 3, 6 );
pGrenade->pev->framerate = 1.0;
// Tumble through the air
// pGrenade->pev->avelocity.x = -400;
pGrenade->pev->gravity = 0.5;
pGrenade->pev->friction = 0.8;
SET_MODEL( ENT( pGrenade->pev ), "models/w_rock.mdl" );
pGrenade->pev->dmg = 100;
return pGrenade;
}
CGrenade *CGrenade::ShootTimed( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity, float time )
{
CGrenade *pGrenade = GetClassPtr( (CGrenade *)NULL );
pGrenade->Spawn();
UTIL_SetOrigin( pGrenade->pev, vecStart );
pGrenade->pev->velocity = vecVelocity;
pGrenade->pev->angles = UTIL_VecToAngles( pGrenade->pev->velocity );
pGrenade->pev->owner = ENT( pevOwner );
pGrenade->SetTouch( &CGrenade::BounceTouch ); // Bounce if touched
// Take one second off of the desired detonation time and set the think to PreDetonate. PreDetonate
// will insert a DANGER sound into the world sound list and delay detonation for one second so that
// the grenade explodes after the exact amount of time specified in the call to ShootTimed().
pGrenade->pev->dmgtime = gpGlobals->time + time;
pGrenade->SetThink( &CGrenade::TumbleThink );
pGrenade->pev->nextthink = gpGlobals->time + 0.1;
if( time < 0.1 )
{
pGrenade->pev->nextthink = gpGlobals->time;
pGrenade->pev->velocity = Vector( 0, 0, 0 );
}
pGrenade->pev->sequence = RANDOM_LONG( 3, 6 );
pGrenade->pev->framerate = 1.0;
// Tumble through the air
// pGrenade->pev->avelocity.x = -400;
pGrenade->pev->gravity = 0.5;
pGrenade->pev->friction = 0.8;
SET_MODEL( ENT( pGrenade->pev ), "models/w_grenade.mdl" );
pGrenade->pev->dmg = 100;
return pGrenade;
}
CGrenade *CGrenade::ShootSatchelCharge( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity )
{
CGrenade *pGrenade = GetClassPtr( (CGrenade *)NULL );
pGrenade->pev->movetype = MOVETYPE_BOUNCE;
pGrenade->pev->classname = MAKE_STRING( "grenade" );
pGrenade->pev->solid = SOLID_BBOX;
SET_MODEL( ENT( pGrenade->pev ), "models/grenade.mdl" ); // Change this to satchel charge model
UTIL_SetSize( pGrenade->pev, Vector( 0, 0, 0 ), Vector( 0, 0, 0 ) );
pGrenade->pev->dmg = 200;
UTIL_SetOrigin( pGrenade->pev, vecStart );
pGrenade->pev->velocity = vecVelocity;
pGrenade->pev->angles = g_vecZero;
pGrenade->pev->owner = ENT( pevOwner );
// Detonate in "time" seconds
pGrenade->SetThink( &CBaseEntity::SUB_DoNothing );
pGrenade->SetUse( &CGrenade::DetonateUse );
pGrenade->SetTouch( &CGrenade::SlideTouch );
pGrenade->pev->spawnflags = SF_DETONATE;
pGrenade->pev->friction = 0.9;
return pGrenade;
}
void CGrenadeRock::BounceTouch( CBaseEntity *pOther )
{
// don't hit the guy that launched this grenade
if( pOther->edict() == pev->owner )
return;
// only do damage if we're moving fairly fast
if( m_flNextAttack < gpGlobals->time && pev->velocity.Length() > 100 )
{
entvars_t *pevOwner = VARS( pev->owner );
if( pevOwner )
{
TraceResult tr = UTIL_GetGlobalTrace();
ClearMultiDamage();
pOther->TraceAttack( pevOwner, 10, gpGlobals->v_forward, &tr, DMG_GIBALWAYS );
ApplyMultiDamage( pev, pevOwner );
}
m_flNextAttack = gpGlobals->time + 1.0; // debounce
}
Vector vecTestVelocity;
// pev->avelocity = Vector( 300, 300, 300 );
// this is my heuristic for modulating the grenade velocity because grenades dropped purely vertical
// or thrown very far tend to slow down too quickly for me to always catch just by testing velocity.
// trimming the Z velocity a bit seems to help quite a bit.
vecTestVelocity = pev->velocity;
vecTestVelocity.z *= 0.45;
if( !m_fRegisteredSound && vecTestVelocity.Length() <= 60 )
{
//ALERT( at_console, "Grenade Registered!: %f\n", vecTestVelocity.Length() );
// grenade is moving really slow. It's probably very close to where it will ultimately stop moving.
// go ahead and emit the danger sound.
// register a radius louder than the explosion, so we make sure everyone gets out of the way
CSoundEnt::InsertSound( bits_SOUND_DANGER, pev->origin, pev->dmg / 0.4, 0.3 );
m_fRegisteredSound = TRUE;
}
if( pev->flags & FL_ONGROUND )
{
// add a bit of static friction
pev->velocity = pev->velocity * 0.8;
pev->sequence = RANDOM_LONG( 1, 1 );
}
else
{
// play bounce sound
BounceSound();
}
pev->framerate = pev->velocity.Length() / 200.0;
if( pev->framerate > 1.0 )
pev->framerate = 1;
else if( pev->framerate < 0.5 )
pev->framerate = 0;
}
void CGrenade::UseSatchelCharges( entvars_t *pevOwner, SATCHELCODE code )
{
edict_t *pentFind;
edict_t *pentOwner;
if( !pevOwner )
return;
CBaseEntity *pOwner = CBaseEntity::Instance( pevOwner );
pentOwner = pOwner->edict();
pentFind = FIND_ENTITY_BY_CLASSNAME( NULL, "grenade" );
while( !FNullEnt( pentFind ) )
{
CBaseEntity *pEnt = Instance( pentFind );
if( pEnt )
{
if( FBitSet( pEnt->pev->spawnflags, SF_DETONATE ) && pEnt->pev->owner == pentOwner )
{
if( code == SATCHEL_DETONATE )
pEnt->Use( pOwner, pOwner, USE_ON, 0 );
else // SATCHEL_RELEASE
pEnt->pev->owner = NULL;
}
}
pentFind = FIND_ENTITY_BY_CLASSNAME( pentFind, "grenade" );
}
}
//======================end grenade

View File

@ -1,213 +0,0 @@
/*
Здесь был rainbow
*/
#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 handgrenade_e
{
HANDGRENADE_IDLE = 0,
HANDGRENADE_FIDGET,
HANDGRENADE_PINPULL,
HANDGRENADE_THROW1, // toss
HANDGRENADE_THROW2, // medium
HANDGRENADE_THROW3, // hard
HANDGRENADE_HOLSTER,
HANDGRENADE_DRAW
};
LINK_ENTITY_TO_CLASS( weapon_handgrenade, CHandGrenade )
void CHandGrenade::Spawn()
{
Precache();
m_iId = WEAPON_HANDGRENADE;
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 CHandGrenade::Precache( void )
{
PRECACHE_MODEL( "models/w_grenade.mdl" );
PRECACHE_MODEL( "models/v_grenade.mdl" );
PRECACHE_MODEL( "models/p_grenade.mdl" );
}
int CHandGrenade::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 = 0;
p->iId = m_iId = WEAPON_HANDGRENADE;
p->iWeight = HANDGRENADE_WEIGHT;
p->iFlags = ITEM_FLAG_LIMITINWORLD | ITEM_FLAG_EXHAUSTIBLE;
return 1;
}
BOOL CHandGrenade::Deploy()
{
m_flReleaseThrow = -1;
return DefaultDeploy( "models/v_grenade.mdl", "models/p_grenade.mdl", HANDGRENADE_DRAW, "crowbar" );
}
BOOL CHandGrenade::CanHolster( void )
{
// can only holster hand grenades when not primed!
return ( m_flStartThrow == 0 );
}
void CHandGrenade::Holster( int skiplocal /* = 0 */ )
{
m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.5;
if( m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] )
{
SendWeaponAnim( HANDGRENADE_HOLSTER );
}
else
{
// no more grenades!
m_pPlayer->pev->weapons &= ~( 1 << WEAPON_HANDGRENADE );
SetThink( &CBasePlayerItem::DestroyItem );
pev->nextthink = gpGlobals->time + 0.1;
}
EMIT_SOUND( ENT( m_pPlayer->pev ), CHAN_WEAPON, "common/null.wav", 1.0, ATTN_NORM );
}
void CHandGrenade::PrimaryAttack()
{
if( !m_flStartThrow && m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] > 0 )
{
m_flStartThrow = gpGlobals->time;
m_flReleaseThrow = 0;
SendWeaponAnim( HANDGRENADE_PINPULL );
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 0.5;
}
}
void CHandGrenade::WeaponIdle( void )
{
if( m_flReleaseThrow == 0 && m_flStartThrow )
m_flReleaseThrow = gpGlobals->time;
if( m_flTimeWeaponIdle > UTIL_WeaponTimeBase() )
return;
if( m_flStartThrow )
{
Vector angThrow = m_pPlayer->pev->v_angle + m_pPlayer->pev->punchangle;
if( angThrow.x < 0 )
angThrow.x = -10 + angThrow.x * ( ( 90 - 10 ) / 90.0 );
else
angThrow.x = -10 + angThrow.x * ( ( 90 + 10 ) / 90.0 );
float flVel = ( 90 - angThrow.x ) * 4;
if( flVel > 500 )
flVel = 500;
UTIL_MakeVectors( angThrow );
Vector vecSrc = m_pPlayer->pev->origin + m_pPlayer->pev->view_ofs + gpGlobals->v_forward * 16;
Vector vecThrow = gpGlobals->v_forward * flVel + m_pPlayer->pev->velocity;
// alway explode 3 seconds after the pin was pulled
float time = m_flStartThrow - gpGlobals->time + 3.0;
if( time < 0 )
time = 0;
CGrenade::ShootTimed( m_pPlayer->pev, vecSrc, vecThrow, time );
if( flVel < 500 )
{
SendWeaponAnim( HANDGRENADE_THROW1 );
}
else if( flVel < 1000 )
{
SendWeaponAnim( HANDGRENADE_THROW2 );
}
else
{
SendWeaponAnim( HANDGRENADE_THROW3 );
}
// player "shoot" animation
m_pPlayer->SetAnimation( PLAYER_ATTACK1 );
m_flReleaseThrow = 0;
m_flStartThrow = 0;
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.5;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 0.5;
m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]--;
if( !m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] )
{
// 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 = UTIL_WeaponTimeBase() + 0.5;// ensure that the animation can finish playing
}
return;
}
else if( m_flReleaseThrow > 0 )
{
// we've finished the throw, restart.
m_flStartThrow = 0;
if( m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] )
{
SendWeaponAnim( HANDGRENADE_DRAW );
}
else
{
RetireWeapon();
return;
}
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + UTIL_SharedRandomFloat( m_pPlayer->random_seed, 10, 15 );
m_flReleaseThrow = -1;
return;
}
if( m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] )
{
int iAnim;
float flRand = UTIL_SharedRandomFloat( m_pPlayer->random_seed, 0, 1 );
if( flRand <= 0.75 )
{
iAnim = HANDGRENADE_IDLE;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + UTIL_SharedRandomFloat( m_pPlayer->random_seed, 10, 15 );// how long till we do this again.
}
else
{
iAnim = HANDGRENADE_FIDGET;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 75.0 / 30.0;
}
SendWeaponAnim( iAnim );
}
}

View File

@ -1,307 +0,0 @@
/***
*
* 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_katana, CKatana )
enum gauss_e
{
CROWBAR_IDLE = 0,
CROWBAR_DRAW,
CROWBAR_HOLSTER,
CROWBAR_ATTACK1HIT,
CROWBAR_ATTACK1MISS,
CROWBAR_ATTACK2MISS,
CROWBAR_ATTACK2HIT,
CROWBAR_ATTACK3MISS,
CROWBAR_ATTACK3HIT
};
void CKatana::Spawn( )
{
Precache();
m_iId = WEAPON_KATANA;
SET_MODEL( ENT( pev ), "models/w_katana.mdl" );
m_iClip = -1;
FallInit();// get ready to fall down.
}
void CKatana::Precache( void )
{
PRECACHE_MODEL( "models/v_katana.mdl" );
PRECACHE_MODEL( "models/w_katana.mdl" );
PRECACHE_MODEL( "models/p_katana.mdl" );
PRECACHE_SOUND( "weapons/katana_hit1.wav" );
PRECACHE_SOUND( "weapons/katana_hit2.wav" );
PRECACHE_SOUND( "weapons/katana_hitbod1.wav" );
PRECACHE_SOUND( "weapons/katana_hitbod2.wav" );
PRECACHE_SOUND( "weapons/katana_hitbod3.wav" );
PRECACHE_SOUND( "weapons/katana_miss1.wav" );
m_usKatana = PRECACHE_EVENT( 1, "events/crowbar.sc" );
}
int CKatana::GetItemInfo( ItemInfo *p )
{
p->pszName = STRING( pev->classname );
p->pszAmmo1 = NULL;
p->iMaxAmmo1 = -1;
p->pszAmmo2 = NULL;
p->iMaxAmmo2 = -1;
p->iMaxClip = WEAPON_NOCLIP;
p->iSlot = 0;
p->iPosition = 1;
p->iId = WEAPON_KATANA;
p->iWeight = CROWBAR_WEIGHT;
return 1;
}
BOOL CKatana::Deploy()
{
return DefaultDeploy( "models/v_katana.mdl", "models/p_katana.mdl", CROWBAR_DRAW, "katana" );
}
void CKatana::Holster( int skiplocal /* = 0 */ )
{
m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.5;
SendWeaponAnim( CROWBAR_HOLSTER );
}
void FindHullIntersection3( 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 CKatana::PrimaryAttack()
{
if( !Swing( 1 ) )
{
SetThink( &CKatana::SwingAgain );
pev->nextthink = gpGlobals->time + 0.1;
}
}
void CKatana::Smack()
{
DecalGunshot( &m_trHit, BULLET_PLAYER_CROWBAR );
}
void CKatana::SwingAgain( void )
{
Swing( 0 );
}
int CKatana::Swing( int fFirst )
{
int fDidHit = FALSE;
TraceResult tr;
UTIL_MakeVectors( m_pPlayer->pev->v_angle );
Vector vecSrc = m_pPlayer->GetGunPosition();
Vector vecEnd = vecSrc + gpGlobals->v_forward * 32;
UTIL_TraceLine( vecSrc, vecEnd, dont_ignore_monsters, ENT( m_pPlayer->pev ), &tr );
#ifndef CLIENT_DLL
if( tr.flFraction >= 1.0 )
{
UTIL_TraceHull( vecSrc, vecEnd, dont_ignore_monsters, head_hull, ENT( m_pPlayer->pev ), &tr );
if( tr.flFraction < 1.0 )
{
// Calculate the point of intersection of the line (or hull) and the object we hit
// This is and approximation of the "best" intersection
CBaseEntity *pHit = CBaseEntity::Instance( tr.pHit );
if( !pHit || pHit->IsBSPModel() )
FindHullIntersection3( 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_usKatana,
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 = UTIL_WeaponTimeBase() + 0.5;
// player "shoot" animation
m_pPlayer->SetAnimation( PLAYER_ATTACK1 );
}
}
else
{
switch( ( ( m_iSwing++ ) % 2 ) + 1 )
{
case 0:
SendWeaponAnim( CROWBAR_ATTACK1HIT );
break;
case 1:
SendWeaponAnim( CROWBAR_ATTACK2HIT );
break;
case 2:
SendWeaponAnim( CROWBAR_ATTACK3HIT );
break;
}
// player "shoot" animation
m_pPlayer->SetAnimation( PLAYER_ATTACK1 );
#ifndef CLIENT_DLL
// hit
fDidHit = TRUE;
CBaseEntity *pEntity = CBaseEntity::Instance( tr.pHit );
ClearMultiDamage();
if( ( m_flNextPrimaryAttack + 1 < UTIL_WeaponTimeBase() ) || g_pGameRules->IsMultiplayer() )
{
// first swing does full damage
pEntity->TraceAttack( m_pPlayer->pev, gSkillData.plrDmgCrowbar, gpGlobals->v_forward, &tr, DMG_CLUB );
}
else
{
// subsequent swings do half
pEntity->TraceAttack( m_pPlayer->pev, 30, gpGlobals->v_forward, &tr, DMG_CLUB );
}
ApplyMultiDamage( m_pPlayer->pev, m_pPlayer->pev );
// play thwack, smack, or dong sound
float flVol = 1.0;
int fHitWorld = TRUE;
if( pEntity )
{
if( pEntity->Classify() != CLASS_NONE && pEntity->Classify() != CLASS_MACHINE )
{
// play thwack or smack sound
switch( RANDOM_LONG( 0, 2 ) )
{
case 0:
EMIT_SOUND( ENT( m_pPlayer->pev ), CHAN_ITEM, "weapons/katana_hitbod1.wav", 1, ATTN_NORM );
break;
case 1:
EMIT_SOUND( ENT( m_pPlayer->pev ), CHAN_ITEM, "weapons/katana_hitbod2.wav", 1, ATTN_NORM );
break;
case 2:
EMIT_SOUND( ENT( m_pPlayer->pev ), CHAN_ITEM, "weapons/katana_hitbod3.wav", 1, ATTN_NORM );
break;
}
m_pPlayer->m_iWeaponVolume = CROWBAR_BODYHIT_VOLUME;
if( !pEntity->IsAlive() )
return TRUE;
else
flVol = 0.1;
fHitWorld = FALSE;
}
}
// play texture hit sound
// UNDONE: Calculate the correct point of intersection when we hit with the hull instead of the line
if( fHitWorld )
{
float fvolbar = TEXTURETYPE_PlaySound( &tr, vecSrc, vecSrc + ( vecEnd - vecSrc ) * 2, BULLET_PLAYER_CROWBAR );
if( g_pGameRules->IsMultiplayer() )
{
// override the volume here, cause we don't play texture sounds in multiplayer,
// and fvolbar is going to be 0 from the above call.
fvolbar = 1;
}
// also play crowbar strike
switch( RANDOM_LONG( 0, 1 ) )
{
case 0:
EMIT_SOUND_DYN( ENT( m_pPlayer->pev ), CHAN_ITEM, "weapons/katana_hit1.wav", fvolbar, ATTN_NORM, 0, 98 + RANDOM_LONG( 0, 3 ) );
break;
case 1:
EMIT_SOUND_DYN( ENT( m_pPlayer->pev ), CHAN_ITEM, "weapons/katana_hit2.wav", fvolbar, ATTN_NORM, 0, 98 + RANDOM_LONG( 0, 3 ) );
break;
}
// delay the decal a bit
m_trHit = tr;
}
m_pPlayer->m_iWeaponVolume = flVol * CROWBAR_WALLHIT_VOLUME;
#endif
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.25;
SetThink( &CKatana::Smack );
pev->nextthink = UTIL_WeaponTimeBase() + 0.2;
}
return fDidHit;
}

View File

@ -1,271 +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.
*
* 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"
void FindHullIntersection(const Vector &vecSrc, TraceResult &tr, float *mins, float *maxs, edict_t *pEntity);
#define KNIFE_BODYHIT_VOLUME 128
#define KNIFE_WALLHIT_VOLUME 512
LINK_ENTITY_TO_CLASS(weapon_knife, CKnife);
enum knife_e {
KNIFE_IDLE1 = 0,
KNIFE_DRAW,
KNIFE_HOLSTER,
KNIFE_ATTACK1HIT,
KNIFE_ATTACK1MISS,
KNIFE_ATTACK2MISS,
KNIFE_ATTACK2HIT,
KNIFE_ATTACK3MISS,
KNIFE_ATTACK3HIT,
KNIFE_IDLE2,
KNIFE_IDLE3,
KNIFE_CHARGE,
KNIFE_STAB,
};
void CKnife::Spawn()
{
Precache();
m_iId = WEAPON_KNIFE;
SET_MODEL(ENT(pev), "models/w_knife.mdl");
m_iClip = -1;
FallInit();// get ready to fall down.
}
void CKnife::Precache(void)
{
PRECACHE_MODEL("models/v_knife.mdl");
PRECACHE_MODEL("models/w_knife.mdl");
PRECACHE_MODEL("models/p_knife.mdl");
PRECACHE_SOUND("weapons/knife_hit_flesh1.wav");
PRECACHE_SOUND("weapons/knife_hit_flesh2.wav");
PRECACHE_SOUND("weapons/knife_hit_wall1.wav");
PRECACHE_SOUND("weapons/knife_hit_wall2.wav");
PRECACHE_SOUND("weapons/knife1.wav");
PRECACHE_SOUND("weapons/knife2.wav");
PRECACHE_SOUND("weapons/knife3.wav");
m_usKnife = PRECACHE_EVENT(1, "events/knife.sc");
}
int CKnife::GetItemInfo(ItemInfo *p)
{
p->pszName = STRING(pev->classname);
p->pszAmmo1 = NULL;
p->iMaxAmmo1 = -1;
p->pszAmmo2 = NULL;
p->iMaxAmmo2 = -1;
p->iMaxClip = WEAPON_NOCLIP;
p->iSlot = 0;
p->iPosition = 2;
p->iId = WEAPON_KNIFE;
p->iWeight = KNIFE_WEIGHT;
return 1;
}
BOOL CKnife::Deploy()
{
return DefaultDeploy("models/v_knife.mdl", "models/p_knife.mdl", KNIFE_DRAW, "knife");
}
void CKnife::Holster(int skiplocal /* = 0 */)
{
m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.5;
SendWeaponAnim(KNIFE_HOLSTER);
}
void CKnife::PrimaryAttack()
{
if (!Swing(1))
{
SetThink(&CKnife::SwingAgain);
pev->nextthink = gpGlobals->time + 0.1;
}
}
void CKnife::Smack()
{
DecalGunshot(&m_trHit, BULLET_PLAYER_CROWBAR);
}
void CKnife::SwingAgain(void)
{
Swing(0);
}
int CKnife::Swing(int fFirst)
{
int fDidHit = FALSE;
TraceResult tr;
UTIL_MakeVectors(m_pPlayer->pev->v_angle);
Vector vecSrc = m_pPlayer->GetGunPosition();
Vector vecEnd = vecSrc + gpGlobals->v_forward * 32;
UTIL_TraceLine(vecSrc, vecEnd, dont_ignore_monsters, ENT(m_pPlayer->pev), &tr);
#ifndef CLIENT_DLL
if (tr.flFraction >= 1.0)
{
UTIL_TraceHull(vecSrc, vecEnd, dont_ignore_monsters, head_hull, ENT(m_pPlayer->pev), &tr);
if (tr.flFraction < 1.0)
{
// Calculate the point of intersection of the line (or hull) and the object we hit
// This is and approximation of the "best" intersection
CBaseEntity *pHit = CBaseEntity::Instance(tr.pHit);
if (!pHit || pHit->IsBSPModel())
FindHullIntersection(vecSrc, tr, VEC_DUCK_HULL_MIN, VEC_DUCK_HULL_MAX, m_pPlayer->edict());
vecEnd = tr.vecEndPos; // This is the point on the actual surface (the hull could have hit space)
}
}
#endif
PLAYBACK_EVENT_FULL(FEV_NOTHOST, m_pPlayer->edict(), m_usKnife,
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);
// player "shoot" animation
m_pPlayer->SetAnimation(PLAYER_ATTACK1);
}
}
else
{
switch (((m_iSwing++) % 2) + 1)
{
case 0:
SendWeaponAnim(KNIFE_ATTACK1HIT); break;
case 1:
SendWeaponAnim(KNIFE_ATTACK2HIT); break;
case 2:
SendWeaponAnim(KNIFE_ATTACK3HIT); break;
}
// player "shoot" animation
m_pPlayer->SetAnimation(PLAYER_ATTACK1);
#ifndef CLIENT_DLL
// hit
fDidHit = TRUE;
CBaseEntity *pEntity = CBaseEntity::Instance(tr.pHit);
ClearMultiDamage();
if ((m_flNextPrimaryAttack + 1 < UTIL_WeaponTimeBase()) || g_pGameRules->IsMultiplayer())
{
// first swing does full damage
pEntity->TraceAttack(m_pPlayer->pev, gSkillData.plrDmgKnife, gpGlobals->v_forward, &tr, DMG_CLUB);
}
else
{
// subsequent swings do half
pEntity->TraceAttack(m_pPlayer->pev, gSkillData.plrDmgKnife / 2, gpGlobals->v_forward, &tr, DMG_CLUB);
}
ApplyMultiDamage(m_pPlayer->pev, m_pPlayer->pev);
// play thwack, smack, or dong sound
float flVol = 1.0;
int fHitWorld = TRUE;
if (pEntity)
{
if (pEntity->Classify() != CLASS_NONE && pEntity->Classify() != CLASS_MACHINE)
{
// play thwack or smack sound
switch (RANDOM_LONG(0, 1))
{
case 0:
EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/knife_hit_flesh1.wav", 1, ATTN_NORM); break;
case 1:
EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/knife_hit_flesh2.wav", 1, ATTN_NORM); break;
}
m_pPlayer->m_iWeaponVolume = KNIFE_BODYHIT_VOLUME;
if (!pEntity->IsAlive())
return TRUE;
else
flVol = 0.1;
fHitWorld = FALSE;
}
}
// play texture hit sound
// UNDONE: Calculate the correct point of intersection when we hit with the hull instead of the line
if (fHitWorld)
{
float fvolbar = TEXTURETYPE_PlaySound(&tr, vecSrc, vecSrc + (vecEnd - vecSrc) * 2, BULLET_PLAYER_CROWBAR);
if (g_pGameRules->IsMultiplayer())
{
// override the volume here, cause we don't play texture sounds in multiplayer,
// and fvolbar is going to be 0 from the above call.
fvolbar = 1;
}
// also play crowbar strike
switch (RANDOM_LONG(0, 1))
{
case 0:
EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/knife_hit_wall1.wav", fvolbar, ATTN_NORM, 0, 98 + RANDOM_LONG(0, 3));
break;
case 1:
EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/knife_hit_wall2.wav", fvolbar, ATTN_NORM, 0, 98 + RANDOM_LONG(0, 3));
break;
}
// delay the decal a bit
m_trHit = tr;
}
m_pPlayer->m_iWeaponVolume = flVol * KNIFE_WALLHIT_VOLUME;
#endif
m_flNextPrimaryAttack = GetNextAttackDelay(0.25);
SetThink(&CKnife::Smack);
pev->nextthink = UTIL_WeaponTimeBase() + 0.2;
}
return fDidHit;
}

View File

@ -1,205 +0,0 @@
/*
Здесь был rainbow
*/
#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 handgrenade_e
{
HANDGRENADE_IDLE = 0,
HANDGRENADE_FIRE,
HANDGRENADE_OPEN,
HANDGRENADE_INSERT,
HANDGRENADE_CLOSE,
HANDGRENADE_DRAW
};
LINK_ENTITY_TO_CLASS( weapon_pepsigun, CPepsigun )
LINK_ENTITY_TO_CLASS( ammo_pepsi, CPepsigun )
void CPepsigun::Spawn()
{
Precache();
m_iId = WEAPON_PEPSIGUN;
SET_MODEL( ENT( pev ), "models/w_pepsigun.mdl" );
#ifndef CLIENT_DLL
pev->dmg = 80;
#endif
m_iDefaultAmmo = 10000;
FallInit();// get ready to fall down.
}
void CPepsigun::Precache( void )
{
PRECACHE_MODEL( "models/w_pepsigun.mdl" );
PRECACHE_MODEL( "models/v_pepsigun.mdl" );
PRECACHE_MODEL( "models/p_pepsigun.mdl" );
}
int CPepsigun::GetItemInfo( ItemInfo *p )
{
p->pszName = STRING( pev->classname );
p->pszAmmo1 = "pepsi";
p->iMaxAmmo1 = 20000;
p->pszAmmo2 = NULL;
p->iMaxAmmo2 = -1;
p->iMaxClip = -1;
p->iSlot = 2;
p->iPosition = 4;
p->iId = m_iId = WEAPON_PEPSIGUN;
p->iWeight = PEPSIGUN_WEIGHT;
p->iFlags = ITEM_FLAG_LIMITINWORLD | ITEM_FLAG_EXHAUSTIBLE;
return 1;
}
BOOL CPepsigun::Deploy()
{
m_flReleaseThrow = -1;
return DefaultDeploy( "models/v_pepsigun.mdl", "models/p_pepsigun.mdl", HANDGRENADE_DRAW, "crowbar" );
}
BOOL CPepsigun::CanHolster( void )
{
// can only holster hand grenades when not primed!
return ( m_flStartThrow == 0 );
}
void CPepsigun::Holster( int skiplocal /* = 0 */ )
{
m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.5;
if( m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] )
{
}
else
{
// no more grenades!
m_pPlayer->pev->weapons &= ~( 1 << WEAPON_PEPSIGUN );
SetThink( &CBasePlayerItem::DestroyItem );
pev->nextthink = gpGlobals->time + 0.1;
}
EMIT_SOUND( ENT( m_pPlayer->pev ), CHAN_WEAPON, "common/null.wav", 1.0, ATTN_NORM );
}
void CPepsigun::PrimaryAttack()
{
m_flStartThrow = gpGlobals->time;
m_flReleaseThrow = 0;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 0.25;
}
void CPepsigun::WeaponIdle( void )
{
if( m_flReleaseThrow == 0 && m_flStartThrow )
m_flReleaseThrow = gpGlobals->time;
if( m_flTimeWeaponIdle > UTIL_WeaponTimeBase() )
return;
if( m_flStartThrow )
{
Vector angThrow = m_pPlayer->pev->v_angle + m_pPlayer->pev->punchangle;
if( angThrow.x < 0 )
angThrow.x = -10 + angThrow.x * ( ( 90 - 10 ) / 90.0 );
else
angThrow.x = -10 + angThrow.x * ( ( 90 + 10 ) / 90.0 );
float flVel = ( 90 - angThrow.x ) * 4;
if( flVel > 500 )
flVel = 1400;
UTIL_MakeVectors( angThrow );
Vector vecSrc = m_pPlayer->pev->origin + m_pPlayer->pev->view_ofs + gpGlobals->v_forward * 16;
Vector vecThrow = gpGlobals->v_forward * flVel + m_pPlayer->pev->velocity;
// alway explode 3 seconds after the pin was pulled
float time = m_flStartThrow - gpGlobals->time + 3.0;
if( time < 0 )
time = 0;
CGrenade::ShootTimed( m_pPlayer->pev, vecSrc, vecThrow, time );
if( flVel < 500 )
{
SendWeaponAnim( HANDGRENADE_FIRE );
}
else if( flVel < 1000 )
{
SendWeaponAnim( HANDGRENADE_FIRE );
}
else
{
SendWeaponAnim( HANDGRENADE_FIRE );
}
// player "shoot" animation
m_pPlayer->SetAnimation( PLAYER_ATTACK1 );
m_flReleaseThrow = 0;
m_flStartThrow = 0;
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.5;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 0.5;
if( !m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] )
{
// 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 = UTIL_WeaponTimeBase() + 0.5;// ensure that the animation can finish playing
}
return;
}
else if( m_flReleaseThrow > 0 )
{
// we've finished the throw, restart.
m_flStartThrow = 0;
if( m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] )
{
SendWeaponAnim( HANDGRENADE_DRAW );
}
else
{
RetireWeapon();
return;
}
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + UTIL_SharedRandomFloat( m_pPlayer->random_seed, 10, 15 );
m_flReleaseThrow = -1;
return;
}
if( m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] )
{
int iAnim;
float flRand = UTIL_SharedRandomFloat( m_pPlayer->random_seed, 0, 1 );
if( flRand <= 0.75 )
{
iAnim = HANDGRENADE_IDLE;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + UTIL_SharedRandomFloat( m_pPlayer->random_seed, 10, 15 );// how long till we do this again.
}
else
{
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 75.0 / 30.0;
}
}
}

View File

@ -1,211 +0,0 @@
/*
Здесь был rainbow
*/
#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 handgrenade_e
{
HANDGRENADE_IDLE = 0,
HANDGRENADE_THROW2,
HANDGRENADE_DRAW,
HANDGRENADE_FIDGET
};
LINK_ENTITY_TO_CLASS( weapon_rock, CRock )
void CRock::Spawn()
{
Precache();
m_iId = WEAPON_ROCK;
SET_MODEL( ENT( pev ), "models/w_rock.mdl" );
#ifndef CLIENT_DLL
pev->dmg = 40;
#endif
m_iDefaultAmmo = 10000000;
FallInit();// get ready to fall down.
}
void CRock::Precache( void )
{
PRECACHE_MODEL( "models/w_rock.mdl" );
PRECACHE_MODEL( "models/v_rock.mdl" );
PRECACHE_MODEL( "models/p_rock.mdl" );
}
int CRock::GetItemInfo( ItemInfo *p )
{
p->pszName = STRING( pev->classname );
p->pszAmmo1 = "Hand Grenade";
p->iMaxAmmo1 = 10000000000000;
p->pszAmmo2 = NULL;
p->iMaxAmmo2 = -1;
p->iMaxClip = WEAPON_NOCLIP;
p->iSlot = 4;
p->iPosition = 4;
p->iId = m_iId = WEAPON_ROCK;
p->iWeight = HANDGRENADE_WEIGHT;
p->iFlags = ITEM_FLAG_LIMITINWORLD | ITEM_FLAG_EXHAUSTIBLE;
return 1;
}
BOOL CRock::Deploy()
{
m_flReleaseThrow = -1;
return DefaultDeploy( "models/v_rock.mdl", "models/p_rock.mdl", HANDGRENADE_DRAW, "crowbar" );
}
BOOL CRock::CanHolster( void )
{
// can only holster hand grenades when not primed!
return ( m_flStartThrow == 0 );
}
void CRock::Holster( int skiplocal /* = 0 */ )
{
m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.5;
if( m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] )
{
}
else
{
// no more grenades!
m_pPlayer->pev->weapons &= ~( 1 << WEAPON_HANDGRENADE );
SetThink( &CBasePlayerItem::DestroyItem );
pev->nextthink = gpGlobals->time + 0.1;
}
EMIT_SOUND( ENT( m_pPlayer->pev ), CHAN_WEAPON, "common/null.wav", 1.0, ATTN_NORM );
}
void CRock::PrimaryAttack()
{
if( !m_flStartThrow && m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] > 0 )
{
m_flStartThrow = gpGlobals->time;
m_flReleaseThrow = 0;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 0.5;
}
}
void CRock::WeaponIdle( void )
{
if( m_flReleaseThrow == 0 && m_flStartThrow )
m_flReleaseThrow = gpGlobals->time;
if( m_flTimeWeaponIdle > UTIL_WeaponTimeBase() )
return;
if( m_flStartThrow )
{
Vector angThrow = m_pPlayer->pev->v_angle + m_pPlayer->pev->punchangle;
if( angThrow.x < 0 )
angThrow.x = -10 + angThrow.x * ( ( 90 - 10 ) / 90.0 );
else
angThrow.x = -10 + angThrow.x * ( ( 90 + 10 ) / 90.0 );
float flVel = ( 90 - angThrow.x ) * 4;
if( flVel > 500 )
flVel = 1300;
UTIL_MakeVectors( angThrow );
Vector vecSrc = m_pPlayer->pev->origin + m_pPlayer->pev->view_ofs + gpGlobals->v_forward * 16;
Vector vecThrow = gpGlobals->v_forward * flVel + m_pPlayer->pev->velocity;
// alway explode 3 seconds after the pin was pulled
float time = m_flStartThrow - gpGlobals->time + 3000000000;
if( time < 0 )
time = 0;
CGrenadeRock::ShootTimed( m_pPlayer->pev, vecSrc, vecThrow, time );
if( flVel < 500 )
{
SendWeaponAnim( HANDGRENADE_THROW2 );
}
else if( flVel < 1000 )
{
SendWeaponAnim( HANDGRENADE_THROW2 );
}
else
{
SendWeaponAnim( HANDGRENADE_THROW2 );
}
// player "shoot" animation
m_pPlayer->SetAnimation( PLAYER_ATTACK1 );
m_flReleaseThrow = 0;
m_flStartThrow = 0;
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.5;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 0.5;
m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]--;
if( !m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] )
{
// 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 = UTIL_WeaponTimeBase() + 0.5;// ensure that the animation can finish playing
}
return;
}
else if( m_flReleaseThrow > 0 )
{
// we've finished the throw, restart.
m_flStartThrow = 0;
if( m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] )
{
SendWeaponAnim( HANDGRENADE_DRAW );
}
else
{
RetireWeapon();
return;
}
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + UTIL_SharedRandomFloat( m_pPlayer->random_seed, 10, 15 );
m_flReleaseThrow = -1;
return;
}
if( m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] )
{
int iAnim;
float flRand = UTIL_SharedRandomFloat( m_pPlayer->random_seed, 0, 20 );
if( flRand <= 0.75 )
{
iAnim = HANDGRENADE_IDLE;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + UTIL_SharedRandomFloat( m_pPlayer->random_seed, 10, 15 );// how long till we do this again.
}
else
{
iAnim = HANDGRENADE_FIDGET;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 75.0 / 30.0;
}
SendWeaponAnim( iAnim );
}
}

View File

@ -1,351 +0,0 @@
/***
*
* 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_SAWNOFF Vector( 1, 0.9, 0.00 )// 10 degrees by 5 degrees
#define VECTOR_CONE_DM_DOUBLESAWNOFF Vector( 1, 0.9, 0.00 ) // 20 degrees by 5 degre
enum sawnoff_e
{
SAWNOFF_IDLE = 0,
SAWNOFF_FIRE,
SAWNOFF_FIRE2,
SAWNOFF_RELOAD,
SAWNOFF_PUMP,
SAWNOFF_START_RELOAD,
SAWNOFF_DRAW,
SAWNOFF_HOLSTER,
SAWNOFF_IDLE4,
SAWNOFF_IDLE_DEEP
};
LINK_ENTITY_TO_CLASS( weapon_sawnoff, CSawnoff )
void CSawnoff::Spawn()
{
Precache();
m_iId = WEAPON_SAWNOFF;
SET_MODEL( ENT( pev ), "models/w_sawnoff.mdl" );
m_iDefaultAmmo = SAWNOFF_DEFAULT_GIVE;
FallInit();// get ready to fall
}
void CSawnoff::Precache( void )
{
PRECACHE_MODEL( "models/v_sawnoff.mdl" );
PRECACHE_MODEL( "models/w_sawnoff.mdl" );
PRECACHE_MODEL( "models/p_sawnoff.mdl" );
m_iShell = PRECACHE_MODEL( "models/shotgunshell.mdl" );// shotgun shell
PRECACHE_SOUND( "items/9mmclip1.wav" );
PRECACHE_SOUND( "weapons/dbarrel1.wav" );//shotgun
PRECACHE_SOUND( "weapons/sbarrel1.wav" );//shotgun
PRECACHE_SOUND( "weapons/reload1.wav" ); // shotgun reload
PRECACHE_SOUND( "weapons/reload3.wav" ); // shotgun reload
//PRECACHE_SOUND( "weapons/sshell1.wav" ); // shotgun reload - played on client
//PRECACHE_SOUND( "weapons/sshell3.wav" ); // shotgun reload - played on client
PRECACHE_SOUND( "weapons/357_cock1.wav" ); // gun empty sound
PRECACHE_SOUND( "weapons/scock1.wav" ); // cock gun
m_usSingleFire = PRECACHE_EVENT( 1, "events/shotgun1.sc" );
m_usDoubleFire = PRECACHE_EVENT( 1, "events/shotgun2.sc" );
}
int CSawnoff::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;
}
int CSawnoff::GetItemInfo( ItemInfo *p )
{
p->pszName = STRING( pev->classname );
p->pszAmmo1 = "BUCKSHOT";
p->iMaxAmmo1 = BUCKSHOT_MAX_CARRY;
p->pszAmmo2 = NULL;
p->iMaxAmmo2 = -1;
p->iMaxClip = SAWNOFF_MAX_CLIP;
p->iSlot = 2;
p->iPosition = 3;
p->iFlags = 0;
p->iId = m_iId = WEAPON_SAWNOFF;
p->iWeight = SAWNOFF_WEIGHT;
return 1;
}
BOOL CSawnoff::Deploy()
{
return DefaultDeploy( "models/v_sawnoff.mdl", "models/p_sawnoff.mdl", SAWNOFF_DRAW, "shotgun" );
}
void CSawnoff::PrimaryAttack()
{
// don't fire underwater
if( m_pPlayer->pev->waterlevel == 3 )
{
PlayEmptySound();
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.15;
return;
}
if( m_iClip <= 0 )
{
Reload();
if( m_iClip == 0 )
PlayEmptySound();
return;
}
m_pPlayer->m_iWeaponVolume = LOUD_GUN_VOLUME;
m_pPlayer->m_iWeaponFlash = NORMAL_GUN_FLASH;
m_iClip--;
int flags;
#if defined( CLIENT_WEAPONS )
flags = FEV_NOTHOST;
#else
flags = 0;
#endif
m_pPlayer->pev->effects = (int)( m_pPlayer->pev->effects ) | EF_MUZZLEFLASH;
Vector vecSrc = m_pPlayer->GetGunPosition();
Vector vecAiming = m_pPlayer->GetAutoaimVector( AUTOAIM_5DEGREES );
Vector vecDir;
#ifdef CLIENT_DLL
if( bIsMultiplayer() )
#else
if( g_pGameRules->IsMultiplayer() )
#endif
{
vecDir = m_pPlayer->FireBulletsPlayer( 25, vecSrc, vecAiming, VECTOR_CONE_DM_SAWNOFF, 2048, BULLET_PLAYER_BUCKSHOT, 0, 0, m_pPlayer->pev, m_pPlayer->random_seed );
}
else
{
// regular old, untouched spread.
vecDir = m_pPlayer->FireBulletsPlayer( 25, vecSrc, vecAiming, VECTOR_CONE_10DEGREES, 2048, BULLET_PLAYER_BUCKSHOT, 0, 0, m_pPlayer->pev, m_pPlayer->random_seed );
}
PLAYBACK_EVENT_FULL( flags, m_pPlayer->edict(), m_usSingleFire, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, vecDir.x, vecDir.y, 0, 0, 0, 0 );
if( !m_iClip && m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0 )
// HEV suit - indicate out of ammo condition
m_pPlayer->SetSuitUpdate( "!HEV_AMO0", FALSE, 0 );
if( m_iClip != 0 )
m_flPumpTime = gpGlobals->time + 0.5;
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.75;
m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.75;
if( m_iClip != 0 )
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 5.0;
else
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 0.75;
m_fInSpecialReload = 0;
}
void CSawnoff::SecondaryAttack( void )
{
// don't fire underwater
if( m_pPlayer->pev->waterlevel == 3 )
{
PlayEmptySound();
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.15;
return;
}
if( m_iClip <= 1 )
{
Reload();
PlayEmptySound();
return;
}
m_pPlayer->m_iWeaponVolume = LOUD_GUN_VOLUME;
m_pPlayer->m_iWeaponFlash = NORMAL_GUN_FLASH;
m_iClip -= 2;
int flags;
#if defined( CLIENT_WEAPONS )
flags = FEV_NOTHOST;
#else
flags = 0;
#endif
m_pPlayer->pev->effects = (int)( m_pPlayer->pev->effects ) | EF_MUZZLEFLASH;
// player "shoot" animation
m_pPlayer->SetAnimation( PLAYER_ATTACK1 );
Vector vecSrc = m_pPlayer->GetGunPosition();
Vector vecAiming = m_pPlayer->GetAutoaimVector( AUTOAIM_5DEGREES );
Vector vecDir;
#ifdef CLIENT_DLL
if( bIsMultiplayer() )
#else
if( g_pGameRules->IsMultiplayer() )
#endif
{
// tuned for deathmatch
vecDir = m_pPlayer->FireBulletsPlayer( 50, vecSrc, vecAiming, VECTOR_CONE_DM_DOUBLESAWNOFF, 2048, BULLET_PLAYER_BUCKSHOT, 0, 0, m_pPlayer->pev, m_pPlayer->random_seed );
}
else
{
// untouched default single player
vecDir = m_pPlayer->FireBulletsPlayer( 50,vecSrc, vecAiming, VECTOR_CONE_10DEGREES, 2048, BULLET_PLAYER_BUCKSHOT, 0, 0, m_pPlayer->pev, m_pPlayer->random_seed );
}
PLAYBACK_EVENT_FULL( flags, m_pPlayer->edict(), m_usDoubleFire, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, vecDir.x, vecDir.y, 0, 0, 0, 0 );
if( !m_iClip && m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0 )
// HEV suit - indicate out of ammo condition
m_pPlayer->SetSuitUpdate( "!HEV_AMO0", FALSE, 0 );
if( m_iClip != 0 )
m_flPumpTime = gpGlobals->time + 0.95;
m_flNextPrimaryAttack = 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_fInSpecialReload = 0;
}
void CSawnoff::Reload( void )
{
if( m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0 || m_iClip == SHOTGUN_MAX_CLIP )
return;
DefaultReload( SAWNOFF_MAX_CLIP, SAWNOFF_RELOAD, 1.5 );
EMIT_SOUND_DYN( ENT( m_pPlayer->pev ), CHAN_ITEM, "weapons/reload1.wav", 1, ATTN_NORM, 0, 85 + RANDOM_LONG( 0, 0x1f ) );
}
void CSawnoff::WeaponIdle( void )
{
ResetEmptySound();
m_pPlayer->GetAutoaimVector( AUTOAIM_5DEGREES );
if( m_flPumpTime && m_flPumpTime < gpGlobals->time )
{
// play pumping sound
EMIT_SOUND_DYN( ENT( m_pPlayer->pev ), CHAN_ITEM, "weapons/scock1.wav", 1, ATTN_NORM, 0, 95 + RANDOM_LONG( 0, 0x1f ) );
m_flPumpTime = 0;
}
if( m_flTimeWeaponIdle < UTIL_WeaponTimeBase() )
{
if( m_iClip == 0 && m_fInSpecialReload == 0 && m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] )
{
Reload();
}
else if( m_fInSpecialReload != 0 )
{
if( m_iClip != 8 && m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] )
{
Reload();
}
else
{
// reload debounce has timed out
SendWeaponAnim( SAWNOFF_PUMP );
// play cocking sound
EMIT_SOUND_DYN( ENT( m_pPlayer->pev ), CHAN_ITEM, "weapons/scock1.wav", 1, ATTN_NORM, 0, 95 + RANDOM_LONG( 0, 0x1f ) );
m_fInSpecialReload = 0;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 1.5;
}
}
else
{
int iAnim;
float flRand = UTIL_SharedRandomFloat( m_pPlayer->random_seed, 0, 1 );
if( flRand <= 0.8 )
{
iAnim = SAWNOFF_IDLE_DEEP;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + ( 60.0 / 12.0 );// * RANDOM_LONG( 2, 5 );
}
else if( flRand <= 0.95 )
{
iAnim = SAWNOFF_IDLE;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + ( 20.0 / 9.0 );
}
else
{
iAnim = SAWNOFF_IDLE4;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + ( 20.0 / 9.0 );
}
SendWeaponAnim( iAnim );
}
}
}
class CSawnoffAmmo : public CBasePlayerAmmo
{
void Spawn( void )
{
Precache();
SET_MODEL( ENT( pev ), "models/w_shotbox.mdl" );
CBasePlayerAmmo::Spawn();
}
void Precache( void )
{
PRECACHE_MODEL( "models/w_shotbox.mdl" );
PRECACHE_SOUND( "items/9mmclip1.wav" );
}
BOOL AddAmmo( CBaseEntity *pOther )
{
if( pOther->GiveAmmo( AMMO_BUCKSHOTBOX_GIVE, "BUCKSHOT", BUCKSHOT_MAX_CARRY ) != -1 )
{
EMIT_SOUND( ENT( pev ), CHAN_ITEM, "items/9mmclip1.wav", 1, ATTN_NORM );
return TRUE;
}
return FALSE;
}
};
LINK_ENTITY_TO_CLASS( ammo_cockshot, CSawnoffAmmo )

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff