Files
Sun1602/Server/GameServer/GM/GMHandler_Slot.cpp
T
2022-10-26 12:25:11 +08:00

1494 lines
49 KiB
C++

#include "stdafx.h"
#include "GMCmdManager.h"
//
//
#include <ItemInfoParser.h>
#include <ItemTypeList.h>
#include <SocketSystem/ZardComposeInfoParser.h> //_NA_000251_20100727_SOCKET_SYSTEM
#ifdef _NA_002253_20100811_CUBE_SYSTEM
#include <CubeSystem/CubeSystemParser.h>
#include "ImplementUtil.h"
#endif //
//
#include <SCItemSlot.h>
#include "DropManager.h"
#include "ItemManager.h"
#include "WarehouseSlotContainer.h"
#include "PacketHandler/Handler_CG_ITEM.h"
// Internal utilities
#include "./GMHandler_InterUtils.hxx"
namespace nsGM {
;
static bool ProcessPickUp(DWORD player_key, const GmCmdTokens& cmd_array)
{
GMCmdManager* const gm_manager = GMCmdManager::Instance();
Player* const player = gm_manager->GetGMPlayer(player_key);
GameField* game_field = NULL;
if (player == NULL || (game_field = player->GetField()) == NULL) {
return false;
}
// (CHANGES) skip check routine to extension
/*if (cmd_array.size() != 1)
{
MSG_CG_GM_STRING_CMD_NAK msg_nak;
msg_nak.m_byErrorCode = RC::RC_GM_INVALID_ARGUMENT;
player->SendPacket(&msg_nak, sizeof(msg_nak));
return false;
}*/
const GM_CMD_STRING::size_type number_of_args = cmd_array.size();
bool use_duplicable_slot_mode = false;
if (number_of_args >= 2) {
use_duplicable_slot_mode = (atoi(cmd_array[1].c_str()) != 0);
}
RC::eGM_RESULT gm_result = RC::RC_GM_CMD_SUCCESS;
if (game_field->PickupAllItems(player, use_duplicable_slot_mode) == false) {
gm_result = RC::RC_GM_USER_STATE_INVALID;
}
else {
gm_result = RC::RC_GM_CMD_FAILED;
}
MSG_CG_GM_PICKUP_ACK msg_ack;
msg_ack.m_byErrorCode = gm_result;
player->SendPacket(&msg_ack, sizeof(msg_ack));
return true;
}
//하임 생성
static bool ProcessCreateHime(DWORD player_key, const GmCmdTokens& vecCmd)
{
GMCmdManager* const gm_manager = GMCmdManager::Instance();
Player* pPlayer = gm_manager->GetGMPlayer(player_key);
if (!pPlayer)
return false;
GameField* pField = pPlayer->GetField();
if (!pField)
return false;
if (vecCmd.size() != 2) //인자 조건이 맞지 않습니다.
{
MSG_CG_GM_STRING_CMD_NAK NakMsg;
NakMsg.m_byErrorCode = RC::RC_GM_INVALID_ARGUMENT; // 인자가 맞지 않습니다.
pPlayer->SendPacket(&NakMsg, sizeof(NakMsg));
return false;
}
int nMoney = atoi(vecCmd[1].c_str());
if (nMoney > GM_MAX_CREATE_MONEY || nMoney <= 0)
{
MSG_CG_GM_STRING_CMD_NAK NakMsg;
NakMsg.m_byErrorCode = RC::RC_GM_NOTEXIST_USER; // USER가 존재하지 않습니다.
pPlayer->SendPacket(&NakMsg, sizeof(NakMsg));
return false;
}
// 떨어뜨릴 위치를 찾는다.
WzVector vDropPos = pPlayer->GetRandomPosInAround(2);
// 돈을 떨어뜨린다.
MONEY money = (MONEY)nMoney;
if (false == g_DropManager.DropMoneyToField(pField,&vDropPos,NULL,0,money))
{
MSG_CG_GM_STRING_CMD_NAK NakMsg;
NakMsg.m_byErrorCode = RC::RC_GM_NOTEXIST_USER; // 하임 생성에 실폐하였습니다.
pPlayer->SendPacket(&NakMsg, sizeof(NakMsg));
return false;
}
GAMELOG->WriteCreateHeim(pPlayer, money);
return true;
}
// 인첸트 아이템 생성
static bool ProcessCreateEnchantItem(DWORD player_key, const GmCmdTokens& vecCmd)
{
GMCmdManager* const gm_manager = GMCmdManager::Instance();
Player* pPlayer = gm_manager->GetGMPlayer(player_key);
if (!pPlayer)
return false;
//인자개수 체크
if (vecCmd.size() != 4)
{
MSG_CG_GM_STRING_CMD_NAK NakMsg;
NakMsg.m_byErrorCode = RC::RC_GM_INVALID_ARGUMENT; // 인자가 맞지 않습니다.
pPlayer->SendPacket(&NakMsg, sizeof(NakMsg));
return false;
}
GameField* pField = pPlayer->GetField();
if (!pField)
return false;
int nItemCode = atoi(vecCmd[1].c_str());
int nItemCount = atoi(vecCmd[2].c_str());
int nItemLevel = atoi(vecCmd[3].c_str());
if (nItemCount > GM_MAX_CREATE_ITEM_NUM || nItemCount <= 0)
{
MSG_CG_GM_STRING_CMD_NAK NakMsg;
NakMsg.m_byErrorCode = RC::RC_GM_INVALID_ARGUMENT; // 인자가 맞지 않습니다.
pPlayer->SendPacket(&NakMsg, sizeof(NakMsg));
return false;
}
if (!ItemInfoParser::Instance()->GetItemInfo(nItemCode))
{
MSG_CG_GM_STRING_CMD_NAK NakMsg;
NakMsg.m_byErrorCode = RC::RC_GM_INVALID_ARGUMENT; // 인자가 맞지 않습니다.
pPlayer->SendPacket(&NakMsg, sizeof(NakMsg));
return false;
}
//인첸트 아이템 레벨 체크
if (nItemLevel < 0 || nItemLevel > MAX_ENCHANT_GRADE)
{
MSG_CG_GM_STRING_CMD_NAK NakMsg;
NakMsg.m_byErrorCode = RC::RC_GM_INVALID_ARGUMENT; // 인자가 맞지 않습니다.
pPlayer->SendPacket(&NakMsg, sizeof(NakMsg));
return false;
}
// 개수만큼 인첸트 아이템을 필드에 떨어뜨린다.
for (int i = 0; i < nItemCount; ++i)
{
WzVector vDropPos = pPlayer->GetRandomPosInAround(2);
SCItemSlot slot;
slot.SetSerial(TEMP_DBSERIAL_VALUE);
slot.SetCode(nItemCode);
slot.SetEnchant(nItemLevel);
g_DropManager.DropItemToField(pField, &vDropPos, NULL, 0, slot);
}
return true;
}
static bool ProcessCreateFateItem(DWORD player_key, const GmCmdTokens& vecCmd)
{
SCItemSlot itemSlot;
itemSlot.SetSerial(TEMP_DBSERIAL_VALUE);
GMCmdManager* const gm_manager = GMCmdManager::Instance();
Player* pPlayer = gm_manager->GetGMPlayer(player_key);
if (!pPlayer)
return false;
const int kMaxNumberOfArgs = 7;
//인자개수 체크
int nArgSize = (int)vecCmd.size();
if (nArgSize < 3 || nArgSize > kMaxNumberOfArgs)
{
MSG_CG_GM_STRING_CMD_NAK NakMsg;
NakMsg.m_byErrorCode = RC::RC_GM_INVALID_ARGUMENT; // 인자가 맞지 않습니다.
pPlayer->SendPacket(&NakMsg, sizeof(NakMsg));
return false;
}
GameField* pField = pPlayer->GetField();
if (!pField)
return false;
//아이템코드 체크
int nItemCode = atoi(vecCmd[1].c_str());
BASE_ITEMINFO* pItemInfo = ItemInfoParser::Instance()->GetItemInfo(nItemCode);
if (!pItemInfo)
{
MSG_CG_GM_STRING_CMD_NAK NakMsg;
NakMsg.m_byErrorCode = RC::RC_GM_INVALID_ARGUMENT; // 인자가 맞지 않습니다.
pPlayer->SendPacket(&NakMsg, sizeof(NakMsg));
return false;
}
else
itemSlot.SetCode(nItemCode);
//아이템수량 체크
int nItemCount = atoi(vecCmd[2].c_str());
if (nItemCount <= 0 || nItemCount > GM_MAX_CREATE_ITEM_NUM)
{
MSG_CG_GM_STRING_CMD_NAK NakMsg;
NakMsg.m_byErrorCode = RC::RC_GM_INVALID_ARGUMENT; // 인자가 맞지 않습니다.
pPlayer->SendPacket(&NakMsg, sizeof(NakMsg));
return false;
}
// 내구도 등급
int DuraRatio = 0;
if (nArgSize > 3)
{
DuraRatio = atoi(vecCmd[3].c_str());
if (DuraRatio <=0 || DuraRatio > MAX_FATE_DURA_RATIO_COUNT)
{
MSG_CG_GM_STRING_CMD_NAK NakMsg;
NakMsg.m_byErrorCode = RC::RC_GM_NOT_MATCH_FATE_RATE;
pPlayer->SendPacket(&NakMsg, sizeof(NakMsg));
return false;
}
//명령어는 1~x 배열은 0~x이므로
DuraRatio--;
}
else
{
DuraRatio = random(0, MAX_FATE_DURA_RATIO_COUNT-1);
}
// 방어/뎀 등급
int AtkDefRatio = 0;
if (nArgSize > 4)
{
AtkDefRatio = atoi(vecCmd[4].c_str());
if (AtkDefRatio <=0 || AtkDefRatio > MAX_FATE_ATK_DEF_RATIO_COUNT)
{
MSG_CG_GM_STRING_CMD_NAK NakMsg;
NakMsg.m_byErrorCode = RC::RC_GM_NOT_MATCH_FATE_RATE; // 없는 리미티드 인덱스
pPlayer->SendPacket(&NakMsg, sizeof(NakMsg));
return false;
}
//명령어는 1~x 배열은 0~x이므로
AtkDefRatio--;
}
else
{
AtkDefRatio = random(0, MAX_FATE_ATK_DEF_RATIO_COUNT-1);
}
//기간 등급
// (f100716.1L) changes a period value rule to support expiriation item test
bool use_period_ratio = true;
uint16_t period_second = 60 * 60;
int PeriodRatio = 0;
if (nArgSize > 5)
{
PeriodRatio = atoi(vecCmd[5].c_str());
if (PeriodRatio < 0 || PeriodRatio > MAX_FATE_USING_TIME_RATIO_COUNT)
{
if(PeriodRatio == 4) // 10초(기간만료 테스트용)
{
use_period_ratio = false;
period_second = 10;
}
else
{
MSG_CG_GM_STRING_CMD_NAK NakMsg;
NakMsg.m_byErrorCode = RC::RC_GM_NOT_MATCH_FATE_RATE; // 없는 리미티드 인덱스
pPlayer->SendPacket(&NakMsg, sizeof(NakMsg));
return false;
}
}
if (PeriodRatio == 0) {
use_period_ratio = false;
}
PeriodRatio--;
}
else
{
PeriodRatio = random(0, MAX_FATE_USING_TIME_RATIO_COUNT-1);
}
sFATE_ITEM_INFO* pFateItemInfo = FateItemInfoParser::Instance()->GetFateItemInfoByRefItemCode(nItemCode);
if (pFateItemInfo == NULL)
{
MSG_CG_GM_STRING_CMD_NAK NakMsg;
NakMsg.m_byErrorCode = RC::RC_GM_CANNOT_FIND_FATE_INDEX; // 인자가 맞지 않습니다.
pPlayer->SendPacket(&NakMsg, sizeof(NakMsg));
return false;
}
INT iRandomValue = 0;
iRandomValue = random(pFateItemInfo->m_wDura_Min[DuraRatio], pFateItemInfo->m_wDura_Max[DuraRatio]);
itemSlot.SetFateDuraMax((WORD)(pItemInfo->m_Dura * (float)iRandomValue / 100.0f));
itemSlot.SetDura(itemSlot.GetMaxDura());
iRandomValue = random(pFateItemInfo->m_wAtkDef_Min[AtkDefRatio], pFateItemInfo->m_wAtkDef_Max[AtkDefRatio]);
itemSlot.SetFateAtkDefRatio(iRandomValue);
// (f100716.1L) changes a period value rule to support expiriation item test
if (use_period_ratio)
{
DWORD period = pFateItemInfo->m_dwUsingTimeValue[PeriodRatio];
itemSlot.SetDateTime(period * 24 * 60 * 60);
itemSlot.SetFatePeriod(static_cast<WORD>(period));
}
else
{
itemSlot.SetDateTime(period_second);
itemSlot.SetFatePeriod(period_second);
}
itemSlot.SetFateIdentify(true);
if (nArgSize > 6)
{
int item_type = atoi(vecCmd[6].c_str());
nsSlot::ItemTypeChanger::ChangeItemByType(&itemSlot, item_type);
}
// 개수만큼 인첸트 아이템을 필드에 떨어뜨린다.
int nFailCount = 0;
for (int i = 0; i < nItemCount; ++i)
{
WzVector vDropPos = pPlayer->GetRandomPosInAround(2);
if (false == g_DropManager.DropItemToField(pField,&vDropPos,NULL,0,itemSlot))
++nFailCount;
}
GAMELOG->WriteCreateItem(pPlayer, nItemCode, nItemCount-nFailCount);
return true;
}
//생성
//
static bool ProcessCreateItemEx(DWORD player_key, const GmCmdTokens& cmd_list)
{
// GM 명령어 형식 : make 키워드 다음에 아래 순서대로 입력
// 예제 : make 1001 1 0 0 0 1
enum GMCmdIndex
{
kItemCode = 1, // 아이템 코드
kNumberOfItem = 2, // 아이템 개수
kEnableOverlapped = 3, // 겹치기 여부(아니오:0) (생략가능)
kItemType = 4, kDeprecatedItemGrade = kItemType, // (생략가능)
kEnchantLevel = 5, // 강화 수준 (생략가능)
// _NA_000251_20100727_SOCKET_SYSTEM 기준 소켓 개수 또는 랭크(삭제예정) (생략가능)
kNumberOfSocket = 6, kDeprecatedRank = kNumberOfSocket,
// CHANGES: f110327.1L
#ifdef _NA_008124_20150313_AWAKENING_SYSTEM
kAwakeningGrade = 7,
kTimerType = 8,
#else
kTimerType = 7,
#endif // _NA_008124_20150313_AWAKENING_SYSTEM
// upperbound
kGmItemCmdArgCounts
};
// @history:
// - 100523|waverix|code arrangement with the item_type controller for the item customizing|
// |changes an overlapped item packaging logic|Sample='make 4001 1000 1'
GMCmdManager* const gm_manager = GMCmdManager::Instance();
Player* const player = gm_manager->GetGMPlayer(player_key);
if (player == NULL) {
return false;
}
//
GameField* const game_field = player->GetField();
if (game_field == NULL) {
return false;
}
//
struct ErrorHandler {
ErrorHandler(Player* player)
: player_(player),
gm_result(RC::RC_GM_CMD_SUCCESS)
{}
~ErrorHandler() {
if (gm_result == RC::RC_GM_CMD_SUCCESS) {
return;
}
MSG_CG_GM_STRING_CMD_NAK msg_nak;
msg_nak.m_byErrorCode = static_cast<BYTE>(gm_result);
player_->SendPacket(&msg_nak, sizeof(msg_nak));
}
Player* player_;
RC::eGM_RESULT gm_result;
} gm_parse_error(player);
// #rule : check number of arguments
const GM_CMD_STRING::difference_type number_of_args = cmd_list.size();
if (number_of_args <= kNumberOfItem || number_of_args > kGmItemCmdArgCounts) {
gm_parse_error.gm_result = RC::RC_GM_INVALID_ARGUMENT;
return false;
};
//
SCItemSlot item_slot;
item_slot.SetSerial(TEMP_DBSERIAL_VALUE);
// #rule : check the making item code
CODETYPE item_code4 = atoi(cmd_list[kItemCode].c_str());
const BASE_ITEMINFO* const item_info = ItemInfoParser::Instance()->GetItemInfo(item_code4);
if (item_info == NULL) {
gm_parse_error.gm_result = RC::RC_GM_INVALID_ARGUMENT;
return false;
}
const SLOTCODE item_code = static_cast<SLOTCODE>(item_code4);
item_slot.SetCode(item_code);
//
const nsSlot::ItemRuleInfo& item_rule_info = item_slot.GetItemRuleInfo();
if (item_rule_info.is_valid_item == false) {
gm_parse_error.gm_result = RC::RC_GM_INVALID_ARGUMENT;
return false;
}
#if SUN_CODE_BACKUP
// #rule : the default time expiration information
switch (item_info->m_ChargeSubType)
{
case eCHARGE_SUB_FIXED_AMOUNT:
case eCHARGE_SUB_FIXED_AMOUNT_EX:
case eCHARGE_SUB_FIXED_QUANTITY:
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:
// 60분 적용
item_slot.SetDateTime(60 * 60);
break;
}
#endif
// #rule : check number of items
const int number_of_items = atoi(cmd_list[kNumberOfItem].c_str());
if (number_of_items <= 0 || number_of_items > GM_MAX_CREATE_ITEM_NUM) {
gm_parse_error.gm_result = RC::RC_GM_INVALID_ARGUMENT;
return false;
}
// -----------------------------
// configure variable arguments
// #rule : make the package item if a item can overlapped.
bool need_packaging = (number_of_args > kEnableOverlapped) ?
(atoi(cmd_list[kEnableOverlapped].c_str()) != 0) : false;
const bool enable_overlapped = item_slot.IsOverlap() != false;
if (need_packaging) {
need_packaging = enable_overlapped;
}
//
int item_type = nsSlot::ItemTypeChanger::Default;
if (number_of_args > kItemType) {
item_type = atoi(cmd_list[kItemType].c_str());
}
if (enable_overlapped == false) {
nsSlot::ItemTypeChanger::ChangeItemByType(&item_slot, item_type);
}
if (enable_overlapped == false && item_rule_info.IsEnableEnchant())
{
int enchant_level = 0; //인첸트등급 기본 0
if (number_of_args > kEnchantLevel) //인첸트정보가 포함되어 있으면..
{
enchant_level = atoi(cmd_list[kEnchantLevel].c_str()); //인첸트 등급
//인첸트 아이템 레벨 체크
if (enchant_level < 0 || enchant_level > MAX_ENCHANT_GRADE) {
gm_parse_error.gm_result = RC::RC_GM_INVALID_ARGUMENT;
return false;
}
item_slot.SetEnchant(static_cast<BYTE>(enchant_level));
}
};
//_NA_000251_20100727_SOCKET_SYSTEM
// 소켓을 생성할 수 있는 아이템이면 소켓을 입력한 개수만큼 생성한다.
// 입력하지 않으면 원래 규칙대로 램덤하게 생성된다.
if (number_of_args > kNumberOfSocket)
{
if (enable_overlapped == false && item_rule_info.IsEnableSocket())
{
const int num_of_socket = atoi(cmd_list[kNumberOfSocket].c_str());
if (num_of_socket < 0 || num_of_socket > SOCKET_MAX)
{
gm_parse_error.gm_result = RC::RC_GM_INVALID_ARGUMENT;
return false;
}
if (num_of_socket == 0)
{
// 개수에 0을 입력하면 소켓 미확인 상태로 생성한다.
item_slot.SetSocketIdentifyType(eSOCKET_UNIDENTIFIED_ITEM);
}
else
{
item_slot.SetSocketNum(static_cast<BYTE>(num_of_socket));
item_slot.SetSocketIdentifyType(eSOCKET_IDENTIFIED_ITEM);
}
}
}
#ifdef _NA_008124_20150313_AWAKENING_SYSTEM
if (number_of_args > kAwakeningGrade)
{
int awakening = atoi(cmd_list[kAwakeningGrade].c_str());
if (awakening < 0 || awakening > MAX_AWAKENING_GRADE)
{
gm_parse_error.gm_result = RC::RC_GM_INVALID_ARGUMENT;
return false;
}
item_slot.SetAwakening(awakening);
}
#endif // _NA_008124_20150313_AWAKENING_SYSTEM
#if SUN_CODE_RENEWAL
// #rule : the default time expiration information
// CHANGES: f110327.1L, changes charge_sub_type access field
// to support various making item with timer
DWORD timeout_interval = 60 * 60; // 1 hour
//
if (number_of_args > kTimerType)
{
int making_timeout = atoi(cmd_list[kTimerType].c_str());
#ifdef _NA_008124_20150313_AWAKENING_SYSTEM
if (making_timeout != 0)
{
if (making_timeout < 0 || (item_slot.ChangeItemToUsingTimer() == false)) {
gm_parse_error.gm_result = RC::RC_GM_INVALID_ARGUMENT;
return false;
};
timeout_interval = making_timeout;
}
#else
if (making_timeout < 0 || (item_slot.ChangeItemToUsingTimer() == false)) {
gm_parse_error.gm_result = RC::RC_GM_INVALID_ARGUMENT;
return false;
};
if (making_timeout != 0) {
timeout_interval = making_timeout;
};
#endif // _NA_008124_20150313_AWAKENING_SYSTEM
}
switch (item_rule_info.charge_sub_type)
{
case eCHARGE_SUB_FIXED_AMOUNT:
case eCHARGE_SUB_FIXED_AMOUNT_EX:
case eCHARGE_SUB_FIXED_QUANTITY:
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:
// 60분 적용
item_slot.SetDateTime(timeout_interval);
break;
}
#endif
if (need_packaging)
{
const DURATYPE max_contains_of_items = item_slot.GetMaxNum();
item_slot.SetNum(max_contains_of_items);
int remains = number_of_items;
for (; remains >= max_contains_of_items; remains -= max_contains_of_items)
{
const WzVector* drop_pos = &player->GetRandomPosInAround(2);
if (g_DropManager.DropItemToField(game_field, drop_pos, 0, 0, item_slot) == false) {
continue;
}
GAMELOG->WriteCreateItem(player, item_code, max_contains_of_items);
}
if (remains)
{
item_slot.SetNum(static_cast<DURATYPE>(remains));
const WzVector* drop_pos = &player->GetRandomPosInAround(2);
if (g_DropManager.DropItemToField(game_field, drop_pos, 0, 0, item_slot)) {
GAMELOG->WriteCreateItem(player, item_code, static_cast<DURATYPE>(remains));
}
}
}
else
{
for (int loop = number_of_items; loop; --loop)
{
const WzVector* drop_pos = &player->GetRandomPosInAround(2);
if (g_DropManager.DropItemToField(game_field, drop_pos, 0, 0, item_slot)) {
GAMELOG->WriteCreateItem(player, item_code, 1);
}
}
}
return true;
}
static bool ProcessCreateLimitedItem(DWORD player_key, const GmCmdTokens& cmd_list)
{
// 형식(한글) : 리미티드생성 [아이템 코드] [리미티드 인덱스] [수량] (디바인 여부 0|1) (인챈트 수준) (랭크) (내구도)
// 형식(영문) : createlimited [item code] [limited index] [quantity] (divine flag 0|1) (enchant level) (rank) (durability)
enum CmdIndex
{
kItemCode = 1, // 아이템 코드
KLimitedIndex = 2, // 리미티드 인덱스
kQuantity = 3, // 수량
kDivineFlag = 4, // 디바인 여부
kEnchantLevel = 5, // 인첸트 수준
// _NA_000251_20100727_SOCKET_SYSTEM 기준 소켓 개수 또는 랭크(삭제예정)
kNumberOfSocket = 6, kDeprecatedRank = kNumberOfSocket,
kDurability = 7, // 내구도
kMaxNumberOfCmd
};
GMCmdManager* const gm_manager = GMCmdManager::Instance();
Player* const gm = gm_manager->GetGMPlayer(player_key);
if (gm == NULL)
{
return false;
}
GameField* const field = gm->GetField();
if (field == NULL)
{
return false;
}
struct ErrorHandler {
ErrorHandler(Player* player)
: player_(player),
gm_result(RC::RC_GM_CMD_SUCCESS)
{}
~ErrorHandler() {
if (gm_result == RC::RC_GM_CMD_SUCCESS) {
return;
}
MSG_CG_GM_STRING_CMD_NAK msg_nak;
msg_nak.m_byErrorCode = static_cast<BYTE>(gm_result);
player_->SendPacket(&msg_nak, sizeof(msg_nak));
}
Player* player_;
RC::eGM_RESULT gm_result;
} gm_parse_error(gm);
const int cmd_size = cmd_list.size();
if (cmd_size < 4 || cmd_size > kMaxNumberOfCmd)
{
gm_parse_error.gm_result = RC::RC_GM_INVALID_ARGUMENT;
return false;
}
// 1. 아이템 코드
const CODETYPE item_code = atoi(cmd_list[kItemCode].c_str());
BASE_ITEMINFO* item_info = ItemInfoParser::Instance()->GetItemInfo(item_code);
if (item_info == NULL)
{
gm_parse_error.gm_result = RC::RC_GM_INVALID_ARGUMENT;
return false;
}
SCItemSlot drop_item;
drop_item.SetSerial(TEMP_DBSERIAL_VALUE);
drop_item.SetCode(static_cast<SLOTCODE>(item_code));
// 2. 리미티드 인덱스
const int limited_index = atoi(cmd_list[KLimitedIndex].c_str());
if (LimitedItemInfoParser::Instance()->GetLimitedItemInfo(limited_index) == NULL)
{
gm_parse_error.gm_result = RC::RC_GM_NOT_EXIST_LIMITED_INDEX;
return false;
}
drop_item.SetLimitedIndex(limited_index);
// 3. 수량
const int quantity = atoi(cmd_list[kQuantity].c_str());
if (quantity <= 0 || quantity > GM_MAX_CREATE_ITEM_NUM)
{
gm_parse_error.gm_result = RC::RC_GM_INVALID_ARGUMENT;
return false;
}
// 4. 디바인 여부
if (cmd_size > kDivineFlag)
{
const int divine_flag = atoi(cmd_list[kDivineFlag].c_str());
if (divine_flag < 0 || divine_flag > MAX_ITEM_GRADE)
{
gm_parse_error.gm_result = RC::RC_GM_INVALID_ARGUMENT;
return false;
}
drop_item.SetSet(static_cast<BYTE>(divine_flag));
}
// 5. 인첸트 레벨
if (cmd_size > kEnchantLevel)
{
const int enchant_level = atoi(cmd_list[kEnchantLevel].c_str());
if (enchant_level < 0 || enchant_level > MAX_ENCHANT_GRADE)
{
gm_parse_error.gm_result = RC::RC_GM_INVALID_ARGUMENT;
return false;
}
drop_item.SetEnchant(enchant_level);
}
// 6. 소켓 개수 / 랭크
// _NA_000251_20100727_SOCKET_SYSTEM
if (cmd_size > kNumberOfSocket)
{
const int num_of_socket = atoi(cmd_list[kNumberOfSocket].c_str());
if (num_of_socket < 0 || num_of_socket > SOCKET_MAX)
{
gm_parse_error.gm_result = RC::RC_GM_INVALID_ARGUMENT;
return false;
}
if (num_of_socket == 0)
{
drop_item.SetSocketIdentifyType(eSOCKET_UNIDENTIFIED_ITEM);
}
else
{
drop_item.SetSocketNum(static_cast<BYTE>(num_of_socket));
drop_item.SetSocketIdentifyType(eSOCKET_IDENTIFIED_ITEM);
}
}
// 7. 내구도
if (cmd_size > kDurability)
{
drop_item.SetDura(atoi(cmd_list[kDurability].c_str()));
}
int fail_count = 0;
for (int i = 0; i < quantity; ++i)
{
const WzVector drop_pos = gm->GetRandomPosInAround(2);
if (g_DropManager.DropItemToField(field, &drop_pos, NULL, 0, drop_item) == false)
{
++fail_count;
}
}
GAMELOG->WriteCreateItem(gm, static_cast<SLOTCODE>(item_code), quantity-fail_count);
return true;
}
static bool ProcessExItem(DWORD player_key, const GmCmdTokens& vecCmd)
{
ASSERT(!"Function not implementation");
return false;
}
static bool ProcessRemovalItem(DWORD player_key, const GmCmdTokens& vecCmd)
{
GMCmdManager* const gm_manager = GMCmdManager::Instance();
Player* pPlayer = gm_manager->GetGMPlayer(player_key);
if (!pPlayer)
return false;
if (vecCmd.size() != 1) //인자 조건이 맞지 않습니다.
{
MSG_CG_GM_STRING_CMD_NAK NakMsg;
NakMsg.m_byErrorCode = RC::RC_GM_INVALID_ARGUMENT; // 인자가 맞지 않습니다.
pPlayer->SendPacket(&NakMsg, sizeof(NakMsg));
return false;
}
GameField* pField = pPlayer->GetField();
if (!pField)
return false;
// 반경 30m 내의 아이템들을 삭제한다.
pField->KillAllItem(pPlayer, 30);
GAMELOG->WriteRemovalItem(pPlayer);
return true;
}
static bool ProcessRemoveInven(DWORD player_key, const GmCmdTokens& vecCmd)
{
GMCmdManager* const gm_manager = GMCmdManager::Instance();
Player* pPlayer = gm_manager->GetGMPlayer(player_key);
if (!pPlayer)
return false;
//인자개수 체크
int nArgSize = (int)vecCmd.size();
if (nArgSize != 1)
{
MSG_CG_GM_STRING_CMD_NAK NakMsg;
NakMsg.m_byErrorCode = RC::RC_GM_INVALID_ARGUMENT; // 인자가 맞지 않습니다.
pPlayer->SendPacket(&NakMsg, sizeof(NakMsg));
return false;
}
//.//
MSG_CG_ITEM_LOSE_ACK loseMsg;
if (false == pPlayer->GetItemManager()->DeleteAllInvenItem(&loseMsg.m_ItemInfo))
{
MSG_CG_GM_STRING_CMD_NAK NakMsg;
NakMsg.m_byErrorCode = RC::RC_GM_INVALID_ARGUMENT; // 인자가 맞지 않습니다.
pPlayer->SendPacket(&NakMsg, sizeof(NakMsg));
return false;
}
pPlayer->SendPacket(&loseMsg, loseMsg.GetSize());
return true;
}
//내구도 [내구도] [아이템위치]
static bool ProcessStrengthCmd(DWORD player_key, const GmCmdTokens& vecCmd)
{
GMCmdManager* const gm_manager = GMCmdManager::Instance();
Player* pPlayer = gm_manager->GetGMPlayer(player_key);
if (!pPlayer)
return false;
//인자개수 체크
INT nArgSize = (INT)vecCmd.size();
CHKSendErr(1 > nArgSize , MSG_CG_GM_STRING_CMD_NAK, RC::RC_GM_INVALID_ARGUMENT, pPlayer);
//.//
INT Dura = 1;
eEQUIPCONTAINER_POS eEquipcontainerPos = eEQUIPCONTAINER_WEAPON;
if (nArgSize > 1)
Dura = atoi(vecCmd[1].c_str());
if (nArgSize > 2)
eEquipcontainerPos = (eEQUIPCONTAINER_POS)atoi(vecCmd[2].c_str());
if (nsSlot::DurabilityImpl* const impl = pPlayer->GetItemManager()->GetDurabilityImpl()) {
impl->ChangeDurabilityForGM(eEquipcontainerPos, Dura);
};
return true;
}
// 하임제거 [인벤토리하임셋팅값]
static bool ProcessRemoveHimeCmd(DWORD player_key, const GmCmdTokens& vecCmd)
{
GMCmdManager* const gm_manager = GMCmdManager::Instance();
Player* pPlayer = gm_manager->GetGMPlayer(player_key);
if (!pPlayer)
return false;
//인자개수 체크
INT nArgSize = (INT)vecCmd.size();
CHKSendErr(1 > nArgSize , MSG_CG_GM_STRING_CMD_NAK, RC::RC_GM_INVALID_ARGUMENT, pPlayer);
MONEY InventoryMoney = 0;
if (nArgSize > 1)
InventoryMoney = (MONEY)atoi(vecCmd[1].c_str());
//.//
pPlayer->MinusMoney(pPlayer->GetMoney());
pPlayer->PlusMoney(InventoryMoney);
//.//
MSG_CG_WAREHOUSE_MONEY_ACK msg;
msg.m_InventoryMoney = pPlayer->GetMoney();
msg.m_WarehouseMoney = pPlayer->GetWarehouseContainer()->GetCurMoney();
pPlayer->SendPacket(&msg, sizeof(msg));
//.//
if (InventoryMoney)
GAMELOG->WriteCreateHeim(pPlayer, InventoryMoney);
return true;
}
// //인챈트 [인챈수] [인벤위치]
static bool ProcessEnchandCmd(DWORD player_key, const GmCmdTokens& vecCmd)
{
GMCmdManager* const gm_manager = GMCmdManager::Instance();
Player* pPlayer = gm_manager->GetGMPlayer(player_key);
if (!pPlayer)
return false;
//인자개수 체크
INT nArgSize = (INT)vecCmd.size();
CHKSendErr(1 > nArgSize , MSG_CG_GM_STRING_CMD_NAK, RC::RC_GM_INVALID_ARGUMENT, pPlayer);
int nEnchant = 1;
POSTYPE TargetPos = 0;
if (nArgSize > 1)
nEnchant = atoi(vecCmd[1].c_str());
if (nArgSize > 2)
TargetPos = (POSTYPE)atoi(vecCmd[2].c_str());
SCSlotContainer * pInventory = pPlayer->GetItemManager()->GetItemSlotContainer(SI_INVENTORY);
SCItemSlot & rTargetSlot = (SCItemSlot &)pInventory->GetSlot(TargetPos);
nEnchant = rTargetSlot.GetEnchant() + nEnchant;
if (nEnchant < 0 ||
nEnchant > MAX_ENCHANT_GRADE)
return false;
//(lst1024)(080918)(2447)인챈트시 내구도를 다시 셋팅 해준다.
rTargetSlot.SetEnchantUpdateDura(nEnchant);
pPlayer->GetItemManager()->SendItemChange(rTargetSlot);
return true;
}
static bool ProcessComposition(DWORD player_key, const GmCmdTokens& gm_cmd_arguments)
{
GMCmdManager* const gm_manager = GMCmdManager::Instance();
Player* const gm = gm_manager->GetGMPlayer(player_key);
if (!util::internal::scoped_check_input_in_gm(
gm,
gm_cmd_arguments,
2,
MSG_CG_ITEM_COMPOSE_OR_DECOMPOSE_SYN::kMaxMaterialSize + 1,
false))
{
return false;
}
// GM 커맨드 형식 : composition 키워드 다음에 아래 순서대로 입력
enum GMCmdIndex
{
kRequestType = 1, // 요청종류(쟈드:1, 큐브:2)
kIsComposition = 2, // 합성여부(합성:1, 분해:2)
kReservedCode = 3, // 예약코드(쟈드합성일때만 첨가제 위치, 그 외는 0)
kUsingItemPosition = 4, // 아이템을 사용해서 요청했다면 아이템 위치
kMaterialPosition = 5 // 재료 위치
};
// 요청 종류를 얻는다.
int request_type = 0;
util::internal::scoped_string_to_number(gm_cmd_arguments[kRequestType], request_type);
if (request_type != MSG_CG_ITEM_COMPOSE_OR_DECOMPOSE_SYN::kZardRequest &&
request_type != MSG_CG_ITEM_COMPOSE_OR_DECOMPOSE_SYN::kCubeRequest)
{
return false;
}
// 합성 분해 여부를 얻는다.
int is_composition = 0;
util::internal::scoped_string_to_number(gm_cmd_arguments[kIsComposition], is_composition);
if (is_composition != 1 && is_composition != 2)
{
return false;
}
// 예약코드를 얻는다.
MSG_CG_ITEM_COMPOSE_OR_DECOMPOSE_SYN::ReservedCode reserved_code = 0;
util::internal::scoped_string_to_number(gm_cmd_arguments[kReservedCode], reserved_code);
// 사용 아이템 위치를 얻는다.
POSTYPE using_item_position = 0;
util::internal::scoped_string_to_number(gm_cmd_arguments[kUsingItemPosition], using_item_position);
// 사용자가 입력한 재료 개수를 얻는다.
const int user_inputed_material_size = gm_cmd_arguments.size() - kMaterialPosition;
if (user_inputed_material_size < 1)
{
return false;
}
// 인벤토리를 얻는다.
ItemManager* const item_manager = gm->GetItemManager();
if (!item_manager->ValidState())
{
return false;
}
SCItemSlotContainer* const inventory = item_manager->GetItemSlotContainer(SI_INVENTORY);
// 요청을 얻는다.
MSG_CG_ITEM_COMPOSE_OR_DECOMPOSE_SYN request;
request.m_dwKey = gm->GetUserKey();
switch (request_type)
{
//_NA_000251_20100727_SOCKET_SYSTEM
case MSG_CG_ITEM_COMPOSE_OR_DECOMPOSE_SYN::kZardRequest:
{
// 재료 개수를 검사한다.
if (user_inputed_material_size != ZardComposeInfoParser::kMaterialSize)
{
return false;
}
// 쟈드의 인벤토리 위치를 얻는다.
POSTYPE zard_position_list[ZardComposeInfoParser::kMaterialSize];
{
for (int zard_index = 0; zard_index < user_inputed_material_size; ++zard_index)
{
const int gm_cmd_index = zard_index + kMaterialPosition;
util::internal::scoped_string_to_number(gm_cmd_arguments[gm_cmd_index], zard_position_list[zard_index]);
}
}
const ZardComposeInfoParser* const zard_compose_parser = ZardComposeInfoParser::Instance();
if (!zard_compose_parser->GetZardCompositionRequest(
*inventory, zard_position_list, static_cast<POSTYPE>(reserved_code), request))
{
return false;
}
}
break;
#ifdef _NA_002253_20100811_CUBE_SYSTEM
case MSG_CG_ITEM_COMPOSE_OR_DECOMPOSE_SYN::kCubeRequest:
{
// 재료 개수를 검사한다.
if (user_inputed_material_size > CompositionInfo::MaterialInfo::kMaxSize)
{
return false;
}
// 재료의 인벤토리 위치 목록을 얻는다.
MaterialInventoryPositionList inventory_position_list;
{
for (MaterialInventoryPositionList::size_type material_index = 0;
material_index < user_inputed_material_size;
++material_index)
{
const int gm_cmd_index = material_index + kMaterialPosition;
POSTYPE inventory_position = 0;
util::internal::scoped_string_to_number(gm_cmd_arguments[gm_cmd_index], inventory_position);
inventory_position_list.push_back(inventory_position);
}
}
const CubeSystemParser* const cube_parser = CubeSystemParser::Instance();
if (!cube_parser->GetRequest(
*inventory, (is_composition == 1), inventory_position_list, using_item_position, request))
{
return false;
}
}
break;
#endif // _NA_002253_20100811_CUBE_SYSTEM
default:
return false;
}
// 처리기를 호출한다.
Handler_CG_ITEM::OnCG_ITEM_COMPOSE_OR_DECOMPOSE_SYN(NULL, &request, request.GetSize());
return true;
}
static bool ProcessCompositionList(DWORD player_key, const GmCmdTokens& gm_cmd_arguments)
{
enum { kArgumentSize = 3 };
GMCmdManager* const gm_manager = GMCmdManager::Instance();
Player* const gm = gm_manager->GetGMPlayer(player_key);
if (!util::internal::scoped_check_input_in_gm(gm, gm_cmd_arguments, kArgumentSize+1, kArgumentSize+1, false))
{
return false;
}
// GM 명령어 형식 : composition_list 키워드 다음에 아래 순서대로 입력
enum GMCmdIndex
{
kRequestType = 1, // 요청 종류(쟈드:1, 큐브:2)
kIsComposition = 2, // 합성 여부(아니오:0, 예:1)
kIsModifyTest = 3, // 수정 기능 테스트 여부(아니오:0, 예:1)
};
// 요청 종류를 얻는다.
MSG_CG_ITEM_GET_COMPOSITION_OR_DECOMPOSITION_HISTORIES_SYN::RequestType request_type = 0;
{
util::internal::scoped_string_to_number(gm_cmd_arguments[kRequestType], request_type);
if (request_type != MSG_CG_ITEM_COMPOSE_OR_DECOMPOSE_SYN::kZardRequest &&
request_type != MSG_CG_ITEM_COMPOSE_OR_DECOMPOSE_SYN::kCubeRequest)
{
return false;
}
}
// 합성 여부를 얻는다.
bool is_composition = false;
{
int cmd_is_composition = 0;
util::internal::scoped_string_to_number(gm_cmd_arguments[kIsComposition], cmd_is_composition);
if (cmd_is_composition != 0 && cmd_is_composition != 1)
{
return false;
}
is_composition = (cmd_is_composition == 1);
}
// 수정 기능 테스트 여부를 얻는다.
bool is_modify_test = false;
{
int cmd_is_modify_test = 0;
util::internal::scoped_string_to_number(gm_cmd_arguments[kIsModifyTest], cmd_is_modify_test);
if (cmd_is_modify_test != 0 && cmd_is_modify_test != 1)
{
return false;
}
is_modify_test = (cmd_is_modify_test == 1);
}
// 내역 수정 기능을 테스트한다.
if (is_modify_test)
{
// 수정 메시지를 만든다.
MSG_CG_ITEM_MODIFY_COMPOSITION_OR_DECOMPOSITION_HISTORIES_CMD modify_histories_cmd;
{
modify_histories_cmd.Init();
modify_histories_cmd.m_dwKey = gm->GetUserKey();
modify_histories_cmd.condition_list_size = 2;
ItemCompositionOrDecompositionHistory::ModifyCondition& condition1 =
modify_histories_cmd.modify_condition_list[0];
condition1.history_id = 7;
condition1.is_memorize = false;
ItemCompositionOrDecompositionHistory::ModifyCondition& condition2 =
modify_histories_cmd.modify_condition_list[1];
condition2.history_id = 9;
condition2.is_memorize = false;
}
// 처리기를 호출한다.
Handler_CG_ITEM::OnCG_ITEM_MODIFY_COMPOSITION_OR_DECOMPOSITION_HISTORIES_CMD(
NULL, &modify_histories_cmd, modify_histories_cmd.GetSize());
return true;
}
// 메시지를 만든다.
MSG_CG_ITEM_GET_COMPOSITION_OR_DECOMPOSITION_HISTORIES_SYN get_histories_syn;
{
get_histories_syn.Init();
get_histories_syn.m_dwKey = gm->GetUserKey();
get_histories_syn.request_type = request_type;
get_histories_syn.is_composition = is_composition;
}
// 처리기를 호출한다.
Handler_CG_ITEM::OnCG_ITEM_GET_COMPOSITION_OR_DECOMPOSITION_HISTORIES_SYN(
NULL, &get_histories_syn, get_histories_syn.GetSize());
return true;
}
// _NA_000251_20100727_SOCKET_SYSTEM
static bool ProcessIdentifySocket(DWORD player_key, const GmCmdTokens& gm_cmd_arguments)
{
GMCmdManager* const gm_manager = GMCmdManager::Instance();
Player* const gm = gm_manager->GetGMPlayer(player_key);
if (!util::internal::scoped_check_input_in_gm(gm, gm_cmd_arguments, 1, 2, false))
{
return false;
}
// GM 커맨드 형식 : identify_socket 키워드 다음에 아래 순서대로 입력
enum GMCmdIndex
{
kUnidentifiedItemPos = 1, // 미확인 아이템 위치
kIdentifyItemPos = 2 // 아이템을 사용하여 확인할 때 확인 아이템 위치 (옵션)
};
MSG_CG_ITEM_IDENTIFY_SOCKET_CMD request;
{
request.m_dwKey = gm->GetUserKey();
util::internal::scoped_string_to_number(
gm_cmd_arguments[kUnidentifiedItemPos], request.unidentified_item_pos_);
if (gm_cmd_arguments.size() == 3)
{
// 아이템을 사용했다면 확인 아이템 위치를 얻는다.
request.use_identify_item_ = true;
util::internal::scoped_string_to_number(
gm_cmd_arguments[kIdentifyItemPos], request.identify_item_pos_);
}
else
{
request.use_identify_item_ = false;
request.identify_item_pos_ = INVALID_POSTYPE_VALUE;
}
}
// 처리기를 호출한다.
Handler_CG_ITEM::OnCG_ITEM_IDENTIFY_SOCKET_CMD(NULL, &request, request.GetSize());
return false;
}
static bool ProcessRecreateSocket(DWORD player_key, const GmCmdTokens& cmd_args)
{
// 명령어 형식 : recreate_socket 키워드 다음에 아래 순서대로 입력
enum CmdIndex
{
kTargetItemPos = 1, // 소켓을 다시 생성할 아이템의 인벤토리 위치
kSocketNumber, // [생략가능] 다시 설정할 소켓 개수 (0이면 규칙에 따라 램덤 생성)
kRecreateItemPos, // [생략가능] 소켓다시생성 아이템의 인벤토리 위치
kNumOfMaxArgs
};
// 명령어 동작 방식
enum CmdMode
{
kUnknownMode,
// 소켓을 규칙에 따라 다시 생성한다.
// 예제> recreate_socket 2 // 인벤토리 2번 위치에 있는 아이템의 소켓을 다시 생성한다.
kRecreateSocket,
// 소켓 개수를 다시 설정한다.
// 예제> recreate_socket 2 3 // 인벤토리 2번 위치에 있는 아이템의 소켓 개수를 3개로 설정한다.
kSetSocketNumber,
// 소켓을 아이템을 사용하여 다시 생성한다.
// recreate_socket 2 0 3 // 인벤토리 2번 위치에 있는 아이템의 소켓을,
// 인벤토리 3번 위치에 있는 소켓다시생성아이템(헤르메시즘의 성서 등)을 사용해서 다시 생성한다.
kRecreateSocketByItem
};
using namespace util::internal;
GMCmdManager* const gm_manager = GMCmdManager::Instance();
Player* const gm = gm_manager->GetGMPlayer(player_key);
if (scoped_check_input_in_gm(gm, cmd_args, 1, kNumOfMaxArgs, false) == false)
{
return false;
}
POSTYPE target_item_pos = INVALID_SLOT_POS;
scoped_string_to_number(cmd_args[kTargetItemPos], target_item_pos);
if (target_item_pos == INVALID_SLOT_POS)
{
return false;
}
CmdMode cmd_mode = kUnknownMode;
{
const uint8_t args_size = cmd_args.size();
if (args_size == kTargetItemPos+1)
{
cmd_mode = kRecreateSocket;
}
else if (args_size == kSocketNumber+1)
{
cmd_mode = kSetSocketNumber;
}
else if (args_size == kRecreateItemPos+1)
{
cmd_mode = kRecreateSocketByItem;
}
else
{
return false;
}
}
switch (cmd_mode)
{
case kRecreateSocket:
case kSetSocketNumber:
{
ItemManager* const item_manager = gm->GetItemManager();
if (item_manager->ValidPos(SI_INVENTORY, target_item_pos) == false)
{
return false;
}
BYTE num_of_socket = 0;
if (cmd_mode == kSetSocketNumber)
{
scoped_string_to_number(cmd_args[kSocketNumber], num_of_socket);
}
SCItemSlotContainer* const inven = item_manager->GetItemSlotContainer(SI_INVENTORY);
SCItemSlot& target_slot = static_cast<SCItemSlot&>(inven->GetSlot(target_item_pos));
if (target_slot.CreateSocketItem(num_of_socket, true) == false)
{
return false;
}
item_manager->SendItemChange(target_slot);
}
break;
case kRecreateSocketByItem:
{
MSG_CG_ITEM_RECREATE_SOCKET_SYN request;
request.Init();
request.m_dwKey = gm->GetUserKey();
scoped_string_to_number(cmd_args[kRecreateItemPos], request.request_item_pos);
request.target_item_pos = target_item_pos;
Handler_CG_ITEM::OnCG_ITEM_RECREATE_SOCKET_SYN(NULL, &request, request.GetSize());
}
break;
default:
return false;
}
return true;
}
static bool ProcessExRider(DWORD player_key, const GmCmdTokens& vecCmd)
{
GMCmdManager* const gm_manager = GMCmdManager::Instance();
Player* pPlayer = gm_manager->GetGMPlayer(player_key);
if (pPlayer == 0)
return false;
nsGM::CmdTokenizer::Route(pPlayer, vecCmd);
return true;
}
#ifdef _NA_002253_20100811_CUBE_SYSTEM
static bool ProcessCreateCubeMaterial(DWORD player_key, const GmCmdTokens& cmd_args)
{
// GM 커맨드 형식 : create_cube_material 키워드 다음에 아래 순서대로 입력
enum GMCmdIndex
{
kCompositionCode = 1, // 합성코드
kNumOfMaxArgs
};
using namespace util::internal;
GMCmdManager* const gm_manager = GMCmdManager::Instance();
Player* const gm = gm_manager->GetGMPlayer(player_key);
if (scoped_check_input_in_gm(gm, cmd_args, 1, kNumOfMaxArgs, false) == false)
{
return false;
}
CompositionInfo::CompositionCode composition_code(CompositionInfo::kUnused);
scoped_string_to_number(cmd_args[kCompositionCode], composition_code);
const CubeSystemParser* const cube_parser = CubeSystemParser::Instance();
const CompositionInfo* const composition = cube_parser->FindComposition(composition_code);
if (composition == NULL)
{
return false;
}
typedef ItemCompositionOrDecompositionReward MaterialRewards;
MaterialRewards material_rewards;
if (material_rewards.Init(gm, MaterialRewards::kItemCodeReward) == false)
{
return false;
}
FOREACH_CONTAINER(
const CompositionInfo::MaterialInfo& material,
composition->material_list_,
CompositionInfo::MaterialList)
{
if (material.is_used_ == false)
{
continue;
}
MaterialRewards::ItemReward material_reward;
{
if (material.code_ != CompositionInfo::kUnused)
{
material_reward.item_code = static_cast<MaterialRewards::RewardItemCode>(material.code_);
}
else if (material.type_code_ != CompositionInfo::kUnused)
{
// 타입에 일치하는 아이템 코드를 찾는다.
bool is_find = false;
{
const ItemInfoParser* const item_parser = ItemInfoParser::Instance();
item_parser->SetFirst();
const BASE_ITEMINFO* material_info(NULL);
while ((material_info = item_parser->GetNext()) != NULL)
{
if (material.type_code_ == material_info->m_wType)
{
material_reward.item_code = material_info->m_Code;
is_find = true;
break;
}
}
}
if (is_find == false)
{
return false;
}
}
else if (material.level_ != CompositionInfo::kUsed)
{
// 레벨에 일치하는 아이템 코드를 찾는다.
bool is_find = false;
{
const ItemInfoParser* const item_parser = ItemInfoParser::Instance();
item_parser->SetFirst();
const BASE_ITEMINFO* material_info(NULL);
while ((material_info = item_parser->GetNext()) != NULL)
{
if (material.level_ == material_info->m_LV)
{
material_reward.item_code = material_info->m_Code;
is_find = true;
break;
}
}
}
if (is_find == false)
{
return false;
}
}
material_reward.number_of_item = material.number_;
material_reward.ig_type = material.ig_type_;
}
if (material_rewards.AddItemReward(material_reward) == false)
{
return false;
}
}
// CHANGES: f110216.3L
MSG_CG_ITEM_OBTAIN_ITEM_CMD obtain_cmd;
if (INVENTORY_TOTAL_INFO* inven_total_info = &obtain_cmd.m_tagInventory)
{
inven_total_info->m_InvenCount = 0;
inven_total_info->m_TmpInvenCount = 0;
}
//
const RC::eITEM_RESULT obtain_result = material_rewards.ObtainRewardToInventory(
MaterialRewards::kDoNotUseLog, obtain_cmd.m_tagInventory);
if (obtain_result != RC::RC_ITEM_SUCCESS)
{
return false;
}
gm->SendPacket(&obtain_cmd, obtain_cmd.GetSize());
return true;
}
#endif // _NA_002253_20100811_CUBE_SYSTEM
}; //end of namespace 'nsGM'
bool GMCmdManager::RegisterSlot(const HandlerNode** node_array, size_t* result_array_count)
{
using namespace nsGM;
bool success = false;
#define GMHANDLER_MAPPING(activated, korean, english, handler) \
{ activated, eGM_GRADE_MAX, 0xFFFFFFFF, 0xFFFFFFFF, handler, korean, english }
static HandlerNode const_node_array[] =
{
GMHANDLER_MAPPING(true, "생성", "make", &ProcessCreateItemEx), // 아이템 생성
GMHANDLER_MAPPING(true, "하임", "heim", &ProcessCreateHime), // 하임생성
GMHANDLER_MAPPING(true, "아이템제거", "removei", &ProcessRemovalItem), // 아이템 제거
GMHANDLER_MAPPING(true, "인첸트만들기", "createenchant", &ProcessCreateEnchantItem), // 인첸트 아이템 생성
GMHANDLER_MAPPING(true, "줍기", "pickup", &ProcessPickUp),
GMHANDLER_MAPPING(true, "리미티드생성", "createlimited", &ProcessCreateLimitedItem),
GMHANDLER_MAPPING(true, "럭키생성", "createlucky", &ProcessCreateFateItem),
GMHANDLER_MAPPING(true, "인벤제거", "removeinven", &ProcessRemoveInven),
GMHANDLER_MAPPING(true, "내구도", "strength", &ProcessStrengthCmd),
GMHANDLER_MAPPING(true, "하임제거", "removeh", &ProcessRemoveHimeCmd),
// unused
GMHANDLER_MAPPING(false, NULL, NULL, &ProcessEnchandCmd),
GMHANDLER_MAPPING(true, NULL, "rider", &ProcessExRider),
GMHANDLER_MAPPING(true, "아이템", "item", &ProcessExItem),
GMHANDLER_MAPPING(false, NULL, "composition", &ProcessComposition), // EP2 아이템 합성/분해
// unused
GMHANDLER_MAPPING(false, NULL, "composition_list", &ProcessCompositionList), // EP2 최근에 성공한 합성 목록 얻기
//_NA_000251_20100727_SOCKET_SYSTEM
GMHANDLER_MAPPING(false, NULL, "identify_socket", &ProcessIdentifySocket),
GMHANDLER_MAPPING(true, "소켓다시생성", "recreate_socket", &ProcessRecreateSocket),
#ifdef _NA_002253_20100811_CUBE_SYSTEM
GMHANDLER_MAPPING(true, "큐브재료생성", "create_cube_material", &ProcessCreateCubeMaterial),
#endif // _NA_002253_20100811_CUBE_SYSTEM
}; //
ModifyGmHandlerNode(const_node_array, _countof(const_node_array));
*node_array = const_node_array;
*result_array_count = _countof(const_node_array);
success = true;
//
return success;
}