Generate Reputation UI bson files (#7340)

This commit is contained in:
Vincent Stumpf 2022-11-27 00:53:54 -08:00 committed by GitHub
parent bc4934373d
commit 4661016445
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 449 additions and 11 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

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

View File

@ -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
db/reputation_group.yml Normal file
View File

@ -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

View File

@ -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

View File

@ -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 );
}

View File

@ -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:

View File

@ -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):

View File

@ -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>

View File

@ -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

View File

@ -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");

View File

@ -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 */