void MM_ClipVelocity2D ( float *in, float *normal, float *out, float overbounce ) { float backoff; float dir_z; float normal2[ 3 ]; if( normal[ 2 ] >= 0.70f ) { if( in[ 0 ] == 0.0f && in[ 1 ] == 0.0f ) { VectorClear( out ); return; } normal2[ 0 ] = in[ 0 ] + DotProduct2D( in, normal ); normal2[ 1 ] = in[ 1 ] + DotProduct2D( in, normal ); normal2[ 2 ] = normal[ 2 ] * DotProduct2D( in, in ); VectorNormalize( normal2 ); dir_z = -normal2[ 2 ]; out[ 0 ] = in[ 0 ]; out[ 1 ] = in[ 1 ]; out[ 2 ] = DotProduct2D( in, normal2 ) / -normal2[ 2 ]; } else { backoff = DotProduct2D( in, normal ); if( backoff < 0 ) backoff *= overbounce; else backoff /= overbounce; out[ 0 ] = in[ 0 ] - normal[ 0 ] * backoff; out[ 1 ] = in[ 1 ] - normal[ 1 ] * backoff; out[ 2 ] = -( backoff * normal[ 2 ] ); } }
int CWeaponCrowbar::WeaponMeleeAttack1Condition( float flDot, float flDist ) { // Attempt to lead the target (needed because citizens can't hit manhacks with the crowbar!) CAI_BaseNPC *pNPC = GetOwner()->MyNPCPointer(); CBaseEntity *pEnemy = pNPC->GetEnemy(); if (!pEnemy) return COND_NONE; Vector vecVelocity; vecVelocity = pEnemy->GetSmoothedVelocity( ); // Project where the enemy will be in a little while float dt = sk_crowbar_lead_time.GetFloat(); dt += random->RandomFloat( -0.3f, 0.2f ); if ( dt < 0.0f ) dt = 0.0f; Vector vecExtrapolatedPos; VectorMA( pEnemy->WorldSpaceCenter(), dt, vecVelocity, vecExtrapolatedPos ); Vector vecDelta; VectorSubtract( vecExtrapolatedPos, pNPC->WorldSpaceCenter(), vecDelta ); if ( fabs( vecDelta.z ) > 70 ) { return COND_TOO_FAR_TO_ATTACK; } Vector vecForward = pNPC->BodyDirection2D( ); vecDelta.z = 0.0f; float flExtrapolatedDist = Vector2DNormalize( vecDelta.AsVector2D() ); if ((flDist > 64) && (flExtrapolatedDist > 64)) { return COND_TOO_FAR_TO_ATTACK; } float flExtrapolatedDot = DotProduct2D( vecDelta.AsVector2D(), vecForward.AsVector2D() ); if ((flDot < 0.7) && (flExtrapolatedDot < 0.7)) { return COND_NOT_FACING_ATTACK; } return COND_CAN_MELEE_ATTACK1; }
//----------------------------------------------------------------------------- // Purpose: // Input : flDot - // flDist - // Output : int //----------------------------------------------------------------------------- int CNPC_Bug_Warrior::MeleeAttack1Conditions( float flDot, float flDist ) { if ( ( gpGlobals->curtime - m_flLastAttackTime ) < 1.0f ) return 0; #if 0 float flPrDist, flPrDot; Vector vecPrPos; Vector2D vec2DPrDir; //Get our likely position in one second UTIL_GetPredictedPosition( GetEnemy(), 0.5f, &vecPrPos ); flPrDist = ( vecPrPos - GetAbsOrigin() ).Length(); vec2DPrDir = ( vecPrPos - GetAbsOrigin() ).AsVector2D(); Vector vecBodyDir; BodyDirection2D( &vecBodyDir ); Vector2D vec2DBodyDir = vecBodyDir.AsVector2D(); flPrDot = DotProduct2D (vec2DPrDir, vec2DBodyDir ); if ( flPrDist > BUG_WARRIOR_MELEE1_RANGE ) return COND_TOO_FAR_TO_ATTACK; if ( flPrDot < 0.5f ) return COND_NOT_FACING_ATTACK; #else if ( flDist > BUG_WARRIOR_MELEE1_RANGE ) return COND_TOO_FAR_TO_ATTACK; if ( flDot < 0.5f ) return COND_NOT_FACING_ATTACK; #endif return COND_CAN_MELEE_ATTACK1; }
//----------------------------------------------------------------------------- // Animation event handlers //----------------------------------------------------------------------------- void CWeaponCrowbar::HandleAnimEventMeleeHit( animevent_t *pEvent, CBaseCombatCharacter *pOperator ) { // Trace up or down based on where the enemy is... // But only if we're basically facing that direction Vector vecDirection; AngleVectors( GetAbsAngles(), &vecDirection ); CBaseEntity *pEnemy = pOperator->MyNPCPointer() ? pOperator->MyNPCPointer()->GetEnemy() : NULL; if ( pEnemy ) { Vector vecDelta; VectorSubtract( pEnemy->WorldSpaceCenter(), pOperator->Weapon_ShootPosition(), vecDelta ); VectorNormalize( vecDelta ); Vector2D vecDelta2D = vecDelta.AsVector2D(); Vector2DNormalize( vecDelta2D ); if ( DotProduct2D( vecDelta2D, vecDirection.AsVector2D() ) > 0.8f ) { vecDirection = vecDelta; } } Vector vecEnd; VectorMA( pOperator->Weapon_ShootPosition(), 50, vecDirection, vecEnd ); CBaseEntity *pHurt = pOperator->CheckTraceHullAttack( pOperator->Weapon_ShootPosition(), vecEnd, Vector(-16,-16,-16), Vector(36,36,36), sk_npc_dmg_crowbar.GetInt(), DMG_CLUB, 0.75 ); // did I hit someone? if ( pHurt ) { // play sound WeaponSound( MELEE_HIT ); // Fake a trace impact, so the effects work out like a player's crowbaw trace_t traceHit; UTIL_TraceLine( pOperator->Weapon_ShootPosition(), pHurt->GetAbsOrigin(), MASK_SHOT_HULL, pOperator, COLLISION_GROUP_NONE, &traceHit ); ImpactEffect( traceHit ); } else { WeaponSound( MELEE_MISS ); } }
int CWeaponStunStick::WeaponMeleeAttack1Condition( float flDot, float flDist ) { // Attempt to lead the target (needed because citizens can't hit manhacks with the crowbar!) CAI_BaseNPC *pNPC = GetOwner()->MyNPCPointer(); CBaseEntity *pEnemy = pNPC->GetEnemy(); if (!pEnemy) return COND_NONE; Vector vecVelocity; AngularImpulse angVelocity; pEnemy->GetVelocity( &vecVelocity, &angVelocity ); // Project where the enemy will be in a little while, add some randomness so he doesn't always hit float dt = sk_crowbar_lead_time.GetFloat(); dt += random->RandomFloat( -0.3f, 0.2f ); if ( dt < 0.0f ) dt = 0.0f; Vector vecExtrapolatedPos; VectorMA( pEnemy->WorldSpaceCenter(), dt, vecVelocity, vecExtrapolatedPos ); Vector vecDelta; VectorSubtract( vecExtrapolatedPos, pNPC->WorldSpaceCenter(), vecDelta ); if ( fabs( vecDelta.z ) > 70 ) { return COND_TOO_FAR_TO_ATTACK; } Vector vecForward = pNPC->BodyDirection2D( ); vecDelta.z = 0.0f; float flExtrapolatedDot = DotProduct2D( vecDelta.AsVector2D(), vecForward.AsVector2D() ); if ((flDot < 0.7) && (flExtrapolatedDot < 0.7)) { return COND_NOT_FACING_ATTACK; } float flExtrapolatedDist = Vector2DNormalize( vecDelta.AsVector2D() ); if( pEnemy->IsPlayer() ) { //Vector vecDir = pEnemy->GetSmoothedVelocity(); //float flSpeed = VectorNormalize( vecDir ); // If player will be in front of me in one-half second, clock his arse. Vector vecProjectEnemy = pEnemy->GetAbsOrigin() + (pEnemy->GetAbsVelocity() * 0.35); Vector vecProjectMe = GetAbsOrigin(); if( (vecProjectMe - vecProjectEnemy).Length2D() <= 48.0f ) { return COND_CAN_MELEE_ATTACK1; } } /* if( metropolice_move_and_melee.GetBool() ) { if( pNPC->IsMoving() ) { flTargetDist *= 1.5f; } } */ float flTargetDist = 48.0f; if ((flDist > flTargetDist) && (flExtrapolatedDist > flTargetDist)) { return COND_TOO_FAR_TO_ATTACK; } return COND_CAN_MELEE_ATTACK1; }
void CWeaponStunStick::Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ) { switch( pEvent->event ) { case EVENT_WEAPON_MELEE_HIT: { // Trace up or down based on where the enemy is... // But only if we're basically facing that direction Vector vecDirection; AngleVectors( GetAbsAngles(), &vecDirection ); CBaseEntity *pEnemy = pOperator->MyNPCPointer() ? pOperator->MyNPCPointer()->GetEnemy() : NULL; if ( pEnemy ) { Vector vecDelta; VectorSubtract( pEnemy->WorldSpaceCenter(), pOperator->Weapon_ShootPosition(), vecDelta ); VectorNormalize( vecDelta ); Vector2D vecDelta2D = vecDelta.AsVector2D(); Vector2DNormalize( vecDelta2D ); if ( DotProduct2D( vecDelta2D, vecDirection.AsVector2D() ) > 0.8f ) { vecDirection = vecDelta; } } Vector vecEnd; VectorMA( pOperator->Weapon_ShootPosition(), 32, vecDirection, vecEnd ); // Stretch the swing box down to catch low level physics objects CBaseEntity *pHurt = pOperator->CheckTraceHullAttack( pOperator->Weapon_ShootPosition(), vecEnd, Vector(-16,-16,-40), Vector(16,16,16), GetDamageForActivity( GetActivity() ), DMG_CLUB, 0.5f, false ); // did I hit someone? if ( pHurt ) { // play sound WeaponSound( MELEE_HIT ); CBasePlayer *pPlayer = ToBasePlayer( pHurt ); CNPC_MetroPolice *pCop = dynamic_cast<CNPC_MetroPolice *>(pOperator); bool bFlashed = false; if ( pCop != NULL && pPlayer != NULL ) { // See if we need to knock out this target if ( pCop->ShouldKnockOutTarget( pHurt ) ) { float yawKick = random->RandomFloat( -48, -24 ); //Kick the player angles pPlayer->ViewPunch( QAngle( -16, yawKick, 2 ) ); color32 white = {255,255,255,255}; UTIL_ScreenFade( pPlayer, white, 0.2f, 1.0f, FFADE_OUT|FFADE_PURGE|FFADE_STAYOUT ); bFlashed = true; pCop->KnockOutTarget( pHurt ); break; } else { // Notify that we've stunned a target pCop->StunnedTarget( pHurt ); } } // Punch angles if ( pPlayer != NULL && !(pPlayer->GetFlags() & FL_GODMODE) ) { float yawKick = random->RandomFloat( -48, -24 ); //Kick the player angles pPlayer->ViewPunch( QAngle( -16, yawKick, 2 ) ); Vector dir = pHurt->GetAbsOrigin() - GetAbsOrigin(); // If the player's on my head, don't knock him up if ( pPlayer->GetGroundEntity() == pOperator ) { dir = vecDirection; dir.z = 0; } VectorNormalize(dir); dir *= 500.0f; //If not on ground, then don't make them fly! if ( !(pPlayer->GetFlags() & FL_ONGROUND ) ) dir.z = 0.0f; //Push the target back pHurt->ApplyAbsVelocityImpulse( dir ); if ( !bFlashed ) { color32 red = {128,0,0,128}; UTIL_ScreenFade( pPlayer, red, 0.5f, 0.1f, FFADE_IN ); } // Force the player to drop anyting they were holding pPlayer->ForceDropOfCarriedPhysObjects(); } // do effect? } else { WeaponSound( MELEE_MISS ); } } break; default: BaseClass::Operator_HandleAnimEvent( pEvent, pOperator ); break; } }
void CHL2MP_Player::KickAttack(void) { if (!IsDead()) { CBaseViewModel *vm = GetViewModel(1); if (vm) { int idealSequence = vm->SelectWeightedSequence(ACT_VM_PRIMARYATTACK); if (idealSequence >= 0) { vm->SendViewModelMatchingSequence(idealSequence); m_flNextKickAttack = gpGlobals->curtime + vm->SequenceDuration(idealSequence) - 0.5f; } QAngle recoil = QAngle(random->RandomFloat(1.0f, 2.0f), random->RandomFloat(-1.0f, 1.0f), 0); this->ViewPunch(recoil); // Trace up or down based on where the enemy is... // But only if we're basically facing that direction Vector vecDirection; int kick_maxrange = 120; AngleVectors(QAngle(clamp(EyeAngles().x, 20, kick_maxrange), EyeAngles().y, EyeAngles().z), &vecDirection); CBaseEntity *pEnemy = MyNPCPointer() ? MyNPCPointer()->GetEnemy() : NULL; if (pEnemy) { Vector vecDelta; VectorSubtract(pEnemy->WorldSpaceCenter(), Weapon_ShootPosition(), vecDelta); VectorNormalize(vecDelta); Vector2D vecDelta2D = vecDelta.AsVector2D(); Vector2DNormalize(vecDelta2D); if (DotProduct2D(vecDelta2D, vecDirection.AsVector2D()) > 0.8f) { vecDirection = vecDelta; } } Vector vecEnd; VectorMA(Weapon_ShootPosition(), 50, vecDirection, vecEnd); trace_t tr; UTIL_TraceHull(Weapon_ShootPosition(), vecEnd, Vector(-16, -16, -16), Vector(16, 16, 16), MASK_SHOT_HULL, this, COLLISION_GROUP_NONE, &tr); // did I hit someone? float KickDamageMult = 50 + (1 * ((fabs(GetAbsVelocity().x) + fabs(GetAbsVelocity().y) + fabs(GetAbsVelocity().z)) / 48)); float KickThrowForceMult = 20 + (1 * ((fabs(GetAbsVelocity().x) + fabs(GetAbsVelocity().y) + fabs(GetAbsVelocity().z)) / 48)); DevMsg("Kicking at %.2f of damage!\n", KickDamageMult); DevMsg("Kicking at %.2f of force!\n", KickThrowForceMult); if (tr.m_pEnt) { if (!(tr.m_pEnt)) { // return; } else { CBasePropDoor *pDoor = dynamic_cast<CBasePropDoor*>((CBaseEntity*)tr.m_pEnt); if (pDoor) { if (pDoor->HasSpawnFlags(SF_BREAKABLE_BY_PLAYER)) { AngularImpulse angVelocity(random->RandomFloat(0, 45), 18, random->RandomFloat(-45, 45)); pDoor->PlayBreakOpenSound(); pDoor->BreakDoor(Weapon_ShootPosition(), angVelocity); return; } pDoor->PlayBreakFailSound(); pDoor->KickFail(); return; } CBaseEntity *Victim = this->CheckTraceHullAttack(Weapon_ShootPosition(), vecEnd, Vector(-16, -16, -16), Vector(16, 16, 16), KickDamageMult, DMG_CRUSH, KickThrowForceMult, true); if (Victim) { EmitSound("HL2Player.kick_body"); return; } } } UTIL_TraceLine(Weapon_ShootPosition(), vecEnd, MASK_SHOT_HULL, this, COLLISION_GROUP_NONE, &tr);//IF we hit anything else if (tr.DidHit()) { EmitSound("HL2Player.kick_wall"); } else { EmitSound("HL2Player.kick_fire"); } } } }
void CHostageImprov::__MAKE_VHOOK(OnUpdate)(float deltaT) { if (!IsAlive() || cv_hostage_stop.value > 0.0f) return; if (m_blinkTimer.IsElapsed()) { if (m_scaredTimer.IsElapsed() && m_animateState.GetPerformance() != HostageAnimateState::Afraid) { m_blinkTimer.Start(RANDOM_FLOAT(3, 10)); m_blinkCounter = RANDOM_LONG(2, 4); } else { m_blinkTimer.Start(RANDOM_FLOAT(0.5f, 2.0f)); m_blinkCounter = RANDOM_LONG(1, 2); } } if (m_blinkCounter) { m_hostage->pev->body = 1; --m_blinkCounter; } else { m_hostage->pev->body = 0; } UpdateGrenadeReactions(); UpdateDelayedChatter(); UpdateVision(); m_behavior.Update(); m_actualVel.x = m_hostage->pev->origin.x - m_lastPosition.x; m_actualVel.y = m_hostage->pev->origin.y - m_lastPosition.y; const float runSpeed = 289.0f; const float walkSpeed = 9.0f; const float fallVelocity = -1000.0f; const float safeTime = 0.4f; if (IsOnGround()) { if (IsCrouching()) { if (m_actualVel.LengthSquared() > 9.0f) { if (m_animateState.GetPerformance() != HostageAnimateState::CrouchWalk) { m_animateState.Reset(); m_animateState.SetPerformance(HostageAnimateState::CrouchWalk); ClearLookAt(); if (m_scaredTimer.IsElapsed() && m_animateState.GetPerformance() != HostageAnimateState::Afraid) m_animateState.AddSequence(this, ACT_CROUCH_WALK, 99.9, 2.0); else m_animateState.AddSequence(this, ACT_CROUCH_WALK_SCARED, 99.9, 2.0); } } else if (m_animateState.GetPerformance() != HostageAnimateState::Crouch) { m_animateState.Reset(); m_animateState.SetPerformance(HostageAnimateState::Crouch); if (m_scaredTimer.IsElapsed()) m_animateState.AddSequence(this, ACT_CROUCH_IDLE, 99.9); else m_animateState.AddSequence(this, ACT_CROUCH_IDLE_SCARED); } } else { UTIL_MakeVectors(m_hostage->pev->angles); float dot = DotProduct2D(gpGlobals->v_forward, m_actualVel); if (dot < -3.0f) { if (m_animateState.GetPerformance() != HostageAnimateState::Walk) { m_animateState.Reset(); m_animateState.SetPerformance(HostageAnimateState::Walk); ClearLookAt(); float speed; if (m_actualVel.LengthSquared() > runSpeed) speed = 2.0f; else speed = 1.0f; m_animateState.AddSequence(this, ACT_WALK_BACK, 99.9, speed); } } else { if (m_actualVel.LengthSquared() > runSpeed) { if (m_animateState.GetPerformance() != HostageAnimateState::Run) { m_animateState.Reset(); m_animateState.SetPerformance(HostageAnimateState::Run); ClearLookAt(); if (m_scaredTimer.IsElapsed() && m_animateState.GetPerformance() != HostageAnimateState::Afraid && !m_behavior.IsState(&m_escapeState)) m_animateState.AddSequence(this, ACT_RUN, 99.9, 2.0); else m_animateState.AddSequence(this, ACT_RUN_SCARED, 99.9, 2.0); } } else if (m_actualVel.LengthSquared() > walkSpeed) { if (m_animateState.GetPerformance() != HostageAnimateState::Walk) { m_animateState.Reset(); m_animateState.SetPerformance(HostageAnimateState::Walk); ClearLookAt(); if (m_behavior.IsState(&m_escapeState)) { m_animateState.AddSequence(this, ACT_WALK_SNEAKY, 99.9, 1.5); } else if (m_scaredTimer.IsElapsed() && m_animateState.GetPerformance() != HostageAnimateState::Afraid) { m_animateState.AddSequence(this, ACT_WALK, 99.9, 1.5); } else m_animateState.AddSequence(this, ACT_WALK_SCARED, 99.9, 1.5); } } else { if (m_animateState.GetPerformance() == HostageAnimateState::Walk || m_animateState.GetPerformance() == HostageAnimateState::Run) m_animateState.Reset(); UpdateStationaryAnimation(); } } } } else if (m_hostage->pev->velocity.z < fallVelocity && m_animateState.GetPerformance() != HostageAnimateState::Fall) { m_animateState.Reset(); m_animateState.SetPerformance(HostageAnimateState::Fall); m_animateState.AddSequence(this, ACT_FALL, 99.9); } if (!m_collisionTimer.HasStarted() || m_collisionTimer.IsGreaterThen(safeTime)) SetKnownGoodPosition(m_lastPosition); m_lastPosition = m_hostage->pev->origin; m_animateState.OnUpdate(this); }
// for backwards compatability vec_t Vector2D::Dot(const Vector2D& vOther) const { return DotProduct2D(*this, vOther); }