Skip to content

Commit 05ea425

Browse files
authored
Merge pull request #69 from Okaetsu/spawner_work
Add support for creating NPC/Pal spawns
2 parents 7e703f2 + d3f4560 commit 05ea425

51 files changed

Lines changed: 2007 additions & 50 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CMakeLists.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,22 @@ file(GLOB SRC_FILES CONFIGURE_DEPENDS
1111
"${CMAKE_CURRENT_SOURCE_DIR}/src/dllmain.cpp"
1212
"${CMAKE_CURRENT_SOURCE_DIR}/src/Loader/*.cpp"
1313
"${CMAKE_CURRENT_SOURCE_DIR}/src/Loader/Blueprint/PalBlueprintMod.cpp"
14+
"${CMAKE_CURRENT_SOURCE_DIR}/src/Loader/Spawner/PalListInfo.cpp"
15+
"${CMAKE_CURRENT_SOURCE_DIR}/src/Loader/Spawner/PalSpawnGroupListInfo.cpp"
16+
"${CMAKE_CURRENT_SOURCE_DIR}/src/Loader/Spawner/SpawnerInfo.cpp"
1417
"${CMAKE_CURRENT_SOURCE_DIR}/src/SDK/*.cpp"
1518
"${CMAKE_CURRENT_SOURCE_DIR}/src/SDK/Classes/*.cpp"
1619
"${CMAKE_CURRENT_SOURCE_DIR}/src/SDK/Classes/Custom/*.cpp"
20+
"${CMAKE_CURRENT_SOURCE_DIR}/src/SDK/Classes/Custom/DataTable/TableSerializer.cpp"
1721
"${CMAKE_CURRENT_SOURCE_DIR}/src/SDK/Helper/*.cpp"
1822
"${CMAKE_CURRENT_SOURCE_DIR}/src/SDK/Structs/*.cpp"
23+
"${CMAKE_CURRENT_SOURCE_DIR}/src/SDK/Structs/Reflected/*.cpp"
1924
"${CMAKE_CURRENT_SOURCE_DIR}/src/SDK/Structs/Custom/*.cpp"
25+
"${CMAKE_CURRENT_SOURCE_DIR}/src/SDK/Structs/Custom/DataTable/FTableSerializerRow.cpp"
2026
"${CMAKE_CURRENT_SOURCE_DIR}/src/Tools/EnumSchemaDefinitionGenerator.cpp"
2127
"${CMAKE_CURRENT_SOURCE_DIR}/src/Utility/Config.cpp"
28+
"${CMAKE_CURRENT_SOURCE_DIR}/src/Utility/JsonHelpers.cpp"
29+
"${CMAKE_CURRENT_SOURCE_DIR}/src/Utility/EnumHelpers.cpp"
2230
)
2331

2432
add_library(${TARGET} SHARED ${SRC_FILES})
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
[
2+
{
3+
"Type": "MonoNPC", // Type should be either MonoNPC or Sheet
4+
"NPCID": "PalDealer",
5+
"OtomoId": "PinkCat", // This is the Pal that the NPC summons when it is attacked
6+
"Level": 2,
7+
"Location": { "X": -342040.178, "Y": 264211.779, "Z": 4050.933 },
8+
"Rotation": { "Pitch": 0.0, "Yaw": 0.0, "Roll": 0.0 }
9+
},
10+
{
11+
"Type": "Sheet",
12+
"Location": { "X": -342040.178, "Y": 263611.779, "Z": 4050.933 },
13+
"Rotation": { "Pitch": 0.0, "Yaw": 0.0, "Roll": 0.0 },
14+
"SpawnerName": "PalSchema_Custom_Spawn001",
15+
"SpawnGroupList": [
16+
{
17+
"Weight": 50,
18+
"PalList": [
19+
{
20+
"PalId": "Plesiosaur",
21+
"Level": 25,
22+
"Level_Max": 30,
23+
"Num": 1,
24+
"Num_Max": 1
25+
},
26+
{
27+
"PalId": "SheepBall",
28+
"Level": 1,
29+
"Level_Max": 5,
30+
"Num": 1,
31+
"Num_Max": 2
32+
}
33+
]
34+
}
35+
]
36+
},
37+
{
38+
"Type": "Sheet",
39+
"Location": { "X": -342040.178, "Y": 262811.779, "Z": 4050.933 },
40+
"Rotation": { "Pitch": 0.0, "Yaw": 0.0, "Roll": 0.0 },
41+
"SpawnerName": "PalSchema_Custom_Boss_Spawn001",
42+
"SpawnerType": "FieldBoss", // Should be FieldBoss if you want it to be a proper boss
43+
"SpawnGroupList": [
44+
{
45+
"Weight": 50,
46+
"PalList": [
47+
{
48+
"PalId": "BOSS_DarkMechaDragon",
49+
"Level": 25,
50+
"Level_Max": 25,
51+
"Num": 1,
52+
"Num_Max": 1
53+
}
54+
]
55+
}
56+
]
57+
}
58+
]

include/Loader/PalHumanModLoader.h

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#pragma once
22

3+
#include <set>
34
#include "Loader/PalModLoaderBase.h"
45
#include "nlohmann/json.hpp"
56

@@ -17,7 +18,7 @@ namespace Palworld {
1718
void Initialize();
1819

1920
virtual void Load(const nlohmann::json& json) override final;
20-
21+
private:
2122
void Add(const RC::Unreal::FName& CharacterId, const nlohmann::json& properties);
2223

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

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

37-
RC::Unreal::UDataTable* n_dataTable;
38-
RC::Unreal::UDataTable* n_iconDataTable;
39-
RC::Unreal::UDataTable* n_palBpClassTable;
40-
RC::Unreal::UDataTable* n_dropItemTable;
41-
RC::Unreal::UDataTable* n_npcNameTable;
42-
RC::Unreal::UDataTable* n_palShortDescTable;
43-
RC::Unreal::UDataTable* n_palLongDescTable;
44-
RC::Unreal::UDataTable* n_npcTalkFlowTable;
45-
RC::Unreal::UDataTable* n_ItemShopLotteryDataTable;
46-
RC::Unreal::UDataTable* n_ItemShopCreateDataTable;
47-
RC::Unreal::UDataTable* n_ItemShopSettingDataTable;
38+
RC::Unreal::UDataTable* n_dataTable = nullptr;
39+
RC::Unreal::UDataTable* n_iconDataTable = nullptr;
40+
RC::Unreal::UDataTable* n_palBpClassTable = nullptr;
41+
RC::Unreal::UDataTable* n_dropItemTable = nullptr;
42+
RC::Unreal::UDataTable* n_npcNameTable = nullptr;
43+
RC::Unreal::UDataTable* n_palShortDescTable = nullptr;
44+
RC::Unreal::UDataTable* n_palLongDescTable = nullptr;
45+
RC::Unreal::UDataTable* n_npcTalkFlowTable = nullptr;
46+
RC::Unreal::UDataTable* n_ItemShopLotteryDataTable = nullptr;
47+
RC::Unreal::UDataTable* n_ItemShopCreateDataTable = nullptr;
48+
RC::Unreal::UDataTable* n_ItemShopSettingDataTable = nullptr;
4849
};
4950
}

include/Loader/PalMainLoader.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "Loader/PalEnumLoader.h"
1515
#include "Loader/PalHelpGuideModLoader.h"
1616
#include "Loader/PalResourceLoader.h"
17+
#include "Loader/PalSpawnLoader.h"
1718
#include "FileWatch.hpp"
1819

1920
namespace RC::Unreal {
@@ -23,6 +24,7 @@ namespace RC::Unreal {
2324

2425
namespace UECustom {
2526
class UCompositeDataTable;
27+
class UWorldPartitionRuntimeLevelStreamingCell;
2628
}
2729

2830
namespace Palworld {
@@ -53,9 +55,16 @@ namespace Palworld {
5355
PalEnumLoader EnumLoader;
5456
PalHelpGuideModLoader HelpGuideModLoader;
5557
PalResourceLoader ResourceLoader;
58+
PalSpawnLoader SpawnLoader;
5659

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

62+
void HookDatatableSerialize();
63+
64+
void HookStaticItemDataTable_Get();
65+
66+
void HookWorldCleanup();
67+
5968
void SetupAutoReload();
6069

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

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

102+
static void UWorld_CleanupWorld(RC::Unreal::UWorld* This, bool bSessionEnded, bool bCleanupResources, RC::Unreal::UWorld* NewWorld);
103+
93104
bool m_hasInit = false;
94105

95106
static inline std::vector<std::function<void(RC::Unreal::UDataTable*)>> DatatableSerializeCallbacks;
96107
static inline std::vector<std::function<void(RC::Unreal::UObject*)>> GameInstanceInitCallbacks;
97108
static inline std::vector<std::function<void(RC::Unreal::UClass*)>> PostLoadCallbacks;
109+
static inline std::vector<std::function<void(RC::Unreal::UWorld*)>> WorldCleanUp_Callbacks;
98110
static inline std::vector<std::function<void()>> GetPakFoldersCallback;
99111

100112
static inline SafetyHookInline DatatableSerialize_Hook;
101113
static inline SafetyHookInline GameInstanceInit_Hook;
102114
static inline SafetyHookInline PostLoad_Hook;
103115
static inline SafetyHookInline GetPakFolders_Hook;
104116
static inline SafetyHookInline StaticItemDataTable_Get_Hook;
117+
static inline SafetyHookInline WorldCleanUp_Hook;
105118
};
106119
}

include/Loader/PalSpawnLoader.h

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#pragma once
2+
3+
#include "Unreal/NameTypes.hpp"
4+
#include "Unreal/UnrealCoreStructs.hpp"
5+
#include "Unreal/Rotator.hpp"
6+
#include "Loader/PalModLoaderBase.h"
7+
#include "Loader/Spawner/SpawnerInfo.h"
8+
#include "nlohmann/json.hpp"
9+
10+
namespace RC::Unreal {
11+
class UWorld;
12+
class UDataTable;
13+
}
14+
15+
namespace UECustom {
16+
class UWorldPartitionRuntimeLevelStreamingCell;
17+
}
18+
19+
namespace Palworld {
20+
class AMonoNPCSpawner;
21+
22+
class PalSpawnLoader : public PalModLoaderBase {
23+
public:
24+
PalSpawnLoader();
25+
26+
~PalSpawnLoader();
27+
28+
void Initialize();
29+
30+
void Load(const std::filesystem::path::string_type& modName, const nlohmann::json& data);
31+
32+
void Reload(const std::filesystem::path::string_type& modName, const nlohmann::json& data);
33+
34+
void OnWorldCleanup(RC::Unreal::UWorld* World);
35+
36+
// This is called whenever a world partition is loaded within the main world.
37+
void OnCellLoaded(UECustom::UWorldPartitionRuntimeLevelStreamingCell* cell);
38+
39+
// This is called whenever a world partition is unloaded within the main world.
40+
void OnCellUnloaded(UECustom::UWorldPartitionRuntimeLevelStreamingCell* cell);
41+
private:
42+
RC::Unreal::UDataTable* m_bossSpawnerLocationData = nullptr;
43+
44+
// Storing loaded cells here for mod reloading purposes.
45+
RC::Unreal::TArray<UECustom::UWorldPartitionRuntimeLevelStreamingCell*> m_loadedCells;
46+
std::vector<PS::SpawnerInfo> m_spawns;
47+
48+
void RegisterSpawn(const std::filesystem::path::string_type& modName, const nlohmann::json& value);
49+
void RegisterSheet(const std::filesystem::path::string_type& modName, PS::SpawnerInfo& spawnerInfo, const nlohmann::json& value);
50+
void RegisterMonoNPC(const std::filesystem::path::string_type& modName, PS::SpawnerInfo& spawnerInfo, const nlohmann::json& value);
51+
52+
void ProcessCellSpawners(UECustom::UWorldPartitionRuntimeLevelStreamingCell* cell);
53+
void CreateSpawner(UECustom::UWorldPartitionRuntimeLevelStreamingCell* cell, PS::SpawnerInfo& spawnerInfo);
54+
void SpawnMonoNPC(UECustom::UWorldPartitionRuntimeLevelStreamingCell* cell, PS::SpawnerInfo& spawnerInfo);
55+
void SpawnSheet(UECustom::UWorldPartitionRuntimeLevelStreamingCell* cell, PS::SpawnerInfo& spawnerInfo);
56+
57+
void AddBossSpawnLocationToMap(PS::SpawnerInfo& spawnerInfo);
58+
void RemoveBossSpawnLocationFromMap(PS::SpawnerInfo& spawnerInfo);
59+
60+
void DestroySpawnersInCell(UECustom::UWorldPartitionRuntimeLevelStreamingCell* cell);
61+
62+
void UnloadMod(const std::filesystem::path::string_type& modName);
63+
};
64+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#pragma once
2+
3+
#include <vector>
4+
#include "SDK/Structs/PalListInfo.h"
5+
#include "nlohmann/json_fwd.hpp"
6+
7+
namespace PS {
8+
struct PalSpawnGroupListInfo {
9+
int Weight = 10;
10+
RC::Unreal::uint8 OnlyTime = 0;
11+
RC::Unreal::uint8 OnlyWeather = 0;
12+
std::vector<Palworld::PalListInfo> PalList;
13+
14+
void AddPalListInfo(const nlohmann::json& value);
15+
};
16+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
#pragma once
2+
3+
#include "Unreal/NameTypes.hpp"
4+
#include "Unreal/UnrealCoreStructs.hpp"
5+
#include "Unreal/Rotator.hpp"
6+
#include "SDK/Structs/Guid.h"
7+
#include "Loader/Spawner/PalSpawnGroupListInfo.h"
8+
#include "nlohmann/json_fwd.hpp"
9+
10+
namespace RC::Unreal {
11+
class UWorld;
12+
}
13+
14+
namespace UECustom {
15+
class UWorldPartitionRuntimeLevelStreamingCell;
16+
}
17+
18+
namespace PS {
19+
class AMonoNPCSpawner;
20+
21+
enum class SpawnerType : RC::Unreal::uint8 {
22+
Undefined,
23+
Sheet,
24+
MonoNPC
25+
};
26+
27+
struct SpawnerInfo {
28+
bool bExistsInWorld = false;
29+
RC::Unreal::AActor* SpawnerActor = nullptr;
30+
UECustom::UWorldPartitionRuntimeLevelStreamingCell* Cell = nullptr;
31+
RC::StringType ModName{};
32+
UECustom::FGuid Guid;
33+
34+
// Generic
35+
36+
SpawnerType Type = SpawnerType::Undefined;
37+
RC::Unreal::FVector Location;
38+
RC::Unreal::FRotator Rotation;
39+
40+
// MonoNPCSpawner
41+
42+
int Level = 1;
43+
RC::Unreal::FName NPCID = RC::Unreal::NAME_None;
44+
RC::Unreal::FName OtomoName = RC::Unreal::NAME_None;
45+
46+
// Sheet
47+
48+
RC::Unreal::FName SpawnerName = RC::Unreal::NAME_None;
49+
RC::Unreal::uint8 SpawnerType = 0;
50+
std::vector<PS::PalSpawnGroupListInfo> SpawnGroupList;
51+
bool bHasMapIcon = false;
52+
53+
void Unload();
54+
55+
void AddSpawnGroupList(const nlohmann::json& value);
56+
57+
RC::StringType ToString();
58+
private:
59+
RC::StringType CachedString = TEXT("");
60+
61+
RC::Unreal::uint8 GetOnlyTimeFromString(const std::string& str);
62+
};
63+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#pragma once
2+
3+
#include "Unreal/AActor.hpp"
4+
5+
namespace Palworld {
6+
class AMonoNPCSpawner : public RC::Unreal::AActor {
7+
public:
8+
int& GetLevel();
9+
10+
RC::Unreal::FName& GetHumanName();
11+
12+
RC::Unreal::FName& GetCharaName();
13+
14+
RC::Unreal::FName& GetOtomoName();
15+
16+
void Spawn();
17+
};
18+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#pragma once
2+
3+
#include "Unreal/AActor.hpp"
4+
#include "SDK/Structs/PalSpawnerGroup.h"
5+
6+
namespace Palworld {
7+
class APalSpawnerStandard : public RC::Unreal::AActor {
8+
public:
9+
void AddSpawnerGroup(const PalSpawnerGroup& spawnerGroup);
10+
11+
void SetSpawnerName(const RC::Unreal::FName& spawnerName);
12+
13+
void SetSpawnerType(const RC::Unreal::uint8& spawnerType);
14+
};
15+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#pragma once
2+
3+
#include "Unreal/NameTypes.hpp"
4+
#include "SDK/Structs/Custom/DataTable/FTableSerializerRow.h"
5+
6+
namespace RC::Unreal {
7+
class UDataTable;
8+
}
9+
10+
namespace Palworld {
11+
class TableSerializer {
12+
public:
13+
TableSerializer(RC::Unreal::UDataTable* table);
14+
15+
FTableSerializerRow* Add(const RC::Unreal::FName& rowId);
16+
17+
FTableSerializerRow* Edit(const RC::Unreal::FName& rowId);
18+
private:
19+
RC::Unreal::UDataTable* m_table = nullptr;
20+
std::vector<std::unique_ptr<FTableSerializerRow>> m_rows;
21+
};
22+
}

0 commit comments

Comments
 (0)