timkurvers / redota

Revisit past Dota 2 matches in the browser

Home Page:https://timkurvers.github.io/redota

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

how to use and how to extract hero positions?

Cyberface opened this issue Β· comments

First of all this project is really feakin' cool!

What I would like to do is to be able to extract the positions of the heros as a function of time.
I'd like to play around with this data, maybe do some modelling with it.

Can I use your code to do this? Ideally, I would like something where I can parse reply files using something on the command line.

Thanks!

Glad this project may be of help 😊 The documentation is a bit scarce at the moment, hope to expand that today and throughout the week.

But just to get you started: there's a binary in bin/parse.js which parses a given file all the way through printing some entity information as well as printing chat messages.

Instructions:

  1. Clone the repository
  2. npm install
  3. npm build:protos npm run build:protos (this will compile some of Valve's definitions into a usable JavaScript format)
  4. Download / obtain a replay file
  5. Run: ./bin/parse.js <path/to/replay.dem>

The Parser and Replay objects have playback methods (play, stop, seek etc.) and in particular the Replay object provides sane access to the current game state:

const replay = new Replay(fileBuffer);
replay.start();

// Jumps to the start of the game
replay.jumpTo(GAME_PHASE.START);

// Seeks 1000 ticks forward
replay.seek(replay.tick + 1000);

for (const player of replay.players) {
  if (!player.isPlayer) continue;

  const { relX, relY } = player.hero.position;

  console.log(player.name, player.hero.name, relX, relY);
}

Not easy to jump to a point in the replay based on in-game clock time, but the current clock time is available as replay.game.clockTime.

Will reply once the docs are fleshed out a bit more.

Thank so much for your detailed instructions!

I had to slightly change one of your commands

from npm build:protos to npm run build:protos

I don't use nodejs so not sure if this was correct but that's what npm told me to do XD

I almost have it working however, when trying to run ./bin/parse.js ~/Downloads/6173366796_1474179147.dem I get the following error:

Any ideas?

(redota) redota $ ./bin/parse.js ~/Downloads/6173366796_1474179147.dem
node:internal/errors:464
    ErrorCaptureStackTrace(err);
    ^

TypeError [ERR_IMPORT_ASSERTION_TYPE_MISSING]: Module "file:///Users/USERNAME/personal/git/stk/bayes/redota/redota/node_modules/dotaconstants/build/hero_names.json" needs an import assertion of type "json"
    at new NodeError (node:internal/errors:371:5)
    at validateAssertions (node:internal/modules/esm/assert:74:15)
    at defaultLoad (node:internal/modules/esm/load:25:3)
    at ESMLoader.load (node:internal/modules/esm/loader:353:26)
    at ESMLoader.moduleProvider (node:internal/modules/esm/loader:274:58)
    at new ModuleJob (node:internal/modules/esm/module_job:66:26)
    at ESMLoader.#createModuleJob (node:internal/modules/esm/loader:291:17)
    at ESMLoader.getModuleJob (node:internal/modules/esm/loader:255:34)
    at async ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:81:21)
    at async Promise.all (index 0) {
  code: 'ERR_IMPORT_ASSERTION_TYPE_MISSING'
}

Node.js v17.1.0

I had to slightly change one of your commands from npm build:protos to npm run build:protos

Ah, my bad. That's correct πŸ‘

TypeError [ERR_IMPORT_ASSERTION_TYPE_MISSING]: Module "file:///../build/hero_names.json" needs an import assertion of type "json"
at new NodeError (node:internal/errors:371:5)
at validateAssertions (node:internal/modules/esm/assert:74:15)

Thanks for bringing this to my attention! Redota currently uses some experimental JSON loading flags that work fine in Node 14 and 16, but seemingly break in Node 17. Will need to fix this, but that may take some time.

For now, if you have the option to use Node 16 that would probably be the easiest.

Nice thanks! Using Node 16 worked!

Just another quick question on your script to get hero positions if you don't mind!

I am a JS noob sorry.

Can you tell me how I can import the "GAME_PHASE" from the "constants.js" file?

I tried import Constants from '../src/lib/constants.js'; but that didn't work 🀷

I just replaced "GAME_PHASE" with "5" and that worked :)

But just wanna know how to do it properly.

Thanks so much again, I've been looking around for quite a while how to get hero positions and finally nearly there now haha.

import fs from 'fs';

import Replay from '../src/lib/replay/Replay.js';
import Parser from '../src/lib/parser/Parser.js';

// Full length parse of given replay file for debugging purposes
const buffer = fs.readFileSync("6173366796_1474179147.dem");

const replay = new Replay(buffer);
replay.start();

// Jumps to the start of the game
//replay.jumpTo(GAME_PHASE.START);
replay.jumpTo(5);

// Seeks 1000 ticks forward
replay.seek(replay.tick + 1000);

for (const player of replay.players) {
  if (!player.isPlayer) continue;

  const { relX, relY } = player.hero.position;

  console.log(player.name, player.hero.name, relX, relY);
}

Nice thanks! Using Node 16 worked!

Excellent, great to hear!

Can you tell me how I can import the "GAME_PHASE" from the "constants.js" file?

This should work:

import { GAME_PHASE } from '../src/lib/constants.js';

Before I forget: Redota requires relative positions (relX and relY) to render things on the map, but you may want the position in Valve in-game units:

hero.position.x
hero.position.y

For additional positional properties, check the Position object.

Likewise, there's a bunch of properties available for the Hero and Unit objects.

Good luck πŸ‘

I managed to extract the hero positions for a game and save them to disk! Thanks so much for you help and this awesome project again!

I think I have just one final question thought! How can I plot the data on top of an image of the dota 2 map? :)

How can I plot the data on top of an image of the dota 2 map? :)

A belated answer, but perhaps still of use πŸ˜„

There's a variety of ways to do this, but ReDota does it by placing an image of the Dota 2 map in a container, and uses the relX and relY unit properties to place them in the correct position in relation to the map.

Sorry, took me a while to try this out.

Thanks for the pointers to the code, I think I managed to recreate it somewhat in python.

Thanks again for all your help and happy new year!!

Screenshot 2022-01-06 at 19 15 21