// look up rate
void AClashOfBallsBall::LookUpAtRate(float Rate)
{
	//UE_LOG(LogTemp, Warning, TEXT("LookUp/Down"));
	// calculate delta for this frame from the rate information
	AddControllerPitchInput(Rate * BaseLookUpRate * GetWorld()->GetDeltaSeconds());
}
void AZombieCharacter::Attack()
{
	//This function is used only when it's permitted by the zombie's animation instance
	//It creates a raycast in a sphere shape and checks for possible hits
	//If the hits contain our player it makes sure it applies damage to him

	//Setting up the start and end location of the raycast
	FVector StartLocation = GetMesh()->GetSocketLocation(FName("MeleeStartSocket"));
	FVector EndLocation = GetMesh()->GetSocketLocation(FName("MeleeEndSocket"));


	//Raycasting in a sphere to detect collisions
	TArray<FHitResult> HitResults;

	//Setting up the shape of the raycast
	FCollisionShape CollisionShape;
	CollisionShape.ShapeType = ECollisionShape::Sphere;
	CollisionShape.SetSphere(AttackRaycastRadius);

	//Object query parameters
	FCollisionObjectQueryParams ObjectQueryParams;
	ObjectQueryParams.AllDynamicObjects;

	//Handling ignored actors
	FCollisionQueryParams QueryParams;
	QueryParams.AddIgnoredActor(this);

	UWorld* World = GetWorld();
	if (World && ZAnimInstance->bEligibleForAttack)
	{
		//Raycasting...
		bool bHit = World->SweepMultiByObjectType(HitResults, StartLocation, EndLocation, FQuat::Identity, ObjectQueryParams, CollisionShape, QueryParams);

		//Raycast visualization
		/*FVector Center = ((EndLocation - StartLocation) / 2) + StartLocation;
		DrawDebugSphere(World, Center, AttackRaycastRadius, 20, FColor::Green, false, 2.f);*/

		//Checking for possible hits
		if (bHit)
		{
			for (auto It = HitResults.CreateIterator(); It; It++)
			{
				ARoguelikeChar* Char = Cast<ARoguelikeChar>(It->GetActor());
				if (Char && ZAnimInstance && GetCharacterMovement())
				{
					//Calling the attack function from character
					Char->TakeDamageFromZombie(Damage);
					
					//Closing the flag which checks for the attack function
					ZAnimInstance->bEligibleForAttack = false;

					//Updating with new movement speed
					GetCharacterMovement()->MaxWalkSpeed = InitialMaxWalkSpeed;
					ZAnimInstance->Speed = InitialMaxWalkSpeed;
					break;
				}
			}
		}
	}

}
Example #3
1
void ASpawnEnemy::SpawnRandomEnemy()
{
	TArray<FString> Parsed;
	TArray<FString> HowMuch;
	TArray<FString> TypeEnemy;
	const TCHAR* Delims[] = { TEXT(":"), TEXT(";") };

	float RandomNumber = (float)rand() / (float)RAND_MAX;
	int SetNumber = RandomNumber * (Enemies.Num());

	Enemies[SetNumber].ParseIntoArray(&Parsed, Delims, 2);

	int SizeOfArrayParsed = Parsed.Num() - 1;

	for (int x = 0; x <= SizeOfArrayParsed; x = x + 2) {
		HowMuch.Add(Parsed[x]);
	}
	for (int x = 1; x <= SizeOfArrayParsed; x = x + 2) {
		TypeEnemy.Add(Parsed[x]);
	}
	
	for (auto Itr(HowMuch.CreateIterator()); Itr; Itr++) {
		APawn* NewPawn = NULL;
		FVector BoxOnWorld = GetActorLocation();
		FRotator RotatorBoxOnWorld = GetActorRotation();
		FBox BoxInfo = GetComponentsBoundingBox();
		FVector BoxSize = BoxInfo.GetSize();

		if (TypeEnemy[Itr.GetIndex()] == "PegEnemyLight") 
		{
			EnemyClass = PegLightEnemyClass;
		}
		else if (TypeEnemy[Itr.GetIndex()] == "PegDarkEnemy") {
			EnemyClass = PegDarkEnemyClass;
		}
		else if (TypeEnemy[Itr.GetIndex()] == "GarbageEnemy") {
			EnemyClass = GarbageEnemyClass;
		}
		else if (TypeEnemy[Itr.GetIndex()] == "MeleeBookEnemy") {
			EnemyClass = MeleeBookEnemyClass;
		}
		else if (TypeEnemy[Itr.GetIndex()] == "RangeBookEnemy") {
			EnemyClass = RangeBookEnemyClass;
		}
		else if (TypeEnemy[Itr.GetIndex()] == "PianoChargeEnemy") {
			EnemyClass = PianoEnemyClass;
		}
		else if (TypeEnemy[Itr.GetIndex()] == "BarrelChargeEnemy") {
			EnemyClass = BarrelEnemyClass;
		}
		else if (TypeEnemy[Itr.GetIndex()] == "FridgeChargeEnemy") {
			EnemyClass = FridgeEnemyClass;
		}

		if (GetWorld())
		{
			int32 MyShinyNewInt = FCString::Atoi(*HowMuch[Itr.GetIndex()]);
			for (int x = 1; x <= MyShinyNewInt; x++) {

				float random = (float)rand() / (float)RAND_MAX;
				float randomy = (float)rand() / (float)RAND_MAX;

				int xValue = 1 + random * ((3) - (1));
				int yValue = 1 + randomy * ((3) - (1));

				float z, y;

				if (xValue == 1)
					z = random * (0 + (BoxSize[0] / 2));
				else
					z = random * (0 - (BoxSize[0] / 2));
				if (yValue == 1)
					y = random * (0 + (BoxSize[1] / 2));
				else
					y = random * (0 - (BoxSize[1] / 2));

				BoxOnWorld[0] += z;
				BoxOnWorld[1] += y;

				if (ShouldSpawnEnemies)
				{
					if (BoxInfo.IsInside(BoxOnWorld))
					{
						NewPawn = GetWorld()->SpawnActor<AAI_BasicEnemy>(EnemyClass, BoxOnWorld, RotatorBoxOnWorld);
						FVector BoxOnWorld = GetActorLocation();
						if (NewPawn != NULL)
						{
							if (NewPawn->Controller == NULL)
							{
								NewPawn->SpawnDefaultController();
							}
							if (BehaviorTree != NULL)
							{
								AAIController* AIController = Cast<AAIController>(NewPawn->Controller);
								if (AIController != NULL)
								{
									AIController->RunBehaviorTree(BehaviorTree);
								}
							}
						}

						//AI Direct laten aanvallen wanneer die spawnt!
						AAI_BasicController* Controller = (AAI_BasicController*)NewPawn->GetController();
						Controller->FoundPlayer();
						Controller->AISetAttackState();
					}
				}
			}
		}
	}
	EnemyClass = NULL;
	APawn* NewPawn = NULL;
}
float APhysicsVolume::GetGravityZ() const
{
	return GetWorld()->GetGravityZ();
}
Example #5
0
void APawn::PostNetReceiveLocationAndRotation()
{
	// always consider Location as changed if we were spawned this tick as in that case our replicated Location was set as part of spawning, before PreNetReceive()
	if( (ReplicatedMovement.Location == GetActorLocation() && ReplicatedMovement.Rotation == GetActorRotation()) && (CreationTime != GetWorld()->TimeSeconds) )
	{
		return;
	}

	if( Role == ROLE_SimulatedProxy )
	{
		// Correction to make sure pawn doesn't penetrate floor after replication rounding
		ReplicatedMovement.Location.Z += 0.01f;

		const FVector OldLocation = GetActorLocation();
		const FQuat OldRotation = GetActorQuat();
		SetActorLocationAndRotation(ReplicatedMovement.Location, ReplicatedMovement.Rotation, /*bSweep=*/ false);

		INetworkPredictionInterface* PredictionInterface = Cast<INetworkPredictionInterface>(GetMovementComponent());
		if (PredictionInterface)
		{
			PredictionInterface->SmoothCorrection(OldLocation, OldRotation, ReplicatedMovement.Location, ReplicatedMovement.Rotation.Quaternion());
		}
	}
}
void APluginsCharacter::LookUpAtRate(float Rate)
{
	// calculate delta for this frame from the rate information
	AddControllerPitchInput(Rate * BaseLookUpRate * GetWorld()->GetDeltaSeconds());
}
bool UNavigationComponent::GeneratePathTo(const FVector& GoalLocation, TSharedPtr<const FNavigationQueryFilter> QueryFilter)
{
	if (GetWorld() == NULL || GetWorld()->GetNavigationSystem() == NULL || GetOuter() == NULL)
	{
		return false;
	}

	// Make sure we're trying to path to the closest valid location TO that location rather than the absolute location.
	// After talking with Steve P., if we need to ever allow pathing WITHOUT projecting to nav-mesh, it will probably be
	// best to do so using a flag while keeping this as the default behavior.  NOTE:` If any changes to this behavior
	// are made, you should search for other places in UNavigationComponent using NavMeshGoalLocation and make sure the
	// behavior remains consistent.
	
	// make sure that nav data is updated
	GetNavData();

	const FNavAgentProperties* NavAgentProps = MyNavAgent ? MyNavAgent->GetNavAgentProperties() : NULL;
	if (NavAgentProps != NULL)
	{
		FVector NavMeshGoalLocation;

#if ENABLE_VISUAL_LOG
		UE_VLOG_LOCATION(GetOwner(), GoalLocation, 34, FColor(0,127,14), TEXT("GoalLocation"));
		const FVector ProjectionExtent = MyNavData ? MyNavData->GetDefaultQueryExtent() : FVector(DEFAULT_NAV_QUERY_EXTENT_HORIZONTAL, DEFAULT_NAV_QUERY_EXTENT_HORIZONTAL, DEFAULT_NAV_QUERY_EXTENT_VERTICAL);
		UE_VLOG_BOX(GetOwner(), FBox(GoalLocation - ProjectionExtent, GoalLocation + ProjectionExtent), FColor::Green, TEXT_EMPTY);
#endif

		if (ProjectPointToNavigation(GoalLocation, NavMeshGoalLocation) == QuerySuccess)
		{
			UE_VLOG_SEGMENT(GetOwner(), GoalLocation, NavMeshGoalLocation, FColor::Blue, TEXT_EMPTY);
			UE_VLOG_LOCATION(GetOwner(), NavMeshGoalLocation, 34, FColor::Blue, TEXT_EMPTY);
			
			UNavigationSystem* NavSys = GetWorld()->GetNavigationSystem();
			FPathFindingQuery Query(MyNavData, MyNavAgent->GetNavAgentLocation(), NavMeshGoalLocation, QueryFilter);

			const EPathFindingMode::Type Mode = bDoHierarchicalPathfinding ? EPathFindingMode::Hierarchical : EPathFindingMode::Regular;
			FPathFindingResult Result = NavSys->FindPathSync(*MyNavAgent->GetNavAgentProperties(), Query, Mode);

			// try reversing direction
			if (bSearchFromGoalWhenOutOfNodes && !bDoHierarchicalPathfinding &&
				Result.Path.IsValid() && Result.Path->DidSearchReachedLimit())
			{
				// quick check if path exists
				bool bPathExists = false;
				{
					DECLARE_SCOPE_CYCLE_COUNTER(TEXT("Pathfinding: HPA* test time"), STAT_Navigation_PathVerifyTime, STATGROUP_Navigation);
					bPathExists = NavSys->TestPathSync(Query, EPathFindingMode::Hierarchical);
				}

				UE_VLOG(GetOwner(), LogNavigation, Log, TEXT("GeneratePathTo: out of nodes, HPA* path: %s"),
					bPathExists ? TEXT("exists, trying reversed search") : TEXT("doesn't exist"));

				// reverse search
				if (bPathExists)
				{
					DECLARE_SCOPE_CYCLE_COUNTER(TEXT("Pathfinding: reversed test time"), STAT_Navigation_PathReverseTime, STATGROUP_Navigation);

					TSharedPtr<FNavigationQueryFilter> Filter = QueryFilter.IsValid() ? QueryFilter->GetCopy() : MyNavData->GetDefaultQueryFilter()->GetCopy();					
					Filter->SetBacktrackingEnabled(true);

					FPathFindingQuery ReversedQuery(MyNavData, Query.EndLocation, Query.StartLocation, Filter);
					Result = NavSys->FindPathSync(*MyNavAgent->GetNavAgentProperties(), Query, Mode);
				}
			}

			if (Result.IsSuccessful() || Result.IsPartial())
			{
				CurrentGoal = NavMeshGoalLocation;
				SetPath(Result.Path);

				if (IsFollowing() == true)
				{
					// make sure ticking is enabled (and it shouldn't be enabled before _first_ async path finding)
					SetComponentTickEnabledAsync(true);
				}

				NotifyPathUpdate();
				return true;
			}
			else
			{
				UE_VLOG(GetOwner(), LogNavigation, Display, TEXT("Failed to generate path to destination"));
			}
		}
		else
		{
			UE_VLOG(GetOwner(), LogNavigation, Display, TEXT("Destination not on navmesh (and nowhere near!)"));
		}
	}
	else
	{
		UE_VLOG(GetOwner(), LogNavigation, Display, TEXT("UNavigationComponent::GeneratePathTo: NavAgentProps == NULL (Probably Pawn died)"));
	}

	return false;
}
Example #8
0
bool ANUTActor::NotifyControlMessage(UNetConnection* Connection, uint8 MessageType, FInBunch& Bunch)
{
	bool bHandledMessage = false;

	if (MessageType == NMT_NUTControl)
	{
		uint8 CmdType = 0;
		FString Command;
		FNetControlMessage<NMT_NUTControl>::Receive(Bunch, CmdType, Command);

		// Console command
		if (CmdType == ENUTControlCommand::Command_NoResult || CmdType == ENUTControlCommand::Command_SendResult)
		{
			UE_LOG(LogUnitTest, Log, TEXT("NMT_NUTControl: Executing command: %s"), *Command);

			FStringOutputDevice CmdResult;
			CmdResult.SetAutoEmitLineTerminator(true);

			bool bCmdSuccess = false;

			bCmdSuccess = GEngine->Exec(GetWorld(), *Command, CmdResult);

			UE_LOG(LogUnitTest, Log, TEXT("NMT_NUTControl: Command result: %s"), *CmdResult);


			bool bSendResult = CmdType == ENUTControlCommand::Command_SendResult;

			if (bSendResult)
			{
				uint8 ReturnCmdType = (bCmdSuccess ? ENUTControlCommand::CommandResult_Success :
										ENUTControlCommand::CommandResult_Failed);

				FNetControlMessage<NMT_NUTControl>::Send(Connection, ReturnCmdType, CmdResult);
			}
		}
		// Console command result
		else if (CmdType == ENUTControlCommand::CommandResult_Failed || CmdType == ENUTControlCommand::CommandResult_Success)
		{
			bool bCmdSuccess = CmdType == ENUTControlCommand::CommandResult_Success;

			if (bCmdSuccess)
			{
				UE_LOG(LogUnitTest, Log, TEXT("NMT_NUTControl: Got command result:"));
				UE_LOG(LogUnitTest, Log, TEXT("%s"), *Command);
			}
			else
			{
				UE_LOG(LogUnitTest, Log, TEXT("NMT_NUTControl: Failed to execute command"));
			}
		}
		// Ping request
		else if (CmdType == ENUTControlCommand::Ping)
		{
			uint8 TempCmdType = ENUTControlCommand::Pong;
			FString Dud;

			FNetControlMessage<NMT_NUTControl>::Send(Connection, TempCmdType, Dud);
		}
		// Pong reply - this should only be implemented by custom unit tests; hence the assert
		else if (CmdType == ENUTControlCommand::Pong)
		{
			UNIT_ASSERT(false);
		}
		// Custom implemented events, with the result triggered through 'NotifyEvent'
		else if (CmdType == ENUTControlCommand::WatchEvent)
		{
			// NOTE: Only the last NetConnection to request a WatchEvent, will receive notifications
			EventWatcher = Connection;

			// Watch for the end of seamless travel
			if (Command == TEXT("SeamlessTravelEnd"))
			{
				FCoreUObjectDelegates::PostLoadMap.AddStatic(&ANUTActor::NotifyPostLoadMap);
			}
		}
		// Event watch notification - should only be implemented by custom unit tests
		else if (CmdType == ENUTControlCommand::NotifyEvent)
		{
			UNIT_ASSERT(false);
		}
		// Create an actor instance (the 'summon' console command, doesn't work without a cheat manager)
		else if (CmdType == ENUTControlCommand::Summon)
		{
			const TCHAR* Cmd = *Command;
			FString SpawnClassName = FParse::Token(Cmd, false);
			bool bForceBeginPlay = FParse::Param(Cmd, TEXT("ForceBeginPlay"));

			// Hack specifically for getting the GameplayDebugger working - think the mainline code is broken
			bool bGameplayDebuggerHack = FParse::Param(Cmd, TEXT("GameplayDebuggerHack"));

			UClass* SpawnClass = FindObject<UClass>(NULL, *SpawnClassName);

			if (SpawnClass != NULL)
			{
				FActorSpawnParameters SpawnParms;
				SpawnParms.Owner = GetOwner();

				AActor* NewActor = GetWorld()->SpawnActor<AActor>(SpawnClass, SpawnParms);

				if (NewActor != NULL)
				{
					UE_LOG(LogUnitTest, Log, TEXT("Successfully summoned actor of class '%s'"), *SpawnClassName);

					if (bForceBeginPlay && !NewActor->HasActorBegunPlay())
					{
						UE_LOG(LogUnitTest, Log, TEXT("Forcing call to 'BeginPlay' on newly spawned actor."));

						NewActor->BeginPlay();
					}

					if (bGameplayDebuggerHack)
					{
						// Assign the LocalPlayerOwner property, to the PC owning this NUTActor, using reflection (to avoid dependency)
						UObjectProperty* LocalPlayerOwnerProp =
								FindField<UObjectProperty>(NewActor->GetClass(), TEXT("LocalPlayerOwner"));

						if (LocalPlayerOwnerProp != NULL)
						{
							LocalPlayerOwnerProp->SetObjectPropertyValue(
								LocalPlayerOwnerProp->ContainerPtrToValuePtr<UObject*>(NewActor), GetOwner());
						}
						else
						{
							UE_LOG(LogUnitTest, Log, TEXT("WARNING: Failed to find 'LocalPlayerOwner' property. Unit test broken."));
						}

						// Also hack-disable ticking, so that the replicator doesn't spawn a second replicator
						NewActor->SetActorTickEnabled(false);
					}
				}
				else
				{
					UE_LOG(LogUnitTest, Log, TEXT("SpawnActor failed for class '%s'"), *Command);
				}
			}
			else
			{
				UE_LOG(LogUnitTest, Log, TEXT("Could not find actor class '%s'"), *Command);
			}
		}
		// Suspend the game, until a resume request is received (used for giving time, to attach a debugger)
		else if (CmdType == ENUTControlCommand::SuspendProcess)
		{
			UE_LOG(LogUnitTest, Log, TEXT("Suspend start."));


			// Setup a named pipe, to monitor for the resume request
			FString ResumePipeName = FString::Printf(TEXT("%s%u"), NUT_SUSPEND_PIPE, FPlatformProcess::GetCurrentProcessId());
			FPlatformNamedPipe ResumePipe;
			bool bPipeCreated = ResumePipe.Create(ResumePipeName, true, false);

			if (bPipeCreated)
			{
				if (!ResumePipe.OpenConnection())
				{
					UE_LOG(LogUnitTest, Log, TEXT("WARNING: Failed to open pipe connection."));
				}
			}
			else
			{
				UE_LOG(LogUnitTest, Log, TEXT("WARNING: Failed to create resume pipe."));
			}



			// Spin/sleep (effectively suspended) until a resume request is received
			while (true)
			{
				if (bPipeCreated && ResumePipe.IsReadyForRW())
				{
					int32 ResumeVal = 0;

					if (ResumePipe.ReadInt32(ResumeVal) && !!ResumeVal)
					{
						UE_LOG(LogUnitTest, Log, TEXT("Got resume request."));
						break;
					}
				}


				FPlatformProcess::Sleep(1.0f);
			}


			ResumePipe.Destroy();

			UE_LOG(LogUnitTest, Log, TEXT("Suspend end."));
		}

		bHandledMessage = true;
	}

	return bHandledMessage;
}
Example #9
0
void ALaser::checkLaserCollisions(float dt)
{
	FHitResult hit;
	FCollisionQueryParams queryParam;
	queryParam.bFindInitialOverlaps = false;
	queryParam.bReturnFaceIndex = true;
	FCollisionObjectQueryParams objectParam = objectParam.DefaultObjectQueryParam;
	if ( !canHitBall ) queryParam.AddIgnoredActor( GetWorld()->GetGameState<AProjectTapGameState>()->GetPlayer() );
	auto pos = GetActorLocation();
	auto rayStart = pos + dir * 5.0f;
	auto laserVector = dir * length;
	auto laserEmitter = laserParticle->EmitterInstances[0];
	//ray cast to see if laser hits anything
	GetWorld()->LineTraceSingleByObjectType(hit,rayStart, pos + laserVector, objectParam,queryParam);
	auto hitActor = hit.Actor.Get();

	if (hitActor != nullptr)
	{
		currHitPoint = hit.ImpactPoint;
		if(!laserSparkParticle->bIsActive) laserSparkParticle->ActivateSystem();
		//kills ball if laser hits it
		auto ball = Cast<ABallPawn>(hitActor);

		if (ball != nullptr)
		{
			ball->Kill();
			laserEmitter->SetBeamTargetPoint(hit.ImpactPoint, 0);
			KillSubLaser();
		}
		else
		{
			//if not set laser end point
			laserEmitter->SetBeamTargetPoint(hit.ImpactPoint, 0);

			bool typeFound = false;
			//if hits deflective tile then spawn a new laser object
			auto tile = Cast<ADeflectiveTile>(hitActor);
			bool isFrame = false;
			if (tile != nullptr)
			{
				typeFound = true;
				TArray<USceneComponent*> Children;
				tile->frameCollisionsComponent->GetChildrenComponents(true, Children);
				for(int i = 0; i < Children.Num() && typeFound ; ++i)
				{
//					printonscreen(hit.Component.Get()->GetName());
//					printonscreen(Children[i]->GetName());
					if(hit.Component.Get() == Children[i])
					{
						typeFound = false;
						isFrame = true;
					}
				}
				//cut the laser length to make sure new sub laser start doesn't hit the same object
				if (typeFound && CanSpawnSubLaser()) SpawnSubLaser(hit.ImpactPoint + hit.ImpactNormal * 10.0f, hit.ImpactNormal);
			}


			//if sub laser already exists then keep updating its rotation and position
			auto subLaserExistsHitDeflectiveTile = currentDepth < MAX_DEPTH && nextLaser != nullptr && tile != nullptr;
			if (subLaserExistsHitDeflectiveTile)
			{
				auto incomingVector = hit.ImpactPoint - GetActorLocation();

				//if the incoming vector's angle is too small then kill sublasers to avoid laser flickering
				auto dot = FVector::DotProduct(-incomingVector.GetSafeNormal(), hit.ImpactNormal);

				auto angle = FMath::RadiansToDegrees(FMath::Acos(dot));
				if (angle < 70.0f)
				{
					auto newDir = FMath::GetReflectionVector(incomingVector, hit.ImpactNormal);

					auto start = hit.ImpactPoint + newDir * 2.0f;
					nextLaser->SetActorLocation(hit.ImpactPoint);
					nextLaser->dir = newDir.IsNormalized() ? newDir : newDir.GetSafeNormal();
					nextLaser->laserParticle->EmitterInstances[0]->SetBeamSourcePoint(hit.ImpactPoint, 0);
					nextLaser->laserParticle->EmitterInstances[0]->SetBeamTargetPoint(start + newDir * length, 0);
				}
				else
				{
					KillSubLaser();
				}
			}

			//if the laser hits turret then kills it
			if (!typeFound)
			{
				auto turret = Cast<ATurretPawn>(hitActor);
				if (turret != nullptr)
				{
					typeFound = true;
					turret->Damage(2.0f);
				}
			}

			APortalTile* portal = nullptr;
			if (!typeFound)
			{
				portal = Cast<APortalTile>(hitActor);
				if (CanSpawnSubLaser() && portal != nullptr)
				{
					typeFound = true;
					auto relativePos = hit.ImpactPoint - hit.GetComponent()->GetComponentLocation();
					currHitPoint = relativePos + portal->GetActorLocation();
					SpawnSubLaser(currHitPoint, hit.ImpactNormal);
				}
			}

			auto subLaserExistsHitPortalTile = currentDepth < MAX_DEPTH && nextLaser != nullptr && portal != nullptr;
			if (subLaserExistsHitPortalTile)
			{
				FVector newSourcePos;
				portal->GetLaserPortalTransportedLocation(hit.GetComponent(), nextLaser->dir, newSourcePos);
				nextLaser->SetActorLocation(newSourcePos);
				nextLaser->laserParticle->EmitterInstances[0]->SetBeamSourcePoint(newSourcePos, 0);
				nextLaser->laserParticle->EmitterInstances[0]->SetBeamTargetPoint(newSourcePos + nextLaser->dir * length, 0);
			}

			bool notHitDeflectiveTile = tile == nullptr || isFrame;
			bool notHitPortal = portal == nullptr;
			if (notHitDeflectiveTile && notHitPortal)
			{
				KillSubLaser();
			}
		}
			laserSparkParticle->SetWorldLocation(currHitPoint);
			laserSparkParticle->SetWorldRotation(FVector(currHitPoint -
												 GetActorLocation()).GetSafeNormal().Rotation().Quaternion());
	}
	else
	{
		currHitPoint = laserVector;
		laserEmitter->SetBeamTargetPoint(pos + currHitPoint, 0);
		laserSparkParticle->SetWorldLocation( pos + currHitPoint );
		laserSparkParticle->SetWorldRotation( FVector( (pos + currHitPoint) -
			GetActorLocation() ).GetSafeNormal().Rotation().Quaternion() );
		KillSubLaser();
	}

	//only root laser can have an emitter mesh
	if (currentDepth != 0)
	{
		//update laser emitter rotation
		mesh->SetVisibility(false);
	}
	else
	{
		mesh->SetWorldRotation(dir.Rotation());
	}
}
Example #10
0
void ANUTActor::ServerAdmin_Implementation(const FString& Command)
{
	UE_LOG(LogUnitTest, Log, TEXT("Executing command: %s"), *Command);

	GEngine->Exec(GetWorld(), *Command);
}
Example #11
0
void ANUTActor::ServerClientStillAlive_Implementation()
{
	LastAliveTime = GetWorld()->RealTimeSeconds;
}
Example #12
0
void ANUTActor::Tick(float DeltaSeconds)
{
	Super::Tick(DeltaSeconds);

	UWorld* CurWorld = GetWorld();

	if (CurWorld != NULL)
	{
		ENetMode CurNetMode = GEngine != NULL ? GEngine->GetNetMode(CurWorld) : NM_Standalone;
		bool bClientTimedOut = CurNetMode != NM_Standalone &&
								(CurWorld->RealTimeSeconds - LastAliveTime) > (CurNetMode == NM_Client ? 5.0f : 10.0f);

		// Have the client tell the server they are still alive
		if (CurNetMode == NM_Client && bClientTimedOut)
		{
			ServerClientStillAlive();
			LastAliveTime = CurWorld->RealTimeSeconds;
		}

		// Have the server set the owner, when appropriate
		if ((Cast<APlayerController>(GetOwner()) == NULL || bClientTimedOut) && GEngine != NULL && CurNetMode != NM_Client)
		{
			AGameState* GameState = CurWorld->GameState;

			if (GameState != NULL)
			{
				// @todo #JohnBReview: You want this to only happen if no remote players are present (perhaps give all players control instead,
				//				if this becomes a problem - requires setting things up differently though)
				if (CurNetMode == NM_ListenServer || CurNetMode == NM_Standalone)
				{
					for (FLocalPlayerIterator It(GEngine, CurWorld); It; ++It)
					{
						if (It->PlayerController != NULL)
						{
							// Reset LastAliveTime, to give client a chance to send initial 'alive' RPC
							LastAliveTime = CurWorld->RealTimeSeconds;

							SetOwner(It->PlayerController);
							break;
						}
					}
				}

				for (int i=0; i<GameState->PlayerArray.Num(); i++)
				{
					APlayerController* PC = Cast<APlayerController>(GameState->PlayerArray[i] != NULL ?
																	GameState->PlayerArray[i]->GetOwner() : NULL);

					if (PC != NULL && PC != GetOwner() && Cast<UNetConnection>(PC->Player) != NULL)
					{
						UE_LOG(LogUnitTest, Log, TEXT("Setting NUTActor owner to: %s (%s)"), *PC->GetName(),
							*GameState->PlayerArray[i]->PlayerName);

						// Reset LastAliveTime, to give client a chance to send initial 'alive' RPC
						LastAliveTime = CurWorld->RealTimeSeconds;

						SetOwner(PC);

						break;
					}
				}
			}
		}


		// Monitor for the beacon net driver, so it can be hooked
		if (bMonitorForBeacon)
		{
#if TARGET_UE4_CL < CL_BEACONHOST
			UNetDriver* BeaconDriver = GEngine->FindNamedNetDriver(CurWorld, NAME_BeaconDriver);
#else
			// Somehow, the beacon driver name got messed up in a subsequent checkin, so now has to be found manually
			UNetDriver* BeaconDriver = NULL;

			FWorldContext* CurContext = GEngine->GetWorldContextFromWorld(CurWorld);

			if (CurContext != NULL)
			{
				for (auto CurDriverRef : CurContext->ActiveNetDrivers)
				{
					if (CurDriverRef.NetDriverDef->DefName == NAME_BeaconDriver)
					{
						BeaconDriver = CurDriverRef.NetDriver;
						break;
					}
				}
			}
#endif

			// Only hook when a client is connected
			if (BeaconDriver != NULL && BeaconDriver->ClientConnections.Num() > 0)
			{
				HookNetDriver(BeaconDriver);

				UE_LOG(LogUnitTest, Log, TEXT("Hooked beacon net driver"));


				// Also switch over replication to the beacon net driver
				Role = ROLE_None;
				SetReplicates(false);

				BeaconDriverName = BeaconDriver->NetDriverName;
				NetDriverName = BeaconDriverName;

				Role = ROLE_Authority;
				SetReplicates(true);


				// Send an RPC, for force actor channel replication
				NetMulticastPing();

				bMonitorForBeacon = false;
			}
		}
	}
}
void UGISInventoryBaseComponent::AddItemOnSlot(const FGISSlotInfo& TargetSlotType, const FGISSlotInfo& LastSlotType)
{
	//Before we start swapping item, let's check if tags match!
	if (GetOwnerRole() < ROLE_Authority)
	{
		ServerAddItemOnSlot(TargetSlotType, LastSlotType);
		return;
	}

	//check if all data is valid.
	if (!TargetSlotType.IsValid() || !LastSlotType.IsValid())
		return;

	//next check should be against item tags, but that's later!
	if (LastSlotType.CurrentInventoryComponent->bRemoveItemsFromInvetoryOnDrag)
	{
		//Tabs.InventoryTabs[TargetSlotType.SlotTabIndex].TabSlots[TargetSlotType.SlotTabIndex].ItemData
		if (TargetSlotType.GetItemData() == nullptr)
		{
			UGISItemData* TargetItem = LastSlotType.GetItemData();
			UGISItemData* LastItem = TargetSlotType.GetItemData();
			if (!CheckIfCanAddItemToSlot(TargetItem, TargetSlotType.SlotTabIndex, TargetSlotType.SlotIndex, LastItem))
				return;

			if (!TargetItem->HasAnyMatchingGameplayTags(TargetSlotType.GetTags()))
				return;

			if (TargetItem)
				if (!TargetItem->CanItemBeSwapped())
					return;
			if (LastItem)
				if (!LastItem->CanItemBeSwapped())
					return;

			TargetItem->AssignInventory(LastSlotType, TargetSlotType);

			LastSlotType.DecrementItemCount();
			TargetSlotType.IncrementItemCount();

			TargetSlotType.SetItemData(TargetItem);
			LastSlotType.SetItemData(nullptr);
			
			if ((LastTargetTab != INDEX_NONE) && (LastOtherOriginTab != INDEX_NONE)
				&& LastOtherOriginInventory)
			{
				LastOtherOriginInventory->CopyItemsFromOtherInventoryTab(this, LastOtherOriginTab, LastTargetTab);
			}

			TargetItem->SetWorld(GetWorld());
			TargetItem->SetCurrentOwner(GetOwner());
			OnItemAddedToSlot(TargetItem);

			SlotSwapInfo.ReplicationCounter++;
			SlotSwapInfo = FGISSlotSwapInfo(LastSlotType, LastItem, TargetSlotType, TargetItem);

			if (GetNetMode() == ENetMode::NM_Standalone)
			{
				OnItemSlotSwapped.Broadcast(SlotSwapInfo);
				LastSlotType.CurrentInventoryComponent->OnItemSlotSwapped.Broadcast(SlotSwapInfo);
			}
			//we will do it on server, to give chance for other
			//componenets/actors to do something if item is removed/swapped in inventory.
			if (GetNetMode() == ENetMode::NM_DedicatedServer)
			{
				OnItemSlotSwapped.Broadcast(SlotSwapInfo);
				LastSlotType.CurrentInventoryComponent->OnItemSlotSwapped.Broadcast(SlotSwapInfo);
			}
		}
		else
		{

			/*
				Last copy item from last inventory, to be placed in Target inventory.
			*/
			UGISItemData* TargetItem = LastSlotType.GetItemData();
			/*
				Copy item from target inventory, to be placed in last inventory.
			*/
			UGISItemData* LastItem = TargetSlotType.GetItemData();
			
			if (!CheckIfCanAddItemToSlot(TargetItem, TargetSlotType.SlotTabIndex, TargetSlotType.SlotIndex, LastItem))
				return;

			if (!TargetItem->HasAnyMatchingGameplayTags(TargetSlotType.GetTags()))
				return;
			
			if (!LastItem->HasAnyMatchingGameplayTags(LastSlotType.GetTags()))
				return;

			if (TargetItem)
				if (!TargetItem->CanItemBeSwapped())
					return;
			if (LastItem)
				if (!LastItem->CanItemBeSwapped())
					return;

			/*
				Assign current inventory to current item.
			*/
			TargetItem->AssignInventory(LastSlotType, TargetSlotType);
			LastItem->AssignInventory(TargetSlotType, LastSlotType);
			
			LastSlotType.DecrementItemCount();
			TargetSlotType.IncrementItemCount();

			TargetSlotType.SetItemData(TargetItem);
			LastSlotType.SetItemData(LastItem);

			if ((LastTargetTab != INDEX_NONE) && (LastOtherOriginTab != INDEX_NONE)
				&& LastOtherOriginInventory)
			{
				LastOtherOriginInventory->CopyItemsFromOtherInventoryTab(this, LastOtherOriginTab, LastTargetTab);
			}

			TargetItem->SetWorld(GetWorld());
			TargetItem->SetCurrentOwner(GetOwner());
			LastItem->SetWorld(GetWorld());
			LastItem->SetCurrentOwner(GetOwner());

			OnItemAddedToSlot(TargetItem);
			OnItemAddedToSlot(LastItem);

			SlotSwapInfo.ReplicationCounter++;
			SlotSwapInfo = FGISSlotSwapInfo(LastSlotType, LastItem, TargetSlotType, TargetItem);
	
			if (GetNetMode() == ENetMode::NM_Standalone)
			{
				OnItemSlotSwapped.Broadcast(SlotSwapInfo);
				LastSlotType.CurrentInventoryComponent->OnItemSlotSwapped.Broadcast(SlotSwapInfo);
			}
			//we will do it on server, to give chance for other
			//componenets/actors to do something if item is removed/swapped in inventory.
			if (GetNetMode() == ENetMode::NM_DedicatedServer)
			{
				OnItemSlotSwapped.Broadcast(SlotSwapInfo);
				LastSlotType.CurrentInventoryComponent->OnItemSlotSwapped.Broadcast(SlotSwapInfo);
			}
				
			//ClientSlotSwap(SlotSwapInfo);
		}
	}
	else
	{ //if there is item in target slot. Remove it. or override it.
		UGISItemData* TargetItem = LastSlotType.GetItemData();
		UGISItemData* LastItem = TargetSlotType.GetItemData(); //Tabs.InventoryTabs[TargetSlotType.SlotTabIndex].TabSlots[TargetSlotType.SlotIndex].ItemData;
		
		if (TargetItem)
			if (!TargetItem->CanItemBeSwapped())
				return;
		if (LastItem)
			if (!LastItem->CanItemBeSwapped())
				return;
		
		LastSlotType.SetItemData(nullptr);
		TargetSlotType.SetItemData(TargetItem);

		TargetItem->CurrentInventory = TargetSlotType.CurrentInventoryComponent.Get();

		if ((LastTargetTab != INDEX_NONE) && (LastOtherOriginTab != INDEX_NONE)
			&& LastOtherOriginInventory)
		{
			LastOtherOriginInventory->CopyItemsFromOtherInventoryTab(this, LastOtherOriginTab, LastTargetTab);
		}

		TargetItem->SetWorld(GetWorld());
		TargetItem->SetCurrentOwner(GetOwner());

		OnItemAddedToSlot(TargetItem);

		SlotSwapInfo.ReplicationCounter++;
		SlotSwapInfo = FGISSlotSwapInfo(LastSlotType, LastItem, TargetSlotType, TargetItem);
		if (GetNetMode() == ENetMode::NM_Standalone)
			OnItemSlotSwapped.Broadcast(SlotSwapInfo);
	}
}
	void CreateRagdollExperiment_0(const dMatrix& location)
	{
		static dJointDefinition jointsDefinition[] =
		{
			{ "body" },
			{ "leg", 100.0f,{ -15.0f, 15.0f, 30.0f },{ 0.0f, 0.0f, 180.0f }, dAnimationRagdollJoint::m_threeDof },
			{ "foot", 100.0f,{ -15.0f, 15.0f, 30.0f },{ 0.0f, 90.0f, 0.0f }, dAnimationRagdollJoint::m_twoDof },
		};
		const int definitionCount = sizeof (jointsDefinition)/sizeof (jointsDefinition[0]);

		NewtonWorld* const world = GetWorld();
		DemoEntityManager* const scene = (DemoEntityManager*)NewtonWorldGetUserData(world);

		DemoEntity* const modelEntity = DemoEntity::LoadNGD_mesh("selfbalance_01.ngd", GetWorld(), scene->GetShaderCache());

		dMatrix matrix0(modelEntity->GetCurrentMatrix());
		//matrix0.m_posit = location;
		//modelEntity->ResetMatrix(*scene, matrix0);
		scene->Append(modelEntity);

		// add the root childBody
		NewtonBody* const rootBody = CreateBodyPart(modelEntity);

		// build the rag doll with rigid bodies connected by joints
		dDynamicsRagdoll* const dynamicRagdoll = new dDynamicsRagdoll(rootBody, dGetIdentityMatrix());
		AddModel(dynamicRagdoll);
		dynamicRagdoll->SetCalculateLocalTransforms(true);

		// save the controller as the collision user data, for collision culling
		NewtonCollisionSetUserData(NewtonBodyGetCollision(rootBody), dynamicRagdoll);

		int stackIndex = 0;
		DemoEntity* childEntities[32];
		dAnimationJoint* parentBones[32];

		for (DemoEntity* child = modelEntity->GetChild(); child; child = child->GetSibling()) {
			parentBones[stackIndex] = dynamicRagdoll;
			childEntities[stackIndex] = child;
			stackIndex++;
		}

		// walk model hierarchic adding all children designed as rigid body bones. 
		while (stackIndex) {
			stackIndex--;
			DemoEntity* const entity = childEntities[stackIndex];
			dAnimationJoint* parentNode = parentBones[stackIndex];

			const char* const name = entity->GetName().GetStr();
			for (int i = 0; i < definitionCount; i++) {
				if (!strcmp(jointsDefinition[i].m_boneName, name)) {
					NewtonBody* const childBody = CreateBodyPart(entity);
					// connect this body part to its parent with a rag doll joint
					parentNode = CreateChildNode(childBody, parentNode, jointsDefinition[i]);

					NewtonCollisionSetUserData(NewtonBodyGetCollision(childBody), parentNode);
					break;
				}
			}

			for (DemoEntity* child = entity->GetChild(); child; child = child->GetSibling()) {
				parentBones[stackIndex] = parentNode;
				childEntities[stackIndex] = child;
				stackIndex++;
			}
		}

		SetModelMass (100.0f, dynamicRagdoll);

		// set the collision mask
		// note this container work best with a material call back for setting bit field 
		//dAssert(0);
		//controller->SetDefaultSelfCollisionMask();

		// transform the entire contraction to its location
		dMatrix worldMatrix(modelEntity->GetCurrentMatrix() * location);
		worldMatrix.m_posit = location.m_posit;
		NewtonBodySetMatrixRecursive(rootBody, &worldMatrix[0][0]);

		// attach effectors here
		for (dAnimationJoint* joint = GetFirstJoint(dynamicRagdoll); joint; joint = GetNextJoint(joint)) {
			if (joint->GetAsRoot()) {
				dAssert(dynamicRagdoll == joint);
				dynamicRagdoll->SetHipEffector(joint);
			} else if (joint->GetAsLeaf()) {
				dynamicRagdoll->SetFootEffector(joint);
			}
		}

		dynamicRagdoll->Finalize();
		//return controller;
	}
Example #15
0
ULocalPlayer* UGameInstance::CreateLocalPlayer(int32 ControllerId, FString& OutError, bool bSpawnActor)
{
	check(GetEngine()->LocalPlayerClass != NULL);

	ULocalPlayer* NewPlayer = NULL;
	int32 InsertIndex = INDEX_NONE;

	const int32 MaxSplitscreenPlayers = (GetGameViewportClient() != NULL) ? GetGameViewportClient()->MaxSplitscreenPlayers : 1;

	if (FindLocalPlayerFromControllerId( ControllerId ) != NULL)
	{
		OutError = FString::Printf(TEXT("A local player already exists for controller ID %d,"), ControllerId);
	}
	else if (LocalPlayers.Num() < MaxSplitscreenPlayers)
	{
		// If the controller ID is not specified then find the first available
		if (ControllerId < 0)
		{
			for (ControllerId = 0; ControllerId < MaxSplitscreenPlayers; ++ControllerId)
			{
				if (FindLocalPlayerFromControllerId( ControllerId ) == NULL)
				{
					break;
				}
			}
			check(ControllerId < MaxSplitscreenPlayers);
		}
		else if (ControllerId >= MaxSplitscreenPlayers)
		{
			UE_LOG(LogPlayerManagement, Warning, TEXT("Controller ID (%d) is unlikely to map to any physical device, so this player will not receive input"), ControllerId);
		}

		NewPlayer = NewObject<ULocalPlayer>(GetEngine(), GetEngine()->LocalPlayerClass);
		InsertIndex = AddLocalPlayer(NewPlayer, ControllerId);
		if (bSpawnActor && InsertIndex != INDEX_NONE && GetWorld() != NULL)
		{
			if (GetWorld()->GetNetMode() != NM_Client)
			{
				// server; spawn a new PlayerController immediately
				if (!NewPlayer->SpawnPlayActor("", OutError, GetWorld()))
				{
					RemoveLocalPlayer(NewPlayer);
					NewPlayer = NULL;
				}
			}
			else
			{
				// client; ask the server to let the new player join
				NewPlayer->SendSplitJoin();
			}
		}
	}
	else
	{
		OutError = FString::Printf(TEXT( "Maximum number of players (%d) already created.  Unable to create more."), MaxSplitscreenPlayers);
	}

	if (OutError != TEXT(""))
	{
		UE_LOG(LogPlayerManagement, Log, TEXT("UPlayer* creation failed with error: %s"), *OutError);
	}

	return NewPlayer;
}
void AMMO_Character::BeginPlay()
{
	Super::BeginPlay();
	
	GetCharacterMovement()->MaxWalkSpeed = MovementSpeed;
	Player_SkeletalMeshComponent = FindComponentByClass<class USkeletalMeshComponent>();
	Player_SpringArmComponent = FindComponentByClass<class USpringArmComponent>();
	Player_Widget = FindComponentByClass<class UWidgetComponent>();

	CurrentHealth = MaxHealth;

	OverheadUI = Cast<UMMO_OverheadUI_HUD>(Player_Widget->GetUserWidgetObject());
	OverheadUI->CharName = CharacterName;
	float TempPercetage = CurrentHealth / MaxHealth;
	OverheadUI->HPBarValue = TempPercetage;

	AnimInstance = Cast<UMMO_Char_AnimInstance>(Player_SkeletalMeshComponent->GetAnimInstance());
	MyController = Cast<AMMO_Player_Controller>(GetController());

	TArray<UCameraComponent*> Cameras;
	GetComponents<UCameraComponent>(Cameras);
	for (size_t i = 0; i < Cameras.Num(); i++)
	{
		if (Cameras[i]->ComponentHasTag("MainCam"))
		{
			MainCam = Cameras[i];
		}
		else
		{
			LockOnCam = Cameras[i];
		}
	}

	if (!bIsWarrior)
	{
		TArray<UStaticMeshComponent*> StaticMeshes;
		GetComponents<UStaticMeshComponent>(StaticMeshes);
		for (size_t i = 0; i < StaticMeshes.Num(); i++)
		{
			if (StaticMeshes[i]->ComponentHasTag("HandArrow"))
			{
				HandArrow = StaticMeshes[i];
			}
			else if (StaticMeshes[i]->ComponentHasTag("ArrowShooterLoc"))
			{
				ShootingLocation = StaticMeshes[i];
			}
			else if (StaticMeshes[i]->ComponentHasTag("ShootTarget"))
			{
				ShootTarget = StaticMeshes[i];
			}
		}

		
	}

	//Get Reference to Other Character.
	if (Role < ROLE_Authority)
	{
		for (TActorIterator<AMMO_Character> ActorItr(GetWorld()); ActorItr; ++ActorItr)
		{
			if (*ActorItr != this)
			{
				OtherCharacter = *ActorItr;
			}
		}
	}

	for (TActorIterator<AObjectPool> ActorItr(GetWorld()); ActorItr; ++ActorItr)
	{
		if (ActorItr->ActorHasTag("ObjectPooler"))
		{
			GlobalPool = *ActorItr;
		}
	}

	
}
Example #17
0
void AWorldSettings::NotifyMatchStarted()
{
    UWorld* World = GetWorld();
    World->bMatchStarted = true;
}
void AMMO_Character::AttemptToLockOn()
{
	if (bIsDead)return;
	if (bMantineeHasControl)return;

	// Part 1 of 2: Set / Unset LockOn Target

	if (!LockedTarget)
	{
		TArray<AMMO_Mob_Character*> Enemies;
		for (TActorIterator<AMMO_Mob_Character> ActorItr(GetWorld()); ActorItr; ++ActorItr)
		{
			if(!ActorItr->bIsDead)
			Enemies.Add(*ActorItr);
		}

		int32 Index = -1;
		float Distance = 100000000;
		for (size_t i = 0; i < Enemies.Num(); i++)
		{
			if (FVector::Dist(GetActorLocation(), Enemies[i]->GetActorLocation()) <= PingAreaForLockOn)
			{
				if (FVector::Dist(GetActorLocation(), Enemies[i]->GetActorLocation()) < Distance)
				{
					if (!Enemies[i]->bIsDead && !Enemies[i]->MonsterAnimInstance->bHasDied )
					{
						Distance = FVector::Dist(GetActorLocation(), Enemies[i]->GetActorLocation());
						Index = i;
					}
				}
			}
		}

		if (Index != -1)
		{
			if (bIsInFocusMode)
			{
				bIsInFocusMode = false;
			}

			LockedTarget = Cast<AActor>(Enemies[Index]);
		}
		else
		{
			LockedTarget = nullptr;
		}
	}
	else
	{
		Cast<AMMO_Mob_Character>(LockedTarget)->MyLockOnWidget->PlayersLockedOn[LockOnID]=-1;
		LockedTarget = nullptr;
	}


	// Part 2 of 2: Activate and Deactivate as well as set some helper variables for Rotation of Actor and Camera.

	if (LockedTarget)
	{
		LastKnownRotation = FRotator((LockedTarget->GetActorLocation() - LockOnCam->GetComponentLocation()).Rotation());
		
		Cast<AMMO_Mob_Character>(LockedTarget)->MyLockOnWidget->PlayersLockedOn[LockOnID] = LockOnID;

		SetActorRotation(LastKnownRotation);
		Player_SkeletalMeshComponent->SetWorldRotation(LastKnownRotation);
		
		LockOnCam->Activate();
		MainCam->Deactivate();

		LockOnCam->SetRelativeLocation(FVector(-300, 0, 120));
		LockOnCam->SetRelativeRotation(FRotator(-22.5f, 0, 0));
	}
	else
	{
		GLog->Log(GetActorLabel());

		LockOnCam->Deactivate();
		MainCam->Activate();
	}
}
void UShardsMovementComponent::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction)
{
	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);

	FHitResult HitResult;
	FHitResult ShapeTraceResult;
	FCollisionShape shape = FCollisionShape::MakeBox(FVector(0.72f*playerradius, 0.72f*playerradius,10.0f));

	FCollisionQueryParams Params;
	Params.bFindInitialOverlaps = true;
	Params.AddIgnoredActor(UpdatedComponent->GetAttachmentRootActor());

	// Telepads don't count.
	for (TActorIterator<ATelePad> ActorItr(GetWorld()); ActorItr; ++ActorItr) {
		Params.AddIgnoredActor(ActorItr.operator->());
	}

	// Neither do destructibles.
	for (TActorIterator<ADestructibleBox> ActorItr(GetWorld()); ActorItr; ++ActorItr) {
		// When they're broken, that is.
		if (ActorItr->fadetimer >= 0.0f) {
			Params.AddIgnoredActor(ActorItr.operator->());
		}
	}

	if (isclimbing) {
		return;
	}

	TArray<FHitResult> results;
	if (forceregiondirection.Z == 0.0f) {
		GetWorld()->SweepMultiByChannel(results, UpdatedComponent->GetComponentLocation() - 0.0f*45.0f*FVector::UpVector, UpdatedComponent->GetComponentLocation() - 1000.0f*FVector::UpVector, FQuat::Identity, ECC_Visibility, shape, Params); //100
		for (FHitResult r : results) {
			if (r.Normal.Z > 0.6f) {
				ShapeTraceResult = r;
				break;
			}
		}
		if (!ShapeTraceResult.IsValidBlockingHit()) {
			GetWorld()->LineTraceSingleByChannel(ShapeTraceResult, UpdatedComponent->GetComponentLocation(), UpdatedComponent->GetComponentLocation() - 1000.0f*FVector::UpVector, ECC_Visibility, Params);
		}
	}

	FVector PlayerCapsuleBottom = UpdatedComponent->GetComponentLocation() - 45.0f * FVector::UpVector; // 50
	float RequiredDistance = (onground ? 50.0f*grounddetecttfudgefactor : 10.0f)*FMath::Pow(playerhalfheight / 90.0f,4.0f) + playerhalfheight/2.0f; //50,1
	DistanceFromImpact = (PlayerCapsuleBottom - ShapeTraceResult.ImpactPoint).Z;
	overground = ShapeTraceResult.IsValidBlockingHit();

	FHitResult groundhitresult;
	GetWorld()->LineTraceSingleByChannel(groundhitresult, UpdatedComponent->GetComponentLocation(), UpdatedComponent->GetComponentLocation() - 10000.0f*FVector::UpVector, ECC_Visibility, Params);
	groundtracehit = groundhitresult.ImpactPoint;

	if (!onground) {
		offGroundTime += DeltaTime;
	}

	toosteep = false;
	if (enforcementtimer >= 0.0f) {
		enforcementtimer += DeltaTime;
		toosteep = true;
	}
	wasonground = onground;
	onground = false;
	prevgroundvelocity = groundvelocity;
	groundvelocity = FVector::ZeroVector;
	platformangularfrequency = 0.0f;
	platformspindir = 1;
	FloorNormal = FVector::ZeroVector;

	if ((enforcementtimer < timerlimit && ShapeTraceResult.Normal.Z>0.6f) && DistanceFromImpact < RequiredDistance && !justjumped) { // (PlayerVelocity.Z <= 0.0f || wasonground)
		if (ShapeTraceResult.Normal.Z < minnormalz) {
			if (enforcementtimer == -1.0f) {
				enforcementtimer = 0.0f;
			}
		} else {
			enforcementtimer = -1.0f;
		}

		FVector pvel;
		// Handle moving platforms.
		if (ShapeTraceResult.GetActor() != nullptr && ShapeTraceResult.GetComponent() != nullptr && ShapeTraceResult.GetComponent()->IsA(UStaticMeshComponent::StaticClass())) {
			
			// The motion of a point on a rigid body is the combination of its motion about the center of mass...
			FVector angvel = FMath::DegreesToRadians((((UStaticMeshComponent*)ShapeTraceResult.GetComponent())->GetPhysicsAngularVelocity()));
			FVector rr = GetActorLocation() - (((UStaticMeshComponent*)ShapeTraceResult.GetComponent())->GetComponentLocation());
			FVector rvel = FVector::CrossProduct(angvel, rr);

			// ...and the motion of the center of mass itself.
			FVector cmvel = (((UStaticMeshComponent*)ShapeTraceResult.GetComponent())->GetPhysicsLinearVelocity());
			
			groundvelocity = rvel + cmvel;
			platformangularfrequency = -angvel.Z;
		}

		if ((PlayerVelocity.Z <= groundvelocity.Z || wasonground)) {
			onground = true;
			offGroundTime = 0.0f;
		}
	}

	justjumped = false;

	bool TraceBlocked;
	FVector newlocation = UpdatedComponent->GetComponentLocation();

	FHitResult TraceHitResult;
	TraceBlocked = GetWorld()->LineTraceSingleByChannel(TraceHitResult, ShapeTraceResult.ImpactPoint + 1.0f*FVector::UpVector, ShapeTraceResult.ImpactPoint - 10.0f*FVector::UpVector, ECC_Visibility,Params);
	if (TraceHitResult.Normal.Z > minnormalz) {
		enforcementtimer = -1.0f;
	}

	if (onground) {

		if (TraceBlocked) {
			newlocation.Z = TraceHitResult.ImpactPoint.Z + playerhalfheight; // 50
			GetWorld()->LineTraceSingleByChannel(TraceHitResult, ShapeTraceResult.ImpactPoint + 1.0f*FVector::UpVector, ShapeTraceResult.ImpactPoint - 10.0f*FVector::UpVector, ECC_Visibility,Params);
			FloorNormal = TraceHitResult.ImpactNormal;
		}

		SafeMoveUpdatedComponent(newlocation - UpdatedComponent->GetComponentLocation(), UpdatedComponent->GetComponentRotation(), true, HitResult);
		SlideAlongSurface(newlocation - UpdatedComponent->GetComponentLocation(), 1.0 - HitResult.Time, HitResult.Normal, HitResult);
	}
};
void UBuoyancyComponent::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction)
{
	if (!OceanManager || !UpdatedComponent || !UpdatedPrimitive) return;

	if (!UpdatedComponent->IsSimulatingPhysics())
	{
		FVector waveHeight = OceanManager->GetWaveHeightValue(UpdatedComponent->GetComponentLocation());
		UpdatedPrimitive->SetWorldLocation(FVector(UpdatedComponent->GetComponentLocation().X, UpdatedComponent->GetComponentLocation().Y, waveHeight.Z), true);
		return;
	}

	//ApplyUprightConstraint is apparently needed again at first tick for BP-updated components. 
	//TODO: there has to be a better way than this(?), PostInitialize(?)
	if (!_hasTicked)
	{
		_hasTicked = true;
		ApplyUprightConstraint();
	}

	float TotalPoints = TestPoints.Num();
	if (TotalPoints < 1) return;

	int PointsUnderWater = 0;
	for (int pointIndex = 0; pointIndex < TotalPoints; pointIndex++)
	{
		if (!TestPoints.IsValidIndex(pointIndex)) return; //Array size changed during runtime

		bool isUnderwater = false;
		FVector testPoint = TestPoints[pointIndex];
		FVector worldTestPoint = UpdatedComponent->GetComponentTransform().TransformPosition(testPoint);
		float waveHeight = OceanManager->GetWaveHeightValue(worldTestPoint).Z;

		//If test point radius is touching water add buoyancy force
		if (waveHeight > (worldTestPoint.Z + _SignedRadius))
		{
			PointsUnderWater++;
			isUnderwater = true;

			float DepthMultiplier = (waveHeight - (worldTestPoint.Z + _SignedRadius)) / (TestPointRadius * 2);
			DepthMultiplier = FMath::Clamp(DepthMultiplier, 0.f, 1.f);

			//If we have a point density override, use the overriden value insted of MeshDensity
			float PointDensity = PointDensityOverride.IsValidIndex(pointIndex) ? PointDensityOverride[pointIndex] : MeshDensity;

			/**
			* --------
			* Buoyancy force formula: (Volume(Mass / Density) * Fluid Density * -Gravity) / Total Points * Depth Multiplier
			* --------
			*/
			float BuoyancyForceZ = UpdatedPrimitive->GetMass() / PointDensity * FluidDensity * -GetGravityZ() / TotalPoints * DepthMultiplier;

			//Experimental velocity damping using GetUnrealWorldVelocityAtPoint!
			FVector DampingForce = -GetVelocityAtPoint(UpdatedPrimitive, worldTestPoint) * VelocityDamper * UpdatedPrimitive->GetMass() * DepthMultiplier;

			//Wave push force
			if (EnableWaveForces)
			{
				float waveVelocity = FMath::Clamp(GetVelocityAtPoint(UpdatedPrimitive, worldTestPoint).Z, -20.f, 150.f) * (1 - DepthMultiplier);
				DampingForce += FVector(OceanManager->GlobalWaveDirection.X, OceanManager->GlobalWaveDirection.Y, 0) * UpdatedPrimitive->GetMass() * waveVelocity * WaveForceMultiplier / TotalPoints;
			}

			//Add force for this test point
			UpdatedPrimitive->AddForceAtLocation(FVector(DampingForce.X, DampingForce.Y, DampingForce.Z + BuoyancyForceZ), worldTestPoint);
		}

		if (DrawDebugPoints)
		{
			FColor DebugColor = FLinearColor(0.8, 0.7, 0.2, 0.8).ToRGBE();
			if (isUnderwater) { DebugColor = FLinearColor(0, 0.2, 0.7, 0.8).ToRGBE(); } //Blue color underwater, yellow out of watter
			DrawDebugSphere(GetWorld(), worldTestPoint, TestPointRadius, 8, DebugColor);
		}
	}

	//Clamp the velocity to MaxUnderwaterVelocity if there is any point underwater
	if (ClampMaxVelocity && PointsUnderWater > 0
		&& UpdatedPrimitive->GetPhysicsLinearVelocity().Size() > MaxUnderwaterVelocity)
	{
		FVector	Velocity = UpdatedPrimitive->GetPhysicsLinearVelocity().GetSafeNormal() * MaxUnderwaterVelocity;
		UpdatedPrimitive->SetPhysicsLinearVelocity(Velocity);
	}

	//Update damping based on number of underwater test points
	UpdatedPrimitive->SetLinearDamping(_baseLinearDamping + FluidLinearDamping / TotalPoints * PointsUnderWater);
	UpdatedPrimitive->SetAngularDamping(_baseAngularDamping + FluidAngularDamping / TotalPoints * PointsUnderWater);
}
void APluginsCharacter::TurnAtRate(float Rate)
{
	// calculate delta for this frame from the rate information
	AddControllerYawInput(Rate * BaseTurnRate * GetWorld()->GetDeltaSeconds());
}
/** Tick */
void UFluidSurfaceComponent::TickComponent( float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction )
{
	Super::TickComponent( DeltaTime, TickType, ThisTickFunction );
	LastDeltaTime = DeltaTime;

	float SimStep = 1.f / UpdateRate;
	static float Time = 0.0f;

#if WITH_EDITOR

	/* Only update if checked */
	if( !UpdateComponent )
		return;

#endif
	
	/* If this water hasn't been rendered for a while, stop updating */
	if (LastRenderTime > 0 && GetWorld()->TimeSeconds - LastRenderTime > 1)
		return;

	Time += DeltaTime;
	if( Time > SimStep )
	{
		Time = 0.0f;
		LatestVerts = !LatestVerts;

		/* Add ripples for actors in the water */
		TArray<struct FOverlapResult> OverlappingActors;

		FCollisionShape CollisionShape;
		CollisionShape.SetBox( FluidBoundingBox.GetExtent( ) );

		/* Find overlapping actors */
		GetWorld()->OverlapMultiByChannel(OverlappingActors, GetComponentLocation(), GetComponentQuat(), ECC_WorldDynamic, CollisionShape, FCollisionQueryParams(false));

		// @todo: handle better

		/* Iterate through found overlapping actors */
		for( int i = 0; i < OverlappingActors.Num( ); i++ )
		{
			TWeakObjectPtr<AActor> Actor = OverlappingActors[ i ].Actor;

			/* Dont care about self and modifiers */
			if( Actor != NULL && !Actor->IsA( AFluidSurfaceActor::StaticClass( ) ) && !Actor->IsA( AFluidSurfaceModifier::StaticClass( ) ) )
			{
				FVector LocalVel = GetWorldToComponent( ).TransformVector( Actor->GetVelocity( ) );
				float HorizVelMag = LocalVel.Size( );

				Pling( Actor->GetActorLocation( ), RippleVelocityFactor * HorizVelMag, Actor->GetSimpleCollisionRadius( ) );
			}
		}

		/* Do test ripple (moving around in a circle) */
		if( GIsEditor && TestRipple )
		{
			TestRippleAng += SimStep * MyU2Rad * TestRippleSpeed;
			FVector WorldRipplePos, LocalRipplePos;

			float RippleRadius = 0.3f * ( FluidXSize - 1 ) * FluidGridSpacing;
			if( FluidGridType == EFluidGridType::FGT_Hexagonal )
				RippleRadius = FMath::Max( RippleRadius, 0.3f * ( FluidYSize - 1 ) * FluidGridSpacing * ROOT3OVER2 );
			else
				RippleRadius = FMath::Max( RippleRadius, 0.3f * ( FluidYSize - 1 ) * FluidGridSpacing );

			LocalRipplePos.X = ( RippleRadius * FMath::Sin( TestRippleAng ) );
			LocalRipplePos.Y = ( RippleRadius * FMath::Cos( TestRippleAng ) );
			LocalRipplePos.Z = 0.f;

			WorldRipplePos = ComponentToWorld.TransformPosition( LocalRipplePos );
			Pling( WorldRipplePos, TestRippleStrength, TestRippleRadius );
		}

		/* Add modifier effects */
		for( int i = 0; i < Modifiers.Num( ); i++ )
		{
			if( Modifiers[ i ] && Modifiers[ i ]->Active )
				Modifiers[ i ]->Update( DeltaTime );
		}

		/* Need to send new dynamic data */
		MarkRenderDynamicDataDirty( );
	}
}
Example #23
0
void APawn::Destroyed()
{
	DetachFromControllerPendingDestroy();
	GetWorld()->RemovePawn( this );
	Super::Destroyed();
}
Example #24
0
void cRoot::LoadWorlds(cSettingsRepositoryInterface & a_Settings, bool a_IsNewIniFile)
{
	if (a_IsNewIniFile)
	{
		a_Settings.AddValue("Worlds", "DefaultWorld", "world");
		a_Settings.AddValue("Worlds", "World", "world_nether");
		a_Settings.AddValue("Worlds", "World", "world_end");
		m_pDefaultWorld = new cWorld("world");
		m_WorldsByName["world"] = m_pDefaultWorld;
		m_WorldsByName["world_nether"] = new cWorld("world_nether", dimNether, "world");
		m_WorldsByName["world_end"] = new cWorld("world_end", dimEnd, "world");
		return;
	}

	// First get the default world
	AString DefaultWorldName = a_Settings.GetValueSet("Worlds", "DefaultWorld", "world");
	m_pDefaultWorld = new cWorld(DefaultWorldName.c_str());
	m_WorldsByName[ DefaultWorldName ] = m_pDefaultWorld;
	auto Worlds = a_Settings.GetValues("Worlds");

	// Fix servers that have default world configs created prior to #2815. See #2810.
	// This can probably be removed several years after 2016
	// We start by inspecting the world linkage and determining if it's the default one
	if ((DefaultWorldName == "world") && (Worlds.size() == 1))
	{
		auto DefaultWorldIniFile= cpp14::make_unique<cIniFile>();
		if (DefaultWorldIniFile->ReadFile("world/world.ini"))
		{
			AString NetherName = DefaultWorldIniFile->GetValue("LinkedWorlds", "NetherWorldName", "");
			AString EndName = DefaultWorldIniFile->GetValue("LinkedWorlds", "EndWorldName", "");
			if ((NetherName.compare("world_nether") == 0) && (EndName.compare("world_end") == 0))
			{
				// This is a default world linkage config, see if the nether and end are in settings.ini
				// If both of them are not in settings.ini, then this is a pre-#2815 default config
				// so we add them to settings.ini
				// Note that if only one of them is not in settings.ini, it's nondefault and we don't touch it

				bool NetherInSettings = false;
				bool EndInSettings = false;

				for (auto WorldNameValue : Worlds)
				{
					AString ValueName = WorldNameValue.first;
					if (ValueName.compare("World") != 0)
					{
						continue;
					}
					AString WorldName = WorldNameValue.second;
					if (WorldName.compare("world_nether") == 0)
					{
						NetherInSettings = true;
					}
					else if (WorldName.compare("world_end") == 0)
					{
						EndInSettings = true;
					}
				}

				if ((!NetherInSettings) && (!EndInSettings))
				{
					a_Settings.AddValue("Worlds", "World", "world_nether");
					a_Settings.AddValue("Worlds", "World", "world_end");
					Worlds = a_Settings.GetValues("Worlds");  // Refresh the Worlds list so that the rest of the function works as usual
					LOG("The server detected an old default config with bad world linkages. This has been autofixed by adding \"world_nether\" and \"world_end\" to settings.ini");
				}
			}
		}
	}

	// Then load the other worlds
	if (Worlds.size() <= 0)
	{
		return;
	}

	/* Here are the world creation rules. Note that these only apply for a world which is in settings.ini but has no world.ini file.
	If an ini file is present, it overrides the world linkages and the dimension type in cWorld::start()
	The creation rules are as follows:

	- If a world exists in settings.ini but has no world.ini, then:
		- If the world name is x_nether, create a world.ini with the dimension type "nether".
			- If a world called x exists, set it as x_nether's overworld.
			- Otherwise set the default world as x_nether's overworld.

		- If the world name is x_end, create a world.ini with the dimension type "end".
			- If a world called x exists, set it as x_end's overworld.
			- Otherwise set the default world as x_end's overworld.

		- If the world name is x (and doesn't end with _end or _nether)
			- Create a world.ini with a dimension type of "overworld".
			- If a world called x_nether exists, set it as x's nether world.
			- Otherwise set x's nether world to blank.h
			- If a world called x_end  exists, set it as x's end world.
			- Otherwise set x's nether world to blank.

	*/

	bool FoundAdditionalWorlds = false;
	for (auto WorldNameValue : Worlds)
	{
		AString ValueName = WorldNameValue.first;
		if (ValueName.compare("World") != 0)
		{
			continue;
		}
		AString WorldName = WorldNameValue.second;
		if (WorldName.empty())
		{
			continue;
		}
		FoundAdditionalWorlds = true;
		cWorld * NewWorld;
		AString LowercaseName = StrToLower(WorldName);
		AString NetherAppend="_nether";
		AString EndAppend="_end";

		// if the world is called x_nether
		if ((LowercaseName.size() > NetherAppend.size()) && (LowercaseName.substr(LowercaseName.size() - NetherAppend.size()) == NetherAppend))
		{
			// The world is called x_nether, see if a world called x exists. If yes, choose it as the linked world,
			// otherwise, choose the default world as the linked world.
			// As before, any ini settings will completely override this if an ini is already present.

			AString LinkTo = WorldName.substr(0, WorldName.size() - NetherAppend.size());
			if (GetWorld(LinkTo) == nullptr)
			{
				LinkTo = DefaultWorldName;
			}
			NewWorld = new cWorld(WorldName.c_str(), dimNether, LinkTo);
		}
		// if the world is called x_end
		else if ((LowercaseName.size() > EndAppend.size()) && (LowercaseName.substr(LowercaseName.size() - EndAppend.size()) == EndAppend))
		{
			// The world is called x_end, see if a world called x exists. If yes, choose it as the linked world,
			// otherwise, choose the default world as the linked world.
			// As before, any ini settings will completely override this if an ini is already present.

			AString LinkTo = WorldName.substr(0, WorldName.size() - EndAppend.size());
			if (GetWorld(LinkTo) == nullptr)
			{
				LinkTo = DefaultWorldName;
			}
			NewWorld = new cWorld(WorldName.c_str(), dimEnd, LinkTo);
		}
		else
		{
			NewWorld = new cWorld(WorldName.c_str());
		}
		m_WorldsByName[WorldName] = NewWorld;
	}  // for i - Worlds

	if (!FoundAdditionalWorlds)
	{
		if (a_Settings.GetKeyComment("Worlds", 0) != " World=secondworld")
		{
			a_Settings.DeleteKeyComment("Worlds", 0);
			a_Settings.AddKeyComment("Worlds", " World=secondworld");
		}
	}
}
Example #25
0
void APhysicsVolume::PostInitializeComponents()
{
	Super::PostInitializeComponents();
	GetWorld()->AddPhysicsVolume(this);
}
ABeaconLeagueGameMode::ABeaconLeagueGameMode(): NnewBeacon(0)
{
	PlayerControllerClass = ABeaconController::StaticClass();
	DefaultPawnClass = ABLCameraSpectatorPawn::StaticClass();
	World = GetWorld();
}
Example #27
0
void ASpawnEnemy::SetTime(float Time)
{
	if (Repeat) {
		GetWorld()->GetTimerManager().SetTimer(this, &ASpawnEnemy::SpawnRandomEnemy, Time, true);
	}
}
Example #28
0
bool UGameInstance::StartPIEGameInstance(ULocalPlayer* LocalPlayer, bool bInSimulateInEditor, bool bAnyBlueprintErrors, bool bStartInSpectatorMode)
{
	UEditorEngine* const EditorEngine = CastChecked<UEditorEngine>(GetEngine());
	ULevelEditorPlaySettings const* PlayInSettings = GetDefault<ULevelEditorPlaySettings>();

	const EPlayNetMode PlayNetMode = [&PlayInSettings]{ EPlayNetMode NetMode(PIE_Standalone); return (PlayInSettings->GetPlayNetMode(NetMode) ? NetMode : PIE_Standalone); }();

	// for clients, just connect to the server
	if (PlayNetMode == PIE_Client)
	{
		FString Error;
		FURL BaseURL = WorldContext->LastURL;
		if (EditorEngine->Browse(*WorldContext, FURL(&BaseURL, TEXT("127.0.0.1"), (ETravelType)TRAVEL_Absolute), Error) == EBrowseReturnVal::Pending)
		{
			EditorEngine->TransitionType = TT_WaitingToConnect;
		}
		else
		{
			FMessageDialog::Open(EAppMsgType::Ok, FText::Format(NSLOCTEXT("UnrealEd", "Error_CouldntLaunchPIEClient", "Couldn't Launch PIE Client: {0}"), FText::FromString(Error)));
			return false;
		}
	}
	else
	{
		// we're going to be playing in the current world, get it ready for play
		UWorld* const PlayWorld = GetWorld();

		// make a URL
		FURL URL;
		// If the user wants to start in spectator mode, do not use the custom play world for now
		if (EditorEngine->UserEditedPlayWorldURL.Len() > 0 && !bStartInSpectatorMode)
		{
			// If the user edited the play world url. Verify that the map name is the same as the currently loaded map.
			URL = FURL(NULL, *EditorEngine->UserEditedPlayWorldURL, TRAVEL_Absolute);
			if (URL.Map != PIEMapName)
			{
				// Ensure the URL map name is the same as the generated play world map name.
				URL.Map = PIEMapName;
			}
		}
		else
		{
			// The user did not edit the url, just build one from scratch.
			URL = FURL(NULL, *EditorEngine->BuildPlayWorldURL(*PIEMapName, bStartInSpectatorMode), TRAVEL_Absolute);
		}

		// If a start location is specified, spawn a temporary PlayerStartPIE actor at the start location and use it as the portal.
		AActor* PlayerStart = NULL;
		if (EditorEngine->SpawnPlayFromHereStart(PlayWorld, PlayerStart, EditorEngine->PlayWorldLocation, EditorEngine->PlayWorldRotation) == false)
		{
			// failed to create "play from here" playerstart
			FMessageDialog::Open(EAppMsgType::Ok, NSLOCTEXT("UnrealEd", "Error_FailedCreatePlayFromHerePlayerStart", "Failed to create PlayerStart at desired starting location."));
			return false;
		}

		if (!PlayWorld->SetGameMode(URL))
		{
			// Setting the game mode failed so bail 
			FMessageDialog::Open(EAppMsgType::Ok, NSLOCTEXT("UnrealEd", "Error_FailedCreateEditorPreviewWorld", "Failed to create editor preview world."));
			return false;
		}
		
		// Make sure "always loaded" sub-levels are fully loaded
		PlayWorld->FlushLevelStreaming(EFlushLevelStreamingType::Visibility);

		UNavigationSystem::InitializeForWorld(PlayWorld, LocalPlayers.Num() > 0 ? FNavigationSystemRunMode::PIEMode : FNavigationSystemRunMode::SimulationMode);
		PlayWorld->CreateAISystem();

		PlayWorld->InitializeActorsForPlay(URL);

		// @todo, just use WorldContext.GamePlayer[0]?
		if (LocalPlayer)
		{
			FString Error;
			if (!LocalPlayer->SpawnPlayActor(URL.ToString(1), Error, PlayWorld))
			{
				FMessageDialog::Open(EAppMsgType::Ok, FText::Format(NSLOCTEXT("UnrealEd", "Error_CouldntSpawnPlayer", "Couldn't spawn player: {0}"), FText::FromString(Error)));
				return false;
			}
		}

		UGameViewportClient* const GameViewport = GetGameViewportClient();
		if (GameViewport != NULL && GameViewport->Viewport != NULL)
		{
			// Stream any levels now that need to be loaded before the game starts
			GEngine->BlockTillLevelStreamingCompleted(PlayWorld);
		}
		
		if (PlayNetMode == PIE_ListenServer)
		{
			// start listen server with the built URL
			PlayWorld->Listen(URL);
		}

		PlayWorld->BeginPlay();
	}

	return true;
}
void UPrimitiveComponent::UnWeldFromParent()
{
	FBodyInstance* NewRootBI = GetBodyInstance(NAME_None, false);
	UWorld* CurrentWorld = GetWorld();
	if (NewRootBI == NULL || NewRootBI->bWelded == false || CurrentWorld == nullptr || IsPendingKill())
	{
		return;
	}

	FName SocketName;
	UPrimitiveComponent * RootComponent = GetRootWelded(this, AttachSocketName, &SocketName);

	if (RootComponent)
	{
		if (FBodyInstance* RootBI = RootComponent->GetBodyInstance(SocketName, false))
		{
			bool bRootIsBeingDeleted = RootComponent->HasAnyFlags(RF_PendingKill) || RootComponent->HasAnyFlags(RF_Unreachable);
			if (!bRootIsBeingDeleted)
			{
				//create new root
				RootBI->UnWeld(NewRootBI);	//don't bother fixing up shapes if RootComponent is about to be deleted
			}

			NewRootBI->bWelded = false;
			const FBodyInstance* PrevWeldParent = NewRootBI->WeldParent;
			NewRootBI->WeldParent = nullptr;

			bool bHasBodySetup = GetBodySetup() != nullptr;

			//if BodyInstance hasn't already been created we need to initialize it
			if (bHasBodySetup && NewRootBI->IsValidBodyInstance() == false)
			{
				bool bPrevAutoWeld = NewRootBI->bAutoWeld;
				NewRootBI->bAutoWeld = false;
				NewRootBI->InitBody(GetBodySetup(), GetComponentToWorld(), this, CurrentWorld->GetPhysicsScene());
				NewRootBI->bAutoWeld = bPrevAutoWeld;
			}

			if(PrevWeldParent == nullptr)	//our parent is kinematic so no need to do any unwelding/rewelding of children
			{
				return;
			}

			//now weld its children to it
			TArray<FBodyInstance*> ChildrenBodies;
			TArray<FName> ChildrenLabels;
			GetWeldedBodies(ChildrenBodies, ChildrenLabels);

			for (int32 ChildIdx = 0; ChildIdx < ChildrenBodies.Num(); ++ChildIdx)
			{
				FBodyInstance* ChildBI = ChildrenBodies[ChildIdx];
				if (ChildBI != NewRootBI)
				{
					if (!bRootIsBeingDeleted)
					{
						RootBI->UnWeld(ChildBI);
					}

					//At this point, NewRootBI must be kinematic because it's being unwelded. It's up to the code that simulates to call Weld on the children as needed
					ChildBI->WeldParent = nullptr;	//null because we are currently kinematic
				}
			}
		}
	}
}
// turn rate
void AClashOfBallsBall::TurnAtRate(float Rate)
{
	// calculate delta for this frame from the rate information
	AddControllerYawInput(Rate * BaseTurnRate * GetWorld()->GetDeltaSeconds());
}