400 lines
No EOL
11 KiB
C++
400 lines
No EOL
11 KiB
C++
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
|
//
|
|
// Purpose:
|
|
//
|
|
// $NoKeywords: $
|
|
//=============================================================================//
|
|
|
|
#include "cbase.h"
|
|
|
|
#if 0
|
|
#include "ai_basenpc.h"
|
|
#include "basecombatweapon.h" // For SpawnBlood
|
|
#include "soundent.h"
|
|
#include "func_break.h" // For materials
|
|
#include "hl2_player.h"
|
|
#include "ai_hull.h"
|
|
#include "decals.h"
|
|
#include "shake.h"
|
|
#include "ndebugoverlay.h"
|
|
#include "player_control.h"
|
|
#include "IEffects.h"
|
|
#include "engine/IEngineSound.h"
|
|
|
|
// memdbgon must be the last include file in a .cpp file!!!
|
|
#include "tier0/memdbgon.h"
|
|
|
|
#define PMANHACK_OFFSET Vector(0,0,-18)
|
|
#define PMANHACK_HULL_MINS Vector(-22,-22,-22)
|
|
#define PMANHACK_HULL_MAXS Vector(22,22,22)
|
|
#define PMANHACK_MAX_SPEED 400
|
|
#define PMANHACK_DECAY 6
|
|
|
|
|
|
class CPlayer_Manhack : public CPlayer_Control
|
|
{
|
|
public:
|
|
DECLARE_CLASS( CPlayer_Manhack, CPlayer_Control );
|
|
|
|
void Precache(void);
|
|
void Spawn(void);
|
|
bool CreateVPhysics( void );
|
|
|
|
// Inputs
|
|
void InputActivate( inputdata_t &inputdata );
|
|
void InputDeactivate( inputdata_t &inputdata );
|
|
void InputSetThrust( inputdata_t &inputdata );
|
|
void InputSetSideThrust( inputdata_t &inputdata );
|
|
|
|
void FlyThink(void);
|
|
void CheckBladeTrace(trace_t &tr);
|
|
|
|
DECLARE_DATADESC();
|
|
};
|
|
|
|
|
|
BEGIN_DATADESC( CPlayer_Manhack )
|
|
|
|
// Function Pointers
|
|
DEFINE_FUNCTION( FlyThink ),
|
|
|
|
END_DATADESC()
|
|
|
|
LINK_ENTITY_TO_CLASS( player_manhack, CPlayer_Manhack );
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Purpose :
|
|
// Input :
|
|
// Output :
|
|
//------------------------------------------------------------------------------
|
|
void CPlayer_Manhack::Precache( void )
|
|
{
|
|
PrecacheModel("models/manhack.mdl");
|
|
PrecacheModel("models/manhack_sphere.mdl");
|
|
|
|
PrecacheScriptSound( "Player_Manhack.ThrustLow"" );
|
|
PrecacheScriptSound( "Player_Manhack.ThrustHigh" );
|
|
PrecacheScriptSound( "Player_Manhack.GrindFlesh" );
|
|
PrecacheScriptSound( "Player_Manhack.Grind" );
|
|
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Purpose :
|
|
// Input :
|
|
// Output :
|
|
//------------------------------------------------------------------------------
|
|
void CPlayer_Manhack::Spawn( void )
|
|
{
|
|
Precache();
|
|
m_flFriction = 0.55; // deading the bounce a bit
|
|
|
|
SetModel( "models/manhack.mdl" );
|
|
UTIL_SetSize(this, PMANHACK_HULL_MINS, PMANHACK_HULL_MAXS);
|
|
|
|
m_bActive = false;
|
|
|
|
CreateVPhysics();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
bool CPlayer_Manhack::CreateVPhysics( void )
|
|
{
|
|
// Create the object in the physics system
|
|
VPhysicsInitNormal( SOLID_BBOX, 0, false );
|
|
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Input handler for turning on the manhack
|
|
//-----------------------------------------------------------------------------
|
|
void CPlayer_Manhack::InputActivate( inputdata_t &inputdata )
|
|
{
|
|
BaseClass::InputActivate( inputdata );
|
|
|
|
SetThink(FlyThink);
|
|
|
|
// Switch to a bigger model (a sphere) that keeps the player's
|
|
// camera outside of walls
|
|
VPhysicsDestroyObject();
|
|
SetModel("models/manhack_sphere.mdl" );
|
|
VPhysicsInitNormal( GetSolid(), GetSolidFlags(), false );
|
|
|
|
CHL2_Player* pPlayer = (CHL2_Player*)UTIL_GetLocalPlayer();
|
|
|
|
Assert( pPlayer );
|
|
|
|
pPlayer->SetFOV( 132 );
|
|
pPlayer->FollowEntity( this );
|
|
pPlayer->m_nControlClass = CLASS_MANHACK;
|
|
pPlayer->GiveNamedItem( "weapon_manhack" );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Input handler for turning off the manhack.
|
|
//-----------------------------------------------------------------------------
|
|
void CPlayer_Manhack::InputDeactivate( inputdata_t &inputdata )
|
|
{
|
|
BaseClass::InputDeactivate( inputdata );
|
|
|
|
CHL2_Player* pPlayer = (CHL2_Player*)UTIL_GetLocalPlayer();
|
|
|
|
Assert( pPlayer );
|
|
|
|
StopSound( pPlayer->entindex(), "Player_Manhack.GrindFlesh" );
|
|
StopSound( pPlayer->entindex(), "Player_Manhack.Grind");
|
|
StopSound( pPlayer->entindex(), "Player_Manhack.ThrustLow" );
|
|
StopSound( pPlayer->entindex(), "Player_Manhack.ThrustHigh" );
|
|
|
|
// Remove manhack blade weapon from player's inventory
|
|
CBaseEntity* pBlade = (CBaseEntity*)(pPlayer->GetActiveWeapon());
|
|
pPlayer->Weapon_Drop( GetActiveWeapon() );
|
|
if (m_pSaveWeapon)
|
|
{
|
|
pPlayer->Weapon_Switch( m_pSaveWeapon );
|
|
}
|
|
UTIL_Remove(pBlade);
|
|
|
|
// Switch back to manhack model
|
|
VPhysicsDestroyObject();
|
|
SetModel("models/manhack.mdl" );
|
|
VPhysicsInitNormal( GetSolid(), GetSolidFlags(), false );
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Purpose:
|
|
//------------------------------------------------------------------------------
|
|
void CPlayer_Manhack::InputSetThrust( inputdata_t &inputdata )
|
|
{
|
|
if (!m_bActive)
|
|
{
|
|
return;
|
|
}
|
|
|
|
CBasePlayer* pPlayer = UTIL_GetLocalPlayer();
|
|
|
|
Assert( pPlayer );
|
|
|
|
if (inputdata.value.Float() == 0)
|
|
{
|
|
CPASAttenuationFilter filter( pPlayer, "Player_Manhack.ThrustLow" );
|
|
EmitSound( filter, pPlayer->entindex(), "Player_Manhack.ThrustLow" );
|
|
return;
|
|
}
|
|
CPASAttenuationFilter filter( pPlayer, "Player_Manhack.ThrustHigh" );
|
|
EmitSound( filter, pPlayer->entindex(), "Player_Manhack.ThrustHigh" );
|
|
|
|
|
|
Vector vForce;
|
|
pPlayer->EyeVectors( &vForce );
|
|
vForce = vForce * inputdata.value.Float() * 600;
|
|
|
|
IPhysicsObject* pPhysObj = VPhysicsGetObject();
|
|
pPhysObj->ApplyForceCenter( vForce );
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Purpose:
|
|
//------------------------------------------------------------------------------
|
|
void CPlayer_Manhack::InputSetSideThrust( inputdata_t &inputdata )
|
|
{
|
|
if (!m_bActive)
|
|
{
|
|
return;
|
|
}
|
|
|
|
CBasePlayer* pPlayer = UTIL_GetLocalPlayer();
|
|
|
|
Assert( pPlayer );
|
|
|
|
if (inputdata.value.Float() == 0)
|
|
{
|
|
CPASAttenuationFilter filter( pPlayer, "Player_Manhack.ThrustLow" );
|
|
EmitSound( filter, pPlayer->entindex(), "Player_Manhack.ThrustLow" );
|
|
return;
|
|
}
|
|
CPASAttenuationFilter filter( pPlayer, "Player_Manhack.ThrustHigh" );
|
|
EmitSound( filter, pPlayer->entindex(), "Player_Manhack.ThrustHigh" );
|
|
|
|
|
|
Vector vForce;
|
|
pPlayer->EyeVectors( 0, &vForce, 0 );
|
|
vForce = vForce * inputdata.value.Float() * 600;
|
|
|
|
IPhysicsObject* pPhysObj = VPhysicsGetObject();
|
|
pPhysObj->ApplyForceCenter( vForce );
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Purpose :
|
|
// Input :
|
|
// Output :
|
|
//------------------------------------------------------------------------------
|
|
void CPlayer_Manhack::CheckBladeTrace(trace_t &tr)
|
|
{
|
|
CBaseEntity* pHitEntity = NULL;
|
|
CBasePlayer* pPlayer = UTIL_GetLocalPlayer();
|
|
|
|
Assert( pPlayer );
|
|
|
|
if (tr.u.ent)
|
|
{
|
|
pHitEntity = CBaseEntity::Instance( tr.u.ent );
|
|
|
|
// Did I hit an entity that isn't a player?
|
|
if (pHitEntity && pHitEntity->Classify()!=CLASS_PLAYER)
|
|
{
|
|
CTakeDamageInfo info( this, this, 1, DMG_SLASH );
|
|
CalculateMeleeDamageForce( &info, (tr.endpos - tr.endpos), tr.endpos );
|
|
pHitEntity->TakeDamage( info );
|
|
}
|
|
}
|
|
if (tr.fraction != 1.0 || tr.startsolid)
|
|
{
|
|
|
|
CBaseCombatCharacter* pBCC = ToBaseCombatCharacter( pHitEntity );
|
|
|
|
if (pBCC)
|
|
{
|
|
// Spawn some extra blood in front of player to see
|
|
Vector vPlayerFacing;
|
|
pPlayer->EyeVectors( &vPlayerFacing );
|
|
Vector vBloodPos = pPlayer->Center() + vPlayerFacing*30;
|
|
SpawnBlood(vBloodPos, g_vecAttackDir, pBCC->BloodColor(), 1.0);
|
|
|
|
CPASAttenuationFilter filter( pPlayer, "Player_Manhack.GrindFlesh" );
|
|
EmitSound( filter, pPlayer->entindex(), "Player_Manhack.GrindFlesh" );
|
|
}
|
|
else
|
|
{
|
|
if (!(m_spawnflags & SF_NPC_GAG))
|
|
{
|
|
CPASAttenuationFilter filter( pPlayer, "Player_Manhack.Grind" );
|
|
EmitSound( filter, pPlayer->entindex(), "Player_Manhack.Grind" );
|
|
}
|
|
// For decals and sparks we must trace a line in the direction of the surface norm
|
|
// that we hit.
|
|
Vector vCheck = GetAbsOrigin() - (tr.plane.normal * 24);
|
|
|
|
UTIL_TraceLine( GetAbsOrigin()+PMANHACK_OFFSET, vCheck+PMANHACK_OFFSET,MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr );
|
|
if (tr.fraction != 1.0)
|
|
{
|
|
g_pEffects->Sparks( tr.endpos );
|
|
|
|
CBroadcastRecipientFilter filter;
|
|
te->DynamicLight( filter, 0.0,
|
|
&tr.endpos, 255, 180, 100, 0, 10, 0.1, 0 );
|
|
|
|
|
|
// Leave decal only if colliding horizontally
|
|
if ((DotProduct(Vector(0,0,1),tr.plane.normal)<0.5) && (DotProduct(Vector(0,0,-1),tr.plane.normal)<0.5))
|
|
{
|
|
UTIL_DecalTrace( &tr, "ManhackCut" );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Manhack is still dangerous when dead
|
|
// Input :
|
|
// Output :
|
|
//-----------------------------------------------------------------------------
|
|
void CPlayer_Manhack::FlyThink()
|
|
{
|
|
SetNextThink( gpGlobals->curtime );
|
|
|
|
// Get physics object
|
|
IPhysicsObject* pPhysObj = VPhysicsGetObject();
|
|
if (!pPhysObj) return;
|
|
Vector vPhysPos;
|
|
pPhysObj->GetPosition(&vPhysPos,NULL);
|
|
|
|
// Update the player's origin
|
|
CBasePlayer* pPlayer = UTIL_GetLocalPlayer();
|
|
|
|
Assert( pPlayer );
|
|
|
|
Vector vPlayerFacing;
|
|
pPlayer->EyeVectors( &vPlayerFacing );
|
|
|
|
|
|
UTIL_SetOrigin(pPlayer,vPhysPos);
|
|
|
|
float flBrightness;
|
|
if (random->RandomInt(0,1)==0)
|
|
{
|
|
flBrightness = 255;
|
|
}
|
|
else
|
|
{
|
|
flBrightness = 1;
|
|
}
|
|
color32 white = {flBrightness,flBrightness,flBrightness,20};
|
|
UTIL_ScreenFade( pPlayer, white, 0.01, 0.1, FFADE_MODULATE );
|
|
|
|
flBrightness = random->RandomInt(0,255);
|
|
NDebugOverlay::ScreenText( 0.4, 0.15, "...M A N H A C K A C T I V A T E D...", 255, flBrightness, flBrightness, 255, 0.0);
|
|
|
|
// ----------------------------------------
|
|
// Trace forward to see if I hit anything
|
|
// ----------------------------------------
|
|
trace_t tr;
|
|
Vector vVelocity;
|
|
GetVelocity( &vVelocity, NULL );
|
|
vVelocity.z = 0;
|
|
Vector vCheckPos = GetAbsOrigin() + (vVelocity*gpGlobals->frametime);
|
|
|
|
// Check in movement direction
|
|
UTIL_TraceHull( GetAbsOrigin()+PMANHACK_OFFSET, vCheckPos+PMANHACK_OFFSET,
|
|
Vector(-22,-22,-1), Vector(22,22,1),
|
|
MASK_SOLID, this, COLLISION_GROUP_NONE, &tr );
|
|
CheckBladeTrace(tr);
|
|
|
|
// Check in facing direction
|
|
UTIL_TraceHull( GetAbsOrigin()+PMANHACK_OFFSET, GetAbsOrigin() + vPlayerFacing*14 + PMANHACK_OFFSET,
|
|
Vector(-22,-22,-1), Vector(22,22,1),
|
|
MASK_SOLID, this, COLLISION_GROUP_NONE, &tr );
|
|
CheckBladeTrace(tr);
|
|
|
|
// ----------
|
|
// Add decay
|
|
// ----------
|
|
Vector vOldVelocity;
|
|
pPhysObj->GetVelocity(&vOldVelocity,NULL);
|
|
float flDecay = -PMANHACK_DECAY*gpGlobals->frametime;
|
|
if (flDecay < -1.0)
|
|
{
|
|
flDecay = -1.0;
|
|
}
|
|
pPhysObj->ApplyForceCenter( flDecay*vOldVelocity );
|
|
|
|
// -----------------------
|
|
// Hover noise
|
|
// -----------------------
|
|
float flNoise1 = 1000*sin(4*gpGlobals->curtime);
|
|
float flNoise = 12000+ flNoise1;
|
|
|
|
Vector vForce = Vector(0,0,flNoise*gpGlobals->frametime);
|
|
pPhysObj->ApplyForceCenter( vForce );
|
|
|
|
// -----------------------
|
|
// Limit velocity
|
|
// -----------------------
|
|
pPhysObj->GetVelocity(&vOldVelocity,NULL);
|
|
if (vOldVelocity.Length() > PMANHACK_MAX_SPEED)
|
|
{
|
|
Vector vNewVelocity = vOldVelocity;
|
|
VectorNormalize(vNewVelocity);
|
|
vNewVelocity = vNewVelocity *PMANHACK_MAX_SPEED;
|
|
Vector vSubtract = vNewVelocity - vOldVelocity;
|
|
pPhysObj->AddVelocity(&vSubtract,NULL);
|
|
}
|
|
}
|
|
#endif
|