diff --git a/Project Reboot 3.0/FortPlayerController.cpp b/Project Reboot 3.0/FortPlayerController.cpp index 655fcf8..fc3c240 100644 --- a/Project Reboot 3.0/FortPlayerController.cpp +++ b/Project Reboot 3.0/FortPlayerController.cpp @@ -1374,28 +1374,58 @@ void AFortPlayerController::ClientOnPawnDiedHook(AFortPlayerController* PlayerCo KillerPlayerState->ClientReportKill(DeadPlayerState); - /* LoopMutators([&](AFortAthenaMutator* Mutator) { - if (auto TDM_Mutator = Cast(Mutator)) - { - struct - { - int EventId; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) - int EventParam1; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) - int EventParam2; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) - int EventParam3; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) - } AFortAthenaMutator_TDM_OnMutatorGameplayEvent_Params{ 1, 0, 0, 0 }; - - static auto TDM_OnMutatorGameplayEventFn = FindObject("/Script/FortniteGame.FortAthenaMutator_TDM.OnMutatorGameplayEvent"); - TDM_Mutator->ProcessEvent(TDM_OnMutatorGameplayEventFn, &AFortAthenaMutator_TDM_OnMutatorGameplayEvent_Params); - } - }); */ - // KillerPlayerState->OnRep_Kills(); + + if (AmountOfHealthSiphon > 0) + { + auto KillerAbilityComp = KillerPlayerState->GetAbilitySystemComponent(); + + if (KillerAbilityComp) + { + auto ActivatableAbilities = KillerAbilityComp->GetActivatableAbilities(); + auto& Items = ActivatableAbilities->GetItems(); + for (size_t i = 0; i < Items.Num(); ++i) + { + auto& Item = Items.At(i, FGameplayAbilitySpec::GetStructSize()); + auto Ability = Item.GetAbility(); + if (Ability && Ability->ClassPrivate && Ability->ClassPrivate->GetName().contains("Siphon")) + { + FGameplayTag Tag{}; + Tag.TagName = UKismetStringLibrary::Conv_StringToName(TEXT("GameplayCue.Shield.PotionConsumed")); + + auto NetMulticast_InvokeGameplayCueAdded = FindObject(L"/Script/GameplayAbilities.AbilitySystemComponent.NetMulticast_InvokeGameplayCueAdded"); + auto NetMulticast_InvokeGameplayCueExecuted = FindObject(L"/Script/GameplayAbilities.AbilitySystemComponent.NetMulticast_InvokeGameplayCueExecuted"); + + if (!NetMulticast_InvokeGameplayCueAdded || !NetMulticast_InvokeGameplayCueExecuted) + break; + + static auto GameplayCueTagOffsetAdded = NetMulticast_InvokeGameplayCueAdded->GetOffsetFunc("GameplayCueTag"); + static auto GameplayCueTagOffsetExecuted = NetMulticast_InvokeGameplayCueExecuted->GetOffsetFunc("GameplayCueTag"); + static auto PredictionKeyOffsetAdded = NetMulticast_InvokeGameplayCueAdded->GetOffsetFunc("PredictionKey"); + + auto AddedParams = Alloc(NetMulticast_InvokeGameplayCueAdded->GetPropertiesSize()); + auto ExecutedParams = Alloc(NetMulticast_InvokeGameplayCueExecuted->GetPropertiesSize()); + + if (!AddedParams || !ExecutedParams) + break; + + *(FGameplayTag*)(int64(AddedParams) + GameplayCueTagOffsetAdded) = Tag; + *(FGameplayTag*)(int64(ExecutedParams) + GameplayCueTagOffsetExecuted) = Tag; + //(FPredictionKey*)(int64(AddedParams) + PredictionKeyOffsetAdded) = Tag; + + KillerAbilityComp->ProcessEvent(NetMulticast_InvokeGameplayCueAdded, AddedParams); + KillerAbilityComp->ProcessEvent(NetMulticast_InvokeGameplayCueExecuted, ExecutedParams); + + break; + } + } + } + } } // LOG_INFO(LogDev, "Reported kill."); - if (AmountOfHealthSiphon != 0) + if (AmountOfHealthSiphon > 0) { if (KillerPawn && KillerPawn != DeadPawn) { @@ -1550,20 +1580,6 @@ void AFortPlayerController::ClientOnPawnDiedHook(AFortPlayerController* PlayerCo /* - STATS: - - Note: This isn't the exact order relative to other functions. - - ClientSendMatchStatsForPlayer - ClientSendTeamStatsForPlayer - ClientSendEndBattleRoyaleMatchForPlayer - - */ - - // FAthenaMatchStats.Stats[ERewardSource] // hmm - - /* - // We need to check if their entire team is dead then I think we send it???? auto DeadControllerAthena = Cast(PlayerController); diff --git a/Project Reboot 3.0/Object.cpp b/Project Reboot 3.0/Object.cpp index f16b8aa..a6a46c0 100644 --- a/Project Reboot 3.0/Object.cpp +++ b/Project Reboot 3.0/Object.cpp @@ -45,6 +45,43 @@ void* UObject::GetProperty(const std::string& ChildName, bool bWarnIfNotFound) c return nullptr; } + +void* UObject::GetPropertyFunc(const std::string& ChildName, bool bWarnIfNotFound) +{ + auto Func = (UFunction*)this; + void* Property = *(void**)(__int64(Func) + Offsets::Children); + + if (Property) + { + // LOG_INFO(LogDev, "Reading prop name.."); + + std::string PropName = GetFNameOfProp(Property)->ToString(); + + // LOG_INFO(LogDev, "PropName: {}", PropName); + + if (PropName == ChildName) + { + return Property; + } + + while (Property) + { + if (PropName == ChildName) + { + return Property; + } + + Property = GetNext(Property); + PropName = Property ? GetFNameOfProp(Property)->ToString() : ""; + } + } + + if (bWarnIfNotFound) + LOG_WARN(LogFinder, "Unable to find3{}", ChildName); + + return nullptr; +} + void* UObject::GetProperty(const std::string& ChildName, bool bWarnIfNotFound) { for (auto CurrentClass = ClassPrivate; CurrentClass; CurrentClass = *(UClass**)(__int64(CurrentClass) + Offsets::SuperStruct)) @@ -90,7 +127,7 @@ int UObject::GetOffset(const std::string& ChildName, bool bWarnIfNotFound) if (!Property) return -1; - return *(int*)(__int64(Property) + Offsets::Offset_Internal); + return *(int*)(__int64(Property) + Offsets::Offset_Internal); } int UObject::GetOffset(const std::string& ChildName, bool bWarnIfNotFound) const @@ -103,6 +140,16 @@ int UObject::GetOffset(const std::string& ChildName, bool bWarnIfNotFound) const return *(int*)(__int64(Property) + Offsets::Offset_Internal); } +int UObject::GetOffsetFunc(const std::string& ChildName, bool bWarnIfNotFound) +{ + auto Property = GetPropertyFunc(ChildName, bWarnIfNotFound); + + if (!Property) + return -1; + + return *(int*)(__int64(Property) + Offsets::Offset_Internal); +} + void* UObject::GetInterfaceAddress(UClass* InterfaceClass) { static void* (*GetInterfaceAddressOriginal)(UObject* a1, UClass* a2) = decltype(GetInterfaceAddressOriginal)(Addresses::GetInterfaceAddress); diff --git a/Project Reboot 3.0/Object.h b/Project Reboot 3.0/Object.h index 9817413..744c62f 100644 --- a/Project Reboot 3.0/Object.h +++ b/Project Reboot 3.0/Object.h @@ -64,8 +64,10 @@ public: void* GetProperty(const std::string& ChildName, bool bWarnIfNotFound = true); void* GetProperty(const std::string& ChildName, bool bWarnIfNotFound = true) const; + void* GetPropertyFunc(const std::string& ChildName, bool bWarnIfNotFound = true); int GetOffset(const std::string& ChildName, bool bWarnIfNotFound = true); int GetOffset(const std::string& ChildName, bool bWarnIfNotFound = true) const; + int GetOffsetFunc(const std::string& ChildName, bool bWarnIfNotFound = true); template inline T& Get(int Offset) const { return *(T*)(__int64(this) + Offset); } diff --git a/Project Reboot 3.0/dllmain.cpp b/Project Reboot 3.0/dllmain.cpp index 590cbea..82f2f26 100644 --- a/Project Reboot 3.0/dllmain.cpp +++ b/Project Reboot 3.0/dllmain.cpp @@ -1201,8 +1201,8 @@ DWORD WINAPI Main(LPVOID) static auto ServerReturnToMainMenuFn = FindObject(L"/Script/FortniteGame.FortPlayerController.ServerReturnToMainMenu"); static auto ServerReturnToMainMenuIdx = GetFunctionIdxOrPtr(ServerReturnToMainMenuFn) / 8; - auto FortServerRestartPlayer = FortPlayerControllerDefault->VFTable[ServerReturnToMainMenuIdx]; - VirtualSwap(FortPlayerControllerAthenaDefault->VFTable, ServerReturnToMainMenuIdx, FortServerRestartPlayer); + auto ServerReturnToMainMenu = FortPlayerControllerDefault->VFTable[ServerReturnToMainMenuIdx]; + VirtualSwap(FortPlayerControllerAthenaDefault->VFTable, ServerReturnToMainMenuIdx, ServerReturnToMainMenu); Hooking::MinHook::Hook(FortPlayerControllerAthenaDefault, FindObject(L"/Script/FortniteGame.FortPlayerController.ServerSuicide"), AFortPlayerController::ServerSuicideHook, nullptr, false); diff --git a/Project Reboot 3.0/gui.h b/Project Reboot 3.0/gui.h index 0a433ee..60d0074 100644 --- a/Project Reboot 3.0/gui.h +++ b/Project Reboot 3.0/gui.h @@ -1474,6 +1474,13 @@ static inline DWORD WINAPI GuiThread(LPVOID) ::RegisterClassEx(&wc); HWND hwnd = ::CreateWindowExW(0L, wc.lpszClassName, (L"Project Reboot " + std::to_wstring(Fortnite_Version)).c_str(), (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX), 100, 100, Width, Height, NULL, NULL, wc.hInstance, NULL); + if (hwnd == NULL) + { + MessageBoxA(0, ("Failed to create GUI window " + std::to_string(GetLastError()) + "!").c_str(), "Reboot 3.0", MB_ICONERROR); + ::UnregisterClass(wc.lpszClassName, wc.hInstance); + return 1; + } + if (false) // idk why this dont work { auto hIcon = LoadIconFromMemory((const char*)reboot_icon_data, strlen((const char*)reboot_icon_data), L"RebootIco"); @@ -1486,6 +1493,7 @@ static inline DWORD WINAPI GuiThread(LPVOID) // Initialize Direct3D if (!CreateDeviceD3D(hwnd)) { + MessageBoxA(0, "Failed to create D3D Device!", "Reboot 3.0", MB_ICONERROR); LOG_ERROR(LogDev, "Failed to create D3D Device!"); CleanupDeviceD3D(); ::UnregisterClass(wc.lpszClassName, wc.hInstance);