diff --git a/src/game/src/input_main.cpp b/src/game/src/input_main.cpp index a97934b..32fecde 100644 --- a/src/game/src/input_main.cpp +++ b/src/game/src/input_main.cpp @@ -1243,258 +1243,6 @@ void CInputMain::Position(LPCHARACTER ch, const char * data) } } -static const int ComboSequenceBySkillLevel[3][8] = -{ - // 0 1 2 3 4 5 6 7 - { 14, 15, 16, 17, 0, 0, 0, 0 }, - { 14, 15, 16, 18, 20, 0, 0, 0 }, - { 14, 15, 16, 18, 19, 17, 0, 0 }, -}; - -#define COMBO_HACK_ALLOWABLE_MS 100 - -// [2013 09 11 CYH] -DWORD ClacValidComboInterval( LPCHARACTER ch, BYTE bArg ) -{ - int nInterval = 300; - float fAdjustNum = 1.5f; // 일반 유저가 speed hack 에 걸리는 것을 막기 위해. 2013.09.10 CYH - - if( !ch ) - { - SPDLOG_ERROR("ClacValidComboInterval() ch is NULL"); - return nInterval; - } - - if( bArg == 13 ) - { - float normalAttackDuration = CMotionManager::instance().GetNormalAttackDuration(ch->GetRaceNum()); - nInterval = (int) (normalAttackDuration / (((float) ch->GetPoint(POINT_ATT_SPEED) / 100.f) * 900.f) + fAdjustNum ); - } - else if( bArg == 14 ) - { - nInterval = (int)(ani_combo_speed(ch, 1 ) / ((ch->GetPoint(POINT_ATT_SPEED) / 100.f) + fAdjustNum) ); - } - else if( bArg > 14 && bArg << 22 ) - { - nInterval = (int)(ani_combo_speed(ch, bArg - 13 ) / ((ch->GetPoint(POINT_ATT_SPEED) / 100.f) + fAdjustNum) ); - } - else - { - SPDLOG_ERROR("ClacValidComboInterval() Invalid bArg({}) ch({})", bArg, ch->GetName() ); - } - - return nInterval; -} - -bool CheckComboHack(LPCHARACTER ch, BYTE bArg, DWORD dwTime, bool CheckSpeedHack) -{ - // 죽거나 기절 상태에서는 공격할 수 없으므로, skip한다. - // 이렇게 하지 말고, CHRACTER::CanMove()에 - // if (IsStun() || IsDead()) return false; - // 를 추가하는게 맞다고 생각하나, - // 이미 다른 부분에서 CanMove()는 IsStun(), IsDead()과 - // 독립적으로 체크하고 있기 때문에 수정에 의한 영향을 - // 최소화하기 위해 이렇게 땜빵 코드를 써놓는다. - if (ch->IsStun() || ch->IsDead()) - return false; - int ComboInterval = dwTime - ch->GetLastComboTime(); - int HackScalar = 0; // 기본 스칼라 단위 1 - - // [2013 09 11 CYH] debugging log - /*SPDLOG_DEBUG("COMBO_TEST_LOG: {} arg:{} interval:{} valid:{} atkspd:{} riding:{}", - ch->GetName(), - bArg, - ComboInterval, - ch->GetValidComboInterval(), - ch->GetPoint(POINT_ATT_SPEED), - ch->IsRiding() ? "yes" : "no");*/ - -#if 0 - SPDLOG_DEBUG("COMBO: {} arg:{} seq:{} delta:{} checkspeedhack:{}", - ch->GetName(), bArg, ch->GetComboSequence(), ComboInterval - ch->GetValidComboInterval(), CheckSpeedHack); -#endif - // bArg 14 ~ 21번 까지 총 8콤보 가능 - // 1. 첫 콤보(14)는 일정 시간 이후에 반복 가능 - // 2. 15 ~ 21번은 반복 불가능 - // 3. 차례대로 증가한다. - if (bArg == 14) - { - if (CheckSpeedHack && ComboInterval > 0 && ComboInterval < ch->GetValidComboInterval() - COMBO_HACK_ALLOWABLE_MS) - { - // FIXME 첫번째 콤보는 이상하게 빨리 올 수가 있어서 300으로 나눔 -_-; - // 다수의 몬스터에 의해 다운되는 상황에서 공격을 하면 - // 첫번째 콤보가 매우 적은 인터벌로 들어오는 상황 발생. - // 이로 인해 콤보핵으로 튕기는 경우가 있어 다음 코드 비 활성화. - //HackScalar = 1 + (ch->GetValidComboInterval() - ComboInterval) / 300; - - //SPDLOG_WARN("COMBO_HACK: 2 {} arg:{} interval:{} valid:{} atkspd:{} riding:{}", - // ch->GetName(), - // bArg, - // ComboInterval, - // ch->GetValidComboInterval(), - // ch->GetPoint(POINT_ATT_SPEED), - // ch->IsRiding() ? "yes" : "no"); - } - - ch->SetComboSequence(1); - // 2013 09 11 CYH edited - //ch->SetValidComboInterval((int) (ani_combo_speed(ch, 1) / (ch->GetPoint(POINT_ATT_SPEED) / 100.f))); - ch->SetValidComboInterval( ClacValidComboInterval(ch, bArg) ); - ch->SetLastComboTime(dwTime); - } - else if (bArg > 14 && bArg < 22) - { - int idx = std::min(2, ch->GetComboIndex()); - - if (ch->GetComboSequence() > 5) // 현재 6콤보 이상은 없다. - { - HackScalar = 1; - ch->SetValidComboInterval(300); - SPDLOG_WARN("COMBO_HACK: 5 {} combo_seq:{}", ch->GetName(), ch->GetComboSequence()); - } - // 자객 쌍수 콤보 예외처리 - else if (bArg == 21 && - idx == 2 && - ch->GetComboSequence() == 5 && - ch->GetJob() == JOB_ASSASSIN && - ch->GetWear(WEAR_WEAPON) && - ch->GetWear(WEAR_WEAPON)->GetSubType() == WEAPON_DAGGER) - ch->SetValidComboInterval(300); - else if (ComboSequenceBySkillLevel[idx][ch->GetComboSequence()] != bArg) - { - HackScalar = 1; - ch->SetValidComboInterval(300); - - SPDLOG_WARN("COMBO_HACK: 3 {} arg:{} valid:{} combo_idx:{} combo_seq:{}", - ch->GetName(), - bArg, - ComboSequenceBySkillLevel[idx][ch->GetComboSequence()], - idx, - ch->GetComboSequence()); - } - else - { - if (CheckSpeedHack && ComboInterval < ch->GetValidComboInterval() - COMBO_HACK_ALLOWABLE_MS) - { - HackScalar = 1 + (ch->GetValidComboInterval() - ComboInterval) / 100; - - SPDLOG_WARN("COMBO_HACK: 2 {} arg:{} interval:{} valid:{} atkspd:{} riding:{}", - ch->GetName(), - bArg, - ComboInterval, - ch->GetValidComboInterval(), - ch->GetPoint(POINT_ATT_SPEED), - ch->IsRiding() ? "yes" : "no"); - } - - // 말을 탔을 때는 15번 ~ 16번을 반복한다 - //if (ch->IsHorseRiding()) - if (ch->IsRiding()) - ch->SetComboSequence(ch->GetComboSequence() == 1 ? 2 : 1); - else - ch->SetComboSequence(ch->GetComboSequence() + 1); - - // 2013 09 11 CYH edited - //ch->SetValidComboInterval((int) (ani_combo_speed(ch, bArg - 13) / (ch->GetPoint(POINT_ATT_SPEED) / 100.f))); - ch->SetValidComboInterval( ClacValidComboInterval(ch, bArg) ); - ch->SetLastComboTime(dwTime); - } - } - else if (bArg == 13) // 기본 공격 (둔갑(Polymorph)했을 때 온다) - { - if (CheckSpeedHack && ComboInterval > 0 && ComboInterval < ch->GetValidComboInterval() - COMBO_HACK_ALLOWABLE_MS) - { - // 다수의 몬스터에 의해 다운되는 상황에서 공격을 하면 - // 첫번째 콤보가 매우 적은 인터벌로 들어오는 상황 발생. - // 이로 인해 콤보핵으로 튕기는 경우가 있어 다음 코드 비 활성화. - //HackScalar = 1 + (ch->GetValidComboInterval() - ComboInterval) / 100; - - //SPDLOG_WARN("COMBO_HACK: 6 {} arg:{} interval:{} valid:{} atkspd:{}", - // ch->GetName(), - // bArg, - // ComboInterval, - // ch->GetValidComboInterval(), - // ch->GetPoint(POINT_ATT_SPEED)); - } - - if (ch->GetRaceNum() >= MAIN_RACE_MAX_NUM) - { - // POLYMORPH_BUG_FIX - - // DELETEME - /* - const CMotion * pkMotion = CMotionManager::instance().GetMotion(ch->GetRaceNum(), MAKE_MOTION_KEY(MOTION_MODE_GENERAL, MOTION_NORMAL_ATTACK)); - - if (!pkMotion) - SPDLOG_ERROR("cannot find motion by race {}", ch->GetRaceNum()); - else - { - // 정상적 계산이라면 1000.f를 곱해야 하지만 클라이언트가 애니메이션 속도의 90%에서 - // 다음 애니메이션 블렌딩을 허용하므로 900.f를 곱한다. - int k = (int) (pkMotion->GetDuration() / ((float) ch->GetPoint(POINT_ATT_SPEED) / 100.f) * 900.f); - ch->SetValidComboInterval(k); - ch->SetLastComboTime(dwTime); - } - */ - - // 2013 09 11 CYH edited - //float normalAttackDuration = CMotionManager::instance().GetNormalAttackDuration(ch->GetRaceNum()); - //int k = (int) (normalAttackDuration / ((float) ch->GetPoint(POINT_ATT_SPEED) / 100.f) * 900.f); - //ch->SetValidComboInterval(k); - ch->SetValidComboInterval( ClacValidComboInterval(ch, bArg) ); - ch->SetLastComboTime(dwTime); - // END_OF_POLYMORPH_BUG_FIX - } - else - { - // 말이 안되는 콤보가 왔다 해커일 가능성? - //if (ch->GetDesc()->DelayedDisconnect(Random::get(2, 9))) - //{ - // LogManager::instance().HackLog("Hacker", ch); - // SPDLOG_WARN("HACKER: {} arg {}", ch->GetName(), bArg); - //} - - // 위 코드로 인해, 폴리모프를 푸는 중에 공격 하면, - // 가끔 핵으로 인식하는 경우가 있다. - - // 자세히 말혀면, - // 서버에서 poly 0를 처리했지만, - // 클라에서 그 패킷을 받기 전에, 몹을 공격. <- 즉, 몹인 상태에서 공격. - // - // 그러면 클라에서는 서버에 몹 상태로 공격했다는 커맨드를 보내고 (arg == 13) - // - // 서버에서는 race는 인간인데 공격형태는 몹인 놈이다! 라고 하여 핵체크를 했다. - - // 사실 공격 패턴에 대한 것은 클라이언트에서 판단해서 보낼 것이 아니라, - // 서버에서 판단해야 할 것인데... 왜 이렇게 해놨을까... - // by rtsummit - } - } - else - { - // 말이 안되는 콤보가 왔다 해커일 가능성? - if (ch->GetDesc()->DelayedDisconnect(Random::get(2, 9))) - { - LogManager::instance().HackLog("Hacker", ch); - SPDLOG_WARN("HACKER: {} arg {}", ch->GetName(), bArg); - } - - HackScalar = 10; - ch->SetValidComboInterval(300); - } - - if (HackScalar) - { - // 말에 타거나 내렸을 때 1.5초간 공격은 핵으로 간주하지 않되 공격력은 없게 하는 처리 - if (get_dword_time() - ch->GetLastMountTime() > 1500) - ch->IncreaseComboHackCount(1 + HackScalar); - - ch->SkipComboAttackByTime(ch->GetValidComboInterval()); - } - - return HackScalar; -} - void CInputMain::Move(LPCHARACTER ch, const char * data) { if (!ch->CanMove()) @@ -1508,68 +1256,16 @@ void CInputMain::Move(LPCHARACTER ch, const char * data) return; } - //enum EMoveFuncType - //{ - // FUNC_WAIT, - // FUNC_MOVE, - // FUNC_ATTACK, - // FUNC_COMBO, - // FUNC_MOB_SKILL, - // _FUNC_SKILL, - // FUNC_MAX_NUM, - // FUNC_SKILL = 0x80, - //}; + // Check for teleportation hacks + const float fDist = DISTANCE_SQRT((ch->GetX() - pinfo->lX) / 100, (ch->GetY() - pinfo->lY) / 100); - // 텔레포트 핵 체크 - -// if (!test_server) //2012.05.15 김용욱 : 테섭에서 (무적상태로) 다수 몬스터 상대로 다운되면서 공격시 콤보핵으로 죽는 문제가 있었다. + if (((false == ch->IsRiding() && fDist > 25) || fDist > 40) && OXEVENT_MAP_INDEX != ch->GetMapIndex()) { - const float fDist = DISTANCE_SQRT((ch->GetX() - pinfo->lX) / 100, (ch->GetY() - pinfo->lY) / 100); + SPDLOG_WARN("MOVE: {} trying to move too far (dist: {:.1f}m) Riding({})", ch->GetName(), fDist, ch->IsRiding()); - if (((false == ch->IsRiding() && fDist > 25) || fDist > 40) && OXEVENT_MAP_INDEX != ch->GetMapIndex()) - { - SPDLOG_WARN("MOVE: {} trying to move too far (dist: {:.1f}m) Riding({})", ch->GetName(), fDist, ch->IsRiding()); - - ch->Show(ch->GetMapIndex(), ch->GetX(), ch->GetY(), ch->GetZ()); - ch->Stop(); - return; - } - - // - // 스피드핵(SPEEDHACK) Check - // - DWORD dwCurTime = get_dword_time(); - // 시간을 Sync하고 7초 후 부터 검사한다. (20090702 이전엔 5초였음) - bool CheckSpeedHack = (false == ch->GetDesc()->IsHandshaking() && dwCurTime - ch->GetDesc()->GetClientTime() > 7000); - - if (CheckSpeedHack) - { - int iDelta = (int) (pinfo->dwTime - ch->GetDesc()->GetClientTime()); - int iServerDelta = (int) (dwCurTime - ch->GetDesc()->GetClientTime()); - - iDelta = (int) (dwCurTime - pinfo->dwTime); - - // 시간이 늦게간다. 일단 로그만 해둔다. 진짜 이런 사람들이 많은지 체크해야함. TODO - if (iDelta >= 30000) - { - SPDLOG_WARN("SPEEDHACK: slow timer name {} delta {}", ch->GetName(), iDelta); - ch->GetDesc()->DelayedDisconnect(3); - } - // 1초에 20msec 빨리 가는거 까지는 이해한다. - else if (iDelta < -(iServerDelta / 50)) - { - SPDLOG_WARN("SPEEDHACK: DETECTED! {} (delta {} {})", ch->GetName(), iDelta, iServerDelta); - ch->GetDesc()->DelayedDisconnect(3); - } - } - - // - // 콤보핵 및 스피드핵 체크 - // - if (pinfo->bFunc == FUNC_COMBO && g_bCheckMultiHack) - { - CheckComboHack(ch, pinfo->bArg, pinfo->dwTime, CheckSpeedHack); // 콤보 체크 - } + ch->Show(ch->GetMapIndex(), ch->GetX(), ch->GetY(), ch->GetZ()); + ch->Stop(); + return; } if (pinfo->bFunc == FUNC_MOVE) @@ -1637,30 +1333,17 @@ void CInputMain::Move(LPCHARACTER ch, const char * data) pack.dwDuration = (pinfo->bFunc == FUNC_MOVE) ? ch->GetCurrentMoveDuration() : 0; ch->PacketAround(&pack, sizeof(TPacketGCMove), ch); -/* - if (pinfo->dwTime == 10653691) // 디버거 발견 - { - if (ch->GetDesc()->DelayedDisconnect(Random::get(15, 30))) - LogManager::instance().HackLog("Debugger", ch); - } - else if (pinfo->dwTime == 10653971) // Softice 발견 - { - if (ch->GetDesc()->DelayedDisconnect(Random::get(15, 30))) - LogManager::instance().HackLog("Softice", ch); - } -*/ - /* SPDLOG_TRACE( - "MOVE: {} Func:{} Arg:{} Pos:{}x{} Time:{} Dist:{:.1f}", - ch->GetName(), - pinfo->bFunc, - pinfo->bArg, - pinfo->lX / 100, - pinfo->lY / 100, - pinfo->dwTime, - fDist); - */ + "MOVE: {} Func:{} Arg:{} Pos:{}x{} Time:{} Dist:{:.1f}", + ch->GetName(), + pinfo->bFunc, + pinfo->bArg, + pinfo->lX / 100, + pinfo->lY / 100, + pinfo->dwTime, + fDist + ); } void CInputMain::Attack(LPCHARACTER ch, const BYTE header, const char* data)