From 77d86c6da59ebc08a99720cd558fe738940cc581 Mon Sep 17 00:00:00 2001 From: Aleos Date: Fri, 20 Dec 2019 12:37:16 -0500 Subject: [PATCH] Converted Reading Spellbook Database to YAML (#4440) * Split database between pre-renewal and renewal. Co-authored-by: Lemongrass3110 --- db/import-tmpl/spellbook_db.txt | 9 -- db/import-tmpl/spellbook_db.yml | 32 ++++++ db/re/spellbook_db.yml | 85 +++++++++++++++ db/spellbook_db.txt | 31 ------ db/spellbook_db.yml | 38 +++++++ doc/yaml/db/spellbook_db.yml | 11 ++ src/map/clif.cpp | 2 +- src/map/itemdb.cpp | 13 --- src/map/itemdb.hpp | 1 - src/map/map-server.vcxproj | 2 +- src/map/skill.cpp | 187 ++++++++++++++++++++------------ src/map/skill.hpp | 22 +++- src/tool/csv2yaml.cpp | 37 +++++++ 13 files changed, 341 insertions(+), 129 deletions(-) delete mode 100644 db/import-tmpl/spellbook_db.txt create mode 100644 db/import-tmpl/spellbook_db.yml create mode 100644 db/re/spellbook_db.yml delete mode 100644 db/spellbook_db.txt create mode 100644 db/spellbook_db.yml create mode 100644 doc/yaml/db/spellbook_db.yml diff --git a/db/import-tmpl/spellbook_db.txt b/db/import-tmpl/spellbook_db.txt deleted file mode 100644 index 7f7e0a17e3..0000000000 --- a/db/import-tmpl/spellbook_db.txt +++ /dev/null @@ -1,9 +0,0 @@ -// Reading Spellbook Preserve Points Database -// -// Structure of Database: -// SkillID,PreservePoints,Required Book -// -// NOTE: -// - To add more entries, increase MAX_SKILL_SPELLBOOK_DB in skill.h. -// - To remove entry by importing, put 0 for 'PreservePoints' - diff --git a/db/import-tmpl/spellbook_db.yml b/db/import-tmpl/spellbook_db.yml new file mode 100644 index 0000000000..c587f05e27 --- /dev/null +++ b/db/import-tmpl/spellbook_db.yml @@ -0,0 +1,32 @@ +# This file is a part of rAthena. +# Copyright(C) 2019 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 . +# +########################################################################### +# Reading Spellbook Database +########################################################################### +# +# Reading Spellbook Settings +# +########################################################################### +# - Skill Skill that is usable through a Spellbook. +# Book Book item required to cast skill. +# PreservePoints Amount of points required to preserve the skill into the book. +########################################################################### + +Header: + Type: READING_SPELLBOOK_DB + Version: 1 diff --git a/db/re/spellbook_db.yml b/db/re/spellbook_db.yml new file mode 100644 index 0000000000..a366226a26 --- /dev/null +++ b/db/re/spellbook_db.yml @@ -0,0 +1,85 @@ +# This file is a part of rAthena. +# Copyright(C) 2019 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 . +# +########################################################################### +# Reading Spellbook Database +########################################################################### +# +# Reading Spellbook Settings +# +########################################################################### +# - Skill Skill that is usable through a Spellbook. +# Book Book item required to cast skill. +# PreservePoints Amount of points required to preserve the skill into the book. +########################################################################### + +Header: + Type: READING_SPELLBOOK_DB + Version: 1 + +Body: + - Skill: MG_COLDBOLT + Book: Magic_Book_CB + PreservePoints: 7 + - Skill: MG_FIREBOLT + Book: Magic_Book_FB + PreservePoints: 7 + - Skill: MG_LIGHTNINGBOLT + Book: Magic_Book_LB + PreservePoints: 7 + - Skill: MG_THUNDERSTORM + Book: Magic_Book_TS + PreservePoints: 9 + - Skill: WZ_METEOR + Book: Magic_Book_MS + PreservePoints: 10 + - Skill: WZ_JUPITEL + Book: Magic_Book_JT + PreservePoints: 9 + - Skill: WZ_VERMILION + Book: Magic_Book_LOV + PreservePoints: 10 + - Skill: WZ_WATERBALL + Book: Magic_Book_WB + PreservePoints: 9 + - Skill: WZ_STORMGUST + Book: Magic_Book_SG + PreservePoints: 10 + - Skill: WZ_EARTHSPIKE + Book: Magic_Book_ES + PreservePoints: 8 + - Skill: WZ_HEAVENDRIVE + Book: Magic_Book_HD + PreservePoints: 9 + - Skill: WL_DRAINLIFE + Book: Magic_Book_DL + PreservePoints: 8 + - Skill: WL_CRIMSONROCK + Book: Magic_Book_CR + PreservePoints: 12 + - Skill: WL_COMET + Book: Magic_Book_CM + PreservePoints: 22 + - Skill: WL_CHAINLIGHTNING + Book: Magic_Book_CL + PreservePoints: 12 + - Skill: WL_EARTHSTRAIN + Book: Magic_Book_ES_ + PreservePoints: 12 + - Skill: WL_TETRAVORTEX + Book: Magic_Book_TV + PreservePoints: 22 diff --git a/db/spellbook_db.txt b/db/spellbook_db.txt deleted file mode 100644 index 1a0b7cf53e..0000000000 --- a/db/spellbook_db.txt +++ /dev/null @@ -1,31 +0,0 @@ -// Reading Spellbook Preserve Points Database -// -// Structure of Database: -// SkillID,PreservePoints,Required Book -// -// NOTE: -// - To add more entries, increase MAX_SKILL_SPELLBOOK_DB in skill.hpp. -// - To remove entry by importing, put 0 for 'PreservePoints' - -//Mage -14,7,6190 //Cold Bolt -19,7,6189 //Fire Bolt -20,7,6191 //Lightning Bolt -21,9,6197 //Thunder Storm - -//Wizard -83,10,6194 //Meteor Storm -84,9,6198 //Jupitel Thunder -85,10,6193 //Lord of Vermillion -86,9,6199 //Water Ball -89,10,6192 //Storm Gust -90,8,6201 //Earth Spike -91,9,6200 //Heaven's Drive - -//Warlock -2210,8,6205 //Drain Life -2211,12,6204 //Crimson Rock -2213,22,6195 //Comet -2214,12,6203 //Chain Lightning -2216,12,6202 //Earth Strain -2217,22,6196 //Tetra Vortex diff --git a/db/spellbook_db.yml b/db/spellbook_db.yml new file mode 100644 index 0000000000..5fa11430d6 --- /dev/null +++ b/db/spellbook_db.yml @@ -0,0 +1,38 @@ +# This file is a part of rAthena. +# Copyright(C) 2019 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 . +# +########################################################################### +# Reading Spellbook Database +########################################################################### +# +# Reading Spellbook Settings +# +########################################################################### +# - Skill Skill that is usable through a Spellbook. +# Book Book item required to cast skill. +# PreservePoints Amount of points required to preserve the skill into the book. +########################################################################### + +Header: + Type: READING_SPELLBOOK_DB + Version: 1 + +Footer: + Imports: + - Path: db/re/spellbook_db.yml + Mode: Renewal + - Path: db/import/spellbook_db.yml diff --git a/doc/yaml/db/spellbook_db.yml b/doc/yaml/db/spellbook_db.yml new file mode 100644 index 0000000000..ee62aeb1af --- /dev/null +++ b/doc/yaml/db/spellbook_db.yml @@ -0,0 +1,11 @@ +########################################################################### +# Reading Spellbook Database +########################################################################### +# +# Reading Spellbook Settings +# +########################################################################### +# - Skill Skill that is usable through a Spellbook. +# Book Book item required to cast skill. +# PreservePoints Amount of points required to preserve the skill into the book. +########################################################################### diff --git a/src/map/clif.cpp b/src/map/clif.cpp index dde5e40c69..6ef185ef61 100644 --- a/src/map/clif.cpp +++ b/src/map/clif.cpp @@ -18382,7 +18382,7 @@ int clif_spellbook_list(struct map_session_data *sd) for( i = 0, c = 0; i < MAX_INVENTORY; i ++ ) { - if( itemdb_is_spellbook2(sd->inventory.u.items_inventory[i].nameid) ) + if( reading_spellbook_db.findBook(sd->inventory.u.items_inventory[i].nameid) ) { WFIFOW(fd, c * 2 + 4) = sd->inventory.u.items_inventory[i].nameid; c++; diff --git a/src/map/itemdb.cpp b/src/map/itemdb.cpp index 98bd999a54..54549969af 100644 --- a/src/map/itemdb.cpp +++ b/src/map/itemdb.cpp @@ -1634,19 +1634,6 @@ bool itemdb_isNoEquip(struct item_data *id, uint16 m) { return false; } -/** -* Check if item is available in spellbook_db or not -* @param nameid -* @return True if item is spellbook; False if not -*/ -bool itemdb_is_spellbook2(unsigned short nameid) { - unsigned char i; - if (!nameid || !itemdb_exists(nameid) || !skill_spellbook_count) - return false; - ARR_FIND(0, MAX_SKILL_SPELLBOOK_DB, i, skill_spellbook_db[i].nameid == nameid); - return i == MAX_SKILL_SPELLBOOK_DB ? false : true; -} - /** * Retrieves random option data */ diff --git a/src/map/itemdb.hpp b/src/map/itemdb.hpp index 564a80ca17..016dfa107e 100644 --- a/src/map/itemdb.hpp +++ b/src/map/itemdb.hpp @@ -916,7 +916,6 @@ struct item_data* itemdb_exists(unsigned short nameid); #define itemdb_dropeffect(n) (itemdb_search(n)->flag.dropEffect) const char* itemdb_typename(enum item_types type); const char *itemdb_typename_ammo (enum e_item_ammo ammo); -bool itemdb_is_spellbook2(unsigned short nameid); struct s_item_group_entry *itemdb_get_randgroupitem(uint16 group_id, uint8 sub_group); unsigned short itemdb_searchrandomid(uint16 group_id, uint8 sub_group); diff --git a/src/map/map-server.vcxproj b/src/map/map-server.vcxproj index 35d6146dde..91ef807b76 100644 --- a/src/map/map-server.vcxproj +++ b/src/map/map-server.vcxproj @@ -369,7 +369,7 @@ - + diff --git a/src/map/skill.cpp b/src/map/skill.cpp index 6fb993d8f2..41e23e56ea 100755 --- a/src/map/skill.cpp +++ b/src/map/skill.cpp @@ -17,6 +17,7 @@ #include "../common/showmsg.hpp" #include "../common/strlib.hpp" #include "../common/timer.hpp" +#include "../common/utilities.hpp" #include "../common/utils.hpp" #include "achievement.hpp" @@ -44,6 +45,8 @@ #include "status.hpp" #include "unit.hpp" +using namespace rathena; + #define SKILLUNITTIMER_INTERVAL 100 #define TIMERSKILL_INTERVAL 150 @@ -91,6 +94,8 @@ AbraDatabase abra_db; ImprovisedSongDatabase improvised_song_db; +ReadingSpellbookDatabase reading_spellbook_db; + #define MAX_SKILL_CHANGEMATERIAL_DB 75 #define MAX_SKILL_CHANGEMATERIAL_SET 3 struct s_skill_changematerial_db { @@ -102,9 +107,6 @@ struct s_skill_changematerial_db { struct s_skill_changematerial_db skill_changematerial_db[MAX_SKILL_CHANGEMATERIAL_DB]; static unsigned short skill_changematerial_count; -//Warlock -struct s_skill_spellbook_db skill_spellbook_db[MAX_SKILL_SPELLBOOK_DB]; -unsigned short skill_spellbook_count; MagicMushroomDatabase magic_mushroom_db; @@ -19913,16 +19915,23 @@ int skill_magicdecoy(struct map_session_data *sd, unsigned short nameid) { // Warlock Spellbooks. [LimitLine/3CeAM] void skill_spellbook(struct map_session_data *sd, unsigned short nameid) { - int i, max_preserve, skill_id, point; - struct status_change *sc; - nullpo_retv(sd); - sc = status_get_sc(&sd->bl); + if (reading_spellbook_db.empty()) + return; + + int i; + struct status_change *sc = status_get_sc(&sd->bl); + status_change_end(&sd->bl, SC_STOP, INVALID_TIMER); for (i = SC_SPELLBOOK1; i <= SC_MAXSPELLBOOK; i++) { - if( sc && !sc->data[i] ) + // No further checks needed + if( !sc ){ + break; + } + + if( !sc->data[i] ) break; } @@ -19931,41 +19940,40 @@ void skill_spellbook(struct map_session_data *sd, unsigned short nameid) { return; } - if (!skill_spellbook_count) + std::shared_ptr spell = reading_spellbook_db.findBook(nameid); + + if (spell == nullptr) return; - ARR_FIND(0,MAX_SKILL_SPELLBOOK_DB,i,skill_spellbook_db[i].nameid == nameid); // Search for information of this item - if( i == MAX_SKILL_SPELLBOOK_DB ) - return; + uint16 skill_id = spell->skill_id, skill_lv = pc_checkskill(sd, skill_id); - if( !pc_checkskill(sd, (skill_id = skill_spellbook_db[i].skill_id)) ) { // User don't know the skill - sc_start(&sd->bl,&sd->bl, SC_SLEEP, 100, 1, skill_get_time(WL_READING_SB, pc_checkskill(sd,WL_READING_SB))); + if (!skill_lv) { // Caster hasn't learned the skill + sc_start(&sd->bl,&sd->bl, SC_SLEEP, 100, 1, skill_get_time(WL_READING_SB, pc_checkskill(sd, WL_READING_SB))); clif_skill_fail(sd, WL_READING_SB, USESKILL_FAIL_SPELLBOOK_DIFFICULT_SLEEP, 0); return; } - max_preserve = 4 * pc_checkskill(sd, WL_FREEZE_SP) + status_get_int(&sd->bl) / 10 + sd->status.base_level / 10; - point = skill_spellbook_db[i].point; + int points = spell->points; - if( sc && sc->data[SC_FREEZE_SP] ) { - if( (sc->data[SC_FREEZE_SP]->val2 + point) > max_preserve ) { + if (sc && sc->data[SC_FREEZE_SP]) { + if ((sc->data[SC_FREEZE_SP]->val2 + points) > 4 * pc_checkskill(sd, WL_FREEZE_SP) + status_get_int(&sd->bl) / 10 + sd->status.base_level / 10) { clif_skill_fail(sd, WL_READING_SB, USESKILL_FAIL_SPELLBOOK_PRESERVATION_POINT, 0); return; } - for(i = SC_MAXSPELLBOOK; i >= SC_SPELLBOOK1; i--){ // This is how official saves spellbook. [malufett] - if( !sc->data[i] ){ - sc->data[SC_FREEZE_SP]->val2 += point; // increase points - sc_start4(&sd->bl,&sd->bl, (sc_type)i, 100, skill_id, pc_checkskill(sd,skill_id), point, 0, INFINITE_TICK); + for (i = SC_MAXSPELLBOOK; i >= SC_SPELLBOOK1; i--) { // This is how official saves spellbook. [malufett] + if (!sc->data[i]) { + sc->data[SC_FREEZE_SP]->val2 += points; // increase points + sc_start4(&sd->bl,&sd->bl, (sc_type)i, 100, skill_id, skill_lv, points, 0, INFINITE_TICK); break; } } } else { - sc_start2(&sd->bl,&sd->bl, SC_FREEZE_SP, 100, 0, point, INFINITE_TICK); - sc_start4(&sd->bl,&sd->bl, SC_MAXSPELLBOOK, 100, skill_id, pc_checkskill(sd,skill_id), point, 0, INFINITE_TICK); + sc_start2(&sd->bl, &sd->bl, SC_FREEZE_SP, 100, 0, points, INFINITE_TICK); + sc_start4(&sd->bl, &sd->bl, SC_MAXSPELLBOOK, 100, skill_id, skill_lv, points, 0, INFINITE_TICK); } // Reading Spell Book SP cost same as the sealed spell. - status_zap(&sd->bl, 0, skill_get_sp(skill_id, pc_checkskill(sd, skill_id))); + status_zap(&sd->bl, 0, skill_get_sp(skill_id, skill_lv)); } int skill_select_menu(struct map_session_data *sd,uint16 skill_id) { @@ -21418,42 +21426,89 @@ static bool skill_parse_row_createarrowdb(char* split[], int columns, int curren return true; } -/** Reads Spell book db - * Structure: SkillID,PreservePoints,RequiredBook +const std::string ReadingSpellbookDatabase::getDefaultLocation() { + return std::string(db_path) + "/spellbook_db.yml"; +} +/** + * Reads and parses an entry from the spellbook_db. + * @param node: YAML node containing the entry. + * @return count of successfully parsed rows */ -static bool skill_parse_row_spellbookdb(char* split[], int columns, int current) -{ - unsigned short skill_id = atoi(split[0]), points = atoi(split[1]), nameid = atoi(split[2]); +uint64 ReadingSpellbookDatabase::parseBodyNode(const YAML::Node &node) { + std::string skill_name; - if (!skill_get_index(skill_id) || !skill_get_max(skill_id)) - ShowError("skill_parse_row_spellbookdb: Invalid skill ID %d\n", skill_id); - if (!skill_get_inf(skill_id)) - ShowError("skill_parse_row_spellbookdb: Passive skills cannot be memorized (%d/%s)\n", skill_id, skill_get_name(skill_id)); - else { - unsigned short i; + if (!this->asString(node, "Skill", skill_name)) + return 0; - ARR_FIND(0, skill_spellbook_count, i, skill_spellbook_db[i].skill_id == skill_id); - if (i >= ARRAYLENGTH(skill_spellbook_db)) { - ShowError("skill_parse_row_spellbookdb: Maximum db entries reached.\n"); - return false; - } - // Import just for clearing/disabling from original data - if (points == 0) { - memset(&skill_spellbook_db[i], 0, sizeof(skill_spellbook_db[i])); - //ShowInfo("skill_parse_row_spellbookdb: Skill %d removed from list.\n", skill_id); - return true; - } + uint16 skill_id = skill_name2id(skill_name.c_str()); - skill_spellbook_db[i].skill_id = skill_id; - skill_spellbook_db[i].point = points; - skill_spellbook_db[i].nameid = nameid; - - if (i == skill_spellbook_count) - skill_spellbook_count++; - return true; + if (skill_id == 0) { + this->invalidWarning(node["Skill"], "Invalid skill name \"%s\", skipping.\n", skill_name.c_str()); + return 0; } - return false; + if (!skill_get_inf(skill_id)) { + this->invalidWarning(node["Skill"], "Passive skill %s cannot be memorized in a Spell Book.\n", skill_name.c_str()); + return 0; + } + + std::shared_ptr spell = this->find(skill_id); + bool exists = spell != nullptr; + + if (!exists) { + if (!this->nodesExist(node, { "Book", "PreservePoints" })) + return 0; + + spell = std::make_shared(); + spell->skill_id = skill_id; + } + + if (this->nodeExists(node, "Book")) { + std::string book_name; + + if (!this->asString(node, "Book", book_name)) + return 0; + + struct item_data *item = itemdb_search_aegisname(book_name.c_str()); + + if (item == nullptr) { + this->invalidWarning(node["Book"], "Book item %s does not exist.\n", book_name.c_str()); + return 0; + } + + spell->nameid = item->nameid; + } + + if (this->nodeExists(node, "PreservePoints")) { + uint16 points; + + if (!this->asUInt16(node, "PreservePoints", points)) + return 0; + + spell->points = points; + } + + if (!exists) + this->put(skill_id, spell); + + return 1; +} + +/** + * Check if the specified item is available in the spellbook_db or not + * @param nameid: Book Item ID + * @return Spell data or nullptr otherwise + */ +std::shared_ptr ReadingSpellbookDatabase::findBook(int32 nameid) { + if (nameid < 1 || !itemdb_exists(nameid) || reading_spellbook_db.size() == 0) + return nullptr; + + for (const auto &spell : reading_spellbook_db) { + if (spell.second->nameid == nameid) + return spell.second; + } + + return nullptr; } @@ -21515,10 +21570,10 @@ const std::string MagicMushroomDatabase::getDefaultLocation() { } /** -* Reads and parses an entry from the magicmushroom_db. -* @param node: YAML node containing the entry. -* @return count of successfully parsed rows -*/ + * Reads and parses an entry from the magicmushroom_db. + * @param node: YAML node containing the entry. + * @return count of successfully parsed rows + */ uint64 MagicMushroomDatabase::parseBodyNode(const YAML::Node &node) { std::string skill_name; @@ -21613,10 +21668,10 @@ const std::string AbraDatabase::getDefaultLocation() { } /** -* Reads and parses an entry from the abra_db. -* @param node: YAML node containing the entry. -* @return count of successfully parsed rows -*/ + * Reads and parses an entry from the abra_db. + * @param node: YAML node containing the entry. + * @return count of successfully parsed rows + */ uint64 AbraDatabase::parseBodyNode(const YAML::Node &node) { std::string skill_name; @@ -21843,10 +21898,8 @@ static void skill_readdb(void) memset(skill_produce_db,0,sizeof(skill_produce_db)); memset(skill_arrow_db,0,sizeof(skill_arrow_db)); - memset(skill_spellbook_db,0,sizeof(skill_spellbook_db)); memset(skill_changematerial_db,0,sizeof(skill_changematerial_db)); - skill_produce_count = skill_arrow_count = - skill_changematerial_count = skill_spellbook_count = 0; + skill_produce_count = skill_arrow_count = skill_changematerial_count = 0; for(i=0; i 0); sv_readdb(dbsubpath1, "create_arrow_db.txt" , ',', 1+2, 1+2*MAX_ARROW_RESULT, MAX_SKILL_ARROW_DB, skill_parse_row_createarrowdb, i > 0); - sv_readdb(dbsubpath1, "spellbook_db.txt" , ',', 3, 3, MAX_SKILL_SPELLBOOK_DB, skill_parse_row_spellbookdb, i > 0); sv_readdb(dbsubpath1, "skill_copyable_db.txt" , ',', 2, 4, -1, skill_parse_row_copyabledb, i > 0); sv_readdb(dbsubpath1, "skill_changematerial_db.txt" , ',', 5, 5+2*MAX_SKILL_CHANGEMATERIAL_SET, MAX_SKILL_CHANGEMATERIAL_DB, skill_parse_row_changematerialdb, i > 0); sv_readdb(dbsubpath1, "skill_nonearnpc_db.txt" , ',', 2, 3, -1, skill_parse_row_nonearnpcrangedb, i > 0); @@ -21884,6 +21936,7 @@ static void skill_readdb(void) abra_db.load(); improvised_song_db.load(); magic_mushroom_db.load(); + reading_spellbook_db.load(); skill_init_unit_layout(); skill_init_nounit_layout(); diff --git a/src/map/skill.hpp b/src/map/skill.hpp index e427f03fc2..92102dceec 100644 --- a/src/map/skill.hpp +++ b/src/map/skill.hpp @@ -2181,20 +2181,30 @@ void skill_usave_trigger(struct map_session_data *sd); /** * Warlock **/ -#define MAX_SKILL_SPELLBOOK_DB 17 enum wl_spheres { WLS_FIRE = 0x44, WLS_WIND, WLS_WATER, WLS_STONE, }; + struct s_skill_spellbook_db { - unsigned short nameid; - unsigned short skill_id; - unsigned short point; + uint16 skill_id, nameid, points; }; -extern struct s_skill_spellbook_db skill_spellbook_db[MAX_SKILL_SPELLBOOK_DB]; -extern unsigned short skill_spellbook_count; + +class ReadingSpellbookDatabase : public TypesafeYamlDatabase { +public: + ReadingSpellbookDatabase() : TypesafeYamlDatabase("READING_SPELLBOOK_DB", 1) { + + } + + const std::string getDefaultLocation(); + uint64 parseBodyNode(const YAML::Node& node); + std::shared_ptr findBook(int32 nameid); +}; + +extern ReadingSpellbookDatabase reading_spellbook_db; + void skill_spellbook(struct map_session_data *sd, unsigned short nameid); int skill_block_check(struct block_list *bl, enum sc_type type, uint16 skill_id); diff --git a/src/tool/csv2yaml.cpp b/src/tool/csv2yaml.cpp index e88f87001c..67dba63981 100644 --- a/src/tool/csv2yaml.cpp +++ b/src/tool/csv2yaml.cpp @@ -72,6 +72,7 @@ static size_t pet_read_db( const char* file ); static bool skill_parse_row_magicmushroomdb(char* split[], int column, int current); static bool skill_parse_row_abradb(char* split[], int columns, int current); static bool skill_parse_row_improvisedb(char* split[], int columns, int current); +static bool skill_parse_row_spellbookdb(char* split[], int columns, int current); // Constants for conversion std::unordered_map aegis_itemnames; @@ -255,6 +256,12 @@ int do_init( int argc, char** argv ){ return 0; } + if (!process("READING_SPELLBOOK_DB", 1, root_paths, "spellbook_db", [](const std::string& path, const std::string& name_ext) -> bool { + return sv_readdb(path.c_str(), name_ext.c_str(), ',', 3, 3, -1, &skill_parse_row_spellbookdb, false); + })) { + return 0; + } + // TODO: add implementations ;-) return 0; @@ -749,11 +756,13 @@ static bool skill_parse_row_abradb(char* split[], int columns, int current) body << YAML::EndSeq; } + body << YAML::EndMap; return true; } +// Copied and adjusted from skill.cpp static bool skill_parse_row_improvisedb(char* split[], int columns, int current) { uint16 skill_id = atoi(split[0]); @@ -771,3 +780,31 @@ static bool skill_parse_row_improvisedb(char* split[], int columns, int current) return true; } + +// Copied and adjusted from skill.cpp +static bool skill_parse_row_spellbookdb(char* split[], int columns, int current) +{ + uint16 skill_id = atoi(split[0]); + std::string *skill_name = util::umap_find(aegis_skillnames, skill_id); + + if (skill_name == nullptr) { + ShowError("Skill name for Spell Book skill ID %hu is not known.\n", skill_id); + return false; + } + + uint16 nameid = atoi(split[2]); + std::string *book_name = util::umap_find(aegis_itemnames, nameid); + + if (book_name == nullptr) { + ShowError("Book name for item ID %hu is not known.\n", nameid); + return false; + } + + body << YAML::BeginMap; + body << YAML::Key << "Skill" << YAML::Value << *skill_name; + body << YAML::Key << "Book" << YAML::Value << *book_name; + body << YAML::Key << "PreservePoints" << YAML::Value << atoi(split[1]); + body << YAML::EndMap; + + return true; +}