浏览代码

Converted Magic Mushroom Database to YAML (#4482)

* Split database into pre-renewal and renewal.
* Left pre-renewal database empty.
Aleos 5 年之前
父节点
当前提交
d56553775a

+ 30 - 0
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 <http://www.gnu.org/licenses/>.
+#
+###########################################################################
+# Magic Mushroom Database
+###########################################################################
+#
+# Magic Mushroom Settings
+#
+###########################################################################
+# - Skill       Skill to be casted by Magic Mushroom.
+###########################################################################
+
+Header:
+  Type: MAGIC_MUSHROOM_DB
+  Version: 1

+ 0 - 31
db/magicmushroom_db.txt

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

+ 38 - 0
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 <http://www.gnu.org/licenses/>.
+#
+###########################################################################
+# 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

+ 30 - 0
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 <http://www.gnu.org/licenses/>.
+#
+###########################################################################
+# Magic Mushroom Database
+###########################################################################
+#
+# Magic Mushroom Settings
+#
+###########################################################################
+# - Skill       Skill to be casted by Magic Mushroom.
+###########################################################################
+
+Header:
+  Type: MAGIC_MUSHROOM_DB
+  Version: 1

+ 55 - 0
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 <http://www.gnu.org/licenses/>.
+#
+###########################################################################
+# 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

+ 9 - 0
doc/yaml/db/magicmushroom_db.yml

@@ -0,0 +1,9 @@
+###########################################################################
+# Magic Mushroom Database
+###########################################################################
+#
+# Magic Mushroom Settings
+#
+###########################################################################
+# - Skill       Skill to be casted by Magic Mushroom.
+###########################################################################

+ 1 - 1
src/map/map-server.vcxproj

@@ -333,7 +333,7 @@
     <Copy SourceFiles="$(SolutionDir)db\import-tmpl\job_noenter_map.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\job_noenter_map.txt')" />
     <Copy SourceFiles="$(SolutionDir)db\import-tmpl\job_param_db.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\job_param_db.txt')" />
     <Copy SourceFiles="$(SolutionDir)db\import-tmpl\level_penalty.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\level_penalty.txt')" />
-    <Copy SourceFiles="$(SolutionDir)db\import-tmpl\magicmushroom_db.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\magicmushroom_db.txt')" />
+    <Copy SourceFiles="$(SolutionDir)db\import-tmpl\magicmushroom_db.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\magicmushroom_db.yml')" />
     <Copy SourceFiles="$(SolutionDir)db\import-tmpl\map_cache.dat" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\map_cache.dat')" />
     <Copy SourceFiles="$(SolutionDir)db\import-tmpl\map_index.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\map_index.txt')" />
     <Copy SourceFiles="$(SolutionDir)db\import-tmpl\mercenary_db.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\mercenary_db.txt')" />

+ 36 - 33
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<s_skill_magicmushroom_db> mushroom = this->find(skill_id);
+	bool exists = mushroom != nullptr;
 
-	return true;
+	if (!exists) {
+		mushroom = std::make_shared<s_skill_magicmushroom_db>();
+		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<ARRAYLENGTH(dbsubpath); i++){
 		size_t n1 = strlen(db_path)+strlen(dbsubpath[i])+1;
@@ -21824,7 +21826,6 @@ static void skill_readdb(void)
 		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, "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();

+ 14 - 6
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<uint16, s_skill_magicmushroom_db> {
+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);
 

+ 9 - 8
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);

+ 24 - 0
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<uint16, std::string> 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;
+}