Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/cvars.md
Original file line number Diff line number Diff line change
Expand Up @@ -692,6 +692,9 @@
|sar_trace_record|0|Record the trace to a slot. Set to 0 for not recording|
|sar_trace_reveal|0|Only draw traces until the specified tick. Set to bbox to draw until the bbox tick.|
|sar_trace_show|cmd|sar_trace_show [trace name] - show the trace with the given name|
|sar_trace_sync|cmd|sar_trace_sync - syncs all the hovered traces to the fastest trace.|
|sar_trace_sync_reset|cmd|sar_trace_sync_reset \<name> - resets the sync of the player trace by the given name.|
|sar_trace_sync_reset_all|cmd|sar_trace_sync_reset_all - resets the sync of all the player traces.|
|sar_trace_teleport_at|cmd|sar_trace_teleport_at \<tick> [player slot] [trace name] - teleports the player at the given trace tick on the given trace ID (defaults to hovered one or the first one ever made) in the given slot (defaults to 0).|
|sar_trace_teleport_eye|cmd|sar_trace_teleport_eye \<tick> [player slot] [trace name] - teleports the player to the eye position at the given trace tick on the given trace (defaults to hovered one or the first one ever made) in the given slot (defaults to 0).|
|sar_trace_use_shot_eyeoffset|1|Uses eye offset and angles accurate for portal shooting.|
Expand Down
67 changes: 61 additions & 6 deletions src/Features/PlayerTrace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "Modules/Surface.hpp"

#include <vector>
#include <climits>

PlayerTrace *playerTrace;

Expand Down Expand Up @@ -60,23 +61,23 @@ static int tickInternalToUser(int tick, const Trace &trace) {
if (tick == -1) return -1;
switch (sar_trace_draw_time.GetInt()) {
case 2:
return tick + trace.startSessionTick;
return tick + trace.startSessionTick + trace.tasTickOffset;
case 3:
if (trace.startTasTick > 0) return tick + trace.startTasTick;
if (trace.startTasTick > 0) return tick + trace.startTasTick + trace.tasTickOffset;
default: // FALLTHROUGH
return tick;
return tick + trace.tasTickOffset;
}
}

static int tickUserToInternal(int tick, const Trace &trace) {
if (tick == -1) return -1;
switch (sar_trace_draw_time.GetInt()) {
case 2:
return tick - trace.startSessionTick;
return tick - trace.startSessionTick - trace.tasTickOffset;
case 3:
if (trace.startTasTick > 0) return tick - trace.startTasTick;
if (trace.startTasTick > 0) return tick - trace.startTasTick - trace.tasTickOffset;
default: // FALLTHROUGH
return tick;
return tick - trace.tasTickOffset;
}
}

Expand Down Expand Up @@ -136,6 +137,12 @@ void PlayerTrace::AddPoint(std::string trace_name, void *player, int slot, bool
if (traces.count(trace_name) == 0) {
traces[trace_name] = Trace();
traces[trace_name].startSessionTick = session->GetTick();

auto it = playerTrace->tickOffsets.find(trace_name);

if (it != playerTrace->tickOffsets.end()) {
traces[trace_name].tasTickOffset = it->second;
}
}

Trace &trace = traces[trace_name];
Expand Down Expand Up @@ -889,6 +896,20 @@ int PlayerTrace::GetTasTraceTick() {
return max_tas_tick;
}

void PlayerTrace::SetTickOffset(std::string &trace_name, int offset) {
playerTrace->tickOffsets[trace_name] = offset;
}

void PlayerTrace::ResetAllTraceOffsets() {
for (auto it = playerTrace->traces.begin(); it != playerTrace->traces.end(); ++it) {
Trace &trace = it->second;

trace.tasTickOffset = 0;
}

playerTrace->tickOffsets.clear();
}

HUD_ELEMENT2(trace, "0", "Draws info about current trace bbox tick.\n", HudType_InGame | HudType_Paused) {
if (!sv_cheats.GetBool()) return;
playerTrace->DrawTraceHud(ctx);
Expand Down Expand Up @@ -1239,6 +1260,40 @@ CON_COMMAND(sar_trace_compare, "sar_trace_compare <trace 1> <trace 2> - compares
}
}

CON_COMMAND(sar_trace_sync, "sar_trace_sync - syncs all the hovered traces to the fastest trace.\n") {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if we don't want to compare to the trace that's fastest? What if our other traces we're comparing to are faster instead?

I think this feature would be more versatile if you could specify which trace to sync to (that is, sar_trace_sync_all_to [trace_name])

size_t min_tick = SIZE_MAX;

for (auto &h : hovers) {
min_tick = std::min(min_tick, h.tick);
}

for (auto &h : hovers) {
auto trace = playerTrace->GetTrace(h.trace_name);

auto offset = min_tick - h.tick;

trace->tasTickOffset = offset;

playerTrace->SetTickOffset(h.trace_name, offset);
}
}

CON_COMMAND(sar_trace_sync_reset_all, "sar_trace_sync_reset_all - resets the sync of all the player traces.\n") {
playerTrace->ResetAllTraceOffsets();
}

CON_COMMAND(sar_trace_sync_reset, "sar_trace_sync_reset <name> - resets the sync of the player trace by the given name.\n") {
if (args.ArgC() < 2) {
return console->Print(sar_trace_sync_reset.ThisPtr()->m_pszHelpString);
}

std::string trace_name = args[1];

playerTrace->GetTrace(trace_name)->tasTickOffset = 0;

playerTrace->SetTickOffset(trace_name, 0);
}

void PlayerTrace::EnterLogScope(const char *name) {
if (!playerTrace->ShouldRecord()) return;
auto trace = this->GetTrace(sar_trace_record.GetString());
Expand Down
7 changes: 7 additions & 0 deletions src/Features/PlayerTrace.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ struct PortalLocations {
struct Trace {
int startSessionTick;
int startTasTick;
int tasTickOffset = 0;
std::vector<Vector> positions[2];
std::vector<Vector> eyepos[2];
std::vector<QAngle> angles[2];
Expand All @@ -69,6 +70,8 @@ class PlayerTrace : public Feature {
private:
// In order to arbitrarily number traces
std::map<std::string, Trace> traces;
// Universal map for trace tick offsets to be able to preserve them between trace recordings
std::unordered_map<std::string, int> tickOffsets;
Comment on lines +73 to +74

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You've created extra trace information which is implicitly not cleared when removing traces. I'm not a fan of that and I'd like to know what justifies this choice.

std::string lastRecordedTrace;
public:
PlayerTrace();
Expand Down Expand Up @@ -114,6 +117,10 @@ class PlayerTrace : public Feature {
void CheckTraceChanged();
// Get the current trace bbox tick for TAS stuff, or -1 if there isn't one
int GetTasTraceTick();
// Set tick offset globally
void SetTickOffset(std::string &trace_name, int offset);
// Reset all offsets
void ResetAllTraceOffsets();

// Returns an identifier for the scope which should be passed to ExitLogScope
void EnterLogScope(const char *name);
Expand Down