diff --git a/Content/Tangibles/TangibleCharacter.uasset b/Content/Tangibles/TangibleCharacter.uasset index fdfc10b6..7fcdcadc 100644 --- a/Content/Tangibles/TangibleCharacter.uasset +++ b/Content/Tangibles/TangibleCharacter.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a6103472ea4290df2384bb46e667187ec0ee6413dcbb17a699c0abae2265e7b5 -size 479813 +oid sha256:9b842fe1f573e136e995261869397027b47f39730d6bc705d7904977769d43cd +size 459158 diff --git a/Source/Integration/IntegrationGameModeBase.cpp b/Source/Integration/IntegrationGameModeBase.cpp index 421b35c4..bbc211e2 100644 --- a/Source/Integration/IntegrationGameModeBase.cpp +++ b/Source/Integration/IntegrationGameModeBase.cpp @@ -80,8 +80,15 @@ void AIntegrationGameModeBase::ResetToInitialState() // Clear the lua call assembly buffer. LuaCallBuffer.clear(); + // Clear the PlayerID + PlayerId = 0; + + // Clear the camera ray state. + CameraRayTarget = nullptr; + CameraRayChanged = false; + // Reset the clocks. - EngineSeconds = 0; + EngineSeconds = 0.0; NextRotateCube = 1.0; } @@ -123,12 +130,6 @@ void AIntegrationGameModeBase::UpdateTangibles() { for (int i = 0; i < alltans.Num(); i++) { alltans[i]->UpdateAnimationQueue(allqueues[i]); } - - // Maybe call 'BecomePossessed' on some tangible. - UlxTangible *poss = TangibleManager->SetPossessedTangible(PlayerId); - if (poss != nullptr) { - IlxTangibleInterface::Execute_BecomePossessed(poss->GetActor()); - } } // This is where we run the blueprint code that updates animation // states. Be aware that the blueprint code could call back @@ -141,6 +142,64 @@ void AIntegrationGameModeBase::UpdateTangibles() { TangibleManager->DeleteFarawayTangibles(); } +void AIntegrationGameModeBase::UpdatePossessedTangible() { + bool updated = TangibleManager->SetPossessedTangible(PlayerId); + if (updated) { + UlxTangible *ptan = TangibleManager->GetPossessedTangible(); + if (ptan != nullptr) { + IlxTangibleInterface::Execute_BecomePossessed(ptan->GetActor()); + } + } +} + +void AIntegrationGameModeBase::CastCameraRay() { + // The range we're using is currently hardwired. + double range = 1000.0; + + // If there's no possessed tangible, then we don't even try casting the ray. + UlxTangible *possessed = TangibleManager->GetPossessedTangible(); + if (possessed == nullptr) { + CameraRayChanged = (CameraRayTarget != nullptr); + CameraRayTarget = nullptr; + return; + } + + // Get the ray in question. + // APlayerCameraManager *camManager = GetWorld()->GetFirstPlayerController()->PlayerCameraManager; + // FVector TraceStart = camManager->GetCameraLocation(); + // FVector TraceEnd = camManager->GetCameraRotation().Vector() * range; + FVector TraceStart, TraceVector; + APlayerController *ctrl = GetWorld()->GetFirstPlayerController(); + ctrl->DeprojectScreenPositionToWorld(0.5, 0.5, TraceStart, TraceVector); + FVector TraceEnd = TraceStart + (TraceVector * range); + + // FHitResult will hold all data returned by our line collision query + FHitResult Hit; + + // You can use FCollisionQueryParams to further configure the query + // Here we add ourselves to the ignored list so we won't block the trace + FCollisionQueryParams QueryParams; + QueryParams.AddIgnoredActor(possessed->GetActor()); + + // To run the query, you need a pointer to the current level, which you can get from an Actor with GetWorld() + // UWorld()->LineTraceSingleByChannel runs a line trace and returns the first actor hit over the provided collision channel. + GetWorld()->LineTraceSingleByChannel(Hit, TraceStart, TraceEnd, ECC_Visibility, QueryParams); + + // You can use DrawDebug helpers and the log to help visualize and debug your trace queries. + // DrawDebugLine(GetWorld(), TraceStart, TraceEnd, Hit.bBlockingHit ? FColor::Blue : FColor::Red, false, 5.0f, 0, 10.0f); + // UE_LOG(LogTemp, Log, TEXT("Tracing line: %s to %s"), *TraceStart.ToCompactString(), *TraceEnd.ToCompactString()); + + // If the trace hit something, bBlockingHit will be true, + // and its fields will be filled with detailed info about what was hit + if (Hit.bBlockingHit && IsValid(Hit.GetActor())) { + CameraRayChanged = (CameraRayTarget != Hit.GetActor()); + CameraRayTarget = Hit.GetActor(); + } else { + CameraRayChanged = (CameraRayTarget != nullptr); + CameraRayTarget = nullptr; + } +} + void AIntegrationGameModeBase::LuaCallEnd(InvocationKind kind, int64 place_id) { std::string_view datapk = LuaCallBuffer.view(); FlxLockedWrapper w(LockableWrapper); @@ -213,6 +272,8 @@ void AIntegrationGameModeBase::OnWorldPreActorTick(UWorld* InWorld, ELevelTick I EngineSeconds += deltaseconds; UpdateConsoleOutput(); UpdateTangibles(); + UpdatePossessedTangible(); + //CastCameraRay(); } } @@ -228,8 +289,6 @@ void AIntegrationGameModeBase::OnWorldPostActorTick(UWorld* InWorld, ELevelTick void AIntegrationGameModeBase::Tick(float deltaseconds) { Super::Tick(deltaseconds); - UpdateConsoleOutput(); - UpdateTangibles(); } void AIntegrationGameModeBase::BeginPlay() diff --git a/Source/Integration/IntegrationGameModeBase.h b/Source/Integration/IntegrationGameModeBase.h index a1e5c96e..64ab7e23 100644 --- a/Source/Integration/IntegrationGameModeBase.h +++ b/Source/Integration/IntegrationGameModeBase.h @@ -69,8 +69,17 @@ public: void UpdateConsoleOutput(); // Update the tangibles according to what Luprex tells us. + // This also includes calling 'AnimationQueueChanged' on all + // tangibles that have been changed. void UpdateTangibles(); + // Maybe call 'BecomePossessed' on the player tangible. + void UpdatePossessedTangible(); + + // Cast a ray forward from the camera. Update the instance + // variables 'CameraRayTarget' and 'CameraRayChanged'. + void CastCameraRay(); + // Pre-tick and post-tick functions. void OnWorldPreActorTick(UWorld* InWorld, ELevelTick InLevelTick, float InDeltaSeconds); void OnWorldPostActorTick(UWorld* InWorld, ELevelTick InLevelTick, float InDeltaSeconds); @@ -110,6 +119,10 @@ public: // Current Player ID int64 PlayerId; + // Object in front of camera. + AActor *CameraRayTarget; + bool CameraRayChanged; + // Amount of elapsed time since BeginPlay. float EngineSeconds; diff --git a/Source/Integration/TangibleManager.cpp b/Source/Integration/TangibleManager.cpp index 7947d9a3..de71a21d 100644 --- a/Source/Integration/TangibleManager.cpp +++ b/Source/Integration/TangibleManager.cpp @@ -77,17 +77,14 @@ TanArray UlxTangibleManager::GetAllTangibles() const { return result; } -UlxTangible *UlxTangibleManager::SetPossessedTangible(int64 id) { +bool UlxTangibleManager::SetPossessedTangible(int64 id) { UlxTangible *t = GetTangible(id); if ((t == nullptr) || (t->GetActor() == nullptr)) { - PossessedTangible = nullptr; - return nullptr; - } else if (t == PossessedTangible) { - return nullptr; - } else { - PossessedTangible = t; - return t; + t = nullptr; } + bool changed = (t != PossessedTangible); + PossessedTangible = t; + return changed; } #pragma optimize("", off) diff --git a/Source/Integration/TangibleManager.h b/Source/Integration/TangibleManager.h index bb75ed5a..fc299cf5 100644 --- a/Source/Integration/TangibleManager.h +++ b/Source/Integration/TangibleManager.h @@ -66,18 +66,19 @@ public: // TanArray GetAllTangibles() const; - // Set the currently-posessed tangible. + // Get the currently-possessed tangible. // - // If the specified tangible is invalid: - // Sets the possessed tangible to nullptr and returns nullptr. + // This can be nullptr if no tangible is possessed. // - // If the specified tangible is valid, but it's already possessed: - // Does nothing and returns nullptr. + UlxTangible *GetPossessedTangible() { return PossessedTangible; } + + // Set the currently-possessed tangible. // - // If the specified tangible is valid, and is not already possessed: - // Sets the possessed tangible as specified and returns it. + // You can also pass 0 for "no possessed tangible." // - UlxTangible *SetPossessedTangible(int64 playerid); + // Returns true if something changed. + // + bool SetPossessedTangible(int64 playerid); // Update the 'NearAccordingToLuprex' flags. //