diff --git a/Project Reboot 3.0/FortGameModeAthena.cpp b/Project Reboot 3.0/FortGameModeAthena.cpp index de57792..36b64c7 100644 --- a/Project Reboot 3.0/FortGameModeAthena.cpp +++ b/Project Reboot 3.0/FortGameModeAthena.cpp @@ -175,6 +175,19 @@ void AFortGameModeAthena::HandleSpawnRateForActorClass(UClass* ActorClass, float } } +void AFortGameModeAthena::StartAircraftPhase() +{ + if (Addresses::StartAircraftPhase) + { + static void (*StartAircraftPhaseOriginal)(AFortGameModeAthena*, bool bDoNotSpawnAircraft) = decltype(StartAircraftPhaseOriginal)(Addresses::StartAircraftPhase); + StartAircraftPhaseOriginal(this, false); // love the double negative fortnite + } + else + { + UKismetSystemLibrary::ExecuteConsoleCommand(GetWorld(), L"startaircraft", nullptr); + } +} + void AFortGameModeAthena::PauseSafeZone(bool bPaused) { auto GameState = GetGameStateAthena(); diff --git a/Project Reboot 3.0/FortGameModeAthena.h b/Project Reboot 3.0/FortGameModeAthena.h index ac6360b..0a8bab5 100644 --- a/Project Reboot 3.0/FortGameModeAthena.h +++ b/Project Reboot 3.0/FortGameModeAthena.h @@ -263,6 +263,7 @@ public: UClass* GetVehicleClassOverride(UClass* DefaultClass); void SkipAircraft(); void PauseSafeZone(bool bPaused = true); + void StartAircraftPhase(); static void HandleSpawnRateForActorClass(UClass* ActorClass, float SpawnPercentage); // idk where to put diff --git a/Project Reboot 3.0/FortInventory.cpp b/Project Reboot 3.0/FortInventory.cpp index be3b04f..a7818ca 100644 --- a/Project Reboot 3.0/FortInventory.cpp +++ b/Project Reboot 3.0/FortInventory.cpp @@ -249,7 +249,7 @@ std::pair, std::vector> AFortInventory::AddI return Ret; } -bool AFortInventory::RemoveItem(const FGuid& ItemGuid, bool* bShouldUpdate, int Count, bool bForceRemoval) +bool AFortInventory::RemoveItem(const FGuid& ItemGuid, bool* bShouldUpdate, int Count, bool bForceRemoval, bool bIgnoreVariables) { if (bShouldUpdate) *bShouldUpdate = false; @@ -280,7 +280,7 @@ bool AFortInventory::RemoveItem(const FGuid& ItemGuid, bool* bShouldUpdate, int bool bOverrideChangeStackSize = false; - if (ItemDefinition->ShouldPersistWhenFinalStackEmpty()) + if (!bIgnoreVariables && ItemDefinition->ShouldPersistWhenFinalStackEmpty()) { bool bIsFinalStack = true; diff --git a/Project Reboot 3.0/FortInventory.h b/Project Reboot 3.0/FortInventory.h index fb14140..5f48463 100644 --- a/Project Reboot 3.0/FortInventory.h +++ b/Project Reboot 3.0/FortInventory.h @@ -101,7 +101,7 @@ public: std::pair, std::vector> AddItem(FFortItemEntry* ItemEntry, bool* bShouldUpdate, bool bShowItemToast = false, int OverrideCount = -1); std::pair, std::vector> AddItem(UFortItemDefinition* ItemDefinition, bool* bShouldUpdate, int Count = 1, int LoadedAmmo = -1, bool bShowItemToast = false); - bool RemoveItem(const FGuid& ItemGuid, bool* bShouldUpdate, int Count, bool bForceRemoval = false); + bool RemoveItem(const FGuid& ItemGuid, bool* bShouldUpdate, int Count, bool bForceRemoval = false, bool bIgnoreVariables = false); void SwapItem(const FGuid& ItemGuid, FFortItemEntry* NewItemEntry, int OverrideNewCount = -1, std::pair* outEntries = nullptr); void ModifyCount(UFortItem* ItemInstance, int New, bool bRemove = false, std::pair* outEntries = nullptr, bool bUpdate = true, bool bShowItemToast = false); diff --git a/Project Reboot 3.0/FortLootPackage.cpp b/Project Reboot 3.0/FortLootPackage.cpp index 9812742..1d73bdf 100644 --- a/Project Reboot 3.0/FortLootPackage.cpp +++ b/Project Reboot 3.0/FortLootPackage.cpp @@ -121,11 +121,11 @@ float GetAmountOfLootPackagesToDrop(FFortLootTierData* LootTierData, int Origina { // HONESTLY IDEK WHAT FORTNITE DOES HERE - float v29 = (float)rand() * 0.000030518509; + float v29 = (float)rand() * 0.000030518509f; float v35 = (int)(float)((float)((float)((float)SumLootPackageCategoryWeightArray * v29) + (float)((float)SumLootPackageCategoryWeightArray * v29)) - + 0.5) >> 1; + + 0.5f) >> 1; // OutLootTierInfo->Hello++; MinimumLootDrops++; @@ -153,27 +153,30 @@ float GetAmountOfLootPackagesToDrop(FFortLootTierData* LootTierData, int Origina FFortLootTierData* PickLootTierData(const std::vector& LTDTables, FName LootTierGroup, int ForcedLootTier = -1, FName* OutRowName = nullptr) // Fortnite returns the row name and then finds the tier data again, but I really don't see the point of this. { + // This like isn't right, at all. + float LootTier = ForcedLootTier; - float IdkForcedWeightorsomething = -1; if (LootTier == -1) { - // IdkForcedWeightorsomething = weightofAlltherowsithink // we don't ened to do this since the pickweightedeleent already does that + // LootTier = ?? } else { - // ITS SO MUCH TO REVERSE AAAAA + // buncha code im too lazy to reverse } - // if (fabs(LootTier) <= 0.0000000099999999) + // if (fabs(LootTier) <= 0.0000000099999999f) // return 0; + int Multiplier = LootTier == -1 ? 1 : LootTier; // Idk i think we need to fill out the code above for this to work properly maybe + LOOTING_MAP_TYPE TierGroupLTDs; CollectDataTablesRows(LTDTables, &TierGroupLTDs, [&](FName RowName, FFortLootTierData* TierData) -> bool { if (LootTierGroup == TierData->GetTierGroup()) { - if ((LootTier == -1 ? true : LootTier == TierData->GetLootTier())) // idek if this is proper + if ((LootTier == -1 ? true : LootTier == TierData->GetLootTier())) { return true; } @@ -186,20 +189,18 @@ FFortLootTierData* PickLootTierData(const std::vector& LTDTables, F FFortLootTierData* ChosenRowLootTierData = PickWeightedElement(TierGroupLTDs, [](FFortLootTierData* LootTierData) -> float { return LootTierData->GetWeight(); }, RandomFloatForLoot, -1, - true, 1, OutRowName, false, false, IdkForcedWeightorsomething); + true, Multiplier, OutRowName); return ChosenRowLootTierData; } -void PickLootDropsFromLootPackage(const std::vector& LPTables, FName LootPackageName, std::vector* OutEntries, int LootPackageCategory = -1, int WorldLevel = 0, bool bPrint = false, bool bCombineDrops = true) +void PickLootDropsFromLootPackage(const std::vector& LPTables, const FName& LootPackageName, std::vector* OutEntries, int LootPackageCategory = -1, int WorldLevel = 0, bool bPrint = false, bool bCombineDrops = true) { if (!OutEntries) return; LOOTING_MAP_TYPE LootPackageIDMap; - float TotalWeight = 0; - CollectDataTablesRows(LPTables, &LootPackageIDMap, [&](FName RowName, FFortLootPackageData* LootPackage) -> bool { if (LootPackage->GetLootPackageID() != LootPackageName) { @@ -214,18 +215,16 @@ void PickLootDropsFromLootPackage(const std::vector& LPTables, FNam if (WorldLevel >= 0) { if (LootPackage->GetMaxWorldLevel() >= 0 && WorldLevel > LootPackage->GetMaxWorldLevel()) - return false; + return 0; if (LootPackage->GetMinWorldLevel() >= 0 && WorldLevel < LootPackage->GetMinWorldLevel()) - return false; + return 0; } - TotalWeight += LootPackage->GetWeight(); - return true; }); - if (TotalWeight == 0) + if (LootPackageIDMap.size() == 0) { // std::cout << std::format("Loot Package {} has no valid weights.\n", LootPackageName.ToString()); return; @@ -233,7 +232,8 @@ void PickLootDropsFromLootPackage(const std::vector& LPTables, FNam FName PickedPackageRowName; FFortLootPackageData* PickedPackage = PickWeightedElement(LootPackageIDMap, - [](FFortLootPackageData* LootPackageData) -> float { return LootPackageData->GetWeight(); }, RandomFloatForLoot, -1, true, 1, &PickedPackageRowName, bPrint); + [](FFortLootPackageData* LootPackageData) -> float { return LootPackageData->GetWeight(); }, RandomFloatForLoot, + -1, true, 1, &PickedPackageRowName, bPrint); if (!PickedPackage) return; @@ -250,7 +250,7 @@ void PickLootDropsFromLootPackage(const std::vector& LPTables, FNam while (v9 < PickedPackage->GetCount()) { int LootPackageCategoryToUseForLPCall = 0; // hmm - + PickLootDropsFromLootPackage(LPTables, PickedPackage->GetLootPackageCall().Data.Data ? UKismetStringLibrary::Conv_StringToName(PickedPackage->GetLootPackageCall()) : FName(0), OutEntries, LootPackageCategoryToUseForLPCall, WorldLevel, bPrint @@ -270,7 +270,7 @@ void PickLootDropsFromLootPackage(const std::vector& LPTables, FNam LOG_INFO(LogLoot, "Loot Package {} does not contain a LootPackageCall or ItemDefinition.", PickedPackage->GetLootPackageID().ToString()); return; } - + auto WeaponItemDefinition = Cast(ItemDefinition); int LoadedAmmo = WeaponItemDefinition ? WeaponItemDefinition->GetClipSize() : 0; // we shouldnt set loaded ammo here techinally @@ -332,14 +332,14 @@ void PickLootDropsFromLootPackage(const std::vector& LPTables, FNam if (Engine_Version >= 424) { /* - + Alright, so Fortnite literally doesn't reference the first loot package category for chests and floor loot (didnt check rest). Usually the first loot package category in our case is ammo, so this is quite weird. I have no clue how Fortnite would actually add the ammo. Guess what, on the chapter 2 new loot tier groups, like FactionChests, they don't even have a package which has ammo as its loot package call. - - */ + + */ bool IsWeapon = PickedPackage->GetLootPackageID().ToString().contains(".Weapon.") && WeaponItemDefinition; // ONG? @@ -366,6 +366,8 @@ void PickLootDropsFromLootPackage(const std::vector& LPTables, FNam } } +// #define brudda + std::vector PickLootDrops(FName TierGroupName, int WorldLevel, int ForcedLootTier, bool bPrint, int recursive, bool bCombineDrops) { std::vector LootDrops; @@ -509,6 +511,23 @@ std::vector PickLootDrops(FName TierGroupName, int WorldLevel, int For if (ptr) { + /* if (bOverrideIsComposite) + { + static auto ParentTablesOffset = ptr->GetOffset("ParentTables"); + + auto ParentTables = ptr->GetPtr>(ParentTablesOffset); + + for (int z = 0; z < ParentTables->size(); z++) + { + auto ParentTable = ParentTables->At(z); + + if (ParentTable) + { + LPTables.push_back(ParentTable); + } + } + } */ + LPTables.push_back(ptr); } } @@ -552,7 +571,7 @@ std::vector PickLootDrops(FName TierGroupName, int WorldLevel, int For auto ParentTables = ptr->GetPtr>(ParentTablesOffset); - for (int z = 0; z < ParentTables->size(); ++z) + for (int z = 0; z < ParentTables->size(); z++) { auto ParentTable = ParentTables->At(z); @@ -598,7 +617,7 @@ std::vector PickLootDrops(FName TierGroupName, int WorldLevel, int For Table->AddToRoot(); LOG_INFO(LogDev, "[{}] LP {}", i, Table->GetFullName()); - } + } } if (!Addresses::LoadAsset) @@ -649,13 +668,13 @@ std::vector PickLootDrops(FName TierGroupName, int WorldLevel, int For } } - + if (LTDTables.size() <= 0 || LPTables.size() <= 0) { LOG_WARN(LogLoot, "Empty tables! ({} {})", LTDTables.size(), LPTables.size()); return LootDrops; } - + FName LootTierRowName; auto ChosenRowLootTierData = PickLootTierData(LTDTables, TierGroupName, ForcedLootTier, &LootTierRowName); @@ -685,11 +704,11 @@ std::vector PickLootDrops(FName TierGroupName, int WorldLevel, int For } else { - NumberLootDrops = (int)(float)((float)(NumLootPackageDrops + NumLootPackageDrops) - 0.5) >> 1; + NumberLootDrops = (int)(float)((float)(NumLootPackageDrops + NumLootPackageDrops) - 0.5f) >> 1; float v20 = NumLootPackageDrops - NumberLootDrops; - if (v20 > 0.0000099999997) + if (v20 > 0.0000099999997f) { - NumberLootDrops += v20 >= (rand() * 0.000030518509); + NumberLootDrops += v20 >= (rand() * 0.000030518509f); } } } diff --git a/Project Reboot 3.0/FortLootPackage.h b/Project Reboot 3.0/FortLootPackage.h index 5101444..a43af74 100644 --- a/Project Reboot 3.0/FortLootPackage.h +++ b/Project Reboot 3.0/FortLootPackage.h @@ -141,10 +141,10 @@ static inline float RandomFloatForLoot(float AllWeightsSum) } template -FORCEINLINE static ValueType PickWeightedElement(const std::map& Elements, +FORCEINLINE static ValueType PickWeightedElement(const std::map& Elements, std::function GetWeightFn, - std::function RandomFloatGenerator = RandomFloatForLoot, - float TotalWeightParam = -1, bool bCheckIfWeightIsZero = false, int RandMultiplier = 1, KeyType* OutName = nullptr, bool bPrint = false, bool bKeepGoingUntilWeGetValue = false, float AHHH = 1) + std::function RandomFloatGenerator = RandomFloatForLoot, + float TotalWeightParam = -1, bool bCheckIfWeightIsZero = false, int RandMultiplier = 1, KeyType* OutName = nullptr, bool bPrint = false, bool bKeepGoingUntilWeGetValue = false) { float TotalWeight = TotalWeightParam; @@ -158,14 +158,15 @@ FORCEINLINE static ValueType PickWeightedElement(const std::map("/Script/FortniteGame.FortPlayerControllerAthena.ClientEquipItem") ? FindObject("/Script/FortniteGame.FortPlayerControllerAthena.ClientEquipItem") : FindObject("/Script/FortniteGame.FortPlayerController.ClientEquipItem"); + static auto ClientEquipItemFn = FindObject(L"/Script/FortniteGame.FortPlayerControllerAthena.ClientEquipItem") + ? FindObject(L"/Script/FortniteGame.FortPlayerControllerAthena.ClientEquipItem") + : FindObject(L"/Script/FortniteGame.FortPlayerController.ClientEquipItem"); if (ClientEquipItemFn) { @@ -920,7 +922,9 @@ AActor* AFortPlayerController::SpawnToyInstanceHook(UObject* Context, FFrame* St if (!ToyClass) return nullptr; - auto NewToy = GetWorld()->SpawnActor(ToyClass, SpawnPosition, CreateSpawnParameters(ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn, false, PlayerController)); + auto Params = CreateSpawnParameters(ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn, false, PlayerController); + auto NewToy = GetWorld()->SpawnActor(ToyClass, SpawnPosition, Params); + // free(Params); // ? static auto ActiveToyInstancesOffset = PlayerController->GetOffset("ActiveToyInstances"); auto& ActiveToyInstances = PlayerController->Get>(ActiveToyInstancesOffset); @@ -993,7 +997,9 @@ void AFortPlayerController::ServerAttemptInventoryDropHook(AFortPlayerController static auto DropBehaviorOffset = ItemDefinition->GetOffset("DropBehavior", false); - if (!ItemDefinition->ShouldIgnoreRespawningOnDrop() && (DropBehaviorOffset != -1 ? ItemDefinition->GetDropBehavior() != EWorldItemDropBehavior::DestroyOnDrop : true)) + EWorldItemDropBehavior DropBehavior = DropBehaviorOffset != -1 ? ItemDefinition->GetDropBehavior() : EWorldItemDropBehavior::EWorldItemDropBehavior_MAX; + + if (!ItemDefinition->ShouldIgnoreRespawningOnDrop() && DropBehavior != EWorldItemDropBehavior::DestroyOnDrop) { PickupCreateData CreateData; CreateData.ItemEntry = ReplicatedEntry; @@ -1013,7 +1019,7 @@ void AFortPlayerController::ServerAttemptInventoryDropHook(AFortPlayerController bool bShouldUpdate = false; - if (!WorldInventory->RemoveItem(ItemGuid, &bShouldUpdate, Count, true)) + if (!WorldInventory->RemoveItem(ItemGuid, &bShouldUpdate, Count, true, DropBehavior == EWorldItemDropBehavior::DropAsPickupDestroyOnEmpty)) return; if (bShouldUpdate) @@ -1171,28 +1177,23 @@ uint8 ToDeathCause(const FGameplayTagContainer& TagContainer, bool bWasDBNO = fa return sub_7FF7AB499410(TagContainer, bWasDBNO); } -std::vector PlayerControllersDead; // make atomic? -// std::array, 100> PlayerControllersDead; -std::atomic numValidElements(0); - -DWORD WINAPI SpectateThread(LPVOID) +DWORD WINAPI SpectateThread(LPVOID PC) { - while (1) - { - for (auto PC : PlayerControllersDead) - // for (int i = 0; i < PlayerControllersDead.size(); ++i) - { - // auto PC = PlayerControllersDead.at(i).load(); + auto PlayerController = (UObject*)PC; - static auto SpectateOnDeathFn = FindObject(L"/Script/FortniteGame.FortPlayerControllerZone.SpectateOnDeath") ? - FindObject(L"/Script/FortniteGame.FortPlayerControllerZone.SpectateOnDeath") : - FindObject(L"/Script/FortniteGame.FortPlayerControllerAthena.SpectateOnDeath"); + if (!PlayerController->IsValidLowLevel()) + return 0; - PC->ProcessEvent(SpectateOnDeathFn); - } + auto SpectatingPC = Cast(PlayerController); - Sleep(4000); - } + if (!SpectatingPC) + return 0; + + Sleep(3000); + + LOG_INFO(LogDev, "bugha!"); + + SpectatingPC->SpectateOnDeath(); return 0; } @@ -1434,110 +1435,98 @@ void AFortPlayerController::ClientOnPawnDiedHook(AFortPlayerController* PlayerCo LOG_INFO(LogDev, "PlayersLeft: {} IsDBNO: {}", GameState->GetPlayersLeft(), DeadPawn->IsDBNO()); - if (bHandleDeath && !DeadPawn->IsDBNO()) + if (!DeadPawn->IsDBNO()) { - if (Fortnite_Version > 1.8 || Fortnite_Version == 1.11) + if (bHandleDeath) { - static void (*RemoveFromAlivePlayers)(AFortGameModeAthena * GameMode, AFortPlayerController * PlayerController, APlayerState * PlayerState, APawn * FinisherPawn, - UFortWeaponItemDefinition * FinishingWeapon, uint8_t DeathCause, char a7) - = decltype(RemoveFromAlivePlayers)(Addresses::RemoveFromAlivePlayers); - - AActor* DamageCauser = *(AActor**)(__int64(DeathReport) + MemberOffsets::DeathReport::DamageCauser); - UFortWeaponItemDefinition* KillerWeaponDef = nullptr; - - static auto FortProjectileBaseClass = FindObject(L"/Script/FortniteGame.FortProjectileBase"); - - if (DamageCauser) + if (Fortnite_Version > 1.8 || Fortnite_Version == 1.11) { - if (DamageCauser->IsA(FortProjectileBaseClass)) + static void (*RemoveFromAlivePlayers)(AFortGameModeAthena * GameMode, AFortPlayerController * PlayerController, APlayerState * PlayerState, APawn * FinisherPawn, + UFortWeaponItemDefinition * FinishingWeapon, uint8_t DeathCause, char a7) + = decltype(RemoveFromAlivePlayers)(Addresses::RemoveFromAlivePlayers); + + AActor* DamageCauser = *(AActor**)(__int64(DeathReport) + MemberOffsets::DeathReport::DamageCauser); + UFortWeaponItemDefinition* KillerWeaponDef = nullptr; + + static auto FortProjectileBaseClass = FindObject(L"/Script/FortniteGame.FortProjectileBase"); + + if (DamageCauser) { - auto Owner = Cast(DamageCauser->GetOwner()); - KillerWeaponDef = Owner->IsValidLowLevel() ? Owner->GetWeaponData() : nullptr; // I just added the IsValidLowLevel check because what if the weapon destroys? - } - if (auto Weapon = Cast(DamageCauser)) - { - KillerWeaponDef = Weapon->GetWeaponData(); - } - } - - RemoveFromAlivePlayers(GameMode, PlayerController, KillerPlayerState == DeadPlayerState ? nullptr : KillerPlayerState, KillerPawn, KillerWeaponDef, DeathCause, 0); - - /* - - 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); - - if (DeadControllerAthena && FAthenaMatchTeamStats::GetStruct()) - { - auto MatchReport = DeadControllerAthena->GetMatchReport(); - - LOG_INFO(LogDev, "MatchReport: {}", __int64(MatchReport)); - - if (MatchReport) - { - MatchReport->GetTeamStats()->GetPlace() = DeadPlayerState->GetPlace(); - MatchReport->GetTeamStats()->GetTotalPlayers() = AmountOfPlayersWhenBusStart; // hmm - MatchReport->HasTeamStats() = true; - - DeadControllerAthena->ClientSendTeamStatsForPlayer(MatchReport->GetTeamStats()); - } - } - - */ - - LOG_INFO(LogDev, "Removed!"); - - if (Fortnite_Version < 6) // Spectating - { - static auto bAllowSpectateAfterDeathOffset = GameMode->GetOffset("bAllowSpectateAfterDeath"); - - bool bAllowSpectate = false; // GameMode->Get(bAllowSpectateAfterDeathOffset); - - LOG_INFO(LogDev, "bAllowSpectate: {}", bAllowSpectate); - - if (bAllowSpectate) - { - LOG_INFO(LogDev, "Starting Spectating!"); - - static auto PlayerToSpectateOnDeathOffset = PlayerController->GetOffset("PlayerToSpectateOnDeath"); - PlayerController->Get(PlayerToSpectateOnDeathOffset) = KillerPawn; - - PlayerControllersDead.push_back(PlayerController); - - /* if (numValidElements < PlayerControllersDead.size()) + if (DamageCauser->IsA(FortProjectileBaseClass)) { - PlayerControllersDead[numValidElements].store(PlayerController); - numValidElements.fetch_add(1); - } */ - - static bool bCreatedThread = false; - - if (!bCreatedThread) + auto Owner = Cast(DamageCauser->GetOwner()); + KillerWeaponDef = Owner->IsValidLowLevel() ? Owner->GetWeaponData() : nullptr; // I just added the IsValidLowLevel check because what if the weapon destroys (idk)? + } + if (auto Weapon = Cast(DamageCauser)) { - bCreatedThread = true; - - CreateThread(0, 0, SpectateThread, 0, 0, 0); + KillerWeaponDef = Weapon->GetWeaponData(); } } + + RemoveFromAlivePlayers(GameMode, PlayerController, KillerPlayerState == DeadPlayerState ? nullptr : KillerPlayerState, KillerPawn, KillerWeaponDef, DeathCause, 0); + + /* + + 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); + + if (DeadControllerAthena && FAthenaMatchTeamStats::GetStruct()) + { + auto MatchReport = DeadControllerAthena->GetMatchReport(); + + LOG_INFO(LogDev, "MatchReport: {}", __int64(MatchReport)); + + if (MatchReport) + { + MatchReport->GetTeamStats()->GetPlace() = DeadPlayerState->GetPlace(); + MatchReport->GetTeamStats()->GetTotalPlayers() = AmountOfPlayersWhenBusStart; // hmm + MatchReport->HasTeamStats() = true; + + DeadControllerAthena->ClientSendTeamStatsForPlayer(MatchReport->GetTeamStats()); + } + } + + */ + + LOG_INFO(LogDev, "Removed!"); } + + // LOG_INFO(LogDev, "KillerPlayerState->Place: {}", KillerPlayerState ? KillerPlayerState->GetPlace() : -1); } - // LOG_INFO(LogDev, "KillerPlayerState->Place: {}", KillerPlayerState ? KillerPlayerState->GetPlace() : -1); + if (Fortnite_Version < 6) // Spectating (is this the actual build or is it like 6.10 when they added it auto). + { + static auto bAllowSpectateAfterDeathOffset = GameMode->GetOffset("bAllowSpectateAfterDeath"); + + bool bAllowSpectate = GameMode->Get(bAllowSpectateAfterDeathOffset); + + LOG_INFO(LogDev, "bAllowSpectate: {}", bAllowSpectate); + + if (bAllowSpectate) + { + LOG_INFO(LogDev, "Starting Spectating!"); + + static auto PlayerToSpectateOnDeathOffset = PlayerController->GetOffset("PlayerToSpectateOnDeath"); + PlayerController->Get(PlayerToSpectateOnDeathOffset) = KillerPawn; + + CreateThread(0, 0, SpectateThread, (LPVOID)PlayerController, 0, 0); + } + } } if (IsRestartingSupported() && Globals::bAutoRestart && !bIsInAutoRestart) diff --git a/Project Reboot 3.0/FortPlayerControllerAthena.h b/Project Reboot 3.0/FortPlayerControllerAthena.h index 871696b..842bc68 100644 --- a/Project Reboot 3.0/FortPlayerControllerAthena.h +++ b/Project Reboot 3.0/FortPlayerControllerAthena.h @@ -141,6 +141,15 @@ public: static inline void (*StartGhostModeOriginal)(UObject* Context, FFrame* Stack, void* Ret); static inline void (*EndGhostModeOriginal)(AFortPlayerControllerAthena* PlayerController); + void SpectateOnDeath() // actually in zone + { + static auto SpectateOnDeathFn = FindObject(L"/Script/FortniteGame.FortPlayerControllerZone.SpectateOnDeath") ? + FindObject(L"/Script/FortniteGame.FortPlayerControllerZone.SpectateOnDeath") : + FindObject(L"/Script/FortniteGame.FortPlayerControllerAthena.SpectateOnDeath"); + + this->ProcessEvent(SpectateOnDeathFn); + } + class UAthenaResurrectionComponent*& GetResurrectionComponent() { static auto ResurrectionComponentOffset = GetOffset("ResurrectionComponent"); diff --git a/Project Reboot 3.0/addresses.cpp b/Project Reboot 3.0/addresses.cpp index 559e8fa..0abdded 100644 --- a/Project Reboot 3.0/addresses.cpp +++ b/Project Reboot 3.0/addresses.cpp @@ -312,6 +312,9 @@ void Addresses::FindAll() LOG_INFO(LogDev, "Finding AddToAlivePlayers"); Addresses::AddToAlivePlayers = FindAddToAlivePlayers(); + LOG_INFO(LogDev, "Finding StartAircraftPhase"); + Addresses::StartAircraftPhase = FindStartAircraftPhase(); + // LOG_INFO(LogDev, "Finding GetSessionInterface"); // Addresses::GetSessionInterface = FindGetSessionInterface(); @@ -392,6 +395,7 @@ void Addresses::Print() LOG_INFO(LogDev, "FinishResurrection: 0x{:x}", FinishResurrection - Base); LOG_INFO(LogDev, "AddToAlivePlayers: 0x{:x}", AddToAlivePlayers - Base); LOG_INFO(LogDev, "GetSessionInterface: 0x{:x}", GetSessionInterface - Base); + LOG_INFO(LogDev, "StartAircraftPhase: 0x{:x}", StartAircraftPhase - Base); } void Offsets::FindAll() diff --git a/Project Reboot 3.0/addresses.h b/Project Reboot 3.0/addresses.h index 6f057a1..d5b6879 100644 --- a/Project Reboot 3.0/addresses.h +++ b/Project Reboot 3.0/addresses.h @@ -76,7 +76,8 @@ namespace Addresses extern inline uint64 AddToAlivePlayers = 0; extern inline uint64 GameSessionPatch = 0; extern inline uint64 GetSessionInterface = 0; // Matchmaking - + extern inline uint64 StartAircraftPhase = 0; + void SetupVersion(); // Finds Engine Version void FindAll(); void Print(); diff --git a/Project Reboot 3.0/finder.cpp b/Project Reboot 3.0/finder.cpp index 879c0d8..ac42fd7 100644 --- a/Project Reboot 3.0/finder.cpp +++ b/Project Reboot 3.0/finder.cpp @@ -3,6 +3,47 @@ #include "reboot.h" #include "FortPlayerControllerAthena.h" +uint64 FindStartAircraftPhase() +{ + if (Engine_Version < 427) // they scuf it + { + auto strRef = Memcury::Scanner::FindStringRef(L"STARTAIRCRAFT").Get(); + + if (!strRef) + return 0; + + int NumCalls = 0; + + for (int i = 0; i < 150; i++) + { + if (*(uint8_t*)(strRef + i) == 0xE8) + { + LOG_INFO(LogDev, "Found call 0x{:x}", __int64(strRef + i) - __int64(GetModuleHandleW(0))); + NumCalls++; + + if (NumCalls == 2) // First is the str compare ig + { + return Memcury::Scanner(strRef + i).RelativeOffset(1).Get(); + } + } + } + } + else + { + auto StatAddress = Memcury::Scanner::FindStringRef(L"STAT_StartAircraftPhase").Get(); + + for (int i = 0; i < 1000; i++) + { + if (*(uint8_t*)(uint8_t*)(StatAddress - i) == 0x48 && *(uint8_t*)(uint8_t*)(StatAddress - i + 1) == 0x8B && *(uint8_t*)(uint8_t*)(StatAddress - i + 2) == 0xC4) + { + return StatAddress - i; + } + } + } + + return 0; +} + uint64 FindGetSessionInterface() { auto strRef = Memcury::Scanner::FindStringRef(L"OnDestroyReservedSessionComplete %s bSuccess: %d", true, 0, Fortnite_Version >= 19).Get(); diff --git a/Project Reboot 3.0/finder.h b/Project Reboot 3.0/finder.h index af647ad..d59e684 100644 --- a/Project Reboot 3.0/finder.h +++ b/Project Reboot 3.0/finder.h @@ -495,6 +495,7 @@ static inline uint64 FindGetMaxTickRate() // UEngine::getmaxtickrate // return FindBytes(stringRef, Fortnite_Version <= 4.1 ? std::vector{ 0x40, 0x53 } : std::vector{ 0x48, 0x89, 0x5C }, 1000, 0, true); } +uint64 FindStartAircraftPhase(); uint64 FindGetSessionInterface(); uint64 FindGetPlayerViewpoint(); uint64 ApplyGameSessionPatch(); diff --git a/Project Reboot 3.0/gui.h b/Project Reboot 3.0/gui.h index a56f749..43a26bd 100644 --- a/Project Reboot 3.0/gui.h +++ b/Project Reboot 3.0/gui.h @@ -104,7 +104,7 @@ static inline LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM static inline void SetIsLategame(bool Value) { Globals::bLateGame.store(Value); - StartingShield = 100; + StartingShield = Value ? 100 : 0; } static inline void Restart() // todo move? @@ -528,7 +528,7 @@ static inline DWORD WINAPI LateGameThread(LPVOID) return Aircrafts; }; - UKismetSystemLibrary::ExecuteConsoleCommand(GetWorld(), L"startaircraft", nullptr); + GameMode->StartAircraftPhase(); while (GetAircrafts().size() <= 0) { @@ -795,7 +795,7 @@ static inline void MainUI() } else { - UKismetSystemLibrary::ExecuteConsoleCommand(GetWorld(), L"startaircraft", nullptr); + GameMode->StartAircraftPhase(); } } } @@ -1086,9 +1086,10 @@ static inline void MainUI() { auto CurrentBuildingSMActor = (ABuildingSMActor*)AllBuildingSMActors.at(i); - if (!CurrentBuildingSMActor->IsPlayerPlaced()) continue; + if (CurrentBuildingSMActor->IsDestroyed() || CurrentBuildingSMActor->IsActorBeingDestroyed() || !CurrentBuildingSMActor->IsPlayerPlaced()) continue; - CurrentBuildingSMActor->K2_DestroyActor(); + CurrentBuildingSMActor->SilentDie(); + // CurrentBuildingSMActor->K2_DestroyActor(); } AllBuildingSMActors.Free(); @@ -1137,9 +1138,12 @@ static inline void MainUI() static auto DefaultGliderRedeployCanRedeployOffset = FindOffsetStruct("/Script/FortniteGame.FortGameStateAthena", "DefaultGliderRedeployCanRedeploy", false); static auto DefaultParachuteDeployTraceForGroundDistanceOffset = GameState->GetOffset("DefaultParachuteDeployTraceForGroundDistance", false); - if (DefaultParachuteDeployTraceForGroundDistanceOffset != -1) + if (Globals::bStartedListening) // it resets accordingly to ProHenis b4 this { - ImGui::InputFloat("Automatic Parachute Pullout Distance", GameState->GetPtr(DefaultParachuteDeployTraceForGroundDistanceOffset)); + if (DefaultParachuteDeployTraceForGroundDistanceOffset != -1) + { + ImGui::InputFloat("Automatic Parachute Pullout Distance", GameState->GetPtr(DefaultParachuteDeployTraceForGroundDistanceOffset)); + } } if (DefaultGliderRedeployCanRedeployOffset != -1) diff --git a/Project Reboot 3.0/inc.h b/Project Reboot 3.0/inc.h index 75d0c38..819a9bd 100644 --- a/Project Reboot 3.0/inc.h +++ b/Project Reboot 3.0/inc.h @@ -20,7 +20,7 @@ extern inline int Engine_Version = 0; // For example, 420, 421, etc. // Prevent extern inline double Fortnite_Version = 0; // For example, 4.1, 6.21, etc. // Prevent using this when possible. extern inline int Fortnite_CL = 0; -#define PROD // this doesnt do anything besides remove processeventhook and some assert stuff +// #define PROD // this doesnt do anything besides remove processeventhook and some assert stuff struct PlaceholderBitfield {