1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010-2019 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
7 // This program is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Affero General Public License as
9 // published by the Free Software Foundation, either version 3 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU Affero General Public License for more details.
17 // You should have received a copy of the GNU Affero General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "stdpch.h" // First include for pre-compiled headers.
28 #include "nel/georges/u_form_elm.h"
30 #include "item_sheet.h"
32 #include "game_share/characteristics.h"
33 #include "game_share/scores.h"
34 #include "game_share/skills.h"
35 #include "game_share/people.h"
36 #include "game_share/protection_type.h"
38 #include "nel/misc/i18n.h"
44 using namespace NLMISC
;
45 using namespace NLGEORGES
;
48 // ***************************************************************************
49 // Easy Macro to translate .typ enum
50 #define TRANSLATE_ENUM( _Var_, _unknown_, _func_, _key_) \
52 if( !item.getValueByName(val, _key_)) \
53 debug( toString("Key '%s' not found.", _key_) ); \
54 else if( (_Var_ = _func_(val)) == _unknown_ ) \
55 debug(#_Var_ " Unknown: " + val);
57 // Same but no error if the result of enum is _unknown_
58 #define TRANSLATE_ENUM_NODB( _Var_, _unknown_, _func_, _key_) \
60 if( !item.getValueByName(val, _key_)) \
61 debug( toString("Key '%s' not found.", _key_) ); \
66 // Easy macro to translate value from georges
67 #define TRANSLATE_VAL( _Var_, _key_ ) \
68 if(!item.getValueByName(_Var_, _key_)) \
69 debug( toString("Key '%s' not found.", _key_) ); \
72 // ***************************************************************************
73 //-----------------------------------------------
76 //-----------------------------------------------
77 CItemSheet::CItemSheet()
82 IdShapeFyrosFemale
= 0;
84 IdShapeMatisFemale
= 0;
86 IdShapeTrykerFemale
= 0;
88 IdShapeZoraiFemale
= 0;
91 ItemType
= ITEM_TYPE::UNDEFINED
;
92 Family
= ITEMFAMILY::UNDEFINED
;
103 IsItemNoRent
= false;
105 IsConsumable
= false;
112 Type
= CEntitySheet::ITEM
;
115 NeverHideWhenEquipped
= false;
116 RequiredCharac
= CHARACTERISTICS::Unknown
;
117 RequiredCharacLevel
= 0;
118 RequiredSkill
= SKILLS::unknown
;
119 RequiredSkillLevel
= 0;
120 IconColor
= NLMISC::CRGBA::White
;
121 IconBackColor
= NLMISC::CRGBA::White
;
122 IconOverColor
= NLMISC::CRGBA::White
;
123 IconOver2Color
= NLMISC::CRGBA::White
;
125 ItemOrigin
= ITEM_ORIGIN::UNKNOWN
;
127 Cosmetic
.VPValue
= 0;
128 Cosmetic
.Gender
= GSGENDER::unknown
;
130 Armor
.ArmorType
= ARMORTYPE::UNKNOWN
;
132 MeleeWeapon
.WeaponType
= WEAPONTYPE::UNKNOWN
;
133 MeleeWeapon
.Skill
= SKILLS::unknown
;
134 MeleeWeapon
.DamageType
= DMGTYPE::UNDEFINED
;
135 MeleeWeapon
.MeleeRange
= 0;
137 RangeWeapon
.WeaponType
= WEAPONTYPE::UNKNOWN
;
138 RangeWeapon
.RangeWeaponType
= RANGE_WEAPON_TYPE::Unknown
;
139 RangeWeapon
.Skill
= SKILLS::unknown
;
141 Ammo
.Skill
= SKILLS::unknown
;
142 Ammo
.DamageType
= DMGTYPE::UNDEFINED
;
145 Mp
.Ecosystem
= ECOSYSTEM::unknown
;
146 Mp
.MpCategory
= MP_CATEGORY::Undefined
;
147 Mp
.HarvestSkill
= SKILLS::unknown
;
148 Mp
.Family
= RM_FAMILY::Unknown
;
149 Mp
.UsedAsCraftRequirement
= false;
154 Shield
.ShieldType
= SHIELDTYPE::NONE
;
156 Tool
.Skill
= SKILLS::unknown
;
157 Tool
.CraftingToolType
= TOOL_TYPE::Unknown
;
158 Tool
.CommandRange
= 0;
161 GuildOption
.MoneyCost
= 0;
162 GuildOption
.XPCost
= 0;
166 Teleport
.Type
= TELEPORT_TYPES::NONE
;
170 //-----------------------------------------------
172 // Build the sheet from an external script.
173 //-----------------------------------------------
174 void CItemSheet::build(const NLGEORGES::UFormElm
&item
)
178 if(!item
.getValueByName(Shape
, "3d.shape"))
179 debug("key '3d.shape' not found.");
180 IdShape
= ClientSheetsStrings
.add(Shape
);
184 if(!item
.getValueByName(ShapeFemale
, "3d.shape_female"))
185 debug("key '3d.shape_female' not found.");
186 IdShapeFemale
= ClientSheetsStrings
.add(ShapeFemale
);
188 // Load the name fyros.
190 if(!item
.getValueByName(ShapeFyros
, "3d.shape_fyros"))
191 debug("key '3d.shape_fyros' not found.");
192 IdShapeFyros
= ClientSheetsStrings
.add(ShapeFyros
);
194 // Load the name fyros .
195 string ShapeFyrosFemale
;
196 if(!item
.getValueByName(ShapeFyrosFemale
, "3d.shape_fyros_female"))
197 debug("key '3d.shape_fyros_female' not found.");
198 IdShapeFyrosFemale
= ClientSheetsStrings
.add(ShapeFyrosFemale
);
200 // Load the name matis.
202 if(!item
.getValueByName(ShapeMatis
, "3d.shape_matis"))
203 debug("key '3d.shape_matis' not found.");
204 IdShapeMatis
= ClientSheetsStrings
.add(ShapeMatis
);
206 // Load the name matis .
207 string ShapeMatisFemale
;
208 if(!item
.getValueByName(ShapeMatisFemale
, "3d.shape_matis_female"))
209 debug("key '3d.shape_matis_female' not found.");
210 IdShapeMatisFemale
= ClientSheetsStrings
.add(ShapeMatisFemale
);
213 // Load the name tryker.
215 if(!item
.getValueByName(ShapeTryker
, "3d.shape_tryker"))
216 debug("key '3d.shape_tryker' not found.");
217 IdShapeTryker
= ClientSheetsStrings
.add(ShapeTryker
);
219 // Load the name tryker .
220 string ShapeTrykerFemale
;
221 if(!item
.getValueByName(ShapeTrykerFemale
, "3d.shape_tryker_female"))
222 debug("key '3d.shape_tryker_female' not found.");
223 IdShapeTrykerFemale
= ClientSheetsStrings
.add(ShapeTrykerFemale
);
226 // Load the name zorai.
228 if(!item
.getValueByName(ShapeZorai
, "3d.shape_zorai"))
229 debug("key '3d.shape_zorai' not found.");
230 IdShapeZorai
= ClientSheetsStrings
.add(ShapeZorai
);
232 // Load the name zorai .
233 string ShapeZoraiFemale
;
234 if(!item
.getValueByName(ShapeZoraiFemale
, "3d.shape_zorai_female"))
235 debug("key '3d.shape_zorai_female' not found.");
236 IdShapeZoraiFemale
= ClientSheetsStrings
.add(ShapeZoraiFemale
);
239 // Get the icon associated.
241 if(!item
.getValueByName (IconMain
, "3d.icon"))
242 debug("key '3d.icon' not found.");
243 IconMain
= toLowerAscii(IconMain
);
244 IdIconMain
= ClientSheetsStrings
.add(IconMain
);
246 // Get the icon associated.
248 if(!item
.getValueByName (IconBack
, "3d.icon background"))
249 debug("key '3d.icon background' not found.");
250 IconBack
= toLowerAscii(IconBack
);
251 IdIconBack
= ClientSheetsStrings
.add(IconBack
);
253 // Get the icon associated.
255 if(!item
.getValueByName (IconOver
, "3d.icon overlay"))
256 debug("key '3d.icon overlay' not found.");
257 IconOver
= toLowerAscii(IconOver
);
258 IdIconOver
= ClientSheetsStrings
.add(IconOver
);
260 // Get the icon associated.
262 if(!item
.getValueByName (IconOver2
, "3d.icon overlay2"))
263 debug("key '3d.icon overlay2' not found.");
264 IconOver2
= toLowerAscii(IconOver2
);
265 IdIconOver2
= ClientSheetsStrings
.add(IconOver2
);
267 // Get Special modulate colors
268 item
.getValueByName (IconColor
, "3d.IconColor" );
269 item
.getValueByName (IconBackColor
, "3d.IconBackColor");
270 item
.getValueByName (IconOverColor
, "3d.IconOverColor");
271 item
.getValueByName (IconOver2Color
, "3d.IconOver2Color");
273 // Get the icon text associated.
275 if(!item
.getValueByName (IconText
, "3d.text overlay"))
276 debug("key '3d.text overlay' not found.");
277 IdIconText
= ClientSheetsStrings
.add(IconText
);
279 // See if this item can be hiden when equipped
280 if(!item
.getValueByName (NeverHideWhenEquipped
, "3d.never hide when equiped"))
281 debug("key '3d.never hide when equiped.");
283 // Load the different slot in wicth the item can be equipped.
284 const UFormElm
*pElt
= 0;
285 // check uint32 is OK!
286 nlassert( SLOTTYPE::NB_SLOT_TYPE
<= 32 );
288 if(item
.getNodeByName(&pElt
, "basics.EquipmentInfo.EquipmentSlots") && pElt
)
292 if(pElt
->getArraySize(size
))
294 for(uint i
= 0; i
< size
; ++i
)
297 if(pElt
->getArrayValue(slotName
, i
))
301 debug(toString("The slot name %d is Empty.", i
));
303 // Push the possible slots for the item in the list.
304 SlotBF
|= SINT64_CONSTANT(1)<< (SLOTTYPE::stringToSlotType(NLMISC::toUpperAscii(slotName
)));
309 debug("The element 'basics.Equipment Slot' is not an array.");
312 debug("Cannot create the element from the name 'basics.Equipment Slot'.");
314 // Get the Item Family.
316 if(!item
.getValueByName(family
, "basics.family"))
318 debug("Key 'basics.family' not found.");
319 Family
= ITEMFAMILY::UNDEFINED
;
323 Family
= (ITEMFAMILY::EItemFamily
) ITEMFAMILY::stringToItemFamily(NLMISC::toUpperAscii( family
) );
324 if(Family
== ITEMFAMILY::UNDEFINED
)
325 debug("Item Family Undefined.");
328 // Get the Item Type.
330 if(!item
.getValueByName(itemtype
, "basics.ItemType"))
332 debug("Key 'basics.ItemType' not found.");
333 ItemType
= ITEM_TYPE::UNDEFINED
;
337 ItemType
= (ITEM_TYPE::TItemType
) ITEM_TYPE::stringToItemType(NLMISC::toUpperAscii(itemtype
) );
338 if (ItemType
== ITEM_TYPE::UNDEFINED
)
339 debug("Item Type Undefined.");
342 // Get the DropOrSell property
343 if(!item
.getValueByName (DropOrSell
, "basics.Drop or Sell"))
344 debug("key 'basics.Drop or Sell' not found.");
346 // Get the IsItemNoRent property
347 if(!item
.getValueByName (IsItemNoRent
, "basics.No Rent"))
348 debug("key 'basics.No Rent' not found.");
350 // Get the stackable property
351 if(!item
.getValueByName (Stackable
, "basics.stackable"))
352 debug("key 'basics.stackable' not found.");
354 // Get the Consumable property
355 if(!item
.getValueByName (IsConsumable
, "basics.Consumable"))
356 debug("key 'basics.Consumable' not found.");
358 // Get the texture variante.
359 if(!item
.getValueByName(MapVariant
, "3d.map_variant"))
360 debug("Key '3d.map_variant' not found.");
364 if(!item
.getValueByName(AnimSet
, "3d.anim_set"))
365 debug("key '3d.anim_set' not found.");
366 // Force the CASE in UPPER to not be CASE SENSITIVE.
368 AnimSet
= NLMISC::toLowerAscii(AnimSet
);
369 IdAnimSet
= ClientSheetsStrings
.add(AnimSet
);
371 // Get the Trail Shape
372 if(!item
.getValueByName(Color
, "3d.color"))
373 debug("key '3d.color' not found.");
376 if(!item
.getValueByName(HasFx
, "3d.has_fx"))
377 debug("key '3d.has_fx' not found.");
379 // Get special Effect1
381 if(!item
.getValueByName(Effect1
, "Effects.Effect1"))
382 debug("key 'Effects.Effect1' not found.");
383 Effect1
= toLowerAscii(Effect1
);
384 IdEffect1
= ClientSheetsStrings
.add(Effect1
);
386 // Get special Effect2
388 if(!item
.getValueByName(Effect2
, "Effects.Effect2"))
389 debug("key 'Effects.Effect2' not found.");
390 Effect2
= toLowerAscii(Effect2
);
391 IdEffect2
= ClientSheetsStrings
.add(Effect2
);
393 // Get special Effect3
395 if(!item
.getValueByName(Effect3
, "Effects.Effect3"))
396 debug("key 'Effects.Effect3' not found.");
397 Effect3
= toLowerAscii(Effect3
);
398 IdEffect3
= ClientSheetsStrings
.add(Effect3
);
400 // Get special Effect4
402 if(!item
.getValueByName(Effect4
, "Effects.Effect4"))
403 debug("key 'Effects.Effect4' not found.");
404 Effect4
= toLowerAscii(Effect4
);
405 IdEffect4
= ClientSheetsStrings
.add(Effect4
);
408 TRANSLATE_VAL( Bulk
, "basics.Bulk" );
410 // Get its equip time
411 TRANSLATE_VAL( EquipTime
, "basics.Time to Equip In Ticks" );
414 FX
.build(item
, "3d.fx.");
416 // **** Build Help Infos
419 TRANSLATE_ENUM( RequiredCharac
, CHARACTERISTICS::Unknown
, CHARACTERISTICS::toCharacteristic
, "basics.RequiredCharac");
420 TRANSLATE_VAL( RequiredCharacLevel
, "basics.MinRequiredCharacLevel");
421 TRANSLATE_ENUM( RequiredSkill
, SKILLS::unknown
, SKILLS::toSkill
, "basics.RequiredSkill");
422 TRANSLATE_VAL( RequiredSkillLevel
, "basics.MinRequiredSkillLevel");
425 TRANSLATE_ENUM ( ItemOrigin
, ITEM_ORIGIN::UNKNOWN
, ITEM_ORIGIN::stringToEnum
, "basics.origin");
428 TRANSLATE_VAL( val
, "basics.CraftPlan" );
430 CraftPlan
= CSheetId(val
);
432 // commands and menu label
433 TRANSLATE_VAL( Scroll
.LuaCommand
, "basics.Scroll.LuaCommand" );
434 TRANSLATE_VAL( Scroll
.WebCommand
, "basics.Scroll.WebCommand" );
435 TRANSLATE_VAL( Scroll
.Label
, "basics.Scroll.Label" );
437 // Special according to Family;
441 case ITEMFAMILY::COSMETIC
:
443 string sheetName
= Id
.toString();
444 string::size_type pos
= sheetName
.find('.',0);
445 if (pos
== string::npos
)
446 nlwarning("<loadCosmetics> Can't load the VPValue from sheet name in sheet %s", Id
.toString().c_str() );
449 sint i
= (sint
)pos
- 1;
452 if ( !isdigit( sheetName
[i
] ) )
457 string val
= sheetName
.substr( i
+ 1, pos
- i
- 1);
458 NLMISC::fromString( val
, Cosmetic
.VPValue
);
462 if ( sheetName
.find( "hof" ) != string::npos
)
463 Cosmetic
.Gender
= GSGENDER::female
;
465 Cosmetic
.Gender
= GSGENDER::male
;
472 case ITEMFAMILY::ARMOR
:
475 TRANSLATE_ENUM ( Armor
.ArmorType
, ARMORTYPE::UNKNOWN
, ARMORTYPE::toArmorType
, "armor.Armor category" );
479 case ITEMFAMILY::MELEE_WEAPON
:
482 TRANSLATE_ENUM ( MeleeWeapon
.WeaponType
, WEAPONTYPE::UNKNOWN
, WEAPONTYPE::stringToWeaponType
, "melee weapon.category" );
485 TRANSLATE_ENUM ( MeleeWeapon
.Skill
, SKILLS::unknown
, SKILLS::toSkill
, "melee weapon.skill" );
488 TRANSLATE_ENUM ( MeleeWeapon
.DamageType
, DMGTYPE::UNDEFINED
, DMGTYPE::stringToDamageType
, "melee weapon.damage type" );
491 TRANSLATE_VAL ( MeleeWeapon
.MeleeRange
, "melee weapon.melee range" );
496 case ITEMFAMILY::RANGE_WEAPON
:
499 TRANSLATE_ENUM ( RangeWeapon
.WeaponType
, WEAPONTYPE::UNKNOWN
, WEAPONTYPE::stringToWeaponType
, "range weapon.category" );
502 TRANSLATE_ENUM ( RangeWeapon
.RangeWeaponType
, RANGE_WEAPON_TYPE::Generic
, RANGE_WEAPON_TYPE::stringToRangeWeaponType
, "range weapon.RangeWeaponType" );
505 TRANSLATE_ENUM ( RangeWeapon
.Skill
, SKILLS::unknown
, SKILLS::toSkill
, "range weapon.skill" );
510 case ITEMFAMILY::AMMO
:
513 TRANSLATE_ENUM ( Ammo
.Skill
, SKILLS::unknown
, SKILLS::toSkill
, "ammo.weapon type" );
516 TRANSLATE_ENUM ( Ammo
.DamageType
, DMGTYPE::UNDEFINED
, DMGTYPE::stringToDamageType
, "ammo.damage type" );
519 TRANSLATE_VAL( Ammo
.Magazine
, "ammo.magazine" );
524 case ITEMFAMILY::RAW_MATERIAL
:
527 TRANSLATE_ENUM( Mp
.Ecosystem
, ECOSYSTEM::unknown
, ECOSYSTEM::stringToEcosystem
, "mp.Ecosystem" );
530 TRANSLATE_ENUM( Mp
.MpCategory
, MP_CATEGORY::Undefined
, MP_CATEGORY::stringToMPCategory
, "mp.Category" );
533 TRANSLATE_ENUM( Mp
.HarvestSkill
, SKILLS::unknown
, SKILLS::toSkill
, "mp.HarvestSkill" );
536 TRANSLATE_VAL( Mp
.Family
, "mp.Family" );
542 // ensure that if you modify RM_FABER_TYPE, you have to rebuild the item sheets.
543 nlctassert(RM_FABER_TYPE::NUM_FABER_TYPE
== 26);
544 // ensure that the bitfields are enough (nb: unknown can be stored)
545 nlctassert(ITEM_ORIGIN::NUM_ITEM_ORIGIN
< 256);
546 // ensure that the bitfield for item part buildable for this MP is possible
547 nlctassert(RM_FABER_TYPE::NUM_FABER_TYPE
<= 32);
551 // check if ok for each
552 for(i
=0;i
<RM_FABER_TYPE::NUM_FABER_TYPE
;i
++)
554 uint32 durability
= 0;
555 string sheetEntry
= RM_FABER_TYPE::faberTypeToSheetEntry((RM_FABER_TYPE::TRMFType
)i
);
557 // read the associated durablity of the MP faberType
558 sprintf(keyTmp
, "mp.MpParam.%s.Durability", sheetEntry
.c_str());
559 TRANSLATE_VAL(durability
, keyTmp
);
561 // If not null, ok this MP is associated to this faberType
564 Mp
.ItemPartBF
|= SINT64_CONSTANT(1)<<i
;
565 MpItemParts
.push_back(CMpItemPart());
566 CMpItemPart
&itemPart
= MpItemParts
.back();
568 // read origin filter
569 sprintf(keyTmp
, "mp.MpParam.%s.CraftCivSpec", sheetEntry
.c_str());
570 TRANSLATE_ENUM( itemPart
.OriginFilter
, ITEM_ORIGIN::UNKNOWN
, ITEM_ORIGIN::stringToEnum
, keyTmp
);
573 for(uint j
=0;j
<RM_FABER_STAT_TYPE::NumRMStatType
;j
++)
575 sprintf(keyTmp
, "mp.MpParam.%s.%s", sheetEntry
.c_str(), RM_FABER_STAT_TYPE::toString((RM_FABER_STAT_TYPE::TRMStatType
)j
).c_str());
576 TRANSLATE_VAL( itemPart
.Stats
[j
], keyTmp
);
581 // UsedAsCraftRequirement
582 TRANSLATE_VAL( Mp
.UsedAsCraftRequirement
, "mp.UsedAsCraftRequirement" );
585 TRANSLATE_VAL( Mp
.MpColor
, "mp.MpColor" );
588 TRANSLATE_VAL( Mp
.StatEnergy
, "mp.StatEnergy");
593 case ITEMFAMILY::SHIELD
:
596 TRANSLATE_ENUM( Shield
.ShieldType
, SHIELDTYPE::NONE
, SHIELDTYPE::stringToShieldType
, "shield.Category" );
599 // TOOL: different for any tool
600 case ITEMFAMILY::CRAFTING_TOOL
:
603 TRANSLATE_ENUM( Tool
.CraftingToolType
, TOOL_TYPE::Unknown
, TOOL_TYPE::toToolType
, "crafting tool.type");
606 case ITEMFAMILY::HARVEST_TOOL
:
609 TRANSLATE_ENUM( Tool
.Skill
, SKILLS::unknown
, SKILLS::toSkill
, "harvest tool.skill" );
612 case ITEMFAMILY::TAMING_TOOL
:
615 TRANSLATE_ENUM( Tool
.Skill
, SKILLS::unknown
, SKILLS::toSkill
, "taming tool.skill" );
618 TRANSLATE_VAL( Tool
.CommandRange
, "taming tool.command range" );
621 TRANSLATE_VAL( Tool
.MaxDonkey
, "taming tool.max donkey" );
625 case ITEMFAMILY::GUILD_OPTION
:
627 // Cost in money of the tool
628 TRANSLATE_VAL( GuildOption
.MoneyCost
, "guild option.Money Cost" );
631 TRANSLATE_VAL( GuildOption
.XPCost
, "guild option.Guild XP Cost" );
634 case ITEMFAMILY::PET_ANIMAL_TICKET
:
636 // Cost in money of the tool
637 TRANSLATE_VAL( Pet
.Slot
, "pet.Pet Slot" );
640 case ITEMFAMILY::TELEPORT
:
643 TRANSLATE_ENUM( Teleport
.Type
, TELEPORT_TYPES::NONE
, TELEPORT_TYPES::getTpTypeFromString
, "teleport.Type" );
646 case ITEMFAMILY::SCROLL
:
649 TRANSLATE_VAL( Scroll
.Texture
, "Scroll.Texture");
652 case ITEMFAMILY::CONSUMABLE
:
654 TRANSLATE_VAL( Consumable
.ConsumptionTime
, "Consumable.ConsumptionTime");
655 TRANSLATE_VAL( Consumable
.OverdoseTimer
, "Consumable.OverdoseTimer");
657 Consumable
.Properties
.clear();
658 for(uint i
=0;i
<4;i
++)
661 item
.getValueByName(val
, toString("Consumable.Property %d", i
).c_str() );
662 if(!val
.empty() && val
!="NULL")
664 Consumable
.Properties
.push_back(val
);
677 //-----------------------------------------------
679 // Serialize character sheet into binary data file.
680 //-----------------------------------------------
681 void CItemSheet::serial(NLMISC::IStream
&f
)
683 ClientSheetsStrings
.serial(f
, IdShape
);
684 ClientSheetsStrings
.serial(f
, IdShapeFemale
);
685 ClientSheetsStrings
.serial(f
, IdShapeFyros
);
686 ClientSheetsStrings
.serial(f
, IdShapeFyrosFemale
);
687 ClientSheetsStrings
.serial(f
, IdShapeMatis
);
688 ClientSheetsStrings
.serial(f
, IdShapeMatisFemale
);
689 ClientSheetsStrings
.serial(f
, IdShapeTryker
);
690 ClientSheetsStrings
.serial(f
, IdShapeTrykerFemale
);
691 ClientSheetsStrings
.serial(f
, IdShapeZorai
);
692 ClientSheetsStrings
.serial(f
, IdShapeZoraiFemale
);
693 f
.serial(SlotBF
); // Serialize Slots used.
694 f
.serial(MapVariant
); // Serialize Map Variant.
695 f
.serialEnum(Family
); // Serialize Family.
696 f
.serialEnum(ItemType
); // Serialize ItemType.
697 ClientSheetsStrings
.serial(f
, IdIconMain
);
698 ClientSheetsStrings
.serial(f
, IdIconBack
);
699 ClientSheetsStrings
.serial(f
, IdIconOver
);
700 ClientSheetsStrings
.serial(f
, IdIconOver2
);
701 f
.serial (IconColor
);
702 f
.serial (IconBackColor
);
703 f
.serial (IconOverColor
);
704 f
.serial (IconOver2Color
);
705 ClientSheetsStrings
.serial(f
, IdIconText
);
706 ClientSheetsStrings
.serial(f
, IdAnimSet
);
707 f
.serial(Color
); // Serialize the item color.
708 f
.serial(HasFx
); // Serialize the has fx.
709 f
.serial(DropOrSell
);
710 f
.serial(IsItemNoRent
);
711 f
.serial(NeverHideWhenEquipped
);
713 f
.serial(IsConsumable
);
719 ClientSheetsStrings
.serial(f
, IdEffect1
);
720 ClientSheetsStrings
.serial(f
, IdEffect2
);
721 ClientSheetsStrings
.serial(f
, IdEffect3
);
722 ClientSheetsStrings
.serial(f
, IdEffect4
);
724 f
.serialCont(MpItemParts
);
728 f
.serialEnum(RequiredCharac
);
729 f
.serial(RequiredCharacLevel
);
730 f
.serialEnum(RequiredSkill
);
731 f
.serial(RequiredSkillLevel
);
733 // **** Serial Help Infos
734 f
.serialEnum(ItemOrigin
);
739 // Different Serial according to family
742 case ITEMFAMILY::COSMETIC
:
745 case ITEMFAMILY::ARMOR
:
748 case ITEMFAMILY::MELEE_WEAPON
:
749 f
.serial(MeleeWeapon
);
751 case ITEMFAMILY::RANGE_WEAPON
:
752 f
.serial(RangeWeapon
);
754 case ITEMFAMILY::AMMO
:
757 case ITEMFAMILY::RAW_MATERIAL
:
760 case ITEMFAMILY::SHIELD
:
764 case ITEMFAMILY::CRAFTING_TOOL
:
765 case ITEMFAMILY::HARVEST_TOOL
:
766 case ITEMFAMILY::TAMING_TOOL
:
769 case ITEMFAMILY::GUILD_OPTION
:
770 f
.serial(GuildOption
);
772 case ITEMFAMILY::PET_ANIMAL_TICKET
:
775 case ITEMFAMILY::TELEPORT
:
778 // keep for readability
779 case ITEMFAMILY::SCROLL
:
782 case ITEMFAMILY::CONSUMABLE
:
783 f
.serial(Consumable
);
792 // ***************************************************************************
793 bool CItemSheet::isFaberisable() const
795 // Only those family of item can be repaired/faber/refined.
796 return Family
==ITEMFAMILY::AMMO
||
797 Family
==ITEMFAMILY::ARMOR
||
798 Family
==ITEMFAMILY::MELEE_WEAPON
||
799 Family
==ITEMFAMILY::RANGE_WEAPON
||
800 Family
==ITEMFAMILY::JEWELRY
||
801 Family
==ITEMFAMILY::CRAFTING_TOOL
||
802 Family
==ITEMFAMILY::HARVEST_TOOL
||
803 Family
==ITEMFAMILY::TAMING_TOOL
||
804 Family
==ITEMFAMILY::SHIELD
;
807 // ***************************************************************************
808 SKILLS::ESkills
CItemSheet::getRequiredSkill() const
812 // case ITEMFAMILY::ARMOR: return Armor.Skill;
813 case ITEMFAMILY::MELEE_WEAPON
: return MeleeWeapon
.Skill
;
814 case ITEMFAMILY::RANGE_WEAPON
: return RangeWeapon
.Skill
;
815 case ITEMFAMILY::AMMO
: return Ammo
.Skill
;
816 // case ITEMFAMILY::SHIELD: return SHIELDTYPE::shieldTypeToSkill(Shield.ShieldType);
817 case ITEMFAMILY::RAW_MATERIAL
: return Mp
.HarvestSkill
;
819 case ITEMFAMILY::HARVEST_TOOL
:
820 case ITEMFAMILY::TAMING_TOOL
:
822 case ITEMFAMILY::CRAFTING_TOOL
:
824 default: return SKILLS::unknown
;
828 // ***************************************************************************
829 bool CItemSheet::isUsedAsCraftRequirement() const
831 if(Family
!=ITEMFAMILY::RAW_MATERIAL
)
834 return Mp
.UsedAsCraftRequirement
;
837 // ***************************************************************************
838 bool CItemSheet::canBuildSomeItemPart() const
840 if(Family
!=ITEMFAMILY::RAW_MATERIAL
)
843 return Mp
.ItemPartBF
!=0;
846 // ***************************************************************************
847 bool CItemSheet::canBuildItemPart(RM_FABER_TYPE::TRMFType e
) const
849 if(e
<RM_FABER_TYPE::NUM_FABER_TYPE
)
851 if(Mp
.ItemPartBF
&(SINT64_CONSTANT(1)<<e
))
855 // all other cases: false
859 // ***************************************************************************
860 bool CItemSheet::canBuildItemPart(RM_FABER_TYPE::TRMFType e
, ITEM_ORIGIN::EItemOrigin origin
) const
862 if(e
<RM_FABER_TYPE::NUM_FABER_TYPE
)
864 if(Mp
.ItemPartBF
&(SINT64_CONSTANT(1)<<e
))
866 const CMpItemPart
&itemPart
= getItemPart(e
);
867 // If this MP can build all origin items, or if origin matchs
868 if( itemPart
.OriginFilter
== ITEM_ORIGIN::COMMON
||
869 itemPart
.OriginFilter
== origin
||
870 origin
== ITEM_ORIGIN::COMMON
)
875 // all other cases: false
879 // ***************************************************************************
880 const CItemSheet::CMpItemPart
&CItemSheet::getItemPart(RM_FABER_TYPE::TRMFType e
) const
882 nlassert(Mp
.ItemPartBF
&(SINT64_CONSTANT(1)<<e
));
884 // count the number of bits set before reaching this item part
886 for(uint i
=0;i
<(uint
)e
;i
++)
888 if(Mp
.ItemPartBF
&(SINT64_CONSTANT(1)<<i
))
892 nlassert(index
<MpItemParts
.size());
893 return MpItemParts
[index
];
896 // ***************************************************************************
897 bool CItemSheet::hasCharacRequirement(uint itemLevel
, CHARACTERISTICS::TCharacteristics
&caracType
, float &caracValue
) const
902 // **** ARMORS / BUCKLERS
903 case ITEMFAMILY::ARMOR
:
904 case ITEMFAMILY::SHIELD
:
907 case ITEM_TYPE::LIGHT_BOOTS
:
908 case ITEM_TYPE::LIGHT_GLOVES
:
909 case ITEM_TYPE::LIGHT_PANTS
:
910 case ITEM_TYPE::LIGHT_SLEEVES
:
911 case ITEM_TYPE::LIGHT_VEST
:
912 // No carac requirement
914 case ITEM_TYPE::MEDIUM_BOOTS
:
915 case ITEM_TYPE::MEDIUM_GLOVES
:
916 case ITEM_TYPE::MEDIUM_PANTS
:
917 case ITEM_TYPE::MEDIUM_SLEEVES
:
918 case ITEM_TYPE::MEDIUM_VEST
:
919 case ITEM_TYPE::BUCKLER
:
920 // Constitution requirement
921 caracType
= CHARACTERISTICS::constitution
;
922 caracValue
= itemLevel
/ 1.5f
;
924 case ITEM_TYPE::HEAVY_BOOTS
:
925 case ITEM_TYPE::HEAVY_GLOVES
:
926 case ITEM_TYPE::HEAVY_PANTS
:
927 case ITEM_TYPE::HEAVY_SLEEVES
:
928 case ITEM_TYPE::HEAVY_VEST
:
929 case ITEM_TYPE::HEAVY_HELMET
:
930 case ITEM_TYPE::SHIELD
:
931 // Constitution requirement
932 caracType
= CHARACTERISTICS::constitution
;
933 caracValue
= float((sint
)itemLevel
- 10);
934 caracValue
= max(caracValue
, 0.f
);
937 // No carac requirement
942 // **** MELEE_WEAPONS
943 case ITEMFAMILY::MELEE_WEAPON
:
946 case ITEM_TYPE::MAGICIAN_STAFF
:
947 // Intelligence requirement
948 caracType
= CHARACTERISTICS::intelligence
;
949 caracValue
= float((sint
)itemLevel
- 10);
950 caracValue
= max(caracValue
, 0.f
);
953 // Strength requirement
954 caracType
= CHARACTERISTICS::strength
;
955 caracValue
= float((sint
)itemLevel
- 10);
956 caracValue
= max(caracValue
, 0.f
);
962 case ITEMFAMILY::RANGE_WEAPON
:
963 caracType
= CHARACTERISTICS::well_balanced
;
964 caracValue
= float((sint
)itemLevel
- 10);
965 caracValue
= max(caracValue
, 0.f
);
970 // No carac requirement
976 // ***************************************************************************
977 bool CItemSheet::canExchangeOrGive(bool botChatGift
) const
983 // still can give any item to bot chat
987 // ***************************************************************************
988 void CItemSheet::getItemPartListAsText(std::string
&ipList
) const
991 for(uint i
=0;i
<RM_FABER_TYPE::NUM_FABER_TYPE
;i
++)
993 RM_FABER_TYPE::TRMFType faberType
= RM_FABER_TYPE::TRMFType(i
);
995 if(canBuildItemPart(faberType
))
999 ipList
+= RM_FABER_TYPE::toLocalString(faberType
);
1003 // Ignore Tools and CampFire
1004 if( faberType
!=RM_FABER_TYPE::MPBT
&&
1005 faberType
!=RM_FABER_TYPE::MPPES
&&
1006 faberType
!=RM_FABER_TYPE::MPSH
&&
1007 faberType
!=RM_FABER_TYPE::MPTK
&&
1008 faberType
!=RM_FABER_TYPE::MPJH
&&
1009 faberType
!=RM_FABER_TYPE::MPCF
)
1015 ipList
= CI18N::get("uihelpItemMPAllCraft");