浏览代码

Added support for level 2 armors (#6251)

Thanks to @Atemo and @aleos89 for their help.

Co-authored-by: Atemo <capucrath@gmail.com>
Co-authored-by: Aleos <aleos89@users.noreply.github.com>
Lemongrass3110 3 年之前
父节点
当前提交
c4df5caa00
共有 48 个文件被更改,包括 3982 次插入3289 次删除
  1. 3 2
      db/import-tmpl/item_db.yml
  2. 3 2
      db/item_db.yml
  3. 3 2
      db/pre-re/item_db.yml
  4. 126 2
      db/pre-re/item_db_equip.yml
  5. 3 2
      db/pre-re/item_db_etc.yml
  6. 3 2
      db/pre-re/item_db_usable.yml
  7. 10 0
      db/re/item_combo_db.txt
  8. 3 2
      db/re/item_db.yml
  9. 126 2
      db/re/item_db_equip.yml
  10. 16 15
      db/re/item_db_etc.yml
  11. 3 2
      db/re/item_db_usable.yml
  12. 34 12
      doc/script_commands.txt
  13. 2 1
      doc/yaml/db/item_db.yml
  14. 1 0
      doc/yaml/sql/item_db.sql
  15. 1 0
      doc/yaml/sql/item_db2.sql
  16. 1 0
      doc/yaml/sql/item_db2_re.sql
  17. 1 0
      doc/yaml/sql/item_db_re.sql
  18. 46 14
      npc/merchants/advanced_refiner.txt
  19. 68 16
      npc/merchants/refine.txt
  20. 2 2
      npc/other/monster_race.txt
  21. 21 19
      npc/quests/seals/mjolnir_seal.txt
  22. 36 21
      npc/re/jobs/novice/academy.txt
  23. 42 26
      npc/re/merchants/advanced_refiner.txt
  24. 43 29
      npc/re/merchants/blessed_refiner.txt
  25. 6 6
      npc/re/merchants/hd_refiner.txt
  26. 47 30
      npc/re/merchants/refine.txt
  27. 30 17
      npc/re/merchants/ticket_refiner.txt
  28. 1 0
      sql-files/item_db.sql
  29. 1 0
      sql-files/item_db2.sql
  30. 1 0
      sql-files/item_db2_re.sql
  31. 1192 1192
      sql-files/item_db_equip.sql
  32. 1 0
      sql-files/item_db_re.sql
  33. 1787 1787
      sql-files/item_db_re_equip.sql
  34. 13 13
      sql-files/item_db_re_etc.sql
  35. 3 1
      src/map/atcommand.cpp
  36. 3 3
      src/map/battle.cpp
  37. 16 15
      src/map/clif.cpp
  38. 60 4
      src/map/itemdb.cpp
  39. 4 3
      src/map/itemdb.hpp
  40. 1 0
      src/map/packets.hpp
  41. 1 1
      src/map/pc.cpp
  42. 111 15
      src/map/script.cpp
  43. 2 1
      src/map/script.hpp
  44. 67 20
      src/map/skill.cpp
  45. 5 6
      src/map/status.cpp
  46. 2 2
      src/tool/csv2yaml.cpp
  47. 2 0
      src/tool/yaml2sql.cpp
  48. 29 0
      src/tool/yamlupgrade.cpp

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

@@ -39,7 +39,8 @@
 #   Classes                 Upper class types that can equip the item. (Map default is 'All: true')
 #   Gender                  Gender that can equip the item. (Default: Both)
 #   Locations               Equipment's placement. (Default: None)
-#   WeaponLevel             Weapon level. (Default: 0)
+#   WeaponLevel             Weapon level. (Default: 1 for Weapons)
+#   ArmorLevel              Armor level. (Default: 1 for Armors)
 #   EquipLevelMin           Minimum required level to equip. (Default: 0)
 #   EquipLevelMax           Maximum level that can equip. (Default: 0)
 #   Refineable              If the item can be refined. (Default: false)
@@ -84,7 +85,7 @@
 
 Header:
   Type: ITEM_DB
-  Version: 1
+  Version: 2
 
 #Body:
 # THQ Quest Items

+ 3 - 2
db/item_db.yml

@@ -39,7 +39,8 @@
 #   Classes                 Upper class types that can equip the item. (Map default is 'All: true')
 #   Gender                  Gender that can equip the item. (Default: Both)
 #   Locations               Equipment's placement. (Default: None)
-#   WeaponLevel             Weapon level. (Default: 0)
+#   WeaponLevel             Weapon level. (Default: 1 for Weapons)
+#   ArmorLevel              Armor level. (Default: 1 for Armors)
 #   EquipLevelMin           Minimum required level to equip. (Default: 0)
 #   EquipLevelMax           Maximum level that can equip. (Default: 0)
 #   Refineable              If the item can be refined. (Default: false)
@@ -84,7 +85,7 @@
 
 Header:
   Type: ITEM_DB
-  Version: 1
+  Version: 2
 
 Footer:
   Imports:

+ 3 - 2
db/pre-re/item_db.yml

@@ -39,7 +39,8 @@
 #   Classes                 Upper class types that can equip the item. (Map default is 'All: true')
 #   Gender                  Gender that can equip the item. (Default: Both)
 #   Locations               Equipment's placement. (Default: None)
-#   WeaponLevel             Weapon level. (Default: 0)
+#   WeaponLevel             Weapon level. (Default: 1 for Weapons)
+#   ArmorLevel              Armor level. (Default: 1 for Armors)
 #   EquipLevelMin           Minimum required level to equip. (Default: 0)
 #   EquipLevelMax           Maximum level that can equip. (Default: 0)
 #   Refineable              If the item can be refined. (Default: false)
@@ -84,7 +85,7 @@
 
 Header:
   Type: ITEM_DB
-  Version: 1
+  Version: 2
 
 Footer:
   Imports:

文件差异内容过多而无法显示
+ 126 - 2
db/pre-re/item_db_equip.yml


+ 3 - 2
db/pre-re/item_db_etc.yml

@@ -39,7 +39,8 @@
 #   Classes                 Upper class types that can equip the item. (Map default is 'All: true')
 #   Gender                  Gender that can equip the item. (Default: Both)
 #   Locations               Equipment's placement. (Default: None)
-#   WeaponLevel             Weapon level. (Default: 0)
+#   WeaponLevel             Weapon level. (Default: 1 for Weapons)
+#   ArmorLevel              Armor level. (Default: 1 for Armors)
 #   EquipLevelMin           Minimum required level to equip. (Default: 0)
 #   EquipLevelMax           Maximum level that can equip. (Default: 0)
 #   Refineable              If the item can be refined. (Default: false)
@@ -84,7 +85,7 @@
 
 Header:
   Type: ITEM_DB
-  Version: 1
+  Version: 2
 
 Body:
   - Id: 670

+ 3 - 2
db/pre-re/item_db_usable.yml

@@ -39,7 +39,8 @@
 #   Classes                 Upper class types that can equip the item. (Map default is 'All: true')
 #   Gender                  Gender that can equip the item. (Default: Both)
 #   Locations               Equipment's placement. (Default: None)
-#   WeaponLevel             Weapon level. (Default: 0)
+#   WeaponLevel             Weapon level. (Default: 1 for Weapons)
+#   ArmorLevel              Armor level. (Default: 1 for Armors)
 #   EquipLevelMin           Minimum required level to equip. (Default: 0)
 #   EquipLevelMax           Maximum level that can equip. (Default: 0)
 #   Refineable              If the item can be refined. (Default: false)
@@ -84,7 +85,7 @@
 
 Header:
   Type: ITEM_DB
-  Version: 1
+  Version: 2
 
 Body:
   - Id: 501

+ 10 - 0
db/re/item_combo_db.txt

@@ -2516,3 +2516,13 @@
 490124:490125,{ bonus bFixedCast,-200; if (BaseLevel >= 30) { bonus bMatkRate,1; bonus bVariableCastrate,-2; } if (BaseLevel >= 45) { bonus bMatkRate,1; bonus bVariableCastrate,-3; } if (BaseLevel >= 85) { bonus bMatkRate,1; bonus bVariableCastrate,-5; } }
 490126:490127,{ bonus bFixedCast,-200; bonus bAspdRate,10; if (BaseLevel >= 105) { bonus2 bAddClass,Class_All,2; } if (BaseLevel >= 110) { bonus bShortAtkRate,5; bonus bLongAtkRate,5; } if (BaseLevel >= 120) { bonus bCritAtkRate,5; } }
 490128:490129,{ bonus bFixedCast,-200; bonus bVariableCastrate,-10; if (BaseLevel >= 105) { bonus bMatkRate,2; } if (BaseLevel >= 110) { bonus2 bMagicAtkEle,Ele_All,5; } if (BaseLevel >= 120) { bonus2 bMagicAddEle,Ele_All,5; } }
+// 400142:500024,{ bonus2 bAddSize,Size_All,15; bonus2 bSkillAtk,"GN_CARTCANNON",12*(getequiprefinerycnt(EQI_HAND_R)/2); }
+// 400142:570016,{ bonus bLongAtkRate,15; bonus2 bSkillAtk,"WM_SEVERE_RAINSTORM",12*(getequiprefinerycnt(EQI_HAND_R)/2); }
+// 400142:580016,{ bonus bLongAtkRate,15; bonus2 bSkillAtk,"WM_SEVERE_RAINSTORM",12*(getequiprefinerycnt(EQI_HAND_R)/2); }
+// 400142:700029,{ bonus2 bAddRace,RC_All,15; bonus2 bSkillAtk,"SN_SHARPSHOOTING",12*(getequiprefinerycnt(EQI_HAND_R)/2); }
+// 400145:510030,{ bonus2 bMagicAtkEle,Ele_All,15; bonus2 bSkillAtk,"SO_PSYCHIC_WAVE",12*(getequiprefinerycnt(EQI_HAND_R)/2); }
+// 400145:550023,{ bonus2 bMagicAddRace,RC_All,15; bonus2 bSkillAtk,"SO_VARETYR_SPEAR",12*(getequiprefinerycnt(EQI_HAND_R)/2); }
+// 400145:640017,{ bonus2 bMagicAddSize,Size_All,15; bonus2 bSkillAtk,"WL_CRIMSONROCK",12*(getequiprefinerycnt(EQI_HAND_R)/2); }
+// 400151:560017,{ bonus bMaxHPrate,15; bonus2 bSkillAtk,"SR_TIGERCANNON",12*(getequiprefinerycnt(EQI_HAND_R)/2); }
+// 400151:590020,{ bonus2 bAddSize,Size_All,15; bonus2 bMagicAddSize,Size_All,15; bonus2 bSkillAtk,"AB_DUPLELIGHT",12*(getequiprefinerycnt(EQI_HAND_R)/2); }
+// 400151:610019,{ bonus bDelayrate,-15; bonus2 bSkillAtk,"GC_ROLLINGCUTTER",12*(getequiprefinerycnt(EQI_HAND_R)/2); }

+ 3 - 2
db/re/item_db.yml

@@ -39,7 +39,8 @@
 #   Classes                 Upper class types that can equip the item. (Map default is 'All: true')
 #   Gender                  Gender that can equip the item. (Default: Both)
 #   Locations               Equipment's placement. (Default: None)
-#   WeaponLevel             Weapon level. (Default: 0)
+#   WeaponLevel             Weapon level. (Default: 1 for Weapons)
+#   ArmorLevel              Armor level. (Default: 1 for Armors)
 #   EquipLevelMin           Minimum required level to equip. (Default: 0)
 #   EquipLevelMax           Maximum level that can equip. (Default: 0)
 #   Refineable              If the item can be refined. (Default: false)
@@ -84,7 +85,7 @@
 
 Header:
   Type: ITEM_DB
-  Version: 1
+  Version: 2
 
 Footer:
   Imports:

文件差异内容过多而无法显示
+ 126 - 2
db/re/item_db_equip.yml


+ 16 - 15
db/re/item_db_etc.yml

@@ -39,7 +39,8 @@
 #   Classes                 Upper class types that can equip the item. (Map default is 'All: true')
 #   Gender                  Gender that can equip the item. (Default: Both)
 #   Locations               Equipment's placement. (Default: None)
-#   WeaponLevel             Weapon level. (Default: 0)
+#   WeaponLevel             Weapon level. (Default: 1 for Weapons)
+#   ArmorLevel              Armor level. (Default: 1 for Armors)
 #   EquipLevelMin           Minimum required level to equip. (Default: 0)
 #   EquipLevelMax           Maximum level that can equip. (Default: 0)
 #   Refineable              If the item can be refined. (Default: false)
@@ -84,7 +85,7 @@
 
 Header:
   Type: ITEM_DB
-  Version: 1
+  Version: 2
 
 Body:
   - Id: 670
@@ -12425,7 +12426,7 @@ Body:
     Script: |
       if (getrefine() > 9)
          .@b += 20;
-      if (getequipweaponlv(-1) == 4)
+      if (getequipweaponlv() == 4)
          .@b += 20;
       bonus2 bSkillAtk,"GC_CROSSIMPACT",20+.@b;
   - Id: 4685
@@ -12442,7 +12443,7 @@ Body:
     Script: |
       if (getrefine() > 9)
          .@b += 20;
-      if (getequipweaponlv(-1) == 4)
+      if (getequipweaponlv() == 4)
          .@b += 20;
       bonus2 bSkillAtk,"AB_ADORAMUS",20+.@b;
   - Id: 4686
@@ -12459,7 +12460,7 @@ Body:
     Script: |
       if (getrefine() > 9)
          .@b += 20;
-      if (getequipweaponlv(-1) == 4)
+      if (getequipweaponlv() == 4)
          .@b += 20;
       bonus2 bSkillAtk,"WL_CRIMSONROCK",20+.@b;
   - Id: 4687
@@ -12476,7 +12477,7 @@ Body:
     Script: |
       if (getrefine() > 9)
          .@b += 20;
-      if (getequipweaponlv(-1) == 4)
+      if (getequipweaponlv() == 4)
          .@b += 20;
       bonus2 bSkillAtk,"RA_CLUSTERBOMB",20+.@b;
   - Id: 4688
@@ -12493,7 +12494,7 @@ Body:
     Script: |
       if (getrefine() > 9)
          .@b += 20;
-      if (getequipweaponlv(-1) == 4)
+      if (getequipweaponlv() == 4)
          .@b += 20;
       bonus2 bSkillAtk,"NC_AXETORNADO",20+.@b;
   - Id: 4689
@@ -12510,7 +12511,7 @@ Body:
     Script: |
       if (getrefine() > 9)
          .@b += 20;
-      if (getequipweaponlv(-1) == 4)
+      if (getequipweaponlv() == 4)
          .@b += 20;
       bonus2 bSkillAtk,"RK_IGNITIONBREAK",20+.@b;
   - Id: 4690
@@ -12527,7 +12528,7 @@ Body:
     Script: |
       if (getrefine() > 9)
          .@b += 20;
-      if (getequipweaponlv(-1) == 4)
+      if (getequipweaponlv() == 4)
          .@b += 20;
       bonus2 bSkillAtk,"LG_EARTHDRIVE",20+.@b;
   - Id: 4691
@@ -12544,7 +12545,7 @@ Body:
     Script: |
       if (getrefine() > 9)
          .@b += 20;
-      if (getequipweaponlv(-1) == 4)
+      if (getequipweaponlv() == 4)
          .@b += 20;
       bonus2 bSkillAtk,"GN_CART_TORNADO",20+.@b;
   - Id: 4692
@@ -12561,7 +12562,7 @@ Body:
     Script: |
       if (getrefine() > 9)
          .@b += 20;
-      if (getequipweaponlv(-1) == 4)
+      if (getequipweaponlv() == 4)
          .@b += 20;
       bonus2 bSkillAtk,"SO_VARETYR_SPEAR",20+.@b;
   - Id: 4693
@@ -12578,7 +12579,7 @@ Body:
     Script: |
       if (getrefine() > 9)
          .@b += 20;
-      if (getequipweaponlv(-1) == 4)
+      if (getequipweaponlv() == 4)
          .@b += 20;
       bonus2 bSkillAtk,"SR_RAMPAGEBLASTER",20+.@b;
   - Id: 4694
@@ -12595,7 +12596,7 @@ Body:
     Script: |
       if (getrefine() > 9)
          .@b += 20;
-      if (getequipweaponlv(-1) == 4)
+      if (getequipweaponlv() == 4)
          .@b += 20;
       bonus2 bSkillAtk,"SC_FEINTBOMB",20+.@b;
   - Id: 4695
@@ -12612,7 +12613,7 @@ Body:
     Script: |
       if (getrefine() > 9)
          .@b += 20;
-      if (getequipweaponlv(-1) == 4)
+      if (getequipweaponlv() == 4)
          .@b += 20;
       bonus2 bSkillAtk,"WM_SEVERE_RAINSTORM",20+.@b;
   - Id: 4696
@@ -12629,7 +12630,7 @@ Body:
     Script: |
       if (getrefine() > 9)
          .@b += 20;
-      if (getequipweaponlv(-1) == 4)
+      if (getequipweaponlv() == 4)
          .@b += 20;
       bonus2 bSkillAtk,"WM_REVERBERATION",20+.@b;
   - Id: 4697

+ 3 - 2
db/re/item_db_usable.yml

@@ -39,7 +39,8 @@
 #   Classes                 Upper class types that can equip the item. (Map default is 'All: true')
 #   Gender                  Gender that can equip the item. (Default: Both)
 #   Locations               Equipment's placement. (Default: None)
-#   WeaponLevel             Weapon level. (Default: 0)
+#   WeaponLevel             Weapon level. (Default: 1 for Weapons)
+#   ArmorLevel              Armor level. (Default: 1 for Armors)
 #   EquipLevelMin           Minimum required level to equip. (Default: 0)
 #   EquipLevelMax           Maximum level that can equip. (Default: 0)
 #   Refineable              If the item can be refined. (Default: false)
@@ -84,7 +85,7 @@
 
 Header:
   Type: ITEM_DB
-  Version: 1
+  Version: 2
 
 Body:
   - Id: 500

+ 34 - 12
doc/script_commands.txt

@@ -2782,43 +2782,63 @@ this is +10:
 
 ---------------------------------------
 
-*getequipweaponlv(<equipment slot>{,<char_id>})
+*getequipweaponlv({<equipment slot>{,<char_id>}})
 
 This function returns the weapon level for the weapon equipped in the specified
 equipment slot on the invoking character. For a list of equipment slots see
 'getequipid'.
 
 Only EQI_HAND_L and EQI_HAND_R normally make sense, since only weapons have
-a weapon level. You can, however, probably, use this field for other equippable
-custom items as a flag or something.
+a weapon level.
 
 If no item is equipped in this slot, or if it doesn't have a weapon level
 according to the database, 0 will be returned.
 
 Examples:
 
-// Right hand can only contain a weapon.
     switch (getequipweaponlv(EQI_HAND_R)) {
       case 1: mes "You are holding a lvl 1 weapon."; break;
       case 2: mes "You are holding a lvl 2 weapon."; break;
       case 3: mes "You are holding a lvl 3 weapon."; break;
       case 4: mes "You are holding a lvl 4 weapon."; break;
-      case 5: mes "You are holding a lvl 5 weapon, hm, must be a custom design..."; break;
+      case 5: mes "You are holding a lvl 5 weapon."; break;
+      case 6: mes "You are holding a lvl 6 weapon, hm, must be a custom design..."; break;
       default: mes "Seems you don't have a weapon on."; break;
     }
 
-// Left hand can hold either a weapon or shield.
-    if (getequipid(EQI_HAND_R) == 0) {
+    if (getequipid(EQI_HAND_L) == 0) {
         mes "Seems you have nothing equipped here.";
         close;
     }
     switch (getequipweaponlv(EQI_HAND_L)) {
-      case 0: mes "You are holding a shield, so it doesn't have a level."; break;
+      case 0: mes "You are not holding a weapon, so it doesn't have a level."; break;
       case 1: mes "You are holding a lvl 1 weapon."; break;
       case 2: mes "You are holding a lvl 2 weapon."; break;
       case 3: mes "You are holding a lvl 3 weapon."; break;
       case 4: mes "You are holding a lvl 4 weapon."; break;
-      case 5: mes "You are holding a lvl 5 weapon, hm, must be a custom design..."; break;
+      case 5: mes "You are holding a lvl 5 weapon."; break;
+      case 6: mes "You are holding a lvl 6 weapon, hm, must be a custom design..."; break;
+    }
+
+---------------------------------------
+
+*getequiparmorlv({<equipment slot>{,<char_id>}})
+
+This function returns the armor level for the item equipped in the specified
+equipment slot on the invoking character. For a list of equipment slots see
+'getequipid'.
+
+If no item is equipped in this slot, or if it doesn't have an armor level
+according to the database, 0 will be returned.
+
+    if (getequipid(EQI_ARMOR) == 0) {
+        mes "Seems you have nothing equipped here.";
+        close;
+    }
+    switch (getequiparmorlv(EQI_ARMOR)) {
+      case 1: mes "You are wearing a lvl 1 armor."; break;
+      case 2: mes "You are wearing a lvl 2 armor."; break;
+      case 3: mes "You are wearing a lvl 3 armor, hm, must be a custom design..."; break;
     }
 
 ---------------------------------------
@@ -3031,7 +3051,8 @@ Valid types are:
 	ITEMINFO_MAGICATTACK    (16)   -  matk if RENEWAL is defined
 	ITEMINFO_ID             (17)   -  item ID
 	ITEMINFO_AEGISNAME      (18)   -  aegis item name
-	
+	ITEMINFO_ARMORLEVEL     (19)   -  armor LV
+
 See the sample in 'doc/sample/getiteminfo.txt'.
 
 ---------------------------------------
@@ -8677,8 +8698,8 @@ Valid types are:
 	ITEMINFO_SELL            (1)   -  Sell Price
 	ITEMINFO_TYPE            (2)   -  Type
 	ITEMINFO_MAXCHANCE       (3)   -  maxchance (max drop chance of this item, e.g. 1 = 0.01%)
-		                        if = 0, then monsters don't drop it at all (rare or a quest item)
-		                        if = 10000, then this item is sold in NPC shops only
+	                                  if = 0, then monsters don't drop it at all (rare or a quest item)
+	                                  if = 10000, then this item is sold in NPC shops only
 	ITEMINFO_GENDER          (4)   -  Gender
 	ITEMINFO_LOCATIONS       (5)   -  Location(s)
 	ITEMINFO_WEIGHT          (6)   -  Weight
@@ -8692,6 +8713,7 @@ Valid types are:
 	ITEMINFO_ALIASNAME      (14)   -  AliasName
 	ITEMINFO_EQUIPLEVELMAX  (15)   -  equipment LV Max
 	ITEMINFO_MAGICATTACK    (16)   -  matk if RENEWAL is defined
+	ITEMINFO_ARMORLEVEL     (19)   -  armor LV
 
 Example:
 	setiteminfo 7049,ITEMINFO_WEIGHT,9990; // Stone now weighs 999.0

+ 2 - 1
doc/yaml/db/item_db.yml

@@ -22,7 +22,8 @@
 #   Classes                 Upper class types that can equip the item. (Map default is 'All: true')
 #   Gender                  Gender that can equip the item. (Default: Both)
 #   Locations               Equipment's placement. (Default: None)
-#   WeaponLevel             Weapon level. (Default: 0)
+#   WeaponLevel             Weapon level. (Default: 1 for Weapons)
+#   ArmorLevel              Armor level. (Default: 1 for Armors)
 #   EquipLevelMin           Minimum required level to equip. (Default: 0)
 #   EquipLevelMax           Maximum level that can equip. (Default: 0)
 #   Refineable              If the item can be refined. (Default: false)

+ 1 - 0
doc/yaml/sql/item_db.sql

@@ -69,6 +69,7 @@ CREATE TABLE `item_db` (
   `location_shadow_right_accessory` tinyint(1) unsigned DEFAULT NULL,
   `location_shadow_left_accessory` tinyint(1) unsigned DEFAULT NULL,
   `weapon_level` tinyint(1) unsigned DEFAULT NULL,
+  `armor_level` tinyint(1) unsigned DEFAULT NULL,
   `equip_level_min` tinyint(3) unsigned DEFAULT NULL,
   `equip_level_max` tinyint(3) unsigned DEFAULT NULL,
   `refineable` tinyint(1) unsigned DEFAULT NULL,

+ 1 - 0
doc/yaml/sql/item_db2.sql

@@ -69,6 +69,7 @@ CREATE TABLE `item_db2` (
   `location_shadow_right_accessory` tinyint(1) unsigned DEFAULT NULL,
   `location_shadow_left_accessory` tinyint(1) unsigned DEFAULT NULL,
   `weapon_level` tinyint(1) unsigned DEFAULT NULL,
+  `armor_level` tinyint(1) unsigned DEFAULT NULL,
   `equip_level_min` tinyint(3) unsigned DEFAULT NULL,
   `equip_level_max` tinyint(3) unsigned DEFAULT NULL,
   `refineable` tinyint(1) unsigned DEFAULT NULL,

+ 1 - 0
doc/yaml/sql/item_db2_re.sql

@@ -76,6 +76,7 @@ CREATE TABLE `item_db2_re` (
   `location_shadow_right_accessory` tinyint(1) unsigned DEFAULT NULL,
   `location_shadow_left_accessory` tinyint(1) unsigned DEFAULT NULL,
   `weapon_level` tinyint(1) unsigned DEFAULT NULL,
+  `armor_level` tinyint(1) unsigned DEFAULT NULL,
   `equip_level_min` tinyint(3) unsigned DEFAULT NULL,
   `equip_level_max` tinyint(3) unsigned DEFAULT NULL,
   `refineable` tinyint(1) unsigned DEFAULT NULL,

+ 1 - 0
doc/yaml/sql/item_db_re.sql

@@ -76,6 +76,7 @@ CREATE TABLE `item_db_re` (
   `location_shadow_right_accessory` tinyint(1) unsigned DEFAULT NULL,
   `location_shadow_left_accessory` tinyint(1) unsigned DEFAULT NULL,
   `weapon_level` tinyint(1) unsigned DEFAULT NULL,
+  `armor_level` tinyint(1) unsigned DEFAULT NULL,
   `equip_level_min` tinyint(3) unsigned DEFAULT NULL,
   `equip_level_max` tinyint(3) unsigned DEFAULT NULL,
   `refineable` tinyint(1) unsigned DEFAULT NULL,

+ 46 - 14
npc/merchants/advanced_refiner.txt

@@ -59,10 +59,11 @@ payon,157,146,6	script	Suhnbi#cash	85,{
 	.@refinerycnt = getequiprefinerycnt(.@part); //save refinery count
 	.@price = getequiprefinecost(.@part, REFINE_COST_ENRICHED, REFINE_ZENY_COST);
 	.@material = getequiprefinecost(.@part, REFINE_COST_ENRICHED, REFINE_MATERIAL_ID);
+	.@itemtype = getiteminfo( .@refineitemid, ITEMINFO_TYPE );
 
 	// Make sure you have the necessary items and Zeny to refine your items
 	// Determines chance of failure and verifies that you want to continue.
-	callsub S_RefineValidate,getequipweaponlv(.@part),.@material,.@price,.@part,.@refineitemid,.@refinerycnt;
+	callsub S_RefineValidate,.@itemtype,.@material,.@price,.@part,.@refineitemid,.@refinerycnt;
 
 	mes "[Suhnbi]";
 	mes "Clang! Clang! Clang!";
@@ -72,7 +73,7 @@ payon,157,146,6	script	Suhnbi#cash	85,{
 		emotion ET_BEST;
 		mes "[Suhnbi]";
 		mes "There you go! It's done.";
-		mes "It's been a while since I've made such a fine "+((getequipweaponlv(.@part))?"weapon":"armor")+". You must be happy because it has become stronger!";
+		mes "It's been a while since I've made such a fine "+((.@itemtype == IT_WEAPON)?"weapon":"armor")+". You must be happy because it has become stronger!";
 		close;
 	}
 	failedrefitem .@part;
@@ -89,32 +90,63 @@ payon,157,146,6	script	Suhnbi#cash	85,{
 	close;
 
 S_RefineValidate:
-	.@weapon_lvl = getarg(0);
+	.@itemtype = getarg(0);
 	.@item_req = getarg(1);
 	.@price = getarg(2);
 	.@part = getarg(3);
 	setarray .@card[0], getequipcardid(.@part,0), getequipcardid(.@part,1), getequipcardid(.@part,2), getequipcardid(.@part,3);
 
-	// If the VIP system is enabled, the prices for non-VIP players are considerably higher.
-	if (VIP_SCRIPT && !vip_status(VIP_STATUS_ACTIVE)) {
-		switch(.@weapon_lvl){
-			case 0: set .@price, .@price * 10; break;
-			case 1: set .@price, .@price * 40; break;
-			case 2: set .@price, .@price * 50; break;
-			case 3: set .@price, .@price * 2; break;
-			case 4: set .@price, .@price * 2; break;
+	if( .@itemtype == IT_ARMOR ){
+		.@equip_lv = getequiparmorlv( .@part );
+
+		// If the VIP system is enabled, the prices for non-VIP players are considerably higher.
+		if (VIP_SCRIPT && !vip_status(VIP_STATUS_ACTIVE)) {
+			switch(.@equip_lv) {
+				case 1:
+					set .@price, .@price * 10;
+					break;
+				default:
+					// TODO:
+					close;
+			}
+		}
+	}else if( .@itemtype == IT_WEAPON ){
+		.@equip_lv = getequipweaponlv( .@part );
+
+		// If the VIP system is enabled, the prices for non-VIP players are considerably higher.
+		if (VIP_SCRIPT && !vip_status(VIP_STATUS_ACTIVE)) {
+			switch( .@equip_lv ){
+				case 1:
+					set .@price, .@price * 40;
+					break;
+				case 2:
+					set .@price, .@price * 50;
+					break;
+				case 3:
+					set .@price, .@price * 2;
+					break;
+				case 4:
+					set .@price, .@price * 2;
+					break;
+				default:
+					// TODO:
+					close;
+			}
 		}
+	}else{
+		// TODO:
+		close;
 	}
 
 	mes "[Suhnbi]";
-	if (.@weapon_lvl)
-		mes "You want to refine a level "+ .@weapon_lvl +" weapon?";
+	if (.@itemtype == IT_WEAPON)
+		mes "You want to refine a level "+ .@equip_lv +" weapon?";
 	mes "To refine that, you'll need to have one ^ff9999"+ getitemname(.@item_req) +"^000000 and "+ .@price +" zeny.";
 	mes "Would you like to continue?";
 	next;
 	if(select("Yes:No") == 1) {
 		if (getequippercentrefinery(.@part) < 100) {
-			if (.@weapon_lvl) {
+			if (.@itemtype == IT_WEAPON) {
 				mes "[Suhnbi]";
 				mes "Wow!!";
 				mes "This weapon probably";

+ 68 - 16
npc/merchants/refine.txt

@@ -682,27 +682,79 @@ function	script	refinemain	{
 	setarray .@card[0], getequipcardid(.@part,0), getequipcardid(.@part,1), getequipcardid(.@part,2), getequipcardid(.@part,3);
 	.@price = getequiprefinecost(.@part, REFINE_COST_NORMAL, REFINE_ZENY_COST);
 	.@material = getequiprefinecost(.@part, REFINE_COST_NORMAL, REFINE_MATERIAL_ID);
+	.@itemtype = getiteminfo( .@refineitemid, ITEMINFO_TYPE );
 
-	switch (getequipweaponlv(.@part)) {
-		case 1: .@safe = 7; break;
-		case 2: .@safe = 6; break;
-		case 3: .@safe = 5; break;
-		case 4:
-		default: .@safe = 4; break;
-	}
+	if( .@itemtype == IT_ARMOR ){
+		.@equip_lv = getequiparmorlv( .@part );
+
+		switch( .@equip_lv ){
+			case 1:
+				.@safe = 4;
+				break;
+			default:
+				// TODO:
+				close;
+		}
+
+		// If the VIP system is enabled, the prices for non-VIP players are considerably higher.
+		if( VIP_SCRIPT && !vip_status(VIP_STATUS_ACTIVE) ){
+			switch( .@equip_lv ){
+				case 1:
+					.@price = .@price * 10;
+					break;
+				default:
+					// TODO:
+					close;
+			}
+		}
+	}else if( .@itemtype == IT_WEAPON ){
+		.@equip_lv = getequipweaponlv( .@part );
+
+		switch( .@equip_lv ){
+			case 1:
+				.@safe = 7;
+				break;
+			case 2:
+				.@safe = 6;
+				break;
+			case 3:
+				.@safe = 5;
+				break;
+			case 4:
+				.@safe = 4;
+				break;
+			default:
+				// TODO:
+				close;
+		}
 
-	// If the VIP system is enabled, the prices for non-VIP players are considerably higher.
-	if (VIP_SCRIPT && !vip_status(VIP_STATUS_ACTIVE)) {
-		switch(getequipweaponlv(.@part)) {
-			case 0: .@price = .@price * 10; break;
-			case 1: .@price = .@price * 40; break;
-			case 2: .@price = .@price * 50; break;
-			case 3: .@price = .@price * 2; break;
-			case 4: .@price = .@price * 2; break;
-			case 5: .@price = .@price * 10; break;
+		// If the VIP system is enabled, the prices for non-VIP players are considerably higher.
+		if( VIP_SCRIPT && !vip_status(VIP_STATUS_ACTIVE) ){
+			switch( .@equip_lv ){
+				case 1:
+					.@price = .@price * 40;
+					break;
+				case 2:
+					.@price = .@price * 50;
+					break;
+				case 3:
+					.@price = .@price * 2;
+					break;
+				case 4:
+					.@price = .@price * 2;
+					break;
+				default:
+					// TODO:
+					close;
+			}
 		}
+	}else{
+		.@safe = 4;
 	}
 
+	// TODO: What was this? Maybe shadow?
+	// case 5: .@price = .@price * 10; break;
+
 	if(.@features != 1) {
 		mes "["+ .@npc_name$ +"]";
 		mes "To refine this I need";

+ 2 - 2
npc/other/monster_race.txt

@@ -2558,7 +2558,7 @@ S_BonusReward:
 		mes "me a reward later?";
 		next;
 		mes "[Ei'felle]";
-		if (!getiteminfo(.@arg1, ITEMINFO_WEAPONLEVEL)) { //use item level to determine if the item is armor (no weapon level)
+		if (getiteminfo( .@arg1, ITEMINFO_TYPE ) == IT_ARMOR) {
 			mes "Of course, of course.";
 			mes "Remember, if you donate";
 			mes "more medals to me, then";
@@ -2601,7 +2601,7 @@ S_BonusReward:
 	getitem .@arg1,1;
 	close;
 }
-	
+
 hugel,71,83,4	script	Wayne	900,{
 	if (!checkweight("Knife",1)) {
 		mes "[Wayne]";

+ 21 - 19
npc/quests/seals/mjolnir_seal.txt

@@ -1965,6 +1965,7 @@ mjolnir_01,35,136,7	script	Dwarf Blacksmith#west	826,{
 					close;
 				}
 				.@equip_id = getequipid(.@part);
+				.@itemtype = getiteminfo( .@equip_id, ITEMINFO_TYPE );
 				.@equip_refine = getequiprefinerycnt(.@part);
 				setarray .@card[0], getequipcardid(.@part,0), getequipcardid(.@part,1), getequipcardid(.@part,2), getequipcardid(.@part,3);
 				if (.@equip_refine >= 10) {
@@ -1983,16 +1984,7 @@ mjolnir_01,35,136,7	script	Dwarf Blacksmith#west	826,{
 					mes "element of risk!";
 					close;
 				}
-				if ((getequipweaponlv(.@part) <= 1) && (getequipweaponlv(.@part) >= 3 )){
-					mes "[Vestri]";
-					mes "Hey...";
-					mes "Don't insult me by expecting me to work on anything less than a Level 4 weapon.";
-					next;
-					mes "[Vestri]";
-					mes "Bring me a Level 4 weapon for me to work on next time, got it?";
-					close;
-				}
-				if (getequipweaponlv(.@part) == 0){
+				if( .@itemtype != IT_WEAPON ){
 					mes "[Vestri]";
 					mes "Armor?!";
 					mes "Didn't I tell";
@@ -2004,6 +1996,15 @@ mjolnir_01,35,136,7	script	Dwarf Blacksmith#west	826,{
 					mes "Blacksmith work on that kind of stuff! Now, a Dwarf like me needs something that's more of a challenge!";
 					close;
 				}
+				if( getequipweaponlv( .@part ) != 4 ){
+					mes "[Vestri]";
+					mes "Hey...";
+					mes "Don't insult me by expecting me to work on anything less than a Level 4 weapon.";
+					next;
+					mes "[Vestri]";
+					mes "Bring me a Level 4 weapon for me to work on next time, got it?";
+					close;
+				}
 
 				mes "[Vestri]";
 				mes "Okay, let me give you the mandatory warning. If your weapon happens to be destroyed by chance during the upgrade, you'll never see the weapon again.";
@@ -2189,6 +2190,7 @@ mjolnir_01,35,136,7	script	Dwarf Blacksmith#west	826,{
 					close;
 				}
 				.@equip_id = getequipid(.@part);
+				.@itemtype = getiteminfo( .@equip_id, ITEMINFO_TYPE );
 				.@equip_refine = getequiprefinerycnt(.@part);
 				setarray .@card[0], getequipcardid(.@part,0), getequipcardid(.@part,1), getequipcardid(.@part,2), getequipcardid(.@part,3);
 				if (.@equip_refine >= 10) {
@@ -2207,7 +2209,15 @@ mjolnir_01,35,136,7	script	Dwarf Blacksmith#west	826,{
 					mes "element of risk!";
 					close;
 				}
-				if ((getequipweaponlv(.@part) <= 1) && (getequipweaponlv(.@part) >= 3 )){
+				if( .@itemtype != IT_WEAPON ){
+					mes "[Vestri]";
+					mes "Armor?!";
+					mes "Didn't I tell";
+					mes "you that I only work";
+					mes "on Level 4 weapons?";
+					close;
+				}
+				if( getequipweaponlv( .@part ) != 4 ){
 					mes "[Vestri]";
 					mes "Hey...";
 					mes "Don't insult me by expecting me to work on anything less than a Level 4 weapon.";
@@ -2216,14 +2226,6 @@ mjolnir_01,35,136,7	script	Dwarf Blacksmith#west	826,{
 					mes "Bring me a Level 4 weapon for me to work on next time, got it?";
 					close;
 				}
-				if (getequipweaponlv(.@part) == 0){
-					mes "[Vestri]";
-					mes "Armor?!";
-					mes "Didn't I tell";
-					mes "you that I only work";
-					mes "on Level 4 weapons?";
-					close;
-				}
 				mes "[Vestri]";
 				mes "Okay, let me give you the mandatory warning. If your weapon happens to be destroyed by chance during the upgrade, you'll never see the weapon again.";
 				next;

+ 36 - 21
npc/re/jobs/novice/academy.txt

@@ -12818,6 +12818,7 @@ izlude_d,153,126,1	duplicate(Refinery Owner Han#iz)	Refinery Owner Han#iz_d	4_M_
 	.@refineitemid = getequipid(.@part); // save id of the item
 	.@refinerycnt = getequiprefinerycnt(.@part); //save refinery count
 	setarray .@card[0], getequipcardid(.@part,0), getequipcardid(.@part,1), getequipcardid(.@part,2), getequipcardid(.@part,3);
+	.@itemtype = getiteminfo( .@refineitemid, ITEMINFO_TYPE );
 
 	if (.@refinerycnt >= 10) {
 		mes "[Refining Machine Wagjak]";
@@ -12876,28 +12877,42 @@ izlude_d,153,126,1	duplicate(Refinery Owner Han#iz)	Refinery Owner Han#iz_d	4_M_
 //	.@price = getequiprefinecost(.@part, REFINE_COST_NORMAL, REFINE_ZENY_COST);
 	.@material = getequiprefinecost(.@part, REFINE_COST_NORMAL, REFINE_MATERIAL_ID);
 
-	switch(getequipweaponlv(.@part)) {
-	default:
-	case 0: // Armor
-		.@price = 20000;
+	if( .@itemtype == IT_ARMOR ){
+		.@equip_lv = getequiparmorlv( .@part );
 		.@type$ = "Armor";
-		break;
-	case 1: // Level 1 Weapon
-		.@price = 1000;
-		.@type$ = "Level 1 weapon";
-		break;
-	case 2: // Level 2 Weapon
-		.@price = 2000;
-		.@type$ = "Level 2 weapon";
-		break;
-	case 3: // Level 3 Weapon
-		.@price = 10000;
-		.@type$ = "Level 3 weapon";
-		break;
-	case 4: // Level 4 Weapon
-		.@price = 20000;
-		.@type$ = "Level 4 weapon";
-		break;
+
+		switch( .@equip_lv ){
+			case 1:
+				.@price = 20000;
+				break;
+			default:
+				// TODO:
+				close;
+		}
+	}else if( .@itemtype == IT_WEAPON ){
+		.@equip_lv = getequipweaponlv( .@part );
+		.@type$ = "Level " + .@equip_lv + " Weapon";
+
+		switch( .@equip_lv ){
+			case 1:
+				.@price = 1000;
+				break;
+			case 2:
+				set .@price,2000;
+				break;
+			case 3:
+				set .@price,10000;
+				break;
+			case 4:
+				set .@price,20000;
+				break;
+			default:
+				// TODO:
+				close;
+		}
+	}else{
+		// TODO:
+		close;
 	}
 
 	mes "[Refining Machine Wagjak]";

+ 42 - 26
npc/re/merchants/advanced_refiner.txt

@@ -71,42 +71,58 @@ malangdo,221,174,6	script	Holink#mal_cash	559,{
 	}
 	mes "[Holink]";
 	.@refineitemid = getequipid(.@part); // save id of the item
+	.@itemtype = getiteminfo( .@refineitemid, ITEMINFO_TYPE );
 	.@refinerycnt = getequiprefinerycnt(.@part); //save refinery count
 	setarray .@card[0], getequipcardid(.@part,0), getequipcardid(.@part,1), getequipcardid(.@part,2), getequipcardid(.@part,3);
 // Holink has different hardcoded prices
 //	.@price = getequiprefinecost(.@part, REFINE_COST_NORMAL, REFINE_ZENY_COST);
 	.@material = getequiprefinecost(.@part, REFINE_COST_NORMAL, REFINE_MATERIAL_ID);
 
-	switch(getequipweaponlv(.@part)) {
-	default:
-	case 0: // Armor
+	if( .@itemtype == IT_ARMOR ){
+		.@equip_lv = getequiparmorlv( .@part );
 		.@type$ = "armor";
-		.@price = 15000;
 		mes "You have chosen an armor, meow~";
-		break;
-	case 1: // Level 1 Weapon
-		.@type$ = "weapon";
-		.@price = 500;
-		mes "A level 1 weapon...?";
-		break;
-	case 2: // Level 2 Weapon
-		.@type$ = "weapon";
-		.@price = 2000;
-		mes "Meow, a level 2 weapon...?";
-		break;
-	case 3: // Level 3 Weapon
-		.@type$ = "weapon";
-		.@price = 20000;
-		mes "Meow Meow~~ A level 3 weapon~~";
-		break;
-	case 4: // Level 4 Weapon
+
+		switch(.@equip_lv) {
+			case 1:
+				.@price = 15000;
+				break;
+			default:
+				// TODO:
+				close;
+		}
+	}else if( .@itemtype == IT_WEAPON ){
+		.@equip_lv = getequipweaponlv( .@part );
 		.@type$ = "weapon";
-		.@price = 50000;
-		mes "Me-Meow!... A level 4 weapon...!";
-		mes "I've only seen it twice while";
-		mes "learning from Aragam... Me-Meow!!";
-		break;
+
+		switch( .@equip_lv ){
+			case 1: // Level 1 Weapon
+				.@price = 500;
+				mes "A level 1 weapon...?";
+				break;
+			case 2: // Level 2 Weapon
+				.@price = 2000;
+				mes "Meow, a level 2 weapon...?";
+				break;
+			case 3: // Level 3 Weapon
+				.@price = 20000;
+				mes "Meow Meow~~ A level 3 weapon~~";
+				break;
+			case 4: // Level 4 Weapon
+				.@price = 50000;
+				mes "Me-Meow!... A level 4 weapon...!";
+				mes "I've only seen it twice while";
+				mes "learning from Aragam... Me-Meow!!";
+				break;
+			default:
+				// TODO:
+				close;
+		}
+	}else{
+		// TODO:
+		close;
 	}
+
 	mes "You need ^ff9999"+getitemname(.@material)+"^000000 and ^ff9999"+.@price+"^000000 Zeny for this refine, meow~";
 	mes "Want to continue, meow?~";
 	next;

+ 43 - 29
npc/re/merchants/blessed_refiner.txt

@@ -69,6 +69,7 @@
 		close;
 	}
 	.@equip_id = getequipid(.@part);
+	.@itemtype = getiteminfo( .@equip_id );
 	.@equip_refine = getequiprefinerycnt(.@part);
 	setarray .@card[0], getequipcardid(.@part,0), getequipcardid(.@part,1), getequipcardid(.@part,2), getequipcardid(.@part,3);
 
@@ -77,34 +78,47 @@
 		mes "This equipment has refined to "+.@equip_refine+". I only handle items with refine levels from +6 to +12!";
 		close;
 	}
-	set .@equip_lv, getequipweaponlv(.@part);
-	switch(.@equip_lv) {
-	default:
-	case 0:
-		set .@price,20000;
-		set .@material,6439; //Unbreakable_Def
-		set .@type$,"Armor";
-		break;
-	case 1:
-		set .@price,1000;
-		set .@material,6438; //Unbreakable_Weap
-		set .@type$,"Weapon";
-		break;
-	case 2:
-		set .@price,2000;
-		set .@material,6438; //Unbreakable_Weap
-		set .@type$,"Weapon";
-		break;
-	case 3:
-		set .@price,20000;
-		set .@material,6438; //Unbreakable_Weap
-		set .@type$,"Weapon";
-		break;
-	case 4:
-		set .@price,40000;
-		set .@material,6438; //Unbreakable_Weap
-		set .@type$,"Weapon";
-		break;
+	if( .@itemtype == IT_ARMOR ){
+		.@equip_lv = getequiparmorlv( .@part );
+		.@type$ = "Armor";
+
+		switch(.@equip_lv) {
+			case 1:
+				set .@price,20000;
+				set .@material,6439; //Unbreakable_Def
+				break;
+			default:
+				// TODO:
+				close;
+		}
+	}else if( .@itemtype == IT_WEAPON ){
+		.@equip_lv = getequipweaponlv( .@part );
+		.@type$ = "Weapon";
+
+		switch( .@equip_lv ){
+			case 1:
+				set .@price,1000;
+				set .@material,6438; //Unbreakable_Weap
+				break;
+			case 2:
+				set .@price,2000;
+				set .@material,6438; //Unbreakable_Weap
+				break;
+			case 3:
+				set .@price,20000;
+				set .@material,6438; //Unbreakable_Weap
+				break;
+			case 4:
+				set .@price,40000;
+				set .@material,6438; //Unbreakable_Weap
+				break;
+			default:
+				// TODO:
+				close;
+		}
+	}else{
+		// TODO:
+		close;
 	}
 	set .@ore$,"^ff9999Blessed "+.@type$+" Ore^000000";
 	mes "[Blacksmith Dister]";
@@ -132,7 +146,7 @@
 	if (countitem(.@material) == 0 || Zeny < .@price) {
 		mes "[Blacksmith Dister]";
 		mes "Materials insufficient.";
-		mes "To refine "+((.@equip_lv)?"a level "+.@equip_lv+" weapon":"armor")+", I need "+.@ore$+" and a "+callfunc("F_InsertComma",.@price)+" zeny refining fee.";
+		mes "To refine a level "+.@equip_lv+" "+.@type$+", I need "+.@ore$+" and a "+callfunc("F_InsertComma",.@price)+" zeny refining fee.";
 		close;
 	}
 	delitem .@material,1;

+ 6 - 6
npc/re/merchants/hd_refiner.txt

@@ -85,6 +85,7 @@
 	}
 
 	.@refineitemid = getequipid(.@part); // save id of the item
+	.@itemtype = getiteminfo( .@refineitemid, ITEMINFO_TYPE );
 	.@refinerycnt = getequiprefinerycnt(.@part); //save refinery count
 	setarray .@card[0], getequipcardid(.@part,0), getequipcardid(.@part,1), getequipcardid(.@part,2), getequipcardid(.@part,3);
 	.@price = getequiprefinecost(.@part, REFINE_COST_HD, REFINE_ZENY_COST);
@@ -113,8 +114,7 @@
 			mes "With the Blacksmith Blessing, the equipment won't vanish if the refine fails!";
 			next;
 			mes "[Blacksmith Mighty Hammer]";
-			.@weapon_lvl = getequipweaponlv(.@part);
-			if (.@weapon_lvl < 1 || .@weapon_lvl > 4)
+			if ( .@itemtype != IT_WEAPON )
 				mes "For +" + getequiprefinerycnt(.@part) + " equipment, refine with^316AC5 " + .@blacksmith_blessing_count + " unit(s) Blacksmith Blessing^000000 can prevent the equipment from vanishing. Do you want use it to refine?";
 			else
 				mes "For +" + getequiprefinerycnt(.@part) + " weapon, refine with^316AC5 " + .@blacksmith_blessing_count + " unit(s) Blacksmith Blessing^000000 can prevent the equipment from vanishing. Do you want use it to refine?";
@@ -161,7 +161,7 @@
 		next;
 		emotion ET_BEST;
 		mes "[Blacksmith Mighty Hammer]";
-		mes "The sound refreshes my mind everytime I hear it.";
+		mes "The sound refreshes my mind every time I hear it.";
 		mes "Here, have it. Refine succeeded flawlessly!";
 		close;
 	}
@@ -253,7 +253,7 @@ lhz_in02,280,19,3	duplicate(MightyHammer)	Mighty Hammer#lhz	4_M_DWARF
 	.@refine_count = getequiprefinerycnt(.@part);
 	if (.@refine_count < 10) {
 		mes "[Basta]";
-		mes "Haven't I told you? I only refine equipments that are +10 and above.";
+		mes "Haven't I told you? I only refine equipment that are +10 and above.";
 		close;
 	}
 	else if (.@refine_count == 10)
@@ -266,13 +266,13 @@ lhz_in02,280,19,3	duplicate(MightyHammer)	Mighty Hammer#lhz	4_M_DWARF
 		close;
 	}
 	.@refineitemid = getequipid(.@part); // save id of the item
+	.@itemtype = getiteminfo( .@refineitemid, ITEMINFO_TYPE );
 	.@refinerycnt = getequiprefinerycnt(.@part); //save refinery count
 	setarray .@card[0], getequipcardid(.@part,0), getequipcardid(.@part,1), getequipcardid(.@part,2), getequipcardid(.@part,3);
 	.@price = getequiprefinecost(.@part, REFINE_COST_HD, REFINE_ZENY_COST);
 	.@material = getequiprefinecost(.@part, REFINE_COST_HD, REFINE_MATERIAL_ID);
 
-	.@weapon_lvl = getequipweaponlv(.@part);
-	if (.@weapon_lvl < 1 || .@weapon_lvl > 4)
+	if ( .@itemtype != IT_WEAPON )
 		.@type$ = "armor";
 	else
 		.@type$ = "weapon";

+ 47 - 30
npc/re/merchants/refine.txt

@@ -108,18 +108,22 @@ function	script	refinenew	{
 	.@price = getequiprefinecost(.@part, REFINE_COST_NORMAL, REFINE_ZENY_COST);
 	.@material = getequiprefinecost(.@part, REFINE_COST_NORMAL, REFINE_MATERIAL_ID);
 	.@safe = 10;
-
-	if (getequipweaponlv(.@part) >= 1 && getequipweaponlv(.@part) <= 4) {
+	.@itemtype = getiteminfo( .@refineitemid, ITEMINFO_TYPE );
+	
+	if( .@itemtype == IT_WEAPON ){
 		.@article$ = "a";
 		.@type$ = "weapon";
-	} else {
+	}else if( .@itemtype == IT_ARMOR ){
 		.@article$ = "an";
 		.@type$ = "armor";
+	}else{
+		// TODO:
+		close;
 	}
-	
+
 	mes "["+ .@npc_name$ +"]";
 	mes "Hmm " + .@article$ + " " + .@type$ + ", is that ok?";
-	mes "If you want to refine this armor,";
+	mes "If you want to refine this " + .@type$ + ",";
 	mes "I will need 1 ^003366" + getitemname(.@material) + "^000000 and " + callfunc("F_InsertComma",.@price) + " zeny.";
 	mes "Are you sure you want to continue?";
 	next;
@@ -131,7 +135,7 @@ function	script	refinenew	{
 	if (getarg(1) != 1) {
 		if (getequippercentrefinery(.@part) < 100) {
 			mes "["+ .@npc_name$ +"]";
-			mes "This "+.@type$+" already has been refined serveral times.";
+			mes "This "+.@type$+" already has been refined several times.";
 			mes "It could be destroyed if I try again.";
 			mes "It won't break for sure, but there is has a small chance.";
 			next;
@@ -455,31 +459,44 @@ malangdo,224,172,6	script	Clink#mal_normal	544,{
 	setarray .@card[0], getequipcardid(.@part,0), getequipcardid(.@part,1), getequipcardid(.@part,2), getequipcardid(.@part,3);
 	.@price = getequiprefinecost(.@part, REFINE_COST_NORMAL, REFINE_ZENY_COST);
 	.@material = getequiprefinecost(.@part, REFINE_COST_NORMAL, REFINE_MATERIAL_ID);
-	
+	.@itemtype = getiteminfo( .@refineitemid, ITEMINFO_TYPE );
 	mes "[Clink]";
-	switch(getequipweaponlv(.@part)) {
-	default:
-	case 0: // Armor
-		.@type$ = "armor";
-		mes "Hmm, an armor refine? Someone like you?";
-		break;
-	case 1: // Level 1 Weapon
-		.@type$ = "weapon";
-		mes "A level 1 weapon?";
-		mes "Urr... Annoying... Okay, let's try...";
-		break;
-	case 2: // Level 2 Weapon
-		.@type$ = "weapon";
-		mes "A level 2 weapon?";
-		break;
-	case 3: // Level 3 Weapon
-		.@type$ = "weapon";
-		mes "Woot!! A level 3 weapon? Impressive~";
-		break;
-	case 4: // Level 4 Weapon
-		.@type$ = "weapon";
-		mes "Wow!... A level 4 weapon~!!";
-		break;
+	if( .@itemtype == IT_ARMOR ){
+		switch( getequiparmorlv( .@part ) ){
+			case 1: // Armor
+				.@type$ = "armor";
+				mes "Hmm, an armor refine? Someone like you?";
+				break;
+			default:
+				// TODO:
+				close;
+		}
+	}else if( .@itemtype == IT_WEAPON ){
+		switch( getequipweaponlv( .@part ) ){
+			case 1: // Level 1 Weapon
+				.@type$ = "weapon";
+				mes "A level 1 weapon?";
+				mes "Urr... Annoying... Okay, let's try...";
+				break;
+			case 2: // Level 2 Weapon
+				.@type$ = "weapon";
+				mes "A level 2 weapon?";
+				break;
+			case 3: // Level 3 Weapon
+				.@type$ = "weapon";
+				mes "Woot!! A level 3 weapon? Impressive~";
+				break;
+			case 4: // Level 4 Weapon
+				.@type$ = "weapon";
+				mes "Wow!... A level 4 weapon~!!";
+				break;
+			default:
+				// TODO:
+				close;
+		}
+	}else{
+		// TODO:
+		close;
 	}
 	mes "You need ^ff9999"+getitemname(.@material)+"^000000 and ^ff9999"+.@price+"^000000 Zeny. Do you have them?";
 	next;

+ 30 - 17
npc/re/merchants/ticket_refiner.txt

@@ -79,23 +79,36 @@ prontera,184,177,6	script	Refine Master	851,{
 	.@refineitemid = getequipid(.@part); // save id of the item
 	.@refinerycnt = getequiprefinerycnt(.@part); //save refinery count
 	setarray .@card[0], getequipcardid(.@part,0), getequipcardid(.@part,1), getequipcardid(.@part,2), getequipcardid(.@part,3);
-	switch(getequipweaponlv(.@part)) {
-	default:
-	case 0:
-		setarray .@tickets[0],6457,6235,6234,6233,6232,6239;
-		setarray .@levels[0],5,6,7,8,9,11;
-		set .@type$,"Armor";
-		set .@check,.@bArmorUp;
-		break;
-	case 1:
-	case 2:
-	case 3:
-	case 4:
-		setarray .@tickets[0],6456,6231,6230,6229,6228,6238;
-		setarray .@levels[0],5,6,7,8,9,11;
-		set .@type$,"Weapon";
-		set .@check,.@bWeaponUp;
-		break;
+	.@itemtype = getiteminfo( .@refineitemid );
+	if( .@itemtype == IT_WEAPON ){
+		switch( getequipweaponlv( .@part ) ){
+			case 1:
+			case 2:
+			case 3:
+			case 4:
+				setarray .@tickets[0],6456,6231,6230,6229,6228,6238;
+				setarray .@levels[0],5,6,7,8,9,11;
+				set .@type$,"Weapon";
+				set .@check,.@bWeaponUp;
+				break;
+			default:
+				// TODO:
+				close;
+		}
+	}else if( .@itemtype == IT_ARMOR ){
+		switch( getequiparmorlv( .@part ) ){
+			case 1:
+				setarray .@tickets[0],6457,6235,6234,6233,6232,6239;
+				setarray .@levels[0],5,6,7,8,9,11;
+				set .@type$,"Armor";
+				set .@check,.@bArmorUp;
+				break;
+			default:
+				// TODO:
+				close;
+	}else{
+		// TODO:
+		close;
 	}
 	if (!.@check) {
 		emotion ET_THINK;

+ 1 - 0
sql-files/item_db.sql

@@ -69,6 +69,7 @@ CREATE TABLE `item_db` (
   `location_shadow_right_accessory` tinyint(1) unsigned DEFAULT NULL,
   `location_shadow_left_accessory` tinyint(1) unsigned DEFAULT NULL,
   `weapon_level` tinyint(1) unsigned DEFAULT NULL,
+  `armor_level` tinyint(1) unsigned DEFAULT NULL,
   `equip_level_min` tinyint(3) unsigned DEFAULT NULL,
   `equip_level_max` tinyint(3) unsigned DEFAULT NULL,
   `refineable` tinyint(1) unsigned DEFAULT NULL,

+ 1 - 0
sql-files/item_db2.sql

@@ -69,6 +69,7 @@ CREATE TABLE `item_db2` (
   `location_shadow_right_accessory` tinyint(1) unsigned DEFAULT NULL,
   `location_shadow_left_accessory` tinyint(1) unsigned DEFAULT NULL,
   `weapon_level` tinyint(1) unsigned DEFAULT NULL,
+  `armor_level` tinyint(1) unsigned DEFAULT NULL,
   `equip_level_min` tinyint(3) unsigned DEFAULT NULL,
   `equip_level_max` tinyint(3) unsigned DEFAULT NULL,
   `refineable` tinyint(1) unsigned DEFAULT NULL,

+ 1 - 0
sql-files/item_db2_re.sql

@@ -76,6 +76,7 @@ CREATE TABLE `item_db2_re` (
   `location_shadow_right_accessory` tinyint(1) unsigned DEFAULT NULL,
   `location_shadow_left_accessory` tinyint(1) unsigned DEFAULT NULL,
   `weapon_level` tinyint(1) unsigned DEFAULT NULL,
+  `armor_level` tinyint(1) unsigned DEFAULT NULL,
   `equip_level_min` tinyint(3) unsigned DEFAULT NULL,
   `equip_level_max` tinyint(3) unsigned DEFAULT NULL,
   `refineable` tinyint(1) unsigned DEFAULT NULL,

文件差异内容过多而无法显示
+ 1192 - 1192
sql-files/item_db_equip.sql


+ 1 - 0
sql-files/item_db_re.sql

@@ -76,6 +76,7 @@ CREATE TABLE `item_db_re` (
   `location_shadow_right_accessory` tinyint(1) unsigned DEFAULT NULL,
   `location_shadow_left_accessory` tinyint(1) unsigned DEFAULT NULL,
   `weapon_level` tinyint(1) unsigned DEFAULT NULL,
+  `armor_level` tinyint(1) unsigned DEFAULT NULL,
   `equip_level_min` tinyint(3) unsigned DEFAULT NULL,
   `equip_level_max` tinyint(3) unsigned DEFAULT NULL,
   `refineable` tinyint(1) unsigned DEFAULT NULL,

文件差异内容过多而无法显示
+ 1787 - 1787
sql-files/item_db_re_equip.sql


+ 13 - 13
sql-files/item_db_re_etc.sql

@@ -955,19 +955,19 @@ REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`price_buy`,`
 REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`price_buy`,`weight`,`location_garment`,`flag_buyingstore`,`flag_dropeffect`,`script`) VALUES (4681,'Genetic_Card','Genetic Flamel Card','Card',20,10,true,true,'CLIENT','if (eaclass()&EAJL_THIRD && BaseJob == Job_Alchemist) {\n   bonus bFlee,20;\n   bonus2 bAddRace,RC_All,15;\n}\nif (BaseLevel>174)\n   bonus bAllStats,10;\nif (getrefine()>9)\n   bonus bAllStats,10;');
 REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`price_buy`,`weight`,`location_garment`,`flag_buyingstore`,`flag_dropeffect`,`script`) VALUES (4682,'ShadowChaser_Card','Shadow Chaser Gertie Card','Card',20,10,true,true,'CLIENT','if (eaclass()&EAJL_THIRD && BaseJob == Job_Rogue) {\n   bonus bMatkRate,15;\n   bonus2 bAddRace,RC_All,5;\n}\nif (BaseLevel>174)\n   bonus bAllStats,10;\nif (getrefine()>9)\n   bonus bAllStats,10;');
 REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`price_buy`,`weight`,`location_garment`,`flag_buyingstore`,`flag_dropeffect`,`script`) VALUES (4683,'Wanderer_Card','Wanderer Trentini Card','Card',20,10,true,true,'CLIENT','if (eaclass()&EAJL_THIRD && BaseJob == Job_Dancer) {\n   bonus bMaxHPrate,10;\n   bonus bMaxSPrate,15;\n}\nif (BaseLevel>174)\n   bonus bAllStats,10;\nif (getrefine()>9)\n   bonus bAllStats,10;');
-REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`price_buy`,`weight`,`location_right_hand`,`flag_buyingstore`,`flag_dropeffect`,`script`) VALUES (4684,'Real_Eremes_Card','True Eremes Guile Card','Card',20,10,true,true,'CLIENT','if (getrefine() > 9)\n   .@b += 20;\nif (getequipweaponlv(-1) == 4)\n   .@b += 20;\nbonus2 bSkillAtk,"GC_CROSSIMPACT",20+.@b;');
-REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`price_buy`,`weight`,`location_right_hand`,`flag_buyingstore`,`flag_dropeffect`,`script`) VALUES (4685,'Real_Magaleta_Card','True Margaretha Sorin Card','Card',20,10,true,true,'CLIENT','if (getrefine() > 9)\n   .@b += 20;\nif (getequipweaponlv(-1) == 4)\n   .@b += 20;\nbonus2 bSkillAtk,"AB_ADORAMUS",20+.@b;');
-REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`price_buy`,`weight`,`location_right_hand`,`flag_buyingstore`,`flag_dropeffect`,`script`) VALUES (4686,'Real_Katrinn_Card','True Kathryne Keyron Card','Card',20,10,true,true,'CLIENT','if (getrefine() > 9)\n   .@b += 20;\nif (getequipweaponlv(-1) == 4)\n   .@b += 20;\nbonus2 bSkillAtk,"WL_CRIMSONROCK",20+.@b;');
-REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`price_buy`,`weight`,`location_right_hand`,`flag_buyingstore`,`flag_dropeffect`,`script`) VALUES (4687,'Real_Shecil_Card','True Cecil Damon Card','Card',20,10,true,true,'CLIENT','if (getrefine() > 9)\n   .@b += 20;\nif (getequipweaponlv(-1) == 4)\n   .@b += 20;\nbonus2 bSkillAtk,"RA_CLUSTERBOMB",20+.@b;');
-REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`price_buy`,`weight`,`location_right_hand`,`flag_buyingstore`,`flag_dropeffect`,`script`) VALUES (4688,'Real_Harword_Card','True Howard Alt-Eisen Card','Card',20,10,true,true,'CLIENT','if (getrefine() > 9)\n   .@b += 20;\nif (getequipweaponlv(-1) == 4)\n   .@b += 20;\nbonus2 bSkillAtk,"NC_AXETORNADO",20+.@b;');
-REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`price_buy`,`weight`,`location_right_hand`,`flag_buyingstore`,`flag_dropeffect`,`script`) VALUES (4689,'Real_Seyren_Card','True Seyren Windsor Card','Card',20,10,true,true,'CLIENT','if (getrefine() > 9)\n   .@b += 20;\nif (getequipweaponlv(-1) == 4)\n   .@b += 20;\nbonus2 bSkillAtk,"RK_IGNITIONBREAK",20+.@b;');
-REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`price_buy`,`weight`,`location_right_hand`,`flag_buyingstore`,`flag_dropeffect`,`script`) VALUES (4690,'Real_Randel_Card','True Randel Lawrence Card','Card',20,10,true,true,'CLIENT','if (getrefine() > 9)\n   .@b += 20;\nif (getequipweaponlv(-1) == 4)\n   .@b += 20;\nbonus2 bSkillAtk,"LG_EARTHDRIVE",20+.@b;');
-REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`price_buy`,`weight`,`location_right_hand`,`flag_buyingstore`,`flag_dropeffect`,`script`) VALUES (4691,'Real_Flamel_Card','True Flamel Emure Card','Card',20,10,true,true,'CLIENT','if (getrefine() > 9)\n   .@b += 20;\nif (getequipweaponlv(-1) == 4)\n   .@b += 20;\nbonus2 bSkillAtk,"GN_CART_TORNADO",20+.@b;');
-REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`price_buy`,`weight`,`location_right_hand`,`flag_buyingstore`,`flag_dropeffect`,`script`) VALUES (4692,'Real_Ceila_Card','True Celia Alde Card','Card',20,10,true,true,'CLIENT','if (getrefine() > 9)\n   .@b += 20;\nif (getequipweaponlv(-1) == 4)\n   .@b += 20;\nbonus2 bSkillAtk,"SO_VARETYR_SPEAR",20+.@b;');
-REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`price_buy`,`weight`,`location_right_hand`,`flag_buyingstore`,`flag_dropeffect`,`script`) VALUES (4693,'Real_Chen_Card','True Chen Liu Card','Card',20,10,true,true,'CLIENT','if (getrefine() > 9)\n   .@b += 20;\nif (getequipweaponlv(-1) == 4)\n   .@b += 20;\nbonus2 bSkillAtk,"SR_RAMPAGEBLASTER",20+.@b;');
-REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`price_buy`,`weight`,`location_right_hand`,`flag_buyingstore`,`flag_dropeffect`,`script`) VALUES (4694,'Real_Gertie_Card','True Gertie Card','Card',20,10,true,true,'CLIENT','if (getrefine() > 9)\n   .@b += 20;\nif (getequipweaponlv(-1) == 4)\n   .@b += 20;\nbonus2 bSkillAtk,"SC_FEINTBOMB",20+.@b;');
-REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`price_buy`,`weight`,`location_right_hand`,`flag_buyingstore`,`flag_dropeffect`,`script`) VALUES (4695,'Real_Trentini_Card','True Trentini Card','Card',20,10,true,true,'CLIENT','if (getrefine() > 9)\n   .@b += 20;\nif (getequipweaponlv(-1) == 4)\n   .@b += 20;\nbonus2 bSkillAtk,"WM_SEVERE_RAINSTORM",20+.@b;');
-REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`price_buy`,`weight`,`location_right_hand`,`flag_buyingstore`,`flag_dropeffect`,`script`) VALUES (4696,'Real_Alphoccio_Card','True Alphoccio Card','Card',20,10,true,true,'CLIENT','if (getrefine() > 9)\n   .@b += 20;\nif (getequipweaponlv(-1) == 4)\n   .@b += 20;\nbonus2 bSkillAtk,"WM_REVERBERATION",20+.@b;');
+REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`price_buy`,`weight`,`location_right_hand`,`flag_buyingstore`,`flag_dropeffect`,`script`) VALUES (4684,'Real_Eremes_Card','True Eremes Guile Card','Card',20,10,true,true,'CLIENT','if (getrefine() > 9)\n   .@b += 20;\nif (getequipweaponlv() == 4)\n   .@b += 20;\nbonus2 bSkillAtk,"GC_CROSSIMPACT",20+.@b;');
+REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`price_buy`,`weight`,`location_right_hand`,`flag_buyingstore`,`flag_dropeffect`,`script`) VALUES (4685,'Real_Magaleta_Card','True Margaretha Sorin Card','Card',20,10,true,true,'CLIENT','if (getrefine() > 9)\n   .@b += 20;\nif (getequipweaponlv() == 4)\n   .@b += 20;\nbonus2 bSkillAtk,"AB_ADORAMUS",20+.@b;');
+REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`price_buy`,`weight`,`location_right_hand`,`flag_buyingstore`,`flag_dropeffect`,`script`) VALUES (4686,'Real_Katrinn_Card','True Kathryne Keyron Card','Card',20,10,true,true,'CLIENT','if (getrefine() > 9)\n   .@b += 20;\nif (getequipweaponlv() == 4)\n   .@b += 20;\nbonus2 bSkillAtk,"WL_CRIMSONROCK",20+.@b;');
+REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`price_buy`,`weight`,`location_right_hand`,`flag_buyingstore`,`flag_dropeffect`,`script`) VALUES (4687,'Real_Shecil_Card','True Cecil Damon Card','Card',20,10,true,true,'CLIENT','if (getrefine() > 9)\n   .@b += 20;\nif (getequipweaponlv() == 4)\n   .@b += 20;\nbonus2 bSkillAtk,"RA_CLUSTERBOMB",20+.@b;');
+REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`price_buy`,`weight`,`location_right_hand`,`flag_buyingstore`,`flag_dropeffect`,`script`) VALUES (4688,'Real_Harword_Card','True Howard Alt-Eisen Card','Card',20,10,true,true,'CLIENT','if (getrefine() > 9)\n   .@b += 20;\nif (getequipweaponlv() == 4)\n   .@b += 20;\nbonus2 bSkillAtk,"NC_AXETORNADO",20+.@b;');
+REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`price_buy`,`weight`,`location_right_hand`,`flag_buyingstore`,`flag_dropeffect`,`script`) VALUES (4689,'Real_Seyren_Card','True Seyren Windsor Card','Card',20,10,true,true,'CLIENT','if (getrefine() > 9)\n   .@b += 20;\nif (getequipweaponlv() == 4)\n   .@b += 20;\nbonus2 bSkillAtk,"RK_IGNITIONBREAK",20+.@b;');
+REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`price_buy`,`weight`,`location_right_hand`,`flag_buyingstore`,`flag_dropeffect`,`script`) VALUES (4690,'Real_Randel_Card','True Randel Lawrence Card','Card',20,10,true,true,'CLIENT','if (getrefine() > 9)\n   .@b += 20;\nif (getequipweaponlv() == 4)\n   .@b += 20;\nbonus2 bSkillAtk,"LG_EARTHDRIVE",20+.@b;');
+REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`price_buy`,`weight`,`location_right_hand`,`flag_buyingstore`,`flag_dropeffect`,`script`) VALUES (4691,'Real_Flamel_Card','True Flamel Emure Card','Card',20,10,true,true,'CLIENT','if (getrefine() > 9)\n   .@b += 20;\nif (getequipweaponlv() == 4)\n   .@b += 20;\nbonus2 bSkillAtk,"GN_CART_TORNADO",20+.@b;');
+REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`price_buy`,`weight`,`location_right_hand`,`flag_buyingstore`,`flag_dropeffect`,`script`) VALUES (4692,'Real_Ceila_Card','True Celia Alde Card','Card',20,10,true,true,'CLIENT','if (getrefine() > 9)\n   .@b += 20;\nif (getequipweaponlv() == 4)\n   .@b += 20;\nbonus2 bSkillAtk,"SO_VARETYR_SPEAR",20+.@b;');
+REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`price_buy`,`weight`,`location_right_hand`,`flag_buyingstore`,`flag_dropeffect`,`script`) VALUES (4693,'Real_Chen_Card','True Chen Liu Card','Card',20,10,true,true,'CLIENT','if (getrefine() > 9)\n   .@b += 20;\nif (getequipweaponlv() == 4)\n   .@b += 20;\nbonus2 bSkillAtk,"SR_RAMPAGEBLASTER",20+.@b;');
+REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`price_buy`,`weight`,`location_right_hand`,`flag_buyingstore`,`flag_dropeffect`,`script`) VALUES (4694,'Real_Gertie_Card','True Gertie Card','Card',20,10,true,true,'CLIENT','if (getrefine() > 9)\n   .@b += 20;\nif (getequipweaponlv() == 4)\n   .@b += 20;\nbonus2 bSkillAtk,"SC_FEINTBOMB",20+.@b;');
+REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`price_buy`,`weight`,`location_right_hand`,`flag_buyingstore`,`flag_dropeffect`,`script`) VALUES (4695,'Real_Trentini_Card','True Trentini Card','Card',20,10,true,true,'CLIENT','if (getrefine() > 9)\n   .@b += 20;\nif (getequipweaponlv() == 4)\n   .@b += 20;\nbonus2 bSkillAtk,"WM_SEVERE_RAINSTORM",20+.@b;');
+REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`price_buy`,`weight`,`location_right_hand`,`flag_buyingstore`,`flag_dropeffect`,`script`) VALUES (4696,'Real_Alphoccio_Card','True Alphoccio Card','Card',20,10,true,true,'CLIENT','if (getrefine() > 9)\n   .@b += 20;\nif (getequipweaponlv() == 4)\n   .@b += 20;\nbonus2 bSkillAtk,"WM_REVERBERATION",20+.@b;');
 REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`price_buy`,`weight`,`location_right_hand`,`flag_dropeffect`,`script`) VALUES (4697,'Charleston_Card','Charleston3 Card','Card',20,10,true,'CLIENT','bonus bBreakArmorRate,5000;\nbonus bMaxSP,-300;');
 REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`price_buy`,`weight`,`location_right_hand`,`flag_dropeffect`,`script`) VALUES (4698,'Step_Card','Step Card','Card',20,10,true,'CLIENT','bonus2 bSkillAtk,"NC_AXEBOOMERANG",30+((getrefine() >= 10)*30);');
 REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`price_buy`,`weight`,`location_right_hand`,`flag_dropeffect`,`script`) VALUES (4699,'Rock_Step_Card','Rock Step Card','Card',20,10,true,'CLIENT','bonus2 bSkillAtk,"NC_ARMSCANNON",20+((getrefine()>=10)*20);');

+ 3 - 1
src/map/atcommand.cpp

@@ -2362,7 +2362,9 @@ ACMD_FUNC(refine)
 			clif_additem(sd, i, 1, 0);
 			pc_equipitem(sd, i, current_position);
 			clif_misceffect(&sd->bl, 3);
-			achievement_update_objective(sd, AG_ENCHANT_SUCCESS, 2, sd->inventory_data[i]->wlv, sd->inventory.u.items_inventory[i].refine);
+			if( sd->inventory_data[i]->type == IT_WEAPON ){
+				achievement_update_objective(sd, AG_ENCHANT_SUCCESS, 2, sd->inventory_data[i]->weapon_level, sd->inventory.u.items_inventory[i].refine);
+			}
 			count++;
 		}
 	}

+ 3 - 3
src/map/battle.cpp

@@ -2259,8 +2259,8 @@ static int64 battle_calc_base_damage(struct block_list *src, struct status_data
 		if (!(flag&1) || (flag&2)) { //Normal attacks
 			atkmin = status->dex;
 
-			if (sd->equip_index[type] >= 0 && sd->inventory_data[sd->equip_index[type]])
-				atkmin = atkmin*(80 + sd->inventory_data[sd->equip_index[type]]->wlv*20)/100;
+			if (sd->equip_index[type] >= 0 && sd->inventory_data[sd->equip_index[type]] && sd->inventory_data[sd->equip_index[type]]->type == IT_WEAPON)
+				atkmin = atkmin*(80 + sd->inventory_data[sd->equip_index[type]]->weapon_level*20)/100;
 
 			if (atkmin > atkmax)
 				atkmin = atkmax;
@@ -3816,7 +3816,7 @@ static int battle_calc_attack_skill_ratio(struct Damage* wd, struct block_list *
 
 					if (index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_WEAPON)
 						skillratio += -100 + sd->inventory_data[index]->weight / 10 + sd->inventory_data[index]->atk +
-							100 * sd->inventory_data[index]->wlv * (sd->inventory.u.items_inventory[index].refine + 6);
+							100 * sd->inventory_data[index]->weapon_level * (sd->inventory.u.items_inventory[index].refine + 6);
 				}
 				status_change_end(src,SC_CRUSHSTRIKE,INVALID_TIMER);
 				skill_break_equip(src,src,EQP_WEAPON,2000,BCT_SELF);

+ 16 - 15
src/map/clif.cpp

@@ -6985,32 +6985,28 @@ void clif_item_damaged(struct map_session_data* sd, unsigned short position)
 void clif_item_refine_list( struct map_session_data *sd ){
 	nullpo_retv( sd );
 
-	int fd = sd->fd;
-
-	if( !session_isActive( fd ) ){
-		return;
-	}
+	struct PACKET_ZC_NOTIFY_WEAPONITEMLIST *p = (struct PACKET_ZC_NOTIFY_WEAPONITEMLIST *)packet_buffer;
 
-	WFIFOHEAD( fd, sizeof( struct PACKET_ZC_NOTIFY_WEAPONITEMLIST ) + sizeof( struct PACKET_ZC_NOTIFY_WEAPONITEMLIST_sub ) * MAX_INVENTORY );
-	struct PACKET_ZC_NOTIFY_WEAPONITEMLIST *p = (struct PACKET_ZC_NOTIFY_WEAPONITEMLIST *)WFIFOP( fd, 0 );
-	p->packetType = 0x221;
+	p->packetType = HEADER_ZC_NOTIFY_WEAPONITEMLIST;
 
 	uint16 skill_lv = pc_checkskill( sd, WS_WEAPONREFINE );
 
-	int refine_item[5];
+	int refine_item[MAX_WEAPON_LEVEL];
 
 	refine_item[0] = -1;
 	refine_item[1] = pc_search_inventory( sd, ITEMID_PHRACON );
 	refine_item[2] = pc_search_inventory( sd, ITEMID_EMVERETARCON );
 	refine_item[3] = refine_item[4] = pc_search_inventory( sd, ITEMID_ORIDECON );
+#ifdef RENEWAL
+	refine_item[5] = -1;
+#endif
 
 	int count = 0;
 	for( int i = 0; i < MAX_INVENTORY; i++ ){
-		uint16 wlv;
-
 		if( sd->inventory.u.items_inventory[i].nameid > 0 && sd->inventory.u.items_inventory[i].refine < skill_lv &&
-			sd->inventory.u.items_inventory[i].identify && ( wlv = itemdb_wlv(sd->inventory.u.items_inventory[i].nameid ) ) >= 1 &&
-			refine_item[wlv] != -1 && !( sd->inventory.u.items_inventory[i].equip & EQP_ARMS ) ){
+			sd->inventory_data[i] != nullptr && sd->inventory_data[i]->type == IT_WEAPON &&
+			sd->inventory.u.items_inventory[i].identify && sd->inventory_data[i]->weapon_level >= 1 &&
+			refine_item[sd->inventory_data[i]->weapon_level] != -1 && !( sd->inventory.u.items_inventory[i].equip & EQP_ARMS ) ){
 
 			p->items[count].index = client_index( i );
 			p->items[count].itemId = client_nameid( sd->inventory.u.items_inventory[i].nameid );
@@ -7021,7 +7017,8 @@ void clif_item_refine_list( struct map_session_data *sd ){
 	}
 
 	p->packetLength = sizeof( struct PACKET_ZC_NOTIFY_WEAPONITEMLIST ) + sizeof( struct PACKET_ZC_NOTIFY_WEAPONITEMLIST_sub ) * count;
-	WFIFOSET( fd, p->packetLength );
+
+	clif_send( p, p->packetLength, &sd->bl, SELF );
 
 	if( count > 0 ){
 		sd->menuskill_id = WS_WEAPONREFINE;
@@ -21993,11 +21990,15 @@ void clif_parse_refineui_refine( int fd, struct map_session_data* sd ){
 
 	// Try to refine the item
 	if( cost->chance >= ( rnd() % 10000 ) ){
+		log_pick_pc( sd, LOG_TYPE_OTHER, -1, item );
 		// Success
 		item->refine = cap_value( item->refine + 1, 0, MAX_REFINE );
+		log_pick_pc( sd, LOG_TYPE_OTHER, 1, item );
 		clif_misceffect( &sd->bl, 3 );
 		clif_refine( fd, 0, index, item->refine );
-		achievement_update_objective( sd, AG_ENCHANT_SUCCESS, 2, id->wlv, item->refine );
+		if( id->type == IT_WEAPON ){
+			achievement_update_objective( sd, AG_ENCHANT_SUCCESS, 2, id->weapon_level, item->refine );
+		}
 		clif_refineui_info( sd, index );
 	}else{
 		// Failure

+ 60 - 4
src/map/itemdb.cpp

@@ -456,18 +456,42 @@ uint64 ItemDatabase::parseBodyNode(const YAML::Node &node) {
 
 		if (lv > MAX_WEAPON_LEVEL) {
 			this->invalidWarning(node["WeaponLevel"], "Invalid weapon level %d, defaulting to 0.\n", lv);
-			lv = REFINE_TYPE_ARMOR;
+			lv = 0;
 		}
 
 		if (item->type != IT_WEAPON) {
 			this->invalidWarning(node["WeaponLevel"], "Item type is not a weapon, defaulting to 0.\n");
-			lv = REFINE_TYPE_ARMOR;
+			lv = 0;
 		}
 
-		item->wlv = lv;
+		item->weapon_level = lv;
 	} else {
 		if (!exists)
-			item->wlv = REFINE_TYPE_ARMOR;
+			item->weapon_level = 0;
+	}
+
+	if( this->nodeExists( node, "ArmorLevel" ) ){
+		uint16 level;
+
+		if( !this->asUInt16( node, "ArmorLevel", level ) ){
+			return 0;
+		}
+
+		if( level > MAX_ARMOR_LEVEL ){
+			this->invalidWarning( node["ArmorLevel"], "Invalid armor level %d, defaulting to 0.\n", level );
+			level = 0;
+		}
+
+		if( item->type != IT_ARMOR ){
+			this->invalidWarning( node["ArmorLevel"], "Item type is not an armor, defaulting to 0.\n" );
+			level = 0;
+		}
+
+		item->armor_level = level;
+	}else{
+		if( !exists ){
+			item->armor_level = 0;
+		}
 	}
 
 	if (this->nodeExists(node, "EquipLevelMin")) {
@@ -1054,6 +1078,38 @@ void ItemDatabase::loadingFinished(){
 			item->flag.delay_consume &= ~DELAYCONSUME_TEMP; // Remove delayed consumption flag if switching types
 		}
 
+		if( item->type == IT_WEAPON ){
+			if( item->weapon_level == 0 ){
+				ShowWarning( "Item %s is a weapon, but does not have a weapon level. Consider adding it. Defaulting to 1.\n", item->name.c_str() );
+				item->weapon_level = 1;
+			}
+
+			if( item->armor_level != 0 ){
+				ShowWarning( "Item %s is a weapon, but has an armor level. Defaulting to 0.\n", item->name.c_str() );
+				item->armor_level = 0;
+			}
+		}else if( item->type == IT_ARMOR ){
+			if( item->armor_level == 0 ){
+				ShowWarning( "Item %s is an armor, but does not have an armor level. Consider adding it. Defaulting to 1.\n", item->name.c_str() );
+				item->armor_level = 1;
+			}
+
+			if( item->weapon_level != 0 ){
+				ShowWarning( "Item %s is an armor, but has a weapon level. Defaulting to 0.\n", item->name.c_str() );
+				item->weapon_level = 0;
+			}
+		}else{
+			if( item->weapon_level != 0 ){
+				ShowWarning( "Item %s is not a weapon, but has a weapon level. Defaulting to 0.\n", item->name.c_str() );
+				item->weapon_level = 0;
+			}
+
+			if( item->armor_level != 0 ){
+				ShowWarning( "Item %s is not an armor, but has an armor level. Defaulting to 0.\n", item->name.c_str() );
+				item->armor_level = 0;
+			}
+		}
+
 		// When a particular price is not given, we should base it off the other one
 		if (item->value_buy == 0 && item->value_sell > 0)
 			item->value_buy = item->value_sell * 2;

+ 4 - 3
src/map/itemdb.hpp

@@ -885,7 +885,8 @@ struct item_data
 	uint16 slots;
 	uint32 look;
 	uint16 elv;
-	uint16 wlv;
+	uint16 weapon_level;
+	uint16 armor_level;
 	t_itemid view_id;
 	uint16 elvmax; ///< Maximum level for this item
 #ifdef RENEWAL
@@ -1030,7 +1031,7 @@ private:
 	e_sex defaultGender( const YAML::Node &node, std::shared_ptr<item_data> id );
 
 public:
-	ItemDatabase() : TypesafeCachedYamlDatabase("ITEM_DB", 1) {
+	ItemDatabase() : TypesafeCachedYamlDatabase("ITEM_DB", 2, 1) {
 
 	}
 
@@ -1085,7 +1086,7 @@ struct item_data* itemdb_exists(t_itemid nameid);
 #define itemdb_equip(n) itemdb_search(n)->equip
 #define itemdb_usescript(n) itemdb_search(n)->script
 #define itemdb_equipscript(n) itemdb_search(n)->script
-#define itemdb_wlv(n) itemdb_search(n)->wlv
+#define itemdb_wlv(n) itemdb_search(n)->weapon_level
 #define itemdb_range(n) itemdb_search(n)->range
 #define itemdb_slots(n) itemdb_search(n)->slots
 #define itemdb_available(n) (itemdb_search(n)->flag.available)

+ 1 - 0
src/map/packets.hpp

@@ -236,6 +236,7 @@ DEFINE_PACKET_HEADER(ZC_SPIRITS, 0x1d0)
 #else
 	DEFINE_PACKET_HEADER(ZC_CHANGE_GUILD, 0x1b4)
 #endif
+DEFINE_PACKET_HEADER(ZC_NOTIFY_WEAPONITEMLIST, 0x221)
 DEFINE_PACKET_HEADER(ZC_ACK_WEAPONREFINE, 0x223)
 DEFINE_PACKET_HEADER(CZ_REQ_MAKINGITEM, 0x25b)
 DEFINE_PACKET_HEADER(ZC_CASH_TIME_COUNTER, 0x298)

+ 1 - 1
src/map/pc.cpp

@@ -1532,7 +1532,7 @@ uint8 pc_isequip(struct map_session_data *sd,int n)
 			if (sd->status.base_level > 90 && item->equip & EQP_HELM)
 				return ITEM_EQUIP_ACK_OK; //Can equip all helms
 
-			if (sd->status.base_level > 96 && item->equip & EQP_ARMS && item->type == IT_WEAPON && item->wlv == 4)
+			if (sd->status.base_level > 96 && item->equip & EQP_ARMS && item->type == IT_WEAPON && item->weapon_level == 4)
 				switch(item->subtype) { //In weapons, the look determines type of weapon.
 					case W_DAGGER: //All level 4 - Daggers
 					case W_1HSWORD: //All level 4 - 1H Swords

+ 111 - 15
src/map/script.cpp

@@ -9185,21 +9185,28 @@ BUILDIN_FUNC(getequiprefinerycnt)
  * return (npc)
  *	x : weapon level
  *	0 : false
- * getequipweaponlv(<equipment slot>{,<char_id>})
+ * getequipweaponlv({<equipment slot>{,<char_id>}})
  *------------------------------------------*/
 BUILDIN_FUNC(getequipweaponlv)
 {
-	int i = -1, num;
-	TBL_PC *sd;
+	int num;
 
-	num = script_getnum(st, 2);
+	if( script_hasdata( st, 2 ) ){
+		num = script_getnum(st, 2);
+	}else{
+		num = EQI_COMPOUND_ON;
+	}
+
+	struct map_session_data* sd;
 
 	if (!script_charid2sd(3, sd)) {
 		script_pushint(st, 0);
 		return SCRIPT_CMD_FAILURE;
 	}
 
-	if (num == -1){
+	int i = -1;
+
+	if( num == EQI_COMPOUND_ON ){
 		if( current_equip_item_index == -1 ){
 			script_pushint(st, 0);
 			return SCRIPT_CMD_FAILURE;
@@ -9208,10 +9215,53 @@ BUILDIN_FUNC(getequipweaponlv)
 		i = current_equip_item_index;
 	}else if (equip_index_check(num))
 		i = pc_checkequip(sd, equip_bitmask[num]);
-	if (i >= 0 && sd->inventory_data[i])
-		script_pushint(st, sd->inventory_data[i]->wlv);
-	else
-		script_pushint(st, 0);
+	if( i >= 0 && sd->inventory_data[i] && sd->inventory_data[i]->type == IT_WEAPON ){
+		script_pushint( st, sd->inventory_data[i]->weapon_level );
+	}else{
+		script_pushint( st, 0 );
+	}
+
+	return SCRIPT_CMD_SUCCESS;
+}
+
+BUILDIN_FUNC(getequiparmorlv){
+	int num;
+
+	if( script_hasdata( st, 2 ) ){
+		num = script_getnum(st, 2);
+	}else{
+		num = EQI_COMPOUND_ON;
+	}
+
+	struct map_session_data* sd;
+
+	if( !script_charid2sd( 3, sd ) ){
+		script_pushint( st, 0 );
+		return SCRIPT_CMD_FAILURE;
+	}
+
+	int i = -1;
+
+	if( num == EQI_COMPOUND_ON ){
+		if( current_equip_item_index == -1 ){
+			script_pushint( st, 0 );
+			return SCRIPT_CMD_FAILURE;
+		}
+
+		i = current_equip_item_index;
+	}else if( equip_index_check( num ) ){
+		i = pc_checkequip( sd, equip_bitmask[num] );
+	}else{
+		ShowError( "buildin_getequiparmorlv: unsupported equip index %d.\n", num );
+		script_pushint( st, 0 );
+		return SCRIPT_CMD_FAILURE;
+	}
+
+	if( i >= 0 && sd->inventory_data[i] && sd->inventory_data[i]->type == IT_ARMOR ){
+		script_pushint( st, sd->inventory_data[i]->armor_level );
+	}else{
+		script_pushint( st, 0 );
+	}
 
 	return SCRIPT_CMD_SUCCESS;
 }
@@ -9308,12 +9358,15 @@ BUILDIN_FUNC(successrefitem) {
 		clif_additem(sd,i,1,0);
 		pc_equipitem(sd,i,ep);
 		clif_misceffect(&sd->bl,3);
-		achievement_update_objective(sd, AG_ENCHANT_SUCCESS, 2, sd->inventory_data[i]->wlv, sd->inventory.u.items_inventory[i].refine);
+		if( sd->inventory_data[i]->type == IT_WEAPON ){
+			achievement_update_objective(sd, AG_ENCHANT_SUCCESS, 2, sd->inventory_data[i]->weapon_level, sd->inventory.u.items_inventory[i].refine);
+		}
 		if (sd->inventory.u.items_inventory[i].refine == battle_config.blacksmith_fame_refine_threshold &&
 			sd->inventory.u.items_inventory[i].card[0] == CARD0_FORGE &&
-			sd->status.char_id == (int)MakeDWord(sd->inventory.u.items_inventory[i].card[2],sd->inventory.u.items_inventory[i].card[3]))
+			sd->status.char_id == (int)MakeDWord(sd->inventory.u.items_inventory[i].card[2],sd->inventory.u.items_inventory[i].card[3]) &&
+			sd->inventory_data[i]->type == IT_WEAPON )
 		{ // Fame point system [DracoRPG]
-			switch (sd->inventory_data[i]->wlv){
+			switch( sd->inventory_data[i]->weapon_level ){
 				case 1:
 					pc_addfame(sd, battle_config.fame_refine_lv1); // Success to refine to +10 a lv1 weapon you forged = +1 fame point
 					break;
@@ -14064,7 +14117,20 @@ BUILDIN_FUNC(getiteminfo)
 			}
 			break;
 		case ITEMINFO_EQUIPLEVELMIN: script_pushint(st, i_data->elv); break;
-		case ITEMINFO_WEAPONLEVEL: script_pushint(st, i_data->wlv); break;
+		case ITEMINFO_WEAPONLEVEL:
+			if( i_data->type == IT_WEAPON ){
+				script_pushint( st, i_data->weapon_level );
+			}else{
+				script_pushint( st, 0 );
+			}
+			break;
+		case ITEMINFO_ARMORLEVEL:
+			if( i_data->type == IT_ARMOR ){
+				script_pushint( st, i_data->armor_level );
+			}else{
+				script_pushint( st, 0 );
+			}
+			break;
 		case ITEMINFO_ALIASNAME: script_pushint(st, i_data->view_id); break;
 		case ITEMINFO_EQUIPLEVELMAX: script_pushint(st, i_data->elvmax); break;
 		case ITEMINFO_MAGICATTACK: {
@@ -14123,7 +14189,36 @@ BUILDIN_FUNC(setiteminfo)
 			}
 			break;
 		case ITEMINFO_EQUIPLEVELMIN: i_data->elv = static_cast<uint16>(value); break;
-		case ITEMINFO_WEAPONLEVEL: i_data->wlv = static_cast<uint16>(value); break;
+		case ITEMINFO_WEAPONLEVEL:
+			if( i_data->type == IT_WEAPON ){
+				if( value > MAX_WEAPON_LEVEL ){
+					ShowError( "buildin_setiteminfo: weapon level %d is above maximum %d.\n", value, MAX_WEAPON_LEVEL );
+					script_pushint( st, -1 );
+					return SCRIPT_CMD_FAILURE;
+				}
+
+				i_data->weapon_level = static_cast<uint16>(value);
+				break;
+			}else{
+				ShowError( "buildin_setiteminfo: Can not set a weapon level for %d.\n", i_data->nameid );
+				script_pushint( st, -1 );
+				return SCRIPT_CMD_FAILURE;
+			}
+		case ITEMINFO_ARMORLEVEL:
+			if( i_data->type == IT_ARMOR ){
+				if( value > MAX_ARMOR_LEVEL ){
+					ShowError( "buildin_setiteminfo: armor level %d is above maximum %d.\n", value, MAX_ARMOR_LEVEL );
+					script_pushint( st, -1 );
+					return SCRIPT_CMD_FAILURE;
+				}
+
+				i_data->armor_level = static_cast<uint16>(value);
+				break;
+			}else{
+				ShowError( "buildin_setiteminfo: Can not set an armor level for %d.\n", i_data->nameid );
+				script_pushint( st, -1 );
+				return SCRIPT_CMD_FAILURE;
+			}
 		case ITEMINFO_ALIASNAME: i_data->view_id = static_cast<t_itemid>(value); break;
 		case ITEMINFO_EQUIPLEVELMAX: i_data->elvmax = static_cast<uint16>(value); break;
 		case ITEMINFO_MAGICATTACK: {
@@ -25289,7 +25384,8 @@ struct script_function buildin_func[] = {
 	BUILDIN_DEF(getequipisequiped,"i?"),
 	BUILDIN_DEF(getequipisenableref,"i?"),
 	BUILDIN_DEF(getequiprefinerycnt,"i?"),
-	BUILDIN_DEF(getequipweaponlv,"i?"),
+	BUILDIN_DEF(getequipweaponlv,"??"),
+	BUILDIN_DEF(getequiparmorlv, "??"),
 	BUILDIN_DEF(getequippercentrefinery,"i?"),
 	BUILDIN_DEF(successrefitem,"i??"),
 	BUILDIN_DEF(failedrefitem,"i?"),

+ 2 - 1
src/map/script.hpp

@@ -2056,7 +2056,8 @@ enum e_iteminfo : uint8 {
 	ITEMINFO_EQUIPLEVELMAX,
 	ITEMINFO_MAGICATTACK,
 	ITEMINFO_ID,
-	ITEMINFO_AEGISNAME	// 18
+	ITEMINFO_AEGISNAME,	// 18
+	ITEMINFO_ARMORLEVEL,
 };
 
 class ConstantDatabase : public YamlDatabase {

+ 67 - 20
src/map/skill.cpp

@@ -7108,7 +7108,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 				short index = dstsd->equip_index[EQI_HAND_R];
 
 				if (index >= 0 && dstsd->inventory_data[index] && dstsd->inventory_data[index]->type == IT_WEAPON)
-					bonus = (20 * skill_lv) * dstsd->inventory_data[index]->wlv;
+					bonus = (20 * skill_lv) * dstsd->inventory_data[index]->weapon_level;
 			}
 
 			clif_skill_nodamage(src, bl, skill_id, skill_lv, sc_start2(src,bl, type, 100, skill_lv, bonus, skill_get_time(skill_id, skill_lv)));
@@ -17413,7 +17413,22 @@ int skill_delayfix(struct block_list *bl, uint16 skill_id, uint16 skill_lv)
  * Weapon Repair [Celest/DracoRPG]
  *------------------------------------------*/
 void skill_repairweapon(struct map_session_data *sd, int idx) {
-	t_itemid material, materials[4] = { ITEMID_IRON_ORE, ITEMID_IRON, ITEMID_STEEL, ITEMID_ORIDECON_STONE };
+	static const t_itemid weapon_materials[MAX_WEAPON_LEVEL] = {
+		ITEMID_IRON_ORE,
+		ITEMID_IRON,
+		ITEMID_STEEL,
+		ITEMID_ORIDECON_STONE,
+#ifdef RENEWAL
+		0
+#endif
+	};
+	static const t_itemid armor_materials[MAX_ARMOR_LEVEL] = {
+		ITEMID_STEEL,
+#ifdef RENEWAL
+		0
+#endif
+	};
+	t_itemid material = 0;
 	struct item *item;
 	struct map_session_data *target_sd;
 
@@ -17439,11 +17454,13 @@ void skill_repairweapon(struct map_session_data *sd, int idx) {
 		return;
 	}
 
-	if ( target_sd->inventory_data[idx]->type == IT_WEAPON )
-		material = materials [ target_sd->inventory_data[idx]->wlv - 1 ]; // Lv1/2/3/4 weapons consume 1 Iron Ore/Iron/Steel/Rough Oridecon
-	else
-		material = materials [2]; // Armors consume 1 Steel
-	if ( pc_search_inventory(sd,material) < 0 ) {
+	if( target_sd->inventory_data[idx]->type == IT_WEAPON ){
+		material = weapon_materials[target_sd->inventory_data[idx]->weapon_level - 1];
+	}else if( target_sd->inventory_data[idx]->type == IT_ARMOR ){
+		material = armor_materials[target_sd->inventory_data[idx]->armor_level - 1];
+	}
+
+	if( material == 0 || pc_search_inventory( sd, material ) < 0 ){
 		clif_skill_fail(sd,sd->menuskill_id,USESKILL_FAIL_LEVEL,0);
 		return;
 	}
@@ -17487,6 +17504,16 @@ void skill_identify(struct map_session_data *sd, int idx)
  *------------------------------------------*/
 void skill_weaponrefine(struct map_session_data *sd, int idx)
 {
+	static const t_itemid material[MAX_WEAPON_LEVEL] = {
+		ITEMID_PHRACON,
+		ITEMID_EMVERETARCON,
+		ITEMID_ORIDECON,
+		ITEMID_ORIDECON,
+#ifdef RENEWAL
+		0
+#endif
+	};
+
 	nullpo_retv(sd);
 
 	if (idx >= 0 && idx < MAX_INVENTORY)
@@ -17496,9 +17523,7 @@ void skill_weaponrefine(struct map_session_data *sd, int idx)
 		item = &sd->inventory.u.items_inventory[idx];
 
 		if(item->nameid > 0 && ditem->type == IT_WEAPON) {
-			int i = 0, per;
-			t_itemid material[5] = { 0, ITEMID_PHRACON, ITEMID_EMVERETARCON, ITEMID_ORIDECON, ITEMID_ORIDECON };
-			if( ditem->flag.no_refine ) { 	// if the item isn't refinable
+			if( ditem->flag.no_refine || ditem->weapon_level < 1 ) { 	// if the item isn't refinable
 				clif_skill_fail(sd,sd->menuskill_id,USESKILL_FAIL_LEVEL,0);
 				return;
 			}
@@ -17506,8 +17531,11 @@ void skill_weaponrefine(struct map_session_data *sd, int idx)
 				clif_upgrademessage(sd, 2, item->nameid);
 				return;
 			}
-			if( (i = pc_search_inventory(sd, material [ditem->wlv])) < 0 ) {
-				clif_upgrademessage(sd, 3, material[ditem->wlv]);
+
+			int i = pc_search_inventory( sd, material[ditem->weapon_level - 1] );
+
+			if( i < 0 ) {
+				clif_upgrademessage( sd, 3, material[ditem->weapon_level - 1] );
 				return;
 			}
 
@@ -17525,12 +17553,13 @@ void skill_weaponrefine(struct map_session_data *sd, int idx)
 				return;
 			}
 
-			if( cost->nameid != material[ditem->wlv] ){
+			if( cost->nameid != material[ditem->weapon_level - 1] ){
+				ShowDebug( "skill_weaponrefine: The hardcoded refine requirement %d for weapon level %d does not match %d from the refine database.\n", material[ditem->weapon_level - 1], ditem->weapon_level, cost->nameid );
 				clif_skill_fail( sd, sd->menuskill_id, USESKILL_FAIL_LEVEL, 0 );
 				return;
 			}
 
-			per = ( cost->chance / 100 );
+			int per = ( cost->chance / 100 );
 			if( sd->class_&JOBL_THIRD )
 				per += 10;
 			else
@@ -17550,7 +17579,9 @@ void skill_weaponrefine(struct map_session_data *sd, int idx)
 				clif_upgrademessage(sd, 0, item->nameid);
 				clif_inventorylist(sd);
 				clif_refine(sd->fd,0,idx,item->refine);
-				achievement_update_objective(sd, AG_ENCHANT_SUCCESS, 2, ditem->wlv, item->refine);
+				if( ditem->type == IT_WEAPON ){
+					achievement_update_objective(sd, AG_ENCHANT_SUCCESS, 2, ditem->weapon_level, item->refine);
+				}
 				if (ep)
 					pc_equipitem(sd,idx,ep);
 				clif_misceffect(&sd->bl,3);
@@ -17558,7 +17589,7 @@ void skill_weaponrefine(struct map_session_data *sd, int idx)
 					item->card[0] == CARD0_FORGE &&
 					(int)MakeDWord(item->card[2],item->card[3]) == sd->status.char_id)
 				{ // Fame point system [DracoRPG]
-					switch(ditem->wlv){
+					switch(ditem->weapon_level){
 						case 1:
 							pc_addfame(sd, battle_config.fame_refine_lv1); // Success to refine to +10 a lv1 weapon you forged = +1 fame point
 							break;
@@ -19806,8 +19837,10 @@ bool skill_produce_mix(struct map_session_data *sd, uint16 skill_id, t_itemid na
 		} while( j >= 0 && x > 0 );
 	}
 
-	if ((equip = (itemdb_isequip(nameid) && skill_id != GN_CHANGEMATERIAL && skill_id != GN_MAKEBOMB  )))
+	if ((equip = (itemdb_isequip(nameid) && skill_id != GN_CHANGEMATERIAL && skill_id != GN_MAKEBOMB)) && itemdb_type(nameid) == IT_WEAPON )
 		wlv = itemdb_wlv(nameid);
+	else
+		wlv = 0;
 
 	if (!equip) {
 		switch (skill_id) {
@@ -20068,8 +20101,22 @@ bool skill_produce_mix(struct map_session_data *sd, uint16 skill_id, t_itemid na
 	} else { // Weapon Forging - skill bonuses are straight from kRO website, other things from a jRO calculator [DracoRPG]
 		make_per = 5000 + ((sd->class_&JOBL_THIRD)?1400:sd->status.job_level*20) + status->dex*10 + status->luk*10; // Base
 		make_per += pc_checkskill(sd,skill_id)*500; // Smithing skills bonus: +5/+10/+15
-		make_per += pc_checkskill(sd,BS_WEAPONRESEARCH)*100 +((wlv >= 3)? pc_checkskill(sd,BS_ORIDEOCON)*100:0); // Weaponry Research bonus: +1/+2/+3/+4/+5/+6/+7/+8/+9/+10, Oridecon Research bonus (custom): +1/+2/+3/+4/+5
-		make_per -= (ele?2000:0) + sc*1500 + (wlv>1?wlv*1000:0); // Element Stone: -20%, Star Crumb: -15% each, Weapon level malus: -0/-20/-30
+		// Weaponry Research bonus: +1/+2/+3/+4/+5/+6/+7/+8/+9/+10
+		make_per += pc_checkskill(sd,BS_WEAPONRESEARCH)*100;
+		//  Oridecon Research bonus (custom): +1/+2/+3/+4/+5
+		if( wlv >= 3 ){
+			make_per += pc_checkskill(sd, BS_ORIDEOCON) * 100;
+		}
+		// Element Stone: -20%
+		if( ele ){
+			make_per -= 2000;
+		}
+		// Star Crumb: -15% each
+		make_per -= sc * 1500;
+		//  Weapon level malus: -0/-10/-20/-30
+		if( wlv > 1 ){
+			make_per -= ( wlv * 1000 );
+		}
 		if      (pc_search_inventory(sd,ITEMID_EMPERIUM_ANVIL) > -1) make_per+= 1000; // Emperium Anvil: +10
 		else if (pc_search_inventory(sd,ITEMID_GOLDEN_ANVIL) > -1)   make_per+= 500; // Golden Anvil: +5
 		else if (pc_search_inventory(sd,ITEMID_ORIDECON_ANVIL) > -1) make_per+= 300; // Oridecon Anvil: +3
@@ -20138,7 +20185,7 @@ bool skill_produce_mix(struct map_session_data *sd, uint16 skill_id, t_itemid na
 		if (equip) {
 			clif_produceeffect(sd,0,nameid);
 			clif_misceffect(&sd->bl,3);
-			if (itemdb_wlv(nameid) >= 3 && ((ele? 1 : 0) + sc) >= 3) // Fame point system [DracoRPG]
+			if (wlv >= 3 && ((ele? 1 : 0) + sc) >= 3) // Fame point system [DracoRPG]
 				pc_addfame(sd, battle_config.fame_forge); // Success to forge a lv3 weapon with 3 additional ingredients = +10 fame point
 		} else {
 			int fame = 0;

+ 5 - 6
src/map/status.cpp

@@ -417,13 +417,12 @@ std::shared_ptr<s_refine_level_info> RefineDatabase::findCurrentLevelInfo( const
 bool RefineDatabase::calculate_refine_info( const struct item_data& data, e_refine_type& refine_type, uint16& level ){
 	if( data.type == IT_WEAPON ){
 		refine_type = REFINE_TYPE_WEAPON;
-		level = data.wlv;
+		level = data.weapon_level;
 
 		return true;
 	}else if( data.type == IT_ARMOR ){
 		refine_type = REFINE_TYPE_ARMOR;
-		// TODO: implement when armor level is supported
-		level = 1;
+		level = data.armor_level;
 
 		return true;
 	}else if( data.type == IT_SHADOWGEAR ){
@@ -4304,7 +4303,7 @@ int status_calc_pc_sub(struct map_session_data* sd, enum e_status_calc_opt opt)
 		std::shared_ptr<s_refine_level_info> info = refine_db.findCurrentLevelInfo( *sd->inventory_data[index], sd->inventory.u.items_inventory[index] );
 
 		if (sd->inventory_data[index]->type == IT_WEAPON) {
-			int wlv = sd->inventory_data[index]->wlv;
+			int wlv = sd->inventory_data[index]->weapon_level;
 			struct weapon_data *wd;
 			struct weapon_atk *wa;
 
@@ -6919,7 +6918,7 @@ static unsigned short status_calc_watk(struct block_list *bl, struct status_chan
 			TBL_PC *sd = (TBL_PC*)bl;
 			short index = sd->equip_index[sd->state.lr_flag?EQI_HAND_L:EQI_HAND_R];
 
-			if(index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->wlv == 4)
+			if(index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_WEAPON && sd->inventory_data[index]->weapon_level == 4)
 				watk += sc->data[SC_NIBELUNGEN]->val2;
 		}
 	}
@@ -11907,7 +11906,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
 				short index = sd->equip_index[EQI_HAND_R];
 
 				if (index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_WEAPON)
-					val2 += 15 * sd->status.job_level + sd->inventory_data[index]->weight / 10 * sd->inventory_data[index]->wlv * status_get_lv(bl) / 100;
+					val2 += 15 * sd->status.job_level + sd->inventory_data[index]->weight / 10 * sd->inventory_data[index]->weapon_level * status_get_lv(bl) / 100;
 			} else // Monster
 				val2 += 750;
 			break;

+ 2 - 2
src/tool/csv2yaml.cpp

@@ -274,14 +274,14 @@ int do_init( int argc, char** argv ){
 	}
 
 	item_txt_data(path_db_mode, path_db);
-	if (!process("ITEM_DB", 1, { path_db_mode }, "item_db", [](const std::string& path, const std::string& name_ext) -> bool {
+	if (!process("ITEM_DB", 2, { path_db_mode }, "item_db", [](const std::string& path, const std::string& name_ext) -> bool {
 		return itemdb_read_db((path + name_ext).c_str());
 	})) {
 		return 0;
 	}
 
 	item_txt_data(path_db_import, path_db_import);
-	if (!process("ITEM_DB", 1, { path_db_import }, "item_db", [](const std::string& path, const std::string& name_ext) -> bool {
+	if (!process("ITEM_DB", 2, { path_db_import }, "item_db", [](const std::string& path, const std::string& name_ext) -> bool {
 		return itemdb_read_db((path + name_ext).c_str());
 	})) {
 		return 0;

+ 2 - 0
src/tool/yaml2sql.cpp

@@ -607,6 +607,8 @@ static bool item_db_yaml2sql(const std::string &file, const std::string &table)
 
 		if (appendEntry(input["WeaponLevel"], value))
 			column.append("`weapon_level`,");
+		if (appendEntry(input["ArmorLevel"], value))
+			column.append("`armor_level`,");
 		if (appendEntry(input["EquipLevelMin"], value))
 			column.append("`equip_level_min`,");
 		if (appendEntry(input["EquipLevelMax"], value))

+ 29 - 0
src/tool/yamlupgrade.cpp

@@ -4,6 +4,7 @@
 #include "yamlupgrade.hpp"
 
 static bool upgrade_achievement_db(std::string file, const uint32 source_version);
+static bool upgrade_item_db(std::string file, const uint32 source_version);
 
 template<typename Func>
 bool process(const std::string &type, uint32 version, const std::vector<std::string> &paths, const std::string &name, Func lambda) {
@@ -108,6 +109,12 @@ int do_init(int argc, char** argv) {
 		return 0;
 	}
 
+	if (!process("ITEM_DB", 2, root_paths, "item_db", [](const std::string& path, const std::string& name_ext, uint32 source_version) -> bool {
+		return upgrade_item_db(path + name_ext, source_version);
+		})) {
+		return 0;
+	}
+
 	return 0;
 }
 
@@ -219,3 +226,25 @@ static bool upgrade_achievement_db(std::string file, const uint32 source_version
 
 	return true;
 }
+
+static bool upgrade_item_db(std::string file, const uint32 source_version) {
+	size_t entries = 0;
+
+	for( auto &input : inNode["Body"] ){
+		// If under version 2
+		if( source_version < 2 ){
+			// Add armor level to all equipments
+			if( input["Type"].IsDefined() && input["Type"].as<std::string>() == "Armor" ){
+				input["ArmorLevel"] = 1;
+			}
+		}
+
+		// TODO: this currently converts all scripts using Literal syntax to normal double quote strings
+		body << input;
+		entries++;
+	}
+
+	ShowStatus("Done converting/upgrading '" CL_WHITE "%d" CL_RESET "' items in '" CL_WHITE "%s" CL_RESET "'.\n", entries, file.c_str());
+
+	return true;
+}

部分文件因为文件数量过多而无法显示