diff --git a/db/import-tmpl/magicmushroom_db.yml b/db/import-tmpl/magicmushroom_db.yml
new file mode 100644
index 0000000000..2f638de7aa
--- /dev/null
+++ b/db/import-tmpl/magicmushroom_db.yml
@@ -0,0 +1,30 @@
+# 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 .
+#
+###########################################################################
+# Magic Mushroom Database
+###########################################################################
+#
+# Magic Mushroom Settings
+#
+###########################################################################
+# - Skill Skill to be casted by Magic Mushroom.
+###########################################################################
+
+Header:
+ Type: MAGIC_MUSHROOM_DB
+ Version: 1
diff --git a/db/magicmushroom_db.txt b/db/magicmushroom_db.txt
deleted file mode 100644
index d5a5e5b193..0000000000
--- a/db/magicmushroom_db.txt
+++ /dev/null
@@ -1,31 +0,0 @@
-// Magic Mushroom Database
-// List of skills that are randomly used through Magic Mushroom status change.
-//
-// Structure of Database:
-// SkillID{,RemoveFlag}
-//
-// - To remove entry by importing, put 1 value on 'RemoveFlag'
-
-7 //SM_MAGNUM
-8 //SM_ENDURE
-10 //MG_SIGHT
-24 //AL_RUWACH
-32 //AL_CRUCIS
-33 //AL_ANGELUS
-45 //AC_CONCENTRATION
-61 //KN_AUTOCOUNTER
-74 //PR_MAGNIFICAT
-110 //BS_HAMMERFALL
-114 //BS_MAXIMIZE
-142 //NV_FIRSTAID
-150 //TF_BACKSLIDING
-151 //TF_PICKSTONE
-157 //MG_ENERGYCOAT
-249 //CR_AUTOGUARD
-256 //CR_PROVIDENCE
-261 //MO_CALLSPIRITS
-270 //MO_EXPLOSIONSPIRITS
-326 //DC_SCREAM
-500 //GS_GLITTERING
-527 //NJ_TATAMIGAESHI
-531 //NJ_UTSUSEMI
diff --git a/db/magicmushroom_db.yml b/db/magicmushroom_db.yml
new file mode 100644
index 0000000000..d03d701ffd
--- /dev/null
+++ b/db/magicmushroom_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 .
+#
+###########################################################################
+# Magic Mushroom Database
+###########################################################################
+#
+# Magic Mushroom Settings
+#
+###########################################################################
+# - Skill Skill to be casted by Magic Mushroom.
+###########################################################################
+
+Header:
+ Type: MAGIC_MUSHROOM_DB
+ Version: 1
+
+Footer:
+ Imports:
+ - Path: db/pre-re/magicmushroom_db.yml
+ Mode: Prerenewal
+ - Path: db/re/magicmushroom_db.yml
+ Mode: Renewal
+ - Path: db/import/magicmushroom_db.yml
diff --git a/db/pre-re/magicmushroom_db.yml b/db/pre-re/magicmushroom_db.yml
new file mode 100644
index 0000000000..2f638de7aa
--- /dev/null
+++ b/db/pre-re/magicmushroom_db.yml
@@ -0,0 +1,30 @@
+# 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 .
+#
+###########################################################################
+# Magic Mushroom Database
+###########################################################################
+#
+# Magic Mushroom Settings
+#
+###########################################################################
+# - Skill Skill to be casted by Magic Mushroom.
+###########################################################################
+
+Header:
+ Type: MAGIC_MUSHROOM_DB
+ Version: 1
diff --git a/db/re/magicmushroom_db.yml b/db/re/magicmushroom_db.yml
new file mode 100644
index 0000000000..e3ba0cd89a
--- /dev/null
+++ b/db/re/magicmushroom_db.yml
@@ -0,0 +1,55 @@
+# 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 .
+#
+###########################################################################
+# Magic Mushroom Database
+###########################################################################
+#
+# Magic Mushroom Settings
+#
+###########################################################################
+# - Skill Skill to be casted by Magic Mushroom.
+###########################################################################
+
+Header:
+ Type: MAGIC_MUSHROOM_DB
+ Version: 1
+
+Body:
+ - Skill: SM_MAGNUM
+ - Skill: SM_ENDURE
+ - Skill: MG_SIGHT
+ - Skill: AL_RUWACH
+ - Skill: AL_CRUCIS
+ - Skill: AL_ANGELUS
+ - Skill: AC_CONCENTRATION
+ - Skill: KN_AUTOCOUNTER
+ - Skill: PR_MAGNIFICAT
+ - Skill: BS_HAMMERFALL
+ - Skill: BS_MAXIMIZE
+ - Skill: NV_FIRSTAID
+ - Skill: TF_BACKSLIDING
+ - Skill: TF_PICKSTONE
+ - Skill: MG_ENERGYCOAT
+ - Skill: CR_AUTOGUARD
+ - Skill: CR_PROVIDENCE
+ - Skill: MO_CALLSPIRITS
+ - Skill: MO_EXPLOSIONSPIRITS
+ - Skill: DC_SCREAM
+ - Skill: GS_GLITTERING
+ - Skill: NJ_TATAMIGAESHI
+ - Skill: NJ_UTSUSEMI
diff --git a/doc/yaml/db/magicmushroom_db.yml b/doc/yaml/db/magicmushroom_db.yml
new file mode 100644
index 0000000000..c1ddd3264d
--- /dev/null
+++ b/doc/yaml/db/magicmushroom_db.yml
@@ -0,0 +1,9 @@
+###########################################################################
+# Magic Mushroom Database
+###########################################################################
+#
+# Magic Mushroom Settings
+#
+###########################################################################
+# - Skill Skill to be casted by Magic Mushroom.
+###########################################################################
diff --git a/src/map/map-server.vcxproj b/src/map/map-server.vcxproj
index a8ba8c8f49..babf974386 100644
--- a/src/map/map-server.vcxproj
+++ b/src/map/map-server.vcxproj
@@ -333,7 +333,7 @@
-
+
diff --git a/src/map/skill.cpp b/src/map/skill.cpp
index b48d4aa363..657b4cd0b3 100755
--- a/src/map/skill.cpp
+++ b/src/map/skill.cpp
@@ -112,9 +112,7 @@ static unsigned short skill_changematerial_count;
struct s_skill_spellbook_db skill_spellbook_db[MAX_SKILL_SPELLBOOK_DB];
unsigned short skill_spellbook_count;
-//Guillotine Cross
-struct s_skill_magicmushroom_db skill_magicmushroom_db[MAX_SKILL_MAGICMUSHROOM_DB];
-unsigned short skill_magicmushroom_count;
+MagicMushroomDatabase magic_mushroom_db;
struct s_skill_unit_layout skill_unit_layout[MAX_SKILL_UNIT_LAYOUT];
int firewall_unit_pos;
@@ -21503,39 +21501,44 @@ static bool skill_parse_row_improvisedb(char* split[], int columns, int current)
return true;
}
-/** Reads Magic mushroom db
- * Structure: SkillID
- */
-static bool skill_parse_row_magicmushroomdb(char* split[], int column, int current)
-{
- unsigned short i, skill_id = atoi(split[0]);
- bool rem = (atoi(split[1]) == 1 ? true : false);
+const std::string MagicMushroomDatabase::getDefaultLocation() {
+ return std::string(db_path) + "/magicmushroom_db.yml";
+}
- if (!skill_get_index(skill_id) || !skill_get_max(skill_id)) {
- ShowError("skill_parse_row_magicmushroomdb: Invalid skill ID %d\n", skill_id);
- return false;
+/**
+* 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;
+
+ if (!this->asString(node, "Skill", skill_name))
+ return 0;
+
+ uint16 skill_id = skill_name2id(skill_name.c_str());
+
+ if (!skill_id) {
+ this->invalidWarning(node["Skill"], "Invalid Magic Mushroom skill name \"%s\", skipping.\n", skill_name.c_str());
+ return 0;
}
+
if (!skill_get_inf(skill_id)) {
- ShowError("skill_parse_row_magicmushroomdb: Passive skills cannot be casted (%d/%s)\n", skill_id, skill_get_name(skill_id));
- return false;
- }
- ARR_FIND(0, skill_magicmushroom_count, i, skill_magicmushroom_db[i].skill_id==skill_id);
- if (i >= ARRAYLENGTH(skill_magicmushroom_db)) {
- ShowError("skill_parse_row_magicmushroomdb: Maximum db entries reached.\n");
- return false;
- }
- // Import just for clearing/disabling from original data
- if (rem) {
- memset(&skill_magicmushroom_db[i], 0, sizeof(skill_magicmushroom_db[i]));
- //ShowInfo("skill_parse_row_magicmushroomdb: Skill %d removed from list.\n", skill_id);
- return true;
+ this->invalidWarning(node["Skill"], "Passive skill %s cannot be casted by Magic Mushroom.\n", skill_name.c_str());
+ return 0;
}
- skill_magicmushroom_db[i].skill_id = skill_id;
- if (i == skill_magicmushroom_count)
- skill_magicmushroom_count++;
+ std::shared_ptr mushroom = this->find(skill_id);
+ bool exists = mushroom != nullptr;
- return true;
+ if (!exists) {
+ mushroom = std::make_shared();
+ mushroom->skill_id = skill_id;
+
+ this->put(skill_id, mushroom);
+ }
+
+ return 1;
}
/** Reads db of copyable skill
@@ -21794,10 +21797,9 @@ static void skill_readdb(void)
memset(skill_arrow_db,0,sizeof(skill_arrow_db));
memset(skill_abra_db,0,sizeof(skill_abra_db));
memset(skill_spellbook_db,0,sizeof(skill_spellbook_db));
- memset(skill_magicmushroom_db,0,sizeof(skill_magicmushroom_db));
memset(skill_changematerial_db,0,sizeof(skill_changematerial_db));
skill_produce_count = skill_arrow_count = skill_abra_count = skill_improvise_count =
- skill_changematerial_count = skill_spellbook_count = skill_magicmushroom_count = 0;
+ skill_changematerial_count = skill_spellbook_count = 0;
for(i=0; i 0);
sv_readdb(dbsubpath1, "abra_db.txt" , ',', 3, 3, MAX_SKILL_ABRA_DB, skill_parse_row_abradb, i > 0);
sv_readdb(dbsubpath1, "spellbook_db.txt" , ',', 3, 3, MAX_SKILL_SPELLBOOK_DB, skill_parse_row_spellbookdb, i > 0);
- sv_readdb(dbsubpath1, "magicmushroom_db.txt" , ',', 1, 2, MAX_SKILL_MAGICMUSHROOM_DB, skill_parse_row_magicmushroomdb, i > 0);
sv_readdb(dbsubpath1, "skill_copyable_db.txt" , ',', 2, 4, -1, skill_parse_row_copyabledb, i > 0);
sv_readdb(dbsubpath1, "skill_improvise_db.txt" , ',', 2, 2, MAX_SKILL_IMPROVISE_DB, skill_parse_row_improvisedb, 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);
@@ -21834,6 +21835,8 @@ static void skill_readdb(void)
aFree(dbsubpath1);
aFree(dbsubpath2);
}
+
+ magic_mushroom_db.load();
skill_init_unit_layout();
skill_init_nounit_layout();
diff --git a/src/map/skill.hpp b/src/map/skill.hpp
index 8fe8fabcdc..6bb670a28c 100644
--- a/src/map/skill.hpp
+++ b/src/map/skill.hpp
@@ -5,6 +5,7 @@
#define SKILL_HPP
#include "../common/cbasetypes.hpp"
+#include "../common/database.hpp"
#include "../common/db.hpp"
#include "../common/mmo.hpp" // MAX_SKILL, struct square
#include "../common/timer.hpp"
@@ -2176,15 +2177,22 @@ extern unsigned short skill_spellbook_count;
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);
-/**
- * Guilottine Cross
- **/
-#define MAX_SKILL_MAGICMUSHROOM_DB 25
struct s_skill_magicmushroom_db {
uint16 skill_id;
};
-extern struct s_skill_magicmushroom_db skill_magicmushroom_db[MAX_SKILL_MAGICMUSHROOM_DB];
-extern unsigned short skill_magicmushroom_count;
+
+class MagicMushroomDatabase : public TypesafeYamlDatabase {
+public:
+ MagicMushroomDatabase() : TypesafeYamlDatabase("MAGIC_MUSHROOM_DB", 1) {
+
+ }
+
+ const std::string getDefaultLocation();
+ uint64 parseBodyNode(const YAML::Node& node);
+};
+
+extern MagicMushroomDatabase magic_mushroom_db;
+
int skill_maelstrom_suction(struct block_list *bl, va_list ap);
bool skill_check_shadowform(struct block_list *bl, int64 damage, int hit);
diff --git a/src/map/status.cpp b/src/map/status.cpp
index 48639c4650..9b0df3a496 100644
--- a/src/map/status.cpp
+++ b/src/map/status.cpp
@@ -13032,18 +13032,19 @@ TIMER_FUNC(status_change_timer){
}
if (!flag) { // Random Skill Cast
- if (skill_magicmushroom_count && sd && !pc_issit(sd)) { // Can't cast if sit
- int mushroom_skill_id = 0, checked = 0, checked_max = MAX_SKILL_MAGICMUSHROOM_DB * 3;
- unit_stop_attack(bl);
- unit_skillcastcancel(bl, 1);
- do {
- int i = rnd() % MAX_SKILL_MAGICMUSHROOM_DB;
- mushroom_skill_id = skill_magicmushroom_db[i].skill_id;
- } while (checked++ < checked_max && mushroom_skill_id == 0);
+ if (magic_mushroom_db.size() > 0 && sd && !pc_issit(sd)) { // Can't cast if sit
+ auto mushroom_spell = magic_mushroom_db.begin();
+
+ std::advance(mushroom_spell, rnd() % magic_mushroom_db.size());
+
+ uint16 mushroom_skill_id = mushroom_spell->second->skill_id;
if (!skill_get_index(mushroom_skill_id))
break;
+ unit_stop_attack(bl);
+ unit_skillcastcancel(bl, 1);
+
switch (skill_get_casttype(mushroom_skill_id)) { // Magic Mushroom skills are buffs or area damage
case CAST_GROUND:
skill_castend_pos2(bl, bl->x, bl->y, mushroom_skill_id, 1, tick, 0);
diff --git a/src/tool/csv2yaml.cpp b/src/tool/csv2yaml.cpp
index c7f8e7b7cc..4ccc54942c 100644
--- a/src/tool/csv2yaml.cpp
+++ b/src/tool/csv2yaml.cpp
@@ -69,6 +69,7 @@ int getch( void ){
// Forward declaration of conversion functions
static bool guild_read_guildskill_tree_db( char* split[], int columns, int current );
static size_t pet_read_db( const char* file );
+static bool skill_parse_row_magicmushroomdb(char* split[], int column, int current);
// Constants for conversion
std::unordered_map aegis_itemnames;
@@ -234,6 +235,12 @@ int do_init( int argc, char** argv ){
return 0;
}
+ if (!process("MAGIC_MUSHROOM_DB", 1, root_paths, "magicmushroom_db", [](const std::string& path, const std::string& name_ext) -> bool {
+ return sv_readdb(path.c_str(), name_ext.c_str(), ',', 1, 1, -1, &skill_parse_row_magicmushroomdb, false);
+ })) {
+ return 0;
+ }
+
// TODO: add implementations ;-)
return 0;
@@ -646,3 +653,20 @@ static size_t pet_read_db( const char* file ){
return entries;
}
+
+static bool skill_parse_row_magicmushroomdb(char* split[], int column, 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 Magic Mushroom skill ID %hu is not known.\n", skill_id);
+ return false;
+ }
+
+ body << YAML::BeginMap;
+ body << YAML::Key << "Skill" << YAML::Value << *skill_name;
+ body << YAML::EndMap;
+
+ return true;
+}