void CFlex::DoBodyLean( void ) { CAI_NPC *myNpc = MyNPCPointer( ); if (myNpc) { Vector vecDelta; Vector vecPos; Vector vecOrigin = GetAbsOrigin(); if (m_vecPrevOrigin == vec3_origin) { m_vecPrevOrigin = vecOrigin; } vecDelta = vecOrigin - m_vecPrevOrigin; vecDelta.x = clamp( vecDelta.x, -50, 50 ); vecDelta.y = clamp( vecDelta.y, -50, 50 ); vecDelta.z = clamp( vecDelta.z, -50, 50 ); float dt = gpGlobals->curtime - GetLastThink(); bool bSkip = ((GetFlags() & (FL_FLY | FL_SWIM)) != 0) || (GetMoveParent() != NULL) || (GetGroundEntity() == NULL) || (GetGroundEntity()->IsMoving()); bSkip |= myNpc->TaskRanAutomovement() || (myNpc->GetVehicleEntity() != NULL); if (!bSkip) { if (vecDelta.LengthSqr() > m_vecPrevVelocity.LengthSqr()) { float decay = ExponentialDecay( 0.6, 0.1, dt ); m_vecPrevVelocity = m_vecPrevVelocity * (decay) + vecDelta * (1.f - decay); } else { float decay = ExponentialDecay( 0.4, 0.1, dt ); m_vecPrevVelocity = m_vecPrevVelocity * (decay) + vecDelta * (1.f - decay); } vecPos = m_vecPrevOrigin + m_vecPrevVelocity; float decay = ExponentialDecay( 0.5, 0.1, dt ); m_vecShift = m_vecShift * (decay) + (vecOrigin - vecPos) * (1.f - decay); // FIXME: Scale this m_vecLean = (vecOrigin - vecPos) * 1.0; // FIXME: Scale this } else { m_vecPrevVelocity = vecDelta; float decay = ExponentialDecay( 0.5, 0.1, dt ); m_vecShift = m_vecLean * decay; m_vecLean = m_vecShift * decay; } m_vecPrevOrigin = vecOrigin; /* DevMsg( "%.2f %.2f %.2f (%.2f %.2f %.2f)\n", m_vecLean.Get().x, m_vecLean.Get().y, m_vecLean.Get().z, vecDelta.x, vecDelta.y, vecDelta.z ); */ } }
//----------------------------------------------------------------------------- // Purpose: Called when it's time for a physically moved objects (plats, doors, etc) // to run it's game code. // All other entity thinking is done during worldspawn's think //----------------------------------------------------------------------------- void C_BaseEntity::PhysicsPyDispatchThink( bp::object thinkFunc ) { float thinkLimit = think_limit.GetFloat(); float startTime = 0.0; /* // This doesn't apply on the client, really if ( IsDormant() ) { Warning( "Dormant entity %s is thinking!!\n", GetClassname() ); Assert(0); } */ if ( thinkLimit ) { startTime = Plat_FloatTime(); } if ( thinkFunc.ptr() != Py_None ) { try { thinkFunc(); } catch(boost::python::error_already_set &) { PyErr_Print(); } } if ( thinkLimit ) { // calculate running time of the AI in milliseconds float time = ( Plat_FloatTime() - startTime ) * 1000.0f; if ( time > thinkLimit ) { #if 0 // If its an NPC print out the shedule/task that took so long CAI_BaseNPC *pNPC = MyNPCPointer(); if (pNPC && pNPC->GetCurSchedule()) { pNPC->ReportOverThinkLimit( time ); } else #endif { Msg( "CLIENT: %s(%s) thinking for %.02f ms!!!\n", GetClassname(), typeid(this).raw_name(), time ); } } } }
//----------------------------------------------------------------------------- // Purpose: Called when it's time for a physically moved objects (plats, doors, etc) // to run it's game code. // All other entity thinking is done during worldspawn's think //----------------------------------------------------------------------------- void C_BaseEntity::PhysicsDispatchThink( BASEPTR thinkFunc ) { float thinkLimit = think_limit.GetFloat(); float startTime = 0.0; /* // This doesn't apply on the client, really if ( IsDormant() ) { Warning( "Dormant entity %s is thinking!!\n", GetClassname() ); Assert(0); } */ if ( thinkLimit ) { startTime = Plat_FloatTime(); } if ( thinkFunc ) { (this->*thinkFunc)(); } if ( thinkLimit ) { // calculate running time of the AI in milliseconds float time = ( Plat_FloatTime() - startTime ) * 1000.0f; if ( time > thinkLimit ) { #if 0 // If its an NPC print out the shedule/task that took so long CAI_BaseNPC *pNPC = MyNPCPointer(); if (pNPC && pNPC->GetCurSchedule()) { pNPC->ReportOverThinkLimit( time ); } else #endif { #ifdef WIN32 Msg( "CLIENT: %s(%s) thinking for %.02f ms!!!\n", GetClassname(), typeid(this).raw_name(), time ); #else Msg( "CLIENT: %s(%s) thinking for %.02f ms!!!\n", GetClassname(), typeid(this).name(), time ); #endif } } } }
bool CFlex::EnterSceneSequence( CChoreoScene *scene, CChoreoEvent *event, bool bRestart ) { CAI_NPC *myNpc = MyNPCPointer( ); if (!myNpc) return false; // 2 seconds past current event, or 0.2 seconds past end of scene, whichever is shorter float flDuration = MIN( 2.0, MIN( event->GetEndTime() - scene->GetTime() + 2.0, scene->FindStopTime() - scene->GetTime() + 0.2 ) ); if (myNpc->IsCurSchedule( SCHED_SCENE_GENERIC )) { myNpc->AddSceneLock( flDuration ); return true; } // for now, don't interrupt sequences that don't understand being interrupted if (myNpc->GetCurSchedule()) { CAI_ScheduleBits testBits; myNpc->GetCurSchedule()->GetInterruptMask( &testBits ); testBits.Clear( COND_PROVOKED ); if (testBits.IsAllClear()) { return false; } } if (myNpc->IsInterruptable()) { if (myNpc->Get_m_hCine()) { // Assert( !(myNpc->GetFlags() & FL_FLY ) ); myNpc->ExitScriptedSequence( ); } myNpc->OnStartScene(); myNpc->SetSchedule( SCHED_SCENE_GENERIC ); myNpc->AddSceneLock( flDuration ); return true; } return false; }
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"); } } } }