Validate interaction NPCs for refine and cube
This commit is contained in:
@@ -1878,6 +1878,7 @@ class CHARACTER : public CEntity, public CFSM, public CHorseRider
|
||||
// by mhh
|
||||
LPITEM* GetCubeItem() { return m_pointsInstant.pCubeItems; }
|
||||
bool IsCubeOpen () const { return (m_pointsInstant.pCubeNpc?true:false); }
|
||||
LPCHARACTER GetCubeNpc() const { return m_pointsInstant.pCubeNpc; }
|
||||
void SetCubeNpc(LPCHARACTER npc) { m_pointsInstant.pCubeNpc = npc; }
|
||||
bool CanDoCube() const;
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "stdafx.h"
|
||||
#include "char.h"
|
||||
#include "utils.h"
|
||||
#include "item.h"
|
||||
#include "desc.h"
|
||||
#include "DragonSoul.h"
|
||||
@@ -150,5 +151,41 @@ bool CHARACTER::DragonSoul_RefineWindow_Close()
|
||||
|
||||
bool CHARACTER::DragonSoul_RefineWindow_CanRefine()
|
||||
{
|
||||
return NULL != m_pointsInstant.m_pDragonSoulRefineWindowOpener;
|
||||
}
|
||||
if (NULL == m_pointsInstant.m_pDragonSoulRefineWindowOpener)
|
||||
return false;
|
||||
|
||||
LPENTITY pOpener = m_pointsInstant.m_pDragonSoulRefineWindowOpener;
|
||||
if (!pOpener->IsType(ENTITY_CHARACTER))
|
||||
{
|
||||
RecordAntiCheatViolation("DRAGON_SOUL_REFINE", 6, "state=invalid_opener", true);
|
||||
m_pointsInstant.m_pDragonSoulRefineWindowOpener = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
LPCHARACTER npc = (LPCHARACTER)pOpener;
|
||||
if (!npc->IsNPC() || npc == this || npc->GetMapIndex() != GetMapIndex())
|
||||
{
|
||||
char szDetail[160];
|
||||
snprintf(szDetail,
|
||||
sizeof(szDetail),
|
||||
"npc=%u map=%ld npc_map=%ld",
|
||||
npc->GetVID(),
|
||||
static_cast<long>(GetMapIndex()),
|
||||
static_cast<long>(npc->GetMapIndex()));
|
||||
RecordAntiCheatViolation("DRAGON_SOUL_REFINE", 8, szDetail, true);
|
||||
m_pointsInstant.m_pDragonSoulRefineWindowOpener = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
const int iDistance = DISTANCE_APPROX(GetX() - npc->GetX(), GetY() - npc->GetY());
|
||||
if (iDistance > 2000)
|
||||
{
|
||||
char szDetail[160];
|
||||
snprintf(szDetail, sizeof(szDetail), "npc=%u distance=%d max=%d", npc->GetVID(), iDistance, 2000);
|
||||
RecordAntiCheatViolation("DRAGON_SOUL_REFINE", iDistance > 2800 ? 12 : 4, szDetail, iDistance > 2800);
|
||||
m_pointsInstant.m_pDragonSoulRefineWindowOpener = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -43,6 +43,57 @@
|
||||
#include "buff_on_attributes.h"
|
||||
#include "belt_inventory_helper.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
constexpr int kRefineNpcMaxDistance = 2000;
|
||||
|
||||
bool ValidateStoredRefineNpc(LPCHARACTER ch, DWORD dwRefineNpcVID, const char* action)
|
||||
{
|
||||
if (!ch)
|
||||
return false;
|
||||
|
||||
if (0 == dwRefineNpcVID)
|
||||
{
|
||||
char szDetail[128];
|
||||
snprintf(szDetail, sizeof(szDetail), "action=%s state=missing", action ? action : "-");
|
||||
ch->RecordAntiCheatViolation("REFINE_NPC", 8, szDetail, true);
|
||||
return false;
|
||||
}
|
||||
|
||||
LPCHARACTER npc = CHARACTER_MANAGER::instance().Find(dwRefineNpcVID);
|
||||
if (!npc || npc == ch || !npc->IsNPC() || npc->GetMapIndex() != ch->GetMapIndex())
|
||||
{
|
||||
char szDetail[160];
|
||||
snprintf(szDetail,
|
||||
sizeof(szDetail),
|
||||
"action=%s npc=%u map=%ld npc_map=%ld",
|
||||
action ? action : "-",
|
||||
dwRefineNpcVID,
|
||||
static_cast<long>(ch->GetMapIndex()),
|
||||
static_cast<long>(npc ? npc->GetMapIndex() : 0));
|
||||
ch->RecordAntiCheatViolation("REFINE_NPC", 8, szDetail, true);
|
||||
return false;
|
||||
}
|
||||
|
||||
const int iDistance = DISTANCE_APPROX(ch->GetX() - npc->GetX(), ch->GetY() - npc->GetY());
|
||||
if (iDistance > kRefineNpcMaxDistance)
|
||||
{
|
||||
char szDetail[160];
|
||||
snprintf(szDetail,
|
||||
sizeof(szDetail),
|
||||
"action=%s npc=%u distance=%d max=%d",
|
||||
action ? action : "-",
|
||||
dwRefineNpcVID,
|
||||
iDistance,
|
||||
kRefineNpcMaxDistance);
|
||||
ch->RecordAntiCheatViolation("REFINE_NPC", iDistance > kRefineNpcMaxDistance + 800 ? 12 : 4, szDetail, iDistance > kRefineNpcMaxDistance + 800);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
const int ITEM_BROKEN_METIN_VNUM = 28960;
|
||||
|
||||
// CHANGE_ITEM_ATTRIBUTES
|
||||
@@ -814,6 +865,12 @@ bool CHARACTER::DoRefine(LPITEM item, bool bMoneyOnly, int iType)
|
||||
ClearRefineMode();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ValidateStoredRefineNpc(this, m_dwRefineNPCVID, bMoneyOnly ? "money_only" : "normal"))
|
||||
{
|
||||
ClearRefineMode();
|
||||
return false;
|
||||
}
|
||||
|
||||
//개량 시간제한 : upgrade_refine_scroll.quest 에서 개량후 5분이내에 일반 개량을
|
||||
//진행할수 없음
|
||||
@@ -993,6 +1050,12 @@ bool CHARACTER::DoRefineWithScroll(LPITEM item, int iType)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ValidateStoredRefineNpc(this, m_dwRefineNPCVID, "scroll"))
|
||||
{
|
||||
ClearRefineMode();
|
||||
return false;
|
||||
}
|
||||
|
||||
ClearRefineMode();
|
||||
|
||||
//개량 시간제한 : upgrade_refine_scroll.quest 에서 개량후 5분이내에 일반 개량을
|
||||
|
||||
@@ -170,6 +170,69 @@ static bool FN_check_valid_npc( WORD vnum )
|
||||
return false;
|
||||
}
|
||||
|
||||
static void FN_close_cube_session(LPCHARACTER ch)
|
||||
{
|
||||
if (!ch)
|
||||
return;
|
||||
|
||||
LPITEM* cube_item = ch->GetCubeItem();
|
||||
for (int i = 0; i < CUBE_MAX_NUM; ++i)
|
||||
cube_item[i] = NULL;
|
||||
|
||||
ch->SetCubeNpc(NULL);
|
||||
ch->ChatPacket(CHAT_TYPE_COMMAND, "cube close");
|
||||
}
|
||||
|
||||
static bool FN_validate_cube_npc(LPCHARACTER ch, const char* action)
|
||||
{
|
||||
if (!ch || !ch->IsCubeOpen())
|
||||
return false;
|
||||
|
||||
LPCHARACTER npc = ch->GetCubeNpc();
|
||||
if (NULL == npc)
|
||||
{
|
||||
char szDetail[128];
|
||||
snprintf(szDetail, sizeof(szDetail), "action=%s state=missing", action ? action : "-");
|
||||
ch->RecordAntiCheatViolation("CUBE_NPC", 6, szDetail, true);
|
||||
FN_close_cube_session(ch);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!npc->IsNPC() || !FN_check_valid_npc(npc->GetRaceNum()) || npc->GetMapIndex() != ch->GetMapIndex())
|
||||
{
|
||||
char szDetail[160];
|
||||
snprintf(szDetail,
|
||||
sizeof(szDetail),
|
||||
"action=%s npc=%u map=%ld npc_map=%ld race=%u",
|
||||
action ? action : "-",
|
||||
npc->GetVID(),
|
||||
static_cast<long>(ch->GetMapIndex()),
|
||||
static_cast<long>(npc->GetMapIndex()),
|
||||
npc->GetRaceNum());
|
||||
ch->RecordAntiCheatViolation("CUBE_NPC", 8, szDetail, true);
|
||||
FN_close_cube_session(ch);
|
||||
return false;
|
||||
}
|
||||
|
||||
const long distance = DISTANCE_APPROX(ch->GetX() - npc->GetX(), ch->GetY() - npc->GetY());
|
||||
if (distance >= CUBE_MAX_DISTANCE)
|
||||
{
|
||||
char szDetail[160];
|
||||
snprintf(szDetail,
|
||||
sizeof(szDetail),
|
||||
"action=%s npc=%u distance=%ld max=%d",
|
||||
action ? action : "-",
|
||||
npc->GetVID(),
|
||||
distance,
|
||||
CUBE_MAX_DISTANCE);
|
||||
ch->RecordAntiCheatViolation("CUBE_NPC", distance >= CUBE_MAX_DISTANCE + 800 ? 12 : 4, szDetail, distance >= CUBE_MAX_DISTANCE + 800);
|
||||
FN_close_cube_session(ch);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// 큐브데이타가 올바르게 초기화 되었는지 체크한다.
|
||||
static bool FN_check_cube_data (CUBE_DATA *cube_data)
|
||||
{
|
||||
@@ -486,12 +549,10 @@ static bool FN_update_cube_status(LPCHARACTER ch)
|
||||
if (NULL == ch)
|
||||
return false;
|
||||
|
||||
if (!ch->IsCubeOpen())
|
||||
if (!FN_validate_cube_npc(ch, "status"))
|
||||
return false;
|
||||
|
||||
LPCHARACTER npc = ch->GetQuestNPC();
|
||||
if (NULL == npc)
|
||||
return false;
|
||||
LPCHARACTER npc = ch->GetCubeNpc();
|
||||
|
||||
CUBE_DATA* cube = FN_find_cube(ch->GetCubeItem(), npc->GetRaceNum());
|
||||
|
||||
@@ -525,11 +586,10 @@ bool Cube_make (LPCHARACTER ch)
|
||||
return false;
|
||||
}
|
||||
|
||||
npc = ch->GetQuestNPC();
|
||||
if (NULL == npc)
|
||||
{
|
||||
if (!FN_validate_cube_npc(ch, "make"))
|
||||
return false;
|
||||
}
|
||||
|
||||
npc = ch->GetCubeNpc();
|
||||
|
||||
items = ch->GetCubeItem();
|
||||
cube_proto = FN_find_cube(items, npc->GetRaceNum());
|
||||
@@ -613,6 +673,9 @@ void Cube_add_item (LPCHARACTER ch, int cube_index, int inven_index)
|
||||
|
||||
RETURN_IF_CUBE_IS_NOT_OPENED(ch);
|
||||
|
||||
if (!FN_validate_cube_npc(ch, "add_item"))
|
||||
return;
|
||||
|
||||
if (inven_index<0 || INVENTORY_MAX_NUM<=inven_index)
|
||||
return;
|
||||
if (cube_index<0 || CUBE_MAX_NUM<=cube_index)
|
||||
@@ -655,6 +718,9 @@ void Cube_delete_item (LPCHARACTER ch, int cube_index)
|
||||
|
||||
RETURN_IF_CUBE_IS_NOT_OPENED(ch);
|
||||
|
||||
if (!FN_validate_cube_npc(ch, "delete_item"))
|
||||
return;
|
||||
|
||||
if (cube_index<0 || CUBE_MAX_NUM<=cube_index) return;
|
||||
|
||||
cube_item = ch->GetCubeItem();
|
||||
@@ -876,10 +942,11 @@ void Cube_request_result_list(LPCHARACTER ch)
|
||||
{
|
||||
RETURN_IF_CUBE_IS_NOT_OPENED(ch);
|
||||
|
||||
LPCHARACTER npc = ch->GetQuestNPC();
|
||||
if (NULL == npc)
|
||||
if (!FN_validate_cube_npc(ch, "result_list"))
|
||||
return;
|
||||
|
||||
LPCHARACTER npc = ch->GetCubeNpc();
|
||||
|
||||
DWORD npcVNUM = npc->GetRaceNum();
|
||||
size_t resultCount = 0;
|
||||
|
||||
@@ -930,10 +997,11 @@ void Cube_request_material_info(LPCHARACTER ch, int requestStartIndex, int reque
|
||||
{
|
||||
RETURN_IF_CUBE_IS_NOT_OPENED(ch);
|
||||
|
||||
LPCHARACTER npc = ch->GetQuestNPC();
|
||||
if (NULL == npc)
|
||||
if (!FN_validate_cube_npc(ch, "material_info"))
|
||||
return;
|
||||
|
||||
LPCHARACTER npc = ch->GetCubeNpc();
|
||||
|
||||
DWORD npcVNUM = npc->GetRaceNum();
|
||||
std::string materialInfoText = "";
|
||||
|
||||
|
||||
Reference in New Issue
Block a user