forked from shavitush/bhoptimer
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcore.inc
More file actions
1461 lines (1288 loc) · 43.9 KB
/
Copy pathcore.inc
File metadata and controls
1461 lines (1288 loc) · 43.9 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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
* shavit's Timer - core.inc file
* by: shavit, KiD Fearless, rtldg, Nairda, GAMMA CASE, carnifex,
*
* This file is part of shavit's Timer (https://github.com/shavitush/bhoptimer)
*
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#if defined _shavit_core_included
#endinput
#endif
#define _shavit_core_included
#define SHAVIT_VERSION_MAJOR 4
#define SHAVIT_VERSION_MINOR 0
#define SHAVIT_VERSION_PATCH 2
#define SHAVIT_VERSION "4.0.2a"
#define STYLE_LIMIT 256
// god i fucking hate sourcemod. NULL_VECTOR isn't const so it's not guaranteed to be 0,0,0
#define ZERO_VECTOR view_as<float>({0,0,0})
// stolen from boosterfix
#define EXPAND_VECTOR(%1) %1[0], %1[1], %1[2]
#include <shavit/bhopstats-timerified>
enum TimerStatus
{
Timer_Stopped,
Timer_Running,
Timer_Paused
};
enum
{
CPR_ByConVar = (1 << 0),
CPR_NoTimer = (1 << 1),
CPR_InStartZone = (1 << 2),
CPR_NotOnGround = (1 << 3),
CPR_Moving = (1 << 4),
CPR_Duck = (1 << 5), // quack
CPR_InEndZone = (1 << 6),
};
enum
{
Track_Main,
Track_Bonus,
Track_Bonus_Last = 8,
TRACKS_SIZE
};
// for Shavit_GetStyleStrings
enum
{
sStyleName,
sShortName,
// Used in CSGO
sHTMLColor,
sChangeCommand,
sClanTag,
sSpecialString,
sStylePermission
};
// for Shavit_GetChatStrings
enum
{
sMessagePrefix,
sMessageText,
sMessageWarning,
sMessageVariable,
sMessageVariable2,
sMessageStyle
};
enum struct stylestrings_t
{
char sStyleName[64];
char sShortName[32];
char sHTMLColor[32];
char sChangeCommand[128];
char sClanTag[32];
char sSpecialString[128];
char sStylePermission[64];
}
enum struct chatstrings_t
{
char sPrefix[64];
char sText[16];
char sWarning[16];
char sVariable[16];
char sVariable2[16];
char sStyle[16];
}
enum struct timer_snapshot_t
{
bool bTimerEnabled;
// fCurrentTime = (float(iFullTicks)+(iFractionalTicks/10000.0)+fZoneOffset[0])*GetTickInterval()
float fCurrentTime;
bool bClientPaused;
int iJumps;
int bsStyle;
int iStrafes;
// Total times we checked if a strafe was "synced".
int iTotalMeasures;
// Not actually "gains". How many times a strafe was "synced".
int iGoodGains;
// Not actually used for anything. GetEngineTime() when the snapshot was taken.
float fServerTime;
// -1 by default which means no key combination
// if a_or_d_only: 0 = IN_MOVELEFT (a), 1 = IN_MOVERIGHT (d)
// if surf hsw: 0 = WA/SD, 1 = WD/SA
int iKeyCombo;
int iTimerTrack;
// How many times we checked if the player jumped on the same tick they land.
// This is only incremented if the player jumps within 10 ticks of landing (this is just an implementation note and could change (99% won't though)).
int iMeasuredJumps;
// How many times the player jumped on the same tick they land.
int iPerfectJumps;
// used as a "tick fraction" basically
float fZoneOffset[2];
float fDistanceOffset[2];
float fAvgVelocity;
float fMaxVelocity;
float fTimescale;
// Internal counter used for calculating the startzone's fZoneOffset & fDistanceOffset
int iZoneIncrement;
int iFullTicks;
int iFractionalTicks; // divide this by 10000.0 to get a fraction of a tick. whole ticks are moved to iFullTicks
bool bPracticeMode;
// Internal bool for checking if the player jumped.
bool bJumped;
// If shavit_core_simplerladders == 1 & we're on a ladder then this is true so the player can use any keys when they're on SW or W-only or etc...
bool bCanUseAllKeys;
// Internal bool for checking if the player is(/was?) on the ground. Complicated...
bool bOnGround;
// Currently unused but saved because why not...
int iLastButtons;
// Internal float used for checking if the player's horizontal viewangle changed so we can do sync stuff.
float fLastAngle;
// Internal int used for the iMeasuredJumps & iPerfectJumps stuff.
// How many ticks the player has been on the ground since landing. 0 = in air.
int iGroundTicks;
// Internal value used for unfucking style/zone gravity when using ladders.
MoveType iLastMoveType;
// Internal value used for blocking +strafe (if block_pstrafe is enabled).
float fStrafeWarning;
// Internal values used for incrementing strafe count.
float fLastInputVel[2];
// Internal value used for unfucking m_flLaggedMovementValue from player_speedmod's when combined with style settings such as "timescale" and "speed".
float fplayer_speedmod;
// Internal value used for timescaling and recording frames and stuff....
float fNextFrameTime;
// Internal value used for timescaling and stuff....
MoveType iLastMoveTypeTAS;
}
stock void Shavit_LogQuery(const char[] query)
{
static File hLogFile;
static ConVar shavit_core_log_sql = null;
if (shavit_core_log_sql == null)
{
shavit_core_log_sql = FindConVar("shavit_core_log_sql");
}
if (!shavit_core_log_sql || !shavit_core_log_sql.BoolValue)
{
return;
}
if (hLogFile == null)
{
char sPlugin[PLATFORM_MAX_PATH];
GetPluginFilename(INVALID_HANDLE, sPlugin, sizeof(sPlugin));
ReplaceString(sPlugin, PLATFORM_MAX_PATH, ".smx", "");
ReplaceString(sPlugin, PLATFORM_MAX_PATH, "\\", "/");
int start = FindCharInString(sPlugin, '/', true);
char sFilename[PLATFORM_MAX_PATH];
BuildPath(Path_SM, sFilename, sizeof(sFilename), "logs/%s_sql.log", sPlugin[start+1]);
hLogFile = OpenFile(sFilename, "a");
}
if (hLogFile)
{
LogToOpenFileEx(hLogFile, "%s", query);
}
}
stock void QueryLog(Database db, SQLQueryCallback callback, const char[] query, any data = 0, DBPriority prio = DBPrio_Normal)
{
Shavit_LogQuery(query);
db.Query(callback, query, data, prio);
}
stock int AddQueryLog(Transaction trans, const char[] query, any data = 0)
{
Shavit_LogQuery(query);
return trans.AddQuery(query, data);
}
// connects synchronously to the bhoptimer database
// call errors if needed
stock Database GetTimerDatabaseHandle(bool reuse_persistent_connection=true)
{
Database db = null;
char sError[255];
if(SQL_CheckConfig("shavit"))
{
if((db = SQL_Connect("shavit", reuse_persistent_connection, sError, 255)) == null)
{
SetFailState("Timer startup failed. Reason: %s", sError);
}
}
else
{
db = SQLite_UseDatabase("shavit", sError, 255);
}
// support unicode names
if (!db.SetCharset("utf8mb4"))
{
db.SetCharset("utf8");
}
return db;
}
enum {
Driver_unknown,
Driver_sqlite,
Driver_mysql,
Driver_pgsql,
}
stock int GetDatabaseDriver(Database db)
{
char sDriver[16];
db.Driver.GetIdentifier(sDriver, sizeof(sDriver));
if (StrEqual(sDriver, "mysql", false))
return Driver_mysql;
else if (StrEqual(sDriver, "sqlite", false))
return Driver_sqlite;
else if (StrEqual(sDriver, "pgsql", false))
return Driver_pgsql;
else
return Driver_unknown;
}
stock void LowercaseString(char[] str)
{
int i, x;
while ((x = str[i]) != 0)
{
if ('A' <= x <= 'Z')
str[i] += ('a' - 'A');
++i;
}
}
stock void UppercaseString(char[] str)
{
int i, x;
while ((x = str[i]) != 0)
{
if ('a' <= x <= 'z')
str[i] -= ('a' - 'A');
++i;
}
}
// GetMapDisplayName ends up opening every single fucking file to verify it's valid.
// I don't care about that. I just want the stupid fucking mapname string.
// Also this lowercases the string.
stock void LessStupidGetMapDisplayName(const char[] map, char[] displayName, int maxlen)
{
char temp[PLATFORM_MAX_PATH];
char temp2[PLATFORM_MAX_PATH];
strcopy(temp, sizeof(temp), map);
ReplaceString(temp, sizeof(temp), "\\", "/", true);
int slashpos = FindCharInString(temp, '/', true);
strcopy(temp2, sizeof(temp2), temp[slashpos+1]);
int ugcpos = StrContains(temp2, ".ugc", true);
if (ugcpos != -1)
{
temp2[ugcpos] = 0;
}
LowercaseString(temp2);
strcopy(displayName, maxlen, temp2);
}
stock void GetLowercaseMapName(char sMap[PLATFORM_MAX_PATH])
{
GetCurrentMap(sMap, sizeof(sMap));
LessStupidGetMapDisplayName(sMap, sMap, sizeof(sMap));
}
// retrieves the table prefix defined in configs/shavit-prefix.txt
stock void GetTimerSQLPrefix(char[] buffer, int maxlen)
{
char sFile[PLATFORM_MAX_PATH];
BuildPath(Path_SM, sFile, PLATFORM_MAX_PATH, "configs/shavit-prefix.txt");
File fFile = OpenFile(sFile, "r");
if(fFile == null)
{
SetFailState("Cannot open \"configs/shavit-prefix.txt\". Make sure this file exists and that the server has read permissions to it.");
}
char sLine[PLATFORM_MAX_PATH * 2];
if(fFile.ReadLine(sLine, PLATFORM_MAX_PATH * 2))
{
TrimString(sLine);
strcopy(buffer, maxlen, sLine);
}
delete fFile;
}
stock bool IsValidClient(int client, bool bAlive = false)
{
return (client >= 1 && client <= MaxClients && IsClientInGame(client) && !IsClientSourceTV(client) && (!bAlive || IsPlayerAlive(client)));
}
stock bool IsSource2013(EngineVersion ev)
{
return (ev == Engine_CSS || ev == Engine_TF2);
}
stock void IPAddressToString(int ip, char[] buffer, int maxlen)
{
FormatEx(buffer, maxlen, "%d.%d.%d.%d", ((ip >> 24) & 0xFF), ((ip >> 16) & 0xFF), ((ip >> 8) & 0xFF), (ip & 0xFF));
}
stock int IPStringToAddress(const char[] ip)
{
char sExplodedAddress[4][4];
ExplodeString(ip, ".", sExplodedAddress, 4, 4, false);
int iIPAddress =
(StringToInt(sExplodedAddress[0]) << 24) |
(StringToInt(sExplodedAddress[1]) << 16) |
(StringToInt(sExplodedAddress[2]) << 8) |
StringToInt(sExplodedAddress[3]);
return iIPAddress;
}
// time formatting!
stock void FormatSeconds(float time, char[] newtime, int newtimesize, bool precise = true, bool nodecimal = false, bool full_hms = false)
{
float fTempTime = time;
if(fTempTime < 0.0)
{
fTempTime = -fTempTime;
}
int iRounded = RoundToFloor(fTempTime);
int iSeconds = (iRounded % 60);
float fSeconds = iSeconds + fTempTime - iRounded;
char sSeconds[8];
if (nodecimal)
{
FormatEx(sSeconds, 8, "%d", iSeconds);
}
else
{
FormatEx(sSeconds, 8, precise? "%.3f":"%.1f", fSeconds);
}
if (!full_hms && fTempTime < 60.0)
{
strcopy(newtime, newtimesize, sSeconds);
FormatEx(newtime, newtimesize, "%s%s", (time < 0.0) ? "-":"", sSeconds);
}
else
{
int iMinutes = (iRounded / 60);
if (!full_hms && fTempTime < 3600.0)
{
FormatEx(newtime, newtimesize, "%s%d:%s%s", (time < 0.0)? "-":"", iMinutes, (fSeconds < 10)? "0":"", sSeconds);
}
else
{
int iHours = (iMinutes / 60);
iMinutes %= 60;
FormatEx(newtime, newtimesize, "%s%d:%s%d:%s%s", (time < 0.0)? "-":"", iHours, (iMinutes < 10)? "0":"", iMinutes, (fSeconds < 10)? "0":"", sSeconds);
}
}
}
stock void PrettyishTimescale(char[] buffer, int size, float ts, float min, float max, float x)
{
ts += x;
ts = (ts < min) ? min : ((ts > max) ? max : ts);
if (ts == 1.0)
{
FormatEx(buffer, size, "1.0");
return;
}
FormatEx(buffer, size, "0.%d", RoundFloat(ts * 10.0));
}
stock bool GuessBestMapName(ArrayList maps, const char input[PLATFORM_MAX_PATH], char output[PLATFORM_MAX_PATH])
{
if(maps.FindString(input) != -1)
{
output = input;
return true;
}
char sCache[PLATFORM_MAX_PATH];
for(int i = 0; i < maps.Length; i++)
{
maps.GetString(i, sCache, PLATFORM_MAX_PATH);
if(StrContains(sCache, input) != -1)
{
output = sCache;
return true;
}
}
return false;
}
stock void GetTrackName(int client, int track, char[] output, int size, bool include_bonus_num=true)
{
if (track == Track_Main)
{
FormatEx(output, size, "%T", "Track_Main", client);
}
else if (Track_Bonus <= track < TRACKS_SIZE)
{
FormatEx(output, size, "%T", include_bonus_num ? "Track_Bonus" : "Track_Bonus_NoNum", client, track);
}
else
{
FormatEx(output, size, "%T", "Track_Unknown", client);
}
}
stock int GetSpectatorTarget(int client, int fallback = -1)
{
int target = fallback;
if(IsClientObserver(client))
{
int iObserverMode = GetEntProp(client, Prop_Send, "m_iObserverMode");
if (iObserverMode >= 3 && iObserverMode <= 7)
{
int iTarget = GetEntPropEnt(client, Prop_Send, "m_hObserverTarget");
if (IsValidEntity(iTarget))
{
target = iTarget;
}
}
}
return target;
}
stock float GetAngleDiff(float current, float previous)
{
float diff = current - previous;
return diff - 360.0 * RoundToFloor((diff + 180.0) / 360.0);
}
// https://forums.alliedmods.net/showthread.php?t=216841
// Trims display string to specified max possible length, and appends "..." if initial string exceeds that length
stock void TrimDisplayString(const char[] str, char[] outstr, int outstrlen, int max_allowed_length)
{
int count, finallen;
for(int i = 0; str[i]; i++)
{
count += ((str[i] & 0xc0) != 0x80) ? 1 : 0;
if(count <= max_allowed_length)
{
outstr[i] = str[i];
finallen = i;
}
}
outstr[finallen + 1] = '\0';
if(count > max_allowed_length)
Format(outstr, outstrlen, "%s...", outstr);
}
// TODO: surfacefriction
stock float MaxPrestrafe(float runspeed, float accelerate, float friction, float tickinterval)
{
if (friction < 0.0) return 9999999.0; // hello ~~mario~~ bhop_ins_mariooo
if (accelerate < 0.0) accelerate = -accelerate;
float something = runspeed * SquareRoot(
(accelerate / friction) *
((2.0 - accelerate * tickinterval) / (2.0 - friction * tickinterval))
);
return something < 0.0 ? -something : something;
}
/**
* Called before shavit-core processes the client's usercmd.
* Before this is called, safety checks (fake/dead clients) happen.
* Use this forward in modules that use OnPlayerRunCmd to avoid errors and unintended behavior.
* If a module conflicts with buttons/velocity/angles being changed in shavit-core, this forward is recommended.
* This forward will NOT be called if a player's timer is paused.
*
* @param client Client index.
* @param buttons Buttons sent in the usercmd.
* @param impulse Impulse sent in the usercmd.
* @param vel A vector that contains the player's desired movement. vel[0] is forwardmove, vel[1] is sidemove.
* @param angles The player's requested viewangles. They will not necessarily be applied as SRCDS itself won't accept every value.
* @param status The player's timer status.
* @param track The player's timer track.
* @param style The player's bhop style.
* @param mouse Mouse direction (x, y).
* @return Plugin_Continue to let shavit-core keep doing what it does, Plugin_Changed to pass different values.
*/
forward Action Shavit_OnUserCmdPre(int client, int &buttons, int &impulse, float vel[3], float angles[3], TimerStatus status, int track, int style, int mouse[2]);
/**
* Called just before shavit-core adds time to a player's timer.
*
* @param client Client index.
* @param snapshot A snapshot with the player's current timer. You cannot manipulate it here.
* @param time The time to be added to the player's timer.
* @noreturn
*/
forward void Shavit_OnTimeIncrement(int client, timer_snapshot_t snapshot, float &time);
/**
* Called just before shavit-core adds time to a player's timer.
*
* @param client Client index.
* @param snapshot A snapshot with the player's current timer. Read above in shavit.inc for more information.
* @param time The time to be added to the player's timer.
* @noreturn
*/
forward void Shavit_OnTimeIncrementPost(int client, float time);
/**
* Called when a player's timer is about to start.
* (WARNING: Will be called every tick when the player stands at the start zone!)
*
* @param client Client index.
* @param track Timer track.
* @param skipGroundTimer Whether shavit-core can skip the on-ground-for-half-a-second check. shavit-misc uses this for some prespeed settings...
* @return Plugin_Continue to do nothing or anything else to not start the timer.
*/
forward Action Shavit_OnStartPre(int client, int track, bool& skipGroundTimer);
/**
* Called when a player's timer starts.
* (WARNING: Will be called every tick when the player stands at the start zone!)
*
* @param client Client index.
* @param track Timer track.
* @return Unused.
*/
forward Action Shavit_OnStart(int client, int track);
/**
* Called when a player uses the restart command.
*
* @param client Client index.
* @param track Timer track.
* @return Plugin_Continue to do nothing or anything else to not restart.
*/
forward Action Shavit_OnRestartPre(int client, int track);
/**
* Called when a player uses the restart command.
*
* @param client Client index.
* @param track Timer track.
* @noreturn
*/
forward void Shavit_OnRestart(int client, int track);
/**
* Called when a player uses the !end command.
*
* @param client Client index.
* @param track Timer track.
* @return Plugin_Continue to do nothing or anything else to not goto the end.
*/
forward Action Shavit_OnEndPre(int client, int track);
/**
* Called when a player uses the !end command.
*
* @param client Client index.
* @param track Timer track.
* @noreturn
*/
forward void Shavit_OnEnd(int client, int track);
/**
* Called before a player's timer is stopped. (stop =/= finish a map)
*
* @param client Client index.
* @param track Timer track.
* @return False to prevent the timer from stopping.
*/
forward bool Shavit_OnStopPre(int client, int track);
/**
* Called when a player's timer stops. (stop =/= finish a map)
*
* @param client Client index.
* @param track Timer track.
* @noreturn
*/
forward void Shavit_OnStop(int client, int track);
/**
* Called before a player finishes a map.
*
* @param client Client index.
* @param snapshot A snapshot of the player's timer.
* @return Plugin_Continue to do nothing, Plugin_Changed to change the variables or anything else to stop the timer from finishing.
*/
forward Action Shavit_OnFinishPre(int client, timer_snapshot_t snapshot);
/**
* Called when a player finishes a map. (touches the end zone)
*
* @param client Client index.
* @param style Style the record was done on.
* @param time Record time.
* @param jumps Jumps amount.
* @param strafes Amount of strafes.
* @param sync Sync percentage (0.0 to 100.0) or -1.0 when not measured.
* @param track Timer track.
* @param oldtime The player's best time on the map before this finish.
* @param perfs Perfect jump percentage (0.0 to 100.0) or 100.0 when not measured.
* @param avgvel Player's average velocity throughout the run.
* @param maxvel Player's highest reached velocity.
* @param timestamp System time of when player finished.
* @noreturn
*/
forward void Shavit_OnFinish(int client, int style, float time, int jumps, int strafes, float sync, int track, float oldtime, float perfs, float avgvel, float maxvel, int timestamp);
/**
* Called when a player's timer paused.
*
* @param client Client index.
* @param track Timer track.
* @noreturn
*/
forward void Shavit_OnPause(int client, int track);
/**
* Called when a player's timer resumed.
*
* @param client Client index.
* @param track Timer track.
* @noreturn
*/
forward void Shavit_OnResume(int client, int track);
/**
* Called when a player tries to change their bhopstyle.
*
* @param client Client index.
* @param oldstyle Old bhop style.
* @param newstyle New bhop style.
* @param track Timer track.
* @return Plugin_Continue to do nothing. Anything else to block.
*/
forward Action Shavit_OnStyleCommandPre(int client, int oldstyle, int newstyle, int track);
/**
* Called when a player changes their bhopstyle.
* Note: Doesn't guarantee that the player is in-game or connected.
*
* @param client Client index.
* @param oldstyle Old bhop style.
* @param newstyle New bhop style.
* @param track Timer track.
* @param manual Was the change manual, or assigned automatically?
* @noreturn
*/
forward void Shavit_OnStyleChanged(int client, int oldstyle, int newstyle, int track, bool manual);
/**
* Called when a player changes their bhop track.
*
* @param client Client index.
* @param oldtrack Old bhop track.
* @param newtrack New bhop track.
* @noreturn
*/
forward void Shavit_OnTrackChanged(int client, int oldtrack, int newtrack);
/**
* Called when the styles configuration finishes loading and it's ready to load everything into the cache.
*
* @param styles Amount of styles loaded.
* @noreturn
*/
forward void Shavit_OnStyleConfigLoaded(int styles);
/**
* Called when there's a successful connection to the database and it is ready to be used.
* Called through shavit-core after migrations have been applied, and after the attempt to create the default `users` table.
*
* @noreturn
*/
forward void Shavit_OnDatabaseLoaded();
/**
* Called when the chat messages configuration finishes loading and it's ready to load everything into the cache.
*
* @noreturn
*/
forward void Shavit_OnChatConfigLoaded();
/**
* Called when a player gets the worst record in the server for the style.
* Note: Will be only called for ranked styles.
*
* @param client Client index.
* @param style Style the record was done on.
* @param time Record time.
* @param jumps Jumps amount.
* @param strafes Amount of strafes.
* @param sync Sync percentage (0.0 to 100.0) or -1.0 when not measured.
* @param track Timer track.
* @param oldtime The player's best time on the map before this finish.
* @param perfs Perfect jump percentage (0.0 to 100.0) or 100.0 when not measured.
* @param avgvel Player's average velocity throughout the run.
* @param maxvel Player's highest reached velocity.
* @param timestamp System time of when player finished.
* @noreturn
*/
forward void Shavit_OnWorstRecord(int client, int style, float time, int jumps, int strafes, float sync, int track, float oldtime, float perfs, float avgvel, float maxvel, int timestamp);
/**
* Called when a time offset is calculated
*
* @param client Client index.
* @param zonetype Zone type (Zone_Start or Zone_End).
* @param offset Time offset from the given zone.
* @param distance Distance used in time offset.
* @noreturn
*/
forward void Shavit_OnTimeOffsetCalculated(int client, int zonetype, float offset, float distance);
/**
* Called when a client's dynamic timescale has been changed.
* For the client's total timescale value, see the comments next to `Shavit_GetClientTimescale()`.
*
* @param client Client index.
* @param oldtimescale The old timescale value
* @param newtimescale The new timescale value
* @noreturn
*/
forward void Shavit_OnTimescaleChanged(int client, float oldtimescale, float newtimescale);
/**
* Called before a sound is played by shavit-sounds.
*
* @param client Index of the client that triggered the sound event.
* @param sound Reference to the sound that will be played.
* @param maxlength Length of the sound buffer, always PLATFORM_MAX_PATH.
* @param clients Reference to the array of clients to receive the sound, maxsize of MaxClients.
* @param count Reference to the number of clients to receive the sound.
* @return Plugin_Handled or Plugin_Stop to block the sound from being played. Anything else to continue the operation.
*/
forward Action Shavit_OnPlaySound(int client, char[] sound, int maxlength, int[] clients, int &count);
/**
* Called before the server & timer handle the ProcessMovement method.
*
* @param client Client Index.
* @noreturn
*/
forward void Shavit_OnProcessMovement(int client);
/**
* Called After the server handles the ProcessMovement method, but before the timer handles the method.
*
* @param client Client Index.
* @noreturn
*/
forward void Shavit_OnProcessMovementPost(int client);
/**
* Called from shavit-timelimit when the 5 second map change countdown starts.
*
* @noreturn
*/
forward void Shavit_OnCountdownStart();
/**
* Returns bhoptimer's database handle.
* Call within Shavit_OnDatabaseLoaded. Safety is not guaranteed anywhere else!
*
* @return Database handle.
*/
native Database Shavit_GetDatabase(int& outdriver=0);
/**
* Starts the timer for a player.
* Will not teleport the player to anywhere, it's handled inside the mapzones plugin.
*
* @param client Client index.
* @param track Timer track.
* @param skipGroundCheck Whether to skip checking if the player is on the ground. This is used in shavit-zones for when teleporting/!restarting players to a floating zone...
* @noreturn
*/
native void Shavit_StartTimer(int client, int track, bool skipGroundCheck=false);
/**
* Restarts the timer for a player.
* Will work as if the player just used sm_r.
*
* @param client Client index.
* @param track Timer track.
* @param force True to force the player to restart. False to call into Shavit_OnRestartPre and Shavit_OnStopPre first.
* @return True on restart and False if a callback blocked the restart.
*/
native bool Shavit_RestartTimer(int client, int track, bool force=true);
/**
* Stops the timer for a player.
* Will not teleport the player to anywhere, it's handled inside the mapzones plugin.
*
* @param client Client index.
* @param bypass Bypass call to Shavit_OnStopPre?
* @return True if the operation went through.
*/
native bool Shavit_StopTimer(int client, bool bypass = true);
/**
* Changes a player's bhop style.
*
* @param client Client index.
* @param style Style.
* @param force Ignore style permissions. This being true will bypass the `inaccessible` style setting as well.
* @param manual Is it a manual style change? (Was it caused by user interaction?)
* @param noforward Bypasses the call to `Shavit_OnStyleChanged`.
* @return False if failed due to lack of access, true otherwise.
*/
native bool Shavit_ChangeClientStyle(int client, int style, bool force = false, bool manual = false, bool noforward = false);
/**
* Finishes the map for a player, with their current timer stats.
* Will not teleport the player to anywhere, it's handled inside the mapzones plugin.
*
* @param client Client index.
* @param track Timer track.
* @noreturn
*/
native void Shavit_FinishMap(int client, int track);
/**
* Retrieve a client's current time.
*
* @param client Client index.
* @return Current time.
*/
native float Shavit_GetClientTime(int client);
/**
* Retrieve the client's track. (Track_Main/Track_Bonus etc..)
*
* @param client Client index.
* @return Timer track.
*/
native int Shavit_GetClientTrack(int client);
/**
* Retrieve client jumps since timer start.
*
* @param client Client index.
* @return Current amount of jumps, 0 if timer is inactive.
*/
native int Shavit_GetClientJumps(int client);
/**
* Retrieve a client's bhopstyle
*
* @param client Client index.
* @return Style.
*/
native int Shavit_GetBhopStyle(int client);
/**
* Retrieve a client's timer status
*
* @param client Client index.
* @return See TimerStatus enum.
*/
native TimerStatus Shavit_GetTimerStatus(int client);
/**
* Retrieve the amount of strafes done since the timer started.
* Will return 0 if timer isn't running.
*
* @param client Client index.
* @return Amount of strafes since timer start.
*/
native int Shavit_GetStrafeCount(int client);
/**
* Retrieve the perfect jumps percentage for the player.
* Will return 100.0 if no jumps were measured.
*
* @param client Client index.
* @return Perfect jump percentage.
*/
native float Shavit_GetPerfectJumps(int client);
/**
* Retrieve strafe sync since timer start.
* Will return 0.0 if timer isn't running or -1.0 when not measured.
*
* @param client Client index.
* @return Amount of strafes since timer start.
*/
native float Shavit_GetSync(int client);
/**
* Pauses a player's timer.
*
* @param client Client index.
* @noreturn
*/
native void Shavit_PauseTimer(int client);
/**
* Resumes a player's timer.
*
* @param client Client index.
* @param teleport Should the player be teleported to their location prior to saving?
* @noreturn
*/
native void Shavit_ResumeTimer(int client, bool teleport = false);
/**
* Gets a players zone offset.
*
* @param client Client index.
* @param zonetype Zone type (Zone_Start or Zone_End).
* @return Zone offset fraction if any for the given zone type.
*/
native float Shavit_GetZoneOffset(int client, int zonetype);