4. 핵을 쓰는경우 어떻게 데이터에 남을까? (GOLD)

chaechae·2023년 5월 25일
0
post-thumbnail

이번에는 리그 오브 레전드 게임에서 핵을 쓰는 경우 입니다. 그 중에서 최근에 유행했던 GOLD 스크립트 핵과 관련해서 핵을 사용했을 때 어떻게 데이터가 남고 다른 유저들과 차이점이 있는지 분석해보려고 합니다.

✔️ MOBA와 RPG속 재화(GOLD)의 가치?

빠르면 몇일, 몇달 내내 재화의 가치가 달라지는 RPG 장르의 GOLD (메이플의 메소 / 로스트아크의 실링, 골드, 크리스탈 등)와 리그 오브 레전드 같은 MOBA 장르의 게임 한 경기안에서 사용되는 GOLD는 아무래도 무게감의 차이가 있습니다. 그래서 MOBA게임과 RPG 게임에서의 재화와 관련된 데이터를 볼 때 다르게 바라봐야할까? 아예 다른거 아닌가..? 생각이 많이들었는데요.. MOBA 게임속에서의 GOLD를 어떻게 접근해야할까 어느정도 생각을 정리해봤습니다.

데이터도 적고 주기성을 갖는다고 하기에도 애매합니다.. 어떤 시세, 가격이 오르고 말고가 아니기 때문에 재화의 가치면에서 완전히 다르구요. 그래도 공통된 부분은 시계열 데이터이고 GOLD를 얻고 사용하는 패턴이 있을거라 생각했기 때문에 어느정도는 추세와 주기성이 남는다고 생각했습니다.

일단 이 정도 생각만 갖고 ! 일단 데이터를 봐봐야 알겠단 말이죠!!

핵을 쓰는 경우 결국은 운영진들이 잡아낼텐데. 과연 어떻게 잡을 수 있을까? 혹시 RIOT API에 제공되는 데이터만으로도 가능한지 확인해보기로 했습니다.

✔️ LOL에서의 GOLD

리그 오브 레전드에서 골드를 얻는 방법은 게임시작 후 1:50 이후부터 10초당 20.4골드씩 기본적으로 수급되고, 챔피언, CS, MONSTER, BUILDING, item 등등으로 인해 골드를 얻는 시스템입니다. (타워골드와 제압골드를 포함해서요)
그리고 위와같이 골드를 얻었을 때 모두 기록될텐데 말이죠🤔
RIOT API 에서 제가 발견한 GOLD에 관한 지표는 크게 다음과 같습니다.

  • CURRENT_GOLD
  • TOTAL_GOLD
  • GOLD_EARNED
  • GOLD_SPENT

CURRENT_GOLD

가장 중요하다고 생각하는 지표 입니다. 현재 시점에서 플레이어가 보유하고 있는 실시간 골드 양을 나타냅니다. 이 값은 게임 중에 계속해서 변할 수 있는데요. 예를 들어, 골드를 소비하거나 획득할 때마다 CURRENT_GOLD 값은 변경됩니다. 60초 1분기준으로 정리 되고 있었습니다.

저번 글에서 언급한 position 데이터와 같은 곳에 있습니다. match_data_log['info']['frames']

TOTAL_GOLD

유저의 전체 총 골드량을 시간별로 측정하고 있습니다. 골드를 소비했을 때는 제외하고 유저가 정말 얻은 골드의 전체량이라고 생각하시면 됩니다. 예를 들어 아래의 데이터에서 볼 수 있듯이

current gold는 현재 시점에서 플레이어가 보유하고 있는 실시간 골드.
total gold는 그시간 동안(까지) 유저가 얻은 총골드량이라고 보시면됩니다.

timestampcurrent goldtotal goldtypegold earndgold used
0350350
1650650CHAMPION_KILL300
250650ITEM_BUY600

GOLD_EARNED / GOLD_SPENT

마지막 timestamp에 찍힌 total_gold가 최종적으로 게임동안 얻은 골드가 됩니다.
그리고 gold_spent 유저가 사용한 골드 입니다. 흔히 게임이 끝나고 통계표에서 볼 수 있습니다.

✔️ 핵 유저의 DATA

일단 유저가 핵을 썼는지 안썼는지 차이점을 보려면 핵을 사용한 유저의 데이터를 찾아야합니다..굉장히 까다로웠는데 유튜브랑, 게임 커뮤니티를 뒤져서 찾았습니다. 보니까 이미 영구정지를 당한 상태이네요ㅎㅎ..

이번에는 바로 시각화를 해서 같이 보면 좋을것같아요
먼저, CURRENT GOLD 와 TOTAL GOLD를 streamlit 의 area chart를 이용해서 시각화 해봤습니다.

똑같이 데이터를 불러와주고 저번에 moving 이라고 저장해놓은 데이터프레임에서 gold 와 관련된 컬럼들만 다 가져온뒤, red팀과 blue팀을 구분해주었습니다.

그렇게한 이유는 10명의 유저를 다 한번에 보이면 너무 복잡하더라구요. 그래서 팀 선택을해서 데이터를 볼 수 있게 만들었습니다.

그리고 summonerName을 추가해줬는데요. 신고를 할 때 소환사 이름으로 하기도하고, participantId로 x축을 표현하면 누가 누군지 헷갈려서 소환사 이름별로 표현했습니다.

    gold = moving[['timestamp','participantId','currentGold','totalGold']]
    # teamid / summonerName 추가 (team 구분)
    gold['teamId'] = gold['participantId'].apply(lambda x: 'blue' if x <= 5 else 'red')
    gold_merge = gold.merge(champion_info[['participantId', 'summonerName']], on='participantId', how='left')
    gold_merge['timestamp'] = gold_merge['timestamp']/60000  # 분단위

    with st.container():
        st.header('GOLD')
        col1,col2 = st.columns(2)
        with col1:
            if hasattr(st.session_state, 'moving'):
                moving = st.session_state.moving
                st.subheader('current gold')
                st.caption('시간별로 유저의 gold값 변동을 확인할 수 있습니다')

                team_option = st.selectbox('Select team', ['blue', 'red'])

                filtered_gold = gold_merge[gold_merge['teamId'] == str(team_option)]
                pivot_gold = filtered_gold.pivot(index='timestamp', columns='summonerName')

                tab1, tab2  = st.tabs(['currentGold','totalGold'])
                with tab1:
                    st.area_chart(pivot_gold['currentGold'], use_container_width=True)
                with tab2:
                    st.line_chart(pivot_gold['totalGold'], use_container_width=True)```

일반유저의 current gold

먼저, 일반 유저들의 current gold 그래프입니다.

일반적인 매치의 데이터를 갖고 current gold의 모양세를 보면 보통 이렇습니다. "gold를 획득하고 gold를 사용하고 다시 획득하고 사용하고" 위아래로 반복되는 추세를 갖고 있죠.

핵유저의 current gold

반면에 골드핵의 사용한 유저의 current gold 그래프를 보면

누가봐도 비정상적인형태를 갖고 있습니다. 추세를 넘어서 완벽한 이상치 형태를 갖고 있죠. 허허.. 너무 대놓고 사용한것 같은데요. 그래프로만 봐로 비정상적인것을 알 수 있지만. 데이터로 한번 확인해보면 아래와 같습니다.

29분 이후부터 1분 동안 current gold가 total gold를 거의 3배이상 넘어섰습니다. 만약 정상적으로 gold를 획득했다면 total gold도 그만큼 증가해야하지만 current gold만 저렇게 증가했다는건 결국 비정상적인 행동이 있다고 판단할 수 있습니다.

게다가 최종 total gold는 오히려 blue팀들중에서 가장 낮습니다;;

✔️ 해당 구간에 어떤일이 발생한거지??

해당 유저가 비정상적인 행동을 했군.. 그렇다면 위 구간이 발생했을 때 무슨일이 발생했길래 저렇게 gold가 증가했을까? 궁금해서 데이터를 시각화해서 표현해봤습니다.

TYPE

저번에서도 보셨지만 events 안에는 생각보다 세세하게 유저들의 행동이 남아있습니다. gold를 어떻게 사용했는지 얻었는지도 말이죠. 그래서 해당 구간에 이상치가 발생했을 때, 어떤 로그들이 발생했는지 요약된 그래프를 대시보드에 추가했습니다.

여러 이벤트들이 발생했지만 위 유저의 경우 item을 거의 1분동안 100번이상 사고팔은 흔적을 확인 할 수 있습니다. timestamp를 보시면 굉장히 빠른 속도로 (서폿이 주로가는)와드석 아이템(조건 13렙)을 사고 판 흔적이 있네요. 스크립트핵을 사용한걸로 추정됩니다.

🚨 GOLD 핵 신고가 들어왔을 경우

그래서 골드핵과 관련된 신고가 들어온 경우 저는 다음과 같은 방법으로 처리했습니다.

(1) current GOLD 가 total GOLD 보다 많을수가 없음.
애초에 current gold가 total gold를 넘을 수 없으니 , 해당 구간이 있는지 확인하고 있는경우 그 시간대에 어떤 type 의 log가 남았는지 보여줍니다.

(2) 이동평균으로 이상치 탐지
그 다음은 이동평균입니다. 시계열 데이터의 이상치를 찾는데 보통 아래와 같은 방법이 있다고 했습니다. (게임 재화에서의 이상치 탐지 포스팅/NDC 을 참고했는데요!)

  • 기존 데이터 분포와 비교해 크게 벗어나는 데이터를 찾는 방법
    (평균, 분산을 이용한 탐지)
  • 추세가 있는 데이터에서 이상 데이터를 찾는 방법
    (이동 평균, 분산을 이용한 탐지)
  • 주기성이 있는 데이터에서 이상 데이터를 찾는 방법
    (시계열 분석 (STL)을 이용한 탐지)

그 중에서 이동평균을 이용해봤습니다. 한 매치안에서 이뤄지는 데이터이기 때문에 데이터가 그렇게 크지 않아 계절성을 갖는다고 하기에는 어렵다고 생각했습니다(골드를 얻고 사용하기 때문에 위아래로 패턴이 있지만..) 그래서 데이터량이 작고, 짧은 시간 동안의 변동성만을 가진다면 이동평균이 간단하고 효과적일 거라 생각했습니다.

(시계열 데이터를 다루는 부분은 새롭게 공부하게 된 내용이라 해당 부분에서는 공부가 더 필요한것 같습니다. 따로 공부해서 다시 정리해보겠습니다)

✔️ DASHBOARD - GOLD

GOLD 핵 관련 의심 신고가 들어온경우 위 두 거름망을 이용해 완성된 대시보드로 표현하면 다음과 같습니다.

한계점 / 배운점

✔️먼저, 시계열데이터를 다루는 부분에서 조금 애매하다 느꼈습니다.
위의 CASE의 경우 스크립트핵을 이용한 경우 current gold 와 total gold를 지표로 쉽게 발견할 수 있지만, 그게 아니라 이동평균을 통해 이상치를 탐지할때는 window size를 5로 thresh hold를 2로 정했는데요! 각 얼마로 정해야할지 기준이 애매했습니다. 어느정도가 크고 어느정도가 작은지 와닿지 않았고 데이터의 특성상 match 시간에 따라 크기가 정해지는데 , 이 크기에 따라 세밀하게 window size를 정해줘야하나 생각했습니다. 그렇게 큰 데이터가 아닌경우에도 쓰이는지 궁금하구요! 해당 부분에 공부할게 많네요

✔️ 또한 핵이외에 current gold가 눈에 띄게 확 증가하는 경우가 있었는데, 바로 아이템을 한번에 다 판매했을 때 급격하게 골드가 증가한 경우였습니다. 결국 이상치라고 판단되는 경우 해당 상황이 어땠는지 확인할 수 밖에 없었습니다. RPG 게임에서의 재화에서도 실제로 이상치라고 판단된 부분이 불법 프로그램으로 인한게 아니라 특정 이벤트 기간이나 시간(밤/낮)에 생기는 경우가 있다고 배웠습니다. 그래서 함부로 판단하지말고 어떤 상황이 있는지 의심하고 확인하는게 꼭 필요하다 느꼈습니다.

✔️그럼에도 실제 핵유저의 매치를 찾아서 어떻게 문제가 발생하는지 직접 데이터로 확인할 수 있다는 점에서 큰 의미가 있었습니다. 또한 streamlit 을 통해서 아이디만 치면 직접 볼 수 있도록 만들었는데 대시보드 만드는게 참 재밌네요 ㅎㅎ

메모

  • window size 란? 이동평균을 계산하는 데 사용되는 윈도우(window)의 크기를 지정합니다. 이동평균은 주어진 윈도우 내 데이터 포인트의 평균을 계산하는 방법입니다. 윈도우 크기가 클수록 더 많은 데이터 포인트를 고려하여 부드러운 추세를 나타내게 됩니다. 반대로 작은 윈도우 크기는 빠른 변동에 민감한 추세를 나타내게 됩니다. 이 값은 데이터 특성과 분석 목적에 따라 조정될 수 있습니다.

  • threshold 란? 이상치로 판단할 z-점수(z-score)의 임계값(threshold)을 설정합니다. z-점수는 해당 데이터 포인트가 이동평균으로부터 얼마나 떨어져 있는지를 나타내는 표준화된 값입니다.

profile
게임 혹은 다양한 컨텐츠가 있는 곳을 좋아합니다. 시리즈를 참고하시면 편하게 글을 보실 수 있습니다🫠

0개의 댓글