-
Notifications
You must be signed in to change notification settings - Fork 0
/
extract_movement.js
103 lines (89 loc) · 3.43 KB
/
extract_movement.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
const demofile = require('demofile');
const fs = require('fs');
const _ = require('lodash');
const { fromEvent, forkJoin } = require('rxjs');
const { map, filter, tap, first } = require('rxjs/operators');
const DEMOS_DIR = '../../demos';
const TICKS_PER_POS = 16;
const OUTPUT_FILE = 'all_inferno_movement.json';
// Find demo files to read
const GAME_DEMOS = fs.readdirSync(DEMOS_DIR)
.filter(fileName => fileName.endsWith('.dem'))
.map(fileName => `${DEMOS_DIR}/${fileName}`);
/* ***** */
let distance3 = (p1, p2) => {
return Math.sqrt( Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2) + Math.pow(p2.z - p1.z, 2) );
};
const parsers$ = GAME_DEMOS.map(DEMO_FILE => {
let playerPositions = {};
let demo = new demofile.DemoFile();
let getTeam = (player) => {
if (_.includes(demo.teams[demofile.TEAM_CTS].members.map(p => p && p.userId), player.userId)) {
return "CT";
}
return "T";
};
// Wait for the first round, we don't care about the warm-up.
let gameStarted = false;
let lastRoundNumber = -1;
demo.gameEvents.on("round_start", e => {
if (demo.gameRules.roundsPlayed > lastRoundNumber) {
console.log(`=== ROUND #${demo.gameRules.roundsPlayed} STARTED IN ${DEMO_FILE} ===`);
demo.players
.filter(player => player.isAlive)
.forEach(player => {
if (gameStarted) {
playerPositions[player.name].push([]);
} else {
playerPositions[player.name] = [[]];
}
});
lastRoundNumber = demo.gameRules.roundsPlayed;
}
gameStarted = true;
});
fromEvent(demo, 'tickend')
.pipe(filter(tick => gameStarted && (tick % TICKS_PER_POS === 0)))
.subscribe(() => {
demo.players
.filter(player => player.isAlive)
.forEach(player => {
const currentPlayerLife = _.last(playerPositions[player.name]);
const lastPos = _.last(currentPlayerLife);
let lastDistance = lastPos && distance3(player.position, lastPos.pos);
if (!lastPos || (lastDistance > 0 && lastDistance < 100)) {
currentPlayerLife.push({
pos: player.position,
team: getTeam(player),
health: player.health,
});
}
});
});
demo.parse(fs.readFileSync(DEMO_FILE));
return fromEvent(demo, 'end').pipe(
tap(e => console.log(`=== DEMO FINISHED PARSING ${DEMO_FILE} ===`)),
map(e => e.error ? e : playerPositions),
first()
);
});
forkJoin(parsers$).subscribe(
results => {
let output = {};
results.forEach(movementJson => {
for (let player in movementJson) {
if (output[player]) {
output[player] = output[player].concat(movementJson[player]);
} else {
output[player] = movementJson[player];
}
}
});
fs.writeFile(OUTPUT_FILE, JSON.stringify(output), 'utf8', (err) => {
if (err) throw err;
console.log(`=== Wrote movement to ${OUTPUT_FILE} ===`);
});
},
error => console.log(error),
() => console.log('Movement extracted.'),
);