void GameProjectile::update( float dt ) { GameObject::update( dt ); if ( !m_hasHit ) { Vector3 vel = velocity(); vel += Vector3( 0, -9.81f, 0 ) * dt * m_gravity; setVelocity( vel ); m_movedDistance += velocity().length() * dt; CollisionInfo cinfo; move( velocity() * dt, &cinfo ); if ( cinfo.isCollision(CollisionInfo::COLLIDE_ALL) ) hit( &cinfo ); if ( m_spinSpeed > 0.f ) setRotation( rotation() * Matrix3x3( m_spinAxis, m_spinSpeed * dt) ); } m_age += dt; if ( m_age > m_ageLimit ) m_removable = true; if ( m_movedDistance > m_maxRange ) m_removable = true; }
void GameWeapon::fire( GameCharacter* character, const Vector3& direction, bool applyRecoilError ) { assert( m_mesh ); if ( m_shells > 0 ) { // find bullet launch position Vector3 launchPos = launchPosition(); // check that we are not too close any obstacle GamePointObject* pointCollisionChecker = character->visibilityCollisionChecker(); pointCollisionChecker->setPosition( character->cell(), character->position() ); Vector3 startpoint = character->headWorldPosition(); pointCollisionChecker->moveWithoutColliding( startpoint - pointCollisionChecker->position() ); CollisionInfo cinfo; pointCollisionChecker->move( launchPos - pointCollisionChecker->position(), &cinfo ); bool removeInFirstUpdate = cinfo.isCollision(CollisionInfo::COLLIDE_ALL); fireVisuals( character ); // Apply recoil error Vector3 launchVector = direction; if ( applyRecoilError ) launchVector = Vector3( perturbVector( direction, m_accumulatedRecoilError, character->up(), character->right() ) ); // Create projectile(s) float limitangle = m_spreadConeLimitAngle; for ( int i = 0; i < m_shotsPerLaunch; ++i ) { GameProjectile* projectile = m_projectileMgr->createProjectile( m_bullet, cell(), this, launchPos, perturbVector( launchVector, limitangle, character->up(), character->right() ) ); if ( removeInFirstUpdate ) projectile->removeInNextUpdate(); } // Accumulate recoil error m_accumulatedRecoilError += m_recoilErrorPerShot; if ( m_accumulatedRecoilError > m_maxRecoilError ) m_accumulatedRecoilError = m_maxRecoilError; // Decrease shells m_shells--; } else { // Call script function for empty clip pushMethod( "signalEmpty" ); vm()->pushTable( character ); call(1, 0); m_clipEmpty = true; } // reset timer for weapon becoming ready for next shot m_fireDeltaTime = 0.f; }
bool GameDynamicObject::isVisiblePoint( const Vector3& worldPos, const Vector3& point ) const { // check if character is occluded by level geometry m_visibilityChecker->setPosition( cell(), position() ); m_visibilityChecker->moveWithoutColliding( point-m_visibilityChecker->position() ); CollisionInfo cinfo; m_visibilityChecker->move( worldPos-m_visibilityChecker->position(), &cinfo ); return !cinfo.isCollision( CollisionInfo::COLLIDE_ALL ); }