issue-7: add stone refine queue command
This commit is contained in:
@@ -215,6 +215,7 @@ void CHARACTER::Initialize()
|
||||
m_pkFireEvent = NULL;
|
||||
m_pkCheckSpeedHackEvent = NULL;
|
||||
m_pkAutoPickupEvent = NULL;
|
||||
m_pkStoneQueueEvent = NULL;
|
||||
m_speed_hack_count = 0;
|
||||
|
||||
m_pkAffectEvent = NULL;
|
||||
@@ -305,6 +306,11 @@ void CHARACTER::Initialize()
|
||||
// REFINE_NPC
|
||||
m_dwRefineNPCVID = 0;
|
||||
// END_OF_REFINE_NPC
|
||||
m_bStoneQueueScrollCell = 0;
|
||||
m_iStoneQueueCurrentIndex = 0;
|
||||
m_iStoneQueueSuccessCount = 0;
|
||||
m_iStoneQueueFailCount = 0;
|
||||
m_vecStoneQueueSlots.clear();
|
||||
|
||||
m_dwPolymorphRace = 0;
|
||||
|
||||
@@ -563,6 +569,7 @@ void CHARACTER::Destroy()
|
||||
event_cancel(&m_pkMiningEvent);
|
||||
// END_OF_MINING
|
||||
event_cancel(&m_pkAutoPickupEvent);
|
||||
event_cancel(&m_pkStoneQueueEvent);
|
||||
|
||||
|
||||
for (itertype(m_mapMobSkillEvent) it = m_mapMobSkillEvent.begin(); it != m_mapMobSkillEvent.end(); ++it)
|
||||
@@ -6535,6 +6542,166 @@ void CHARACTER::RefreshAutoPickup()
|
||||
SendAutoPickupState();
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
const int kStoneQueueTick = PASSES_PER_SEC(1);
|
||||
enum
|
||||
{
|
||||
HYUNIRON_CHN = 1,
|
||||
MUSIN_SCROLL = 3,
|
||||
BDRAGON_SCROLL = 6,
|
||||
};
|
||||
|
||||
int GetStoneQueueRefineType(LPITEM scrollItem, LPITEM targetItem)
|
||||
{
|
||||
if (!scrollItem || !targetItem)
|
||||
return -1;
|
||||
|
||||
if (scrollItem->GetType() != ITEM_USE || scrollItem->GetSubType() != USE_TUNING)
|
||||
return -1;
|
||||
|
||||
if (scrollItem->GetValue(0) == MUSIN_SCROLL)
|
||||
return REFINE_TYPE_MUSIN;
|
||||
|
||||
if (scrollItem->GetValue(0) == HYUNIRON_CHN)
|
||||
return REFINE_TYPE_HYUNIRON;
|
||||
|
||||
if (scrollItem->GetValue(0) == BDRAGON_SCROLL)
|
||||
{
|
||||
if (targetItem->GetRefineSet() != 702)
|
||||
return -1;
|
||||
|
||||
return REFINE_TYPE_BDRAGON;
|
||||
}
|
||||
|
||||
if (targetItem->GetRefineSet() == 501)
|
||||
return -1;
|
||||
|
||||
return REFINE_TYPE_SCROLL;
|
||||
}
|
||||
|
||||
EVENTFUNC(stone_queue_event)
|
||||
{
|
||||
char_event_info* info = dynamic_cast<char_event_info*>(event->info);
|
||||
if (!info)
|
||||
{
|
||||
sys_err("stone_queue_event> <Factor> Null pointer");
|
||||
return 0;
|
||||
}
|
||||
|
||||
LPCHARACTER ch = info->ch;
|
||||
if (!ch)
|
||||
return 0;
|
||||
|
||||
return ch->ProcessStoneQueueTick() ? kStoneQueueTick : 0;
|
||||
}
|
||||
}
|
||||
|
||||
int CHARACTER::GetStoneQueueMax() const
|
||||
{
|
||||
return GetPremiumRemainSeconds(PREMIUM_GOLD) > 0 ? 8 : 3;
|
||||
}
|
||||
|
||||
void CHARACTER::SendStoneQueueState()
|
||||
{
|
||||
ChatPacket(CHAT_TYPE_COMMAND,
|
||||
"StoneQueueState %d %d %d %d %d",
|
||||
GetStoneQueueMax(),
|
||||
m_pkStoneQueueEvent ? 1 : 0,
|
||||
m_iStoneQueueCurrentIndex,
|
||||
m_iStoneQueueSuccessCount,
|
||||
m_iStoneQueueFailCount);
|
||||
}
|
||||
|
||||
void CHARACTER::CancelStoneQueue(bool resetResults)
|
||||
{
|
||||
event_cancel(&m_pkStoneQueueEvent);
|
||||
m_vecStoneQueueSlots.clear();
|
||||
m_bStoneQueueScrollCell = 0;
|
||||
if (resetResults)
|
||||
{
|
||||
m_iStoneQueueCurrentIndex = 0;
|
||||
m_iStoneQueueSuccessCount = 0;
|
||||
m_iStoneQueueFailCount = 0;
|
||||
}
|
||||
SendStoneQueueState();
|
||||
}
|
||||
|
||||
void CHARACTER::StartStoneQueue(const std::vector<BYTE>& slots, BYTE scrollCell)
|
||||
{
|
||||
CancelStoneQueue();
|
||||
m_vecStoneQueueSlots = slots;
|
||||
m_bStoneQueueScrollCell = scrollCell;
|
||||
char_event_info* info = AllocEventInfo<char_event_info>();
|
||||
info->ch = this;
|
||||
m_pkStoneQueueEvent = event_create(stone_queue_event, info, 1);
|
||||
SendStoneQueueState();
|
||||
}
|
||||
|
||||
void CHARACTER::OnStoneQueueRefineResult(bool success)
|
||||
{
|
||||
if (!m_pkStoneQueueEvent)
|
||||
return;
|
||||
|
||||
if (success)
|
||||
++m_iStoneQueueSuccessCount;
|
||||
else
|
||||
++m_iStoneQueueFailCount;
|
||||
|
||||
++m_iStoneQueueCurrentIndex;
|
||||
|
||||
if (m_iStoneQueueCurrentIndex >= static_cast<int>(m_vecStoneQueueSlots.size()))
|
||||
{
|
||||
ChatPacket(CHAT_TYPE_INFO, LC_TEXT("Stone queue finished. Success: %d Fail: %d"), m_iStoneQueueSuccessCount, m_iStoneQueueFailCount);
|
||||
CancelStoneQueue(false);
|
||||
return;
|
||||
}
|
||||
|
||||
SendStoneQueueState();
|
||||
}
|
||||
|
||||
bool CHARACTER::ProcessStoneQueueTick()
|
||||
{
|
||||
if (!IsPC() || IsDead())
|
||||
{
|
||||
CancelStoneQueue();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_iStoneQueueCurrentIndex >= static_cast<int>(m_vecStoneQueueSlots.size()))
|
||||
{
|
||||
CancelStoneQueue();
|
||||
return false;
|
||||
}
|
||||
|
||||
LPITEM scrollItem = GetInventoryItem(m_bStoneQueueScrollCell);
|
||||
if (!scrollItem)
|
||||
{
|
||||
CancelStoneQueue();
|
||||
return false;
|
||||
}
|
||||
|
||||
const BYTE targetSlot = m_vecStoneQueueSlots[m_iStoneQueueCurrentIndex];
|
||||
LPITEM targetItem = GetInventoryItem(targetSlot);
|
||||
const int refineType = GetStoneQueueRefineType(scrollItem, targetItem);
|
||||
|
||||
if (!targetItem || targetItem->GetType() != ITEM_METIN || refineType < 0)
|
||||
{
|
||||
OnStoneQueueRefineResult(false);
|
||||
return m_pkStoneQueueEvent != NULL;
|
||||
}
|
||||
|
||||
SetRefineMode(m_bStoneQueueScrollCell);
|
||||
SetRefineTime();
|
||||
if (!DoRefineWithScroll(targetItem, refineType))
|
||||
{
|
||||
OnStoneQueueRefineResult(false);
|
||||
return m_pkStoneQueueEvent != NULL;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CHARACTER::IsGuardNPC() const
|
||||
{
|
||||
return IsNPC() && (GetRaceNum() == 11000 || GetRaceNum() == 11002 || GetRaceNum() == 11004);
|
||||
|
||||
@@ -759,6 +759,12 @@ class CHARACTER : public CEntity, public CFSM, public CHorseRider
|
||||
bool HasAutoPickupVip() const;
|
||||
int GetAutoPickupRadius() const;
|
||||
bool ShouldAutoPickupItem(LPITEM item) const;
|
||||
int GetStoneQueueMax() const;
|
||||
void SendStoneQueueState();
|
||||
void StartStoneQueue(const std::vector<BYTE>& slots, BYTE scrollCell);
|
||||
void CancelStoneQueue(bool resetResults = true);
|
||||
void OnStoneQueueRefineResult(bool success);
|
||||
bool ProcessStoneQueueTick();
|
||||
|
||||
bool IsPolymorphed() const { return m_dwPolymorphRace>0; }
|
||||
bool IsPolyMaintainStat() const { return m_bPolyMaintainStat; } // 이전 스텟을 유지하는 폴리모프.
|
||||
@@ -1179,6 +1185,11 @@ class CHARACTER : public CEntity, public CFSM, public CHorseRider
|
||||
int m_iRefineAdditionalCell;
|
||||
bool m_bUnderRefine;
|
||||
DWORD m_dwRefineNPCVID;
|
||||
std::vector<BYTE> m_vecStoneQueueSlots;
|
||||
BYTE m_bStoneQueueScrollCell;
|
||||
int m_iStoneQueueCurrentIndex;
|
||||
int m_iStoneQueueSuccessCount;
|
||||
int m_iStoneQueueFailCount;
|
||||
|
||||
public:
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -1785,6 +1796,7 @@ class CHARACTER : public CEntity, public CFSM, public CHorseRider
|
||||
LPEVENT m_pkCheckSpeedHackEvent;
|
||||
LPEVENT m_pkDestroyWhenIdleEvent;
|
||||
LPEVENT m_pkAutoPickupEvent;
|
||||
LPEVENT m_pkStoneQueueEvent;
|
||||
LPEVENT m_pkPetSystemUpdateEvent;
|
||||
|
||||
bool IsWarping() const { return m_pkWarpEvent ? true : false; }
|
||||
|
||||
@@ -1030,6 +1030,7 @@ void NotifyRefineSuccess(LPCHARACTER ch, LPITEM item, const char* way, int iType
|
||||
if (NULL != ch && item != NULL)
|
||||
{
|
||||
ch->ChatPacket(CHAT_TYPE_COMMAND, "RefineSuceeded %d", iType);
|
||||
ch->OnStoneQueueRefineResult(true);
|
||||
|
||||
LogManager::instance().RefineLog(ch->GetPlayerID(), item->GetName(), item->GetID(), item->GetRefineLevel(), 1, way);
|
||||
}
|
||||
@@ -1040,6 +1041,7 @@ void NotifyRefineFail(LPCHARACTER ch, LPITEM item, const char* way, int iType, i
|
||||
if (NULL != ch && NULL != item)
|
||||
{
|
||||
ch->ChatPacket(CHAT_TYPE_COMMAND, "RefineFailed %d", iType);
|
||||
ch->OnStoneQueueRefineResult(false);
|
||||
|
||||
LogManager::instance().RefineLog(ch->GetPlayerID(), item->GetName(), item->GetID(), item->GetRefineLevel(), success, way);
|
||||
}
|
||||
|
||||
@@ -210,6 +210,7 @@ ACMD(do_special_item);
|
||||
ACMD(do_biolog_submit);
|
||||
ACMD(do_teleport_system);
|
||||
ACMD(do_autopickup);
|
||||
ACMD(do_stone_queue);
|
||||
|
||||
ACMD(do_click_mall);
|
||||
|
||||
@@ -469,6 +470,7 @@ struct command_info cmd_info[] =
|
||||
{ "biolog_submit", do_biolog_submit, 0, POS_DEAD, GM_PLAYER },
|
||||
{ "teleport_system", do_teleport_system, 0, POS_DEAD, GM_PLAYER },
|
||||
{ "autopickup", do_autopickup, 0, POS_DEAD, GM_PLAYER },
|
||||
{ "stone_queue", do_stone_queue, 0, POS_DEAD, GM_PLAYER },
|
||||
{ "siege", do_siege, 0, POS_DEAD, GM_LOW_WIZARD },
|
||||
{ "temp", do_temp, 0, POS_DEAD, GM_IMPLEMENTOR },
|
||||
{ "frog", do_frog, 0, POS_DEAD, GM_HIGH_WIZARD },
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "stdafx.h"
|
||||
#include <sodium.h>
|
||||
#include <set>
|
||||
|
||||
#include "utils.h"
|
||||
#include "config.h"
|
||||
@@ -1963,6 +1964,85 @@ ACMD(do_autopickup)
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("Usage: /autopickup [sync|enable|mode|mask]"));
|
||||
}
|
||||
|
||||
ACMD(do_stone_queue)
|
||||
{
|
||||
char arg1[256];
|
||||
argument = one_argument(argument, arg1, sizeof(arg1));
|
||||
|
||||
if (!*arg1 || !strcmp(arg1, "sync"))
|
||||
{
|
||||
ch->SendStoneQueueState();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!strcmp(arg1, "cancel"))
|
||||
{
|
||||
ch->CancelStoneQueue();
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(arg1, "start"))
|
||||
{
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("Usage: /stone_queue [sync|cancel|start]"));
|
||||
return;
|
||||
}
|
||||
|
||||
char scrollArg[256];
|
||||
argument = one_argument(argument, scrollArg, sizeof(scrollArg));
|
||||
|
||||
int scrollCell = -1;
|
||||
str_to_number(scrollCell, scrollArg);
|
||||
if (scrollCell < 0 || scrollCell >= INVENTORY_MAX_NUM)
|
||||
{
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("Invalid stone queue scroll slot."));
|
||||
return;
|
||||
}
|
||||
|
||||
LPITEM scrollItem = ch->GetInventoryItem(scrollCell);
|
||||
if (!scrollItem || scrollItem->GetType() != ITEM_USE || scrollItem->GetSubType() != USE_TUNING)
|
||||
{
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("Invalid stone queue scroll item."));
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<BYTE> slots;
|
||||
std::set<int> uniqueSlots;
|
||||
char slotArg[256];
|
||||
|
||||
while (*argument)
|
||||
{
|
||||
argument = one_argument(argument, slotArg, sizeof(slotArg));
|
||||
if (!*slotArg)
|
||||
break;
|
||||
|
||||
int slot = -1;
|
||||
str_to_number(slot, slotArg);
|
||||
if (slot < 0 || slot >= INVENTORY_MAX_NUM)
|
||||
continue;
|
||||
|
||||
if (uniqueSlots.find(slot) != uniqueSlots.end())
|
||||
continue;
|
||||
|
||||
LPITEM targetItem = ch->GetInventoryItem(slot);
|
||||
if (!targetItem || targetItem->GetType() != ITEM_METIN)
|
||||
continue;
|
||||
|
||||
if (slots.size() >= static_cast<size_t>(ch->GetStoneQueueMax()))
|
||||
break;
|
||||
|
||||
uniqueSlots.insert(slot);
|
||||
slots.push_back(static_cast<BYTE>(slot));
|
||||
}
|
||||
|
||||
if (slots.empty())
|
||||
{
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("Stone queue is empty."));
|
||||
return;
|
||||
}
|
||||
|
||||
ch->StartStoneQueue(slots, static_cast<BYTE>(scrollCell));
|
||||
}
|
||||
|
||||
ACMD(do_in_game_mall)
|
||||
{
|
||||
if (LC_IsYMIR() == true || LC_IsKorea() == true)
|
||||
|
||||
Reference in New Issue
Block a user