2024-08-29 19:18:30 -04:00
# include "cbase.h"
# include "asw_shareddefs.h"
# include "gamestringpool.h"
# ifdef GAME_DLL
# include "asw_player.h"
# include "asw_marine.h"
# include "asw_marine_resource.h"
# include "asw_gamerules.h"
# include "asw_game_resource.h"
# include "props.h"
# include "vphysics_interface.h"
# include "physics.h"
# include "vphysics/friction.h"
# include "asw_computer_area.h"
# include "point_camera.h"
# include "asw_remote_turret_shared.h"
# include "asw_computer_area.h"
# include "asw_button_area.h"
# include "fogcontroller.h"
# include "asw_point_camera.h"
# else
# include "asw_gamerules.h"
# include "c_asw_drone_advanced.h"
# include "c_asw_fx.h"
# include "c_asw_marine.h"
# include "c_asw_game_resource.h"
# include "c_asw_marine_resource.h"
# include "c_asw_computer_area.h"
# include "c_point_camera.h"
# include "asw_remote_turret_shared.h"
# include "c_asw_player.h"
# include "c_playerresource.h"
# include "c_asw_computer_area.h"
# include "c_asw_button_area.h"
# include "vgui/cursor.h"
# include "iinput.h"
# include <vgui/ISurface.h>
# include "vguimatsurface/imatsystemsurface.h"
# include "vgui_controls\Controls.h"
# include <vgui/IVGUI.h>
# include "ivieweffects.h"
# include "asw_input.h"
# include "c_asw_point_camera.h"
# include "baseparticleentity.h"
# include "vgui/ILocalize.h"
# include "asw_hud_floating_number.h"
# include "takedamageinfo.h"
# include "clientmode_asw.h"
# include "engine/IVDebugOverlay.h"
# include "c_user_message_register.h"
# define CASW_Marine C_ASW_Marine
# define CASW_Game_Resource C_ASW_Game_Resource
# define CASW_Marine_Resource C_ASW_Marine_Resource
# define CASW_Computer_Area C_ASW_Computer_Area
# define CPointCamera C_PointCamera
# define CASW_PointCamera C_ASW_PointCamera
# define CASW_Remote_Turret C_ASW_Remote_Turret
# define CASW_Button_Area C_ASW_Button_Area
# define CASW_Computer_Area C_ASW_Computer_Area
# endif
# include "shake.h"
# include "asw_util_shared.h"
// memdbgon must be the last include file in a .cpp file!!!
# include "tier0/memdbgon.h"
# ifndef CLIENT_DLL
2024-08-29 19:27:02 -04:00
ConVar asw_debug_marine_can_see ( " asw_debug_marine_can_see " , " 0 " , FCVAR_CHEAT , " Display lines for waking up aliens " ) ;
2024-08-29 19:18:30 -04:00
# else
extern int g_asw_iGUIWindowsOpen ;
# endif
ConVar asw_marine_view_cone_dist ( " asw_marine_view_cone_dist " , " 700 " , FCVAR_REPLICATED , " Distance for marine view cone checks " ) ;
ConVar asw_marine_view_cone_dot ( " asw_marine_view_cone_dot " , " 0.5 " , FCVAR_REPLICATED , " Dot for marine view cone checks " ) ;
extern ConVar asw_rts_controls ;
ConVar asw_shake_test_punch_dirx ( " asw_shake_test_punch_dirx " , " 0 " , FCVAR_REPLICATED | FCVAR_HIDDEN ) ;
ConVar asw_shake_test_punch_diry ( " asw_shake_test_punch_diry " , " 0 " , FCVAR_REPLICATED | FCVAR_HIDDEN ) ;
ConVar asw_shake_test_punch_dirz ( " asw_shake_test_punch_dirz " , " 1 " , FCVAR_REPLICATED | FCVAR_HIDDEN ) ;
ConVar asw_shake_test_punch_freq ( " asw_shake_test_punch_freq " , " 1.5 " , FCVAR_REPLICATED | FCVAR_HIDDEN ) ;
ConVar asw_shake_test_punch_amp ( " asw_shake_test_punch_amp " , " 60 " , FCVAR_REPLICATED | FCVAR_HIDDEN ) ;
ConVar asw_shake_test_punch_dura ( " asw_shake_test_punch_dura " , " 0.75 " , FCVAR_REPLICATED | FCVAR_HIDDEN ) ;
// rotates one angle towards another, with a fixed turning rate over the time
float ASW_ClampYaw ( float yawSpeedPerSec , float current , float target , float time )
{
if ( current ! = target )
{
float speed = yawSpeedPerSec * time ;
float move = target - current ;
if ( target > current )
{
if ( move > = 180 )
move = move - 360 ;
}
else
{
if ( move < = - 180 )
move = move + 360 ;
}
if ( move > 0 )
{ // turning to the npc's left
if ( move > speed )
move = speed ;
}
else
{ // turning to the npc's right
if ( move < - speed )
move = - speed ;
}
return anglemod ( current + move ) ;
}
return target ;
}
float ASW_Linear_Approach ( float current , float target , float delta )
{
if ( current < target )
current = MIN ( current + delta , target ) ;
else if ( current > target )
current = MAX ( current - delta , target ) ;
return current ;
}
// time independent movement of one angle to a fraction of the desired
float ASW_ClampYaw_Fraction ( float fraction , float current , float target , float time )
{
if ( current ! = target )
{
float move = target - current ;
if ( target > current )
{
if ( move > = 180 )
move = move - 360 ;
}
else
{
if ( move < = - 180 )
move = move + 360 ;
}
move = move * pow ( fraction , time ) ;
float r = anglemod ( target - move ) ;
return r ;
}
return target ;
}
bool ASW_LineCircleIntersection (
const Vector2D & center ,
const float radius ,
const Vector2D & vLinePt ,
const Vector2D & vLineDir ,
float * fIntersection1 ,
float * fIntersection2 )
{
// Line = P + Vt
// Sphere = r (assume we've translated to origin)
// (P + Vt)^2 = r^2
// VVt^2 + 2PVt + (PP - r^2)
// Solve as quadratic: (-b +/- sqrt(b^2 - 4ac)) / 2a
// If (b^2 - 4ac) is < 0 there is no solution.
// If (b^2 - 4ac) is = 0 there is one solution (a case this function doesn't support).
// If (b^2 - 4ac) is > 0 there are two solutions.
Vector2D P ;
float a , b , c , sqr , insideSqr ;
// Translate circle to origin.
P [ 0 ] = vLinePt [ 0 ] - center [ 0 ] ;
P [ 1 ] = vLinePt [ 1 ] - center [ 1 ] ;
a = vLineDir . Dot ( vLineDir ) ;
b = 2.0f * P . Dot ( vLineDir ) ;
c = P . Dot ( P ) - ( radius * radius ) ;
insideSqr = b * b - 4 * a * c ;
if ( insideSqr < = 0.000001f )
return false ;
// Ok, two solutions.
sqr = ( float ) FastSqrt ( insideSqr ) ;
float denom = 1.0 / ( 2.0f * a ) ;
* fIntersection1 = ( - b - sqr ) * denom ;
* fIntersection2 = ( - b + sqr ) * denom ;
return true ;
}
# ifdef GAME_DLL
// a local helper to normalize some code below -- gets inlined
static void ASW_WriteScreenShakeToMessage ( CBasePlayer * pPlayer , ShakeCommand_t eCommand , float amplitude , float frequency , float duration , const Vector & direction )
{
CSingleUserRecipientFilter user ( pPlayer ) ;
user . MakeReliable ( ) ;
if ( direction . IsZeroFast ( ) ) // nondirectional shake
{
UserMessageBegin ( user , " Shake " ) ;
WRITE_BYTE ( eCommand ) ; // shake command (SHAKE_START, STOP, FREQUENCY, AMPLITUDE)
WRITE_FLOAT ( amplitude ) ; // shake magnitude/amplitude
WRITE_FLOAT ( frequency ) ; // shake noise frequency
WRITE_FLOAT ( duration ) ; // shake lasts this long
MessageEnd ( ) ;
}
else // directional shake
{
UserMessageBegin ( user , " ShakeDir " ) ;
WRITE_BYTE ( eCommand ) ; // shake command (SHAKE_START, STOP, FREQUENCY, AMPLITUDE)
WRITE_FLOAT ( amplitude ) ; // shake magnitude/amplitude
WRITE_FLOAT ( frequency ) ; // shake noise frequency
WRITE_FLOAT ( duration ) ; // shake lasts this long
WRITE_VEC3NORMAL ( direction ) ;
MessageEnd ( ) ;
}
}
# endif
//-----------------------------------------------------------------------------
// Transmits the actual shake event
//-----------------------------------------------------------------------------
void ASW_TransmitShakeEvent ( CBasePlayer * pPlayer , float localAmplitude , float frequency , float duration , ShakeCommand_t eCommand , const Vector & direction )
{
if ( ( localAmplitude > 0 ) | | ( eCommand = = SHAKE_STOP ) )
{
if ( eCommand = = SHAKE_STOP )
localAmplitude = 0 ;
# ifdef GAME_DLL
ASW_WriteScreenShakeToMessage ( pPlayer , eCommand , localAmplitude , frequency , duration , direction ) ;
# else
ScreenShake_t shake ;
shake . command = eCommand ;
shake . amplitude = localAmplitude ;
shake . frequency = frequency ;
shake . duration = duration ;
shake . direction = direction ;
ASW_TransmitShakeEvent ( pPlayer , shake ) ;
# endif
}
}
void ASW_TransmitShakeEvent ( CBasePlayer * pPlayer , const ScreenShake_t & shake )
{
if ( shake . command = = SHAKE_STOP & & shake . amplitude ! = 0 )
{
// create a corrected screenshake and recursively call myself
AssertMsg1 ( false , " A ScreenShake_t had a SHAKE_STOP command but a nonzero amplitude %.1f; this is meaningless. \n " , shake . amplitude ) ;
ScreenShake_t localShake = shake ;
localShake . amplitude = 0 ;
ASW_TransmitShakeEvent ( pPlayer , localShake ) ;
}
# ifdef GAME_DLL
ASW_WriteScreenShakeToMessage ( pPlayer , shake . command , shake . amplitude , shake . frequency , shake . duration , shake . direction ) ;
# else
GetViewEffects ( ) - > Shake ( shake ) ;
# endif
}
# ifdef GAME_DLL
//-----------------------------------------------------------------------------
// Compute shake amplitude
//-----------------------------------------------------------------------------
inline float ASW_ComputeShakeAmplitude ( const Vector & center , const Vector & shakePt , float amplitude , float radius )
{
if ( radius < = 0 )
return amplitude ;
float localAmplitude = - 1 ;
Vector delta = center - shakePt ;
float distance = delta . Length ( ) ;
if ( distance < = radius )
{
// Make the amplitude fall off over distance
float flPerc = 1.0 - ( distance / radius ) ;
localAmplitude = amplitude * flPerc ;
}
return localAmplitude ;
}
//-----------------------------------------------------------------------------
// Purpose: Shake the screen of all clients within radius.
// radius == 0, shake all clients
// UNDONE: Fix falloff model (disabled)?
// UNDONE: Affect user controls?
// Input : center - Center of screen shake, radius is measured from here.
// amplitude - Amplitude of shake
// frequency -
// duration - duration of shake in seconds.
// radius - Radius of effect, 0 shakes all clients.
// command - One of the following values:
// SHAKE_START - starts the screen shake for all players within the radius
// SHAKE_STOP - stops the screen shake for all players within the radius
// SHAKE_AMPLITUDE - modifies the amplitude of the screen shake
// for all players within the radius
// SHAKE_FREQUENCY - modifies the frequency of the screen shake
// for all players within the radius
// bAirShake - completely ignored
//-----------------------------------------------------------------------------
const float ASW_MAX_SHAKE_AMPLITUDE = 16.0f ;
void UTIL_ASW_ScreenShake ( const Vector & center , float amplitude , float frequency , float duration , float radius , ShakeCommand_t eCommand , bool bAirShake )
{
int i ;
float localAmplitude ;
if ( amplitude > ASW_MAX_SHAKE_AMPLITUDE )
{
amplitude = ASW_MAX_SHAKE_AMPLITUDE ;
}
for ( i = 1 ; i < = gpGlobals - > maxClients ; i + + )
{
CBaseEntity * pPlayer = UTIL_PlayerByIndex ( i ) ;
//
// Only start shakes for players that are on the ground unless doing an air shake.
//
if ( ! pPlayer )
{
continue ;
}
// find the player's marine
CASW_Player * pASWPlayer = dynamic_cast < CASW_Player * > ( pPlayer ) ;
if ( ! pASWPlayer | | ! pASWPlayer - > GetMarine ( ) )
continue ;
Vector vecMarinePos = pASWPlayer - > GetMarine ( ) - > WorldSpaceCenter ( ) ;
if ( pASWPlayer - > GetMarine ( ) - > IsControllingTurret ( ) & & pASWPlayer - > GetMarine ( ) - > GetRemoteTurret ( ) )
vecMarinePos = pASWPlayer - > GetMarine ( ) - > GetRemoteTurret ( ) - > GetAbsOrigin ( ) ;
localAmplitude = ASW_ComputeShakeAmplitude ( center , vecMarinePos , amplitude , radius ) ;
// This happens if the player is outside the radius, in which case we should ignore
// all commands
if ( localAmplitude < 0 )
continue ;
ASW_TransmitShakeEvent ( ( CBasePlayer * ) pPlayer , localAmplitude , frequency , duration , eCommand ) ;
}
}
//-----------------------------------------------------------------------------
// Purpose: Perform a directional "punch" on the screen of all clients within radius.
// radius == 0, shake all clients
// Input : center - Center of screen shake, radius is measured from here.
// direction - (world space) direction in which to punch camera. punching down makes it look like the world is moving up. must be normal.
// amplitude - Amplitude of shake, in world units for the camera
// frequency - controls number of bounces before shake settles; a frequency of 1 means three peaks (forward, back, little forward, settle)
// duration - duration of shake in seconds.
// radius - Radius of effect, 0 shakes all clients.
//-----------------------------------------------------------------------------
void UTIL_ASW_ScreenPunch ( const Vector & center , const Vector & direction , float amplitude , float frequency , float duration , float radius )
{
ScreenShake_t shake ;
shake . command = SHAKE_START ;
shake . direction = direction ;
shake . amplitude = amplitude ;
shake . frequency = frequency ;
shake . duration = duration ;
UTIL_ASW_ScreenPunch ( center , radius , shake ) ;
}
void UTIL_ASW_ScreenPunch ( const Vector & center , float radius , const ScreenShake_t & shake )
{
int i ;
const float radiusSqr = radius * radius ;
AssertMsg ( CloseEnough ( shake . direction . LengthSqr ( ) , 1 ) , " Direction param to ASW_ScreenPunch is abnormal \n " ) ;
for ( i = 1 ; i < = gpGlobals - > maxClients ; i + + )
{
CBaseEntity * pPlayer = UTIL_PlayerByIndex ( i ) ;
//
// Only start shakes for players that are on the ground unless doing an air shake.
//
if ( ! pPlayer )
{
continue ;
}
// find the player's marine
CASW_Player * pASWPlayer = assert_cast < CASW_Player * > ( pPlayer ) ;
if ( ! pASWPlayer | | ! pASWPlayer - > GetMarine ( ) )
continue ;
Vector vecMarinePos = pASWPlayer - > GetMarine ( ) - > WorldSpaceCenter ( ) ;
if ( pASWPlayer - > GetMarine ( ) - > IsControllingTurret ( ) & & pASWPlayer - > GetMarine ( ) - > GetRemoteTurret ( ) )
vecMarinePos = pASWPlayer - > GetMarine ( ) - > GetRemoteTurret ( ) - > GetAbsOrigin ( ) ;
if ( vecMarinePos . DistToSqr ( center ) > radiusSqr )
continue ;
ASW_TransmitShakeEvent ( ( CBasePlayer * ) pPlayer , shake ) ;
}
}
// returns the nearest marine to this point
CASW_Marine * UTIL_ASW_NearestMarine ( const Vector & pos , float & marine_distance , ASW_Marine_Class marineClass , bool bAIOnly )
{
// check through all marines, finding the closest that we're aware of
CASW_Game_Resource * pGameResource = ASWGameResource ( ) ;
float distance = 0.0f ;
marine_distance = - 1.0f ;
CASW_Marine * pNearest = NULL ;
for ( int i = 0 ; i < pGameResource - > GetMaxMarineResources ( ) ; i + + )
{
CASW_Marine_Resource * pMR = pGameResource - > GetMarineResource ( i ) ;
if ( pMR ! = NULL & & pMR - > GetMarineEntity ( ) ! = NULL & & pMR - > GetMarineEntity ( ) - > GetHealth ( ) > 0 )
{
if ( bAIOnly & & pMR - > IsInhabited ( ) )
continue ;
if ( marineClass ! = MARINE_CLASS_UNDEFINED & & pMR - > GetProfile ( ) & & pMR - > GetProfile ( ) - > GetMarineClass ( ) ! = marineClass )
continue ;
distance = pMR - > GetMarineEntity ( ) - > GetAbsOrigin ( ) . DistTo ( pos ) ;
if ( marine_distance = = - 1.0f | | distance < marine_distance )
{
marine_distance = distance ;
pNearest = pMR - > GetMarineEntity ( ) ;
}
}
}
return pNearest ;
}
CASW_Marine * UTIL_ASW_NearestMarine ( const CASW_Marine * pMarine , float & marine_distance )
{
// check through all marines, finding the closest that we're aware of
CASW_Game_Resource * pGameResource = ASWGameResource ( ) ;
float distance = 0 ;
marine_distance = - 1.0f ;
CASW_Marine * pNearest = NULL ;
for ( int i = 0 ; i < pGameResource - > GetMaxMarineResources ( ) ; i + + )
{
CASW_Marine_Resource * pMR = pGameResource - > GetMarineResource ( i ) ;
if ( pMR ! = NULL & & pMR - > GetMarineEntity ( ) ! = NULL & & pMR - > GetMarineEntity ( ) ! = pMarine & & pMR - > GetMarineEntity ( ) - > GetHealth ( ) > 0 )
{
distance = pMR - > GetMarineEntity ( ) - > GetAbsOrigin ( ) . DistTo ( pMarine - > GetAbsOrigin ( ) ) ;
if ( marine_distance = = - 1.0f | | distance < marine_distance )
{
marine_distance = distance ;
pNearest = pMR - > GetMarineEntity ( ) ;
}
}
}
return pNearest ;
}
int UTIL_ASW_NumCommandedMarines ( const CASW_Player * pPlayer )
{
int nNumMarines = 0 ;
// check through all marines
CASW_Game_Resource * pGameResource = ASWGameResource ( ) ;
for ( int i = 0 ; i < pGameResource - > GetMaxMarineResources ( ) ; i + + )
{
CASW_Marine_Resource * pMR = pGameResource - > GetMarineResource ( i ) ;
if ( pMR & & pMR - > GetMarineEntity ( ) & & pMR - > GetMarineEntity ( ) - > GetHealth ( ) > 0 )
{
if ( pMR - > GetMarineEntity ( ) - > GetCommander ( ) = = pPlayer )
{
nNumMarines + + ;
}
}
}
return nNumMarines ;
}
# else
// make a specific clientside entity gib
bool UTIL_ASW_ClientsideGib ( C_BaseAnimating * pEnt )
{
if ( ! pEnt )
return false ;
C_BaseAnimating * pAnimating = dynamic_cast < C_BaseAnimating * > ( pEnt ) ;
if ( ! pAnimating )
return false ;
if ( ! stricmp ( STRING ( pAnimating - > GetModelName ( ) ) , SWARM_DRONE_MODEL ) )
{
Vector vMins , vMaxs , vGibOrigin , vGibVelocity ( 0 , 0 , 1 ) ;
if ( pEnt - > m_pRagdoll )
{
pEnt - > m_pRagdoll - > GetRagdollBounds ( vMins , vMaxs ) ;
vGibOrigin = pEnt - > m_pRagdoll - > GetRagdollOrigin ( ) + ( ( vMins + vMaxs ) / 2.0f ) ;
pEnt - > m_pRagdoll - > GetElement ( 0 ) - > GetVelocity ( & vGibVelocity , NULL ) ;
}
else
{
vGibOrigin = pEnt - > WorldSpaceCenter ( ) ;
}
FX_DroneGib ( vGibOrigin , Vector ( 0 , 0 , 1 ) , 0.5f , pAnimating - > GetSkin ( ) , pEnt - > IsOnFire ( ) ) ;
return true ;
}
else if ( ! stricmp ( STRING ( pAnimating - > GetModelName ( ) ) , SWARM_HARVESTER_MODEL ) )
{
FX_HarvesterGib ( pEnt - > WorldSpaceCenter ( ) , Vector ( 0 , 0 , 1 ) , 0.5f , pAnimating - > GetSkin ( ) , pEnt - > IsOnFire ( ) ) ;
return true ;
}
else if ( ! stricmp ( STRING ( pAnimating - > GetModelName ( ) ) , SWARM_SHIELDBUG_MODEL ) )
{
FX_HarvesterGib ( pEnt - > WorldSpaceCenter ( ) , Vector ( 0 , 0 , 1 ) , 0.5f , 1 , pEnt - > IsOnFire ( ) ) ;
return true ;
}
// todo: code to gib other types of things clientside?
return false ;
}
# endif
//void UTIL_ASW_ValidateSoundName( string_t &name, const char *defaultStr )
void UTIL_ASW_ValidateSoundName ( char * szString , int stringlength , const char * defaultStr )
{
Assert ( szString ) ;
if ( szString [ 0 ] = = ' \0 ' )
{
Q_snprintf ( szString , stringlength , " %s " , defaultStr ) ;
}
}
# ifdef GAME_DLL
void UTIL_ASW_PoisonBlur ( CBaseEntity * pEntity , float duration )
{
if ( ! pEntity | | ! pEntity - > IsNetClient ( ) )
return ;
CSingleUserRecipientFilter user ( ( CBasePlayer * ) pEntity ) ;
user . MakeReliable ( ) ;
UserMessageBegin ( user , " ASWBlur " ) ; // use the magic #1 for "one client"
WRITE_SHORT ( ( int ) ( duration * 10.0f ) ) ; // blur lasts this long / 10
MessageEnd ( ) ;
}
// tests if a particular entity is blocking any marines (used by phys props to see if they should leave pushaway mode)
bool UTIL_ASW_BlockingMarine ( CBaseEntity * pEntity )
{
CASW_Game_Resource * pGameResource = ASWGameResource ( ) ;
if ( ! pGameResource )
return false ;
int iCurrentGroup = pEntity - > GetCollisionGroup ( ) ;
pEntity - > SetCollisionGroup ( COLLISION_GROUP_NONE ) ;
bool bBlockedMarine = false ;
for ( int i = 0 ; i < pGameResource - > GetMaxMarineResources ( ) ; i + + )
{
CASW_Marine_Resource * pMR = pGameResource - > GetMarineResource ( i ) ;
if ( pMR ! = NULL & & pMR - > GetMarineEntity ( ) ! = NULL & & pMR - > GetMarineEntity ( ) - > GetHealth ( ) > 0 )
{
CASW_Marine * pMarine = pMR - > GetMarineEntity ( ) ;
// check if this marine's bounding box trace collides with the specified entity
Ray_t ray ;
trace_t tr ;
ray . Init ( pMarine - > GetAbsOrigin ( ) , pMarine - > GetAbsOrigin ( ) - Vector ( 0 , 0 , 1 ) ,
pMarine - > CollisionProp ( ) - > OBBMins ( ) , pMarine - > CollisionProp ( ) - > OBBMaxs ( ) ) ;
if ( pEntity - > TestCollision ( ray , MASK_PLAYERSOLID , tr ) )
{
bBlockedMarine = true ;
break ;
}
}
}
pEntity - > SetCollisionGroup ( iCurrentGroup ) ;
return bBlockedMarine ;
}
CASW_Marine * UTIL_ASW_Marine_Can_Chatter_Spot ( CBaseEntity * pEntity , float fDist )
{
CASW_Game_Resource * pGameResource = ASWGameResource ( ) ;
if ( ! pGameResource )
return NULL ;
// find how many marines can see us
int iFound = 0 ;
for ( int i = 0 ; i < pGameResource - > GetMaxMarineResources ( ) ; i + + )
{
CASW_Marine_Resource * pMarineResource = pGameResource - > GetMarineResource ( i ) ;
if ( ! pMarineResource )
continue ;
CASW_Marine * pMarine = pMarineResource - > GetMarineEntity ( ) ;
if ( ! pMarine )
continue ;
if ( pMarine - > GetAbsOrigin ( ) . DistTo ( pEntity - > GetAbsOrigin ( ) ) < fDist )
{
Vector vecFacing ;
AngleVectors ( pMarine - > GetAbsAngles ( ) , & vecFacing ) ;
Vector vecDir = pEntity - > GetAbsOrigin ( ) - pMarine - > GetAbsOrigin ( ) ;
vecDir . NormalizeInPlace ( ) ;
if ( vecFacing . Dot ( vecDir ) > 0.5f )
iFound + + ;
}
}
if ( iFound < = 0 )
return NULL ;
// randomly pick one
int iChosen = random - > RandomInt ( 0 , iFound - 1 ) ;
for ( int i = 0 ; i < pGameResource - > GetMaxMarineResources ( ) ; i + + )
{
CASW_Marine_Resource * pMarineResource = pGameResource - > GetMarineResource ( i ) ;
if ( ! pMarineResource )
continue ;
CASW_Marine * pMarine = pMarineResource - > GetMarineEntity ( ) ;
if ( ! pMarine )
continue ;
if ( pMarine - > GetAbsOrigin ( ) . DistTo ( pEntity - > GetAbsOrigin ( ) ) < 600.0f )
{
Vector vecFacing ;
AngleVectors ( pMarine - > GetAbsAngles ( ) , & vecFacing ) ;
Vector vecDir = pEntity - > GetAbsOrigin ( ) - pMarine - > GetAbsOrigin ( ) ;
vecDir . NormalizeInPlace ( ) ;
if ( vecFacing . Dot ( vecDir ) > 0.5f )
{
if ( iChosen < = 0 )
return pMarine ;
iChosen - - ;
}
}
}
return NULL ;
}
# endif
//-----------------------------------------------------------------------------
// Purpose: Trace filter that only hits aliens (all NPCS but the marines, eggs, goo)
//-----------------------------------------------------------------------------
bool CTraceFilterAliensEggsGoo : : ShouldHitEntity ( IHandleEntity * pServerEntity , int contentsMask )
{
if ( CTraceFilterSimple : : ShouldHitEntity ( pServerEntity , contentsMask ) )
{
# ifndef CLIENT_DLL
CBaseEntity * pEntity = EntityFromEntityHandle ( pServerEntity ) ;
if ( pEntity - > Classify ( ) = = CLASS_ASW_MARINE ) // we dont hit marines
return false ;
if ( IsAlienClass ( pEntity - > Classify ( ) ) )
return true ;
# endif // !CLIENT_DLL
}
return false ;
}
// NOTE: This function assumes 75 fov and 4:3 ratio (todo: support widescreen all the time?)
bool CanFrustumSee ( const Vector & vecCameraCenter , const QAngle & angCameraFacing ,
const Vector & pos , const int padding , const int forward_limit , float fov = 75.0f )
{
Vector vForward , vRight , vUp ;
AngleVectors ( angCameraFacing , & vForward , & vRight , & vUp ) ;
Vector vecTestPos = pos ;
// bring in the x coord by the padding
if ( vecTestPos . x < vecCameraCenter . x )
vecTestPos . x = MIN ( vecCameraCenter . x , vecTestPos . x + padding ) ;
else if ( vecTestPos . x > vecCameraCenter . x )
vecTestPos . x = MAX ( vecCameraCenter . x , vecTestPos . x - padding ) ;
// bring in the y coord by the padding
if ( vecTestPos . y < vecCameraCenter . y )
vecTestPos . y = MIN ( vecCameraCenter . y , vecTestPos . y + padding ) ;
else if ( vecTestPos . y > vecCameraCenter . y )
vecTestPos . y = MAX ( vecCameraCenter . y , vecTestPos . y - padding ) ;
float ratio = 4.0f / 3.0f ; // assume 4:3 res
float fov_tangent = tan ( DEG2RAD ( fov ) * 0.5f ) ;
Vector vDiff = vecTestPos - vecCameraCenter ; // vector from camera to testing position
float forward_diff = vDiff . Dot ( vForward ) ;
if ( forward_diff < 0 ) // behind the camera
return false ;
if ( forward_limit > 0 & & forward_diff > forward_limit )
return false ; // too far away
//int padding_at_this_distance = padding * (forward_diff / 405.0f); // adjust padding by ratio of distance to default camera height
float up_diff = vDiff . Dot ( vUp ) ;
float max_up_diff = forward_diff * fov_tangent ;
if ( up_diff > max_up_diff | | up_diff < - max_up_diff )
return false ;
float right_diff = vDiff . Dot ( vRight ) ;
float max_right_diff = max_up_diff * ratio ;
if ( right_diff > max_right_diff | | right_diff < - max_right_diff )
return false ;
return true ;
}
CASW_Marine * UTIL_ASW_MarineCanSee ( CASW_Marine_Resource * pMarineResource , const Vector & pos , const int padding , bool & bCorpseCanSee , const int forward_limit )
{
if ( ! pMarineResource )
return NULL ;
Vector vecMarinePos ;
CASW_Marine * pMarine = NULL ;
# ifndef CLIENT_DLL
if ( pMarineResource - > GetHealthPercent ( ) < = 0 | | ! pMarineResource - > IsAlive ( ) ) // if we're dead, take the corpse position
{
vecMarinePos = pMarineResource - > m_vecDeathPosition ;
}
else
# endif
{
pMarine = pMarineResource - > GetMarineEntity ( ) ;
if ( ! pMarine )
return NULL ;
vecMarinePos = pMarine - > GetAbsOrigin ( ) ;
}
// note: assumes 60 degree pitch camera and 405 dist (actual convars for these are on the client...)
QAngle angCameraFacing ( 60 , 90 , 0 ) ;
Vector vForward , vRight , vUp ;
AngleVectors ( angCameraFacing , & vForward , & vRight , & vUp ) ;
Vector vecCameraCenter = vecMarinePos - vForward * 405 ;
// see if they're beyond the fog plane
# ifdef CLIENT_DLL
C_ASW_Player * pPlayer = C_ASW_Player : : GetLocalASWPlayer ( ) ;
if ( pPlayer )
{
if ( pPlayer - > GetPlayerFog ( ) . m_hCtrl - > m_fog . enable )
{
float dist = ( vecCameraCenter - pos ) . Length ( ) ;
if ( dist > pPlayer - > GetPlayerFog ( ) . m_hCtrl - > m_fog . end )
return NULL ;
}
}
# else
// ASWTODO - no worldfogparams anymore?
/*
fogparams_t fog ;
GetWorldFogParams ( fog ) ;
if ( fog . enable . Get ( ) )
{
float dist = ( vecCameraCenter - pos ) . Length ( ) ;
if ( dist > fog . end . Get ( ) )
return NULL ;
}
*/
# endif
// check for plain near the marine
bool bNearby = CanFrustumSee ( vecCameraCenter , angCameraFacing , pos , padding , forward_limit ) ;
// check if he's looking through a remote turret and can possibly see us from that
if ( ! bNearby & & pMarine & & pMarine - > IsControllingTurret ( ) & & pMarine - > GetRemoteTurret ( ) )
{
// a turret can look in any direction, so let's just do a radius check (would match up with the fog anyways)
bNearby = ( pMarine - > GetRemoteTurret ( ) - > GetAbsOrigin ( ) . DistTo ( pos ) < = 1024 ) ; // assume fog distance of 1024 when in first person
}
// check if he's looking through a security cam
if ( ! bNearby & & pMarine & & pMarine - > m_hUsingEntity . Get ( ) )
{
CASW_Computer_Area * pComputer = dynamic_cast < CASW_Computer_Area * > ( pMarine - > m_hUsingEntity . Get ( ) ) ;
if ( pComputer )
{
if ( pComputer - > m_iActiveCam = = 1 & & pComputer - > m_hSecurityCam1 . Get ( ) )
{
CPointCamera * pCam = dynamic_cast < CPointCamera * > ( pComputer - > m_hSecurityCam1 . Get ( ) ) ;
if ( pCam )
{
Vector vecCamFacing ;
AngleVectors ( pCam - > GetAbsAngles ( ) , & vecCamFacing ) ;
bNearby = ( vecCamFacing . Dot ( pos - pCam - > GetAbsOrigin ( ) ) > 0 ) & & // check facing
( pCam - > GetAbsOrigin ( ) . DistTo ( pos ) < = 1024 ) ; // assume fog distance of 1024 when in first person
}
}
}
}
# ifndef CLIENT_DLL
if ( asw_debug_marine_can_see . GetBool ( ) )
{
if ( bNearby )
{
NDebugOverlay : : Line ( pos , vecMarinePos + Vector ( 0 , 0 , 10 ) , 255 , 255 , 0 , true , 0.1f ) ;
}
else
{
NDebugOverlay : : Line ( pos , vecMarinePos + Vector ( 0 , 0 , 10 ) , 255 , 0 , 0 , true , 0.1f ) ;
}
}
# endif
if ( bNearby )
{
if ( ! pMarine )
bCorpseCanSee = true ;
return pMarine ;
}
return NULL ;
}
CASW_Marine * UTIL_ASW_AnyMarineCanSee ( const Vector & pos , const int padding , bool & bCorpseCanSee , const int forward_limit )
{
// find the closest marine
CASW_Game_Resource * pGameResource = ASWGameResource ( ) ;
if ( ! pGameResource )
return NULL ;
bCorpseCanSee = false ;
for ( int i = 0 ; i < pGameResource - > GetMaxMarineResources ( ) ; i + + )
{
CASW_Marine_Resource * pMarineResource = pGameResource - > GetMarineResource ( i ) ;
bool bCorpse = false ;
CASW_Marine * pMarine = ( UTIL_ASW_MarineCanSee ( pMarineResource , pos , padding , bCorpse , forward_limit ) ) ;
bCorpseCanSee | = bCorpse ;
if ( pMarine )
return pMarine ;
}
return NULL ;
}
bool UTIL_ASW_MarineViewCone ( const Vector & pos )
{
// find the closest marine
CASW_Game_Resource * pGameResource = ASWGameResource ( ) ;
if ( ! pGameResource )
return false ;
for ( int i = 0 ; i < pGameResource - > GetMaxMarineResources ( ) ; i + + )
{
CASW_Marine_Resource * pMarineResource = pGameResource - > GetMarineResource ( i ) ;
if ( ! pMarineResource )
continue ;
Vector vecMarinePos ;
CASW_Marine * pMarine = pMarineResource - > GetMarineEntity ( ) ;
if ( ! pMarine )
continue ;
// check it's not too far away
Vector vecDiff = pos - pMarine - > GetAbsOrigin ( ) ;
if ( vecDiff . LengthSqr ( ) > asw_marine_view_cone_dist . GetFloat ( ) )
continue ;
// check dot
Vector vecFacing ;
AngleVectors ( pMarine - > EyeAngles ( ) , & vecFacing ) ;
float dot = vecDiff . Dot ( vecFacing ) ;
if ( dot < asw_marine_view_cone_dot . GetFloat ( ) )
continue ;
return true ;
}
return false ;
}
# ifdef CLIENT_DLL
extern ConVar asw_cam_mode ;
extern ConVar joy_pan_camera ;
# else
extern ConVar asw_debug_medals ;
extern ConVar asw_wire_full_random ;
# endif
float UTIL_ASW_CalcFastDoorHackTime ( int iNumRows , int iNumColumns , int iNumWires , int iHackLevel , float fSpeedScale )
{
float ideal_time = 1.0f ;
// assume 0.5 seconds per row
float seconds_per_column = 0.5f ;
if ( iNumRows = = 2 )
seconds_per_column = 1.0f ;
else if ( iNumRows = = 3 )
seconds_per_column = 1.5f ;
float time_to_assemble_wire = seconds_per_column * iNumColumns ;
# ifndef CLIENT_DLL
if ( ! asw_wire_full_random . GetBool ( ) )
{
time_to_assemble_wire = 3.0f ; // assumes 5 mistakes per wire
}
if ( asw_debug_medals . GetBool ( ) )
Msg ( " time_to_assemble_wire = %f \n " , time_to_assemble_wire ) ;
# endif
// ok so after this amount of time, the wire would be charging
if ( iNumWires < = 0 )
iNumWires = 1 ;
float speed_per_wire = 1.0f / iNumWires ;
speed_per_wire * = fSpeedScale ;
float charge_before_assembling_wire_2 = speed_per_wire * time_to_assemble_wire ;
if ( charge_before_assembling_wire_2 > = iHackLevel | | iNumWires < 2 )
{
// if we're here, it means we would have finished the hack before wire two was assembled
// so the ideal time is just how long it takes to charge up with 1 wire, plus the time it took us to assemble
ideal_time = ( float ( iHackLevel ) / speed_per_wire ) + time_to_assemble_wire ;
}
else
{
// if we're in here, then wire 1 and 2 will be charging
float charge_before_assembling_wire_3 = charge_before_assembling_wire_2
+ speed_per_wire * time_to_assemble_wire * 2 ; // wire 2's contribution
if ( charge_before_assembling_wire_3 > = iHackLevel | | iNumWires < 3 )
{
// if we're here, it means we would have finished the hack before wire three was assembled
float first_wire_time = time_to_assemble_wire + time_to_assemble_wire ;
float duo_charge = float ( iHackLevel ) - charge_before_assembling_wire_2 ; // how much charge up to do with both wires
ideal_time = ( duo_charge / ( speed_per_wire * 2 ) ) + first_wire_time ;
}
else
{
// if we're in here, then wires 1, 2 and 3 will be charging
float charge_before_assembling_wire_4 = charge_before_assembling_wire_3
+ speed_per_wire * time_to_assemble_wire * 3 ; // wire 3's contribution
if ( charge_before_assembling_wire_3 > = iHackLevel | | iNumWires < 4 )
{
// if we're here, it means we would have finished the hack before wire 4 was assembled
float first_wire_time = time_to_assemble_wire + time_to_assemble_wire ;
float two_wire_time = time_to_assemble_wire + first_wire_time ;
float triple_charge = float ( iHackLevel ) - charge_before_assembling_wire_3 ; // how much charge do we with 3 wires
ideal_time = ( triple_charge / ( speed_per_wire * 3 ) ) + two_wire_time ;
}
else
{
// if we're in here, then wires 1,2,3 and 4 will be charging
float first_wire_time = time_to_assemble_wire + time_to_assemble_wire ;
float two_wire_time = time_to_assemble_wire + first_wire_time ;
float three_wire_time = time_to_assemble_wire + two_wire_time ;
float quad_charge = float ( iHackLevel ) - charge_before_assembling_wire_4 ; // how much charge do we with 3 wires
ideal_time = ( quad_charge / ( speed_per_wire * 4 ) ) + three_wire_time ;
}
}
}
int iSkill = ASWGameRules ( ) ? ASWGameRules ( ) - > GetSkillLevel ( ) : 2 ;
if ( iSkill = = 1 )
ideal_time * = 1.05f ; // 5% slower on easy mode
else if ( iSkill = = 3 )
ideal_time * = 0.95f ; // 5% faster on hard mode
else if ( iSkill = = 4 )
ideal_time * = 0.90f ; // 10% faster on insane mode
return ideal_time ;
}
int UTIL_ASW_GetNumPlayers ( )
{
int count = 0 ;
for ( int i = 0 ; i < MAX_PLAYERS ; i + + )
{
// found a connected player who isn't ready?
# ifdef CLIENT_DLL
if ( g_PR - > IsConnected ( i + 1 ) )
count + + ;
# else
CBasePlayer * pPlayer = UTIL_PlayerByIndex ( i + 1 ) ;
// if they're not connected, skip them
if ( pPlayer & & pPlayer - > IsConnected ( ) )
count + + ;
# endif
}
return count ;
}
bool UTIL_ASW_MissionHasBriefing ( const char * mapname )
{
bool bSpecialMap = ( ! Q_strnicmp ( mapname , " intro_ " , 6 ) | |
! Q_strnicmp ( mapname , " outro_ " , 6 ) | |
! Q_strnicmp ( mapname , " tutorial " , 8 ) | |
! Q_strnicmp ( mapname , " swarmselectionscreen " , 20 ) ) ;
return ! bSpecialMap ;
}
bool ASW_IsSecurityCam ( CPointCamera * pCameraEnt )
{
CASW_PointCamera * pASW_Cam = dynamic_cast < CASW_PointCamera * > ( pCameraEnt ) ;
return pASW_Cam & & pASW_Cam - > m_bSecurityCam ;
}
// copies a string
char * ASW_AllocString ( const char * szString )
{
if ( ! szString )
return NULL ;
int len = Q_strlen ( szString ) + 1 ;
if ( len < = 1 )
return NULL ;
char * text = new char [ len ] ;
Q_strncpy ( text , szString , len ) ;
return text ;
}
# ifdef CLIENT_DLL
CNewParticleEffect * UTIL_ASW_CreateFireEffect ( C_BaseEntity * pEntity )
{
CNewParticleEffect * pBurningEffect = pEntity - > ParticleProp ( ) - > Create ( " ent_on_fire " , PATTACH_ABSORIGIN_FOLLOW ) ;
if ( pBurningEffect )
{
Vector vecOffest1 = ( pEntity - > WorldSpaceCenter ( ) - pEntity - > GetAbsOrigin ( ) ) + Vector ( 0 , 0 , 16 ) ;
pEntity - > ParticleProp ( ) - > AddControlPoint ( pBurningEffect , 1 , pEntity , PATTACH_ABSORIGIN_FOLLOW , NULL , vecOffest1 ) ;
// all bounding boxes are the same, skip this for now
Vector vecSurroundMins , vecSurroundMaxs ;
vecSurroundMins = pEntity - > CollisionProp ( ) - > OBBMins ( ) ;
vecSurroundMaxs = pEntity - > CollisionProp ( ) - > OBBMaxs ( ) ;
// this sets the maximum bounds for scaling up or down the fire
float flMaxBounds = 34.0 ;
flMaxBounds = MAX ( flMaxBounds , vecSurroundMaxs . x - vecSurroundMins . x ) ;
flMaxBounds = MAX ( flMaxBounds , vecSurroundMaxs . y - vecSurroundMins . y ) ;
flMaxBounds = MAX ( flMaxBounds , vecSurroundMaxs . z - vecSurroundMins . z ) ;
float flScalar = 1.0f ;
flMaxBounds / = 115.0f ;
flMaxBounds = clamp ( flMaxBounds , 0.75f , 1.75f ) ;
// position 0 of CP2 controls the scale of the flames, we want to scale them a bit based on how big the creature is
// position 1 is the number generated
if ( flMaxBounds > 220 )
flScalar = 2.0f ;
pBurningEffect - > SetControlPoint ( 2 , Vector ( flMaxBounds , flMaxBounds * flScalar , 0 ) ) ;
}
return pBurningEffect ;
}
// attempts to localize a string
// if it fails, it just fills the destination with the token name
void TryLocalize ( const char * token , wchar_t * unicode , int unicodeBufferSizeInBytes )
{
if ( token [ 0 ] = = ' # ' )
{
wchar_t * pLocalized = g_pVGuiLocalize - > Find ( token ) ;
if ( pLocalized )
{
_snwprintf ( unicode , unicodeBufferSizeInBytes , L " %s " , pLocalized ) ;
return ;
}
}
g_pVGuiLocalize - > ConvertANSIToUnicode ( token , unicode , unicodeBufferSizeInBytes ) ;
}
ConVar asw_floating_number_type ( " asw_floating_number_type " , " 0 " , FCVAR_NONE , " 1 = vgui, 2 = particles " ) ;
void UTIL_ASW_ClientFloatingDamageNumber ( const CTakeDamageInfo & info )
{
// TODO: Move this to some rendering step?
if ( asw_floating_number_type . GetInt ( ) = = 1 )
{
Vector screenPos ;
Vector vecPos = info . GetDamagePosition ( ) ; // WorldSpaceCenter()
//debugoverlay->ScreenPosition( vecPos, screenPos );
floating_number_params_t params ;
params . x = 0 ; //screenPos.x;
params . y = 0 ; //screenPos.y;
params . bShowPlus = false ;
//params.hFont = m_fontLargeFloatingText;
params . flMoveDuration = 0.9f ;
params . flFadeStart = 0.6f ;
params . flFadeDuration = 0.3f ;
params . rgbColor = Color ( 200 , 200 , 200 , 255 ) ;
if ( info . GetDamageCustom ( ) & DAMAGE_FLAG_WEAKSPOT )
{
params . rgbColor = Color ( 255 , 170 , 150 , 255 ) ;
params . flFadeStart = 0.65f ;
params . flFadeDuration = 0.4f ;
params . flMoveDuration = 0.95f ;
}
params . alignment = vgui : : Label : : a_center ;
params . bWorldSpace = true ;
params . vecPos = vecPos ;
new CFloatingNumber ( ( int ) info . GetDamage ( ) , params , GetClientMode ( ) - > GetViewport ( ) ) ;
}
else if ( asw_floating_number_type . GetInt ( ) = = 2 )
{
C_ASW_Marine * pMarine = dynamic_cast < C_ASW_Marine * > ( info . GetAttacker ( ) ) ;
if ( ! pMarine )
return ;
C_ASW_Player * pAttackingPlayer = pMarine - > GetCommander ( ) ;
if ( ! pAttackingPlayer )
return ;
if ( pAttackingPlayer ! = C_BasePlayer : : GetLocalPlayer ( ) )
return ;
UTIL_ASW_ParticleDamageNumber ( info . GetAttacker ( ) , info . GetDamagePosition ( ) , int ( info . GetDamage ( ) ) , info . GetDamageCustom ( ) , 1.0f , false ) ;
}
}
void UTIL_ASW_ParticleDamageNumber ( C_BaseEntity * pEnt , Vector vecPos , int iDamage , int iDmgCustom , float flScale , bool bRandomVelocity )
{
if ( asw_floating_number_type . GetInt ( ) ! = 2 )
return ;
if ( ! pEnt )
return ;
QAngle vecAngles ;
vecAngles [ PITCH ] = 0.0f ;
vecAngles [ YAW ] = ASWInput ( ) - > ASW_GetCameraYaw ( ) ;
vecAngles [ ROLL ] = ASWInput ( ) - > ASW_GetCameraPitch ( ) ;
//Msg( "DMG # angles ( %f, %f, %f )\n", vecAngles[PITCH], vecAngles[YAW], vecAngles[ROLL] );
Vector vecForward , vecRight , vecUp ;
AngleVectors ( vecAngles , & vecForward , & vecRight , & vecUp ) ;
Color cNumber = Color ( 255 , 240 , 240 ) ;
int iCrit = 0 ;
float flNewScale = MAX ( flScale , 1.0f ) ;
float flLifetime = 1.0f ;
int r , g , b ;
if ( iDmgCustom & DAMAGE_FLAG_CRITICAL )
{
flNewScale * = 1.8f ;
flLifetime = 3.0f ;
iCrit = 1 ;
cNumber = Color ( 255 , 0 , 0 ) ;
}
else if ( iDmgCustom & DAMAGE_FLAG_WEAKSPOT )
{
flNewScale * = 1.3f ;
flLifetime = 1.25f ;
cNumber = Color ( 255 , 128 , 128 ) ;
}
else if ( iDmgCustom & DAMAGE_FLAG_T75 )
{
flNewScale = 1.3f ;
cNumber = Color ( 255 , 0 , 0 ) ;
// TODO: Stop these numbers from moving randomly
}
r = cNumber . r ( ) ;
g = cNumber . g ( ) ;
b = cNumber . b ( ) ;
CUtlReference < CNewParticleEffect > pEffect ;
if ( bRandomVelocity )
{
pEffect = pEnt - > ParticleProp ( ) - > Create ( " damage_numbers " , PATTACH_CUSTOMORIGIN ) ;
}
else
{
pEffect = pEnt - > ParticleProp ( ) - > Create ( " floating_numbers " , PATTACH_CUSTOMORIGIN ) ;
}
pEffect - > SetControlPoint ( 0 , vecPos ) ;
pEffect - > SetControlPoint ( 1 , Vector ( 0 , iDamage , iCrit ) ) ;
pEffect - > SetControlPoint ( 2 , Vector ( r , g , b ) ) ;
pEffect - > SetControlPoint ( 3 , Vector ( flNewScale , flLifetime , 0 ) ) ;
pEffect - > SetControlPointOrientation ( 5 , vecForward , vecRight , vecUp ) ;
}
void __MsgFunc_ASWDamageNumber ( bf_read & msg )
{
int iAmount = msg . ReadShort ( ) ;
int iFlags = msg . ReadShort ( ) ;
int iEntIndex = msg . ReadShort ( ) ;
C_BaseEntity * pEnt = iEntIndex > 0 ? ClientEntityList ( ) . GetEnt ( iEntIndex ) : NULL ;
if ( ! pEnt )
return ;
if ( asw_floating_number_type . GetInt ( ) = = 1 )
{
Vector vecPos ;
vecPos . x = msg . ReadFloat ( ) ;
vecPos . y = msg . ReadFloat ( ) ;
vecPos . z = msg . ReadFloat ( ) ;
if ( pEnt )
{
vecPos = pEnt - > WorldSpaceCenter ( ) ;
}
Vector screenPos ;
debugoverlay - > ScreenPosition ( vecPos , screenPos ) ;
floating_number_params_t params ;
params . x = 0 ; //screenPos.x;
params . y = 0 ; // screenPos.y;
params . bShowPlus = false ;
//params.hFont = m_fontLargeFloatingText;
params . flMoveDuration = 0.85f ;
params . flFadeStart = 0.6f ;
params . flFadeDuration = 0.3f ;
params . rgbColor = Color ( 200 , 200 , 200 , 255 ) ;
if ( iFlags & DAMAGE_FLAG_WEAKSPOT )
{
params . rgbColor = Color ( 255 , 170 , 150 , 255 ) ;
params . flFadeStart = 0.65f ;
params . flFadeDuration = 0.4f ;
params . flMoveDuration = 0.95f ;
}
params . alignment = vgui : : Label : : a_center ;
params . bWorldSpace = true ;
params . vecPos = vecPos ;
new CFloatingNumber ( iAmount , params , GetClientMode ( ) - > GetViewport ( ) ) ;
}
else if ( asw_floating_number_type . GetInt ( ) = = 2 )
{
UTIL_ASW_ParticleDamageNumber ( pEnt , pEnt - > WorldSpaceCenter ( ) , iAmount , iFlags , 1.25f , false ) ;
}
}
USER_MESSAGE_REGISTER ( ASWDamageNumber ) ;
# endif
/// @desc This function can be used as a convenience for when you want to
/// rapidly experiment with different screenshakes for a gameplay feature.
/// You have a single "scratchpad" screen shake which you can fill out with
/// the concommand asw_shake_setscratch .
/// Then you can read it in code with the ASW_DefaultScreenShake.
/// So, the way you use it is,
/// if you have a function Kaboom() that needs to do a screenpunch,
/// but you don't know what numbers you want for that punch yet,
/// you write the function to use the default screen shake:
///
/// void Kaboom() {
/// ASW_TransmitShakeEvent( player, ASW_DefaultScreenShake() );
/// }
///
/// and then, while the game is running, you can fiddle the numbers around
/// with asw_shake_setscratch and try the Kaboom() function over and over
/// again to see the results without having to recompile.
/// Once you have numbers you are happy with, you can go back and hardcode
/// them into Kaboom(), freeing up the "Default" shake to be used somewhere
/// else.
ScreenShake_t ASW_DefaultScreenShake ( void )
{
return ScreenShake_t ( SHAKE_START ,
asw_shake_test_punch_amp . GetFloat ( ) ,
asw_shake_test_punch_freq . GetFloat ( ) ,
asw_shake_test_punch_dura . GetFloat ( ) ,
Vector ( asw_shake_test_punch_dirx . GetFloat ( ) , asw_shake_test_punch_diry . GetFloat ( ) , asw_shake_test_punch_dirz . GetFloat ( ) )
) ;
}
static void ASW_PrintDefaultScreenShake ( void )
{
// x y z f a d
Msg ( " < %.3f,%.3f,%.3f > %.3f %.3f %.3f \n " ,
asw_shake_test_punch_dirx . GetFloat ( ) , asw_shake_test_punch_diry . GetFloat ( ) , asw_shake_test_punch_dirz . GetFloat ( ) ,
asw_shake_test_punch_freq . GetFloat ( ) ,
asw_shake_test_punch_amp . GetFloat ( ) ,
asw_shake_test_punch_dura . GetFloat ( )
) ;
}
# ifndef CLIENT_DLL
/// convenient console command for setting the default screen shake parameters
//-----------------------------------------------------------------------------
// Purpose: Test a punch-type screen shake
//-----------------------------------------------------------------------------
static void CC_ASW_Shake_SetScratch ( const CCommand & args )
{
if ( args . ArgC ( ) < 7 )
{
Msg ( " Usage: %s x y z f a d \n "
" where x,y,z are direction of screen punch \n "
" f is frequency (1 means three bounces before settling) \n "
" a is amplitude \n "
" d is duration \n "
" you can specify a direction 0 0 0 to mean a classic 'vibrating' shake rather than a directional punch. \n "
" The current default screen shake is: \n \t " ,
args [ 0 ]
) ;
ASW_PrintDefaultScreenShake ( ) ;
}
const float x = atof ( args [ 1 ] ) ;
const float y = atof ( args [ 2 ] ) ;
const float z = atof ( args [ 3 ] ) ;
const float f = atof ( args [ 4 ] ) ;
const float a = atof ( args [ 5 ] ) ;
const float d = atof ( args [ 6 ] ) ;
asw_shake_test_punch_dirx . SetValue ( x ) ;
asw_shake_test_punch_diry . SetValue ( y ) ;
asw_shake_test_punch_dirz . SetValue ( z ) ;
asw_shake_test_punch_freq . SetValue ( f ) ;
asw_shake_test_punch_amp . SetValue ( a ) ;
asw_shake_test_punch_dura . SetValue ( d ) ;
}
static ConCommand asw_shake_setscratch ( " asw_shake_setscratch " , CC_ASW_Shake_SetScratch , " Set values for the \" default \" screenshake used for rapid iteration. \n " , FCVAR_CHEAT | FCVAR_DEVELOPMENTONLY ) ;
# endif //#ifndef CLIENT_DLL
/// get a parabola that goes from source to destination in specified time
Vector UTIL_LaunchVector ( const Vector & src , const Vector & dest , float gravity , float flightTime )
{
Assert ( gravity > 0 ) ;
Assert ( ! AlmostEqual ( src , dest ) ) ;
if ( flightTime = = 0.0f )
{
flightTime = MAX ( 0.8f , sqrt ( ( ( dest - src ) . Length2D ( ) * 1.5f ) / gravity ) ) ;
}
// delta high from start to end
float H = dest . z - src . z ;
// azimuth vector
Vector azimuth = dest - src ;
azimuth . z = 0 ;
// get horizontal distance start to end
float D = azimuth . Length2D ( ) ;
// normalize azimuth
azimuth / = D ;
float Vy = ( H / flightTime + 0.5 * gravity * flightTime ) ;
float Vx = ( D / flightTime ) ;
Vector ret = azimuth * Vx ;
ret . z = Vy ;
return ret ;
}
extern ConVar sv_maxvelocity ;
void UTIL_Bound_Velocity ( Vector & vec )
{
for ( int i = 0 ; i < 3 ; i + + )
{
if ( IS_NAN ( vec [ i ] ) )
{
vec [ i ] = 0 ;
}
if ( vec [ i ] > sv_maxvelocity . GetFloat ( ) )
{
vec [ i ] = sv_maxvelocity . GetFloat ( ) ;
}
else if ( vec [ i ] < - sv_maxvelocity . GetFloat ( ) )
{
vec [ i ] = - sv_maxvelocity . GetFloat ( ) ;
}
}
}
extern ConVar sv_gravity ;
Vector UTIL_Check_Throw ( const Vector & vecSrc , const Vector & vecThrowVelocity , float flGravity , const Vector & vecHullMins , const Vector & vecHullMaxs ,
int iCollisionMask , int iCollisionGroup , CBaseEntity * pIgnoreEnt , bool bDrawArc )
{
Vector vecVelocity = vecThrowVelocity ;
const int iMaxSteps = 200 ;
Vector vecPos = vecSrc ;
float flInterval = 0.016667f ;
float flActualGravity = sv_gravity . GetFloat ( ) * flGravity ;
for ( int i = 0 ; i < iMaxSteps ; i + + )
{
// add gravity
Vector vecAbsVelocity = vecVelocity ;
Vector vecMove ;
vecMove . x = ( vecVelocity . x ) * flInterval ;
vecMove . y = ( vecVelocity . y ) * flInterval ;
// linear acceleration due to gravity
float newZVelocity = vecVelocity . z - flActualGravity * flInterval ;
vecMove . z = ( ( vecVelocity . z + newZVelocity ) / 2.0 ) * flInterval ;
vecVelocity . z = newZVelocity ;
UTIL_Bound_Velocity ( vecVelocity ) ;
// trace to new pos
trace_t tr ;
Vector vecNewPos = vecPos + vecVelocity * flInterval ;
UTIL_TraceHull ( vecPos , vecNewPos , vecHullMins , vecHullMaxs , iCollisionMask , pIgnoreEnt , iCollisionGroup , & tr ) ;
if ( bDrawArc )
{
debugoverlay - > AddLineOverlay ( vecPos , vecNewPos , 65 , 65 , 255 , true , 3.0f ) ;
}
if ( tr . fraction < 1.0f | | tr . startsolid )
break ;
vecPos = tr . endpos ;
}
return vecPos ;
}