Add pickup route telemetry
This commit is contained in:
@@ -140,6 +140,15 @@ void CHARACTER::Initialize()
|
||||
LastDropTime = 0;
|
||||
m_dwPickupWindowStart = 0;
|
||||
m_iPickupWindowCount = 0;
|
||||
m_dwPickupPatternWindowStart = 0;
|
||||
m_dwLastPickupPatternTime = 0;
|
||||
m_lLastPickupPatternX = 0;
|
||||
m_lLastPickupPatternY = 0;
|
||||
m_iPickupPatternSampleCount = 0;
|
||||
m_iPickupPatternMinIntervalMs = 0;
|
||||
m_iPickupPatternMaxIntervalMs = 0;
|
||||
m_iPickupPatternMinStep = 0;
|
||||
m_iPickupPatternMaxStep = 0;
|
||||
m_dwFishingWindowStart = 0;
|
||||
m_iFishingWindowCount = 0;
|
||||
m_lFishingStartX = 0;
|
||||
|
||||
@@ -2052,6 +2052,15 @@ class CHARACTER : public CEntity, public CFSM, public CHorseRider
|
||||
int CountDrops;
|
||||
DWORD m_dwPickupWindowStart;
|
||||
int m_iPickupWindowCount;
|
||||
DWORD m_dwPickupPatternWindowStart;
|
||||
DWORD m_dwLastPickupPatternTime;
|
||||
long m_lLastPickupPatternX;
|
||||
long m_lLastPickupPatternY;
|
||||
int m_iPickupPatternSampleCount;
|
||||
int m_iPickupPatternMinIntervalMs;
|
||||
int m_iPickupPatternMaxIntervalMs;
|
||||
int m_iPickupPatternMinStep;
|
||||
int m_iPickupPatternMaxStep;
|
||||
DWORD m_dwFishingWindowStart;
|
||||
int m_iFishingWindowCount;
|
||||
long m_lFishingStartX;
|
||||
|
||||
@@ -46,6 +46,12 @@
|
||||
namespace
|
||||
{
|
||||
constexpr int kRefineNpcMaxDistance = 2000;
|
||||
constexpr DWORD kPickupPatternWindowMs = 8 * 60 * 1000;
|
||||
constexpr int kPickupPatternMinSamples = 12;
|
||||
constexpr int kPickupPatternMaxIntervalSpreadMs = 180;
|
||||
constexpr int kPickupPatternMaxStepSpread = 220;
|
||||
constexpr int kPickupPatternMinRouteStep = 250;
|
||||
constexpr int kPickupPatternMaxIntervalMs = 15000;
|
||||
|
||||
bool ValidateStoredRefineNpc(LPCHARACTER ch, DWORD dwRefineNpcVID, const char* action)
|
||||
{
|
||||
@@ -92,6 +98,84 @@ namespace
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ResetPickupPatternWindow(LPCHARACTER ch, DWORD now, long x, long y)
|
||||
{
|
||||
ch->m_dwPickupPatternWindowStart = now;
|
||||
ch->m_dwLastPickupPatternTime = now;
|
||||
ch->m_lLastPickupPatternX = x;
|
||||
ch->m_lLastPickupPatternY = y;
|
||||
ch->m_iPickupPatternSampleCount = 0;
|
||||
ch->m_iPickupPatternMinIntervalMs = 0;
|
||||
ch->m_iPickupPatternMaxIntervalMs = 0;
|
||||
ch->m_iPickupPatternMinStep = 0;
|
||||
ch->m_iPickupPatternMaxStep = 0;
|
||||
}
|
||||
|
||||
void ObservePickupPattern(LPCHARACTER ch, DWORD now, long x, long y)
|
||||
{
|
||||
if (!ch)
|
||||
return;
|
||||
|
||||
if (0 == ch->m_dwPickupPatternWindowStart || now - ch->m_dwPickupPatternWindowStart >= kPickupPatternWindowMs)
|
||||
{
|
||||
ResetPickupPatternWindow(ch, now, x, y);
|
||||
return;
|
||||
}
|
||||
|
||||
const int iIntervalMs = static_cast<int>(now - ch->m_dwLastPickupPatternTime);
|
||||
const int iStep = DISTANCE_APPROX(x - ch->m_lLastPickupPatternX, y - ch->m_lLastPickupPatternY);
|
||||
|
||||
ch->m_dwLastPickupPatternTime = now;
|
||||
ch->m_lLastPickupPatternX = x;
|
||||
ch->m_lLastPickupPatternY = y;
|
||||
|
||||
if (iIntervalMs <= 0 || iIntervalMs > kPickupPatternMaxIntervalMs)
|
||||
{
|
||||
ResetPickupPatternWindow(ch, now, x, y);
|
||||
return;
|
||||
}
|
||||
|
||||
if (0 == ch->m_iPickupPatternSampleCount)
|
||||
{
|
||||
ch->m_iPickupPatternSampleCount = 1;
|
||||
ch->m_iPickupPatternMinIntervalMs = iIntervalMs;
|
||||
ch->m_iPickupPatternMaxIntervalMs = iIntervalMs;
|
||||
ch->m_iPickupPatternMinStep = iStep;
|
||||
ch->m_iPickupPatternMaxStep = iStep;
|
||||
return;
|
||||
}
|
||||
|
||||
++ch->m_iPickupPatternSampleCount;
|
||||
ch->m_iPickupPatternMinIntervalMs = MIN(ch->m_iPickupPatternMinIntervalMs, iIntervalMs);
|
||||
ch->m_iPickupPatternMaxIntervalMs = MAX(ch->m_iPickupPatternMaxIntervalMs, iIntervalMs);
|
||||
ch->m_iPickupPatternMinStep = MIN(ch->m_iPickupPatternMinStep, iStep);
|
||||
ch->m_iPickupPatternMaxStep = MAX(ch->m_iPickupPatternMaxStep, iStep);
|
||||
|
||||
if (ch->m_iPickupPatternSampleCount < kPickupPatternMinSamples)
|
||||
return;
|
||||
|
||||
const int iIntervalSpread = ch->m_iPickupPatternMaxIntervalMs - ch->m_iPickupPatternMinIntervalMs;
|
||||
const int iStepSpread = ch->m_iPickupPatternMaxStep - ch->m_iPickupPatternMinStep;
|
||||
if (iIntervalSpread > kPickupPatternMaxIntervalSpreadMs || iStepSpread > kPickupPatternMaxStepSpread || ch->m_iPickupPatternMaxStep < kPickupPatternMinRouteStep)
|
||||
return;
|
||||
|
||||
char szDetail[160];
|
||||
snprintf(szDetail,
|
||||
sizeof(szDetail),
|
||||
"samples=%d interval=%d..%d step=%d..%d",
|
||||
ch->m_iPickupPatternSampleCount,
|
||||
ch->m_iPickupPatternMinIntervalMs,
|
||||
ch->m_iPickupPatternMaxIntervalMs,
|
||||
ch->m_iPickupPatternMinStep,
|
||||
ch->m_iPickupPatternMaxStep);
|
||||
ch->RecordAntiCheatViolation("PICKUP_PATTERN",
|
||||
iIntervalSpread <= 100 && iStepSpread <= 140 ? 4 : 2,
|
||||
szDetail,
|
||||
iIntervalSpread <= 100 && iStepSpread <= 140);
|
||||
|
||||
ResetPickupPatternWindow(ch, now, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
const int ITEM_BROKEN_METIN_VNUM = 28960;
|
||||
@@ -5908,6 +5992,8 @@ bool CHARACTER::PickupItem(DWORD dwVID)
|
||||
return false;
|
||||
|
||||
const DWORD dwNow = get_dword_time();
|
||||
const long lPickupX = GetX();
|
||||
const long lPickupY = GetY();
|
||||
|
||||
if (m_dwPickupWindowStart == 0 || dwNow - m_dwPickupWindowStart >= 1000)
|
||||
{
|
||||
@@ -5990,6 +6076,7 @@ bool CHARACTER::PickupItem(DWORD dwVID)
|
||||
if (bCount == 0)
|
||||
{
|
||||
ItemGetPacket(item2->GetVnum(), item2->GetCount());
|
||||
ObservePickupPattern(this, dwNow, lPickupX, lPickupY);
|
||||
M2_DESTROY_ITEM(item);
|
||||
if (item2->GetType() == ITEM_QUEST)
|
||||
quest::CQuestManager::instance().PickupItem (GetPlayerID(), item2);
|
||||
@@ -6038,6 +6125,7 @@ bool CHARACTER::PickupItem(DWORD dwVID)
|
||||
}
|
||||
|
||||
//Motion(MOTION_PICKUP);
|
||||
ObservePickupPattern(this, dwNow, lPickupX, lPickupY);
|
||||
return true;
|
||||
}
|
||||
else if (item->HasOwnership())
|
||||
@@ -6110,6 +6198,7 @@ bool CHARACTER::PickupItem(DWORD dwVID)
|
||||
if (item->GetType() == ITEM_QUEST)
|
||||
quest::CQuestManager::instance().PickupItem (owner->GetPlayerID(), item);
|
||||
|
||||
ObservePickupPattern(this, dwNow, lPickupX, lPickupY);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user