Wimberton / OriginPalia

A multi-purpose tool for Palia, written in C++. For non-commercial usage, looking for contributors. Features such as ESP, Teleportation, Auto-fishing, and more.
https://www.unknowncheats.me/forum/palia/636934-originpalia-feature-packed-multitool-imagine.html
29 stars 10 forks source link

Fixed filtering for the Pickable List #23

Closed VoidPollo closed 1 month ago

VoidPollo commented 1 month ago

~ Pickable List now populates from enabled Forageable ESP options. ~ Added a slight Z increase to the pickable list entries. ~ Changed the only 2 instances of K2_TeleportTo to K2_SetActorLocation, as the rest of the project uses it. (Commented it out this time, hehe)

Wimberton commented 1 month ago

I've approved this merge request. Thanks for putting in the time to finalize the item pickables list! Got a bit lazy since I had to work on a ton of other stuff at the same time.

VoidPollo commented 1 month ago

I'm trying to fix the low-hanging fruits just for polishing while your mind is set on the upcoming features.

Wimberton commented 1 month ago

I'm trying to fix the low-hanging fruits just for polishing while your mind is set on the upcoming features.

I appreciate all of the contributions! I'm almost finished with the gather all from the map, without moving. Having a slight issue getting the FSessionActorId, and possibly getting that through the QueryManager ActorToSessionId method.

It'll be figured out... Feel free to dig yourself. I've provided my current code below for it:

Method

void TryGatherItems() {
    PaliaOverlay* Overlay = static_cast<PaliaOverlay*>(OverlayBase::Instance);

    auto World = GetWorld();
    if (!World) return;

    UGameplayStatics* GameplayStatics = static_cast<UGameplayStatics*>(UGameplayStatics::StaticClass()->DefaultObject);
    if (!GameplayStatics) return;

    auto GameInstance = World->OwningGameInstance;
    if (!GameInstance) return;

    if (GameInstance->LocalPlayers.Num() == 0) return;

    ULocalPlayer* LocalPlayer = GameInstance->LocalPlayers[0];
    if (!LocalPlayer) return;

    APlayerController* PlayerController = LocalPlayer->PlayerController;
    if (!PlayerController) return;

    AValeriaPlayerController* ValeriaController = static_cast<AValeriaPlayerController*>(PlayerController);
    if (!ValeriaController) return;

    AValeriaCharacter* ValeriaCharacter = static_cast<AValeriaCharacter*>(PlayerController->K2_GetPawn());
    if (!ValeriaCharacter) return;

    UQueryManager* QueryManager = static_cast<UQueryManager*>(UQueryManager::StaticClass()->DefaultObject);
    if (!QueryManager) return;

    SDK::TArray<SDK::AActor*> actors;
    GameplayStatics->GetAllActorsOfClass(World, SDK::ABP_ValeriaGatherable_C::StaticClass(), &actors);

    int gathered = 0;
    for (int i = 0; i < actors.Num(); ++i) {

        auto* actor = reinterpret_cast<SDK::ABP_ValeriaGatherable_C*>(actors[i]);
        auto* GatherComponent = actor->Gatherable;
        auto* InteractorComponent = actor->Interactable;

        if (GatherComponent->CanBeGatheredBy(ValeriaCharacter) &&
            !GatherComponent->bEquipmentRequiredToGather &&
            GatherComponent->EquipmentRequiredItemTags.Num() == 0 &&
            GatherComponent->EquipmentRequiredItemGameplayTags.GameplayTags.GameplayTags.Num() == 0 &&
            GatherComponent->EquipmentRequiredItemGameplayTags.GameplayTags.ParentTags.Num() == 0 &&
            PaliaOverlay::IsFree(GatherComponent) &&
            InteractorComponent->IsInteractable(ValeriaCharacter) &&
            InteractorComponent->InteractableRequirementsMet(ValeriaCharacter)) {
            FSessionActorId GatherableId;

            ValeriaController->RpcServer_GatherActorOrPlaceables(GatherableId, nullptr, false);
            ++gathered;
        }
    }
}

// COULD BE DONE SOMEWHAT LIKE THIS ALSO
FSessionActorId* SessionId = QueryManager->ActorToSessionId.Find(actor);
if (SessionId) {
    ValeriaController->RpcServer_GatherActorOrPlaceables(*SessionId, nullptr, false);
    ++gathered;
}

Button (Movement & Teleport - Under pickable list)

if (ImGui::Button("Gather Actors")) {
    TryGatherItems();
}

The code above works, but throws the no permission notification in-game, so the only thing we need to figure out is getting each iterated Gatherable's FSessionActorId to pick them up.

VoidPollo commented 1 month ago

Time to poke around

Wimberton commented 1 month ago

Time to poke around

Tbh I'm not even sure that's the right way. I'm sure it'll have something to do with the Interactor and Gatherable, but after I've continued to tweak it, it doesn't seem right.

I'd think we'd be able to trigger the PrimaryInteractPressed() which would lead us closer to the objects that'll handle gathering. It used to be RpcServer_GatherActor(); but that seems to have changed. It was old either way.

Here's some old code that might help. It's interesting, nonetheless. (source)

    SDK::TArray<SDK::AActor*> actors;
    gameplayStatics->GetAllActorsOfClass(GetWorld(),
                                         SDK::ABP_ValeriaGatherable_C::StaticClass(), &actors);
    for (int i = 0; i < actors.Num(); ++i) {
        auto* actor = reinterpret_cast<SDK::ABP_ValeriaGatherable_C*>(actors[i]);
        auto* gComp = actor->Gatherable;
        auto* iComp = actor->Interactable;
        if (gComp->CanBeGatheredBy(character) &&
            !gComp->bEquipmentRequiredToGather &&
            gComp->EquipmentRequiredItemTags.Num() == 0 &&
            gComp->EquipmentRequiredItemGameplayTags.GameplayTags.GameplayTags.Num() == 0 &&
            gComp->EquipmentRequiredItemGameplayTags.GameplayTags.ParentTags.Num() == 0 &&
            IsFree(gComp) &&
            iComp->IsInteractable(character) &&
            iComp->InteractableRequirementsMet(character)) {
            controller->RpcServer_GatherActor(actor);
            ++gathered;
        }
    }

bool IsFree(SDK::UGatherableComponent* comp) {
    auto isFree = [](SDK::EVitalType type) {
        return type != SDK::EVitalType::Coins &&
                type != SDK::EVitalType::CommunityPoints &&
                type != SDK::EVitalType::Health &&
                type != SDK::EVitalType::MedalFishing &&
                type != SDK::EVitalType::PremiumCurrency;
    };
    return isFree(comp->VitalRequired) && isFree(comp->Vital2Required);
}
VoidPollo commented 1 month ago

gotime

The live debugger works in this game too... why didn't I even try this before.. so much easier to search and look for things.

Wimberton commented 1 month ago

gotime

The live debugger works in this game too... why didn't I even try this before.. so much easier to search and look for things.

LMFAO good to know. I've been hooking VS into it and just breakpointing some functions that way. This will speed some things up.

VoidPollo commented 1 month ago

pawn

Ummh? So my thinking was, instead of sending to the server RpcServer_Gather-- I teleport the actors to me instead to see If I could pick them up manually first, but a Wardrobe that I can interact with got put on my location instead of gatherables..

Wimberton commented 1 month ago

pawn

Ummh? So my thinking was, instead of sending to the server RpcServer_Gather-- I teleport the actors to me instead to see If I could pick them up manually first, but a Wardrobe that I can interact with got put on my location instead of gatherables..

That was my worry also. I figured based on the AHousingOwnershipActor* that it could be a housing RPC. There's also a chance my start of the Interactable code would work instead. Here's that.

void SimulateGatherInteractables(UInteractorComponent* Interactor, TArray<FEntry>& CachedActors) {
    for (auto& Entry : CachedActors) {
        if (Entry.shouldAdd && (Entry.ActorType == EType::Forage || Entry.ActorType == EType::Loot)) {
            UInteractableComponent* Interactable = static_cast<UInteractableComponent*>(Entry.Actor->GetComponentByClass(UInteractableComponent::StaticClass()));
            if (Interactable) {
                Interactable->SetPreventHideByRequirementsCheck(true);
                while (Interactable->InteractionBlockerCount > 0) {
                    Interactable->RemoveInteractionBlocker();
                }

                FVAL_InteractorLockParams LockParams;
                LockParams.Interactable = Interactable;
                LockParams.bEnforceFacing = false;
                LockParams.bEnforcePosition = false;

                if (Interactor->LockPlayerToInteractable(LockParams)) {
                    FInteractEventParams Params;
                    Interactor->InteractWithHighlighted(Params);
                    Interactor->UnlockPlayerFromInteractable(LockParams);
                }
            }
        }
    }
}