Repository navigation
Expand file tree
/
Copy pathRadar.h
More file actions
139 lines (110 loc) · 4.54 KB
/
Copy pathRadar.h
File metadata and controls
139 lines (110 loc) · 4.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#pragma once
/// @file
/// The Radar feature: a small 2D radar in the top-right corner plotting enemy
/// players relative to the local player's position and facing. See the class
/// comment for the in-game tuning caveats.
#include "Feature.h"
#include "../ue/Engine.h"
#include "../utils/Rgb.h"
#include "../cache/ActorCache.h"
#include "../render/Render.h"
#include <cmath>
// A simple 2D radar drawn in the top-right of the screen: enemy players are
// plotted relative to the local player's position and facing (forward = up).
//
// NOTE: rendering + world math that can only be tuned in-game — the rotation
// mapping (and its sign) and the range/size constants may need adjusting on a
// live game.
class Radar : public Feature
{
private:
UObject* CharacterClass = 0; ///< resolved PortalWarsCharacter UClass, used as the actor filter
static constexpr float Size = 200.f; // radar panel size, px
static constexpr float Margin = 20.f; // distance from the screen edge, px
static constexpr float Range = 6000.f; // world units mapped to the radar radius
/// Draw a small plus sign centred at (x, y) with arm length @p half.
void Cross(float x, float y, float half, float thickness, const Render::Color& color)
{
Render::Line({x - half, y}, {x + half, y}, thickness, color);
Render::Line({x, y - half}, {x, y + half}, thickness, color);
}
public:
Radar()
{
Name = "Radar";
UpdateEnabled();
Log("Created");
};
void UpdateEnabled()
{
Enabled = Settings.VISUALS.Radar;
};
bool Check()
{
if (!Initialized) return false;
if (!Engine::PlayerController) return false;
if (!Engine::IsInGame) return false;
if (!Engine::Canvas) return false;
return true;
};
void Init()
{
CharacterClass = Engine::GObjects->FindObject("Class PortalWars.PortalWarsCharacter");
Initialized = (!!CharacterClass);
Log("Initialized");
};
void Destroy() {
};
/// Draw the radar panel and player marker, then plot each enemy: rotate its
/// world delta into player-relative forward/right, scale by Range onto the
/// radar radius (forward = up), and drop points outside the panel.
void Run()
{
auto* controller = Engine::PlayerController;
auto* localPawn = controller->AcknowledgedPawn;
if (!localPawn) return;
const bool showFriendly = Settings.VISUALS.RadarShowFriendly;
const Render::Color friendColor = Settings.VISUALS.FriendColor;
// The local player's team, so teammates plot in FriendColor (and only when shown).
char localTeam = -1;
if (auto* localChar = reinterpret_cast<APortalWarsCharacter*>(controller->Character))
localTeam = localChar->GetTeamNum();
const FVector playerPos = localPawn->K2_GetActorLocation();
const float yaw = controller->ControlRotation.Yaw * (3.14159265f / 180.f);
const float cosYaw = cosf(yaw);
const float sinYaw = sinf(yaw);
const float radius = Size * 0.5f;
const float cx = Engine::Canvas->ClipX - Margin - radius;
const float cy = Margin + radius;
// Panel border + own marker: the cycling RGB color when enabled, else the default white.
const Render::Color border = Settings.MENU.Rgb ? Render::Color(Rgb::Current()) : Render::Color{1.f, 1.f, 1.f, 1.f};
const Render::Color dot{1.f, 0.f, 0.f, 1.f};
// Panel border + player marker at the centre.
const FVector2D tl{cx - radius, cy - radius}, tr{cx + radius, cy - radius};
const FVector2D bl{cx - radius, cy + radius}, br{cx + radius, cy + radius};
Render::Line(tl, tr, 1.f, border);
Render::Line(tr, br, 1.f, border);
Render::Line(br, bl, 1.f, border);
Render::Line(bl, tl, 1.f, border);
Cross(cx, cy, 3.f, 1.f, border);
// Shared per-frame actor pass (ActorCache); location + team already resolved there.
for (const auto& cached : ActorCache::Players())
{
if (reinterpret_cast<AActor*>(cached.character) == reinterpret_cast<AActor*>(localPawn)) continue;
const char team = cached.team;
const bool friendly = (localTeam >= 0 && team == localTeam);
if (friendly && !showFriendly) continue;
const Render::Color color = friendly ? friendColor : dot;
const FVector enemyPos = cached.location;
const float dx = enemyPos.X - playerPos.X;
const float dy = enemyPos.Y - playerPos.Y;
// Rotate the world delta into player-relative space (forward/right).
const float forward = dx * cosYaw + dy * sinYaw;
const float right = -dx * sinYaw + dy * cosYaw;
const float px = cx + (right / Range) * radius;
const float py = cy - (forward / Range) * radius; // forward = up
if (px < cx - radius || px > cx + radius || py < cy - radius || py > cy + radius) continue;
Cross(px, py, 2.f, 2.f, color);
}
};
};