//------------------------------------------------ // Spawn //------------------------------------------------ void CPropAPC::Spawn( void ) { BaseClass::Spawn(); SetBlocksLOS( true ); m_iHealth = m_iMaxHealth = sk_apc_health.GetFloat(); SetCycle( 0 ); m_iMachineGunBurstLeft = MACHINE_GUN_BURST_SIZE; m_iRocketSalvoLeft = ROCKET_SALVO_SIZE; m_nRocketSide = 0; m_lifeState = LIFE_ALIVE; m_bInFiringCone = false; m_flHandbrakeTime = gpGlobals->curtime + 0.1; m_bInitialHandbrake = false; // Reset the gun to a default pose. SetPoseParameter( "vehicle_weapon_pitch", 0 ); SetPoseParameter( "vehicle_weapon_yaw", 90 ); CreateAPCLaserDot(); if ( IsXbox() ) { AddFlag( FL_AIMTARGET ); } }
void PhysicsLevelInit( void ) { physenv = physics->CreateEnvironment(); assert( physenv ); #ifdef PORTAL physenv_main = physenv; #endif { MEM_ALLOC_CREDIT(); g_EntityCollisionHash = physics->CreateObjectPairHash(); } // TODO: need to get the right factory function here //physenv->SetDebugOverlay( appSystemFactory ); physenv->SetGravity( Vector(0, 0, -sv_gravity.GetFloat() ) ); // 15 ms per tick // NOTE: Always run client physics at this rate - helps keep ragdolls stable physenv->SetSimulationTimestep( IsXbox() ? DEFAULT_XBOX_CLIENT_VPHYSICS_TICK : DEFAULT_TICK_INTERVAL ); physenv->SetCollisionEventHandler( &g_Collisions ); physenv->SetCollisionSolver( &g_Collisions ); g_PhysWorldObject = PhysCreateWorld_Shared( GetClientWorldEntity(), modelinfo->GetVCollide(1), g_PhysDefaultObjectParams ); staticpropmgr->CreateVPhysicsRepresentations( physenv, &g_SolidSetup, NULL ); }
//----------------------------------------------------------------------------- // Purpose: Handle weapon impacts from the helicopter shooting (cheaper versions) //----------------------------------------------------------------------------- void ImpactHelicopterCallback( const CEffectData &data ) { VPROF_BUDGET( "ImpactHelicopterCallback", VPROF_BUDGETGROUP_PARTICLE_RENDERING ); trace_t tr; Vector vecOrigin, vecStart, vecShotDir; int iMaterial, iDamageType, iHitbox; short nSurfaceProp; C_BaseEntity *pEntity = ParseImpactData( data, &vecOrigin, &vecStart, &vecShotDir, nSurfaceProp, iMaterial, iDamageType, iHitbox ); if ( !pEntity ) { // This happens for impacts that occur on an object that's then destroyed. // Clear out the fraction so it uses the server's data tr.fraction = 1.0; PlayImpactSound( pEntity, tr, vecOrigin, nSurfaceProp ); return; } // If we hit, perform our custom effects and play the sound. Don't create decals if ( Impact( vecOrigin, vecStart, iMaterial, iDamageType, iHitbox, pEntity, tr, IMPACT_NODECAL | IMPACT_REPORT_RAGDOLL_IMPACTS ) ) { FX_AirboatGunImpact( vecOrigin, tr.plane.normal, IsXbox() ? 1 : 2 ); // Only do metal + computer custom effects if ( (iMaterial == CHAR_TEX_METAL) || (iMaterial == CHAR_TEX_COMPUTER) ) { PerformCustomEffects( vecOrigin, tr, vecShotDir, iMaterial, 1.0, FLAGS_CUSTIOM_EFFECTS_NOFLECKS ); } } PlayImpactSound( pEntity, tr, vecOrigin, nSurfaceProp ); }
CBaseHudChat::~CBaseHudChat() { if ( IsXbox() ) return; gameeventmanager->RemoveListener( this ); }
void CBaseShader::DrawElements( IMaterialVar **ppParams, int nModulationFlags, IShaderShadow* pShaderShadow, IShaderDynamicAPI* pShaderAPI ) { VPROF("CBaseShader::DrawElements"); // Re-entrancy check Assert( !s_ppParams ); s_ppParams = ppParams; s_pShaderAPI = pShaderAPI; s_pShaderShadow = pShaderShadow; s_nModulationFlags = nModulationFlags; s_pMeshBuilder = IsXbox() ? NULL : (pShaderAPI ? pShaderAPI->GetVertexModifyBuilder() : NULL); if ( IsSnapshotting() ) { // Set up the shadow state SetInitialShadowState( ); } OnDrawElements( ppParams, pShaderShadow, pShaderAPI ); s_nModulationFlags = 0; s_ppParams = NULL; s_pShaderAPI = NULL; s_pShaderShadow = NULL; s_pMeshBuilder = NULL; }
void CBaseHudChat::Init( void ) { if ( IsXbox() ) return; ListenForGameEvent( "hltv_chat" ); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CItem::Spawn( void ) { if ( g_pGameRules->IsAllowedToSpawn( this ) == false ) { UTIL_Remove( this ); return; } SetMoveType( MOVETYPE_FLYGRAVITY ); SetSolid( SOLID_BBOX ); SetBlocksLOS( false ); AddEFlags( EFL_NO_ROTORWASH_PUSH ); if( IsXbox() ) { AddEffects( EF_ITEM_BLINK ); } // This will make them not collide with the player, but will collide // against other items + weapons SetCollisionGroup( COLLISION_GROUP_WEAPON ); CollisionProp()->UseTriggerBounds( true, ITEM_PICKUP_BOX_BLOAT ); SetTouch(&CItem::ItemTouch); if ( CreateItemVPhysicsObject() == false ) return; m_takedamage = DAMAGE_EVENTS_ONLY; #if defined( HL2MP ) SetThink( &CItem::FallThink ); SetNextThink( gpGlobals->curtime + 0.1f ); #endif }
void AddSurfacepropFile( const char *pFileName, IPhysicsSurfaceProps *pProps, IFileSystem *pFileSystem ) { // Load file into memory FileHandle_t file = pFileSystem->Open( pFileName, "rb", "GAME" ); if ( file ) { int len = pFileSystem->Size( file ); // read the file int nBufSize = len+1; if ( IsXbox() ) { nBufSize = AlignValue( nBufSize , 512 ); } char *buffer = (char *)stackalloc( nBufSize ); pFileSystem->ReadEx( buffer, nBufSize, len, file ); pFileSystem->Close( file ); buffer[len] = 0; pProps->ParseSurfaceData( pFileName, buffer ); // buffer is on the stack, no need to free } else { Error( "Unable to load surface prop file '%s' (referenced by manifest file '%s')\n", pFileName, SURFACEPROP_MANIFEST_FILE ); } }
//----------------------------------------------------------------------------- // Compute fade amount //----------------------------------------------------------------------------- unsigned char UTIL_ComputeEntityFade( C_BaseEntity *pEntity, float flMinDist, float flMaxDist, float flFadeScale ) { unsigned char nAlpha = 255; // If we're taking devshots, don't fade props at all if ( g_MakingDevShots || cl_leveloverview.GetFloat() > 0 ) return 255; #ifdef _DEBUG if ( r_FadeProps.GetBool() ) #endif { nAlpha = ComputeDistanceFade( pEntity, flMinDist, flMaxDist ); // NOTE: This computation for the center + radius is invalid! // The center of the sphere is at the center of the OBB, which is not necessarily // at the render origin. But it should be close enough. Vector vecMins, vecMaxs; pEntity->GetRenderBounds( vecMins, vecMaxs ); float flRadius = vecMins.DistTo( vecMaxs ) * 0.5f; Vector vecAbsCenter; if ( modelinfo->GetModelType( pEntity->GetModel() ) == mod_brush ) { Vector vecRenderMins, vecRenderMaxs; pEntity->GetRenderBoundsWorldspace( vecRenderMins, vecRenderMaxs ); VectorAdd( vecRenderMins, vecRenderMaxs, vecAbsCenter ); vecAbsCenter *= 0.5f; } else { vecAbsCenter = pEntity->GetRenderOrigin(); } unsigned char nGlobalAlpha = IsXbox() ? 255 : modelinfo->ComputeLevelScreenFade( vecAbsCenter, flRadius, flFadeScale ); unsigned char nDistAlpha; if ( !engine->IsLevelMainMenuBackground() ) { nDistAlpha = modelinfo->ComputeViewScreenFade( vecAbsCenter, flRadius, flFadeScale ); } else { nDistAlpha = 255; } if ( nDistAlpha < nGlobalAlpha ) { nGlobalAlpha = nDistAlpha; } if ( nGlobalAlpha < nAlpha ) { nAlpha = nGlobalAlpha; } } return nAlpha; }
//----------------------------------------------------------------------------- // Purpose: // Input : id - // *tableName - // maxentries - //----------------------------------------------------------------------------- CNetworkStringTable::CNetworkStringTable( TABLEID id, const char *tableName, int maxentries, int userdatafixedsize, int userdatanetworkbits, bool bIsFilenames ) : m_bAllowClientSideAddString( false ), m_pItemsClientSide( NULL ) { m_id = id; int len = strlen( tableName ) + 1; m_pszTableName = new char[ len ]; assert( m_pszTableName ); assert( tableName ); Q_strncpy( m_pszTableName, tableName, len ); m_changeFunc = NULL; m_pObject = NULL; m_nTickCount = 0; m_pMirrorTable = NULL; m_nLastChangedTick = 0; m_bChangeHistoryEnabled = false; m_bLocked = false; m_nMaxEntries = maxentries; m_nEntryBits = Q_log2( m_nMaxEntries ); m_bUserDataFixedSize = userdatafixedsize != 0; m_nUserDataSize = userdatafixedsize; m_nUserDataSizeBits = userdatanetworkbits; if ( m_nUserDataSizeBits > CNetworkStringTableItem::MAX_USERDATA_BITS ) { Host_Error( "String tables user data bits restricted to %i bits, requested %i is too large\n", CNetworkStringTableItem::MAX_USERDATA_BITS, m_nUserDataSizeBits ); } if ( m_nUserDataSize > CNetworkStringTableItem::MAX_USERDATA_SIZE ) { Host_Error( "String tables user data size restricted to %i bytes, requested %i is too large\n", CNetworkStringTableItem::MAX_USERDATA_SIZE, m_nUserDataSize ); } // Make sure maxentries is power of 2 if ( ( 1 << m_nEntryBits ) != maxentries ) { Host_Error( "String tables must be powers of two in size!, %i is not a power of 2\n", maxentries ); } if ( IsXbox() || bIsFilenames ) { m_bIsFilenames = true; m_pItems = new CNetworkStringFilenameDict; } else { m_bIsFilenames = false; m_pItems = new CNetworkStringDict; } }
//----------------------------------------------------------------------------- //----------------------------------------------------------------------------- bool CPropAPC::ShouldAttractAutoAim( CBaseEntity *pAimingEnt ) { if( IsXbox() && pAimingEnt->IsPlayer() && GetDriver() ) { return true; } return BaseClass::ShouldAttractAutoAim( pAimingEnt ); }
//----------------------------------------------------------------------------- //----------------------------------------------------------------------------- Vector CPropAPC::BodyTarget( const Vector &posSrc, bool bNoisy ) { if ( IsXbox() ) { return WorldSpaceCenter(); } return BaseClass::BodyTarget( posSrc, bNoisy ); }
void PrecacheFileWeaponInfoDatabase( IFileSystem *filesystem, const unsigned char *pICEKey ) { if ( m_WeaponInfoDatabase.Count() ) return; #if !defined( _XBOX ) FileFindHandle_t findHandle; const char *pFilename = filesystem->FindFirstEx( "scripts/weapon_*.txt", IsXbox() ? "XGAME" : "GAME", &findHandle ); while ( pFilename != NULL ) { char fileBase[512]; Q_FileBase( pFilename, fileBase, sizeof(fileBase) ); WEAPON_FILE_INFO_HANDLE tmp; #ifdef CLIENT_DLL if ( ReadWeaponDataFromFileForSlot( filesystem, fileBase, &tmp, pICEKey ) ) { gWR.LoadWeaponSprites( tmp ); } #else ReadWeaponDataFromFileForSlot( filesystem, fileBase, &tmp, pICEKey ); #endif pFilename = filesystem->FindNext( findHandle ); } filesystem->FindClose( findHandle ); #else #define WEAPON_SCRIPT_MANIFEST_FILE "scripts/_weapon_manifest.txt" // Use a manifest file on the xbox KeyValues *manifest = new KeyValues( "weaponscripts" ); if ( manifest->LoadFromFile( filesystem, WEAPON_SCRIPT_MANIFEST_FILE, "XGAME" ) ) { for ( KeyValues *sub = manifest->GetFirstSubKey(); sub != NULL ; sub = sub->GetNextKey() ) { if ( !Q_stricmp( sub->GetName(), "file" ) ) { char fileBase[512]; Q_FileBase( sub->GetString(), fileBase, sizeof(fileBase) ); WEAPON_FILE_INFO_HANDLE tmp; #ifdef CLIENT_DLL if ( ReadWeaponDataFromFileForSlot( filesystem, fileBase, &tmp, pICEKey ) ) { gWR.LoadWeaponSprites( tmp ); } #else ReadWeaponDataFromFileForSlot( filesystem, fileBase, &tmp, pICEKey ); #endif } else { Error( "Expecting 'file', got %s\n", sub->GetName() ); } } } manifest->deleteThis(); #endif }
void C_AR2Explosion::RenderParticles( CParticleRenderIterator *pIterator ) { const AR2ExplosionParticle *pParticle = (const AR2ExplosionParticle *)pIterator->GetFirst(); while ( pParticle ) { float sortKey = 0; if ( pParticle->m_Lifetime >= 0.0f ) { // Draw. float lifetimePercent = ( pParticle->m_Lifetime - AR2_DUST_FADE_IN_TIME ) / pParticle->m_Dwell; // FIXME: base color should be a dirty version of the material color Vector color = g_AR2DustColor1 * (1.0 - lifetimePercent) + g_AR2DustColor2 * lifetimePercent; Vector tPos; TransformParticle(m_pParticleMgr->GetModelView(), pParticle->m_Pos, tPos); sortKey = tPos.z; float alpha; if ( pParticle->m_Lifetime < AR2_DUST_FADE_IN_TIME ) { alpha = AR2_DUST_ALPHA * ( pParticle->m_Lifetime / AR2_DUST_FADE_IN_TIME ); } else { alpha = AR2_DUST_ALPHA * ( 1.0f - lifetimePercent ); } alpha *= GetAlphaDistanceFade( tPos, IsXbox() ? 100 : 50, IsXbox() ? 200 : 150 ); RenderParticle_ColorSizeAngle( pIterator->GetParticleDraw(), tPos, color, alpha, pParticle->m_Dist, // size based on how far it's traveled pParticle->m_Roll); } pParticle = (const AR2ExplosionParticle *)pIterator->GetNext( sortKey ); } }
void CBaseHudChat::Init( void ) { if ( IsXbox() ) return; CreateChatInputLine(); CreateChatLines(); gameeventmanager->AddListener( this, "hltv_chat", false ); }
void TerrainMod_Add( TerrainModType type, const CTerrainModParams ¶ms ) { if ( IsXbox() ) { return; } // Move players out of the way so they don't get stuck on the terrain. float playerStartHeights[MAX_PLAYERS]; int i; int nPlayers = MIN( MAX_PLAYERS, gpGlobals->maxClients ); for( i=0; i < nPlayers; i++ ) { CBasePlayer *pPlayer = UTIL_PlayerByIndex( i+1 ); if( !pPlayer ) continue; playerStartHeights[i] = pPlayer->GetAbsOrigin().z; // Cast a ray upwards to see if we can move the player out of the way. trace_t trace; UTIL_TraceEntity( pPlayer, pPlayer->GetAbsOrigin(), pPlayer->GetAbsOrigin() + Vector( 0, 0, params.m_flRadius*2 ), MASK_SOLID, &trace ); pPlayer->SetLocalOrigin( trace.endpos ); } // Apply the mod. engine->ApplyTerrainMod( type, params ); // Move players back down. for( i=0; i < nPlayers; i++ ) { CBasePlayer *pPlayer = UTIL_PlayerByIndex( i+1 ); if( !pPlayer ) continue; // Cast a ray upwards to see if we can move the player out of the way. trace_t trace; UTIL_TraceEntity( pPlayer, pPlayer->GetAbsOrigin(), Vector( pPlayer->GetAbsOrigin().x, pPlayer->GetAbsOrigin().y, playerStartHeights[i] ), MASK_SOLID, &trace ); pPlayer->SetLocalOrigin( trace.endpos ); } }
//--------------------------------------------------------- //--------------------------------------------------------- void CRumbleEffects::UpdateEffects( float curtime ) { float fLeftMotor = 0.0f; float fRightMotor = 0.0f; for( int i = 0 ; i < MAX_RUMBLE_CHANNELS ; i++ ) { // Expire old channels RumbleChannel_t *pChannel = & m_Channels[i]; if( pChannel->in_use ) { float left, right; ComputeAmplitudes( pChannel, curtime, &left, &right ); fLeftMotor += left; fRightMotor += right; } } // Add in any screenshake float shakeLeft = 0.0f; float shakeRight = 0.0f; if( m_flScreenShake != 0.0f ) { if( m_flScreenShake < 0.0f ) { shakeLeft = fabs( m_flScreenShake ); } else { shakeRight = m_flScreenShake; } } fLeftMotor += shakeLeft; fRightMotor += shakeRight; fLeftMotor *= cl_rumblescale.GetFloat(); fRightMotor *= cl_rumblescale.GetFloat(); if( engine->IsPaused() ) { // Send nothing when paused. fLeftMotor = 0.0f; fRightMotor = 0.0f; } if ( IsXbox() ) { inputsystem->SetRumble( fLeftMotor, fRightMotor ); } }
//----------------------------------------------------------------------------- // Purpose: Must be facing toward ladder // Input : *ladder - // Output : Returns true on success, false on failure. //----------------------------------------------------------------------------- bool CHL2GameMovement::LookingAtLadder( CFuncLadder *ladder ) { if ( !ladder ) { return false; } // Get ladder end points Vector top, bottom; ladder->GetTopPosition( top ); ladder->GetBottomPosition( bottom ); // Find closest point on ladder to player (could be an endpoint) Vector closest; CalcClosestPointOnLineSegment( mv->m_vecAbsOrigin, bottom, top, closest, NULL ); // Flatten our view direction to 2D Vector flatForward = m_vecForward; flatForward.z = 0.0f; // Because the ladder itself is not a solid, the player's origin may actually be // permitted to pass it, and that will screw up our dot product. // So back up the player's origin a bit to do the facing calculation. Vector vecAdjustedOrigin = mv->m_vecAbsOrigin - 8.0f * flatForward; // Figure out vector from player to closest point on ladder Vector vecToLadder = closest - vecAdjustedOrigin; // Flatten it to 2D Vector flatLadder = vecToLadder; flatLadder.z = 0.0f; // Normalize the vectors (unnecessary) VectorNormalize( flatLadder ); VectorNormalize( flatForward ); // Compute dot product to see if forward is in same direction as vec to ladder float facingDot = flatForward.Dot( flatLadder ); float requiredDot = ( IsXbox() ) ? 0.5 : 0.0; // Facing same direction if dot > = requiredDot... bool facingladder = ( facingDot >= requiredDot ); return facingladder; }
virtual void Init() { // //CASW_VGUI_Debug_Panel *pDebugPanel = new CASW_VGUI_Debug_Panel( GetViewport(), "ASW Debug Panel" ); //g_hDebugPanel = pDebugPanel; // Skip over BaseClass!!! BaseClass::BaseClass::Init(); // Load up the combine control panel scheme if ( !g_hVGuiCombineScheme ) { g_hVGuiCombineScheme = vgui::scheme()->LoadSchemeFromFileEx( enginevgui->GetPanel( PANEL_CLIENTDLL ), IsXbox() ? "resource/ClientScheme.res" : "resource/CombinePanelScheme.res", "CombineScheme" ); if (!g_hVGuiCombineScheme) { Warning( "Couldn't load combine panel scheme!\n" ); } } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void ClientModeHLNormal::Init() { BaseClass::Init(); // Load up the combine control panel scheme g_hVGuiCombineScheme = vgui::scheme()->LoadSchemeFromFileEx( enginevgui->GetPanel( PANEL_CLIENTDLL ), IsXbox() ? "resource/ClientScheme.res" : "resource/CombinePanelScheme.res", "CombineScheme" ); if (!g_hVGuiCombineScheme) { Warning( "Couldn't load combine panel scheme!\n" ); } }
//----------------------------------------------------------------------------- // Purpose: Advanced joystick setup //----------------------------------------------------------------------------- void CInput::Joystick_Advanced(void) { // called whenever an update is needed int i; DWORD dwTemp; if ( IsXbox() ) { // Xbox always uses a joystick in_joystick.SetValue( 1 ); } // Initialize all the maps for ( i = 0; i < MAX_JOYSTICK_AXES; i++ ) { m_rgAxes[i].AxisMap = GAME_AXIS_NONE; m_rgAxes[i].ControlMap = JOY_ABSOLUTE_AXIS; } if ( !joy_advanced.GetBool() ) { // default joystick initialization // 2 axes only with joystick control m_rgAxes[JOY_AXIS_X].AxisMap = GAME_AXIS_YAW; m_rgAxes[JOY_AXIS_Y].AxisMap = GAME_AXIS_FORWARD; } else { if ( Q_stricmp( joy_name.GetString(), "joystick") != 0 ) { // notify user of advanced controller Msg( "Using joystick '%s' configuration\n", joy_name.GetString() ); } // advanced initialization here // data supplied by user via joy_axisn cvars dwTemp = (DWORD)joy_advaxisx.GetInt(); m_rgAxes[JOY_AXIS_X].AxisMap = dwTemp & 0x0000000f; m_rgAxes[JOY_AXIS_X].ControlMap = dwTemp & JOY_RELATIVE_AXIS; DescribeJoystickAxis( "JOY_AXIS_X", &m_rgAxes[JOY_AXIS_X] ); dwTemp = (DWORD)joy_advaxisy.GetInt(); m_rgAxes[JOY_AXIS_Y].AxisMap = dwTemp & 0x0000000f; m_rgAxes[JOY_AXIS_Y].ControlMap = dwTemp & JOY_RELATIVE_AXIS; DescribeJoystickAxis( "JOY_AXIS_Y", &m_rgAxes[JOY_AXIS_Y] ); dwTemp = (DWORD)joy_advaxisz.GetInt(); m_rgAxes[JOY_AXIS_Z].AxisMap = dwTemp & 0x0000000f; m_rgAxes[JOY_AXIS_Z].ControlMap = dwTemp & JOY_RELATIVE_AXIS; DescribeJoystickAxis( "JOY_AXIS_Z", &m_rgAxes[JOY_AXIS_Z] ); dwTemp = (DWORD)joy_advaxisr.GetInt(); m_rgAxes[JOY_AXIS_R].AxisMap = dwTemp & 0x0000000f; m_rgAxes[JOY_AXIS_R].ControlMap = dwTemp & JOY_RELATIVE_AXIS; DescribeJoystickAxis( "JOY_AXIS_R", &m_rgAxes[JOY_AXIS_R] ); dwTemp = (DWORD)joy_advaxisu.GetInt(); m_rgAxes[JOY_AXIS_U].AxisMap = dwTemp & 0x0000000f; m_rgAxes[JOY_AXIS_U].ControlMap = dwTemp & JOY_RELATIVE_AXIS; DescribeJoystickAxis( "JOY_AXIS_U", &m_rgAxes[JOY_AXIS_U] ); dwTemp = (DWORD)joy_advaxisv.GetInt(); m_rgAxes[JOY_AXIS_V].AxisMap = dwTemp & 0x0000000f; m_rgAxes[JOY_AXIS_V].ControlMap = dwTemp & JOY_RELATIVE_AXIS; DescribeJoystickAxis( "JOY_AXIS_V", &m_rgAxes[JOY_AXIS_V] ); Msg( "Advanced Joystick settings initialized\n" ); } }
//----------------------------------------------------------------------------- // Purpose: // Input : bOnLadder - //----------------------------------------------------------------------------- void CHL2GameMovement::FullLadderMove() { #if !defined( CLIENT_DLL ) CFuncLadder *ladder = GetLadder(); Assert( ladder ); if ( !ladder ) { return; } CheckWater(); // Was jump button pressed? If so, don't do anything here if ( mv->m_nButtons & IN_JUMP ) { CheckJumpButton(); return; } else { mv->m_nOldButtons &= ~IN_JUMP; } player->SetGroundEntity( NULL ); // Remember old positions in case we cancel this movement Vector oldVelocity = mv->m_vecVelocity; Vector oldOrigin = mv->m_vecAbsOrigin; Vector topPosition; Vector bottomPosition; ladder->GetTopPosition( topPosition ); ladder->GetBottomPosition( bottomPosition ); // Compute parametric distance along ladder vector... float oldt; CalcDistanceSqrToLine( mv->m_vecAbsOrigin, topPosition, bottomPosition, &oldt ); // Perform the move accounting for any base velocity. VectorAdd (mv->m_vecVelocity, player->GetBaseVelocity(), mv->m_vecVelocity); TryPlayerMove(); VectorSubtract (mv->m_vecVelocity, player->GetBaseVelocity(), mv->m_vecVelocity); // Pressed buttons are "changed(xor)" and'ed with the mask of currently held buttons int buttonsChanged = ( mv->m_nOldButtons ^ mv->m_nButtons ); // These buttons have changed this frame int buttonsPressed = buttonsChanged & mv->m_nButtons; bool pressed_use = ( buttonsPressed & IN_USE ) ? true : false; bool pressing_forward_or_side = mv->m_flForwardMove != 0.0f || mv->m_flSideMove != 0.0f; Vector ladderVec = topPosition - bottomPosition; float LadderLength = VectorNormalize( ladderVec ); // This test is not perfect by any means, but should help a bit bool moving_along_ladder = false; if ( pressing_forward_or_side ) { float fwdDot = m_vecForward.Dot( ladderVec ); if ( fabs( fwdDot ) > 0.9f ) { moving_along_ladder = true; } } // Compute parametric distance along ladder vector... float newt; CalcDistanceSqrToLine( mv->m_vecAbsOrigin, topPosition, bottomPosition, &newt ); // Fudge of 2 units float tolerance = 1.0f / LadderLength; bool wouldleaveladder = false; // Moving pPast top or bottom? if ( newt < -tolerance ) { wouldleaveladder = newt < oldt; } else if ( newt > ( 1.0f + tolerance ) ) { wouldleaveladder = newt > oldt; } // See if we are near the top or bottom but not moving float dist1sqr, dist2sqr; dist1sqr = ( topPosition - mv->m_vecAbsOrigin ).LengthSqr(); dist2sqr = ( bottomPosition - mv->m_vecAbsOrigin ).LengthSqr(); float dist = MIN( dist1sqr, dist2sqr ); bool neardismountnode = ( dist < 16.0f * 16.0f ) ? true : false; float ladderUnitsPerTick = ( MAX_CLIMB_SPEED * gpGlobals->interval_per_tick ); bool neardismountnode2 = ( dist < ladderUnitsPerTick * ladderUnitsPerTick ) ? true : false; // Really close to node, cvar is set, and pressing a key, then simulate a +USE bool auto_dismount_use = ( neardismountnode2 && sv_autoladderdismount.GetBool() && pressing_forward_or_side && !moving_along_ladder ); bool fully_underwater = ( player->GetWaterLevel() == WL_Eyes ) ? true : false; // If the user manually pressed use or we're simulating it, then use_dismount will occur bool use_dismount = pressed_use || auto_dismount_use; if ( fully_underwater && !use_dismount ) { // If fully underwater, we require looking directly at a dismount node /// to "float off" a ladder mid way... if ( ExitLadderViaDismountNode( ladder, true ) ) { // See if they +used a dismount point mid-span.. return; } } // If the movement would leave the ladder and they're not automated or pressing use, disallow the movement if ( !use_dismount ) { if ( wouldleaveladder ) { // Don't let them leave the ladder if they were on it mv->m_vecVelocity = oldVelocity; mv->m_vecAbsOrigin = oldOrigin; } return; } // If the move would not leave the ladder and we're near close to the end, then just accept the move if ( !wouldleaveladder && !neardismountnode ) { // Otherwise, if the move would leave the ladder, disallow it. if ( pressed_use ) { if ( ExitLadderViaDismountNode( ladder, false, IsXbox() ) ) { // See if they +used a dismount point mid-span.. return; } player->SetMoveType( MOVETYPE_WALK ); player->SetMoveCollide( MOVECOLLIDE_DEFAULT ); SetLadder( NULL ); GetHL2Player()->m_bPlayUseDenySound = false; // Dismount with a bit of velocity in facing direction VectorScale( m_vecForward, USE_DISMOUNT_SPEED, mv->m_vecVelocity ); mv->m_vecVelocity.z = 50; } return; } // Debounce the use key if ( pressed_use ) { SwallowUseKey(); } // Try auto exit, if possible if ( ExitLadderViaDismountNode( ladder, false, pressed_use ) ) { return; } if ( wouldleaveladder ) { // Otherwise, if the move would leave the ladder, disallow it. if ( pressed_use ) { player->SetMoveType( MOVETYPE_WALK ); player->SetMoveCollide( MOVECOLLIDE_DEFAULT ); SetLadder( NULL ); // Dismount with a bit of velocity in facing direction VectorScale( m_vecForward, USE_DISMOUNT_SPEED, mv->m_vecVelocity ); mv->m_vecVelocity.z = 50; } else { mv->m_vecVelocity = oldVelocity; mv->m_vecAbsOrigin = oldOrigin; } } #endif }
#include "c_basehlplayer.h" #define CHL2_Player C_BaseHLPlayer #else #include "hl2_player.h" #endif // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" static ConVar sv_autoladderdismount( "sv_autoladderdismount", "1", FCVAR_REPLICATED, "Automatically dismount from ladders when you reach the end (don't have to +USE)." ); static ConVar sv_ladderautomountdot( "sv_ladderautomountdot", "0.4", FCVAR_REPLICATED, "When auto-mounting a ladder by looking up its axis, this is the tolerance for looking now directly along the ladder axis." ); static ConVar xc_newladders( "xc_newladders", IsXbox() ? "1" : "0", FCVAR_REPLICATED, "Stick forward is ALWAYS up, stick back is ALWAYS down" ); class CReservePlayerSpot; #define USE_DISMOUNT_SPEED 100 struct NearbyDismount_t { CInfoLadderDismount *dismount; float distSqr; }; //----------------------------------------------------------------------------- // Purpose: HL2 specific movement code //----------------------------------------------------------------------------- class CHL2GameMovement : public CGameMovement
//----------------------------------------------------------------------------- // Purpose: Apply joystick to CUserCmd creation // Input : frametime - // *cmd - //----------------------------------------------------------------------------- void CInput::JoyStickMove( float frametime, CUserCmd *cmd ) { // complete initialization if first time in ( needed as cvars are not available at initialization time ) if ( !m_fJoystickAdvancedInit ) { Joystick_Advanced(); m_fJoystickAdvancedInit = true; } // verify joystick is available and that the user wants to use it if ( !in_joystick.GetInt() || 0 == inputsystem->GetJoystickCount() ) { return; } QAngle viewangles; // Get starting angles engine->GetViewAngles( viewangles ); struct axis_t { float value; int controlType; }; axis_t gameAxes[ MAX_GAME_AXES ]; memset( &gameAxes, 0, sizeof(gameAxes) ); // Get each joystick axis value, and normalize the range for ( int i = 0; i < MAX_JOYSTICK_AXES; ++i ) { if ( GAME_AXIS_NONE == m_rgAxes[i].AxisMap ) continue; float fAxisValue = inputsystem->GetAnalogValue( (AnalogCode_t)JOYSTICK_AXIS( 0, i ) ); if (joy_wwhack2.GetInt() != 0 ) { // this is a special formula for the Logitech WingMan Warrior // y=ax^b; where a = 300 and b = 1.3 // also x values are in increments of 800 (so this is factored out) // then bounds check result to level out excessively high spin rates float fTemp = 300.0 * pow(abs(fAxisValue) / 800.0, 1.3); if (fTemp > 14000.0) fTemp = 14000.0; // restore direction information fAxisValue = (fAxisValue > 0.0) ? fTemp : -fTemp; } unsigned int idx = m_rgAxes[i].AxisMap; gameAxes[idx].value = fAxisValue; gameAxes[idx].controlType = m_rgAxes[i].ControlMap; } // Re-map the axis values if necessary, based on the joystick configuration if ( (joy_advanced.GetInt() == 0) && (in_jlook.state & 1) ) { // user wants forward control to become pitch control gameAxes[GAME_AXIS_PITCH] = gameAxes[GAME_AXIS_FORWARD]; gameAxes[GAME_AXIS_FORWARD].value = 0; // if mouse invert is on, invert the joystick pitch value // Note: only absolute control support here - joy_advanced = 0 if ( m_pitch.GetFloat() < 0.0 ) { gameAxes[GAME_AXIS_PITCH].value *= -1; } } if ( (in_strafe.state & 1) || lookstrafe.GetFloat() && (in_jlook.state & 1) ) { // user wants yaw control to become side control gameAxes[GAME_AXIS_SIDE] = gameAxes[GAME_AXIS_YAW]; gameAxes[GAME_AXIS_YAW].value = 0; } float forward = ScaleAxisValue( gameAxes[GAME_AXIS_FORWARD].value, MAX_BUTTONSAMPLE * joy_forwardthreshold.GetFloat() ); float side = ScaleAxisValue( gameAxes[GAME_AXIS_SIDE].value, MAX_BUTTONSAMPLE * joy_sidethreshold.GetFloat() ); float pitch = ScaleAxisValue( gameAxes[GAME_AXIS_PITCH].value, MAX_BUTTONSAMPLE * joy_pitchthreshold.GetFloat() ); float yaw = ScaleAxisValue( gameAxes[GAME_AXIS_YAW].value, MAX_BUTTONSAMPLE * joy_yawthreshold.GetFloat() ); float joySideMove = 0.f; float joyForwardMove = 0.f; float aspeed = frametime * gHUD.GetFOVSensitivityAdjust(); // apply forward and side control joyForwardMove += ResponseCurve( joy_response_move.GetInt(), forward ) * joy_forwardsensitivity.GetFloat() * cl_forwardspeed.GetFloat(); joySideMove += ResponseCurve( joy_response_move.GetInt(), side ) * joy_sidesensitivity.GetFloat() * cl_sidespeed.GetFloat(); Vector2D move( yaw, pitch ); float dist = move.Length(); // apply turn control float angle = 0.f; if ( JOY_ABSOLUTE_AXIS == gameAxes[GAME_AXIS_YAW].controlType ) { float fAxisValue = ResponseCurveLook( joy_response_look.GetInt(), yaw, YAW, pitch, dist ); angle = fAxisValue * joy_yawsensitivity.GetFloat() * aspeed * cl_yawspeed.GetFloat(); } else { angle = yaw * joy_yawsensitivity.GetFloat() * aspeed * 180.0; } viewangles[YAW] += angle; cmd->mousedx = angle; // apply look control if ( IsXbox() || in_jlook.state & 1 ) { float angle = 0; if ( JOY_ABSOLUTE_AXIS == gameAxes[GAME_AXIS_PITCH].controlType ) { float fAxisValue = ResponseCurveLook( joy_response_look.GetInt(), pitch, PITCH, yaw, dist ); angle = fAxisValue * joy_pitchsensitivity.GetFloat() * aspeed * cl_pitchspeed.GetFloat(); } else { angle = pitch * joy_pitchsensitivity.GetFloat() * aspeed * 180.0; } viewangles[PITCH] += angle; cmd->mousedy = angle; view->StopPitchDrift(); if( pitch == 0.f && lookspring.GetFloat() == 0.f ) { // no pitch movement // disable pitch return-to-center unless requested by user // *** this code can be removed when the lookspring bug is fixed // *** the bug always has the lookspring feature on view->StopPitchDrift(); } } cmd->forwardmove += joyForwardMove; cmd->sidemove += joySideMove; if ( IsPC() ) { if ( FloatMakePositive(joyForwardMove) >= joy_autosprint.GetFloat() || FloatMakePositive(joySideMove) >= joy_autosprint.GetFloat() ) { KeyDown( &in_joyspeed, true ); } else { KeyUp( &in_joyspeed, true ); } } // Bound pitch viewangles[PITCH] = clamp( viewangles[ PITCH ], -cl_pitchup.GetFloat(), cl_pitchdown.GetFloat() ); engine->SetViewAngles( viewangles ); }
//----------------------------------------------------------------------------- // Purpose: // Input : &origin - // &normal - // scale - // *pColor - //----------------------------------------------------------------------------- void FX_GunshotSlimeSplash( const Vector &origin, const Vector &normal, float scale ) { if ( cl_show_splashes.GetBool() == false ) return; VPROF_BUDGET( "FX_GunshotSlimeSplash", VPROF_BUDGETGROUP_PARTICLE_RENDERING ); float colorRamp; float flScale = MIN( 1.0f, scale / 8.0f ); PMaterialHandle hMaterial = ParticleMgr()->GetPMaterial( "effects/slime1" ); PMaterialHandle hMaterial2 = ParticleMgr()->GetPMaterial( "effects/splash4" ); Vector color; float luminosity; // Get our lighting information FX_GetSplashLighting( origin + ( normal * scale ), &color, &luminosity ); Vector offDir; Vector offset; TrailParticle *tParticle; CSmartPtr<CTrailParticles> sparkEmitter = CTrailParticles::Create( "splash" ); if ( !sparkEmitter ) return; sparkEmitter->SetSortOrigin( origin ); sparkEmitter->m_ParticleCollision.SetGravity( 800.0f ); sparkEmitter->SetFlag( bitsPARTICLE_TRAIL_VELOCITY_DAMPEN ); sparkEmitter->SetVelocityDampen( 2.0f ); if ( IsXbox() ) { sparkEmitter->GetBinding().SetBBox( origin - Vector( 32, 32, 64 ), origin + Vector( 32, 32, 64 ) ); } //Dump out drops for ( int i = 0; i < 24; i++ ) { offset = origin; offset[0] += random->RandomFloat( -16.0f, 16.0f ) * flScale; offset[1] += random->RandomFloat( -16.0f, 16.0f ) * flScale; tParticle = (TrailParticle *) sparkEmitter->AddParticle( sizeof(TrailParticle), hMaterial, offset ); if ( tParticle == NULL ) break; tParticle->m_flLifetime = 0.0f; tParticle->m_flDieTime = random->RandomFloat( 0.25f, 0.5f ); offDir = normal + RandomVector( -0.6f, 0.6f ); tParticle->m_vecVelocity = offDir * random->RandomFloat( SPLASH_MIN_SPEED * flScale * 3.0f, SPLASH_MAX_SPEED * flScale * 3.0f ); tParticle->m_vecVelocity[2] += random->RandomFloat( 32.0f, 64.0f ) * flScale; tParticle->m_flWidth = random->RandomFloat( 3.0f, 6.0f ) * flScale; tParticle->m_flLength = random->RandomFloat( 0.025f, 0.05f ) * flScale; colorRamp = random->RandomFloat( 0.75f, 1.25f ); tParticle->m_color.r = MIN( 1.0f, color.x * colorRamp ) * 255; tParticle->m_color.g = MIN( 1.0f, color.y * colorRamp ) * 255; tParticle->m_color.b = MIN( 1.0f, color.z * colorRamp ) * 255; tParticle->m_color.a = 255 * luminosity; } // Setup splash emitter CSmartPtr<CSplashParticle> pSimple = CSplashParticle::Create( "splish" ); pSimple->SetSortOrigin( origin ); pSimple->SetClipHeight( origin.z ); pSimple->SetParticleCullRadius( scale * 2.0f ); if ( IsXbox() ) { pSimple->GetBinding().SetBBox( origin - Vector( 32, 32, 64 ), origin + Vector( 32, 32, 64 ) ); } SimpleParticle *pParticle; // Tint colorRamp = random->RandomFloat( 0.75f, 1.0f ); color = Vector( 1.0f, 0.8f, 0.0f ) * color * colorRamp; //Main gout for ( int i = 0; i < 8; i++ ) { pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), hMaterial2, origin ); if ( pParticle == NULL ) break; pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = 2.0f; //NOTENOTE: We use a clip plane to realistically control our lifespan pParticle->m_vecVelocity.Random( -0.2f, 0.2f ); pParticle->m_vecVelocity += ( normal * random->RandomFloat( 4.0f, 6.0f ) ); VectorNormalize( pParticle->m_vecVelocity ); pParticle->m_vecVelocity *= 50 * flScale * (8-i); colorRamp = random->RandomFloat( 0.75f, 1.25f ); pParticle->m_uchColor[0] = MIN( 1.0f, color[0] * colorRamp ) * 255.0f; pParticle->m_uchColor[1] = MIN( 1.0f, color[1] * colorRamp ) * 255.0f; pParticle->m_uchColor[2] = MIN( 1.0f, color[2] * colorRamp ) * 255.0f; pParticle->m_uchStartSize = 24 * flScale * RemapValClamped( i, 7, 0, 1, 0.5f ); pParticle->m_uchEndSize = MIN( 255, pParticle->m_uchStartSize * 2 ); pParticle->m_uchStartAlpha = RemapValClamped( i, 7, 0, 255, 32 ) * luminosity; pParticle->m_uchEndAlpha = 0; pParticle->m_flRoll = random->RandomInt( 0, 360 ); pParticle->m_flRollDelta = random->RandomFloat( -4.0f, 4.0f ); } //Play a sound CLocalPlayerFilter filter; EmitSound_t ep; ep.m_nChannel = CHAN_VOICE; ep.m_pSoundName = "Physics.WaterSplash"; ep.m_flVolume = 1.0f; ep.m_SoundLevel = SNDLVL_NORM; ep.m_pOrigin = &origin; C_BaseEntity::EmitSound( filter, SOUND_FROM_WORLD, ep ); }
virtual void Init() { CreateInterfaceFn gameUIFactory = g_GameUI.GetFactory(); if ( gameUIFactory ) { IGameUI *pGameUI = (IGameUI *) gameUIFactory(GAMEUI_INTERFACE_VERSION, NULL ); if ( NULL != pGameUI ) { // insert stats summary panel as the loading background dialog CSDK_Loading_Panel *pPanel = GSDKLoadingPanel(); pPanel->InvalidateLayout( false, true ); pPanel->SetVisible( false ); pPanel->MakePopup( false ); pGameUI->SetLoadingBackgroundDialog( pPanel->GetVPanel() ); #if 0 // add ASI logo to main menu CSDK_Logo_Panel *pLogo = new CSDK_Logo_Panel( NULL, "ASILogo" ); vgui::VPANEL GameUIRoot = enginevgui->GetPanel( PANEL_GAMEUIDLL ); pLogo->SetParent( GameUIRoot ); g_hLogoPanel = pLogo; #endif // 0 } } // //CASW_VGUI_Debug_Panel *pDebugPanel = new CASW_VGUI_Debug_Panel( GetViewport(), "ASW Debug Panel" ); //g_hDebugPanel = pDebugPanel; // Skip over BaseClass!!! BaseClass::BaseClass::Init(); // Load up the combine control panel scheme if ( !g_hVGuiCombineScheme ) { g_hVGuiCombineScheme = vgui::scheme()->LoadSchemeFromFileEx( enginevgui->GetPanel( PANEL_CLIENTDLL ), IsXbox() ? "resource/ClientScheme.res" : "resource/CombinePanelScheme.res", "CombineScheme" ); if (!g_hVGuiCombineScheme) { Warning( "Couldn't load combine panel scheme!\n" ); } } }
//==================================================================== //==================================================================== void InClientModeFullscreen::Init() { CreateInterfaceFn gameUIFactory = g_GameUI.GetFactory(); if ( gameUIFactory ) { IGameUI *pGameUI = (IGameUI *) gameUIFactory(GAMEUI_INTERFACE_VERSION, NULL ); // Se ha cargado la librería con éxito if ( pGameUI ) { // TODO! //pGameUI->SetLoadingBackgroundDialog( pPanel->GetVPanel() ); } } // Skip over BaseClass!!! BaseClass::Init(); // Load up the combine control panel scheme if ( !g_hVGuiCombineScheme ) { g_hVGuiCombineScheme = vgui::scheme()->LoadSchemeFromFileEx( enginevgui->GetPanel( PANEL_CLIENTDLL ), IsXbox() ? "resource/ClientScheme.res" : "resource/CombinePanelScheme.res", "CombineScheme" ); if ( !g_hVGuiCombineScheme ) { Warning( "Couldn't load combine panel scheme!\n" ); } } }
//----------------------------------------------------------------------------- // Airboat muzzle flashes //----------------------------------------------------------------------------- void MuzzleFlash_Airboat( ClientEntityHandle_t hEntity, int attachmentIndex ) { VPROF_BUDGET( "MuzzleFlash_Airboat", VPROF_BUDGETGROUP_PARTICLE_RENDERING ); CSmartPtr<CLocalSpaceEmitter> pSimple = CLocalSpaceEmitter::Create( "MuzzleFlash", hEntity, attachmentIndex ); SimpleParticle *pParticle; Vector forward(1,0,0), offset; //NOTENOTE: All coords are in local space float flScale = random->RandomFloat( 0.75f, IsXbox() ? 2.0f : 2.5f ); PMaterialHandle pMuzzle[2]; pMuzzle[0] = pSimple->GetPMaterial( "effects/combinemuzzle1" ); pMuzzle[1] = pSimple->GetPMaterial( "effects/combinemuzzle2" ); // Flash for ( int i = 1; i < 7; i++ ) { offset = (forward * (i*6.0f*flScale)); pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), pMuzzle[random->RandomInt(0,1)], offset ); if ( pParticle == NULL ) return; pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = IsXbox() ? 0.0001f : 0.01f; pParticle->m_vecVelocity.Init(); pParticle->m_uchColor[0] = 255; pParticle->m_uchColor[1] = 255; pParticle->m_uchColor[2] = 255; pParticle->m_uchStartAlpha = 255; pParticle->m_uchEndAlpha = 128; pParticle->m_uchStartSize = ( (random->RandomFloat( 6.0f, 8.0f ) * (9-(i))/7) * flScale ); pParticle->m_uchEndSize = pParticle->m_uchStartSize; pParticle->m_flRoll = random->RandomInt( 0, 360 ); pParticle->m_flRollDelta = 0.0f; } // Tack on the smoke pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), pSimple->GetPMaterial( "sprites/ar2_muzzle1" ), vec3_origin ); if ( pParticle == NULL ) return; pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = 0.05f; pParticle->m_vecVelocity.Init(); pParticle->m_uchColor[0] = 255; pParticle->m_uchColor[1] = 255; pParticle->m_uchColor[2] = 255; pParticle->m_uchStartAlpha = 255; pParticle->m_uchEndAlpha = 128; pParticle->m_uchStartSize = random->RandomFloat( 16.0f, 24.0f ); pParticle->m_uchEndSize = pParticle->m_uchStartSize; float spokePos = random->RandomInt( 0, 5 ); pParticle->m_flRoll = (360.0/6.0f)*spokePos; pParticle->m_flRollDelta = 0.0f; // Grab the origin out of the transform for the attachment if ( muzzleflash_light.GetInt() ) { // If the client hasn't seen this entity yet, bail. matrix3x4_t matAttachment; if ( FX_GetAttachmentTransform( hEntity, attachmentIndex, matAttachment ) ) { Vector origin; MatrixGetColumn( matAttachment, 3, &origin ); CreateMuzzleflashELight( origin, 5, 64, 128, hEntity ); } } }
void CGrenadeAR2::Spawn( void ) { Precache( ); SetSolid( SOLID_BBOX ); SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE ); // Hits everything but debris SetCollisionGroup( COLLISION_GROUP_PROJECTILE ); SetModel( "models/Weapons/ar2_grenade.mdl"); UTIL_SetSize(this, Vector(-3, -3, -3), Vector(3, 3, 3)); // UTIL_SetSize(this, Vector(0, 0, 0), Vector(0, 0, 0)); SetUse( &CGrenadeAR2::DetonateUse ); SetTouch( &CGrenadeAR2::GrenadeAR2Touch ); SetThink( &CGrenadeAR2::GrenadeAR2Think ); SetNextThink( gpGlobals->curtime + 0.1f ); if( GetOwnerEntity() && GetOwnerEntity()->IsPlayer() ) { m_flDamage = sk_plr_dmg_smg1_grenade.GetFloat(); } else { m_flDamage = sk_npc_dmg_smg1_grenade.GetFloat(); } m_DmgRadius = sk_smg1_grenade_radius.GetFloat(); m_takedamage = DAMAGE_YES; m_bIsLive = true; m_iHealth = 1; SetGravity( UTIL_ScaleForGravity( 400 ) ); // use a lower gravity for grenades to make them easier to see SetFriction( 0.8 ); SetSequence( 0 ); m_fDangerRadius = 100; m_fSpawnTime = gpGlobals->curtime; // ------------- // Smoke trail. // ------------- if( g_CV_SmokeTrail.GetInt() && !IsXbox() ) { m_hSmokeTrail = SmokeTrail::CreateSmokeTrail(); if( m_hSmokeTrail ) { m_hSmokeTrail->m_SpawnRate = 48; m_hSmokeTrail->m_ParticleLifetime = 1; m_hSmokeTrail->m_StartColor.Init(0.1f, 0.1f, 0.1f); m_hSmokeTrail->m_EndColor.Init(0,0,0); m_hSmokeTrail->m_StartSize = 12; m_hSmokeTrail->m_EndSize = m_hSmokeTrail->m_StartSize * 4; m_hSmokeTrail->m_SpawnRadius = 4; m_hSmokeTrail->m_MinSpeed = 4; m_hSmokeTrail->m_MaxSpeed = 24; m_hSmokeTrail->m_Opacity = 0.2f; m_hSmokeTrail->SetLifetime(10.0f); m_hSmokeTrail->FollowEntity(this); } } }
void C_AR2Explosion::Start(CParticleMgr *pParticleMgr, IPrototypeArgAccess *pArgs) { m_pParticleMgr = pParticleMgr; if(!pParticleMgr->AddEffect(&m_ParticleEffect, this)) return; if (!m_szMaterialName[0]) { Q_strncpy(m_szMaterialName, "particle/particle_noisesphere", sizeof( m_szMaterialName ) ); } m_MaterialHandle = m_ParticleEffect.FindOrAddMaterial(m_szMaterialName); // Precalculate stuff for the particle spawning.. #define NUM_DUSTEMITTER_SURFINFOS 128 SurfInfo surfInfos[NUM_DUSTEMITTER_SURFINFOS]; int nSurfInfos; // Center of explosion. Vector vCenter = GetAbsOrigin(); // HACKHACK.. when the engine bug is fixed, use origin. if ( IsXbox() ) { m_ParticleEffect.SetBBox( vCenter-Vector(300,300,300), vCenter+Vector(300,300,300) ); } #ifdef PARTICLEPROTOTYPE_APP float surfSize = 10000; nSurfInfos = 1; surfInfos[0].m_Verts[0].Init(-surfSize,-surfSize,0); surfInfos[0].m_Verts[1].Init(-surfSize,surfSize,0); surfInfos[0].m_Verts[2].Init(surfSize, surfSize,0); surfInfos[0].m_Verts[3].Init(surfSize,-surfSize,0); surfInfos[0].m_nVerts = 4; surfInfos[0].m_Plane.m_Normal.Init(0,0,1); surfInfos[0].m_Plane.m_Dist = -3; #else { nSurfInfos = 0; C_BaseEntity *ent = cl_entitylist->GetEnt( 0 ); if ( ent ) { nSurfInfos = engine->GetIntersectingSurfaces( ent->GetModel(), vCenter, AR2_DUST_RADIUS, true, surfInfos, NUM_DUSTEMITTER_SURFINFOS); } } #endif int nParticles = 0; int iParticlesToSpawn = NUM_AR2_EXPLOSION_PARTICLES; if(nSurfInfos > 0) { // For nParticles*N, generate a ray and cast it out. If it hits anything, spawn a particle there. int nTestsPerParticle=3; for(int i=0; i < iParticlesToSpawn; i++) { for(int iTest=0; iTest < nTestsPerParticle; iTest++) { Vector randVec = RandomVector(-1,1); VectorNormalize( randVec ); Vector startPos = vCenter + randVec * AR2_DUST_RADIUS; randVec = RandomVector(-1,1); VectorNormalize( randVec ); Vector endPos = vCenter + randVec * AR2_DUST_RADIUS; #define MAX_SURFINFO_INTERSECTIONS 4 SurfInfo *pIntersected[MAX_SURFINFO_INTERSECTIONS]; Vector vIntersections[MAX_SURFINFO_INTERSECTIONS]; int nIntersections; nIntersections = IntersectSegmentWithSurfInfos( startPos, endPos, surfInfos, nSurfInfos, pIntersected, vIntersections, MAX_SURFINFO_INTERSECTIONS); if(nIntersections) { int iIntersection = rand() % nIntersections; Vector velocity; //velocity.Init(-1.0f + ((float)rand()/RAND_MAX) * 2.0f, -1.0f + ((float)rand()/RAND_MAX) * 2.0f, -1.0f + ((float)rand()/RAND_MAX) * 2.0f); //velocity = velocity * FRand(m_MinSpeed, m_MaxSpeed); Vector direction = (vIntersections[iIntersection] - vCenter ); float dist = VectorNormalize( direction ); if(dist > AR2_DUST_RADIUS) dist = AR2_DUST_RADIUS; static float power = 2.0f; float falloffMul = pow(1.0f - dist / AR2_DUST_RADIUS, power); Vector reflection = direction - 2 * DotProduct( direction, pIntersected[iIntersection]->m_Plane.m_Normal ) * pIntersected[iIntersection]->m_Plane.m_Normal; VectorNormalize( reflection ); velocity = reflection * AR2_DUST_SPEED * falloffMul; // velocity = velocity + (vIntersections[iIntersection] - vCenter) * falloffMul; /* debugoverlay->AddLineOverlay( vIntersections[iIntersection], vIntersections[iIntersection] + reflection * 64, 128, 128, 255, false, 15.0 ); */ #if 1 AR2ExplosionParticle *pParticle = (AR2ExplosionParticle*)m_ParticleEffect.AddParticle( sizeof(AR2ExplosionParticle), m_MaterialHandle ); if(pParticle) { pParticle->m_Pos = vIntersections[iIntersection]; pParticle->m_Start = pParticle->m_Pos; pParticle->m_Dist = 8.0; pParticle->m_Velocity = velocity; // sound == 13031.496062992125984251968503937ips pParticle->m_Lifetime = -dist / 13031.5f - 0.1; pParticle->m_Roll = FRand( 0, M_PI * 2 ); pParticle->m_RollSpeed = FRand( -1, 1 ) * 0.4; pParticle->m_Dwell = AR2_DUST_LIFETIME + random->RandomFloat( 0, AR2_DUST_LIFETIME_DELTA ); nParticles++; break; } #endif } } } } // build interior smoke particles for(int i=nParticles; i < iParticlesToSpawn; i++) { Vector randVec = RandomVector(-1,1); VectorNormalize( randVec ); Vector endPos = vCenter + randVec * AR2_DUST_RADIUS / 4.0; Vector direction = (endPos - vCenter ); float dist = VectorNormalize( direction ) + random->RandomFloat( 0, AR2_DUST_RADIUS / 4.0 ); if(dist > AR2_DUST_RADIUS) dist = AR2_DUST_RADIUS; static float power = 2.0f; float falloffMul = pow(1.0f - dist / (AR2_DUST_RADIUS / 2), power); Vector velocity = direction * AR2_DUST_SPEED * falloffMul; AR2ExplosionParticle *pParticle = (AR2ExplosionParticle*)m_ParticleEffect.AddParticle( sizeof(AR2ExplosionParticle), m_MaterialHandle ); if(pParticle) { pParticle->m_Pos = endPos; pParticle->m_Start = pParticle->m_Pos; pParticle->m_Dist = 8.0; pParticle->m_Velocity = velocity; // sound == 13031.496062992125984251968503937ips pParticle->m_Lifetime = -dist / 13031.5f - 0.1; pParticle->m_Roll = FRand( 0, M_PI * 2 ); pParticle->m_RollSpeed = FRand( -1, 1 ) * 4.0; pParticle->m_Dwell = 0.5 * (AR2_DUST_LIFETIME + random->RandomFloat( 0, AR2_DUST_LIFETIME_DELTA )); } } }