2010-05-06 00:08:41 +00:00
|
|
|
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
|
|
|
|
// 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 <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/////////////
|
|
|
|
// 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.
|
2010-07-15 17:58:04 +00:00
|
|
|
SlotBF|= SINT64_CONSTANT(1)<< (SLOTTYPE::stringToSlotType(NLMISC::toUpper(slotName)));
|
2010-05-06 00:08:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
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
|
|
|
|
{
|
2010-07-15 17:58:04 +00:00
|
|
|
Family = (ITEMFAMILY::EItemFamily) ITEMFAMILY::stringToItemFamily(NLMISC::toUpper( family) );
|
2010-05-06 00:08:41 +00:00
|
|
|
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
|
|
|
|
{
|
2010-07-15 17:58:04 +00:00
|
|
|
ItemType = (ITEM_TYPE::TItemType) ITEM_TYPE::stringToItemType(NLMISC::toUpper(itemtype) );
|
2010-05-06 00:08:41 +00:00
|
|
|
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("<loadCosmetics> Can't load the VPValue from sheet name in sheet %s", Id.toString().c_str() );
|
|
|
|
else
|
|
|
|
{
|
2010-05-13 20:45:24 +00:00
|
|
|
sint i = (sint)pos - 1;
|
2010-05-06 00:08:41 +00:00
|
|
|
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<RM_FABER_TYPE::NUM_FABER_TYPE ;i++)
|
|
|
|
{
|
|
|
|
uint32 durability= 0;
|
|
|
|
string sheetEntry= RM_FABER_TYPE::faberTypeToSheetEntry((RM_FABER_TYPE::TRMFType)i);
|
|
|
|
|
|
|
|
// read the associated durablity of the MP faberType
|
|
|
|
sprintf(keyTmp, "mp.MpParam.%s.Durability", sheetEntry.c_str());
|
|
|
|
TRANSLATE_VAL(durability, keyTmp);
|
|
|
|
|
|
|
|
// If not null, ok this MP is associated to this faberType
|
|
|
|
if(durability)
|
|
|
|
{
|
|
|
|
Mp.ItemPartBF |= SINT64_CONSTANT(1)<<i;
|
|
|
|
MpItemParts.push_back(CMpItemPart());
|
|
|
|
CMpItemPart &itemPart= MpItemParts.back();
|
|
|
|
|
|
|
|
// read origin filter
|
|
|
|
sprintf(keyTmp, "mp.MpParam.%s.CraftCivSpec", sheetEntry.c_str());
|
|
|
|
TRANSLATE_ENUM( itemPart.OriginFilter, ITEM_ORIGIN::UNKNOWN, ITEM_ORIGIN::stringToEnum, keyTmp);
|
|
|
|
|
|
|
|
// read each stat
|
|
|
|
for(uint j=0;j<RM_FABER_STAT_TYPE::NumRMStatType;j++)
|
|
|
|
{
|
|
|
|
sprintf(keyTmp, "mp.MpParam.%s.%s", sheetEntry.c_str(), RM_FABER_STAT_TYPE::toString((RM_FABER_STAT_TYPE::TRMStatType)j).c_str());
|
|
|
|
TRANSLATE_VAL( itemPart.Stats[j], keyTmp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// UsedAsCraftRequirement
|
|
|
|
TRANSLATE_VAL( Mp.UsedAsCraftRequirement, "mp.UsedAsCraftRequirement" );
|
|
|
|
|
|
|
|
// MpColor
|
|
|
|
TRANSLATE_VAL( Mp.MpColor, "mp.MpColor" );
|
|
|
|
|
|
|
|
// Mp Stat Energy
|
|
|
|
TRANSLATE_VAL( Mp.StatEnergy, "mp.StatEnergy");
|
|
|
|
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
// SHIELD
|
|
|
|
case ITEMFAMILY::SHIELD :
|
|
|
|
{
|
|
|
|
// ShieldType
|
|
|
|
TRANSLATE_ENUM( Shield.ShieldType, SHIELDTYPE::NONE, SHIELDTYPE::stringToShieldType, "shield.Category" );
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
// TOOL: different for any tool
|
|
|
|
case ITEMFAMILY::CRAFTING_TOOL :
|
|
|
|
{
|
|
|
|
// CraftingToolType
|
|
|
|
TRANSLATE_ENUM( Tool.CraftingToolType, TOOL_TYPE::Unknown, TOOL_TYPE::toToolType, "crafting tool.type");
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ITEMFAMILY::HARVEST_TOOL :
|
|
|
|
{
|
|
|
|
// Skill
|
|
|
|
TRANSLATE_ENUM( Tool.Skill, SKILLS::unknown, SKILLS::toSkill, "harvest tool.skill" );
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ITEMFAMILY::TAMING_TOOL :
|
|
|
|
{
|
|
|
|
// Skill
|
|
|
|
TRANSLATE_ENUM( Tool.Skill, SKILLS::unknown, SKILLS::toSkill, "taming tool.skill" );
|
|
|
|
|
|
|
|
// CommandRange
|
|
|
|
TRANSLATE_VAL( Tool.CommandRange, "taming tool.command range" );
|
|
|
|
|
|
|
|
// MaxDonkey
|
|
|
|
TRANSLATE_VAL( Tool.MaxDonkey, "taming tool.max donkey" );
|
|
|
|
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ITEMFAMILY::GUILD_OPTION :
|
|
|
|
{
|
|
|
|
// Cost in money of the tool
|
|
|
|
TRANSLATE_VAL( GuildOption.MoneyCost, "guild option.Money Cost" );
|
|
|
|
|
|
|
|
// Cost in guild XP
|
|
|
|
TRANSLATE_VAL( GuildOption.XPCost, "guild option.Guild XP Cost" );
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ITEMFAMILY::PET_ANIMAL_TICKET :
|
|
|
|
{
|
|
|
|
// Cost in money of the tool
|
|
|
|
TRANSLATE_VAL( Pet.Slot, "pet.Pet Slot" );
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ITEMFAMILY::TELEPORT:
|
|
|
|
{
|
|
|
|
// Type of teleport
|
|
|
|
TRANSLATE_ENUM( Teleport.Type, TELEPORT_TYPES::NONE, TELEPORT_TYPES::getTpTypeFromString, "teleport.Type" );
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ITEMFAMILY::SCROLL:
|
|
|
|
{
|
|
|
|
// Scroll texture
|
|
|
|
TRANSLATE_VAL( Scroll.Texture, "Scroll.Texture");
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ITEMFAMILY::CONSUMABLE:
|
|
|
|
{
|
|
|
|
TRANSLATE_VAL( Consumable.ConsumptionTime, "Consumable.ConsumptionTime");
|
|
|
|
TRANSLATE_VAL( Consumable.OverdoseTimer, "Consumable.OverdoseTimer");
|
|
|
|
|
|
|
|
Consumable.Properties.clear();
|
|
|
|
for(uint i=0;i<4;i++)
|
|
|
|
{
|
|
|
|
string val;
|
|
|
|
item.getValueByName(val, toString("Consumable.Property %d", i).c_str() );
|
|
|
|
if(!val.empty() && val!="NULL")
|
|
|
|
{
|
|
|
|
Consumable.Properties.push_back(val);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
};
|
|
|
|
|
|
|
|
}// build //
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------
|
|
|
|
// serial :
|
|
|
|
// Serialize character sheet into binary data file.
|
|
|
|
//-----------------------------------------------
|
|
|
|
void CItemSheet::serial(class NLMISC::IStream &f) throw(NLMISC::EStream)
|
|
|
|
{
|
|
|
|
ClientSheetsStrings.serial(f, IdShape);
|
|
|
|
ClientSheetsStrings.serial(f, IdShapeFemale);
|
|
|
|
f.serial(SlotBF); // Serialize Slots used.
|
|
|
|
f.serial(MapVariant); // Serialize Map Variant.
|
|
|
|
f.serialEnum(Family); // Serialize Family.
|
|
|
|
f.serialEnum(ItemType); // Serialize ItemType.
|
|
|
|
ClientSheetsStrings.serial(f, IdIconMain);
|
|
|
|
ClientSheetsStrings.serial(f, IdIconBack);
|
|
|
|
ClientSheetsStrings.serial(f, IdIconOver);
|
|
|
|
ClientSheetsStrings.serial(f, IdIconOver2);
|
|
|
|
f.serial (IconColor);
|
|
|
|
f.serial (IconBackColor);
|
|
|
|
f.serial (IconOverColor);
|
|
|
|
f.serial (IconOver2Color);
|
|
|
|
ClientSheetsStrings.serial(f, IdIconText);
|
|
|
|
ClientSheetsStrings.serial(f, IdAnimSet);
|
|
|
|
f.serial(Color); // Serialize the item color.
|
|
|
|
f.serial(HasFx); // Serialize the has fx.
|
|
|
|
f.serial(DropOrSell);
|
|
|
|
f.serial(IsItemNoRent);
|
|
|
|
f.serial(NeverHideWhenEquiped);
|
|
|
|
f.serial(Stackable);
|
|
|
|
f.serial(IsConsumable);
|
|
|
|
f.serial(Bulk);
|
|
|
|
f.serial(EquipTime);
|
|
|
|
|
|
|
|
f.serial(FX);
|
|
|
|
|
|
|
|
ClientSheetsStrings.serial(f, IdEffect1);
|
|
|
|
ClientSheetsStrings.serial(f, IdEffect2);
|
|
|
|
ClientSheetsStrings.serial(f, IdEffect3);
|
|
|
|
ClientSheetsStrings.serial(f, IdEffect4);
|
|
|
|
|
|
|
|
f.serialCont(MpItemParts);
|
|
|
|
|
|
|
|
f.serial(CraftPlan);
|
|
|
|
|
|
|
|
f.serialEnum(RequiredCharac);
|
|
|
|
f.serial(RequiredCharacLevel);
|
|
|
|
f.serialEnum(RequiredSkill);
|
|
|
|
f.serial(RequiredSkillLevel);
|
|
|
|
|
|
|
|
// **** Serial Help Infos
|
|
|
|
f.serialEnum(ItemOrigin);
|
|
|
|
|
|
|
|
// Different Serial according to family
|
|
|
|
switch(Family)
|
|
|
|
{
|
|
|
|
case ITEMFAMILY::COSMETIC :
|
|
|
|
f.serial(Cosmetic);
|
|
|
|
break;
|
|
|
|
case ITEMFAMILY::ARMOR :
|
|
|
|
f.serial(Armor);
|
|
|
|
break;
|
|
|
|
case ITEMFAMILY::MELEE_WEAPON :
|
|
|
|
f.serial(MeleeWeapon);
|
|
|
|
break;
|
|
|
|
case ITEMFAMILY::RANGE_WEAPON :
|
|
|
|
f.serial(RangeWeapon);
|
|
|
|
break;
|
|
|
|
case ITEMFAMILY::AMMO :
|
|
|
|
f.serial(Ammo);
|
|
|
|
break;
|
|
|
|
case ITEMFAMILY::RAW_MATERIAL :
|
|
|
|
f.serial(Mp);
|
|
|
|
break;
|
|
|
|
case ITEMFAMILY::SHIELD :
|
|
|
|
f.serial(Shield);
|
|
|
|
break;
|
|
|
|
// Same for any tool
|
|
|
|
case ITEMFAMILY::CRAFTING_TOOL :
|
|
|
|
case ITEMFAMILY::HARVEST_TOOL :
|
|
|
|
case ITEMFAMILY::TAMING_TOOL :
|
|
|
|
f.serial(Tool);
|
|
|
|
break;
|
|
|
|
case ITEMFAMILY::GUILD_OPTION :
|
|
|
|
f.serial(GuildOption);
|
|
|
|
break;
|
|
|
|
case ITEMFAMILY::PET_ANIMAL_TICKET :
|
|
|
|
f.serial(Pet);
|
|
|
|
break;
|
|
|
|
case ITEMFAMILY::TELEPORT:
|
|
|
|
f.serial(Teleport);
|
|
|
|
break;
|
|
|
|
case ITEMFAMILY::SCROLL:
|
|
|
|
f.serial(Scroll);
|
|
|
|
break;
|
|
|
|
case ITEMFAMILY::CONSUMABLE:
|
|
|
|
f.serial(Consumable);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
};
|
|
|
|
|
|
|
|
}// serial //
|
|
|
|
|
|
|
|
|
|
|
|
// ***************************************************************************
|
|
|
|
bool CItemSheet::isFaberisable() const
|
|
|
|
{
|
|
|
|
// Only those family of item can be repaired/faber/refined.
|
|
|
|
return Family==ITEMFAMILY::AMMO ||
|
|
|
|
Family==ITEMFAMILY::ARMOR ||
|
|
|
|
Family==ITEMFAMILY::MELEE_WEAPON ||
|
|
|
|
Family==ITEMFAMILY::RANGE_WEAPON ||
|
|
|
|
Family==ITEMFAMILY::JEWELRY ||
|
|
|
|
Family==ITEMFAMILY::CRAFTING_TOOL ||
|
|
|
|
Family==ITEMFAMILY::HARVEST_TOOL ||
|
|
|
|
Family==ITEMFAMILY::TAMING_TOOL ||
|
|
|
|
Family==ITEMFAMILY::SHIELD;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ***************************************************************************
|
|
|
|
SKILLS::ESkills CItemSheet::getRequiredSkill() const
|
|
|
|
{
|
|
|
|
switch(Family)
|
|
|
|
{
|
|
|
|
// case ITEMFAMILY::ARMOR: return Armor.Skill;
|
|
|
|
case ITEMFAMILY::MELEE_WEAPON: return MeleeWeapon.Skill;
|
|
|
|
case ITEMFAMILY::RANGE_WEAPON: return RangeWeapon.Skill;
|
|
|
|
case ITEMFAMILY::AMMO: return Ammo.Skill;
|
|
|
|
// case ITEMFAMILY::SHIELD: return SHIELDTYPE::shieldTypeToSkill(Shield.ShieldType);
|
|
|
|
case ITEMFAMILY::RAW_MATERIAL: return Mp.HarvestSkill;
|
|
|
|
//
|
|
|
|
case ITEMFAMILY::HARVEST_TOOL:
|
|
|
|
case ITEMFAMILY::TAMING_TOOL:
|
|
|
|
return Tool.Skill;
|
|
|
|
case ITEMFAMILY::CRAFTING_TOOL:
|
|
|
|
return SKILLS::SC;
|
2010-05-15 16:47:21 +00:00
|
|
|
default: return SKILLS::unknown;
|
2010-05-06 00:08:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ***************************************************************************
|
|
|
|
bool CItemSheet::isUsedAsCraftRequirement() const
|
|
|
|
{
|
|
|
|
if(Family!=ITEMFAMILY::RAW_MATERIAL)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return Mp.UsedAsCraftRequirement;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ***************************************************************************
|
|
|
|
bool CItemSheet::canBuildSomeItemPart() const
|
|
|
|
{
|
|
|
|
if(Family!=ITEMFAMILY::RAW_MATERIAL)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return Mp.ItemPartBF!=0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ***************************************************************************
|
|
|
|
bool CItemSheet::canBuildItemPart(RM_FABER_TYPE::TRMFType e) const
|
|
|
|
{
|
|
|
|
if(e<RM_FABER_TYPE::NUM_FABER_TYPE)
|
|
|
|
{
|
|
|
|
if(Mp.ItemPartBF&(SINT64_CONSTANT(1)<<e))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// all other cases: false
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ***************************************************************************
|
|
|
|
bool CItemSheet::canBuildItemPart(RM_FABER_TYPE::TRMFType e, ITEM_ORIGIN::EItemOrigin origin) const
|
|
|
|
{
|
|
|
|
if(e<RM_FABER_TYPE::NUM_FABER_TYPE)
|
|
|
|
{
|
|
|
|
if(Mp.ItemPartBF&(SINT64_CONSTANT(1)<<e))
|
|
|
|
{
|
|
|
|
const CMpItemPart &itemPart= getItemPart(e);
|
|
|
|
// If this MP can build all origin items, or if origin matchs
|
|
|
|
if( itemPart.OriginFilter == ITEM_ORIGIN::COMMON ||
|
|
|
|
itemPart.OriginFilter == origin ||
|
|
|
|
origin == ITEM_ORIGIN::COMMON )
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// all other cases: false
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ***************************************************************************
|
|
|
|
const CItemSheet::CMpItemPart &CItemSheet::getItemPart(RM_FABER_TYPE::TRMFType e) const
|
|
|
|
{
|
|
|
|
nlassert(Mp.ItemPartBF&(SINT64_CONSTANT(1)<<e));
|
|
|
|
|
|
|
|
// count the number of bits set before reaching this item part
|
|
|
|
uint index= 0;
|
|
|
|
for(uint i=0;i<(uint)e;i++)
|
|
|
|
{
|
|
|
|
if(Mp.ItemPartBF&(SINT64_CONSTANT(1)<<i))
|
|
|
|
index++;
|
|
|
|
}
|
|
|
|
|
|
|
|
nlassert(index<MpItemParts.size());
|
|
|
|
return MpItemParts[index];
|
|
|
|
}
|
|
|
|
|
|
|
|
// ***************************************************************************
|
|
|
|
bool CItemSheet::hasCharacRequirement(uint itemLevel, CHARACTERISTICS::TCharacteristics &caracType, float &caracValue) const
|
|
|
|
{
|
|
|
|
|
|
|
|
switch( Family )
|
|
|
|
{
|
|
|
|
// **** ARMORS / BUCKLERS
|
|
|
|
case ITEMFAMILY::ARMOR:
|
|
|
|
case ITEMFAMILY::SHIELD:
|
|
|
|
switch( ItemType )
|
|
|
|
{
|
|
|
|
case ITEM_TYPE::LIGHT_BOOTS:
|
|
|
|
case ITEM_TYPE::LIGHT_GLOVES:
|
|
|
|
case ITEM_TYPE::LIGHT_PANTS:
|
|
|
|
case ITEM_TYPE::LIGHT_SLEEVES:
|
|
|
|
case ITEM_TYPE::LIGHT_VEST:
|
|
|
|
// No carac requirement
|
|
|
|
return false;
|
|
|
|
case ITEM_TYPE::MEDIUM_BOOTS:
|
|
|
|
case ITEM_TYPE::MEDIUM_GLOVES:
|
|
|
|
case ITEM_TYPE::MEDIUM_PANTS:
|
|
|
|
case ITEM_TYPE::MEDIUM_SLEEVES:
|
|
|
|
case ITEM_TYPE::MEDIUM_VEST:
|
|
|
|
case ITEM_TYPE::BUCKLER:
|
|
|
|
// Constitution requirement
|
|
|
|
caracType= CHARACTERISTICS::constitution;
|
|
|
|
caracValue= itemLevel / 1.5f;
|
|
|
|
return true;
|
|
|
|
case ITEM_TYPE::HEAVY_BOOTS:
|
|
|
|
case ITEM_TYPE::HEAVY_GLOVES:
|
|
|
|
case ITEM_TYPE::HEAVY_PANTS:
|
|
|
|
case ITEM_TYPE::HEAVY_SLEEVES:
|
|
|
|
case ITEM_TYPE::HEAVY_VEST:
|
|
|
|
case ITEM_TYPE::HEAVY_HELMET:
|
|
|
|
case ITEM_TYPE::SHIELD:
|
|
|
|
// Constitution requirement
|
|
|
|
caracType= CHARACTERISTICS::constitution;
|
|
|
|
caracValue= float((sint)itemLevel - 10);
|
|
|
|
caracValue= max(caracValue, 0.f);
|
|
|
|
return true;
|
|
|
|
default:
|
|
|
|
// No carac requirement
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
// **** MELEE_WEAPONS
|
|
|
|
case ITEMFAMILY::MELEE_WEAPON:
|
|
|
|
switch( ItemType )
|
|
|
|
{
|
|
|
|
case ITEM_TYPE::MAGICIAN_STAFF:
|
|
|
|
// Intelligence requirement
|
|
|
|
caracType= CHARACTERISTICS::intelligence;
|
|
|
|
caracValue= float((sint)itemLevel - 10);
|
|
|
|
caracValue= max(caracValue, 0.f);
|
|
|
|
return true;
|
|
|
|
default:
|
|
|
|
// Strength requirement
|
|
|
|
caracType= CHARACTERISTICS::strength;
|
|
|
|
caracValue= float((sint)itemLevel - 10);
|
|
|
|
caracValue= max(caracValue, 0.f);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
// **** RANGE_WEAPON
|
|
|
|
case ITEMFAMILY::RANGE_WEAPON:
|
|
|
|
caracType= CHARACTERISTICS::well_balanced;
|
|
|
|
caracValue= float((sint)itemLevel - 10);
|
|
|
|
caracValue= max(caracValue, 0.f);
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// **** OTHERS
|
|
|
|
default:
|
|
|
|
// No carac requirement
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ***************************************************************************
|
|
|
|
bool CItemSheet::canExchangeOrGive(bool botChatGift) const
|
|
|
|
{
|
|
|
|
// DropOrSell => 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<RM_FABER_TYPE::NUM_FABER_TYPE;i++)
|
|
|
|
{
|
|
|
|
RM_FABER_TYPE::TRMFType faberType= RM_FABER_TYPE::TRMFType(i);
|
|
|
|
|
|
|
|
if(canBuildItemPart(faberType))
|
|
|
|
{
|
|
|
|
if(!ipList.empty())
|
|
|
|
ipList+= ", ";
|
|
|
|
ipList+= RM_FABER_TYPE::toLocalString(faberType);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Ignore Tools and CampFire
|
|
|
|
if( faberType!=RM_FABER_TYPE::MPBT &&
|
|
|
|
faberType!=RM_FABER_TYPE::MPPES &&
|
|
|
|
faberType!=RM_FABER_TYPE::MPSH &&
|
|
|
|
faberType!=RM_FABER_TYPE::MPTK &&
|
|
|
|
faberType!=RM_FABER_TYPE::MPJH &&
|
|
|
|
faberType!=RM_FABER_TYPE::MPCF )
|
|
|
|
all= false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(all)
|
|
|
|
{
|
|
|
|
ipList= CI18N::get("uihelpItemMPAllCraft");
|
|
|
|
}
|
|
|
|
}
|