Splitted guild_skill_tree.txt into re and pre-re (#3841)

Converted Guild Skill Tree database to YAML

Please run csv2yaml to convert your existing databases if necessary.

Thanks to @aleos89, @Atemo and @Lemongrass3110
This commit is contained in:
Daegaladh
2019-03-11 19:57:52 +01:00
committed by Lemongrass3110
parent 54ac2ae132
commit cbe0d6b271
10 changed files with 541 additions and 103 deletions

View File

@@ -4,8 +4,10 @@
#include "guild.hpp"
#include <stdlib.h>
#include <yaml-cpp/yaml.h>
#include "../common/cbasetypes.hpp"
#include "../common/database.hpp"
#include "../common/ers.hpp"
#include "../common/malloc.hpp"
#include "../common/mapindex.hpp"
@@ -13,6 +15,7 @@
#include "../common/showmsg.hpp"
#include "../common/strlib.hpp"
#include "../common/timer.hpp"
#include "../common/utilities.hpp"
#include "../common/utils.hpp"
#include "battle.hpp"
@@ -28,6 +31,8 @@
#include "storage.hpp"
#include "trade.hpp"
using namespace rathena;
static DBMap* guild_db; // int guild_id -> struct guild*
static DBMap* castle_db; // int castle_id -> struct guild_castle*
static DBMap* guild_expcache_db; // uint32 char_id -> struct guild_expcache*
@@ -50,15 +55,139 @@ struct guild_expcache {
};
static struct eri *expcache_ers; //For handling of guild exp payment.
#define MAX_GUILD_SKILL_REQUIRE 5
struct s_guild_skill_tree {
int id;
int max;
struct{
short id;
short lv;
}need[MAX_GUILD_SKILL_REQUIRE];
} guild_skill_tree[MAX_GUILDSKILL];
struct s_guild_skill_requirement{
uint16 id;
uint16 lv;
};
struct s_guild_skill_tree{
uint16 id;
uint16 max;
std::unordered_map<uint16,std::shared_ptr<s_guild_skill_requirement>> need;
};
class GuildSkillTreeDatabase : public TypesafeYamlDatabase<uint16, s_guild_skill_tree>{
public:
GuildSkillTreeDatabase() : TypesafeYamlDatabase( "GUILD_SKILL_TREE_DB", 1 ){
}
const std::string getDefaultLocation();
uint64 parseBodyNode( const YAML::Node& node );
};
const std::string GuildSkillTreeDatabase::getDefaultLocation(){
return std::string(db_path) + "/guild_skill_tree.yml";
}
uint64 GuildSkillTreeDatabase::parseBodyNode( const YAML::Node &node ){
std::string name;
if( !this->asString( node, "Id", name ) ){
return 0;
}
uint16 skill_id;
if( !( skill_id = skill_name2id( name.c_str() ) ) ){
this->invalidWarning( node["Id"], "Invalid guild skill name \"%s\", skipping.\n", name.c_str() );
return 0;
}
if( !SKILL_CHK_GUILD( skill_id ) ){
this->invalidWarning( node["Id"], "Guild skill \"%s\" with Id %u is out of the guild skill range [%u-%u], skipping.\n", name.c_str(), skill_id, GD_SKILLBASE, GD_MAX );
return 0;
}
std::shared_ptr<s_guild_skill_tree> skill = this->find( skill_id );
bool exists = skill != nullptr;
if( !exists ){
if( !this->nodeExists( node, "MaxLevel" ) ){
this->invalidWarning( node, "Missing node \"MaxLevel\", skipping.\n" );
return 0;
}
skill = std::make_shared<s_guild_skill_tree>();
skill->id = skill_id;
}
if( this->nodeExists( node, "MaxLevel" ) ){
uint16 level;
if( !this->asUInt16( node, "MaxLevel", level ) ){
return 0;
}
// Enable Guild's Glory when required for emblems
if( skill_id == GD_GLORYGUILD && battle_config.require_glory_guild && level == 0 ){
level = 1;
}
skill->max = level;
}
if( this->nodeExists( node, "Required" ) ){
for( const YAML::Node& requiredNode : node["Required"] ){
std::string requiredName;
if( !this->asString( requiredNode, "Id", requiredName ) ){
return 0;
}
uint16 requiredSkillId;
if( !( requiredSkillId = skill_name2id( requiredName.c_str() ) ) ){
this->invalidWarning( requiredNode["Id"], "Invalid required guild skill name \"%s\", skipping.\n", requiredName.c_str() );
return 0;
}
if( !SKILL_CHK_GUILD( requiredSkillId ) ){
this->invalidWarning( requiredNode["Id"], "Required guild skill \"%s\" with Id %u is out of the guild skill range [%u-%u], skipping.\n", requiredName.c_str(), requiredSkillId, GD_SKILLBASE, GD_MAX );
return 0;
}
std::shared_ptr<s_guild_skill_requirement> requirement = util::umap_find( skill->need, requiredSkillId );
bool requirement_exists = requirement != nullptr;
if( !requirement_exists ){
if( !this->nodeExists( requiredNode, "Level" ) ){
this->invalidWarning( requiredNode, "Missing node \"Level\", skipping.\n" );
return 0;
}
requirement = std::make_shared<s_guild_skill_requirement>();
requirement->id = requiredSkillId;
}
if( this->nodeExists( requiredNode, "Level" ) ){
uint16 requiredLevel;
if( !this->asUInt16( requiredNode, "Level", requiredLevel ) ){
return 0;
}
if( requiredLevel == 0 ){
continue;
}
requirement->lv = requiredLevel;
}
if( !requirement_exists ){
skill->need[requiredSkillId] = requirement;
}
}
}
if( !exists ){
this->put( skill_id, skill );
}
return 1;
}
GuildSkillTreeDatabase guild_skill_tree_db;
TIMER_FUNC(guild_payexp_timer);
static TIMER_FUNC(guild_send_xy_timer);
@@ -68,7 +197,7 @@ struct npc_data **guild_flags;
unsigned short guild_flags_count;
/**
* Get guild skill index in guild_skill_tree
* Get guild skill index in guild structure of mmo.hpp
* @param skill_id
* @return Index in skill_tree or -1
**/
@@ -100,10 +229,14 @@ static TBL_PC* guild_sd_check(int guild_id, uint32 account_id, uint32 char_id) {
}
// Modified [Komurka]
int guild_skill_get_max (int id) {
if ((id = guild_skill_get_index(id)) < 0)
uint16 guild_skill_get_max( uint16 id ){
std::shared_ptr<s_guild_skill_tree> skill = guild_skill_tree_db.find( id );
if( skill == nullptr ){
return 0;
return guild_skill_tree[id].max;
}
return skill->max;
}
// Retrieve skill_lv learned by guild
@@ -114,54 +247,28 @@ int guild_checkskill(struct guild *g, int id) {
}
/*==========================================
* guild_skill_tree.txt reading - from jA [Komurka]
* Guild skill check - from jA [Komurka]
*------------------------------------------*/
static bool guild_read_guildskill_tree_db(char* split[], int columns, int current) {// <skill id>,<max lv>,<req id1>,<req lv1>,<req id2>,<req lv2>,<req id3>,<req lv3>,<req id4>,<req lv4>,<req id5>,<req lv5>
int k, skill_id = atoi(split[0]);
short idx = -1;
if ((idx = guild_skill_get_index(skill_id)) < 0) {
ShowError("guild_read_guildskill_tree_db: Invalid Guild skill '%s'.\n", split[1]);
bool guild_check_skill_require( struct guild *g, uint16 id ){
if( g == nullptr ){
return false;
}
guild_skill_tree[idx].id = skill_id;
guild_skill_tree[idx].max = atoi(split[1]);
std::shared_ptr<s_guild_skill_tree> skill = guild_skill_tree_db.find( id );
if( guild_skill_tree[idx].id == GD_GLORYGUILD && battle_config.require_glory_guild && guild_skill_tree[idx].max == 0 ) {// enable guild's glory when required for emblems
guild_skill_tree[idx].max = 1;
if( skill == nullptr ){
return false;
}
for( k = 0; k < MAX_GUILD_SKILL_REQUIRE; k++ ) {
guild_skill_tree[idx].need[k].id = atoi(split[k*2+2]);
guild_skill_tree[idx].need[k].lv = atoi(split[k*2+3]);
for( const auto& pair : skill->need ){
if( pair.second->lv > guild_checkskill( g, pair.second->id ) ){
return false;
}
}
return true;
}
/*==========================================
* Guild skill check - from jA [Komurka]
*------------------------------------------*/
int guild_check_skill_require(struct guild *g,int id) {
uint8 i;
short idx = -1;
if(g == NULL)
return 0;
if ((idx = guild_skill_get_index(id)) < 0)
return 0;
for(i=0;i<MAX_GUILD_SKILL_REQUIRE;i++)
{
if(guild_skill_tree[idx].need[i].id == 0) break;
if(guild_skill_tree[idx].need[i].lv > guild_checkskill(g,guild_skill_tree[idx].need[i].id))
return 0;
}
return 1;
}
static bool guild_read_castledb(char* str[], int columns, int current) {// <castle id>,<map name>,<castle name>,<castle event>[,<reserved/unused switch flag>]
struct guild_castle *gc;
int mapindex = mapindex_name2id(str[1]);
@@ -2314,20 +2421,19 @@ void do_init_guild(void) {
expcache_ers = ers_new(sizeof(struct guild_expcache),"guild.cpp::expcache_ers",ERS_OPT_NONE);
guild_flags_count = 0;
memset(guild_skill_tree,0,sizeof(guild_skill_tree));
for(i=0; i<ARRAYLENGTH(dbsubpath); i++){
int n1 = strlen(db_path)+strlen(dbsubpath[i])+1;
uint8 n1 = (uint8)(strlen(db_path)+strlen(dbsubpath[i])+1);
char* dbsubpath1 = (char*)aMalloc(n1+1);
safesnprintf(dbsubpath1,n1+1,"%s%s",db_path,dbsubpath[i]);
safesnprintf(dbsubpath1,n1,"%s%s",db_path,dbsubpath[i]);
sv_readdb(dbsubpath1, "castle_db.txt", ',', 4, 4, -1, &guild_read_castledb, i > 0);
sv_readdb(dbsubpath1, "guild_skill_tree.txt", ',', 2+MAX_GUILD_SKILL_REQUIRE*2, 2+MAX_GUILD_SKILL_REQUIRE*2, -1, &guild_read_guildskill_tree_db, i > 0); //guild skill tree [Komurka]
aFree(dbsubpath1);
}
guild_skill_tree_db.load();
add_timer_func_list(guild_payexp_timer,"guild_payexp_timer");
add_timer_func_list(guild_send_xy_timer, "guild_send_xy_timer");
add_timer_interval(gettick()+GUILD_PAYEXP_INTERVAL,guild_payexp_timer,0,0,GUILD_PAYEXP_INTERVAL);