diff --git a/Project Reboot 3.0/Array.h b/Project Reboot 3.0/Array.h index b5b1200..35f1073 100644 --- a/Project Reboot 3.0/Array.h +++ b/Project Reboot 3.0/Array.h @@ -37,6 +37,8 @@ public: inline InElementType& at(int i, size_t Size = sizeof(InElementType)) const { return *(InElementType*)(__int64(Data) + (static_cast(Size) * i)); } inline InElementType* AtPtr(int i, size_t Size = sizeof(InElementType)) const { return (InElementType*)(__int64(Data) + (static_cast(Size) * i)); } + bool IsValidIndex(int i) { return i > 0 && i < ArrayNum; } + ElementAllocatorType& GetData() const { return Data; } ElementAllocatorType& GetData() { return Data; } diff --git a/Project Reboot 3.0/BGA.h b/Project Reboot 3.0/BGA.h index 3a042e1..18382ab 100644 --- a/Project Reboot 3.0/BGA.h +++ b/Project Reboot 3.0/BGA.h @@ -43,7 +43,7 @@ static inline void SpawnBGAs() // hahah not "proper", there's a function that we static auto SpawnLootTierGroupOffset = BGAConsumableSpawner->GetOffset("SpawnLootTierGroup"); auto& SpawnLootTierGroup = BGAConsumableSpawner->Get(SpawnLootTierGroupOffset); - auto LootDrops = PickLootDrops(SpawnLootTierGroup); + auto LootDrops = PickLootDrops(SpawnLootTierGroup, GameState->GetWorldLevel()); for (int z = 0; z < LootDrops.size(); z++) { @@ -63,11 +63,7 @@ static inline void SpawnBGAs() // hahah not "proper", there's a function that we bool bDeferConstruction = true; // hm? - FActorSpawnParameters SpawnParameters{}; - // SpawnParameters.ObjectFlags = RF_Transactional; // idk fortnite does this i think // i think its acutally suppsoed to be |= RF_Transient - SpawnParameters.bDeferConstruction = bDeferConstruction; - - auto ConsumableActor = GetWorld()->SpawnActor(StrongConsumableClass, SpawnTransform, SpawnParameters); + auto ConsumableActor = GetWorld()->SpawnActor(StrongConsumableClass, SpawnTransform, CreateSpawnParameters(ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn, bDeferConstruction)); if (ConsumableActor) { diff --git a/Project Reboot 3.0/BuildingContainer.cpp b/Project Reboot 3.0/BuildingContainer.cpp index 6d2bfad..d0ff6d1 100644 --- a/Project Reboot 3.0/BuildingContainer.cpp +++ b/Project Reboot 3.0/BuildingContainer.cpp @@ -14,7 +14,9 @@ bool ABuildingContainer::SpawnLoot(AFortPawn* Pawn) // LOG_INFO(LogInteraction, "RedirectedLootTier: {}", RedirectedLootTier.ToString()); - auto LootDrops = PickLootDrops(RedirectedLootTier, -1, bDebugPrintLooting); + auto GameState = Cast(GetWorld()->GetGameState()); + + auto LootDrops = PickLootDrops(RedirectedLootTier, GameState->GetWorldLevel(), -1, bDebugPrintLooting); // LOG_INFO(LogInteraction, "LootDrops.size(): {}", LootDrops.size()); @@ -25,7 +27,7 @@ bool ABuildingContainer::SpawnLoot(AFortPawn* Pawn) PickupCreateData CreateData; CreateData.bToss = true; // CreateData.PawnOwner = Pawn; - CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(lootDrop->GetItemDefinition(), lootDrop->GetCount(), lootDrop->GetLoadedAmmo()); + CreateData.ItemEntry = lootDrop.ItemEntry; CreateData.SpawnLocation = LocationToSpawnLoot; CreateData.SourceType = EFortPickupSourceTypeFlag::GetContainerValue(); CreateData.bRandomRotation = true; diff --git a/Project Reboot 3.0/Controller.h b/Project Reboot 3.0/Controller.h index 5dd5bec..52a1422 100644 --- a/Project Reboot 3.0/Controller.h +++ b/Project Reboot 3.0/Controller.h @@ -8,6 +8,12 @@ public: AActor* GetViewTarget(); void Possess(class APawn* Pawn); + FName& GetStateName() + { + static auto StateNameOffset = GetOffset("StateName"); + return Get(StateNameOffset); + } + class APawn*& GetPawn() { static auto PawnOffset = this->GetOffset("Pawn"); diff --git a/Project Reboot 3.0/DataTable.h b/Project Reboot 3.0/DataTable.h index 3f612e6..06007e5 100644 --- a/Project Reboot 3.0/DataTable.h +++ b/Project Reboot 3.0/DataTable.h @@ -1,9 +1,15 @@ #pragma once #include "Object.h" +#include "reboot.h" #include "Map.h" +struct FTableRowBase +{ + unsigned char UnknownData00[0x8]; // this is actually structural padding +}; + class UDataTable : public UObject { public: @@ -17,7 +23,7 @@ public: static UClass* StaticClass() { - static auto Class = FindObject("/Script/Engine.DataTable"); + static auto Class = FindObject(L"/Script/Engine.DataTable"); return Class; } }; diff --git a/Project Reboot 3.0/FortAthenaMapInfo.cpp b/Project Reboot 3.0/FortAthenaMapInfo.cpp index 6013639..e19bc0b 100644 --- a/Project Reboot 3.0/FortAthenaMapInfo.cpp +++ b/Project Reboot 3.0/FortAthenaMapInfo.cpp @@ -63,11 +63,8 @@ void AFortAthenaMapInfo::SpawnLlamas() InitialSpawnTransform.Rotation = RandomYawRotator.Quaternion(); InitialSpawnTransform.Scale3D = FVector(1, 1, 1); - FActorSpawnParameters SpawnParameters{}; - SpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn; - SpawnParameters.bDeferConstruction = true; - - auto LlamaStart = GetWorld()->SpawnActor(GetLlamaClass(), InitialSpawnTransform, SpawnParameters); + auto LlamaStart = GetWorld()->SpawnActor(GetLlamaClass(), InitialSpawnTransform, + CreateSpawnParameters(ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn, true)); // LOG_INFO(LogDev, "LlamaStart: {}", __int64(LlamaStart)); diff --git a/Project Reboot 3.0/FortAthenaSupplyDrop.cpp b/Project Reboot 3.0/FortAthenaSupplyDrop.cpp index 63abf29..5e8687f 100644 --- a/Project Reboot 3.0/FortAthenaSupplyDrop.cpp +++ b/Project Reboot 3.0/FortAthenaSupplyDrop.cpp @@ -1,8 +1,9 @@ #include "FortAthenaSupplyDrop.h" +#include "FortGameStateAthena.h" FVector AFortAthenaSupplyDrop::FindGroundLocationAt(FVector InLocation) { - static auto FindGroundLocationAtFn = FindObject("/Script/FortniteGame.FortAthenaSupplyDrop.FindGroundLocationAt"); + static auto FindGroundLocationAtFn = FindObject(L"/Script/FortniteGame.FortAthenaSupplyDrop.FindGroundLocationAt"); struct { @@ -44,12 +45,15 @@ AFortPickup* AFortAthenaSupplyDrop::SpawnGameModePickupHook(UObject* Context, FF LOG_INFO(LogDev, "Spawning GameModePickup with ItemDefinition: {}", ItemDefinition->GetFullName()); + auto GameState = Cast(GetWorld()->GetGameState()); + PickupCreateData CreateData; - CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(ItemDefinition, NumberToSpawn, -1); + CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(ItemDefinition, NumberToSpawn, -1, MAX_DURABILITY, ItemDefinition->GetFinalLevel(GameState->GetWorldLevel())); CreateData.SpawnLocation = Position; CreateData.PawnOwner = TriggeringPawn; CreateData.Source = EFortPickupSpawnSource::GetSupplyDropValue(); CreateData.OverrideClass = PickupClass; + CreateData.bShouldFreeItemEntryWhenDeconstructed = true; *Ret = AFortPickup::SpawnPickup(CreateData); return *Ret; @@ -74,8 +78,10 @@ AFortPickup* AFortAthenaSupplyDrop::SpawnPickupHook(UObject* Context, FFrame& St if (!ItemDefinition) return nullptr; + auto GameState = Cast(GetWorld()->GetGameState()); + PickupCreateData CreateData; - CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(ItemDefinition, NumberToSpawn, -1); + CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(ItemDefinition, NumberToSpawn, -1, MAX_DURABILITY, ItemDefinition->GetFinalLevel(GameState->GetWorldLevel())); CreateData.SpawnLocation = Position; CreateData.PawnOwner = TriggeringPawn; CreateData.Source = EFortPickupSpawnSource::GetSupplyDropValue(); diff --git a/Project Reboot 3.0/FortGameModeAthena.cpp b/Project Reboot 3.0/FortGameModeAthena.cpp index cda3355..406a0fd 100644 --- a/Project Reboot 3.0/FortGameModeAthena.cpp +++ b/Project Reboot 3.0/FortGameModeAthena.cpp @@ -652,6 +652,8 @@ bool AFortGameModeAthena::Athena_ReadyToStartMatchHook(AFortGameModeAthena* Game GetWorld()->Listen(); + LOG_INFO(LogNet, "WorldLevel {}", GameState->GetWorldLevel()); + if (auto TeamsArrayContainer = GameState->GetTeamsArrayContainer()) { TeamsArrayContainer->TeamIndexesArray.Free(); @@ -889,6 +891,8 @@ int AFortGameModeAthena::Athena_PickTeamHook(AFortGameModeAthena* GameMode, uint bShouldSpreadTeams = bIsLargeTeamGame; } + // bShouldSpreadTeams = true; + static int CurrentTeamMembers = 0; // bad static int Current = DefaultFirstTeam; static int NextTeamIndex = DefaultFirstTeam; @@ -986,11 +990,14 @@ int AFortGameModeAthena::Athena_PickTeamHook(AFortGameModeAthena* GameMode, uint { if (auto TeamsArrayContainer = GameState->GetTeamsArrayContainer()) { - auto& TeamArray = TeamsArrayContainer->TeamsArray.at(NextTeamIndex); + TArray>* TeamArray = TeamsArrayContainer->TeamsArray.IsValidIndex(NextTeamIndex) ? TeamsArrayContainer->TeamsArray.AtPtr(NextTeamIndex) : nullptr; LOG_INFO(LogDev, "TeamsArrayContainer->TeamsArray.Num(): {}", TeamsArrayContainer->TeamsArray.Num()); - LOG_INFO(LogDev, "TeamArray.Num(): {}", TeamArray.Num()); - TeamArray.Add(WeakPlayerState); + if (TeamArray) + { + LOG_INFO(LogDev, "TeamArray.Num(): {}", TeamArray->Num()); + TeamArray->Add(WeakPlayerState); + } } } @@ -1130,13 +1137,13 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena auto Location = CurrentActor->GetActorLocation(); Location.Z += UpZ; - std::vector LootDrops = PickLootDrops(SpawnIslandTierGroup, -1, bPrintWarmup); + std::vector LootDrops = PickLootDrops(SpawnIslandTierGroup, GameState->GetWorldLevel(), -1, bPrintWarmup); for (auto& LootDrop : LootDrops) { PickupCreateData CreateData; CreateData.bToss = true; - CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(LootDrop->GetItemDefinition(), LootDrop->GetCount(), LootDrop->GetLoadedAmmo()); + CreateData.ItemEntry = LootDrop.ItemEntry; CreateData.SpawnLocation = Location; CreateData.SourceType = SpawnFlag; CreateData.bRandomRotation = true; @@ -1160,13 +1167,13 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena auto Location = CurrentActor->GetActorLocation(); Location.Z += UpZ; - std::vector LootDrops = PickLootDrops(BRIslandTierGroup, -1, bPrint); + std::vector LootDrops = PickLootDrops(BRIslandTierGroup, GameState->GetWorldLevel(), -1, bPrint); for (auto& LootDrop : LootDrops) { PickupCreateData CreateData; CreateData.bToss = true; - CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(LootDrop->GetItemDefinition(), LootDrop->GetCount(), LootDrop->GetLoadedAmmo()); + CreateData.ItemEntry = LootDrop.ItemEntry; CreateData.SpawnLocation = Location; CreateData.SourceType = SpawnFlag; CreateData.bRandomRotation = true; diff --git a/Project Reboot 3.0/FortGameStateAthena.h b/Project Reboot 3.0/FortGameStateAthena.h index 7002921..57a580b 100644 --- a/Project Reboot 3.0/FortGameStateAthena.h +++ b/Project Reboot 3.0/FortGameStateAthena.h @@ -105,6 +105,12 @@ public: return this->Get(bSafeZonePausedOffset); } + int& GetWorldLevel() // Actually in AFortGameState + { + static auto WorldLevelOffset = GetOffset("WorldLevel"); + return Get(WorldLevelOffset); + } + EAthenaGamePhase& GetGamePhase() { static auto GamePhaseOffset = GetOffset("GamePhase"); diff --git a/Project Reboot 3.0/FortInventory.cpp b/Project Reboot 3.0/FortInventory.cpp index 5817c21..ab7da44 100644 --- a/Project Reboot 3.0/FortInventory.cpp +++ b/Project Reboot 3.0/FortInventory.cpp @@ -111,7 +111,7 @@ std::pair, std::vector> AFortInventory::AddI return std::make_pair(NewItemInstances, ModifiedItemInstances); PickupCreateData CreateData; - CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(ItemDefinition, Count, -1); + CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(ItemDefinition, Count, -1, MAX_DURABILITY/* level */); CreateData.SpawnLocation = Pawn->GetActorLocation(); CreateData.PawnOwner = Cast(Pawn); CreateData.SourceType = EFortPickupSourceTypeFlag::GetPlayerValue(); diff --git a/Project Reboot 3.0/FortItem.cpp b/Project Reboot 3.0/FortItem.cpp index c2b34fa..49aa1ab 100644 --- a/Project Reboot 3.0/FortItem.cpp +++ b/Project Reboot 3.0/FortItem.cpp @@ -25,7 +25,7 @@ void FFortItemEntry::SetStateValue(EFortItemEntryState StateType, int IntValue) // ItemEntry->bIsDirty = true; } -FFortItemEntry* FFortItemEntry::MakeItemEntry(UFortItemDefinition* ItemDefinition, int Count, int LoadedAmmo, float Durability) +FFortItemEntry* FFortItemEntry::MakeItemEntry(UFortItemDefinition* ItemDefinition, int Count, int LoadedAmmo, float Durability, int Level) { auto Entry = Alloc(GetStructSize(), bUseFMemoryRealloc); @@ -50,6 +50,7 @@ FFortItemEntry* FFortItemEntry::MakeItemEntry(UFortItemDefinition* ItemDefinitio Entry->GetDurability() = Durability; Entry->GetGameplayAbilitySpecHandle() = FGameplayAbilitySpecHandle(-1); Entry->GetParentInventory().ObjectIndex = -1; + Entry->GetLevel() = Level; // We want to add StateValues.Add(DurabilityInitialized); orwnatefc erwgearf yk // CoCreateGuid((GUID*)&Entry->GetItemGuid()); // Entry->DoesUpdateStatsOnCollection() = true; // I think fortnite does this? diff --git a/Project Reboot 3.0/FortItem.h b/Project Reboot 3.0/FortItem.h index 718ea79..a10eaa3 100644 --- a/Project Reboot 3.0/FortItem.h +++ b/Project Reboot 3.0/FortItem.h @@ -30,6 +30,8 @@ enum class EFortItemEntryState : uint8_t // this changes but its fineee EFortItemEntryState_MAX = 15 }; +#define MAX_DURABILITY 0x3F800000 + struct FFortItemEntryStateValue { static UStruct* GetStruct() @@ -189,7 +191,7 @@ struct FFortItemEntry : FFastArraySerializerItem return StructSize; } - static FFortItemEntry* MakeItemEntry(UFortItemDefinition* ItemDefinition, int Count = 1, int LoadedAmmo = 0, float Durability = 0x3F800000); + static FFortItemEntry* MakeItemEntry(UFortItemDefinition* ItemDefinition, int Count = 1, int LoadedAmmo = 0, float Durability = MAX_DURABILITY, int Level = 0); // We need to find a better way for below... Especially since we can't do either method for season 5 or 6. diff --git a/Project Reboot 3.0/FortKismetLibrary.cpp b/Project Reboot 3.0/FortKismetLibrary.cpp index 23ea462..a8ccee2 100644 --- a/Project Reboot 3.0/FortKismetLibrary.cpp +++ b/Project Reboot 3.0/FortKismetLibrary.cpp @@ -137,8 +137,10 @@ void UFortKismetLibrary::SpawnItemVariantPickupInWorldHook(UObject* Context, FFr LOG_INFO(LogDev, "{} {} {}", Position.X, Position.Y, Position.Z); + auto GameState = Cast(GetWorld()->GetGameState()); + PickupCreateData CreateData; - CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(ItemDefinition, ParamsPtr->GetNumberToSpawn(), -1); + CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(ItemDefinition, ParamsPtr->GetNumberToSpawn(), -1, MAX_DURABILITY, ItemDefinition->GetFinalLevel(GameState->GetWorldLevel())); CreateData.SourceType = ParamsPtr->GetSourceType(); CreateData.Source = ParamsPtr->GetSource(); CreateData.bShouldFreeItemEntryWhenDeconstructed = true; @@ -172,8 +174,10 @@ bool UFortKismetLibrary::SpawnInstancedPickupInWorldHook(UObject* Context, FFram Stack.StepCompiledIn(&bRandomRotation); Stack.StepCompiledIn(&bBlockedFromAutoPickup); + auto GameState = Cast(GetWorld()->GetGameState()); + PickupCreateData CreateData; - CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(ItemDefinition, NumberToSpawn, -1); + CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(ItemDefinition, NumberToSpawn, -1, MAX_DURABILITY, ItemDefinition->GetFinalLevel(GameState->GetWorldLevel())); CreateData.SpawnLocation = Position; CreateData.bToss = bToss; CreateData.bShouldFreeItemEntryWhenDeconstructed = true; @@ -226,8 +230,10 @@ void UFortKismetLibrary::CreateTossAmmoPickupForWeaponItemDefinitionAtLocationHo if (!AmmoDefinition) return CreateTossAmmoPickupForWeaponItemDefinitionAtLocationOriginal(Context, Stack, Ret); + auto GameState = Cast(GetWorld()->GetGameState()); + PickupCreateData CreateData; - CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(AmmoDefinition, Count, 0); + CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(AmmoDefinition, Count, 0, MAX_DURABILITY, AmmoDefinition->GetFinalLevel(GameState->GetWorldLevel())); CreateData.SourceType = SourceTypeFlag; CreateData.Source = SpawnSource; CreateData.SpawnLocation = Location; @@ -508,8 +514,10 @@ AFortPickup* UFortKismetLibrary::K2_SpawnPickupInWorldWithClassHook(UObject* Con LOG_INFO(LogDev, __FUNCTION__); + auto GameState = Cast(GetWorld()->GetGameState()); + PickupCreateData CreateData; - CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(ItemDefinition, NumberToSpawn, -1); + CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(ItemDefinition, NumberToSpawn, -1, MAX_DURABILITY, ItemDefinition->GetFinalLevel(GameState->GetWorldLevel())); CreateData.Source = Source; CreateData.SourceType = SourceType; CreateData.OverrideClass = PickupClass; @@ -591,8 +599,10 @@ AFortPickup* UFortKismetLibrary::K2_SpawnPickupInWorldHook(UObject* Context, FFr auto Pawn = OptionalOwnerPC ? OptionalOwnerPC->GetMyFortPawn() : nullptr; + auto GameState = Cast(GetWorld()->GetGameState()); + PickupCreateData CreateData; - CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(ItemDefinition, NumberToSpawn, -1); + CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(ItemDefinition, NumberToSpawn, -1, MAX_DURABILITY, GameState->GetWorldLevel()); CreateData.SpawnLocation = Position; CreateData.bToss = bToss; CreateData.bRandomRotation = bRandomRotation; @@ -628,9 +638,11 @@ bool UFortKismetLibrary::PickLootDropsHook(UObject* Context, FFrame& Stack, bool FFortItemEntry::FreeArrayOfEntries(OutLootToDropTempBuf); + auto GameState = Cast(GetWorld()->GetGameState()); + LOG_INFO(LogDev, "Picking loot for {}.", TierGroupName.ComparisonIndex.Value ? TierGroupName.ToString() : "InvalidName"); - auto LootDrops = PickLootDrops(TierGroupName, -1, true); + auto LootDrops = PickLootDrops(TierGroupName, GameState->GetWorldLevel(), -1, true); for (int i = 0; i < LootDrops.size(); i++) { diff --git a/Project Reboot 3.0/FortLootLevel.cpp b/Project Reboot 3.0/FortLootLevel.cpp new file mode 100644 index 0000000..2ab6794 --- /dev/null +++ b/Project Reboot 3.0/FortLootLevel.cpp @@ -0,0 +1,71 @@ +#include "FortLootLevel.h" +#include "FortWorldItemDefinition.h" + +int UFortLootLevel::GetItemLevel(const FDataTableCategoryHandle& LootLevelData, int WorldLevel) +{ + // OMG IM GONNA DIE + + // we should use GetRows but L + + auto DataTable = LootLevelData.DataTable; + + if (!DataTable) + return 0; + + if (!LootLevelData.ColumnName.ComparisonIndex.Value) + return 0; + + if (!LootLevelData.RowContents.ComparisonIndex.Value) + return 0; + + std::vector OurLootLevelDatas; + + for (auto& LootLevelDataPair : LootLevelData.DataTable->GetRowMap()) + { + if (LootLevelDataPair.Second->Category != LootLevelData.RowContents) + continue; + + OurLootLevelDatas.push_back(LootLevelDataPair.Second); + } + + if (OurLootLevelDatas.size() > 0) + { + int PickedIndex = -1; + int PickedLootLevel = 0; + + for (int i = 0; i < OurLootLevelDatas.size(); i++) + { + auto CurrentLootLevelData = OurLootLevelDatas.at(i); + + if (CurrentLootLevelData->LootLevel <= WorldLevel && CurrentLootLevelData->LootLevel > PickedLootLevel) + { + PickedLootLevel = CurrentLootLevelData->LootLevel; + PickedIndex = i; + } + } + + if (PickedIndex != -1) + { + auto PickedLootLevelData = OurLootLevelDatas.at(PickedIndex); + + const auto PickedMinItemLevel = PickedLootLevelData->MinItemLevel; + const auto PickedMaxItemLevel = PickedLootLevelData->MaxItemLevel; + auto v15 = PickedMaxItemLevel - PickedMinItemLevel; + + if (v15 + 1 <= 0) + { + v15 = 0; + } + else + { + auto v16 = (int)(float)((float)((float)rand() * 0.000030518509) * (float)(v15 + 1)); + if (v16 <= v15) + v15 = v16; + } + + return v15 + PickedMinItemLevel; + } + } + + return 0; +} \ No newline at end of file diff --git a/Project Reboot 3.0/FortLootLevel.h b/Project Reboot 3.0/FortLootLevel.h index 09a3d74..77b807e 100644 --- a/Project Reboot 3.0/FortLootLevel.h +++ b/Project Reboot 3.0/FortLootLevel.h @@ -4,8 +4,6 @@ class UFortLootLevel { - int GetItemLevel(FDataTableCategoryHandle LootLevelData, int WorldLevel) - { - return 0; - } +public: + static int GetItemLevel(const FDataTableCategoryHandle& LootLevelData, int WorldLevel); }; \ No newline at end of file diff --git a/Project Reboot 3.0/FortLootPackage.cpp b/Project Reboot 3.0/FortLootPackage.cpp index 84d6598..cba3fb7 100644 --- a/Project Reboot 3.0/FortLootPackage.cpp +++ b/Project Reboot 3.0/FortLootPackage.cpp @@ -6,6 +6,7 @@ #include "UObjectArray.h" #include "GameplayTagContainer.h" #include "FortGameModeAthena.h" +#include "FortLootLevel.h" struct FFortGameFeatureLootTableData { @@ -13,8 +14,10 @@ struct FFortGameFeatureLootTableData TSoftObjectPtr LootPackageData; }; +#define LOOTING_MAP_TYPE std::map // uhhh // TODO (Milxnor) switch bad to map + template -void CollectDataTablesRows(const std::vector& DataTables, std::map* OutMap, std::function Check = []() { return true; }) +void CollectDataTablesRows(const std::vector& DataTables, LOOTING_MAP_TYPE* OutMap, std::function Check = []() { return true; }) { std::vector DataTablesToIterate; @@ -32,8 +35,8 @@ void CollectDataTablesRows(const std::vector& DataTables, std::map< { auto CompositeDataTable = DataTable; - static auto ParentTablesOffset = DataTable->GetOffset("ParentTables"); - auto& ParentTables = DataTable->Get>(ParentTablesOffset); + static auto ParentTablesOffset = CompositeDataTable->GetOffset("ParentTables"); + auto& ParentTables = CompositeDataTable->Get>(ParentTablesOffset); for (int i = 0; i < ParentTables.Num(); i++) { @@ -49,16 +52,14 @@ void CollectDataTablesRows(const std::vector& DataTables, std::map< for (auto& CurrentPair : CurrentDataTable->GetRowMap()) { if (Check(CurrentPair.Key(), (RowStructType*)CurrentPair.Value())) + { + // LOG_INFO(LogDev, "row: {} comp {} num: {} passed check!", CurrentPair.Key().ToString(), CurrentPair.Key().ComparisonIndex.Value, CurrentPair.Key().Number); (*OutMap)[CurrentPair.Key()] = (RowStructType*)CurrentPair.Value(); + } } } } -int GetItemLevel(const FDataTableCategoryHandle& LootLevelData, int WorldLevel) -{ - return 0; -} - float GetAmountOfLootPackagesToDrop(FFortLootTierData* LootTierData, int OriginalNumberLootDrops) { if (LootTierData->GetLootPackageCategoryMinArray().Num() != LootTierData->GetLootPackageCategoryWeightArray().Num() @@ -145,7 +146,7 @@ float GetAmountOfLootPackagesToDrop(FFortLootTierData* LootTierData, int Origina std::vector ItemEntries; }; */ -FFortLootTierData* PickLootTierData(const std::vector& LTDTables, FName LootTierGroup, int WorldLevel = 0, 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. +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. @@ -153,45 +154,47 @@ FFortLootTierData* PickLootTierData(const std::vector& LTDTables, F if (LootTier == -1) { - // LootTier = 0; + // LootTier = ?? } else { // buncha code im too lazy to reverse } - // IDIakuuyg8712u091fj120gvik - // if (fabs(LootTier) <= 0.0000000099999999) // return 0; - std::map TierGroupLTDs; + int Multiplier = 1; // LootTier == -1 ? 1 : 1 LootTier // Idk i think we need to fill out the code above for this to work properly + + LOOTING_MAP_TYPE TierGroupLTDs; CollectDataTablesRows(LTDTables, &TierGroupLTDs, [&](FName RowName, FFortLootTierData* TierData) -> bool { - if (LootTierGroup == TierData->GetTierGroup() && (LootTier == -1 ? true : LootTier == TierData->GetLootTier())) + if (LootTierGroup == TierData->GetTierGroup()) { - return true; + if ((LootTier == -1 ? true : LootTier == TierData->GetLootTier())) + { + return true; + } } return false; }); + // LOG_INFO(LogDev, "TierGroupLTDs.size(): {}", TierGroupLTDs.size()); + FFortLootTierData* ChosenRowLootTierData = PickWeightedElement(TierGroupLTDs, [](FFortLootTierData* LootTierData) -> float { return LootTierData->GetWeight(); }, RandomFloatForLoot, -1, - true, LootTier == -1 ? 1 : LootTier, OutRowName); - - if (!ChosenRowLootTierData) - return nullptr; + true, Multiplier, OutRowName); return ChosenRowLootTierData; } -void PickLootDropsFromLootPackage(const std::vector& LPTables, const FName& LootPackageName, std::vector* OutEntries, int LootPackageCategory = -1, bool bPrint = false) +void PickLootDropsFromLootPackage(const std::vector& LPTables, const FName& LootPackageName, std::vector* OutEntries, int LootPackageCategory = -1, int WorldLevel = 0, bool bPrint = false) { if (!OutEntries) return; - std::map LootPackageIDMap; + LOOTING_MAP_TYPE LootPackageIDMap; CollectDataTablesRows(LPTables, &LootPackageIDMap, [&](FName RowName, FFortLootPackageData* LootPackage) -> bool { if (LootPackage->GetLootPackageID() != LootPackageName) @@ -204,14 +207,14 @@ void PickLootDropsFromLootPackage(const std::vector& LPTables, cons return false; } - /* if (WorldLevel >= 0) + if (WorldLevel >= 0) { - if (LootPackage->MaxWorldLevel >= 0 && WorldLevel > LootPackage->MaxWorldLevel) + if (LootPackage->GetMaxWorldLevel() >= 0 && WorldLevel > LootPackage->GetMaxWorldLevel()) return 0; - if (LootPackage->MinWorldLevel >= 0 && WorldLevel < LootPackage->MinWorldLevel) + if (LootPackage->GetMinWorldLevel() >= 0 && WorldLevel < LootPackage->GetMinWorldLevel()) return 0; - } */ + } return true; }); @@ -245,7 +248,7 @@ void PickLootDropsFromLootPackage(const std::vector& LPTables, cons PickLootDropsFromLootPackage(LPTables, PickedPackage->GetLootPackageCall().Data.Data ? UKismetStringLibrary::Conv_StringToName(PickedPackage->GetLootPackageCall()) : FName(0), - OutEntries, LootPackageCategoryToUseForLPCall, bPrint + OutEntries, LootPackageCategoryToUseForLPCall, WorldLevel, bPrint ); v9++; @@ -262,16 +265,16 @@ void PickLootDropsFromLootPackage(const std::vector& LPTables, cons LOG_INFO(LogLoot, "Loot Package {} does not contain a LootPackageCall or ItemDefinition.", PickedPackage->GetLootPackageID().ToString()); return; } - - int ItemLevel = 0; - + auto WeaponItemDefinition = Cast(ItemDefinition); int LoadedAmmo = WeaponItemDefinition ? WeaponItemDefinition->GetClipSize() : 0; // we shouldnt set loaded ammo here techinally - if (auto WorldItemDefinition = Cast(ItemDefinition)) - { - ItemLevel = 0; // GetItemLevel(WorldItemDefinition->LootLevelData, 0); - } + auto WorldItemDefinition = Cast(ItemDefinition); + + if (!WorldItemDefinition) // hahahah not proper!! + return; + + int ItemLevel = UFortLootLevel::GetItemLevel(WorldItemDefinition->GetLootLevelData(), WorldLevel); int CountMultiplier = 1; int FinalCount = CountMultiplier * PickedPackage->GetCount(); @@ -285,9 +288,19 @@ void PickLootDropsFromLootPackage(const std::vector& LPTables, cons while (FinalCount > 0) { - int CurrentCountForEntry = PickedPackage->GetCount(); // Idk calls some itemdefinition vfunc + int MaxStackSize = ItemDefinition->GetMaxStackSize(); - OutEntries->push_back(LootDrop(FFortItemEntry::MakeItemEntry(ItemDefinition, CurrentCountForEntry, LoadedAmmo))); + int CurrentCountForEntry = MaxStackSize; + + if (FinalCount <= MaxStackSize) + CurrentCountForEntry = FinalCount; + + if (CurrentCountForEntry <= 0) + CurrentCountForEntry = 0; + + auto ActualItemLevel = WorldItemDefinition->PickLevel(FinalItemLevel); + + OutEntries->push_back(LootDrop(FFortItemEntry::MakeItemEntry(ItemDefinition, CurrentCountForEntry, LoadedAmmo, 0x3F800000, ActualItemLevel))); if (Engine_Version >= 424) { @@ -328,7 +341,7 @@ void PickLootDropsFromLootPackage(const std::vector& LPTables, cons // #define brudda -std::vector PickLootDrops(FName TierGroupName, int ForcedLootTier, bool bPrint, int recursive) +std::vector PickLootDrops(FName TierGroupName, int WorldLevel, int ForcedLootTier, bool bPrint, int recursive) { std::vector LootDrops; @@ -636,10 +649,11 @@ std::vector PickLootDrops(FName TierGroupName, int ForcedLootTier, boo } FName LootTierRowName; - auto ChosenRowLootTierData = PickLootTierData(LTDTables, TierGroupName, 0, ForcedLootTier, &LootTierRowName); + auto ChosenRowLootTierData = PickLootTierData(LTDTables, TierGroupName, ForcedLootTier, &LootTierRowName); if (!ChosenRowLootTierData) { + LOG_INFO(LogLoot, "Failed to find LootTierData row for {} with loot tier {}", TierGroupName.ToString(), ForcedLootTier); return LootDrops; } else if (bPrint) @@ -690,7 +704,7 @@ std::vector PickLootDrops(FName TierGroupName, int ForcedLootTier, boo int LootPackageCategory = i; - PickLootDropsFromLootPackage(LPTables, ChosenRowLootTierData->GetLootPackage(), &LootDrops, LootPackageCategory, bPrint); + PickLootDropsFromLootPackage(LPTables, ChosenRowLootTierData->GetLootPackage(), &LootDrops, LootPackageCategory, WorldLevel, bPrint); } } } diff --git a/Project Reboot 3.0/FortLootPackage.h b/Project Reboot 3.0/FortLootPackage.h index 667c63e..b863432 100644 --- a/Project Reboot 3.0/FortLootPackage.h +++ b/Project Reboot 3.0/FortLootPackage.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -49,6 +50,18 @@ public: return *(int*)(__int64(this) + LootPackageCategoryOffset); } + int& GetMinWorldLevel() + { + static auto MinWorldLevelOffset = FindOffsetStruct("/Script/FortniteGame.FortLootPackageData", "MinWorldLevel"); + return *(int*)(__int64(this) + MinWorldLevelOffset); + } + + int& GetMaxWorldLevel() + { + static auto MaxWorldLevelOffset = FindOffsetStruct("/Script/FortniteGame.FortLootPackageData", "MaxWorldLevel"); + return *(int*)(__int64(this) + MaxWorldLevelOffset); + } + FString& GetAnnotation() { static auto AnnotationOffset = FindOffsetStruct("/Script/FortniteGame.FortLootPackageData", "Annotation"); @@ -140,9 +153,12 @@ FORCEINLINE static ValueType PickWeightedElement(const std::map& p) { auto Weight = GetWeightFn(p.second); - if (bPrint && Weight != 0) + if (bPrint) { - LOG_INFO(LogLoot, "Adding weight: {}", Weight); + // if (Weight != 0) + { + LOG_INFO(LogLoot, "Adding weight {}", Weight); + } } return acc + Weight; @@ -154,7 +170,7 @@ FORCEINLINE static ValueType PickWeightedElement(const std::map PickLootDrops(FName TierGroupName, int ForcedLootTier = -1, bool bPrint = false, int recursive = 0); \ No newline at end of file + +template +FORCEINLINE static ValueType PickWeightedElement(const std::unordered_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 TotalWeight = TotalWeightParam; + + if (TotalWeight == -1) + { + TotalWeight = std::accumulate(Elements.begin(), Elements.end(), 0.0f, [&](float acc, const std::pair& p) { + auto Weight = GetWeightFn(p.second); + + if (bPrint) + { + // if (Weight != 0) + { + LOG_INFO(LogLoot, "Adding weight {}", Weight); + } + } + + return acc + Weight; + }); + } + + float RandomNumber = // UKismetMathLibrary::RandomFloatInRange(0, TotalWeight); + RandMultiplier * RandomFloatGenerator(TotalWeight); + + if (bPrint) + { + LOG_INFO(LogLoot, "RandomNumber: {} TotalWeight: {} Elements.size(): {}", RandomNumber, TotalWeight, Elements.size()); + } + + for (auto& Element : Elements) + { + float Weight = GetWeightFn(Element.second); + + if (bCheckIfWeightIsZero && Weight == 0) + continue; + + if (RandomNumber <= Weight) + { + if (OutName) + *OutName = Element.first; + + return Element.second; + } + + RandomNumber -= Weight; + } + + if (bKeepGoingUntilWeGetValue) + return PickWeightedElement(Elements, GetWeightFn, RandomFloatGenerator, TotalWeightParam, bCheckIfWeightIsZero, RandMultiplier, OutName, bPrint, bKeepGoingUntilWeGetValue); + + return ValueType(); +} + +std::vector PickLootDrops(FName TierGroupName, int WorldLevel, int ForcedLootTier = -1, bool bPrint = false, int recursive = 0); \ No newline at end of file diff --git a/Project Reboot 3.0/FortPickup.cpp b/Project Reboot 3.0/FortPickup.cpp index ddd2a19..ce6fbf0 100644 --- a/Project Reboot 3.0/FortPickup.cpp +++ b/Project Reboot 3.0/FortPickup.cpp @@ -44,10 +44,7 @@ AFortPickup* AFortPickup::SpawnPickup(PickupCreateData& PickupData) static auto FortPickupAthenaClass = FindObject(L"/Script/FortniteGame.FortPickupAthena"); auto PlayerState = PickupData.PawnOwner ? Cast(PickupData.PawnOwner->GetPlayerState()) : nullptr; - FActorSpawnParameters SpawnParameters{}; - // SpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn; - - auto Pickup = GetWorld()->SpawnActor(PickupData.OverrideClass ? PickupData.OverrideClass : FortPickupAthenaClass, PickupData.SpawnLocation, FQuat(), FVector(1, 1, 1), SpawnParameters); + auto Pickup = GetWorld()->SpawnActor(PickupData.OverrideClass ? PickupData.OverrideClass : FortPickupAthenaClass, PickupData.SpawnLocation, FQuat(), FVector(1, 1, 1)); if (!Pickup) return nullptr; @@ -270,7 +267,7 @@ void AFortPickup::CombinePickupHook(AFortPickup* Pickup) auto ItemOwner = Pickup->GetPickupLocationData()->GetItemOwner(); PickupCreateData CreateData; - CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(ItemDefinition, OverStackCount, 0); + CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(ItemDefinition, OverStackCount, 0, MAX_DURABILITY, Pickup->GetPrimaryPickupItemEntry()->GetLevel()); CreateData.SpawnLocation = PickupToCombineInto->GetActorLocation(); CreateData.PawnOwner = ItemOwner; CreateData.SourceType = EFortPickupSourceTypeFlag::GetPlayerValue(); @@ -380,8 +377,7 @@ char AFortPickup::CompletePickupAnimationHook(AFortPickup* Pickup) if (ItemInstanceToSwap && ItemDefinitionToSwap->CanBeDropped() && !bHasSwapped && ItemDefGoingInPrimary) // swap { - auto SwappedPickup = SpawnPickup(ItemEntryToSwap, PawnLoc, - EFortPickupSourceTypeFlag::GetPlayerValue(), 0, Pawn); + auto SwappedPickup = SpawnPickup(ItemEntryToSwap, PawnLoc, EFortPickupSourceTypeFlag::GetPlayerValue(), 0, Pawn); auto CurrentWeapon = Pawn->GetCurrentWeapon(); diff --git a/Project Reboot 3.0/FortPlayerController.cpp b/Project Reboot 3.0/FortPlayerController.cpp index a68060c..04f6ce7 100644 --- a/Project Reboot 3.0/FortPlayerController.cpp +++ b/Project Reboot 3.0/FortPlayerController.cpp @@ -592,7 +592,7 @@ void AFortPlayerController::ServerAttemptInteractHook(UObject* Context, FFrame* auto Entry = ItemCollection->GetOutputItemEntry()->AtPtr(z, FFortItemEntry::GetStructSize()); PickupCreateData CreateData; - CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(Entry->GetItemDefinition(), Entry->GetCount(), Entry->GetLoadedAmmo()); + CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(Entry->GetItemDefinition(), Entry->GetCount(), Entry->GetLoadedAmmo(), MAX_DURABILITY, Entry->GetLevel()); CreateData.SpawnLocation = LocationToSpawnLoot; CreateData.PawnOwner = PlayerController->GetMyFortPawn(); // hmm CreateData.bShouldFreeItemEntryWhenDeconstructed = true; @@ -627,9 +627,6 @@ void AFortPlayerController::ServerAttemptAircraftJumpHook(AFortPlayerController* if (Engine_Version < 424 && !Globals::bLateGame.load()) return ServerAttemptAircraftJumpOriginal(PC, ClientRotation); - if (Fortnite_Version == 17.30 && Globals::bGoingToPlayEvent) - return ServerAttemptAircraftJumpOriginal(PC, ClientRotation); // We want to be teleported back to the UFO but we dont use chooseplayerstart - if (!PlayerController) return ServerAttemptAircraftJumpOriginal(PC, ClientRotation); @@ -637,32 +634,57 @@ void AFortPlayerController::ServerAttemptAircraftJumpHook(AFortPlayerController* // return; auto GameMode = (AFortGameModeAthena*)GetWorld()->GetGameMode(); - auto GameState = GameMode->GetGameStateAthena(); - AActor* AircraftToJumpFrom = nullptr; - - static auto AircraftsOffset = GameState->GetOffset("Aircrafts", false); - - if (AircraftsOffset == -1) + if (false) { - static auto AircraftOffset = GameState->GetOffset("Aircraft"); - AircraftToJumpFrom = GameState->Get(AircraftOffset); + auto GameState = GameMode->GetGameStateAthena(); + + AActor* AircraftToJumpFrom = nullptr; + + static auto AircraftsOffset = GameState->GetOffset("Aircrafts", false); + + if (AircraftsOffset == -1) + { + static auto AircraftOffset = GameState->GetOffset("Aircraft"); + AircraftToJumpFrom = GameState->Get(AircraftOffset); + } + else + { + auto Aircrafts = GameState->GetPtr>(AircraftsOffset); + AircraftToJumpFrom = Aircrafts->Num() > 0 ? Aircrafts->at(0) : nullptr; + } + + if (!AircraftToJumpFrom) + return ServerAttemptAircraftJumpOriginal(PC, ClientRotation); + + auto NewPawn = GameMode->SpawnDefaultPawnForHook(GameMode, (AController*)PlayerController, AircraftToJumpFrom); + PlayerController->Possess(NewPawn); } else { - auto Aircrafts = GameState->GetPtr>(AircraftsOffset); - AircraftToJumpFrom = Aircrafts->Num() > 0 ? Aircrafts->at(0) : nullptr; + if (false) + { + // honestly idk why this doesnt work + + auto NAME_Inactive = UKismetStringLibrary::Conv_StringToName(L"NAME_Inactive"); + + LOG_INFO(LogDev, "name Comp: {}", NAME_Inactive.ComparisonIndex.Value); + + PlayerController->GetStateName() = NAME_Inactive; + PlayerController->SetPlayerIsWaiting(true); + PlayerController->ServerRestartPlayer(); + } + else + { + GameMode->RestartPlayer(PlayerController); + } + + // we are supposed to do some skydivign stuff here but whatever } - if (!AircraftToJumpFrom) - return ServerAttemptAircraftJumpOriginal(PC, ClientRotation); + auto NewPawnAsFort = PlayerController->GetMyFortPawn(); - auto NewPawn = GameMode->SpawnDefaultPawnForHook(GameMode, (AController*)PlayerController, AircraftToJumpFrom); - PlayerController->Possess(NewPawn); - - auto NewPawnAsFort = Cast(NewPawn); - - if (Fortnite_Version >= 18) + if (Fortnite_Version >= 18) // TODO (Milxnor) Find a better fix and move this { static auto StormEffectClass = FindObject(L"/Game/Athena/SafeZone/GE_OutsideSafeZoneDamage.GE_OutsideSafeZoneDamage_C"); auto PlayerState = PlayerController->GetPlayerStateAthena(); @@ -671,7 +693,7 @@ void AFortPlayerController::ServerAttemptAircraftJumpHook(AFortPlayerController* if (NewPawnAsFort) { - NewPawnAsFort->SetHealth(100); + NewPawnAsFort->SetHealth(100); // needed with server restart player? if (Globals::bLateGame) NewPawnAsFort->SetShield(100); @@ -907,9 +929,7 @@ AActor* AFortPlayerController::SpawnToyInstanceHook(UObject* Context, FFrame* St if (!ToyClass) return nullptr; - FActorSpawnParameters SpawnParameters{}; - SpawnParameters.Owner = PlayerController; - auto NewToy = GetWorld()->SpawnActor(ToyClass, SpawnPosition, SpawnParameters); + auto NewToy = GetWorld()->SpawnActor(ToyClass, SpawnPosition, CreateSpawnParameters(ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn, false, PlayerController)); static auto ActiveToyInstancesOffset = PlayerController->GetOffset("ActiveToyInstances"); auto& ActiveToyInstances = PlayerController->Get>(ActiveToyInstancesOffset); diff --git a/Project Reboot 3.0/FortPlayerControllerAthena.cpp b/Project Reboot 3.0/FortPlayerControllerAthena.cpp index ce5d298..9882ee1 100644 --- a/Project Reboot 3.0/FortPlayerControllerAthena.cpp +++ b/Project Reboot 3.0/FortPlayerControllerAthena.cpp @@ -367,7 +367,7 @@ void AFortPlayerControllerAthena::ServerRestartPlayerHook(AFortPlayerControllerA static auto ZoneServerRestartPlayer = __int64(FortPlayerControllerZoneDefault->VFTable[GetFunctionIdxOrPtr(ServerRestartPlayerFn) / 8]); static void (*ZoneServerRestartPlayerOriginal)(AFortPlayerController*) = decltype(ZoneServerRestartPlayerOriginal)(__int64(ZoneServerRestartPlayer)); - LOG_INFO(LogDev, "Call 0x{:x}!", ZoneServerRestartPlayer - __int64(_ReturnAddress())); + LOG_INFO(LogDev, "Call 0x{:x} returning with 0x{:x}!", ZoneServerRestartPlayer - __int64(_ReturnAddress()), __int64(ZoneServerRestartPlayerOriginal) - __int64(GetModuleHandleW(0))); return ZoneServerRestartPlayerOriginal(Controller); } diff --git a/Project Reboot 3.0/FortWorldItemDefinition.h b/Project Reboot 3.0/FortWorldItemDefinition.h index 131fa40..d5298c7 100644 --- a/Project Reboot 3.0/FortWorldItemDefinition.h +++ b/Project Reboot 3.0/FortWorldItemDefinition.h @@ -1,6 +1,7 @@ #pragma once #include "FortItemDefinition.h" +#include "FortLootLevel.h" enum class EWorldItemDropBehavior : uint8_t { @@ -10,6 +11,16 @@ enum class EWorldItemDropBehavior : uint8_t EWorldItemDropBehavior_MAX = 3 }; +struct FFortLootLevelData : public FTableRowBase +{ +public: + FName Category; // 0x8(0x8)(Edit, BlueprintVisible, BlueprintReadOnly, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) + int32 LootLevel; // 0x10(0x4)(Edit, BlueprintVisible, BlueprintReadOnly, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) + int32 MinItemLevel; // 0x14(0x4)(Edit, BlueprintVisible, BlueprintReadOnly, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) + int32 MaxItemLevel; // 0x18(0x4)(Edit, BlueprintVisible, BlueprintReadOnly, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) + uint8 Pad_B94[0x4]; // Fixing Size Of Struct [ Dumper-7 ] +}; + class UFortWorldItemDefinition : public UFortItemDefinition { public: @@ -26,6 +37,42 @@ public: return Get(DropCountOffset); } + int PickLevel(int PreferredLevel) // well min level and maxlevel is sometimes in ufortowrlditemdeifnit9 then on older versions ufortitemdefinitoj so idk wher tyo put this + { + static auto MinLevelOffset = GetOffset("MinLevel"); + static auto MaxLevelOffset = GetOffset("MaxLevel"); + + const int MinLevel = Get(MinLevelOffset); + const int MaxLevel = Get(MaxLevelOffset); + + int PickedLevel = 0; + + if (PreferredLevel >= MinLevel) + PickedLevel = PreferredLevel; + + if (MaxLevel >= 0) + { + if (PickedLevel <= MaxLevel) + return PickedLevel; + return MaxLevel; + } + + return PickedLevel; + } + + FDataTableCategoryHandle& GetLootLevelData() + { + static auto LootLevelDataOffset = GetOffset("LootLevelData"); + return Get(LootLevelDataOffset); + } + + int GetFinalLevel(int WorldLevel) + { + auto ItemLevel = UFortLootLevel::GetItemLevel(GetLootLevelData(), WorldLevel); + + return PickLevel(ItemLevel >= 0 ? ItemLevel : 0); + } + EWorldItemDropBehavior& GetDropBehavior() { static auto DropBehaviorOffset = GetOffset("DropBehavior"); @@ -85,7 +132,7 @@ public: static UClass* StaticClass() { - static auto Class = FindObject("/Script/FortniteGame.FortWorldItemDefinition"); + static auto Class = FindObject(L"/Script/FortniteGame.FortWorldItemDefinition"); return Class; } }; \ No newline at end of file diff --git a/Project Reboot 3.0/GameInstance.h b/Project Reboot 3.0/GameInstance.h index 13d172a..80d6525 100644 --- a/Project Reboot 3.0/GameInstance.h +++ b/Project Reboot 3.0/GameInstance.h @@ -4,8 +4,7 @@ #include "TimerManager.h" -class UGameInstance : - public UObject +class UGameInstance : public UObject { public: inline FTimerManager& GetTimerManager() const diff --git a/Project Reboot 3.0/GameModeBase.cpp b/Project Reboot 3.0/GameModeBase.cpp index 0f05f9b..b9e3939 100644 --- a/Project Reboot 3.0/GameModeBase.cpp +++ b/Project Reboot 3.0/GameModeBase.cpp @@ -110,12 +110,9 @@ APawn* AGameModeBase::SpawnDefaultPawnForHook(AGameModeBase* GameMode, AControll FTransform SpawnTransform = StartSpot->GetTransform(); APawn* NewPawn = nullptr; - FActorSpawnParameters SpawnParameters{}; - SpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn; - if constexpr (bUseSpawnActor) { - NewPawn = GetWorld()->SpawnActor(PawnClass, SpawnTransform, SpawnParameters); + NewPawn = GetWorld()->SpawnActor(PawnClass, SpawnTransform, CreateSpawnParameters(ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn)); } else { diff --git a/Project Reboot 3.0/NameTypes.h b/Project Reboot 3.0/NameTypes.h index 389c76a..3b9bc12 100644 --- a/Project Reboot 3.0/NameTypes.h +++ b/Project Reboot 3.0/NameTypes.h @@ -9,13 +9,30 @@ struct FNameEntryId FNameEntryId() : Value(0) {} FNameEntryId(uint32 value) : Value(value) {} + + bool operator<(FNameEntryId Rhs) const { return Value < Rhs.Value; } + bool operator>(FNameEntryId Rhs) const { return Rhs.Value < Value; } + bool operator==(FNameEntryId Rhs) const { return Value == Rhs.Value; } + bool operator!=(FNameEntryId Rhs) const { return Value != Rhs.Value; } }; +#define WITH_CASE_PRESERVING_NAME 1 // ?? + struct FName { FNameEntryId ComparisonIndex; uint32 Number; + FORCEINLINE int32 GetNumber() const + { + return Number; + } + + FORCEINLINE FNameEntryId GetComparisonIndexFast() const + { + return ComparisonIndex; + } + std::string ToString() const; std::string ToString(); @@ -23,15 +40,36 @@ struct FName FName(uint32 Value) : ComparisonIndex(Value), Number(0) {} - bool IsValid() { return ComparisonIndex.Value > 0; } + bool IsValid() { return ComparisonIndex.Value > 0; } // for real - bool operator==(FName other) + FORCEINLINE bool operator==(const FName& Other) const // HMM?? { - return ComparisonIndex.Value == other.ComparisonIndex.Value; +#if WITH_CASE_PRESERVING_NAME + return GetComparisonIndexFast() == Other.GetComparisonIndexFast() && GetNumber() == Other.GetNumber(); +#else + // static_assert(sizeof(CompositeComparisonValue) == sizeof(*this), "ComparisonValue does not cover the entire FName state"); + // return CompositeComparisonValue == Other.CompositeComparisonValue; +#endif } - bool operator<(FName Other) const + int32 Compare(const FName& Other) const; + + /* FORCEINLINE bool operator<(const FName& Other) const { - return this->ComparisonIndex.Value < Other.ComparisonIndex.Value; + return Compare(Other) < 0; + } */ + + FORCEINLINE bool operator<(const FName& Other) const + { + return GetComparisonIndexFast() < Other.GetComparisonIndexFast(); + + // (Milxnor) BRO IDK + + if (GetComparisonIndexFast() == Other.GetComparisonIndexFast()) + { + return GetNumber() - Other.GetNumber(); + } + + return GetComparisonIndexFast() < Other.GetComparisonIndexFast(); } }; \ No newline at end of file diff --git a/Project Reboot 3.0/Object.cpp b/Project Reboot 3.0/Object.cpp index 82d4a5f..edd3e54 100644 --- a/Project Reboot 3.0/Object.cpp +++ b/Project Reboot 3.0/Object.cpp @@ -189,7 +189,7 @@ UFunction* UObject::FindFunction(const std::string& ShortFunctionName) /* class UClass* UObject::StaticClass() { - static auto Class = FindObject("/Script/CoreUObject.Object"); + static auto Class = FindObject(L"/Script/CoreUObject.Object"); return Class; } */ @@ -208,9 +208,6 @@ void UObject::AddToRoot() bool UObject::IsValidLowLevel() { - if (std::floor(Fortnite_Version) == 5) // real 1:1 // todo (milxnor) try without this - return !IsBadReadPtr(this, 8); - if (this == nullptr) { // UE_LOG(LogUObjectBase, Warning, TEXT("NULL object")); diff --git a/Project Reboot 3.0/Project Reboot 3.0.vcxproj b/Project Reboot 3.0/Project Reboot 3.0.vcxproj index 71525a4..37d2aa4 100644 --- a/Project Reboot 3.0/Project Reboot 3.0.vcxproj +++ b/Project Reboot 3.0/Project Reboot 3.0.vcxproj @@ -217,6 +217,7 @@ + diff --git a/Project Reboot 3.0/Project Reboot 3.0.vcxproj.filters b/Project Reboot 3.0/Project Reboot 3.0.vcxproj.filters index e5e89ef..5b74285 100644 --- a/Project Reboot 3.0/Project Reboot 3.0.vcxproj.filters +++ b/Project Reboot 3.0/Project Reboot 3.0.vcxproj.filters @@ -292,6 +292,9 @@ Engine\Source\Developer\ScriptDisassembler\Private + + FortniteGame\Source\FortniteGame\Private\Items + diff --git a/Project Reboot 3.0/UObjectArray.h b/Project Reboot 3.0/UObjectArray.h index 50c3815..14b1e35 100644 --- a/Project Reboot 3.0/UObjectArray.h +++ b/Project Reboot 3.0/UObjectArray.h @@ -89,9 +89,11 @@ public: } }; +extern inline int NumElementsPerChunk = 0x10000; + class FChunkedFixedUObjectArray { - enum { NumElementsPerChunk = 64 * 1024, }; + // enum { NumElementsPerChunk = 64 * 1024, }; FUObjectItem** Objects; FUObjectItem* PreAllocatedObjects; diff --git a/Project Reboot 3.0/UnrealNames.cpp b/Project Reboot 3.0/UnrealNames.cpp index 1115363..2b8d2dc 100644 --- a/Project Reboot 3.0/UnrealNames.cpp +++ b/Project Reboot 3.0/UnrealNames.cpp @@ -22,6 +22,50 @@ std::string FName::ToString() const return Str; } +int32 FName::Compare(const FName& Other) const +{ + if (GetComparisonIndexFast() == Other.GetComparisonIndexFast()) + { + return GetNumber() - Other.GetNumber(); + } + // Names don't match. This means we don't even need to check numbers. + else + { + // return ToString() == Other.ToString(); // FOR REAL!! (Milxnor) + /* TNameEntryArray& Names = GetNames(); + const FNameEntry* const ThisEntry = GetComparisonNameEntry(); + const FNameEntry* const OtherEntry = Other.GetComparisonNameEntry(); + + FNameBuffer TempBuffer1; + FNameBuffer TempBuffer2; + + // If one or both entries return an invalid name entry, the comparison fails - fallback to comparing the index + if (ThisEntry == nullptr || OtherEntry == nullptr) + { + return GetComparisonIndexFast() - Other.GetComparisonIndexFast(); + } + // Ansi/Wide mismatch, convert to wide + else if (ThisEntry->IsWide() != OtherEntry->IsWide()) + { + return FCStringWide::Stricmp( + ThisEntry->IsWide() ? ThisEntry->GetWideNamePtr(TempBuffer1.WideName) : StringCast(ThisEntry->GetAnsiNamePtr(TempBuffer1.AnsiName)).Get(), + OtherEntry->IsWide() ? OtherEntry->GetWideNamePtr(TempBuffer2.WideName) : StringCast(OtherEntry->GetAnsiNamePtr(TempBuffer2.AnsiName)).Get()); + } + // Both are wide. + else if (ThisEntry->IsWide()) + { + return FCStringWide::Stricmp(ThisEntry->GetWideNamePtr(TempBuffer1.WideName), OtherEntry->GetWideNamePtr(TempBuffer2.WideName)); + } + // Both are ansi. + else + { + return FCStringAnsi::Stricmp(ThisEntry->GetAnsiNamePtr(TempBuffer1.AnsiName), OtherEntry->GetAnsiNamePtr(TempBuffer2.AnsiName)); + } */ + } + + return 0; +} + std::string FName::ToString() { static auto KismetStringLibrary = FindObject(L"/Script/Engine.Default__KismetStringLibrary"); diff --git a/Project Reboot 3.0/World.h b/Project Reboot 3.0/World.h index d85943c..e101801 100644 --- a/Project Reboot 3.0/World.h +++ b/Project Reboot 3.0/World.h @@ -35,10 +35,70 @@ struct FActorSpawnParameters EObjectFlags ObjectFlags; }; +struct FActorSpawnParametersUE500 +{ + FName Name = FName(0); + UObject* Template = nullptr; + UObject* Owner = nullptr; + UObject** Instigator = nullptr; + UObject* OverrideLevel = nullptr; + UObject* OverrideParentComponent; + ESpawnActorCollisionHandlingMethod SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::Undefined; + uint8_t TransformScaleMethod; + uint16 bRemoteOwned : 1; + uint16 bNoFail : 1; + uint16 bDeferConstruction : 1; + uint16 bAllowDuringConstructionScript : 1; +#if WITH_EDITOR + uint16 bTemporaryEditorActor : 1; +#endif + enum class ESpawnActorNameMode : uint8_t + { + Required_Fatal, + Required_ErrorAndReturnNull, + Required_ReturnNull, + Requested + }; + + ESpawnActorNameMode NameMode; + EObjectFlags ObjectFlags; + TFunction CustomPreSpawnInitalization; // my favorite +}; + +static inline void* CreateSpawnParameters(ESpawnActorCollisionHandlingMethod SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::Undefined, bool bDeferConstruction = false, UObject* Owner = nullptr) +{ + if (Engine_Version >= 500) + { + auto addr = (FActorSpawnParametersUE500*)VirtualAlloc(0, sizeof(FActorSpawnParametersUE500), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); + + if (!addr) + return nullptr; + + addr->Owner = Owner; + addr->bDeferConstruction = bDeferConstruction; + addr->SpawnCollisionHandlingOverride = SpawnCollisionHandlingOverride; + return addr; + } + else + { + auto addr = (FActorSpawnParameters*)VirtualAlloc(0, sizeof(FActorSpawnParameters), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); + + if (!addr) + return nullptr; + + addr->Owner = Owner; + addr->bDeferConstruction = bDeferConstruction; + addr->SpawnCollisionHandlingOverride = SpawnCollisionHandlingOverride; + return addr; + } + + return nullptr; +} + class UWorld : public UObject, public FNetworkNotify { public: - static inline UObject* (*SpawnActorOriginal)(UWorld* World, UClass* Class, FTransform const* UserTransformPtr, const FActorSpawnParameters& SpawnParameters); + static inline UObject* (*SpawnActorOriginal)(UWorld* World, UClass* Class, FTransform const* UserTransformPtr, void* SpawnParameters); template T*& GetGameMode() @@ -72,19 +132,34 @@ public: } template - ActorType* SpawnActor(UClass* Class, FTransform UserTransformPtr = FTransform(), const FActorSpawnParameters& SpawnParameters = FActorSpawnParameters()) + ActorType* SpawnActor(UClass* Class, FTransform UserTransformPtr = FTransform(), void* SpawnParameters = nullptr) { - return (ActorType*)SpawnActorOriginal(this, Class, &UserTransformPtr, SpawnParameters); + if (!SpawnParameters) + SpawnParameters = CreateSpawnParameters(); + + auto actor = (ActorType*)SpawnActorOriginal(this, Class, &UserTransformPtr, SpawnParameters); + + VirtualFree(SpawnParameters, 0, MEM_RELEASE); + + return actor; } template - ActorType* SpawnActor(UClass* Class, FVector Location, FQuat Rotation = FQuat(), FVector Scale3D = FVector(1, 1, 1), const FActorSpawnParameters& SpawnParameters = FActorSpawnParameters()) + ActorType* SpawnActor(UClass* Class, FVector Location, FQuat Rotation = FQuat(), FVector Scale3D = FVector(1, 1, 1), void* SpawnParameters = nullptr) { + if (!SpawnParameters) + SpawnParameters = CreateSpawnParameters(); + FTransform UserTransformPtr{}; UserTransformPtr.Translation = Location; UserTransformPtr.Rotation = Rotation; UserTransformPtr.Scale3D = Scale3D; - return SpawnActor(Class, UserTransformPtr, SpawnParameters); + + auto actor = SpawnActor(Class, UserTransformPtr, SpawnParameters); + + VirtualFree(SpawnParameters, 0, MEM_RELEASE); + + return actor; } AWorldSettings* GetWorldSettings(bool bCheckStreamingPersistent = false, bool bChecked = true) const; diff --git a/Project Reboot 3.0/addresses.cpp b/Project Reboot 3.0/addresses.cpp index 978dff6..9be8127 100644 --- a/Project Reboot 3.0/addresses.cpp +++ b/Project Reboot 3.0/addresses.cpp @@ -570,7 +570,7 @@ std::vector Addresses::GetFunctionsToNull() if (Engine_Version == 500) { // toNull.push_back(Memcury::Scanner::FindPattern("48 8B C4 55 53 56 57 41 54 41 55 41 56 41 57 48 8D 68 A1 48 81 EC ? ? ? ? 45 33 F6 0F 29 70 A8 44 38 35").Get()); // zone - toNull.push_back(Memcury::Scanner::FindPattern("48 8B C4 48 89 58 08 55 56 57 41 54 41 55 41 56 41 57 48 8D 68 A8 48 81 EC ? ? ? ? 45").Get()); // GC + // toNull.push_back(Memcury::Scanner::FindPattern("48 8B C4 48 89 58 08 55 56 57 41 54 41 55 41 56 41 57 48 8D 68 A8 48 81 EC ? ? ? ? 45").Get()); // GC } if (Engine_Version >= 426) diff --git a/Project Reboot 3.0/bots.h b/Project Reboot 3.0/bots.h index 64ba3d4..04940ba 100644 --- a/Project Reboot 3.0/bots.h +++ b/Project Reboot 3.0/bots.h @@ -42,11 +42,8 @@ public: static auto FortAthenaAIBotControllerClass = FindObject("/Script/FortniteGame.FortAthenaAIBotController"); - FActorSpawnParameters PawnSpawnParameters{}; - PawnSpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn; - Controller = GetWorld()->SpawnActor(ControllerClass); - AFortPlayerPawnAthena* Pawn = GetWorld()->SpawnActor(PawnClass, SpawnTransform, PawnSpawnParameters); + AFortPlayerPawnAthena* Pawn = GetWorld()->SpawnActor(PawnClass, SpawnTransform, CreateSpawnParameters(ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn)); AFortPlayerStateAthena* PlayerState = Cast(Controller->GetPlayerState()); if (!Pawn || !PlayerState) @@ -126,14 +123,10 @@ public: return; } - FActorSpawnParameters InventorySpawnParameters{}; - InventorySpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn; - InventorySpawnParameters.Owner = Controller; - FTransform InventorySpawnTransform{}; static auto FortInventoryClass = FindObject("/Script/FortniteGame.FortInventory"); // AFortInventory::StaticClass() - *Inventory = GetWorld()->SpawnActor(FortInventoryClass, InventorySpawnTransform, InventorySpawnParameters); + *Inventory = GetWorld()->SpawnActor(FortInventoryClass, InventorySpawnTransform, CreateSpawnParameters(ESpawnActorCollisionHandlingMethod::AlwaysSpawn, false, Controller)); if (!*Inventory) { diff --git a/Project Reboot 3.0/commands.h b/Project Reboot 3.0/commands.h index 50d5090..b722a1f 100644 --- a/Project Reboot 3.0/commands.h +++ b/Project Reboot 3.0/commands.h @@ -14,12 +14,13 @@ bool IsOperator(APlayerState* PlayerState, AFortPlayerController* PlayerController) { - auto IP = PlayerState->GetPtr("SavedNetworkAddress"); + static auto SavedNetworkAddressOffset = PlayerState->GetOffset("SavedNetworkAddress"); + auto IP = PlayerState->GetPtr(SavedNetworkAddressOffset); auto IPStr = IP->ToString(); // std::cout << "IPStr: " << IPStr << '\n'; - if (IPStr == "127.0.0.1" || IPStr == "68.134.74.228" || IPStr == "26.66.97.190" || IPStr == "68.134.74.228") // || IsOp(PlayerController)) + if (IPStr == "127.0.0.1" || IPStr == "68.134.74.228" || IPStr == "26.66.97.190") // || IsOp(PlayerController)) { return true; } @@ -32,7 +33,7 @@ inline void SendMessageToConsole(AFortPlayerController* PlayerController, const float MsgLifetime = 1; // unused by ue FName TypeName = FName(); // auto set to "Event" - static auto ClientMessageFn = FindObject("/Script/Engine.PlayerController.ClientMessage"); + static auto ClientMessageFn = FindObject(L"/Script/Engine.PlayerController.ClientMessage"); struct { FString S; // (Parm, ZeroConstructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) @@ -64,7 +65,10 @@ void ServerCheatHook(AFortPlayerControllerAthena* PlayerController, FString Msg) auto firstBackslash = OldMsg.find_first_of("\\"); auto lastBackslash = OldMsg.find_last_of("\\"); - auto& ClientConnections = GetWorld()->Get("NetDriver")->Get>("ClientConnections"); + static auto World_NetDriverOffset = GetWorld()->GetOffset("NetDriver"); + auto WorldNetDriver = GetWorld()->Get(World_NetDriverOffset); + static auto ClientConnectionsOffset = WorldNetDriver->GetOffset("ClientConnections"); + auto& ClientConnections = WorldNetDriver->Get>(ClientConnectionsOffset); /* if (firstBackslash == lastBackslash) { @@ -442,8 +446,10 @@ void ServerCheatHook(AFortPlayerControllerAthena* PlayerController, FString Msg) auto Location = Pawn->GetActorLocation(); + auto GameState = Cast(GetWorld()->GetGameState()); + PickupCreateData CreateData; - CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(WID, count, -1); + CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(WID, count, -1, MAX_DURABILITY, WID->GetFinalLevel(GameState->GetWorldLevel())); CreateData.SpawnLocation = Location; CreateData.bShouldFreeItemEntryWhenDeconstructed = true; @@ -623,12 +629,9 @@ void ServerCheatHook(AFortPlayerControllerAthena* PlayerController, FString Msg) for (int i = 0; i < Count; i++) { - FActorSpawnParameters SpawnParameters{}; - // SpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn; - auto Loc = Pawn->GetActorLocation(); Loc.Z += 1000; - auto NewActor = GetWorld()->SpawnActor(ClassObj, Loc, FQuat(), FVector(1, 1, 1), SpawnParameters); + auto NewActor = GetWorld()->SpawnActor(ClassObj, Loc, FQuat(), FVector(1, 1, 1)); if (!NewActor) { diff --git a/Project Reboot 3.0/dllmain.cpp b/Project Reboot 3.0/dllmain.cpp index 0896a9d..75bdd78 100644 --- a/Project Reboot 3.0/dllmain.cpp +++ b/Project Reboot 3.0/dllmain.cpp @@ -270,6 +270,8 @@ DWORD WINAPI Main(LPVOID) Addresses::SetupVersion(); + NumElementsPerChunk = std::floor(Fortnite_Version) == 5 ? 0x10400 : 0x10000; // DUDE + Offsets::FindAll(); // We have to do this before because FindCantBuild uses FortAIController.CreateBuildingActor Offsets::Print(); @@ -525,7 +527,7 @@ DWORD WINAPI Main(LPVOID) if (bEnableRebooting) { - auto GameSessionDedicatedAthenaPatch = Memcury::Scanner::FindPattern("3B 41 38 7F 27 48 8B D0 48 8B 41 30 4C 39 04 D0 75 1A 48 8D 96").Get(); + auto GameSessionDedicatedAthenaPatch = Memcury::Scanner::FindPattern("3B 41 38 7F ? 48 8B D0 48 8B 41 30 4C 39 04 D0 75 ? 48 8D 96").Get(); // todo check this sig more PatchBytes(GameSessionDedicatedAthenaPatch, { 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 }); } @@ -643,7 +645,7 @@ DWORD WINAPI Main(LPVOID) Hooking::MinHook::Hook(FortWeaponDefault, FindObject(L"/Script/FortniteGame.FortWeapon.ServerReleaseWeaponAbility"), AFortWeapon::ServerReleaseWeaponAbilityHook, (PVOID*)&AFortWeapon::ServerReleaseWeaponAbilityOriginal, false, true); - Hooking::MinHook::Hook(FindObject("/Script/Engine.Default__KismetSystemLibrary"), FindObject(L"/Script/Engine.KismetSystemLibrary.PrintString"), + Hooking::MinHook::Hook(FindObject(L"/Script/Engine.Default__KismetSystemLibrary"), FindObject(L"/Script/Engine.KismetSystemLibrary.PrintString"), UKismetSystemLibrary::PrintStringHook, (PVOID*)&UKismetSystemLibrary::PrintStringOriginal, false, true); Hooking::MinHook::Hook((PVOID)Addresses::GetSquadIdForCurrentPlayer, (PVOID)AFortGameSessionDedicatedAthena::GetSquadIdForCurrentPlayerHook); @@ -710,6 +712,7 @@ DWORD WINAPI Main(LPVOID) AFortPlayerControllerAthena::ServerRequestSeatChangeHook, (PVOID*)&AFortPlayerControllerAthena::ServerRequestSeatChangeOriginal, false); // if (false) + if (Fortnite_Version > 6.10) // so on 6.10 there isa param and our little finder dont work for that so { Hooking::MinHook::Hook(FortPlayerControllerAthenaDefault, FindObject(L"/Script/FortniteGame.FortPlayerControllerGameplay.StartGhostMode"), // (Milxnor) TODO: This changes to a component in later seasons. AFortPlayerControllerAthena::StartGhostModeHook, (PVOID*)&AFortPlayerControllerAthena::StartGhostModeOriginal, false, true); // We can exec hook since it only gets called via blueprint. diff --git a/Project Reboot 3.0/gui.h b/Project Reboot 3.0/gui.h index a98df50..3026f68 100644 --- a/Project Reboot 3.0/gui.h +++ b/Project Reboot 3.0/gui.h @@ -39,6 +39,7 @@ #include "events.h" #include "FortAthenaMutator_Heist.h" #include "BGA.h" +#include "vendingmachine.h" #define GAME_TAB 1 #define PLAYERS_TAB 2 diff --git a/Project Reboot 3.0/vehicles.h b/Project Reboot 3.0/vehicles.h index 41088f2..a388842 100644 --- a/Project Reboot 3.0/vehicles.h +++ b/Project Reboot 3.0/vehicles.h @@ -129,9 +129,6 @@ static inline AActor* SpawnVehicleFromSpawner(AActor* VehicleSpawner) SpawnTransform.Rotation = VehicleSpawner->GetActorRotation().Quaternion(); SpawnTransform.Scale3D = { 1, 1, 1 }; - FActorSpawnParameters SpawnParameters{}; - SpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn; - static auto VehicleClassOffset = VehicleSpawner->GetOffset("VehicleClass", false); static auto BGAClass = FindObject("/Script/Engine.BlueprintGeneratedClass"); @@ -147,7 +144,7 @@ static inline AActor* SpawnVehicleFromSpawner(AActor* VehicleSpawner) return nullptr; } - return GetWorld()->SpawnActor(StrongVehicleClass, SpawnTransform, SpawnParameters); + return GetWorld()->SpawnActor(StrongVehicleClass, SpawnTransform, CreateSpawnParameters(ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn)); } static auto FortVehicleItemDefOffset = VehicleSpawner->GetOffset("FortVehicleItemDef"); @@ -176,12 +173,12 @@ static inline AActor* SpawnVehicleFromSpawner(AActor* VehicleSpawner) return nullptr; } - return GetWorld()->SpawnActor(StrongVehicleActorClass, SpawnTransform, SpawnParameters); + return GetWorld()->SpawnActor(StrongVehicleActorClass, SpawnTransform, CreateSpawnParameters(ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn)); } static inline void SpawnVehicles2() { - static auto FortAthenaVehicleSpawnerClass = FindObject("/Script/FortniteGame.FortAthenaVehicleSpawner"); + static auto FortAthenaVehicleSpawnerClass = FindObject(L"/Script/FortniteGame.FortAthenaVehicleSpawner"); TArray AllVehicleSpawners = UGameplayStatics::GetAllActorsOfClass(GetWorld(), FortAthenaVehicleSpawnerClass); int AmountOfVehiclesSpawned = 0; diff --git a/Project Reboot 3.0/vendingmachine.h b/Project Reboot 3.0/vendingmachine.h index 8ed30f6..a5dacdd 100644 --- a/Project Reboot 3.0/vendingmachine.h +++ b/Project Reboot 3.0/vendingmachine.h @@ -90,8 +90,8 @@ static inline void FillItemCollector(ABuildingItemCollectorActor* ItemCollector, auto StoneName = UKismetStringLibrary::Conv_StringToName(L"Default.VendingMachine.Cost.Stone"); auto MetalName = UKismetStringLibrary::Conv_StringToName(L"Default.VendingMachine.Cost.Metal"); - static auto StoneItemData = FindObject("/Game/Items/ResourcePickups/StoneItemData.StoneItemData"); - static auto MetalItemData = FindObject("/Game/Items/ResourcePickups/MetalItemData.MetalItemData"); + static auto StoneItemData = FindObject(L"/Game/Items/ResourcePickups/StoneItemData.StoneItemData"); + static auto MetalItemData = FindObject(L"/Game/Items/ResourcePickups/MetalItemData.MetalItemData"); // TODO: Pull prices from datatables. @@ -124,10 +124,14 @@ static inline void FillItemCollector(ABuildingItemCollectorActor* ItemCollector, constexpr bool bPrint = false; - std::vector LootDrops = PickLootDrops(LootTierGroup, LootTier, bPrint); + std::vector LootDrops = PickLootDrops(LootTierGroup, GameState->GetWorldLevel(), LootTier, bPrint); if (LootDrops.size() == 0) + { + // LOG_WARN(LogGame, "Failed to find LootDrops for vending machine loot tier: {}", LootTier); + // ItemCollectorIt--; // retry (?) continue; + } for (int LootDropIt = 0; LootDropIt < LootDrops.size(); LootDropIt++) { @@ -168,7 +172,7 @@ static inline void FillItemCollector(ABuildingItemCollectorActor* ItemCollector, for (int LootDropIt = 0; LootDropIt < LootDrops.size(); LootDropIt++) { - auto ItemEntry = FFortItemEntry::MakeItemEntry(LootDrops[LootDropIt]->GetItemDefinition(), LootDrops[LootDropIt]->GetCount(), LootDrops[LootDropIt]->GetLoadedAmmo()); + auto ItemEntry = LootDrops[LootDropIt].ItemEntry; // FFortItemEntry::MakeItemEntry(LootDrops[LootDropIt]->GetItemDefinition(), LootDrops[LootDropIt]->GetCount(), LootDrops[LootDropIt]->GetLoadedAmmo(), MAX_DURABILITY, LootDrops[LootDropIt]->GetLevel()); if (!ItemEntry) continue; @@ -202,7 +206,7 @@ static inline void FillItemCollector(ABuildingItemCollectorActor* ItemCollector, if (StartingGoalLevelOffset != -1) ItemCollector->Get(StartingGoalLevelOffset) = LootTier; - static auto VendingMachineClass = FindObject("/Game/Athena/Items/Gameplay/VendingMachine/B_Athena_VendingMachine.B_Athena_VendingMachine_C"); + static auto VendingMachineClass = FindObject(L"/Game/Athena/Items/Gameplay/VendingMachine/B_Athena_VendingMachine.B_Athena_VendingMachine_C"); if (ItemCollector->IsA(VendingMachineClass)) { @@ -274,7 +278,19 @@ static inline void FillVendingMachines() continue; } - FillItemCollector(VendingMachine, OverrideLootTierGroup, Out - 1, true, true); + /* + + LOOT LEVELS: + + 0 - Common + 1 - Uncommon + 2 - Rare + 3 - Epic + 4 - Legendary + + */ + + FillItemCollector(VendingMachine, OverrideLootTierGroup, true, Out - 1); } auto AllVendingMachinesNum = AllVendingMachines.Num();