diff --git a/Project Reboot 3.0/AbilitySystemComponent.h b/Project Reboot 3.0/AbilitySystemComponent.h index e01adbc..6247d81 100644 --- a/Project Reboot 3.0/AbilitySystemComponent.h +++ b/Project Reboot 3.0/AbilitySystemComponent.h @@ -11,8 +11,11 @@ struct PadHexB0 { char Pad[0xB0]; }; // using FPredictionKey = PadHex18; // using FGameplayEventData = PadHexA8; +// using FPredictionKey = PadHex10; +using FGameplayEventData = PadHexB0; + using FPredictionKey = __int64; -using FGameplayEventData = __int64; +// using FGameplayEventData = __int64; class UAbilitySystemComponent : public UObject { @@ -32,7 +35,10 @@ public: FGameplayAbilitySpecHandle GiveAbilityEasy(UClass* AbilityClass); FGameplayAbilitySpec* FindAbilitySpecFromHandle(FGameplayAbilitySpecHandle Handle); - static void ServerTryActivateAbilityHook(UAbilitySystemComponent* AbilitySystemComponent, FGameplayAbilitySpecHandle Handle, bool InputPressed, FPredictionKey PredictionKey); - static void ServerTryActivateAbilityWithEventDataHook(UAbilitySystemComponent* AbilitySystemComponent, FGameplayAbilitySpecHandle Handle, bool InputPressed, FPredictionKey PredictionKey, FGameplayEventData TriggerEventData); + static void ServerTryActivateAbilityHook1(UAbilitySystemComponent* AbilitySystemComponent, FGameplayAbilitySpecHandle Handle, bool InputPressed, PadHex10 PredictionKey); + static void ServerTryActivateAbilityHook2(UAbilitySystemComponent* AbilitySystemComponent, FGameplayAbilitySpecHandle Handle, bool InputPressed, PadHex18 PredictionKey); + static void ServerTryActivateAbilityWithEventDataHook1(UAbilitySystemComponent* AbilitySystemComponent, FGameplayAbilitySpecHandle Handle, bool InputPressed, PadHex10 PredictionKey, FGameplayEventData TriggerEventData); + static void ServerTryActivateAbilityWithEventDataHook2(UAbilitySystemComponent* AbilitySystemComponent, FGameplayAbilitySpecHandle Handle, bool InputPressed, PadHex18 PredictionKey, FGameplayEventData TriggerEventData); + static void ServerAbilityRPCBatchHook(UAbilitySystemComponent* AbilitySystemComponent, __int64 BatchInfo); }; \ No newline at end of file diff --git a/Project Reboot 3.0/AbilitySystemComponent_Abilities.cpp b/Project Reboot 3.0/AbilitySystemComponent_Abilities.cpp index c4e1dd7..0a01505 100644 --- a/Project Reboot 3.0/AbilitySystemComponent_Abilities.cpp +++ b/Project Reboot 3.0/AbilitySystemComponent_Abilities.cpp @@ -7,7 +7,7 @@ void LoopSpecs(UAbilitySystemComponent* AbilitySystemComponent, std::functionGetPtr(ActivatableAbilitiesOffset); static auto ItemsOffset = FindOffsetStruct("/Script/GameplayAbilities.GameplayAbilitySpecContainer", "Items"); - auto Items = (TArray<__int64>*)(__int64(ActivatableAbilities) + ItemsOffset); + auto Items = (TArray*)(__int64(ActivatableAbilities) + ItemsOffset); static auto SpecSize = FGameplayAbilitySpec::GetStructSize(); @@ -15,7 +15,7 @@ void LoopSpecs(UAbilitySystemComponent* AbilitySystemComponent, std::functionNum(); i++) { - auto CurrentSpec = (FGameplayAbilitySpec*)(__int64(Items->Data) + (static_cast(SpecSize) * i)); + auto CurrentSpec = Items->AtPtr(i, SpecSize); // (FGameplayAbilitySpec*)(__int64(Items->Data) + (static_cast(SpecSize) * i)); func(CurrentSpec); } } @@ -62,20 +62,20 @@ void InternalServerTryActivateAbility(UAbilitySystemComponent* AbilitySystemComp else LOG_ERROR(LogAbilities, "Prediction key size does not match with any of them!"); - if (res) + if (!res) { LOG_INFO(LogAbilities, "InternalServerTryActivateAbility. Rejecting ClientActivation of {}. InternalTryActivateAbility failed: ", AbilityToActivate->GetName()); AbilitySystemComponent->ClientActivateAbilityFailed(Handle, *(int16_t*)(__int64(PredictionKey) + CurrentOffset)); SetBitfield(Spec, 1, false); // InputPressed = false - - static auto ActivatableAbilitiesOffset = AbilitySystemComponent->GetOffset("ActivatableAbilities"); - AbilitySystemComponent->Get(ActivatableAbilitiesOffset).MarkItemDirty(Spec); } else { LOG_INFO(LogAbilities, "InternalServerTryActivateAbility. Activated {}", AbilityToActivate->GetName()); } + + static auto ActivatableAbilitiesOffset = AbilitySystemComponent->GetOffset("ActivatableAbilities"); + AbilitySystemComponent->Get(ActivatableAbilitiesOffset).MarkItemDirty(Spec); // we only need to do this if the ability fails but eh } FGameplayAbilitySpecHandle UAbilitySystemComponent::GiveAbilityEasy(UClass* AbilityClass) @@ -112,19 +112,30 @@ FGameplayAbilitySpec* UAbilitySystemComponent::FindAbilitySpecFromHandle(FGamepl return SpecToReturn; } -void UAbilitySystemComponent::ServerTryActivateAbilityHook(UAbilitySystemComponent* AbilitySystemComponent, - FGameplayAbilitySpecHandle Handle, bool InputPressed, FPredictionKey PredictionKey) +void UAbilitySystemComponent::ServerTryActivateAbilityHook1(UAbilitySystemComponent* AbilitySystemComponent, FGameplayAbilitySpecHandle Handle, bool InputPressed, PadHex10 PredictionKey) { - LOG_INFO(LogAbilities, "ServerTryActivateAbility"); - InternalServerTryActivateAbility(AbilitySystemComponent, Handle, /* InputPressed, */ &PredictionKey, nullptr); + LOG_INFO(LogAbilities, "ServerTryActivateAbility1"); + InternalServerTryActivateAbility(AbilitySystemComponent, Handle, /* InputPressed, */ (FPredictionKey*)&PredictionKey, nullptr); } -void UAbilitySystemComponent::ServerTryActivateAbilityWithEventDataHook(UAbilitySystemComponent* AbilitySystemComponent, - FGameplayAbilitySpecHandle Handle, bool InputPressed, FPredictionKey PredictionKey, FGameplayEventData TriggerEventData) +void UAbilitySystemComponent::ServerTryActivateAbilityHook2(UAbilitySystemComponent* AbilitySystemComponent, FGameplayAbilitySpecHandle Handle, bool InputPressed, PadHex18 PredictionKey) { - LOG_INFO(LogAbilities, "ServerTryActivateAbilityWithEventData"); + LOG_INFO(LogAbilities, "ServerTryActivateAbility2"); + InternalServerTryActivateAbility(AbilitySystemComponent, Handle, /* InputPressed, */ (FPredictionKey*)&PredictionKey, nullptr); +} + +void UAbilitySystemComponent::ServerTryActivateAbilityWithEventDataHook1(UAbilitySystemComponent* AbilitySystemComponent, FGameplayAbilitySpecHandle Handle, bool InputPressed, PadHex10 PredictionKey, FGameplayEventData TriggerEventData) +{ + LOG_INFO(LogAbilities, "ServerTryActivateAbilityWithEventData1"); InternalServerTryActivateAbility(AbilitySystemComponent, Handle, /* InputPressed, */ - &PredictionKey, &TriggerEventData); + (FPredictionKey*)&PredictionKey, &TriggerEventData); +} + +void UAbilitySystemComponent::ServerTryActivateAbilityWithEventDataHook2(UAbilitySystemComponent* AbilitySystemComponent, FGameplayAbilitySpecHandle Handle, bool InputPressed, PadHex18 PredictionKey, FGameplayEventData TriggerEventData) +{ + LOG_INFO(LogAbilities, "ServerTryActivateAbilityWithEventData2"); + InternalServerTryActivateAbility(AbilitySystemComponent, Handle, /* InputPressed, */ + (FPredictionKey*)&PredictionKey, &TriggerEventData); } void UAbilitySystemComponent::ServerAbilityRPCBatchHook(UAbilitySystemComponent* AbilitySystemComponent, __int64 BatchInfo) diff --git a/Project Reboot 3.0/Actor.cpp b/Project Reboot 3.0/Actor.cpp index ded9732..fc55efe 100644 --- a/Project Reboot 3.0/Actor.cpp +++ b/Project Reboot 3.0/Actor.cpp @@ -43,6 +43,17 @@ UActorComponent* AActor::GetComponentByClass(class UClass* ComponentClass) return AActor_GetComponentByClass_Params.ReturnValue; } +float AActor::GetDistanceTo(AActor* OtherActor) +{ + static auto fn = FindObject("/Script/Engine.Actor.GetDistanceTo"); + + struct { AActor* OtherActor; float ReturnValue; } AActor_GetDistanceTo_Params{OtherActor}; + + this->ProcessEvent(fn, &AActor_GetDistanceTo_Params); + + return AActor_GetDistanceTo_Params.ReturnValue; +} + FVector AActor::GetActorLocation() { static auto K2_GetActorLocationFn = FindObject("/Script/Engine.Actor.K2_GetActorLocation"); diff --git a/Project Reboot 3.0/Actor.h b/Project Reboot 3.0/Actor.h index be2fc5b..f167f13 100644 --- a/Project Reboot 3.0/Actor.h +++ b/Project Reboot 3.0/Actor.h @@ -12,4 +12,5 @@ public: struct FVector GetActorRightVector(); void K2_DestroyActor(); class UActorComponent* GetComponentByClass(class UClass* ComponentClass); + float GetDistanceTo(AActor* OtherActor); }; \ No newline at end of file diff --git a/Project Reboot 3.0/BuildingActor.cpp b/Project Reboot 3.0/BuildingActor.cpp index 1640fe8..d10d139 100644 --- a/Project Reboot 3.0/BuildingActor.cpp +++ b/Project Reboot 3.0/BuildingActor.cpp @@ -61,7 +61,7 @@ void ABuildingActor::OnDamageServerHook(ABuildingActor* BuildingActor, float Dam auto DamageThatWillAffect = Damage; - auto skid = Out / (BuildingSMActor->GetMaxHealth() / DamageThatWillAffect); + float skid = Out / (BuildingSMActor->GetMaxHealth() / DamageThatWillAffect); ResourceCount = round(skid); // almost right } diff --git a/Project Reboot 3.0/BuildingActor.h b/Project Reboot 3.0/BuildingActor.h index 16c01d9..ba089c7 100644 --- a/Project Reboot 3.0/BuildingActor.h +++ b/Project Reboot 3.0/BuildingActor.h @@ -33,7 +33,16 @@ public: void SetTeam(unsigned char InTeam) { static auto fn = FindObject("/Script/FortniteGame.BuildingActor.SetTeam"); - this->ProcessEvent(fn, &InTeam); + + if (!fn) + { + static auto TeamOffset = GetOffset("Team"); + Get(TeamOffset) = InTeam; + } + else + { + this->ProcessEvent(fn, &InTeam); + } } static inline void (*OnDamageServerOriginal)(ABuildingActor* BuildingActor, float Damage, FGameplayTagContainer DamageTags, diff --git a/Project Reboot 3.0/FortGameModeAthena.cpp b/Project Reboot 3.0/FortGameModeAthena.cpp index 43f9e5d..3b5d7e8 100644 --- a/Project Reboot 3.0/FortGameModeAthena.cpp +++ b/Project Reboot 3.0/FortGameModeAthena.cpp @@ -42,11 +42,21 @@ void ShowFoundation(UObject* BuildingFoundation) if (!BuildingFoundation) return; - SetBitfield(BuildingFoundation->GetPtr("bServerStreamedInLevel"), 2, true); + static auto bServerStreamedInLevelFieldMask = GetFieldMask(BuildingFoundation->GetProperty("bServerStreamedInLevel")); + static auto bServerStreamedInLevelOffset = BuildingFoundation->GetOffset("bServerStreamedInLevel"); + BuildingFoundation->SetBitfieldValue(bServerStreamedInLevelOffset, bServerStreamedInLevelFieldMask, true); static auto DynamicFoundationTypeOffset = BuildingFoundation->GetOffset("DynamicFoundationType"); BuildingFoundation->Get(DynamicFoundationTypeOffset) = true ? 0 : 3; + static auto bShowHLODWhenDisabledOffset = BuildingFoundation->GetOffset("bShowHLODWhenDisabled", false); + + if (bShowHLODWhenDisabledOffset != 0) + { + static auto bShowHLODWhenDisabledFieldMask = GetFieldMask(BuildingFoundation->GetProperty("bShowHLODWhenDisabled")); + BuildingFoundation->SetBitfieldValue(bShowHLODWhenDisabledOffset, bShowHLODWhenDisabledFieldMask, true); + } + static auto OnRep_ServerStreamedInLevelFn = FindObject("/Script/FortniteGame.BuildingFoundation.OnRep_ServerStreamedInLevel"); BuildingFoundation->ProcessEvent(OnRep_ServerStreamedInLevelFn); @@ -54,7 +64,7 @@ void ShowFoundation(UObject* BuildingFoundation) if (DynamicFoundationRepDataOffset != 0) { - auto DynamicFoundationRepData = BuildingFoundation->GetPtr(DynamicFoundationRepDataOffset); + auto DynamicFoundationRepData = BuildingFoundation->GetPtr(DynamicFoundationRepDataOffset); static auto EnabledStateOffset = FindOffsetStruct("/Script/FortniteGame.DynamicBuildingFoundationRepData", "EnabledState"); @@ -178,6 +188,21 @@ bool AFortGameModeAthena::Athena_ReadyToStartMatchHook(AFortGameModeAthena* Game (*(int*)(__int64(CurrentPlaylistInfo) + PlaylistReplicationKeyOffset))++; CurrentPlaylistInfo->MarkArrayDirty(); + auto aeuh = *(UObject**)(__int64(CurrentPlaylistInfo) + BasePlaylistOffset); + + if (aeuh) + { + if (Fortnite_Version >= 13) + { + static auto LastSafeZoneIndexOffset = aeuh->GetOffset("LastSafeZoneIndex"); + + if (LastSafeZoneIndexOffset != -1) + { + *(int*)(__int64(aeuh) + LastSafeZoneIndexOffset) = 0; + } + } + } + GameState->OnRep_CurrentPlaylistInfo(); } else @@ -288,8 +313,15 @@ bool AFortGameModeAthena::Athena_ReadyToStartMatchHook(AFortGameModeAthena* Game auto TheBlock = FindObject("/Game/Athena/Maps/Athena_POI_Foundations.Athena_POI_Foundations.PersistentLevel.SLAB_2"); // SLAB_3 is blank ShowFoundation(TheBlock); } + + if (Fortnite_Version == 14.60 && Globals::bGoingToPlayEvent) + { + auto aircraftcarrier = FindObject("/Game/Athena/Apollo/Maps/Apollo_POI_Foundations.Apollo_POI_Foundations.PersistentLevel.Lobby_Foundation3"); + LOG_INFO(LogDev, "aircraftcarrier: {}", __int64(aircraftcarrier)); + ShowFoundation(aircraftcarrier); + } - if (Fortnite_Version == 17.50f) { + if (Fortnite_Version == 17.50) { auto FarmAfter = FindObject(("/Game/Athena/Apollo/Maps/Apollo_Mother.Apollo_Mother.PersistentLevel.farmbase_2")); ShowFoundation(FarmAfter); @@ -297,7 +329,7 @@ bool AFortGameModeAthena::Athena_ReadyToStartMatchHook(AFortGameModeAthena* Game ShowFoundation(FarmPhase); } - if (Fortnite_Version == 17.40f) { + if (Fortnite_Version == 17.40) { auto AbductedCoral = FindObject(("/Game/Athena/Apollo/Maps/Apollo_Mother.Apollo_Mother.PersistentLevel.CoralPhase_02")); // Coral Castle Phases (CoralPhase_01, CoralPhase_02 and CoralPhase_03) ShowFoundation(AbductedCoral); @@ -320,7 +352,7 @@ bool AFortGameModeAthena::Athena_ReadyToStartMatchHook(AFortGameModeAthena* Game ShowFoundation(CoralFoundation_17); } - if (Fortnite_Version == 17.30f) { + if (Fortnite_Version == 17.30) { auto AbductedSlurpy = FindObject(("LF_Athena_POI_50x50_C /Game/Athena/Apollo/Maps/Apollo_Mother.Apollo_Mother.PersistentLevel.Slurpy_Phase03")); // Slurpy Swamp Phases (Slurpy_Phase01, Slurpy_Phase02 and Slurpy_Phase03) ShowFoundation(AbductedSlurpy); } @@ -358,18 +390,22 @@ bool AFortGameModeAthena::Athena_ReadyToStartMatchHook(AFortGameModeAthena* Game if (PlaylistToUse) { - static auto AdditionalLevelsOffset = PlaylistToUse->GetOffset("AdditionalLevels"); - auto& AdditionalLevels = PlaylistToUse->Get>>(AdditionalLevelsOffset); + static auto AdditionalLevelsOffset = PlaylistToUse->GetOffset("AdditionalLevels", false); - LOG_INFO(LogPlaylist, "Loading {} playlist levels.", AdditionalLevels.Num()); - - for (int i = 0; i < AdditionalLevels.Num(); i++) + if (AdditionalLevelsOffset != 0) { - // auto World = Cast(Playlist->AdditionalLevels[i].Get()); - // StreamLevel(UKismetSystemLibrary::GetPathName(World->PersistentLevel).ToString()); - auto LevelName = AdditionalLevels.at(i).SoftObjectPtr.ObjectID.AssetPathName.ToString(); - LOG_INFO(LogPlaylist, "Loading level {}.", LevelName); - StreamLevel(LevelName); + auto& AdditionalLevels = PlaylistToUse->Get>>(AdditionalLevelsOffset); + + LOG_INFO(LogPlaylist, "Loading {} playlist levels.", AdditionalLevels.Num()); + + for (int i = 0; i < AdditionalLevels.Num(); i++) + { + // auto World = Cast(Playlist->AdditionalLevels[i].Get()); + // StreamLevel(UKismetSystemLibrary::GetPathName(World->PersistentLevel).ToString()); + auto LevelName = AdditionalLevels.at(i).SoftObjectPtr.ObjectID.AssetPathName.ToString(); + LOG_INFO(LogPlaylist, "Loading level {}.", LevelName); + StreamLevel(LevelName); + } } } } @@ -409,7 +445,6 @@ bool AFortGameModeAthena::Athena_ReadyToStartMatchHook(AFortGameModeAthena* Game } } - /* static auto FortPlayerStartWarmupClass = FindObject("/Script/FortniteGame.FortPlayerStartWarmup"); TArray Actors = UGameplayStatics::GetAllActorsOfClass(GetWorld(), FortPlayerStartWarmupClass); @@ -419,7 +454,6 @@ bool AFortGameModeAthena::Athena_ReadyToStartMatchHook(AFortGameModeAthena* Game if (ActorsNum == 0) return false; - */ static int LastNum9 = 1; @@ -431,11 +465,9 @@ bool AFortGameModeAthena::Athena_ReadyToStartMatchHook(AFortGameModeAthena* Game static auto MapInfoOffset = GameState->GetOffset("MapInfo"); auto MapInfo = GameState->Get(MapInfoOffset); - if (!MapInfo) + if (!MapInfo && Engine_Version >= 421) return false; - static auto FlightInfosOffset = MapInfo->GetOffset("FlightInfos"); - // if (GameState->GetPlayersLeft() < GameMode->Get("WarmupRequiredPlayerCount")) // if (!bFirstPlayerJoined) // return false; @@ -460,6 +492,7 @@ bool AFortGameModeAthena::Athena_ReadyToStartMatchHook(AFortGameModeAthena* Game GameState->Get("WarmupCountdownStartTime") = TimeSeconds; GameMode->Get("WarmupEarlyCountdownDuration") = EarlyDuration; + /* auto AllMegaStormManagers = UGameplayStatics::GetAllActorsOfClass(GetWorld(), GameMode->Get("MegaStormManagerClass")); LOG_INFO(LogDev, "AllMegaStormManagers.Num() {}", AllMegaStormManagers.Num()); @@ -475,10 +508,11 @@ bool AFortGameModeAthena::Athena_ReadyToStartMatchHook(AFortGameModeAthena* Game LOG_INFO(LogDev, "MegaStormManager->GetMegaStormCircles().Num() {}", MegaStormManager->GetMegaStormCircles().Num()); } } + */ // GameState->Get("bGameModeWillSkipAircraft") = Globals::bGoingToPlayEvent && Fortnite_Version == 17.30; - if (Engine_Version < 424) + // if (Engine_Version < 424) GameState->OnRep_CurrentPlaylistInfo(); // ? // SetupNavConfig(); @@ -490,16 +524,21 @@ bool AFortGameModeAthena::Athena_ReadyToStartMatchHook(AFortGameModeAthena* Game { if (GameState->GetPlayersLeft() >= GameMode->Get("WarmupRequiredPlayerCount")) { - if (MapInfo->Get>(FlightInfosOffset).ArrayNum <= 0) - return true; + if (MapInfo) + { + static auto FlightInfosOffset = MapInfo->GetOffset("FlightInfos"); + + if (MapInfo->Get>(FlightInfosOffset).ArrayNum <= 0) + return true; + } } } - /* static auto TeamsOffset = GameState->GetOffset("Teams"); + static auto TeamsOffset = GameState->GetOffset("Teams"); auto& Teams = GameState->Get>(TeamsOffset); if (Teams.Num() <= 0) - return false; */ + return false; static int LastNum3 = 1; @@ -521,8 +560,9 @@ bool AFortGameModeAthena::Athena_ReadyToStartMatchHook(AFortGameModeAthena* Game int AFortGameModeAthena::Athena_PickTeamHook(AFortGameModeAthena* GameMode, uint8 preferredTeam, AActor* Controller) { + LOG_INFO(LogTeam, "PickTeam called!"); static auto NextTeamIndex = 3; - return ++NextTeamIndex; + return NextTeamIndex; } void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena* GameMode, AActor* NewPlayerActor) @@ -544,8 +584,12 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena GameState->OnRep_GamePhase(); } - if (false) + static bool bSpawnedFloorLoot = false; + + if (!bSpawnedFloorLoot) { + bSpawnedFloorLoot = true; + auto SpawnIsland_FloorLoot = FindObject("/Game/Athena/Environments/Blueprints/Tiered_Athena_FloorLoot_Warmup.Tiered_Athena_FloorLoot_Warmup_C"); auto BRIsland_FloorLoot = FindObject("/Game/Athena/Environments/Blueprints/Tiered_Athena_FloorLoot_01.Tiered_Athena_FloorLoot_01_C"); @@ -621,8 +665,9 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena if (Globals::bNoMCP) { static auto CharacterPartsOffset = PlayerStateAthena->GetOffset("CharacterParts", false); + static auto CustomCharacterPartsStruct = FindObject("/Script/FortniteGame.CustomCharacterParts"); - if (CharacterPartsOffset != 0) + if (CharacterPartsOffset != 0) // && CustomCharacterPartsStruct) { auto CharacterParts = PlayerStateAthena->GetPtr<__int64>("CharacterParts"); @@ -700,11 +745,11 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena }; FUniqueNetIdReplExperimental bugha{}; - auto& PlayerStateUniqueId = bugha; // PlayerStateAthena->Get("UniqueId"); + auto& PlayerStateUniqueId = PlayerStateAthena->Get("UniqueId"); // if (false) // if (GameMemberInfoArrayOffset != 0) - if (Engine_Version >= 423 && false) + if (Engine_Version >= 423) { struct FGameMemberInfo : public FFastArraySerializerItem { @@ -818,7 +863,7 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena } } - static auto SpawnActorDataListOffset = GameMode->GetOffset("SpawnActorDataList"); + static auto SpawnActorDataListOffset = GameMode->GetOffset("SpawnActorDataList", false); if (SpawnActorDataListOffset != 0) { diff --git a/Project Reboot 3.0/FortInventory.cpp b/Project Reboot 3.0/FortInventory.cpp index dce9dec..36ac3eb 100644 --- a/Project Reboot 3.0/FortInventory.cpp +++ b/Project Reboot 3.0/FortInventory.cpp @@ -25,6 +25,9 @@ std::pair, std::vector> AFortInventory::AddI if (NewItemInstance) { + if (LoadedAmmo != -1) + NewItemInstance->GetItemEntry()->GetLoadedAmmo() = LoadedAmmo; + NewItemInstances.push_back(NewItemInstance); // NewItemInstance->GetItemEntry()->GetItemDefinition() = ItemDefinition; @@ -74,8 +77,8 @@ bool AFortInventory::RemoveItem(const FGuid& ItemGuid, bool* bShouldUpdate, int return true; } - static auto FortItemEntryStruct = FindObject(L"/Script/FortniteGame.FortItemEntry"); - static auto FortItemEntrySize = *(int*)(__int64(FortItemEntryStruct) + Offsets::PropertiesSize); + static auto FortItemEntryStruct = FindObject(L"/Script/FortniteGame.FortItemEntry"); + static auto FortItemEntrySize = FortItemEntryStruct->GetPropertiesSize(); auto& ItemInstances = GetItemList().GetItemInstances(); auto& ReplicatedEntries = GetItemList().GetReplicatedEntries(); @@ -91,7 +94,7 @@ bool AFortInventory::RemoveItem(const FGuid& ItemGuid, bool* bShouldUpdate, int for (int i = 0; i < ReplicatedEntries.Num(); i++) { - if (ReplicatedEntries.at(i).GetItemGuid() == ItemGuid) + if (ReplicatedEntries.at(i, FortItemEntrySize).GetItemGuid() == ItemGuid) { ReplicatedEntries.Remove(i, FortItemEntrySize); break; @@ -134,6 +137,21 @@ void AFortInventory::ModifyCount(UFortItem* ItemInstance, int New, bool bRemove, } } +UFortItem* AFortInventory::FindItemInstance(UFortItemDefinition* ItemDefinition) +{ + auto& ItemInstances = GetItemList().GetItemInstances(); + + for (int i = 0; i < ItemInstances.Num(); i++) + { + auto ItemInstance = ItemInstances.At(i); + + if (ItemInstance->GetItemEntry()->GetItemDefinition() == ItemDefinition) + return ItemInstance; + } + + return nullptr; +} + UFortItem* AFortInventory::FindItemInstance(const FGuid& Guid) { auto& ItemInstances = GetItemList().GetItemInstances(); @@ -151,11 +169,14 @@ UFortItem* AFortInventory::FindItemInstance(const FGuid& Guid) FFortItemEntry* AFortInventory::FindReplicatedEntry(const FGuid& Guid) { + static auto FortItemEntryStruct = FindObject(L"/Script/FortniteGame.FortItemEntry"); + static auto FortItemEntrySize = FortItemEntryStruct->GetPropertiesSize(); + auto& ReplicatedEntries = GetItemList().GetReplicatedEntries(); for (int i = 0; i < ReplicatedEntries.Num(); i++) { - auto& ReplicatedEntry = ReplicatedEntries.At(i); + auto& ReplicatedEntry = ReplicatedEntries.At(i, FortItemEntrySize); if (ReplicatedEntry.GetItemGuid() == Guid) return &ReplicatedEntry; diff --git a/Project Reboot 3.0/FortInventory.h b/Project Reboot 3.0/FortInventory.h index ffdd2e0..6252a55 100644 --- a/Project Reboot 3.0/FortInventory.h +++ b/Project Reboot 3.0/FortInventory.h @@ -95,6 +95,8 @@ public: bool RemoveItem(const FGuid& ItemGuid, bool* bShouldUpdate, int Count); void ModifyCount(UFortItem* ItemInstance, int New, bool bRemove = false, std::pair* outEntries = nullptr, bool bUpdate = true); + UFortItem* FindItemInstance(UFortItemDefinition* ItemDefinition); + UFortItem* FindItemInstance(const FGuid& Guid); FFortItemEntry* FindReplicatedEntry(const FGuid& Guid); }; \ No newline at end of file diff --git a/Project Reboot 3.0/FortKismetLibrary.cpp b/Project Reboot 3.0/FortKismetLibrary.cpp index e50da21..8d93d1c 100644 --- a/Project Reboot 3.0/FortKismetLibrary.cpp +++ b/Project Reboot 3.0/FortKismetLibrary.cpp @@ -1,4 +1,5 @@ #include "FortKismetLibrary.h" +#include "ScriptInterface.h" UFortResourceItemDefinition* UFortKismetLibrary::K2_GetResourceItemDefinition(EFortResourceType ResourceType) { @@ -40,16 +41,21 @@ void UFortKismetLibrary::ApplyCharacterCosmetics(UObject* WorldContextObject, co { auto CharacterPartsPS = PlayerState->GetPtr<__int64>("CharacterParts"); - static auto PartsOffset = FindOffsetStruct("/Script/FortniteGame.CustomCharacterParts", "Parts"); - auto Parts = (UObject**)(__int64(CharacterPartsPS) + PartsOffset); // UCustomCharacterPart* Parts[0x6] + static auto CustomCharacterPartsStruct = FindObject("/Script/FortniteGame.CustomCharacterParts"); - for (int i = 0; i < CharacterParts.Num(); i++) + // if (CustomCharacterPartsStruct) { - Parts[i] = CharacterParts.at(i); - } + static auto PartsOffset = FindOffsetStruct("/Script/FortniteGame.CustomCharacterParts", "Parts"); + auto Parts = (UObject**)(__int64(CharacterPartsPS) + PartsOffset); // UCustomCharacterPart* Parts[0x6] - static auto OnRep_CharacterPartsFn = FindObject("/Script/FortniteGame.FortPlayerState.OnRep_CharacterParts"); - PlayerState->ProcessEvent(OnRep_CharacterPartsFn); + for (int i = 0; i < CharacterParts.Num(); i++) + { + Parts[i] = CharacterParts.at(i); + } + + static auto OnRep_CharacterPartsFn = FindObject("/Script/FortniteGame.FortPlayerState.OnRep_CharacterParts"); + PlayerState->ProcessEvent(OnRep_CharacterPartsFn); + } } else { @@ -57,6 +63,107 @@ void UFortKismetLibrary::ApplyCharacterCosmetics(UObject* WorldContextObject, co } } +void UFortKismetLibrary::GiveItemToInventoryOwnerHook(UObject* Context, FFrame& Stack, void* Ret) +{ + auto Params = /*(UFortKismetLibrary_GiveItemToInventoryOwner_Params*)*/Stack.Locals; + + static auto InventoryOwnerOffset = FindOffsetStruct("/Script/FortniteGame.FortKismetLibrary.GiveItemToInventoryOwner", "InventoryOwner"); + static auto ItemDefinitionOffset = FindOffsetStruct("/Script/FortniteGame.FortKismetLibrary.GiveItemToInventoryOwner", "ItemDefinition"); + static auto NumberToGiveOffset = FindOffsetStruct("/Script/FortniteGame.FortKismetLibrary.GiveItemToInventoryOwner", "NumberToGive"); + static auto bNotifyPlayerOffset = FindOffsetStruct("/Script/FortniteGame.FortKismetLibrary.GiveItemToInventoryOwner", "bNotifyPlayer"); + static auto ItemLevelOffset = FindOffsetStruct("/Script/FortniteGame.FortKismetLibrary.GiveItemToInventoryOwner", "ItemLevel"); + static auto PickupInstigatorHandleOffset = FindOffsetStruct("/Script/FortniteGame.FortKismetLibrary.GiveItemToInventoryOwner", "PickupInstigatorHandle"); + + auto InventoryOwner = *(TScriptInterface*)(__int64(Params) + InventoryOwnerOffset); + auto ItemDefinition = *(UFortWorldItemDefinition**)(__int64(Params) + ItemDefinitionOffset); + auto NumberToGive = *(int*)(__int64(Params) + NumberToGiveOffset); + auto bNotifyPlayer = *(bool*)(__int64(Params) + bNotifyPlayerOffset); + auto ItemLevel = *(int*)(__int64(Params) + ItemLevelOffset); + auto PickupInstigatorHandle = *(int*)(__int64(Params) + PickupInstigatorHandleOffset); + + auto InterfacePointer = InventoryOwner.InterfacePointer; + + LOG_INFO(LogDev, "InterfacePointer: {}", __int64(InterfacePointer)); + + if (!InterfacePointer) + return; + + auto ObjectPointer = InventoryOwner.ObjectPointer; + + if (!ObjectPointer) + return; + + // LOG_INFO(LogDev, "ObjectPointer Name: {}", ObjectPointer->GetFullName()); + + return GiveItemToInventoryOwnerOriginal(Context, Stack, Ret); +} + +void UFortKismetLibrary::K2_RemoveItemFromPlayerHook(UObject* Context, FFrame& Stack, void* Ret) +{ + struct UFortKismetLibrary_K2_RemoveItemFromPlayer_Params + { + AFortPlayerController* PlayerController; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) + UFortWorldItemDefinition* ItemDefinition; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) + int AmountToRemove; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) + bool bForceRemoval; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) + int ReturnValue; // (Parm, OutParm, ZeroConstructor, ReturnParm, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) + }; + + auto Params = /*(UFortKismetLibrary_K2_RemoveItemFromPlayer_Params*)*/Stack.Locals; + + static auto PlayerControllerOffset = FindOffsetStruct("/Script/FortniteGame.FortKismetLibrary.K2_RemoveItemFromPlayer", "PlayerController"); + static auto ItemDefinitionOffset = FindOffsetStruct("/Script/FortniteGame.FortKismetLibrary.K2_RemoveItemFromPlayer", "ItemDefinition"); + static auto AmountToRemoveOffset = FindOffsetStruct("/Script/FortniteGame.FortKismetLibrary.K2_RemoveItemFromPlayer", "AmountToRemove"); + + auto PlayerController = *(AFortPlayerController**)(__int64(Params) + PlayerControllerOffset); + auto ItemDefinition = *(UFortWorldItemDefinition**)(__int64(Params) + ItemDefinitionOffset); + auto AmountToRemove = *(int*)(__int64(Params) + AmountToRemoveOffset); + + auto WorldInventory = PlayerController->GetWorldInventory(); + + if (!WorldInventory) + return; + + auto ItemInstance = WorldInventory->FindItemInstance(ItemDefinition); + + if (!ItemInstance) + return; + + bool bShouldUpdate = false; + WorldInventory->RemoveItem(ItemInstance->GetItemEntry()->GetItemGuid(), &bShouldUpdate, AmountToRemove); + + if (bShouldUpdate) + WorldInventory->Update(); + + return K2_RemoveItemFromPlayerOriginal(Context, Stack, Ret); +} + +void UFortKismetLibrary::K2_GiveItemToPlayerHook(UObject* Context, FFrame& Stack, void* Ret) +{ + struct UFortKismetLibrary_K2_GiveItemToPlayer_Params + { + AFortPlayerController* PlayerController; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) + UFortWorldItemDefinition* ItemDefinition; // (ConstParm, Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) + int NumberToGive; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) + bool bNotifyPlayer; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) + }; + + auto Params = (UFortKismetLibrary_K2_GiveItemToPlayer_Params*)Stack.Locals; + + auto PlayerController = Params->PlayerController; + auto ItemDefinition = Params->ItemDefinition; + auto NumberToGive = Params->NumberToGive; + auto bNotifyPlayer = Params->bNotifyPlayer; + + bool bShouldUpdate = false; + PlayerController->GetWorldInventory()->AddItem(ItemDefinition, &bShouldUpdate, NumberToGive, -1, bNotifyPlayer); + + if (bShouldUpdate) + PlayerController->GetWorldInventory()->Update(); + + return K2_GiveItemToPlayerOriginal(Context, Stack, Ret); +} + UClass* UFortKismetLibrary::StaticClass() { static auto ptr = FindObject(L"/Script/FortniteGame.FortKismetLibrary"); diff --git a/Project Reboot 3.0/FortKismetLibrary.h b/Project Reboot 3.0/FortKismetLibrary.h index 3729127..9d16468 100644 --- a/Project Reboot 3.0/FortKismetLibrary.h +++ b/Project Reboot 3.0/FortKismetLibrary.h @@ -3,13 +3,24 @@ #include "Object.h" #include "FortResourceItemDefinition.h" +#include "FortPlayerController.h" #include "BuildingSMActor.h" class UFortKismetLibrary : public UObject { public: + using UFortInventoryOwnerInterface = UObject; + + static inline void (*K2_GiveItemToPlayerOriginal)(UObject* Context, FFrame& Stack, void* Ret); + static inline void (*K2_RemoveItemFromPlayerOriginal)(UObject* Context, FFrame& Stack, void* Ret); + static inline void (*GiveItemToInventoryOwnerOriginal)(UObject* Context, FFrame& Stack, void* Ret); + static UFortResourceItemDefinition* K2_GetResourceItemDefinition(EFortResourceType ResourceType); static void ApplyCharacterCosmetics(UObject* WorldContextObject, const TArray& CharacterParts, UObject* PlayerState, bool* bSuccess); + static void GiveItemToInventoryOwnerHook(UObject* Context, FFrame& Stack, void* Ret); + static void K2_RemoveItemFromPlayerHook(UObject* Context, FFrame& Stack, void* Ret); + static void K2_GiveItemToPlayerHook(UObject* Context, FFrame& Stack, void* Ret); + static UClass* StaticClass(); }; \ No newline at end of file diff --git a/Project Reboot 3.0/FortLootPackage.cpp b/Project Reboot 3.0/FortLootPackage.cpp index 392fad0..eaa23bd 100644 --- a/Project Reboot 3.0/FortLootPackage.cpp +++ b/Project Reboot 3.0/FortLootPackage.cpp @@ -86,8 +86,8 @@ std::vector> PickLootDrops(FName TierGroupN { bHasFoundTables = true; - LTDTables.push_back(FindObject(L"/Game/Items/Datatables/AthenaLootTierData_Client.AthenaLootTierData_Client")); - LPTables.push_back(FindObject(L"/Game/Items/Datatables/AthenaLootPackages_Client.AthenaLootPackages_Client")); + LTDTables.push_back(LoadObject(L"/Game/Items/Datatables/AthenaLootTierData_Client.AthenaLootTierData_Client")); + LPTables.push_back(LoadObject(L"/Game/Items/Datatables/AthenaLootPackages_Client.AthenaLootPackages_Client")); } std::vector TierGroupLTDs; @@ -104,11 +104,16 @@ std::vector> PickLootDrops(FName TierGroupN // auto TierGroupNameStr = TierGroupName.ToString(); + // LOG_INFO(LogLoot, "LTDRowMapNum: {}", LTDRowMapNum); + for (int i = 0; i < LTDRowMapNum; i++) { auto& CurrentLTD = LTDRowMap.Pairs.Elements[i].ElementData.Value; auto TierData = (FFortLootTierData*)CurrentLTD.Value(); + if (IsBadReadPtr(TierData, 8)) + continue; + // auto TierDataGroupStr = TierData->TierGroup.ToString(); // std::cout << "TierData->TierGroup.ToString(): " << TierDataGroupStr << '\n'; @@ -148,7 +153,10 @@ std::vector> PickLootDrops(FName TierGroupN return PickLootDrops(TierGroupName, bPrint, ++recursive); // hm int MinimumLootDrops = 0; - float NumLootPackageDrops = std::floor(ChosenRowLootTierData->GetNumLootPackageDrops()); + + static int AmountToAdd = Engine_Version >= 424 ? 1 : 0; // fr + + float NumLootPackageDrops = std::floor(ChosenRowLootTierData->GetNumLootPackageDrops() + AmountToAdd); if (LootPackageCategoryMinArray.ArrayNum) { @@ -252,9 +260,7 @@ std::vector> PickLootDrops(FName TierGroupN std::cout << "b: " << b << '\n'; */ } - static int AmountToAdd = Engine_Version >= 424 ? 1 : 0; // fr - - LootDrops.reserve(NumLootPackageDrops + AmountToAdd); + LootDrops.reserve(NumLootPackageDrops); for (float i = 0; i < NumLootPackageDrops; i++) { diff --git a/Project Reboot 3.0/FortPickup.cpp b/Project Reboot 3.0/FortPickup.cpp index 0918d11..f1d0d3c 100644 --- a/Project Reboot 3.0/FortPickup.cpp +++ b/Project Reboot 3.0/FortPickup.cpp @@ -87,6 +87,10 @@ char AFortPickup::CompletePickupAnimationHook(AFortPickup* Pickup) auto& CurrentItemGuid = Pickup->GetPickupLocationData()->GetPickupGuid(); // Pawn->CurrentWeapon->ItemEntryGuid; auto ItemInstanceToSwap = WorldInventory->FindItemInstance(CurrentItemGuid); + + if (!ItemInstanceToSwap) + return CompletePickupAnimationOriginal(Pickup); + auto ItemEntryToSwap = ItemInstanceToSwap->GetItemEntry(); auto ItemDefinitionToSwap = ItemEntryToSwap ? Cast(ItemEntryToSwap->GetItemDefinition()) : nullptr; bool bHasSwapped = false; @@ -137,7 +141,6 @@ char AFortPickup::CompletePickupAnimationHook(AFortPickup* Pickup) if (CurrentItemEntry->GetItemDefinition() == PickupItemDefinition) { - if (CurrentItemEntry->GetCount() < PickupItemDefinition->GetMaxStackSize()) { int OverStack = CurrentItemEntry->GetCount() + cpyCount - PickupItemDefinition->GetMaxStackSize(); diff --git a/Project Reboot 3.0/FortPlayerController.cpp b/Project Reboot 3.0/FortPlayerController.cpp index 5a7bf05..1132b0a 100644 --- a/Project Reboot 3.0/FortPlayerController.cpp +++ b/Project Reboot 3.0/FortPlayerController.cpp @@ -15,6 +15,7 @@ #include "FortLootPackage.h" #include "FortPickup.h" #include "FortPlayerPawn.h" +#include void AFortPlayerController::ClientReportDamagedResourceBuilding(ABuildingSMActor* BuildingSMActor, EFortResourceType PotentialResourceType, int PotentialResourceCount, bool bDestroyed, bool bJustHitWeakspot) { @@ -160,12 +161,17 @@ void AFortPlayerController::ServerAttemptAircraftJumpHook(AFortPlayerController* // PC->ServerRestartPlayer(); } -void AFortPlayerController::ServerCreateBuildingActorHook(AFortPlayerController* PlayerController, FCreateBuildingActorData CreateBuildingData) +void AFortPlayerController::ServerCreateBuildingActorHook(UObject* Context, FFrame* Stack, void* Ret) { + auto PlayerController = Cast(Context); + + if (!PlayerController) // ?? + return ServerCreateBuildingActorOriginal(Context, Stack, Ret); + auto PlayerStateAthena = Cast(PlayerController->GetPlayerState()); if (!PlayerStateAthena) - return; + return ServerCreateBuildingActorOriginal(Context, Stack, Ret); UClass* BuildingClass = nullptr; FVector BuildLocation; @@ -174,9 +180,11 @@ void AFortPlayerController::ServerCreateBuildingActorHook(AFortPlayerController* if (Fortnite_Version >= 8.30) { - BuildLocation = CreateBuildingData.BuildLoc; - BuildRotator = CreateBuildingData.BuildRot; - bMirrored = CreateBuildingData.bMirrored; + auto CreateBuildingData = (FCreateBuildingActorData*)Stack->Locals; + + BuildLocation = CreateBuildingData->BuildLoc; + BuildRotator = CreateBuildingData->BuildRot; + bMirrored = CreateBuildingData->bMirrored; static auto BroadcastRemoteClientInfoOffset = PlayerController->GetOffset("BroadcastRemoteClientInfo"); auto BroadcastRemoteClientInfo = PlayerController->Get(BroadcastRemoteClientInfoOffset); @@ -186,13 +194,21 @@ void AFortPlayerController::ServerCreateBuildingActorHook(AFortPlayerController* } else { + struct FBuildingClassData { UClass* BuildingClass; int PreviousBuildingLevel; int UpgradeLevel; }; + struct SCBAParams { FBuildingClassData BuildingClassData; FVector BuildLoc; FRotator BuildRot; bool bMirrored; }; + auto Params = (SCBAParams*)Stack->Locals; + + BuildingClass = Params->BuildingClassData.BuildingClass; + BuildLocation = Params->BuildLoc; + BuildRotator = Params->BuildRot; + bMirrored = Params->bMirrored; } // LOG_INFO(LogDev, "BuildingClass {}", __int64(BuildingClass)); if (!BuildingClass) - return; + return ServerCreateBuildingActorOriginal(Context, Stack, Ret); TArray ExistingBuildings; char idk; @@ -202,9 +218,9 @@ void AFortPlayerController::ServerCreateBuildingActorHook(AFortPlayerController* if (!bCanBuild) { // LOG_INFO(LogDev, "cant build"); - return; + return ServerCreateBuildingActorOriginal(Context, Stack, Ret); } - + for (int i = 0; i < ExistingBuildings.Num(); i++) { auto ExistingBuilding = ExistingBuildings.At(i); @@ -222,11 +238,13 @@ void AFortPlayerController::ServerCreateBuildingActorHook(AFortPlayerController* auto BuildingActor = GetWorld()->SpawnActor(BuildingClass, Transform); if (!BuildingActor) - return; + return ServerCreateBuildingActorOriginal(Context, Stack, Ret); BuildingActor->SetPlayerPlaced(true); BuildingActor->SetTeam(PlayerStateAthena->GetTeamIndex()); BuildingActor->InitializeBuildingActor(PlayerController, BuildingActor, true); + + return ServerCreateBuildingActorOriginal(Context, Stack, Ret); } void AFortPlayerController::ServerAttemptInventoryDropHook(AFortPlayerController* PlayerController, FGuid ItemGuid, int Count) @@ -246,7 +264,7 @@ void AFortPlayerController::ServerAttemptInventoryDropHook(AFortPlayerController auto ItemDefinition = Cast(ReplicatedEntry->GetItemDefinition()); - if (!ItemDefinition) + if (!ItemDefinition || !ItemDefinition->CanBeDropped()) return; auto Pickup = AFortPickup::SpawnPickup(ItemDefinition, Pawn->GetActorLocation(), Count, @@ -274,6 +292,14 @@ void AFortPlayerController::ServerPlayEmoteItemHook(AFortPlayerController* Playe UObject* AbilityToUse = nullptr; + static auto AthenaSprayItemDefinitionClass = FindObject("/Script/FortniteGame.AthenaSprayItemDefinition"); + + if (EmoteAsset->IsA(AthenaSprayItemDefinitionClass)) + { + static auto SprayGameplayAbilityDefault = FindObject("/Game/Abilities/Sprays/GAB_Spray_Generic.Default__GAB_Spray_Generic_C"); + AbilityToUse = SprayGameplayAbilityDefault; + } + if (!AbilityToUse) { static auto EmoteGameplayAbilityDefault = FindObject("/Game/Abilities/Emotes/GAB_Emote_Generic.Default__GAB_Emote_Generic_C"); @@ -296,23 +322,109 @@ void AFortPlayerController::ServerPlayEmoteItemHook(AFortPlayerController* Playe GiveAbilityAndActivateOnce(PlayerState->GetAbilitySystemComponent(), &outHandle, __int64(Spec)); } -void AFortPlayerController::ClientOnPawnDiedHook(AFortPlayerController* PlayerController, __int64 DeathReport) +uint8 ToDeathCause(const FGameplayTagContainer& TagContainer, bool bWasDBNO = false) +{ + static auto ToDeathCauseFn = FindObject("/Script/FortniteGame.FortPlayerStateAthena.ToDeathCause"); + + if (ToDeathCauseFn) + { + struct + { + FGameplayTagContainer InTags; // (ConstParm, Parm, OutParm, ReferenceParm, NativeAccessSpecifierPublic) + bool bWasDBNO; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) + uint8_t ReturnValue; // (Parm, OutParm, ZeroConstructor, ReturnParm, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) + } AFortPlayerStateAthena_ToDeathCause_Params{ TagContainer, bWasDBNO }; + + AFortPlayerStateAthena::StaticClass()->ProcessEvent(ToDeathCauseFn, &AFortPlayerStateAthena_ToDeathCause_Params); + + return AFortPlayerStateAthena_ToDeathCause_Params.ReturnValue; + } + + static bool bHaveFoundAddress = false; + + static uint64 Addr = 0; + + if (!bHaveFoundAddress) + { + bHaveFoundAddress = true; + + if (Engine_Version == 420) + Addr = Memcury::Scanner::FindPattern("48 89 5C 24 ? 48 89 74 24 ? 57 48 83 EC 20 0F B6 FA 48 8B D9 E8 ? ? ? ? 33 F6 48 89 74 24").Get(); + + if (!Addr) + { + LOG_WARN(LogPlayer, "Failed to find ToDeathCause address!"); + return 0; + } + } + + if (!Addr) + { + return 0; + } + + static uint8 (*sub_7FF7AB499410)(FGameplayTagContainer TagContainer, char bWasDBNOIg) = decltype(sub_7FF7AB499410)(Addr); + return sub_7FF7AB499410(TagContainer, bWasDBNO); +} + +void AFortPlayerController::ClientOnPawnDiedHook(AFortPlayerController* PlayerController, void* DeathReport) { auto DeadPawn = Cast(PlayerController->GetPawn()); + auto DeadPlayerState = Cast(PlayerController->GetPlayerState()); + auto KillerPawn = Cast(*(AFortPawn**)(__int64(DeathReport) + MemberOffsets::DeathReport::KillerPawn)); if (!DeadPawn) - return; + return ClientOnPawnDiedOriginal(PlayerController, DeathReport); static auto DeathInfoStruct = FindObject("/Script/FortniteGame.DeathInfo"); static auto DeathInfoStructSize = DeathInfoStruct->GetPropertiesSize(); - auto DeathInfo = Alloc(DeathInfoStructSize); + auto DeathLocation = DeadPawn->GetActorLocation(); + + static auto FallDamageEnumValue = 1; + + auto DeathInfo = (void*)(__int64(DeadPlayerState) + MemberOffsets::FortPlayerStateAthena::DeathInfo); // Alloc(DeathInfoStructSize); + RtlSecureZeroMemory(DeathInfo, DeathInfoStructSize); + + auto Tags = *(FGameplayTagContainer*)(__int64(DeathReport) + MemberOffsets::DeathReport::Tags); + + // LOG_INFO(LogDev, "Tags: {}", Tags.ToStringSimple(true)); + + auto DeathCause = ToDeathCause(Tags, false); + + LOG_INFO(LogDev, "DeathCause: {}", (int)DeathCause); *(bool*)(__int64(DeathInfo) + MemberOffsets::DeathInfo::bDBNO) = DeadPawn->IsDBNO(); + *(uint8*)(__int64(DeathInfo) + MemberOffsets::DeathInfo::DeathCause) = DeathCause; + *(FVector*)(__int64(DeathInfo) + MemberOffsets::DeathInfo::DeathLocation) = DeathLocation; + + if (MemberOffsets::DeathInfo::DeathTags != 0) + *(FGameplayTagContainer*)(__int64(DeathInfo) + MemberOffsets::DeathInfo::DeathTags) = Tags; + + if (MemberOffsets::DeathInfo::bInitialized != 0) + *(bool*)(__int64(DeathInfo) + MemberOffsets::DeathInfo::bInitialized) = true; + + if (DeathCause == FallDamageEnumValue) + { + static auto LastFallDistanceOffset = DeadPawn->GetOffset("LastFallDistance"); + *(float*)(__int64(DeathInfo) + MemberOffsets::DeathInfo::Distance) = DeadPawn->Get(LastFallDistanceOffset); + } + else + { + *(float*)(__int64(DeathInfo) + MemberOffsets::DeathInfo::Distance) = KillerPawn ? KillerPawn->GetDistanceTo(DeadPawn) : 0; + } + + static auto PawnDeathLocationOffset = DeadPlayerState->GetOffset("PawnDeathLocation"); + DeadPlayerState->Get(PawnDeathLocationOffset) = DeathLocation; + + static auto OnRep_DeathInfoFn = FindObject("/Script/FortniteGame.FortPlayerStateAthena.OnRep_DeathInfo"); + DeadPlayerState->ProcessEvent(OnRep_DeathInfoFn); - auto DeathLocation = DeadPawn->GetActorLocation(); auto WorldInventory = PlayerController->GetWorldInventory(); + if (!WorldInventory) + return ClientOnPawnDiedOriginal(PlayerController, DeathReport); + auto& ItemInstances = WorldInventory->GetItemList().GetItemInstances(); for (int i = 0; i < ItemInstances.Num(); i++) @@ -334,6 +446,8 @@ void AFortPlayerController::ClientOnPawnDiedHook(AFortPlayerController* PlayerCo AFortPickup::SpawnPickup(WorldItemDefinition, DeathLocation, ItemEntry->GetCount(), EFortPickupSourceTypeFlag::Player, EFortPickupSpawnSource::PlayerElimination, ItemEntry->GetLoadedAmmo()); } + + return ClientOnPawnDiedOriginal(PlayerController, DeathReport); } void AFortPlayerController::ServerBeginEditingBuildingActorHook(AFortPlayerController* PlayerController, ABuildingSMActor* BuildingActorToEdit) diff --git a/Project Reboot 3.0/FortPlayerController.h b/Project Reboot 3.0/FortPlayerController.h index 34762b1..355b33c 100644 --- a/Project Reboot 3.0/FortPlayerController.h +++ b/Project Reboot 3.0/FortPlayerController.h @@ -28,6 +28,8 @@ struct FFortAthenaLoadout class AFortPlayerController : public APlayerController { public: + static inline void (*ClientOnPawnDiedOriginal)(AFortPlayerController* PlayerController, void* DeathReport); + static inline void (*ServerCreateBuildingActorOriginal)(UObject* Context, FFrame* Stack, void* Ret); static inline void (*ServerAttemptInteractOriginal)(UObject* Context, FFrame* Stack, void* Ret); void ClientReportDamagedResourceBuilding(ABuildingSMActor* BuildingSMActor, EFortResourceType PotentialResourceType, int PotentialResourceCount, bool bDestroyed, bool bJustHitWeakspot); @@ -60,11 +62,12 @@ public: static void ServerAttemptInteractHook(UObject* Context, FFrame* Stack, void* Ret); static void ServerAttemptAircraftJumpHook(AFortPlayerController* PC, FRotator ClientRotation); - static void ServerCreateBuildingActorHook(AFortPlayerController* PlayerController, FCreateBuildingActorData CreateBuildingData); - + // static void ServerCreateBuildingActorHook(AFortPlayerController* PlayerController, FCreateBuildingActorData CreateBuildingData); + static void ServerCreateBuildingActorHook(UObject* Context, FFrame* Stack, void* Ret); + static void ServerAttemptInventoryDropHook(AFortPlayerController* PlayerController, FGuid ItemGuid, int Count); static void ServerPlayEmoteItemHook(AFortPlayerController* PlayerController, UObject* EmoteAsset); - static void ClientOnPawnDiedHook(AFortPlayerController* PlayerController, __int64 DeathReport); + static void ClientOnPawnDiedHook(AFortPlayerController* PlayerController, void* DeathReport); static void ServerBeginEditingBuildingActorHook(AFortPlayerController* PlayerController, ABuildingSMActor* BuildingActorToEdit); static void ServerEditBuildingActorHook(AFortPlayerController* PlayerController, ABuildingSMActor* BuildingActorToEdit, UClass* NewBuildingClass, int RotationIterations, char bMirrored); diff --git a/Project Reboot 3.0/FortPlayerPawn.cpp b/Project Reboot 3.0/FortPlayerPawn.cpp index 6ce13e4..433667d 100644 --- a/Project Reboot 3.0/FortPlayerPawn.cpp +++ b/Project Reboot 3.0/FortPlayerPawn.cpp @@ -38,9 +38,12 @@ void AFortPlayerPawn::ServerSendZiplineStateHook(AFortPlayerPawn* Pawn, FZipline { bFoundFunc = true; - static auto Addrr = Memcury::Scanner::FindStringRef(L"ZIPLINES!! Role(%s) AFortPlayerPawn::OnRep_ZiplineState ZiplineState.bIsZiplining=%d").Get(); + static auto Addrr = Memcury::Scanner::FindStringRef(L"ZIPLINES!! Role(%s) AFortPlayerPawn::OnRep_ZiplineState ZiplineState.bIsZiplining=%d", false).Get(); - std::cout << "Addrr: " << Addrr << '\n'; + if (!Addrr) + Addrr = Memcury::Scanner::FindStringRef(L"ZIPLINES!! GetLocalRole()(%s) AFortPlayerPawn::OnRep_ZiplineState ZiplineState.bIsZiplining=%d").Get(); + + // std::cout << "Addrr: " << Addrr << '\n'; if (Addrr) { @@ -51,11 +54,18 @@ void AFortPlayerPawn::ServerSendZiplineStateHook(AFortPlayerPawn* Pawn, FZipline if (*(uint8_t*)(uint8_t*)(Addrr - i) == 0x40 && *(uint8_t*)(uint8_t*)(Addrr - i + 1) == 0x53) { OnRep_ZiplineState = decltype(OnRep_ZiplineState)(Addrr - i); + break; + } + + if (*(uint8_t*)(uint8_t*)(Addrr - i) == 0x48 && *(uint8_t*)(uint8_t*)(Addrr - i + 1) == 0x89 && *(uint8_t*)(uint8_t*)(Addrr - i + 2) == 0x5C) + { + OnRep_ZiplineState = decltype(OnRep_ZiplineState)(Addrr - i); + break; } } } - // LOG_INFO(LogDev, "OnRep_ZiplineState: 0x{:x}\n", (uintptr_t)OnRep_ZiplineState - __int64(GetModuleHandleW(0))); + LOG_INFO(LogDev, "OnRep_ZiplineState: 0x{:x}\n", (uintptr_t)OnRep_ZiplineState - __int64(GetModuleHandleW(0))); } if (OnRep_ZiplineState) diff --git a/Project Reboot 3.0/GameModeBase.cpp b/Project Reboot 3.0/GameModeBase.cpp index 477882b..f23f300 100644 --- a/Project Reboot 3.0/GameModeBase.cpp +++ b/Project Reboot 3.0/GameModeBase.cpp @@ -48,6 +48,7 @@ APawn* AGameModeBase::SpawnDefaultPawnForHook(AGameModeBase* GameMode, AControll WorldInventory->AddItem(BuildingItemData_RoofS, nullptr); WorldInventory->AddItem(PickaxeDefinition, nullptr); WorldInventory->AddItem(WoodItemData, nullptr, 100); + // WorldInventory->AddItem(FindObject(L"/ParallelGameplay/Items/WestSausage/WID_WestSausage_Parallel.WID_WestSausage_Parallel"), nullptr, 1, 1000); WorldInventory->Update(true); } diff --git a/Project Reboot 3.0/ScriptInterface.h b/Project Reboot 3.0/ScriptInterface.h index f4c09a4..cd2fe73 100644 --- a/Project Reboot 3.0/ScriptInterface.h +++ b/Project Reboot 3.0/ScriptInterface.h @@ -4,9 +4,14 @@ class FScriptInterface { -private: +public: UObject* ObjectPointer; void* InterfacePointer; + + FORCEINLINE UObject*& GetObjectRef() + { + return ObjectPointer; + } }; template diff --git a/Project Reboot 3.0/Stack.h b/Project Reboot 3.0/Stack.h index 453db8b..3f9a30f 100644 --- a/Project Reboot 3.0/Stack.h +++ b/Project Reboot 3.0/Stack.h @@ -6,13 +6,13 @@ struct FFrame : public FOutputDevice // https://github.com/EpicGames/UnrealEngine/blob/7acbae1c8d1736bb5a0da4f6ed21ccb237bc8851/Engine/Source/Runtime/CoreUObject/Public/UObject/Stack.h#L83 { public: - void** VFT; + void** VFT; // 10 // Variables. - UFunction* Node; - UObject* Object; - uint8* Code; - uint8* Locals; + UFunction* Node; // 16 + UObject* Object; // 24 // 0x18 + uint8* Code; // 32 // 0x20 + uint8* Locals; // 40 // MORE STUFF HERE }; \ No newline at end of file diff --git a/Project Reboot 3.0/addresses.cpp b/Project Reboot 3.0/addresses.cpp index 0b56445..90bb875 100644 --- a/Project Reboot 3.0/addresses.cpp +++ b/Project Reboot 3.0/addresses.cpp @@ -195,6 +195,7 @@ void Addresses::FindAll() Addresses::LoadPlayset = FindLoadPlayset(); Addresses::SetZoneToIndex = FindSetZoneToIndex(); Addresses::CompletePickupAnimation = FindCompletePickupAnimation(); + Addresses::CanActivateAbility = FindCanActivateAbility(); } void Addresses::Print() @@ -233,6 +234,7 @@ void Addresses::Print() LOG_INFO(LogDev, "LoadPlayset: 0x{:x}", LoadPlayset - Base); LOG_INFO(LogDev, "SetZoneToIndex: 0x{:x}", SetZoneToIndex - Base); LOG_INFO(LogDev, "CompletePickupAnimation: 0x{:x}", CompletePickupAnimation - Base); + LOG_INFO(LogDev, "CanActivateAbility: 0x{:x}", CanActivateAbility - Base); } void Offsets::FindAll() @@ -348,6 +350,11 @@ std::vector Addresses::GetFunctionsToNull() // toNull.push_back(Memcury::Scanner::FindPattern("48 89 4C 24 ? 55 56 57 41 56 48 81 EC ? ? ? ? 4C 8B B1 ? ? ? ? 33 F6 4C 89 B4 24 ? ? ? ? 48 8B").Get()); // fritter crash } + if (Fortnite_Version == 14.60) + { + toNull.push_back(Memcury::Scanner::FindPattern("40 55 57 41 57 48 8D 6C 24 ? 48 81 EC ? ? ? ? 80 3D ? ? ? ? ? 0F B6 FA 44 8B F9 74 3B 80 3D ? ? ? ? ? 0F").Get()); + } + if (Fortnite_Version == 17.30) { toNull.push_back(Memcury::Scanner::FindPattern("48 8B C4 48 89 70 08 48 89 78 10 55 41 54 41 55 41 56 41 57 48 8D 68 A1 48 81 EC ? ? ? ? 45 33 ED").Get()); diff --git a/Project Reboot 3.0/addresses.h b/Project Reboot 3.0/addresses.h index d0734ef..cf1aca8 100644 --- a/Project Reboot 3.0/addresses.h +++ b/Project Reboot 3.0/addresses.h @@ -42,6 +42,7 @@ namespace Addresses extern inline uint64 LoadPlayset = 0; extern inline uint64 SetZoneToIndex = 0; extern inline uint64 CompletePickupAnimation = 0; + extern inline uint64 CanActivateAbility = 0; void SetupVersion(); // Finds Engine Version void FindAll(); diff --git a/Project Reboot 3.0/dllmain.cpp b/Project Reboot 3.0/dllmain.cpp index 191f47c..a2e3813 100644 --- a/Project Reboot 3.0/dllmain.cpp +++ b/Project Reboot 3.0/dllmain.cpp @@ -13,6 +13,7 @@ #include "Map.h" #include "events.h" +#include "FortKismetLibrary.h" enum ENetMode { @@ -67,6 +68,7 @@ DWORD WINAPI Main(LPVOID) static auto FortPlayerControllerAthenaDefault = FindObject(L"/Script/FortniteGame.Default__FortPlayerControllerAthena"); // FindObject(L"/Game/Athena/Athena_PlayerController.Default__Athena_PlayerController_C"); static auto FortPlayerPawnAthenaDefault = FindObject(L"/Game/Athena/PlayerPawn_Athena.Default__PlayerPawn_Athena_C"); static auto FortAbilitySystemComponentAthenaDefault = FindObject(L"/Script/FortniteGame.Default__FortAbilitySystemComponentAthena"); + static auto FortKismetLibraryDefault = FindObject(L"/Script/FortniteGame.Default__FortKismetLibrary"); static auto SwitchLevel = FindObject(L"/Script/Engine.PlayerController.SwitchLevel"); FString Level = Engine_Version < 424 @@ -144,7 +146,7 @@ DWORD WINAPI Main(LPVOID) // UNetDriver::ReplicationDriverOffset = FindOffsetStruct("/Script/Engine.NetDriver", "ReplicationDriver"); // NetDriver->GetOffset("ReplicationDriver"); Hooking::MinHook::Hook(GameModeDefault, FindObject(L"/Script/Engine.GameMode.ReadyToStartMatch"), AFortGameModeAthena::Athena_ReadyToStartMatchHook, - (PVOID*)&AFortGameModeAthena::Athena_ReadyToStartMatchOriginal, false); + (PVOID*)&AFortGameModeAthena::Athena_ReadyToStartMatchOriginal, false); // return false; @@ -176,7 +178,7 @@ DWORD WINAPI Main(LPVOID) Hooking::MinHook::Hook(FortPlayerControllerAthenaDefault, FindObject(L"/Script/FortniteGame.FortPlayerController.ServerPlayEmoteItem"), AFortPlayerController::ServerPlayEmoteItemHook, nullptr, false); Hooking::MinHook::Hook(FortPlayerControllerAthenaDefault, FindObject(L"/Script/FortniteGame.FortPlayerController.ServerCreateBuildingActor"), - AFortPlayerController::ServerCreateBuildingActorHook, nullptr, false); + AFortPlayerController::ServerCreateBuildingActorHook, (PVOID*)&AFortPlayerController::ServerCreateBuildingActorOriginal, false, true); Hooking::MinHook::Hook(FortPlayerControllerAthenaDefault, FindObject(L"/Script/FortniteGame.FortPlayerController.ServerBeginEditingBuildingActor"), AFortPlayerController::ServerBeginEditingBuildingActorHook, nullptr, false); Hooking::MinHook::Hook(FortPlayerControllerAthenaDefault, FindObject(L"/Script/FortniteGame.FortPlayerController.ServerEditBuildingActor"), @@ -189,6 +191,16 @@ DWORD WINAPI Main(LPVOID) Hooking::MinHook::Hook(FortPlayerPawnAthenaDefault, FindObject(L"/Script/FortniteGame.FortPlayerPawn.ServerSendZiplineState"), AFortPlayerPawn::ServerSendZiplineStateHook, nullptr, false); + if (false) + { + Hooking::MinHook::Hook(FortKismetLibraryDefault, FindObject(L"Script/FortniteGame.FortKismetLibrary.K2_GiveItemToPlayer"), + UFortKismetLibrary::K2_GiveItemToPlayerHook, (PVOID*)&UFortKismetLibrary::K2_GiveItemToPlayerOriginal, false, true); + Hooking::MinHook::Hook(FortKismetLibraryDefault, FindObject(L"/Script/FortniteGame.FortKismetLibrary.GiveItemToInventoryOwner"), + UFortKismetLibrary::GiveItemToInventoryOwnerHook, (PVOID*)&UFortKismetLibrary::GiveItemToInventoryOwnerOriginal, false, true); + Hooking::MinHook::Hook(FortKismetLibraryDefault, FindObject(L"/Script/FortniteGame.FortKismetLibrary.K2_RemoveItemFromPlayer"), + UFortKismetLibrary::K2_RemoveItemFromPlayerHook, (PVOID*)&UFortKismetLibrary::K2_RemoveItemFromPlayerOriginal, false, true); + } + static auto ServerHandlePickupInfoFn = FindObject("/Script/FortniteGame.FortPlayerPawn.ServerHandlePickupInfo"); if (ServerHandlePickupInfoFn) @@ -203,10 +215,24 @@ DWORD WINAPI Main(LPVOID) if (Globals::bAbilitiesEnabled) { - Hooking::MinHook::Hook(FortAbilitySystemComponentAthenaDefault, FindObject(L"/Script/GameplayAbilities.AbilitySystemComponent.ServerTryActivateAbility"), - UAbilitySystemComponent::ServerTryActivateAbilityHook, nullptr, false); - Hooking::MinHook::Hook(FortAbilitySystemComponentAthenaDefault, FindObject(L"/Script/GameplayAbilities.AbilitySystemComponent.ServerTryActivateAbilityWithEventData"), - UAbilitySystemComponent::ServerTryActivateAbilityWithEventDataHook, nullptr, false); + static auto PredictionKeyStruct = FindObject("/Script/GameplayAbilities.PredictionKey"); + static auto PredictionKeySize = PredictionKeyStruct->GetPropertiesSize(); + + if (PredictionKeySize == 0x10) + { + Hooking::MinHook::Hook(FortAbilitySystemComponentAthenaDefault, FindObject(L"/Script/GameplayAbilities.AbilitySystemComponent.ServerTryActivateAbility"), + UAbilitySystemComponent::ServerTryActivateAbilityHook1, nullptr, false); + Hooking::MinHook::Hook(FortAbilitySystemComponentAthenaDefault, FindObject(L"/Script/GameplayAbilities.AbilitySystemComponent.ServerTryActivateAbilityWithEventData"), + UAbilitySystemComponent::ServerTryActivateAbilityWithEventDataHook1, nullptr, false); + } + else if (PredictionKeySize == 0x18) + { + Hooking::MinHook::Hook(FortAbilitySystemComponentAthenaDefault, FindObject(L"/Script/GameplayAbilities.AbilitySystemComponent.ServerTryActivateAbility"), + UAbilitySystemComponent::ServerTryActivateAbilityHook2, nullptr, false); + Hooking::MinHook::Hook(FortAbilitySystemComponentAthenaDefault, FindObject(L"/Script/GameplayAbilities.AbilitySystemComponent.ServerTryActivateAbilityWithEventData"), + UAbilitySystemComponent::ServerTryActivateAbilityWithEventDataHook2, nullptr, false); + } + // Hooking::MinHook::Hook(FortAbilitySystemComponentAthenaDefault, FindObject(L"/Script/GameplayAbilities.AbilitySystemComponent.ServerAbilityRPCBatch"), // UAbilitySystemComponent::ServerAbilityRPCBatchHook, nullptr, false); } @@ -223,9 +249,38 @@ DWORD WINAPI Main(LPVOID) Hooking::MinHook::Hook((PVOID)Addresses::TickFlush, (PVOID)UNetDriver::TickFlushHook, (PVOID*)&UNetDriver::TickFlushOriginal); // Hooking::MinHook::Hook((PVOID)Addresses::OnDamageServer, (PVOID)ABuildingActor::OnDamageServerHook, (PVOID*)&ABuildingActor::OnDamageServerOriginal); // Hooking::MinHook::Hook((PVOID)Addresses::CollectGarbage, (PVOID)CollectGarbageHook, nullptr); - Hooking::MinHook::Hook((PVOID)Addresses::PickTeam, (PVOID)AFortGameModeAthena::Athena_PickTeamHook, nullptr); + Hooking::MinHook::Hook((PVOID)Addresses::PickTeam, (PVOID)AFortGameModeAthena::Athena_PickTeamHook); Hooking::MinHook::Hook((PVOID)Addresses::SetZoneToIndex, (PVOID)AFortGameModeAthena::SetZoneToIndexHook, (PVOID*)&AFortGameModeAthena::SetZoneToIndexOriginal); Hooking::MinHook::Hook((PVOID)Addresses::CompletePickupAnimation, (PVOID)AFortPickup::CompletePickupAnimationHook, (PVOID*)&AFortPickup::CompletePickupAnimationOriginal); + // Hooking::MinHook::Hook((PVOID)Addresses::CanActivateAbility, ReturnTrueHook); + + LOG_INFO(LogDev, "Test: 0x{:x}", FindFunctionCall(L"ClientOnPawnDied") - __int64(GetModuleHandleW(0))); + Hooking::MinHook::Hook((PVOID)FindFunctionCall(L"ClientOnPawnDied"), AFortPlayerController::ClientOnPawnDiedHook, (PVOID*)&AFortPlayerController::ClientOnPawnDiedOriginal); + + { + MemberOffsets::FortPlayerStateAthena::DeathInfo = FindOffsetStruct("/Script/FortniteGame.FortPlayerStateAthena", "DeathInfo"); + + MemberOffsets::DeathInfo::bDBNO = FindOffsetStruct("/Script/FortniteGame.DeathInfo", "bDBNO"); + MemberOffsets::DeathInfo::DeathCause = FindOffsetStruct("/Script/FortniteGame.DeathInfo", "DeathCause"); + MemberOffsets::DeathInfo::bInitialized = FindOffsetStruct("/Script/FortniteGame.DeathInfo", "bInitialized", false); + MemberOffsets::DeathInfo::Distance = FindOffsetStruct("/Script/FortniteGame.DeathInfo", "Distance"); + MemberOffsets::DeathInfo::DeathTags = FindOffsetStruct("/Script/FortniteGame.DeathInfo", "DeathTags", false); + MemberOffsets::DeathInfo::DeathLocation = FindOffsetStruct("/Script/FortniteGame.DeathInfo", "DeathLocation"); + + MemberOffsets::DeathReport::Tags = FindOffsetStruct("FortniteGame.FortPlayerDeathReport", "Tags"); + MemberOffsets::DeathReport::KillerPawn = FindOffsetStruct("FortniteGame.FortPlayerDeathReport", "KillerPawn"); + MemberOffsets::DeathReport::KillerPlayerState = FindOffsetStruct("FortniteGame.FortPlayerDeathReport", "KillerPlayerState"); + MemberOffsets::DeathReport::DamageCauser = FindOffsetStruct("FortniteGame.FortPlayerDeathReport", "DamageCauser"); + } + + /* auto GetMaxTickRateIndex = *Memcury::Scanner::FindStringRef(L"GETMAXTICKRATE") + .ScanFor({ 0x4D, 0x8B, 0xC7, 0xE8 }) + .RelativeOffset(4) + .ScanFor({ 0xFF, 0x90 }) + .AbsoluteOffset(2) + .GetAs() / 8; + + LOG_INFO(LogHook, "GetMaxTickRateIndex {}", GetMaxTickRateIndex); */ srand(time(0)); @@ -258,6 +313,11 @@ DWORD WINAPI Main(LPVOID) GameMode->Get("WarmupEarlyCountdownDuration") = 0; } + /* else if (GetAsyncKeyState(VK_F9) & 1) + { + GetWorld()->Listen(); + } */ + Sleep(1000 / 30); } diff --git a/Project Reboot 3.0/events.h b/Project Reboot 3.0/events.h index 578f4da..dcae8a0 100644 --- a/Project Reboot 3.0/events.h +++ b/Project Reboot 3.0/events.h @@ -57,6 +57,62 @@ static inline std::vector Events = "/Game/Athena/Playlists/Music/Playlist_Music_High.Playlist_Music_High", 12.41 ), + Event( + "Devourer of Worlds", + "/Junior/Blueprints/BP_Junior_Loader.BP_Junior_Loader_C", + "/Junior/Blueprints/BP_Junior_Loader.BP_Junior_Loader_C.LoadJuniorLevel", + 1, + { + { + false, + "/Junior/Blueprints/BP_Event_Master_Scripting.BP_Event_Master_Scripting_C.OnReady_872E6C4042121944B78EC9AC2797B053" + } + }, + { + { + { + false, + "/Junior/Blueprints/BP_Junior_Scripting.BP_Junior_Scripting_C.startevent" + }, + + 0 + } + }, + + "/Junior/Blueprints/BP_Junior_Scripting.BP_Junior_Scripting_C", + "/Game/Athena/Playlists/Music/Playlist_Junior_32.Playlist_Junior_32", + 14.60 + ), + Event( + "The End", + "", + "", + 1, + { + { + false, + "/Game/Athena/Prototype/Blueprints/NightNight/BP_NightNight_Scripting.BP_NightNight_Scripting_C.LoadNightNightLevel" // skunked + }, + { + false, + "/Game/Athena/Prototype/Blueprints/NightNight/BP_NightNight_Scripting.BP_NightNight_Scripting_C.OnReady_D0847F7B4E80F01E77156AA4E7131AF6" + } + }, + { + { + { + false, + "/Game/Athena/Prototype/Blueprints/NightNight/BP_NightNight_Scripting.BP_NightNight_Scripting_C.startevent" + }, + + 0 + } + }, + + "/Game/Athena/Prototype/Blueprints/NightNight/BP_NightNight_Scripting.BP_NightNight_Scripting_C", + "/Game/Athena/Playlists/Music/Playlist_Music_High.Playlist_Music_High", + 10.40 + ), Event ( "Device", @@ -145,7 +201,34 @@ static inline std::vector Events = // "/Buffet/Gameplay/Blueprints/BP_Buffet_Master_Scripting.BP_Buffet_Master_Scripting_C", "/BuffetPlaylist/Playlist/Playlist_Buffet.Playlist_Buffet", 17.30 - ) + ), + Event + ( + "Ice King Event", + "/Game/Athena/Prototype/Blueprints/Mooney/BP_MooneyLoader.BP_MooneyLoader_C", + "/Game/Athena/Prototype/Blueprints/Mooney/BP_MooneyLoader.BP_MooneyLoader_C.LoadMap", + 0, + { + { + false, + "/Game/Athena/Prototype/Blueprints/Mooney/BP_MooneyScripting.BP_MooneyScripting_C.OnReady_9968C1F648044523426FE198948B0CC9" + } + }, + { + { + { + false, + "/Game/Athena/Prototype/Blueprints/Mooney/BP_MooneyScripting.BP_MooneyScripting_C.BeginIceKingEvent" + }, + + 0 + } + }, + + "/Game/Athena/Prototype/Blueprints/Mooney/BP_MooneyScripting.BP_MooneyScripting_C", + "/Game/Athena/Playlists/Playlist_DefaultSolo.Playlist_DefaultSolo", + 7.20 + ) }; static inline UObject* GetEventPlaylist() @@ -314,9 +397,11 @@ static inline bool CallOnReadys(bool* bWereAllSuccessful = nullptr) if (bWereAllSuccessful) *bWereAllSuccessful = true; + auto EventPlaylist = GetEventPlaylist(); + struct { UObject* GameState; UObject* Playlist; FGameplayTagContainer PlaylistContextTags; } OnReadyParams{ - ((AFortGameModeAthena*)GetWorld()->GetGameMode())->GetGameStateAthena(), GetEventPlaylist(), - GetEventPlaylist()->Get("GameplayTagContainer")}; + ((AFortGameModeAthena*)GetWorld()->GetGameMode())->GetGameStateAthena(), EventPlaylist, + EventPlaylist ? EventPlaylist->Get("GameplayTagContainer") : FGameplayTagContainer()}; for (auto& OnReadyFunc : OurEvent.OnReadyFunctions) { @@ -404,12 +489,13 @@ static inline void StartEvent() auto EventScripting = GetEventScripting(); LOG_INFO(LogDev, "EventScripting {}", __int64(EventScripting)); - LOG_INFO(LogDev, "EventScripting Name {}", EventScripting->GetFullName()); + + if (EventScripting) + LOG_INFO(LogDev, "EventScripting Name {}", EventScripting->GetFullName()); // if (!EventScripting) // return; // GetEventScripting handles the printing - CallOnReadys(); if (Fortnite_Version == 17.30) diff --git a/Project Reboot 3.0/finder.h b/Project Reboot 3.0/finder.h index 22ef530..e3a7264 100644 --- a/Project Reboot 3.0/finder.h +++ b/Project Reboot 3.0/finder.h @@ -48,6 +48,19 @@ static inline uintptr_t FindBytes(Memcury::Scanner& Scanner, const std::vector>& Bytes, int Count = 255, int SkipBytes = 0, bool bGoUp = false, int Skip = 0, const bool bPrint = false) +{ + for (auto& ByteArray : Bytes) + { + auto Res = FindBytes(Scanner, ByteArray, Count, SkipBytes, false, Skip, bPrint); + + if (Res) + return Res; + } + + return 0; +} */ + static inline uint64 FindStaticFindObject() { if (Engine_Version == 500) @@ -151,6 +164,9 @@ static inline uint64 FindPauseBeaconRequests() if (Engine_Version == 426) return Memcury::Scanner::FindPattern("40 57 48 83 EC 30 48 8B F9 84 D2 74 62 80 3D").Get(); + if (Engine_Version == 420) + return Memcury::Scanner::FindPattern("40 53 48 83 EC 30 48 8B D9 84 D2 74 68 80 3D ? ? ? ? ? 72 2C 48 8B 05 ? ? ? ? 4C 8D 44").Get(); + auto Addr = Memcury::Scanner::FindStringRef(L"All Beacon Requests Resumed."); return FindBytes(Addr, { 0x40, 0x53 }, 1000, 0, true); } @@ -226,11 +242,38 @@ static inline uint64 FindStaticLoadObject() static inline uint64 FindCompletePickupAnimation() { - return Memcury::Scanner::FindPattern("40 53 56 48 83 EC 38 4C 89 6C 24 ? 48 8B F1 4C 8B A9 ? ? ? ? 4D 85 ED").Get(); // 14.60 + if (Engine_Version == 420) + return Memcury::Scanner::FindPattern("48 89 5C 24 ? 57 48 83 EC 20 48 8B D9 48 8B 89 ? ? ? ? 48 85 C9 74 20 48 8D 44 24").Get(); + + if (Engine_Version == 421) + return Memcury::Scanner::FindPattern("40 53 56 57 48 83 EC 30 4C 89 6C 24 ? 48 8B F1 4C 8B A9 ? ? ? ? 4D 85 ED 0F 84").Get(); // 6.21 + + if (Engine_Version == 422) + return Memcury::Scanner::FindPattern("40 53 56 57 48 83 EC 30 4C 89 6C 24 ? 48 8B F1 4C 8B A9 ? ? ? ? 4D 85 ED 0F 84").Get(); // 7.30 + + if (Engine_Version == 423) + return Memcury::Scanner::FindPattern("40 53 56 48 83 EC 38 4C 89 6C 24 ? 48 8B F1 4C 8B A9 ? ? ? ? 4D 85 ED 0F 84 ? ? ? ? 49 63 8D").Get(); // 10.40 + + if (Engine_Version == 424) + return Memcury::Scanner::FindPattern("40 53 56 48 83 EC 38 4C 89 6C 24 ? 48 8B F1 4C 8B A9 ? ? ? ? 4D 85 ED 0F 84 ? ? ? ? 49 63 8D").Get(); // 11.31 + + if (Engine_Version == 425) + return Memcury::Scanner::FindPattern("40 53 56 48 83 EC 38 4C 89 6C 24 ? 48 8B F1 4C 8B A9 ? ? ? ? 4D 85 ED 0F 84 ? ? ? ? 49 63 8D").Get(); // 12.41 + + if (Engine_Version == 426) + return Memcury::Scanner::FindPattern("40 53 56 48 83 EC 38 4C 89 6C 24 ? 48 8B F1 4C 8B A9 ? ? ? ? 4D 85 ED").Get(); // 14.60 + + return 0; } static inline uint64 FindNoMCP() { + if (std::floor(Fortnite_Version) == 3) + return Memcury::Scanner::FindPattern("E8 ? ? ? ? 83 A7 ? ? ? ? ? 48 8D 4C 24 ?").Get(); + + if (std::floor(Fortnite_Version) == 4) + return Memcury::Scanner::FindPattern("E8 ? ? ? ? 83 A7 ? ? ? ? ? 83 E0 01").RelativeOffset(1).Get(); + auto fn = FindObject("/Script/FortniteGame.FortKismetLibrary.IsRunningNoMCP"); LOG_INFO(LogDev, "fn: {}", __int64(fn)); @@ -240,9 +283,6 @@ static inline uint64 FindNoMCP() auto noMcpIthink = GetFunctionIdxOrPtr(fn); return noMcpIthink; - if (Fortnite_Version == 4) - return Memcury::Scanner::FindPattern("E8 ? ? ? ? 83 A7 ? ? ? ? ? 83 E0 01").RelativeOffset(1).Get(); - if (Fortnite_Version >= 17) { // todo make this relative @@ -297,12 +337,8 @@ static inline uint64 FindActorGetNetMode() if (Engine_Version == 427) return Memcury::Scanner::FindPattern("48 89 5C 24 ? 57 48 83 EC 20 48 8B D9 E8 ? ? ? ? 48 8B 93 ? ? ? ? 48 8B C8 48 8B F8 E8 ? ? ? ? 48 85 C0 75 29").Get(); - auto AActorGetNetmode = Memcury::Scanner::FindStringRef(L"ClientPlayerLeft %s") - .ScanFor({ 0x48, 0x8B, 0xCF, 0xE8 }) - .RelativeOffset(4) - .Get(); - - return AActorGetNetmode; + auto AActorGetNetmode = Memcury::Scanner::FindStringRef(L"STAT_ServerUpdateCamera"); + return Memcury::Scanner(FindBytes(AActorGetNetmode, { 0xE8 }, 255, 0, true)).RelativeOffset(1).Get(); } static inline uint64 FindTickFlush() @@ -319,7 +355,7 @@ static inline uint64 FindTickFlush() static inline uint64 FindAddNavigationSystemToWorld() { - return Memcury::Scanner::FindPattern("48 89 5C 24 ? 48 89 6C 24 ? 48 89 74 24 ? 57 48 83 EC 20 33 ED 41").Get(); + return Memcury::Scanner::FindPattern("48 89 5C 24 ? 48 89 6C 24 ? 48 89 74 24 ? 57 48 83 EC 20 33 ED 41", false).Get(); } static inline uint64 FindNavSystemCleanUp() @@ -350,6 +386,9 @@ static inline uint64 FindGIsServer() // if (Fortnite_Version == 19.10) // return __int64(GetModuleHandleW(0)) + 0xB30CF9D; + if (Fortnite_Version == 14.60) + return __int64(GetModuleHandleW(0)) + 0x939930E; + if (Fortnite_Version == 17.30) return __int64(GetModuleHandleW(0)) + 0x973E499; @@ -443,6 +482,9 @@ static inline uint64 FindDispatchRequest() static inline uint64 FindGIsClient() { + if (Fortnite_Version == 14.60) + return __int64(GetModuleHandleW(0)) + 0x939930D; + if (Fortnite_Version == 17.30) return __int64(GetModuleHandleW(0)) + 0x973E49B; @@ -573,6 +615,15 @@ static inline uint64 FindInternalTryActivateAbility() return FindBytes(Addr, { 0x4C, 0x89, 0x4C }, 1000, 0, true); } +static inline uint64 FindCanActivateAbility() +{ + if (Engine_Version == 421 || Engine_Version == 422) + return Memcury::Scanner::FindPattern("4C 89 4C 24 20 55 56 57 41 56 48 8D 6C 24 D1").Get(); + + auto Addr = Memcury::Scanner::FindStringRef(L"CanActivateAbility %s failed, blueprint refused"); + return FindBytes(Addr, { 0x48, 0x89, 0x5C }, 2000, 0, true); +} + static inline uint64 FindGiveAbilityAndActivateOnce() { if (Engine_Version == 426) @@ -586,6 +637,12 @@ static inline uint64 FindGiveAbilityAndActivateOnce() static inline uint64 FindGiveAbility() { + if (Engine_Version == 420) + return Memcury::Scanner::FindPattern("48 89 5C 24 ? 56 57 41 56 48 83 EC 20 83 B9 ? ? ? ? ? 49 8B F0 4C 8B F2 48 8B D9 7E 61").Get(); + + if (Engine_Version == 421) + return Memcury::Scanner::FindPattern("48 89 5C 24 ? 48 89 6C 24 ? 48 89 7C 24 ? 41 56 48 83 EC 20 83 B9 ? ? ? ? ? 49 8B E8 4C 8B F2").Get(); + // auto Addr = Memcury::Scanner::FindStringRef(L"GiveAbilityAndActivateOnce called on ability %s on the client, not allowed!"); // has 2 refs for some reason on some versions // auto realGiveAbility = Memcury::Scanner(FindBytes(Addr, { 0xE8 }, 500, 0, false, 0, true)).RelativeOffset(1).Get(); @@ -627,5 +684,5 @@ static inline uint64 FindReplaceBuildingActor() return 0; } - return FindBytes(StringRef, { 0x4C, 0x8B }, 1000, 0, true); + return FindBytes(StringRef, (Engine_Version == 420 ? std::vector{ 0x48, 0x8B, 0xC4 } : std::vector{ 0x4C, 0x8B }), 1000, 0, true); } \ No newline at end of file diff --git a/Project Reboot 3.0/globals.h b/Project Reboot 3.0/globals.h index 9c301c7..7d1f466 100644 --- a/Project Reboot 3.0/globals.h +++ b/Project Reboot 3.0/globals.h @@ -3,7 +3,7 @@ namespace Globals { extern inline bool bCreative = false; - extern inline bool bGoingToPlayEvent = false; + extern inline bool bGoingToPlayEvent = true; extern inline bool bNoMCP = true; extern inline bool bLateGame = false; extern inline bool bAbilitiesEnabled = true; diff --git a/Project Reboot 3.0/log.h b/Project Reboot 3.0/log.h index d12315f..7203b76 100644 --- a/Project Reboot 3.0/log.h +++ b/Project Reboot 3.0/log.h @@ -56,6 +56,7 @@ inline void InitLogger() sinks.emplace_back(std::make_shared())->set_pattern("[%D-%T] %n: %^%v%$"); sinks.emplace_back(std::make_shared(logName, true))->set_pattern("[%D-%T] %n: %l: %v"); + MakeLogger("LogTeams"); MakeLogger("LogMemory"); MakeLogger("LogFinder"); MakeLogger("LogInit"); diff --git a/Project Reboot 3.0/reboot.h b/Project Reboot 3.0/reboot.h index 7a728c5..3fb41f8 100644 --- a/Project Reboot 3.0/reboot.h +++ b/Project Reboot 3.0/reboot.h @@ -205,13 +205,15 @@ inline void SetBitfield(void* Addr, uint8_t FieldMask, bool NewVal) *(bool*)Bitfield = NewVal; } -inline int FindOffsetStruct(const std::string& StructName, const std::string& MemberName) +inline int FindOffsetStruct(const std::string& StructName, const std::string& MemberName, bool bWarnIfNotFound = true) { UObject* Struct = FindObject(StructName); if (!Struct) { - LOG_WARN(LogFinder, "Unable to find struct {}", StructName); + if (bWarnIfNotFound) + LOG_WARN(LogFinder, "Unable to find struct {}", StructName); + return 0; } @@ -257,7 +259,8 @@ inline int FindOffsetStruct(const std::string& StructName, const std::string& Me } } - LOG_WARN(LogFinder, "Unable to find1{}", MemberName); + if (bWarnIfNotFound) + LOG_WARN(LogFinder, "Unable to find1 {}", MemberName); return 0; } @@ -275,8 +278,16 @@ static T* Alloc(size_t Size) namespace MemberOffsets { + namespace FortPlayerStateAthena + { + extern inline int DeathInfo = 0; + } + namespace DeathReport + { + extern inline int Tags = 0, KillerPlayerState = 0, KillerPawn = 0, DamageCauser = 0; + } namespace DeathInfo { - static inline int bDBNO, Downer, FinisherOrDowner, DeathCause, Distance, DeathLocation, bInitialized, DeathTags; + extern inline int bDBNO = 0, Downer = 0, FinisherOrDowner = 0, DeathCause = 0, Distance = 0, DeathLocation = 0, bInitialized = 0, DeathTags = 0; } } \ No newline at end of file diff --git a/vendor/memcury.h b/vendor/memcury.h index 44c5ba8..5cf9e22 100644 --- a/vendor/memcury.h +++ b/vendor/memcury.h @@ -880,12 +880,12 @@ { if constexpr (bIsWide) { - auto aaa = (L"FindStringRef " + std::wstring(string)); + auto aaa = (L"failed FindStringRef " + std::wstring(string)); MessageBoxA(0, std::string(aaa.begin(), aaa.end()).c_str(), "Memcury", MB_ICONERROR); } else { - MessageBoxA(0, ("FindStringRef " + std::string(string)).c_str(), "Memcury", MB_ICONERROR); + MessageBoxA(0, ("failed FindStringRef " + std::string(string)).c_str(), "Memcury", MB_ICONERROR); } } }