void GravityGun::Update( float dt ) { if( !IsWeaponSelected() ) return; // Vector3 vOwnerMuzzlePos = rWeaponSystem.m_vMuzzlePosition + rWeaponSystem.m_vMuzzleDirection * 0.25f // + rWeaponSystem.m_vMuzzleDir_Up * 0.90f; Vector3 vOwnerMuzzlePos = m_MuzzleEndWorldPose.vPosition; CCopyEntity *pTarget = m_Target.GetRawPtr(); if( pTarget ) { // calc the translation from the center of the target to the muzzle position Vector3 vDist = vOwnerMuzzlePos - pTarget->GetWorldPosition(); float fDistSq = Vec3LengthSq(vDist); if( m_fMaxRange * m_fMaxRange < fDistSq ) { m_iHoldingTargetToggle = 0; // m_pTarget->pPhysicsActor->SetAllowFreezing( true ); m_Target.Reset(); return; } STrace tr; tr.bvType = BVTYPE_DOT; tr.vStart = vOwnerMuzzlePos; Vector3 vGoal = pTarget->GetWorldPosition(); tr.vGoal = vGoal; tr.sTraceType = TRACETYPE_IGNORE_NOCLIP_ENTITIES; /* CTrace tr; tr.BVType = BVTYPE_DOT; tr.vStart = &vOwnerMuzzlePos; tr.vGoal = &pTarget->GetWorldPosition(); tr.TypeFlags = CTrace::FLAG_IGNORE_NOCLIP_ENTITIES;//TRACETYPE_IGNORE_NOCLIP_ENTITIES; */ // check trace CStageSharedPtr pStage = m_pStage.lock(); if( pStage ) pStage->ClipTrace( tr ); if( tr.pTouchedEntity != pTarget ) { // found an obstacle between the player and the target object // - unable to hold the target any more m_iHoldingTargetToggle = 0; // m_pTarget->pPhysicsActor->SetAllowFreezing( true ); m_Target.Reset(); return; } if( fDistSq < m_fGraspRange * m_fGraspRange || m_aTriggerState[1] == 1 ) { // the gravity gun is holding the target object // account for the target object's size so that it does not bump into the shooter float fDist = sqrtf(fDistSq); Vector3 vDir = vDist / fDist; // normalization fDist -= ( pTarget->fRadius + 0.2f ); vDist = vDir * fDist; // calc relative velocity Vector3 vRVel = pTarget->Velocity() - m_vMuzzleEndVelocity; Vector3 vForce; // vForce = m_fPosGain * vDist - m_fSpeedGain * vRVel; // m_pTarget->ApplyWorldImpulse( vForce, m_pTarget->GetWorldPosition()); if( 6.0f < fDist ) vForce = vDir * 6.0f * 2.5f; else if( fDist < 0.6f ) vForce = vDir * fDist * 8.0f; else // vForce = vDir * fDist * 2.5f; vForce = vDir * ( fDist * 2.0f + 3.0f ); vForce += m_vMuzzleEndVelocity; physics::CActor *pPhysicsActor = pTarget->GetPrimaryPhysicsActor(); if( pPhysicsActor ) pPhysicsActor->SetLinearVelocity( vForce ); /* Vector3 vPos = m_pTarget->pPhysicsActor->GetPosition(); Vector3 vVel = m_pTarget->pPhysicsActor->GetVelocity(); SmoothCD( vPos, vPos + vDist, vVel, 0.25f, dt ); if( 12.0f * 12.0f < Vec3LengthSq(vVel) ) { Vec3Normalize( vVel, vVel ); vVel *= 12.0f; } m_pTarget->pPhysicsActor->SetVelocity( vVel ); */ return; } else { // lost control of the target m_iHoldingTargetToggle = 0; ReleaseObject(); return; } } }
void CBE_Enemy::OnDestroyed( CCopyEntity* pCopyEnt ) { // explosion - usu. done by texture animation CCopyEntityDesc explosion; explosion.pBaseEntityHandle = &m_Explosion; explosion.SetWorldPose( pCopyEnt->GetWorldPose() ); explosion.vVelocity = Vector3(0,0,0); this->m_pStage->CreateEntity( explosion ); // avoid overlaps with fragment entities pCopyEnt->bNoClip = true; LOG_PRINT( " An enemy entity destroyed - velocity: " + to_string(pCopyEnt->Velocity()) ); CCopyEntity* pFragEntity; // MsgBoxFmt( "%s destroyed - creating %d fragments", pCopyEnt->GetName().c_str(), m_iNumFragments ); const int num_fragments = m_iNumFragments; for(int i=0; i<num_fragments; i++) { const Fragment& frag = m_aFragment[i]; CCopyEntityDesc& rFrag = explosion; // reuse desc object rFrag.pBaseEntityHandle = &m_aFragment[i].BaseEntity; rFrag.SetWorldPosition( pCopyEnt->GetWorldPose() * frag.vOffset ); // D3DXVec3TransformCoord( &vWorldFragmentOffset, &m_avFragmentOffset[i], &pCopyEnt->GetOrientation() ); // rFrag.vPosition = pCopyEnt->GetWorldPosition() + vWorldFragmentOffset; rFrag.SetWorldOrient( pCopyEnt->GetWorldPose().matOrient ); //BSPStageBase rFrag.vVelocity = pCopyEnt->Velocity() * 0.3f + vWorldFragmentOffset * 20.0f //BSPStageBase + Vector3( RangedRand(-10.0f,10.0f), RangedRand(-8.0f,8.0f), RangedRand(-10.0f,10.0f) ); rFrag.vVelocity = Vec3RandDir() * RangedRand( frag.InitVelocity.min, frag.InitVelocity.max ) // rFrag.vVelocity = Vec3RandDir() * RangedRand( 15.5f, 35.0f ) + pCopyEnt->Velocity(); pFragEntity = this->m_pStage->CreateEntity( rFrag ); if( pFragEntity ) { physics::CActor *pPhysicsActor = pFragEntity->GetPrimaryPhysicsActor(); if( pPhysicsActor ) { pPhysicsActor->SetAngularVelocity( Vec3RandDir() * RangedRand( 0.5f, 8.0f ) ); } } } /* int num_items = m_vecRewardItem.size(); float f = 0, rand_val; for(i=0; i<m_iNumFragments; i++) { rand_val = GetRangedRand( 0.0f, 1.0f ); f += m_vecRewardItem[i].m_fProbability; if( rand_val < f ) { } } */ // leave a life item // m_pStage->CreateEntity( "s_Life", pCopyEnt->GetWorldPosition(), // Vector3(0,0,0), Vector3(0,0,1) ); }
bool GravityGun::HandleInput( int input_code, int input_type, float fParam ) { Vector3 vOwnerMuzzlePos = m_MuzzleEndWorldPose.vPosition; switch( input_code ) { case ACTION_ATK_FIRE: if( input_type == ITYPE_KEY_PRESSED ) { m_aTriggerState[0] = 1; CCopyEntity *pTarget = m_Target.GetRawPtr(); if( pTarget ) { physics::CActor *pPhysicsActor = pTarget->GetPrimaryPhysicsActor(); Vector3 vDist = vOwnerMuzzlePos - pTarget->GetWorldPosition(); float fDistSq = Vec3LengthSq(vDist); if( fDistSq < m_fGraspRange * m_fGraspRange ) { Vector3 vImpulse = m_MuzzleEndLocalPose.matOrient.GetColumn(2) * m_fPower; // shoot object // pTarget->ApplyWorldImpulse( vImpulse, m_pTarget->GetWorldPosition() ); pPhysicsActor->SetLinearVelocity( vImpulse ); // release object // m_pTarget->pPhysicsActor->SetAllowFreezing( true ); m_Target.Reset(); m_iHoldingTargetToggle = 0; return true; } } } else if( input_type == ITYPE_KEY_RELEASED ) { m_aTriggerState[0] = 0; return true; } break; case ACTION_ATK_RAISEWEAPON: case ACTION_ATK_UNLOCK_TRIGGER_SAFETY: if( input_type == ITYPE_KEY_PRESSED ) { m_aTriggerState[1] = 1; // the owner pulled the second trigger m_iHoldingTargetToggle = ~m_iHoldingTargetToggle; CCopyEntity *pTarget = m_Target.GetRawPtr(); if( !pTarget ) { // trigger is pulled and the gravity gun is not holding any object right now // - check if there is an object in the aim direction return GraspObjectInAimDirection(); } else { // trigger is pulled when the gun is holding an object // - release the object ReleaseObject(); return true; } } else if( input_type == ITYPE_KEY_RELEASED ) { m_aTriggerState[1] = 0; return true; } break; default: break; } return false; }