Harden melee sync authority
This commit is contained in:
@@ -24,6 +24,27 @@
|
||||
|
||||
int battle_hit(LPCHARACTER ch, LPCHARACTER victim, int & iRetDam);
|
||||
|
||||
namespace
|
||||
{
|
||||
bool battle_melee_angle_valid(LPCHARACTER ch, LPCHARACTER victim, int distance, int maxDistance, float* outRotDelta)
|
||||
{
|
||||
if (!ch || !victim || !ch->IsPC() || victim->IsBuilding())
|
||||
return true;
|
||||
|
||||
if (distance <= 170)
|
||||
return true;
|
||||
|
||||
const float desiredRotation = GetDegreeFromPositionXY(ch->GetX(), ch->GetY(), victim->GetX(), victim->GetY());
|
||||
const float rotDelta = fabs(GetDegreeDelta(ch->GetRotation(), desiredRotation));
|
||||
|
||||
if (outRotDelta)
|
||||
*outRotDelta = rotDelta;
|
||||
|
||||
const float allowedDelta = distance >= MAX(220, maxDistance - 40) ? 95.0f : 120.0f;
|
||||
return rotDelta <= allowedDelta;
|
||||
}
|
||||
}
|
||||
|
||||
bool battle_distance_valid_by_xy(long x, long y, long tx, long ty)
|
||||
{
|
||||
long distance = DISTANCE_APPROX(x - tx, y - ty);
|
||||
@@ -160,6 +181,25 @@ int battle_melee_attack(LPCHARACTER ch, LPCHARACTER victim)
|
||||
|
||||
return BATTLE_NONE;
|
||||
}
|
||||
|
||||
float rotDelta = 0.0f;
|
||||
if (!battle_melee_angle_valid(ch, victim, distance, max, &rotDelta))
|
||||
{
|
||||
char szDetail[160];
|
||||
snprintf(szDetail,
|
||||
sizeof(szDetail),
|
||||
"rot_delta=%.1f distance=%d max=%d victim=%u",
|
||||
rotDelta,
|
||||
distance,
|
||||
max,
|
||||
victim->GetVID());
|
||||
ch->RecordAntiCheatViolation("MELEE_ANGLE", rotDelta > 140.0f ? 18 : 8, szDetail, rotDelta > 140.0f);
|
||||
|
||||
if (test_server)
|
||||
sys_log(0, "MELEE_ANGLE: %s rot_delta=%.1f distance=%d max=%d", ch->GetName(), rotDelta, distance, max);
|
||||
|
||||
return BATTLE_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
if (timed_event_cancel(ch))
|
||||
@@ -176,6 +216,10 @@ int battle_melee_attack(LPCHARACTER ch, LPCHARACTER victim)
|
||||
|
||||
int dam;
|
||||
int ret = battle_hit(ch, victim, dam);
|
||||
|
||||
if ((ret == BATTLE_DAMAGE || ret == BATTLE_DEAD) && ch->IsPC() && victim->IsPC())
|
||||
victim->LockSyncOwner(450);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
|
||||
@@ -189,6 +189,7 @@ void CHARACTER::Initialize()
|
||||
m_pkDestroyWhenIdleEvent = NULL;
|
||||
|
||||
m_pkChrSyncOwner = NULL;
|
||||
m_dwSyncOwnerLockExpire = 0;
|
||||
|
||||
memset(&m_points, 0, sizeof(m_points));
|
||||
memset(&m_pointsInstant, 0, sizeof(m_pointsInstant));
|
||||
@@ -4317,6 +4318,7 @@ bool CHARACTER::SetSyncOwner(LPCHARACTER ch, bool bRemoveFromList)
|
||||
|
||||
// 리스트에서 제거하지 않더라도 포인터는 NULL로 셋팅되어야 한다.
|
||||
m_pkChrSyncOwner = NULL;
|
||||
m_dwSyncOwnerLockExpire = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -4345,6 +4347,7 @@ bool CHARACTER::SetSyncOwner(LPCHARACTER ch, bool bRemoveFromList)
|
||||
|
||||
m_pkChrSyncOwner = ch;
|
||||
m_pkChrSyncOwner->m_kLst_pkChrSyncOwned.push_back(this);
|
||||
m_dwSyncOwnerLockExpire = 0;
|
||||
|
||||
// SyncOwner가 바뀌면 LastSyncTime을 초기화한다.
|
||||
static const timeval zero_tv = {0, 0};
|
||||
@@ -4401,6 +4404,28 @@ bool CHARACTER::IsSyncOwner(LPCHARACTER ch) const
|
||||
return false;
|
||||
}
|
||||
|
||||
void CHARACTER::LockSyncOwner(DWORD dwDurationMs)
|
||||
{
|
||||
if (!m_pkChrSyncOwner || !dwDurationMs)
|
||||
return;
|
||||
|
||||
const DWORD dwNow = get_dword_time();
|
||||
const DWORD dwExpire = dwNow + dwDurationMs;
|
||||
|
||||
if (m_dwSyncOwnerLockExpire < dwExpire)
|
||||
m_dwSyncOwnerLockExpire = dwExpire;
|
||||
}
|
||||
|
||||
bool CHARACTER::IsSyncOwnerLocked() const
|
||||
{
|
||||
return m_pkChrSyncOwner && get_dword_time() < m_dwSyncOwnerLockExpire;
|
||||
}
|
||||
|
||||
bool CHARACTER::IsSyncOwnerLockedFor(LPCHARACTER ch) const
|
||||
{
|
||||
return ch && m_pkChrSyncOwner == ch && get_dword_time() < m_dwSyncOwnerLockExpire;
|
||||
}
|
||||
|
||||
void CHARACTER::SetParty(LPPARTY pkParty)
|
||||
{
|
||||
if (pkParty == m_pkParty)
|
||||
|
||||
@@ -829,6 +829,10 @@ class CHARACTER : public CEntity, public CFSM, public CHorseRider
|
||||
|
||||
bool SetSyncOwner(LPCHARACTER ch, bool bRemoveFromList = true);
|
||||
bool IsSyncOwner(LPCHARACTER ch) const;
|
||||
LPCHARACTER GetSyncOwner() const { return m_pkChrSyncOwner; }
|
||||
void LockSyncOwner(DWORD dwDurationMs);
|
||||
bool IsSyncOwnerLocked() const;
|
||||
bool IsSyncOwnerLockedFor(LPCHARACTER ch) const;
|
||||
|
||||
bool WarpSet(long x, long y, long lRealMapIndex = 0);
|
||||
void SetWarpLocation(long lMapIndex, long x, long y);
|
||||
@@ -852,6 +856,7 @@ class CHARACTER : public CEntity, public CFSM, public CHorseRider
|
||||
|
||||
float m_fSyncTime;
|
||||
LPCHARACTER m_pkChrSyncOwner;
|
||||
DWORD m_dwSyncOwnerLockExpire;
|
||||
CHARACTER_LIST m_kLst_pkChrSyncOwned; // 내가 SyncOwner인 자들
|
||||
|
||||
PIXEL_POSITION m_posDest;
|
||||
|
||||
@@ -1580,12 +1580,35 @@ void CInputMain::Move(LPCHARACTER ch, const char * data)
|
||||
// FUNC_SKILL = 0x80,
|
||||
//};
|
||||
|
||||
const float fDist = DISTANCE_SQRT((ch->GetX() - pinfo->lX) / 100, (ch->GetY() - pinfo->lY) / 100);
|
||||
|
||||
if (ch->IsPC() && ch->IsSyncOwnerLocked() && ch->GetSyncOwner() && ch->GetSyncOwner() != ch && fDist > 2.5f)
|
||||
{
|
||||
char szDetail[192];
|
||||
snprintf(szDetail,
|
||||
sizeof(szDetail),
|
||||
"func=%u dist=%.1f owner=%s cur=(%ld,%ld) dst=(%ld,%ld)",
|
||||
pinfo->bFunc,
|
||||
fDist,
|
||||
ch->GetSyncOwner()->GetName(),
|
||||
static_cast<long>(ch->GetX()),
|
||||
static_cast<long>(ch->GetY()),
|
||||
static_cast<long>(pinfo->lX),
|
||||
static_cast<long>(pinfo->lY));
|
||||
if (fDist > 8.0f)
|
||||
ch->RecordAntiCheatViolation("SYNC_LOCK_MOVE", 8, szDetail, true);
|
||||
else
|
||||
sys_log(1, "SYNC_LOCK_MOVE: %s %s", ch->GetName(), szDetail);
|
||||
|
||||
ch->Show(ch->GetMapIndex(), ch->GetX(), ch->GetY(), ch->GetZ());
|
||||
ch->Stop();
|
||||
return;
|
||||
}
|
||||
|
||||
// 텔레포트 핵 체크
|
||||
|
||||
// if (!test_server) //2012.05.15 김용욱 : 테섭에서 (무적상태로) 다수 몬스터 상대로 다운되면서 공격시 콤보핵으로 죽는 문제가 있었다.
|
||||
{
|
||||
const float fDist = DISTANCE_SQRT((ch->GetX() - pinfo->lX) / 100, (ch->GetY() - pinfo->lY) / 100);
|
||||
|
||||
if (((false == ch->IsRiding() && fDist > 25) || fDist > 40) && OXEVENT_MAP_INDEX != ch->GetMapIndex())
|
||||
{
|
||||
char szDetail[160];
|
||||
@@ -1916,6 +1939,21 @@ int CInputMain::SyncPosition(LPCHARACTER ch, const char * c_pcData, size_t uiByt
|
||||
continue;
|
||||
}
|
||||
|
||||
if (victim->IsSyncOwnerLocked() && !victim->IsSyncOwnerLockedFor(ch))
|
||||
{
|
||||
char szDetail[192];
|
||||
snprintf(szDetail,
|
||||
sizeof(szDetail),
|
||||
"victim=%s owner=%s requester=%s sync=(%ld,%ld)",
|
||||
victim->GetName(),
|
||||
victim->GetSyncOwner() ? victim->GetSyncOwner()->GetName() : "-",
|
||||
ch->GetName(),
|
||||
static_cast<long>(e->lX),
|
||||
static_cast<long>(e->lY));
|
||||
ch->RecordAntiCheatViolation("SYNC_OWNER_STEAL", 4, szDetail);
|
||||
continue;
|
||||
}
|
||||
|
||||
// 소유권 검사
|
||||
if (!victim->SetSyncOwner(ch))
|
||||
continue;
|
||||
|
||||
Reference in New Issue
Block a user