Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,22 @@ file(GLOB SRC_FILES CONFIGURE_DEPENDS
"${CMAKE_CURRENT_SOURCE_DIR}/src/dllmain.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/Loader/*.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/Loader/Blueprint/PalBlueprintMod.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/Loader/Spawner/PalListInfo.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/Loader/Spawner/PalSpawnGroupListInfo.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/Loader/Spawner/SpawnerInfo.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/SDK/*.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/SDK/Classes/*.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/SDK/Classes/Custom/*.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/SDK/Classes/Custom/DataTable/TableSerializer.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/SDK/Helper/*.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/SDK/Structs/*.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/SDK/Structs/Reflected/*.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/SDK/Structs/Custom/*.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/SDK/Structs/Custom/DataTable/FTableSerializerRow.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/Tools/EnumSchemaDefinitionGenerator.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/Utility/Config.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/Utility/JsonHelpers.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/Utility/EnumHelpers.cpp"
)

add_library(${TARGET} SHARED ${SRC_FILES})
Expand Down
58 changes: 58 additions & 0 deletions assets/examples/NewSpawnsAtPlateau/spawns/new_spawns.jsonc
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
[
{
"Type": "MonoNPC", // Type should be either MonoNPC or Sheet
"NPCID": "PalDealer",
"OtomoId": "PinkCat", // This is the Pal that the NPC summons when it is attacked
"Level": 2,
"Location": { "X": -342040.178, "Y": 264211.779, "Z": 4050.933 },
"Rotation": { "Pitch": 0.0, "Yaw": 0.0, "Roll": 0.0 }
},
{
"Type": "Sheet",
"Location": { "X": -342040.178, "Y": 263611.779, "Z": 4050.933 },
"Rotation": { "Pitch": 0.0, "Yaw": 0.0, "Roll": 0.0 },
"SpawnerName": "PalSchema_Custom_Spawn001",
"SpawnGroupList": [
{
"Weight": 50,
"PalList": [
{
"PalId": "Plesiosaur",
"Level": 25,
"Level_Max": 30,
"Num": 1,
"Num_Max": 1
},
{
"PalId": "SheepBall",
"Level": 1,
"Level_Max": 5,
"Num": 1,
"Num_Max": 2
}
]
}
]
},
{
"Type": "Sheet",
"Location": { "X": -342040.178, "Y": 262811.779, "Z": 4050.933 },
"Rotation": { "Pitch": 0.0, "Yaw": 0.0, "Roll": 0.0 },
"SpawnerName": "PalSchema_Custom_Boss_Spawn001",
"SpawnerType": "FieldBoss", // Should be FieldBoss if you want it to be a proper boss
"SpawnGroupList": [
{
"Weight": 50,
"PalList": [
{
"PalId": "BOSS_DarkMechaDragon",
"Level": 25,
"Level_Max": 25,
"Num": 1,
"Num_Max": 1
}
]
}
]
}
]
25 changes: 13 additions & 12 deletions include/Loader/PalHumanModLoader.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include <set>
#include "Loader/PalModLoaderBase.h"
#include "nlohmann/json.hpp"

Expand All @@ -17,7 +18,7 @@ namespace Palworld {
void Initialize();

virtual void Load(const nlohmann::json& json) override final;

private:
void Add(const RC::Unreal::FName& CharacterId, const nlohmann::json& properties);

void Edit(uint8_t* TableRow, const RC::Unreal::FName& CharacterId, const nlohmann::json& properties);
Expand All @@ -34,16 +35,16 @@ namespace Palworld {

void AddShop(const RC::Unreal::FName& CharacterId, const nlohmann::json& properties);

RC::Unreal::UDataTable* n_dataTable;
RC::Unreal::UDataTable* n_iconDataTable;
RC::Unreal::UDataTable* n_palBpClassTable;
RC::Unreal::UDataTable* n_dropItemTable;
RC::Unreal::UDataTable* n_npcNameTable;
RC::Unreal::UDataTable* n_palShortDescTable;
RC::Unreal::UDataTable* n_palLongDescTable;
RC::Unreal::UDataTable* n_npcTalkFlowTable;
RC::Unreal::UDataTable* n_ItemShopLotteryDataTable;
RC::Unreal::UDataTable* n_ItemShopCreateDataTable;
RC::Unreal::UDataTable* n_ItemShopSettingDataTable;
RC::Unreal::UDataTable* n_dataTable = nullptr;
RC::Unreal::UDataTable* n_iconDataTable = nullptr;
RC::Unreal::UDataTable* n_palBpClassTable = nullptr;
RC::Unreal::UDataTable* n_dropItemTable = nullptr;
RC::Unreal::UDataTable* n_npcNameTable = nullptr;
RC::Unreal::UDataTable* n_palShortDescTable = nullptr;
RC::Unreal::UDataTable* n_palLongDescTable = nullptr;
RC::Unreal::UDataTable* n_npcTalkFlowTable = nullptr;
RC::Unreal::UDataTable* n_ItemShopLotteryDataTable = nullptr;
RC::Unreal::UDataTable* n_ItemShopCreateDataTable = nullptr;
RC::Unreal::UDataTable* n_ItemShopSettingDataTable = nullptr;
};
}
13 changes: 13 additions & 0 deletions include/Loader/PalMainLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "Loader/PalEnumLoader.h"
#include "Loader/PalHelpGuideModLoader.h"
#include "Loader/PalResourceLoader.h"
#include "Loader/PalSpawnLoader.h"
#include "FileWatch.hpp"

namespace RC::Unreal {
Expand All @@ -23,6 +24,7 @@ namespace RC::Unreal {

namespace UECustom {
class UCompositeDataTable;
class UWorldPartitionRuntimeLevelStreamingCell;
}

namespace Palworld {
Expand Down Expand Up @@ -53,9 +55,16 @@ namespace Palworld {
PalEnumLoader EnumLoader;
PalHelpGuideModLoader HelpGuideModLoader;
PalResourceLoader ResourceLoader;
PalSpawnLoader SpawnLoader;

std::unique_ptr<filewatch::FileWatch<std::wstring>> m_fileWatch;

void HookDatatableSerialize();

void HookStaticItemDataTable_Get();

void HookWorldCleanup();

void SetupAutoReload();

// Makes PalSchema read paks from the 'PalSchema/mods' folder. Although the paks can be anywhere, prefer for them to be put inside 'YourModName/paks'.
Expand Down Expand Up @@ -90,17 +99,21 @@ namespace Palworld {

static RC::Unreal::UObject* StaticItemDataTable_Get(UPalStaticItemDataTable* This, RC::Unreal::FName ItemId);

static void UWorld_CleanupWorld(RC::Unreal::UWorld* This, bool bSessionEnded, bool bCleanupResources, RC::Unreal::UWorld* NewWorld);

bool m_hasInit = false;

static inline std::vector<std::function<void(RC::Unreal::UDataTable*)>> DatatableSerializeCallbacks;
static inline std::vector<std::function<void(RC::Unreal::UObject*)>> GameInstanceInitCallbacks;
static inline std::vector<std::function<void(RC::Unreal::UClass*)>> PostLoadCallbacks;
static inline std::vector<std::function<void(RC::Unreal::UWorld*)>> WorldCleanUp_Callbacks;
static inline std::vector<std::function<void()>> GetPakFoldersCallback;

static inline SafetyHookInline DatatableSerialize_Hook;
static inline SafetyHookInline GameInstanceInit_Hook;
static inline SafetyHookInline PostLoad_Hook;
static inline SafetyHookInline GetPakFolders_Hook;
static inline SafetyHookInline StaticItemDataTable_Get_Hook;
static inline SafetyHookInline WorldCleanUp_Hook;
};
}
64 changes: 64 additions & 0 deletions include/Loader/PalSpawnLoader.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#pragma once

#include "Unreal/NameTypes.hpp"
#include "Unreal/UnrealCoreStructs.hpp"
#include "Unreal/Rotator.hpp"
#include "Loader/PalModLoaderBase.h"
#include "Loader/Spawner/SpawnerInfo.h"
#include "nlohmann/json.hpp"

namespace RC::Unreal {
class UWorld;
class UDataTable;
}

namespace UECustom {
class UWorldPartitionRuntimeLevelStreamingCell;
}

namespace Palworld {
class AMonoNPCSpawner;

class PalSpawnLoader : public PalModLoaderBase {
public:
PalSpawnLoader();

~PalSpawnLoader();

void Initialize();

void Load(const std::filesystem::path::string_type& modName, const nlohmann::json& data);

void Reload(const std::filesystem::path::string_type& modName, const nlohmann::json& data);

void OnWorldCleanup(RC::Unreal::UWorld* World);

// This is called whenever a world partition is loaded within the main world.
void OnCellLoaded(UECustom::UWorldPartitionRuntimeLevelStreamingCell* cell);

// This is called whenever a world partition is unloaded within the main world.
void OnCellUnloaded(UECustom::UWorldPartitionRuntimeLevelStreamingCell* cell);
private:
RC::Unreal::UDataTable* m_bossSpawnerLocationData = nullptr;

// Storing loaded cells here for mod reloading purposes.
RC::Unreal::TArray<UECustom::UWorldPartitionRuntimeLevelStreamingCell*> m_loadedCells;
std::vector<PS::SpawnerInfo> m_spawns;

void RegisterSpawn(const std::filesystem::path::string_type& modName, const nlohmann::json& value);
void RegisterSheet(const std::filesystem::path::string_type& modName, PS::SpawnerInfo& spawnerInfo, const nlohmann::json& value);
void RegisterMonoNPC(const std::filesystem::path::string_type& modName, PS::SpawnerInfo& spawnerInfo, const nlohmann::json& value);

void ProcessCellSpawners(UECustom::UWorldPartitionRuntimeLevelStreamingCell* cell);
void CreateSpawner(UECustom::UWorldPartitionRuntimeLevelStreamingCell* cell, PS::SpawnerInfo& spawnerInfo);
void SpawnMonoNPC(UECustom::UWorldPartitionRuntimeLevelStreamingCell* cell, PS::SpawnerInfo& spawnerInfo);
void SpawnSheet(UECustom::UWorldPartitionRuntimeLevelStreamingCell* cell, PS::SpawnerInfo& spawnerInfo);

void AddBossSpawnLocationToMap(PS::SpawnerInfo& spawnerInfo);
void RemoveBossSpawnLocationFromMap(PS::SpawnerInfo& spawnerInfo);

void DestroySpawnersInCell(UECustom::UWorldPartitionRuntimeLevelStreamingCell* cell);

void UnloadMod(const std::filesystem::path::string_type& modName);
};
}
16 changes: 16 additions & 0 deletions include/Loader/Spawner/PalSpawnGroupListInfo.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#pragma once

#include <vector>
#include "SDK/Structs/PalListInfo.h"
#include "nlohmann/json_fwd.hpp"

namespace PS {
struct PalSpawnGroupListInfo {
int Weight = 10;
RC::Unreal::uint8 OnlyTime = 0;
RC::Unreal::uint8 OnlyWeather = 0;
std::vector<Palworld::PalListInfo> PalList;

void AddPalListInfo(const nlohmann::json& value);
};
}
63 changes: 63 additions & 0 deletions include/Loader/Spawner/SpawnerInfo.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#pragma once

#include "Unreal/NameTypes.hpp"
#include "Unreal/UnrealCoreStructs.hpp"
#include "Unreal/Rotator.hpp"
#include "SDK/Structs/Guid.h"
#include "Loader/Spawner/PalSpawnGroupListInfo.h"
#include "nlohmann/json_fwd.hpp"

namespace RC::Unreal {
class UWorld;
}

namespace UECustom {
class UWorldPartitionRuntimeLevelStreamingCell;
}

namespace PS {
class AMonoNPCSpawner;

enum class SpawnerType : RC::Unreal::uint8 {
Undefined,
Sheet,
MonoNPC
};

struct SpawnerInfo {
bool bExistsInWorld = false;
RC::Unreal::AActor* SpawnerActor = nullptr;
UECustom::UWorldPartitionRuntimeLevelStreamingCell* Cell = nullptr;
RC::StringType ModName{};
UECustom::FGuid Guid;

// Generic

SpawnerType Type = SpawnerType::Undefined;
RC::Unreal::FVector Location;
RC::Unreal::FRotator Rotation;

// MonoNPCSpawner

int Level = 1;
RC::Unreal::FName NPCID = RC::Unreal::NAME_None;
RC::Unreal::FName OtomoName = RC::Unreal::NAME_None;

// Sheet

RC::Unreal::FName SpawnerName = RC::Unreal::NAME_None;
RC::Unreal::uint8 SpawnerType = 0;
std::vector<PS::PalSpawnGroupListInfo> SpawnGroupList;
bool bHasMapIcon = false;

void Unload();

void AddSpawnGroupList(const nlohmann::json& value);

RC::StringType ToString();
private:
RC::StringType CachedString = TEXT("");

RC::Unreal::uint8 GetOnlyTimeFromString(const std::string& str);
};
}
18 changes: 18 additions & 0 deletions include/SDK/Classes/AMonoNPCSpawner.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#pragma once

#include "Unreal/AActor.hpp"

namespace Palworld {
class AMonoNPCSpawner : public RC::Unreal::AActor {
public:
int& GetLevel();

RC::Unreal::FName& GetHumanName();

RC::Unreal::FName& GetCharaName();

RC::Unreal::FName& GetOtomoName();

void Spawn();
};
}
15 changes: 15 additions & 0 deletions include/SDK/Classes/APalSpawnerStandard.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#pragma once

#include "Unreal/AActor.hpp"
#include "SDK/Structs/PalSpawnerGroup.h"

namespace Palworld {
class APalSpawnerStandard : public RC::Unreal::AActor {
public:
void AddSpawnerGroup(const PalSpawnerGroup& spawnerGroup);

void SetSpawnerName(const RC::Unreal::FName& spawnerName);

void SetSpawnerType(const RC::Unreal::uint8& spawnerType);
};
}
22 changes: 22 additions & 0 deletions include/SDK/Classes/Custom/DataTable/TableSerializer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#pragma once

#include "Unreal/NameTypes.hpp"
#include "SDK/Structs/Custom/DataTable/FTableSerializerRow.h"

namespace RC::Unreal {
class UDataTable;
}

namespace Palworld {
class TableSerializer {
public:
TableSerializer(RC::Unreal::UDataTable* table);

FTableSerializerRow* Add(const RC::Unreal::FName& rowId);

FTableSerializerRow* Edit(const RC::Unreal::FName& rowId);
private:
RC::Unreal::UDataTable* m_table = nullptr;
std::vector<std::unique_ptr<FTableSerializerRow>> m_rows;
};
}
Loading
Loading