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

429 lines
16 KiB
C++

#include "stdafx.h"
#include "./EtherealizeImpl.h"
//
#include <SCItemSlot.h>
#include <SCItemSlotContainer.h>
//
#include "ItemManager.h"
//==================================================================================================
namespace nsSlot {
;
// implemented by _NA000109_100427_ITEM_CUSTOMIZING_CONTENTS_
void EtheriaImpl::SetInstance(Player* player, EtheriaControlOption* control_option)
{
player_ = player;
control_option_ = control_option;
}
EtheriaImpl::eResult EtheriaImpl::Casting(const EtheriaControl& req_info,
EtheriaControl* const result,
EtheriaControlData* const broad_result_data)
{
assert(req_info.request == req_info.eReq_CastingStart ||
req_info.request == req_info.eReq_CastingCancel);
result->Clear();
broad_result_data->Clear();
// client passing data
result->request = req_info.request;
result->args = req_info.args;
const WORD player_key = static_cast<WORD>(player_->GetObjectKey());
const DWORD tick_count = GetTickCount();
bool pass = true;
;{
ePLAYER_BEHAVE_STATE behave = player_->GetBehave();
if (behave != PLAYER_BEHAVE_IDLE_STATE)
{
pass = false;
broad_result_data->data_type = broad_result_data->eDataType_Actor;
broad_result_data->actor.requester = player_key;
result->result = req_info.eRet_ItemFailed;
result->result_code = RC::RC_ITEM_UNUSABLE_FUNCTION;
return this->eResult_Fail;
}
};
//
if (pass == false) {
}
else if (req_info.request == req_info.eReq_CastingStart)
{
if (control_option_->doing_casting_) {
// fault tolerant
pass = (control_option_->timeout_ < tick_count);
}
if (control_option_->doing_casting_ && pass == false)
{
broad_result_data->data_type = broad_result_data->eDataType_Actor;
broad_result_data->actor.requester = player_key;
result->result = req_info.eRet_Failed;
result->result_code = req_info.eRetCode_CastingToggleError;
return this->eResult_1to1;
}
else
{
control_option_->doing_casting_ = true;
control_option_->timeout_ = tick_count +
(req_info.kCastingDelay - (req_info.kCastingDelay >> 2));
broad_result_data->data_type = broad_result_data->eDataType_Actor;
broad_result_data->actor.requester = player_key;
result->result = req_info.eRet_Success;
return this->eResult_1toN;
}
}
else if (req_info.request == req_info.eReq_CastingCancel)
{
if (control_option_->doing_casting_)
{
control_option_->doing_casting_ = false;
control_option_->timeout_ = 0;
broad_result_data->data_type = broad_result_data->eDataType_Actor;
broad_result_data->actor.requester = player_key;
result->result = req_info.eRet_Success;
return this->eResult_1toN;
}
else
{
broad_result_data->data_type = broad_result_data->eDataType_Actor;
broad_result_data->actor.requester = player_key;
result->result = req_info.eRet_Failed;
result->result_code = req_info.eRetCode_CastingToggleError;
return this->eResult_1to1;
}
}
;{
broad_result_data->data_type = broad_result_data->eDataType_Actor;
broad_result_data->actor.requester = player_key;
result->result = req_info.eRet_Failed;
result->result_code = req_info.eRetCode_Unknown;
return this->eResult_Fail;
};
}
EtheriaImpl::eResult EtheriaImpl::ExtractToEtheria(const EtheriaControl& req_info,
EtheriaControl* const result,
EtheriaControlData* const result_data)
{
//_NA000109_100427_ITEM_CUSTOMIZING_CONTENTS_USING_ETHEREALIZER_
const bool kUseEtherealizer = true;
const int kDefaultExtractOperation = 0; // BASE_ITEMINFO::m_byWasteType == 0, redirected value
//
assert(req_info.request == req_info.eReq_Extract);
result->Clear();
result_data->Clear();
// client passing data
result->request = req_info.request;
result->args = req_info.args;
bool success = true;
RC::eITEM_RESULT item_result = RC::RC_ITEM_SUCCESS;
//...
const EtheriaControl::Req_Extract& extract_info = req_info.args.extract;
//
ePLAYER_BEHAVE_STATE behave = player_->GetBehave();
if (behave != PLAYER_BEHAVE_IDLE_STATE)
{
success = false;
result->result = req_info.eRet_ItemFailed;
result->result_code = RC::RC_ITEM_UNUSABLE_FUNCTION;
return this->eResult_Fail;
}
// (f100526.5L) add casting presentation
if (this->control_option_->doing_casting_ == false)
{
success = false;
result->result = req_info.eRet_Failed;
result->result_code = req_info.eRetCode_ExtractNeedCasting;
return this->eResult_Fail;
}
this->control_option_->doing_casting_ = false;
//
ItemManager* const item_manager = player_->GetItemManager();
if (item_manager->ValidPos(SI_INVENTORY, extract_info.slot_pos, true) == false ||
(kUseEtherealizer &&
item_manager->ValidPos(SI_INVENTORY, extract_info.etherealizer_pos, true) == false))
{
success = false;
result->result = result->eRet_ItemFailed;
result->result_code = RC::RC_ITEM_INVALIDPOS;
return this->eResult_Fail;
}
SCSlotContainer* const inventory = item_manager->GetItemSlotContainer(SI_INVENTORY);
//
SCItemSlot* etherealizer = NULL;
const BASE_ITEMINFO* etherealizer_info = NULL;
if (kUseEtherealizer)
{
etherealizer = static_cast<SCItemSlot*>(&inventory->GetSlot(extract_info.etherealizer_pos));
if (etherealizer->IsContainValidItem() == false ||
(etherealizer_info = etherealizer->GetItemInfo())->m_wType != eITEMTYPE_ETHEREALIZER)
{
success = false;
result->result = result->eRet_ItemFailed;
result->result_code = RC::RC_ITEM_INVALID_TYPE;
return this->eResult_Fail;
}
if (etherealizer->IsLocked() || etherealizer->IsBlocked())
{
success = false;
result->result = result->eRet_ItemFailed;
result->result_code = RC::RC_ITEM_INVALIDPOS;
return this->eResult_Fail;
}
// eWASTETYPE = { 0, eITEMWASTE_ETHEREALIZER_SHELL, eITEMWASTE_ETHEREALIZER_ETHERIA };
assert(etherealizer_info);
switch (etherealizer_info->m_byWasteType)
{
case kDefaultExtractOperation:
//_NA000541_100901_ITEM_CUSTOMIZING_CONTENTS_USING_VARIOUS_ETHEREALIZER_
case eITEMWASTE_ETHEREALIZER_SHELL:
case eITEMWASTE_ETHEREALIZER_ETHERIA:
{
// passed, notthing to do
};
break;
default:
SUNLOG(eCRITICAL_LOG,
_T("|["__FUNCTION__"]|ÐÅÏ¢=unexpected an etherealizer's waste type|")
_T("|ItemCode=%d|WasteType=%d|"),
etherealizer_info->m_Code, etherealizer_info->m_byWasteType);
//
success = false;
result->result = result->eRet_ItemFailed;
result->result_code = RC::RC_ITEM_INVALID_TYPE;
return this->eResult_Fail;
}; //end 'switch'
};
//
const int extract_operation = etherealizer_info ? etherealizer_info->m_byWasteType
: kDefaultExtractOperation;
//
SCItemSlot& extract_item = static_cast<SCItemSlot&>(inventory->GetSlot(extract_info.slot_pos));
if (extract_item.CanExtractToEtheria(&item_result) == false) // need result variation
{
success = false;
result->result = result->eRet_ItemFailed;
result->result_code = item_result;
return this->eResult_Fail;
};
// added rules to support _NA001202_101104_ITEM_CUSTOMIZING_CONTENTS_ETHEREALIZABLE_LUCKYITEM
// CHANGES: f101104.3L, added a filter about 'etherealization_mode_'
// as represent of 'ExtractType' in item scripts
const BASE_ITEMINFO* extract_item_info = extract_item.GetItemInfo();
const eEtherealizeMode& etherealize_mode = extract_item_info->etherealization_mode_;
switch (etherealize_mode.value)
{
case etherealize_mode.NoFilter:
break;
case etherealize_mode.ExtractEtheriaOnly:
if (extract_operation != eITEMWASTE_ETHEREALIZER_ETHERIA) {
success = false;
result->result = result->eRet_ItemFailed;
result->result_code = RC::RC_ITEM_INVALID_TYPE;
return this->eResult_Fail;
}
break;
case etherealize_mode.ExtractShellOnly:
if (extract_operation != eITEMWASTE_ETHEREALIZER_SHELL) {
success = false;
result->result = result->eRet_ItemFailed;
result->result_code = RC::RC_ITEM_INVALID_TYPE;
return this->eResult_Fail;
}
break;
case etherealize_mode.CantEtherealize:
default:
success = false;
result->result = result->eRet_ItemFailed;
result->result_code = RC::RC_ITEM_INVALID_TYPE;
return this->eResult_Fail;
}
// NOTE, a default action require a new slot to insert an extracted etheria item.
// CHANGES, f100901.2L, changes a check sequence and
// add a rule that a process enables the next step when a requisite empty slot is exist
// if an operation is a default.
if (extract_operation == kDefaultExtractOperation)
{ // check empty slot
int empty_slots = item_manager->CheckInsertItem(SI_INVENTORY,
HardCode::ITEMCODE_of_ETHERIA, 1);
if (empty_slots != 1)
{
success = false;
result->result = result->eRet_ItemFailed;
result->result_code = RC::RC_ITEM_NOSPACEININVENTORY;
return this->eResult_Fail;
}
};
//
int log_type_for_change_item = ITEM_CHANGED_TO_SHELL;
SCItemSlot making_item;
switch (extract_operation)
{
case kDefaultExtractOperation:
log_type_for_change_item = ITEM_CHANGED_TO_SHELL;
item_result = extract_item.ExtractToEtheria(&making_item);
break;
case eITEMWASTE_ETHEREALIZER_SHELL:
log_type_for_change_item = ITEM_CHANGED_TO_SHELL;
if (extract_item.ChangeToShellItem() == false) {
item_result = RC::RC_ITEM_INVALIDSTATE;
}
break;
case eITEMWASTE_ETHEREALIZER_ETHERIA:
log_type_for_change_item = ITEM_CHANGED_TO_ETHERIA;
if (extract_item.ChangeToEtheriaItem() == false) {
item_result = RC::RC_ITEM_INVALIDSTATE;
}
break;
};
if (item_result != RC::RC_ITEM_SUCCESS)
{
success = false;
result->result = result->eRet_ItemFailed;
result->result_code = item_result;
return this->eResult_Fail;
}
// logging
GAMELOG->LogItem(log_type_for_change_item, player_, &extract_item);
//
if (kUseEtherealizer)
{
WORD item_code_out = 0;
RC::eITEM_RESULT item_result = \
item_manager->Use(SI_INVENTORY, extract_info.etherealizer_pos, item_code_out);
if (item_result != RC::RC_ITEM_SUCCESS)
{
success = false;
result->result = req_info.eRet_ItemFailed;
result->result_code = item_result;
return eResult_Fail;
}
};
// success control
assert(success != false);
if (extract_operation != kDefaultExtractOperation)
{
result->result = result->eRet_Success;
result_data->data_type = result_data->eDataType_Changed;
result_data->changed.is_etheria = (extract_operation == eITEMWASTE_ETHEREALIZER_ETHERIA);
extract_item.CopyOut(result_data->changed.changed_item);
}
else //if (extract_operation == kDefaultExtractOperation)
{
// last update logic ... should be success
INVENTORY_TOTAL_INFO inven_total_info;
item_result = item_manager->Obtain(making_item, 1, &inven_total_info);
if (FlowControl::FCAssert(item_result == RC::RC_ITEM_SUCCESS) == false)
{
success = false;
result->result = result->eRet_ItemFailed;
result->result_code = item_result;
// rollback
item_result = extract_item.CombineWithEtheria(making_item);
ASSERT(item_result == RC::RC_ITEM_SUCCESS);
return this->eResult_Fail;
}
result->result = result->eRet_Success;
result_data->data_type = result_data->eDataType_Extract;
extract_item.CopyOut(result_data->extract.shell_item);
result_data->extract.etheria_item = inven_total_info.m_Slot[0];
// logging
POSTYPE acquied_etheria_pos = inven_total_info.m_Slot[0].m_Pos;
const SCItemSlot& acquied_etheria = \
static_cast<SCItemSlot&>(inventory->GetSlot(acquied_etheria_pos));
GAMELOG->LogItem(ITEM_PICK, player_, &acquied_etheria);
};
return this->eResult_1to1;
}
EtheriaImpl::eResult EtheriaImpl::CombineWithEtheria(const EtheriaControl& req_info,
EtheriaControl* const result,
EtheriaControlData* const result_data)
{
assert(req_info.request == req_info.eReq_Combine);
result->Clear();
result_data->Clear();
// client passing data
result->request = req_info.request;
result->args = req_info.args;
bool success = true;
RC::eITEM_RESULT item_result = RC::RC_ITEM_SUCCESS;
//
const EtheriaControl::Req_Combine& combine_info = req_info.args.combine;
//
ePLAYER_BEHAVE_STATE behave = player_->GetBehave();
if (behave != PLAYER_BEHAVE_IDLE_STATE)
{
success = false;
result->result = req_info.eRet_ItemFailed;
result->result_code = RC::RC_ITEM_UNUSABLE_FUNCTION;
return this->eResult_Fail;
}
//
ItemManager* const item_manager = player_->GetItemManager();
if (item_manager->ValidPos(SI_INVENTORY, combine_info.from_etheria, true) == false ||
item_manager->ValidPos(SI_INVENTORY, combine_info.to_shell, true) == false)
{
success = false;
result->result = result->eRet_ItemFailed;
result->result_code = RC::RC_ITEM_INVALIDPOS;
return this->eResult_Fail;
}
SCSlotContainer* const inventory = item_manager->GetItemSlotContainer(SI_INVENTORY);
SCItemSlot& etheria_item = \
static_cast<SCItemSlot&>(inventory->GetSlot(combine_info.from_etheria));
SCItemSlot& shell_item = static_cast<SCItemSlot&>(inventory->GetSlot(combine_info.to_shell));
item_result = shell_item.CombineWithEtheria(etheria_item);
if (item_result != RC::RC_ITEM_SUCCESS)
{
success = false;
result->result = result->eRet_ItemFailed;
result->result_code = item_result;
return this->eResult_Fail;
}
GAMELOG->LogItem(ITEM_COMBINED_WITH_ETHERIA, player_, &shell_item);
//
SCItemSlot item_for_logging;
success = inventory->DeleteSlot(combine_info.from_etheria, &item_for_logging) != false;
assert(success);
;{
result->result = result->eRet_Success;
result_data->data_type = result_data->eDataType_Combine;
shell_item.CopyOut(result_data->combine.combined_item);
GAMELOG->LogItem(ITEM_USE, player_, &item_for_logging);
};
return this->eResult_1to1;
}
//==================================================================================================
void EtheriaFailHandler::SetFailResult(uint8_t result_type, uint16_t result_code, bool show_log)
{
result_->request = req_info_.request;
result_->args = req_info_.args;
//
result_->result = result_type;
result_->result_code = result_code;
result_data_->data_type = result_data_->eDataType_None;
BOOST_STATIC_ASSERT(result_data_->eDataType_None == 0); //for clear memory stream
if (show_log) {
OutputLog();
}
}
void EtheriaFailHandler::OutputLog()
{
SUNLOG(eCRITICAL_LOG,
_T("|["__FUNCTION__"]|Can't Accept Request|Request=%d|CharName=%s|"),
req_info_.request, player_->GetCharName());
}
}; //end of namespace