#include "stdafx.h" #include "./ItemManager_Trading.h" #include "ItemManager.h" #include "ItemTypeList.h" #include "ExchangeRewardInfo.h" #include "RewardInfoList.h" #include "InventorySlotContainer.h" #include "SlotManager.h" #include "RewardManager.h" #include "ChaoState.h" #include "AchievementManager.h" #include "AccumulatePoint.h" #include #include #include //================================================================================================== namespace nsSlot { ; // NOTE: sub-manager is implemented to decompose ItemManager. // this object has not extra members and virtual function table except the instance of ItemManager. BOOST_STATIC_ASSERT(sizeof(nsSlot::ItemTradingImpl) == sizeof(ItemManager*)); }; //end of namespace //================================================================================================== // RC::eITEM_RESULT nsSlot::ItemTradingImpl::Exchange( POSTYPE atPos, INVENTORY_TOTAL_INFO* OUT pTotalInfo) { if (root_->IsRestrictFunction(eFUNCTIONALRESTRICT_EXCHANGE_ITEM)) return RC::RC_ITEM_UNUSABLE_FUNCTION; if (!root_->ValidState()) return RC::RC_ITEM_INVALIDSTATE; if (!root_->ValidPos(SI_INVENTORY, atPos)) return RC::RC_ITEM_INVALIDPOS; SCSlotContainer* pAtContainer = root_->GetItemSlotContainer(SI_INVENTORY); SCItemSlot& rItemSlot = (SCItemSlot &)pAtContainer->GetSlot(atPos); //BASE_ITEMINFO* pInfo = rItemSlot.GetItemInfo(); // ÆÇ¸ÅºÒ°¡´ÉÀΰ¡? // Exchange¾ÆÀÌÅÛÀº ÆÇ¸ÅºÒ°¡ ¾ÆÀÌÅÛÀÌ´Ù. /* if ((rItemSlot.GetItemInfo()->m_byTradeSellType & eITEM_TRADESELL_SELL)) { return RC::RC_ITEM_CANNOT_SELL_ITEM; } */ // ¼ÒÄÏ °³¼ö ´Ù½Ã »ý¼º Á¾·ù ¾ÆÀÌÅÛÀº ±ÔÄ¢»ó ±³È¯ ºÒ°¡´ÉÇÏ´Ù. if (rItemSlot.GetItemInfo()->m_wType == eITEMTYPE_STAT_CHANGE) { return RC::RC_ITEM_INVALID_TYPE; } if (0 == rItemSlot.GetItemInfo()->m_ExchangedItem) { return RC::RC_ITEM_CANNOT_EXCHANGE_ITEM; } if (rItemSlot.GetItemInfo()->IsChargeItem()) { return RC::RC_ITEM_CANNOT_DO_THIS_FOR_CHARGEITEM; } RC::eITEM_RESULT rt = root_->Obtain(rItemSlot.GetItemInfo()->m_ExchangedItem, 1, pTotalInfo); if (rt == RC::RC_ITEM_SUCCESS) { // ¾ÆÀÌÅÛ »èÁ¦ ·Î±× SCItemSlot ObtainItem; ObtainItem.SetCode(rItemSlot.GetItemInfo()->m_ExchangedItem); GAMELOG->LogItemEx(ITEM_EXCHANGE, root_->player_, rItemSlot, ObtainItem); root_->Lose(pAtContainer, atPos, 1); } return rt; } RC::eITEM_RESULT nsSlot::ItemTradingImpl::Sell( const SLOTIDX slot_type, const POSTYPE slot_position, const DURATYPE sell_quantity) { if (root_->IsRestrictFunction(eFUNCTIONALRESTRICT_SELL_ITEM)) { return RC::RC_ITEM_UNUSABLE_FUNCTION; } if (!root_->ValidState()) { return RC::RC_ITEM_INVALIDSTATE; } if (!root_->ValidPos(slot_type, slot_position)) { return RC::RC_ITEM_INVALIDPOS; } // Àκ¥Å丮°¡ ¾Æ´Ï¸é ÆÈ ¼ö ¾ø´Ù. if (slot_type != SI_INVENTORY) { return RC::RC_ITEM_INVALIDSTATE; } if (!root_->player_->GetChaoState().CanUseFuction(CHAO_USE_STORE)) { return RC::RC_ITEM_UNABLE_FUNCTION_FOR_CHAOSTATE; } if (root_->player_->GetBehave() == PLAYER_BEHAVE_UNEXPECTED_WAITING) { return RC::RC_ITEM_INVALIDSTATEOFPLAYER; } SCSlotContainer* const item_slot_container = root_->GetItemSlotContainer(slot_type); SCItemSlot& item_slot = static_cast(item_slot_container->GetSlot(slot_position)); const BASE_ITEMINFO* const item_info = item_slot.GetItemInfo(); if (item_info == NULL) { return RC::RC_ITEM_NOINFO; } // ÆÇ¸ÅºÒ°¡´ÉÀΰ¡? if (item_slot.CanTradeSell(eITEM_TRADESELL_SELL) == false) { return RC::RC_ITEM_CANNOT_SELL_ITEM; } // ¾ÆÀÌÅÛÀ» ºÐÇÒÇÏ¿© ÆÇ¸ÅÇÑ´Ù¸é const bool is_divide_sell = (sell_quantity > 0 && sell_quantity != item_slot.GetNum()); if (is_divide_sell) { // ÆÇ¸Å °³¼ö¸¦ °Ë»çÇÑ´Ù. if (sell_quantity > item_slot.GetNum()) { return RC::RC_ITEM_INVALID_VALUE; } // Àӽà ¾ÆÀÌÅÛ ½½·ÔÀ» ¸¸µé¾î¼­ SCItemSlot temp_item_slot; temp_item_slot.Copy(item_slot); temp_item_slot.SetNum(sell_quantity); temp_item_slot.SetSerial(TEMP_DBSERIAL_VALUE); // ±Ý¾×À» ȹµæÇÑ´Ù. const MONEY price_of_goods = temp_item_slot.GetPriceForSell(); if (!root_->player_->PlusMoney(price_of_goods)) { return RC::RC_ITEM_FAILED; } // ÇöÀç ¾ÆÀÌÅÛ ¼ö·®À» ÆÇ¸Å °³¼ö¸¸Å­ °¨¼ÒÇϰí item_slot_container->UpdateSlot(slot_position, -sell_quantity); // ÆÇ¸Å ¸ñ·Ï¿¡ µî·ÏÇÑ´Ù. RegisterSaleItem(temp_item_slot); // ·Î±×¸¦ ±â·ÏÇÑ´Ù. { GAMELOG->LogItem_Pos(ITEM_NPC_SELL, root_->player_, &temp_item_slot, price_of_goods, temp_item_slot.GetNum(), slot_type, slot_position, 0, 0); GAMELOG->LogMoney(MONEY_NPC_SELL, root_->player_, price_of_goods); } } else // ºÐÇÒ ÆÇ¸Å°¡ ¾Æ´Ï¶ó¸é ÀÌÀü°ú µ¿ÀÏÇÑ ¹æ½ÄÀ¸·Î ÆÇ¸ÅÇÑ´Ù. { const MONEY price_of_goods = item_slot.GetPriceForSell(); if (!root_->player_->PlusMoney(price_of_goods)) { return RC::RC_ITEM_FAILED; } DEBUG_CODE( if (price_of_goods == 0 && item_slot.GetItemInfo()->m_wType != eITEMTYPE_WASTE) SUNLOG(eFULL_LOG, _T("[nsSlot::ItemTradingImpl::Sell] ¾ÆÀÌÅÛ(%s)ÆÄ´Â°¡°ÝÀÌ%I64u=0ÀÌ´Ù."), item_info->m_pszName, price_of_goods);); GAMELOG->LogItem_Pos(ITEM_NPC_SELL, root_->player_, &item_slot, price_of_goods, item_slot.GetNum(), slot_type, slot_position, 0, 0); GAMELOG->LogMoney(MONEY_NPC_SELL, root_->player_, price_of_goods); RegisterSaleItem(item_slot); item_slot_container->DeleteSlot(slot_position, NULL); } return RC::RC_ITEM_SUCCESS; } //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // @praram // byNumberOfItemToBuy : m_byDupNumÀ» ³ÑÀ» ¼ö ¾ø´Ù. //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! RC::eITEM_RESULT nsSlot::ItemTradingImpl::Buy( const DWORD shop_list_id, const BYTE shop_tab_index, const BYTE shop_item_index, MSG_CG_ITEM_BUY_ACK* OUT const buy_msg, const DURATYPE buy_quantity) { if (root_->IsRestrictFunction(eFUNCTIONALRESTRICT_BUY_ITEM)) { return RC::RC_ITEM_UNUSABLE_FUNCTION; } if (!root_->ValidState()) { return RC::RC_ITEM_INVALIDSTATE; } if (!root_->ValidContainer(SI_INVENTORY)) { return RC::RC_ITEM_INVALIDSTATE; } if (!root_->player_->GetChaoState().CanUseFuction(CHAO_USE_STORE)) { return RC::RC_ITEM_UNABLE_FUNCTION_FOR_CHAOSTATE; } if (root_->player_->GetBehave() == PLAYER_BEHAVE_UNEXPECTED_WAITING) { return RC::RC_ITEM_INVALIDSTATEOFPLAYER; } SHOPINFO* const shop_info = ShopInfoParser::Instance()->GetShopList(shop_list_id); if (shop_info == NULL) { return RC::RC_ITEM_INVALIDSHOPLISTID; } if (shop_tab_index >= SHOPINFO::_MAX_TAB_NUM || shop_item_index >= SHOPINFO::_MAX_SELLITEM_NUM) { return RC::RC_ITEM_OUTOFSHOPITEMINDEX; } SHOPINFO::SHOP_ITEM* const shop_item = shop_info->GetItemForIndex(shop_tab_index, shop_item_index); if (shop_item == NULL) { return RC::RC_ITEM_OUTOFSHOPITEMINDEX; } const SLOTCODE buy_wanted_item_code = shop_item->m_SellItemCode; //!Àӽð¡°Ý!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! //!Àӽð¡°Ý!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // µ·ÀÌ ÀÖ´ÂÁö üũ const DURATYPE number_of_buy_wanted_item = (buy_quantity > 0) ? buy_quantity : shop_item->m_SellItemNum; SCItemSlot buy_wanted_item_slot; // (f100728.1L) add a making item interface related to the item type information if (nsSlot::ItemTypeChanger::MakeItemSlotByType(&buy_wanted_item_slot, buy_wanted_item_code, number_of_buy_wanted_item, shop_item->item_type_) == false) { return RC::RC_ITEM_INVALIDSTATE; } // const BASE_ITEMINFO* const buy_wanted_item_info = buy_wanted_item_slot.GetItemInfo(); // for client check routine if (buy_wanted_item_info == NULL || buy_wanted_item_info->m_Code == 0) { return RC::RC_ITEM_OUTOFSHOPITEMINDEX; } #ifdef _NA_007031_20140116_CAN_SELL_CASH_ITEM_IN_STORE #else if (buy_wanted_item_info->IsChargeItem()) { return RC::RC_ITEM_CANNOT_DO_THIS_FOR_CHARGEITEM; } #endif //_NA_007031_20140116_CAN_SELL_CASH_ITEM_IN_STORE #ifdef _NA004034_20120102_GUILD_POINT_SYSTEM if (shop_info->GetShopType() == SHOP_TYPE_OF_CURRENCY && shop_info->GetCurrencyItemCode() == CURRENCY_INFO_GUILD_COIN) { GUILDGUID guid = root_->player_->GetGuildGuid(); if (INVALID_GUILDGUID == guid) return RC::RC_ITEM_INVALIDSTATE; GameGuild* game_guild = g_GameGuildManager.FindGuild(guid); if (NULL == game_guild) return RC::RC_ITEM_INVALIDSTATE; // fame_rating_¸¦ ±æµå·¹º§·Î »ç¿ë. if (game_guild->GetGuildGrade() < shop_item->fame_rating_) return RC::RC_ITEM_BUY_ERROR_GUILD_LEVEL; // repute_rating_À» ±æµå°øÇåµµ·Î »ç¿ë PointWalletManager* const pointwallet_manager = root_->player_->GetPointWalletManager(); int guild_point = pointwallet_manager->GetPointWallet(CURRENCY_INFO_DONATION_GUILDCOIN); if (guild_point < shop_item->repute_rating_) return RC::RC_ITEM_BUY_ERROR_GUILD_EXP; } else { HonorManager* honor_manager = root_->player_->GetHonorManager(); if (shop_item->repute_area_ > 0 && shop_item->repute_rating_ > 0) { int repute_rating= \ honor_manager->GetFameReputeGrade(HONOR_POINT_INFO::REPUTE, shop_item->repute_area_); if(repute_rating < shop_item->repute_rating_) { return RC::RC_ITEM_BUY_ERROR_OF_REPUTE; } } if (shop_item->fame_area_ > 0 && shop_item->fame_rating_ > 0) { int fame_rating = \ honor_manager->GetFameReputeGrade(HONOR_POINT_INFO::FAME, shop_item->fame_area_); if(fame_rating < shop_item->fame_rating_) { return RC::RC_ITEM_BUY_ERROR_OF_FAME; } } } #else #ifdef _NA_003027_20111013_HONOR_SYSTEM HonorManager* honor_manager = root_->player_->GetHonorManager(); if(shop_item->repute_area_ > 0 && shop_item->repute_rating_ > 0) { int repute_rating= \ honor_manager->GetFameReputeGrade(HONOR_POINT_INFO::REPUTE, shop_item->repute_area_); if(repute_rating < shop_item->repute_rating_) { return RC::RC_ITEM_BUY_ERROR_OF_REPUTE; } } if(shop_item->fame_area_ > 0 && shop_item->fame_rating_ > 0) { int fame_rating = \ honor_manager->GetFameReputeGrade(HONOR_POINT_INFO::FAME, shop_item->fame_area_); if(fame_rating < shop_item->fame_rating_) { return RC::RC_ITEM_BUY_ERROR_OF_FAME; } } #endif //NA_003027_20111013_HONOR_SYSTEM #endif //_NA004034_20120102_GUILD_POINT_SYSTEM //_NA_000251_20100727_SOCKET_SYSTEM // »óÁ¡¿¡¼­ ÆÄ´Â°ÍµéÀº ±âº»ÀûÀ¸·Î ¼ÒÄÏÀ» »ý¼ºÇÏÁö ¾ÊÁö¸¸ // ¾ÆÀÌÅÛ Å¸ÀÔ Á¤º¸°¡ ¼³Á¤µÇ¾î ÀÖÀ¸¸é ¼ÒÄÏ »ý¼º¿¡ ¿ì¼±ÀûÀ¸·Î »ç¿ëÇÑ´Ù. const nsSlot::ItemRuleInfo& item_rule_info = buy_wanted_item_slot.GetItemRuleInfo(); if (shop_item->item_type_ == NULL && item_rule_info.IsEnableSocket()) { buy_wanted_item_slot.SetSocketIdentifyType(eSOCKET_FAIL_IDENTIFY_PROCESS); } #ifdef _NA_007444_20140722_TIMELIMITITEM_SELL_ON_SHOP buy_wanted_item_slot.SetDateTime(shop_item->timelimit_ * 60); #endif //_NA_007444_20140722_TIMELIMITITEM_SELL_ON_SHOP #ifdef _NA_20110303_ADD_TYPE_OF_NPCSHOP const RC::eITEM_RESULT pay_result = _PayProcessing(shop_tab_index, number_of_buy_wanted_item, buy_wanted_item_slot, buy_msg, shop_info, shop_item); #else //_NA_20110303_ADD_TYPE_OF_NPCSHOP const RC::eITEM_RESULT pay_result = _PayProcessing(shop_tab_index, number_of_buy_wanted_item, buy_wanted_item_slot, buy_msg, shop_info); #endif //_NA_20110303_ADD_TYPE_OF_NPCSHOP return pay_result; } #ifdef _NA_20110303_ADD_TYPE_OF_NPCSHOP //gamelulu_dev_note : ¾ÆÀÌÅÛ ¸Þ´ÏÀú¿¡¼­ npc»óÁ¡ ºÎºÐÀ» ºÐ¸® ÇØ¾ßÇÒ Çʿ伺ÀÌ ÀÖ´Ù. RC::eITEM_RESULT nsSlot::ItemTradingImpl::_PayProcessing( const BYTE shop_tab_index, const DURATYPE number_of_buy_wanted_item, const SCItemSlot buy_wanted_item_slot, MSG_CG_ITEM_BUY_ACK* OUT const buy_msg, SHOPINFO* shop_info, SHOPINFO::SHOP_ITEM* const shop_item) { RC::eITEM_RESULT process_result_value = RC::RC_ITEM_SUCCESS; switch (shop_info->GetShopType()) { case SHOP_TYPE_OF_NARMAL://ÀÏ¹Ý process_result_value = _PayNormalShop(shop_info, shop_tab_index, buy_wanted_item_slot, number_of_buy_wanted_item, buy_msg); break; case SHOP_TYPE_OF_ITEM://¾ÆÀÌÅÛ process_result_value = _PayItemShop(shop_info, shop_item, buy_wanted_item_slot, number_of_buy_wanted_item, buy_msg); break; case SHOP_TYPE_OF_ACCUMULATE://Àû¸³ Æ÷ÀÎÆ® process_result_value = _PayAccumulatePointShop(shop_info, shop_item, buy_wanted_item_slot, number_of_buy_wanted_item, buy_msg); break; #ifdef _NA004034_20120102_POINT_WALLET_SYSTEM case SHOP_TYPE_OF_CURRENCY: { process_result_value = _PayPointWalletShop( \ shop_info, shop_item, buy_wanted_item_slot, number_of_buy_wanted_item, buy_msg); } break; #endif //_NA004034_20120102_POINT_WALLET_SYSTEM default: return RC::RC_ITEM_FAILED; } //_NA_001990_ACSYSTEM_ADD if (process_result_value == RC::RC_ITEM_SUCCESS) { const BASE_ITEMINFO* item_info = buy_wanted_item_slot.GetItemInfo(); if (item_info->m_wACCode) { root_->player_->GetACManager()->ProcessItemObtain( item_info->m_Code, item_info->m_wACCode, item_info->m_byACReferenceID, number_of_buy_wanted_item); } } return process_result_value; } RC::eITEM_RESULT nsSlot::ItemTradingImpl::_PayNormalShop( SHOPINFO* shop_info, const BYTE shop_tab_index, const SCItemSlot buy_wanted_item_slot, const DURATYPE number_of_buy_wanted_item, MSG_CG_ITEM_BUY_ACK* OUT const buy_msg) { MSG_CG_ITEM_BUY_ACK* msg = static_cast(buy_msg); MONEY price_of_goods = buy_wanted_item_slot.GetPriceForBuy() * number_of_buy_wanted_item; ASSERT(price_of_goods > 0); #ifdef _NA_007330_20140620_GUILD_SYSTEM_EXTENSION //»óÁ¡ ±¸¸Å ÇÏÀÓ Áõ°¨ ¾îÆ®¸®ºäÆ® Àû¿ë price_of_goods = root_->player_->GetAttr().GetValueAppliedAttr(price_of_goods, \ eATTR_SHOP_BUY_HEIM_RATIO); #endif // _NA_007330_20140620_GUILD_SYSTEM_EXTENSION //üũ if (root_->player_->GetMoney() < price_of_goods) { return RC::RC_ITEM_HAVENOTMONEY; } //Áö±Þ const RC::eITEM_RESULT pay_result_value = root_->Obtain(buy_wanted_item_slot, number_of_buy_wanted_item, &(msg->m_TotalInfo)); if (pay_result_value != RC::RC_ITEM_SUCCESS) { return pay_result_value; } //»èÁ¦ root_->player_->MinusMoney(price_of_goods); GAMELOG->LogMoney(MONEY_NPC_BUY, root_->player_, price_of_goods); msg->m_Money = root_->player_->GetMoney(); msg->m_ShopType = shop_info->GetShopType(); GAMELOG->LogItem(ITEM_BUY_NPC_SHOP_TO_ADDITIONAL_TYPE_, root_->player_, &buy_wanted_item_slot, number_of_buy_wanted_item, static_cast(price_of_goods),shop_info); //gamelulu_dev_note : ±âÁ¸ ·Î±× Áö¿øÀ» À§ÇØ ³²±ä´Ù. GAMELOG->LogItem(ITEM_NPC_BUY, root_->player_, &buy_wanted_item_slot, price_of_goods, number_of_buy_wanted_item); g_pGameServer->NotifyHeimConsumption(root_->player_->GetCharGuid(), eHEIM_CONSUMPTION_NPC_SHOP, price_of_goods, shop_info->GetLottoAccumRatio(shop_tab_index)); return RC::RC_ITEM_SUCCESS; } RC::eITEM_RESULT nsSlot::ItemTradingImpl::_PayItemShop( SHOPINFO* shop_info, SHOPINFO::SHOP_ITEM* const shop_item, const SCItemSlot buy_wanted_item_slot, const DURATYPE number_of_buy_wanted_item, MSG_CG_ITEM_BUY_ACK* OUT const buy_msg) { MSG_CG_ITEM_BUY_ACK* msg = static_cast(buy_msg); size_t check_price_of_goods = shop_item->item_cost_ * number_of_buy_wanted_item; if (check_price_of_goods > USHRT_MAX) { SUNLOG( eCRITICAL_LOG, __FUNCTION__" : Item price value is over : prive value : %d", check_price_of_goods); check_price_of_goods = USHRT_MAX; } const WORD price_of_goods = static_cast(check_price_of_goods); ASSERT(price_of_goods > 0); //üũ ns_functor::EmptyItemCheck empty_checker(shop_info->GetCurrencyItemCode(), price_of_goods); if (root_->ForeachSlot(SI_INVENTORY, &empty_checker) == false) { return RC::RC_ITEM_IS_SHORT_HAVE_ITEM; } //Áö±Þ const RC::eITEM_RESULT obtain_result_value = root_->Obtain(buy_wanted_item_slot, number_of_buy_wanted_item, &(msg->m_TotalInfo)); if (obtain_result_value != RC::RC_ITEM_SUCCESS) { return obtain_result_value; } //»èÁ¦ MSG_CG_ITEM_LOSE_ACK pay_msg; SLOTCODE currency_item_code = shop_info->GetCurrencyItemCode(); const RC::eITEM_RESULT pay_result_value = root_->DeleteOneKindOfItem(currency_item_code, price_of_goods, &(pay_msg.m_ItemInfo)); if (pay_result_value != RC::RC_ITEM_SUCCESS) { return pay_result_value; } root_->player_->SendPacket(&pay_msg, pay_msg.GetSize()); msg->m_Money = root_->player_->GetMoney(); msg->m_ShopType = shop_info->GetShopType(); GAMELOG->LogItem(ITEM_BUY_NPC_SHOP_TO_ADDITIONAL_TYPE_, root_->player_, &buy_wanted_item_slot, number_of_buy_wanted_item, static_cast(price_of_goods),shop_info); return RC::RC_ITEM_SUCCESS; } RC::eITEM_RESULT nsSlot::ItemTradingImpl::_PayAccumulatePointShop( SHOPINFO* shop_info, SHOPINFO::SHOP_ITEM* const shop_item, const SCItemSlot buy_wanted_item_slot, const DURATYPE number_of_buy_wanted_item, MSG_CG_ITEM_BUY_ACK* OUT const buy_msg) { MSG_CG_ITEM_BUY_ACK* msg = static_cast(buy_msg); #ifdef _NA_008647_20160115_NPCSHOP_CALCULATE_CHANGE WORD price_of_goods = static_cast(shop_item->item_cost_); if(shop_item->m_SellItemNum > 1) { // »ç·Á°í ÇÏ´Â ¼ö·®ÀÌ ±âº» ¹­À½º¸´Ù Ä¿¾ß ÇÑ´Ù. if(number_of_buy_wanted_item < shop_item->m_SellItemNum) { return RC::RC_ITEM_FAILED_TO_EXCHANGE_CURRENCY_ITEM_BY_LIMIT; } // ¹­À½ ¾ÆÀÌÅÛÀÏ °æ¿ì´Â °¡°ÝÀ» ´Ù½Ã ¼³Á¤ÇØ Áà¾ß ÇÑ´Ù. if((number_of_buy_wanted_item % shop_item->m_SellItemNum) != 0) { return RC::RC_ITEM_FAILED_TO_EXCHANGE_CURRENCY_ITEM_BY_LIMIT; } else { price_of_goods *= (number_of_buy_wanted_item / shop_item->m_SellItemNum); } } else { price_of_goods = static_cast(shop_item->item_cost_ * number_of_buy_wanted_item); } #else WORD price_of_goods = static_cast(shop_item->item_cost_ * number_of_buy_wanted_item); #endif //(_NA_008647_20160115_NPCSHOP_CALCULATE_CHANGE) ASSERT(price_of_goods > 0); //üũ if (root_->player_->GetAccumulatePoint()->get_accumulate_point() < price_of_goods) { return RC::RC_ITEM_IS_SHORT_HAVE_ACCUMULATEPOINT; } //Áö±Þ const RC::eITEM_RESULT pay_result_value = root_->Obtain(buy_wanted_item_slot, number_of_buy_wanted_item, &(msg->m_TotalInfo)); if (pay_result_value != RC::RC_ITEM_SUCCESS) { return pay_result_value; } //»èÁ¦ root_->player_->GetAccumulatePoint()->MinusAccumulatePoint(price_of_goods); GAMELOG->LogAccumulatePoint(ACCUM_CONSUMPTION_ROULETTE, root_->player_, price_of_goods, buy_wanted_item_slot.GetItemCode()); msg->m_Money = static_cast(root_->player_->GetAccumulatePoint()->get_accumulate_point()); msg->m_ShopType = shop_info->GetShopType(); GAMELOG->LogItem(ITEM_BUY_NPC_SHOP_TO_ADDITIONAL_TYPE_, root_->player_, &buy_wanted_item_slot, number_of_buy_wanted_item, static_cast(price_of_goods),shop_info); return RC::RC_ITEM_SUCCESS; } #else //_NA_20110303_ADD_TYPE_OF_NPCSHOP RC::eITEM_RESULT nsSlot::ItemTradingImpl::_PayProcessing( const BYTE shop_tab_index, const DURATYPE number_of_buy_wanted_item, const SCItemSlot buy_wanted_item_slot, MSG_CG_ITEM_BUY_ACK* OUT const buy_msg, SHOPINFO* shop_info) { MSG_CG_ITEM_BUY_ACK* msg = static_cast(buy_msg); const MONEY price_of_goods = buy_wanted_item_slot.GetPriceForBuy() * number_of_buy_wanted_item; ASSERT(price_of_goods > 0); if (root_->player_->GetMoney() < price_of_goods) { return RC::RC_ITEM_HAVENOTMONEY; } const RC::eITEM_RESULT obtain_result = root_->Obtain(buy_wanted_item_slot, number_of_buy_wanted_item, &(msg->m_TotalInfo)); if (obtain_result == RC::RC_ITEM_SUCCESS) { root_->player_->MinusMoney(price_of_goods); msg->m_Money = root_->player_->GetMoney(); GAMELOG->LogItem(ITEM_NPC_BUY, root_->player_, &buy_wanted_item_slot, price_of_goods, number_of_buy_wanted_item); GAMELOG->LogMoney(MONEY_NPC_BUY, root_->player_, price_of_goods); g_pGameServer->NotifyHeimConsumption(root_->player_->GetCharGuid(), eHEIM_CONSUMPTION_NPC_SHOP, price_of_goods, shop_info->GetLottoAccumRatio(shop_tab_index)); //_NA_001990_ACSYSTEM_ADD const BASE_ITEMINFO* item_info = buy_wanted_item_slot.GetItemInfo(); if (item_info->m_wACCode) { root_->player_->GetACManager()->ProcessItemObtain( item_info->m_Code, item_info->m_wACCode, item_info->m_byACReferenceID, number_of_buy_wanted_item); } return obtain_result;//success } return obtain_result;//fail } #endif //_NA_20110303_ADD_TYPE_OF_NPCSHOP #ifdef _NA004034_20120102_POINT_WALLET_SYSTEM RC::eITEM_RESULT nsSlot::ItemTradingImpl::_PayPointWalletShop( SHOPINFO* shop_info, SHOPINFO::SHOP_ITEM* const shop_item, const SCItemSlot buy_wanted_item_slot, const DURATYPE number_of_buy_wanted_item, MSG_CG_ITEM_BUY_ACK* OUT const buy_msg) { MSG_CG_ITEM_BUY_ACK* msg = static_cast(buy_msg); DWORD pointwallet_code = shop_info->GetCurrencyItemCode(); DWORD price_of_goods = static_cast(shop_item->item_cost_ * number_of_buy_wanted_item); //1. üũ PointWalletManager* const pointwallet_manager = root_->player_->GetPointWalletManager(); if (pointwallet_manager->GetPointWallet(pointwallet_code) < price_of_goods) { return RC::RC_ITEM_FAILED_TO_BUY_BY_POINT; } //2. Áö±Þ const RC::eITEM_RESULT pay_result_value = \ root_->Obtain(buy_wanted_item_slot, number_of_buy_wanted_item, &msg->m_TotalInfo); if (pay_result_value != RC::RC_ITEM_SUCCESS) { return pay_result_value; } //3. Â÷°¨ DWORD previous_point = pointwallet_manager->GetPointWallet(pointwallet_code); DWORD result_point = pointwallet_manager->ChangeWalletPoint(pointwallet_code, -price_of_goods); msg->m_Money = root_->player_->GetMoney(); msg->m_ShopType = shop_info->GetShopType(); //4. ·Î±× GAMELOG->LogItem(ITEM_BUY_NPC_SHOP_TO_ADDITIONAL_TYPE_, root_->player_, &buy_wanted_item_slot, number_of_buy_wanted_item, static_cast(price_of_goods), shop_info); GAMELOG->LogPointWallet(root_->player_, POINTWALLET_WITHDRAW_BY_BUYING_ITEMS_ON_MARKET, pointwallet_code, previous_point, -price_of_goods, result_point); return RC::RC_ITEM_SUCCESS; } #endif //_NA004034_20120102_POINT_WALLET_SYSTEM //================================================================================================== //================================================================================================== //================================================================================================== #ifdef __NA_001027_20080423_RANDOM_REWARD_EVENT_ RC::eITEM_RESULT nsSlot::ItemTradingImpl::ExchangeRewardItem( SLOTCODE ItemCode, DURATYPE num, INVENTORY_TOTAL_INFO* OUT pTotalInfo) { if (!root_->ValidState()) return RC::RC_ITEM_INVALIDSTATE; // ±³È¯ °¡´ÉÇÑ ¾ÆÀÌÅÛÀÎÁö ½ºÅ©¸³Æ® üũ EXCHANGE_REWARDINFO* pExchangeInfo = \ ExchangeRewardInfoParser::Instance()->GetRewardInfo(ItemCode, num); if (!pExchangeInfo) return RC::RC_ITEM_CANNOT_EXCHANGE_ITEM; // ÃæºÐÇÑ °³¼öÀÇ ¾ÆÀÌÅÛÀÌ ÀÖ´ÂÁö üũ int ExistCount = root_->ExistItem(SI_INVENTORY, ItemCode, num); if (ExistCount < num) return RC::RC_ITEM_CANNOT_DELETE_FOR_SHORT_COUNT; // ¼±Åà ¾ÆÀÌÅÛ ¼±Åà RewardInfo* pRewardInfo = RewardInfoList::Instance()->FindRewardInfo( pExchangeInfo->m_RewardIndex); if (!pRewardInfo) return RC::RC_ITEM_CANNOT_EXCHANGE_ITEM; int SelectableCount = 0; for (int i = 0 ; i < RewardInfo::MAX_DROP_INDEX_NUM ; ++i) { if (pRewardInfo->GetTypeCode(i)) SelectableCount++; } SelectableCount = max(0, SelectableCount - 1); BYTE SelectItemBits = (1 << random(0,SelectableCount)); // º¸»ó ¾ÆÀÌÅÛ È¹µæ RC::eREWARD_RESULT rcResult = g_RewardManager.RewardItem( RewardManager::eREWARD_EXCHANGE_ITEM, pExchangeInfo->m_RewardIndex, SelectItemBits, root_->player_, *pTotalInfo); if (rcResult != RC::RC_REWARD_SUCCESS) return RC::RC_ITEM_ISNOTEMPTYSLOT; // ±³È¯ÇÒ ¾ÆÀÌÅÛ »èÁ¦ MSG_CG_ITEM_LOSE_ACK LoseMsg; RC::eITEM_RESULT rcResult2 = \ root_->DeleteAllKindOfItem(1, &ItemCode, &num, &(LoseMsg.m_ItemInfo)); if (rcResult2 != RC::RC_ITEM_SUCCESS) return rcResult2; root_->player_->SendPacket(&LoseMsg, LoseMsg.GetSize()); return RC::RC_ITEM_SUCCESS; } #endif //================================================================================================== //================================================================================================== //================================================================================================== void nsSlot::ItemTradingImpl::RegisterSaleItem(SCItemSlot& item) { BYTE pos = 0; RepurchaseSlot* pRepurchase = NULL; for (;pos < MAX_REPURCHASE_ITEM_NUM; ++pos) { // ºñ¾îÀÖ´Â ½½·ÔÀ» ã´Â´Ù. pRepurchase = &root_->saled_item_list_[pos]; #ifdef _DEBUG if (!pRepurchase) ASSERT(0); #endif if (!pRepurchase->m_bIsUse) { pRepurchase->m_bIsUse = true; pRepurchase->m_itemSlot = new SCItemSlot; pRepurchase->m_itemSlot->Copy(item); break; } } // ºñ¾îÀÖ´Â ½½·ÔÀÌ ¾øÀ» °æ¿ì if (MAX_REPURCHASE_ITEM_NUM <=pos) { // (CHANGES) (f100802.1L) fix up an unsafe pointer usage case. // a deque event after pop_front has free operation or reuse operation. SCItemSlot* reuse_slot = NULL; ;{ RepurchaseSlot* delete_reserved_repurchase_slot = &root_->saled_item_list_[0]; reuse_slot = delete_reserved_repurchase_slot->m_itemSlot; root_->saled_item_list_.pop_front(); }; ;{ RepurchaseSlot realign_repurchase_slot; realign_repurchase_slot.m_bIsUse = true; reuse_slot = reuse_slot ? reuse_slot : new SCItemSlot; reuse_slot->Copy(item); realign_repurchase_slot.m_itemSlot = reuse_slot; root_->saled_item_list_.push_back(realign_repurchase_slot); }; } } RC::eITEM_RESULT nsSlot::ItemTradingImpl::Repurchase(POSTYPE RepurchasePos, INVENTORY_TOTAL_INFO* pTotalInfo) { if (0 >= root_->saled_item_list_.size() || MAX_REPURCHASE_ITEM_NUM <= RepurchasePos) return RC::RC_ITEM_EMPTYSLOT; ItemManager::SALE_ITEM_DEQ::iterator it(root_->saled_item_list_.begin() + RepurchasePos); RepurchaseSlot pRepurchase = *it; if (pRepurchase.m_bIsUse == false) return RC::RC_ITEM_EMPTYSLOT; SCItemSlot* Slotitem = pRepurchase.m_itemSlot; if (!Slotitem || !Slotitem->GetItemInfo()) return RC::RC_ITEM_INVALIDSTATE; MONEY PriceOfGoods = Slotitem->GetPriceForSell(); if (0 > PriceOfGoods) return RC::RC_ITEM_INVALIDSTATE; if (root_->player_->GetMoney() < PriceOfGoods) return RC::RC_ITEM_HAVENOTMONEY; int itemNum = Slotitem->GetNum(); Slotitem->SetNum(1); RC::eITEM_RESULT rt = root_->Obtain(*Slotitem, itemNum, pTotalInfo); if (rt == RC::RC_ITEM_SUCCESS) { root_->player_->MinusMoney(PriceOfGoods); GAMELOG->LogItem(ITEM_NPC_REPURCHASE, root_->player_, Slotitem, PriceOfGoods, itemNum); GAMELOG->LogMoney(MONEY_NPC_BUY, root_->player_, PriceOfGoods); pRepurchase.m_bIsUse = false; SAFE_DELETE(pRepurchase.m_itemSlot); root_->saled_item_list_.erase(it); root_->saled_item_list_.push_back(pRepurchase); #ifdef _DEBUG //5°³ À¯Áö.. if (MAX_REPURCHASE_ITEM_NUM != root_->saled_item_list_.size()) ASSERT("ÆÇ¸Å¸®½ºÆ® 5°³ Ãʰú.. Á¨Àå"); #endif } return rt; } #ifdef _NA_20100106_REPURCHAS_BUGFIX_2496 void nsSlot::ItemTradingImpl::SerializeRepurchaseItems( REPURCHASITEM_TOTAL_INFO& RepurchasItems, eSERIALIZE eType) { if (eType == SERIALIZE_LOAD) { // f101014.1L, added clear routine in this function RepurchasItems.Clear(); ItemManager::SALE_ITEM_DEQ::iterator iter; for (iter = root_->saled_item_list_.begin(); iter != root_->saled_item_list_.end() && MAX_REPURCHASE_ITEM_NUM > RepurchasItems.m_Count; ++iter) { RepurchaseSlot& slot = *iter; if (slot.m_bIsUse) { slot.m_itemSlot->CopyOut(RepurchasItems.m_Slot[RepurchasItems.m_Count++]); } } } else if (eType == SERIALIZE_STORE) { // f101014.1L, fixed unclear remained data. // NOTE: if fails, it already occur buffer overrun. ASSERT(RepurchasItems.m_Count <= MAX_REPURCHASE_ITEM_NUM); // const int number_of_items = min(RepurchasItems.m_Count, MAX_REPURCHASE_ITEM_NUM); for (int i = 0; i < number_of_items; ++i) { BYTE pos = 0; RepurchaseSlot* pRepurchase = NULL; pRepurchase = &root_->saled_item_list_[i]; if (pRepurchase) { pRepurchase->m_bIsUse = true; pRepurchase->m_itemSlot = new SCItemSlot; pRepurchase->m_itemSlot->Copy(RepurchasItems.m_Slot[i]); } else { ASSERT("Æ÷ÀÎÅͰ¡ ¾øÀ»¼ö°¡ ¾ø´Âµ¥"); } } } else { ASSERT("·Îµùµµ ¾Æ´Ï°í ÀúÀåµµ ¾Æ´Ï°í~ ÀÖÀ»¼ö ¾ø´ÂÀÏ..."); } } #endif //_NA_20100106_REPURCHAS_BUGFIX_2496 void nsSlot::ItemTradingImpl::ClearRepurchasItemList() { ItemManager::SALE_ITEM_DEQ::iterator iter; for (iter = root_->saled_item_list_.begin(); iter != root_->saled_item_list_.end(); ++iter) { RepurchaseSlot& slot = *iter; SAFE_DELETE(slot.m_itemSlot); } root_->saled_item_list_.clear(); } //================================================================================================== //================================================================================================== //==================================================================================================