// Ryzom - MMORPG Framework
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
/////////////
// INCLUDE //
/////////////
#include "stdpch.h" // First include for pre-compiled headers.
// Georges
#include "nel/georges/u_form_elm.h"
// Client.
#include "item_sheet.h"
#include "game_share/characteristics.h"
#include "game_share/scores.h"
#include "game_share/skills.h"
#include "game_share/people.h"
#include "game_share/protection_type.h"
#include "nel/misc/i18n.h"
///////////
// USING //
///////////
using namespace std;
using namespace NLMISC;
using namespace NLGEORGES;
// ***************************************************************************
// Easy Macro to translate .typ enum
#define TRANSLATE_ENUM( _Var_, _unknown_, _func_, _key_) \
_Var_ = _unknown_; \
if( !item.getValueByName(val, _key_)) \
debug( toString("Key '%s' not found.", _key_) ); \
else if( (_Var_ = _func_(val)) == _unknown_ ) \
debug(#_Var_ " Unknown: " + val);
// Same but no error if the result of enum is _unknown_
#define TRANSLATE_ENUM_NODB( _Var_, _unknown_, _func_, _key_) \
_Var_ = _unknown_; \
if( !item.getValueByName(val, _key_)) \
debug( toString("Key '%s' not found.", _key_) ); \
else \
_Var_ = _func_(val);
// Easy macro to translate value from georges
#define TRANSLATE_VAL( _Var_, _key_ ) \
if(!item.getValueByName(_Var_, _key_)) \
debug( toString("Key '%s' not found.", _key_) ); \
// ***************************************************************************
//-----------------------------------------------
// CItemSheet :
// Constructor.
//-----------------------------------------------
CItemSheet::CItemSheet()
{
IdShape = 0;
IdShapeFemale = 0;
MapVariant = 0;
ItemType = ITEM_TYPE::UNDEFINED;
Family = ITEMFAMILY::UNDEFINED;
SlotBF= 0;
IdIconBack = 0;
IdIconMain = 0;
IdIconOver = 0;
IdIconOver2 = 0;
IdIconText = 0;
IdAnimSet = 0;
Color = 0;
HasFx = false;
DropOrSell = false;
IsItemNoRent = false;
Stackable = 0;
IsConsumable = false;
IdEffect1 = 0;
IdEffect2 = 0;
IdEffect3 = 0;
IdEffect4 = 0;
Type = CEntitySheet::ITEM;
Bulk= 0.f;
EquipTime= 0;
NeverHideWhenEquiped = false;
RequiredCharac = CHARACTERISTICS::Unknown;
RequiredCharacLevel = 0;
RequiredSkill = SKILLS::unknown;
RequiredSkillLevel = 0;
IconColor= NLMISC::CRGBA::White;
IconBackColor= NLMISC::CRGBA::White;
IconOverColor= NLMISC::CRGBA::White;
IconOver2Color= NLMISC::CRGBA::White;
ItemOrigin = ITEM_ORIGIN::UNKNOWN;
Cosmetic.VPValue = 0;
Cosmetic.Gender = GSGENDER::unknown;
Armor.ArmorType = ARMORTYPE::UNKNOWN;
MeleeWeapon.WeaponType = WEAPONTYPE::UNKNOWN;
MeleeWeapon.Skill = SKILLS::unknown;
MeleeWeapon.DamageType = DMGTYPE::UNDEFINED;
MeleeWeapon.MeleeRange = 0;
RangeWeapon.WeaponType = WEAPONTYPE::UNKNOWN;
RangeWeapon.RangeWeaponType = RANGE_WEAPON_TYPE::Unknown;
RangeWeapon.Skill = SKILLS::unknown;
Ammo.Skill = SKILLS::unknown;
Ammo.DamageType = DMGTYPE::UNDEFINED;
Ammo.Magazine = 0;
Mp.Ecosystem = ECOSYSTEM::unknown;
Mp.MpCategory = MP_CATEGORY::Undefined;
Mp.HarvestSkill = SKILLS::unknown;
Mp.Family = RM_FAMILY::Unknown;
Mp.UsedAsCraftRequirement = false;
Mp.MpColor = 0;
Mp.StatEnergy = 0;
Mp.ItemPartBF = 0;
Shield.ShieldType = SHIELDTYPE::NONE;
Tool.Skill = SKILLS::unknown;
Tool.CraftingToolType = TOOL_TYPE::Unknown;
Tool.CommandRange = 0;
Tool.MaxDonkey = 0;
GuildOption.MoneyCost = 0;
GuildOption.XPCost = 0;
Pet.Slot = 0;
Teleport.Type = TELEPORT_TYPES::NONE;
}// CItemSheet //
//-----------------------------------------------
// build :
// Build the sheet from an external script.
//-----------------------------------------------
void CItemSheet::build(const NLGEORGES::UFormElm &item)
{
// Load the name.
string Shape;
if(!item.getValueByName(Shape, "3d.shape"))
debug("key '3d.shape' not found.");
IdShape = ClientSheetsStrings.add(Shape);
// Load the name.
string ShapeFemale;
if(!item.getValueByName(ShapeFemale, "3d.shape_female"))
debug("key '3d.shape_female' not found.");
IdShapeFemale = ClientSheetsStrings.add(ShapeFemale);
// Get the icon associated.
string IconMain;
if(!item.getValueByName (IconMain, "3d.icon"))
debug("key '3d.icon' not found.");
IconMain = strlwr (IconMain);
IdIconMain = ClientSheetsStrings.add(IconMain);
// Get the icon associated.
string IconBack;
if(!item.getValueByName (IconBack, "3d.icon background"))
debug("key '3d.icon background' not found.");
IconBack = strlwr (IconBack);
IdIconBack = ClientSheetsStrings.add(IconBack);
// Get the icon associated.
string IconOver;
if(!item.getValueByName (IconOver, "3d.icon overlay"))
debug("key '3d.icon overlay' not found.");
IconOver = strlwr (IconOver);
IdIconOver = ClientSheetsStrings.add(IconOver);
// Get the icon associated.
string IconOver2;
if(!item.getValueByName (IconOver2, "3d.icon overlay2"))
debug("key '3d.icon overlay2' not found.");
IconOver2 = strlwr (IconOver2);
IdIconOver2 = ClientSheetsStrings.add(IconOver2);
// Get Special modulate colors
item.getValueByName (IconColor, "3d.IconColor" );
item.getValueByName (IconBackColor, "3d.IconBackColor");
item.getValueByName (IconOverColor, "3d.IconOverColor");
item.getValueByName (IconOver2Color, "3d.IconOver2Color");
// Get the icon text associated.
string IconText;
if(!item.getValueByName (IconText, "3d.text overlay"))
debug("key '3d.text overlay' not found.");
IconText = strlwr (IconText);
IdIconText = ClientSheetsStrings.add(IconText);
// See if this item can be hiden when equiped
if(!item.getValueByName (NeverHideWhenEquiped, "3d.never hide when equiped"))
debug("key '3d.never hide when equiped.");
// Load the different slot in wicth the item can be equipped.
const UFormElm *pElt = 0;
// check uint32 is OK!
nlassert( SLOTTYPE::NB_SLOT_TYPE <= 32 );
SlotBF= 0;
if(item.getNodeByName(&pElt, "basics.EquipmentInfo.EquipmentSlots") && pElt)
{
// Get all slots.
uint size;
if(pElt->getArraySize(size))
{
for(uint i = 0; i < size; ++i)
{
string slotName;
if(pElt->getArrayValue(slotName, i))
{
// Check name.
if(slotName.empty())
debug(toString("The slot name %d is Empty.", i));
// Push the possible slots for the item in the list.
SlotBF|= SINT64_CONSTANT(1)<< (SLOTTYPE::stringToSlotType(NLMISC::strupr(slotName)));
}
}
}
else
debug("The element 'basics.Equipment Slot' is not an array.");
}
else
debug("Cannot create the element from the name 'basics.Equipment Slot'.");
// Get the Item Family.
string family;
if(!item.getValueByName(family, "basics.family"))
{
debug("Key 'basics.family' not found.");
Family = ITEMFAMILY::UNDEFINED;
}
else
{
Family = (ITEMFAMILY::EItemFamily) ITEMFAMILY::stringToItemFamily(NLMISC::strupr( family) );
if(Family == ITEMFAMILY::UNDEFINED)
debug("Item Family Undefined.");
}
// Get the Item Type.
string itemtype;
if(!item.getValueByName(itemtype, "basics.ItemType"))
{
debug("Key 'basics.ItemType' not found.");
ItemType = ITEM_TYPE::UNDEFINED;
}
else
{
ItemType = (ITEM_TYPE::TItemType) ITEM_TYPE::stringToItemType(NLMISC::strupr(itemtype) );
if (ItemType == ITEM_TYPE::UNDEFINED)
debug("Item Type Undefined.");
}
// Get the DropOrSell property
if(!item.getValueByName (DropOrSell, "basics.Drop or Sell"))
debug("key 'basics.Drop or Sell' not found.");
// Get the IsItemNoRent property
if(!item.getValueByName (IsItemNoRent, "basics.No Rent"))
debug("key 'basics.No Rent' not found.");
// Get the stackable property
if(!item.getValueByName (Stackable, "basics.stackable"))
debug("key 'basics.stackable' not found.");
// Get the Consumable property
if(!item.getValueByName (IsConsumable, "basics.Consumable"))
debug("key 'basics.Consumable' not found.");
// Get the texture variante.
if(!item.getValueByName(MapVariant, "3d.map_variant"))
debug("Key '3d.map_variant' not found.");
// Load the name.
string AnimSet;
if(!item.getValueByName(AnimSet, "3d.anim_set"))
debug("key '3d.anim_set' not found.");
// Force the CASE in UPPER to not be CASE SENSITIVE.
else
NLMISC::strlwr(AnimSet);
IdAnimSet = ClientSheetsStrings.add(AnimSet);
// Get the Trail Shape
if(!item.getValueByName(Color, "3d.color"))
debug("key '3d.color' not found.");
// Get the Fx flag
if(!item.getValueByName(HasFx, "3d.has_fx"))
debug("key '3d.has_fx' not found.");
// Get special Effect1
string Effect1;
if(!item.getValueByName(Effect1, "Effects.Effect1"))
debug("key 'Effects.Effect1' not found.");
Effect1 = strlwr(Effect1);
IdEffect1 = ClientSheetsStrings.add(Effect1);
// Get special Effect2
string Effect2;
if(!item.getValueByName(Effect2, "Effects.Effect2"))
debug("key 'Effects.Effect2' not found.");
Effect2 = strlwr(Effect2);
IdEffect2 = ClientSheetsStrings.add(Effect2);
// Get special Effect3
string Effect3;
if(!item.getValueByName(Effect3, "Effects.Effect3"))
debug("key 'Effects.Effect3' not found.");
Effect3 = strlwr(Effect3);
IdEffect3 = ClientSheetsStrings.add(Effect3);
// Get special Effect4
string Effect4;
if(!item.getValueByName(Effect4, "Effects.Effect4"))
debug("key 'Effects.Effect4' not found.");
Effect4 = strlwr(Effect4);
IdEffect4 = ClientSheetsStrings.add(Effect4);
// Get its bulk
TRANSLATE_VAL( Bulk, "basics.Bulk" );
// Get its equip time
TRANSLATE_VAL( EquipTime, "basics.Time to Equip In Ticks" );
// build fx part
FX.build(item, "3d.fx.");
// **** Build Help Infos
string val;
TRANSLATE_ENUM( RequiredCharac, CHARACTERISTICS::Unknown, CHARACTERISTICS::toCharacteristic, "basics.RequiredCharac");
TRANSLATE_VAL( RequiredCharacLevel, "basics.MinRequiredCharacLevel");
TRANSLATE_ENUM( RequiredSkill, SKILLS::unknown, SKILLS::toSkill, "basics.RequiredSkill");
TRANSLATE_VAL( RequiredSkillLevel, "basics.MinRequiredSkillLevel");
// item Origin
TRANSLATE_ENUM ( ItemOrigin, ITEM_ORIGIN::UNKNOWN, ITEM_ORIGIN::stringToEnum, "basics.origin");
/// item craft plan
TRANSLATE_VAL( val, "basics.CraftPlan" );
if (!val.empty())
CraftPlan = CSheetId(val);
// Special according to Family;
switch(Family)
{
// COSMETIC
case ITEMFAMILY::COSMETIC :
{
string sheetName = Id.toString();
string::size_type pos = sheetName.find('.',0);
if (pos == string::npos)
nlwarning(" Can't load the VPValue from sheet name in sheet %s", Id.toString().c_str() );
else
{
sint i = (sint)pos - 1;
for(; i >= 0; i-- )
{
if ( !isdigit( sheetName[i] ) )
break;
}
if ( i >= -1 )
{
string val = sheetName.substr( i + 1, pos - i - 1);
NLMISC::fromString( val, Cosmetic.VPValue );
}
}
if ( sheetName.find( "hof" ) != string::npos )
Cosmetic.Gender = GSGENDER::female;
else
Cosmetic.Gender = GSGENDER::male;
}
break;
// ARMOR
case ITEMFAMILY::ARMOR :
{
// ArmorType
TRANSLATE_ENUM ( Armor.ArmorType, ARMORTYPE::UNKNOWN, ARMORTYPE::toArmorType, "armor.Armor category" );
}
break;
// MELEE_WEAPON
case ITEMFAMILY::MELEE_WEAPON :
{
// WeaponType
TRANSLATE_ENUM ( MeleeWeapon.WeaponType, WEAPONTYPE::UNKNOWN, WEAPONTYPE::stringToWeaponType, "melee weapon.category" );
// Skill
TRANSLATE_ENUM ( MeleeWeapon.Skill, SKILLS::unknown, SKILLS::toSkill, "melee weapon.skill" );
// DamageType
TRANSLATE_ENUM ( MeleeWeapon.DamageType, DMGTYPE::UNDEFINED, DMGTYPE::stringToDamageType, "melee weapon.damage type" );
// DamageType
TRANSLATE_VAL ( MeleeWeapon.MeleeRange, "melee weapon.melee range" );
}
break;
// RANGE_WEAPON
case ITEMFAMILY::RANGE_WEAPON :
{
// WeaponType
TRANSLATE_ENUM ( RangeWeapon.WeaponType, WEAPONTYPE::UNKNOWN, WEAPONTYPE::stringToWeaponType, "range weapon.category" );
// Range weapon type
TRANSLATE_ENUM ( RangeWeapon.RangeWeaponType, RANGE_WEAPON_TYPE::Generic, RANGE_WEAPON_TYPE::stringToRangeWeaponType, "range weapon.RangeWeaponType" );
// Skill
TRANSLATE_ENUM ( RangeWeapon.Skill, SKILLS::unknown, SKILLS::toSkill, "range weapon.skill" );
}
break;
// AMMO
case ITEMFAMILY::AMMO :
{
// Skill
TRANSLATE_ENUM ( Ammo.Skill, SKILLS::unknown, SKILLS::toSkill, "ammo.weapon type" );
// DamageType
TRANSLATE_ENUM ( Ammo.DamageType, DMGTYPE::UNDEFINED, DMGTYPE::stringToDamageType, "ammo.damage type" );
// Magazine
TRANSLATE_VAL( Ammo.Magazine, "ammo.magazine" );
}
break;
// RAW_MATERIAL
case ITEMFAMILY::RAW_MATERIAL :
{
// Ecosystem
TRANSLATE_ENUM( Mp.Ecosystem, ECOSYSTEM::unknown, ECOSYSTEM::stringToEcosystem, "mp.Ecosystem" );
// MpCategory
TRANSLATE_ENUM( Mp.MpCategory, MP_CATEGORY::Undefined, MP_CATEGORY::stringToMPCategory, "mp.Category" );
// Skill
TRANSLATE_ENUM( Mp.HarvestSkill, SKILLS::unknown, SKILLS::toSkill, "mp.HarvestSkill" );
// MP Family
TRANSLATE_VAL( Mp.Family, "mp.Family" );
// Faber Item Part
uint i;
char keyTmp[256];
// ensure that if you modify RM_FABER_TYPE, you have to rebuild the item sheets.
nlctassert(RM_FABER_TYPE::NUM_FABER_TYPE == 26);
// ensure that the bitfields are enough (nb: unknown can be stored)
nlctassert(ITEM_ORIGIN::NUM_ITEM_ORIGIN < 256);
// ensure that the bitfield for item part buildable for this MP is possible
nlctassert(RM_FABER_TYPE::NUM_FABER_TYPE <= 32);
// reset
Mp.ItemPartBF= 0;
MpItemParts.clear();
// check if ok for each
for(i=0;i ok
if(DropOrSell)
return true;
// still can give any item to bot chat
return botChatGift;
}
// ***************************************************************************
void CItemSheet::getItemPartListAsText(ucstring &ipList) const
{
bool all= true;
for(uint i=0;i