From 304efb8ec9d6de6fce3f11d6b30d5a72332962e6 Mon Sep 17 00:00:00 2001 From: Beats <61994374+Beats-Dh@users.noreply.github.com> Date: Tue, 23 Nov 2021 15:30:45 -0400 Subject: [PATCH] Decouple "ParseItem Attributes" in it own file (#140) ItemParse has been refactored and decoupled in a own file to allow for better organization and avoid breakage in the compilation Fixed some bugs, such as fields in items.xml This commit is necessary for the pull request (12.72 protocol) to work correctly: #143 Co-authored-by @dudantas --- data/events/scripts/player.lua | 23 +- data/global.lua | 7 + data/items/items.xml | 1122 +++++++++++++++------------- src/CMakeLists.txt | 1 + src/items/functions/item_parse.cpp | 816 ++++++++++++++++++++ src/items/functions/item_parse.hpp | 291 ++++++++ src/items/item.cpp | 1 + src/items/item.h | 6 +- src/items/items.cpp | 582 +-------------- src/items/items.h | 5 +- src/items/items_definitions.hpp | 115 +++ 11 files changed, 1880 insertions(+), 1089 deletions(-) create mode 100644 src/items/functions/item_parse.cpp create mode 100644 src/items/functions/item_parse.hpp diff --git a/data/events/scripts/player.lua b/data/events/scripts/player.lua index a86b937e71b..39bb5ffbc4f 100644 --- a/data/events/scripts/player.lua +++ b/data/events/scripts/player.lua @@ -6,10 +6,10 @@ function Player:onLook(thing, position, distance) local description = "You see " description = description .. thing:getDescription(distance) if thing:isItem() then - local item = thing:getType() - if (item and item:getImbuingSlots() > 0) then + local itemType = thing:getType() + if (itemType and itemType:getImbuingSlots() > 0) then local imbuingSlots = "Imbuements: (" - for slot = 0, item:getImbuingSlots() - 1 do + for slot = 0, itemType:getImbuingSlots() - 1 do if slot > 0 then imbuingSlots = string.format("%s, ", imbuingSlots) end @@ -25,6 +25,13 @@ function Player:onLook(thing, position, distance) imbuingSlots = string.format("%s).", imbuingSlots) description = string.gsub(description, "It weighs", imbuingSlots.. "\nIt weighs") end + elseif thing:isMonster() then + description = description .. thing:getDescription(distance) + local master = thing:getMaster() + if master and table.contains(FAMILIARSNAME, thing:getName():lower()) then + description = description..' (Master: ' .. master:getName() .. '). \z + It will disappear in ' .. getTimeinWords(master:getStorageValue(Storage.PetSummon) - os.time()) + end end if self:getGroup():getAccess() then @@ -41,18 +48,18 @@ function Player:onLook(thing, position, distance) description = string.format("%s, Unique ID: %d", description, uniqueId) end - local item = thing:getType() + local itemType = thing:getType() - if item then - local transformEquipId = item:getTransformEquipId() - local transformDeEquipId = item:getTransformDeEquipId() + if itemType then + local transformEquipId = itemType:getTransformEquipId() + local transformDeEquipId = itemType:getTransformDeEquipId() if transformEquipId ~= 0 then description = string.format("%s\nTransforms to: %d (onEquip)", description, transformEquipId) elseif transformDeEquipId ~= 0 then description = string.format("%s\nTransforms to: %d (onDeEquip)", description, transformDeEquipId) end - local decayId = item:getDecayId() + local decayId = itemType:getDecayId() if decayId ~= -1 then description = string.format("%s\nDecays to: %d", description, decayId) end diff --git a/data/global.lua b/data/global.lua index 0d7b07e03b2..5c1926bb170 100644 --- a/data/global.lua +++ b/data/global.lua @@ -161,6 +161,13 @@ staminaBonus = { eventsPz = {} -- stamina in Pz } +FAMILIARSNAME = { + "sorcerer familiar", + "knight familiar", + "druid familiar", + "paladin familiar" +} + function addStamina(playerId, ...) -- Creature:onTargetCombat if playerId then diff --git a/data/items/items.xml b/data/items/items.xml index f4468f863d1..c8e5dd0430e 100644 --- a/data/items/items.xml +++ b/data/items/items.xml @@ -32,7 +32,11 @@ - + + + + + @@ -1401,7 +1405,7 @@ - + @@ -1445,7 +1449,7 @@ - + @@ -1453,7 +1457,7 @@ - + @@ -1461,7 +1465,7 @@ - + @@ -2375,7 +2379,12 @@ - + + + + + + @@ -2469,13 +2478,21 @@ - + + + + + - + + + + + @@ -2486,23 +2503,40 @@ - + + + + + - + + + + + - + + + + + + - + + + + + @@ -2512,7 +2546,11 @@ - + + + + + @@ -2536,7 +2574,11 @@ - + + + + + @@ -2548,13 +2590,21 @@ - + + + + + - + + + + + @@ -2565,14 +2615,18 @@ - + + + - + + + @@ -3614,7 +3668,7 @@ - + @@ -3668,49 +3722,49 @@ - + - + - + - + - + - + - + - + @@ -4180,7 +4234,7 @@ - + @@ -4349,7 +4403,7 @@ - + @@ -4437,7 +4491,7 @@ - + @@ -4453,7 +4507,7 @@ - + @@ -4639,7 +4693,7 @@ - + @@ -5026,9 +5080,9 @@ - + - + @@ -5180,7 +5234,7 @@ - + @@ -5215,7 +5269,7 @@ - + @@ -5254,7 +5308,7 @@ - + @@ -5302,7 +5356,7 @@ - + @@ -5360,7 +5414,7 @@ - + @@ -5378,7 +5432,7 @@ - + @@ -5430,7 +5484,7 @@ - + @@ -5476,7 +5530,7 @@ - + @@ -5523,7 +5577,7 @@ - + @@ -5532,7 +5586,7 @@ - + @@ -5541,7 +5595,7 @@ - + @@ -5582,7 +5636,7 @@ - + @@ -5596,7 +5650,7 @@ - + @@ -5605,7 +5659,7 @@ - + @@ -5627,7 +5681,7 @@ - + @@ -5641,7 +5695,7 @@ - + @@ -5649,7 +5703,7 @@ - + @@ -5658,7 +5712,7 @@ - + @@ -5691,7 +5745,7 @@ - + @@ -5700,7 +5754,7 @@ - + @@ -5713,7 +5767,7 @@ - + @@ -5746,7 +5800,7 @@ - + @@ -5755,7 +5809,7 @@ - + @@ -5763,7 +5817,7 @@ - + @@ -5778,7 +5832,7 @@ - + @@ -5806,7 +5860,7 @@ - + @@ -5815,7 +5869,7 @@ - + @@ -5824,7 +5878,7 @@ - + @@ -5832,7 +5886,7 @@ - + @@ -5848,7 +5902,7 @@ - + @@ -5886,7 +5940,7 @@ - + @@ -5904,7 +5958,7 @@ - + @@ -5935,7 +5989,7 @@ - + @@ -5946,7 +6000,7 @@ - + @@ -5973,13 +6027,13 @@ - + - + @@ -5996,13 +6050,13 @@ - + - + @@ -6053,13 +6107,13 @@ - + - + @@ -6080,26 +6134,26 @@ - + - + - + - + @@ -6115,27 +6169,27 @@ - + - + - + - + @@ -6147,14 +6201,14 @@ - + - + @@ -6166,7 +6220,7 @@ - + @@ -6193,7 +6247,7 @@ - + @@ -6214,13 +6268,13 @@ - + - + @@ -6247,7 +6301,7 @@ - + @@ -6258,7 +6312,7 @@ - + @@ -6270,20 +6324,20 @@ - + - + - + @@ -6295,7 +6349,7 @@ - + @@ -6308,7 +6362,7 @@ - + @@ -6329,7 +6383,7 @@ - + @@ -6346,7 +6400,7 @@ - + @@ -6357,32 +6411,32 @@ - + - + - + - + - + @@ -6394,7 +6448,7 @@ - + @@ -6410,7 +6464,7 @@ - + @@ -6421,7 +6475,7 @@ - + @@ -6698,43 +6752,43 @@ - + - + - + - + - + - + - + @@ -6792,7 +6846,7 @@ - + @@ -6823,7 +6877,7 @@ - + @@ -7422,7 +7476,7 @@ - + @@ -10251,7 +10305,7 @@ - + @@ -10711,7 +10765,7 @@ - + @@ -10804,7 +10858,7 @@ - + @@ -11068,7 +11122,7 @@ - + @@ -11170,7 +11224,7 @@ - + @@ -12826,7 +12880,7 @@ - + @@ -12845,7 +12899,7 @@ - + @@ -13008,7 +13062,7 @@ - + @@ -13108,7 +13162,7 @@ - + @@ -13946,7 +14000,7 @@ - + @@ -14121,7 +14175,7 @@ - + @@ -14136,7 +14190,7 @@ - + @@ -14144,7 +14198,7 @@ - + @@ -14153,7 +14207,7 @@ - + @@ -14161,7 +14215,7 @@ - + @@ -14192,7 +14246,7 @@ - + @@ -14208,7 +14262,7 @@ - + @@ -14217,7 +14271,7 @@ - + @@ -14252,7 +14306,7 @@ - + @@ -14260,7 +14314,7 @@ - + @@ -14268,7 +14322,7 @@ - + @@ -14276,7 +14330,7 @@ - + @@ -14285,7 +14339,7 @@ - + @@ -14293,7 +14347,7 @@ - + @@ -14301,7 +14355,7 @@ - + @@ -14315,7 +14369,7 @@ - + @@ -14329,7 +14383,7 @@ - + @@ -14346,7 +14400,7 @@ - + @@ -14355,7 +14409,7 @@ - + @@ -14363,7 +14417,7 @@ - + @@ -14371,7 +14425,7 @@ - + @@ -14379,7 +14433,7 @@ - + @@ -14387,7 +14441,7 @@ - + @@ -14401,7 +14455,7 @@ - + @@ -14416,7 +14470,7 @@ - + @@ -14424,7 +14478,7 @@ - + @@ -14439,7 +14493,7 @@ - + @@ -14464,7 +14518,7 @@ - + @@ -14472,7 +14526,7 @@ - + @@ -14480,7 +14534,7 @@ - + @@ -14503,7 +14557,7 @@ - + @@ -14511,7 +14565,7 @@ - + @@ -14526,7 +14580,7 @@ - + @@ -14536,7 +14590,7 @@ - + @@ -14591,7 +14645,7 @@ - + @@ -14599,7 +14653,7 @@ - + @@ -14607,7 +14661,7 @@ - + @@ -14622,14 +14676,14 @@ - + - + @@ -14637,14 +14691,14 @@ - + - + @@ -14656,7 +14710,7 @@ - + @@ -14673,7 +14727,7 @@ - + @@ -14684,7 +14738,9 @@ - + + + @@ -15204,7 +15260,7 @@ - + @@ -15257,7 +15313,7 @@ - + @@ -15266,7 +15322,7 @@ - + @@ -15276,7 +15332,7 @@ - + @@ -15286,7 +15342,7 @@ - + @@ -15295,7 +15351,7 @@ - + @@ -15305,7 +15361,7 @@ - + @@ -15315,7 +15371,7 @@ - + @@ -15332,7 +15388,7 @@ - + @@ -15396,13 +15452,13 @@ - + - + @@ -15516,7 +15572,7 @@ - + @@ -15537,50 +15593,50 @@ - + - + - + - + - + - + - + - + - + @@ -15634,7 +15690,7 @@ - + @@ -15642,7 +15698,7 @@ - + @@ -15655,7 +15711,7 @@ - + @@ -15668,7 +15724,7 @@ - + @@ -15676,7 +15732,7 @@ - + @@ -15684,7 +15740,7 @@ - + @@ -15697,7 +15753,7 @@ - + @@ -15705,7 +15761,7 @@ - + @@ -15713,7 +15769,7 @@ - + @@ -15728,7 +15784,7 @@ - + @@ -15736,7 +15792,7 @@ - + @@ -15744,7 +15800,7 @@ - + @@ -15752,7 +15808,7 @@ - + @@ -16596,7 +16652,7 @@ - + @@ -16620,8 +16676,8 @@ - - + + @@ -17020,7 +17076,7 @@ - + @@ -17377,8 +17433,8 @@ - - + + @@ -18010,7 +18066,7 @@ - + @@ -18024,7 +18080,7 @@ - + @@ -18045,7 +18101,7 @@ - + @@ -18054,35 +18110,35 @@ - + - + - + - + - + @@ -18417,13 +18473,13 @@ - + - + @@ -18434,13 +18490,13 @@ - + - + @@ -18586,7 +18642,7 @@ - + @@ -18867,17 +18923,32 @@ - + + + + + + - + + + + + + - + + + + + + @@ -18981,7 +19052,7 @@ - + @@ -18989,13 +19060,13 @@ - + - + @@ -19247,13 +19318,13 @@ - + - + @@ -19266,13 +19337,13 @@ - + - + @@ -19361,7 +19432,7 @@ - + @@ -19511,14 +19582,14 @@ - + - + @@ -19532,7 +19603,7 @@ - + @@ -19547,7 +19618,7 @@ - + @@ -19562,7 +19633,7 @@ - + @@ -19635,7 +19706,7 @@ - + @@ -19814,9 +19885,9 @@ - + - + @@ -20769,7 +20840,7 @@ - + @@ -20804,7 +20875,7 @@ - + @@ -20883,7 +20954,7 @@ - + @@ -20945,7 +21016,7 @@ - + @@ -20954,7 +21025,7 @@ - + @@ -20962,7 +21033,7 @@ - + @@ -20972,7 +21043,7 @@ - + @@ -20982,7 +21053,7 @@ - + @@ -20990,7 +21061,7 @@ - + @@ -23401,7 +23472,7 @@ - + @@ -23410,7 +23481,7 @@ - + @@ -23433,15 +23504,15 @@ - + - + - + @@ -23456,14 +23527,14 @@ - + - + @@ -23606,7 +23677,7 @@ - + @@ -23615,7 +23686,7 @@ - + @@ -23689,7 +23760,7 @@ - + @@ -23703,14 +23774,14 @@ - + - + @@ -23885,7 +23956,7 @@ - + @@ -23900,20 +23971,20 @@ - + - + - + @@ -23972,7 +24043,7 @@ - + @@ -24084,7 +24155,7 @@ - + @@ -24092,7 +24163,7 @@ - + @@ -24931,7 +25002,7 @@ - + @@ -24945,13 +25016,13 @@ - + - + @@ -24970,7 +25041,7 @@ - + @@ -24978,7 +25049,7 @@ - + @@ -24986,12 +25057,12 @@ - + - + @@ -25020,7 +25091,7 @@ - + @@ -25036,7 +25107,7 @@ - + @@ -25063,7 +25134,7 @@ - + @@ -25079,7 +25150,7 @@ - + @@ -25087,7 +25158,7 @@ - + @@ -25258,7 +25329,7 @@ - + @@ -25267,7 +25338,7 @@ - + @@ -25286,7 +25357,7 @@ - + @@ -25319,7 +25390,7 @@ - + @@ -26428,7 +26499,7 @@ - + @@ -26518,7 +26589,7 @@ - + @@ -29686,7 +29757,7 @@ - + @@ -29810,7 +29881,7 @@ - + @@ -29824,7 +29895,7 @@ - + @@ -29846,14 +29917,14 @@ - + - + @@ -29889,13 +29960,13 @@ - + - + @@ -29912,7 +29983,7 @@ - + @@ -30130,7 +30201,7 @@ - + @@ -30138,7 +30209,7 @@ - + @@ -30153,7 +30224,7 @@ - + @@ -30161,7 +30232,7 @@ - + @@ -30178,7 +30249,7 @@ - + @@ -30186,7 +30257,7 @@ - + @@ -30201,7 +30272,7 @@ - + @@ -30209,7 +30280,7 @@ - + @@ -30226,7 +30297,7 @@ - + @@ -30234,7 +30305,7 @@ - + @@ -30249,7 +30320,7 @@ - + @@ -30257,7 +30328,7 @@ - + @@ -30276,7 +30347,7 @@ - + @@ -30286,7 +30357,7 @@ - + @@ -30306,7 +30377,7 @@ - + @@ -30316,7 +30387,7 @@ - + @@ -30329,7 +30400,7 @@ - + @@ -30339,8 +30410,8 @@ - - + + @@ -30350,8 +30421,8 @@ - - + + @@ -30952,7 +31023,7 @@ - + @@ -31613,19 +31684,19 @@ - + - + - + @@ -31638,7 +31709,7 @@ - + @@ -31656,7 +31727,7 @@ - + @@ -31856,7 +31927,7 @@ - + @@ -31866,7 +31937,7 @@ - + @@ -32191,7 +32262,12 @@ - + + + + + + @@ -32970,7 +33046,7 @@ - + @@ -33378,7 +33454,7 @@ - + @@ -33392,7 +33468,7 @@ - + @@ -33571,7 +33647,7 @@ - + @@ -33757,7 +33833,7 @@ - + @@ -33793,7 +33869,7 @@ - + @@ -34022,7 +34098,7 @@ - + @@ -34030,7 +34106,7 @@ - + @@ -34038,7 +34114,7 @@ - + @@ -34046,7 +34122,7 @@ - + @@ -34274,14 +34350,14 @@ - + - + @@ -34363,20 +34439,20 @@ - + - - + + - + @@ -34387,7 +34463,7 @@ - + @@ -34414,7 +34490,7 @@ - + @@ -34444,7 +34520,7 @@ - + @@ -34629,7 +34705,7 @@ - + @@ -34639,7 +34715,7 @@ - + @@ -34769,19 +34845,35 @@ - + + + + + - + + + + + - + + + + + - + + + + + @@ -35296,14 +35388,14 @@ - + - + @@ -35318,7 +35410,7 @@ - + @@ -35348,7 +35440,7 @@ - + @@ -35370,7 +35462,7 @@ - + @@ -36008,7 +36100,7 @@ - + @@ -36018,7 +36110,7 @@ - + @@ -37066,15 +37158,15 @@ - - + + - - + + @@ -37240,7 +37332,7 @@ - + @@ -38982,14 +39074,14 @@ - + - + @@ -38997,14 +39089,14 @@ - + - + @@ -39012,14 +39104,14 @@ - + - + @@ -39028,7 +39120,7 @@ - + @@ -39038,7 +39130,7 @@ - + @@ -39046,15 +39138,15 @@ - - + + - - + + @@ -39622,8 +39714,8 @@ - - + + @@ -39632,7 +39724,7 @@ - + @@ -39641,7 +39733,7 @@ - + @@ -39650,7 +39742,7 @@ - + @@ -39661,7 +39753,7 @@ - + @@ -40391,7 +40483,7 @@ - + @@ -41026,8 +41118,8 @@ - - + + @@ -41035,7 +41127,7 @@ - + @@ -41043,8 +41135,8 @@ - - + + @@ -41052,8 +41144,8 @@ - - + + @@ -41064,7 +41156,7 @@ - + @@ -41074,7 +41166,7 @@ - + @@ -41094,7 +41186,7 @@ - + @@ -41102,7 +41194,7 @@ - + @@ -41110,7 +41202,7 @@ - + @@ -41121,7 +41213,7 @@ - + @@ -41133,7 +41225,7 @@ - + @@ -41566,8 +41658,8 @@ - - + + @@ -41575,8 +41667,8 @@ - - + + @@ -41588,7 +41680,7 @@ - + @@ -41598,7 +41690,7 @@ - + @@ -41608,7 +41700,7 @@ - + @@ -41618,7 +41710,7 @@ - + @@ -42122,7 +42214,7 @@ - + @@ -42133,8 +42225,8 @@ - - + + @@ -42142,7 +42234,7 @@ - + @@ -42151,8 +42243,8 @@ - - + + @@ -42161,7 +42253,7 @@ - + @@ -42171,7 +42263,7 @@ - + @@ -42179,23 +42271,23 @@ - - + + - - + + - - + + @@ -42204,15 +42296,15 @@ - - + + - + @@ -42229,7 +42321,7 @@ - + @@ -42238,8 +42330,8 @@ - - + + @@ -43135,7 +43227,7 @@ - + @@ -43660,7 +43752,7 @@ - + @@ -43668,7 +43760,7 @@ - + @@ -43676,20 +43768,20 @@ - + - + - + @@ -43699,19 +43791,19 @@ - + - - + + - - + + @@ -43725,7 +43817,7 @@ - + @@ -44416,7 +44508,11 @@ - + + + + + @@ -45086,7 +45182,7 @@ - + @@ -45097,8 +45193,8 @@ - - + + @@ -45106,7 +45202,7 @@ - + @@ -45116,7 +45212,7 @@ - + @@ -45126,7 +45222,7 @@ - + @@ -45137,16 +45233,16 @@ - - + + - - + + @@ -45236,7 +45332,7 @@ - + @@ -45258,7 +45354,7 @@ - + @@ -45294,7 +45390,7 @@ - + @@ -46502,7 +46598,7 @@ - + @@ -46522,7 +46618,7 @@ - + @@ -46530,15 +46626,15 @@ - - + + - + @@ -46576,7 +46672,7 @@ - + @@ -46587,7 +46683,7 @@ - + @@ -48193,20 +48289,20 @@ - + - - + + - + @@ -48221,20 +48317,20 @@ - + - - + + - + @@ -48249,20 +48345,20 @@ - + - - + + - + @@ -48273,11 +48369,11 @@ - - + + - + @@ -48290,45 +48386,45 @@ - + - - + + - + - + - + - + - + - + @@ -48340,25 +48436,25 @@ - + - + - + - + - + @@ -48371,7 +48467,7 @@ - + @@ -48381,7 +48477,7 @@ - + @@ -48390,7 +48486,7 @@ - + @@ -48620,39 +48716,39 @@ - + - - - + + + - + - + - + - + - + @@ -48671,7 +48767,7 @@ - + @@ -48681,7 +48777,7 @@ - + @@ -48692,7 +48788,7 @@ - + @@ -49020,7 +49116,7 @@ - + @@ -49031,7 +49127,7 @@ - + @@ -49230,7 +49326,7 @@ - + @@ -49240,7 +49336,7 @@ - + @@ -49268,45 +49364,45 @@ - + - + - + - + - + - + - + - + - + diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b24b24c5964..1d8fe5d16e0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -154,6 +154,7 @@ target_sources(${PROJECT_NAME} items/cylinder.cpp items/item.cpp items/items.cpp + items/functions/item_parse.cpp items/thing.cpp items/tile.cpp items/trashholder.cpp diff --git a/src/items/functions/item_parse.cpp b/src/items/functions/item_parse.cpp new file mode 100644 index 00000000000..16f592ace40 --- /dev/null +++ b/src/items/functions/item_parse.cpp @@ -0,0 +1,816 @@ +/** + * Canary - A free and open-source MMORPG server emulator + * Copyright (C) 2018-2021 OpenTibiaBR + * + * 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 2 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, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "otpch.h" + +#include "items/functions/item_parse.hpp" + +void ItemParse::initParse(const std::string& tmpStrValue, pugi::xml_node attributeNode, pugi::xml_attribute valueAttribute, ItemType& itemType) { + // Parse all item attributes + ItemParse::parseType(tmpStrValue, valueAttribute, itemType); + ItemParse::parseDescription(tmpStrValue, valueAttribute, itemType); + ItemParse::parseRuneSpellName(tmpStrValue, valueAttribute, itemType); + ItemParse::parseWeight(tmpStrValue, valueAttribute, itemType); + ItemParse::parseShowCount(tmpStrValue, valueAttribute, itemType); + ItemParse::parseArmor(tmpStrValue, valueAttribute, itemType); + ItemParse::parseDefense(tmpStrValue, valueAttribute, itemType); + ItemParse::parseExtraDefense(tmpStrValue, valueAttribute, itemType); + ItemParse::parseAttack(tmpStrValue, valueAttribute, itemType); + ItemParse::parseRotateTo(tmpStrValue, valueAttribute, itemType); + ItemParse::parseWrapContainer(tmpStrValue, valueAttribute, itemType); + ItemParse::parseImbuingSlot(tmpStrValue, valueAttribute, itemType); + ItemParse::parseWrapableTo(tmpStrValue, valueAttribute, itemType); + ItemParse::parseMoveable(tmpStrValue, valueAttribute, itemType); + ItemParse::parsePodium(tmpStrValue, valueAttribute, itemType); + ItemParse::parseBlockProjectTile(tmpStrValue, valueAttribute, itemType); + ItemParse::parsePickupable(tmpStrValue, valueAttribute, itemType); + ItemParse::parseFloorChange(tmpStrValue, valueAttribute, itemType); + ItemParse::parseCorpseType(tmpStrValue, valueAttribute, itemType); + ItemParse::parseContainerSize(tmpStrValue, valueAttribute, itemType); + ItemParse::parseFluidSource(tmpStrValue, valueAttribute, itemType); + ItemParse::parseWriteables(tmpStrValue, valueAttribute, itemType); + ItemParse::parseWeaponType(tmpStrValue, valueAttribute, itemType); + ItemParse::parseSlotType(tmpStrValue, valueAttribute, itemType); + ItemParse::parseAmmoType(tmpStrValue, valueAttribute, itemType); + ItemParse::parseShootType(tmpStrValue, valueAttribute, itemType); + ItemParse::parseMagicEffect(tmpStrValue, valueAttribute, itemType); + ItemParse::parseLootType(tmpStrValue, valueAttribute, itemType); + ItemParse::parseRange(tmpStrValue, valueAttribute, itemType); + ItemParse::parseDuration(tmpStrValue, valueAttribute, itemType); + ItemParse::parseTransform(tmpStrValue, valueAttribute, itemType); + ItemParse::parseCharges(tmpStrValue, valueAttribute, itemType); + ItemParse::parseShowAttributes(tmpStrValue, valueAttribute, itemType); + ItemParse::parseHitChance(tmpStrValue, valueAttribute, itemType); + ItemParse::parseInvisible(tmpStrValue, valueAttribute, itemType); + ItemParse::parseSpeed(tmpStrValue, valueAttribute, itemType); + ItemParse::parseHealthAndMana(tmpStrValue, valueAttribute, itemType); + ItemParse::parseSkills(tmpStrValue, valueAttribute, itemType); + ItemParse::parseCriticalHit(tmpStrValue, valueAttribute, itemType); + ItemParse::parseLifeAndManaLeech(tmpStrValue, valueAttribute, itemType); + ItemParse::parseMaxHitAndManaPoints(tmpStrValue, valueAttribute, itemType); + ItemParse::parseMagicPoints(tmpStrValue, valueAttribute, itemType); + ItemParse::parseFieldAbsorbPercent(tmpStrValue, valueAttribute, itemType); + ItemParse::parseAbsorbPercent(tmpStrValue, valueAttribute, itemType); + ItemParse::parseSupressDrunk(tmpStrValue, valueAttribute, itemType); + ItemParse::parseField(tmpStrValue, attributeNode, valueAttribute, itemType); + ItemParse::parseReplaceable(tmpStrValue, valueAttribute, itemType); + ItemParse::parseLevelDoor(tmpStrValue, valueAttribute, itemType); + ItemParse::parseBeds(tmpStrValue, valueAttribute, itemType); + ItemParse::parseElement(tmpStrValue, valueAttribute, itemType); + ItemParse::parseWalk(tmpStrValue, valueAttribute, itemType); + ItemParse::parseAllowDistanceRead(tmpStrValue, valueAttribute, itemType); +} + +void ItemParse::parseType(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType) { + std::string stringValue = tmpStrValue; + if (stringValue == "type") { + stringValue = asLowerCaseString(valueAttribute.as_string()); + auto itemMap = ItemTypesMap.find(stringValue); + if (itemMap != ItemTypesMap.end()) { + itemType.type = itemMap->second; + if (itemType.type == ITEM_TYPE_CONTAINER) { + itemType.group = ITEM_GROUP_CONTAINER; + } + } else { + SPDLOG_WARN("[Items::parseItemNode] - Unknown type: {}", + valueAttribute.as_string()); + } + } +} + +void ItemParse::parseDescription(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType) { + std::string stringValue = tmpStrValue; + if (stringValue == "description") { + itemType.description = valueAttribute.as_string(); + } +} + +void ItemParse::parseRuneSpellName(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType) { + std::string stringValue = tmpStrValue; + if (stringValue == "runespellname") { + itemType.runeSpellName = valueAttribute.as_string(); + } +} + +void ItemParse::parseWeight(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType) { + std::string stringValue = tmpStrValue; + if (stringValue == "weight") { + itemType.weight = pugi::cast(valueAttribute.value()); + } +} + +void ItemParse::parseShowCount(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType) { + std::string stringValue = tmpStrValue; + if (stringValue == "showcount") { + itemType.showCount = valueAttribute.as_bool(); + } +} + +void ItemParse::parseArmor(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType) { + std::string stringValue = tmpStrValue; + if (stringValue == "armor") { + itemType.armor = pugi::cast(valueAttribute.value()); + } +} + +void ItemParse::parseDefense(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType) { + std::string stringValue = tmpStrValue; + if (stringValue == "defense") { + itemType.defense = pugi::cast(valueAttribute.value()); + } +} + +void ItemParse::parseExtraDefense(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType) { + std::string stringValue = tmpStrValue; + if (stringValue == "extradef") { + itemType.extraDefense = pugi::cast(valueAttribute.value()); + } +} + +void ItemParse::parseAttack(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType) { + std::string stringValue = tmpStrValue; + if (stringValue == "attack") { + itemType.attack = pugi::cast(valueAttribute.value()); + } +} + +void ItemParse::parseRotateTo(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType) { + std::string stringValue = tmpStrValue; + if (stringValue == "rotateto") { + itemType.rotateTo = pugi::cast(valueAttribute.value()); + } +} + +void ItemParse::parseWrapContainer(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType) { + std::string stringValue = tmpStrValue; + if (stringValue == "wrapcontainer") { + itemType.wrapContainer = valueAttribute.as_bool(); + } +} + +void ItemParse::parseImbuingSlot(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType) { + std::string stringValue = tmpStrValue; + if (stringValue == "imbuingslot") { + itemType.imbuingSlots = pugi::cast(valueAttribute.value()); + } +} + +void ItemParse::parseWrapableTo(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType) { + std::string stringValue = tmpStrValue; + if (stringValue == "wrapableto") { + itemType.wrapableTo = pugi::cast(valueAttribute.value()); + itemType.wrapable = true; + } +} + +void ItemParse::parseMoveable(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType) { + std::string stringValue = tmpStrValue; + if (stringValue == "moveable") { + itemType.moveable = valueAttribute.as_bool(); + } +} + +void ItemParse::parsePodium(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType) { + std::string stringValue = tmpStrValue; + if (stringValue == "podium") { + itemType.isPodium = valueAttribute.as_bool(); + } +} + +void ItemParse::parseBlockProjectTile(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType) { + std::string stringValue = tmpStrValue; + if (stringValue == "blockprojectile") { + itemType.blockProjectile = valueAttribute.as_bool(); + } +} + +void ItemParse::parsePickupable(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType) { + std::string stringValue = tmpStrValue; + if (stringValue == "pickupable") { + itemType.allowPickupable = valueAttribute.as_bool(); + } +} + +void ItemParse::parseFloorChange(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType) { + std::string stringValue = tmpStrValue; + if (stringValue == "floorchange") { + stringValue = asLowerCaseString(valueAttribute.as_string()); + auto itemMap = TileStatesMap.find(stringValue); + if (itemMap != TileStatesMap.end()) { + itemType.floorChange = itemMap->second; + } else { + SPDLOG_WARN("[ItemParse::parseFloorChange] - Unknown floorChange {}", + valueAttribute.as_string()); + } + } +} + +void ItemParse::parseCorpseType(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType) { + std::string stringValue = tmpStrValue; + if (stringValue == "corpsetype") { + stringValue = asLowerCaseString(valueAttribute.as_string()); + auto itemMap = RaceTypesMap.find(stringValue); + if (itemMap != RaceTypesMap.end()) { + itemType.corpseType = itemMap->second; + } else { + SPDLOG_WARN("[ItemParse::parseCorpseType] - Unknown corpseType {}", + valueAttribute.as_string()); + } + } +} + +void ItemParse::parseContainerSize(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType) { + std::string stringValue = tmpStrValue; + if (stringValue == "containersize") { + itemType.maxItems = pugi::cast(valueAttribute.value()); + } +} + +void ItemParse::parseFluidSource(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType) { + std::string stringValue = tmpStrValue; + if (stringValue == "fluidsource") { + stringValue = asLowerCaseString(valueAttribute.as_string()); + auto itemMap = FluidTypesMap.find(stringValue); + if (itemMap != FluidTypesMap.end()) { + itemType.fluidSource = itemMap->second; + } else { + SPDLOG_WARN("[Items::parseItemNode] - Unknown fluidSource {}", + valueAttribute.as_string()); + } + } +} + +void ItemParse::parseWriteables(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType) { + std::string stringValue = tmpStrValue; + if (stringValue == "readable") { + itemType.canReadText = valueAttribute.as_bool(); + } else if (stringValue == "writeable") { + itemType.canWriteText = valueAttribute.as_bool(); + itemType.canReadText = itemType.canWriteText; + } else if (stringValue == "maxtextlen") { + itemType.maxTextLen = pugi::cast(valueAttribute.value()); + } else if (stringValue == "writeonceitemid") { + itemType.writeOnceItemId = pugi::cast(valueAttribute.value()); + } +} + +void ItemParse::parseWeaponType(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType) { + std::string stringValue = tmpStrValue; + if (stringValue == "weapontype") { + stringValue = asLowerCaseString(valueAttribute.as_string()); + auto itemMap = WeaponTypesMap.find(stringValue); + if (itemMap != WeaponTypesMap.end()) { + itemType.weaponType = itemMap->second; + } else { + SPDLOG_WARN("[Items::parseItemNode] - Unknown weaponType {}", + valueAttribute.as_string()); + } + } +} + +void ItemParse::parseSlotType(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType) { + std::string stringValue = tmpStrValue; + if (stringValue == "slottype") { + stringValue = asLowerCaseString(valueAttribute.as_string()); + if (stringValue == "head") { + itemType.slotPosition |= SLOTP_HEAD; + } else if (stringValue == "body") { + itemType.slotPosition |= SLOTP_ARMOR; + } else if (stringValue == "legs") { + itemType.slotPosition |= SLOTP_LEGS; + } else if (stringValue == "feet") { + itemType.slotPosition |= SLOTP_FEET; + } else if (stringValue == "backpack") { + itemType.slotPosition |= SLOTP_BACKPACK; + } else if (stringValue == "two-handed") { + itemType.slotPosition |= SLOTP_TWO_HAND; + } else if (stringValue == "right-hand") { + itemType.slotPosition &= ~SLOTP_LEFT; + } else if (stringValue == "left-hand") { + itemType.slotPosition &= ~SLOTP_RIGHT; + } else if (stringValue == "necklace") { + itemType.slotPosition |= SLOTP_NECKLACE; + } else if (stringValue == "ring") { + itemType.slotPosition |= SLOTP_RING; + } else if (stringValue == "ammo") { + itemType.slotPosition |= SLOTP_AMMO; + } else if (stringValue == "hand") { + itemType.slotPosition |= SLOTP_HAND; + } else { + SPDLOG_WARN("[itemParseSlotType - Items::parseItemNode] - Unknown slotType {}", + valueAttribute.as_string()); + } + } +} + +void ItemParse::parseAmmoType(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType) { + std::string stringValue = tmpStrValue; + if (stringValue == "ammotype") { + itemType.ammoType = getAmmoType(asLowerCaseString(valueAttribute.as_string())); + if (itemType.ammoType == AMMO_NONE) { + SPDLOG_WARN("[Items::parseItemNode] - Unknown ammoType {}", + valueAttribute.as_string()); + } + } +} + +void ItemParse::parseShootType(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType) { + std::string stringValue = tmpStrValue; + if (stringValue == "shoottype") { + ShootType_t shoot = getShootType(asLowerCaseString(valueAttribute.as_string())); + if (shoot != CONST_ANI_NONE) { + itemType.shootType = shoot; + } else { + SPDLOG_WARN("[Items::parseItemNode] - Unknown shootType {}", + valueAttribute.as_string()); + } + } +} + +void ItemParse::parseMagicEffect(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType) { + std::string stringValue = tmpStrValue; + if (stringValue == "effect") { + MagicEffectClasses effect = getMagicEffect(asLowerCaseString(valueAttribute.as_string())); + if (effect != CONST_ME_NONE) { + itemType.magicEffect = effect; + } else { + SPDLOG_WARN("[Items::parseItemNode] - Unknown effect {}", + valueAttribute.as_string()); + } + } +} + +void ItemParse::parseLootType(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType) { + std::string stringValue = tmpStrValue; + if (stringValue == "loottype") { + itemType.type = Item::items.getLootType(valueAttribute.as_string()); + } +} + +void ItemParse::parseRange(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType) { + std::string stringValue = tmpStrValue; + if (stringValue == "range") { + itemType.shootRange = pugi::cast(valueAttribute.value()); + } +} + +void ItemParse::parseDuration(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType) { + std::string stringValue = tmpStrValue; + if (stringValue == "duration") { + itemType.decayTime = pugi::cast(valueAttribute.value()); + } else if (stringValue == "stopduration") { + itemType.stopTime = valueAttribute.as_bool(); + } else if (stringValue == "showduration") { + itemType.showDuration = valueAttribute.as_bool(); + } +} + +void ItemParse::parseTransform(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType) { + std::string stringValue = tmpStrValue; + if (stringValue == "transformequipto") { + itemType.transformEquipTo = pugi::cast(valueAttribute.value()); + } else if (stringValue == "transformdeequipto") { + itemType.transformDeEquipTo = pugi::cast(valueAttribute.value()); + } else if (stringValue == "transformto") { + itemType.transformToFree = pugi::cast(valueAttribute.value()); + } else if (stringValue == "destroyto") { + itemType.destroyTo = pugi::cast(valueAttribute.value()); + } +} + +void ItemParse::parseCharges(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType) { + std::string stringValue = tmpStrValue; + if (stringValue == "charges") { + itemType.charges = pugi::cast(valueAttribute.value()); + } else if (stringValue == "showcharges") { + itemType.showCharges = valueAttribute.as_bool(); + } +} + +void ItemParse::parseShowAttributes(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType) { + std::string stringValue = tmpStrValue; + if (stringValue == "showattributes") { + itemType.showAttributes = valueAttribute.as_bool(); + } +} + +void ItemParse::parseHitChance(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType) { + std::string stringValue = tmpStrValue; + if (stringValue == "hitchance") { + itemType.hitChance = std::min(100, std::max(-100, pugi::cast(valueAttribute.value()))); + } else if (stringValue == "maxhitchance") { + itemType.maxHitChance = std::min(100, pugi::cast(valueAttribute.value())); + } +} + +void ItemParse::parseInvisible(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType) { + std::string stringValue = tmpStrValue; + if (stringValue == "invisible") { + itemType.getAbilities().invisible = valueAttribute.as_bool(); + } +} + +void ItemParse::parseSpeed(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType) { + std::string stringValue = tmpStrValue; + if (stringValue == "speed") { + itemType.getAbilities().speed = pugi::cast(valueAttribute.value()); + } +} + +void ItemParse::parseHealthAndMana(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType) { + std::string stringValue = tmpStrValue; + if (stringValue == "healthgain") { + Abilities & abilities = itemType.getAbilities(); + abilities.regeneration = true; + abilities.healthGain = pugi::cast(valueAttribute.value()); + } else if (stringValue == "healthticks") { + Abilities & abilities = itemType.getAbilities(); + abilities.regeneration = true; + abilities.healthTicks = pugi::cast(valueAttribute.value()); + } else if (stringValue == "managain") { + Abilities & abilities = itemType.getAbilities(); + abilities.regeneration = true; + abilities.manaGain = pugi::cast(valueAttribute.value()); + } else if (stringValue == "manaticks") { + Abilities & abilities = itemType.getAbilities(); + abilities.regeneration = true; + abilities.manaTicks = pugi::cast(valueAttribute.value()); + } else if (stringValue == "manashield") { + itemType.getAbilities().manaShield = valueAttribute.as_bool(); + } +} + +void ItemParse::parseSkills(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType) { + std::string stringValue = tmpStrValue; + if (stringValue == "skillsword") { + itemType.getAbilities().skills[SKILL_SWORD] = pugi::cast(valueAttribute.value()); + } else if (stringValue == "skillaxe") { + itemType.getAbilities().skills[SKILL_AXE] = pugi::cast(valueAttribute.value()); + } else if (stringValue == "skillclub") { + itemType.getAbilities().skills[SKILL_CLUB] = pugi::cast(valueAttribute.value()); + } else if (stringValue == "skilldist") { + itemType.getAbilities().skills[SKILL_DISTANCE] = pugi::cast(valueAttribute.value()); + } else if (stringValue == "skillfish") { + itemType.getAbilities().skills[SKILL_FISHING] = pugi::cast(valueAttribute.value()); + } else if (stringValue == "skillshield") { + itemType.getAbilities().skills[SKILL_SHIELD] = pugi::cast(valueAttribute.value()); + } else if (stringValue == "skillfist") { + itemType.getAbilities().skills[SKILL_FIST] = pugi::cast(valueAttribute.value()); + } +} + +void ItemParse::parseCriticalHit(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType) { + std::string stringValue = tmpStrValue; + if (stringValue == "criticalhitchance") { + itemType.getAbilities().skills[SKILL_CRITICAL_HIT_CHANCE] = pugi::cast(valueAttribute.value()); + } else if (stringValue == "criticalhitdamage") { + itemType.getAbilities().skills[SKILL_CRITICAL_HIT_DAMAGE] = pugi::cast(valueAttribute.value()); + } +} + +void ItemParse::parseLifeAndManaLeech(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType) { + std::string stringValue = tmpStrValue; + if (stringValue == "lifeleechchance") { + itemType.getAbilities().skills[SKILL_LIFE_LEECH_CHANCE] = pugi::cast(valueAttribute.value()); + } else if (stringValue == "lifeleechamount") { + itemType.getAbilities().skills[SKILL_LIFE_LEECH_AMOUNT] = pugi::cast(valueAttribute.value()); + } else if (stringValue == "manaleechchance") { + itemType.getAbilities().skills[SKILL_MANA_LEECH_CHANCE] = pugi::cast(valueAttribute.value()); + } else if (stringValue == "manaleechamount") { + itemType.getAbilities().skills[SKILL_MANA_LEECH_AMOUNT] = pugi::cast(valueAttribute.value()); + } +} + +void ItemParse::parseMaxHitAndManaPoints(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType) { + std::string stringValue = tmpStrValue; + if (stringValue == "maxhitpoints") { + itemType.getAbilities().stats[STAT_MAXHITPOINTS] = pugi::cast(valueAttribute.value()); + } else if (stringValue == "maxhitpointspercent") { + itemType.getAbilities().statsPercent[STAT_MAXHITPOINTS] = pugi::cast(valueAttribute.value()); + } else if (stringValue == "maxmanapoints") { + itemType.getAbilities().stats[STAT_MAXMANAPOINTS] = pugi::cast(valueAttribute.value()); + } else if (stringValue == "maxmanapointspercent") { + itemType.getAbilities().statsPercent[STAT_MAXMANAPOINTS] = pugi::cast(valueAttribute.value()); + } +} + +void ItemParse::parseMagicPoints(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType) { + std::string stringValue = tmpStrValue; + if (stringValue == "magicpoints") { + itemType.getAbilities().stats[STAT_MAGICPOINTS] = pugi::cast(valueAttribute.value()); + } else if (stringValue == "magicpointspercent") { + itemType.getAbilities().statsPercent[STAT_MAGICPOINTS] = pugi::cast(valueAttribute.value()); + } +} + +void ItemParse::parseFieldAbsorbPercent(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType) { + std::string stringValue = tmpStrValue; + if (stringValue == "fieldabsorbpercentenergy") { + itemType.getAbilities().fieldAbsorbPercent[combatTypeToIndex(COMBAT_ENERGYDAMAGE)] += pugi::cast(valueAttribute.value()); + } else if (stringValue == "fieldabsorbpercentfire") { + itemType.getAbilities().fieldAbsorbPercent[combatTypeToIndex(COMBAT_FIREDAMAGE)] += pugi::cast(valueAttribute.value()); + } else if (stringValue == "fieldabsorbpercentpoison") { + itemType.getAbilities().fieldAbsorbPercent[combatTypeToIndex(COMBAT_EARTHDAMAGE)] += pugi::cast(valueAttribute.value()); + } +} + +void ItemParse::parseAbsorbPercent(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType) { + std::string stringValue = tmpStrValue; + if (stringValue == "absorbpercentall") { + int16_t value = pugi::cast(valueAttribute.value()); + Abilities & abilities = itemType.getAbilities(); + for (auto & i: abilities.absorbPercent) { + i += value; + } + } else if (stringValue == "absorbpercentelements") { + int16_t value = pugi::cast(valueAttribute.value()); + Abilities & abilities = itemType.getAbilities(); + abilities.absorbPercent[combatTypeToIndex(COMBAT_ENERGYDAMAGE)] += value; + abilities.absorbPercent[combatTypeToIndex(COMBAT_FIREDAMAGE)] += value; + abilities.absorbPercent[combatTypeToIndex(COMBAT_EARTHDAMAGE)] += value; + abilities.absorbPercent[combatTypeToIndex(COMBAT_ICEDAMAGE)] += value; + } else if (stringValue == "absorbpercentmagic") { + int16_t value = pugi::cast(valueAttribute.value()); + Abilities & abilities = itemType.getAbilities(); + abilities.absorbPercent[combatTypeToIndex(COMBAT_ENERGYDAMAGE)] += value; + abilities.absorbPercent[combatTypeToIndex(COMBAT_FIREDAMAGE)] += value; + abilities.absorbPercent[combatTypeToIndex(COMBAT_EARTHDAMAGE)] += value; + abilities.absorbPercent[combatTypeToIndex(COMBAT_ICEDAMAGE)] += value; + abilities.absorbPercent[combatTypeToIndex(COMBAT_HOLYDAMAGE)] += value; + abilities.absorbPercent[combatTypeToIndex(COMBAT_DEATHDAMAGE)] += value; + } else if (stringValue == "absorbpercentenergy") { + itemType.getAbilities().absorbPercent[combatTypeToIndex(COMBAT_ENERGYDAMAGE)] += pugi::cast(valueAttribute.value()); + } else if (stringValue == "absorbpercentfire") { + itemType.getAbilities().absorbPercent[combatTypeToIndex(COMBAT_FIREDAMAGE)] += pugi::cast(valueAttribute.value()); + } else if (stringValue == "absorbpercentpoison") { + itemType.getAbilities().absorbPercent[combatTypeToIndex(COMBAT_EARTHDAMAGE)] += pugi::cast(valueAttribute.value()); + } else if (stringValue == "absorbpercentice") { + itemType.getAbilities().absorbPercent[combatTypeToIndex(COMBAT_ICEDAMAGE)] += pugi::cast(valueAttribute.value()); + } else if (stringValue == "absorbpercentholy") { + itemType.getAbilities().absorbPercent[combatTypeToIndex(COMBAT_HOLYDAMAGE)] += pugi::cast(valueAttribute.value()); + } else if (stringValue == "absorbpercentdeath") { + itemType.getAbilities().absorbPercent[combatTypeToIndex(COMBAT_DEATHDAMAGE)] += pugi::cast(valueAttribute.value()); + } else if (stringValue == "absorbpercentlifedrain") { + itemType.getAbilities().absorbPercent[combatTypeToIndex(COMBAT_LIFEDRAIN)] += pugi::cast(valueAttribute.value()); + } else if (stringValue == "absorbpercentmanadrain") { + itemType.getAbilities().absorbPercent[combatTypeToIndex(COMBAT_MANADRAIN)] += pugi::cast(valueAttribute.value()); + } else if (stringValue == "absorbpercentdrown") { + itemType.getAbilities().absorbPercent[combatTypeToIndex(COMBAT_DROWNDAMAGE)] += pugi::cast(valueAttribute.value()); + } else if (stringValue == "absorbpercentphysical") { + itemType.getAbilities().absorbPercent[combatTypeToIndex(COMBAT_PHYSICALDAMAGE)] += pugi::cast(valueAttribute.value()); + } else if (stringValue == "absorbpercenthealing") { + itemType.getAbilities().absorbPercent[combatTypeToIndex(COMBAT_HEALING)] += pugi::cast(valueAttribute.value()); + } +} + +void ItemParse::parseSupressDrunk(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType) { + std::string stringValue = tmpStrValue; + if (valueAttribute.as_bool()) { + if (stringValue == "suppressdrunk") { + itemType.getAbilities().conditionSuppressions |= CONDITION_DRUNK; + } else if (stringValue == "suppressenergy") { + itemType.getAbilities().conditionSuppressions |= CONDITION_ENERGY; + } else if (stringValue == "suppressfire") { + itemType.getAbilities().conditionSuppressions |= CONDITION_FIRE; + } else if (stringValue == "suppresspoison") { + itemType.getAbilities().conditionSuppressions |= CONDITION_POISON; + } else if (stringValue == "suppressdrown") { + itemType.getAbilities().conditionSuppressions |= CONDITION_DROWN; + } else if (stringValue == "suppressphysical") { + itemType.getAbilities().conditionSuppressions |= CONDITION_BLEEDING; + } else if (stringValue == "suppressfreeze") { + itemType.getAbilities().conditionSuppressions |= CONDITION_FREEZING; + } else if (stringValue == "suppressdazzle") { + itemType.getAbilities().conditionSuppressions |= CONDITION_DAZZLED; + } else if (stringValue == "suppresscurse") { + itemType.getAbilities().conditionSuppressions |= CONDITION_CURSED; + } + } +} + +std::tuple ItemParse::parseFieldConditions(ConditionId_t conditionId, ConditionType_t conditionType, std::string lowerStringValue, pugi::xml_attribute valueAttribute) { + lowerStringValue = asLowerCaseString(valueAttribute.as_string()); + conditionId = CONDITIONID_COMBAT; + if (lowerStringValue == "fire") { + conditionType = CONDITION_FIRE; + return std::make_tuple(conditionId, conditionType, lowerStringValue, valueAttribute); + } else if (lowerStringValue == "energy") { + conditionType = CONDITION_ENERGY; + return std::make_tuple(conditionId, conditionType, lowerStringValue, valueAttribute); + } else if (lowerStringValue == "poison") { + conditionType = CONDITION_POISON; + return std::make_tuple(conditionId, conditionType, lowerStringValue, valueAttribute); + } else if (lowerStringValue == "drown") { + conditionType = CONDITION_DROWN; + return std::make_tuple(conditionId, conditionType, lowerStringValue, valueAttribute); + } else if (lowerStringValue == "physical") { + conditionType = CONDITION_BLEEDING; + return std::make_tuple(conditionId, conditionType, lowerStringValue, valueAttribute); + } else { + SPDLOG_WARN("[Items::parseItemNode] Unknown field value {}", + valueAttribute.as_string()); + } + return std::make_tuple(CONDITIONID_DEFAULT, CONDITION_NONE, lowerStringValue, valueAttribute); +} + +CombatType_t ItemParse::parseFieldCombatType(std::string lowerStringValue, pugi::xml_attribute valueAttribute) { + lowerStringValue = asLowerCaseString(valueAttribute.as_string()); + if (lowerStringValue == "fire") { + return COMBAT_FIREDAMAGE; + } else if (lowerStringValue == "energy") { + return COMBAT_ENERGYDAMAGE; + } else if (lowerStringValue == "poison") { + return COMBAT_EARTHDAMAGE; + } else if (lowerStringValue == "drown") { + return COMBAT_DROWNDAMAGE; + } else if (lowerStringValue == "physical") { + return COMBAT_PHYSICALDAMAGE; + } else { + SPDLOG_WARN("[Items::parseItemNode] Unknown field value {}", + valueAttribute.as_string()); + } + return COMBAT_NONE; +} + +void ItemParse::parseFieldCombatDamage(ConditionDamage *conditionDamage, std::string stringValue, pugi::xml_node attributeNode) { + uint32_t combatTicks = 0; + int32_t combatDamage = 0; + int32_t combatStart = 0; + int32_t combatCount = 1; + + for (auto subAttributeNode: attributeNode.children()) { + pugi::xml_attribute subKeyAttribute = subAttributeNode.attribute("key"); + if (!subKeyAttribute) { + continue; + } + + pugi::xml_attribute subValueAttribute = subAttributeNode.attribute("value"); + if (!subValueAttribute) { + continue; + } + + stringValue = asLowerCaseString(subKeyAttribute.as_string()); + if (stringValue == "ticks") { + combatTicks = pugi::cast(subValueAttribute.value()); + } else if (stringValue == "count") { + combatCount = std::max(1, pugi::cast(subValueAttribute.value())); + } else if (stringValue == "start") { + combatStart = std::max(0, pugi::cast(subValueAttribute.value())); + } else if (stringValue == "damage") { + combatDamage = -pugi::cast(subValueAttribute.value()); + if (combatStart == 0) { + conditionDamage->addDamage(combatCount, combatTicks, combatDamage); + } + + std::listdamageList; + ConditionDamage::generateDamageList(combatDamage, combatStart, damageList); + for (int32_t damageValue: damageList) { + conditionDamage->addDamage(1, combatTicks, -damageValue); + } + + combatStart = 0; + } + } +} + +void ItemParse::parseField(const std::string& tmpStrValue, pugi::xml_node attributeNode, pugi::xml_attribute valueAttribute, ItemType& itemType) { + std::string stringValue = tmpStrValue; + if (stringValue == "field") { + CombatType_t combatType = COMBAT_NONE; + ConditionDamage* conditionDamage = nullptr; + + // Parse fields conditions (fire/energy/poison/drown/physical) + combatType = parseFieldCombatType(stringValue, valueAttribute); + ConditionId_t condID = CONDITIONID_DEFAULT; + ConditionType_t condType = CONDITION_NONE; + auto result = parseFieldConditions(condID, condType, stringValue, valueAttribute); + condID = std::get<0>(result); + condType = std::get<1>(result); + stringValue = std::get<2>(result); + valueAttribute = std::get<3>(result); + + if (combatType != COMBAT_NONE) { + if (conditionDamage) { + delete conditionDamage; + } + + conditionDamage = new ConditionDamage(condID, condType); + + itemType.combatType = combatType; + itemType.conditionDamage.reset(conditionDamage); + + parseFieldCombatDamage(conditionDamage, stringValue, attributeNode); + + conditionDamage->setParam(CONDITION_PARAM_FIELD, 1); + + if (conditionDamage->getTotalDamage() > 0) { + conditionDamage->setParam(CONDITION_PARAM_FORCEUPDATE, 1); + } + } + } +} + +void ItemParse::parseReplaceable(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType) { + std::string stringValue = tmpStrValue; + if (stringValue == "replaceable") { + itemType.replaceable = valueAttribute.as_bool(); + } +} + +void ItemParse::parseLevelDoor(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType) { + std::string stringValue = tmpStrValue; + if (stringValue == "leveldoor") { + itemType.levelDoor = pugi::cast(valueAttribute.value()); + } +} + +void ItemParse::parseBeds(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType) { + std::string stringValue = tmpStrValue; + if (stringValue == "partnerdirection") { + itemType.bedPartnerDir = getDirection(valueAttribute.as_string()); + } + + uint16_t value = pugi::cast(valueAttribute.value()); + ItemType & other = Item::items.getItemType(value); + if (stringValue == "maletransformto") { + itemType.transformToOnUse[PLAYERSEX_MALE] = value; + if (other.transformToFree == 0) { + other.transformToFree = itemType.id; + } + + if (itemType.transformToOnUse[PLAYERSEX_FEMALE] == 0) { + itemType.transformToOnUse[PLAYERSEX_FEMALE] = value; + } + } else if (stringValue == "femaletransformto") { + itemType.transformToOnUse[PLAYERSEX_FEMALE] = value; + + if (other.transformToFree == 0) { + other.transformToFree = itemType.id; + } + + if (itemType.transformToOnUse[PLAYERSEX_MALE] == 0) { + itemType.transformToOnUse[PLAYERSEX_MALE] = value; + } + } +} + +void ItemParse::parseElement(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType) { + std::string stringValue = tmpStrValue; + if (stringValue == "elementice") { + Abilities & abilities = itemType.getAbilities(); + abilities.elementDamage = pugi::cast(valueAttribute.value()); + abilities.elementType = COMBAT_ICEDAMAGE; + } else if (stringValue == "elementearth") { + Abilities & abilities = itemType.getAbilities(); + abilities.elementDamage = pugi::cast(valueAttribute.value()); + abilities.elementType = COMBAT_EARTHDAMAGE; + } else if (stringValue == "elementfire") { + Abilities & abilities = itemType.getAbilities(); + abilities.elementDamage = pugi::cast(valueAttribute.value()); + abilities.elementType = COMBAT_FIREDAMAGE; + } else if (stringValue == "elementenergy") { + Abilities & abilities = itemType.getAbilities(); + abilities.elementDamage = pugi::cast(valueAttribute.value()); + abilities.elementType = COMBAT_ENERGYDAMAGE; + } else if (stringValue == "elementdeath") { + Abilities & abilities = itemType.getAbilities(); + abilities.elementDamage = pugi::cast(valueAttribute.value()); + abilities.elementType = COMBAT_DEATHDAMAGE; + } else if (stringValue == "elementholy") { + Abilities & abilities = itemType.getAbilities(); + abilities.elementDamage = pugi::cast(valueAttribute.value()); + abilities.elementType = COMBAT_HOLYDAMAGE; + } +} + +void ItemParse::parseWalk(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType) { + std::string stringValue = tmpStrValue; + if (stringValue == "walkstack") { + itemType.walkStack = valueAttribute.as_bool(); + } else if (stringValue == "block_solid") { + itemType.blockSolid = valueAttribute.as_bool(); + } +} + +void ItemParse::parseAllowDistanceRead(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType) { + std::string stringValue = tmpStrValue; + if (stringValue == "allowdistread") { + itemType.allowDistRead = booleanString(valueAttribute.as_string()); + } +} diff --git a/src/items/functions/item_parse.hpp b/src/items/functions/item_parse.hpp new file mode 100644 index 00000000000..a2fc34122bf --- /dev/null +++ b/src/items/functions/item_parse.hpp @@ -0,0 +1,291 @@ +/** + * Canary - A free and open-source MMORPG server emulator + * Copyright (C) 2018-2021 OpenTibiaBR + * + * 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 2 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, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#ifndef SRC_ITEMS_FUNCTIONS_ITEM_PARSE_HPP_ +#define SRC_ITEMS_FUNCTIONS_ITEM_PARSE_HPP_ + +#include "creatures/combat/condition.h" +#include "declarations.hpp" +#include "items/item.h" +#include "items/items.h" +#include "utils/pugicast.h" + +class ConditionDamage; + +const std::unordered_map ItemParseAttributesMap = { + {"type", ITEM_PARSE_TYPE}, + {"description", ITEM_PARSE_DESCRIPTION}, + {"runespellname", ITEM_PARSE_RUNESPELLNAME}, + {"weight", ITEM_PARSE_WEIGHT}, + {"showcount", ITEM_PARSE_SHOWCOUNT}, + {"armor", ITEM_PARSE_ARMOR}, + {"defense", ITEM_PARSE_DEFENSE}, + {"extradef", ITEM_PARSE_EXTRADEF}, + {"attack", ITEM_PARSE_ATTACK}, + {"rotateto", ITEM_PARSE_ROTATETO}, + {"wrapcontainer", ITEM_PARSE_WRAPCONTAINER}, + {"imbuingslot", ITEM_PARSE_IMBUINGSLOT}, + {"wrapableto", ITEM_PARSE_WRAPABLETO}, + {"unwrapableto", ITEM_PARSE_WRAPABLETO}, + {"moveable", ITEM_PARSE_MOVEABLE}, + {"movable", ITEM_PARSE_MOVEABLE}, + {"ispodium", ITEM_PARSE_PODIUM}, + {"blockprojectile", ITEM_PARSE_BLOCKPROJECTILE}, + {"allowpickupable", ITEM_PARSE_PICKUPABLE}, + {"pickupable", ITEM_PARSE_PICKUPABLE}, + {"floorchange", ITEM_PARSE_FLOORCHANGE}, + {"corpsetype", ITEM_PARSE_CORPSETYPE}, + {"containersize", ITEM_PARSE_CONTAINERSIZE}, + {"fluidsource", ITEM_PARSE_FLUIDSOURCE}, + {"readable", ITEM_PARSE_READABLE}, + {"writeable", ITEM_PARSE_WRITEABLE}, + {"maxtextlen", ITEM_PARSE_MAXTEXTLEN}, + {"writeonceitemid", ITEM_PARSE_WRITEONCEITEMID}, + {"weapontype", ITEM_PARSE_WEAPONTYPE}, + {"slottype", ITEM_PARSE_SLOTTYPE}, + {"ammotype", ITEM_PARSE_AMMOTYPE}, + {"shoottype", ITEM_PARSE_SHOOTTYPE}, + {"effect", ITEM_PARSE_EFFECT}, + {"loottype", ITEM_PARSE_LOOTTYPE}, + {"range", ITEM_PARSE_RANGE}, + {"stopduration", ITEM_PARSE_STOPDURATION}, + {"decayto", ITEM_PARSE_DECAYTO}, + {"transformequipto", ITEM_PARSE_TRANSFORMEQUIPTO}, + {"transformdeequipto", ITEM_PARSE_TRANSFORMDEEQUIPTO}, + {"duration", ITEM_PARSE_DURATION}, + {"showduration", ITEM_PARSE_SHOWDURATION}, + {"charges", ITEM_PARSE_CHARGES}, + {"showcharges", ITEM_PARSE_SHOWCHARGES}, + {"showattributes", ITEM_PARSE_SHOWATTRIBUTES}, + {"hitchance", ITEM_PARSE_HITCHANCE}, + {"maxhitchance", ITEM_PARSE_MAXHITCHANCE}, + {"invisible", ITEM_PARSE_INVISIBLE}, + {"speed", ITEM_PARSE_SPEED}, + {"healthgain", ITEM_PARSE_HEALTHGAIN}, + {"healthticks", ITEM_PARSE_HEALTHTICKS}, + {"managain", ITEM_PARSE_MANAGAIN}, + {"manaticks", ITEM_PARSE_MANATICKS}, + {"manashield", ITEM_PARSE_MANASHIELD}, + {"skillsword", ITEM_PARSE_SKILLSWORD}, + {"skillaxe", ITEM_PARSE_SKILLAXE}, + {"skillclub", ITEM_PARSE_SKILLCLUB}, + {"skilldist", ITEM_PARSE_SKILLDIST}, + {"skillfish", ITEM_PARSE_SKILLFISH}, + {"skillshield", ITEM_PARSE_SKILLSHIELD}, + {"skillfist", ITEM_PARSE_SKILLFIST}, + {"criticalhitchance", ITEM_PARSE_CRITICALHITCHANCE}, + {"criticalhitdamage", ITEM_PARSE_CRITICALHITDAMAGE}, + {"skilllifechance", ITEM_PARSE_LIFELEECHCHANCE}, + {"skilllifeamount", ITEM_PARSE_LIFELEECHAMOUNT}, + {"skillmanachance", ITEM_PARSE_MANALEECHCHANCE}, + {"skillmanaamount", ITEM_PARSE_MANALEECHAMOUNT}, + {"maxhitpoints", ITEM_PARSE_MAXHITPOINTS}, + {"maxhitpointspercent", ITEM_PARSE_MAXHITPOINTSPERCENT}, + {"maxmanapoints", ITEM_PARSE_MAXMANAPOINTS}, + {"maxmanapointspercent", ITEM_PARSE_MAXMANAPOINTSPERCENT}, + {"magicpoints", ITEM_PARSE_MAGICPOINTS}, + {"magicpointspercent", ITEM_PARSE_MAGICPOINTSPERCENT}, + {"fieldabsorbpercentenergy", ITEM_PARSE_FIELDABSORBPERCENTENERGY}, + {"fieldabsorbpercentfire", ITEM_PARSE_FIELDABSORBPERCENTFIRE}, + {"fieldabsorbpercentpoison", ITEM_PARSE_FIELDABSORBPERCENTPOISON}, + {"fieldabsorbpercentearth", ITEM_PARSE_FIELDABSORBPERCENTPOISON}, + {"absorbpercentall", ITEM_PARSE_ABSORBPERCENTALL}, + {"absorbpercentallelements", ITEM_PARSE_ABSORBPERCENTELEMENTS}, + {"absorbpercentelements", ITEM_PARSE_ABSORBPERCENTELEMENTS}, + {"absorbpercentmagic", ITEM_PARSE_ABSORBPERCENTMAGIC}, + {"absorbpercentenergy", ITEM_PARSE_ABSORBPERCENTENERGY}, + {"absorbpercentfire", ITEM_PARSE_ABSORBPERCENTFIRE}, + {"absorbpercentpoison", ITEM_PARSE_ABSORBPERCENTPOISON}, + {"absorbpercentearth", ITEM_PARSE_ABSORBPERCENTPOISON}, + {"absorbpercentice", ITEM_PARSE_ABSORBPERCENTICE}, + {"absorbpercentholy", ITEM_PARSE_ABSORBPERCENTHOLY}, + {"absorbpercentdeath", ITEM_PARSE_ABSORBPERCENTDEATH}, + {"absorbpercentlifedrain", ITEM_PARSE_ABSORBPERCENTLIFEDRAIN}, + {"absorbpercentmanadrain", ITEM_PARSE_ABSORBPERCENTMANADRAIN}, + {"absorbpercentdrown", ITEM_PARSE_ABSORBPERCENTDROWN}, + {"absorbpercentphysical", ITEM_PARSE_ABSORBPERCENTPHYSICAL}, + {"absorbpercenthealing", ITEM_PARSE_ABSORBPERCENTHEALING}, + {"suppressdrunk", ITEM_PARSE_SUPPRESSDRUNK}, + {"suppressenergy", ITEM_PARSE_SUPPRESSENERGY}, + {"suppressfire", ITEM_PARSE_SUPPRESSFIRE}, + {"suppresspoison", ITEM_PARSE_SUPPRESSPOISON}, + {"suppressdrown", ITEM_PARSE_SUPPRESSDROWN}, + {"suppressphysical", ITEM_PARSE_SUPPRESSPHYSICAL}, + {"suppressfreeze", ITEM_PARSE_SUPPRESSFREEZE}, + {"suppressdazzle", ITEM_PARSE_SUPPRESSDAZZLE}, + {"suppresscurse", ITEM_PARSE_SUPPRESSCURSE}, + {"field", ITEM_PARSE_FIELD}, + {"replaceable", ITEM_PARSE_REPLACEABLE}, + {"partnerdirection", ITEM_PARSE_PARTNERDIRECTION}, + {"leveldoor", ITEM_PARSE_LEVELDOOR}, + {"maletransformto", ITEM_PARSE_MALETRANSFORMTO}, + {"malesleeper", ITEM_PARSE_MALETRANSFORMTO}, + {"femaletransformto", ITEM_PARSE_FEMALETRANSFORMTO}, + {"femalesleeper", ITEM_PARSE_FEMALETRANSFORMTO}, + {"transformto", ITEM_PARSE_TRANSFORMTO}, + {"destroyto", ITEM_PARSE_DESTROYTO}, + {"elementice", ITEM_PARSE_ELEMENTICE}, + {"elementearth", ITEM_PARSE_ELEMENTEARTH}, + {"elementfire", ITEM_PARSE_ELEMENTFIRE}, + {"elementenergy", ITEM_PARSE_ELEMENTENERGY}, + {"elementdeath", ITEM_PARSE_ELEMENTDEATH}, + {"elementholy", ITEM_PARSE_ELEMENTHOLY}, + {"walkstack", ITEM_PARSE_WALKSTACK}, + {"blocking", ITEM_PARSE_BLOCK_SOLID}, + {"allowdistread", ITEM_PARSE_ALLOWDISTREAD}, +}; + +const std::unordered_map ItemTypesMap = { + {"key", ITEM_TYPE_KEY}, + {"magicfield", ITEM_TYPE_MAGICFIELD}, + {"container", ITEM_TYPE_CONTAINER}, + {"depot", ITEM_TYPE_DEPOT}, + {"rewardchest", ITEM_TYPE_REWARDCHEST}, + {"carpet", ITEM_TYPE_CARPET}, + {"mailbox", ITEM_TYPE_MAILBOX}, + {"trashholder", ITEM_TYPE_TRASHHOLDER}, + {"teleport", ITEM_TYPE_TELEPORT}, + {"door", ITEM_TYPE_DOOR}, + {"bed", ITEM_TYPE_BED}, + {"rune", ITEM_TYPE_RUNE}, + {"supply", ITEM_TYPE_SUPPLY}, + {"creatureproduct", ITEM_TYPE_CREATUREPRODUCT}, + {"food", ITEM_TYPE_FOOD}, + {"valuable", ITEM_TYPE_VALUABLE}, + {"potion", ITEM_TYPE_POTION}, +}; + +const std::unordered_map TileStatesMap = { + {"down", TILESTATE_FLOORCHANGE_DOWN}, + {"north", TILESTATE_FLOORCHANGE_NORTH}, + {"south", TILESTATE_FLOORCHANGE_SOUTH}, + {"southalt", TILESTATE_FLOORCHANGE_SOUTH_ALT}, + {"west", TILESTATE_FLOORCHANGE_WEST}, + {"east", TILESTATE_FLOORCHANGE_EAST}, + {"eastalt", TILESTATE_FLOORCHANGE_EAST_ALT}, +}; + +const std::unordered_map RaceTypesMap = { + {"venom", RACE_VENOM}, + {"blood", RACE_BLOOD}, + {"undead", RACE_UNDEAD}, + {"fire", RACE_FIRE}, + {"energy", RACE_ENERGY}, +}; + +const std::unordered_map FluidTypesMap = { + {"water", FLUID_WATER }, + {"blood", FLUID_BLOOD}, + {"beer", FLUID_BEER}, + {"slime", FLUID_SLIME}, + {"lemonade", FLUID_LEMONADE}, + {"milk", FLUID_MILK }, + {"mana", FLUID_MANA }, + {"life", FLUID_LIFE }, + {"oil", FLUID_OIL }, + {"urine", FLUID_URINE }, + {"coconut", FLUID_COCONUTMILK }, + {"wine", FLUID_WINE }, + {"mud", FLUID_MUD }, + {"fruitjuice", FLUID_FRUITJUICE }, + {"lava", FLUID_LAVA }, + {"rum", FLUID_RUM }, + {"swamp", FLUID_SWAMP }, + {"tea", FLUID_TEA }, + {"mead", FLUID_MEAD }, +}; + +const std::unordered_map WeaponTypesMap = { + {"sword", WEAPON_SWORD}, + {"club", WEAPON_CLUB}, + {"axe", WEAPON_AXE}, + {"shield", WEAPON_SHIELD}, + {"distance", WEAPON_DISTANCE}, + {"wand", WEAPON_WAND}, + {"ammunition", WEAPON_AMMO}, + {"quiver", WEAPON_QUIVER}, +}; + +class ItemParse final : public Items +{ + public: + static void initParse(const std::string& tmpStrValue, pugi::xml_node attributeNode, pugi::xml_attribute valueAttribute, ItemType& itemType); + + private: + static void parseType(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType); + static void parseDescription(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType); + static void parseRuneSpellName(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType); + static void parseWeight(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType); + static void parseShowCount(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType); + static void parseArmor(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType); + static void parseDefense(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType); + static void parseExtraDefense(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType); + static void parseAttack(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType); + static void parseRotateTo(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType); + static void parseWrapContainer(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType); + static void parseImbuingSlot(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType); + static void parseWrapableTo(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType); + static void parseMoveable(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType); + static void parsePodium(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType); + static void parseBlockProjectTile(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType); + static void parsePickupable(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType); + static void parseFloorChange(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType); + static void parseCorpseType(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType); + static void parseContainerSize(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType); + static void parseFluidSource(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType); + static void parseWriteables(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType); + static void parseWeaponType(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType); + static void parseSlotType(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType); + static void parseAmmoType(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType); + static void parseShootType(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType); + static void parseMagicEffect(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType); + static void parseLootType(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType); + static void parseRange(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType); + static void parseDuration(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType); + static void parseTransform(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType); + static void parseCharges(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType); + static void parseShowAttributes(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType); + static void parseHitChance(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType); + static void parseInvisible(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType); + static void parseSpeed(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType); + static void parseHealthAndMana(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType); + static void parseSkills(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType); + static void parseCriticalHit(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType); + static void parseLifeAndManaLeech(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType); + static void parseMaxHitAndManaPoints(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType); + static void parseMagicPoints(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType); + static void parseFieldAbsorbPercent(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType); + static void parseAbsorbPercent(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType); + static void parseSupressDrunk(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType); + static void parseField(const std::string& tmpStrValue, pugi::xml_node attributeNode, pugi::xml_attribute valueAttribute, ItemType& itemType); + static void parseReplaceable(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType); + static void parseLevelDoor(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType); + static void parseBeds(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType); + static void parseElement(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType); + static void parseWalk(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType); + static void parseAllowDistanceRead(const std::string& tmpStrValue, pugi::xml_attribute valueAttribute, ItemType& itemType); + + private: + // Parent of the function: static void parseField + static std::tuple parseFieldConditions(ConditionId_t conditionId, ConditionType_t conditionType, std::string lowerStringValue, pugi::xml_attribute valueAttribute); + static CombatType_t parseFieldCombatType(std::string string, pugi::xml_attribute valueAttribute); + static void parseFieldCombatDamage(ConditionDamage *conditionDamage, std::string stringValue, pugi::xml_node attributeNode); +}; + +#endif // SRC_ITEMS_FUNCTIONS_ITEM_PARSE_HPP_ diff --git a/src/items/item.cpp b/src/items/item.cpp index 6a8a38b3376..f6d2c9f2c18 100644 --- a/src/items/item.cpp +++ b/src/items/item.cpp @@ -20,6 +20,7 @@ #include "otpch.h" #include "items/item.h" +#include "items/functions/item_parse.hpp" #include "items/containers/container.h" #include "game/movement/teleport.h" #include "items/trashholder.h" diff --git a/src/items/item.h b/src/items/item.h index 0be9cc7416d..ffa74a990d4 100644 --- a/src/items/item.h +++ b/src/items/item.h @@ -918,9 +918,9 @@ class Item : virtual public Thing count = n; } - static uint32_t countByType(const Item* i, int32_t subType) { - if (subType == -1 || subType == i->getSubType()) { - return i->getItemCount(); + static uint32_t countByType(const Item* item, int32_t subType) { + if (subType == -1 || subType == item->getSubType()) { + return item->getItemCount(); } return 0; diff --git a/src/items/items.cpp b/src/items/items.cpp index be2451d647a..6416c2095a6 100644 --- a/src/items/items.cpp +++ b/src/items/items.cpp @@ -19,6 +19,7 @@ #include "otpch.h" +#include "items/functions/item_parse.hpp" #include "items/items.h" #include "creatures/combat/spells.h" #include "items/weapons/weapons.h" @@ -409,36 +410,38 @@ void Items::buildInventoryList() std::sort(inventory.begin(), inventory.end()); } -void Items::parseItemNode(const pugi::xml_node& itemNode, uint16_t id) -{ +void Items::parseItemNode(const pugi::xml_node & itemNode, uint16_t id) { if (id >= items.size()) { items.resize(id + 1); } - ItemType& iType = items[id]; + ItemType & iType = items[id]; iType.id = id; - ItemType& it = getItemType(id); - if (it.id == 0) { + ItemType & itemType = getItemType(id); + if (itemType.id == 0) { return; } - if (!it.name.empty()) { + if (!itemType.name.empty()) { SPDLOG_WARN("[Items::parseItemNode] - Duplicate item with id: {}", id); return; } - it.name = itemNode.attribute("name").as_string(); + itemType.name = itemNode.attribute("name").as_string(); - nameToItems.insert({ asLowerCaseString(it.name), id }); + nameToItems.insert({ + asLowerCaseString(itemType.name), + id + }); pugi::xml_attribute articleAttribute = itemNode.attribute("article"); if (articleAttribute) { - it.article = articleAttribute.as_string(); + itemType.article = articleAttribute.as_string(); } pugi::xml_attribute pluralAttribute = itemNode.attribute("plural"); if (pluralAttribute) { - it.pluralName = pluralAttribute.as_string(); + itemType.pluralName = pluralAttribute.as_string(); } for (auto attributeNode : itemNode.children()) { @@ -453,565 +456,18 @@ void Items::parseItemNode(const pugi::xml_node& itemNode, uint16_t id) } std::string tmpStrValue = asLowerCaseString(keyAttribute.as_string()); - - // Put here because have many conditions (C1601 - compiler limit: blocks nested too deeply) - if (tmpStrValue == "type") { - tmpStrValue = asLowerCaseString(valueAttribute.as_string()); - if (tmpStrValue == "key") { - it.type = ITEM_TYPE_KEY; - } else if (tmpStrValue == "magicfield") { - it.type = ITEM_TYPE_MAGICFIELD; - } else if (tmpStrValue == "container") { - it.group = ITEM_GROUP_CONTAINER; - it.type = ITEM_TYPE_CONTAINER; - } else if (tmpStrValue == "depot") { - it.type = ITEM_TYPE_DEPOT; - } else if (tmpStrValue == "rewardchest") { - it.type = ITEM_TYPE_REWARDCHEST; - } else if (tmpStrValue == "carpet") { - it.type = ITEM_TYPE_CARPET; - } else if (tmpStrValue == "mailbox") { - it.type = ITEM_TYPE_MAILBOX; - } else if (tmpStrValue == "trashholder") { - it.type = ITEM_TYPE_TRASHHOLDER; - } else if (tmpStrValue == "teleport") { - it.type = ITEM_TYPE_TELEPORT; - } else if (tmpStrValue == "door") { - it.type = ITEM_TYPE_DOOR; - } else if (tmpStrValue == "bed") { - it.type = ITEM_TYPE_BED; - } else if (tmpStrValue == "rune") { - it.type = ITEM_TYPE_RUNE; - } else if (tmpStrValue == "supply") { - it.type = ITEM_TYPE_SUPPLY; - } else if (tmpStrValue == "creatureproduct") { - it.type = ITEM_TYPE_CREATUREPRODUCT; - } else if (tmpStrValue == "food") { - it.type = ITEM_TYPE_FOOD; - } else if (tmpStrValue == "valuable") { - it.type = ITEM_TYPE_VALUABLE; - } else if (tmpStrValue == "potion") { - it.type = ITEM_TYPE_POTION; - } else { - SPDLOG_WARN("[Items::parseItemNode] - Unknown type: {}", - valueAttribute.as_string()); - } - } else if (tmpStrValue == "description") { - it.description = valueAttribute.as_string(); - } else if (tmpStrValue == "runespellname") { - it.runeSpellName = valueAttribute.as_string(); - } else if (tmpStrValue == "weight") { - it.weight = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "showcount") { - it.showCount = valueAttribute.as_bool(); - } else if (tmpStrValue == "armor") { - it.armor = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "defense") { - it.defense = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "extradef") { - it.extraDefense = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "attack") { - it.attack = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "rotateto") { - it.rotateTo = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "wrapcontainer") { - it.wrapContainer = valueAttribute.as_bool(); - } else if (tmpStrValue == "imbuingslots") { - it.imbuingSlots = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "wrapableto" || tmpStrValue == "unwrapableto") { - it.wrapableTo = pugi::cast(valueAttribute.value()); - it.wrapable = true; - } else if (tmpStrValue == "moveable" || tmpStrValue == "movable") { - it.moveable = valueAttribute.as_bool(); - } else if (tmpStrValue == "ispodium") { - it.isPodium = valueAttribute.as_bool(); - } else if (tmpStrValue == "blockprojectile") { - it.blockProjectile = valueAttribute.as_bool(); - } else if (tmpStrValue == "allowpickupable" || tmpStrValue == "pickupable") { - it.allowPickupable = valueAttribute.as_bool(); - } else if (tmpStrValue == "floorchange") { - tmpStrValue = asLowerCaseString(valueAttribute.as_string()); - if (tmpStrValue == "down") { - it.floorChange |= TILESTATE_FLOORCHANGE_DOWN; - } else if (tmpStrValue == "north") { - it.floorChange |= TILESTATE_FLOORCHANGE_NORTH; - } else if (tmpStrValue == "south") { - it.floorChange |= TILESTATE_FLOORCHANGE_SOUTH; - } else if (tmpStrValue == "southalt") { - it.floorChange |= TILESTATE_FLOORCHANGE_SOUTH_ALT; - } else if (tmpStrValue == "west") { - it.floorChange |= TILESTATE_FLOORCHANGE_WEST; - } else if (tmpStrValue == "east") { - it.floorChange |= TILESTATE_FLOORCHANGE_EAST; - } else if (tmpStrValue == "eastalt") { - it.floorChange |= TILESTATE_FLOORCHANGE_EAST_ALT; - } else { - SPDLOG_WARN("[Items::parseItemNode] - Unknown floorChange: {}", - valueAttribute.as_string()); - } - } else if (tmpStrValue == "corpsetype") { - tmpStrValue = asLowerCaseString(valueAttribute.as_string()); - if (tmpStrValue == "venom") { - it.corpseType = RACE_VENOM; - } else if (tmpStrValue == "blood") { - it.corpseType = RACE_BLOOD; - } else if (tmpStrValue == "undead") { - it.corpseType = RACE_UNDEAD; - } else if (tmpStrValue == "fire") { - it.corpseType = RACE_FIRE; - } else if (tmpStrValue == "energy") { - it.corpseType = RACE_ENERGY; - } else { - SPDLOG_WARN("[Items::parseItemNode] - Unknown corpseType: {}", - valueAttribute.as_string()); - } - } else if (tmpStrValue == "containersize") { - it.maxItems = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "fluidsource") { - tmpStrValue = asLowerCaseString(valueAttribute.as_string()); - if (tmpStrValue == "water") { - it.fluidSource = FLUID_WATER; - } else if (tmpStrValue == "blood") { - it.fluidSource = FLUID_BLOOD; - } else if (tmpStrValue == "beer") { - it.fluidSource = FLUID_BEER; - } else if (tmpStrValue == "slime") { - it.fluidSource = FLUID_SLIME; - } else if (tmpStrValue == "lemonade") { - it.fluidSource = FLUID_LEMONADE; - } else if (tmpStrValue == "milk") { - it.fluidSource = FLUID_MILK; - } else if (tmpStrValue == "mana") { - it.fluidSource = FLUID_MANA; - } else if (tmpStrValue == "life") { - it.fluidSource = FLUID_LIFE; - } else if (tmpStrValue == "oil") { - it.fluidSource = FLUID_OIL; - } else if (tmpStrValue == "urine") { - it.fluidSource = FLUID_URINE; - } else if (tmpStrValue == "coconut") { - it.fluidSource = FLUID_COCONUTMILK; - } else if (tmpStrValue == "wine") { - it.fluidSource = FLUID_WINE; - } else if (tmpStrValue == "mud") { - it.fluidSource = FLUID_MUD; - } else if (tmpStrValue == "fruitjuice") { - it.fluidSource = FLUID_FRUITJUICE; - } else if (tmpStrValue == "lava") { - it.fluidSource = FLUID_LAVA; - } else if (tmpStrValue == "rum") { - it.fluidSource = FLUID_RUM; - } else if (tmpStrValue == "swamp") { - it.fluidSource = FLUID_SWAMP; - } else if (tmpStrValue == "tea") { - it.fluidSource = FLUID_TEA; - } else if (tmpStrValue == "mead") { - it.fluidSource = FLUID_MEAD; - } else { - SPDLOG_WARN("[Items::parseItemNode] - Unknown fluidSource: {}", - valueAttribute.as_string()); - } - } else if (tmpStrValue == "readable") { - it.canReadText = valueAttribute.as_bool(); - } else if (tmpStrValue == "writeable") { - it.canWriteText = valueAttribute.as_bool(); - it.canReadText = it.canWriteText; - } else if (tmpStrValue == "maxtextlen") { - it.maxTextLen = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "writeonceitemid") { - it.writeOnceItemId = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "weapontype") { - tmpStrValue = asLowerCaseString(valueAttribute.as_string()); - if (tmpStrValue == "sword") { - it.weaponType = WEAPON_SWORD; - } else if (tmpStrValue == "club") { - it.weaponType = WEAPON_CLUB; - } else if (tmpStrValue == "axe") { - it.weaponType = WEAPON_AXE; - } else if (tmpStrValue == "shield") { - it.weaponType = WEAPON_SHIELD; - } else if (tmpStrValue == "distance") { - it.weaponType = WEAPON_DISTANCE; - } else if (tmpStrValue == "wand") { - it.weaponType = WEAPON_WAND; - } else if (tmpStrValue == "ammunition") { - it.weaponType = WEAPON_AMMO; - } else if (tmpStrValue == "quiver") { - it.weaponType = WEAPON_QUIVER; - } else { - SPDLOG_WARN("[Items::parseItemNode] - Unknown weaponType: {}", - valueAttribute.as_string()); - } - } else if (tmpStrValue == "slottype") { - tmpStrValue = asLowerCaseString(valueAttribute.as_string()); - if (tmpStrValue == "head") { - it.slotPosition |= SLOTP_HEAD; - } else if (tmpStrValue == "body") { - it.slotPosition |= SLOTP_ARMOR; - } else if (tmpStrValue == "legs") { - it.slotPosition |= SLOTP_LEGS; - } else if (tmpStrValue == "feet") { - it.slotPosition |= SLOTP_FEET; - } else if (tmpStrValue == "backpack") { - it.slotPosition |= SLOTP_BACKPACK; - } else if (tmpStrValue == "two-handed") { - it.slotPosition |= SLOTP_TWO_HAND; - } else if (tmpStrValue == "right-hand") { - it.slotPosition &= ~SLOTP_LEFT; - } else if (tmpStrValue == "left-hand") { - it.slotPosition &= ~SLOTP_RIGHT; - } else if (tmpStrValue == "necklace") { - it.slotPosition |= SLOTP_NECKLACE; - } else if (tmpStrValue == "ring") { - it.slotPosition |= SLOTP_RING; - } else if (tmpStrValue == "ammo") { - it.slotPosition |= SLOTP_AMMO; - } else if (tmpStrValue == "hand") { - it.slotPosition |= SLOTP_HAND; - } else { - SPDLOG_WARN("[Items::parseItemNode] - Unknown slotType: {}", - valueAttribute.as_string()); - } - } else if (tmpStrValue == "ammotype") { - it.ammoType = getAmmoType(asLowerCaseString(valueAttribute.as_string())); - if (it.ammoType == AMMO_NONE) { - SPDLOG_WARN("[Items::parseItemNode] - Unknown ammoType: {}", - valueAttribute.as_string()); - } - } else if (tmpStrValue == "shoottype") { - ShootType_t shoot = getShootType(asLowerCaseString(valueAttribute.as_string())); - if (shoot != CONST_ANI_NONE) { - it.shootType = shoot; - } else { - SPDLOG_WARN("[Items::parseItemNode] - Unknown shootType: {}", - valueAttribute.as_string()); - } - } else if (tmpStrValue == "effect") { - MagicEffectClasses effect = getMagicEffect(asLowerCaseString(valueAttribute.as_string())); - if (effect != CONST_ME_NONE) { - it.magicEffect = effect; - } else { - SPDLOG_WARN("[Items::parseItemNode] - Unknown effect: {}", - valueAttribute.as_string()); - } - } else if (tmpStrValue == "loottype") { - it.type = getLootType(valueAttribute.as_string()); - } else if (tmpStrValue == "range") { - it.shootRange = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "stopduration") { - it.stopTime = valueAttribute.as_bool(); - } else if (tmpStrValue == "decayto") { - it.decayTo = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "transformequipto") { - it.transformEquipTo = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "transformdeequipto") { - it.transformDeEquipTo = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "duration") { - it.decayTime = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "showduration") { - it.showDuration = valueAttribute.as_bool(); - } else if (tmpStrValue == "charges") { - it.charges = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "showcharges") { - it.showCharges = valueAttribute.as_bool(); - } else if (tmpStrValue == "showattributes") { - it.showAttributes = valueAttribute.as_bool(); - } else if (tmpStrValue == "hitchance") { - it.hitChance = std::min(100, std::max(-100, pugi::cast(valueAttribute.value()))); - } else if (tmpStrValue == "maxhitchance") { - it.maxHitChance = std::min(100, pugi::cast(valueAttribute.value())); - } else if (tmpStrValue == "invisible") { - it.getAbilities().invisible = valueAttribute.as_bool(); - } else if (tmpStrValue == "speed") { - it.getAbilities().speed = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "healthgain") { - Abilities& abilities = it.getAbilities(); - abilities.regeneration = true; - abilities.healthGain = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "healthticks") { - Abilities& abilities = it.getAbilities(); - abilities.regeneration = true; - abilities.healthTicks = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "managain") { - Abilities& abilities = it.getAbilities(); - abilities.regeneration = true; - abilities.manaGain = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "manaticks") { - Abilities& abilities = it.getAbilities(); - abilities.regeneration = true; - abilities.manaTicks = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "manashield") { - it.getAbilities().manaShield = valueAttribute.as_bool(); - } else if (tmpStrValue == "skillsword") { - it.getAbilities().skills[SKILL_SWORD] = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "skillaxe") { - it.getAbilities().skills[SKILL_AXE] = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "skillclub") { - it.getAbilities().skills[SKILL_CLUB] = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "skilldist") { - it.getAbilities().skills[SKILL_DISTANCE] = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "skillfish") { - it.getAbilities().skills[SKILL_FISHING] = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "skillshield") { - it.getAbilities().skills[SKILL_SHIELD] = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "skillfist") { - it.getAbilities().skills[SKILL_FIST] = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "skillcriticalchance") { - it.getAbilities().skills[SKILL_CRITICAL_HIT_CHANCE] = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "skillcriticaldamage") { - it.getAbilities().skills[SKILL_CRITICAL_HIT_DAMAGE] = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "skilllifechance") { - it.getAbilities().skills[SKILL_LIFE_LEECH_CHANCE] = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "skilllifeamount") { - it.getAbilities().skills[SKILL_LIFE_LEECH_AMOUNT] = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "skillmanachance") { - it.getAbilities().skills[SKILL_MANA_LEECH_CHANCE] = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "skillmanaamount") { - it.getAbilities().skills[SKILL_MANA_LEECH_AMOUNT] = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "maxhitpoints") { - it.getAbilities().stats[STAT_MAXHITPOINTS] = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "maxhitpointspercent") { - it.getAbilities().statsPercent[STAT_MAXHITPOINTS] = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "maxmanapoints") { - it.getAbilities().stats[STAT_MAXMANAPOINTS] = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "maxmanapointspercent") { - it.getAbilities().statsPercent[STAT_MAXMANAPOINTS] = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "magicpoints" || tmpStrValue == "magiclevelpoints") { - it.getAbilities().stats[STAT_MAGICPOINTS] = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "magicpointspercent") { - it.getAbilities().statsPercent[STAT_MAGICPOINTS] = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "fieldabsorbpercentenergy") { - it.getAbilities().fieldAbsorbPercent[combatTypeToIndex(COMBAT_ENERGYDAMAGE)] += pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "fieldabsorbpercentfire") { - it.getAbilities().fieldAbsorbPercent[combatTypeToIndex(COMBAT_FIREDAMAGE)] += pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "fieldabsorbpercentpoison" || tmpStrValue == "fieldabsorpercentearth") { - it.getAbilities().fieldAbsorbPercent[combatTypeToIndex(COMBAT_EARTHDAMAGE)] += pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "absorbpercentall" || tmpStrValue == "absorbpercentallelements") { - int16_t value = pugi::cast(valueAttribute.value()); - Abilities& abilities = it.getAbilities(); - for (auto& i : abilities.absorbPercent) { - i += value; - } - } else if (tmpStrValue == "absorbpercentelements") { - int16_t value = pugi::cast(valueAttribute.value()); - Abilities& abilities = it.getAbilities(); - abilities.absorbPercent[combatTypeToIndex(COMBAT_ENERGYDAMAGE)] += value; - abilities.absorbPercent[combatTypeToIndex(COMBAT_FIREDAMAGE)] += value; - abilities.absorbPercent[combatTypeToIndex(COMBAT_EARTHDAMAGE)] += value; - abilities.absorbPercent[combatTypeToIndex(COMBAT_ICEDAMAGE)] += value; - } else if (tmpStrValue == "absorbpercentmagic") { - int16_t value = pugi::cast(valueAttribute.value()); - Abilities& abilities = it.getAbilities(); - abilities.absorbPercent[combatTypeToIndex(COMBAT_ENERGYDAMAGE)] += value; - abilities.absorbPercent[combatTypeToIndex(COMBAT_FIREDAMAGE)] += value; - abilities.absorbPercent[combatTypeToIndex(COMBAT_EARTHDAMAGE)] += value; - abilities.absorbPercent[combatTypeToIndex(COMBAT_ICEDAMAGE)] += value; - abilities.absorbPercent[combatTypeToIndex(COMBAT_HOLYDAMAGE)] += value; - abilities.absorbPercent[combatTypeToIndex(COMBAT_DEATHDAMAGE)] += value; - } else if (tmpStrValue == "absorbpercentenergy") { - it.getAbilities().absorbPercent[combatTypeToIndex(COMBAT_ENERGYDAMAGE)] += pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "absorbpercentfire") { - it.getAbilities().absorbPercent[combatTypeToIndex(COMBAT_FIREDAMAGE)] += pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "absorbpercentpoison" || tmpStrValue == "absorbpercentearth") { - it.getAbilities().absorbPercent[combatTypeToIndex(COMBAT_EARTHDAMAGE)] += pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "absorbpercentice") { - it.getAbilities().absorbPercent[combatTypeToIndex(COMBAT_ICEDAMAGE)] += pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "absorbpercentholy") { - it.getAbilities().absorbPercent[combatTypeToIndex(COMBAT_HOLYDAMAGE)] += pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "absorbpercentdeath") { - it.getAbilities().absorbPercent[combatTypeToIndex(COMBAT_DEATHDAMAGE)] += pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "absorbpercentlifedrain") { - it.getAbilities().absorbPercent[combatTypeToIndex(COMBAT_LIFEDRAIN)] += pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "absorbpercentmanadrain") { - it.getAbilities().absorbPercent[combatTypeToIndex(COMBAT_MANADRAIN)] += pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "absorbpercentdrown") { - it.getAbilities().absorbPercent[combatTypeToIndex(COMBAT_DROWNDAMAGE)] += pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "absorbpercentphysical") { - it.getAbilities().absorbPercent[combatTypeToIndex(COMBAT_PHYSICALDAMAGE)] += pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "absorbpercenthealing") { - it.getAbilities().absorbPercent[combatTypeToIndex(COMBAT_HEALING)] += pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "suppressdrunk") { - if (valueAttribute.as_bool()) { - it.getAbilities().conditionSuppressions |= CONDITION_DRUNK; - } - } else if (tmpStrValue == "suppressenergy") { - if (valueAttribute.as_bool()) { - it.getAbilities().conditionSuppressions |= CONDITION_ENERGY; - } - } else if (tmpStrValue == "suppressfire") { - if (valueAttribute.as_bool()) { - it.getAbilities().conditionSuppressions |= CONDITION_FIRE; - } - } else if (tmpStrValue == "suppresspoison") { - if (valueAttribute.as_bool()) { - it.getAbilities().conditionSuppressions |= CONDITION_POISON; - } - } else if (tmpStrValue == "suppressdrown") { - if (valueAttribute.as_bool()) { - it.getAbilities().conditionSuppressions |= CONDITION_DROWN; - } - } else if (tmpStrValue == "suppressphysical") { - if (valueAttribute.as_bool()) { - it.getAbilities().conditionSuppressions |= CONDITION_BLEEDING; - } - } else if (tmpStrValue == "suppressfreeze") { - if (valueAttribute.as_bool()) { - it.getAbilities().conditionSuppressions |= CONDITION_FREEZING; - } - } else if (tmpStrValue == "suppressdazzle") { - if (valueAttribute.as_bool()) { - it.getAbilities().conditionSuppressions |= CONDITION_DAZZLED; - } - } else if (tmpStrValue == "suppresscurse") { - if (valueAttribute.as_bool()) { - it.getAbilities().conditionSuppressions |= CONDITION_CURSED; - } - } else if (tmpStrValue == "field") { - CombatType_t combatType = COMBAT_NONE; - ConditionDamage* conditionDamage = nullptr; - - tmpStrValue = asLowerCaseString(valueAttribute.as_string()); - if (tmpStrValue == "fire") { - conditionDamage = new ConditionDamage(CONDITIONID_COMBAT, CONDITION_FIRE); - combatType = COMBAT_FIREDAMAGE; - } else if (tmpStrValue == "energy") { - conditionDamage = new ConditionDamage(CONDITIONID_COMBAT, CONDITION_ENERGY); - combatType = COMBAT_ENERGYDAMAGE; - } else if (tmpStrValue == "poison") { - conditionDamage = new ConditionDamage(CONDITIONID_COMBAT, CONDITION_POISON); - combatType = COMBAT_EARTHDAMAGE; - } else if (tmpStrValue == "drown") { - conditionDamage = new ConditionDamage(CONDITIONID_COMBAT, CONDITION_DROWN); - combatType = COMBAT_DROWNDAMAGE; - } else if (tmpStrValue == "physical") { - conditionDamage = new ConditionDamage(CONDITIONID_COMBAT, CONDITION_BLEEDING); - combatType = COMBAT_PHYSICALDAMAGE; - } else { - SPDLOG_WARN("[Items::parseItemNode] Unknown field value: {}", - valueAttribute.as_string()); - } - - if (combatType != COMBAT_NONE) { - it.combatType = combatType; - it.conditionDamage.reset(conditionDamage); - uint32_t ticks = 0; - int32_t damage = 0; - int32_t start = 0; - int32_t count = 1; - - for (auto subAttributeNode : attributeNode.children()) { - pugi::xml_attribute subKeyAttribute = subAttributeNode.attribute("key"); - if (!subKeyAttribute) { - continue; - } - - pugi::xml_attribute subValueAttribute = subAttributeNode.attribute("value"); - if (!subValueAttribute) { - continue; - } - - tmpStrValue = asLowerCaseString(subKeyAttribute.as_string()); - if (tmpStrValue == "ticks") { - ticks = pugi::cast(subValueAttribute.value()); - } else if (tmpStrValue == "count") { - count = std::max(1, pugi::cast(subValueAttribute.value())); - } else if (tmpStrValue == "start") { - start = std::max(0, pugi::cast(subValueAttribute.value())); - } else if (tmpStrValue == "damage") { - damage = -pugi::cast(subValueAttribute.value()); - - if (start > 0) { - std::list damageList; - ConditionDamage::generateDamageList(damage, start, damageList); - for (int32_t damageValue : damageList) { - conditionDamage->addDamage(1, ticks, -damageValue); - } - - start = 0; - } else { - conditionDamage->addDamage(count, ticks, damage); - } - } - } - - conditionDamage->setParam(CONDITION_PARAM_FIELD, 1); - - if (conditionDamage->getTotalDamage() > 0) { - conditionDamage->setParam(CONDITION_PARAM_FORCEUPDATE, 1); - } - } - } else if (tmpStrValue == "replaceable") { - it.replaceable = valueAttribute.as_bool(); - } else if (tmpStrValue == "partnerdirection") { - it.bedPartnerDir = getDirection(valueAttribute.as_string()); - } else if (tmpStrValue == "leveldoor") { - it.levelDoor = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "maletransformto" || tmpStrValue == "malesleeper") { - uint16_t value = pugi::cast(valueAttribute.value()); - it.transformToOnUse[PLAYERSEX_MALE] = value; - ItemType& other = getItemType(value); - if (other.transformToFree == 0) { - other.transformToFree = it.id; - } - - if (it.transformToOnUse[PLAYERSEX_FEMALE] == 0) { - it.transformToOnUse[PLAYERSEX_FEMALE] = value; - } - } else if (tmpStrValue == "femaletransformto" || tmpStrValue == "femalesleeper") { - uint16_t value = pugi::cast(valueAttribute.value()); - it.transformToOnUse[PLAYERSEX_FEMALE] = value; - - ItemType& other = getItemType(value); - if (other.transformToFree == 0) { - other.transformToFree = it.id; - } - - if (it.transformToOnUse[PLAYERSEX_MALE] == 0) { - it.transformToOnUse[PLAYERSEX_MALE] = value; - } - } else if (tmpStrValue == "transformto") { - it.transformToFree = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "destroyto") { - it.destroyTo = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "elementice") { - Abilities& abilities = it.getAbilities(); - abilities.elementDamage = pugi::cast(valueAttribute.value()); - abilities.elementType = COMBAT_ICEDAMAGE; - } else if (tmpStrValue == "elementearth") { - Abilities& abilities = it.getAbilities(); - abilities.elementDamage = pugi::cast(valueAttribute.value()); - abilities.elementType = COMBAT_EARTHDAMAGE; - } else if (tmpStrValue == "elementfire") { - Abilities& abilities = it.getAbilities(); - abilities.elementDamage = pugi::cast(valueAttribute.value()); - abilities.elementType = COMBAT_FIREDAMAGE; - } else if (tmpStrValue == "elementenergy") { - Abilities& abilities = it.getAbilities(); - abilities.elementDamage = pugi::cast(valueAttribute.value()); - abilities.elementType = COMBAT_ENERGYDAMAGE; - } else if (tmpStrValue == "elementdeath") { - Abilities& abilities = it.getAbilities(); - abilities.elementDamage = pugi::cast(valueAttribute.value()); - abilities.elementType = COMBAT_DEATHDAMAGE; - } else if (tmpStrValue == "elementholy") { - Abilities& abilities = it.getAbilities(); - abilities.elementDamage = pugi::cast(valueAttribute.value()); - abilities.elementType = COMBAT_HOLYDAMAGE; - } else if (tmpStrValue == "walkstack") { - it.walkStack = valueAttribute.as_bool(); - } else if (tmpStrValue == "blocking") { - it.blockSolid = valueAttribute.as_bool(); - } else if (tmpStrValue == "allowdistread") { - it.allowDistRead = booleanString(valueAttribute.as_string()); + auto parseAttribute = ItemParseAttributesMap.find(tmpStrValue); + if (parseAttribute != ItemParseAttributesMap.end()) { + ItemParse::initParse(tmpStrValue, attributeNode, valueAttribute, itemType); } else { SPDLOG_WARN("[Items::parseItemNode] - Unknown key value: {}", keyAttribute.as_string()); } } - //check bed items - if ((it.transformToFree != 0 || it.transformToOnUse[PLAYERSEX_FEMALE] != 0 || it.transformToOnUse[PLAYERSEX_MALE] != 0) && it.type != ITEM_TYPE_BED) { - SPDLOG_WARN("[Items::parseItemNode] - Item {} is not set as a bed-type", it.id); + // Check bed items + if ((itemType.transformToFree != 0 || itemType.transformToOnUse[PLAYERSEX_FEMALE] != 0 || itemType.transformToOnUse[PLAYERSEX_MALE] != 0) && itemType.type != ITEM_TYPE_BED) { + SPDLOG_WARN("[Items::parseItemNode] - Item {} is not set as a bed-type", itemType.id); } } diff --git a/src/items/items.h b/src/items/items.h index ca7b3d78e81..392a36f288c 100644 --- a/src/items/items.h +++ b/src/items/items.h @@ -212,8 +212,8 @@ class ItemType ShootType_t shootType = CONST_ANI_NONE; RaceType_t corpseType = RACE_NONE; FluidTypes_t fluidSource = FLUID_NONE; + TileFlags_t floorChange = TILESTATE_NONE; - uint8_t floorChange = 0; uint8_t alwaysOnTopOrder = 0; uint8_t lightLevel = 0; uint8_t lightColor = 0; @@ -276,6 +276,8 @@ class Items uint16_t getItemIdByName(const std::string& name); + ItemTypes_t getLootType(const std::string& strValue); + uint32_t majorVersion = 0; uint32_t minorVersion = 0; uint32_t buildNumber = 0; @@ -295,7 +297,6 @@ class Items NameMap nameToItems; private: - ItemTypes_t getLootType(const std::string& strValue); std::map reverseItemMap; std::vector items; diff --git a/src/items/items_definitions.hpp b/src/items/items_definitions.hpp index 6a032cba906..1b6b38e3fc5 100644 --- a/src/items/items_definitions.hpp +++ b/src/items/items_definitions.hpp @@ -500,4 +500,119 @@ enum CylinderLink_t { LINK_NEAR, }; +enum ItemParseAttributes_t { + ITEM_PARSE_TYPE, + ITEM_PARSE_DESCRIPTION, + ITEM_PARSE_RUNESPELLNAME, + ITEM_PARSE_WEIGHT, + ITEM_PARSE_SHOWCOUNT, + ITEM_PARSE_ARMOR, + ITEM_PARSE_DEFENSE, + ITEM_PARSE_EXTRADEF, + ITEM_PARSE_ATTACK, + ITEM_PARSE_ROTATETO, + ITEM_PARSE_WRAPCONTAINER, + ITEM_PARSE_IMBUINGSLOT, + ITEM_PARSE_WRAPABLETO, + ITEM_PARSE_MOVEABLE, + ITEM_PARSE_PODIUM, + ITEM_PARSE_BLOCKPROJECTILE, + ITEM_PARSE_PICKUPABLE, + ITEM_PARSE_FLOORCHANGE, + ITEM_PARSE_CORPSETYPE, + ITEM_PARSE_CONTAINERSIZE, + ITEM_PARSE_FLUIDSOURCE, + ITEM_PARSE_READABLE, + ITEM_PARSE_WRITEABLE, + ITEM_PARSE_MAXTEXTLEN, + ITEM_PARSE_WRITEONCEITEMID, + ITEM_PARSE_WEAPONTYPE, + ITEM_PARSE_SLOTTYPE, + ITEM_PARSE_AMMOTYPE, + ITEM_PARSE_SHOOTTYPE, + ITEM_PARSE_EFFECT, + ITEM_PARSE_LOOTTYPE, + ITEM_PARSE_RANGE, + ITEM_PARSE_STOPDURATION, + ITEM_PARSE_DECAYTO, + ITEM_PARSE_TRANSFORMEQUIPTO, + ITEM_PARSE_TRANSFORMDEEQUIPTO, + ITEM_PARSE_DURATION, + ITEM_PARSE_SHOWDURATION, + ITEM_PARSE_CHARGES, + ITEM_PARSE_SHOWCHARGES, + ITEM_PARSE_SHOWATTRIBUTES, + ITEM_PARSE_HITCHANCE, + ITEM_PARSE_MAXHITCHANCE, + ITEM_PARSE_INVISIBLE, + ITEM_PARSE_SPEED, + ITEM_PARSE_HEALTHGAIN, + ITEM_PARSE_HEALTHTICKS, + ITEM_PARSE_MANAGAIN, + ITEM_PARSE_MANATICKS, + ITEM_PARSE_MANASHIELD, + ITEM_PARSE_SKILLSWORD, + ITEM_PARSE_SKILLAXE, + ITEM_PARSE_SKILLCLUB, + ITEM_PARSE_SKILLDIST, + ITEM_PARSE_SKILLFISH, + ITEM_PARSE_SKILLSHIELD, + ITEM_PARSE_SKILLFIST, + ITEM_PARSE_CRITICALHITCHANCE, + ITEM_PARSE_CRITICALHITDAMAGE, + ITEM_PARSE_LIFELEECHCHANCE, + ITEM_PARSE_LIFELEECHAMOUNT, + ITEM_PARSE_MANALEECHCHANCE, + ITEM_PARSE_MANALEECHAMOUNT, + ITEM_PARSE_MAXHITPOINTS, + ITEM_PARSE_MAXHITPOINTSPERCENT, + ITEM_PARSE_MAXMANAPOINTS, + ITEM_PARSE_MAXMANAPOINTSPERCENT, + ITEM_PARSE_MAGICPOINTS, + ITEM_PARSE_MAGICPOINTSPERCENT, + ITEM_PARSE_FIELDABSORBPERCENTENERGY, + ITEM_PARSE_FIELDABSORBPERCENTFIRE, + ITEM_PARSE_FIELDABSORBPERCENTPOISON, + ITEM_PARSE_ABSORBPERCENTALL, + ITEM_PARSE_ABSORBPERCENTELEMENTS, + ITEM_PARSE_ABSORBPERCENTMAGIC, + ITEM_PARSE_ABSORBPERCENTENERGY, + ITEM_PARSE_ABSORBPERCENTFIRE, + ITEM_PARSE_ABSORBPERCENTPOISON, + ITEM_PARSE_ABSORBPERCENTICE, + ITEM_PARSE_ABSORBPERCENTHOLY, + ITEM_PARSE_ABSORBPERCENTDEATH, + ITEM_PARSE_ABSORBPERCENTLIFEDRAIN, + ITEM_PARSE_ABSORBPERCENTMANADRAIN, + ITEM_PARSE_ABSORBPERCENTDROWN, + ITEM_PARSE_ABSORBPERCENTPHYSICAL, + ITEM_PARSE_ABSORBPERCENTHEALING, + ITEM_PARSE_SUPPRESSDRUNK, + ITEM_PARSE_SUPPRESSENERGY, + ITEM_PARSE_SUPPRESSFIRE, + ITEM_PARSE_SUPPRESSPOISON, + ITEM_PARSE_SUPPRESSDROWN, + ITEM_PARSE_SUPPRESSPHYSICAL, + ITEM_PARSE_SUPPRESSFREEZE, + ITEM_PARSE_SUPPRESSDAZZLE, + ITEM_PARSE_SUPPRESSCURSE, + ITEM_PARSE_FIELD, + ITEM_PARSE_REPLACEABLE, + ITEM_PARSE_PARTNERDIRECTION, + ITEM_PARSE_LEVELDOOR, + ITEM_PARSE_MALETRANSFORMTO, + ITEM_PARSE_FEMALETRANSFORMTO, + ITEM_PARSE_TRANSFORMTO, + ITEM_PARSE_DESTROYTO, + ITEM_PARSE_ELEMENTICE, + ITEM_PARSE_ELEMENTEARTH, + ITEM_PARSE_ELEMENTFIRE, + ITEM_PARSE_ELEMENTENERGY, + ITEM_PARSE_ELEMENTDEATH, + ITEM_PARSE_ELEMENTHOLY, + ITEM_PARSE_WALKSTACK, + ITEM_PARSE_BLOCK_SOLID, + ITEM_PARSE_ALLOWDISTREAD, +}; + #endif // SRC_ITEMS_ITEMS_DEFINITIONS_HPP_