void C_Func_Dust::AttemptSpawnNewParticle() { // Find a random spot inside our bmodel. static int nTests=10; for( int iTest=0; iTest < nTests; iTest++ ) { Vector vPercent = RandomVector( 0, 1 ); Vector vTest = WorldAlignMins() + (WorldAlignMaxs() - WorldAlignMins()) * vPercent; int contents = enginetrace->GetPointContents_Collideable( GetCollideable(), vTest ); if( contents & CONTENTS_SOLID ) { CFuncDustParticle *pParticle = (CFuncDustParticle*)m_Effect.AddParticle( 10, m_hMaterial, vTest ); if( pParticle ) { pParticle->m_vVelocity = RandomVector( -m_SpeedMax, m_SpeedMax ); pParticle->m_vVelocity.z -= m_FallSpeed; pParticle->m_flLifetime = 0; pParticle->m_flDieTime = RemapVal( rand(), 0, RAND_MAX, m_LifetimeMin, m_LifetimeMax ); if( m_DustFlags & DUSTFLAGS_SCALEMOTES ) pParticle->m_flSize = RemapVal( rand(), 0, RAND_MAX, m_flSizeMin/10000.0f, m_flSizeMax/10000.0f ); else pParticle->m_flSize = RemapVal( rand(), 0, RAND_MAX, m_flSizeMin, m_flSizeMax ); pParticle->m_Color = m_Color; } break; } } }
void CNPC_Ichthyosaur::DragVictim( float moveDist ) { Vector mins, maxs; float width; mins = WorldAlignMins(); maxs = WorldAlignMaxs(); width = ( maxs.y - mins.y ) * 0.5f; Vector forward, up; GetVectors( &forward, NULL, &up ); Vector newPos = GetAbsOrigin() + ( (forward+(up*0.25f)) * ( moveDist + width + DRAG_OFFSET ) ); trace_t tr; AI_TraceEntity( this, m_pVictim->GetAbsOrigin(), newPos, MASK_NPCSOLID, &tr ); if ( ( tr.fraction == 1.0f ) && ( tr.m_pEnt != this ) ) { UTIL_SetOrigin( m_pVictim, tr.endpos ); } else { ReleaseVictim(); } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CNPC_Bug_Builder::Spawn( void ) { Precache(); SetModel( BUG_BUILDER_MODEL ); SetHullType(HULL_TINY); SetHullSizeNormal(); SetDefaultEyeOffset(); SetViewOffset( (WorldAlignMins() + WorldAlignMaxs()) * 0.5 ); // See from my center SetDistLook( 1024.0 ); m_flNextDawdle = 0; SetNavType(NAV_GROUND); m_NPCState = NPC_STATE_NONE; SetBloodColor( BLOOD_COLOR_YELLOW ); m_iHealth = npc_bug_builder_health.GetFloat(); SetSolid( SOLID_BBOX ); AddSolidFlags( FSOLID_NOT_STANDABLE ); SetMoveType( MOVETYPE_STEP ); CapabilitiesAdd( bits_CAP_MOVE_GROUND ); NPCInit(); BaseClass::Spawn(); }
void CBaseTurret::Deploy(void) { SetNextThink( gpGlobals->curtime + 0.1f ); StudioFrameAdvance( ); if ( m_Activity != ACT_TURRET_OPEN ) { m_iOn = 1; SetActivity( (Activity)ACT_TURRET_OPEN ); EmitSound( "NPC_Turret.Deploy" ); m_OnDeploy.FireOutput(NULL, this); } if (m_fSequenceFinished) { Vector curmins, curmaxs; curmins = WorldAlignMins(); curmaxs = WorldAlignMaxs(); curmaxs.z = m_iDeployHeight; curmins.z = -m_iDeployHeight; SetCollisionBounds( curmins, curmaxs ); Relink(); SetActivity( (Activity)ACT_TURRET_OPEN_IDLE ); m_flPlaybackRate = 0; SetThink(SearchThink); } m_flLastSight = gpGlobals->curtime + m_flMaxWait; }
inline Vector GetSmokeParticlePos(int x, int y, int z ) { return WorldAlignMins() + Vector( x * m_SpacingRadius * 2 + m_SpacingRadius, y * m_SpacingRadius * 2 + m_SpacingRadius, z * m_SpacingRadius * 2 + m_SpacingRadius ); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CNPC_Bug_Warrior::Spawn( void ) { Precache(); SetModel( BUG_WARRIOR_MODEL ); SetHullType(HULL_WIDE_HUMAN);//HULL_WIDE_SHORT; SetHullSizeNormal(); SetDefaultEyeOffset(); SetViewOffset( (WorldAlignMins() + WorldAlignMaxs()) * 0.5 ); // See from my center SetDistLook( 1024.0 ); SetNavType(NAV_GROUND); m_NPCState = NPC_STATE_NONE; SetBloodColor( BLOOD_COLOR_YELLOW ); m_iHealth = npc_bug_warrior_health.GetFloat(); SetSolid( SOLID_BBOX ); AddSolidFlags( FSOLID_NOT_STANDABLE ); SetMoveType( MOVETYPE_STEP ); m_iszPatrolPathName = NULL_STRING; // Only do this if a squadname appears in the entity if ( m_SquadName != NULL_STRING ) { CapabilitiesAdd( bits_CAP_SQUAD ); } CapabilitiesAdd( bits_CAP_MOVE_GROUND | bits_CAP_INNATE_MELEE_ATTACK1 ); NPCInit(); BaseClass::Spawn(); }
//----------------------------------------------------------------------------- // Default to a simple single trace, but allow overriding. // This is used for the strider, so it can determine the height based on the legs. //----------------------------------------------------------------------------- void UnitBaseAirLocomotion::UpdateCurrentHeight() { trace_t pm; UTIL_TraceHull( mv->origin, mv->origin-Vector(0, 0, MAX_TRACE_LENGTH), WorldAlignMins(), WorldAlignMaxs(), MASK_NPCWORLDSTATIC, m_pOuter, GetOuter()->CalculateIgnoreOwnerCollisionGroup(), &pm ); m_fCurrentHeight = fabs( pm.endpos.z-mv->origin.z ); }
//========================================================= // SetEyePosition // // queries the units's model for $eyeposition and copies // that vector to the npc's m_vDefaultEyeOffset and m_vecViewOffset // //========================================================= void CUnitBase::SetDefaultEyeOffset( Vector *pCustomOfset ) { if( pCustomOfset ) { m_vDefaultEyeOffset = *pCustomOfset; } else if ( GetModelPtr() ) { GetEyePosition( GetModelPtr(), m_vDefaultEyeOffset ); if ( m_vDefaultEyeOffset == vec3_origin ) { //if ( Classify() != CLASS_NONE ) { DevMsg( "WARNING: %s(%s) has no eye offset in .qc!\n", GetClassname(), STRING(GetModelName()) ); } VectorAdd( WorldAlignMins(), WorldAlignMaxs(), m_vDefaultEyeOffset ); m_vDefaultEyeOffset *= 0.75; } } else m_vDefaultEyeOffset = vec3_origin; // Clamp to values in dt m_vDefaultEyeOffset.x = Max<float>( Min<float>( m_vDefaultEyeOffset.x, 256.0f ), -256.0 ); m_vDefaultEyeOffset.y = Max<float>( Min<float>( m_vDefaultEyeOffset.y, 256.0f ), -256.0 ); m_vDefaultEyeOffset.z = Max<float>( Min<float>( m_vDefaultEyeOffset.z, 1024.0f ), -1.0f ); #ifndef CLIENT_DLL SetViewOffset( m_vDefaultEyeOffset ); #endif // CLIENT_DLL }
//----------------------------------------------------------------------------- // Purpose: Do not test against hit boxes, but against the bounding box. // Much cheaper and we don't really need hitboxes for hl2wars. //----------------------------------------------------------------------------- bool CUnitBase::TestHitboxes( const Ray_t &ray, unsigned int fContentsMask, trace_t& tr ) { #if 1 if( unit_cheaphitboxtest.GetBool() == false ) return BaseClass::TestHitboxes( ray, fContentsMask, tr ); CStudioHdr *pStudioHdr = GetModelPtr( ); if (!pStudioHdr) return false; Ray_t ray2 = ray; Vector start = GetAbsOrigin() - ray.m_Start; ray2.Init(start, start+ray.m_Delta); IntersectRayWithBox(ray2, WorldAlignMins(), WorldAlignMaxs(), 0.0f, &tr); if ( tr.DidHit() ) { tr.surface.name = "**studio**"; tr.surface.flags = SURF_HITBOX; tr.surface.surfaceProps = VPhysicsGetObject() ? VPhysicsGetObject()->GetMaterialIndex() : 0; //NDebugOverlay::SweptBox(ray.m_Start, tr.endpos, -Vector(32, 32, 32), Vector(32, 32, 32), GetAbsAngles(), 255, 0, 0, 255, 1.0f); return true; } return false; #else return BaseClass::TestHitboxes( ray, fContentsMask, tr ); #endif // 0 }
void CRopeKeyframe::UpdateBBox( bool bForceRelink ) { Vector v1, v2; Vector vMin, vMax; if ( GetEndPointPos( 0, v1 ) ) { if ( GetEndPointPos( 1, v2 ) ) { VectorMin( v1, v2, vMin ); VectorMax( v1, v2, vMax ); // Set our bounds to enclose both endpoints and relink. vMin -= GetAbsOrigin(); vMax -= GetAbsOrigin(); } else { vMin = vMax = v1 - GetAbsOrigin(); } } else { vMin = vMax = Vector( 0, 0, 0 ); } if ( WorldAlignMins() != vMin || WorldAlignMaxs() != vMax ) { UTIL_SetSize( this, vMin, vMax ); } }
void C_FuncSmokeVolume::OnDataChanged( DataUpdateType_t updateType ) { m_MinColor[0] = ( 1.0f / 255.0f ) * m_Color1.r; m_MinColor[1] = ( 1.0f / 255.0f ) * m_Color1.g; m_MinColor[2] = ( 1.0f / 255.0f ) * m_Color1.b; m_MaxColor[0] = ( 1.0f / 255.0f ) * m_Color2.r; m_MaxColor[1] = ( 1.0f / 255.0f ) * m_Color2.g; m_MaxColor[2] = ( 1.0f / 255.0f ) * m_Color2.b; m_ParticleRadius = m_ParticleDrawWidth * 0.5f; m_SpacingRadius = m_ParticleSpacingDistance * 0.5f; // Warning( "m_Density: %f\n", m_Density ); // Warning( "m_MovementSpeed: %f\n", m_MovementSpeed ); if(updateType == DATA_UPDATE_CREATED) { Vector size = WorldAlignMaxs() - WorldAlignMins(); m_xCount = 0.5f + ( size.x / ( m_SpacingRadius * 2.0f ) ); m_yCount = 0.5f + ( size.y / ( m_SpacingRadius * 2.0f ) ); m_zCount = 0.5f + ( size.z / ( m_SpacingRadius * 2.0f ) ); m_CurrentDensity = m_Density; delete [] m_pSmokeParticleInfos; m_pSmokeParticleInfos = new SmokeParticleInfo[m_xCount * m_yCount * m_zCount]; Start( &g_ParticleMgr, NULL ); } BaseClass::OnDataChanged( updateType ); }
//----------------------------------------------------------------------------- // Purpose: custom code to fix collision errors //----------------------------------------------------------------------------- bool CBaseHelicopter::TestCollision( const Ray_t &ray, unsigned int mask, trace_t& trace ) { // Let normal hitbox code handle rays if ( mask & CONTENTS_HITBOX ) return BaseClass::TestCollision( ray, mask, trace ); return TestCollisionBox( ray, mask, trace, WorldAlignMins() + GetAbsOrigin(), WorldAlignMaxs() + GetAbsOrigin() ); }
//========================================================= // Retire - stop being active //========================================================= void CNPC_BaseTurret::Retire(void) { // make the turret level m_vecGoalAngles.x = 0; m_vecGoalAngles.y = m_flStartYaw; SetNextThink( gpGlobals->curtime + 0.1 ); StudioFrameAdvance( ); EyeOff( ); if (!MoveTurret()) { if (m_iSpin) { SpinDownCall(); } else if (GetSequence() != TURRET_ANIM_RETIRE) { SetTurretAnim(TURRET_ANIM_RETIRE); CPASAttenuationFilter filter( this ); EmitSound( filter, entindex(), "Turret.Undeploy" ); m_OnDeactivate.FireOutput(this, this); } //else if (IsSequenceFinished()) else if( GetSequence() == TURRET_ANIM_RETIRE && GetCycle() <= 0.0 ) { m_iOn = 0; m_flLastSight = 0; //SetTurretAnim(TURRET_ANIM_NONE); Vector curmins, curmaxs; curmins = WorldAlignMins(); curmaxs = WorldAlignMaxs(); curmaxs.z = m_iRetractHeight; curmins.z = -m_iRetractHeight; SetCollisionBounds( curmins, curmaxs ); if (m_iAutoStart) { SetThink(&CNPC_BaseTurret::AutoSearchThink); SetNextThink( gpGlobals->curtime + 0.1 ); } else { SetThink( &CBaseEntity::SUB_DoNothing ); } } } else { SetTurretAnim(TURRET_ANIM_SPIN); } }
virtual void SetObjectCollisionBox( void ) { SetAbsMins( GetAbsOrigin() + WorldAlignMins() ); SetAbsMaxs( GetAbsOrigin() + WorldAlignMaxs() ); // Extend our bounding box downwards the length of the tongue Vector vecAbsMins = GetAbsMins(); vecAbsMins.z -= m_flAltitude; SetAbsMins( vecAbsMins ); }
//----------------------------------------------------------------------------- // Purpose: Checks collisions against other entities //----------------------------------------------------------------------------- void CTFFlameEntity::CheckCollision( CBaseEntity *pOther, bool *pbHitWorld ) { *pbHitWorld = false; // if we've already burnt this entity, don't do more damage, so skip even checking for collision with the entity int iIndex = m_hEntitiesBurnt.Find( pOther ); if ( iIndex != m_hEntitiesBurnt.InvalidIndex() ) return; // Do a bounding box check against the entity Vector vecMins, vecMaxs; pOther->GetCollideable()->WorldSpaceSurroundingBounds( &vecMins, &vecMaxs ); CBaseTrace trace; Ray_t ray; float flFractionLeftSolid; ray.Init( m_vecPrevPos, GetAbsOrigin(), WorldAlignMins(), WorldAlignMaxs() ); if ( IntersectRayWithBox( ray, vecMins, vecMaxs, 0.0, &trace, &flFractionLeftSolid ) ) { // if bounding box check passes, check player hitboxes trace_t trHitbox; trace_t trWorld; bool bTested = pOther->GetCollideable()->TestHitboxes( ray, MASK_SOLID | CONTENTS_HITBOX, trHitbox ); if ( !bTested || !trHitbox.DidHit() ) return; // now, let's see if the flame visual could have actually hit this player. Trace backward from the // point of impact to where the flame was fired, see if we hit anything. Since the point of impact was // determined using the flame's bounding box and we're just doing a ray test here, we extend the // start point out by the radius of the box. Vector vDir = ray.m_Delta; vDir.NormalizeInPlace(); UTIL_TraceLine( GetAbsOrigin() + vDir * WorldAlignMaxs().x, m_vecInitialPos, MASK_SOLID, this, COLLISION_GROUP_DEBRIS, &trWorld ); if ( tf_debug_flamethrower.GetInt() ) { NDebugOverlay::Line( trWorld.startpos, trWorld.endpos, 0, 255, 0, true, 3.0f ); } if ( trWorld.fraction == 1.0 ) { // if there is nothing solid in the way, damage the entity OnCollide( pOther ); } else { // we hit the world, remove ourselves *pbHitWorld = true; UTIL_Remove( this ); } } }
void CBaseTurret::Retire(void) { // make the turret level m_vecGoalAngles = GetAngles( ); SetNextThink( gpGlobals->curtime + 0.1f ); StudioFrameAdvance( ); EyeOff( ); if ( m_Activity != ACT_TURRET_CLOSE ) { SetActivity( (Activity)ACT_TURRET_OPEN_IDLE ); if (!MoveTurret()) { SetActivity( (Activity)ACT_TURRET_CLOSE ); EmitSound( "NPC_Turret.Retire" ); m_OnRetire.FireOutput(NULL, this); } } else if (m_fSequenceFinished) { m_iOn = 0; m_flLastSight = 0; SetActivity( (Activity)ACT_TURRET_CLOSED_IDLE ); Vector curmins, curmaxs; curmins = WorldAlignMins(); curmaxs = WorldAlignMaxs(); curmaxs.z = m_iRetractHeight; curmins.z = -m_iRetractHeight; SetCollisionBounds( curmins, curmaxs ); Relink(); if (m_iAutoStart) { SetThink(AutoSearchThink); SetNextThink( gpGlobals->curtime + .1 ); } else { SetThink(SUB_DoNothing); } } }
//----------------------------------------------------------------------------- // Purpose: Does not change the entities velocity at all // Input : push - // Output : trace_t //----------------------------------------------------------------------------- void C_BaseEntity::PhysicsCheckSweep( const Vector& vecAbsStart, const Vector &vecAbsDelta, trace_t *pTrace ) { unsigned int mask = PhysicsSolidMaskForEntity(); Vector vecAbsEnd; VectorAdd( vecAbsStart, vecAbsDelta, vecAbsEnd ); // Set collision type if ( !IsSolid() || IsSolidFlagSet( FSOLID_VOLUME_CONTENTS ) ) { // don't collide with monsters mask &= ~CONTENTS_MONSTER; } Physics_TraceHull( this, vecAbsStart, vecAbsEnd, WorldAlignMins(), WorldAlignMaxs(), mask, pTrace ); }
//========================================================= // Deploy - go active //========================================================= void CNPC_BaseTurret::Deploy(void) { SetNextThink( gpGlobals->curtime + 0.1 ); StudioFrameAdvance( ); if (GetSequence() != TURRET_ANIM_DEPLOY) { m_iOn = 1; SetTurretAnim(TURRET_ANIM_DEPLOY); CPASAttenuationFilter filter( this ); EmitSound( filter, entindex(), "Turret.Deploy" ); m_OnActivate.FireOutput(this, this); } if (IsSequenceFinished()) { Vector curmins, curmaxs; curmins = WorldAlignMins(); curmaxs = WorldAlignMaxs(); curmaxs.z = m_iDeployHeight; curmins.z = -m_iDeployHeight; SetCollisionBounds( curmins, curmaxs ); m_vecCurAngles.x = 0; QAngle angles = GetAbsAngles(); if (m_iOrientation == TURRET_ORIENTATION_CEILING) { m_vecCurAngles.y = UTIL_AngleMod( angles.y + 180 ); } else { m_vecCurAngles.y = UTIL_AngleMod( angles.y ); } SetTurretAnim(TURRET_ANIM_SPIN); m_flPlaybackRate = 0; SetThink(&CNPC_BaseTurret::SearchThink); } m_flLastSight = gpGlobals->curtime + m_flMaxWait; }
void C_WeaponSpawner::ClientThink() { m_qAngle.y += 90 * gpGlobals->frametime; if ( m_qAngle.y >= 360 ) m_qAngle.y -= 360; SetAbsAngles( m_qAngle ); C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); bool bShouldGlow = false; bool bTouchingPlayer = false; if ( pPlayer ) { Vector vecPlayerOrigin = pPlayer->GetAbsOrigin(); Vector vecPlayerMins = vecPlayerOrigin + pPlayer->GetPlayerMins(); Vector vecPlayerMaxs = vecPlayerOrigin + pPlayer->GetPlayerMaxs(); bTouchingPlayer = IsBoxIntersectingBox( GetAbsOrigin() + WorldAlignMins(), GetAbsOrigin() + WorldAlignMaxs(), vecPlayerMins, vecPlayerMaxs ); // Disable the outline if the weapon has been picked up. if ( !m_bRespawning && !m_bDisabled ) { // Temp crutch for Occluded\Unoccluded glow parameters not working. trace_t tr; UTIL_TraceLine( GetAbsOrigin(), pPlayer->EyePosition(), MASK_OPAQUE, this, COLLISION_GROUP_NONE, &tr ); if ( tr.fraction == 1.0f ) { bShouldGlow = true; } } } if ( m_bShouldGlow != bShouldGlow || m_bTouchingPlayer != bTouchingPlayer ) { m_bShouldGlow = bShouldGlow; m_bTouchingPlayer = bTouchingPlayer; UpdateGlowEffect(); } SetNextClientThink( CLIENT_THINK_ALWAYS ); }
// This creates a vphysics object with a shadow controller that follows the AI IPhysicsObject *C_RagdollShadow::VPhysicsInitShadow( bool allowPhysicsMovement, bool allowPhysicsRotation ) { studiohdr_t *hdr = GetModelPtr(); if ( !hdr ) { return NULL; } // If this entity already has a physics object, then it should have been deleted prior to making this call. Assert(!m_pPhysicsObject); // make sure m_vecOrigin / m_vecAngles are correct const Vector &origin = GetAbsOrigin(); QAngle angles = GetAbsAngles(); IPhysicsObject *pPhysicsObject = NULL; if ( GetSolid() == SOLID_BBOX ) { const char *pSurfaceProps = "flesh"; if ( GetModelIndex() && modelinfo->GetModelType( GetModel() ) == mod_studio ) { pSurfaceProps = Studio_GetDefaultSurfaceProps( hdr ); } angles = vec3_angle; CPhysCollide *pCollide = PhysCreateBbox( WorldAlignMins(), WorldAlignMaxs() ); if ( !pCollide ) return NULL; pPhysicsObject = PhysModelCreateCustom( this, pCollide, origin, angles, pSurfaceProps ); } else { pPhysicsObject = PhysModelCreateRagdoll( this, GetModelIndex(), origin, angles ); } VPhysicsSetObject( pPhysicsObject ); pPhysicsObject->SetShadow( Vector(1e4,1e4,1e4), AngularImpulse(1e4,1e4,1e4), allowPhysicsMovement, allowPhysicsRotation ); pPhysicsObject->UpdateShadow( GetAbsOrigin(), GetAbsAngles(), false, 0 ); // PhysAddShadow( this ); return pPhysicsObject; }
//------------------------------------------------------------------------------ // Purpose : // Input : // Output : //------------------------------------------------------------------------------ void CNPC_LightStalk::Spawn( void ) { Precache(); SetModel( LIGHTSTALK_MODEL ); SetMoveType( MOVETYPE_NONE ); SetSolid( SOLID_BBOX ); AddSolidFlags( FSOLID_TRIGGER ); UTIL_SetSize( this, Vector(-80,-80,0), Vector(80,80,32)); Relink(); SetActivity( ACT_IDLE ); SetNextThink( gpGlobals->curtime + 0.1f ); m_pGlow = CSprite::SpriteCreate( LIGHTSTALK_GLOW_SPRITE, GetLocalOrigin() + Vector(0,0,(WorldAlignMins().z+WorldAlignMaxs().z)*0.5), false ); m_pGlow->SetTransparency( kRenderGlow, m_clrRender->r, m_clrRender->g, m_clrRender->b, m_clrRender->a, kRenderFxGlowShell ); m_pGlow->SetScale( 1.0 ); m_pGlow->SetAttachment( this, 1 ); LightRise(); }
//------------------------------------------------------------------------------ // Purpose : // Input : // Output : //------------------------------------------------------------------------------ void CNPC_CombineDropship::PrescheduleThink( void ) { BaseClass::PrescheduleThink(); // keep track of think time deltas for burn calc below float dt = gpGlobals->curtime - m_flLastTime; m_flLastTime = gpGlobals->curtime; switch( m_iLandState ) { case LANDING_NO: { if ( IsActivityFinished() && (GetActivity() != ACT_DROPSHIP_FLY_IDLE_EXAGG && GetActivity() != ACT_DROPSHIP_FLY_IDLE_CARGO) ) { if ( m_hContainer ) { SetIdealActivity( (Activity)ACT_DROPSHIP_FLY_IDLE_CARGO ); } else { SetIdealActivity( (Activity)ACT_DROPSHIP_FLY_IDLE_EXAGG ); } } DoRotorWash(); } break; case LANDING_LEVEL_OUT: { // Approach the drop point Vector vecToTarget = (GetDesiredPosition() - GetAbsOrigin()); float flDistance = vecToTarget.Length(); // If we're slowing, make it look like we're slowing /* if ( IsActivityFinished() && GetActivity() != ACT_DROPSHIP_DESCEND_IDLE ) { SetActivity( (Activity)ACT_DROPSHIP_DESCEND_IDLE ); } */ // Are we there yet? float flSpeed = GetAbsVelocity().Length(); if ( flDistance < 70 && flSpeed < 100 ) { m_flLandingSpeed = flSpeed; m_iLandState = LANDING_DESCEND; // save off current angles so we can work them out over time QAngle angles = GetLocalAngles(); m_existPitch = angles.x; m_existRoll = angles.z; } DoRotorWash(); } break; case LANDING_DESCEND: { float flAltitude; SetLocalAngularVelocity( vec3_angle ); // Ensure we land on the drop point Vector vecToTarget = (GetDesiredPosition() - GetAbsOrigin()); float flDistance = vecToTarget.Length(); float flRampedSpeed = m_flLandingSpeed * (flDistance / 70); Vector vecVelocity = (flRampedSpeed / flDistance) * vecToTarget; vecVelocity.z = -75; SetAbsVelocity( vecVelocity ); flAltitude = GetAltitude(); if ( IsActivityFinished() && GetActivity() != ACT_DROPSHIP_DESCEND_IDLE ) { SetActivity( (Activity)ACT_DROPSHIP_DESCEND_IDLE ); } if ( flAltitude < 72 ) { QAngle angles = GetLocalAngles(); // Level out quickly. angles.x = UTIL_Approach( 0.0, angles.x, 0.2 ); angles.z = UTIL_Approach( 0.0, angles.z, 0.2 ); SetLocalAngles( angles ); } else { // randomly move as if buffeted by ground effects // gently flatten ship from starting pitch/yaw m_existPitch = UTIL_Approach( 0.0, m_existPitch, 1 ); m_existRoll = UTIL_Approach( 0.0, m_existRoll, 1 ); QAngle angles = GetLocalAngles(); angles.x = m_existPitch + ( sin( gpGlobals->curtime * 3.5f ) * DROPSHIP_MAX_LAND_TILT ); angles.z = m_existRoll + ( sin( gpGlobals->curtime * 3.75f ) * DROPSHIP_MAX_LAND_TILT ); SetLocalAngles( angles ); // figure out where to face (nav point) Vector targetDir = GetDesiredPosition() - GetAbsOrigin(); // NDebugOverlay::Cross3D( m_pGoalEnt->GetAbsOrigin(), -Vector(2,2,2), Vector(2,2,2), 255, 0, 0, false, 20 ); QAngle targetAngles = GetAbsAngles(); targetAngles.y += UTIL_AngleDiff(UTIL_VecToYaw( targetDir ), targetAngles.y); // orient ship towards path corner on the way down angles = GetAbsAngles(); angles.y = UTIL_Approach(targetAngles.y, angles.y, 2 ); SetAbsAngles( angles ); } if ( flAltitude <= 0.5f ) { m_iLandState = LANDING_TOUCHDOWN; // upon landing, make sure ship is flat QAngle angles = GetLocalAngles(); angles.x = 0; angles.z = 0; SetLocalAngles( angles ); // TODO: Release cargo anim SetActivity( (Activity)ACT_DROPSHIP_DESCEND_IDLE ); } DoRotorWash(); // place danger sounds 1 foot above ground to get troops to scatter if they are below dropship Vector vecBottom = GetAbsOrigin(); vecBottom.z += WorldAlignMins().z; Vector vecSpot = vecBottom + Vector(0, 0, -1) * (GetAltitude() - 12 ); CSoundEnt::InsertSound( SOUND_DANGER, vecSpot, 400, 0.2, this, 0 ); CSoundEnt::InsertSound( SOUND_PHYSICS_DANGER, vecSpot, 400, 0.2, this, 1 ); // NDebugOverlay::Cross3D( vecSpot, -Vector(4,4,4), Vector(4,4,4), 255, 0, 255, false, 10.0f ); // now check to see if player is below us, if so, cause heat damage to them (i.e. get them to move) trace_t tr; Vector vecBBoxMin = CRATE_BBOX_MIN; // use flat box for check vecBBoxMin.z = -5; Vector vecBBoxMax = CRATE_BBOX_MAX; vecBBoxMax.z = 5; Vector pEndPoint = vecBottom + Vector(0, 0, -1) * ( GetAltitude() - 12 ); AI_TraceHull( vecBottom, pEndPoint, vecBBoxMin, vecBBoxMax, MASK_SOLID, this, COLLISION_GROUP_NONE, &tr ); if ( tr.fraction < 1.0f ) { if ( tr.GetEntityIndex() == 1 ) // player??? { CTakeDamageInfo info( this, this, 20 * dt, DMG_BURN ); CBasePlayer *pPlayer = UTIL_PlayerByIndex(1); pPlayer->TakeDamage( info ); } } } break; case LANDING_TOUCHDOWN: { if ( IsActivityFinished() && ( GetActivity() != ACT_DROPSHIP_DESCEND_IDLE ) ) { SetActivity( (Activity)ACT_DROPSHIP_DESCEND_IDLE ); } m_iLandState = LANDING_UNLOADING; m_flTroopDeployPause = gpGlobals->curtime + DROPSHIP_PAUSE_B4_TROOP_UNLOAD; m_flTimeTakeOff = m_flTroopDeployPause + DROPSHIP_DEPLOY_TIME; } break; case LANDING_UNLOADING: { // pause before dropping troops if ( gpGlobals->curtime > m_flTroopDeployPause ) { if ( m_hContainer ) // don't drop troops if we don't have a crate any more { SpawnTroops(); m_flTroopDeployPause = m_flTimeTakeOff + 2; // only drop once } } // manage engine wash and volume if ( m_flTimeTakeOff - gpGlobals->curtime < 0.5f ) { m_engineThrust = UTIL_Approach( 1.0f, m_engineThrust, 0.1f ); DoRotorWash(); } else { float idleVolume = 0.2f; m_engineThrust = UTIL_Approach( idleVolume, m_engineThrust, 0.04f ); if ( m_engineThrust > idleVolume ) { DoRotorWash(); // make sure we're kicking up dust/water as long as engine thrust is up } } if( gpGlobals->curtime > m_flTimeTakeOff ) { m_iLandState = LANDING_LIFTOFF; SetActivity( (Activity)ACT_DROPSHIP_LIFTOFF ); m_engineThrust = 1.0f; // ensure max volume once we're airborne if ( m_bIsFiring ) { StopCannon(); // kill cannon sounds if they are on } // detach container from ship if ( m_hContainer && m_leaveCrate ) { m_hContainer->SetParent(NULL); m_hContainer->SetMoveType( (MoveType_t)m_iContainerMoveType ); // If the container has a physics object, remove it's shadow IPhysicsObject *pPhysicsObject = m_hContainer->VPhysicsGetObject(); if ( pPhysicsObject ) { pPhysicsObject->RemoveShadowController(); } m_hContainer = NULL; } } } break; case LANDING_LIFTOFF: { // give us some clearance before changing back to larger hull -- keeps ship from getting stuck on // things like the player, etc since we "pop" the hull... if ( GetAltitude() > 120 ) { m_OnFinishedDropoff.FireOutput( this, this ); m_iLandState = LANDING_NO; // change bounding box back to normal ship hull Vector vecBBMin, vecBBMax; ExtractBbox( SelectHeaviestSequence( ACT_DROPSHIP_DEPLOY_IDLE ), vecBBMin, vecBBMax ); UTIL_SetSize( this, vecBBMin, vecBBMax ); Relink(); } } break; case LANDING_SWOOPING: { // Did we lose our pickup target? if ( !m_hPickupTarget ) { m_iLandState = LANDING_NO; } else { // Decrease altitude and speed to hit the target point. Vector vecToTarget = (GetDesiredPosition() - GetAbsOrigin()); float flDistance = vecToTarget.Length(); // Start cheating when we get near it if ( flDistance < 50 ) { /* if ( flDistance > 10 ) { // Cheat and ensure we touch the target float flSpeed = GetAbsVelocity().Length(); Vector vecVelocity = vecToTarget; VectorNormalize( vecVelocity ); SetAbsVelocity( vecVelocity * min(flSpeed,flDistance) ); } else */ { // Grab the target m_hContainer = m_hPickupTarget; m_hPickupTarget = NULL; m_iContainerMoveType = m_hContainer->GetMoveType(); // If the container has a physics object, move it to shadow IPhysicsObject *pPhysicsObject = m_hContainer->VPhysicsGetObject(); if ( pPhysicsObject ) { pPhysicsObject->SetShadow( Vector(1e4,1e4,1e4), AngularImpulse(1e4,1e4,1e4), false, false ); pPhysicsObject->UpdateShadow( GetAbsOrigin(), GetAbsAngles(), false, 0 ); } int iIndex = 0;//LookupAttachment("Cargo"); /* Vector vecOrigin; QAngle vecAngles; GetAttachment( iIndex, vecOrigin, vecAngles ); m_hContainer->SetAbsOrigin( vecOrigin ); m_hContainer->SetAbsAngles( vec3_angle ); */ m_hContainer->SetAbsOrigin( GetAbsOrigin() ); m_hContainer->SetParent(this, iIndex); m_hContainer->SetMoveType( MOVETYPE_PUSH ); m_hContainer->RemoveFlag( FL_ONGROUND ); m_hContainer->Relink(); m_hContainer->SetAbsAngles( vec3_angle ); m_OnFinishedPickup.FireOutput( this, this ); m_iLandState = LANDING_NO; } } } DoRotorWash(); } break; } DoCombatStuff(); if ( GetActivity() != GetIdealActivity() ) { //Msg( "setactivity" ); SetActivity( GetIdealActivity() ); } }
//----------------------------------------------------------------------------- // Purpose: Override to check throw // Input : // Output : //----------------------------------------------------------------------------- int CWeaponMolotov::WeaponRangeAttack1Condition( float flDot, float flDist ) { // If things haven't changed too much since last time // just return that previously calculated value if (gpGlobals->curtime < m_fNextThrowCheck ) { return m_iThrowBits; } if ( flDist < m_fMinRange1) { m_iThrowBits = COND_TOO_CLOSE_TO_ATTACK; } else if (flDist > m_fMaxRange1) { m_iThrowBits = COND_TOO_FAR_TO_ATTACK; } else if (flDot < 0.5) { m_iThrowBits = COND_NOT_FACING_ATTACK; } // If moving, can't throw. else if ( m_flGroundSpeed != 0 ) { m_iThrowBits = COND_NONE; } else { // Ok we should check again as some time has passed // This function is only used by NPC's so we can cast to a Base Monster CAI_BaseNPC *pNPC = GetOwner()->MyNPCPointer(); CBaseEntity *pEnemy = pNPC->GetEnemy(); if (!pEnemy) { m_iThrowBits = COND_NONE; } // Get Enemy Position Vector vecTarget; pEnemy->CollisionProp()->NormalizedToWorldSpace( Vector( 0.5f, 0.5f, 0.0f ), &vecTarget ); // Get Toss Vector Vector throwStart = pNPC->Weapon_ShootPosition(); Vector vecToss; CBaseEntity* pBlocker = NULL; float throwDist = (throwStart - vecTarget).Length(); float fGravity = sv_gravity.GetFloat(); float throwLimit = pNPC->ThrowLimit(throwStart, vecTarget, fGravity, 35, WorldAlignMins(), WorldAlignMaxs(), pEnemy, &vecToss, &pBlocker); // If I can make the throw (or most of the throw) if (!throwLimit || (throwLimit != throwDist && throwLimit > 0.8*throwDist)) { m_vecTossVelocity = vecToss; m_iThrowBits = COND_CAN_RANGE_ATTACK1; } else { m_iThrowBits = COND_NONE; } } // don't check again for a while. m_fNextThrowCheck = gpGlobals->curtime + 0.33; // 1/3 second. return m_iThrowBits; }
void CNPC_Dog::SetPlayerAvoidState( void ) { bool bIntersectingBoneFollowers = false; bool bIntersectingNPCBox = false; Vector vNothing; GetSequenceLinearMotion( GetSequence(), &vNothing ); bool bIsMoving = ( IsMoving() || ( vNothing != vec3_origin ) ); //If we are coming out of a script, check if we are stuck inside the player. if ( m_bPerformAvoidance || ( ShouldPlayerAvoid() && bIsMoving ) ) { trace_t trace; Vector vMins, vMaxs; Vector vWorldMins, vWorldMaxs; Vector vPlayerMins, vPlayerMaxs; physfollower_t *pBone; int i; #ifdef SecobMod__Enable_Fixed_Multiplayer_AI CBasePlayer *pLocalPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); #else CBasePlayer *pLocalPlayer = AI_GetSinglePlayer(); #endif //SecobMod__Enable_Fixed_Multiplayer_AI if ( pLocalPlayer ) { vWorldMins = WorldAlignMins(); vWorldMaxs = WorldAlignMaxs(); vPlayerMins = pLocalPlayer->GetAbsOrigin() + pLocalPlayer->WorldAlignMins(); vPlayerMaxs = pLocalPlayer->GetAbsOrigin() + pLocalPlayer->WorldAlignMaxs(); // check if the player intersects the bounds of any of the bone followers for ( i = 0; i < m_BoneFollowerManager.GetNumBoneFollowers(); i++ ) { pBone = m_BoneFollowerManager.GetBoneFollower( i ); if ( pBone && pBone->hFollower ) { pBone->hFollower->CollisionProp()->WorldSpaceSurroundingBounds( &vMins, &vMaxs ); if ( IsBoxIntersectingBox( vMins, vMaxs, vPlayerMins, vPlayerMaxs ) ) { bIntersectingBoneFollowers = true; break; } } } bIntersectingNPCBox = IsBoxIntersectingBox( GetAbsOrigin() + vWorldMins, GetAbsOrigin() + vWorldMaxs, vPlayerMins, vPlayerMaxs ); if ( ai_debug_avoidancebounds.GetBool() ) { int iRed = ( bIntersectingNPCBox == true ) ? 255 : 0; NDebugOverlay::Box( GetAbsOrigin(), vWorldMins, vWorldMaxs, iRed, 0, 255, 64, 0.1 ); // draw the bounds of the bone followers for ( i = 0; i < m_BoneFollowerManager.GetNumBoneFollowers(); i++ ) { pBone = m_BoneFollowerManager.GetBoneFollower( i ); if ( pBone && pBone->hFollower ) { pBone->hFollower->CollisionProp()->WorldSpaceSurroundingBounds( &vMins, &vMaxs ); iRed = ( IsBoxIntersectingBox( vMins, vMaxs, vPlayerMins, vPlayerMaxs ) ) ? 255 : 0; NDebugOverlay::Box( vec3_origin, vMins, vMaxs, iRed, 0, 255, 64, 0.1 ); } } } } } m_bPlayerAvoidState = ShouldPlayerAvoid(); m_bPerformAvoidance = bIntersectingNPCBox || bIntersectingBoneFollowers; if ( GetCollisionGroup() == COLLISION_GROUP_NPC || GetCollisionGroup() == COLLISION_GROUP_NPC_ACTOR ) { if ( bIntersectingNPCBox == true ) { SetCollisionGroup( COLLISION_GROUP_NPC_ACTOR ); } else { SetCollisionGroup( COLLISION_GROUP_NPC ); } if ( bIntersectingBoneFollowers == true ) { MantainBoneFollowerCollisionGroups( COLLISION_GROUP_NPC_ACTOR ); } else { MantainBoneFollowerCollisionGroups( COLLISION_GROUP_NPC ); } } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- bool CObjectResupply::CalculatePlacement( CBaseTFPlayer *pPlayer ) { trace_t tr; Vector vecAiming; // Get an aim vector. Don't use GetAimVector() because we don't want autoaiming. Vector vecSrc = pPlayer->Weapon_ShootPosition( ); pPlayer->EyeVectors( &vecAiming ); Vector vecTarget; VectorMA( vecSrc, 90, vecAiming, vecTarget ); m_vecBuildOrigin = vecTarget; // Angle it towards me Vector vecForward = pPlayer->WorldSpaceCenter() - m_vecBuildOrigin; SetLocalAngles( QAngle( 0, UTIL_VecToYaw( vecForward ), 0 ) ); // Is there something to attach to? // Use my bounding box, not the build box, so I fit to the wall UTIL_TraceLine( vecSrc, vecTarget, MASK_SOLID, pPlayer, COLLISION_GROUP_PLAYER_MOVEMENT, &tr); //UTIL_TraceHull( vecSrc, vecTarget, WorldAlignMins(), WorldAlignMaxs(), MASK_SOLID, pPlayer, TFCOLLISION_GROUP_OBJECT, &tr ); m_vecBuildOrigin = tr.endpos; bool bTryToPlaceGroundVersion = false; if ( tr.allsolid || (tr.fraction == 1.0) ) { bTryToPlaceGroundVersion = true; } else { // Make sure we're planting on the world CBaseEntity *pEntity = tr.m_pEnt; if ( pEntity != GetWorldEntity() ) { bTryToPlaceGroundVersion = true; } } // Make sure the wall we've touched is vertical if ( !bTryToPlaceGroundVersion && fabs(tr.plane.normal.z) > 0.3 ) { bTryToPlaceGroundVersion = true; } // Aborting? if ( bTryToPlaceGroundVersion ) { // We couldn't find a wall, so try and place a ground version instead if ( GetTeamNumber() == TEAM_HUMANS ) { SetModel( RESUPPLY_GROUND_MODEL_HUMAN ); } else { SetModel( RESUPPLY_GROUND_MODEL ); } UTIL_SetSize(this, RESUPPLY_GROUND_MINS, RESUPPLY_GROUND_MAXS); m_vecBuildMins = WorldAlignMins() - Vector( 4,4,0 ); m_vecBuildMaxs = WorldAlignMaxs() + Vector( 4,4,0 ); return BaseClass::CalculatePlacement( pPlayer ); } SetupAttachedVersion(); m_vecBuildMins = WorldAlignMins() - Vector( 4,4,0 ); m_vecBuildMaxs = WorldAlignMaxs() + Vector( 4,4,0 ); // Set the angles vecForward = tr.plane.normal; SetLocalAngles( QAngle( 0, UTIL_VecToYaw( vecForward ), 0 ) ); // Trace back from the corners Vector vecMins, vecMaxs, vecModelMins, vecModelMaxs; const model_t *pModel = GetModel(); modelinfo->GetModelBounds( pModel, vecModelMins, vecModelMaxs ); // Check the four build points Vector vecPointCheck = (vecForward * 32); Vector vecUp = Vector(0,0,1); Vector vecRight; CrossProduct( vecUp, vecForward, vecRight ); float flWidth = fabs(vecModelMaxs.y - vecModelMins.y) * 0.5; float flHeight = fabs(vecModelMaxs.z - vecModelMins.z) * 0.5; bool bResult = true; if ( bResult ) { bResult = CheckBuildPoint( m_vecBuildOrigin + (vecRight * flWidth) + (vecUp * flHeight), vecPointCheck ); } if ( bResult ) { bResult = CheckBuildPoint( m_vecBuildOrigin + (vecRight * flWidth) - (vecUp * flHeight), vecPointCheck ); } if ( bResult ) { bResult = CheckBuildPoint( m_vecBuildOrigin - (vecRight * flWidth) + (vecUp * flHeight), vecPointCheck ); } if ( bResult ) { bResult = CheckBuildPoint( m_vecBuildOrigin - (vecRight * flWidth) - (vecUp * flHeight), vecPointCheck ); } AttemptToFindPower(); return bResult; }