Linux multi-monitor fullscreen support
[ryzomcore.git] / ryzom / client / src / client_sheets / item_sheet.cpp
blobd5831167c3564b931029409cc614e3557ad0b49b
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010-2019 Winch Gate Property Limited
3 //
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
6 //
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/>.
23 /////////////
24 // INCLUDE //
25 /////////////
26 #include "stdpch.h" // First include for pre-compiled headers.
27 // Georges
28 #include "nel/georges/u_form_elm.h"
29 // Client.
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"
40 ///////////
41 // USING //
42 ///////////
43 using namespace std;
44 using namespace NLMISC;
45 using namespace NLGEORGES;
48 // ***************************************************************************
49 // Easy Macro to translate .typ enum
50 #define TRANSLATE_ENUM( _Var_, _unknown_, _func_, _key_) \
51 _Var_ = _unknown_; \
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_) \
59 _Var_ = _unknown_; \
60 if( !item.getValueByName(val, _key_)) \
61 debug( toString("Key '%s' not found.", _key_) ); \
62 else \
63 _Var_ = _func_(val);
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 //-----------------------------------------------
74 // CItemSheet :
75 // Constructor.
76 //-----------------------------------------------
77 CItemSheet::CItemSheet()
79 IdShape = 0;
80 IdShapeFemale = 0;
81 IdShapeFyros = 0;
82 IdShapeFyrosFemale = 0;
83 IdShapeMatis = 0;
84 IdShapeMatisFemale = 0;
85 IdShapeTryker = 0;
86 IdShapeTrykerFemale = 0;
87 IdShapeZorai = 0;
88 IdShapeZoraiFemale = 0;
90 MapVariant = 0;
91 ItemType = ITEM_TYPE::UNDEFINED;
92 Family = ITEMFAMILY::UNDEFINED;
93 SlotBF= 0;
94 IdIconBack = 0;
95 IdIconMain = 0;
96 IdIconOver = 0;
97 IdIconOver2 = 0;
98 IdIconText = 0;
99 IdAnimSet = 0;
100 Color = 0;
101 HasFx = false;
102 DropOrSell = false;
103 IsItemNoRent = false;
104 Stackable = 0;
105 IsConsumable = false;
107 IdEffect1 = 0;
108 IdEffect2 = 0;
109 IdEffect3 = 0;
110 IdEffect4 = 0;
112 Type = CEntitySheet::ITEM;
113 Bulk= 0.f;
114 EquipTime= 0;
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;
143 Ammo.Magazine = 0;
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;
150 Mp.MpColor = 0;
151 Mp.StatEnergy = 0;
152 Mp.ItemPartBF = 0;
154 Shield.ShieldType = SHIELDTYPE::NONE;
156 Tool.Skill = SKILLS::unknown;
157 Tool.CraftingToolType = TOOL_TYPE::Unknown;
158 Tool.CommandRange = 0;
159 Tool.MaxDonkey = 0;
161 GuildOption.MoneyCost = 0;
162 GuildOption.XPCost = 0;
164 Pet.Slot = 0;
166 Teleport.Type = TELEPORT_TYPES::NONE;
167 }// CItemSheet //
170 //-----------------------------------------------
171 // build :
172 // Build the sheet from an external script.
173 //-----------------------------------------------
174 void CItemSheet::build(const NLGEORGES::UFormElm &item)
176 // Load the name.
177 string Shape;
178 if(!item.getValueByName(Shape, "3d.shape"))
179 debug("key '3d.shape' not found.");
180 IdShape = ClientSheetsStrings.add(Shape);
182 // Load the name.
183 string ShapeFemale;
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.
189 string ShapeFyros;
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.
201 string ShapeMatis;
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.
214 string ShapeTryker;
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.
227 string ShapeZorai;
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.
240 string IconMain;
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.
247 string IconBack;
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.
254 string IconOver;
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.
261 string IconOver2;
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.
274 string IconText;
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 );
287 SlotBF= 0;
288 if(item.getNodeByName(&pElt, "basics.EquipmentInfo.EquipmentSlots") && pElt)
290 // Get all slots.
291 uint size;
292 if(pElt->getArraySize(size))
294 for(uint i = 0; i < size; ++i)
296 string slotName;
297 if(pElt->getArrayValue(slotName, i))
299 // Check name.
300 if(slotName.empty())
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)));
308 else
309 debug("The element 'basics.Equipment Slot' is not an array.");
311 else
312 debug("Cannot create the element from the name 'basics.Equipment Slot'.");
314 // Get the Item Family.
315 string family;
316 if(!item.getValueByName(family, "basics.family"))
318 debug("Key 'basics.family' not found.");
319 Family = ITEMFAMILY::UNDEFINED;
321 else
323 Family = (ITEMFAMILY::EItemFamily) ITEMFAMILY::stringToItemFamily(NLMISC::toUpperAscii( family) );
324 if(Family == ITEMFAMILY::UNDEFINED)
325 debug("Item Family Undefined.");
328 // Get the Item Type.
329 string itemtype;
330 if(!item.getValueByName(itemtype, "basics.ItemType"))
332 debug("Key 'basics.ItemType' not found.");
333 ItemType = ITEM_TYPE::UNDEFINED;
335 else
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.");
362 // Load the name.
363 string AnimSet;
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.
367 else
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.");
375 // Get the Fx flag
376 if(!item.getValueByName(HasFx, "3d.has_fx"))
377 debug("key '3d.has_fx' not found.");
379 // Get special Effect1
380 string 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
387 string 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
394 string 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
401 string Effect4;
402 if(!item.getValueByName(Effect4, "Effects.Effect4"))
403 debug("key 'Effects.Effect4' not found.");
404 Effect4 = toLowerAscii(Effect4);
405 IdEffect4 = ClientSheetsStrings.add(Effect4);
407 // Get its bulk
408 TRANSLATE_VAL( Bulk, "basics.Bulk" );
410 // Get its equip time
411 TRANSLATE_VAL( EquipTime, "basics.Time to Equip In Ticks" );
413 // build fx part
414 FX.build(item, "3d.fx.");
416 // **** Build Help Infos
417 string val;
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");
424 // item Origin
425 TRANSLATE_ENUM ( ItemOrigin, ITEM_ORIGIN::UNKNOWN, ITEM_ORIGIN::stringToEnum, "basics.origin");
427 /// item craft plan
428 TRANSLATE_VAL( val, "basics.CraftPlan" );
429 if (!val.empty())
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;
438 switch(Family)
440 // COSMETIC
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() );
447 else
449 sint i = (sint)pos - 1;
450 for(; i >= 0; i-- )
452 if ( !isdigit( sheetName[i] ) )
453 break;
455 if ( i >= -1 )
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;
464 else
465 Cosmetic.Gender = GSGENDER::male;
470 break;
471 // ARMOR
472 case ITEMFAMILY::ARMOR :
474 // ArmorType
475 TRANSLATE_ENUM ( Armor.ArmorType, ARMORTYPE::UNKNOWN, ARMORTYPE::toArmorType, "armor.Armor category" );
477 break;
478 // MELEE_WEAPON
479 case ITEMFAMILY::MELEE_WEAPON :
481 // WeaponType
482 TRANSLATE_ENUM ( MeleeWeapon.WeaponType, WEAPONTYPE::UNKNOWN, WEAPONTYPE::stringToWeaponType, "melee weapon.category" );
484 // Skill
485 TRANSLATE_ENUM ( MeleeWeapon.Skill, SKILLS::unknown, SKILLS::toSkill, "melee weapon.skill" );
487 // DamageType
488 TRANSLATE_ENUM ( MeleeWeapon.DamageType, DMGTYPE::UNDEFINED, DMGTYPE::stringToDamageType, "melee weapon.damage type" );
490 // DamageType
491 TRANSLATE_VAL ( MeleeWeapon.MeleeRange, "melee weapon.melee range" );
494 break;
495 // RANGE_WEAPON
496 case ITEMFAMILY::RANGE_WEAPON :
498 // WeaponType
499 TRANSLATE_ENUM ( RangeWeapon.WeaponType, WEAPONTYPE::UNKNOWN, WEAPONTYPE::stringToWeaponType, "range weapon.category" );
501 // Range weapon type
502 TRANSLATE_ENUM ( RangeWeapon.RangeWeaponType, RANGE_WEAPON_TYPE::Generic, RANGE_WEAPON_TYPE::stringToRangeWeaponType, "range weapon.RangeWeaponType" );
504 // Skill
505 TRANSLATE_ENUM ( RangeWeapon.Skill, SKILLS::unknown, SKILLS::toSkill, "range weapon.skill" );
508 break;
509 // AMMO
510 case ITEMFAMILY::AMMO :
512 // Skill
513 TRANSLATE_ENUM ( Ammo.Skill, SKILLS::unknown, SKILLS::toSkill, "ammo.weapon type" );
515 // DamageType
516 TRANSLATE_ENUM ( Ammo.DamageType, DMGTYPE::UNDEFINED, DMGTYPE::stringToDamageType, "ammo.damage type" );
518 // Magazine
519 TRANSLATE_VAL( Ammo.Magazine, "ammo.magazine" );
522 break;
523 // RAW_MATERIAL
524 case ITEMFAMILY::RAW_MATERIAL :
526 // Ecosystem
527 TRANSLATE_ENUM( Mp.Ecosystem, ECOSYSTEM::unknown, ECOSYSTEM::stringToEcosystem, "mp.Ecosystem" );
529 // MpCategory
530 TRANSLATE_ENUM( Mp.MpCategory, MP_CATEGORY::Undefined, MP_CATEGORY::stringToMPCategory, "mp.Category" );
532 // Skill
533 TRANSLATE_ENUM( Mp.HarvestSkill, SKILLS::unknown, SKILLS::toSkill, "mp.HarvestSkill" );
535 // MP Family
536 TRANSLATE_VAL( Mp.Family, "mp.Family" );
539 // Faber Item Part
540 uint i;
541 char keyTmp[256];
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);
548 // reset
549 Mp.ItemPartBF= 0;
550 MpItemParts.clear();
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
562 if(durability)
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);
572 // read each stat
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" );
584 // MpColor
585 TRANSLATE_VAL( Mp.MpColor, "mp.MpColor" );
587 // Mp Stat Energy
588 TRANSLATE_VAL( Mp.StatEnergy, "mp.StatEnergy");
591 break;
592 // SHIELD
593 case ITEMFAMILY::SHIELD :
595 // ShieldType
596 TRANSLATE_ENUM( Shield.ShieldType, SHIELDTYPE::NONE, SHIELDTYPE::stringToShieldType, "shield.Category" );
598 break;
599 // TOOL: different for any tool
600 case ITEMFAMILY::CRAFTING_TOOL :
602 // CraftingToolType
603 TRANSLATE_ENUM( Tool.CraftingToolType, TOOL_TYPE::Unknown, TOOL_TYPE::toToolType, "crafting tool.type");
605 break;
606 case ITEMFAMILY::HARVEST_TOOL :
608 // Skill
609 TRANSLATE_ENUM( Tool.Skill, SKILLS::unknown, SKILLS::toSkill, "harvest tool.skill" );
611 break;
612 case ITEMFAMILY::TAMING_TOOL :
614 // Skill
615 TRANSLATE_ENUM( Tool.Skill, SKILLS::unknown, SKILLS::toSkill, "taming tool.skill" );
617 // CommandRange
618 TRANSLATE_VAL( Tool.CommandRange, "taming tool.command range" );
620 // MaxDonkey
621 TRANSLATE_VAL( Tool.MaxDonkey, "taming tool.max donkey" );
624 break;
625 case ITEMFAMILY::GUILD_OPTION :
627 // Cost in money of the tool
628 TRANSLATE_VAL( GuildOption.MoneyCost, "guild option.Money Cost" );
630 // Cost in guild XP
631 TRANSLATE_VAL( GuildOption.XPCost, "guild option.Guild XP Cost" );
633 break;
634 case ITEMFAMILY::PET_ANIMAL_TICKET :
636 // Cost in money of the tool
637 TRANSLATE_VAL( Pet.Slot, "pet.Pet Slot" );
639 break;
640 case ITEMFAMILY::TELEPORT:
642 // Type of teleport
643 TRANSLATE_ENUM( Teleport.Type, TELEPORT_TYPES::NONE, TELEPORT_TYPES::getTpTypeFromString, "teleport.Type" );
645 break;
646 case ITEMFAMILY::SCROLL:
648 // Scroll texture
649 TRANSLATE_VAL( Scroll.Texture, "Scroll.Texture");
651 break;
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++)
660 string val;
661 item.getValueByName(val, toString("Consumable.Property %d", i).c_str() );
662 if(!val.empty() && val!="NULL")
664 Consumable.Properties.push_back(val);
668 break;
670 default:
671 break;
674 }// build //
677 //-----------------------------------------------
678 // serial :
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);
712 f.serial(Stackable);
713 f.serial(IsConsumable);
714 f.serial(Bulk);
715 f.serial(EquipTime);
717 f.serial(FX);
719 ClientSheetsStrings.serial(f, IdEffect1);
720 ClientSheetsStrings.serial(f, IdEffect2);
721 ClientSheetsStrings.serial(f, IdEffect3);
722 ClientSheetsStrings.serial(f, IdEffect4);
724 f.serialCont(MpItemParts);
726 f.serial(CraftPlan);
728 f.serialEnum(RequiredCharac);
729 f.serial(RequiredCharacLevel);
730 f.serialEnum(RequiredSkill);
731 f.serial(RequiredSkillLevel);
733 // **** Serial Help Infos
734 f.serialEnum(ItemOrigin);
736 // item commands
737 f.serial(Scroll);
739 // Different Serial according to family
740 switch(Family)
742 case ITEMFAMILY::COSMETIC :
743 f.serial(Cosmetic);
744 break;
745 case ITEMFAMILY::ARMOR :
746 f.serial(Armor);
747 break;
748 case ITEMFAMILY::MELEE_WEAPON :
749 f.serial(MeleeWeapon);
750 break;
751 case ITEMFAMILY::RANGE_WEAPON :
752 f.serial(RangeWeapon);
753 break;
754 case ITEMFAMILY::AMMO :
755 f.serial(Ammo);
756 break;
757 case ITEMFAMILY::RAW_MATERIAL :
758 f.serial(Mp);
759 break;
760 case ITEMFAMILY::SHIELD :
761 f.serial(Shield);
762 break;
763 // Same for any tool
764 case ITEMFAMILY::CRAFTING_TOOL :
765 case ITEMFAMILY::HARVEST_TOOL :
766 case ITEMFAMILY::TAMING_TOOL :
767 f.serial(Tool);
768 break;
769 case ITEMFAMILY::GUILD_OPTION :
770 f.serial(GuildOption);
771 break;
772 case ITEMFAMILY::PET_ANIMAL_TICKET :
773 f.serial(Pet);
774 break;
775 case ITEMFAMILY::TELEPORT:
776 f.serial(Teleport);
777 break;
778 // keep for readability
779 case ITEMFAMILY::SCROLL:
780 //f.serial(Scroll);
781 break;
782 case ITEMFAMILY::CONSUMABLE:
783 f.serial(Consumable);
784 break;
785 default:
786 break;
789 }// serial //
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
810 switch(Family)
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:
821 return Tool.Skill;
822 case ITEMFAMILY::CRAFTING_TOOL:
823 return SKILLS::SC;
824 default: return SKILLS::unknown;
828 // ***************************************************************************
829 bool CItemSheet::isUsedAsCraftRequirement() const
831 if(Family!=ITEMFAMILY::RAW_MATERIAL)
832 return false;
834 return Mp.UsedAsCraftRequirement;
837 // ***************************************************************************
838 bool CItemSheet::canBuildSomeItemPart() const
840 if(Family!=ITEMFAMILY::RAW_MATERIAL)
841 return false;
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))
852 return true;
855 // all other cases: false
856 return 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 )
871 return true;
875 // all other cases: false
876 return 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
885 uint index= 0;
886 for(uint i=0;i<(uint)e;i++)
888 if(Mp.ItemPartBF&(SINT64_CONSTANT(1)<<i))
889 index++;
892 nlassert(index<MpItemParts.size());
893 return MpItemParts[index];
896 // ***************************************************************************
897 bool CItemSheet::hasCharacRequirement(uint itemLevel, CHARACTERISTICS::TCharacteristics &caracType, float &caracValue) const
900 switch( Family )
902 // **** ARMORS / BUCKLERS
903 case ITEMFAMILY::ARMOR:
904 case ITEMFAMILY::SHIELD:
905 switch( ItemType )
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
913 return false;
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;
923 return true;
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);
935 return true;
936 default:
937 // No carac requirement
938 return false;
940 break;
942 // **** MELEE_WEAPONS
943 case ITEMFAMILY::MELEE_WEAPON:
944 switch( ItemType )
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);
951 return true;
952 default:
953 // Strength requirement
954 caracType= CHARACTERISTICS::strength;
955 caracValue= float((sint)itemLevel - 10);
956 caracValue= max(caracValue, 0.f);
957 return true;
959 break;
961 // **** RANGE_WEAPON
962 case ITEMFAMILY::RANGE_WEAPON:
963 caracType= CHARACTERISTICS::well_balanced;
964 caracValue= float((sint)itemLevel - 10);
965 caracValue= max(caracValue, 0.f);
966 return true;
968 // **** OTHERS
969 default:
970 // No carac requirement
971 return false;
976 // ***************************************************************************
977 bool CItemSheet::canExchangeOrGive(bool botChatGift) const
979 // DropOrSell => ok
980 if(DropOrSell)
981 return true;
983 // still can give any item to bot chat
984 return botChatGift;
987 // ***************************************************************************
988 void CItemSheet::getItemPartListAsText(std::string &ipList) const
990 bool all= true;
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))
997 if(!ipList.empty())
998 ipList+= ", ";
999 ipList+= RM_FABER_TYPE::toLocalString(faberType);
1001 else
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 )
1010 all= false;
1013 if(all)
1015 ipList= CI18N::get("uihelpItemMPAllCraft");