const int TICK_INTERVAL = 20; // process inputs every 20 milliseconds
const int TELEPORT_DELAY = 500; // delay teleport by 500 milliseconds
struct InputBuffer {
Vector vel; // player's desired velocity
QAngle ang; // player's desired view angle
bool bAttack; // true if the player wants to attack
bool bJump; // true if the player wants to jump
bool bDuck; // true if the player wants to duck
};
std::queue<InputBuffer> g_InputBuffer; // input buffer
void ProcessInputs() {
// get player's current velocity and view angle
C_BasePlayer* pPlayer = (C_BasePlayer*)C_BaseEntity::GetLocalPlayer();
Vector vel = pPlayer->GetAbsVelocity();
QAngle ang = pPlayer->GetAbsAngles();
// process stored inputs
while (!g_InputBuffer.empty()) {
const InputBuffer& input = g_InputBuffer.front();
// update player's velocity and view angle
vel = input.vel;
ang = input.ang;
// perform attack, jump, and duck actions if necessary
if (input.bAttack)
pPlayer->PressAttack();
if (input.bJump)
pPlayer->PressJump();
if (input.bDuck)
pPlayer->PressDuck();
g_InputBuffer.pop();
}
// update player's position and orientation
pPlayer->SetAbsVelocity(vel);
pPlayer->SetAbsAngles(ang);
}
// called when the player wants to move
void OnMove(CUserCmd* cmd) {
// store the player's desired velocity and view angle in the input buffer
InputBuffer input;
input.vel = cmd->forwardmove * cmd->viewangles.Forward() + cmd->sidemove * cmd->viewangles.Right();
input.ang = cmd->viewangles;
input.bAttack = cmd->buttons & IN_ATTACK;
input.bJump = cmd->buttons & IN_JUMP;
input.bDuck = cmd->buttons & IN_DUCK;
g_InputBuffer.push(input);
}
// called when the player wants to teleport
void OnTeleport(Vector pos) {
// store the player's desired destination in the input buffer
InputBuffer input;
input.vel = pos;
g_InputBuffer.push(input);
// set a timer to delay the teleport
g_flTeleportTime = engine->Time() + TELEPORT_DELAY / 1000.0f;
}
// called every frame
void OnTick() {
// check if it's time to process the stored inputs
static float flNextTickTime = 0;
if (engine->Time() >= flNextTickTime) {
ProcessInputs();
flNextTickTime = engine->Time() + TICK_INTERVAL / 1000.0f;
}
// check if it's time to teleport
static float flTeleportTime = 0;
if (g_flTeleportTime > 0 && engine->Time() >= g_flTeleportTime) {
// get the player's weapon
C_BaseCombatWeapon* pWeapon = pPlayer->GetActiveWeapon();
// check if the weapon is uncharged
if (pWeapon && !pWeapon->IsCharged()) {
// get the player's desired destination
Vector pos = g_InputBuffer.front().vel;
// teleport the player
pPlayer->SetAbsOrigin(pos);
pPlayer->SetAbsVelocity(Vector(0, 0, 0));
g_InputBuffer.pop();
}
// reset the teleport timer
g_flTeleportTime = 0;
}