Дота на гитхабе или в чатах?. Дота 2, скрипт автоматического управления рутиной

Дота на гитхабе или в чатах?. Дота 2, скрипт автоматического управления рутиной

Kronusme/dota2-api

DotA 2 Web API PHP wrapper

Updated 3 hours ago

Дота на гитхабе или в чатах?. Дота 2, скрипт автоматического управления рутиной

Arcana/node-dota2

A node-steam plugin for Dota 2.

Updated 3 weeks ago

Дота на гитхабе или в чатах?. Дота 2, скрипт автоматического управления рутиной

SteamDatabase/GameTracking-Dota2

📥 Game Tracker: Dota 2

Updated 3 days ago

Дота на гитхабе или в чатах?. Дота 2, скрипт автоматического управления рутиной

Odota/core

Open source Dota 2 data platform

Updated 2 days ago

Дота на гитхабе или в чатах?. Дота 2, скрипт автоматического управления рутиной

Pissang/dota2hero

Online Dota2 hero viewer based on WebGL

Updated 1 day ago

Дота на гитхабе или в чатах?. Дота 2, скрипт автоматического управления рутиной

Uin3566/Dota2Helper

Updated 6 months ago

Дота на гитхабе или в чатах?. Дота 2, скрипт автоматического управления рутиной

Lightbringer/dota2ai

Dota2 AI Framework

Updated 1 week ago

Дота на гитхабе или в чатах?. Дота 2, скрипт автоматического управления рутиной

Joshuaduffy/dota2api

Wrapper and parser

Updated 3 hours ago

Дота на гитхабе или в чатах?. Дота 2, скрипт автоматического управления рутиной

Andreiapostoae/dota2-predictor

Tool that predicts the outcome of a Dota 2 game using Machine Learning

Updated 3 weeks ago

Дота на гитхабе или в чатах?. Дота 2, скрипт автоматического управления рутиной

ValveSoftware/Dota2-Gameplay

Public Bug Tracker for Dota2

Updated 17 hours ago

Дота на гитхабе или в чатах?. Дота 2, скрипт автоматического управления рутиной

CAPTAIN-WHU/DOTA_devkit

No information provided.

Updated 1 day ago

Дота на гитхабе или в чатах?. Дота 2, скрипт автоматического управления рутиной

No-Bling/DOTA

winter is coming..

Updated 1 week ago

Дота на гитхабе или в чатах?. Дота 2, скрипт автоматического управления рутиной

Adamqqqplay/dota2ai

Updated 6 hours ago

Дота на гитхабе или в чатах?. Дота 2, скрипт автоматического управления рутиной

SJTU-Thinklab-Det/DOTA-DOAI

This repo is the codebase for our team to participate in DOTA related competitions, including rotation and horizontal detection.

Updated 3 days ago

Дота на гитхабе или в чатах?. Дота 2, скрипт автоматического управления рутиной

OpenAngelArena/oaa

A really great Dota 2 game mode.

Updated 2 months ago

Дота на гитхабе или в чатах?. Дота 2, скрипт автоматического управления рутиной

Odota/dotaconstants

Constant data for Dota applications

Updated 1 week ago

Дота на гитхабе или в чатах?. Дота 2, скрипт автоматического управления рутиной

Bilibili/LastOrder-Dota2

Dota2 AI bot

Updated 4 days ago

Дота на гитхабе или в чатах?. Дота 2, скрипт автоматического управления рутиной

Algotech/dotaliases

Helpful bash aliases for true professionals.

Updated 2 weeks ago

Дота на гитхабе или в чатах?. Дота 2, скрипт автоматического управления рутиной

Zym2014/DotaSkeletonAnim

Updated 4 months ago

Дота на гитхабе или в чатах?. Дота 2, скрипт автоматического управления рутиной

Lupuleasa-core/Dota2-TheCore-Config-Engine

Updated 10 months ago

Дота на гитхабе или в чатах?. Дота 2, скрипт автоматического управления рутиной

Vinnicc/dota

Ruby client for the Dota 2 WebAPI

Updated 1 year ago

Дота на гитхабе или в чатах?. Дота 2, скрипт автоматического управления рутиной

Pizzalol/SpellLibrary

Repo for recreating the original dota skills

Updated 2 weeks ago

Дота на гитхабе или в чатах?. Дота 2, скрипт автоматического управления рутиной

Mitchtabian/Dota-Info

Multi-module, Kotlin, MVI, Compose, Hilt, Navigation Component, Use-cases, SQL-Delight, Ktor

Updated 3 days ago

Дота на гитхабе или в чатах?. Дота 2, скрипт автоматического управления рутиной

MNoya/DotaCraft

Bringing back the legendary RTS game from which Dota was created

Updated 1 month ago

Дота на гитхабе или в чатах?. Дота 2, скрипт автоматического управления рутиной

Paralin/Dota2

Updated 3 weeks ago

Дота на гитхабе или в чатах?. Дота 2, скрипт автоматического управления рутиной

ValvePython/dota2

🐸 Python package for interacting with Dota 2 Game Coordinator

Updated 1 week ago

Дота на гитхабе или в чатах?. Дота 2, скрипт автоматического управления рутиной

Nostrademous/Dota2-FullOverwrite

Updated 7 months ago

Дота на гитхабе или в чатах?. Дота 2, скрипт автоматического управления рутиной

Thinklab-SJTU/R3Det_Tensorflow

Code for AAAI 2021 paper: R3Det: Refined Single-Stage Detector with Feature Refinement for Rotating Object

Updated 1 day ago

Дота на гитхабе или в чатах?. Дота 2, скрипт автоматического управления рутиной

Jessemelpolio/Faster_RCNN_for_DOTA

Code used for training Faster R-CNN on DOTA

Updated 4 days ago

Дота на гитхабе или в чатах?. Дота 2, скрипт автоматического управления рутиной

Eroica-cpp/dota2scripts

Lua scripts for DotA2.

Updated 1 week ago

Разработчик Джефф Хилл, работающий в Valve, в частности над Dota 2, придумал механизм для оповещения о багах в игре, а также для их дальнейшего учета. Новшеством он поделился в соответствующей теме на Reddit.

Джефф Хилл

В качестве эксперимента разработчик предложил использовать специальный раздел для учета багов в его личном аккаунте на Github. Таким образом пользователи смогут видеть, о каких багах сообщество уже сообщило, добавлять новые жалобы, а также следить за прогрессом исправления и комментариями разработчика.

Читайте также


  • img


    RamirezSup img115324

    Dota Plus, компендиумы и ивенты


  • img

    NAVI против SPIRIT. Жалко NAVI


    BolshoiDlinnuiNeobrezanui img38

    Киберспорт: матчи, турниры, команды и игроки


  • img

    Даныло идёт по головам!


    Жабик img32

    Киберспорт: матчи, турниры, команды и игроки


  • img

    Весна 2023 — призыв к оружию


    Who_I_am img30

    Dota Plus, компендиумы и ивенты


  • img

    Квопа еще живой мидер?


    Проснулся img29

    Герои: общие обсуждения


  • img


    KraaqIsPerfect img24

    Киберспорт: матчи, турниры, команды и игроки


  • img

    В патруле неадекваты


    Pivo228gachi img69


  • img

    Когда начнут банить уродов на сапах?


    meliodas322 img53


  • img

    ЧТо это такое хааххах


    Subj Bruh img36


  • img

    Жидкость — зло или благо?


    Salovar img18

    Сборка ПК, значительный апгрейд


  • img

    Аниме наподобие хантера


    TobiWan KiNoBi img55

    Аниме и прочее


  • img

    Даже в турбо руинеры?


    Clwn img5

Время на прочтение

Привет, в этой статье будут рассматриваться легальные способы получить преимущество перед противником с помощью таких простых средств, как NodeJS, Electron и React, при этом обходя бан стороной. На эксперименты меня вдохновила другая статья Визуализация времени возрождения Рошана и желание автоматизировать часть рутины. Стоит заметить что сейчас будут рассматриваться инструменты не модифицирующие каким либо нечестным способом игру — все API открыты, данные получены честным путём, никакого вмешательства в процесс игры не происходит. Под катом будет несколько картинок и немного кода.

Пример использования в демо режиме игры
Пример использования в демо режиме игры

Весь исходный код расположен на Github, с ним можно ознакомится, лайкнуть, форкнуть, предложить изменения. Писал его левой пяткой правой ноги, прямо во время игры, поэтому просьба не ругаться сильно за стилистику.

Если честно, то я ничего нового не придумал, уже всё до меня придумали и даже есть готовые приложения, которые примерно тоже самое умеют.

Дальнейшими знаниями можно пользоваться, как во имя добра — делать инструменты для студий аналитики, киберспорта, стримов Twitch, тренировок команд и т.д., так и во имя зла — написания читов, выбор за вами.

Disclaimer: Автор не несёт ответственности за применение вами знаний полученных в данной статье или ущерб в результате их использования. Вся информация здесь изложена только в познавательных целях. Особенно для компаний разрабатывающих MOBA, чтобы помочь им бороться с читерами. И, естественно, автор статьи ботовод, читер и всегда им был.

В итоге созданные инструменты умеют:

  • Отслеживать игровое время

  • Воспроизводить звуки до начала важных событий

  • Отображать текущие показатели золота (GPM)

  • Отображать статистику по герою из открытого источника OpenDota.com

  • Отслеживать время возрождения рошана

  • Собирать данные о любимых героях противника

Какие ещё можно сделать улучшения:

  • Отображать историю средних показателей противника

  • Добавить ретроспективный анализ игры по её окончанию

  • Добавить больше звуковых/визуальных уведомлений

  • Дать возможность отслеживать «ультимейты»

  • Добавить больше визуальных данных во время просмотра киберспортивных игр

  • Добавить подробнейшие руководства прямо во время игры

Дота на гитхабе или в чатах?. Дота 2, скрипт автоматического управления рутиной

С чего всё начиналось

У Dota 2 неожиданно есть GSI (Game State Integration), который придумали для интеграции сторонних приложений / оверлеев (наложение картинки поверх игры) и синхронизации этих самых оверлеев с игрой в реальном времени. Это говорит о том, что можно получать состояние игры и дальше что — то с ним делать. Для интеграции с NodeJS есть готовое решение в виде библиотеки. Для работы GSI сервера, в первую очередь, нужно создать файл конфигурации в «Steam\steamapps\common\dota 2 beta\game\dota\cfg», в этом файле прописываются настройки, например, такие:

"dota2-gsi Configuration"
{
    "uri"               "http://localhost:3001/"
    "timeout"           "5.0"
    "buffer"            "0.1"
    "throttle"          "0.1"
    "heartbeat"         "30.0"
    "data"
    {
        "buildings"     "1"
        "provider"      "1"
        "map"           "1"
        "player"        "1"
        "hero"          "1"
        "abilities"     "1"
        "items"         "1"
        "draft"         "1"
        "wearables"     "1"
    }
}

После перезапуска игры, подтягиваются новые настройки и запускается сервер GSI, который будет отправлять данные по HTTP на localhost:3001, на котором и поднимается NodeJS сервер:

var server = app.listen(3001, () => {
  console.log("Dota 2 GSI listening on port " + server.address().port);
});

Собственно, после запускается код слушателя, который как раз и позаимствован из сторонней библиотеки NodeJS

Сервер получения данных об игровом мире готов.

Данные, которые не дают преимущества

Во время рейтингового матча в Dota 2, GSI отдаёт обрезанные данные, из полезного доступно

  • Прошедшее количество секунд с начала игры

  • Игровое время в секундах

Пример данных (в игре запущена карта с демо режимом)
{
    "ip": "::ffff:127.0.0.1",
    "gamestate": {
        "buildings": {
            "radiant": {
                "dota_goodguys_tower1_top": {
                    "health": 1800,
                    "max_health": 1800
                },
                "dota_goodguys_tower2_top": {
                    "health": 2500,
                    "max_health": 2500
                },
                "dota_goodguys_tower3_top": {
                    "health": 2500,
                    "max_health": 2500
                },
                "dota_goodguys_tower1_mid": {
                    "health": 1800,
                    "max_health": 1800
                },
                "dota_goodguys_tower2_mid": {
                    "health": 2500,
                    "max_health": 2500
                },
                "dota_goodguys_tower3_mid": {
                    "health": 2500,
                    "max_health": 2500
                },
                "dota_goodguys_tower1_bot": {
                    "health": 1800,
                    "max_health": 1800
                },
                "dota_goodguys_tower2_bot": {
                    "health": 2500,
                    "max_health": 2500
                },
                "dota_goodguys_tower3_bot": {
                    "health": 2500,
                    "max_health": 2500
                },
                "dota_goodguys_tower4_top": {
                    "health": 2600,
                    "max_health": 2600
                },
                "dota_goodguys_tower4_bot": {
                    "health": 2600,
                    "max_health": 2600
                },
                "good_rax_melee_top": { "health": 2200, "max_health": 2200 },
                "good_rax_range_top": { "health": 1300, "max_health": 1300 },
                "good_rax_melee_mid": { "health": 2200, "max_health": 2200 },
                "good_rax_range_mid": { "health": 1300, "max_health": 1300 },
                "good_rax_melee_bot": { "health": 2200, "max_health": 2200 },
                "good_rax_range_bot": { "health": 1300, "max_health": 1300 },
                "dota_goodguys_fort": { "health": 4500, "max_health": 4500 }
            }
        },
        "provider": {
            "name": "Dota 2",
            "appid": 570,
            "version": 47,
            "timestamp": 1613780229
        },
        "map": {
            "name": "dota",
            "matchid": "0",
            "game_time": 2,
            "clock_time": 1,
            "daytime": true,
            "nightstalker_night": false,
            "game_state": "DOTA_GAMERULES_STATE_GAME_IN_PROGRESS",
            "paused": false,
            "win_team": "none",
            "customgamename": "C:\\Program Files (x86)\\Steam\\steamapps\\common\\dota 2 beta\\game\\dota_addons\\hero_demo",
            "ward_purchase_cooldown": 0
        },
        "player": {
            "steamid": "76561198282999022",
            "name": "D1rty F0x",
            "activity": "playing",
            "kills": 0,
            "deaths": 0,
            "assists": 0,
            "last_hits": 0,
            "denies": 0,
            "kill_streak": 0,
            "commands_issued": 0,
            "kill_list": {},
            "team_name": "radiant",
            "gold": 99999,
            "gold_reliable": 0,
            "gold_unreliable": 99999,
            "gold_from_hero_kills": 0,
            "gold_from_creep_kills": 0,
            "gold_from_income": 2,
            "gold_from_shared": 0,
            "gpm": 3913086,
            "xpm": 0
        },
        "hero": {
            "xpos": -6700,
            "ypos": -6700,
            "id": 6,
            "name": "npc_dota_hero_drow_ranger",
            "level": 1,
            "alive": true,
            "respawn_seconds": 0,
            "buyback_cost": 8540,
            "buyback_cooldown": 0,
            "health": 560,
            "max_health": 560,
            "health_percent": 100,
            "mana": 255,
            "max_mana": 255,
            "mana_percent": 100,
            "silenced": false,
            "stunned": false,
            "disarmed": false,
            "magicimmune": false,
            "hexed": false,
            "muted": false,
            "break": false,
            "smoked": false,
            "has_debuff": false,
            "talent_1": false,
            "talent_2": false,
            "talent_3": false,
            "talent_4": false,
            "talent_5": false,
            "talent_6": false,
            "talent_7": false,
            "talent_8": false
        },
        "abilities": {
            "ability0": {
                "name": "drow_ranger_frost_arrows",
                "level": 0,
                "can_cast": false,
                "passive": false,
                "ability_active": true,
                "cooldown": 0,
                "ultimate": false
            },
            "ability1": {
                "name": "drow_ranger_wave_of_silence",
                "level": 0,
                "can_cast": false,
                "passive": false,
                "ability_active": true,
                "cooldown": 0,
                "ultimate": false
            },
            "ability2": {
                "name": "drow_ranger_multishot",
                "level": 0,
                "can_cast": false,
                "passive": false,
                "ability_active": true,
                "cooldown": 0,
                "ultimate": false
            },
            "ability3": {
                "name": "drow_ranger_marksmanship",
                "level": 0,
                "can_cast": false,
                "passive": true,
                "ability_active": true,
                "cooldown": 0,
                "ultimate": true
            }
        },
        "items": {
            "slot0": { "name": "empty" },
            "slot1": { "name": "empty" },
            "slot2": { "name": "empty" },
            "slot3": { "name": "empty" },
            "slot4": { "name": "empty" },
            "slot5": { "name": "empty" },
            "slot6": { "name": "empty" },
            "slot7": { "name": "empty" },
            "slot8": { "name": "empty" },
            "stash0": { "name": "empty" },
            "stash1": { "name": "empty" },
            "stash2": { "name": "empty" },
            "stash3": { "name": "empty" },
            "stash4": { "name": "empty" },
            "stash5": { "name": "empty" }
        },
        "draft": {},
        "wearables": {
            "wearable0": 77,
            "wearable1": 76,
            "wearable2": 5841,
            "wearable3": 80,
            "wearable4": 78,
            "wearable5": 267,
            "wearable6": 79,
            "wearable7": 8632,
            "wearable8": 737,
            "wearable9": 14912
        },
        "previously": { "player": { "gpm": 5000054 } }
    }
}

Если просматривать реплей или чужую игру, то доступно гораздо больше информации — вся она описана тут. Что-ж, самая важная информация нам уже доступна — GPM, игровое время, Id героя.

После получения информации мы должны с ней что — то поделать, например, отрисовать или предупредить о наступившем моменте в игре.

UI, Оповещения, Electron

Для UI решено было использовать Electron и внутри этого электрона запускать React. Идея заключается в том, чтобы рисовать Electron приложение поверх игры (оверлей). Исходник оверлея можно найти тут, немного задержимся на нём — есть пару особенностей.

Для начала нужно настроить окно, в котором будет всё отображаться:

const win = new BrowserWindow({
  width: 210,
  height: 200,
  // Окно должно без рамки
  frame: false,
  // Окно может быть прозрачным
  transparent: true,
  webPreferences: {
    // Фикс багов связанных с импортами React
    nodeIntegration: true,
  },
});
// Окно должно всегда быть поверх остальных
win.setAlwaysOnTop(true, "screen-saver");

Сначала у меня не получалось поверх доты что — то вывести, пока не наткнулся на настройку в файле machine_convars.vcfg (Dota 2) под названием «dota_mouse_window_lock», которую нужно выставить в «0», а в самой игре (либо в тех же файлах конфигурации) настроить режим отображения в окне без рамки.

UI написан с использованием React, поэтому решено его было загружать прямо с dev сервера разработки (да, я ленивый):

function loadWindow() {
  setTimeout(() => {
    win.loadURL("http://localhost:3000").catch(loadWindow);
  }, 3000);
}
loadWindow();

Если dev сервер не успел загрузиться, то мы попробуем ещё разок через 3 секунды, вот для этого и нужен setTimeout.

Всё, с overlay закончили, теперь UI часть.

Styled-Components, Typescript, Хуки, - стильно, модно, молодёжно
Styled-Components, Typescript, Хуки, — стильно, модно, молодёжно

В UI был выбран мой любимый стек: TS, CRA (Styled только для одного/двух классов использовался — рисовать то особо нечего). После того, как GSI Dota2 отправил данные на express сервер, их нужно передать на фронт. Пишется простая GET ручка для отдачи данных. Затем на фронте пишется хук, который раз в секунду запрашивает эти данные и дальше они попадают сразу во все остальные хуки. То есть в приложении каждую секунду запускаются все хуки — это важный факт, ведь иногда понадобится хранить время запуска хука, чтобы случайно его не запустить несколько раз (если этого не делать, то у вас произойдёт в лучшем случае два оповещения подряд, в худшем случае взрыв из оповещений). Логика получения данных:

import { State } from "../state/state";
import { useState } from "react";
import { useInterval } from "./useInterval";

const SERVER_URL = "http://localhost:3001/time";
const UPDATE_FREQUENTLY = Number(process.env.REACT_APP_SERVER_UPDATE_FREQUENTLY);

export function useServerState(): State {
  const [state, setState] = useState<State>({});

  useInterval(async () => {
    try {
      const data = await (await fetch(SERVER_URL)).json();
      setState(data);
    } catch {}
  }, UPDATE_FREQUENTLY);

  return state;
}

Теперь, когда есть все данные на фронте, можно написать хук для звуковых оповещений, что пора бы пойти (за 30 секунд до начала оповещает) забрать руны богатства, появляющиеся на каждой минуте кратной пяти (5, 10, 15, 20 минута):

export function useBountyRunes(state: State) {
  const clockTime = clockTimeSelector(state);
  const [play] = useSound(bountiesMp3, { volume: 0.25 });
  const [lastIntervalPlay, setLastIntervalPlay] = useState<number>(-1);

  useEffect(() => {
    // Проверка, что  время пришло корректное
    if (!clockTime || isNegative(clockTime)) {
      return;
    }

    // Проверка кратности минуты на 4,5 и проверка от двойного оповещения
    if (isNeedToPlay(clockTime, lastIntervalPlay)) {
      // Проигрываем звук
      play();
      // Записываем когда последний раз было оповещение
      setLastIntervalPlay(getInterval(clockTime + ALARM_BEFORE));
    }
  }, [clockTime, lastIntervalPlay, play]);
}

Запись о последнем воспроизведении (setLastIntervalPlay) нужна чтобы не повторить оповещение случайно дважды.

И вот уже в игре одно преимущество, может быть оно несущественное, но как мне кажется неплохо управляет вниманием команды. Что — ж можно пойти дальше и сделать такую же кнопку возрождения рошана, как из прошлой статьи:

Хук useRoshanSpawn для кнопки
export function useRoshanSpawn(state: State) {
  const currentGameTime = gameTimeSelector(state) || 0;
  const [play] = useSound(roshanRespawnMp3, { volume: 0.25 });
  const [roshanStopwatch, setRoshanStopwatch] = useState<RoshanStopwatch>({
    isActive: false,
    time: 0,
    isPlayedSound: false,
  });

  // Фиксация смерти роши
  function handleDead() {
    setRoshanStopwatch({
      time: currentGameTime,
      isActive: true,
      isPlayedSound: false,
    });
  }

  // Сброс таймера
  function handleReset() {
    setRoshanStopwatch({
      time: 0,
      isActive: false,
      isPlayedSound: false,
    });
  }

  // Проверяем роша жив, жив/мёртв, и сколько времени прошло с момента смерти
  const isDead = roshanIsDead(roshanStopwatch, currentGameTime);
  const isDeadOrLive = schrodingerRoshan(roshanStopwatch, currentGameTime);
  const timeToSpawn = roshanTimeDeadSelector(roshanStopwatch, currentGameTime);

  useEffect(() => {
    // Оповещаем звуком за 30 секунд до возможного возрождения
    if (needToPlaySound(roshanStopwatch, currentGameTime)) {
      play();
      setRoshanStopwatch({
        ...roshanStopwatch,
        isPlayedSound: true,
      });
    }
  }, [roshanStopwatch, currentGameTime, setRoshanStopwatch]);

  return { handleDead, handleReset, isDead, isDeadOrLive, timeToSpawn };
}

С рошаном всё немного запутаннее, чем с рунами — он может возрождаться в интервале от 9 до 12 минут. То есть у него есть состояния:

  • Точно мёртв (прошло до 9 минут с момента смерти)

  • Он жив или мёртв (прошло от 9 до 12 минут с момента смерти)

  • Он точно жив (прошло свыше 12 минут с момента смерти или это начало игры)

Поэтому у таймера есть три визуальных состояния:

  • Кнопка — для запуска таймера

  • Таймер тикает и сообщает о том что роша точно мёртв

  • Таймер тикает и сообщает о том что роша возможно жив, а возможно мёртв

И одно звуковое оповещение: Рошан будет в состоянии Шредингера через 30 секунд (то есть, и жив, и мёртв одновременно — пока не проверишь, не узнаешь). Также есть возможность сбросить таймер, ведь если мы проверили и узнали, что он жив — то таймер больше не нужен, а нужна кнопка о том чтобы сообщить о новой смерти рошана. Из минусов — иногда забываешь запускать таймер, было бы здорово в будущем это тоже автоматизировать.

Обогащаем данные

Ещё есть информация о том, на каком герое мы играем, поэтому пускай клиент запрашивает бенчмарки с сайта OpenDota.com и отображаем их, чтобы было понятно, на сколько мы отстаём от ритма игры. Я взял перцентиль 99%, то есть мне интересно, с какими показателями отыгрывается 1% лучших игр на том или ином герое.

Бенчмарки на героя Abaddon
Бенчмарки на героя Abaddon

Вся логика описана в хуке useBenchmark:

export function useBenchmarks(state: State): State {
  const [localState, setLocalState] = useState<Benchmarks>();

  const updateBenchmarksForHero = useCallback(
    async function (id: number) {
      try {
        // Запросили данные по герою
        const response = await fetch(`${BENCHMARKS_URL}?hero_id=${id}`);
        const benchmarks = (await response.json()) as Benchmarks;

        // Сохранили бенчмарк
        setLocalState(benchmarks);
      } catch (error) {
        setLocalState({
          error,
        });
      }
    },
    [setLocalState]
  );

  useEffect(() => {
    const heroId = heroIdSelector(state);
    const benchmarksHeroId = localState?.hero_id;

    // Запрашиваем бенчмарк, при появлении информации о герое
    if (heroId && heroId !== benchmarksHeroId && !localState?.error) {
      updateBenchmarksForHero(heroId);
    }
  }, [state, localState, updateBenchmarksForHero]);
  
  // Возвращаем данные о бенчмарке
  return { ...state, benchmarks: localState };
}

Узнаём предпочтения игрока

Было бы здорово получать информацию о том, на каких героях вероятнее всего будет играть противник, чтобы забанить, отобрать, законтрить их у него. Для этого нужно считывать память файл игры: «server_log.txt» и дальше распарсить его регуляркой, найти там ID ваших оппонентов, затем запросить историю игр в OpenDota или Dotabuff. У этого способа есть минусы — если оппоненты сделал свой игровой профиль скрытым в Dota 2, то никакой информации о нём вы не получите. Есть ещё один момент, который я забыл учесть — данные могут быть устаревшими, но в коде это легко исправляется добавлением фильтра по времени.

Attention: код по ссылке может совершить BSoD ваших глаз.

import fs from "fs";

const DEFAULT_FILE =
  "C:\\Program Files (x86)\\Steam\\steamapps\\common\\dota 2 beta\\game\\dota\\server_log.txt";

// Парсим все ID в строке
const getDotaIdsFromLine = (line) => {
  let playersRegex = /\d:(\[U:\d:(\d+)])/g;
  let playersMatch;
  let dotaIds = [];
  while ((playersMatch = playersRegex.exec(line))) {
    dotaIds.push(playersMatch[2]);
  }
  return dotaIds;
};

const getState = () => {
  return new Promise((res) => {
    // ищем последнюю строку со словом Lobby
    fs.readFile(DEFAULT_FILE, (err, data) => {
      const rowString = data.toString();
      const startIndex = rowString.lastIndexOf("Lobby");
      const finishIndex = rowString.indexOf("\n", startIndex);
      const lobbyString = rowString.slice(startIndex, finishIndex);

      res(getDotaIdsFromLine(lobbyString));
    });
  });
};

export const getSteamIDs = () => {
  return getState();
};

После, будет здорово это тоже вывести, поэтому решено было сделать отдельное React приложение на localhost:3002. Без дизайна выглядит оно совсем по страшному, но это уже был просто спортивный интерес и вообще я им не пользуюсь. В нём есть информация о прошлых десяти играх. Кнопочка «Ban this id», чтобы убирать друзей, с которыми играешь, из этой статистики и ссылка на Dotabuff профиль, если вдруг хочется подробностей.

Дота на гитхабе или в чатах?. Дота 2, скрипт автоматического управления рутиной

Это приложение тоже можно было бы красиво оформить в виде Electron оверлея и запускать его на стадии выбора героев, но кажется я слишком много играю в игры и мало уделяю времени действительно полезным вещам 🙂

Что ещё пробовалось:

  • Пробовался DLL Injection из прошлой статьи и чтение памяти с помощью Rust, но там был большой изъян в том, что все найденные указатели на структуры данных жили до обновления игры, поэтому эта идея была заброшена.

  • Попытка создать сервис подбора героев на основе ML обучения по выгрузке игр из OpenDota.com или с тех же серверов Valve (провал — хотя мне кажется я просто не сумел правильно приготовить ML часть)

  • Парсинг Dota 2 реплеев — там не сложно, используется Protobuff и все структуры легко находятся на гитхабе. Вот только что дальше с этим огромным объёмом данных делать?

Вывод: интегрироваться с Dota2 не вызывает труда, можно делать быстрый анализ прямо во время игры, при просмотре киберспортивных игр можно сделать огромное количество красивого оверлея для Twitch стрима, также можно развивать эту тему в сторону ретроспективного анализа из реплеев, что скорее всего будет полезно профессионалам.

Надеюсь вам было интересно почитать про то, как я собрал на коленке читы (на самом деле хороший вопрос — читы это или нет?), да ещё и на JS, если есть орфографические или лексические ошибки, то пишите пожалуйста в ЛС, спасибо за внимание.

Add this topic to your repo

To associate your repository with the

topic, visit your repo’s landing page and select «manage topics.»

Improve this page

Add a description, image, and links to the

topic page so that developers can more easily learn about it.


Curate this topic

Here are
150 public repositories
matching this topic.

Open source Dota 2 data platform

  • Updated
    Mar 24, 2023

yolov5 + csl_label.(Oriented Object Detection)(Rotation Detection)(Rotated BBox)基于yolov5的旋转目标检测

  • Updated
    Feb 11, 2023

React web interface for the OpenDota platform

  • Updated
    Mar 10, 2023

This repo is the codebase for our team to participate in DOTA related competitions, including rotation and horizontal detection.

  • Updated
    Mar 8, 2023

Rotational region detection based on Faster-RCNN.

  • Updated
    Nov 20, 2020

Code for AAAI 2021 paper: R3Det: Refined Single-Stage Detector with Feature Refinement for Rotating Object

  • Updated
    Aug 29, 2021

Tool that predicts the outcome of a Dota 2 game using Machine Learning

  • Updated
    Dec 8, 2022

Code used for training Faster R-CNN on DOTA

  • Updated
    Jul 7, 2018

Focal Loss for Dense Rotation Object Detection

  • Updated
    Apr 13, 2021

A tensorflow re-implementation of RRPN: Arbitrary-Oriented Scene Text Detection via Rotation Proposals.

  • Updated
    Jan 8, 2020

Protobufs

👑 Automatically tracked Steam, CS:GO, Dota 2, Artifact, Underlords and TF2 protobufs.

  • Updated
    Mar 24, 2023

This is a tensorflow implementation of R2CNN++: Multi-Dimensional Attention Based Rotation Invariant Detector with Robust Anchor Strategy.

  • Updated
    Jun 14, 2021

Satellite-Imagery-Datasets-Containing-Ships

A list of radar and optical satellite datasets for ship detection, classification, semantic segmentation and instance segmentation tasks.

  • Updated
    Jan 12, 2023

Make Dota 2 fps great again

  • Updated
    Dec 23, 2022

Repo for the development of Dota IMBA, a mod for Valve’s Dota 2.

  • Updated
    Mar 19, 2023

React Native apps for viewing Dota 2 data on Android/iOS

  • Updated
    Oct 13, 2019
  • Updated
    Oct 29, 2019

foda

Fight over dat Ancient

  • Updated
    Dec 2, 2022
  • Updated
    Apr 3, 2021

饰品筛选倒余额 比例自定义 已适配buff c5game igxe

  • Updated
    Nov 18, 2022
Новости:  Аниме романтика без гарема
Оцените статью
Dota Help