Przeglądaj źródła

Generate Reputation UI bson files (#7340)

Vincent Stumpf 2 lat temu
rodzic
commit
4661016445

+ 33 - 0
db/import-tmpl/reputation_group.yml

@@ -0,0 +1,33 @@
+# This file is a part of rAthena.
+#   Copyright(C) 2022 rAthena Development Team
+#   https://rathena.org - https://github.com/rathena
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+###########################################################################
+# Reputation Group Database
+###########################################################################
+#
+# Reputation Group Settings
+#
+###########################################################################
+# - Id                                  Client side group index.
+#   ScriptName                          Unused? Used for "ID" in client
+#   Name                                Visible name in window
+#   ReputeList                          List of Reputations
+###########################################################################
+
+Header:
+  Type: REPUTATION_GROUP_DB
+  Version: 1

+ 43 - 0
db/re/generator/reputation.yml

@@ -0,0 +1,43 @@
+# This file is a part of rAthena.
+#   Copyright(C) 2022 rAthena Development Team
+#   https://rathena.org - https://github.com/rathena
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+###########################################################################
+# Reputation Database
+###########################################################################
+#
+# Reputation Settings
+#
+###########################################################################
+# - Id                                  Client side index.
+#   Visibility                          Always = Always show
+#                                       Never = Never show
+#                                       Exist = Only show if greater than 0
+###########################################################################
+
+Header:
+  Type: REPUTATION_DB
+  Version: 1
+
+Body:
+  - Id: 1
+    Visibility: Always
+  - Id: 2
+    Visibility: Always
+  - Id: 3
+    Visibility: Exist
+  - Id: 4
+    Visibility: Exist

+ 51 - 0
db/re/generator/reputation_group.yml

@@ -0,0 +1,51 @@
+# This file is a part of rAthena.
+#   Copyright(C) 2022 rAthena Development Team
+#   https://rathena.org - https://github.com/rathena
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+###########################################################################
+# Reputation Group Database
+###########################################################################
+#
+# Reputation Group Settings
+#
+###########################################################################
+# - Id                                  Client side group index.
+#   ScriptName                          Unused? Used for "ID" in client
+#   Name                                Visible name in window
+#   ReputeList                          List of Reputations
+###########################################################################
+
+Header:
+  Type: REPUTATION_GROUP_DB
+  Version: 1
+
+Body:
+  - Id: 1
+    ScriptName: MonsterGroup1
+    Name: Monster Friends
+    ReputeList:
+      - 1
+      - 2
+  - Id: 2
+    ScriptName: Arunafelts
+    Name: Arunafeltz
+    ReputeList:
+      - 3
+  - Id: 3
+    ScriptName: Isgard
+    Name: Isgard
+    ReputeList:
+      - 4

+ 5 - 0
db/re/reputation.yml

@@ -54,3 +54,8 @@ Body:
     Variable: RepPointsIsgard
     Minimum: -3000
     Maximum: 3000
+
+Footer:
+  Imports:
+  - Path: db/re/generator/reputation.yml
+    Generator: true

+ 38 - 0
db/re/reputation_group.yml

@@ -0,0 +1,38 @@
+# This file is a part of rAthena.
+#   Copyright(C) 2022 rAthena Development Team
+#   https://rathena.org - https://github.com/rathena
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+###########################################################################
+# Reputation Group Database
+###########################################################################
+#
+# Reputation Group Settings
+#
+###########################################################################
+# - Id                                  Client side group index.
+#   ScriptName                          Unused? Used for "ID" in client
+#   Name                                Visible name in window
+#   ReputeList                          List of Reputations
+###########################################################################
+
+Header:
+  Type: REPUTATION_GROUP_DB
+  Version: 1
+
+Footer:
+  Imports:
+    - Path: db/re/generator/reputation_group.yml
+      Generator: true

+ 39 - 0
db/reputation_group.yml

@@ -0,0 +1,39 @@
+# This file is a part of rAthena.
+#   Copyright(C) 2022 rAthena Development Team
+#   https://rathena.org - https://github.com/rathena
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+###########################################################################
+# Reputation Group Database
+###########################################################################
+#
+# Reputation Group Settings
+#
+###########################################################################
+# - Id                                  Client side group index.
+#   ScriptName                          Unused? Used for "ID" in client
+#   Name                                Visible name in window
+#   ReputeList                          List of Reputations
+###########################################################################
+
+Header:
+  Type: REPUTATION_GROUP_DB
+  Version: 1
+
+Footer:
+  Imports:
+    - Path: db/re/reputation_group.yml
+      Mode: Renewal
+    - Path: db/import/reputation_group.yml

+ 3 - 3
doc/map_server_generator.md

@@ -2,8 +2,6 @@
 
 This is a tool to generate files that are hard to manually create.
 
-Only navigation files can be generated at this time.
-
 ## How to run
 ### Linux
 Run `make tools`.
@@ -21,6 +19,8 @@ On Windows, prefix with `/`
 
 option | feature
 ---|---
-generate-navi | create navigation files
+`generate-navi` | create navigation files
+`generate-reputation` | create reputation bson files
+`generate-itemmoveinfo` | create itemmoveinfov5.txt
 
 

+ 14 - 1
src/common/database.cpp

@@ -198,7 +198,16 @@ void YamlDatabase::parseImports( const ryml::Tree& rootNode ){
 						// Skip this import
 						continue;
 					}
-				}				
+				}
+
+				if (this->nodeExists(node, "Generator")) {
+					bool isGenerator;
+					if (!this->asBool(node, "Generator", isGenerator)) {
+						continue;
+					}
+					if (!(shouldLoadGenerator && isGenerator))
+						continue; // skip import
+				}
 
 				this->load( importFile );
 			}
@@ -358,6 +367,10 @@ std::string YamlDatabase::getCurrentFile(){
 	return this->currentFile;
 }
 
+void YamlDatabase::setGenerator(bool shouldLoad) {
+	shouldLoadGenerator = shouldLoad;
+}
+
 void on_yaml_error( const char* msg, size_t len, ryml::Location loc, void *user_data ){
 	throw std::runtime_error( msg );
 }

+ 3 - 0
src/common/database.hpp

@@ -23,6 +23,7 @@ private:
 	uint16 version;
 	uint16 minimumVersion;
 	std::string currentFile;
+	bool shouldLoadGenerator{false};
 
 	bool verifyCompatibility( const ryml::Tree& rootNode );
 	bool load( const std::string& path );
@@ -56,6 +57,8 @@ protected:
 	bool asUInt16Rate(const ryml::NodeRef& node, const std::string& name, uint16& out, uint16 maximum=10000);
 	bool asUInt32Rate(const ryml::NodeRef& node, const std::string& name, uint32& out, uint32 maximum=10000);
 
+	void setGenerator(bool shouldLoad);
+
 	virtual void loadingFinished();
 
 public:

+ 5 - 2
src/map/Makefile.in

@@ -13,6 +13,9 @@ RAPIDYAML_AR = ../../3rdparty/rapidyaml/obj/ryml.a
 RAPIDYAML_H = $(shell find ../../3rdparty/rapidyaml/ -type f -name "*.h*")
 RAPIDYAML_INCLUDE = -I../../3rdparty/rapidyaml/src -I../../3rdparty/rapidyaml/ext/c4core/src
 
+NLOHMANN_H = $(shell find ../../3rdparty/json/include/nlohmann/ -type f -name "*.hpp")
+NLOHMANN_INCLUDE = -I../../3rdparty/json/include
+
 MAP_OBJ = $(shell ls *.cpp | sed -e "s/\.cpp/\.o/g")
 #MAP_OBJ += $(shell ls *.c | sed -e "s/\.c/\.o/g")
 MAP_DIR_OBJ = $(MAP_OBJ:%=obj/%)
@@ -116,9 +119,9 @@ obj-gen/npc.o: npc.cpp $(MAP_H) $(COMMON_H) $(LIBCONFIG_H) $(RAPIDYAML_H)
 	@echo "	CXX	$< (custom rule)"
 	@@CXX@ @CXXFLAG_CLEARS@ $(TOOLS_FLAGS) $(COMMON_INCLUDE) $(LIBCONFIG_INCLUDE) $(PCRE_CFLAGS) $(RAPIDYAML_INCLUDE) @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
 	
-obj-gen/%.o: %.cpp $(MAP_H) $(COMMON_H) $(LIBCONFIG_H) $(RAPIDYAML_H)
+obj-gen/%.o: %.cpp $(MAP_H) $(COMMON_H) $(LIBCONFIG_H) $(RAPIDYAML_H) $(NLOHMANN_H)
 	@echo "	CXX	$<"
-	@@CXX@ @CXXFLAGS@ $(TOOLS_FLAGS) $(COMMON_INCLUDE) $(LIBCONFIG_INCLUDE) $(PCRE_CFLAGS) $(RAPIDYAML_INCLUDE) @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
+	@@CXX@ @CXXFLAGS@ $(TOOLS_FLAGS) $(COMMON_INCLUDE) $(LIBCONFIG_INCLUDE) $(PCRE_CFLAGS) $(RAPIDYAML_INCLUDE) $(NLOHMANN_INCLUDE) @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
 
 # missing object files
 $(COMMON_AR):

+ 5 - 4
src/map/map-server-generator.vcxproj

@@ -111,7 +111,7 @@
       <DisableSpecificWarnings>4018;4200</DisableSpecificWarnings>
       <MultiProcessorCompilation>true</MultiProcessorCompilation>
       <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-      <AdditionalIncludeDirectories>$(SolutionDir)\3rdparty\rapidyaml\src;$(SolutionDir)\3rdparty\rapidyaml\ext\c4core\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>$(SolutionDir)\3rdparty\rapidyaml\src;$(SolutionDir)\3rdparty\rapidyaml\ext\c4core\src;$(SolutionDir)\3rdparty\json\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
     </ClCompile>
     <Link>
       <SubSystem>Console</SubSystem>
@@ -128,7 +128,7 @@
       <PreprocessorDefinitions>$(DefineConstants);MAP_GENERATOR;WIN32;FD_SETSIZE=4096;PCRE_SUPPORT;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_WINSOCK_DEPRECATED_NO_WARNINGS;LIBCONFIG_STATIC;YY_USE_CONST;_DEBUG;_CONSOLE;_LIB;_ITERATOR_DEBUG_LEVEL=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <DisableSpecificWarnings>4018</DisableSpecificWarnings>
       <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-      <AdditionalIncludeDirectories>$(SolutionDir)\3rdparty\rapidyaml\src;$(SolutionDir)\3rdparty\rapidyaml\ext\c4core\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>$(SolutionDir)\3rdparty\rapidyaml\src;$(SolutionDir)\3rdparty\rapidyaml\ext\c4core\src;$(SolutionDir)\3rdparty\json\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
     </ClCompile>
     <Link>
       <SubSystem>Console</SubSystem>
@@ -147,7 +147,7 @@
       <PreprocessorDefinitions>$(DefineConstants);MAP_GENERATOR;WIN32;FD_SETSIZE=4096;PCRE_SUPPORT;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_WINSOCK_DEPRECATED_NO_WARNINGS;LIBCONFIG_STATIC;YY_USE_CONST;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
       <DisableSpecificWarnings>4018</DisableSpecificWarnings>
-      <AdditionalIncludeDirectories>$(SolutionDir)\3rdparty\rapidyaml\src;$(SolutionDir)\3rdparty\rapidyaml\ext\c4core\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>$(SolutionDir)\3rdparty\rapidyaml\src;$(SolutionDir)\3rdparty\rapidyaml\ext\c4core\src;$(SolutionDir)\3rdparty\json\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
     </ClCompile>
     <Link>
       <SubSystem>Console</SubSystem>
@@ -169,7 +169,7 @@
       <PreprocessorDefinitions>$(DefineConstants);MAP_GENERATOR;WIN32;FD_SETSIZE=4096;PCRE_SUPPORT;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_WINSOCK_DEPRECATED_NO_WARNINGS;LIBCONFIG_STATIC;YY_USE_CONST;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
       <DisableSpecificWarnings>4018</DisableSpecificWarnings>
-      <AdditionalIncludeDirectories>$(SolutionDir)\3rdparty\rapidyaml\src;$(SolutionDir)\3rdparty\rapidyaml\ext\c4core\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>$(SolutionDir)\3rdparty\rapidyaml\src;$(SolutionDir)\3rdparty\rapidyaml\ext\c4core\src;$(SolutionDir)\3rdparty\json\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
     </ClCompile>
     <Link>
       <SubSystem>Console</SubSystem>
@@ -368,5 +368,6 @@
     <Copy SourceFiles="$(SolutionDir)db\import-tmpl\status.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\status.yml')" />
     <Copy SourceFiles="$(SolutionDir)db\import-tmpl\stylist.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\stylist.yml')" />
     <MakeDir Directories="$(SolutionDir)generated\clientside\data\luafiles514\lua files\navigation\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)generated\clientside\data\luafiles514\lua files\navigation\')" />
+    <MakeDir Directories="$(SolutionDir)generated\clientside\data\contentdata\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)generated\clientside\data\contentdata\')" />
   </Target>
 </Project>

+ 5 - 0
src/map/map.cpp

@@ -192,6 +192,7 @@ int enable_grf = 0;	//To enable/disable reading maps from GRF files, bypassing m
 struct s_generator_options {
 	bool navi;
 	bool itemmoveinfo;
+	bool reputation;
 } gen_options;
 #endif
 
@@ -5106,6 +5107,8 @@ int mapgenerator_get_options(int argc, char** argv) {
 				gen_options.navi = true;
 			} else if (strcmp(arg, "generate-itemmoveinfo") == 0) {
 				gen_options.itemmoveinfo = true;
+			} else if (strcmp(arg, "generate-reputation") == 0) {
+				gen_options.reputation = true;
 			} else {
 				// pass through to default get_options
 				continue;
@@ -5297,6 +5300,8 @@ int do_init(int argc, char *argv[])
 		navi_create_lists();
 	if (gen_options.itemmoveinfo)
 		itemdb_gen_itemmoveinfo();
+	if (gen_options.reputation)
+		pc_reputation_generate();
 	runflag = CORE_ST_STOP;
 #endif
 

+ 174 - 0
src/map/pc.cpp

@@ -8,6 +8,12 @@
 #include <math.h>
 #include <stdlib.h>
 
+#ifdef MAP_GENERATOR
+#include <fstream>
+#include <iostream>
+#include <nlohmann/json.hpp>
+#endif
+
 #include "../common/cbasetypes.hpp"
 #include "../common/core.hpp" // get_svn_revision()
 #include "../common/database.hpp"
@@ -343,6 +349,29 @@ uint64 ReputationDatabase::parseBodyNode( const ryml::NodeRef& node ){
 		}
 	}
 
+#ifdef MAP_GENERATOR
+	if (this->nodeExists(node, "Visibility")) {
+		std::string visibility;
+		if (!this->asString(node, "Visibility", visibility)) {
+			return 0;
+		}
+		if (visibility == "Always")
+			reputation->visibility = s_reputation::e_visibility::ALWAYS;
+		else if (visibility == "Never")
+			reputation->visibility = s_reputation::e_visibility::NEVER;
+		else if (visibility == "Exist")
+			reputation->visibility = s_reputation::e_visibility::EXIST;
+		else {
+			this->invalidWarning(node, "Visibility \"%s\" unknown.\n", visibility.c_str());
+			return 0;
+		}
+	} else {
+		if (!exists) {
+			reputation->visibility = s_reputation::e_visibility::ALWAYS;
+		}
+	}
+#endif
+
 	if( !exists ){
 		this->put( id, reputation );
 	}
@@ -352,6 +381,145 @@ uint64 ReputationDatabase::parseBodyNode( const ryml::NodeRef& node ){
 
 ReputationDatabase reputation_db;
 
+const std::string ReputationGroupDatabase::getDefaultLocation() {
+	return std::string(db_path) + "/reputation_group.yml";
+}
+
+uint64 ReputationGroupDatabase::parseBodyNode(const ryml::NodeRef& node) {
+	int64 id;
+
+	if (!this->asInt64(node, "Id", id)) {
+		return 0;
+	}
+
+	std::shared_ptr<s_reputationgroup> group = this->find(id);
+	bool exists = group != nullptr;
+
+	if (!exists) {
+		if (!this->nodesExist(node, {"Name", "ReputeList"})) {
+			return 0;
+		}
+
+		group = std::make_shared<s_reputationgroup>();
+		group->id = id;
+	}
+
+	if (this->nodeExists(node, "Name")) {
+		std::string name;
+		if (!this->asString(node, "Name", name)) {
+			return 0;
+		}
+		group->name = name;
+	}
+
+	if (this->nodeExists(node, "ScriptName")) {
+		std::string script_name;
+		if (!this->asString(node, "ScriptName", script_name)) {
+			return 0;
+		}
+		group->script_name = script_name;
+	}
+
+	if (this->nodeExists(node, "ReputeList")) {
+		const auto& reputelist = node[c4::to_csubstr("ReputeList")];
+		for (const auto& repute : reputelist) {
+			int64 repute_id;
+			try {
+				repute >> repute_id;
+			} catch (std::runtime_error const&) {
+				this->invalidWarning(node, "Value \"%s\" cannot be parsed as int64.\n", repute.val().str);
+				continue;
+			}
+
+			if (!reputation_db.find(repute_id)) {
+				this->invalidWarning(node, "Reputation id %lld does not exist in reputation_db!\n", repute_id);
+				continue;
+			}
+
+			group->reputations.push_back(repute_id);
+		}
+	}
+
+
+	if (!exists) {
+		this->put(id, group);
+	}
+
+	return 1;
+}
+
+ReputationGroupDatabase reputationgroup_db;
+
+void pc_reputation_generate() {
+#ifdef MAP_GENERATOR
+	const std::string filePrefix = "generated/clientside/data/contentdata/";
+	auto reputeInfo = nlohmann::json::object();
+	for (const auto& pair : reputation_db) {
+		auto id = pair.first;
+		auto rep = pair.second;
+		nlohmann::json node;
+		switch (rep->visibility) {
+		case s_reputation::e_visibility::ALWAYS:
+			node["Invisible"] = "VISIBLE_TRUE";
+			break;
+		case s_reputation::e_visibility::NEVER:
+			node["Invisible"] = "VISIBLE_FALSE";
+			break;
+		case s_reputation::e_visibility::EXIST:
+			node["Invisible"] = "VISIBLE_EXIST";
+			break;
+		}
+		node["MaxPoint_Negative"] = std::abs(rep->minimum);
+		node["MaxPoint_Positive"] = std::abs(rep->maximum);
+		node["Name"] = rep->name;
+
+		reputeInfo[std::to_string(id)] = node;
+	}
+
+	auto j = nlohmann::json::object();
+	j["reputeInfo"] = reputeInfo;
+	// std::cout << j.dump(2) << "\n";
+
+	auto bson = nlohmann::json::to_bson(j);
+
+	auto reputation_file = std::ofstream(filePrefix + "./reputeinfodata.bson", std::ios::binary);
+	if (!reputation_file) {
+		ShowError("Failed to create reputation file.\n");
+		ShowError("Maybe the file directory \"%s\" does not exist?\n", filePrefix.c_str());
+		ShowInfo("Create the directory and rerun map-server-generator\n");
+		exit(1);
+	}
+
+	reputation_file.write((const char *)&bson[0], bson.size());
+
+	auto reputeGroupInfo = nlohmann::json::object();
+	for (const auto& pair : reputationgroup_db) {
+		auto id = pair.first;
+		auto group = pair.second;
+		nlohmann::json node;
+
+		node["ID"] = group->script_name;
+		node["Name"] = group->name;
+		node["ReputeList"] = group->reputations;
+
+		reputeGroupInfo[std::to_string(id)] = node;
+	}
+	j = nlohmann::json::object();
+	j["ReputeGroup"] = reputeGroupInfo;
+	// std::cout << j.dump(2) << "\n";
+	bson = nlohmann::json::to_bson(j);
+	auto reputation_group_file = std::ofstream(filePrefix + "./reputegroupdata.bson", std::ios::binary);
+	if (!reputation_group_file) {
+		ShowError("Failed to create reputation group file.\n");
+		ShowError("Maybe the file directory \"%s\" does not exist?\n", filePrefix.c_str());
+		ShowInfo("Create the directory and rerun map-server-generator\n");
+		exit(1);
+	}
+
+	reputation_group_file.write((const char *)&bson[0], bson.size());
+#endif
+}
+
 const std::string PenaltyDatabase::getDefaultLocation(){
 	return std::string( db_path ) + "/level_penalty.yml";
 }
@@ -15425,6 +15593,9 @@ void do_final_pc(void) {
 
 	attendance_db.clear();
 	reputation_db.clear();
+#ifdef MAP_GENERATOR
+	reputationgroup_db.clear();
+#endif
 	penalty_db.clear();
 	captcha_db.clear();
 }
@@ -15437,6 +15608,9 @@ void do_init_pc(void) {
 	pc_read_motd(); // Read MOTD [Valaris]
 	attendance_db.load();
 	reputation_db.load();
+#ifdef MAP_GENERATOR
+	reputationgroup_db.load();
+#endif
 	captcha_db.load();
 
 	add_timer_func_list(pc_invincible_timer, "pc_invincible_timer");

+ 31 - 1
src/map/pc.hpp

@@ -1273,12 +1273,17 @@ struct s_reputation{
 	std::string variable;
 	int64 minimum;
 	int64 maximum;
+#ifdef MAP_GENERATOR
+	enum e_visibility {ALWAYS, NEVER, EXIST} visibility;
+#endif
 };
 
 class ReputationDatabase : public TypesafeYamlDatabase<int64, s_reputation>{
 public:
 	ReputationDatabase() : TypesafeYamlDatabase( "REPUTATION_DB", 1 ){
-
+#ifdef MAP_GENERATOR
+	setGenerator(true);
+#endif
 	}
 
 	const std::string getDefaultLocation() override;
@@ -1287,6 +1292,27 @@ public:
 
 extern ReputationDatabase reputation_db;
 
+struct s_reputationgroup {
+	int64 id;
+	std::string script_name;
+	std::string name;
+	std::vector<int64> reputations;
+};
+
+class ReputationGroupDatabase : public TypesafeYamlDatabase<int64, s_reputationgroup> {
+public:
+	ReputationGroupDatabase() : TypesafeYamlDatabase("REPUTATION_GROUP_DB", 1) {
+#ifdef MAP_GENERATOR
+	setGenerator(true);
+#endif
+	}
+
+	const std::string getDefaultLocation() override;
+	uint64 parseBodyNode(const ryml::NodeRef& node) override;
+};
+
+extern ReputationGroupDatabase reputationgroup_db;
+
 struct s_statpoint_entry{
 	uint16 level;
 	uint32 statpoints;
@@ -1708,4 +1734,8 @@ void pc_macro_detector_disconnect(map_session_data &sd);
 void pc_macro_reporter_area_select(map_session_data &sd, const int16 x, const int16 y, const int8 radius);
 void pc_macro_reporter_process(map_session_data &ssd, map_session_data &tsd);
 
+#ifdef MAP_GENERATOR
+void pc_reputation_generate();
+#endif
+
 #endif /* PC_HPP */