📄 hl1_npc_gargantua.cpp
字号:
//=========== (C) Copyright 2000 Valve, L.L.C. All rights reserved. ===========
//
// The copyright to the contents herein is the property of Valve, L.L.C.
// The contents may be used and/or copied only with the written permission of
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
// the agreement/contract under which the contents have been supplied.
//
// Purpose: Bullseyes act as targets for other NPC's to attack and to trigger
// events
//
// $Workfile: $
// $Date: $
//
//-----------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================
#include "cbase.h"
#include "beam_shared.h"
#include "Sprite.h"
#include "AI_Default.h"
#include "AI_Task.h"
#include "AI_Schedule.h"
#include "AI_Node.h"
#include "AI_Hull.h"
#include "AI_Hint.h"
#include "AI_Route.h"
#include "hl1_npc_gargantua.h"
#include "soundent.h"
#include "game.h"
#include "NPCEvent.h"
#include "EntityList.h"
#include "activitylist.h"
#include "animation.h"
#include "basecombatweapon.h"
#include "IEffects.h"
#include "vstdlib/random.h"
#include "engine/IEngineSound.h"
#include "ammodef.h"
#include "shake.h"
#include "decals.h"
#include "customentity.h"
#include "particle_smokegrenade.h"
#include "gib.h"
#include "func_break.h"
extern short g_sModelIndexFireball;
int gGargGibModel;
//=========================================================
// Gargantua Monster
//=========================================================
#define GARG_ATTACKDIST 120.0f
// Garg animation events
#define GARG_AE_SLASH_LEFT 1
//#define GARG_AE_BEAM_ATTACK_RIGHT 2 // No longer used
#define GARG_AE_LEFT_FOOT 3
#define GARG_AE_RIGHT_FOOT 4
#define GARG_AE_STOMP 5
#define GARG_AE_BREATHE 6
// Gargantua is immune to any damage but this
#define GARG_DAMAGE ( DMG_ENERGYBEAM | DMG_CRUSH | DMG_MISSILEDEFENSE | DMG_BLAST )
#define GARG_EYE_SPRITE_NAME "sprites/gargeye1.vmt"
#define GARG_BEAM_SPRITE_NAME "sprites/xbeam3.vmt"
#define GARG_BEAM_SPRITE2 "sprites/xbeam3.vmt"
#define GARG_STOMP_SPRITE_NAME "sprites/gargeye1.vmt"
#define GARG_STOMP_BUZZ_SOUND "weapons/mine_charge.wav"
#define GARG_FLAME_LENGTH 330
#define GARG_GIB_MODEL "models/metalplategibs.mdl"
#define ATTN_GARG ( ATTN_NORM )
#define STOMP_SPRITE_COUNT 10
#define ATTACH_EYE 1
ConVar sk_gargantua_health ( "sk_gargantua_health", "800" );
ConVar sk_gargantua_dmg_slash( "sk_gargantua_dmg_slash", "10" );
ConVar sk_gargantua_dmg_fire ( "sk_gargantua_dmg_fire", "3" );
ConVar sk_gargantua_dmg_stomp( "sk_gargantua_dmg_stomp", "50" );
enum
{
TASK_SOUND_ATTACK = LAST_SHARED_TASK,
TASK_FLAME_SWEEP,
};
enum
{
SCHED_GARG_FLAME = LAST_SHARED_SCHEDULE,
SCHED_GARG_SWIPE,
};
const char *CNPC_Gargantua::pAttackHitSounds[] =
{
"zombie/claw_strike1.wav",
"zombie/claw_strike2.wav",
"zombie/claw_strike3.wav",
};
const char *CNPC_Gargantua::pBeamAttackSounds[] =
{
"garg/gar_flameoff1.wav",
"garg/gar_flameon1.wav",
"garg/gar_flamerun1.wav",
};
const char *CNPC_Gargantua::pAttackMissSounds[] =
{
"zombie/claw_miss1.wav",
"zombie/claw_miss2.wav",
};
const char *CNPC_Gargantua::pRicSounds[] =
{
#if 0
"weapons/ric1.wav",
"weapons/ric2.wav",
"weapons/ric3.wav",
"weapons/ric4.wav",
"weapons/ric5.wav",
#else
"debris/metal4.wav",
"debris/metal6.wav",
"weapons/ric4.wav",
"weapons/ric5.wav",
#endif
};
const char *CNPC_Gargantua::pFootSounds[] =
{
"garg/gar_step1.wav",
"garg/gar_step2.wav",
};
const char *CNPC_Gargantua::pIdleSounds[] =
{
"garg/gar_idle1.wav",
"garg/gar_idle2.wav",
"garg/gar_idle3.wav",
"garg/gar_idle4.wav",
"garg/gar_idle5.wav",
};
const char *CNPC_Gargantua::pAttackSounds[] =
{
"garg/gar_attack1.wav",
"garg/gar_attack2.wav",
"garg/gar_attack3.wav",
};
const char *CNPC_Gargantua::pAlertSounds[] =
{
"garg/gar_alert1.wav",
"garg/gar_alert2.wav",
"garg/gar_alert3.wav",
};
const char *CNPC_Gargantua::pPainSounds[] =
{
"garg/gar_pain1.wav",
"garg/gar_pain2.wav",
"garg/gar_pain3.wav",
};
const char *CNPC_Gargantua::pStompSounds[] =
{
"garg/gar_stomp1.wav",
};
const char *CNPC_Gargantua::pBreatheSounds[] =
{
"garg/gar_breathe1.wav",
"garg/gar_breathe2.wav",
"garg/gar_breathe3.wav",
};
LINK_ENTITY_TO_CLASS( monster_gargantua, CNPC_Gargantua );
BEGIN_DATADESC( CNPC_Gargantua )
DEFINE_FIELD( CNPC_Gargantua, m_pEyeGlow, FIELD_CLASSPTR ),
DEFINE_FIELD( CNPC_Gargantua, m_eyeBrightness, FIELD_INTEGER ),
DEFINE_FIELD( CNPC_Gargantua, m_seeTime, FIELD_TIME ),
DEFINE_FIELD( CNPC_Gargantua, m_flameTime, FIELD_TIME ),
DEFINE_FIELD( CNPC_Gargantua, m_streakTime, FIELD_TIME ),
DEFINE_ARRAY( CNPC_Gargantua, m_pFlame, FIELD_CLASSPTR, 4 ),
DEFINE_FIELD( CNPC_Gargantua, m_flameX, FIELD_FLOAT ),
DEFINE_FIELD( CNPC_Gargantua, m_flameY, FIELD_FLOAT ),
DEFINE_FIELD( CNPC_Gargantua, m_flDmgTime, FIELD_FLOAT ),
END_DATADESC()
static void MoveToGround( Vector *position, CBaseEntity *ignore, const Vector &mins, const Vector &maxs )
{
trace_t tr;
// Find point on floor where enemy would stand at chasePosition
Vector floor = *position;
floor.z -= 1024;
UTIL_TraceHull( *position, floor, mins, maxs, MASK_NPCSOLID, ignore, COLLISION_GROUP_NONE, &tr );
if ( tr.fraction < 1 )
{
position->z = tr.endpos.z;
}
}
class CStomp : public CBaseEntity
{
DECLARE_CLASS( CStomp, CBaseEntity );
public:
void Spawn( void );
void Think( void );
static CStomp *StompCreate( Vector &origin, Vector &end, float speed, CBaseEntity* pOwner );
private:
Vector m_vecMoveDir;
float m_flScale;
float m_flSpeed;
unsigned int m_uiFramerate;
float m_flDmgTime;
CBaseEntity* m_pOwner;
// UNDONE: re-use this sprite list instead of creating new ones all the time
// CSprite *m_pSprites[ STOMP_SPRITE_COUNT ];
};
LINK_ENTITY_TO_CLASS( garg_stomp, CStomp );
CStomp *CStomp::StompCreate( Vector &origin, Vector &end, float speed, CBaseEntity* pOwner )
{
CStomp *pStomp = (CStomp*)CreateEntityByName( "garg_stomp" );
pStomp->SetAbsOrigin( origin );
Vector dir = (end - origin);
// pStomp->m_flScale = dir.Length();
pStomp->m_flScale = 2048;
pStomp->m_vecMoveDir = dir;
VectorNormalize( pStomp->m_vecMoveDir );
pStomp->m_flSpeed = speed;
pStomp->m_pOwner = pOwner;
pStomp->Spawn();
return pStomp;
}
void CStomp::Spawn( void )
{
SetNextThink( gpGlobals->curtime );
pev->classname = MAKE_STRING("garg_stomp");
m_flDmgTime = gpGlobals->curtime;
m_uiFramerate = 30;
// pev->rendermode = kRenderTransTexture;
// SetBrightness( 0 );
CPASAttenuationFilter filter( this );
enginesound->EmitSound( filter, entindex(), CHAN_VOICE, GARG_STOMP_BUZZ_SOUND, 1.0, ATTN_NORM, 0, PITCH_NORM );
}
#define STOMP_INTERVAL 0.025
void CStomp::Think( void )
{
trace_t tr;
SetNextThink( gpGlobals->curtime + 0.1 );
// Do damage for this frame
Vector vecStart = GetAbsOrigin();
vecStart.z += 30;
Vector vecEnd = vecStart + (m_vecMoveDir * m_flSpeed * gpGlobals->frametime);
UTIL_TraceHull( vecStart, vecEnd, Vector(-32, -32, -32), Vector(32, 32, 32), MASK_SOLID, m_pOwner, COLLISION_GROUP_NONE, &tr );
// NDebugOverlay::Line( vecStart, vecEnd, 0, 255, 0, false, 10.0f );
if ( tr.m_pEnt )
{
CBaseEntity *pEntity = tr.m_pEnt;
CTakeDamageInfo info( this, this, 50, DMG_SONIC );
CalculateMeleeDamageForce( &info, m_vecMoveDir, tr.endpos );
pEntity->TakeDamage( info );
}
// Accelerate the effect
m_flSpeed += (gpGlobals->frametime) * m_uiFramerate;
m_uiFramerate += (gpGlobals->frametime) * 2000;
// Move and spawn trails
while ( gpGlobals->curtime - m_flDmgTime > STOMP_INTERVAL )
{
SetAbsOrigin( GetAbsOrigin() + m_vecMoveDir * m_flSpeed * STOMP_INTERVAL );
for ( int i = 0; i < 2; i++ )
{
CSprite *pSprite = CSprite::SpriteCreate( GARG_STOMP_SPRITE_NAME, GetAbsOrigin(), TRUE );
if ( pSprite )
{
UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() - Vector(0,0,500), MASK_SOLID, this, COLLISION_GROUP_NONE, &tr );
pSprite->SetAbsOrigin( tr.endpos );
// pSprite->pev->velocity = Vector(RandomFloat(-200,200),RandomFloat(-200,200),175);
pSprite->SetNextThink( gpGlobals->curtime + 0.3 );
pSprite->SetThink( &CSprite::SUB_Remove );
pSprite->SetTransparency( kRenderTransAdd, 255, 255, 255, 255, kRenderFxFadeFast );
}
g_pEffects->EnergySplash( tr.endpos, tr.plane.normal );
}
m_flDmgTime += STOMP_INTERVAL;
// Scale has the "life" of this effect
m_flScale -= STOMP_INTERVAL * m_flSpeed;
if ( m_flScale <= 0 )
{
// Life has run out
UTIL_Remove(this);
// STOP_SOUND( edict(), CHAN_BODY, GARG_STOMP_BUZZ_SOUND );
CPASAttenuationFilter filter( this );
StopSound( entindex(), CHAN_STATIC, GARG_STOMP_BUZZ_SOUND );
}
}
}
//=========================================================================
// Gargantua
//=========================================================================
//=========================================================
// Spawn
//=========================================================
void CNPC_Gargantua::Spawn()
{
Precache( );
SetModel( "models/garg.mdl" );
SetNavType(NAV_GROUND);
SetSolid( SOLID_BBOX );
AddSolidFlags( FSOLID_NOT_STANDABLE );
SetMoveType( MOVETYPE_STEP );
m_bloodColor = BLOOD_COLOR_GREEN;
m_iHealth = sk_gargantua_health.GetFloat();
SetViewOffset( Vector ( 0, 0, 96 ) );// taken from mdl file
m_flFieldOfView = -0.2;// width of forward view cone ( as a dotproduct result )
m_NPCState = NPC_STATE_NONE;
CapabilitiesAdd( bits_CAP_MOVE_GROUND );
CapabilitiesAdd( bits_CAP_INNATE_RANGE_ATTACK1 | bits_CAP_INNATE_MELEE_ATTACK1 | bits_CAP_INNATE_MELEE_ATTACK2 );
SetHullType( HULL_WIDE_HUMAN );
SetHullSizeNormal();
m_pEyeGlow = CSprite::SpriteCreate( GARG_EYE_SPRITE_NAME, GetAbsOrigin(), FALSE );
m_pEyeGlow->SetTransparency( kRenderGlow, 255, 255, 255, 0, kRenderFxNoDissipation );
m_pEyeGlow->SetAttachment( this, 1 );
EyeOff();
m_seeTime = gpGlobals->curtime + 5;
m_flameTime = gpGlobals->curtime + 2;
NPCInit();
BaseClass::Spawn();
Relink();
}
//=========================================================
// Precache - precaches all resources this monster needs
//=========================================================
void CNPC_Gargantua::Precache()
{
engine->PrecacheModel("models/garg.mdl");
engine->PrecacheModel( GARG_EYE_SPRITE_NAME );
engine->PrecacheModel( GARG_BEAM_SPRITE_NAME );
engine->PrecacheModel( GARG_BEAM_SPRITE2 );
//gStompSprite = PRECACHE_MODEL( GARG_STOMP_SPRITE_NAME );
gGargGibModel = engine->PrecacheModel( GARG_GIB_MODEL );
enginesound->PrecacheSound( GARG_STOMP_BUZZ_SOUND );
PRECACHE_SOUND_ARRAY(pAttackHitSounds);
PRECACHE_SOUND_ARRAY(pBeamAttackSounds);
PRECACHE_SOUND_ARRAY(pAttackMissSounds);
PRECACHE_SOUND_ARRAY(pRicSounds);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -