Extended item_group_db.yml (#6173)

* Added Index field
  The structure now allows to define the same item with different data
* Updated the tool yamlupgrade for version upgrade
This commit is contained in:
Atemo 2023-10-10 17:21:09 +02:00 committed by GitHub
parent 61311f5912
commit b4e066a37f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 47960 additions and 24233 deletions

View File

@ -26,8 +26,9 @@
# SubGroups:
# - SubGroup: SubGroup number associated with the list of item. See doc/item_group.txt for more information.
# List: List of item(s) for the SubGroup.
# - Item AegisName of item that will be obtained from this item group.
# Rate Probability to get the item. See doc/item_group.txt for more information. (Default: 0)
# - Index Unique number that can be used to add the same Item with different data in the list.
# Item AegisName of item that will be obtained from this item group.
# Rate Probability to get the item. (Default: 0)
# Amount Amount of item that will be obtained. (Default: 1)
# Duration Makes the item a rental item which will expire within the given amount in minutes. Not intended for use with stackable items. (Default: 0)
# Announced If player obtains this item it will be broadcasted to the server. (Default: false)
@ -38,10 +39,10 @@
# RandomOptionGroup Applies random options of this group to all equipable items (Default: None)
# RefineMinimum Applies at least this refine level to all equipable items (Default: 0)
# RefineMaximum Applies at most this refine level to all equipable items (Default: 0)
# Clear Remove the given item. (Optional)
# Clear Whether the current datas should be removed. (Optional)
# Clear Remove the given SubGroup. (Optional)
###########################################################################
Header:
Type: ITEM_GROUP_DB
Version: 2
Version: 3

View File

@ -26,8 +26,9 @@
# SubGroups:
# - SubGroup: SubGroup number associated with the list of item. See doc/item_group.txt for more information.
# List: List of item(s) for the SubGroup.
# - Item AegisName of item that will be obtained from this item group.
# Rate Probability to get the item. See doc/item_group.txt for more information. (Default: 0)
# - Index Unique number that can be used to add the same Item with different data in the list.
# Item AegisName of item that will be obtained from this item group.
# Rate Probability to get the item. (Default: 0)
# Amount Amount of item that will be obtained. (Default: 1)
# Duration Makes the item a rental item which will expire within the given amount in minutes. Not intended for use with stackable items. (Default: 0)
# Announced If player obtains this item it will be broadcasted to the server. (Default: false)
@ -38,13 +39,13 @@
# RandomOptionGroup Applies random options of this group to all equipable items (Default: None)
# RefineMinimum Applies at least this refine level to all equipable items (Default: 0)
# RefineMaximum Applies at most this refine level to all equipable items (Default: 0)
# Clear Remove the given item. (Optional)
# Clear Whether the current datas should be removed. (Optional)
# Clear Remove the given SubGroup. (Optional)
###########################################################################
Header:
Type: ITEM_GROUP_DB
Version: 2
Version: 3
Footer:
Imports:

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -43,8 +43,12 @@ GroupID: See the "Item Group ID" section in 'src/map/itemdb.hpp' and the "item g
---------------------------------------
Index: Unique number that can be used to add the same Item with different data in the list.
---------------------------------------
Item: Available item that will be obtained from this item group.
Requires the AegisName of the item.
Requires the AegisName of the item.
---------------------------------------
@ -52,12 +56,14 @@ Rate: Probability to get the item. Not a percentage value!
Examples:
- Group: MyItemGroup
Contain:
SubGroups:
- SubGroup: 1
List:
- Item: Knife
- Index: 0
Item: Knife
Rate: 5
- Item: Dagger
- Index: 1
Item: Dagger
Rate: 1
- Knife has chance 5/6 (83.3%) to be obtained
@ -74,22 +80,28 @@ SubGroup: Setting this to '0' makes the item always obtainable ("must" item).
Item Group:
- Group: MyItemGroup
Contain:
SubGroups:
- SubGroup: 0
List:
- Item: Knife # "must" item(s)
- Item: Dagger # "must" item(s)
- Index: 0
Item: Knife # "must" item(s)
- Index: 1
Item: Dagger # "must" item(s)
- SubGroup: 1
List:
- Item: Stiletto # random at SubGroup 1
- Index: 0
Item: Stiletto # random at SubGroup 1
Rate: 5
- Item: Stiletto_ # random at SubGroup 1
- Index: 1
Item: Stiletto_ # random at SubGroup 1
Rate: 2
- SubGroup: 2
List:
- Item: Stiletto # random at SubGroup 2
- Index: 0
Item: Stiletto # random at SubGroup 2
Rate: 5
- Item: Dagger_ # random at SubGroup 2
- Index: 1
Item: Dagger_ # random at SubGroup 2
Rate: 4
Usages:

View File

@ -9,8 +9,9 @@
# SubGroups:
# - SubGroup: SubGroup number associated with the list of item. See doc/item_group.txt for more information.
# List: List of item(s) for the SubGroup.
# - Item AegisName of item that will be obtained from this item group.
# Rate Probability to get the item. See doc/item_group.txt for more information. (Default: 0)
# - Index Unique number that can be used to add the same Item with different data in the list.
# Item AegisName of item that will be obtained from this item group.
# Rate Probability to get the item. (Default: 0)
# Amount Amount of item that will be obtained. (Default: 1)
# Duration Makes the item a rental item which will expire within the given amount in minutes. Not intended for use with stackable items. (Default: 0)
# Announced If player obtains this item it will be broadcasted to the server. (Default: false)
@ -21,6 +22,6 @@
# RandomOptionGroup Applies random options of this group to all equipable items (Default: None)
# RefineMinimum Applies at least this refine level to all equipable items (Default: 0)
# RefineMaximum Applies at most this refine level to all equipable items (Default: 0)
# Clear Remove the given item. (Optional)
# Clear Whether the current datas should be removed. (Optional)
# Clear Remove the given SubGroup. (Optional)
###########################################################################

View File

@ -3300,43 +3300,58 @@ uint64 ItemGroupDatabase::parseBodyNode(const ryml::NodeRef& node) {
const auto& listNode = subit["List"];
for (const auto& listit : listNode) {
uint32 index;
if (!this->asUInt32(listit, "Index", index))
continue;
if (this->nodeExists(listit, "Clear")) {
std::string item_name;
bool active;
if (!this->asString(listit, "Clear", item_name))
if (!this->asBool(listit, "Clear", active) || !active)
continue;
std::shared_ptr<item_data> item = item_db.search_aegisname( item_name.c_str() );
if (item == nullptr) {
this->invalidWarning(listit["Clear"], "Unknown Item %s. Clear failed.\n", item_name.c_str());
continue;
}
if (random->data.erase(item->nameid) == 0)
this->invalidWarning(listit["Clear"], "Item %hu doesn't exist in the SubGroup %hu (group %s). Clear failed.\n", item->nameid, subgroup, group_name.c_str());
if (random->data.erase(index) == 0)
this->invalidWarning(listit["Clear"], "Index %u doesn't exist in the SubGroup %hu (group %s). Clear failed.\n", index, subgroup, group_name.c_str());
continue;
}
std::string item_name;
if (!this->asString(listit, "Item", item_name))
continue;
std::shared_ptr<item_data> item = item_db.search_aegisname( item_name.c_str() );
if (item == nullptr) {
this->invalidWarning(listit["Item"], "Unknown Item %s.\n", item_name.c_str());
continue;
}
std::shared_ptr<s_item_group_entry> entry = util::umap_find(random->data, item->nameid);
std::shared_ptr<s_item_group_entry> entry = util::umap_find(random->data, index);
bool entry_exists = entry != nullptr;
if (!entry_exists) {
if (!this->nodesExist(listit, { "Item" }))
return 0;
entry = std::make_shared<s_item_group_entry>();
random->data[item->nameid] = entry;
random->data[index] = entry;
}
std::shared_ptr<item_data> item = nullptr;
if (this->nodeExists(listit, "Item")) {
std::string item_name;
if (!this->asString(listit, "Item", item_name))
continue;
item = item_db.search_aegisname( item_name.c_str() );
if (item == nullptr) {
this->invalidWarning(listit["Item"], "Unknown Item %s.\n", item_name.c_str());
continue;
}
} else {
if (!entry_exists) {
item = item_db.find( entry->nameid );
}
}
// (shouldn't happen)
if (item == nullptr) {
this->invalidWarning(listit["index"], "Missing Item definition for Index %u.\n", index);
continue;
}
entry->nameid = item->nameid;

View File

@ -2016,7 +2016,7 @@ struct s_item_group_entry
struct s_item_group_random
{
uint32 total_rate;
std::unordered_map<t_itemid, std::shared_ptr<s_item_group_entry>> data; /// item ID, s_item_group_entry
std::unordered_map<uint32, std::shared_ptr<s_item_group_entry>> data; /// index, s_item_group_entry
std::shared_ptr<s_item_group_entry> get_random_itemsubgroup();
};
@ -2175,7 +2175,7 @@ extern ItemDatabase item_db;
class ItemGroupDatabase : public TypesafeCachedYamlDatabase<uint16, s_item_group_db> {
public:
ItemGroupDatabase() : TypesafeCachedYamlDatabase("ITEM_GROUP_DB", 2, 1) {
ItemGroupDatabase() : TypesafeCachedYamlDatabase("ITEM_GROUP_DB", 3, 1) {
}

View File

@ -11,6 +11,7 @@ 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 );
static bool upgrade_item_group_db( std::string file, const uint32 source_version );
template<typename Func>
bool process(const std::string &type, uint32 version, const std::vector<std::string> &paths, const std::string &name, Func lambda) {
@ -144,6 +145,11 @@ bool YamlUpgradeTool::initialize( int argc, char* argv[] ){
} ) ){
return false;
}
if( !process( "ITEM_GROUP_DB", 3, root_paths, "item_group_db", []( const std::string& path, const std::string& name_ext, uint32 source_version ) -> bool {
return upgrade_item_group_db( path + name_ext, source_version );
} ) ){
return false;
}
return true;
}
@ -426,6 +432,90 @@ static bool upgrade_enchantgrade_db( std::string file, const uint32 source_versi
return true;
}
static bool upgrade_item_group_db( std::string file, const uint32 source_version ){
size_t entries = 0;
for( const auto input : inNode["Body"] ){
// If under version 3
if( source_version < 3 ){
body << YAML::BeginMap;
body << YAML::Key << "Group" << YAML::Value << input["Group"];
if( input["SubGroups"].IsDefined() ){
body << YAML::Key << "SubGroups";
body << YAML::BeginSeq;
for (const auto &it : input["SubGroups"]) {
body << YAML::BeginMap;
if( it["SubGroup"].IsDefined() ){
body << YAML::Key << "SubGroup" << YAML::Value << it["SubGroup"];
}
if( it["List"].IsDefined() )
body << YAML::Key << "List";{
body << YAML::BeginSeq;
uint32 index = 0;
for( auto ListNode : it["List"] ){
if( !ListNode["Item"].IsDefined() ){
ShowError( "Cannot upgrade automatically, Item is missing" );
return false;
}
body << YAML::BeginMap;
body << YAML::Key << "Index" << YAML::Value << index;
body << YAML::Key << "Item" << YAML::Value << ListNode["Item"];
if( ListNode["Rate"].IsDefined() )
body << YAML::Key << "Rate" << YAML::Value << ListNode["Rate"];
if( ListNode["Amount"].IsDefined() )
body << YAML::Key << "Amount" << YAML::Value << ListNode["Amount"];
if( ListNode["Duration"].IsDefined() )
body << YAML::Key << "Duration" << YAML::Value << ListNode["Duration"];
if( ListNode["Announced"].IsDefined() )
body << YAML::Key << "Announced" << YAML::Value << ListNode["Announced"];
if( ListNode["UniqueId"].IsDefined() )
body << YAML::Key << "UniqueId" << YAML::Value << ListNode["UniqueId"];
if( ListNode["Stacked"].IsDefined() )
body << YAML::Key << "Stacked" << YAML::Value << ListNode["Stacked"];
if( ListNode["Named"].IsDefined() )
body << YAML::Key << "Named" << YAML::Value << ListNode["Named"];
if( ListNode["Bound"].IsDefined() )
body << YAML::Key << "Bound" << YAML::Value << ListNode["Bound"];
if( ListNode["RandomOptionGroup"].IsDefined() )
body << YAML::Key << "RandomOptionGroup" << YAML::Value << ListNode["RandomOptionGroup"];
if( ListNode["RefineMinimum"].IsDefined() )
body << YAML::Key << "RefineMinimum" << YAML::Value << ListNode["RefineMinimum"];
if( ListNode["RefineMaximum"].IsDefined() )
body << YAML::Key << "RefineMaximum" << YAML::Value << ListNode["RefineMaximum"];
if( ListNode["Clear"].IsDefined() )
body << YAML::Key << "Clear" << YAML::Value << ListNode["Clear"];
index++;
body << YAML::EndMap;
}
body << YAML::EndSeq;
}
if( it["Clear"].IsDefined() )
body << YAML::Key << "Clear" << YAML::Value << it["Clear"];
body << YAML::EndMap;
}
body << YAML::EndSeq;
}
body << YAML::EndMap;
}
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<YamlUpgradeTool>( argc, argv );