Skip to content

Commit 0cb8a3d

Browse files
committed
fix camera zoom on spec while keys rebinded
1 parent 755b78f commit 0cb8a3d

File tree

1 file changed

+268
-0
lines changed

1 file changed

+268
-0
lines changed

Rules/CommonScripts/Spectator.as

Lines changed: 268 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,268 @@
1+
#include "CinematicCommon.as"
2+
#include "MapVotesCommon.as"
3+
4+
#define CLIENT_ONLY
5+
6+
const bool FOCUS_ON_IMPORTANT_BLOBS = true; //whether camera should focus on important blobs
7+
8+
const float CINEMATIC_PAN_X_EASE = 6.0f; //amount of ease along the x-axis while cinematic
9+
const float CINEMATIC_PAN_Y_EASE = 6.0f; //amount of ease along the y-axis while cinematic
10+
11+
const float CINEMATIC_ZOOM_EASE = 16.0f; //amount of ease when zooming while cinematic
12+
const float CINEMATIC_CLOSEST_ZOOM = 1.0f; //how close the camera can zoom in while cinematic (default is 2.0f)
13+
const float CINEMATIC_FURTHEST_ZOOM = 0.5f; //how far the camera can zoom out while cinematic (default is 0.5f)
14+
15+
const float AUTO_CINEMATIC_TIME = 3.0f; //time until camera automatically becomes cinematic. set to zero to disable
16+
17+
Vec2f posActual;
18+
Vec2f posTarget; //position which cinematic camera moves towards
19+
float zoomTarget = 1.0f; //zoom level which camera zooms towards
20+
float timeToScroll = 0.0f; //time until next able to scroll to zoom camera
21+
float timeToCinematic = 0.0f; //time until camera automatically becomes cinematic
22+
float panEaseModifier = 1.0f; //by how much the x/y ease values are multiplied
23+
float zoomEaseModifier = 1.0f; //by how much the zoom ease values are multiplied
24+
uint currentTarget; //the current target blob
25+
uint switchTarget; //time when camera can move onto new target
26+
27+
bool justClicked = false;
28+
string _targetPlayer;
29+
bool waitForRelease = false;
30+
31+
CPlayer@ targetPlayer()
32+
{
33+
return getPlayerByUsername(_targetPlayer);
34+
}
35+
36+
const Vec2f[] easePosLerpTable = {
37+
Vec2f(0.0, 1.0),
38+
Vec2f(8.0, 1.0),
39+
Vec2f(16.0, 0.8),
40+
Vec2f(64.0, 0.6),
41+
Vec2f(96.0, 0.8),
42+
Vec2f(128.0, 1.0),
43+
};
44+
45+
float ease(float current, float target, float factor)
46+
{
47+
const float diff = target - current;
48+
const float linearCorrection = diff * factor * panEaseModifier;
49+
50+
const float x = Maths::Abs(diff);
51+
52+
float cubicCorrectionMod = 1.0;
53+
for (int i = 1; i < easePosLerpTable.size(); ++i)
54+
{
55+
Vec2f a = easePosLerpTable[i-1];
56+
Vec2f b = easePosLerpTable[i];
57+
if (x >= a.x && x < b.x)
58+
{
59+
const float f = (x - a.x) / (b.x - a.x);
60+
cubicCorrectionMod = Maths::Lerp(a.y, b.y, f);
61+
break;
62+
}
63+
}
64+
65+
const float finalCorrection = linearCorrection * cubicCorrectionMod;
66+
67+
return current + linearCorrection * cubicCorrectionMod;
68+
}
69+
70+
void SetTargetPlayer(CPlayer@ p)
71+
{
72+
_targetPlayer = "";
73+
if (p is null) return;
74+
_targetPlayer = p.getUsername();
75+
}
76+
77+
void Spectator(CRules@ this)
78+
{
79+
CCamera@ camera = getCamera();
80+
CControls@ controls = getControls();
81+
CMap@ map = getMap();
82+
83+
if (camera is null || controls is null || map is null)
84+
{
85+
return;
86+
}
87+
88+
//variables
89+
Vec2f mapDim = map.getMapDimensions();
90+
float camSpeed = getRenderApproximateCorrectionFactor() * 15.0f / zoomTarget;
91+
92+
if (this.get_bool("set new target"))
93+
{
94+
string newTarget = this.get_string("new target");
95+
_targetPlayer = newTarget;
96+
if (targetPlayer() !is null)
97+
{
98+
waitForRelease = true;
99+
this.set_bool("set new target", false);
100+
}
101+
}
102+
103+
//scroll to zoom
104+
if (timeToScroll <= 0)
105+
{
106+
if (controls.isKeyJustPressed(controls.getActionKeyKey(AK_ZOOMIN)))
107+
{
108+
timeToScroll = 7;
109+
setCinematicEnabled(false);
110+
111+
if (zoomTarget < 1.0f)
112+
{
113+
zoomTarget = 1.0f;
114+
}
115+
else
116+
{
117+
zoomTarget = 2.0f;
118+
}
119+
}
120+
else if (controls.isKeyJustPressed(controls.getActionKeyKey(AK_ZOOMOUT)))
121+
{
122+
timeToScroll = 7;
123+
setCinematicEnabled(false);
124+
125+
if (zoomTarget > 1.0f)
126+
{
127+
zoomTarget = 1.0f;
128+
}
129+
else
130+
{
131+
zoomTarget = 0.5f;
132+
}
133+
}
134+
}
135+
else
136+
{
137+
timeToScroll -= getRenderApproximateCorrectionFactor();
138+
}
139+
140+
//move camera using action movement keys
141+
if (controls.ActionKeyPressed(AK_MOVE_LEFT))
142+
{
143+
posActual.x -= camSpeed;
144+
SetTargetPlayer(null);
145+
setCinematicEnabled(false);
146+
}
147+
if (controls.ActionKeyPressed(AK_MOVE_RIGHT))
148+
{
149+
posActual.x += camSpeed;
150+
SetTargetPlayer(null);
151+
setCinematicEnabled(false);
152+
}
153+
if (controls.ActionKeyPressed(AK_MOVE_UP))
154+
{
155+
posActual.y -= camSpeed;
156+
SetTargetPlayer(null);
157+
setCinematicEnabled(false);
158+
}
159+
if (controls.ActionKeyPressed(AK_MOVE_DOWN))
160+
{
161+
posActual.y += camSpeed;
162+
SetTargetPlayer(null);
163+
setCinematicEnabled(false);
164+
}
165+
166+
if (controls.isKeyJustReleased(KEY_LBUTTON))
167+
{
168+
waitForRelease = false;
169+
}
170+
171+
if (!isCinematicEnabled() || targetPlayer() !is null) //player-controlled zoom
172+
{
173+
if (Maths::Abs(camera.targetDistance - zoomTarget) > 0.001f)
174+
{
175+
camera.targetDistance = (camera.targetDistance * (3.0f - getRenderApproximateCorrectionFactor() + 1.0f) + (zoomTarget * getRenderApproximateCorrectionFactor())) / 4.0f;
176+
}
177+
else
178+
{
179+
camera.targetDistance = zoomTarget;
180+
}
181+
182+
if (AUTO_CINEMATIC_TIME > 0)
183+
{
184+
timeToCinematic -= getRenderSmoothDeltaTime();
185+
if (timeToCinematic <= 0)
186+
{
187+
setCinematicEnabled(true);
188+
}
189+
}
190+
}
191+
else //cinematic camera
192+
{
193+
const float corrFactor = getRenderApproximateCorrectionFactor();
194+
camera.targetDistance += (zoomTarget - camera.targetDistance) / CINEMATIC_ZOOM_EASE * corrFactor * zoomEaseModifier;
195+
196+
posActual.x = ease(posActual.x, posTarget.x, corrFactor / CINEMATIC_PAN_X_EASE);
197+
posActual.y = ease(posActual.y, posTarget.y, corrFactor / CINEMATIC_PAN_Y_EASE);
198+
}
199+
200+
//click on players to track them or set camera to mousePos
201+
Vec2f mousePos = controls.getMouseWorldPos();
202+
if (controls.isKeyJustPressed(KEY_LBUTTON) && !waitForRelease)
203+
{
204+
CBlob@[] players;
205+
SetTargetPlayer(null);
206+
getBlobsByTag("player", @players);
207+
for (uint i = 0; i < players.length; i++)
208+
{
209+
CBlob@ blob = players[i];
210+
Vec2f bpos = blob.getInterpolatedPosition();
211+
if (blob.getName() == "migrant") //screw migrants
212+
{
213+
continue;
214+
}
215+
216+
if (Maths::Pow(mousePos.x - bpos.x, 2) + Maths::Pow(mousePos.y - bpos.y, 2) <= Maths::Pow(blob.getRadius() * 2, 2) && camera.getTarget() !is blob)
217+
{
218+
SetTargetPlayer(blob.getPlayer());
219+
camera.setTarget(blob);
220+
waitForRelease = true;
221+
setCinematicEnabled(false);
222+
}
223+
}
224+
}
225+
else if (!waitForRelease && controls.isKeyPressed(KEY_LBUTTON) && camera.getTarget() is null) //classic-like held mouse moving
226+
{
227+
// HACK: this is terrible and we need proper GUI and cursor capture shit
228+
// ofc this is still an issue with the queue stuff now :upside_down:
229+
MapVotesMenu@ mvm = null;
230+
this.get("MapVotesMenu", @mvm);
231+
232+
if (mvm is null || !isMapVoteActive() || !mvm.screenPositionOverlaps(controls.getMouseScreenPos()))
233+
{
234+
posActual += (mousePos - posActual) / 8.0f * getRenderApproximateCorrectionFactor();
235+
setCinematicEnabled(false);
236+
}
237+
}
238+
239+
if (targetPlayer() !is null)
240+
{
241+
if (camera.getTarget() !is targetPlayer().getBlob())
242+
{
243+
camera.setTarget(targetPlayer().getBlob());
244+
}
245+
posActual = camera.getPosition();
246+
}
247+
else
248+
{
249+
camera.setTarget(null);
250+
}
251+
252+
//set specific zoom if we have a target
253+
if (camera.getTarget() !is null)
254+
{
255+
camera.mousecamstyle = 1;
256+
camera.mouseFactor = 0.5f;
257+
return;
258+
}
259+
260+
//keep camera within map boundaries
261+
float borderMarginX = map.tilesize * 2.0f / zoomTarget;
262+
float borderMarginY = map.tilesize * 2.0f / zoomTarget;
263+
posActual.x = Maths::Clamp(posActual.x, borderMarginX, mapDim.x - borderMarginX);
264+
posActual.y = Maths::Clamp(posActual.y, borderMarginY, mapDim.y - borderMarginY);
265+
266+
//set camera position
267+
camera.setPosition(posActual);
268+
}

0 commit comments

Comments
 (0)