Skip to main content

subtr_actor/stats/calculators/
frame_components.rs

1use 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;