diff --git a/db/enchantgrade.yml b/db/enchantgrade.yml index 4b5140f6fd..c97c4e4651 100644 --- a/db/enchantgrade.yml +++ b/db/enchantgrade.yml @@ -1,5 +1,5 @@ # This file is a part of rAthena. -# Copyright(C) 2022 rAthena Development Team +# Copyright(C) 2023 rAthena Development Team # https://rathena.org - https://github.com/rathena # # This program is free software: you can redistribute it and/or modify @@ -27,8 +27,9 @@ # - Level Item level. # Grades: Enchantgrade settings per grade level. # - Grade Enchantgrade level. -# Refine Required refine level. -# Chance Base chance of success out of 0~10000. +# Chances: Chance settings per refine level. +# - Refine Refine level. +# Chance Base chance of success out of 0~10000. # Bonus Enchantgrade bonus. (Default: 0) # AnnounceSuccess Announce on upgrade success. (Default: true) # AnnounceFail Announce on upgrade failure. (Default: false) @@ -51,7 +52,7 @@ Header: Type: ENCHANTGRADE_DB - Version: 2 + Version: 3 Footer: Imports: diff --git a/db/import-tmpl/enchantgrade.yml b/db/import-tmpl/enchantgrade.yml index eff8cfbf3f..64ccd4cad5 100644 --- a/db/import-tmpl/enchantgrade.yml +++ b/db/import-tmpl/enchantgrade.yml @@ -1,5 +1,5 @@ # This file is a part of rAthena. -# Copyright(C) 2022 rAthena Development Team +# Copyright(C) 2023 rAthena Development Team # https://rathena.org - https://github.com/rathena # # This program is free software: you can redistribute it and/or modify @@ -27,8 +27,9 @@ # - Level Item level. # Grades: Enchantgrade settings per grade level. # - Grade Enchantgrade level. -# Refine Required refine level. -# Chance Base chance of success out of 0~10000. +# Chances: Chance settings per refine level. +# - Refine Refine level. +# Chance Base chance of success out of 0~10000. # Bonus Enchantgrade bonus. (Default: 0) # AnnounceSuccess Announce on upgrade success. (Default: true) # AnnounceFail Announce on upgrade failure. (Default: false) @@ -51,4 +52,4 @@ Header: Type: ENCHANTGRADE_DB - Version: 2 + Version: 3 diff --git a/db/re/enchantgrade.yml b/db/re/enchantgrade.yml index d02008f814..29a9fc7454 100644 --- a/db/re/enchantgrade.yml +++ b/db/re/enchantgrade.yml @@ -1,5 +1,5 @@ # This file is a part of rAthena. -# Copyright(C) 2022 rAthena Development Team +# Copyright(C) 2023 rAthena Development Team # https://rathena.org - https://github.com/rathena # # This program is free software: you can redistribute it and/or modify @@ -27,8 +27,9 @@ # - Level Item level. # Grades: Enchantgrade settings per grade level. # - Grade Enchantgrade level. -# Refine Required refine level. -# Chance Base chance of success out of 0~10000. +# Chances: Chance settings per refine level. +# - Refine Refine level. +# Chance Base chance of success out of 0~10000. # Bonus Enchantgrade bonus. (Default: 0) # AnnounceSuccess Announce on upgrade success. (Default: true) # AnnounceFail Announce on upgrade failure. (Default: false) @@ -51,7 +52,7 @@ Header: Type: ENCHANTGRADE_DB - Version: 2 + Version: 3 Body: - Type: Armor @@ -59,8 +60,31 @@ Body: - Level: 2 Grades: - Grade: None - Refine: 11 - Chance: 7000 + Chances: + - Refine: 9 + Chance: 1000 + - Refine: 10 + Chance: 2000 + - Refine: 11 + Chance: 7000 + - Refine: 12 + Chance: 7000 + - Refine: 13 + Chance: 7000 + - Refine: 14 + Chance: 7000 + - Refine: 15 + Chance: 7000 + - Refine: 16 + Chance: 7000 + - Refine: 17 + Chance: 7000 + - Refine: 18 + Chance: 7000 + - Refine: 19 + Chance: 7000 + - Refine: 20 + Chance: 7000 Bonus: 10 Catalyst: Item: Blessed_Etel_Dust @@ -78,8 +102,29 @@ Body: Amount: 5 Zeny: 875000 - Grade: D - Refine: 11 - Chance: 6000 + Chances: + - Refine: 10 + Chance: 2000 + - Refine: 11 + Chance: 6000 + - Refine: 12 + Chance: 6000 + - Refine: 13 + Chance: 6000 + - Refine: 14 + Chance: 6000 + - Refine: 15 + Chance: 6000 + - Refine: 16 + Chance: 6000 + - Refine: 17 + Chance: 6000 + - Refine: 18 + Chance: 6000 + - Refine: 19 + Chance: 6000 + - Refine: 20 + Chance: 6000 Bonus: 30 Catalyst: Item: Blessed_Etel_Dust @@ -97,8 +142,27 @@ Body: Amount: 5 Zeny: 875000 - Grade: C - Refine: 11 - Chance: 5000 + Chances: + - Refine: 11 + Chance: 5000 + - Refine: 12 + Chance: 5000 + - Refine: 13 + Chance: 5000 + - Refine: 14 + Chance: 5000 + - Refine: 15 + Chance: 5000 + - Refine: 16 + Chance: 5000 + - Refine: 17 + Chance: 5000 + - Refine: 18 + Chance: 5000 + - Refine: 19 + Chance: 5000 + - Refine: 20 + Chance: 5000 Bonus: 50 AnnounceFail: true Catalyst: @@ -117,8 +181,27 @@ Body: Amount: 5 Zeny: 875000 - Grade: B - Refine: 11 - Chance: 4000 + Chances: + - Refine: 11 + Chance: 4000 + - Refine: 12 + Chance: 4000 + - Refine: 13 + Chance: 4000 + - Refine: 14 + Chance: 4000 + - Refine: 15 + Chance: 4000 + - Refine: 16 + Chance: 4000 + - Refine: 17 + Chance: 4000 + - Refine: 18 + Chance: 4000 + - Refine: 19 + Chance: 4000 + - Refine: 20 + Chance: 4000 Bonus: 100 AnnounceFail: true Catalyst: @@ -141,8 +224,31 @@ Body: - Level: 5 Grades: - Grade: None - Refine: 11 - Chance: 7000 + Chances: + - Refine: 9 + Chance: 1000 + - Refine: 10 + Chance: 2000 + - Refine: 11 + Chance: 7000 + - Refine: 12 + Chance: 7000 + - Refine: 13 + Chance: 7000 + - Refine: 14 + Chance: 7000 + - Refine: 15 + Chance: 7000 + - Refine: 16 + Chance: 7000 + - Refine: 17 + Chance: 7000 + - Refine: 18 + Chance: 7000 + - Refine: 19 + Chance: 7000 + - Refine: 20 + Chance: 7000 Bonus: 10 Catalyst: Item: Blessed_Etel_Dust @@ -160,8 +266,29 @@ Body: Amount: 5 Zeny: 875000 - Grade: D - Refine: 11 - Chance: 6000 + Chances: + - Refine: 10 + Chance: 2000 + - Refine: 11 + Chance: 6000 + - Refine: 12 + Chance: 6000 + - Refine: 13 + Chance: 6000 + - Refine: 14 + Chance: 6000 + - Refine: 15 + Chance: 6000 + - Refine: 16 + Chance: 6000 + - Refine: 17 + Chance: 6000 + - Refine: 18 + Chance: 6000 + - Refine: 19 + Chance: 6000 + - Refine: 20 + Chance: 6000 Bonus: 30 Catalyst: Item: Blessed_Etel_Dust @@ -179,8 +306,27 @@ Body: Amount: 5 Zeny: 875000 - Grade: C - Refine: 11 - Chance: 5000 + Chances: + - Refine: 11 + Chance: 5000 + - Refine: 12 + Chance: 5000 + - Refine: 13 + Chance: 5000 + - Refine: 14 + Chance: 5000 + - Refine: 15 + Chance: 5000 + - Refine: 16 + Chance: 5000 + - Refine: 17 + Chance: 5000 + - Refine: 18 + Chance: 5000 + - Refine: 19 + Chance: 5000 + - Refine: 20 + Chance: 5000 Bonus: 50 AnnounceFail: true Catalyst: @@ -199,8 +345,27 @@ Body: Amount: 5 Zeny: 875000 - Grade: B - Refine: 11 - Chance: 4000 + Chances: + - Refine: 11 + Chance: 4000 + - Refine: 12 + Chance: 4000 + - Refine: 13 + Chance: 4000 + - Refine: 14 + Chance: 4000 + - Refine: 15 + Chance: 4000 + - Refine: 16 + Chance: 4000 + - Refine: 17 + Chance: 4000 + - Refine: 18 + Chance: 4000 + - Refine: 19 + Chance: 4000 + - Refine: 20 + Chance: 4000 Bonus: 100 AnnounceFail: true Catalyst: diff --git a/doc/yaml/db/enchantgrade.yml b/doc/yaml/db/enchantgrade.yml new file mode 100644 index 0000000000..a1fd2ef5fe --- /dev/null +++ b/doc/yaml/db/enchantgrade.yml @@ -0,0 +1,34 @@ +########################################################################### +# Enchantgrade Database +########################################################################### +# +# Enchantgrade Settings +# +########################################################################### +# - Type Item type. +# Levels: Enchantgrade settings per item level. +# - Level Item level. +# Grades: Enchantgrade settings per grade level. +# - Grade Enchantgrade level. +# Chances: Chance settings per refine level. +# - Refine Refine level. +# Chance Base chance of success out of 0~10000. +# Bonus Enchantgrade bonus. (Default: 0) +# AnnounceSuccess Announce on upgrade success. (Default: true) +# AnnounceFail Announce on upgrade failure. (Default: false) +# Announce Announce on upgrade success and failure. +# Catalyst: Catalyst item to increase chance of success. +# Item The item that can be used. +# AmountPerStep Amount of Item needed. +# Set to 0 to disable the catalyst. +# MaximumSteps Maximum amount of times Item can be used. +# ChanceIncrease Amount at which the chance increases for each Item used. +# Options: Success chance based on cost type. +# - Option Index of the client option. +# Item Required item. +# Amount Amount of required item. (Default: 1) +# Set to 0 to remove an option. +# Price Amount of zeny required. (Default: 0) +# BreakingRate Chance of item breaking out of 0~10000. (Default: 0) +# DowngradeAmount Number of refine levels reduced on failure. (Default: 0) +########################################################################### diff --git a/doc/yaml/db/license.yml b/doc/yaml/db/license.yml index 87d322dcce..d77cfefe5a 100644 --- a/doc/yaml/db/license.yml +++ b/doc/yaml/db/license.yml @@ -1,5 +1,5 @@ # This file is a part of rAthena. -# Copyright(C) 2021 rAthena Development Team +# Copyright(C) 2023 rAthena Development Team # https://rathena.org - https://github.com/rathena # # This program is free software: you can redistribute it and/or modify diff --git a/src/map/clif.cpp b/src/map/clif.cpp index becf0351c3..cf18d6a52d 100644 --- a/src/map/clif.cpp +++ b/src/map/clif.cpp @@ -23570,11 +23570,7 @@ void clif_enchantgrade_add( map_session_data& sd, uint16 index = UINT16_MAX, std if( index < UINT16_MAX ){ p->index = client_index( index ); - if( sd.inventory.u.items_inventory[index].refine >= gradeLevel->refine ){ - p->success_chance = gradeLevel->chance / 100; - }else{ - p->success_chance = 0; - } + p->success_chance = gradeLevel->chances[sd.inventory.u.items_inventory[index].refine] / 100; p->blessing_info.id = client_nameid( gradeLevel->catalyst.item ); p->blessing_info.amount = gradeLevel->catalyst.amountPerStep; p->blessing_info.max_blessing = gradeLevel->catalyst.maximumSteps; @@ -23750,8 +23746,10 @@ void clif_parse_enchantgrade_start( int fd, map_session_data* sd ){ return; } - // Not refined enough - if( sd->inventory.u.items_inventory[index].refine < enchantgradelevel->refine ){ + uint16 totalChance = enchantgradelevel->chances[sd->inventory.u.items_inventory[index].refine]; + + // No chance to increase the enchantgrade + if( totalChance == 0 ){ return; } @@ -23767,7 +23765,6 @@ void clif_parse_enchantgrade_start( int fd, map_session_data* sd ){ return; } - uint16 totalChance = enchantgradelevel->chance; uint16 steps = min( p->blessing_amount, enchantgradelevel->catalyst.maximumSteps ); std::unordered_map requiredItems; diff --git a/src/map/status.cpp b/src/map/status.cpp index 008ad8f7f1..38ad25ad83 100644 --- a/src/map/status.cpp +++ b/src/map/status.cpp @@ -653,37 +653,38 @@ uint64 EnchantgradeDatabase::parseBodyNode( const ryml::NodeRef& node ){ bool gradeExists = grade != nullptr; if( !gradeExists ){ + if( !this->nodesExist( gradeNode, { "Chances", "Options" } ) ){ + return 0; + } + grade = std::make_shared(); grade->grade = gradeLevel; - - if( !this->nodesExist( gradeNode, { "Refine", "Chance", "Options" } ) ){ - return 0; + for( int i = 0; i < ARRAYLENGTH( grade->chances ); i++ ){ + grade->chances[i] = 0; } } - if( this->nodeExists( gradeNode, "Refine" ) ){ - uint16 refine; + if( this->nodeExists( gradeNode, "Chances" ) ){ + for( const ryml::NodeRef& chanceNode : gradeNode["Chances"] ){ + uint16 refine; - if( !this->asUInt16( gradeNode, "Refine", refine ) ){ - return 0; + if( !this->asUInt16( chanceNode, "Refine", refine ) ){ + return 0; + } + + if( refine > MAX_REFINE ){ + this->invalidWarning( chanceNode["Refine"], "Refine %hu is too high. Maximum: %hu.\n", refine, MAX_REFINE ); + return 0; + } + + uint16 chance; + + if( !this->asUInt16Rate( chanceNode, "Chance", chance ) ){ + return 0; + } + + grade->chances[refine] = chance; } - - if( refine > MAX_REFINE ){ - this->invalidWarning( gradeNode["Refine"], "Refine %hu is too high, capping to %hu...\n", refine, MAX_REFINE ); - refine = MAX_REFINE; - } - - grade->refine = refine; - } - - if( this->nodeExists( gradeNode, "Chance" ) ){ - uint16 chance; - - if( !this->asUInt16Rate( gradeNode, "Chance", chance ) ){ - return 0; - } - - grade->chance = chance; } if( this->nodeExists( gradeNode, "Bonus" ) ){ diff --git a/src/map/status.hpp b/src/map/status.hpp index b6b524ab41..e77b50d9b9 100644 --- a/src/map/status.hpp +++ b/src/map/status.hpp @@ -165,8 +165,7 @@ struct s_enchantgradeoption{ struct s_enchantgradelevel{ e_enchantgrade grade; - uint16 refine; - uint16 chance; + uint16 chances[MAX_REFINE + 1]; uint16 bonus; bool announceSuccess; bool announceFail; @@ -186,7 +185,7 @@ struct s_enchantgrade{ class EnchantgradeDatabase : public TypesafeYamlDatabase{ public: - EnchantgradeDatabase() : TypesafeYamlDatabase( "ENCHANTGRADE_DB", 2, 1 ){ + EnchantgradeDatabase() : TypesafeYamlDatabase( "ENCHANTGRADE_DB", 3 ){ } diff --git a/src/tool/yamlupgrade.cpp b/src/tool/yamlupgrade.cpp index cf1e63901d..8976b894cb 100644 --- a/src/tool/yamlupgrade.cpp +++ b/src/tool/yamlupgrade.cpp @@ -10,6 +10,7 @@ static bool upgrade_item_db(std::string file, const uint32 source_version); static bool upgrade_job_stats(std::string file, const uint32 source_version); static bool upgrade_status_db(std::string file, const uint32 source_version); static bool upgrade_map_drops_db(std::string file, const uint32 source_version); +static bool upgrade_enchantgrade_db( std::string file, const uint32 source_version ); template bool process(const std::string &type, uint32 version, const std::vector &paths, const std::string &name, Func lambda) { @@ -129,7 +130,7 @@ bool YamlUpgradeTool::initialize( int argc, char* argv[] ){ if (!process("STATUS_DB", 3, root_paths, "status", [](const std::string& path, const std::string& name_ext, uint32 source_version) -> bool { return upgrade_status_db(path + name_ext, source_version); })) { - return 0; + return false; } if (!process("MAP_DROP_DB", 2, root_paths, "map_drops", [](const std::string& path, const std::string& name_ext, uint32 source_version) -> bool { @@ -138,6 +139,12 @@ bool YamlUpgradeTool::initialize( int argc, char* argv[] ){ return 0; } + if( !process( "ENCHANTGRADE_DB", 3, root_paths, "enchantgrade", []( const std::string& path, const std::string& name_ext, uint32 source_version ) -> bool { + return upgrade_enchantgrade_db( path + name_ext, source_version ); + } ) ){ + return false; + } + return true; } @@ -366,6 +373,60 @@ static bool upgrade_map_drops_db(std::string file, const uint32 source_version) return true; } +static bool upgrade_enchantgrade_db( std::string file, const uint32 source_version ){ + size_t entries = 0; + + for( auto input : inNode["Body"] ){ + // If under version 3 + if( source_version < 3 ){ + if( input["Levels"].IsDefined() ){ + for( auto levelNode : input["Levels"] ){ + if( levelNode["Grades"].IsDefined() ){ + for( auto gradeNode : levelNode["Grades"] ){ + // Convert Refine + Chance to a Chances array + if( gradeNode["Refine"].IsDefined() && !gradeNode["Chance"].IsDefined() ){ + ShowError( "Cannot upgrade automatically, because Refine is specified, but Chance is missing" ); + return false; + } + + if( gradeNode["Chance"].IsDefined() && !gradeNode["Refine"].IsDefined() ){ + ShowError( "Cannot upgrade automatically, because Chance is specified, but Refine is missing" ); + return false; + } + + uint16 refine = gradeNode["Refine"].as(); + uint16 chance = gradeNode["Chance"].as(); + + auto chancesNode = gradeNode["Chances"]; + + for( int i = refine, j = 0; i <= MAX_REFINE; i++, j++ ){ + auto chanceNode = chancesNode[j]; + + chanceNode["Refine"] = i; + chanceNode["Chance"] = chance; + } + + // Remove the existing Refine entry + gradeNode.remove( "Refine" ); + + // Remove the existing Chance entry + gradeNode.remove( "Chance" ); + } + } + } + } + } + + body << input; + entries++; + } + + ShowStatus( "Done converting/upgrading '" CL_WHITE "%zu" CL_RESET "' entries in '" CL_WHITE "%s" CL_RESET "'.\n", entries, file.c_str() ); + + return true; +} + + int main( int argc, char *argv[] ){ return main_core( argc, argv ); }