· 6 years ago · Jan 13, 2020, 11:20 PM
1#include <amxmodx>
2#include <amxmisc>
3#include <cstrike>
4#include <engine>
5#include <fakemeta>
6#include <hamsandwich>
7#include <geoip>
8#include <sqlx>
9#include <speedrun>
10#include <tutor>
11
12new const PluginName [] = "Speedrun Mod [Timer & Stats]"
13new const PluginVersion [] = "1.3"
14new const PluginAuthor [] = "IceBeam / SQN, Nemek, Mistrick, R3X"
15
16new const PREFIX[] = "^4[SpeedRun]";
17
18#define FL_WATERJUMP (1<<11)
19#define FL_ONGROUND (1<<9)
20
21#define MAX_STRAFES 600
22
23enum _:Categories
24{
25 Cat_60fps,
26 Cat_100fps,
27 Cat_200fps,
28 Cat_250fps,
29 Cat_333fps,
30 Cat_500fps,
31 Cat_1000fps,
32 Cat_CS,
33 Cat_HCS,
34 Cat_2kRun,
35 Cat_3kRun,
36 Cat_4kRun,
37 Cat_5kRun,
38 Cat_Simulated1000fps,
39 Cat_Gravity,
40 Cat_Legit,
41 Cat_dj,
42 Cat_tj
43};
44
45new const szSounds[][] = {
46 "sound/kaniel/speedrun1.mp3",
47 "sound/kaniel/speedrun2.mp3",
48 "sound/kaniel/speedrun3.mp3",
49 "sound/kaniel/speedrun4.mp3",
50 "sound/kaniel/speedrun5.mp3"
51}
52new const szSoundss[][] = {
53"sound/kaniel/reklamaspeedrun.mp3",
54"sound/kaniel/reklamaspeedrun2.mp3",
55}
56new const DATABASE[] = "addons/amxmodx/data/speedrun_stats.db";
57
58new const g_szCategory[][] = { "60 FPS", "100 FPS", "200 FPS", "250 FPS", "333 FPS", "500 FPS", "1000 FPS", "Crazy Speed", "Hard Crazy Speed", "2KRun", "3KRun", "4KRun", "5KRun", "Cat_Simulated1000fps", "Low Gravity", "Legit (No AutoBH)", "Cat_Double Jump", "Cat_Triple Jump"};
59new Handle:g_hTuple, g_szQuery[512];
60new g_szMapName[32];
61new g_iMapIndex;
62new g_szMotd[1536];
63new g_iBestTime[33][Categories];
64new g_iBestTimeofMap[Categories];
65new g_iPlayerFinished;
66new g_iReturn;
67
68new m_iPlayerIndex[33];
69new m_iPlayerAuthorized[33];
70new m_iPlayerConnected[33];
71
72new Float:m_iStarted[33];
73new bool:m_iFinished[33];
74new m_iTimerStarted[33];
75new m_iJumpCount[33];
76new m_iStrafeCount[33];
77new m_CheckButton[33];
78
79new m_LastTime[33];
80new Float:m_LastInfo[33];
81
82new bool:g_bStrafingAw[33], bool:g_bStrafingSd[33], bool:g_bTurningLeft[33], bool:g_bTurningRight[33];
83new Float:g_fMaxSpeed[33], Float:g_fOldAngles[33], Float:g_fOldSpeed[33]
84new g_iGoodSync[33], g_iSyncFrames[33]
85new g_iStrafeFrames[33][MAX_STRAFES], g_iStrafeGoodSync[33][MAX_STRAFES];
86
87new FinishEntity = 0;
88new const EntityName[] = "sr_finish";
89new EntitySprite;
90new const EntitySprite2[] = "sprites/kaniel/logo_sr.spr";
91
92public plugin_init()
93{
94 register_plugin(PluginName, PluginVersion, PluginAuthor)
95
96 register_clcmd("setfinish", "Command_SetFinish", ADMIN_BAN);
97
98 register_think(EntityName, "CBasePlayer_Think");
99
100
101 register_clcmd("say /top15", "Command_Top15");
102 register_clcmd("say /top", "Command_Top15");
103
104 register_clcmd("say /update", "Command_Update")
105 register_clcmd("say /nick", "Command_Update")
106 register_clcmd("say /updatenickname", "Command_Update")
107
108 tutorInit();
109
110 RegisterHam(Ham_Spawn, "player", "CBasePlayer_Spawn");
111
112 register_forward(FM_PlayerPreThink, "CBasePlayer_PreThink");
113 register_forward(FM_PlayerPreThink, "CBasePlayer_StartTimer");
114 register_forward(FM_CmdStart, "CBasePlayer_JumpCount");
115
116 register_forward(FM_PlayerPostThink, "SRPlayer_Strafecount", 0);
117
118 g_iPlayerFinished = CreateMultiForward("SR_PlayerFinished", ET_IGNORE, FP_CELL, FP_CELL, FP_CELL);
119
120 SQL_Init();
121}
122
123public plugin_precache()
124{
125 precache_model(EntitySprite2);
126 EntitySprite = precache_model("sprites/kaniel/speedrun_logo_g.spr");
127
128 for(new i=0; i<sizeof(szSounds); i++)
129 precache_generic(szSounds[i]);
130 for(new i=0; i<sizeof(szSoundss); i++)
131 precache_generic(szSoundss[i]);
132 tutorPrecache()
133}
134public Command_SetFinish(id, level, cid)
135{
136 if(!cmd_access(id, level, cid, 1 ))
137 return PLUGIN_HANDLED;
138
139 if(!FinishEntity){
140 if(get_user_flags(id) & ADMIN_BAN)
141 client_print_color(id, print_team_default, "%s^1[ADMIN]^3 You can set the finish entity sprite using 'setfinish' command.", PREFIX);
142 }
143
144 new Float:fOrigin[3];
145 pev(id, pev_origin, fOrigin);
146
147 Create_Finish(fOrigin);
148 Save_FinishOrigin()
149
150 client_print_color(id, print_team_default, "%s^1[ADMIN]^3 Finish entity sprite set!", PREFIX);
151
152 return PLUGIN_HANDLED;
153}
154
155Save_FinishOrigin()
156{
157 if(is_valid_ent(FinishEntity))
158 {
159 new Float:fOrigin[3]; pev(FinishEntity, pev_origin, fOrigin);
160 new iOrigin[3]; FVecIVec(fOrigin, iOrigin);
161
162 formatex(g_szQuery, charsmax(g_szQuery), "UPDATE `maps` SET finishX = '%d', finishY = '%d', finishZ = '%d' WHERE mid=%d",
163 iOrigin[0], iOrigin[1], iOrigin[2], g_iMapIndex);
164
165 SQL_ThreadQuery(g_hTuple, "Query_IngnoredHandle", g_szQuery);
166 }
167}
168SQL_Init() {
169 SQL_SetAffinity("sqlite");
170 SQL_MakeDbTuple("localhost", "root", "", "DATABASE");
171
172 if(!file_exists(DATABASE))
173 {
174 new file = fopen(DATABASE, "w");
175 if(!file)
176 {
177 new szMsg[128]; formatex(szMsg, charsmax(szMsg), "%s file not found and cant be created.", DATABASE);
178 set_fail_state(szMsg);
179 }
180 fclose(file);
181 }
182
183 g_hTuple = SQL_MakeDbTuple("", "", "", DATABASE, 0);
184
185 formatex(g_szQuery, charsmax(g_szQuery),
186 "CREATE TABLE IF NOT EXISTS `runners`( \
187 id INTEGER PRIMARY KEY,\
188 steamid TEXT NOT NULL, \
189 nickname TEXT NOT NULL, \
190 ip TEXT NOT NULL, \
191 nationality TEXT NULL)");
192
193 SQL_ThreadQuery(g_hTuple, "Query_IngnoredHandle", g_szQuery);
194
195 formatex(g_szQuery, charsmax(g_szQuery),
196 "CREATE TABLE IF NOT EXISTS `maps`( \
197 mid INTEGER PRIMARY KEY,\
198 mapname TEXT NOT NULL UNIQUE, \
199 finishX INTEGER NOT NULL DEFAULT 0, \
200 finishY INTEGER NOT NULL DEFAULT 0, \
201 finishZ INTEGER NOT NULL DEFAULT 0)");
202
203 SQL_ThreadQuery(g_hTuple, "Query_IngnoredHandle", g_szQuery);
204
205 formatex(g_szQuery, charsmax(g_szQuery),
206 "CREATE TABLE IF NOT EXISTS `results`( \
207 id INTEGER NOT NULL, \
208 mid INTEGER NOT NULL, \
209 category INTEGER NOT NULL, \
210 besttime INTEGER NOT NULL, \
211 bestjumps INTEGER NOT NULL, \
212 beststrafes INTEGER NOT NULL, \
213 recorddate DATETIME NULL, \
214 FOREIGN KEY(id) REFERENCES `runners`(id) ON DELETE CASCADE, \
215 FOREIGN KEY(mid) REFERENCES `maps`(mid) ON DELETE CASCADE, \
216 PRIMARY KEY(id, mid, category))");
217
218 SQL_ThreadQuery(g_hTuple, "Query_IngnoredHandle", g_szQuery);
219
220 set_task(1.0, "DelayedLoadMapInfo");
221}
222public DelayedLoadMapInfo()
223{
224 get_mapname(g_szMapName, charsmax(g_szMapName));
225 formatex(g_szQuery, charsmax(g_szQuery), "SELECT mid, finishX, finishY, finishZ FROM `maps` WHERE mapname='%s'", g_szMapName);
226 SQL_ThreadQuery(g_hTuple, "Query_LoadMapHandle", g_szQuery);
227}
228public Query_LoadMapHandle(failstate, Handle:query, error[], errnum, data[], size)
229{
230 if(failstate != TQUERY_SUCCESS)
231 {
232 log_amx("SQL error[LoadMapHandle]: %s", error); return;
233 }
234
235 if(SQL_MoreResults(query))
236 {
237 g_iMapIndex = SQL_ReadResult(query, 0);
238
239 CreateFinishI(SQL_ReadResult(query, 1), SQL_ReadResult(query, 2), SQL_ReadResult(query, 3));
240 }
241 else
242 {
243 formatex(g_szQuery, charsmax(g_szQuery), "INSERT INTO `maps`(mapname) VALUES ('%s')", g_szMapName);
244 SQL_ThreadQuery(g_hTuple, "Query_IngnoredHandle", g_szQuery);
245
246 formatex(g_szQuery, charsmax(g_szQuery), "SELECT mid, finishX, finishY, finishZ FROM `maps` WHERE mapname='%s'", g_szMapName);
247 SQL_ThreadQuery(g_hTuple, "Query_LoadMapHandle", g_szQuery);
248 }
249
250 if(g_iMapIndex)
251 {
252 for(new i = 1; i <= 32; i++)
253 {
254 if(m_iPlayerConnected[i]) ClientAuthorization(i);
255 }
256 for(new i; i < Categories; i++)
257 {
258 ShowTop15(0, i);
259 }
260 }
261}
262public Query_IngnoredHandle(failstate, Handle:query, error[], errnum, data[], size)
263{
264 if(failstate != TQUERY_SUCCESS)
265 {
266 log_amx("SQL error[IngnoredHandle]: %s", error); return;
267 }
268}
269CreateFinishI(x, y, z)
270{
271 if(!x && !y && !z) return;
272
273 new Float:fOrigin[3];
274 fOrigin[0] = float(x);
275 fOrigin[1] = float(y);
276 fOrigin[2] = float(z);
277
278 Create_Finish(fOrigin);
279}
280// not the best shit...
281public Create_Finish(const Float:fOrigin[3]) {
282
283 if(pev_valid(FinishEntity))
284 {
285 remove_entity(FinishEntity);
286 }
287
288 FinishEntity = 0;
289
290 new ent = create_entity("info_target");
291 set_pev(ent, pev_classname, EntityName);
292
293 engfunc( EngFunc_SetModel, ent, EntitySprite2);
294
295 set_pev(ent, pev_origin, fOrigin);
296
297 dllfunc(DLLFunc_Spawn, ent);
298
299 entity_set_size(ent, Float:{-50.0, -50.0, -25.0}, Float:{50.0, 50.0, 25.0});
300
301 set_pev(ent, pev_solid, SOLID_TRIGGER);
302 set_pev(ent, pev_movetype, MOVETYPE_NONE);
303
304 set_pev( ent, pev_rendermode, kRenderTransAdd);
305 set_pev( ent, pev_renderamt, 220.0);
306
307 FinishEntity = ent;
308
309 set_pev(ent, pev_nextthink, get_gametime() + 3);
310
311}
312
313public client_connect(id)
314{
315 m_iPlayerAuthorized[id] = false;
316 m_iFinished[id] = false;
317 m_iTimerStarted[id] = false;
318 m_iPlayerIndex[id] = 0;
319 m_LastTime[id] = 0;
320 m_CheckButton[id] = 0;
321 m_iJumpCount[id] = 0;
322 m_iStrafeCount[id] = 0;
323}
324public client_putinserver(id)
325{
326 if(!is_user_bot(id) && !is_user_hltv(id))
327 {
328 m_iPlayerConnected[id] = true;
329 ClientAuthorization(id);
330 }
331}
332public CBasePlayer_JumpCount(id, uc_handle)
333{
334 static button,flags
335 button = get_uc(uc_handle,UC_Buttons)
336 flags = pev(id, pev_flags)
337
338 if(button & IN_JUMP) {
339 if(flags & FL_ONGROUND) {
340 m_iJumpCount[id]++
341 }
342 }
343}
344public CBasePlayer_Spawn(id)
345{
346 if(!is_user_alive(id)) return;
347
348 m_iTimerStarted[id] = false;
349 m_iFinished[id] = false;
350 m_iStarted[id] = -1.0;
351 m_iJumpCount[id] = 0;
352 m_iStrafeCount[id] = 0;
353 m_CheckButton[id] = 0;
354
355 hide_timer(id);
356}
357
358public SRPlayer_Strafecount(id)
359{
360 if(!is_user_alive(id)) return FMRES_IGNORED;
361
362 static bool:bOnGround; bOnGround = bool:(pev(id, pev_flags) & FL_ONGROUND);
363
364 static Float:fAngles[3]; pev(id, pev_angles, fAngles);
365
366 g_bTurningRight[id] = false;
367 g_bTurningLeft[id] = false;
368
369 if(fAngles[1] < g_fOldAngles[id])
370 {
371 g_bTurningRight[id] = true;
372 }
373 else if(fAngles[1] > g_fOldAngles[id])
374 {
375 g_bTurningLeft[id] = true;
376 }
377 g_fOldAngles[id] = fAngles[1];
378
379 if(bOnGround) return FMRES_IGNORED;
380
381 static iButtons; iButtons = pev(id, pev_button);
382 static Float:fVelocity[3]; pev(id, pev_velocity, fVelocity);
383 static Float:fSpeed; fSpeed = floatsqroot(fVelocity[0] * fVelocity[0] + fVelocity[1] * fVelocity[1]);
384
385 if(g_bTurningLeft[id] || g_bTurningRight[id])
386 {
387 if(!g_bStrafingAw[id] && ((iButtons & IN_FORWARD)
388 || (iButtons & IN_MOVELEFT)) && !(iButtons & IN_MOVERIGHT) && !(iButtons & IN_BACK))
389 {
390 g_bStrafingAw[id] = true;
391 g_bStrafingSd[id] = false;
392
393 m_iStrafeCount[id]++;
394 }
395 else if(!g_bStrafingSd[id] && ((iButtons & IN_BACK)
396 || (iButtons & IN_MOVERIGHT)) && !(iButtons & IN_MOVELEFT) && !(iButtons & IN_FORWARD))
397 {
398 g_bStrafingAw[id] = false;
399 g_bStrafingSd[id] = true;
400
401 m_iStrafeCount[id]++;
402 }
403 }
404
405 if(g_fMaxSpeed[id] < fSpeed)
406 {
407 g_fMaxSpeed[id] = fSpeed;
408 }
409
410 if(g_fOldSpeed[id] < fSpeed)
411 {
412 g_iGoodSync[id]++;
413
414 if(m_iStrafeCount[id] && m_iStrafeCount[id] <= MAX_STRAFES)
415 {
416 g_iStrafeGoodSync[id][m_iStrafeCount[id] - 1]++;
417 }
418 }
419
420 g_iSyncFrames[id]++;
421
422 if(m_iStrafeCount[id] && m_iStrafeCount[id] <= MAX_STRAFES)
423 {
424 g_iStrafeFrames[id][m_iStrafeCount[id] - 1]++;
425 }
426
427 g_fOldSpeed[id] = fSpeed;
428
429 return FMRES_IGNORED;
430}
431public CBasePlayer_PreThink(id)
432{
433 if(!is_user_alive(id) || m_iStarted[id] <= 0.0)
434 return FMRES_IGNORED;
435
436 static Float:fNow;
437
438 if(!m_iFinished[id])
439 {
440 fNow = get_gametime();
441
442 if((fNow-m_LastInfo[id]) <= 0.5) return FMRES_IGNORED;
443
444 display_time(id, get_running_time(id));
445 }
446 return FMRES_IGNORED;
447}
448public CBasePlayer_StartTimer(id)
449{
450 if (entity_get_int(id, EV_INT_button) & 2) {
451 new flags = entity_get_int(id, EV_INT_flags)
452
453 if (flags & FL_WATERJUMP)
454 return PLUGIN_CONTINUE
455 if (entity_get_int(id, EV_INT_waterlevel) >= 2)
456 return PLUGIN_CONTINUE
457 if (!(flags & FL_ONGROUND))
458 return PLUGIN_CONTINUE
459
460 if(m_CheckButton[id] == 0 && !m_iTimerStarted[id])
461 {
462 PlayerStarted(id);
463 m_CheckButton[id] = 1;
464 }
465 }
466 new button = get_user_button(id)
467 if (button & IN_DUCK)
468 {
469 if(m_CheckButton[id] == 0 && !m_iTimerStarted[id])
470 {
471 PlayerStarted(id);
472 m_CheckButton[id] = 1;
473 }
474 }
475 return PLUGIN_CONTINUE
476}
477ClientAuthorization(id)
478{
479 if(!g_iMapIndex) return;
480
481 new szAuth[32]; get_user_authid(id, szAuth, charsmax(szAuth));
482
483 new data[1]; data[0] = id;
484 formatex(g_szQuery, charsmax(g_szQuery), "SELECT id, ip, nationality FROM `runners` WHERE steamid='%s'", szAuth);
485 SQL_ThreadQuery(g_hTuple, "Query_LoadRunnerInfoHandler", g_szQuery, data, sizeof(data));
486}
487public Query_LoadRunnerInfoHandler(failstate, Handle:query, error[], errnum, data[], size)
488{
489 if(failstate != TQUERY_SUCCESS)
490 {
491 log_amx("SQL error[LoadRunnerInfo]: %s",error); return;
492 }
493
494 new id = data[0];
495 if(!is_user_connected(id)) return;
496
497 new szCode[5];
498
499 if(SQL_MoreResults(query))
500 {
501 client_authorized_db(id, SQL_ReadResult(query, 0));
502
503 SQL_ReadResult(query, 2, szCode, 1);
504
505 if(szCode[0] == 0)
506 {
507 new szIP[32]; get_user_ip(id, szIP, charsmax(szIP), 1);
508
509 get_nationality(id, szIP, szCode);
510 formatex(g_szQuery, charsmax(g_szQuery), "UPDATE `runners` SET nationality='%s' WHERE id=%d", szCode, m_iPlayerIndex[id]);
511 SQL_ThreadQuery(g_hTuple, "Query_IngnoredHandle", g_szQuery);
512 }
513 }
514 else
515 {
516 new szAuth[32]; get_user_authid(id, szAuth, charsmax(szAuth));
517 new szIP[32]; get_user_ip(id, szIP, charsmax(szIP), 1);
518 new szName[64]; get_user_name(id, szName, charsmax(szName));
519 SQL_PrepareString(szName, szName, 63);
520
521 get_nationality(id, szIP, szCode);
522
523 formatex(g_szQuery, charsmax(g_szQuery), "INSERT INTO `runners` (steamid, nickname, ip, nationality) VALUES ('%s', '%s', '%s', '%s')", szAuth, szName, szIP, szCode);
524 SQL_ThreadQuery(g_hTuple, "Query_InsertRunnerHandle", g_szQuery, data, size);
525 }
526}
527public Query_InsertRunnerHandle(failstate, Handle:query, error[], errnum, data[], size)
528{
529 if(failstate != TQUERY_SUCCESS)
530 {
531 log_amx("SQL error[InsertRunner]: %s",error); return;
532 }
533
534 new id = data[0];
535 if(!is_user_connected(id)) return;
536
537 client_authorized_db(id , SQL_GetInsertId(query));
538}
539client_authorized_db(id, pid)
540{
541 m_iPlayerIndex[id] = pid;
542 m_iPlayerAuthorized[id] = true;
543
544 arrayset(g_iBestTime[id], 0, sizeof(g_iBestTime[]));
545
546 LoadRunnerData(id);
547}
548LoadRunnerData(id)
549{
550 if(!m_iPlayerAuthorized[id]) return;
551
552 new data[1]; data[0] = id;
553
554 formatex(g_szQuery, charsmax(g_szQuery), "SELECT * FROM `results` WHERE id=%d AND mid=%d", m_iPlayerIndex[id], g_iMapIndex);
555 SQL_ThreadQuery(g_hTuple, "Query_LoadDataHandle", g_szQuery, data, sizeof(data));
556}
557public Query_LoadDataHandle(failstate, Handle:query, error[], errnum, data[], size)
558{
559 if(failstate != TQUERY_SUCCESS)
560 {
561 log_amx("SQL Insert error: %s",error); return;
562 }
563
564 new id = data[0];
565 if(!is_user_connected(id)) return;
566
567 while(SQL_MoreResults(query))
568 {
569 new category = SQL_ReadResult(query, 2);
570 g_iBestTime[id][category] = SQL_ReadResult(query, 3);
571
572 SQL_NextRow(query);
573 }
574}
575
576public client_disconnected(id)
577{
578 m_iPlayerAuthorized[id] = false;
579 m_iPlayerConnected[id] = false;
580}
581
582
583public Command_Top15(id)
584{
585 if(is_flooding(id)) return PLUGIN_HANDLED;
586
587 ShowTop15(id, get_user_category(id));
588
589 return PLUGIN_CONTINUE;
590}
591
592public Command_Update(id)
593{
594 if(!m_iPlayerAuthorized[id] || is_flooding(id)) return PLUGIN_HANDLED;
595
596 new szName[32]; get_user_name(id, szName, charsmax(szName)); SQL_PrepareString(szName, szName, charsmax(szName));
597 formatex(g_szQuery, charsmax(g_szQuery), "UPDATE `runners` SET nickname = '%s' WHERE id=%d", szName, m_iPlayerIndex[id]);
598
599 client_print_color(id, print_team_default, "^4Nickname changed!");
600
601 SQL_ThreadQuery(g_hTuple, "Query_IngnoredHandle", g_szQuery);
602
603 return PLUGIN_CONTINUE;
604}
605
606PlayerStarted(id)
607{
608 m_iStarted[id] = get_gametime();
609 m_iTimerStarted[id] = 1;
610 m_iJumpCount[id] = 1;
611 m_iStrafeCount[id] = 1;
612 return 0;
613}
614PlayerFinished(id)
615{
616 m_iFinished[id] = true;
617
618 new record = false;
619 new iTime = get_running_time(id);
620 new iJumps = m_iJumpCount[id];
621 new iStrafes = m_iStrafeCount[id];
622 new szName[32]; get_user_name(id, szName, charsmax(szName));
623 new category = get_user_category(id);
624 new szTime[32]; get_formated_time(iTime, szTime, charsmax(szTime));
625 new szBestTime[32]; get_formated_time(iTime - g_iBestTimeofMap[category], szBestTime, charsmax(szBestTime));
626
627
628 if(g_iBestTimeofMap[category] != 0 && g_iBestTimeofMap[category]<iTime)
629 {
630 client_print_color(0, print_team_red, "%s ^3%s^4 finished ^3%s ^4@ ^3| ^4Time: ^3[%s]^4 To The Record: ^3+%s^4 @ ^1Jumps: ^3%d^1 | Strafes: ^3%i", PREFIX, szName, g_szCategory[category], szTime, szBestTime, m_iJumpCount[id], m_iStrafeCount[id]);
631 tutorMake(id, TUTOR_YELLOW, 5.0, "[SpeedRun] To The Record!!! Time: [+%s]", szBestTime);
632 }
633
634 if(g_iBestTimeofMap[category] == 0 || g_iBestTimeofMap[category] > iTime)
635 {
636 g_iBestTimeofMap[category] = iTime;
637
638 new szName[32]; get_user_name(id, szName, charsmax(szName))
639 get_formated_time(iTime, szTime, charsmax(szTime));
640
641 client_print_color(0, print_team_red, "^3NEW RECORD on ^4%s ^3- ^4%s ^3!!!", szName, g_szCategory[category]);
642 client_print_color(0, print_team_red, "^3NEW RECORD on ^4%s ^3- ^4%s ^3!!!", szName, g_szCategory[category]);
643 client_print_color(0, print_team_red, "%s ^3%s^4 broke the map record on ^3- ^4%s ^3!!! ^4@ ^3Time: [%s] ^4@ ^1Jumps: ^3%d^1 | Strafes: ^3%i^1", PREFIX,szName, g_szCategory[category], szTime, m_iJumpCount[id], m_iStrafeCount[id]);
644 tutorMake(id,TUTOR_RED,5.0,"[SpeedRun] NEW RECORD on!!! Time: [%s]", szTime);
645 SaveRunnerData(id, category, iTime, iJumps, iStrafes);
646 record = true;
647
648 client_cmd(0, "mp3 play %s", szSounds[random(sizeof(szSounds))]);
649 new Float:vOrigin[3]
650 pev(id, pev_origin, vOrigin)
651
652 //sprite_play_animation(vOrigin, 30.0)
653 sprites_play_animation2(id);
654 screen_player_effects(id);
655 }
656
657 ExecuteForward(g_iPlayerFinished, g_iReturn, id, iTime, record);
658
659 hide_timer(id);
660}
661
662public SaveRunnerData(id, category, iTime, iJumps, iStrafes)
663{
664 if(!m_iPlayerAuthorized[id]) return;
665
666 new iJumps = m_iJumpCount[id];
667 new iStrafes = m_iStrafeCount[id];
668 new szRecordTime[32]; get_time("%Y-%m-%d %H:%M:%S", szRecordTime, charsmax(szRecordTime));
669
670 formatex(g_szQuery, charsmax(g_szQuery), "INSERT OR IGNORE INTO `results` VALUES (%d, %d, %d, %d, %d, %d, '%s'); \
671 UPDATE `results` SET besttime=%d, bestjumps=%d, beststrafes=%d, recorddate='%s' WHERE id=%d AND mid=%d AND category=%d",
672 m_iPlayerIndex[id], g_iMapIndex, category, iTime, iJumps, iStrafes, szRecordTime,
673 iTime, iJumps, iStrafes, szRecordTime, m_iPlayerIndex[id], g_iMapIndex, category);
674
675 SQL_ThreadQuery(g_hTuple, "Query_IngnoredHandle", g_szQuery);
676}
677
678ShowTop15(id, category)
679{
680 formatex(g_szQuery, charsmax(g_szQuery), "SELECT nickname, besttime, bestjumps, beststrafes, recorddate FROM `results` JOIN `runners` ON `runners`.id=`results`.id WHERE mid=%d AND category=%d AND besttime ORDER BY besttime ASC LIMIT 100", g_iMapIndex, category);
681
682
683 new data[2]
684 data[0] = id;
685 data[1] = category;
686 SQL_ThreadQuery(g_hTuple, "Query_LoadTop15Handle", g_szQuery, data, sizeof(data));
687}
688public Query_LoadTop15Handle(failstate, Handle:query, error[], errnum, data[], size)
689{
690 if(failstate != TQUERY_SUCCESS)
691 {
692 log_amx("SQL error[LoadTop15]: %s",error); return;
693 }
694
695 new id = data[0];
696 if(!is_user_connected(id) && id != 0) return;
697
698 new category = data[1];
699
700 new iLen = 0, iMax = charsmax(g_szMotd);
701 iLen = formatex(g_szMotd[iLen], iMax-iLen, "<meta charset=utf-8>");
702 iLen += formatex(g_szMotd[iLen], iMax-iLen, "<style>{font:normal 10px} table, th, td{border: 1px solid black;border-collapse:remain;text-align:center;}");
703 iLen += formatex(g_szMotd[iLen], iMax-iLen, "</style><html><table width=100%%><thead><tr><th width=5%%>%s</th> <th width=10%%>%s</th> <th width=10%%>%s</th> <th width=10%%>%s</th> <th width=10%%>%s</th> <th width=10%%>%s <th width=10%%>%s</th>", "#", "Nick", "Time", "Jumps", "Strafes", "Category", "Data")
704
705 new i = 1;
706 new recorddate;
707 new iTime, szName[32], szTime[32], iJumps, iStrafes;
708 while(SQL_MoreResults(query))
709 {
710 SQL_ReadResult(query, 0, szName, charsmax(szName));
711 iTime = SQL_ReadResult(query, 1);
712 iJumps = SQL_ReadResult(query, 2);
713 iStrafes = SQL_ReadResult(query, 3);
714 recorddate = SQL_ReadResult(query, 4);
715 get_formated_time(iTime, szTime, 31);
716
717 iLen += formatex(g_szMotd[iLen], iMax-iLen, "<tr><td>%d</td><td>%s</td>", i, szName);
718 if(i == 1)
719 {
720 g_iBestTimeofMap[category] = iTime;
721 iLen += formatex(g_szMotd[iLen], iMax-iLen, "<td>%s</td><td>%d</td><td>%d</td><td>%s</td><td>%s</td>", szTime, iJumps, iStrafes, g_szCategory[category], recorddate);
722 if(id == 0) return;
723 }
724 else
725 {
726 iLen += formatex(g_szMotd[iLen], iMax-iLen, "<td>%s</td><td>%d</td><td>%d</td><td>%i</td>", szTime, iJumps, iStrafes, recorddate);
727 get_formated_time(iTime-g_iBestTimeofMap[category], szTime, 31);
728 iLen += formatex(g_szMotd[iLen], iMax-iLen, "<td>%s</td><td>%d</td><td>%d</td><td>%i</td>", szTime, iJumps, iStrafes, recorddate);
729 }
730
731 i++;
732 SQL_NextRow(query);
733 }
734 iLen += formatex(g_szMotd[iLen], iMax-iLen, "");
735 show_motd(id, g_szMotd, "SpeedRun top15");
736}
737
738/*
739sprite_play_animation(const Float:vOrigin[3], Float:Add)
740{
741 engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, vOrigin, 0)
742 write_byte(TE_SPRITE)
743 engfunc(EngFunc_WriteCoord, vOrigin[0])
744 engfunc(EngFunc_WriteCoord, vOrigin[1])
745 engfunc(EngFunc_WriteCoord, vOrigin[2] + Add)
746 write_short(EntitySprite)
747 write_byte(25)
748 write_byte(250)
749 message_end()
750}
751*/
752sprites_play_animation2(id) {
753 new Float:vOrigin[3]
754
755 set_pev(id, pev_iuser2, 0)
756 pev(id, pev_origin, vOrigin)
757
758 message_begin (MSG_BROADCAST,SVC_TEMPENTITY)
759 write_byte( TE_SPRITETRAIL )
760 write_coord( floatround(vOrigin[ 0 ]) )
761 write_coord( floatround(vOrigin[ 1 ]) )
762 write_coord( floatround(vOrigin[ 2 ]) )
763 write_coord( floatround(vOrigin[ 0 ]) )
764 write_coord( floatround(vOrigin[ 1 ]) )
765 write_coord( floatround(vOrigin[ 2 ]) +20)
766 write_short(EntitySprite)
767 write_byte(20)
768 write_byte(random_num(2,3))
769 write_byte(2)
770 write_byte(random_num(25,30))
771 write_byte(15)
772 message_end()
773}
774screen_player_effects(id)
775{
776 message_begin(MSG_ONE_UNRELIABLE, get_user_msgid("ScreenFade"), _, id);
777 write_short((1<<12) * 1)
778 write_short(1<<12)
779 write_short(0)
780 write_byte(random(255))
781 write_byte(random(255))
782 write_byte(random(255))
783 write_byte(155)
784 message_end()
785
786 message_begin(MSG_ONE,get_user_msgid("ScreenShake"),{0,0,0},id);
787 write_short(7<<14);
788 write_short(1<<13);
789 write_short(1<<14);
790 message_end();
791}
792
793// [BOX SYSTEM]
794public box_start_touch(box, id, const szClass[])
795{
796 if(!is_user_alive(id))
797 return PLUGIN_CONTINUE;
798 if(equal(szClass, "box"))
799 {
800
801 }
802 if(equal(szClass, "finish") && !m_iFinished[id])
803 {
804 PlayerFinished(id);
805 }
806 return PLUGIN_CONTINUE;
807}
808public box_stop_touch(box, id, const szClass[]) {
809 if(!is_user_alive(id))
810 return PLUGIN_CONTINUE;
811
812 if(m_iPlayerAuthorized[id] && !m_iTimerStarted[id])
813 {
814 PlayerStarted(id);
815 }
816 return PLUGIN_CONTINUE;
817}
818
819display_time(id, iTime)
820{
821 show_status(id, "TIME: [%d:%02d,%03ds] | Jump: [%d] | Strafe: [%d]", iTime / 60000, (iTime / 1000) % 60, iTime % 1000, m_iJumpCount[id], m_iStrafeCount[id]);
822 tutorMake(id,TUTOR_GREEN,5.00, "Jump [%d] | Strafe [%d]", m_iJumpCount[id], m_iStrafeCount[id]);
823}
824hide_timer(id)
825{
826 show_status(id, "");
827}
828get_running_time(id)
829{
830 return floatround((get_gametime() - m_iStarted[id]) * 1000, floatround_ceil);
831}
832get_formated_time(iTime, szTime[], size)
833{
834 formatex(szTime, size, "%d:%02d.%03ds", iTime / 60000, (iTime / 1000) % 60, iTime % 1000);
835}
836show_status(id, const szMsg[], any:...)
837{
838 static szStatus[128]; vformat(szStatus, charsmax(szStatus), szMsg, 3);
839 static StatusText; if(!StatusText) StatusText = get_user_msgid("StatusText");
840
841 message_begin(MSG_ONE_UNRELIABLE, StatusText, _, id);
842 write_byte(0);
843 write_string(szStatus);
844 message_end();
845}
846get_nationality(id, const szIP[], szCode[5])
847{
848 new szTemp[3];
849 if(geoip_code2_ex(szIP, szTemp))
850 {
851 copy(szCode, 4, szTemp);
852 }
853 else
854 {
855 get_user_info(id, "lang", szCode, 2);
856 SQL_PrepareString(szCode, szCode, 4);
857 }
858}
859bool:is_flooding(id)
860{
861 static Float:fAntiFlood[33];
862 new bool:fl = false;
863 new Float:fNow = get_gametime();
864
865 if((fNow-fAntiFlood[id]) < 1.0) fl = true;
866
867 fAntiFlood[id] = fNow;
868 return fl;
869}
870stock SQL_PrepareString(const szQuery[], szOutPut[], size)
871{
872 copy(szOutPut, size, szQuery);
873 replace_all(szOutPut, size, "'", "\'");
874 replace_all(szOutPut,size, "`", "\`");
875 replace_all(szOutPut,size, "\\", "\\\\");
876}
877/* AMXX-Studio Notes - DO NOT MODIFY BELOW HERE
878*{\\ rtf1\\ ansi\\ deff0{\\ fonttbl{\\ f0\\ fnil Tahoma;}}\n\\ viewkind4\\ uc1\\ pard\\ lang1045\\ f0\\ fs16 \n\\ par }
879*/