subtr_actor/stats/calculators/
frame_components.rs1use crate::*;
2
3use super::{BallSample, DemoEventSample, PlayerSample};
4
5#[derive(Debug, Clone, Default)]
6pub struct FrameInfo {
7 pub frame_number: usize,
8 pub time: f32,
9 pub dt: f32,
10 pub seconds_remaining: Option<i32>,
11}
12
13#[derive(Debug, Clone, Default)]
14pub struct GameplayState {
15 pub game_state: Option<i32>,
16 pub ball_has_been_hit: Option<bool>,
17 pub kickoff_countdown_time: Option<i32>,
18 pub team_zero_score: Option<i32>,
19 pub team_one_score: Option<i32>,
20 pub possession_team_is_team_0: Option<bool>,
21 pub scored_on_team_is_team_0: Option<bool>,
22 pub current_in_game_team_player_counts: [usize; 2],
23}
24
25impl GameplayState {
26 pub fn is_live_play(&self) -> bool {
27 !self.kickoff_phase_active() && self.game_state != Some(GAME_STATE_GOAL_SCORED_REPLAY)
28 }
29
30 pub fn current_score(&self) -> Option<(i32, i32)> {
31 Some((self.team_zero_score?, self.team_one_score?))
32 }
33
34 pub fn kickoff_phase_active(&self) -> bool {
35 self.game_state == Some(GAME_STATE_KICKOFF_COUNTDOWN)
36 || self.kickoff_countdown_time.is_some_and(|time| time > 0)
37 || self.ball_has_been_hit == Some(false)
38 }
39
40 pub fn current_in_game_team_player_count(&self, is_team_0: bool) -> usize {
41 self.current_in_game_team_player_counts[usize::from(!is_team_0)]
42 }
43}
44
45#[derive(Debug, Clone, Default)]
46pub enum BallFrameState {
47 #[default]
48 Missing,
49 Present(BallSample),
50}
51
52impl BallFrameState {
53 pub fn sample(&self) -> Option<&BallSample> {
54 match self {
55 Self::Missing => None,
56 Self::Present(ball) => Some(ball),
57 }
58 }
59
60 pub fn into_sample(self) -> Option<BallSample> {
61 match self {
62 Self::Missing => None,
63 Self::Present(ball) => Some(ball),
64 }
65 }
66
67 pub fn position(&self) -> Option<glam::Vec3> {
68 self.sample().map(BallSample::position)
69 }
70
71 pub fn velocity(&self) -> Option<glam::Vec3> {
72 self.sample().map(BallSample::velocity)
73 }
74}
75
76impl From<BallSample> for BallFrameState {
77 fn from(ball: BallSample) -> Self {
78 Self::Present(ball)
79 }
80}
81
82impl From<Option<BallSample>> for BallFrameState {
83 fn from(ball: Option<BallSample>) -> Self {
84 match ball {
85 Some(ball) => Self::Present(ball),
86 None => Self::Missing,
87 }
88 }
89}
90
91#[derive(Debug, Clone, Default)]
92pub struct PlayerFrameState {
93 pub players: Vec<PlayerSample>,
94}
95
96#[derive(Debug, Clone, Default)]
97pub struct FrameEventsState {
98 pub active_demos: Vec<DemoEventSample>,
99 pub demo_events: Vec<DemolishInfo>,
100 pub boost_pad_events: Vec<BoostPadEvent>,
101 pub touch_events: Vec<TouchEvent>,
102 pub dodge_refreshed_events: Vec<DodgeRefreshedEvent>,
103 pub player_stat_events: Vec<PlayerStatEvent>,
104 pub goal_events: Vec<GoalEvent>,
105}
106
107pub(crate) const GAME_STATE_KICKOFF_COUNTDOWN: i32 = 55;
108pub(crate) const GAME_STATE_GOAL_SCORED_REPLAY: i32 = 86;