VoltMod
C++23 framework for CS2 server plugins
Loading...
Searching...
No Matches
PlayerInput.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <array>
4#include <cstdint>
5#include <optional>
6#include <span>
7#include <type_traits>
8
9namespace VoltMod
10{
11
12/** One CSubtickMoveStep from the usercmd: a sub-tick input change with its intra-tick time. */
14{
15 uint64_t Button = 0; // button bit(s) this step toggles; 0 for pure aim steps
16 bool Pressed = false; // press vs release when Button != 0
17 float When = 0.0f; // intra-tick fraction [0,1)
18 float PitchDelta = 0.0f;
19 float YawDelta = 0.0f;
20};
21
22/**
23 * One CSGOInputHistoryEntryPB. ViewYaw/ViewPitch is the angle the bullet was fired along, which
24 * a cheat can diverge from the visible viewangles (the silent-aim signature).
25 */
27{
28 bool HasViewAngles = false;
29 float ViewPitch = 0.0f; // view_angles.x
30 float ViewYaw = 0.0f; // view_angles.y
31 int32_t TargetEntIndex = -1; // entity the client claims it hit, -1 if none
32};
33
34/**
35 * @brief Protobuf-free snapshot of the CUserCmd handed to
36 * CPlayer_MovementServices::RunCommand, decoded once per command by @ref Movement.
37 *
38 * Valid is false when the usercmd pointer was null or the "CUserCmd::CSGOUserCmdPB" gamedata
39 * offset is missing - fields then hold their defaults and must not be trusted.
40 */
42{
43 bool Valid = false;
45
46 // Client command counter from gamedata "CUserCmdBase::cmdNum". Missing gamedata falls
47 // back to legacy_command_number, which live clients leave at zero.
49
50 /** False when the client omitted viewangles: the three fields below then hold defaults rather
51 * than a reading, so treat the angles as untrusted. */
52 bool HasViewAngles = false;
53
54 // CBaseUserCmdPB.viewangles (x = pitch, y = yaw, z = roll)
55 float ViewPitch = 0.0f;
56 float ViewYaw = 0.0f;
57 float ViewRoll = 0.0f;
58
59 float ForwardMove = 0.0f;
60 float LeftMove = 0.0f;
61
62 // CInButtonStatePB words: held and changed-this-tick button masks
65
66 // Raw mouse movement the client reported for this command
69
70 // Sub-tick shooting bookkeeping (-1 = no attack started this command)
73
74 static constexpr int MaxSubtickMoves = 12;
75 int SubtickMoveCount = 0; // clamped to MaxSubtickMoves
76 std::array<SubtickMove, MaxSubtickMoves> SubtickMoves{};
77
78 // Fired-view samples, capped at MaxInputHistory. Attack indices address the
79 // full client list, so an index beyond this snapshot names a discarded sample.
80 static constexpr int MaxInputHistory = 16;
81 int InputHistoryCount = 0; // clamped to MaxInputHistory
82 /** Entries the client actually sent, before the MaxInputHistory cap. Greater than
83 * InputHistoryCount means the tail was capped away. */
85 std::array<InputHistorySample, MaxInputHistory> InputHistorySamples{};
86
87 /** The decoded sub-tick steps. */
88 std::span<const SubtickMove> Subticks() const
89 {
90 return {SubtickMoves.data(), static_cast<size_t>(SubtickMoveCount)};
91 }
92
93 /** The decoded fired-view samples. */
94 std::span<const InputHistorySample> InputHistory() const
95 {
96 return {InputHistorySamples.data(), static_cast<size_t>(InputHistoryCount)};
97 }
98
99 /** The decoded entry at @p index, or nullopt when @p index is negative or was capped away. */
100 std::optional<InputHistorySample> SampleAt(int index) const
101 {
103 {
104 return std::nullopt;
105 }
106 return InputHistorySamples[index];
107 }
108};
109
110// The host hands it to every plugin, whose allocators differ, so it must own nothing.
111static_assert(std::is_trivially_copyable_v<PlayerInput>);
112
113} // namespace VoltMod
static std::string ReadFile(const std::filesystem::path &path)
Definition Loader.cpp:56
Protobuf-free snapshot of the CUserCmd handed to CPlayer_MovementServices::RunCommand,...
static constexpr int MaxInputHistory
int32_t Attack1StartHistoryIndex
std::span< const InputHistorySample > InputHistory() const
std::span< const SubtickMove > Subticks() const
static constexpr int MaxSubtickMoves
std::array< SubtickMove, MaxSubtickMoves > SubtickMoves
std::array< InputHistorySample, MaxInputHistory > InputHistorySamples
int32_t Attack2StartHistoryIndex
std::optional< InputHistorySample > SampleAt(int index) const