Browse Source

Algorithm for opening group items in renewal (#8849)

- Introduced a new item_group_db attribute "Algorithm" with three possible values: All, Random and SharedPool
  * The attribute now affects behavior of how an item is selected within the group instead of SubGroup
  * This affects the commands "getgroupitem", "getrandgroupitem" and "groupranditem"
  * Be aware that various commands use or default to SubGroup=1
- Implemented the "SharedPool" algorithm where rate is the amount of items in the group
  * When an item is retrieved from the group, it is removed from the group
  * Only when the group is completely empty or the server restarts, the group refills
  * This algorithm is used by many renewal item groups
- The algorithm "All" replaces the previous SubGroup=0 check
  * When using "getgroupitem" on a group with "All" as algorithm, you will receive all items from the group
  * When using "getrandgroupitem" on a group with "All" as algorithm, you will receive a random item from the group
  * When using "groupranditem" on a group with "All" as algorithm, it will return a random item from the group
- The algorithm "Random" is the previous algorithm that returns a random item using rate as chance
- Battle config "item_group_rate" now only applies to GROUP_ALGORITHM_DROP
  * This is accomplished by storing the adjusted rate in a separate variable
- Updated documentation accordingly
- Fixes #8848 

---------

Co-authored-by: Atemo
Playtester 5 months ago
parent
commit
f41a14cbd1

+ 3 - 2
db/import-tmpl/item_group_db.yml

@@ -1,5 +1,5 @@
 # This file is a part of rAthena.
 # This file is a part of rAthena.
-#   Copyright(C) 2021 rAthena Development Team
+#   Copyright(C) 2024 rAthena Development Team
 #   https://rathena.org - https://github.com/rathena
 #   https://rathena.org - https://github.com/rathena
 #
 #
 # This program is free software: you can redistribute it and/or modify
 # This program is free software: you can redistribute it and/or modify
@@ -25,6 +25,7 @@
 # - Group                      Group name of the item.
 # - Group                      Group name of the item.
 #   SubGroups:
 #   SubGroups:
 #     - SubGroup:              SubGroup number associated with the list of item. See doc/item_group.txt for more information.
 #     - SubGroup:              SubGroup number associated with the list of item. See doc/item_group.txt for more information.
+#       Algorithm:             Type of algorithm associated with SubGroup. (Default: SharedPool)
 #       List:                  List of item(s) for the SubGroup.
 #       List:                  List of item(s) for the SubGroup.
 #        - Index               Unique number that can be used to add the same Item with different data in the list.
 #        - 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.
 #          Item                AegisName of item that will be obtained from this item group.
@@ -45,4 +46,4 @@
 
 
 Header:
 Header:
   Type: ITEM_GROUP_DB
   Type: ITEM_GROUP_DB
-  Version: 3
+  Version: 4

+ 9 - 8
db/item_group_db.yml

@@ -1,5 +1,5 @@
 # This file is a part of rAthena.
 # This file is a part of rAthena.
-#   Copyright(C) 2021 rAthena Development Team
+#   Copyright(C) 2024 rAthena Development Team
 #   https://rathena.org - https://github.com/rathena
 #   https://rathena.org - https://github.com/rathena
 #
 #
 # This program is free software: you can redistribute it and/or modify
 # This program is free software: you can redistribute it and/or modify
@@ -25,6 +25,7 @@
 # - Group                      Group name of the item.
 # - Group                      Group name of the item.
 #   SubGroups:
 #   SubGroups:
 #     - SubGroup:              SubGroup number associated with the list of item. See doc/item_group.txt for more information.
 #     - SubGroup:              SubGroup number associated with the list of item. See doc/item_group.txt for more information.
+#       Algorithm:             Type of algorithm associated with SubGroup. (Default: SharedPool)
 #       List:                  List of item(s) for the SubGroup.
 #       List:                  List of item(s) for the SubGroup.
 #        - Index               Unique number that can be used to add the same Item with different data in the list.
 #        - 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.
 #          Item                AegisName of item that will be obtained from this item group.
@@ -32,7 +33,7 @@
 #          Amount              Amount of item that will be obtained. (Default: 1)
 #          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)
 #          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)
 #          Announced           If player obtains this item it will be broadcasted to the server. (Default: false)
-#          UniqueId            Makes the given item(s) have a Unique ID. (Default: false)
+#          UniqueId            Makes the given item(s) have a Unique ID. (Default: UniqueId from item_db)
 #          Stacked             Whether stackable items are given stacked or not. (Default: true)
 #          Stacked             Whether stackable items are given stacked or not. (Default: true)
 #          Named               Inscribes the item with the obtainer's name. (Default: false)
 #          Named               Inscribes the item with the obtainer's name. (Default: false)
 #          Bound               Binds the obtained item. (Default: None)
 #          Bound               Binds the obtained item. (Default: None)
@@ -45,12 +46,12 @@
 
 
 Header:
 Header:
   Type: ITEM_GROUP_DB
   Type: ITEM_GROUP_DB
-  Version: 3
+  Version: 4
 
 
 Footer:
 Footer:
   Imports:
   Imports:
-  - Path: db/pre-re/item_group_db.yml
-    Mode: Prerenewal
-  - Path: db/re/item_group_db.yml
-    Mode: Renewal
-  - Path: db/import/item_group_db.yml
+    - Path: db/pre-re/item_group_db.yml
+      Mode: Prerenewal
+    - Path: db/re/item_group_db.yml
+      Mode: Renewal
+    - Path: db/import/item_group_db.yml

+ 59 - 59
db/pre-re/item_db_usable.yml

@@ -1061,7 +1061,7 @@ Body:
       BuyingStore: true
       BuyingStore: true
       Container: true
       Container: true
     Script: |
     Script: |
-      getrandgroupitem(IG_BlueBox,1);
+      getgroupitem(IG_BLUEBOX);
   - Id: 604
   - Id: 604
     AegisName: Branch_Of_Dead_Tree
     AegisName: Branch_Of_Dead_Tree
     Name: Dead Branch
     Name: Dead Branch
@@ -1199,7 +1199,7 @@ Body:
       BuyingStore: true
       BuyingStore: true
       Container: true
       Container: true
     Script: |
     Script: |
-      getrandgroupitem(IG_CardAlbum,1);
+      getgroupitem(IG_CARDALBUM);
   - Id: 617
   - Id: 617
     AegisName: Old_Violet_Box
     AegisName: Old_Violet_Box
     Name: Old Purple Box
     Name: Old Purple Box
@@ -1210,7 +1210,7 @@ Body:
       BuyingStore: true
       BuyingStore: true
       Container: true
       Container: true
     Script: |
     Script: |
-      getrandgroupitem(IG_VioletBox,1);
+      getgroupitem(IG_VIOLETBOX);
   - Id: 618
   - Id: 618
     AegisName: Worn_Out_Scroll
     AegisName: Worn_Out_Scroll
     Name: Worn Out Scroll
     Name: Worn Out Scroll
@@ -1528,7 +1528,7 @@ Body:
       BuyingStore: true
       BuyingStore: true
       Container: true
       Container: true
     Script: |
     Script: |
-      getrandgroupitem(IG_GiftBox,1);
+      getgroupitem(IG_GIFTBOX);
   - Id: 645
   - Id: 645
     AegisName: Center_Potion
     AegisName: Center_Potion
     Name: Concentration Potion
     Name: Concentration Potion
@@ -1674,7 +1674,7 @@ Body:
       BuyingStore: true
       BuyingStore: true
       Container: true
       Container: true
     Script: |
     Script: |
-      getrandgroupitem(IG_GiftBox_1,1);
+      getgroupitem(IG_GIFTBOX_1);
   - Id: 665
   - Id: 665
     AegisName: Gift_Box_2
     AegisName: Gift_Box_2
     Name: Gift Box
     Name: Gift Box
@@ -1685,7 +1685,7 @@ Body:
       BuyingStore: true
       BuyingStore: true
       Container: true
       Container: true
     Script: |
     Script: |
-      getrandgroupitem(IG_GiftBox_2,1);
+      getgroupitem(IG_GIFTBOX_2);
   - Id: 666
   - Id: 666
     AegisName: Gift_Box_3
     AegisName: Gift_Box_3
     Name: Gift Box
     Name: Gift Box
@@ -1696,7 +1696,7 @@ Body:
       BuyingStore: true
       BuyingStore: true
       Container: true
       Container: true
     Script: |
     Script: |
-      getrandgroupitem(IG_GiftBox_3,1);
+      getgroupitem(IG_GIFTBOX_3);
   - Id: 667
   - Id: 667
     AegisName: Gift_Box_4
     AegisName: Gift_Box_4
     Name: Gift Box
     Name: Gift Box
@@ -1707,7 +1707,7 @@ Body:
       BuyingStore: true
       BuyingStore: true
       Container: true
       Container: true
     Script: |
     Script: |
-      getrandgroupitem(IG_GiftBox_4,1);
+      getgroupitem(IG_GIFTBOX_4);
   - Id: 668
   - Id: 668
     AegisName: Handsei
     AegisName: Handsei
     Name: Red Envelope
     Name: Red Envelope
@@ -2663,7 +2663,7 @@ Body:
     Flags:
     Flags:
       Container: true
       Container: true
     Script: |
     Script: |
-      getrandgroupitem(IG_GiftBoxChina,1);
+      getgroupitem(IG_GIFTBOXCHINA);
   - Id: 12024
   - Id: 12024
     AegisName: Red_Pouch_Of_Surprise
     AegisName: Red_Pouch_Of_Surprise
     Name: Red Pouch
     Name: Red Pouch
@@ -2683,7 +2683,7 @@ Body:
     Flags:
     Flags:
       Container: true
       Container: true
     Script: |
     Script: |
-      getrandgroupitem(IG_EggBoy,1);
+      getgroupitem(IG_EGGBOY);
   - Id: 12026
   - Id: 12026
     AegisName: Egg_Girl
     AegisName: Egg_Girl
     Name: Dano Festival Egg
     Name: Dano Festival Egg
@@ -2693,7 +2693,7 @@ Body:
     Flags:
     Flags:
       Container: true
       Container: true
     Script: |
     Script: |
-      getrandgroupitem(IG_EggGirl,1);
+      getgroupitem(IG_EGGGIRL);
   - Id: 12027
   - Id: 12027
     AegisName: Giggling_Box
     AegisName: Giggling_Box
     Name: Giggling Box
     Name: Giggling Box
@@ -2821,7 +2821,7 @@ Body:
     Flags:
     Flags:
       Container: true
       Container: true
     Script: |
     Script: |
-      getrandgroupitem(IG_LottoBox,1);
+      getgroupitem(IG_LOTTOBOX);
   - Id: 12039
   - Id: 12039
     AegisName: Lotto_Box05
     AegisName: Lotto_Box05
     Name: Lotto Box 05
     Name: Lotto Box 05
@@ -3536,7 +3536,7 @@ Body:
       BuyingStore: true
       BuyingStore: true
       Container: true
       Container: true
     Script: |
     Script: |
-      getrandgroupitem(IG_Quiver,1);
+      getgroupitem(IG_QUIVER);
   - Id: 12105
   - Id: 12105
     AegisName: Set_Of_Taiming_Item
     AegisName: Set_Of_Taiming_Item
     Name: Taming Gift Set
     Name: Taming Gift Set
@@ -3547,9 +3547,9 @@ Body:
       BuyingStore: true
       BuyingStore: true
       Container: true
       Container: true
     Script: |
     Script: |
-      getrandgroupitem(IG_Taming,1);
-      getrandgroupitem(IG_Taming,1);
-      getrandgroupitem(IG_Taming,1);
+      getgroupitem(IG_TAMING);
+      getgroupitem(IG_TAMING);
+      getgroupitem(IG_TAMING);
   - Id: 12106
   - Id: 12106
     AegisName: Accessory_Box
     AegisName: Accessory_Box
     Name: Jewelry Box
     Name: Jewelry Box
@@ -3560,7 +3560,7 @@ Body:
       BuyingStore: true
       BuyingStore: true
       Container: true
       Container: true
     Script: |
     Script: |
-      getrandgroupitem(IG_Accesory,1);
+      getgroupitem(IG_ACCESORY);
   - Id: 12107
   - Id: 12107
     AegisName: Wrapped_Mask
     AegisName: Wrapped_Mask
     Name: Wrapped Mask
     Name: Wrapped Mask
@@ -3571,7 +3571,7 @@ Body:
       BuyingStore: true
       BuyingStore: true
       Container: true
       Container: true
     Script: |
     Script: |
-      getrandgroupitem(IG_Mask,1);
+      getgroupitem(IG_MASK);
   - Id: 12108
   - Id: 12108
     AegisName: Bundle_Of_Magic_Scroll
     AegisName: Bundle_Of_Magic_Scroll
     Name: Scroll Package
     Name: Scroll Package
@@ -3582,11 +3582,11 @@ Body:
       BuyingStore: true
       BuyingStore: true
       Container: true
       Container: true
     Script: |
     Script: |
-      getrandgroupitem(IG_Scroll,1);
-      getrandgroupitem(IG_Scroll,1);
-      getrandgroupitem(IG_Scroll,1);
-      getrandgroupitem(IG_Scroll,1);
-      getrandgroupitem(IG_Scroll,1);
+      getgroupitem(IG_SCROLL);
+      getgroupitem(IG_SCROLL);
+      getgroupitem(IG_SCROLL);
+      getgroupitem(IG_SCROLL);
+      getgroupitem(IG_SCROLL);
   - Id: 12109
   - Id: 12109
     AegisName: Poring_Box
     AegisName: Poring_Box
     Name: Poring Box
     Name: Poring Box
@@ -3608,11 +3608,11 @@ Body:
       BuyingStore: true
       BuyingStore: true
       Container: true
       Container: true
     Script: |
     Script: |
-      getrandgroupitem(IG_FirstAid,1);
-      getrandgroupitem(IG_FirstAid,1);
-      getrandgroupitem(IG_FirstAid,1);
-      getrandgroupitem(IG_FirstAid,1);
-      getrandgroupitem(IG_FirstAid,1);
+      getgroupitem(IG_FIRSTAID);
+      getgroupitem(IG_FIRSTAID);
+      getgroupitem(IG_FIRSTAID);
+      getgroupitem(IG_FIRSTAID);
+      getgroupitem(IG_FIRSTAID);
   - Id: 12111
   - Id: 12111
     AegisName: Food_Package
     AegisName: Food_Package
     Name: Bundle of Food
     Name: Bundle of Food
@@ -3623,9 +3623,9 @@ Body:
       BuyingStore: true
       BuyingStore: true
       Container: true
       Container: true
     Script: |
     Script: |
-      getrandgroupitem(IG_FoodBag,1);
-      getrandgroupitem(IG_FoodBag,1);
-      getrandgroupitem(IG_FoodBag,1);
+      getgroupitem(IG_FOODBAG);
+      getgroupitem(IG_FOODBAG);
+      getgroupitem(IG_FOODBAG);
   - Id: 12112
   - Id: 12112
     AegisName: Tropical_Sograt
     AegisName: Tropical_Sograt
     Name: Tropical Sograt
     Name: Tropical Sograt
@@ -3817,9 +3817,9 @@ Body:
       BuyingStore: true
       BuyingStore: true
       Container: true
       Container: true
     Script: |
     Script: |
-      getrandgroupitem(IG_CookieBag,1);
-      getrandgroupitem(IG_CookieBag,1);
-      getrandgroupitem(IG_CookieBag,1);
+      getgroupitem(IG_COOKIEBAG);
+      getgroupitem(IG_COOKIEBAG);
+      getgroupitem(IG_COOKIEBAG);
   - Id: 12131
   - Id: 12131
     AegisName: Lucky_Potion
     AegisName: Lucky_Potion
     Name: Lucky Potion
     Name: Lucky Potion
@@ -4514,7 +4514,7 @@ Body:
     Flags:
     Flags:
       Container: true
       Container: true
     Script: |
     Script: |
-      getrandgroupitem(IG_RedBox,1);
+      getgroupitem(IG_REDBOX);
   - Id: 12187
   - Id: 12187
     AegisName: Green_Box
     AegisName: Green_Box
     Name: Old Green Box
     Name: Old Green Box
@@ -4524,7 +4524,7 @@ Body:
     Flags:
     Flags:
       Container: true
       Container: true
     Script: |
     Script: |
-      getrandgroupitem(IG_GreenBox,1);
+      getgroupitem(IG_GREENBOX);
   - Id: 12188
   - Id: 12188
     AegisName: Magical_Moon_Cake
     AegisName: Magical_Moon_Cake
     Name: Grace Moon Cake
     Name: Grace Moon Cake
@@ -4542,7 +4542,7 @@ Body:
     Flags:
     Flags:
       Container: true
       Container: true
     Script: |
     Script: |
-      getrandgroupitem(IG_RedBox_2,1);
+      getgroupitem(IG_REDBOX_2);
   - Id: 12190
   - Id: 12190
     AegisName: Moon_Cake
     AegisName: Moon_Cake
     Name: Moon Cake
     Name: Moon Cake
@@ -4579,9 +4579,9 @@ Body:
       BuyingStore: true
       BuyingStore: true
       Container: true
       Container: true
     Script: |
     Script: |
-      getrandgroupitem(IG_HometownGift,1);
-      getrandgroupitem(IG_HometownGift,1);
-      getrandgroupitem(IG_HometownGift,1);
+      getgroupitem(IG_HOMETOWNGIFT);
+      getgroupitem(IG_HOMETOWNGIFT);
+      getgroupitem(IG_HOMETOWNGIFT);
   - Id: 12195
   - Id: 12195
     AegisName: Plain_Rice_Cake
     AegisName: Plain_Rice_Cake
     Name: Plain Rice Cake
     Name: Plain Rice Cake
@@ -5185,7 +5185,7 @@ Body:
     Flags:
     Flags:
       Container: true
       Container: true
     Script: |
     Script: |
-      getrandgroupitem(IG_YellowBox,1);
+      getgroupitem(IG_YELLOWBOX);
   - Id: 12241
   - Id: 12241
     AegisName: M_Center_Potion
     AegisName: M_Center_Potion
     Name: Mercenary Concentration Potion
     Name: Mercenary Concentration Potion
@@ -5225,7 +5225,7 @@ Body:
     Flags:
     Flags:
       Container: true
       Container: true
     Script: |
     Script: |
-      getrandgroupitem(IG_OldGiftBox,1);
+      getgroupitem(IG_OLDGIFTBOX);
   - Id: 12245
   - Id: 12245
     AegisName: Green_Ale_US
     AegisName: Green_Ale_US
     Name: Green Ale
     Name: Green Ale
@@ -5244,7 +5244,7 @@ Body:
       BuyingStore: true
       BuyingStore: true
       Container: true
       Container: true
     Script: |
     Script: |
-      getrandgroupitem(IG_MagicCardAlbum,1);
+      getgroupitem(IG_MAGICCARDALBUM);
   - Id: 12247
   - Id: 12247
     AegisName: Halohalo
     AegisName: Halohalo
     Name: Halo-Halo
     Name: Halo-Halo
@@ -5263,7 +5263,7 @@ Body:
     Flags:
     Flags:
       Container: true
       Container: true
     Script: |
     Script: |
-      getrandgroupitem(IG_Masquerade,1);
+      getgroupitem(IG_MASQUERADE);
   - Id: 12249
   - Id: 12249
     AegisName: Payroll_Of_Kafra_
     AegisName: Payroll_Of_Kafra_
     Name: Payment Statement for Kafra Employee
     Name: Payment Statement for Kafra Employee
@@ -5678,7 +5678,7 @@ Body:
     Flags:
     Flags:
       Container: true
       Container: true
     Script: |
     Script: |
-      getrandgroupitem(IG_Tresure_Box_WoE,1);
+      getgroupitem(IG_TRESURE_BOX_WOE);
   - Id: 12282
   - Id: 12282
     AegisName: Internet_Cafe1
     AegisName: Internet_Cafe1
     Name: Internet Cafe1
     Name: Internet Cafe1
@@ -5728,7 +5728,7 @@ Body:
     Flags:
     Flags:
       Container: true
       Container: true
     Script: |
     Script: |
-      getrandgroupitem(IG_Masquerade_2,1);
+      getgroupitem(IG_MASQUERADE_2);
   - Id: 12287
   - Id: 12287
     AegisName: Love_Angel
     AegisName: Love_Angel
     Name: Love Angel Magic Powder
     Name: Love Angel Magic Powder
@@ -6341,7 +6341,7 @@ Body:
     Flags:
     Flags:
       Container: true
       Container: true
     Script: |
     Script: |
-      getrandgroupitem(IG_Cherish_Box,1);
+      getgroupitem(IG_CHERISH_BOX);
   - Id: 12335
   - Id: 12335
     AegisName: Yummy_Skewered_Dish
     AegisName: Yummy_Skewered_Dish
     Name: Grilled Delicious Skewer
     Name: Grilled Delicious Skewer
@@ -6384,7 +6384,7 @@ Body:
     Flags:
     Flags:
       Container: true
       Container: true
     Script: |
     Script: |
-      getrandgroupitem(IG_Cherish_Box_Ori,1);
+      getgroupitem(IG_CHERISH_BOX_ORI);
   - Id: 12340
   - Id: 12340
     AegisName: Mysterious_Rice_Powder
     AegisName: Mysterious_Rice_Powder
     Name: Chewy Rice Powder
     Name: Chewy Rice Powder
@@ -6623,7 +6623,7 @@ Body:
       BuyingStore: true
       BuyingStore: true
       Container: true
       Container: true
     Script: |
     Script: |
-      getrandgroupitem(IG_Xmas_Gift,1);
+      getgroupitem(IG_XMAS_GIFT);
   - Id: 12356
   - Id: 12356
     AegisName: Louise_Costume_Box
     AegisName: Louise_Costume_Box
     Name: Louise Costume Box
     Name: Louise Costume Box
@@ -6634,7 +6634,7 @@ Body:
       BuyingStore: true
       BuyingStore: true
       Container: true
       Container: true
     Script: |
     Script: |
-      getrandgroupitem(IG_Louise_Costume_Box,1);
+      getgroupitem(IG_LOUISE_COSTUME_BOX);
   - Id: 12357
   - Id: 12357
     AegisName: Shiny_Wing_Gown
     AegisName: Shiny_Wing_Gown
     Name: Shiny Wing Gown
     Name: Shiny Wing Gown
@@ -8678,8 +8678,8 @@ Body:
     Flags:
     Flags:
       Container: true
       Container: true
     Script: |
     Script: |
-      getrandgroupitem(IG_BleuBox,1);
-      getrandgroupitem(IG_BleuBox,1);
+      getgroupitem(IG_BLEUBOX);
+      getgroupitem(IG_BLEUBOX);
   - Id: 12703
   - Id: 12703
     AegisName: Holy_Egg_2
     AegisName: Holy_Egg_2
     Name: Holy Egg
     Name: Holy Egg
@@ -8796,7 +8796,7 @@ Body:
       NoMail: true
       NoMail: true
       NoAuction: true
       NoAuction: true
     Script: |
     Script: |
-      getrandgroupitem(IG_Easter_Scroll,1);
+      getgroupitem(IG_EASTER_SCROLL);
   - Id: 12715
   - Id: 12715
     AegisName: Black_Treasure_Box
     AegisName: Black_Treasure_Box
     Name: Black Treasure Box
     Name: Black Treasure Box
@@ -21622,12 +21622,12 @@ Body:
     Flags:
     Flags:
       Container: true
       Container: true
     Script: |
     Script: |
-      getrandgroupitem(IG_Pierre_Treasurebox,1);
-      getrandgroupitem(IG_Pierre_Treasurebox,1);
-      getrandgroupitem(IG_Pierre_Treasurebox,1);
-      getrandgroupitem(IG_Pierre_Treasurebox,1);
-      getrandgroupitem(IG_Pierre_Treasurebox,1);
-      getrandgroupitem(IG_Pierre_Treasurebox,1);
+      getgroupitem(IG_PIERRE_TREASUREBOX);
+      getgroupitem(IG_PIERRE_TREASUREBOX);
+      getgroupitem(IG_PIERRE_TREASUREBOX);
+      getgroupitem(IG_PIERRE_TREASUREBOX);
+      getgroupitem(IG_PIERRE_TREASUREBOX);
+      getgroupitem(IG_PIERRE_TREASUREBOX);
   - Id: 14597
   - Id: 14597
     AegisName: PhreeoniS
     AegisName: PhreeoniS
     Name: Phreeoni Scroll
     Name: Phreeoni Scroll

+ 65 - 2
db/pre-re/item_group_db.yml

@@ -1,5 +1,5 @@
 # This file is a part of rAthena.
 # This file is a part of rAthena.
-#   Copyright(C) 2023 rAthena Development Team
+#   Copyright(C) 2024 rAthena Development Team
 #   https://rathena.org - https://github.com/rathena
 #   https://rathena.org - https://github.com/rathena
 #
 #
 # This program is free software: you can redistribute it and/or modify
 # This program is free software: you can redistribute it and/or modify
@@ -25,6 +25,7 @@
 # - Group                      Group name of the item.
 # - Group                      Group name of the item.
 #   SubGroups:
 #   SubGroups:
 #     - SubGroup:              SubGroup number associated with the list of item. See doc/item_group.txt for more information.
 #     - SubGroup:              SubGroup number associated with the list of item. See doc/item_group.txt for more information.
+#       Algorithm:             Type of algorithm associated with SubGroup. (Default: SharedPool)
 #       List:                  List of item(s) for the SubGroup.
 #       List:                  List of item(s) for the SubGroup.
 #        - Index               Unique number that can be used to add the same Item with different data in the list.
 #        - 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.
 #          Item                AegisName of item that will be obtained from this item group.
@@ -45,12 +46,13 @@
 
 
 Header:
 Header:
   Type: ITEM_GROUP_DB
   Type: ITEM_GROUP_DB
-  Version: 3
+  Version: 4
 
 
 Body:
 Body:
   - Group: ACCESORY
   - Group: ACCESORY
     SubGroups:
     SubGroups:
       - SubGroup: 1
       - SubGroup: 1
+        Algorithm: Random
         List:
         List:
           - Index: 0
           - Index: 0
             Item: Ring
             Item: Ring
@@ -181,6 +183,7 @@ Body:
   - Group: BLEUBOX
   - Group: BLEUBOX
     SubGroups:
     SubGroups:
       - SubGroup: 1
       - SubGroup: 1
+        Algorithm: Random
         List:
         List:
           - Index: 0
           - Index: 0
             Item: Milk
             Item: Milk
@@ -218,6 +221,7 @@ Body:
   - Group: BLUEBOX
   - Group: BLUEBOX
     SubGroups:
     SubGroups:
       - SubGroup: 1
       - SubGroup: 1
+        Algorithm: Random
         List:
         List:
           - Index: 0
           - Index: 0
             Item: Red_Potion
             Item: Red_Potion
@@ -3288,6 +3292,7 @@ Body:
   - Group: BOMB
   - Group: BOMB
     SubGroups:
     SubGroups:
       - SubGroup: 1
       - SubGroup: 1
+        Algorithm: Random
         List:
         List:
           - Index: 0
           - Index: 0
             Item: Apple_Bomb
             Item: Apple_Bomb
@@ -3316,6 +3321,7 @@ Body:
   - Group: BOX
   - Group: BOX
     SubGroups:
     SubGroups:
       - SubGroup: 1
       - SubGroup: 1
+        Algorithm: Random
         List:
         List:
           - Index: 0
           - Index: 0
             Item: Old_Blue_Box
             Item: Old_Blue_Box
@@ -3329,6 +3335,7 @@ Body:
   - Group: CANDY
   - Group: CANDY
     SubGroups:
     SubGroups:
       - SubGroup: 1
       - SubGroup: 1
+        Algorithm: Random
         List:
         List:
           - Index: 0
           - Index: 0
             Item: Candy
             Item: Candy
@@ -3339,6 +3346,7 @@ Body:
   - Group: CARDALBUM
   - Group: CARDALBUM
     SubGroups:
     SubGroups:
       - SubGroup: 1
       - SubGroup: 1
+        Algorithm: Random
         List:
         List:
           - Index: 0
           - Index: 0
             Item: Poring_Card
             Item: Poring_Card
@@ -4429,6 +4437,7 @@ Body:
   - Group: CASH_FOOD
   - Group: CASH_FOOD
     SubGroups:
     SubGroups:
       - SubGroup: 1
       - SubGroup: 1
+        Algorithm: Random
         List:
         List:
           - Index: 0
           - Index: 0
             Item: Str_Dish10_
             Item: Str_Dish10_
@@ -4451,6 +4460,7 @@ Body:
   - Group: CHERISH_BOX
   - Group: CHERISH_BOX
     SubGroups:
     SubGroups:
       - SubGroup: 1
       - SubGroup: 1
+        Algorithm: Random
         List:
         List:
           - Index: 0
           - Index: 0
             Item: Dog_Cap_
             Item: Dog_Cap_
@@ -4464,6 +4474,7 @@ Body:
   - Group: CHERISH_BOX_ORI
   - Group: CHERISH_BOX_ORI
     SubGroups:
     SubGroups:
       - SubGroup: 1
       - SubGroup: 1
+        Algorithm: Random
         List:
         List:
           - Index: 0
           - Index: 0
             Item: Ragnarok_Limited_Ed
             Item: Ragnarok_Limited_Ed
@@ -4483,6 +4494,7 @@ Body:
   - Group: COOKIEBAG
   - Group: COOKIEBAG
     SubGroups:
     SubGroups:
       - SubGroup: 1
       - SubGroup: 1
+        Algorithm: Random
         List:
         List:
           - Index: 0
           - Index: 0
             Item: Candy
             Item: Candy
@@ -4535,6 +4547,7 @@ Body:
   - Group: EASTER_SCROLL
   - Group: EASTER_SCROLL
     SubGroups:
     SubGroups:
       - SubGroup: 1
       - SubGroup: 1
+        Algorithm: Random
         List:
         List:
           - Index: 0
           - Index: 0
             Item: No_Recipient
             Item: No_Recipient
@@ -4581,6 +4594,7 @@ Body:
   - Group: EGGBOY
   - Group: EGGBOY
     SubGroups:
     SubGroups:
       - SubGroup: 1
       - SubGroup: 1
+        Algorithm: Random
         List:
         List:
           - Index: 0
           - Index: 0
             Item: Grape
             Item: Grape
@@ -4606,6 +4620,7 @@ Body:
   - Group: EGGGIRL
   - Group: EGGGIRL
     SubGroups:
     SubGroups:
       - SubGroup: 1
       - SubGroup: 1
+        Algorithm: Random
         List:
         List:
           - Index: 0
           - Index: 0
             Item: Grape
             Item: Grape
@@ -4631,6 +4646,7 @@ Body:
   - Group: ELEMENT
   - Group: ELEMENT
     SubGroups:
     SubGroups:
       - SubGroup: 1
       - SubGroup: 1
+        Algorithm: Random
         List:
         List:
           - Index: 0
           - Index: 0
             Item: Scarlet_Pts
             Item: Scarlet_Pts
@@ -4647,6 +4663,7 @@ Body:
   - Group: FIRSTAID
   - Group: FIRSTAID
     SubGroups:
     SubGroups:
       - SubGroup: 1
       - SubGroup: 1
+        Algorithm: Random
         List:
         List:
           - Index: 0
           - Index: 0
             Item: Red_Potion
             Item: Red_Potion
@@ -4705,6 +4722,7 @@ Body:
   - Group: FISH
   - Group: FISH
     SubGroups:
     SubGroups:
       - SubGroup: 1
       - SubGroup: 1
+        Algorithm: Random
         List:
         List:
           - Index: 0
           - Index: 0
             Item: Fish_Slice
             Item: Fish_Slice
@@ -4715,6 +4733,7 @@ Body:
   - Group: FOOD
   - Group: FOOD
     SubGroups:
     SubGroups:
       - SubGroup: 1
       - SubGroup: 1
+        Algorithm: Random
         List:
         List:
           - Index: 0
           - Index: 0
             Item: Royal_Jelly
             Item: Royal_Jelly
@@ -4785,6 +4804,7 @@ Body:
   - Group: FOODBAG
   - Group: FOODBAG
     SubGroups:
     SubGroups:
       - SubGroup: 1
       - SubGroup: 1
+        Algorithm: Random
         List:
         List:
           - Index: 0
           - Index: 0
             Item: Apple
             Item: Apple
@@ -4921,6 +4941,7 @@ Body:
   - Group: FRUIT
   - Group: FRUIT
     SubGroups:
     SubGroups:
       - SubGroup: 1
       - SubGroup: 1
+        Algorithm: Random
         List:
         List:
           - Index: 0
           - Index: 0
             Item: Apple
             Item: Apple
@@ -4940,6 +4961,7 @@ Body:
   - Group: GEMSTONE
   - Group: GEMSTONE
     SubGroups:
     SubGroups:
       - SubGroup: 1
       - SubGroup: 1
+        Algorithm: Random
         List:
         List:
           - Index: 0
           - Index: 0
             Item: Yellow_Gemstone
             Item: Yellow_Gemstone
@@ -4953,6 +4975,7 @@ Body:
   - Group: GIFTBOX
   - Group: GIFTBOX
     SubGroups:
     SubGroups:
       - SubGroup: 1
       - SubGroup: 1
+        Algorithm: Random
         List:
         List:
           - Index: 0
           - Index: 0
             Item: Red_Potion
             Item: Red_Potion
@@ -5167,6 +5190,7 @@ Body:
   - Group: GIFTBOXCHINA
   - Group: GIFTBOXCHINA
     SubGroups:
     SubGroups:
       - SubGroup: 1
       - SubGroup: 1
+        Algorithm: Random
         List:
         List:
           - Index: 0
           - Index: 0
             Item: Red_Potion
             Item: Red_Potion
@@ -5963,6 +5987,7 @@ Body:
   - Group: GIFTBOX_1
   - Group: GIFTBOX_1
     SubGroups:
     SubGroups:
       - SubGroup: 1
       - SubGroup: 1
+        Algorithm: Random
         List:
         List:
           - Index: 0
           - Index: 0
             Item: Red_Potion
             Item: Red_Potion
@@ -6177,6 +6202,7 @@ Body:
   - Group: GIFTBOX_2
   - Group: GIFTBOX_2
     SubGroups:
     SubGroups:
       - SubGroup: 1
       - SubGroup: 1
+        Algorithm: Random
         List:
         List:
           - Index: 0
           - Index: 0
             Item: Red_Potion
             Item: Red_Potion
@@ -6391,6 +6417,7 @@ Body:
   - Group: GIFTBOX_3
   - Group: GIFTBOX_3
     SubGroups:
     SubGroups:
       - SubGroup: 1
       - SubGroup: 1
+        Algorithm: Random
         List:
         List:
           - Index: 0
           - Index: 0
             Item: Red_Potion
             Item: Red_Potion
@@ -6605,6 +6632,7 @@ Body:
   - Group: GIFTBOX_4
   - Group: GIFTBOX_4
     SubGroups:
     SubGroups:
       - SubGroup: 1
       - SubGroup: 1
+        Algorithm: Random
         List:
         List:
           - Index: 0
           - Index: 0
             Item: Red_Potion
             Item: Red_Potion
@@ -6819,6 +6847,7 @@ Body:
   - Group: GREENBOX
   - Group: GREENBOX
     SubGroups:
     SubGroups:
       - SubGroup: 1
       - SubGroup: 1
+        Algorithm: Random
         List:
         List:
           - Index: 0
           - Index: 0
             Item: Chocolate_Drink
             Item: Chocolate_Drink
@@ -6856,6 +6885,7 @@ Body:
   - Group: HERB
   - Group: HERB
     SubGroups:
     SubGroups:
       - SubGroup: 1
       - SubGroup: 1
+        Algorithm: Random
         List:
         List:
           - Index: 0
           - Index: 0
             Item: Red_Herb
             Item: Red_Herb
@@ -6869,6 +6899,7 @@ Body:
   - Group: HOMETOWNGIFT
   - Group: HOMETOWNGIFT
     SubGroups:
     SubGroups:
       - SubGroup: 1
       - SubGroup: 1
+        Algorithm: Random
         List:
         List:
           - Index: 0
           - Index: 0
             Item: Korea_Rice_Cake
             Item: Korea_Rice_Cake
@@ -6897,6 +6928,7 @@ Body:
   - Group: JEWEL
   - Group: JEWEL
     SubGroups:
     SubGroups:
       - SubGroup: 1
       - SubGroup: 1
+        Algorithm: Random
         List:
         List:
           - Index: 0
           - Index: 0
             Item: Yellow_Gemstone
             Item: Yellow_Gemstone
@@ -6961,6 +6993,7 @@ Body:
   - Group: JUICE
   - Group: JUICE
     SubGroups:
     SubGroups:
       - SubGroup: 1
       - SubGroup: 1
+        Algorithm: Random
         List:
         List:
           - Index: 0
           - Index: 0
             Item: Apple_Juice
             Item: Apple_Juice
@@ -6974,6 +7007,7 @@ Body:
   - Group: LOTTOBOX
   - Group: LOTTOBOX
     SubGroups:
     SubGroups:
       - SubGroup: 1
       - SubGroup: 1
+        Algorithm: Random
         List:
         List:
           - Index: 0
           - Index: 0
             Item: Lotto31
             Item: Lotto31
@@ -7008,6 +7042,7 @@ Body:
   - Group: LOUISE_COSTUME_BOX
   - Group: LOUISE_COSTUME_BOX
     SubGroups:
     SubGroups:
       - SubGroup: 1
       - SubGroup: 1
+        Algorithm: Random
         List:
         List:
           - Index: 0
           - Index: 0
             Item: Red_Bag
             Item: Red_Bag
@@ -7018,6 +7053,7 @@ Body:
   - Group: MAGICCARDALBUM
   - Group: MAGICCARDALBUM
     SubGroups:
     SubGroups:
       - SubGroup: 1
       - SubGroup: 1
+        Algorithm: Random
         List:
         List:
           - Index: 0
           - Index: 0
             Item: Ghostring_Card
             Item: Ghostring_Card
@@ -7115,6 +7151,7 @@ Body:
   - Group: MASK
   - Group: MASK
     SubGroups:
     SubGroups:
       - SubGroup: 1
       - SubGroup: 1
+        Algorithm: Random
         List:
         List:
           - Index: 0
           - Index: 0
             Item: Mr_Smile
             Item: Mr_Smile
@@ -7158,6 +7195,7 @@ Body:
   - Group: MASQUERADE
   - Group: MASQUERADE
     SubGroups:
     SubGroups:
       - SubGroup: 1
       - SubGroup: 1
+        Algorithm: Random
         List:
         List:
           - Index: 0
           - Index: 0
             Item: Drooping_Nine_Tail_
             Item: Drooping_Nine_Tail_
@@ -7174,6 +7212,7 @@ Body:
   - Group: MASQUERADE_2
   - Group: MASQUERADE_2
     SubGroups:
     SubGroups:
       - SubGroup: 1
       - SubGroup: 1
+        Algorithm: Random
         List:
         List:
           - Index: 0
           - Index: 0
             Item: Dress_Hat
             Item: Dress_Hat
@@ -7190,6 +7229,7 @@ Body:
   - Group: MEAT
   - Group: MEAT
     SubGroups:
     SubGroups:
       - SubGroup: 1
       - SubGroup: 1
+        Algorithm: Random
         List:
         List:
           - Index: 0
           - Index: 0
             Item: Meat
             Item: Meat
@@ -7200,6 +7240,7 @@ Body:
   - Group: MERCENARY
   - Group: MERCENARY
     SubGroups:
     SubGroups:
       - SubGroup: 1
       - SubGroup: 1
+        Algorithm: Random
         List:
         List:
           - Index: 0
           - Index: 0
             Item: Bow_Mercenary_Scroll1
             Item: Bow_Mercenary_Scroll1
@@ -7294,6 +7335,7 @@ Body:
   - Group: MINERAL
   - Group: MINERAL
     SubGroups:
     SubGroups:
       - SubGroup: 1
       - SubGroup: 1
+        Algorithm: Random
         List:
         List:
           - Index: 0
           - Index: 0
             Item: Emperium
             Item: Emperium
@@ -7358,6 +7400,7 @@ Body:
   - Group: OLDGIFTBOX
   - Group: OLDGIFTBOX
     SubGroups:
     SubGroups:
       - SubGroup: 1
       - SubGroup: 1
+        Algorithm: Random
         List:
         List:
           - Index: 0
           - Index: 0
             Item: Fallen_Leaves_
             Item: Fallen_Leaves_
@@ -7371,6 +7414,7 @@ Body:
   - Group: ORE
   - Group: ORE
     SubGroups:
     SubGroups:
       - SubGroup: 1
       - SubGroup: 1
+        Algorithm: Random
         List:
         List:
           - Index: 0
           - Index: 0
             Item: Iron_Ore
             Item: Iron_Ore
@@ -7435,6 +7479,7 @@ Body:
   - Group: PIERRE_TREASUREBOX
   - Group: PIERRE_TREASUREBOX
     SubGroups:
     SubGroups:
       - SubGroup: 1
       - SubGroup: 1
+        Algorithm: Random
         List:
         List:
           - Index: 0
           - Index: 0
             Item: Old_Blue_Box
             Item: Old_Blue_Box
@@ -7523,6 +7568,7 @@ Body:
   - Group: POISON
   - Group: POISON
     SubGroups:
     SubGroups:
       - SubGroup: 1
       - SubGroup: 1
+        Algorithm: Random
         List:
         List:
           - Index: 0
           - Index: 0
             Item: Poison_Paralysis
             Item: Poison_Paralysis
@@ -7551,6 +7597,7 @@ Body:
   - Group: POTION
   - Group: POTION
     SubGroups:
     SubGroups:
       - SubGroup: 1
       - SubGroup: 1
+        Algorithm: Random
         List:
         List:
           - Index: 0
           - Index: 0
             Item: Red_Potion
             Item: Red_Potion
@@ -7567,6 +7614,7 @@ Body:
   - Group: QUIVER
   - Group: QUIVER
     SubGroups:
     SubGroups:
       - SubGroup: 1
       - SubGroup: 1
+        Algorithm: Random
         List:
         List:
           - Index: 0
           - Index: 0
             Item: Arrow_Container
             Item: Arrow_Container
@@ -7610,6 +7658,7 @@ Body:
   - Group: RECOVERY
   - Group: RECOVERY
     SubGroups:
     SubGroups:
       - SubGroup: 1
       - SubGroup: 1
+        Algorithm: Random
         List:
         List:
           - Index: 0
           - Index: 0
             Item: Fruit_Of_Mastela
             Item: Fruit_Of_Mastela
@@ -7656,6 +7705,7 @@ Body:
   - Group: REDBOX
   - Group: REDBOX
     SubGroups:
     SubGroups:
       - SubGroup: 1
       - SubGroup: 1
+        Algorithm: Random
         List:
         List:
           - Index: 0
           - Index: 0
             Item: Cat_Hat
             Item: Cat_Hat
@@ -7702,6 +7752,7 @@ Body:
   - Group: REDBOX_2
   - Group: REDBOX_2
     SubGroups:
     SubGroups:
       - SubGroup: 1
       - SubGroup: 1
+        Algorithm: Random
         List:
         List:
           - Index: 0
           - Index: 0
             Item: Alice_Doll
             Item: Alice_Doll
@@ -7718,6 +7769,7 @@ Body:
   - Group: RESIST
   - Group: RESIST
     SubGroups:
     SubGroups:
       - SubGroup: 1
       - SubGroup: 1
+        Algorithm: Random
         List:
         List:
           - Index: 0
           - Index: 0
             Item: Resist_Fire
             Item: Resist_Fire
@@ -7734,6 +7786,7 @@ Body:
   - Group: SCROLL
   - Group: SCROLL
     SubGroups:
     SubGroups:
       - SubGroup: 1
       - SubGroup: 1
+        Algorithm: Random
         List:
         List:
           - Index: 0
           - Index: 0
             Item: Earth_Scroll_1_3
             Item: Earth_Scroll_1_3
@@ -7792,6 +7845,7 @@ Body:
   - Group: TAMING
   - Group: TAMING
     SubGroups:
     SubGroups:
       - SubGroup: 1
       - SubGroup: 1
+        Algorithm: Random
         List:
         List:
           - Index: 0
           - Index: 0
             Item: Unripe_Apple
             Item: Unripe_Apple
@@ -7946,6 +8000,7 @@ Body:
   - Group: THROWABLE
   - Group: THROWABLE
     SubGroups:
     SubGroups:
       - SubGroup: 1
       - SubGroup: 1
+        Algorithm: Random
         List:
         List:
           - Index: 0
           - Index: 0
             Item: Mysterious_Powder
             Item: Mysterious_Powder
@@ -8019,6 +8074,7 @@ Body:
   - Group: TOKEN_OF_SIEGFRIED
   - Group: TOKEN_OF_SIEGFRIED
     SubGroups:
     SubGroups:
       - SubGroup: 1
       - SubGroup: 1
+        Algorithm: Random
         List:
         List:
           - Index: 0
           - Index: 0
             Item: F_Token_Of_Siegfried
             Item: F_Token_Of_Siegfried
@@ -8032,6 +8088,7 @@ Body:
   - Group: TRESURE_BOX_WOE
   - Group: TRESURE_BOX_WOE
     SubGroups:
     SubGroups:
       - SubGroup: 1
       - SubGroup: 1
+        Algorithm: Random
         List:
         List:
           - Index: 0
           - Index: 0
             Item: Old_Blue_Box
             Item: Old_Blue_Box
@@ -8096,6 +8153,7 @@ Body:
   - Group: VIOLETBOX
   - Group: VIOLETBOX
     SubGroups:
     SubGroups:
       - SubGroup: 1
       - SubGroup: 1
+        Algorithm: Random
         List:
         List:
           - Index: 0
           - Index: 0
             Item: Red_Potion
             Item: Red_Potion
@@ -10869,6 +10927,7 @@ Body:
   - Group: XMAS_GIFT
   - Group: XMAS_GIFT
     SubGroups:
     SubGroups:
       - SubGroup: 1
       - SubGroup: 1
+        Algorithm: Random
         List:
         List:
           - Index: 0
           - Index: 0
             Item: HandMade_Chocolate
             Item: HandMade_Chocolate
@@ -10930,6 +10989,7 @@ Body:
   - Group: YELLOWBOX
   - Group: YELLOWBOX
     SubGroups:
     SubGroups:
       - SubGroup: 1
       - SubGroup: 1
+        Algorithm: Random
         List:
         List:
           - Index: 0
           - Index: 0
             Item: Elephant_Hat_
             Item: Elephant_Hat_
@@ -10946,6 +11006,7 @@ Body:
   - Group: MF_NOTELEPORT
   - Group: MF_NOTELEPORT
     SubGroups:
     SubGroups:
       - SubGroup: 0
       - SubGroup: 0
+        Algorithm: All
         List:
         List:
           - Index: 0
           - Index: 0
             Item: Wing_Of_Fly
             Item: Wing_Of_Fly
@@ -10960,6 +11021,7 @@ Body:
   - Group: MF_NORETURN
   - Group: MF_NORETURN
     SubGroups:
     SubGroups:
       - SubGroup: 0
       - SubGroup: 0
+        Algorithm: All
         List:
         List:
           - Index: 0
           - Index: 0
             Item: Wing_Of_Butterfly
             Item: Wing_Of_Butterfly
@@ -11008,6 +11070,7 @@ Body:
   - Group: GIANT_FLY_WING
   - Group: GIANT_FLY_WING
     SubGroups:
     SubGroups:
       - SubGroup: 0
       - SubGroup: 0
+        Algorithm: All
         List:
         List:
           - Index: 0
           - Index: 0
             Item: Giant_Fly_Wing
             Item: Giant_Fly_Wing

File diff suppressed because it is too large
+ 130 - 8
db/re/item_group_db.yml


+ 76 - 2
doc/item_group.txt

@@ -75,19 +75,39 @@ Amount: Amount of item that will be obtained.
 
 
 ---------------------------------------
 ---------------------------------------
 
 
-SubGroup: Setting this to '0' makes the item always obtainable ("must" item).
-		  SubGroup value will allocate where the item will be stored at random group.
+SubGroup: Unique number to create a list of item.
 
 
+---------------------------------------
+
+Algorithm: Type of algorithm associated with SubGroup.
+
+Random            - A random item is picked from the sub group using rate as chance for an item being picked.
+                    The chance remains the same every time.
+All               - All items in this sub group shall be picked.
+                    If you use a command that is supposed to return only one item with such a sub group, then a random item is returned instead, with each
+                    item having the same chance to be picked.
+                    When using this algorithm, the rate must remain unspecified (0).
+SharedPool        - Rate is the amount of items of this item ID in the sub group. A random item is picked from all the items in the group and then removed
+                    from the sub group. That means each time an item is returned from the sub group, it will have a lower chance to be returned again and if
+                    no more items of this item ID remain in the sub group, it cannot be returned at all anymore. This also means that if the server requests
+                    an item from this sub group as often as there are total items in this sub group, it will get exactly the amounts specified under "rate".
+                    Only when the group is completely empty or the server restarts, the group refills.
+
+Default: SharedPool
+
+Example:
 	Item Group:
 	Item Group:
       - Group: MyItemGroup
       - Group: MyItemGroup
         SubGroups:
         SubGroups:
           - SubGroup: 0
           - SubGroup: 0
+            Algorithm: All
             List:
             List:
               - Index: 0
               - Index: 0
                 Item: Knife       # "must" item(s)
                 Item: Knife       # "must" item(s)
               - Index: 1
               - Index: 1
                 Item: Dagger      # "must" item(s)
                 Item: Dagger      # "must" item(s)
           - SubGroup: 1
           - SubGroup: 1
+            Algorithm: Random
             List:
             List:
               - Index: 0
               - Index: 0
                 Item: Stiletto    # random at SubGroup 1
                 Item: Stiletto    # random at SubGroup 1
@@ -96,6 +116,7 @@ SubGroup: Setting this to '0' makes the item always obtainable ("must" item).
                 Item: Stiletto_   # random at SubGroup 1
                 Item: Stiletto_   # random at SubGroup 1
                 Rate: 2
                 Rate: 2
           - SubGroup: 2
           - SubGroup: 2
+            Algorithm: Random
             List:
             List:
               - Index: 0
               - Index: 0
                 Item: Stiletto    # random at SubGroup 2
                 Item: Stiletto    # random at SubGroup 2
@@ -151,6 +172,59 @@ SubGroup: Setting this to '0' makes the item always obtainable ("must" item).
 		- Returns Item ID of Dagger by chance 2/7 from 'must' SubGroup
 		- Returns Item ID of Dagger by chance 2/7 from 'must' SubGroup
 		- 'SubGroup 1' and 'SubGroup 2' are ignored
 		- 'SubGroup 1' and 'SubGroup 2' are ignored
 
 
+Example #2:
+
+	Item Group:
+	  - Group: MyItemGroup2
+	    SubGroups:
+	      - SubGroup: 1
+	        Algorithm: SharedPool
+	        List:
+	          - Index: 0
+	            Item: Milk
+	            Rate: 10
+	            Amount: 3
+	          - Index: 1
+	            Item: Well_Baked_Cookie
+	            Rate: 5
+	            Amount: 2
+	          - Index: 2
+	            Item: Gift_Box
+	            Rate: 1
+
+(Note: Specifying the "SharedPool" algorithm is optional, as it defaults to SharedPool if not specified.)
+
+You can interpret this as within MyItemGroup2 there are 10 packs of 3x Milk, 5 packs of 2x Well_Baked_Cookie and 1 Gift_Box; 16 packs in total.
+
+Usages:
+'getgroupitem(IG_MyItemGroup2);'
+'getrandgroupitem(IG_MyItemGroup2);'
+
+The first time one of the two commands above are called:
+	- Player has chance to get 3x Milk by chance 10/16
+	- Player has chance to get 2x Well_Baked_Cookie by chance 5/16
+	- Player has chance to get 1x Gift_Box by chance 1/16
+
+Let's say a pack of Well_Baked_Cookie was received from the group. That means only 4 packs of Well_Baked_Cookie remain in the group.
+
+The second time one of the two commands above are called:
+	- Player has chance to get 3x Milk by chance 10/15
+	- Player has chance to get 2x Well_Baked_Cookie by chance 4/15
+	- Player has chance to get 1x Gift_Box by chance 1/15
+
+Now a Gift_Box is received from the group. That means no more Gift_Box are remaining in the group.
+
+The third time one of the two commands above are called:
+	- Player has chance to get 3x Milk by chance 10/14
+	- Player has chance to get 2x Well_Baked_Cookie by chance 4/14
+
+After the two commands were called 16 times, the server will always have given out exactly:
+	- 30 Milk (10 packs of 3x Milk)
+	- 10 Well_Baked_Cookie (5 packs of 2x Well_Baked_Cookie)
+	- 1 Gift_Box
+
+Now the group is refilled and the next time the command is called, it will behave similar to the first time.
+
 ---------------------------------------
 ---------------------------------------
 
 
 Announced: If player obtained this item, it will be broadcast to the server.
 Announced: If player obtained this item, it will be broadcast to the server.

+ 10 - 4
doc/script_commands.txt

@@ -5389,7 +5389,11 @@ example, for a random pet lure:
 getitem groupranditem(IG_Taming),1;
 getitem groupranditem(IG_Taming),1;
 
 
 'sub_group' is used to get the available random items of item group from specified random
 'sub_group' is used to get the available random items of item group from specified random
-group. 0 for 'must' item group, and random item group is 1 until 5 (MAX_ITEMGROUP_RANDGROUP+1).
+group. If 'sub_group' is not defined the value will be 1. Make sure the group has defined a
+sub group with the given value.
+The algorithm specified in the sub group determines how the item is picked.
+If the sub group algorithm is "All", then a random item in the group will be returned with
+each item having the same chance of being picked.
 
 
 More info, see doc/item_group.txt.
 More info, see doc/item_group.txt.
 
 
@@ -5397,14 +5401,13 @@ More info, see doc/item_group.txt.
 
 
 *getrandgroupitem <group_id>{,<quantity>{,<sub_group>{,<identify>{,<char_id>}}}};
 *getrandgroupitem <group_id>{,<quantity>{,<sub_group>{,<identify>{,<char_id>}}}};
 
 
-Similar to the above example, this command allows players to obtain the specified
+Similar to "groupranditem", this command allows players to obtain the specified
 quantity of a random item from the group "<group id>". The different groups and
 quantity of a random item from the group "<group id>". The different groups and
 their group number are specified in db/(pre-)re/item_group_db.yml
 their group number are specified in db/(pre-)re/item_group_db.yml
 
 
 If 'quantity' is not defined or 0, it will uses defined amount from Item Group list.
 If 'quantity' is not defined or 0, it will uses defined amount from Item Group list.
 
 
-If 'sub_group' is not defined the value will be 1 (since random group is 1 ~ 5, and 0 is
-'must' item group).
+Sub groups and their algorithm work the same way as explained for "groupranditem".
 
 
 For item with type IT_WEAPON, IT_ARMOR, IT_PETARMOR, and IT_SHADOWGEAR will be given
 For item with type IT_WEAPON, IT_ARMOR, IT_PETARMOR, and IT_SHADOWGEAR will be given
 as unidentified item (as defined by itemdb_isidentified in src/map/itemdb.cpp) except
 as unidentified item (as defined by itemdb_isidentified in src/map/itemdb.cpp) except
@@ -5424,6 +5427,9 @@ For item with type IT_WEAPON, IT_ARMOR, IT_PETARMOR, and IT_SHADOWGEAR will be g
 as unidentified item (as defined by itemdb_isidentified in src/map/itemdb.cpp) except
 as unidentified item (as defined by itemdb_isidentified in src/map/itemdb.cpp) except
 if 'identify' is defined with value 1.
 if 'identify' is defined with value 1.
 
 
+For each sub group defined for the item group, items will be given out according to
+their corresponding algorithm.
+
 More info, see doc/item_group.txt.
 More info, see doc/item_group.txt.
 
 
 ---------------------------------------
 ---------------------------------------

+ 1 - 0
doc/yaml/db/item_group_db.yml

@@ -8,6 +8,7 @@
 # - Group                      Group name of the item.
 # - Group                      Group name of the item.
 #   SubGroups:
 #   SubGroups:
 #     - SubGroup:              SubGroup number associated with the list of item. See doc/item_group.txt for more information.
 #     - SubGroup:              SubGroup number associated with the list of item. See doc/item_group.txt for more information.
+#       Algorithm:             Type of algorithm associated with SubGroup. (Default: SharedPool)
 #       List:                  List of item(s) for the SubGroup.
 #       List:                  List of item(s) for the SubGroup.
 #        - Index               Unique number that can be used to add the same Item with different data in the list.
 #        - 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.
 #          Item                AegisName of item that will be obtained from this item group.

+ 113 - 58
src/map/itemdb.cpp

@@ -2888,33 +2888,72 @@ uint16 itemdb_searchname_array(std::map<t_itemid, std::shared_ptr<item_data>> &d
 	return static_cast<uint16>(data.size());
 	return static_cast<uint16>(data.size());
 }
 }
 
 
-std::shared_ptr<s_item_group_entry> ItemGroupDatabase::get_random_itemsubgroup(std::shared_ptr<s_item_group_random> random, e_group_search_type search_type) {
+std::shared_ptr<s_item_group_entry> ItemGroupDatabase::get_random_itemsubgroup(std::shared_ptr<s_item_group_random> random, e_group_algorithm_type algorithm) {
 	if (random == nullptr)
 	if (random == nullptr)
 		return nullptr;
 		return nullptr;
 
 
-	if (search_type == GROUP_SEARCH_DROP) {
-		// We pick a random item from the group and then do a drop check based on the rate
-		std::shared_ptr<s_item_group_entry> entry = util::umap_random(random->data);
-		if (rnd_chance_official<uint16>(entry->rate, 10000))
-			return entry;
-	}
-	else {
-		// Each item has x positions whereas x is the rate defined for the item in the umap
-		// We pick a random position and find the item that is at this position
-		uint32 pos = rnd_value<uint32>(1, random->total_rate);
-		uint32 current_pos = 1;
-		// Iterate through each item in the umap
-		for (const auto& [index, entry] : random->data) {
-			if (entry == nullptr)
-				return nullptr;
-			// If rate is 0 it means that this is SubGroup 0 which should just return any random item
-			if (entry->rate == 0)
-				return util::umap_random(random->data);
-			// We move "rate" positions
-			current_pos += entry->rate;
-			// If we passed the target position, entry is the item we are looking for
-			if (current_pos > pos)
+	// Use algorithm defined for the sub group
+	if (algorithm == GROUP_ALGORITHM_USEDB)
+		algorithm = random->algorithm;
+
+	switch( algorithm ) {
+		case GROUP_ALGORITHM_DROP: {
+			// We pick a random item from the group and then do a drop check based on the rate. On fail, do not return any item
+			std::shared_ptr<s_item_group_entry> entry = util::umap_random(random->data);
+			if (rnd_chance_official<uint16>(entry->adj_rate, 10000))
 				return entry;
 				return entry;
+			break;
+		}
+		case GROUP_ALGORITHM_ALL:
+			// This group algorithm is usually used to return all items in the group
+			// The code here is only reached when using this algorithm in a command that expects to return only one item
+			// In this case, we return a random item in the group
+			return util::umap_random(random->data);
+		case GROUP_ALGORITHM_RANDOM: {
+			// Each item has x positions whereas x is the rate defined for the item in the umap
+			// We pick a random position and find the item that is at this position
+			uint32 pos = rnd_value<uint32>(1, random->total_rate);
+			uint32 current_pos = 1;
+			// Iterate through each item in the umap
+			for (const auto& [index, entry] : random->data) {
+				if (entry == nullptr)
+					return nullptr;
+				// We move "rate" positions
+				current_pos += entry->rate;
+				// If we passed the target position, entry is the item we are looking for
+				if (current_pos > pos)
+					return entry;
+			}
+			break;
+		}
+		case GROUP_ALGORITHM_SHAREDPOOL: {
+			// By default, each item has x positions whereas x is the rate defined for the item in the umap
+			// Each time an item is picked, it has one of its positions removed until no positions remain in the group
+			// We pick a random position from all remaining positions and find the item that is at this position
+			uint32 pos = rnd_value<uint32>(1, random->total_rate - random->total_given);
+			uint32 current_pos = 1;
+			// Iterate through each item in the umap
+			for (const auto& [index, entry] : random->data) {
+				if (entry == nullptr)
+					return nullptr;
+				// We move as many positions as this item has left
+				current_pos += (entry->rate - entry->given);
+				// If we passed the target position, entry is the item we are looking for
+				if (current_pos > pos) {
+					// Increase amount item has been given out
+					entry->given++;
+					random->total_given++;
+					// All items have been given out, reset all entries in the group
+					if (random->total_given >= random->total_rate) {
+						random->total_given = 0;
+						for (const auto& [reset_index, reset_entry] : random->data) {
+							reset_entry->given = 0;
+						}
+					}
+					return entry;
+				}
+			}
+			break;
 		}
 		}
 	}
 	}
 	// Return nullptr on fail
 	// Return nullptr on fail
@@ -2924,11 +2963,11 @@ std::shared_ptr<s_item_group_entry> ItemGroupDatabase::get_random_itemsubgroup(s
 /**
 /**
 * Return a random group entry from Item Group
 * Return a random group entry from Item Group
 * @param group_id
 * @param group_id
-* @param sub_group: 0 is 'must' item group, random groups start from 1
-* @param search_type: see e_group_search_type
+* @param sub_group
+* @param search_type: see e_group_algorithm_type
 * @return Item group entry or nullptr on fail
 * @return Item group entry or nullptr on fail
 */
 */
-std::shared_ptr<s_item_group_entry> ItemGroupDatabase::get_random_entry(uint16 group_id, uint8 sub_group, e_group_search_type search_type) {
+std::shared_ptr<s_item_group_entry> ItemGroupDatabase::get_random_entry(uint16 group_id, uint8 sub_group, e_group_algorithm_type algorithm) {
 	std::shared_ptr<s_item_group_db> group = this->find(group_id);
 	std::shared_ptr<s_item_group_db> group = this->find(group_id);
 
 
 	if (group == nullptr) {
 	if (group == nullptr) {
@@ -2944,14 +2983,14 @@ std::shared_ptr<s_item_group_entry> ItemGroupDatabase::get_random_entry(uint16 g
 		return nullptr;
 		return nullptr;
 	}
 	}
 
 
-	return this->get_random_itemsubgroup(group->random[sub_group], search_type);
+	return this->get_random_itemsubgroup(group->random[sub_group], algorithm);
 }
 }
 
 
 /** [Cydh]
 /** [Cydh]
 * Gives item(s) to the player based on item group
 * Gives item(s) to the player based on item group
 * @param sd: Player that obtains item from item group
 * @param sd: Player that obtains item from item group
-* @param group_id: The group ID of item that obtained by player
-* @param *group: struct s_item_group from itemgroup_db[group_id].random[idx] or itemgroup_db[group_id].must[sub_group][idx]
+* @param identify
+* @param data: item data selected in a subgroup
 */
 */
 void ItemGroupDatabase::pc_get_itemgroup_sub( map_session_data& sd, bool identify, std::shared_ptr<s_item_group_entry> data ){
 void ItemGroupDatabase::pc_get_itemgroup_sub( map_session_data& sd, bool identify, std::shared_ptr<s_item_group_entry> data ){
 	if (data == nullptr)
 	if (data == nullptr)
@@ -3029,21 +3068,17 @@ uint8 ItemGroupDatabase::pc_get_itemgroup( uint16 group_id, bool identify, map_s
 	if (group->random.empty())
 	if (group->random.empty())
 		return 0;
 		return 0;
 
 
-	// Get all the 'must' item(s) (subgroup 0)
-	std::shared_ptr<s_item_group_random> must = util::umap_find(group->random, static_cast<uint16>(0));
-	if( must != nullptr ){
-		for (const auto &it : must->data)
-			this->pc_get_itemgroup_sub( sd, identify, it.second );
-	}
-
-	// Get 1 'random' item from each subgroup
 	for (const auto &random : group->random) {
 	for (const auto &random : group->random) {
-		// Skip the 'must' group
-		if( random.first == 0 ){
-			continue;
+		switch( random.second->algorithm ) {
+			case GROUP_ALGORITHM_RANDOM:
+			case GROUP_ALGORITHM_SHAREDPOOL:
+				this->pc_get_itemgroup_sub( sd, identify, this->get_random_itemsubgroup( random.second ) );
+				break;
+			case GROUP_ALGORITHM_ALL:
+				for (const auto &it : random.second->data)
+					this->pc_get_itemgroup_sub( sd, identify, it.second );
+				break;
 		}
 		}
-
-		this->pc_get_itemgroup_sub( sd, identify, this->get_random_itemsubgroup( random.second ) );
 	}
 	}
 
 
 	return 0;
 	return 0;
@@ -3315,20 +3350,38 @@ uint64 ItemGroupDatabase::parseBodyNode(const ryml::NodeRef& node) {
 
 
 			uint16 subgroup;
 			uint16 subgroup;
 
 
-			if (this->nodeExists(subit, "SubGroup")) {
-				if (!this->asUInt16(subit, "SubGroup", subgroup))
-					continue;
-			} else {
-				subgroup = 1;
-			}
+			if (!this->asUInt16(subit, "SubGroup", subgroup))
+				continue;
 
 
 			std::shared_ptr<s_item_group_random> random = util::umap_find(group->random, subgroup);
 			std::shared_ptr<s_item_group_random> random = util::umap_find(group->random, subgroup);
+			bool random_exists = random != nullptr;
 
 
-			if (random == nullptr) {
+			if (!random_exists) {
 				random = std::make_shared<s_item_group_random>();
 				random = std::make_shared<s_item_group_random>();
 				group->random[subgroup] = random;
 				group->random[subgroup] = random;
 			}
 			}
 
 
+			if (this->nodeExists(subit, "Algorithm")) {
+				std::string sub_str;
+
+				if (!this->asString(subit, "Algorithm", sub_str))
+					return 0;
+
+				std::string sub_constant_str = "GROUP_ALGORITHM_" + sub_str;
+				int64 constant_str;
+
+				if (!script_get_constant(sub_constant_str.c_str(), &constant_str)) {
+					this->invalidWarning(subit["Algorithm"], "Invalid algorithm %s.\n", sub_str.c_str());
+					continue;
+				}
+
+				random->algorithm = static_cast<e_group_algorithm_type>(constant_str);
+			} else {
+				if (!random_exists) {
+					random->algorithm = GROUP_ALGORITHM_SHAREDPOOL;
+				}
+			}
+
 			const auto& listNode = subit["List"];
 			const auto& listNode = subit["List"];
 
 
 			for (const auto& listit : listNode) {
 			for (const auto& listit : listNode) {
@@ -3400,20 +3453,21 @@ uint64 ItemGroupDatabase::parseBodyNode(const ryml::NodeRef& node) {
 						entry->rate = 0;
 						entry->rate = 0;
 				}
 				}
 
 
-				if (subgroup == 0 && entry->rate > 0) {
-					this->invalidWarning(listit["Item"], "SubGroup 0 is reserved for item without Rate ('must' item). Defaulting Rate to 0.\n");
+				if (random->algorithm == GROUP_ALGORITHM_ALL && entry->rate > 0) {
+					this->invalidWarning(listit["Item"], "Item cannot have a rate with \"All\" algorithm. Defaulting Rate to 0.\n");
 					entry->rate = 0;
 					entry->rate = 0;
 				}
 				}
-				if (subgroup != 0 && entry->rate == 0) {
-					this->invalidWarning(listit["Item"], "Entry must have a Rate for group above 0, skipping.\n");
+				if (random->algorithm != GROUP_ALGORITHM_ALL && entry->rate == 0) {
+					this->invalidWarning(listit["Item"], "Missing rate, item skipped.\n");
 					continue;
 					continue;
 				}
 				}
 
 
-				// Rate adjustment
-				if (battle_config.item_group_rate != 100) {
-					entry->rate = (entry->rate * battle_config.item_group_rate) / 100;
-					entry->rate = cap_value(entry->rate, battle_config.item_group_drop_min, battle_config.item_group_drop_max);
-				}
+				// Adjusted rate
+				entry->adj_rate = (entry->rate * battle_config.item_group_rate) / 100;
+				entry->adj_rate = cap_value(entry->adj_rate, battle_config.item_group_drop_min, battle_config.item_group_drop_max);
+
+				// Reset amount given
+				entry->given = 0;
 
 
 				if (this->nodeExists(listit, "Amount")) {
 				if (this->nodeExists(listit, "Amount")) {
 					uint16 amount;
 					uint16 amount;
@@ -3592,6 +3646,7 @@ void ItemGroupDatabase::loadingFinished() {
 	for (const auto &group : *this) {
 	for (const auto &group : *this) {
 		for (const auto &random : group.second->random) {
 		for (const auto &random : group.second->random) {
 			random.second->total_rate = 0;
 			random.second->total_rate = 0;
+			random.second->total_given = 0;
 			for (const auto &it : random.second->data) {
 			for (const auto &it : random.second->data) {
 				random.second->total_rate += it.second->rate;
 				random.second->total_rate += it.second->rate;
 			}
 			}

+ 13 - 6
src/map/itemdb.hpp

@@ -3009,9 +3009,12 @@ enum e_delay_consume : uint8 {
 };
 };
 
 
 /// Enum for different ways to search an item group
 /// Enum for different ways to search an item group
-enum e_group_search_type : uint8 {
-	GROUP_SEARCH_BOX = 0, // Always return an item from the group, rate determines which item is more likely to be returned
-	GROUP_SEARCH_DROP = 1, // Pick one item from the group and check use rate as drop rate, on fail, do not return any item
+enum e_group_algorithm_type : uint8 {
+	GROUP_ALGORITHM_USEDB, // Use algorithm defined in the database for the sub group (All, Random or SharedPool).
+	GROUP_ALGORITHM_DROP, // Pick one item from the group and use rate as drop rate, on fail, do not return any item.
+	GROUP_ALGORITHM_ALL, // All items have an equal chance to be returned. Using getgroupitem will return all items in the group.
+	GROUP_ALGORITHM_RANDOM, // Always return an item from the group, rate determines which item is more likely to be returned.
+	GROUP_ALGORITHM_SHAREDPOOL, // Rate is the amount of items in the group, return a random item and remove it from the group.
 };
 };
 
 
 /// Item combo struct
 /// Item combo struct
@@ -3123,6 +3126,8 @@ struct s_item_group_entry
 {
 {
 	t_itemid nameid; /// Item ID
 	t_itemid nameid; /// Item ID
 	uint16 rate;
 	uint16 rate;
+	uint16 adj_rate; /// Rate adjusted by the battle_config.item_group_rate
+	uint16 given; /// Amount of times this item has already been given out
 	uint16 duration, /// Duration if item as rental item (in minutes)
 	uint16 duration, /// Duration if item as rental item (in minutes)
 		amount; /// Amount of item will be obtained
 		amount; /// Amount of item will be obtained
 	bool isAnnounced, /// Broadcast if player get this item
 	bool isAnnounced, /// Broadcast if player get this item
@@ -3139,6 +3144,8 @@ struct s_item_group_entry
 struct s_item_group_random
 struct s_item_group_random
 {
 {
 	uint32 total_rate;
 	uint32 total_rate;
+	uint32 total_given; /// Amount of times an item from this group has been given out
+	e_group_algorithm_type algorithm;
 	std::unordered_map<uint32, std::shared_ptr<s_item_group_entry>> data; /// index, s_item_group_entry
 	std::unordered_map<uint32, std::shared_ptr<s_item_group_entry>> data; /// index, s_item_group_entry
 };
 };
 
 
@@ -3296,7 +3303,7 @@ extern ItemDatabase item_db;
 
 
 class ItemGroupDatabase : public TypesafeCachedYamlDatabase<uint16, s_item_group_db> {
 class ItemGroupDatabase : public TypesafeCachedYamlDatabase<uint16, s_item_group_db> {
 public:
 public:
-	ItemGroupDatabase() : TypesafeCachedYamlDatabase("ITEM_GROUP_DB", 3, 1) {
+	ItemGroupDatabase() : TypesafeCachedYamlDatabase("ITEM_GROUP_DB", 4, 1) {
 
 
 	}
 	}
 
 
@@ -3307,11 +3314,11 @@ public:
 	// Additional
 	// Additional
 	bool item_exists(uint16 group_id, t_itemid nameid);
 	bool item_exists(uint16 group_id, t_itemid nameid);
 	int16 item_exists_pc(map_session_data *sd, uint16 group_id);
 	int16 item_exists_pc(map_session_data *sd, uint16 group_id);
-	std::shared_ptr<s_item_group_entry> get_random_entry(uint16 group_id, uint8 sub_group, e_group_search_type search_type = GROUP_SEARCH_BOX);
+	std::shared_ptr<s_item_group_entry> get_random_entry(uint16 group_id, uint8 sub_group, e_group_algorithm_type algorithm = GROUP_ALGORITHM_USEDB);
 	uint8 pc_get_itemgroup( uint16 group_id, bool identify, map_session_data& sd );
 	uint8 pc_get_itemgroup( uint16 group_id, bool identify, map_session_data& sd );
 
 
 private:
 private:
-	std::shared_ptr<s_item_group_entry> get_random_itemsubgroup(std::shared_ptr<s_item_group_random> random, e_group_search_type search_type = GROUP_SEARCH_BOX);
+	std::shared_ptr<s_item_group_entry> get_random_itemsubgroup(std::shared_ptr<s_item_group_random> random, e_group_algorithm_type algorithm = GROUP_ALGORITHM_USEDB);
 	void pc_get_itemgroup_sub( map_session_data& sd, bool identify, std::shared_ptr<s_item_group_entry> data );
 	void pc_get_itemgroup_sub( map_session_data& sd, bool identify, std::shared_ptr<s_item_group_entry> data );
 };
 };
 
 

+ 4 - 4
src/map/mob.cpp

@@ -2961,10 +2961,10 @@ int32 mob_dead(struct mob_data *md, struct block_list *src, int32 type)
 						mobdrop.rate = drop_rate;
 						mobdrop.rate = drop_rate;
 					}
 					}
 					else {
 					else {
-						std::shared_ptr<s_item_group_entry> entry = itemdb_group.get_random_entry(it.group, 1, GROUP_SEARCH_DROP);
+						std::shared_ptr<s_item_group_entry> entry = itemdb_group.get_random_entry(it.group, 1, GROUP_ALGORITHM_DROP);
 						if (entry == nullptr) continue;
 						if (entry == nullptr) continue;
 						mobdrop.nameid = entry->nameid;
 						mobdrop.nameid = entry->nameid;
-						mobdrop.rate = entry->rate * drop_rate / 10000;
+						mobdrop.rate = entry->adj_rate * drop_rate / 10000;
 					}
 					}
 
 
 					std::shared_ptr<s_item_drop> ditem = mob_setdropitem(mobdrop, 1, md->mob_id);
 					std::shared_ptr<s_item_drop> ditem = mob_setdropitem(mobdrop, 1, md->mob_id);
@@ -3018,11 +3018,11 @@ int32 mob_dead(struct mob_data *md, struct block_list *src, int32 type)
 
 
 		// Ore Discovery (triggers if owner has loot priority, does not require to be the killer)
 		// Ore Discovery (triggers if owner has loot priority, does not require to be the killer)
 		if (mvp_sd && pc_checkskill(mvp_sd, BS_FINDINGORE) > 0) {
 		if (mvp_sd && pc_checkskill(mvp_sd, BS_FINDINGORE) > 0) {
-			std::shared_ptr<s_item_group_entry> entry = itemdb_group.get_random_entry(IG_ORE, 1, GROUP_SEARCH_DROP);
+			std::shared_ptr<s_item_group_entry> entry = itemdb_group.get_random_entry(IG_ORE, 1, GROUP_ALGORITHM_DROP);
 			if (entry != nullptr) {
 			if (entry != nullptr) {
 				s_mob_drop mobdrop = {};
 				s_mob_drop mobdrop = {};
 				mobdrop.nameid = entry->nameid;
 				mobdrop.nameid = entry->nameid;
-				mobdrop.rate = entry->rate;
+				mobdrop.rate = entry->adj_rate;
 
 
 				std::shared_ptr<s_item_drop> ditem = mob_setdropitem(mobdrop, 1, md->mob_id);
 				std::shared_ptr<s_item_drop> ditem = mob_setdropitem(mobdrop, 1, md->mob_id);
 
 

+ 4 - 0
src/map/script_constants.hpp

@@ -10560,6 +10560,10 @@
 	export_constant(SEARCHSTORE_EFFECT_NORMAL);
 	export_constant(SEARCHSTORE_EFFECT_NORMAL);
 	export_constant(SEARCHSTORE_EFFECT_REMOTE);
 	export_constant(SEARCHSTORE_EFFECT_REMOTE);
 
 
+	export_constant(GROUP_ALGORITHM_RANDOM);
+	export_constant(GROUP_ALGORITHM_SHAREDPOOL);
+	export_constant(GROUP_ALGORITHM_ALL);
+
 	#undef export_constant
 	#undef export_constant
 	#undef export_constant2
 	#undef export_constant2
 	#undef export_parameter
 	#undef export_parameter

+ 6 - 2
src/tool/csv2yaml.cpp

@@ -440,14 +440,14 @@ bool Csv2YamlTool::initialize( int32 argc, char* argv[] ){
 	}
 	}
 
 
 	item_group_txt_data(path_db_mode, path_db);
 	item_group_txt_data(path_db_mode, path_db);
-	if (!process("ITEM_GROUP_DB", 2, { path_db_mode }, "item_group_db", [](const std::string &path, const std::string &name_ext) -> bool {
+	if (!process("ITEM_GROUP_DB", 4, { path_db_mode }, "item_group_db", [](const std::string &path, const std::string &name_ext) -> bool {
 		return itemdb_read_group_yaml();
 		return itemdb_read_group_yaml();
 	})) {
 	})) {
 		return false;
 		return false;
 	}
 	}
 
 
 	item_group_txt_data(path_db_import, path_db_import);
 	item_group_txt_data(path_db_import, path_db_import);
-	if (!process("ITEM_GROUP_DB", 2, { path_db_import }, "item_group_db", [](const std::string &path, const std::string &name_ext) -> bool {
+	if (!process("ITEM_GROUP_DB", 4, { path_db_import }, "item_group_db", [](const std::string &path, const std::string &name_ext) -> bool {
 		return itemdb_read_group_yaml();
 		return itemdb_read_group_yaml();
 	})) {
 	})) {
 		return false;
 		return false;
@@ -4084,6 +4084,10 @@ static bool itemdb_read_group_yaml(void) {
 		for (const auto &item : it.second.item) {	// subgroup
 		for (const auto &item : it.second.item) {	// subgroup
 			body << YAML::BeginMap;
 			body << YAML::BeginMap;
 			body << YAML::Key << "SubGroup" << YAML::Value << item.first;
 			body << YAML::Key << "SubGroup" << YAML::Value << item.first;
+			if (item.first == 0)
+				body << YAML::Key << "Algorithm" << YAML::Value << "All";
+			else if (item.first == 6)
+				body << YAML::Key << "Algorithm" << YAML::Value << "Random";
 			body << YAML::Key << "List";
 			body << YAML::Key << "List";
 			body << YAML::BeginSeq;
 			body << YAML::BeginSeq;
 			for (const auto &listit : item.second) {
 			for (const auto &listit : item.second) {

+ 13 - 5
src/tool/yamlupgrade.cpp

@@ -145,7 +145,7 @@ bool YamlUpgradeTool::initialize( int32 argc, char* argv[] ){
 		} ) ){
 		} ) ){
 		return false;
 		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 {
+	if( !process( "ITEM_GROUP_DB", 4, 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 upgrade_item_group_db( path + name_ext, source_version );
 		} ) ){
 		} ) ){
 		return false;
 		return false;
@@ -436,8 +436,7 @@ static bool upgrade_item_group_db( std::string file, const uint32 source_version
 	size_t entries = 0;
 	size_t entries = 0;
 
 
 	for( const auto input : inNode["Body"] ){
 	for( const auto input : inNode["Body"] ){
-		// If under version 3
-		if( source_version < 3 ){
+		if( source_version < 4 ){
 			body << YAML::BeginMap;
 			body << YAML::BeginMap;
 			body << YAML::Key << "Group" << YAML::Value << input["Group"];
 			body << YAML::Key << "Group" << YAML::Value << input["Group"];
 
 
@@ -447,9 +446,18 @@ static bool upgrade_item_group_db( std::string file, const uint32 source_version
 
 
 				for (const auto &it : input["SubGroups"]) {
 				for (const auto &it : input["SubGroups"]) {
 					body << YAML::BeginMap;
 					body << YAML::BeginMap;
-					if( it["SubGroup"].IsDefined() ){
-						body << YAML::Key << "SubGroup" << YAML::Value << it["SubGroup"];
+					if( !it["SubGroup"].IsDefined() ){
+						ShowError( "Cannot upgrade automatically, SubGroup is missing." );
+						return false;
 					}
 					}
+					body << YAML::Key << "SubGroup" << YAML::Value << it["SubGroup"];
+
+					if (it["SubGroup"].as<uint16>() == 0)
+						body << YAML::Key << "Algorithm" << YAML::Value << "All";
+					else if (it["SubGroup"].as<uint16>() == 6)
+						body << YAML::Key << "Algorithm" << YAML::Value << "Random";
+					// else
+						// body << YAML::Key << "Algorithm" << YAML::Value << "SharedPool";
 
 
 					if( it["List"].IsDefined() )
 					if( it["List"].IsDefined() )
 						body << YAML::Key << "List";{
 						body << YAML::Key << "List";{

Some files were not shown because too many files changed in this diff