float UMovementComponent::SlideAlongSurface(const FVector& Delta, float Time, const FVector& Normal, FHitResult& Hit, bool bHandleImpact)
{
	if (!Hit.bBlockingHit)
	{
		return 0.f;
	}

	float PercentTimeApplied = 0.f;
	const FVector OldHitNormal = Normal;

	FVector SlideDelta = ComputeSlideVector(Delta, Time, Normal, Hit);

	if ((SlideDelta | Delta) > 0.f)
	{
		const FQuat Rotation = UpdatedComponent->GetComponentQuat();
		SafeMoveUpdatedComponent(SlideDelta, Rotation, true, Hit);

		const float FirstHitPercent = Hit.Time;
		PercentTimeApplied = FirstHitPercent;
		if (Hit.IsValidBlockingHit())
		{
			// Notify first impact
			if (bHandleImpact)
			{
				HandleImpact(Hit, FirstHitPercent * Time, SlideDelta);
			}

			// Compute new slide normal when hitting multiple surfaces.
			TwoWallAdjust(SlideDelta, Hit, OldHitNormal);

			// Only proceed if the new direction is of significant length and not in reverse of original attempted move.
			if (!SlideDelta.IsNearlyZero(1e-3f) && (SlideDelta | Delta) > 0.f)
			{
				// Perform second move
				SafeMoveUpdatedComponent(SlideDelta, Rotation, true, Hit);
				const float SecondHitPercent = Hit.Time * (1.f - FirstHitPercent);
				PercentTimeApplied += SecondHitPercent;

				// Notify second impact
				if (bHandleImpact && Hit.bBlockingHit)
				{
					HandleImpact(Hit, SecondHitPercent * Time, SlideDelta);
				}
			}
		}

		return FMath::Clamp(PercentTimeApplied, 0.f, 1.f);
	}

	return 0.f;
}
void UFloatingPawnMovement::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction)
{
	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);

	if (!PawnOwner || !UpdatedComponent || ShouldSkipUpdate(DeltaTime))
	{
		return;
	}

	const AController* Controller = PawnOwner->GetController();
	if (Controller && Controller->IsLocalController())
	{
		ApplyControlInputToVelocity(DeltaTime);
		LimitWorldBounds();
		bPositionCorrected = false;

		// Move actor
		FVector Delta = Velocity * DeltaTime;

		if (!Delta.IsNearlyZero(1e-6f))
		{
			const FVector OldLocation = UpdatedComponent->GetComponentLocation();
			const FRotator Rotation = UpdatedComponent->GetComponentRotation();
			FVector TraceStart = OldLocation;

			FHitResult Hit(1.f);
			SafeMoveUpdatedComponent(Delta, Rotation, true, Hit);

			if (Hit.IsValidBlockingHit())
			{
				HandleImpact(Hit, DeltaTime, Delta);
				// Try to slide the remaining distance along the surface.
				SlideAlongSurface(Delta, 1.f-Hit.Time, Hit.Normal, Hit, true);
			}

			// Update velocity
			// We don't want position changes to vastly reverse our direction (which can happen due to penetration fixups etc)
			if (!bPositionCorrected)
			{
				const FVector NewLocation = UpdatedComponent->GetComponentLocation();
				Velocity = ((NewLocation - OldLocation) / DeltaTime);
			}
		}
		
		// Finalize
		UpdateComponentVelocity();
	}
};
bool UInterpToMovementComponent::HandleHitWall(const FHitResult& Hit, float Time, const FVector& MoveDelta)
{
	AActor* ActorOwner = UpdatedComponent ? UpdatedComponent->GetOwner() : NULL;
	if (!CheckStillInWorld() || !ActorOwner || ActorOwner->IsPendingKill())
	{
		return true;
	}
	HandleImpact(Hit, Time, MoveDelta);

	if (ActorOwner->IsPendingKill() || !UpdatedComponent)
	{
		return true;
	}

	return false;
}
UProjectileMovementComponent::EHandleBlockingHitResult UProjectileMovementComponent::HandleBlockingHit(const FHitResult& Hit, float TimeTick, const FVector& MoveDelta, float& SubTickTimeRemaining)
{
	AActor* ActorOwner = UpdatedComponent ? UpdatedComponent->GetOwner() : NULL;
	if (!CheckStillInWorld() || !ActorOwner || ActorOwner->IsPendingKill())
	{
		return EHandleBlockingHitResult::Abort;
	}
	
	HandleImpact(Hit, TimeTick, MoveDelta);
	
	if (ActorOwner->IsPendingKill() || HasStoppedSimulation())
	{
		return EHandleBlockingHitResult::Abort;
	}

	SubTickTimeRemaining = TimeTick * (1.f - Hit.Time);
	return EHandleBlockingHitResult::Deflect;
}
void CProjectile::HandleTouch(HOBJECT hObj)
{
	if (m_bObjectRemoved) return;

	// Don't process any touches until this has been cleared...

	if (m_bProcessInvImpact) return;

	 // Let it get out of our bounding box...

	if (hObj == m_hFiredFrom) return;

	CCharacterHitBox* pHitBox = LTNULL;

	// If we've hit a character (or body), let its hit box take control...

	if (IsCharacter(hObj))
	{
       CCharacter* pChar = (CCharacter*)g_pLTServer->HandleToObject(hObj);
		if (pChar)
		{
			hObj = pChar->GetHitBox();
		}
	}
	else if (IsBody(hObj))
	{
	    Body* pBody = (Body*)g_pLTServer->HandleToObject(hObj);
		if (pBody)
		{
			hObj = pBody->GetHitBox();
		}
	}


	if (IsCharacterHitBox(hObj))
	{
        pHitBox = (CCharacterHitBox*)g_pLTServer->HandleToObject(hObj);
		if (!pHitBox) return;

		if (pHitBox->GetModelObject() == m_hFiredFrom) return;
	}


	// Don't hit our own type of projectiles (for multi-projectile weapons
	// and projectiles that stick to objects)...

	if (IsKindOf(hObj, m_hObject))
	{
        CProjectile* pObj = (CProjectile*)g_pLTServer->HandleToObject(hObj);
		if (pObj)
		{
			if (pObj->GetFiredFrom() == m_hFiredFrom)
			{
				return;
			}
		}
	}



	// See if we want to impact on this object...

    uint32 dwUsrFlags = g_pLTServer->GetObjectUserFlags(hObj);
	if (dwUsrFlags & USRFLG_IGNORE_PROJECTILES) return;

    LTBOOL bIsWorld = IsMainWorld(hObj);


	// Don't impact on non-solid objects...unless it is a CharacterHitBox
	// object...

    uint32 dwFlags = g_pLTServer->GetObjectFlags(hObj);
	if (!bIsWorld && !(dwFlags & FLAG_SOLID))
	{
		if (pHitBox)
		{
			// See if we really impacted on the box...

			if (pHitBox->DidProjectileImpact(this))
			{
				// This is the object that we really hit...

				hObj = pHitBox->GetModelObject();
			}
			else
			{
				return;
			}
		}
		else if (!(dwFlags & FLAG_RAYHIT))
		{
			// If we have ray hit set to true, projectiles should
			// impact on us too...

			return;
		}
	}


	// See if we hit the sky...

	if (bIsWorld || (OT_WORLDMODEL == g_pLTServer->GetObjectType(hObj)))
	{
		CollisionInfo info;
        g_pLTServer->GetLastCollision(&info);

		SurfaceType eType = GetSurfaceType(info);

		if (eType == ST_SKY)
		{
			RemoveObject();
			return;
		}
		else if (eType == ST_INVISIBLE)
		{
			// Update 1.002 [KLS] - If multiplayer and we hit an invisible
			// surface, just treat it like a normal surface...
			if (!IsMultiplayerGame())
			{
				m_bProcessInvImpact = LTTRUE;

				g_pLTServer->GetObjectPos(m_hObject, &m_vInvisNewPos);
				g_pLTServer->GetVelocity(m_hObject, &m_vInvisVel);
				m_vInvisNewPos += (m_vInvisVel * g_pLTServer->GetFrameTime());

				// Make sure this new position is inside the world...else
				// just blow up...

				if (LT_INSIDE == g_pLTServer->Common()->GetPointStatus(&m_vInvisNewPos))
				{
					return;
				}
			}
		}
	}


	HandleImpact(hObj);
}