-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathsequence.py
More file actions
68 lines (53 loc) · 2.27 KB
/
sequence.py
File metadata and controls
68 lines (53 loc) · 2.27 KB
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
from abc import ABC, abstractmethod
from dataclasses import dataclass, field
from typing import override
from rlbot.flat import ControllerState, GamePacket
@dataclass(slots=True)
class StepResult:
controls: ControllerState
done: bool
class Step(ABC):
@abstractmethod
def tick(self, packet: GamePacket) -> StepResult:
"""
Return appropriate controls for this step in the sequence. If the step is over, you should
set done to True in the result, and we'll move on to the next step during the next frame.
If you panic and can't return controls at all, you may return None and we will move on to
the next step immediately.
"""
raise NotImplementedError
@dataclass(slots=True)
class ControlStep(Step):
"""
This allows you to repeat the same controls every frame for some specified duration. It's useful for
scheduling the button presses needed for kickoffs / dodges / etc.
"""
duration: float
controls: ControllerState
start_time: float | None = field(default=None, init=False)
@override
def tick(self, packet: GamePacket) -> StepResult:
if self.start_time is None:
self.start_time = packet.match_info.seconds_elapsed
elapsed_time = packet.match_info.seconds_elapsed - self.start_time
return StepResult(controls=self.controls, done=elapsed_time > self.duration)
@dataclass(slots=True)
class Sequence:
steps: list[Step]
index: int = field(default=0, init=False)
done: bool = field(default=False, init=False)
def tick(self, packet: GamePacket) -> ControllerState:
while self.index < len(self.steps):
step = self.steps[self.index]
result = step.tick(packet)
if result.done:
self.index += 1
if self.index >= len(self.steps):
# The bot will know not to use this sequence next frame, even though we may be giving it controls.
self.done = True
# If the step was able to give us controls, return them to the bot.
return result.controls
# Otherwise we will loop to the next step in the sequence.
# If we reach here, we ran out of steps to attempt.
self.done = True
return ControllerState()