#include "stdafx.h" #include "ItemInfoParser.h" #include "./Define.h" #include "./Struct.h" #include #include //================================================================================================== ItemInfoParser* ItemInfoParser::item_info_parser_static_ = NULL; ItemInfoParser* ItemInfoParser::CreateInstance() { // (NOTE) thread-unsafe singleton item_info_parser_static_ = new ItemInfoParser; return item_info_parser_static_; } void ItemInfoParser::DestroyInstance() { SAFE_DELETE(item_info_parser_static_); } //================================================================================================== #ifdef _SERVER static void _ItemLoggingForDuplicatedViolation(CODETYPE item_code, int duplicable_num, const char* category) { SUNLOG(eCRITICAL_LOG, "ItemCode|%u|DupNum(%d) != 1|'%s'DupNum必须是1,不能重复", item_code, duplicable_num, category); } static void _ItemLoggingForFunctionViolation(CODETYPE item_code, const char* category, const char* func_attribute) { SUNLOG(eCRITICAL_LOG, "ItemCode|%u|'%s' 不能使用 '%s'", item_code, category, func_attribute); } #define LOG_ITEM_VIOLATION_DUPLICATE(arg0, arg1, arg2) \ _ItemLoggingForDuplicatedViolation(arg0, arg1, arg2) #define LOG_ITEM_VIOLATION_FUCTION(arg0, arg1, arg2) \ _ItemLoggingForFunctionViolation(arg0, arg1, arg2) #else //!_SERVER #define LOG_ITEM_VIOLATION_DUPLICATE(arg0, arg1, arg2) #define LOG_ITEM_VIOLATION_FUCTION(arg0, arg1, arg2) #endif //!_SERVER //================================================================================================== ItemInfoParser::ItemInfoParser() : RENDER_EFFECT_ITEMS(render_effect_item_list_) { } ItemInfoParser::~ItemInfoParser() { } void ItemInfoParser::Release() { Unload(); } void ItemInfoParser::Init(DWORD unused_arg) { __UNUSED(unused_arg); // (CHANGES) (f100505.1L) changes data structure related to the BASE_ITEMINFO loaded_ = false; cool_time_table_.clear(); #if defined (_NA_0_20091208_VENDOR_ITEM_SEARCH) || (defined(_DH_GM_ITEM_WINDOW) && !defined(_SERVER)) item_name_code_table_.clear(); #endif//_NA_0_20091208_VENDOR_ITEM_SEARCH render_effect_item_list_.clear(); ZeroMemory(&item_table_, sizeof(item_table_)); ZeroMemory(file_name_, sizeof(file_name_)); } void ItemInfoParser::Init(DWORD unused_arg, char* pack_file_name) { Init(unused_arg); SetPackFileName(pack_file_name); } void ItemInfoParser::Unload() { // (CHANGES) (f100505.1L) changes data structure related to the BASE_ITEMINFO if (loaded_ == false) { return; } ;{ // release all resource in a table this->SetFirst(); while (BASE_ITEMINFO* item_info = this->GetNext()) { delete item_info; }; if (item_table_.seq_total_indexes_) { ::free(const_cast(item_table_.seq_total_indexes_)); }; if (item_table_.client_checksum_array_) { ::free(item_table_.client_checksum_array_); }; ZeroMemory(&item_table_, sizeof(item_table_)); }; // render_effect_item_list_.clear(); ;{ // (NOTE) it has not the usage case at this point in time (100505) DUP_EQUIP_GROUP_INFO_MAP::const_iterator it = dup_item_group_.begin(); const DUP_EQUIP_GROUP_INFO_MAP::const_iterator end = dup_item_group_.end(); for ( ; it != end; ++it) { delete it->second; } dup_item_group_.clear(); }; #if defined (_NA_0_20091208_VENDOR_ITEM_SEARCH) || (defined(_DH_GM_ITEM_WINDOW) && !defined(_SERVER)) item_name_code_table_.clear(); #endif//_NA_0_20091208_VENDOR_ITEM_SEARCH // // must be settled last position loaded_ = false; } // (CHANGES) (f100505.1L) add the item access facility which is supported an O(1) time complexity bool ItemInfoParser::_AddItemInfo(CODETYPE item_code, BASE_ITEMINFO* item_info) { if (item_code == 0 || item_code > USHRT_MAX || item_info == NULL) { return false; } --item_code; item_table_.array_[item_code] = item_info; return true; } // (CHANGES) (f100505.1L) add the item access facility which is supported an O(1) time complexity bool ItemInfoParser::_BuildReference(int added_number_of_items) { if (added_number_of_items <= 0) { return false; } const int resize_number = item_table_.number_of_total_items_ + added_number_of_items; if (item_table_.seq_total_indexes_) { ::free(const_cast(item_table_.seq_total_indexes_)); } const int chunk_size = sizeof(uint16_t) * resize_number; ;{ void* ptr = ::malloc(chunk_size); ZeroMemory(ptr, chunk_size); item_table_.seq_total_indexes_ = reinterpret_cast(ptr); }; uint16_t* dest_it = const_cast(item_table_.seq_total_indexes_); // const BASE_ITEMINFO* const * it = item_table_.array_; const BASE_ITEMINFO* const * const end = &item_table_.array_[_countof(item_table_.array_)]; while (true) { while (it < end && (*it) == NULL) { ++it; } if (it >= end) { break; } *dest_it = static_cast(it - item_table_.array_); ++dest_it; ++it; } item_table_.number_of_total_items_ = resize_number; return true; } //================================================================================================== BOOL ItemInfoParser::_Load(BOOL reloaded) { CODETYPE previous_item_code_for_debugging = 0; if (item_table_.client_checksum_array_ == NULL) { void* ptr = ::malloc(sizeof(ulong) * USHRT_MAX); ZeroMemory(ptr, (sizeof(ulong) * USHRT_MAX)); item_table_.client_checksum_array_ = reinterpret_cast(ptr); }; const int max_rows = GetRowSize(); for (int row_no = 0; row_no < max_rows; ++row_no) { const CODETYPE item_code = GetDataDWORD("Code", row_no); if (!FlowControl::FCAssert(item_code != 0 && item_code <= USHRT_MAX)) { SUNLOG(eCRITICAL_LOG, _T("["__FUNCTION__"]|物品代码规范无效.|Code=%d|File={%s}|"), item_code, GetCurFileName()); FASSERT(!"["__FUNCTION__"]|物品代码规范无效.|"); }; BASE_ITEMINFO* item_info = GetItemInfo(item_code); if (item_info == NULL) { item_info = new BASE_ITEMINFO; ZeroMemory(item_info, sizeof(*item_info)); _AddItemInfo(item_code, item_info); } else { if (false == reloaded) { SUNLOG(eCRITICAL_LOG, _T("["__FUNCTION__"]|物品代码已存在|Code=%d|File={%s}|"), item_code, GetCurFileName()); FASSERT(!"["__FUNCTION__"]|物品代码已存在|"); } } item_info->m_Code = SLOTCODE(item_code); item_info->m_ChargeType = GetDataBYTE("ChargeType", row_no); item_info->m_ChargeSubType = GetDataBYTE("ChargeSubType", row_no); strncpy(item_info->m_pszName, GetDataString("Name", row_no), _countof(item_info->m_pszName)); item_info->m_pszName[_countof(item_info->m_pszName) - 1] = '\0'; item_info->m_NCode = GetDataDWORD("NameCode", row_no); item_info->m_bUse = (GetDataBYTE("NameColorType", row_no) != 0); // (NOTE) boundary... strncpy(item_info->m_szColor, GetDataString("NameColorCode", row_no), item_info->MAX_COLOR_LENGTH); item_info->m_SCNCode = GetDataDWORD("NameCode2", row_no); item_info->m_TDNCode = GetDataDWORD("DNCode3", row_no); item_info->m_wWICode = GetDataDWORD("WearImageCode", row_no); #ifdef _NA_002050_20110216_ADD_GENDER // m_wWICode : 用于男性角色的图片源代码 item_info->m_wWICode2 = GetDataDWORD("WearImageCode2", row_no); //用于女性角色的图形源代码 #endif //_NA_002050_20110216_ADD_GENDER item_info->m_wVICode = GetDataDWORD("InvenImageCode", row_no); item_info->m_wDICode = GetDataDWORD("DropImageCode", row_no); #ifdef _20220413_ITEM_DROP_EFFECT item_info->m_wzItemDropEffect = StrToWzID(GetDataString("ItemDropEffect",row_no)); #endif item_info->m_wType = GetDataWORD("Type", row_no); item_info->m_byEventCode = GetDataBYTE("Etype", row_no); item_info->m_nSoundIndex = GetDataInt("ItemSoundIndex", row_no); // (CHANGES) (091202) (WAVERIX) change type item_info->m_byEffectPosition = GetDataBYTE("EffectPosition", row_no); item_info->m_dwEffectCode = StrToWzID(GetDataString("EffectCode", row_no)); // (CHANGES) (091202) (WAVERIX) change type item_info->m_bEfffectBoneRot = GetDataBYTE("RotBone", row_no); item_info->m_dwEquipBoneID = StrToWzID(GetDataString("BoneName", row_no)); item_info->m_bEquipRot = (GetDataBYTE("SABoneType", row_no) != 0); // (REF) eITEMSUBTYPE item_info->m_wSubType = GetDataWORD("SubType", row_no); #ifdef _NA_002050_20110216_ADD_GENDER item_info->gender_type = GetDataBYTE(_T("GenderType"), row_no); if (item_info->gender_type != GenderType::kAll && item_info->gender_type != GenderType::kMale && item_info->gender_type != GenderType::kFemale) { item_info->gender_type = GenderType::kAll; SUNLOG(eCRITICAL_LOG, _T("|%s|性别设置不正确,初始化为0。| Item Code=%u,行号=%u |"), __FUNCTION__, item_info->m_Code, row_no); } #endif // _NA_002050_20110216_ADD_GENDER // (REF) BASE_ITEMINFO::eSetItemOption item_info->m_bySetOptionType = GetDataBYTE("SetOptionType", row_no); item_info->set_group_code = GetDataWORD("SetType", row_no); item_info->m_LV = GetDataWORD("Level", row_no); SASSERT(item_info->m_LV > 0, "物品等级必须在0以上。数据错误!"); item_info->m_Dura = GetDataBYTE("Dura", row_no); item_info->m_dwDuraStr = GetDataDWORD("DuraStrenth", row_no); if (item_info->m_dwDuraStr == 0) { // 企划中故意设置为0 // if (pInfo->IsWeapon() || pInfo->IsArmor()) // SUNLOG("[版绊:%u]:DuraStrength啊 0涝聪促.\n", pInfo->m_NCode); } #ifdef __NA_001062_20080623_STRENGTH_PENALTY item_info->m_dwStrengthPenaltyIdx = GetDataBYTE("StrengthPenaltyIndex", row_no); #endif item_info->m_DropLV = GetDataDWORD64("ItemSellMoney", row_no); item_info->m_byPopup = GetDataBYTE("Popup", row_no); item_info->m_byMaterialType = GetDataBYTE("MaterialType", row_no); item_info->trade_sell_type = GetDataWORD("TradeSellType", row_no); item_info->m_byMixture = GetDataBYTE("Mixture", row_no); item_info->m_bPossessionItem = GetDataBYTE("ReversionType", row_no); //_NA000960_101011_ITEM_CUSTOMIZING_CONTENTS_ADD_RULE_ item_info->etherealization_mode_.value = GetDataBYTE("ExtractType", row_no); item_info->m_LimitEqLevel = GetDataWORD("LimitEqLevel", row_no); //__CN_1299_WASTE_ITEM_LEVEL_LIMITE_CHECK item_info->m_LimitUseLevel = GetDataWORD("LimitUseLevel", row_no); item_info->m_wLimitStr = GetDataWORD("LimitStr", row_no); item_info->m_wLimitDex = GetDataWORD("LimitDex", row_no); item_info->m_wLimitVit = GetDataWORD("LimitVit", row_no); item_info->m_wLimitInt = GetDataWORD("LimitInt", row_no); item_info->m_wLimitSpr = GetDataWORD("LimitSpr", row_no); item_info->m_wLimitSkil1 = GetDataWORD("LimitSkill1", row_no); item_info->m_wLimitSkil2 = GetDataWORD("LimitSkill2", row_no); item_info->m_wMinDamage = GetDataWORD("MinDamage", row_no); item_info->m_wMaxDamage = GetDataWORD("MaxDamage", row_no); #ifdef _NA001605_EP2_ATTRIBUTES_RENEWAL_ item_info->m_wPhyAttRate = static_cast( util::LL_Round(GetDataNumber("PhyAttRate", row_no) * 100.0f)); item_info->m_wPhyAvoid = static_cast( util::LL_Round(GetDataNumber("PhyAvoid", row_no) * 100.0f)); #else item_info->m_wPhyAttRate = GetDataWORD("PhyAttRate", row_no); item_info->m_wPhyAvoid = GetDataWORD("PhyAvoid", row_no); #endif item_info->m_wPhyAttSpeed = GetDataWORD("PhyAttSpeed", row_no); item_info->m_wPhyDef = GetDataWORD("PhyDef", row_no); item_info->m_byBaseAttType = GetDataBYTE("BaseAttType", row_no); item_info->m_byMagicalAttType = GetDataBYTE("MagicalAttType", row_no); item_info->m_byMeleeType = GetDataBYTE("MeleeType", row_no); item_info->m_fAttRange = GetDataFloat("AttRange", row_no); item_info->m_byArmorType = GetDataBYTE("ArmorType", row_no); item_info->m_wMagicAttMinDamgage = GetDataWORD("MagicAttMinDamgage", row_no); item_info->m_wMagicAttMaxDamgage = GetDataWORD("MagicAttMaxDamgage", row_no); item_info->m_wMagicAttSpeed = GetDataWORD("MagicAttSpeed", row_no); #if !defined(_NA001605_EP2_ATTRIBUTES_RENEWAL_) item_info->m_wMagicDef = GetDataWORD("MagicDef", row_no); #endif item_info->m_wSpeed = GetDataWORD("Speed", row_no); ;{ // NOTE: f110408.2L, 添加复合位字段 = { (1 << eCHAR_BERSERKER) | ... } item_info->m_wEqClass1 = GetDataWORD("EqClass1", row_no); item_info->m_wEqClass2 = GetDataWORD("EqClass2", row_no); item_info->m_wEqClass3 = GetDataWORD("EqClass3", row_no); item_info->m_wEqClass4 = GetDataWORD("EqClass4", row_no); item_info->m_wEqClass5 = GetDataWORD("EqClass5", row_no); // _NA_004965_20120613_NEW_CHARACTER_MYSTIC item_info->m_wEqClass6 = GetDataWORD("EqClass6", row_no); #ifdef _NA_000000_20130812_NEW_CHARACTER_HELLROID item_info->m_wEqClass7 = GetDataWORD("EqClass7", row_no); #endif //_NA_000000_20130812_NEW_CHARACTER_HELLROID #ifdef _NA_007514_20140828_NEW_CHARACTER_WITCHBLADE item_info->m_wEqClass8 = GetDataWORD("EqClass8", row_no); #endif //_NA_007514_20140828_NEW_CHARACTER_WITCHBLADE uint16_t composed = 0; if (item_info->m_wEqClass1) { composed |= (1 << eCHAR_BERSERKER); } if (item_info->m_wEqClass2) { composed |= (1 << eCHAR_DRAGON); } if (item_info->m_wEqClass3) { composed |= (1 << eCHAR_SHADOW); } if (item_info->m_wEqClass4) { composed |= (1 << eCHAR_VALKYRIE); } if (item_info->m_wEqClass5) { composed |= (1 << eCHAR_ELEMENTALIST); } // _NA_004965_20120613_NEW_CHARACTER_MYSTIC if (item_info->m_wEqClass6) { composed |= (1 << eCHAR_MYSTIC); } #ifdef _NA_000000_20130812_NEW_CHARACTER_HELLROID if (item_info->m_wEqClass7) { composed |= (1 << eCHAR_HELLROID); } #endif //_NA_000000_20130812_NEW_CHARACTER_HELLROID #ifdef _NA_007514_20140828_NEW_CHARACTER_WITCHBLADE if (item_info->m_wEqClass8) { composed |= (1 << eCHAR_WITCHBLADE); } #endif //_NA_007514_20140828_NEW_CHARACTER_WITCHBLADE item_info->equip_class_bits = composed; }; // (REF) {eEQUIPCONTAINER_POS, eRIDER_PARTS_POS} 装备位置+骑士帕兹装备位置 item_info->m_wEqPos = GetDataBYTE("EqPos", row_no); char szName[32]; for (int op = 0; op < _countof(item_info->m_byOptionExEffect); ++op) { BYTE& rExcerciseEffect = item_info->m_byOptionExEffect[op]; _snprintf(szName, 32, "ExerciseEffect%d", op + 1); rExcerciseEffect = GetDataBYTE(szName, row_no); switch (rExcerciseEffect) { case eITEM_EFFECT_NONE: case eITEM_EFFECT_ON_EQUIP: case eITEM_EFFECT_ON_INVEN: break; default: SUNLOG(eCRITICAL_LOG, "[%u]OptionExcerciseEffect值(%u)无效,已修复为“NONE”", item_info->m_Code, rExcerciseEffect); rExcerciseEffect = eITEM_EFFECT_NONE; break; } _snprintf(szName, 32, "OptionKind%d", op + 1); item_info->m_wOptionIndex[op] = GetDataWORD(szName, row_no); _snprintf(szName, 32, "OptionType%d", op + 1); item_info->m_byOptionType[op] = GetDataBYTE(szName, row_no); _snprintf(szName, 32, "OptionValue%d", op + 1); item_info->m_iOptionValue[op] = GetDataInt(szName, row_no); if (item_info->m_wOptionIndex[op] >= _countof(g_ITEM_OPTION)) { SUNLOG(eCRITICAL_LOG, "物品代码|%u|OptionIndex : OptionValue = %u : %u|超出范围", item_info->m_Code, item_info->m_wOptionIndex[op], item_info->m_iOptionValue[op]); } } for (int i = 0; i < _countof(item_info->m_byPCOptionExEffect); ++i) { BYTE& rExcerciseEffect = item_info->m_byPCOptionExEffect[i]; _snprintf(szName, 32, "PCExerciseEffect%d", i+1); rExcerciseEffect = GetDataBYTE(szName, row_no); switch (rExcerciseEffect) { case eITEM_EFFECT_NONE: case eITEM_EFFECT_ON_EQUIP: case eITEM_EFFECT_ON_INVEN: break; default: SUNLOG(eCRITICAL_LOG, "物品代码|%u|OptionExcerciseEffect 值 (%u)无效, 更改为NONE", item_info->m_Code, rExcerciseEffect); rExcerciseEffect = eITEM_EFFECT_NONE; break; } _snprintf(szName, 32, "PCOptionKind%d", i+1); item_info->m_wPCOptionIndex[i] = GetDataWORD(szName, row_no); _snprintf(szName, 32, "PCOptionType%d", i+1); item_info->m_byPCOptionType[i] = GetDataBYTE(szName, row_no); _snprintf(szName, 32, "PCOptionValue%d", i+1); item_info->m_iPCOptionValue[i] = GetDataInt(szName, row_no); if (item_info->m_wPCOptionIndex[i] >= _countof(g_ITEM_OPTION)) { SUNLOG(eCRITICAL_LOG, "物品代码|%u|OptionIndex : OptionValue = %u : %u|超出范围s", item_info->m_Code, item_info->m_wPCOptionIndex[i], item_info->m_iPCOptionValue[i]); } } item_info->m_wMissile = GetDataWORD("Missile", row_no); item_info->m_bHeadType = GetDataBYTE("HeadType", row_no); if (item_info->m_bHeadType) --item_info->m_bHeadType;// (NOTE) what is it? //-如果该价格是1的话,就不会画脸和头发。 //(使用头盔时头发会露出来的情况) //-追加:如果该价格为2,就不会画头发。 //(为了与现有脚本的兼容性.。添加新值。) item_info->m_wCustomize = GetDataWORD("Customize", row_no); #ifdef _NA_002050_20110216_ADD_GENDER item_info->m_bHeadType1 = GetDataBYTE("HeadType2", row_no); if (item_info->m_bHeadType1) --item_info->m_bHeadType1; item_info->m_wCustomize1 = GetDataWORD("Customize2", row_no); #endif //_NA_002050_20110216_ADD_GENDER item_info->m_byDupNum = GetDataWORD("DupNum", row_no); if (item_info->m_byDupNum == 0) { SUNLOG(eCRITICAL_LOG, "物品代码|%u|m_byDupNum = 0", item_info->m_Code); item_info->m_byDupNum = 1; } item_info->m_byDupEquipNum = GetDataBYTE("DupEquipNum", row_no); item_info->m_byDupEquipTypeNum = GetDataBYTE("DupEquipTypeNum", row_no); item_info->m_byDupEquipGroup = GetDataBYTE("DupEquipGroup", row_no); item_info->m_byDupEquipGroupNum = GetDataBYTE("DupEquipGroupNum", row_no); DUP_EQUIP_GROUP_INFO_MAP::const_iterator find_dup_equip = \ dup_item_group_.find(item_info->m_byDupEquipGroup); // 存在的话。.. if (find_dup_equip != dup_item_group_.end()) { // 存在的话…检查当前值。. const DUP_EQUIP_GROUP_INFO* equip_group_info = find_dup_equip->second; if (equip_group_info->m_byDupEquipGroupNum != item_info->m_byDupEquipGroupNum) { SUNLOG(eCRITICAL_LOG, "["__FUNCTION__"]|物品代码|%d|GroupNum|%d|字段[DupEquipGroupNum]无效", item_info->m_Code, item_info->m_byDupEquipGroupNum); } } else { //不存在就放在内存里. DUP_EQUIP_GROUP_INFO* pGroupInfo = new DUP_EQUIP_GROUP_INFO; pGroupInfo->m_byDupEquipGroup = item_info->m_byDupEquipGroup; pGroupInfo->m_byDupEquipGroupNum = item_info->m_byDupEquipGroupNum; dup_item_group_.insert(std::make_pair(pGroupInfo->m_byDupEquipGroup, pGroupInfo)); } item_info->m_byWasteType = GetDataBYTE("WasteType", row_no); item_info->m_wCoolTimeType = GetDataWORD("CoolTimeType", row_no); item_info->m_wHealHP = GetDataWORD("HealHP", row_no); item_info->m_dwExp = GetDataDWORD64("ExpHP", row_no); item_info->m_wTimes = GetDataWORD("Times", row_no); item_info->m_dCoolTime = GetDataDWORD("CoolTime", row_no); item_info->m_wHealHPTime = GetDataDWORD("HealTime", row_no); if (0 != item_info->m_wCoolTimeType) { ITEM_COOLTIME_ITER it = cool_time_table_.find(item_info->m_wCoolTimeType); if (it == cool_time_table_.end()) { ITEM_COOLTIME_INFO item_cooltime_info; item_cooltime_info.m_wCoolTimeType = item_info->m_wCoolTimeType; item_cooltime_info.m_dwCoolTime = item_info->m_dCoolTime; cool_time_table_.insert(\ std::make_pair(item_info->m_wCoolTimeType, item_cooltime_info)); } else { it->second.m_wCoolTimeType = item_info->m_wCoolTimeType; it->second.m_dwCoolTime = item_info->m_dCoolTime; } } //__NA_1323_CHAO_TIME_DECREASE_ITEM item_info->m_byChaoTimeDec = GetDataBYTE("ChaoTimeDec", row_no); // m_wSpecialEffect 变为 m_wQuestCode (2006. 8. 7.) item_info->m_wQuestCode = GetDataWORD("QuestCode", row_no); // (REF) Lottery index group item_info->m_MaterialCode = GetDataWORD("MaterialCode", row_no); // (WARNING) 多用途项目。 //与道具相关的(技能/MAPCODE/Wax Level),等等根据道具类型不同处理。. item_info->m_wSkillCode = GetDataWORD("SkillCode", row_no); // _NA_000251_20100727_SOCKET_SYSTEM item_info->zard_grade = GetDataBYTE(_T("ZardGrade"), row_no); item_info->zard_item_option_kind = GetDataBYTE(_T("ZardOptionKind"), row_no); item_info->zard_success_per = GetDataWORD(_T("ZardSuccesPer"), row_no); item_info->m_ExchangedItem = GetDataWORD("ExchangedItem", row_no); item_info->m_RidingClass.value = GetDataBYTE("EqRidingClass", row_no); //------------------------------------------------------------------------------------------ // 2006/3/20 : 关于神界 item_info->m_wDivLimitStr = GetDataWORD("DivLimitStr", row_no); item_info->m_wDivLimitDex = GetDataWORD("DivLimitDex", row_no); item_info->m_wDivLimitVit = GetDataWORD("DivLimitVit", row_no); item_info->m_wDivLimitInt = GetDataWORD("DivLimitInt", row_no); item_info->m_wDivLimitSpr = GetDataWORD("DivLimitSpr", row_no); item_info->m_wDivLimitSkill1 = GetDataWORD("DivLimitSkill1", row_no); item_info->m_wDivLimitSkill2 = GetDataWORD("DivLimitSkill2", row_no); item_info->m_wDivPhyMinDamage = GetDataWORD("DivPhyMinDamage", row_no); item_info->m_wDivPhyMaxDamage = GetDataWORD("DivPhyMaxDamage", row_no); item_info->m_wDivMagicMinDamage = GetDataWORD("DivMagicMinDamage", row_no); item_info->m_wDivMagicMaxDamage = GetDataWORD("DivMagicMaxDamage", row_no); item_info->m_wDivPhyDef = GetDataWORD("DivPhyDef", row_no); #if !defined(_NA001605_EP2_ATTRIBUTES_RENEWAL_) item_info->m_wDivMagicDef = GetDataWORD("DivMagicDef", row_no); #endif //------------------------------------------------------------------------------------------ //区域征服组 // m_wACCode在ep2 AC系统后更改为smalltype item_info->m_wACCode = GetDataBYTE("ACCode", row_no); item_info->m_byACReferenceID = GetDataBYTE("ACReferenceID", row_no); if (item_info->m_wACCode == 0 && item_info->m_byACReferenceID != 0) { SUNLOG(eCRITICAL_LOG, "物品代码|%u|m_wACCode|%d|m_byACReferenceID|%d|" "如果[ref_id]不为0,那么[ACcode]必须不为0", item_info->m_Code, item_info->m_wACCode, item_info->m_byACReferenceID); } //------------------------------------------------------------------------------------------ // 精英项目选项 item_info->m_wElitePhyMinDamage = GetDataWORD("ElitePhyMinDamage", row_no); item_info->m_wElitePhyMaxDamage = GetDataWORD("ElitePhyMaxDamage", row_no); item_info->m_wEliteMagicMinDamage = GetDataWORD("EliteMagicMinDamage", row_no); item_info->m_wEliteMagicMaxDamage = GetDataWORD("EliteMagicMaxDamage", row_no); item_info->m_wElitePhyDef = GetDataWORD("ElitePhyDef", row_no); #if !defined(_NA001605_EP2_ATTRIBUTES_RENEWAL_) item_info->m_wEliteMagicDef = GetDataWORD("EliteMagicDef", row_no); #endif //------------------------------------------------------------------------------------------ // 独特的物品选项 item_info->m_wUniPhyMinDamage = GetDataWORD("UniPhyMinDamage", row_no); item_info->m_wUniPhyMaxDamage = GetDataWORD("UniPhyMaxDamage", row_no); item_info->m_wUniMagicMinDamage = GetDataWORD("UniMagicMinDamage", row_no); item_info->m_wUniMagicMaxDamage = GetDataWORD("UniMagicMaxDamage", row_no); item_info->m_wUniPhyDef = GetDataWORD("UniPhyDef", row_no); #if !defined(_NA001605_EP2_ATTRIBUTES_RENEWAL_) item_info->m_wUniMagicDef = GetDataWORD("UniMagicDef", row_no); #endif #if SUN_CODE_BACKUP // 客户端:选择项目类型 item_info->m_wItemListType = GetDataWORD("ItemListType", row_no); #endif #ifdef _NA_20100307_BETAKEY_SYSTEM item_info->m_betakey = GetDataInt("BetaKeyCode", row_no); #endif //------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------ // 规则检查部分 // //------------------------------------------------------------------------------------------ // 非常重要的数据 // Rule: 重叠的项目没有有效期. switch (item_info->m_ChargeSubType) { #ifdef _NA_008440_20150818_ADD_CHARGE_SUB_IMMEDIATELY_USE case eCHARGE_SUB_IMMEDIATELY_USE: case eCHARGE_SUB_IMMEDIATELY_USE_AND_DELETE: #endif // _NA_008440_20150818_ADD_CHARGE_SUB_IMMEDIATELY_USE case eCHARGE_SUB_FIXED_AMOUNT: case eCHARGE_SUB_FIXED_AMOUNT_EX: case eCHARGE_SUB_FIXED_QUANTITY: case eCHARGE_SUB_COORDINATE: // (WAVERIX) 这也不能重叠. case eCHARGE_SUB_FIXED_AMOUNT_WAIT: case eCHARGE_SUB_FATE: case eCHARGE_SUB_COORDINATE_EX: case eCHARGE_SUB_RIDER_WITH_PART: case eCHARGE_SUB_RIDER_WITH_PART_NOTIMER: //虽无有效期,但因同类关系,请此处检查 case eCHARGE_SUB_FIXED_AMOUNT_EX2: //assert(item_info->m_byDupNum == 1); if (item_info->m_byDupNum != 1) { LOG_ITEM_VIOLATION_DUPLICATE(item_info->m_Code, item_info->m_byDupNum, "ChargeItem"); item_info->m_byDupNum = 1; } break; } switch (item_info->m_wType) { case eITEMTYPE_TWOHANDAXE: case eITEMTYPE_TWOHANDSWORD: case eITEMTYPE_ONEHANDSWORD: case eITEMTYPE_SPEAR: case eITEMTYPE_WHIP: case eITEMTYPE_DAGGER: case eITEMTYPE_ONEHANDCROSSBOW: case eITEMTYPE_ETHERWEAPON: case eITEMTYPE_SCIMITAR: case eITEMTYPE_STAFF: case eITEMTYPE_ORB: case eITEMTYPE_GUNTLET: // _NA_004965_20120613_NEW_CHARACTER_MYSTIC case eITEMTYPE_POLEARM: // _NA_004965_20120613_NEW_CHARACTER_MYSTIC case eITEMTYPE_HELLROID_1: //_NA_000000_20130812_NEW_CHARACTER_HELLROID case eITEMTYPE_ARCBLADE: //_NA_007514_20140828_NEW_CHARACTER_WITCHBLADE assert(item_info->m_byDupNum == 1); if (item_info->m_byDupNum != 1) { LOG_ITEM_VIOLATION_DUPLICATE(item_info->m_Code, item_info->m_byDupNum, "WeaponItem"); item_info->m_byDupNum = 1; } break; // 盔甲 case eITEMTYPE_ARMOR: case eITEMTYPE_PROTECTOR: case eITEMTYPE_HELMET: case eITEMTYPE_PANTS: case eITEMTYPE_BOOTS: case eITEMTYPE_GLOVE: case eITEMTYPE_BELT: case eITEMTYPE_SHIRTS: assert(item_info->m_byDupNum == 1); if (item_info->m_byDupNum != 1) { LOG_ITEM_VIOLATION_DUPLICATE(item_info->m_Code, item_info->m_byDupNum, "ArmorItem"); item_info->m_byDupNum = 1; } break; // 配饰 case eITEMTYPE_RING: case eITEMTYPE_NECKLACE: assert(item_info->m_byDupNum == 1); if (item_info->m_byDupNum != 1) { LOG_ITEM_VIOLATION_DUPLICATE(item_info->m_Code, item_info->m_byDupNum, "Accessory"); item_info->m_byDupNum = 1; } break; case eITEMTYPE_BERSERKER_SACCESSORY : case eITEMTYPE_DRAGON_SACCESSORY: case eITEMTYPE_VALKYRIE_SACCESSORY: case eITEMTYPE_SHADOW_SACCESSORY: case eITEMTYPE_ELEMENTALIST_SACCESSORY: case eITEMTYPE_MYSTIC_SPECIAL_ACCESSORY1: // _NA_004965_20120613_NEW_CHARACTER_MYSTIC case eITEMTYPE_HELLROID_SPECIAL_ACCESSORY1: //_NA_000000_20130812_NEW_CHARACTER_HELLROID case eITEMTYPE_WITCHBLADE_SPECIAL_ACCESSORY1: //_NA_007514_20140828_NEW_CHARACTER_WITCHBLADE case eITEMTYPE_ELEMENTALIST_KALVUS_ACCESSORY: //_NA_007827_20141117_ADD_ACCESSORY_TYPE case eITEMTYPE_ALLCLASS_CHAOSEYE: //_NA_007827_20141117_ADD_ACCESSORY_TYPE case eITEMTYPE_BERSERKER_KALVUS_ACCESSORY: //_NA_007827_20141117_ADD_ACCESSORY_TYPE case eITEMTYPE_DRAGON_KALVUS_ACCESSORY: //_NA_007827_20141117_ADD_ACCESSORY_TYPE case eITEMTYPE_VALKYRIE_SHADOW_KALVUS_ACCESSORY: //_NA_007827_20141117_ADD_ACCESSORY_TYPE case eITEMTYPE_MYSTIC_KALVUS_ACCESSORY: //_NA_007827_20141117_ADD_ACCESSORY_TYPE case eITEMTYPE_HELLROID_WITCHBLADE_KALVUS_ACCESSORY: //_NA_007827_20141117_ADD_ACCESSORY_TYPE assert(item_info->m_byDupNum == 1); if (item_info->m_byDupNum != 1) { LOG_ITEM_VIOLATION_DUPLICATE(item_info->m_Code, item_info->m_byDupNum, "SpecialAccessory"); item_info->m_byDupNum = 1; } break; }; //end 'switch' for modify duplicable item switch (item_info->m_wType) { case eITEMTYPE_TWOHANDAXE: case eITEMTYPE_TWOHANDSWORD: case eITEMTYPE_ONEHANDSWORD: case eITEMTYPE_SPEAR: case eITEMTYPE_WHIP: case eITEMTYPE_DAGGER: case eITEMTYPE_ONEHANDCROSSBOW: case eITEMTYPE_ETHERWEAPON: case eITEMTYPE_SCIMITAR: case eITEMTYPE_STAFF: case eITEMTYPE_ORB: case eITEMTYPE_GUNTLET: // _NA_004965_20120613_NEW_CHARACTER_MYSTIC case eITEMTYPE_POLEARM: // _NA_004965_20120613_NEW_CHARACTER_MYSTIC case eITEMTYPE_HELLROID_1: //_NA_000000_20130812_NEW_CHARACTER_HELLROID case eITEMTYPE_ARCBLADE: //_NA_007514_20140828_NEW_CHARACTER_WITCHBLADE assert(item_info->m_wEqPos == eEQUIPCONTAINER_WEAPON); if (item_info->m_wEqPos != eEQUIPCONTAINER_WEAPON) { SUNLOG(eCRITICAL_LOG, "物品代码|%u|EqPos:%u != value:%u", item_info->m_Code, item_info->m_wEqPos, eEQUIPCONTAINER_WEAPON); } break; // 规绢备 case eITEMTYPE_ARMOR: assert(item_info->m_wEqPos == eEQUIPCONTAINER_ARMOR); if (item_info->m_wEqPos != eEQUIPCONTAINER_ARMOR) { SUNLOG(eCRITICAL_LOG, "物品代码|%u|EqPos:%u != value:%u", item_info->m_Code, item_info->m_wEqPos, eEQUIPCONTAINER_ARMOR); } break; case eITEMTYPE_PROTECTOR: assert(item_info->m_wEqPos == eEQUIPCONTAINER_PROTECTOR); if (item_info->m_wEqPos != eEQUIPCONTAINER_PROTECTOR) { SUNLOG(eCRITICAL_LOG, "物品代码|%u|EqPos:%u != value:%u", item_info->m_Code, item_info->m_wEqPos, eEQUIPCONTAINER_PROTECTOR); } break; case eITEMTYPE_HELMET: assert(item_info->m_wEqPos == eEQUIPCONTAINER_HELMET); if (item_info->m_wEqPos != eEQUIPCONTAINER_HELMET) { SUNLOG(eCRITICAL_LOG, "物品代码|%u|EqPos:%u != value:%u", item_info->m_Code, item_info->m_wEqPos, eEQUIPCONTAINER_HELMET); } break; case eITEMTYPE_PANTS: assert(item_info->m_wEqPos == eEQUIPCONTAINER_PANTS); if (item_info->m_wEqPos != eEQUIPCONTAINER_PANTS) { SUNLOG(eCRITICAL_LOG, "物品代码|%u|EqPos:%u != value:%u", item_info->m_Code, item_info->m_wEqPos, eEQUIPCONTAINER_PANTS); } break; case eITEMTYPE_BOOTS: assert(item_info->m_wEqPos == eEQUIPCONTAINER_BOOTS); if (item_info->m_wEqPos != eEQUIPCONTAINER_BOOTS) { SUNLOG(eCRITICAL_LOG, "物品代码|%u|EqPos:%u != value:%u", item_info->m_Code, item_info->m_wEqPos, eEQUIPCONTAINER_BOOTS); } break; case eITEMTYPE_GLOVE: assert(item_info->m_wEqPos == eEQUIPCONTAINER_GLOVE); if (item_info->m_wEqPos != eEQUIPCONTAINER_GLOVE) { SUNLOG(eCRITICAL_LOG, "物品代码|%u|EqPos:%u != value:%u", item_info->m_Code, item_info->m_wEqPos, eEQUIPCONTAINER_GLOVE); } break; case eITEMTYPE_BELT: assert(item_info->m_wEqPos == eEQUIPCONTAINER_BELT); if (item_info->m_wEqPos != eEQUIPCONTAINER_BELT) { SUNLOG(eCRITICAL_LOG, "物品代码|%u|EqPos:%u != value:%u", item_info->m_Code, item_info->m_wEqPos, eEQUIPCONTAINER_BELT); } break; case eITEMTYPE_SHIRTS: assert(item_info->m_wEqPos == eEQUIPCONTAINER_SHIRTS); if (item_info->m_wEqPos != eEQUIPCONTAINER_SHIRTS) { SUNLOG(eCRITICAL_LOG, "物品代码|%u|EqPos:%u != value:%u", item_info->m_Code, item_info->m_wEqPos, eEQUIPCONTAINER_SHIRTS); } break; // 配饰 case eITEMTYPE_RING: if (item_info->m_wEqPos != eEQUIPCONTAINER_RING1 && item_info->m_wEqPos != eEQUIPCONTAINER_CHARGE1 && item_info->m_wEqPos != eEQUIPCONTAINER_CHARGE2 && item_info->m_wEqPos != eEQUIPCONTAINER_CHARGE3 && item_info->m_wEqPos != eEQUIPCONTAINER_CHARGE4 && item_info->m_wEqPos != eEQUIPCONTAINER_CHARGE5 && item_info->m_wEqPos != eEQUIPCONTAINER_PC_ROOM1 && item_info->m_wEqPos != eEQUIPCONTAINER_PC_ROOM2 && item_info->m_wEqPos != eEQUIPCONTAINER_PC_ROOM3) { SUNLOG(eCRITICAL_LOG, "物品代码|%u|EqPos:%u != value:%u", item_info->m_Code, item_info->m_wEqPos, eEQUIPCONTAINER_RING1); } break; case eITEMTYPE_NECKLACE: assert(item_info->m_wEqPos == eEQUIPCONTAINER_NECKLACE); if (item_info->m_wEqPos != eEQUIPCONTAINER_NECKLACE) { SUNLOG(eCRITICAL_LOG, "物品代码|%u|EqPos:%u != value:%u\n", item_info->m_Code, item_info->m_wEqPos, eEQUIPCONTAINER_NECKLACE); } break; case eITEMTYPE_BERSERKER_SACCESSORY: case eITEMTYPE_DRAGON_SACCESSORY: case eITEMTYPE_VALKYRIE_SACCESSORY: case eITEMTYPE_SHADOW_SACCESSORY: case eITEMTYPE_ELEMENTALIST_SACCESSORY: case eITEMTYPE_MYSTIC_SPECIAL_ACCESSORY1: // _NA_004965_20120613_NEW_CHARACTER_MYSTIC case eITEMTYPE_HELLROID_SPECIAL_ACCESSORY1: //_NA_000000_20130812_NEW_CHARACTER_HELLROID case eITEMTYPE_WITCHBLADE_SPECIAL_ACCESSORY1: //_NA_007514_20140828_NEW_CHARACTER_WITCHBLADE case eITEMTYPE_ALLCLASS_CHAOSEYE: //_NA_007827_20141117_ADD_ACCESSORY_TYPE case eITEMTYPE_ELEMENTALIST_KALVUS_ACCESSORY: //_NA_007827_20141117_ADD_ACCESSORY_TYPE case eITEMTYPE_BERSERKER_KALVUS_ACCESSORY: //_NA_007827_20141117_ADD_ACCESSORY_TYPE case eITEMTYPE_DRAGON_KALVUS_ACCESSORY: //_NA_007827_20141117_ADD_ACCESSORY_TYPE case eITEMTYPE_VALKYRIE_SHADOW_KALVUS_ACCESSORY: //_NA_007827_20141117_ADD_ACCESSORY_TYPE case eITEMTYPE_MYSTIC_KALVUS_ACCESSORY: //_NA_007827_20141117_ADD_ACCESSORY_TYPE case eITEMTYPE_HELLROID_WITCHBLADE_KALVUS_ACCESSORY: //_NA_007827_20141117_ADD_ACCESSORY_TYPE ASSERT(item_info->m_wEqPos == eEQUIPCONTAINER_SACCESSORY1); break; case eITEMTYPE_RIDER_PARTS: { const eRIDER_CLASS& rider = item_info->m_RidingClass; FASSERT(rider.value == rider.Charger || rider.value == rider.Leopard || rider.value == rider.OrcPig || rider.value == rider.Kalvus ); FASSERT(item_info->m_wEqPos == eRIDER_PARTS_POS::HeadPart || item_info->m_wEqPos == eRIDER_PARTS_POS::BodyPart || item_info->m_wEqPos == eRIDER_PARTS_POS::LegsPart); } break; } // 分配物品 item_info->m_bApplyItemDistribution = (GetDataBYTE("UseItemDistribution", row_no) != 0); #ifdef _NA_003033_20110831_DICECAST_ITEM_ROUTING item_info->dice_cast_type = GetDataBYTE("DiceCast", row_no); #endif //_NA_003033_20110831_DICECAST_ITEM_ROUTING #ifdef _NA_003740_20210624_ADDBOXKEY item_info->m_BoxKeyIndex=GetDataDWORD("BoxKey", row_no); //增加箱子钥匙 by:十里坡剑神 2021-07-23 #endif //_NA_003740_20210624_ADDBOXKEY //------------------------------------------------------------------------------------------ // CHANGES: f110414.1L, 内部配置。 计算“SubTypeDetailed”值 item_info->_UpdateSubTypeDetailedValue(); //------------------------------------------------------------------------------------------ // Event Handling // switch (item_info->m_wType) { case eITEMTYPE_RENDER_EFFECT_ITEM: render_effect_item_list_.push_back((SLOTCODE)item_info->m_Code); break; } #ifdef _DEBUG static BASE_ITEMINFO* pPreInfo = 0; pPreInfo = item_info;//脚本运行时要知道上一个物品信息!! #endif // 验证有效性. CheckValidity(item_info); previous_item_code_for_debugging = item_code; // CHANGES: f110802.3L item_table_.client_checksum_array_[item_code - 1] = util::StreamHashKey::GetMemoryHashKey(item_info, sizeof(*item_info)); } // (CHANGES) (f100505.1L) 添加支持 O(1) 时间复杂度的物品访问设施 if (!FlowControl::FCAssert(_BuildReference(max_rows))) { return false; } loaded_ = true; return true; } //================================================================================================== void ItemInfoParser::CheckValidity(BASE_ITEMINFO* item_info) { const SLOTCODE item_code = item_info->m_Code; const eCHARGE_SUB_TYPE charge_sub_type = eCHARGE_SUB_TYPE(item_info->m_ChargeSubType); //Enchant if (SCItemSlot::CanUseMixture(item_info, MIXTURE_ENCHANT)) { if (item_info->IsWeapon() == 0 && item_info->IsArmor() == 0 && item_info->m_wType != eITEMTYPE_WINGS) // CHANGES: f111007.1L, added rule { // + rider parts 不是明确的附魔功能. LOG_ITEM_VIOLATION_FUCTION(item_code, "不是武器,不是盔甲,不是翅膀", "Enchant"); } } //RankUp if (SCItemSlot::CanUseMixture(item_info, MIXTURE_RANKUP)) { if (item_info->IsChargeItem()) { if (charge_sub_type != eCHARGE_SUB_FIXED_AMOUNT_WAIT) { LOG_ITEM_VIOLATION_FUCTION(item_code, "Charge item", "Rankup"); } } if (item_info->IsElite()) { LOG_ITEM_VIOLATION_FUCTION(item_code, "Elite item", "Rankup"); } if (item_info->IsUnique()) { LOG_ITEM_VIOLATION_FUCTION(item_code, "Unique item", "Rankup"); } if (item_info->IsWeapon() == 0 && item_info->IsArmor() == 0 && item_info->IsAccessory() == 0) { LOG_ITEM_VIOLATION_FUCTION(item_code, \ "不是武器,不是盔甲,不是翅膀", "Rankup"); } if (item_info->m_wSubType == eITEMSUBTYPE_FATE) { LOG_ITEM_VIOLATION_FUCTION(item_code, "Lucky item", "Rankup"); FASSERT(0); } } //Crystalize if (SCItemSlot::CanUseMixture(item_info, MIXTURE_CRYSTALIZE)) { if (item_info->IsChargeItem() && (item_info->m_wSubType != eITEMSUBTYPE_FATE)) { if (item_info->m_ChargeSubType != eCHARGE_SUB_FIXED_AMOUNT_WAIT) { LOG_ITEM_VIOLATION_FUCTION(item_code, "Charge item", "Crystalize"); } } // [10/26/2009 namka199]通过结晶化扩张作业,可以决定精英道具。 //不可使用特殊道具 if (item_info->IsUnique()) { LOG_ITEM_VIOLATION_FUCTION(item_code, "Unique item", "Crystalize"); } if (item_info->IsWeapon() == 0 && item_info->IsArmor() == 0 && item_info->IsAccessory() == 0) { LOG_ITEM_VIOLATION_FUCTION(item_code, \ "不是武器,不是盔甲,不是翅膀", "Crystalize"); } } //Compose if (SCItemSlot::CanUseMixture(item_info, MIXTURE_COMPOSE)) { // noting to do }; //ExtraStone if (SCItemSlot::CanUseMixture(item_info, MIXTURE_EXTRASTONE)) { // 武器,防具,饰品,特殊饰品 if (item_info->IsWeapon() == 0 && item_info->IsArmor() == 0 && item_info->IsAccessory() == 0 && item_info->IsSpecialAccessory() == 0) { LOG_ITEM_VIOLATION_FUCTION(item_code, \ "不是武器,不是盔甲,不是配件,不是特殊配件", "Extra Stone"); } } // 检查物品系列值. /* 根据SubType的不同,LV的价格也多种多样,这样单纯的验证是没有意义的. - arycoat 2012.07.20 if (item_info->GetSubTypeDetail() == ItemSubTypeDetail::kInvalid) { switch(item_info->m_wSubType) { case eITEMSUBTYPE_ELITE_SSQ: case eITEMSUBTYPE_ELITE: case eITEMSUBTYPE_UNIQUE: case eITEMSUBTYPE_FATE: case eITEMSUBTYPE_RARE: case eITEMSUBTYPE_GENERAL: { SUNLOG(eCRITICAL_LOG, _T( "|物品系列值与等级不一致。” "|ItemCode = %u, SubType = %d, ItemLevel = %u|"), item_code, item_info->m_wSubType, item_info->m_LV); } break; default: break; } }*/ #if !defined(_NA001605_EP2_ATTRIBUTES_RENEWAL_) // 武器攻击类型确认 if (item_info->IsWeapon()) { if (item_info->m_byMeleeType == 0 || item_info->m_byMeleeType >= eMELEE_TYPE_MAX) { SUNLOG(eCRITICAL_LOG, "物品代码|%u|字段[m_byMeleeType](%d)值无效,取值范围[0~%d]!", item_code, item_info->m_byMeleeType,eMELEE_TYPE_MAX-1); item_info->m_byMeleeType = 1; } } // 检查装甲类型 if (item_info->IsArmor()) { if (item_info->m_byArmorType == 0 || item_info->m_byArmorType >= eARMOR_TYPE_MAX) { SUNLOG(eCRITICAL_LOG, "物品代码|%u|字段[m_byArmorType](%d)值无效,取值范围[0~%d]!", item_code, item_info->m_byArmorType,eARMOR_TYPE_MAX-1); item_info->m_byArmorType = 1; } } #endif // CHANGES: f110329.5L, 添加规则,强制排他选项 if (item_info->IsExistInvenOptions() && item_info->IsExistEquipOptions()) { SUNLOG(eCRITICAL_LOG, _T("物品代码|%u|默认选项应用程序只有一件事. ") _T("ex: 是否在装备上套用选择权? 或在 inven 上应用选项?"), item_code); FASSERT("强制停止"); } // 检查比例类型选项 for (int op = 0; op < _countof(item_info->m_wOptionIndex); ++op) { if (!CheckOptionValidity(item_info->m_wOptionIndex[op], item_info->m_byOptionType[op], item_info->m_iOptionValue[op])) { SUNLOG(eCRITICAL_LOG, "|物品代码=%u|下列字段无效 Option|OptionIndex=%d|OptionType=%d|OptionValue=%d|", item_code, item_info->m_wOptionIndex[op], item_info->m_byOptionType[op], item_info->m_iOptionValue[op]); } } if (item_info->m_wType == eITEMTYPE_PET) { #ifdef _NA_007854_20141127_MODIFY_PET_CHARGE_SUBTYPE if (charge_sub_type != eCHARGE_SUB_GENERAL && charge_sub_type != eCHARGE_SUB_FIXED_QUANTITY && charge_sub_type != eCHARGE_SUB_FIXED_AMOUNT) { SUNLOG(eCRITICAL_LOG, "物品代码|%u|宠物子类型无效(%u)", item_code, charge_sub_type); FASSERT(0); } #else if (charge_sub_type != eCHARGE_SUB_GENERAL && charge_sub_type != eCHARGE_SUB_FIXED_QUANTITY) { SUNLOG(eCRITICAL_LOG, "ItemCode|%u|Invalid Pet SubType(%u)", item_code, charge_sub_type); FASSERT(0); } #endif //_NA_000000_20141127_MODIFY_PET_CHARGE_SUBTYPE } if (item_info->m_wType == eITEMTYPE_RIDER || item_info->m_wType == eITEMTYPE_RIDER_PARTS) { if (charge_sub_type != eCHARGE_SUB_RIDER_WITH_PART && charge_sub_type != eCHARGE_SUB_RIDER_WITH_PART_NOTIMER) { SUNLOG(eCRITICAL_LOG, "物品代码|%u|字段[ChargeSubType](%u)值无效", item_code, charge_sub_type); FASSERT(0); //时间设置问题是关键。必须解决. } } if (item_info->m_bPossessionItem != false) { if (item_info->m_byMaterialType == 0) { SUNLOG(eCRITICAL_LOG, "物品代码|%u|字段[MaterialType](%u)值无效 \n", item_code, item_info->m_byMaterialType); } if (item_info->m_byPopup == 0) { SUNLOG(eCRITICAL_LOG, "物品代码|%u|字段[m_byPopup](%u)值无效 \n", item_code, item_info->m_byPopup); } } if (SCItemSlot::CanTradeSell(item_info, eITEM_TRADESELL_TRADE) == false && SCItemSlot::CanTradeSell(item_info, eITEM_TRADESELL_DROP) == true) { //可交易&&可掉落=>OK //不可交易&&不可掉落=>OK //可交易&&不可掉落=>OK(为了防止将可交易的物品掉落在地上而设置) //不可交易&&可掉落=>Not OK SUNLOG(eCRITICAL_LOG, "物品代码|%u|字段[TradeSellType](%u)值无效\n", item_code, item_info->trade_sell_type); } #ifdef _NA002217_100728_EP2_PERK_SYSTEM_ if (item_info->m_wType == eITEMTYPE_PERK_CASH_ITEM) { // f100915.3L, 增加一个关于现金奖励注册项目的规则. const bool is_desirable_charge_sub_type = \ item_info->m_ChargeSubType == eCHARGE_SUB_FIXED_AMOUNT_EX; __UNUSED(is_desirable_charge_sub_type); assert(is_desirable_charge_sub_type); if (item_info->m_byDupNum != 1 || (item_info->IsMaterialWaste() == false)) { SUNLOG(eCRITICAL_LOG, _T("|物品代码=%d|信息=违反特权物品规则,强制更改|") _T("|DupNum=1<-(%d), MaterialType=2<-(%d)|ChargeSubType=2<-(%d)|"), item_code, item_info->m_byDupNum, item_info->m_byMaterialType, item_info->m_ChargeSubType); // item_info->m_ChargeSubType = eCHARGE_SUB_FIXED_AMOUNT_EX; item_info->m_byDupNum = 1; item_info->m_byMaterialType = eITEM_MATERIAL_TYPE_CAN_USE; } }; #endif // _NA_000251_20100727_SOCKET_SYSTEM // 检查ZARD物品. if (item_info->m_wType == eITEMTYPE_SOCKET_ZARD || item_info->m_wType == eITEMTYPE_SOCKET_ZARD_RINGS) // xiaomi add ItemInfoParser::CheckValidity(BASE_ITEMINFO* item_info) { if (item_info->zard_grade >= kZardGradeMax) { SUNLOG(eCRITICAL_LOG, _T("|%s |ZARD物品等级范围不正确,初始化为0。| 物品代码=%u,等级=%d |"), __FUNCTION__, item_info->m_Code, item_info->zard_grade); item_info->zard_grade = 0; } if (item_info->zard_item_option_kind >= _countof(g_ITEM_OPTION)) { SUNLOG(eCRITICAL_LOG, _T("|%s |ZARD物品选项范围不正确,初始化为0。| 物品代码=%u,选项=%d |"), __FUNCTION__, item_info->m_Code, item_info->zard_item_option_kind); item_info->zard_item_option_kind = 0; } } // 检验ZARD物品合成添加剂. if (item_info->m_wType == eITEMTYPE_SOCKET_COMPOSE_ADDITIVE) { enum { kMaxZardSuccessPer = 1000 }; if (item_info->zard_success_per > kMaxZardSuccessPer) { SUNLOG(eCRITICAL_LOG, _T("|%s |ZARD物品合成追加成功率范围不正确,初始化为0。| 物品代码=%u,追加成功率=%d |"), __FUNCTION__, item_info->m_Code, item_info->zard_success_per); item_info->zard_success_per = 0; } if (item_info->m_byDupNum > 1 && (item_info->IsMaterialWaste() == false)) { SUNLOG(eCRITICAL_LOG, _T("|%s |ZARD物品合成添加剂可重叠,但不是消耗性,初始化为消耗性| 物品代码=%u,重叠数量=%u |"), __FUNCTION__, item_info->m_Code, item_info->m_byDupNum); item_info->m_byMaterialType = eITEM_MATERIAL_TYPE_CAN_USE; } } // 检查插槽计数重置项. if (item_info->m_wType == eITEMTYPE_STAT_CHANGE) { if (item_info->m_ExchangedItem < 0 || item_info->m_ExchangedItem > SOCKET_MAX) { SUNLOG(eCRITICAL_LOG, _T("|%s |插槽数量设置不正确,初始化为0。| 物品代码=%u,插口数量=%d |"), __FUNCTION__, item_info->m_Code, item_info->m_ExchangedItem); item_info->m_ExchangedItem = 0; } enum { kMaxSocketRatioType = 255 }; const WORD fixed_ratio_type = item_info->m_wSubType; if (fixed_ratio_type < 0 || fixed_ratio_type >= kMaxSocketRatioType) { SUNLOG(eCRITICAL_LOG, _T("|%s |插槽生成概率种类不正确,初始化为0。| 物品代码=%u,概率种类=%u |"), __FUNCTION__, item_info->m_Code, item_info->m_wSubType); item_info->m_wSubType = 0; } if (item_info->m_byDupNum > 1 && (item_info->IsMaterialWaste() == false)) { SUNLOG(eCRITICAL_LOG, _T("|%s |插槽个数重置项目可叠加,但不是消耗性,初始化为消耗性| 物品代码=%u,叠加个数=%u |"), __FUNCTION__, item_info->m_Code, item_info->m_byDupNum); item_info->m_byMaterialType = eITEM_MATERIAL_TYPE_CAN_USE; } } //#ifdef _NA_004035_20120227_COSTUME_ITEM // // 服装道具属性为消耗性时.. // if (item_info->m_wType == eITEMTYPE_COSTUME) // { // if (item_info->IsMaterialWaste()) // { // SUNLOG(eCRITICAL_LOG, // _T("|%s |%d |初始化服装道具设置为消耗性,无法删除。| 物品代码=%u,MaterialType=%u |"), // __FUNCTION__, // __LINE__, // item_info->m_Code, // item_info->m_byMaterialType); // //setting // item_info->m_byMaterialType = eITEM_MATERIAL_TYPE_CAN_USE_NOT_DELETE; // } // } //#endif // _NA_004035_20120227_COSTUME_ITEM // last order. FlowControl::FCAssert(\ nsSlot::ItemRuleInfo::PrefetchRuleInfo(&item_info->item_rule_info, item_info)); } //================================================================================================== // CHANGES: f110408.3L, 添加了支持事件等外部控制的接口. _SERVER contents void ItemInfoParser::ChangeToTimeExpirationItem(CODETYPE item_code) { // (CHANGES) (f100505.1L) 更改搜索算法+添加常量版本 if (item_code == 0 || item_code > USHRT_MAX) { assert(!"索引超出范围"); return; } --item_code; BASE_ITEMINFO* item_info = item_table_.array_[item_code]; if (item_info == NULL) { assert(!"找不到物品"); return; }; item_info->time_expiration_item = true; } //================================================================================================== BOOL ItemInfoParser::LoadScript(eSCRIPT_CODE script_code, BOOL reloaded) { switch (script_code) { case SCRIPT_ACCESSORYITEMINFO: case SCRIPT_ARMORITEMINFO: case SCRIPT_WASTEITEMINFO: case SCRIPT_WEAPONITEMINFO: case SCRIPT_CHARGEITEMINFO: return _Load(reloaded); } return false; } #if defined (_NA_0_20091208_VENDOR_ITEM_SEARCH) || (defined(_DH_GM_ITEM_WINDOW) && !defined(_SERVER)) void ItemInfoParser::PushItemName(TCHAR* stName, DWORD ItemCode, TCHAR* description_string /*=NULL*/) { _ITEM_NAME_INFO temp; temp.m_stName = stName; temp.m_dwItemCode = ItemCode; temp.description_string = description_string; item_name_code_table_.push_back(temp); } DWORD ItemInfoParser::GetItemNameforCode(char *stName) { ITEM_NAME_INFO::iterator itr; for (itr = item_name_code_table_.begin(); itr != item_name_code_table_.end(); ++itr) { //sInfo = itr; //if (itr->m_stName.IndexOf(nStName, 0) != -1) if (itr->m_stName.find(stName, 0) != std::string::npos) { strncpy(stName, itr->m_stName.c_str(), MAX_VENDOR_SEARCH_LENGTH); return itr->m_dwItemCode; } } return 0; } ITEM_NAME_INFO::iterator ItemInfoParser::GetItemNamesBegin() { return item_name_code_table_.begin(); } ITEM_NAME_INFO::iterator ItemInfoParser::GetItemNamesEnd() { return item_name_code_table_.end(); } DWORD ItemInfoParser::GetItemAllCount() { return item_name_code_table_.size(); } #endif//_NA_0_20091208_VENDOR_ITEM_SEARCH // CHANGES: f110802.3L, _NA000000_SPEED_HACK_PREVENTION_SUPPORT bool ItemInfoParser::CheckChecksum(CODETYPE item_code) const { if (item_code == 0 || item_code > USHRT_MAX) { return NULL; } --item_code; const BASE_ITEMINFO* item_info = item_table_.array_[item_code]; if (item_info == NULL) { return true; }; ulong checksum = item_table_.client_checksum_array_[item_code]; ulong runtime_checksum = util::StreamHashKey::GetMemoryHashKey(item_info, sizeof(*item_info)); if (checksum != runtime_checksum) { return false; } return true; }