Beispiel #1
0
/**	Change the Pawn's base. */
void ACharacter::SetBase( UPrimitiveComponent* NewBaseComponent, bool bNotifyPawn )
{
	if (NewBaseComponent != MovementBase)
	{
		// Verify no recursion.
		APawn* Loop = (NewBaseComponent ? Cast<APawn>(NewBaseComponent->GetOwner()) : NULL);
		for(  ; Loop!=NULL; Loop=Cast<APawn>(Loop->GetMovementBase()) )
		{
			if( Loop == this )
			{
				UE_LOG(LogCharacter, Warning, TEXT(" SetBase failed! Recursion detected. Pawn %s already based on %s."), *GetName(), *NewBaseComponent->GetName());
				return;
			}
		}

		// Set base.
		MovementBase = NewBaseComponent;

		if (Role == ROLE_Authority)
		{
			// Update replicated value
			UE_LOG(LogCharacter, Verbose, TEXT("Setting base on server for '%s' to '%s'"), *GetName(), *GetFullNameSafe(NewBaseComponent));
			RelativeMovement.MovementBase = NewBaseComponent;
			RelativeMovement.bServerHasBaseComponent = (NewBaseComponent != NULL); // Flag whether the server had a non-null base.
		}
		else
		{
			UE_LOG(LogCharacter, Verbose, TEXT("Setting base on CLIENT for '%s' to '%s'"), *GetName(), *GetFullNameSafe(NewBaseComponent));
		}

		// Update relative location/rotation
		if ( Role == ROLE_Authority || Role == ROLE_AutonomousProxy )
		{
			if (MovementBaseUtility::UseRelativePosition(MovementBase))
			{
				RelativeMovement.Location = GetActorLocation() - MovementBase->GetComponentLocation();
				RelativeMovement.Rotation = (FRotationMatrix(GetActorRotation()) * FRotationMatrix(MovementBase->GetComponentRotation()).GetTransposed()).Rotator();
			}
		}

		// Notify this actor of his new floor.
		if ( bNotifyPawn )
		{
			BaseChange();
		}

		if (MovementBase && CharacterMovement)
		{
			// Update OldBaseLocation/Rotation as those were referring to a different base
			CharacterMovement->OldBaseLocation = MovementBase->GetComponentLocation();
			CharacterMovement->OldBaseRotation = MovementBase->GetComponentRotation();
		}
	}
}
Beispiel #2
0
/**	Change the Pawn's base. */
void ACharacter::SetBase( UPrimitiveComponent* NewBaseComponent, const FName InBoneName, bool bNotifyPawn )
{
    // If NewBaseComponent is null, ignore bone name.
    const FName BoneName = (NewBaseComponent ? InBoneName : NAME_None);

    // See what changed.
    const bool bBaseChanged = (NewBaseComponent != BasedMovement.MovementBase);
    const bool bBoneChanged = (BoneName != BasedMovement.BoneName);

    if (bBaseChanged || bBoneChanged)
    {
        // Verify no recursion.
        APawn* Loop = (NewBaseComponent ? Cast<APawn>(NewBaseComponent->GetOwner()) : NULL);
        for(  ; Loop!=NULL; Loop=Cast<APawn>(Loop->GetMovementBase()) )
        {
            if( Loop == this )
            {
                UE_LOG(LogCharacter, Warning, TEXT(" SetBase failed! Recursion detected. Pawn %s already based on %s."), *GetName(), *NewBaseComponent->GetName());
                return;
            }
        }

        // Set base.
        UPrimitiveComponent* OldBase = BasedMovement.MovementBase;
        BasedMovement.MovementBase = NewBaseComponent;
        BasedMovement.BoneName = BoneName;

        if (CharacterMovement)
        {
            if (bBaseChanged)
            {
                MovementBaseUtility::RemoveTickDependency(CharacterMovement->PrimaryComponentTick, OldBase);
                MovementBaseUtility::AddTickDependency(CharacterMovement->PrimaryComponentTick, NewBaseComponent);
            }

            if (NewBaseComponent)
            {
                // Update OldBaseLocation/Rotation as those were referring to a different base
                // ... but not when handling replication for proxies (since they are going to copy this data from the replicated values anyway)
                if (!bInBaseReplication)
                {
                    CharacterMovement->SaveBaseLocation();
                }

                // Enable pre-cloth tick if we are standing on a physics object, as we need to to use post-physics transforms
                CharacterMovement->PreClothComponentTick.SetTickFunctionEnable(NewBaseComponent->IsSimulatingPhysics());
            }
            else
            {
                BasedMovement.BoneName = NAME_None; // None, regardless of whether user tried to set a bone name, since we have no base component.
                BasedMovement.bRelativeRotation = false;
                CharacterMovement->CurrentFloor.Clear();
                CharacterMovement->PreClothComponentTick.SetTickFunctionEnable(false);
            }

            if (Role == ROLE_Authority || Role == ROLE_AutonomousProxy)
            {
                BasedMovement.bServerHasBaseComponent = (BasedMovement.MovementBase != NULL); // Also set on proxies for nicer debugging.
                UE_LOG(LogCharacter, Verbose, TEXT("Setting base on %s for '%s' to '%s'"), Role == ROLE_Authority ? TEXT("Server") : TEXT("AutoProxy"), *GetName(), *GetFullNameSafe(NewBaseComponent));
            }
            else
            {
                UE_LOG(LogCharacter, Verbose, TEXT("Setting base on Client for '%s' to '%s'"), *GetName(), *GetFullNameSafe(NewBaseComponent));
            }

        }

        // Notify this actor of his new floor.
        if ( bNotifyPawn )
        {
            BaseChange();
        }
    }
}