Explorar o código

Converted create_arrow_db.txt to YAML (#6039)

Converts the create_arrow_db.txt into YAML.
Includes CSV2YAML converter.

Co-authored-by: Aleos <aleos89@users.noreply.github.com>
Co-authored-by: Lemongrass3110 <lemongrass@kstp.at>
Atemo %!s(int64=3) %!d(string=hai) anos
pai
achega
0599ee1832

+ 0 - 289
db/create_arrow_db.txt

@@ -1,289 +0,0 @@
-// Arrow Crafting Database
-//
-// Structure of Database:
-// SourceID,MakeID1,MakeAmount1,...,MakeID5,MakeAmount5
-//
-// 01. SourceID     ID of the item, that is consumed by Arrow Crafting.
-// 02. MakeID       ID of the item received from Arrow Crafting.
-// 03. MakeAmount   Amount of MakeID item received from Arrow Crafting.
-// ...
-//
-// NOTE:
-// - Up to MAX_ARROW_RESULT (typically 5) ID/Amount pairs can be specified.
-// - To remove entry by importing, put 0 on 'MakeID'
-
-// Old Blue Box --> 50 Sharp Arrows, 50 Sleep Arrows
-603,1764,50,1768,50
-// Dead Branch --> 40 Mute Arrows
-604,1769,40
-// Amulet --> 40 Cursed Arrows
-609,1761,40
-// Empty Bottle --> 2 Iron Arrows
-713,1770,2
-// Emperium --> 600 Immaterial Arrows, 600 Mute Arrows, 600 Oridecon Arrows
-714,1757,600,1769,600,1765,600
-// Yellow Gemstone --> 30 Stone Arrows, 1 Sleep Arrow
-715,1756,30,1768,1
-// Red Gemstone --> 10 Rusty Arrows, 1 Poison Arrow, 1 Cursed Arrow
-716,1762,10,1763,1,1761,1
-// Blue Gemstone --> 30 Crystal Arrows, 1 Frozen Arrow
-717,1754,30,1759,1
-// Cursed Ruby --> 50 Cursed Arrows, 10 Sleep Arrows
-724,1761,50,1768,10
-// Cracked Diamond --> 50 Sharp Arrows
-733,1764,50
-// Rough Oridecon --> 50 Oridecon Arrows
-756,1765,50
-// Rough Elunium --> 200 Steel Arrows, 5 Stun Arrows
-757,1753,200,1758,5
-// Tree Root --> 7 Arrows
-902,1750,7
-// Scorpion Tail --> 3 Rusty Arrows
-904,1762,3
-// Jellopy --> 4 Arrows
-909,1750,4
-// Garlet --> 12 Iron Arrows
-910,1770,12
-// Scell --> 8 Steel Arrows
-911,1753,8
-// Zargon --> 50 Silver Arrows
-912,1751,50
-// Tooth of Bat --> 1 Shadow Arrow
-913,1767,1
-// Wolf Claw --> 15 Iron Arrows
-920,1770,15
-// Orc's Fang --> 30 Iron Arrows, 5 Steel Arrows, 10 Stone Arrows
-922,1770,30,1753,5,1756,10
-// Evil Horn --> 20 Shadow Arrows, 10 Flash Arrows, 5 Stun Arrows
-923,1767,20,1760,10,1758,5
-// Venom Canine --> 1 Poison Arrow
-937,1763,1
-// Bee Sting --> 1 Rusty Arrow
-939,1762,1
-// Horn --> 35 Iron Arrows
-947,1770,35
-// Cactus Needle --> 50 Arrows
-952,1750,50
-// Gill --> 80 Iron Arrows, 150 Crystal Arrows
-956,1770,80,1754,150
-// Decayed Nail --> 1 Rusty Arrow, 1 Shadow Arrow
-957,1762,1,1767,1
-// Horrendous Mouth --> 5 Shadow Arrows
-958,1767,5
-// Stinky Scale --> 1 Poison Arrow
-959,1763,1
-// Heroic Emblem --> 1 Oridecon Arrow, 5 Stun Arrows
-968,1765,1,1758,5
-// Gold --> 50 Flash Arrows, 50 Oridecon Arrows
-969,1760,50,1765,50
-// Oridecon --> 250 Oridecon Arrows
-984,1765,250
-// Elunium --> 1000 Steel Arrows, 50 Stun Arrows
-985,1753,1000,1758,50
-// Red Blood --> 600 Fire Arrows
-990,1752,600
-// Crystal Blue --> 150 Crystal Arrows
-991,1754,150
-// Wind of Verdure --> 150 Arrows of Wind
-992,1755,150
-// Green Live --> 150 Stone Arrows
-993,1756,150
-// Flame Heart --> 1800 Fire Arrows, 5 Mute Arrows
-994,1752,1800,1769,5
-// Mystic Frozen --> 450 Crystal Arrows, 5 Frozen Arrows
-995,1754,450,1759,5
-// Rough Wind --> 450 Arrows of Wind, 5 Sleep Arrows
-996,1755,450,1768,5
-// Great Nature --> 450 Stone Arrows, 5 Flash Arrows
-997,1756,450,1760,5
-// Iron --> 100 Iron Arrows
-998,1770,100
-// Steel --> 100 Steel Arrows
-999,1753,100
-// Star Crumb --> 30 Flash Arrows
-1000,1760,30
-// Star Dust --> 10 Flash Arrows
-1001,1760,10
-// Iron Ore --> 50 Iron Arrows
-1002,1770,50
-// Coal --> 8 Shadow Arrows
-1003,1767,8
-// Phracon --> 50 Iron Arrows
-1010,1770,50
-// Emveretarcon --> 200 Iron Arrows, 40 Silver Arrows
-1011,1770,200,1751,40
-// Mole Claw --> 50 Iron Arrows, 60 Stone Arrows
-1018,1770,50,1756,60
-// Trunk --> 40 Arrows
-1019,1750,40
-// Dokebi Horn --> 40 Iron Arrows, 2 Shadow Arrows
-1021,1770,40,1767,2
-// Porcupine Quill --> 70 Arrows, 30 Stone Arrows
-1027,1750,70,1756,30
-// Mantis Scythe --> 1 Sharp Arrow
-1031,1764,1
-// Dragon Canine --> 1 Oridecon Arrow, 50 Iron Arrows
-1035,1765,1,1770,50
-// Little Evil Horn --> 2 Cursed Arrows, 50 Iron Arrows
-1038,1761,2,1770,50
-// Lantern --> 80 Iron Arrows
-1041,1770,80
-// Orc Claw --> 10 Steel Arrows
-1043,1753,10
-// Zenorc's Fang --> 5 Rusty Arrows
-1044,1762,5
-// Ancient Tooth --> 20 Steel Arrows, 300 Crystal Arrows
-1053,1753,20,1754,300
-// Fang --> 2 Sharp Arrows, 40 Silver Arrows
-1063,1764,2,1751,40
-// Reins --> 100 Iron Arrows, 50 Steel Arrows
-1064,1770,100,1753,50
-// Fine-grained Trunk --> 20 Arrows
-1066,1750,20
-// Solid Trunk --> 20 Arrows
-1067,1750,20
-// Barren Trunk --> 20 Arrows
-1068,1750,20
-// Clock Hand --> 5 Sleep Arrows, 100 Arrows
-1095,1768,5,1750,100
-// Manacles --> 50 Steel Arrows
-1098,1753,50
-// Unicorn Horn --> 1000 Silver Arrows
-2257,1751,1000
-// Opera Masque --> 200 Steel Arrows, 40 Mute Arrows
-2281,1753,200,1769,40
-// Mr. Scream --> 200 Sharp Arrows, 300 Steel Arrows
-2288,1764,200,1753,300
-// Welding Mask --> 200 Steel Arrows, 40 Stun Arrows
-2292,1753,200,1758,40
-// Glittering Jacket --> 1000 Flash Arrows
-2319,1760,1000
-// Wooden Mail --> 700 Arrows, 500 Iron Arrows
-2328,1750,700,1770,500
-// Wooden Mail (Slotted) --> 1000 Arrows, 700 Iron Arrows
-2329,1750,1000,1770,700
-// Silver Robe --> 700 Silver Arrows
-2332,1751,700
-// Silver Robe (Slotted) --> 1000 Silver Arrows, 10 Immaterial Arrows
-2333,1751,1000,1757,10
-// Shackles --> 700 Iron Arrows, 50 Steel Arrows
-2408,1770,700,1753,50
-// Matyr's Leash --> 150 Arrows of Wind, 100 Steel Arrows, 10 Sharp Arrows
-2618,1755,150,1753,100,1764,10
-// Fin Helm --> 600 Crystal Arrows, 200 Steel Arrows
-5014,1754,600,1753,200
-// Ogre Tooth --> 30 Steel Arrows, 5 Rusty Arrows
-7002,1753,30,1762,5
-// Stiff Horn --> 2 Stun Arrows
-7008,1758,2
-// Tail of Steel Scorpion --> 250 Steel Arrows, 1 Poison Arrow
-7010,1753,250,1763,1
-// Young Twig --> 1000 Mute Arrows
-7018,1769,1000
-// Loki's Whispers --> 1000 Shadow Arrows
-7019,1767,1000
-// Mother's Nightmare --> 1000 Cursed Arrows
-7020,1761,1000
-// Foolishness of the Blind --> 200 Flash Arrows
-7021,1760,200
-// Old Hilt --> 1000 Oridecon Arrows
-7022,1765,1000
-// Blade of Darkness --> 600 Sharp Arrows, 200 Shadow Arrows
-7023,1764,600,1767,200
-// Bloody Edge --> 600 Sharp Arrows, 200 Cursed Arrows
-7024,1764,600,1761,200
-// Lucifer's Lament --> 800 Stun Arrows, 400 Mute Arrows, 800 Sleep Arrows
-7025,1758,800,1769,400,1768,800
-// Key of the Clock Tower --> 50 Oridecon Arrows
-7026,1765,50
-// Key of the Underground --> 100 Shadow Arrows
-7027,1767,100
-// Matchstick --> 3000 Fire Arrows
-7035,1752,3000
-// Fang of Garm --> 300 Crystal Arrows
-7036,1754,300
-
-//New Ingredients
-
-// Ice Cubic --> 100 Crystal Arrows
-7066,1754,100
-// Stone Fragment --> 50 Stone Arrows, 30 Stun Arrows
-7067,1756,50,1758,30
-// Burnt Tree --> 250 Fire Arrows
-7068,1752,250
-// Destroyed Armor --> 150 Steel Arrows
-7069,1753,150
-// Burning Heart --> 150 Fire Arrows
-7097,1752,150
-// Live Coal --> 100 Fire Arrows
-7098,1752,100
-// Sharp Leaf --> 30 Sharp Arrows
-7100,1764,30
-// Piece of Shield --> 100 Steel Arrows, 100 Oridecon Arrows, 300 Immaterial Arrows
-7108,1753,100,1765,100,1757,300
-// Shining Spear Blade --> 100 Oridecon Arrows
-7109,1765,100
-// Burning Horseshoe --> 100 Steel Arrows
-7120,1753,100
-// Dragon Skin --> 10 Steel Arrows, 50 Cursed Arrows, 50 Mute Arrows
-7123,1753,10,1761,50,1769,50
-// Piece of Bamboo --> 100 Arrows
-7150,1750,100
-// Poisonous Toad Skin --> 20 Poison Arrows
-7155,1763,20
-// Hard Feeler --> 20 Sharp Arrows
-7163,1764,20
-// Solid Peach --> 30 Stun Arrows
-7164,1758,30
-// Leopard Claw --> 10 Sharp Arrows
-7172,1764,10
-// Armor Piece of Dullahan --> 150 Shadow Arrows
-7210,1767,150
-// Tangled Chains --> 50 Steel Arrows, 50 Shadow Arrows
-7221,1753,50,1767,50
-// Cat's Eye --> 200 Arrows of Wind
-7263,1755,200
-// Dark Crystal Fragment --> 30 Cursed Arrows, 50 Shadow Arrows
-7315,1761,30,1767,50
-// Insect Leg --> 10 Sharp Arrows, 50 Poison Arrows
-7316,1764,10,1763,50
-// Old Pick --> 100 Rusty Arrows, 50 Steel Arrows
-7318,1762,100,1753,50
-// Used Iron Plate --> 100 Rusty Arrows, 100 Steel Arrows
-7319,1762,100,1753,100
-// Crystal Fragment --> 10 Flash Arrows, 30 Sleep Arrows
-7321,1760,10,1768,30
-// Battered Kettle --> 50 Steel Arrows
-7323,1753,50
-// Will of the Darkness --> 30 Cursed Arrows, 30 Poison Arrows, 50 Shadow Arrows
-7340,1761,30,1763,30,1767,50
-// Golden Ornament --> 200 Silver Arrows, 300 Holy Arrows
-7435,1751,200,1772,300
-// Cursed Seal --> 50 Cursed Arrows, 50 Mute Arrows
-7442,1761,50,1769,50
-// Green Bijou --> 100 Stone Arrows, 80 Poison Arrows
-7445,1756,100,1763,80
-// Blue Bijou --> 50 Arrows of Wind, 50 Crystal Arrows, 80 Frozen Arrows
-7446,1755,50,1754,50,1759,80
-// Red Bijou --> 100 Fire Arrows, 80 Flash Arrows
-7447,1752,100,1760,80
-// Yellow Bijou --> 50 Silver Arrows, 50 Immaterial Arrows, 80 Sleep Arrows
-7448,1751,50,1757,50,1768,80
-// Skeletal Armor Piece --> 500 Immaterial Arrows, 200 Shadow Arrows, 100 Oridecon Arrows
-7450,1757,500,1767,200,1765,100
-// Fire Dragon Scale --> 300 Fire Arrows, 300 Stun Arrows
-7451,1752,300,1758,300
-// Valhalla's Flower --> 600 Immaterial Arrows, 600 Holy Arrows, 600 Sharp Arrows
-7510,1757,600,1772,600,1764,600
-// Darkness Rune --> 300 Shadow Arrows, 150 Flash Arrows
-7511,1767,300,1760,150
-// Ice Heart --> 50 Crystal Arrows, 50 Frozen Arrows
-7561,1754,50,1759,50
-// Ice Scale --> 150 Crystal Arrows, 400 Frozen Arrows, 200 Mute Arrows
-7562,1754,150,1759,400,1769,200
-// Will of Red Darkness --> 200 Cursed Arrows, 200 Poison Arrows, 100 Shadow Arrows
-7566,1761,200,1763,200,1767,100
-// Clattering Skull --> 50 Shadow Arrows, 50 Cursed Arrows
-7752,1767,50,1761,50
-// Broken Farm Tools --> 50 Rusty Arrows, 10 Iron Arrows, 20 Cursed Arrows
-7753,1762,50,1770,10,1761,20

+ 749 - 0
db/create_arrow_db.yml

@@ -0,0 +1,749 @@
+# This file is a part of rAthena.
+#   Copyright(C) 2021 rAthena Development Team
+#   https://rathena.org - https://github.com/rathena
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+###########################################################################
+# Arrow Crafting Database
+###########################################################################
+#
+# Arrow Crafting Settings
+#
+###########################################################################
+# - Source              AegisName of the item that is consumed.
+#   Make:               List of item(s) received by the player.
+#     - Item            AegisName of the item received.
+#       Amount          Amount of Item received. (Use 0 to remove the Item on import)
+###########################################################################
+
+Header:
+  Type: CREATE_ARROW_DB
+  Version: 1
+
+Body:
+  - Source: Old_Blue_Box
+    Make:
+      - Item: Incisive_Arrow
+        Amount: 50
+      - Item: Sleep_Arrow
+        Amount: 50
+  - Source: Branch_Of_Dead_Tree
+    Make:
+      - Item: Silence_Arrow
+        Amount: 40
+  - Source: Amulet
+    Make:
+      - Item: Curse_Arrow
+        Amount: 40
+  - Source: Empty_Bottle
+    Make:
+      - Item: Iron_Arrow
+        Amount: 2
+  - Source: Emperium
+    Make:
+      - Item: Immatrial_Arrow
+        Amount: 600
+      - Item: Oridecon_Arrow
+        Amount: 600
+      - Item: Silence_Arrow
+        Amount: 600
+  - Source: Yellow_Gemstone
+    Make:
+      - Item: Sleep_Arrow
+        Amount: 1
+      - Item: Stone_Arrow
+        Amount: 30
+  - Source: Red_Gemstone
+    Make:
+      - Item: Curse_Arrow
+        Amount: 1
+      - Item: Poison_Arrow
+        Amount: 1
+      - Item: Rusty_Arrow
+        Amount: 10
+  - Source: Blue_Gemstone
+    Make:
+      - Item: Crystal_Arrow
+        Amount: 30
+      - Item: Freezing_Arrow
+        Amount: 1
+  - Source: Cardinal_Jewel_
+    Make:
+      - Item: Curse_Arrow
+        Amount: 50
+      - Item: Sleep_Arrow
+        Amount: 10
+  - Source: Crystal_Jewel___
+    Make:
+      - Item: Incisive_Arrow
+        Amount: 50
+  - Source: Oridecon_Stone
+    Make:
+      - Item: Oridecon_Arrow
+        Amount: 50
+  - Source: Elunium_Stone
+    Make:
+      - Item: Steel_Arrow
+        Amount: 200
+      - Item: Stun_Arrow
+        Amount: 5
+  - Source: Tree_Root
+    Make:
+      - Item: Arrow
+        Amount: 7
+  - Source: Scorpion's_Tail
+    Make:
+      - Item: Rusty_Arrow
+        Amount: 3
+  - Source: Jellopy
+    Make:
+      - Item: Arrow
+        Amount: 4
+  - Source: Garlet
+    Make:
+      - Item: Iron_Arrow
+        Amount: 12
+  - Source: Scell
+    Make:
+      - Item: Steel_Arrow
+        Amount: 8
+  - Source: Zargon
+    Make:
+      - Item: Silver_Arrow
+        Amount: 50
+  - Source: Tooth_Of_Bat
+    Make:
+      - Item: Arrow_Of_Shadow
+        Amount: 1
+  - Source: Claw_Of_Wolves
+    Make:
+      - Item: Iron_Arrow
+        Amount: 15
+  - Source: Orcish_Cuspid
+    Make:
+      - Item: Iron_Arrow
+        Amount: 30
+      - Item: Steel_Arrow
+        Amount: 5
+      - Item: Stone_Arrow
+        Amount: 10
+  - Source: Evil_Horn
+    Make:
+      - Item: Arrow_Of_Shadow
+        Amount: 20
+      - Item: Flash_Arrow
+        Amount: 10
+      - Item: Stun_Arrow
+        Amount: 5
+  - Source: Posionous_Canine
+    Make:
+      - Item: Poison_Arrow
+        Amount: 1
+  - Source: Bee_Sting
+    Make:
+      - Item: Rusty_Arrow
+        Amount: 1
+  - Source: Horn
+    Make:
+      - Item: Iron_Arrow
+        Amount: 35
+  - Source: Cactus_Needle
+    Make:
+      - Item: Arrow
+        Amount: 50
+  - Source: Gill
+    Make:
+      - Item: Crystal_Arrow
+        Amount: 150
+      - Item: Iron_Arrow
+        Amount: 80
+  - Source: Decayed_Nail
+    Make:
+      - Item: Arrow_Of_Shadow
+        Amount: 1
+      - Item: Rusty_Arrow
+        Amount: 1
+  - Source: Horrendous_Mouth
+    Make:
+      - Item: Arrow_Of_Shadow
+        Amount: 5
+  - Source: Rotten_Scale
+    Make:
+      - Item: Poison_Arrow
+        Amount: 1
+  - Source: Voucher_Of_Orcish_Hero
+    Make:
+      - Item: Oridecon_Arrow
+        Amount: 1
+      - Item: Stun_Arrow
+        Amount: 5
+  - Source: Gold
+    Make:
+      - Item: Flash_Arrow
+        Amount: 50
+      - Item: Oridecon_Arrow
+        Amount: 50
+  - Source: Oridecon
+    Make:
+      - Item: Oridecon_Arrow
+        Amount: 250
+  - Source: Elunium
+    Make:
+      - Item: Steel_Arrow
+        Amount: 1000
+      - Item: Stun_Arrow
+        Amount: 50
+  - Source: Boody_Red
+    Make:
+      - Item: Fire_Arrow
+        Amount: 600
+  - Source: Crystal_Blue
+    Make:
+      - Item: Crystal_Arrow
+        Amount: 150
+  - Source: Wind_Of_Verdure
+    Make:
+      - Item: Arrow_Of_Wind
+        Amount: 150
+  - Source: Yellow_Live
+    Make:
+      - Item: Stone_Arrow
+        Amount: 150
+  - Source: Flame_Heart
+    Make:
+      - Item: Fire_Arrow
+        Amount: 1800
+      - Item: Silence_Arrow
+        Amount: 5
+  - Source: Mistic_Frozen
+    Make:
+      - Item: Crystal_Arrow
+        Amount: 450
+      - Item: Freezing_Arrow
+        Amount: 5
+  - Source: Rough_Wind
+    Make:
+      - Item: Arrow_Of_Wind
+        Amount: 450
+      - Item: Sleep_Arrow
+        Amount: 5
+  - Source: Great_Nature
+    Make:
+      - Item: Flash_Arrow
+        Amount: 5
+      - Item: Stone_Arrow
+        Amount: 450
+  - Source: Iron
+    Make:
+      - Item: Iron_Arrow
+        Amount: 100
+  - Source: Steel
+    Make:
+      - Item: Steel_Arrow
+        Amount: 100
+  - Source: Star_Crumb
+    Make:
+      - Item: Flash_Arrow
+        Amount: 30
+  - Source: Sparkling_Dust
+    Make:
+      - Item: Flash_Arrow
+        Amount: 10
+  - Source: Iron_Ore
+    Make:
+      - Item: Iron_Arrow
+        Amount: 50
+  - Source: Coal
+    Make:
+      - Item: Arrow_Of_Shadow
+        Amount: 8
+  - Source: Phracon
+    Make:
+      - Item: Iron_Arrow
+        Amount: 50
+  - Source: Emveretarcon
+    Make:
+      - Item: Iron_Arrow
+        Amount: 200
+      - Item: Silver_Arrow
+        Amount: 40
+  - Source: Nail_Of_Mole
+    Make:
+      - Item: Iron_Arrow
+        Amount: 50
+      - Item: Stone_Arrow
+        Amount: 60
+  - Source: Wooden_Block
+    Make:
+      - Item: Arrow
+        Amount: 40
+  - Source: Dokkaebi_Horn
+    Make:
+      - Item: Arrow_Of_Shadow
+        Amount: 2
+      - Item: Iron_Arrow
+        Amount: 40
+  - Source: Porcupine_Spike
+    Make:
+      - Item: Arrow
+        Amount: 70
+      - Item: Stone_Arrow
+        Amount: 30
+  - Source: Limb_Of_Mantis
+    Make:
+      - Item: Incisive_Arrow
+        Amount: 1
+  - Source: Dragon_Canine
+    Make:
+      - Item: Iron_Arrow
+        Amount: 50
+      - Item: Oridecon_Arrow
+        Amount: 1
+  - Source: Petite_DiablOfs_Horn
+    Make:
+      - Item: Curse_Arrow
+        Amount: 2
+      - Item: Iron_Arrow
+        Amount: 50
+  - Source: Lantern
+    Make:
+      - Item: Iron_Arrow
+        Amount: 80
+  - Source: Nail_Of_Orc
+    Make:
+      - Item: Steel_Arrow
+        Amount: 10
+  - Source: Tooth_Of_
+    Make:
+      - Item: Rusty_Arrow
+        Amount: 5
+  - Source: Tooth_Of_Ancient_Fish
+    Make:
+      - Item: Crystal_Arrow
+        Amount: 300
+      - Item: Steel_Arrow
+        Amount: 20
+  - Source: Sharpened_Cuspid
+    Make:
+      - Item: Incisive_Arrow
+        Amount: 2
+      - Item: Silver_Arrow
+        Amount: 40
+  - Source: Reins
+    Make:
+      - Item: Iron_Arrow
+        Amount: 100
+      - Item: Steel_Arrow
+        Amount: 50
+  - Source: Tree_Of_Archer_1
+    Make:
+      - Item: Arrow
+        Amount: 20
+  - Source: Tree_Of_Archer_2
+    Make:
+      - Item: Arrow
+        Amount: 20
+  - Source: Tree_Of_Archer_3
+    Make:
+      - Item: Arrow
+        Amount: 20
+  - Source: Needle_Of_Alarm
+    Make:
+      - Item: Arrow
+        Amount: 100
+      - Item: Sleep_Arrow
+        Amount: 5
+  - Source: Manacles
+    Make:
+      - Item: Steel_Arrow
+        Amount: 50
+  - Source: Snowy_Horn
+    Make:
+      - Item: Silver_Arrow
+        Amount: 1000
+  - Source: Phantom_Of_Opera
+    Make:
+      - Item: Silence_Arrow
+        Amount: 40
+      - Item: Steel_Arrow
+        Amount: 200
+  - Source: Mr_Scream
+    Make:
+      - Item: Incisive_Arrow
+        Amount: 200
+      - Item: Steel_Arrow
+        Amount: 300
+  - Source: Welding_Mask
+    Make:
+      - Item: Steel_Arrow
+        Amount: 200
+      - Item: Stun_Arrow
+        Amount: 40
+  - Source: Glittering_Clothes
+    Make:
+      - Item: Flash_Arrow
+        Amount: 1000
+  - Source: Wooden_Mail
+    Make:
+      - Item: Arrow
+        Amount: 700
+      - Item: Iron_Arrow
+        Amount: 500
+  - Source: Wooden_Mail_
+    Make:
+      - Item: Arrow
+        Amount: 1000
+      - Item: Iron_Arrow
+        Amount: 700
+  - Source: Silver_Robe
+    Make:
+      - Item: Silver_Arrow
+        Amount: 700
+  - Source: Silver_Robe_
+    Make:
+      - Item: Immatrial_Arrow
+        Amount: 10
+      - Item: Silver_Arrow
+        Amount: 1000
+  - Source: Cuffs
+    Make:
+      - Item: Iron_Arrow
+        Amount: 700
+      - Item: Steel_Arrow
+        Amount: 50
+  - Source: Matyr's_Flea_Guard
+    Make:
+      - Item: Arrow_Of_Wind
+        Amount: 150
+      - Item: Incisive_Arrow
+        Amount: 10
+      - Item: Steel_Arrow
+        Amount: 100
+  - Source: Fin_Helm
+    Make:
+      - Item: Crystal_Arrow
+        Amount: 600
+      - Item: Steel_Arrow
+        Amount: 200
+  - Source: Ogre_Tooth
+    Make:
+      - Item: Rusty_Arrow
+        Amount: 5
+      - Item: Steel_Arrow
+        Amount: 30
+  - Source: Stiff_Horn
+    Make:
+      - Item: Stun_Arrow
+        Amount: 2
+  - Source: Tail_Of_Steel_Scorpion
+    Make:
+      - Item: Poison_Arrow
+        Amount: 1
+      - Item: Steel_Arrow
+        Amount: 250
+  - Source: Young_Twig
+    Make:
+      - Item: Silence_Arrow
+        Amount: 1000
+  - Source: Loki's_Whispers
+    Make:
+      - Item: Arrow_Of_Shadow
+        Amount: 1000
+  - Source: Mother's_Nightmare
+    Make:
+      - Item: Curse_Arrow
+        Amount: 1000
+  - Source: Foolishness_Of_Blind
+    Make:
+      - Item: Flash_Arrow
+        Amount: 200
+  - Source: Old_Hilt
+    Make:
+      - Item: Oridecon_Arrow
+        Amount: 1000
+  - Source: Blade_Lost_In_Darkness
+    Make:
+      - Item: Arrow_Of_Shadow
+        Amount: 200
+      - Item: Incisive_Arrow
+        Amount: 600
+  - Source: Bloody_Edge
+    Make:
+      - Item: Curse_Arrow
+        Amount: 200
+      - Item: Incisive_Arrow
+        Amount: 600
+  - Source: Lucifer's_Lament
+    Make:
+      - Item: Silence_Arrow
+        Amount: 400
+      - Item: Sleep_Arrow
+        Amount: 800
+      - Item: Stun_Arrow
+        Amount: 800
+  - Source: Key_Of_Clock_Tower
+    Make:
+      - Item: Oridecon_Arrow
+        Amount: 50
+  - Source: Underground_Key
+    Make:
+      - Item: Arrow_Of_Shadow
+        Amount: 100
+  - Source: Matchstick
+    Make:
+      - Item: Fire_Arrow
+        Amount: 3000
+  - Source: Fang_Of_Garm
+    Make:
+      - Item: Crystal_Arrow
+        Amount: 300
+  - Source: Ice_Piece
+    Make:
+      - Item: Crystal_Arrow
+        Amount: 100
+  - Source: Stone_Piece
+    Make:
+      - Item: Stone_Arrow
+        Amount: 50
+      - Item: Stun_Arrow
+        Amount: 30
+  - Source: Burn_Tree
+    Make:
+      - Item: Fire_Arrow
+        Amount: 250
+  - Source: Broken_Armor_Piece
+    Make:
+      - Item: Steel_Arrow
+        Amount: 150
+  - Source: Burning_Heart
+    Make:
+      - Item: Fire_Arrow
+        Amount: 150
+  - Source: Live_Coal
+    Make:
+      - Item: Fire_Arrow
+        Amount: 100
+  - Source: Sharp_Leaf
+    Make:
+      - Item: Incisive_Arrow
+        Amount: 30
+  - Source: Boroken_Shiled_Piece
+    Make:
+      - Item: Immatrial_Arrow
+        Amount: 300
+      - Item: Oridecon_Arrow
+        Amount: 100
+      - Item: Steel_Arrow
+        Amount: 100
+  - Source: Shine_Spear_Blade
+    Make:
+      - Item: Oridecon_Arrow
+        Amount: 100
+  - Source: Burning_Horse_Shoe
+    Make:
+      - Item: Steel_Arrow
+        Amount: 100
+  - Source: Dragon's_Skin
+    Make:
+      - Item: Curse_Arrow
+        Amount: 50
+      - Item: Silence_Arrow
+        Amount: 50
+      - Item: Steel_Arrow
+        Amount: 10
+  - Source: Bamboo_Cut
+    Make:
+      - Item: Arrow
+        Amount: 100
+  - Source: Poison_Toad's_Skin
+    Make:
+      - Item: Poison_Arrow
+        Amount: 20
+  - Source: Sharp_Feeler
+    Make:
+      - Item: Incisive_Arrow
+        Amount: 20
+  - Source: Hard_Peach
+    Make:
+      - Item: Stun_Arrow
+        Amount: 30
+  - Source: Leopard_Talon
+    Make:
+      - Item: Incisive_Arrow
+        Amount: 10
+  - Source: Dullahan_Armor
+    Make:
+      - Item: Arrow_Of_Shadow
+        Amount: 150
+  - Source: Tangled_Chain
+    Make:
+      - Item: Arrow_Of_Shadow
+        Amount: 50
+      - Item: Steel_Arrow
+        Amount: 50
+  - Source: Cat_Eyed_Stone
+    Make:
+      - Item: Arrow_Of_Wind
+        Amount: 200
+  - Source: Dark_Crystal_Fragment
+    Make:
+      - Item: Arrow_Of_Shadow
+        Amount: 50
+      - Item: Curse_Arrow
+        Amount: 30
+  - Source: Long_Limb
+    Make:
+      - Item: Incisive_Arrow
+        Amount: 10
+      - Item: Poison_Arrow
+        Amount: 50
+  - Source: Old_Pick
+    Make:
+      - Item: Rusty_Arrow
+        Amount: 100
+      - Item: Steel_Arrow
+        Amount: 50
+  - Source: Old_Steel_Plate
+    Make:
+      - Item: Rusty_Arrow
+        Amount: 100
+      - Item: Steel_Arrow
+        Amount: 100
+  - Source: Fragment_Of_Crystal
+    Make:
+      - Item: Flash_Arrow
+        Amount: 10
+      - Item: Sleep_Arrow
+        Amount: 30
+  - Source: Battered_Kettle
+    Make:
+      - Item: Steel_Arrow
+        Amount: 50
+  - Source: Will_Of_Darkness
+    Make:
+      - Item: Arrow_Of_Shadow
+        Amount: 50
+      - Item: Curse_Arrow
+        Amount: 30
+      - Item: Poison_Arrow
+        Amount: 30
+  - Source: Golden_Bracelet
+    Make:
+      - Item: Holy_Arrow
+        Amount: 300
+      - Item: Silver_Arrow
+        Amount: 200
+  - Source: Cursed_Seal
+    Make:
+      - Item: Curse_Arrow
+        Amount: 50
+      - Item: Silence_Arrow
+        Amount: 50
+  - Source: Dragonball_Green
+    Make:
+      - Item: Poison_Arrow
+        Amount: 80
+      - Item: Stone_Arrow
+        Amount: 100
+  - Source: Dragonball_Blue
+    Make:
+      - Item: Arrow_Of_Wind
+        Amount: 50
+      - Item: Crystal_Arrow
+        Amount: 50
+      - Item: Freezing_Arrow
+        Amount: 80
+  - Source: Dragonball_Red
+    Make:
+      - Item: Fire_Arrow
+        Amount: 100
+      - Item: Flash_Arrow
+        Amount: 80
+  - Source: Dragonball_Yellow
+    Make:
+      - Item: Immatrial_Arrow
+        Amount: 50
+      - Item: Silver_Arrow
+        Amount: 50
+      - Item: Sleep_Arrow
+        Amount: 80
+  - Source: Piece_Of_Bone_Armor
+    Make:
+      - Item: Arrow_Of_Shadow
+        Amount: 200
+      - Item: Immatrial_Arrow
+        Amount: 500
+      - Item: Oridecon_Arrow
+        Amount: 100
+  - Source: Scale_Of_Red_Dragon
+    Make:
+      - Item: Fire_Arrow
+        Amount: 300
+      - Item: Stun_Arrow
+        Amount: 300
+  - Source: Valhalla_Flower
+    Make:
+      - Item: Holy_Arrow
+        Amount: 600
+      - Item: Immatrial_Arrow
+        Amount: 600
+      - Item: Incisive_Arrow
+        Amount: 600
+  - Source: Rune_Of_Darkness
+    Make:
+      - Item: Arrow_Of_Shadow
+        Amount: 300
+      - Item: Flash_Arrow
+        Amount: 150
+  - Source: Ice_Heart
+    Make:
+      - Item: Crystal_Arrow
+        Amount: 50
+      - Item: Freezing_Arrow
+        Amount: 50
+  - Source: Ice_Scale
+    Make:
+      - Item: Crystal_Arrow
+        Amount: 150
+      - Item: Freezing_Arrow
+        Amount: 400
+      - Item: Silence_Arrow
+        Amount: 200
+  - Source: Will_Of_Darkness_
+    Make:
+      - Item: Arrow_Of_Shadow
+        Amount: 100
+      - Item: Curse_Arrow
+        Amount: 200
+      - Item: Poison_Arrow
+        Amount: 200
+  - Source: Clattering_Skull
+    Make:
+      - Item: Arrow_Of_Shadow
+        Amount: 50
+      - Item: Curse_Arrow
+        Amount: 50
+  - Source: Broken_Farming_Utensil
+    Make:
+      - Item: Curse_Arrow
+        Amount: 20
+      - Item: Iron_Arrow
+        Amount: 10
+      - Item: Rusty_Arrow
+        Amount: 50
+
+Footer:
+  Imports:
+  - Path: db/import/create_arrow_db.yml

+ 0 - 14
db/import-tmpl/create_arrow_db.txt

@@ -1,14 +0,0 @@
-// Arrow Crafting Database
-//
-// Structure of Database:
-// SourceID,MakeID1,MakeAmount1,...,MakeID5,MakeAmount5
-//
-// 01. SourceID     ID of the item, that is consumed by Arrow Crafting.
-// 02. MakeID       ID of the item received from Arrow Crafting.
-// 03. MakeAmount   Amount of MakeID item received from Arrow Crafting.
-// ...
-//
-// NOTE:
-// - Up to MAX_ARROW_RESULT (typically 5) ID/Amount pairs can be specified.
-// - To remove entry by importing, put 0 on 'MakeID'
-

+ 33 - 0
db/import-tmpl/create_arrow_db.yml

@@ -0,0 +1,33 @@
+# This file is a part of rAthena.
+#   Copyright(C) 2021 rAthena Development Team
+#   https://rathena.org - https://github.com/rathena
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+###########################################################################
+# Arrow Crafting Database
+###########################################################################
+#
+# Arrow Crafting Settings
+#
+###########################################################################
+# - Source              AegisName of the item that is consumed.
+#   Make:               List of item(s) received by the player.
+#     - Item            AegisName of the item received.
+#       Amount          Amount of Item received. (Use 0 to remove the Item on import)
+###########################################################################
+
+Header:
+  Type: CREATE_ARROW_DB
+  Version: 1

+ 12 - 0
doc/yaml/db/create_arrow_db.yml

@@ -0,0 +1,12 @@
+###########################################################################
+# Arrow Crafting Database
+###########################################################################
+#
+# Arrow Crafting Settings
+#
+###########################################################################
+# - Source              AegisName of the item that is consumed.
+#   Make:               List of item(s) received by the player.
+#     - Item            AegisName of the item received.
+#       Amount          Amount of Item received. (Use 0 to remove the Item on import)
+###########################################################################

+ 10 - 21
src/map/clif.cpp

@@ -3851,21 +3851,15 @@ void clif_arrow_fail(struct map_session_data *sd,int type) {
 void clif_arrow_create_list( struct map_session_data *sd ){
 	nullpo_retv( sd );
 
-	int fd = sd->fd;
-
-	if( !session_isActive( fd ) ){
-		return;
-	}
-
-	WFIFOHEAD( fd, sizeof( struct PACKET_ZC_MAKINGARROW_LIST ) + MAX_SKILL_ARROW_DB * sizeof( struct PACKET_ZC_MAKINGARROW_LIST_sub ) );
-	struct PACKET_ZC_MAKINGARROW_LIST *p = (struct PACKET_ZC_MAKINGARROW_LIST *)WFIFOP( fd, 0 );
+	struct PACKET_ZC_MAKINGARROW_LIST *p = (struct PACKET_ZC_MAKINGARROW_LIST *)packet_buffer;
 	p->packetType = HEADER_ZC_MAKINGARROW_LIST;
 
 	int count = 0;
-	for( int i = 0; i < MAX_SKILL_ARROW_DB; i++ ){
-		t_itemid nameid = skill_arrow_db[i].nameid;
 
-		if( !itemdb_exists( nameid ) ){
+	for (const auto &it : skill_arrow_db) {
+		t_itemid nameid = it.second->nameid;
+
+		if( !item_db.exists( nameid ) ){
 			continue;
 		}
 
@@ -3888,7 +3882,8 @@ void clif_arrow_create_list( struct map_session_data *sd ){
 	}
 
 	p->packetLength = sizeof( struct PACKET_ZC_MAKINGARROW_LIST ) + count * sizeof( struct PACKET_ZC_MAKINGARROW_LIST_sub );
-	WFIFOSET( fd, p->packetLength );
+
+	clif_send( p, p->packetLength, &sd->bl, SELF );
 
 	if( count > 0 ){
 		sd->menuskill_id = AC_MAKINGARROW;
@@ -19033,14 +19028,7 @@ void clif_parse_debug(int fd,struct map_session_data *sd)
 void clif_elementalconverter_list( struct map_session_data *sd ){
 	nullpo_retv( sd );
 
-	int fd = sd->fd;
-
-	if( !session_isActive( fd ) ){
-		return;
-	}
-
-	WFIFOHEAD( fd, sizeof( struct PACKET_ZC_MAKINGARROW_LIST ) + MAX_SKILL_ARROW_DB * sizeof( struct PACKET_ZC_MAKINGARROW_LIST_sub ) );
-	struct PACKET_ZC_MAKINGARROW_LIST *p = (struct PACKET_ZC_MAKINGARROW_LIST *)WFIFOP( fd, 0 );
+	struct PACKET_ZC_MAKINGARROW_LIST *p = (struct PACKET_ZC_MAKINGARROW_LIST *)packet_buffer;
 	p->packetType = HEADER_ZC_MAKINGARROW_LIST;
 
 	int count = 0;
@@ -19052,7 +19040,8 @@ void clif_elementalconverter_list( struct map_session_data *sd ){
 	}
 
 	p->packetLength = sizeof( struct PACKET_ZC_MAKINGARROW_LIST ) + count * sizeof( struct PACKET_ZC_MAKINGARROW_LIST_sub );
-	WFIFOSET( fd, p->packetLength );
+
+	clif_send( p, p->packetLength, &sd->bl, SELF );
 
 	if( count > 0 ){
 		sd->menuskill_id = SA_CREATECON;

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

@@ -302,7 +302,7 @@
     <Copy SourceFiles="$(SolutionDir)db\import-tmpl\battleground_db.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\battleground_db.yml')" />
     <Copy SourceFiles="$(SolutionDir)db\import-tmpl\castle_db.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\castle_db.txt')" />
     <Copy SourceFiles="$(SolutionDir)db\import-tmpl\const.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\const.txt')" />
-    <Copy SourceFiles="$(SolutionDir)db\import-tmpl\create_arrow_db.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\create_arrow_db.txt')" />
+    <Copy SourceFiles="$(SolutionDir)db\import-tmpl\create_arrow_db.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\create_arrow_db.yml')" />
     <Copy SourceFiles="$(SolutionDir)db\import-tmpl\elemental_db.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\elemental_db.txt')" />
     <Copy SourceFiles="$(SolutionDir)db\import-tmpl\elemental_skill_db.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\elemental_skill_db.txt')" />
     <Copy SourceFiles="$(SolutionDir)db\import-tmpl\exp_guild.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\exp_guild.txt')" />

+ 86 - 47
src/map/skill.cpp

@@ -84,12 +84,9 @@ struct skill_usave {
 struct s_skill_produce_db skill_produce_db[MAX_SKILL_PRODUCE_DB];
 static unsigned short skill_produce_count;
 
-struct s_skill_arrow_db skill_arrow_db[MAX_SKILL_ARROW_DB];
-static unsigned short skill_arrow_count;
-
 AbraDatabase abra_db;
-
 ReadingSpellbookDatabase reading_spellbook_db;
+SkillArrowDatabase skill_arrow_db;
 
 #define MAX_SKILL_CHANGEMATERIAL_DB 75
 #define MAX_SKILL_CHANGEMATERIAL_SET 3
@@ -20341,34 +20338,36 @@ bool skill_produce_mix(struct map_session_data *sd, uint16 skill_id, t_itemid na
  */
 bool skill_arrow_create(struct map_session_data *sd, t_itemid nameid)
 {
-	short i, j, idx = -1;
-	struct item tmp_item;
-
 	nullpo_ret(sd);
 
-	if (!nameid || !itemdb_exists(nameid) || !skill_arrow_count)
+	if (!nameid || !item_db.exists(nameid) || skill_arrow_db.empty())
 		return false;
 
-	for (i = 0; i < MAX_SKILL_ARROW_DB;i++) {
-		if (nameid == skill_arrow_db[i].nameid) {
-			idx = i;
+	std::shared_ptr<s_skill_arrow_db> arrow = nullptr;
+
+	for (const auto &it : skill_arrow_db) {
+		if (nameid == it.second->nameid) {
+			arrow = it.second;
 			break;
 		}
 	}
+	short j;
 
-	if (idx < 0 || (j = pc_search_inventory(sd,nameid)) < 0)
+	if (arrow == nullptr || (j = pc_search_inventory(sd,nameid)) < 0 || arrow->created.empty())
 		return false;
 
 	pc_delitem(sd,j,1,0,0,LOG_TYPE_PRODUCE);
-	for (i = 0; i < MAX_ARROW_RESULT; i++) {
+
+	for (const auto &it : arrow->created) {
 		char flag = 0;
 
-		if (skill_arrow_db[idx].cre_id[i] == 0 || !itemdb_exists(skill_arrow_db[idx].cre_id[i]) || skill_arrow_db[idx].cre_amount[i] == 0)
+		if (it.first == 0 || !item_db.exists(it.first) || it.second == 0)
 			continue;
-		memset(&tmp_item,0,sizeof(tmp_item));
+
+		struct item tmp_item = { 0 };
 		tmp_item.identify = 1;
-		tmp_item.nameid = skill_arrow_db[idx].cre_id[i];
-		tmp_item.amount = skill_arrow_db[idx].cre_amount[i];
+		tmp_item.nameid = it.first;
+		tmp_item.amount = it.second;
 		if (battle_config.produce_item_name_input&0x4) {
 			tmp_item.card[0] = CARD0_CREATE;
 			tmp_item.card[1] = 0;
@@ -22717,42 +22716,75 @@ static bool skill_parse_row_producedb(char* split[], int columns, int current)
 	return true;
 }
 
-/** Reads create arrow db
- * Sturcture: SourceID,MakeID1,MakeAmount1,...,MakeID5,MakeAmount5
+const std::string SkillArrowDatabase::getDefaultLocation() {
+	return std::string(db_path) + "/create_arrow_db.yml";
+}
+
+/**
+ * Reads and parses an entry from the create_arrow_db.
+ * @param node: YAML node containing the entry.
+ * @return count of successfully parsed rows
  */
-static bool skill_parse_row_createarrowdb(char* split[], int columns, int current)
-{
-	unsigned short x, y, i;
-	t_itemid material_id = strtoul(split[0], nullptr, 10);
+uint64 SkillArrowDatabase::parseBodyNode(const YAML::Node &node) {
+	std::string source_name;
 
-	if (!(itemdb_exists(material_id))) {
-		ShowError("skill_parse_row_createarrowdb: Invalid item %u.\n", material_id);
-		return false;
-	}
+	if (!this->asString(node, "Source", source_name))
+		return 0;
 
-	//search if we override something, (if not i=last idx)
-	ARR_FIND(0, skill_arrow_count, i, skill_arrow_db[i].nameid == material_id);
-	if (i >= ARRAYLENGTH(skill_arrow_db)) {
-		ShowError("skill_parse_row_createarrowdb: Maximum db entries reached.\n");
-		return false;
+	struct item_data *item = itemdb_search_aegisname(source_name.c_str());
+
+	if (item == nullptr) {
+		this->invalidWarning(node["Source"], "Item %s does not exist.\n", source_name.c_str());
+		return 0;
 	}
 
-	// Import just for clearing/disabling from original data
-	if (strtoul(split[1], nullptr, 10) == 0) {
-		memset(&skill_arrow_db[i], 0, sizeof(skill_arrow_db[i]));
-		//ShowInfo("skill_parse_row_createarrowdb: Arrow creation with Material ID %u removed from list.\n", material_id);
-		return true;
+	t_itemid nameid = item->nameid;
+
+	std::shared_ptr<s_skill_arrow_db> arrow = this->find(nameid);
+	bool exists = arrow != nullptr;
+
+	if (!exists) {
+		arrow = std::make_shared<s_skill_arrow_db>();
+		arrow->nameid = nameid;
 	}
 
-	skill_arrow_db[i].nameid = material_id;
-	for (x = 1, y = 0; x+1 < columns && split[x] && split[x+1] && y < MAX_ARROW_RESULT; x += 2, y++) {
-		skill_arrow_db[i].cre_id[y] = strtoul(split[x], nullptr, 10);
-		skill_arrow_db[i].cre_amount[y] = atoi(split[x+1]);
+	const YAML::Node &MakeNode = node["Make"];
+
+	for (const auto &it : MakeNode) {
+		std::string item_name;
+
+		if (!this->asString(it, "Item", item_name))
+			return 0;
+
+		struct item_data *item = itemdb_search_aegisname(item_name.c_str());
+
+		if (item == nullptr) {
+			this->invalidWarning(it["Item"], "Item %s does not exist.\n", item_name.c_str());
+			return 0;
+		}
+
+		uint16 amount;
+
+		if (!this->asUInt16(it, "Amount", amount))
+			return 0;
+
+		if (amount == 0) {
+			if (arrow->created.erase(item->nameid) == 0)
+				this->invalidWarning(it["Amount"], "Failed to remove %s, the entry doesn't exist in Source %s.\n", item_name.c_str(), source_name.c_str());
+			continue;
+		}
+		if (amount > MAX_AMOUNT) {
+			this->invalidWarning(it["Amount"], "Amount %hu exceeds %hu, skipping.\n", amount, MAX_AMOUNT);
+			continue;
+		}
+
+		arrow->created[item->nameid] = amount;
 	}
-	if (i == skill_arrow_count)
-		skill_arrow_count++;
 
-	return true;
+	if (!exists)
+		this->put(nameid, arrow);
+
+	return 1;
 }
 
 const std::string AbraDatabase::getDefaultLocation() {
@@ -22974,9 +23006,8 @@ static void skill_readdb(void)
 	};
 
 	memset(skill_produce_db,0,sizeof(skill_produce_db));
-	memset(skill_arrow_db,0,sizeof(skill_arrow_db));
 	memset(skill_changematerial_db,0,sizeof(skill_changematerial_db));
-	skill_produce_count = skill_arrow_count = skill_changematerial_count = 0;
+	skill_produce_count = skill_changematerial_count = 0;
 
 	skill_db.load();
 
@@ -22996,7 +23027,6 @@ static void skill_readdb(void)
 		sv_readdb(dbsubpath2, "skill_nocast_db.txt"   , ',',   2,  2, -1, skill_parse_row_nocastdb, i > 0);
 
 		sv_readdb(dbsubpath2, "produce_db.txt"        , ',',   5,  5+2*MAX_PRODUCE_RESOURCE, MAX_SKILL_PRODUCE_DB, skill_parse_row_producedb, i > 0);
-		sv_readdb(dbsubpath1, "create_arrow_db.txt"   , ',', 1+2,  1+2*MAX_ARROW_RESULT, MAX_SKILL_ARROW_DB, skill_parse_row_createarrowdb, i > 0);
 		sv_readdb(dbsubpath1, "skill_changematerial_db.txt" , ',',   5,  5+2*MAX_SKILL_CHANGEMATERIAL_SET, MAX_SKILL_CHANGEMATERIAL_DB, skill_parse_row_changematerialdb, i > 0);
 		sv_readdb(dbsubpath1, "skill_damage_db.txt"         , ',',   4,  3+SKILLDMG_MAX, -1, skill_parse_row_skilldamage, i > 0);
 
@@ -23007,6 +23037,7 @@ static void skill_readdb(void)
 	abra_db.load();
 	magic_mushroom_db.load();
 	reading_spellbook_db.load();
+	skill_arrow_db.load();
 
 	skill_init_unit_layout();
 	skill_init_nounit_layout();
@@ -23017,6 +23048,8 @@ void skill_reload (void) {
 	abra_db.clear();
 	magic_mushroom_db.clear();
 	reading_spellbook_db.clear();
+	skill_arrow_db.clear();
+
 	skill_readdb();
 	initChangeTables(); // Re-init Status Change tables
 
@@ -23059,6 +23092,12 @@ void do_init_skill(void)
 
 void do_final_skill(void)
 {
+	skill_db.clear();
+	abra_db.clear();
+	magic_mushroom_db.clear();
+	reading_spellbook_db.clear();
+	skill_arrow_db.clear();
+
 	db_destroy(skillunit_group_db);
 	db_destroy(skillunit_db);
 	db_destroy(skillusave_db);

+ 13 - 5
src/map/skill.hpp

@@ -29,8 +29,6 @@ struct status_change_entry;
 
 #define MAX_SKILL_PRODUCE_DB	282 /// Max Produce DB
 #define MAX_PRODUCE_RESOURCE	12 /// Max Produce requirements
-#define MAX_SKILL_ARROW_DB		150 /// Max Arrow Creation DB
-#define MAX_ARROW_RESULT		5 /// Max Arrow results/created
 #define MAX_SKILL_LEVEL 13 /// Max Skill Level (for skill_db storage)
 #define MAX_MOBSKILL_LEVEL 100	/// Max monster skill level (on skill usage)
 #define MAX_SKILL_CRIMSON_MARKER 3 /// Max Crimson Marker targets (RL_C_MARKER)
@@ -433,10 +431,20 @@ extern struct s_skill_produce_db skill_produce_db[MAX_SKILL_PRODUCE_DB];
 /// Creating database arrow
 struct s_skill_arrow_db {
 	t_itemid nameid; /// Material ID
-	t_itemid cre_id[MAX_ARROW_RESULT]; /// Arrow created
-	uint16 cre_amount[MAX_ARROW_RESULT]; /// Amount of each arrow created
+	std::unordered_map<t_itemid, uint16> created; /// Arrow created
 };
-extern struct s_skill_arrow_db skill_arrow_db[MAX_SKILL_ARROW_DB];
+
+class SkillArrowDatabase : public TypesafeYamlDatabase<t_itemid, s_skill_arrow_db> {
+public:
+	SkillArrowDatabase() : TypesafeYamlDatabase("CREATE_ARROW_DB", 1) {
+
+	}
+
+	const std::string getDefaultLocation();
+	uint64 parseBodyNode(const YAML::Node& node);
+};
+
+extern SkillArrowDatabase skill_arrow_db;
 
 /// Abracadabra database
 struct s_skill_abra_db {

+ 59 - 0
src/tool/csv2yaml.cpp

@@ -337,6 +337,12 @@ int do_init( int argc, char** argv ){
 		return 0;
 	}
 
+	if (!process("CREATE_ARROW_DB", 1, root_paths, "create_arrow_db", [](const std::string& path, const std::string& name_ext) -> bool {
+		return sv_readdb(path.c_str(), name_ext.c_str(), ',', 1+2, 1+2*MAX_ARROW_RESULT, MAX_SKILL_ARROW_DB, &skill_parse_row_createarrowdb, false);
+	})) {
+		return 0;
+	}
+
 	// TODO: add implementations ;-)
 
 	return 0;
@@ -3607,3 +3613,56 @@ static bool mob_readdb_group_yaml(void) {
 	}
 	return true;
 }
+
+// Copied and adjusted from skill.cpp
+static bool skill_parse_row_createarrowdb(char* split[], int columns, int current)
+{
+	t_itemid nameid = static_cast<t_itemid>(strtoul(split[0], nullptr, 10));
+
+	if (nameid == 0)
+		return true;
+
+	std::string *material_name = util::umap_find(aegis_itemnames, nameid);
+
+	if (!material_name) {
+		ShowError("skill_parse_row_createarrowdb: Invalid item %u.\n", nameid);
+		return false;
+	}
+
+	// Import just for clearing/disabling from original data
+	if (strtoul(split[1], nullptr, 10) == 0) {
+		body << YAML::BeginMap;
+		body << YAML::Key << "Remove" << YAML::Value << *material_name;
+		body << YAML::EndMap;
+		return true;
+	}
+
+	std::map<std::string, uint32> item_created;
+	
+	for (uint16 x = 1; x+1 < columns && split[x] && split[x+1]; x += 2) {
+		nameid = static_cast<t_itemid>(strtoul(split[x], nullptr, 10));
+		std::string* item_name = util::umap_find(aegis_itemnames, nameid);
+
+		if (!item_name) {
+			ShowError("skill_parse_row_createarrowdb: Invalid item %u.\n", nameid);
+			return false;
+		}
+
+		item_created.insert({ *item_name, strtoul(split[x+1], nullptr, 10) });
+	}
+
+	body << YAML::BeginMap;
+	body << YAML::Key << "Source" << YAML::Value << *material_name;
+	body << YAML::Key << "Make";
+	body << YAML::BeginSeq;
+	for (const auto &it : item_created) {
+		body << YAML::BeginMap;
+		body << YAML::Key << "Item" << YAML::Value << it.first;
+		body << YAML::Key << "Amount" << YAML::Value << it.second;
+		body << YAML::EndMap;
+	}
+	body << YAML::EndSeq;
+	body << YAML::EndMap;
+
+	return true;
+}

+ 3 - 0
src/tool/csv2yaml.hpp

@@ -13,6 +13,8 @@
 #define MAX_SKILL_EQUIP_REQUIRE 10
 #define MAX_QUEST_DROPS 3
 #define MAX_MAP_PER_INSTANCE 255
+#define MAX_ARROW_RESULT		5 /// Max Arrow results/created
+#define MAX_SKILL_ARROW_DB		150 /// Max Arrow Creation DB
 
 // Database to memory maps
 struct s_skill_unit_csv : s_skill_db {
@@ -420,5 +422,6 @@ static bool mob_parse_row_chatdb(char* fields[], int columns, int current);
 static bool read_homunculus_expdb(const char* file);
 static bool mob_readdb_group(char* str[], int columns, int current);
 static bool mob_readdb_group_yaml(void);
+static bool skill_parse_row_createarrowdb(char* fields[], int columns, int current);
 
 #endif /* CSV2YAML_HPP */