#include "stdafx.h" #include "./ItemAttrCalculator.h" #if defined(_NA_002289_20110322_EQUIPMENTS_CALCULATOR_CHANGES_FOR_IMPROVEMENT) __EMPTY_FILE_TAG(); #else //if !defined(_NA_002289_20110322_EQUIPMENTS_CALCULATOR_CHANGES_FOR_IMPROVEMENT) #include #include #include #include #include #include // #include // #include #include #include #include // //================================================================================================== // @history // - ~~~ // - 09/10/24|waverix|code arrangement, remove warnings // (NOTE) for set item operation, real equip position marking, for safely boundary static bool sRealEquipSlotSafeArray[256]; //================================================================================================== // ItemAttrCalculator::ItemAttrCalculator(PlayerAttributes& attributes, SCSlotContainer& equip_container, bool auto_update) : attributes_((Attributes&)attributes), slot_container_(equip_container), auto_update_(auto_update) , equip_container_calculation_(true) , set_item_count_calculation_type_(false) , real_equip_slots_((REAL_EQUIPSLOTS&)sRealEquipSlotSafeArray) // _NA_000251_20100727_SOCKET_SYSTEM , socket_option_calculator_(attributes.GetSocketOptionAttributes()) {} ItemAttrCalculator::~ItemAttrCalculator() { } //================================================================================================== // STEP 1 inline bool ItemAttrCalculator::_CheckCalcAttr(const SCItemSlot& IN item_slot, const BASE_ITEMINFO* IN item_info) { __UNUSED(item_info); //if (item_slot.IsBlocked()) return; #ifndef __NA_001062_20080623_STRENGTH_PENALTY // ³»±¸µµ°¡ ÀÖ´ÂÁö üũ if (item_slot.WithDura()) { if (!item_slot.GetDura()) { return false; } } #endif // ±â°£ÀÌ ¸¸·áµÇ¸é ¼öÄ¡¸¦ Àû¿ë¾ÈÇÑ´Ù. if (item_slot.IsExpiredTime()) { return false; } if (item_slot.IsExpiredWaitTime()) { return false; } return true; } //================================================================================================== void ItemAttrCalculator::_ForeachAttrByRank(const SCItemSlot& IN item_slot, bool is_add) { const eRANK rank_upperbound = static_cast(item_slot.GetRank() + 1); for (eRANK rank = RANK_D; rank < rank_upperbound; rank = static_cast(rank + 1)) { const sRANK_OPTION* rank_option = item_slot.GetRankAttrDesc(rank); if (rank_option == NULL) { continue; }; eATTR_TYPE rank_attr = item_slot.GetRankAttr(rank); BYTE value_type = static_cast(rank_option->m_NumericType); int value = item_slot.GetRankAttrValue(rank); if (is_add) { PlusOptionAttribute(rank_attr, value_type, value); } else { MinusOptionAttribute(rank_attr, value_type, value); } } } void ItemAttrCalculator::_ForeachAttrBySocket(const SCItemSlot& IN item_slot, bool is_add) { // _NA_000251_20100727_SOCKET_SYSTEM socket_option_calculator_.Calculate(item_slot, is_add, *this); } #if SUN_CODE_BACKUP inline void ItemAttrCalculator::_ForeachAddAttrByRank(const SCItemSlot& IN item_slot) { //·©Å© //BYTE Index = 0, Value = 0; const BYTE upper = item_slot.GetRank() + 1; for (BYTE rank = (BYTE)RANK_D; rank < upper; ++rank) { if (item_slot.GetRankAttrDesc((eRANK)rank)) { PlusOptionAttribute(item_slot.GetRankAttr((eRANK)rank), (BYTE)item_slot.GetRankAttrDesc((eRANK)rank)->m_NumericType, item_slot.GetRankAttrValue((eRANK)rank)); } } } inline void ItemAttrCalculator::_ForeachAddAttrBySocket(const SCItemSlot& IN item_slot) { // ¼ÒÄÏ ¿É¼Ç const int upper = item_slot.GetSocketNum(); for (int sock = (int)SOCKET_1; sock < upper; ++sock) { if (item_slot.GetSocketAttrDesc((eSOCKET)sock)) { PlusOptionAttribute(item_slot.GetSocketAttr((eSOCKET)sock), item_slot.GetSocketAttrDesc((eSOCKET)sock)->m_NumericType, item_slot.GetSocketAttrValue((eSOCKET)sock)); } } }; inline void ItemAttrCalculator::_ForeachSubAttrByRank(const SCItemSlot& IN item_slot) { //·©Å© //BYTE Index = 0, Value = 0; const BYTE upper = item_slot.GetRank() + 1; for (BYTE rank = (BYTE)RANK_D; rank < upper; ++rank) { if (item_slot.GetRankAttrDesc((eRANK)rank)) { MinusOptionAttribute(item_slot.GetRankAttr((eRANK)rank), (BYTE)item_slot.GetRankAttrDesc((eRANK)rank)->m_NumericType, item_slot.GetRankAttrValue((eRANK)rank)); } } } inline void ItemAttrCalculator::_ForeachSubAttrBySocket(const SCItemSlot& IN item_slot) { // ¼ÒÄÏ ¿É¼Ç const int upper = item_slot.GetSocketNum(); for (int sock = (int)SOCKET_1; sock < upper; ++sock) { if (item_slot.GetSocketAttrDesc((eSOCKET)sock)) { MinusOptionAttribute(item_slot.GetSocketAttr((eSOCKET)sock), item_slot.GetSocketAttrDesc((eSOCKET)sock)->m_NumericType, item_slot.GetSocketAttrValue((eSOCKET)sock)); } } } #endif //SUN_CODE_BACKUP //================================================================================================== // STEP 2 bool ItemAttrCalculator::_CalcGenericAttr1st(const SCItemSlot& IN item_slot, const BASE_ITEMINFO* IN item_info, bool add_op) { __UNUSED(item_slot); // (f100721.1L) static const Attributes::Operation attr_item_array[] = { eATTR_PHYSICAL_ATTACK_SUCCESS_RATIO, #ifdef _NA001605_EP2_ATTRIBUTES_RENEWAL_ // CHANGES: f110209.6L, changes formula by planner request eATTR_PHYSICAL_ATTACK_BLOCK_BASE_ARMOR_RATIO, #else eATTR_PHYSICAL_ATTACK_BLOCK_RATIO, #endif eATTR_ATTACK_SPEED, eATTR_MOVE_SPEED }; // const int value_array[_countof(attr_item_array)] = { item_info->m_wPhyAttRate, item_info->m_wPhyAvoid, item_info->m_wPhyAttSpeed, item_info->m_wSpeed }; const Attributes::Operation::eOper oper_type = add_op ? attr_item_array->eOper_Add : attr_item_array->eOper_Sub; // return attributes_.GroupOperate(oper_type, eATTR_KIND_ITEM, attr_item_array, value_array, _countof(attr_item_array)); } #if SUN_CODE_BACKUP // STEP 2 inline bool ItemAttrCalculator::_CalcGenericAddAttr1st(const SCItemSlot& IN item_slot, const BASE_ITEMINFO* IN item_info) { __UNUSED(item_slot); // ¹°¸® °ø°Ý ¼º°ø·ü, ȸÇÇÀ² if (item_info->m_wPhyAttRate) attributes_[eATTR_PHYSICAL_ATTACK_SUCCESS_RATIO][eATTR_KIND_ITEM] += item_info->m_wPhyAttRate; if (item_info->m_wPhyAvoid) attributes_[eATTR_PHYSICAL_ATTACK_BLOCK_RATIO][eATTR_KIND_ITEM] += item_info->m_wPhyAvoid; // °ø°Ý, À̵¿ ¼Óµµ if (item_info->m_wPhyAttSpeed) attributes_[eATTR_ATTACK_SPEED][eATTR_KIND_ITEM] += item_info->m_wPhyAttSpeed; if (item_info->m_wSpeed) attributes_[eATTR_MOVE_SPEED][eATTR_KIND_ITEM] += item_info->m_wSpeed; return true; } // STEP 2 inline bool ItemAttrCalculator::_CalcGenericSubAttr1st(const SCItemSlot& IN item_slot, const BASE_ITEMINFO* IN item_info) { __UNUSED(item_slot); // ¹°¸® °ø°Ý ¼º°ø·ü, ȸÇÇÀ² if (item_info->m_wPhyAttRate) attributes_[eATTR_PHYSICAL_ATTACK_SUCCESS_RATIO][eATTR_KIND_ITEM] -= item_info->m_wPhyAttRate; if (item_info->m_wPhyAvoid) attributes_[eATTR_PHYSICAL_ATTACK_BLOCK_RATIO][eATTR_KIND_ITEM] -= item_info->m_wPhyAvoid; // °ø°Ý, À̵¿ ¼Óµµ if (item_info->m_wPhyAttSpeed) attributes_[eATTR_ATTACK_SPEED][eATTR_KIND_ITEM] -= item_info->m_wPhyAttSpeed; if (item_info->m_wSpeed) attributes_[eATTR_MOVE_SPEED][eATTR_KIND_ITEM] -= item_info->m_wSpeed; return true; } #endif //SUN_CODE_BACKUP //================================================================================================== // NOTE: f110111.2L, magical defense values are used to increase it of all elements // in the Episode II. struct sInterDamageOp { enum { LAST_MIN_DAMAGE_PHY = 0, LAST_MAX_DAMAGE_PHY , LAST_MIN_DAMAGE_MAG , LAST_MAX_DAMAGE_MAG , MAX_DAMAGES , }; sInterDamageOp() { ZeroMemory(this, sizeof(*this)); } __forceinline void SetWeaponValue(DWORD lastMinPhy, DWORD lastMaxPhy, DWORD lastMinMag, DWORD lastMaxMag) { LastPhyMinDamage = lastMinPhy; LastPhyMaxDamage = lastMaxPhy; #if !defined(_NA001605_EP2_ATTRIBUTES_RENEWAL_) LastMagicMinDamage = lastMinMag; LastMagicMaxDamage = lastMaxMag; #endif } __forceinline void SetArmorValue(DWORD lastPhyDef, DWORD lastMagDef, WORD itemPhyDef, WORD itemMagDef) { LastPhyDef = lastPhyDef; ItemPhyDef = itemPhyDef; #if !defined(_NA001605_EP2_ATTRIBUTES_RENEWAL_) LastMagicDef = lastMagDef; ItemMagicDef = itemMagDef; #endif } __forceinline void AddWeaponValue(DWORD value) { LastPhyMinDamage += value; LastPhyMaxDamage += value; #if !defined(_NA001605_EP2_ATTRIBUTES_RENEWAL_) LastMagicMinDamage += value; LastMagicMaxDamage += value; #endif } __forceinline void AddWeaponValueByLimited(float ratio) { if (ratio >= 0) { LastPhyMinDamage += (int)((ratio / 100.0f) * (float)LastPhyMinDamage + 0.5f); LastPhyMaxDamage += (int)((ratio / 100.0f) * (float)LastPhyMaxDamage + 0.5f); #if !defined(_NA001605_EP2_ATTRIBUTES_RENEWAL_) LastMagicMinDamage += (int)((ratio / 100.0f) * (float)LastMagicMinDamage + 0.5f); LastMagicMaxDamage += (int)((ratio / 100.0f) * (float)LastMagicMaxDamage + 0.5f); #endif } else { LastPhyMinDamage += (int)((ratio / 100.0f) * (float)LastPhyMinDamage - 0.5f); LastPhyMaxDamage += (int)((ratio / 100.0f) * (float)LastPhyMaxDamage - 0.5f); #if !defined(_NA001605_EP2_ATTRIBUTES_RENEWAL_) LastMagicMinDamage += (int)((ratio / 100.0f) * (float)LastMagicMinDamage - 0.5f); LastMagicMaxDamage += (int)((ratio / 100.0f) * (float)LastMagicMaxDamage - 0.5f); #endif } } __forceinline void AddArmorValueByLimited(float ratio) { if (ratio >= 0) { ItemPhyDef += (WORD)(int)((ratio / 100.0f) * (float)ItemPhyDef + 0.5f); #ifdef _NA001605_EP2_ATTRIBUTES_RENEWAL_ #else ItemMagicDef += (WORD)(int)((ratio / 100.0f) * (float)ItemMagicDef + 0.5f); #endif } else { ItemPhyDef += (WORD)(int)((ratio / 100.0f) * (float)ItemPhyDef - 0.5f); #ifdef _NA001605_EP2_ATTRIBUTES_RENEWAL_ #else ItemMagicDef += (WORD)(int)((ratio / 100.0f) * (float)ItemMagicDef - 0.5f); #endif } } #ifdef __NA_001062_20080623_STRENGTH_PENALTY __forceinline void AddWeaponValueByStrength(float ratio) { if (ratio >= 0) { LastPhyMinDamage = (WORD)((LastPhyMinDamage * ratio) + 0.5f); LastPhyMaxDamage = (WORD)((LastPhyMaxDamage * ratio) + 0.5f); #if !defined(_NA001605_EP2_ATTRIBUTES_RENEWAL_) LastMagicMinDamage = (WORD)((LastMagicMinDamage * ratio) + 0.5f); LastMagicMaxDamage = (WORD)((LastMagicMaxDamage * ratio) + 0.5f); #endif } else { LastPhyMinDamage = (WORD)((LastPhyMinDamage * ratio) - 0.5f); LastPhyMaxDamage = (WORD)((LastPhyMaxDamage * ratio) - 0.5f); #if !defined(_NA001605_EP2_ATTRIBUTES_RENEWAL_) LastMagicMinDamage = (WORD)((LastMagicMinDamage * ratio) - 0.5f); LastMagicMaxDamage = (WORD)((LastMagicMaxDamage * ratio) - 0.5f); #endif } } __forceinline void AddArmorValueByStrength(float ratio) { if (ratio >= 0) { LastPhyDef = (WORD)((LastPhyDef * ratio) + 0.5f); #ifdef _NA001605_EP2_ATTRIBUTES_RENEWAL_ #else LastMagicDef = (WORD)((LastMagicDef * ratio) + 0.5f); #endif } else { LastPhyDef = (WORD)((LastPhyDef * ratio) - 0.5f); #ifdef _NA001605_EP2_ATTRIBUTES_RENEWAL_ #else LastMagicDef = (WORD)((LastMagicDef * ratio) - 0.5f); #endif } } #endif //__NA_001062_20080623_STRENGTH_PENALTY __forceinline void AddWeaponValueByFate(float ratio) { if (ratio >= 0) { LastPhyMinDamage = (WORD)(LastPhyMinDamage * (ratio / 100.0f) + 0.5f); LastPhyMaxDamage = (WORD)(LastPhyMaxDamage * (ratio / 100.0f) + 0.5f); #if !defined(_NA001605_EP2_ATTRIBUTES_RENEWAL_) LastMagicMinDamage = (WORD)(LastMagicMinDamage * (ratio / 100.0f) + 0.5f); LastMagicMaxDamage = (WORD)(LastMagicMaxDamage * (ratio / 100.0f) + 0.5f); #endif } else { LastPhyMinDamage = (WORD)(LastPhyMinDamage * (ratio / 100.0f) - 0.5f); LastPhyMaxDamage = (WORD)(LastPhyMaxDamage * (ratio / 100.0f) - 0.5f); #if !defined(_NA001605_EP2_ATTRIBUTES_RENEWAL_) LastMagicMinDamage = (WORD)(LastMagicMinDamage * (ratio / 100.0f) - 0.5f); LastMagicMaxDamage = (WORD)(LastMagicMaxDamage * (ratio / 100.0f) - 0.5f); #endif } } __forceinline void AddArmorValueByFate(float ratio) { if (ratio >= 0) { ItemPhyDef = (WORD)(ItemPhyDef * (ratio / 100.0f) + 0.5f); #ifdef _NA001605_EP2_ATTRIBUTES_RENEWAL_ #else ItemMagicDef = (WORD)(ItemMagicDef * (ratio / 100.0f) + 0.5f); #endif } else { ItemPhyDef = (WORD)(ItemPhyDef * (ratio / 100.0f) - 0.5f); #ifdef _NA001605_EP2_ATTRIBUTES_RENEWAL_ #else ItemMagicDef = (WORD)(ItemMagicDef * (ratio / 100.0f) - 0.5f); #endif } } #pragma warning(push) #pragma warning(disable:4201) union { struct { DWORD LastPhyMinDamage; DWORD LastPhyMaxDamage; #if !defined(_NA001605_EP2_ATTRIBUTES_RENEWAL_) DWORD LastMagicMinDamage; DWORD LastMagicMaxDamage; #endif }; struct { DWORD LastPhyDef; //reordering assume align 4 WORD ItemPhyDef; #if !defined(_NA001605_EP2_ATTRIBUTES_RENEWAL_) DWORD LastMagicDef; WORD ItemMagicDef; #endif }; }; #pragma warning(pop) }; // ¹«±â °ø°Ý·Â inline bool ItemAttrCalculator::_CalcAttrWeapon(const SCItemSlot& IN item_slot, const BASE_ITEMINFO* IN item_info, bool is_add) { sInterDamageOp op; DWORD WeightDamage = CalcAttackPower(item_slot.GetEnchant(), item_info->m_LV); if (item_slot.IsDivine()) { op.SetWeaponValue(item_info->m_wDivPhyMinDamage, item_info->m_wDivPhyMaxDamage, item_info->m_wDivMagicMinDamage, item_info->m_wDivMagicMaxDamage); } else if (item_info->IsElite()) { op.SetWeaponValue(item_info->m_wElitePhyMinDamage, item_info->m_wElitePhyMaxDamage, item_info->m_wEliteMagicMinDamage, item_info->m_wEliteMagicMaxDamage); } else if (item_info->IsUnique()) { op.SetWeaponValue(item_info->m_wUniPhyMinDamage, item_info->m_wUniPhyMaxDamage, item_info->m_wUniMagicMinDamage, item_info->m_wUniMagicMaxDamage); } else { op.SetWeaponValue(item_info->m_wMinDamage, item_info->m_wMaxDamage, item_info->m_wMagicAttMinDamgage, item_info->m_wMagicAttMaxDamgage); } if (item_slot.IsLimited()) { op.AddWeaponValueByLimited((float)item_slot.GetDamageRatio()); } else if (item_slot.IsFateItem()) { op.AddWeaponValueByFate((float)item_slot.GetFateAtkDefRatio()); } op.AddWeaponValue(WeightDamage); #ifdef __NA_001062_20080623_STRENGTH_PENALTY ;{ const DWORD penalty_index = item_info->m_dwStrengthPenaltyIdx; if (penalty_index != 0) { const sSTRENGTH_PENALTY* strength_penalty = \ StrengthPenaltyParser::Instance()->GetStrengthPenaltyInfo(\ penalty_index, item_slot.GetMaxDura(), item_slot.GetDura()); // op.AddWeaponValueByStrength(strength_penalty->m_fStrengthPro); } }; #endif // (f100721.1L) static const Attributes::Operation attr_item_array[] = { eATTR_BASE_MELEE_MIN_ATTACK_POWER, eATTR_BASE_MELEE_MAX_ATTACK_POWER, eATTR_BASE_RANGE_MIN_ATTACK_POWER, eATTR_BASE_RANGE_MAX_ATTACK_POWER, #if !defined(_NA001605_EP2_ATTRIBUTES_RENEWAL_) eATTR_BASE_MAGICAL_MIN_ATTACK_POWER, eATTR_BASE_MAGICAL_MAX_ATTACK_POWER #endif }; const int value_array[_countof(attr_item_array)] = { op.LastPhyMinDamage, op.LastPhyMaxDamage, op.LastPhyMinDamage, op.LastPhyMaxDamage, #if !defined(_NA001605_EP2_ATTRIBUTES_RENEWAL_) op.LastMagicMinDamage, op.LastMagicMaxDamage #endif }; const Attributes::Operation::eOper oper_type = \ is_add ? attr_item_array->eOper_Add : attr_item_array->eOper_Sub; attributes_.GroupOperate(oper_type, eATTR_KIND_ITEM, attr_item_array, value_array, _countof(attr_item_array)); // _ForeachAttrByRank(item_slot, is_add); _ForeachAttrBySocket(item_slot, is_add); // return true; } inline bool ItemAttrCalculator::_CalcAttrArmor(const SCItemSlot& IN item_slot, const BASE_ITEMINFO* IN item_info, bool is_add) { // Divine ¾ÆÀÌÅÛ Ã³¸®! ¹æ¾î·Â »ó½ÂµÈ °ªÀÌ ±âº» PhyDef ÀÌ µÈ´Ù. sInterDamageOp op; // if (item_slot.IsDivine()) { op.SetArmorValue(0, 0, item_info->m_wDivPhyDef, item_info->m_wDivMagicDef); } else if (item_info->IsElite()) { op.SetArmorValue(0, 0, item_info->m_wElitePhyDef, item_info->m_wEliteMagicDef); } else if (item_info->IsUnique()) { op.SetArmorValue(0, 0, item_info->m_wUniPhyDef, item_info->m_wUniMagicDef); } else { op.SetArmorValue(0, 0, item_info->m_wPhyDef, item_info->m_wMagicDef); }; // if (item_slot.IsLimited()) { op.AddArmorValueByLimited((float)item_slot.GetDamageRatio()); } else if (item_slot.IsFateItem()) { op.AddArmorValueByFate((float)item_slot.GetFateAtkDefRatio()); } BYTE enchant = item_slot.GetEnchant(); LEVELTYPE level = item_info->m_LV; op.LastPhyDef = CalcPhyDef(op.ItemPhyDef, enchant, level); #if !defined(_NA001605_EP2_ATTRIBUTES_RENEWAL_) op.LastMagicDef = CalcPhyDef(op.ItemMagicDef, enchant, level); #endif #ifdef __NA_001062_20080623_STRENGTH_PENALTY ;{ const DWORD penalty_index = item_info->m_dwStrengthPenaltyIdx; if (penalty_index != 0) { const sSTRENGTH_PENALTY* strength_penalty = \ StrengthPenaltyParser::Instance()->GetStrengthPenaltyInfo(\ penalty_index, item_slot.GetMaxDura(), item_slot.GetDura()); // op.AddArmorValueByStrength(strength_penalty->m_fStrengthPro); } }; #endif // (f100721.1L) static const Attributes::Operation attr_item_array[] = { eATTR_BASE_MELEE_DEFENSE_POWER, eATTR_BASE_RANGE_DEFENSE_POWER, #if !defined(_NA001605_EP2_ATTRIBUTES_RENEWAL_) eATTR_BASE_MAGICAL_DEFENSE_POWER, #endif }; const int value_array[_countof(attr_item_array)] = { op.LastPhyDef, op.LastPhyDef #if !defined(_NA001605_EP2_ATTRIBUTES_RENEWAL_) , op.LastMagicDef #endif }; const Attributes::Operation::eOper oper_type = \ is_add ? attr_item_array->eOper_Add : attr_item_array->eOper_Sub; attributes_.GroupOperate(oper_type, eATTR_KIND_ITEM, attr_item_array, value_array, _countof(attr_item_array)); // _ForeachAttrByRank(item_slot, is_add); if (item_info->IsArmor()) { _ForeachAttrBySocket(item_slot, is_add); } return true; } bool ItemAttrCalculator::_CalcAttrAccessary(const SCItemSlot& IN item_slot, const BASE_ITEMINFO* IN item_info, bool add_op) { __UNUSED(item_info); _ForeachAttrByRank(item_slot, add_op); return true; } #if SUN_CODE_BACKUP // STEP 3 CASE 3 inline bool ItemAttrCalculator::_CalcAddAttrAccessary(const SCItemSlot& IN item_slot, const BASE_ITEMINFO* IN item_info) { __UNUSED(item_info); _ForeachAddAttrByRank(item_slot); return true; } // STEP 3 CASE 3 inline bool ItemAttrCalculator::_CalcSubAttrAccessary(const SCItemSlot& IN item_slot, const BASE_ITEMINFO* IN item_info) { __UNUSED(item_info); _ForeachSubAttrByRank(item_slot); return true; } #endif //SUN_CODE_BACKUP #if SUN_CODE_BACKUP // STEP 4 (last) inline bool ItemAttrCalculator::_CalcGenericAddAttr2nd(const SCItemSlot& IN item_slot, const BASE_ITEMINFO* IN item_info, BOOL* is_pc_room, BOOL* pbIsSetItemFull) { return _CalcGenericAttr2nd(item_slot, item_info, true, is_pc_room, pbIsSetItemFull); } // STEP 4 (last) inline bool ItemAttrCalculator::_CalcGenericSubAttr2nd(const SCItemSlot& IN item_slot, const BASE_ITEMINFO* IN item_info, BOOL* is_pc_room, BOOL* pbIsSetItemFull) { return _CalcGenericAttr2nd(item_slot, item_info, false, is_pc_room, pbIsSetItemFull); } #endif //SUN_CODE_BACKUP bool ItemAttrCalculator::_CalcGenericAttr2nd(const SCItemSlot& IN item_slot, const BASE_ITEMINFO* IN item_info, bool is_add, BOOL* is_pc_room) { // (NOTE) extra-stone option // (CHANGES) (f100406.2L) (WAVERIX) add filter condition \ // because of inventory effect item is not equip but can apply option const nsSlot::ItemRuleInfo& item_rule_info = item_slot.GetItemRuleInfo(); if (item_rule_info.IsEnableExtraOption()) { if (int n_option_attr_index = item_slot.GetNOptionAttrIndex()) { const sEXTRASTONE_OPT_INFO* extra_option = item_slot.GetNOptionAttrDesc(); if (extra_option) { const eATTR_TYPE attr_type = item_slot.GetNOptionAttr(); const int attr_value = item_slot.GetNOptionAttrValue(); if (is_add) { PlusOptionAttribute(attr_type, extra_option->m_byValueType, attr_value); } else { MinusOptionAttribute(attr_type, extra_option->m_byValueType, attr_value); } } } } //end extra option part // (NOTE) calculate item option by script // (CHANGES) (WAVERIX) changes to more simple code BOOST_STATIC_ASSERT(0 < BASE_ITEMINFO::_MAX_OPTION_NUM && BASE_ITEMINFO::_MAX_OPTION_NUM <= sizeof(DWORD64)); typedef util::SEQ_BYTE_MASK OPTION_EFFECT_MASK; int upperbound_selector = (*is_pc_room) ? 2 : 1; //Normal|PC option groups for (int selector = 0; selector < upperbound_selector; ++selector) { const BASE_ITEMINFO::OptionEffects* __option_effects = selector == 0 ? &item_info->m_byOptionExEffect : &item_info->m_byPCOptionExEffect; const BASE_ITEMINFO::OptionEffects& option_effects = *__option_effects; bool apply = ARR_CHECK_IS_CONTAIN(OPTION_EFFECT_MASK::MASK, option_effects); if (apply == false) { continue; } const BASE_ITEMINFO::OptionIndexes* __option_indexes = selector == 0 ? &item_info->m_wOptionIndex : &item_info->m_wPCOptionIndex; const BASE_ITEMINFO::OptionTypes* __option_types = selector == 0 ? &item_info->m_byOptionType : &item_info->m_byPCOptionType; const BASE_ITEMINFO::OptionValues* __option_values = selector == 0 ? &item_info->m_iOptionValue : &item_info->m_iPCOptionValue; // const BASE_ITEMINFO::OptionIndexes& option_indexes = *__option_indexes; const BASE_ITEMINFO::OptionTypes& option_types = *__option_types; const BASE_ITEMINFO::OptionValues& option_values = *__option_values; for (int op = 0; op < _countof(option_indexes); ++op) { bool is_valid_values = option_indexes[op] != 0 && option_values[op] != 0 && option_indexes[op] < _countof(g_ITEM_OPTION); if (is_valid_values == false) { continue; } const eATTR_TYPE attr_type = g_ITEM_OPTION[option_indexes[op]]; if (is_add) { PlusOptionAttribute(attr_type, option_types[op], option_values[op]); } else { MinusOptionAttribute(attr_type, option_types[op], option_values[op]); } } } if (IsEquipCalc()) { real_equip_slots_[item_slot.GetPos()] = is_add; ApplySetItemOption(&item_slot, is_add); } return true; } bool ItemAttrCalculator::_CalculateRoot(const SCItemSlot& IN item_slot, const BASE_ITEMINFO* IN item_info, bool add_op, BOOL is_pc_room, BOOL use_update_ex) { if (!_CheckCalcAttr(item_slot, item_info)) { return false; } const nsSlot::ItemRuleInfo& item_rule_info = item_slot.GetItemRuleInfo(); // _CalcGenericAttr1st(item_slot, item_info, add_op); if (false) ; // no operation else if (item_rule_info.is_weapon) { _CalcAttrWeapon(item_slot, item_info, add_op); } else if (item_rule_info.is_armor) { _CalcAttrArmor(item_slot, item_info, add_op); } else if (item_rule_info.is_accessory || item_rule_info.is_accessory_special) { _CalcAttrAccessary(item_slot, item_info, add_op); } _CalcGenericAttr2nd(item_slot, item_info, add_op, &is_pc_room); if (auto_update_) { if (use_update_ex) { attributes_.UpdateEx(); } else { attributes_.Update(); } } return true; } //¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬ // void ItemAttrCalculator::Equip(const SCSlot& IN slot, BOOL is_pc_room, BOOL use_update_ex, BOOL& OUT dummy_ref) { __UNUSED(dummy_ref); const SCItemSlot& item_slot = static_cast(slot); const BASE_ITEMINFO* item_info = item_slot.GetItemInfo(); //assert(item_info != 0); // (NOTE) EquipitemÀ̸鼭 equip¿¬»êÀÌ ÇÊ¿äÇÏÁö ¾Ê´Â ¾ÆÀÌÅÛ(°£ÆÇ...)µîÀÌ Á¸ÀçÇÑ´Ù. const nsSlot::ItemRuleInfo& item_rule_info = item_slot.GetItemRuleInfo(); bool need_apply = item_rule_info.is_valid_item && (item_rule_info.is_weapon || item_rule_info.is_armor || item_rule_info.is_accessory || item_rule_info.is_accessory_special); if (need_apply == false) { // (CHANGES) (f100406.2L) (WAVERIX) fix up missing process on the inventory option effect \ // item which is not equal equip item that need applied option typedef util::SEQ_BYTE_MASK \ OPTION_EFFECT_INVEN_MASK; const bool is_inven_effect_item = \ ARR_CHECK_IS_CONTAIN(OPTION_EFFECT_INVEN_MASK::MASK, item_info->m_byOptionExEffect) || ARR_CHECK_IS_CONTAIN(OPTION_EFFECT_INVEN_MASK::MASK, item_info->m_byPCOptionExEffect); if (is_inven_effect_item == false) { return; } } // (f100721.1L) _CalculateRoot(item_slot, item_info, true, is_pc_room, use_update_ex); // #if SUN_CODE_BACKUP if (!_CheckCalcAttr(item_slot, item_info)) return; _CalcGenericAddAttr1st(item_slot, item_info); if (false) ; // no operation else if (item_rule_info.is_weapon) _CalcAddAttrWeapon(item_slot, item_info); else if (item_rule_info.is_armor) _CalcAddAttrArmor(item_slot, item_info); else if (item_rule_info.is_accessory || item_rule_info.is_accessory_special) _CalcAddAttrAccessary(item_slot, item_info); _CalcGenericAddAttr2nd(item_slot, item_info, &is_pc_room, &dummy_ref); if (auto_update_) { if (use_update_ex) attributes_.UpdateEx(); else attributes_.Update(); } #endif //SUN_CODE_BACKUP } //================================================================================================== // // ºñȰ¼ºÈ­ ¾ÆÀÌÅÛÀº Equip¸¦ ÇÏÁö ¾ÊÀ¸¹Ç·Î UnEquipÀ» È£ÃâÇÏÁö ¾Êµµ·Ï ÇÏÀÚ!!! void ItemAttrCalculator::UnEquip(const SCSlot* slot, BOOL is_pc_room, BOOL use_update_ex, BOOL& OUT dummy_ref) { __UNUSED(dummy_ref); if (slot == NULL) { return; } const SCItemSlot& item_slot = static_cast(*slot); const BASE_ITEMINFO* item_info = item_slot.GetItemInfo(); //assert(item_info != 0); // (NOTE) EquipitemÀ̸鼭 equip¿¬»êÀÌ ÇÊ¿äÇÏÁö ¾Ê´Â ¾ÆÀÌÅÛ(°£ÆÇ...)µîÀÌ Á¸ÀçÇÑ´Ù. const nsSlot::ItemRuleInfo& item_rule_info = item_slot.GetItemRuleInfo(); bool need_apply = item_rule_info.is_valid_item && (item_rule_info.is_weapon || item_rule_info.is_armor || item_rule_info.is_accessory || item_rule_info.is_accessory_special); if (need_apply == false) { // (CHANGES) (f100520.4L) (WAVERIX) critical, add a missing logic to match an equip operation // (CHANGES) (f100406.2L) (WAVERIX) fix up missing process on the inventory option effect \ // item which is not equal equip item that need applied option typedef util::SEQ_BYTE_MASK \ OPTION_EFFECT_INVEN_MASK; const bool is_inven_effect_item = ARR_CHECK_IS_CONTAIN(OPTION_EFFECT_INVEN_MASK::MASK, item_info->m_byOptionExEffect) || ARR_CHECK_IS_CONTAIN(OPTION_EFFECT_INVEN_MASK::MASK, item_info->m_byPCOptionExEffect); if (is_inven_effect_item == false) { return; } } // (f100721.1L) _CalculateRoot(item_slot, item_info, false, is_pc_room, use_update_ex); // #if SUN_CODE_BACKUP if (!_CheckCalcAttr(item_slot, item_info)) return; _CalcGenericSubAttr1st(item_slot, item_info); if (false) ; //no operation else if (item_rule_info.is_weapon) _CalcSubAttrWeapon(item_slot, item_info); else if (item_rule_info.is_armor) _CalcSubAttrArmor(item_slot, item_info); else if (item_rule_info.is_accessory || item_rule_info.is_accessory_special) _CalcSubAttrAccessary(item_slot, item_info); _CalcGenericSubAttr2nd(item_slot, item_info, &is_pc_room, &dummy_ref); if (auto_update_) { if (use_update_ex) attributes_.UpdateEx(); else attributes_.Update(); } #endif //SUN_CODE_BACKUP } // ÇöÀç ¼¼Æ® ¾ÆÀÌÅÛ ¿É¼ÇÀ» ¹Ù²ã¾ß Çϴ°¡? // ¸®Åϰª : 0ÀÌ¸é ¹Ù²ÙÁö ¾Ê´Â´Ù. // 1À̸é ÇöÀç »õ·Î ÀåÂø, Å»Âø µÈ ¾ÆÀÌÅÛ °ª¸¸ ¹Ù²Û´Ù. // 2À̸é ÇöÀç ¼¼Æ® ¾ÆÀÌÅÛ ±×·ìÀÇ ¸ðµç ¾ÆÀÌÅÛÀÌ ¹Ù²î¾î¾ß ÇÑ´Ù. BYTE ItemAttrCalculator::GetSetItemChangeType(BYTE number_of_items, bool is_equip) { // Ç® ¿É¼ÇÀ϶§ ¾î¶»°Ô ÇÒ °ÍÀÎÁö »ý°¢ÇØ º¸ÀÚ. if (is_equip) { switch(number_of_items) { case 1: return 0; // ÀåÂø½Ã case 2: case 4: case 6: return 2; default: return 1; } } else { switch(number_of_items) { case 0: return 0; // »¬½Ã.. case 1: case 3: case 5: return 2; default: return 1; } } // Unreached return 0; } void ItemAttrCalculator::Clear() { // (f100720.3L) attributes_.ClearRelatedAttrKind(eATTR_KIND_ITEM); /* for (int attr_type = 0; attr_type < eATTR_MAX; ++attr_type) { if (!attributes_.IsNULL((eATTR_TYPE)attr_type)) { AttrValue& attrs = attributes_[(eATTR_TYPE)attr_type]; attrs[eATTR_KIND_ITEM] = 0; attrs[eATTR_KIND_ITEM_RATIO] = 0; } } */ if (auto_update_) { attributes_.Update(); } set_item_count_calculation_type_ = false; ZeroMemory(real_equip_slots_, sizeof(real_equip_slots_)); // _NA_000251_20100727_SOCKET_SYSTEM socket_option_calculator_.Clear(); } void ItemAttrCalculator::UpdateAll(BOOL is_pc_room) { Clear(); POSTYPE size = slot_container_.GetMaxSlotNum(); for (POSTYPE posIdx = 0; posIdx < size; ++posIdx) { if (!slot_container_.IsEmpty(posIdx)) { const SCSlot& pSlot = slot_container_.GetSlot(posIdx); BOOL bIsFull = false; Equip(pSlot, is_pc_room, false, bIsFull); } } } // (f100812.2L) add an interface to support external module can access add rule filter void ItemAttrCalculator::ModifyAttrKindAndCalculatedValue(uint8_t value_type, //eVALUE_TYPE uint8_t* attr_kind, //eATTR_KIND int * value) { *attr_kind = eATTR_KIND_ITEM; float calced_value = static_cast(*value); if (value_type == VALUE_TYPE_PERCENT_PER_MAX || value_type == VALUE_TYPE_PERCENT_PER_CUR) { *attr_kind = eATTR_KIND_ITEM_RATIO; } // *value = static_cast(calced_value); } void ItemAttrCalculator::MinusOptionAttribute(eATTR_TYPE attr_type, BYTE value_type, int value) { if (value == 0) return; if (!(eATTR_TYPE_INVALID < attr_type && attr_type < eATTR_MAX)) return; eATTR_KIND attr_kind = eATTR_KIND_ITEM; if (value_type == VALUE_TYPE_PERCENT_PER_MAX || value_type == VALUE_TYPE_PERCENT_PER_CUR) { attr_kind = eATTR_KIND_ITEM_RATIO; } static const Attributes::Operation attr_array_for_all_stats[] = { eATTR_STR, eATTR_DEX, eATTR_VIT, eATTR_INT, eATTR_SPR }; switch (attr_type) { case eATTR_INCREASE_STAT_POINT: { // (f100722.2L) int value_array[_countof(attr_array_for_all_stats)] = { value, value, value, value, value }; // attributes_.GroupOperate(attr_array_for_all_stats->eOper_Sub, attr_kind, attr_array_for_all_stats, value_array, _countof(attr_array_for_all_stats)); #if SUN_CODE_BACKUP // ·©Å© ¹ÝÁö attributes_[eATTR_STR][attr_kind] -= value; attributes_[eATTR_DEX][attr_kind] -= value; attributes_[eATTR_VIT][attr_kind] -= value; attributes_[eATTR_INT][attr_kind] -= value; attributes_[eATTR_SPR][attr_kind] -= value; #endif } break; default: { attributes_[attr_type][attr_kind] -= value; } break; } } void ItemAttrCalculator::PlusOptionAttribute(eATTR_TYPE attr_type, BYTE value_type, int value) { if (value == 0) return; if (!(eATTR_TYPE_INVALID < attr_type && attr_type < eATTR_MAX)) return; eATTR_KIND attr_kind = eATTR_KIND_ITEM; if (value_type == VALUE_TYPE_PERCENT_PER_MAX || value_type == VALUE_TYPE_PERCENT_PER_CUR) { attr_kind = eATTR_KIND_ITEM_RATIO; } static const Attributes::Operation attr_array_for_all_stats[] = { eATTR_STR, eATTR_DEX, eATTR_VIT, eATTR_INT, eATTR_SPR }; switch (attr_type) { case eATTR_INCREASE_STAT_POINT: { // (f100722.2L) int value_array[_countof(attr_array_for_all_stats)] = { value, value, value, value, value }; // attributes_.GroupOperate(attr_array_for_all_stats->eOper_Add, attr_kind, attr_array_for_all_stats, value_array, _countof(attr_array_for_all_stats)); #if SUN_CODE_BACKUP // ·©Å© ¹ÝÁö attributes_[eATTR_STR][attr_kind] += value; attributes_[eATTR_DEX][attr_kind] += value; attributes_[eATTR_VIT][attr_kind] += value; attributes_[eATTR_INT][attr_kind] += value; attributes_[eATTR_SPR][attr_kind] += value; #endif } break; default: { attributes_[attr_type][attr_kind] += value; } break; } } // ÀÌ ÇÔ¼ö´Â ¹Ýµå½Ã ÀåÂø ÈÄ¿¡ È£ÃâµÇ¾î¾ß ÇÑ´Ù. // ³»ºÎ¿¡¼­ °è»êµÈ °ªÀº ÇöÀç ÀåÂøµÈ ¾ÆÀÌÅÛ¿¡ ´ëÇØ¿©¸¸ °è»êÇÑ´Ù. void ItemAttrCalculator::ApplySetItemOption(const SCSlot* pSlot, bool is_equip) { if (!pSlot) return; const SCItemSlot& item_slot = static_cast(*pSlot); SCItemSlotContainer& item_container = static_cast(slot_container_); assert(item_container.GetSlotIdx() == SI_EQUIPMENT); const BASE_ITEMINFO* item_info = item_slot.GetItemInfo(); BYTE set_item_code = item_info->m_bySetType; POSTYPE equip_pos = item_slot.GetPos(); // replaced by _SOLAR_SLOT_INTEGRITY_CONTAINER_PROCESS_ //ÇöÀç ÀåÂøµÇ¾î ÀÖ´Â ¾ÆÀÌÅÛÁß ÇØ´ç ŸÀÔÀÇ ¼¼Æ® ¾ÆÀÌÅÛÀ» °¡Áö°í ¿Â´Ù. // (CHANGES) find related set item, to support special accessory multi-link SCItemSlot* temp_set_item_slot_array[MAX_INVENTORY_SLOT_NUM]; SCItemSlotContainer::SameSetItemSlotsResult find_result = \ item_container.GetSameSetItemSlots(temp_set_item_slot_array, _countof(temp_set_item_slot_array), item_info, is_equip); // compatible set if (find_result.number_of_same_set_items == 0) { return; } BYTE temp_set_item_count = find_result.number_of_same_set_items; set_item_code = find_result.set_item_code; // replacing SCSlot* set_item_slot_array[MAX_INVENTORY_SLOT_NUM]; BYTE real_set_item_count = 0; if (set_item_count_calculation_type_ && IsEquipCalc()) { // ¾ÆÀÌÅÛ °³¼ö¸¦ ³»ºÎ Áõ°¡¿¡ ÀÇÇÑ ¹æ¹ýÀ¸·Î °è»ê½Ã for (BYTE byIdx = 0; byIdx < temp_set_item_count; byIdx++) { POSTYPE Pos = temp_set_item_slot_array[byIdx]->GetPos(); if (real_equip_slots_[Pos]) { set_item_slot_array[real_set_item_count] = temp_set_item_slot_array[byIdx]; real_set_item_count++; } } } else { for (int i = 0; i < temp_set_item_count; i++) { set_item_slot_array[i] = temp_set_item_slot_array[i]; } real_set_item_count = temp_set_item_count; } SetItemOptionInfoParser* const set_item_parser = SetItemOptionInfoParser::Instance(); eSETITEM_OPTION_LEVEL CurEquipLevel = set_item_parser->GetSetItemOptionLevel(real_set_item_count); //1. ÇöÀç Àå/Å»ÂøÀÌ Ç® ¿É¼ÇÀ¸·ÎÀÇ ? ¶Ç´Â Ç® ¿É¼Ç¿¡¼­´Â º¯È­Àΰ¡? bool is_full_option = false; if (is_equip) { is_full_option = set_item_parser->IsFullOption(set_item_code, real_set_item_count) != false; } else { BYTE byAddCount = 0; // ½ºÆä¼È ¾ÆÀÌÅÛÀ̸é.. ¼¼Æ®¾ÆÀÌÅÛ À̸鼭 Ç® ¿É¼Ç¿¡ ¿µÇâÀ» ÁÖÁö ¸»¾Æ¾ß ÇÑ´Ù. if (item_info->m_bySetOptionType == item_info->eSetItem_Special) { byAddCount = 0; } else { byAddCount = 1; } is_full_option = set_item_parser->IsFullOption(set_item_code, real_set_item_count + byAddCount) != false; } //2. Ç® ¼¼Æ®¾ÆÀÌÅÛ ¿É¼ÇÀ» ´õÇÏ´øÁö »«´Ù. if (is_full_option && item_info->m_bySetOptionType == item_info->eSetItem_Active) { ApplySetItemFullOption(set_item_code, is_equip); } ////////////////////////////////////////////////////////////////////////// //3. ÀÏ¹Ý ¼¼Æ®¾ÆÀÌÅÛ ¿É¼ÇÀ» Àû¿ë½ÃŲ´Ù. // ½ºÆä¼È¾ÆÀÌÅÛÀÌ¸é µî±Þó¸® ÇÏÁö ¾Ê´Â´Ù. BYTE byChangeType = 0; if (item_info->m_bySetOptionType == item_info->eSetItem_Special) { byChangeType = 0; } else { byChangeType = GetSetItemChangeType(real_set_item_count, is_equip); } //4. µî±ÞÀÇ º¯È­°¡ ¾ø´Ù¸é... if (byChangeType == 1) { // ÇöÀç ÀåÂøµÈ ¾ÆÀÌÅÛÀº »õ·Î ÀåÂøµÈ ¾ÆÀÌÅÛ À̹ǷΠÇöÀç µî±Þ ±îÁöÀÇ ¸ðµç ¿É¼ÇÀ» Àû¿ë½ÃŲ´Ù. if (CurEquipLevel > SETITEM_OPTION_LEVEL_NONE) { for (BYTE Level = 1 ; Level <= CurEquipLevel ; Level++) { ApplySetItemOption(set_item_code, equip_pos, (eSETITEM_OPTION_LEVEL)Level, is_equip); } } } //2. µî±Þ¿¡ º¯È­°¡ ÀÖÀ»½Ã. else if (byChangeType == 2) { eSETITEM_OPTION_LEVEL OptionLevel = SETITEM_OPTION_LEVEL_NONE; if (is_equip) { OptionLevel = CurEquipLevel; } else { OptionLevel = (eSETITEM_OPTION_LEVEL)(CurEquipLevel + 1); //Å»Âø½Ã¿¡´Â ÀÌÀü µî±ÞÀÇ ¿É¼ÇÀ» Á¦°ÅÇØ¾ß ÇϹǷΠ+ 1ÇÑ´Ù. } //3. ÇöÀç Àå/Å»ÂøµÈ ¾ÆÀÌÅÛÀº ÇöÀç µî±Þ ±îÁöÀÇ ¸ðµç ¿É¼ÇÀ» Àû¿ë½ÃŲ´Ù. for (BYTE Level = 1 ; Level <= OptionLevel ; Level++) { ApplySetItemOption(set_item_code, equip_pos, (eSETITEM_OPTION_LEVEL)Level, is_equip); } //4. ÇöÀç ÀåÂøµÈ ÇØ´ç ¼¼Æ® µî±ÞÀÇ ¸ðµç ¾ÆÀÌÅÛ¿¡ ÇöÀç µî±Þ ¿É¼ÇÀ» Àû¿ë ½ÃŲ´Ù.(ÇöÀç ÀåÂøµÈ ¾ÆÀÌÅÛ Á¦¿Ü) //BYTE bySetOptionResult = 0; for (BYTE byIdx = 0; byIdx < real_set_item_count; byIdx++) { POSTYPE Pos = set_item_slot_array[byIdx]->GetPos(); if (equip_pos != Pos) { ApplySetItemOption(set_item_code, Pos, OptionLevel, is_equip); } } } ////////////////////////////////////////////////////////////////////////// // ÇöÀç Ç® ¿É¼ÇÀ̰í, pos¿¡ ÇØ´ç ¾ÆÀÌÅÛÀÌ ÀåÂøµÇ¾î ÀÖ´Ù¸é. if (is_full_option) { const SETITEM_OPTION_INFO* pSetItemOption = \ SetItemOptionInfoParser::Instance()->Find(set_item_code); if (!pSetItemOption) { return; } //1. ÇöÀç ´õÇϰųª »©´Â°Ô ½ºÆä¼È ¾ÆÀÌÅÛÀ̸é. if (item_info->m_Code == pSetItemOption->m_SpecialEquipOptionItem.m_wItemCode) { ApplySpecialSetItemOption(set_item_code, is_equip); } else { // ÇÔ²² ¼¼Æ® È¿°ú°¡ ¹ßµ¿ÇÏ´Â ¾ÆÀÌÅÛÀÌ ÀåÂøµÇ¾î ÀÖ´ÂÁö È®ÀÎ const SCItemSlot& special_item = item_container.GetItemOfType(\ pSetItemOption->m_SpecialEquipOptionItem.m_EqPos, pSetItemOption->m_SpecialEquipOptionItem.m_wItemCode); if (special_item.GetItemCode() != 0 && special_item.GetItemCode() == pSetItemOption->m_SpecialEquipOptionItem.m_wItemCode && real_equip_slots_[pSetItemOption->m_SpecialEquipOptionItem.m_EqPos]) { ApplySpecialSetItemOption(set_item_code, is_equip); } } } return; } void ItemAttrCalculator::ApplySpecialSetItemOption(BYTE bySetCode, bool is_equip) { const SETITEM_OPTION_INFO* pSetItemOption = \ SetItemOptionInfoParser::Instance()->Find(bySetCode); if (!pSetItemOption) { return; } // _countof(g_ITEM_OPTION)´Â ¹è¿­À̹ǷÎ, 51°³°¡ ÀÖ´Ù¸é... °ªÀº 52·Î ³ª¿Ã°ÍÀÌ´Ù. // µû¶ó¼­ "=" ¸¦ ÇØÁØ´Ù. // // (WAVERIX) (NOTE) À§ÀÇ ÁÖ¼®: ÷»èÇÏÁö ¾ÊÀ¸¸é ¿ÀÇØÀÇ ¿©Áö°¡ À־... _countof´Â ¹è¿­ÀÇ °³¼ö¸¦ // °è»êÇÏ´Â À¯Æ¿, µû¶ó¼­ ¹è¿­ Å©±â°¡ 51À̸é, 51°³°¡ ³ª¿Â´Ù. // ´ÜÁö g_ITEM_OPTIONÀÇ °æ¿ì´Â eATTR_TYPE_INVALID°ªÀ» Ãß°¡ÇØ µÎ¾ú±â ¶§¹®¿¡ Çϱâ¿Í °°Àº ¿¬»êÀÌ // °¡´ÉÇØÁö´Â °ÍÀÌ´Ù. for (int i = 0; i < MAX_SETITEM_SPECIAL_OPTION; i++) { const SET_ITEM_OPTION& special_option = \ pSetItemOption->m_SpecialEquipOptionItem.m_ActiveOption[i]; int option_index = special_option.m_byOptionKind; if (option_index == 0) { continue; } if (option_index >= _countof(g_ITEM_OPTION)) { continue; } //ÀÌ ¾ÆÀÌÅÛ ¿É¼ÇÀ» ÇöÀç ¼Ó¼º¿¡ Àû¿ëÇÑ´Ù. const eATTR_TYPE attr_type = g_ITEM_OPTION[option_index]; if (is_equip) { PlusOptionAttribute(attr_type, special_option.m_byUseType, special_option.m_nOption); } else { MinusOptionAttribute(attr_type, special_option.m_byUseType, special_option.m_nOption); } } } //set_item_count ¸¸Å­ ÇØ´ç ´É·ÂÄ¡¸¦ Àû¿ë ½ÃŲ´Ù. void ItemAttrCalculator::ApplySetItemOption(BYTE bySetCode, POSTYPE pos, eSETITEM_OPTION_LEVEL Level, bool is_equip) { const SET_ITEM_OPTION* pSetItemOption = SetItemOptionInfoParser::Instance()->GetSetItemOption(bySetCode, pos, Level); if (!pSetItemOption) { return; } // _countof(g_ITEM_OPTION)´Â ¹è¿­À̹ǷÎ, 51°³°¡ ÀÖ´Ù¸é... °ªÀº 52·Î ³ª¿Ã°ÍÀÌ´Ù. // µû¶ó¼­ "=" ¸¦ ÇØÁØ´Ù. // // (WAVERIX) (NOTE) À§ÀÇ ÁÖ¼®: ÷»èÇÏÁö ¾ÊÀ¸¸é ¿ÀÇØÀÇ ¿©Áö°¡ À־... _countof´Â ¹è¿­ÀÇ °³¼ö¸¦ // °è»êÇÏ´Â À¯Æ¿, µû¶ó¼­ ¹è¿­ Å©±â°¡ 51À̸é, 51°³°¡ ³ª¿Â´Ù. // ´ÜÁö g_ITEM_OPTIONÀÇ °æ¿ì´Â eATTR_TYPE_INVALID°ªÀ» Ãß°¡ÇØ µÎ¾ú±â ¶§¹®¿¡ Çϱâ¿Í °°Àº ¿¬»êÀÌ // °¡´ÉÇØÁö´Â °ÍÀÌ´Ù. if (pSetItemOption->m_byOptionKind >= _countof(g_ITEM_OPTION)) return; //ÀÌ ¾ÆÀÌÅÛ ¿É¼ÇÀ» ÇöÀç ¼Ó¼º¿¡ Àû¿ëÇÑ´Ù. const eATTR_TYPE attr_type = g_ITEM_OPTION[ pSetItemOption->m_byOptionKind ]; if (is_equip) { PlusOptionAttribute(attr_type, pSetItemOption->m_byUseType, pSetItemOption->m_nOption); } else { MinusOptionAttribute(attr_type, pSetItemOption->m_byUseType, pSetItemOption->m_nOption); } #if defined(_DEBUG) && defined(_SERVER) SUNLOG(eDEV_LOG, "[ItemAttrCalculator::ApplySetItemOption] " "Equip = %d, SetCode = %d, Pos = %d, Level = %d, AttrType =%d, Option = %d", is_equip, bySetCode, pos, Level, attr_type, pSetItemOption->m_nOption); #endif } //¼¼Æ® ¾ÆÀÌÅÛ Ç® ¿É¼ÇÀ» Àû¿ë ½ÃŲ´Ù. void ItemAttrCalculator::ApplySetItemFullOption(BYTE bySetCode, bool is_equip) { SET_ITEM_OPTION* pSetItemOptionArray[MAX_SETITEM_FULL_OPTION]; int upperbound = SetItemOptionInfoParser::Instance()->GetSetItemFullOption(bySetCode, pSetItemOptionArray); if (upperbound == 0) { return; } for (int i = 0; i < upperbound; ++i) { // _countof(g_ITEM_OPTION)´Â ¹è¿­À̹ǷÎ, 51°³°¡ ÀÖ´Ù¸é... °ªÀº 52·Î ³ª¿Ã°ÍÀÌ´Ù. // µû¶ó¼­ "=" ¸¦ ÇØÁØ´Ù. // // (WAVERIX) (NOTE) À§ÀÇ ÁÖ¼®: ÷»èÇÏÁö ¾ÊÀ¸¸é ¿ÀÇØÀÇ ¿©Áö°¡ À־... _countof´Â ¹è¿­ÀÇ °³¼ö¸¦ // °è»êÇÏ´Â À¯Æ¿, µû¶ó¼­ ¹è¿­ Å©±â°¡ 51À̸é, 51°³°¡ ³ª¿Â´Ù. // ´ÜÁö g_ITEM_OPTIONÀÇ °æ¿ì´Â eATTR_TYPE_INVALID°ªÀ» Ãß°¡ÇØ µÎ¾ú±â ¶§¹®¿¡ Çϱâ¿Í °°Àº ¿¬»êÀÌ // °¡´ÉÇØÁö´Â °ÍÀÌ´Ù. const SET_ITEM_OPTION* set_item_option = pSetItemOptionArray[i]; if (set_item_option->m_byOptionKind >= _countof(g_ITEM_OPTION)) { return; } //ÀÌ ¾ÆÀÌÅÛ ¿É¼ÇÀ» ÇöÀç ¼Ó¼º¿¡ Àû¿ëÇÑ´Ù. const eATTR_TYPE attr_type = g_ITEM_OPTION[ set_item_option->m_byOptionKind ]; if (is_equip) { PlusOptionAttribute(attr_type, set_item_option->m_byUseType, set_item_option->m_nOption); } else { MinusOptionAttribute(attr_type, set_item_option->m_byUseType, set_item_option->m_nOption); } } } // _NA_000251_20100727_SOCKET_SYSTEM ItemAttrCalculator::SocketOptionCalculator::SocketOptionCalculator( SocketOptionAttributes& socket_option_attributes) : socket_option_attributes_(socket_option_attributes) { } void ItemAttrCalculator::SocketOptionCalculator::Clear() { socket_option_attributes_.Clear(); } bool ItemAttrCalculator::SocketOptionCalculator::CalculateItemOptionPoint( const SCItemSlot& item_slot, CalculationResultMap& OUT item_calc_result_map) { item_calc_result_map.clear(); const int number_of_socket = item_slot.GetSocketNum(); for (eSOCKET socket = SOCKET_1; socket < number_of_socket; socket = static_cast(socket+1)) { // ¼ÒÄÏ ¿É¼Ç Á¤º¸°¡ À¯È¿ÇÑÁö °Ë»çÇÑ´Ù. const sSOCKET_OPTION* const socket_option = item_slot.GetSocketOption(socket); if (socket_option == NULL) { continue; } // ¼ÒÄÏ ¿É¼ÇÀÇ °¢ ¿É¼Ç Æ÷ÀÎÆ®¿¡ ´ëÇØ for (sSOCKET_OPTION::OptionPointInfo::ListSizeType i = 0; i < socket_option->option_point_list_size; ++i) { // Æ÷ÀÎÆ® Á¤º¸°¡ À¯È¿ÇÑÁö °Ë»çÇÑ´Ù. const sSOCKET_OPTION::OptionPointInfo* const option_point_info = socket_option->GetPointInfo(i); if (option_point_info == NULL) { continue; } // ¿É¼Ç Á¤º¸°¡ À¯È¿ÇÑÁö °Ë»çÇÑ´Ù. const ZardOptionInfo* const zard_option = option_point_info->zard_option; if (zard_option == NULL || zard_option->attr_option_code == eATTR_TYPE_INVALID || zard_option->item_option_code == eATTR_TYPE_INVALID) { continue; } // Áߺ¹ ¿É¼ÇÀÎÁö °Ë»çÇØ¼­ Áߺ¹ÀÌ¸é Æ÷ÀÎÆ® ¼öÄ¡¸¦ ÇÕÄ£´Ù. CalculationResult& item_calc_result = item_calc_result_map[zard_option->attr_option_code]; if (item_calc_result.attr_option_code == eATTR_TYPE_INVALID) { item_calc_result.attr_option_code = zard_option->attr_option_code; item_calc_result.item_option_code = zard_option->item_option_code; item_calc_result.option_point = option_point_info->option_point; } else { item_calc_result.option_point += option_point_info->option_point; } } } if (item_calc_result_map.empty()) { return false; } return true; } bool ItemAttrCalculator::SocketOptionCalculator::CalculateItemOptionValue( const bool is_add, const CalculationResult& item_calc_result, ItemAttrCalculator& OUT item_calculator) { // ¾ÆÀÌÅÛ Æ÷ÀÎÆ® °è»ê °á°ú°¡ 0ÀÌ¸é º¯°æ½Ãų °ªÀÌ ¾ø´Ù. if (item_calc_result.option_point == 0) { return false; } // À¯È¿ÇÑ ¿É¼ÇÀÎÁö °Ë»çÇÑ´Ù. if (item_calc_result.attr_option_code == eATTR_TYPE_INVALID || item_calc_result.item_option_code == eATTR_TYPE_INVALID) { return false; } const ZardOptionInfo* const zard_option = (SocketOptionParser::Instance())->FindZardOption(item_calc_result.item_option_code); if (zard_option == NULL) { return false; } // ¿É¼Ç ŸÀÔÀ» ¾ò´Â´Ù. const BYTE option_value_type = static_cast(zard_option->GetOptionType()); // ÀÌÀü °è»ê °á°ú¸¦ Á¦°ÅÇÑ´Ù. SocketOptionAttributes::AttrValue& prev_attr_value = socket_option_attributes_.GetAttrValueByMutable(item_calc_result.attr_option_code); if (prev_attr_value.calc_value != 0) { item_calculator.MinusOptionAttribute( item_calc_result.attr_option_code, option_value_type, prev_attr_value.calc_value); } // ÀÌÀü °è»ê °á°ú¸¦ °»½ÅÇÑ´Ù. { if (is_add) { prev_attr_value.point += item_calc_result.option_point; } else { prev_attr_value.point -= item_calc_result.option_point; } const ZardOptionInfo::OptionValueInfo* const zard_option_value = zard_option->Find(prev_attr_value.point); if (zard_option_value != NULL) { prev_attr_value.calc_value = zard_option_value->value; } else { prev_attr_value.calc_value = 0; } } // »õ·Î¿î °è»ê °á°ú¸¦ Àû¿ëÇÑ´Ù. if (prev_attr_value.calc_value != 0) { item_calculator.PlusOptionAttribute( item_calc_result.attr_option_code, option_value_type, prev_attr_value.calc_value); } //#define SOCKET_OPTION_POINT_CALC_DEBUG // °è»ê°á°ú µð¹ö±ë #ifdef SOCKET_OPTION_POINT_CALC_DEBUG SUNLOG(eCRITICAL_LOG, _T("|OptionPointCalcDebug|IsAdd = %d|ItemOptionCode = %d, ItemOptionPoint = %d|UpdatedAttrPoint = %d, UpdatedAttrCalcValue = %d|"), (is_add ? 1 : 0), item_calc_result.item_option_code, item_calc_result.option_point, prev_attr_value.point, prev_attr_value.calc_value); #endif // SOCKET_OPTION_POINT_CALC_DEBUG return true; } void ItemAttrCalculator::SocketOptionCalculator::Calculate( const SCItemSlot& item_slot, const bool is_add, ItemAttrCalculator& OUT item_calculator) { #ifdef _NA_001699_20110104_SOCKET_OPTION_POINT // Æ÷ÀÎÆ® ¹æ½Ä °è»ê¿¡¼­´Â ÀåÂø ÁßÀÎ ¸ðµç ¾ÆÀÌÅÛÀÇ ¿É¼Ç Æ÷ÀÎÆ®ÇÕÀ» ±âÁØÀ¸·Î ½ÇÁ¦ ¿É¼Ç°ªÀ¸·Î º¯È¯ÇØ¾ß ÇÑ´Ù. // ¾ÆÀÌÅÛÀÇ Âø¿ë »óŰ¡ º¯°æµÉ ¶§ ´ÙÀ½°ú °°ÀÌ °è»êÇÑ´Ù. // 1. Âø¿ë »óÅ º¯°æ Àü¿¡ Àû¿ëµÈ ¿É¼Ç°ªÀ» Á¦°ÅÇÑ´Ù. // 2. Âø¿ë »óÅ º¯°æ ÈÄÀÇ ¿É¼Ç Æ÷ÀÎÆ®¸¦ °è»êÇØ¼­ ¿É¼Ç°ªÀ¸·Î º¯È¯ÇÑ ÈÄ Àû¿ëÇÑ´Ù. // ÀåÂø ¶Ç´Â ÇØÁ¦ÇÏ·Á´Â ¾ÆÀÌÅÛ¸¸ÀÇ ¿É¼Ç Æ÷ÀÎÆ®¸¦ °è»êÇÑ´Ù. CalculationResultMap item_calc_result_map; if (CalculateItemOptionPoint(item_slot, item_calc_result_map) == false) { return; } // ¾ÆÀÌÅÛÀÇ ¿É¼Ç Æ÷ÀÎÆ® °è»ê °á°ú¿¡ ´ëÇØ FOREACH_CONTAINER( const CalculationResultMap::value_type& item_calc_result_pair, item_calc_result_map, CalculationResultMap) { // ¿É¼Ç°ªÀ» °è»êÇÑ´Ù. CalculateItemOptionValue(is_add, item_calc_result_pair.second, item_calculator); } #else // _NA_001699_20110104_SOCKET_OPTION_POINT const int number_of_socket = item_slot.GetSocketNum(); for (eSOCKET socket = SOCKET_1; socket < number_of_socket; socket = static_cast(socket+1)) { const sSOCKET_OPTION* const socket_option = item_slot.GetSocketOption(socket); if (socket_option == NULL) { continue; } if (is_add) { item_calculator.PlusOptionAttribute( socket_option->attr_option_kind, socket_option->option_type, socket_option->option_value); } else { item_calculator.MinusOptionAttribute( socket_option->attr_option_kind, socket_option->option_type, socket_option->option_value); } } #endif // _NA_001699_20110104_SOCKET_OPTION_POINT } #endif //if !defined(_NA_002289_20110322_EQUIPMENTS_CALCULATOR_CHANGES_FOR_IMPROVEMENT)