· 6 years ago · Oct 30, 2019, 10:20 PM
1
2#include <sourcemod>
3#include <cstrike>
4#include <sdktools>
5#include <sdkhooks>
6#include <h2k_rangi>
7
8#pragma semicolon 1
9#pragma newdecls required
10
11/*
12
13Globalne...
14
15*/
16
17#define LoopClients(%1) for(int %1 = 1; %1 <= MaxClients; %1++)\
18if(IsClientInGame(%1))
19
20#define LoopRanks(%1) for(int %1 = 1; %1 < sizeof g_iRanks; %1++)
21
22#define PREFIX_NORMAL " \x02[RANK]"
23#define PREFIX_ERROR " \x02[\x04#\x02RANK]"
24
25#define PINS_COUNT 200
26
27//Zmienne Meshara, prawie
28static const char g_sMySQLCreate[] = "CREATE TABLE IF NOT EXISTS `h2k_ranks` (`steamid` VARCHAR(64) NOT NULL, `name` VARCHAR(128) NOT NULL, `points` INT NOT NULL, `rank` INT NOT NULL, `coin` INT, `rank_name` VARCHAR(64) NOT NULL, UNIQUE KEY `steamid` (`steamid`)) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci";
29static const char g_sMySQLLoad[] = "SELECT points, rank, coin FROM h2k_ranks WHERE steamid = '%s'";
30static const char g_sMySQLInsert[] = "INSERT INTO `h2k_ranks` (steamid, name, points, rank, coin, rank_name) VALUES ('%s', '%s', %i, %i, %i, '%s')";
31static const char g_sMySQLSave[] = "UPDATE `h2k_ranks` SET `name`='%s', `points`=%i, `rank`=%i, `coin`=%i, `rank_name`='%s' WHERE steamid = '%s'";
32
33Database db;
34KeyValues g_hRanks;
35
36char sPath [PLATFORM_MAX_PATH];
37
38int g_iRank [MAXPLAYERS+1];
39int g_iPoints [MAXPLAYERS+1];
40int g_iCoin [MAXPLAYERS+1];
41
42int g_iWingmanRanks;
43
44int g_iRanks[] =
45{
46 1150,
47 1250,
48 1350,
49 1450,
50 1550,
51 1650,
52 1700,
53 1850,
54 1900,
55 2050,
56 2300,
57 2500,
58 2700,
59 3000,
60 3500,
61 3750,
62 4000,
63 4500,
64 8000
65};
66
67char g_sRanksNames[][128] =
68{
69 "Unranked",
70 "Silver 1",
71 "Silver 2",
72 "Silver 3",
73 "Silver 4",
74 "Silver Elite",
75 "Silver Elite Master",
76 "Gold Nova 1",
77 "Gold Nova 2",
78 "Gold Nova 3",
79 "Gold Nova Master",
80 "Master Guardian 1",
81 "Master Guardian 2",
82 "Master Guardian Elite",
83 "Distinguished Master Guardian",
84 "Legendary Eagle",
85 "Legendary Eagle Master",
86 "Supreme Master First Class",
87 "The Global Elite"
88};
89
90char g_sCoinsNames[PINS_COUNT + 1][300] =
91 {
92
93 "Brak odznaki",
94 "5 Year Service Coin",
95
96 /*** Major ***/
97 "DH.SS 2013 Champ",
98 "DH.SS 2013 Finalist",
99 "DH.SS 2013 Semif.",
100 "DH.SS 2013 Quarter.",
101 "EMS.O.K 2014 Champ",
102 "EMS.O.K 2014 Finalist",
103 "EMS.O.K 2014 Semif.",
104 "EMS.O.K 2014 Quarter.",
105 "ESL.O.C 2014 Champ",
106 "ESL.O.C 2014 Finalist",
107 "ESL.O.C 2014 Semif.",
108 "ESL.O.C 2014 Quarter.",
109 "ESL.O.C 2014 PEC Bronze",
110 "ESL.O.C 2014 PEC Silver",
111 "ESL.O.C 2014 PEC Gold",
112 "DH.W 2014 Champ",
113 "DH.W 2014 Finalist",
114 "DH.W 2014 Semif.",
115 "DH.W 2014 Quarter.",
116 "DH.W 2014 PEC Bronze",
117 "DH.W 2014 PEC Silver",
118 "DH.W 2014 PEC Gold",
119 "ESL.O.K 2015 Champ",
120 "ESL.O.K 2015 Finalist",
121 "ESL.O.K 2015 Semif.",
122 "ESL.O.K 2015 Quarter.",
123 "ESL.O.K 2015 PEC Bronze",
124 "ESL.O.K 2015 PEC Silver",
125 "ESL.O.K 2015 PEC Gold",
126 "ESL.O.C 2015 Champ",
127 "ESL.O.C 2015 Finalist",
128 "ESL.O.C 2015 Semif.",
129 "ESL.O.C 2015 Quarter.",
130 "ESL.O.C 2015 PEC Bronze",
131 "ESL.O.C 2015 PEC Silver",
132 "ESL.O.C 2015 PEC Gold",
133 "DH.C-N 2015 PEC Bronze",
134 "DH.C-N 2015 PEC Silver",
135 "DH.C-N 2015 PEC Gold",
136 "DH.C-N 2015 FT Bronze",
137 "DH.C-N 2015 FT Silver",
138 "DH.C-N 2015 FT Gold",
139 "DH.C-N 2015 Champ",
140 "DH.C-N 2015 Finalist",
141 "DH.C-N 2015 Semif.",
142 "DH.C-N 2015 Quarter.",
143 "MLG.C 2016 PEC Bronze",
144 "MLG.C 2016 PEC Silver",
145 "MLG.C 2016 PEC Gold",
146 "MLG.C 2016 FT Bronze",
147 "MLG.C 2016 FT Silver",
148 "MLG.C 2016 FT Gold",
149 "MLG.C 2016 Champ",
150 "MLG.C 2016 Finalist",
151 "MLG.C 2016 Semif.",
152 "MLG.C 2016 Quarter.",
153 "ESL.O.C 2016 Champ",
154 "ESL.O.C 2016 Finalist",
155 "ESL.O.C 2016 Semif.",
156 "ESL.O.C 2016 Quarter.",
157 "ESL.O.C 2016 PEC Bronze",
158 "ESL.O.C 2016 PEC Silver",
159 "ESL.O.C 2016 PEC Gold",
160 "ESL.O.C 2016 FT Bronze",
161 "ESL.O.C 2016 FT Silver",
162 "ESL.O.C 2016 FT Gold",
163 "E.Atlanta 2017 Champ",
164 "E.Atlanta 2017 Finalist",
165 "E.Atlanta 2017 Semif.",
166 "E.Atlanta 2017 Quarter.",
167 "E.Atlanta 2017 PEC Bronze",
168 "E.Atlanta 2017 PEC Silver",
169 "E.Atlanta 2017 PEC Gold",
170 "PGL.K 2017 Champ",
171 "PGL.K 2017 Finalist",
172 "PGL.K 2017 Semif.",
173 "PGL.K 2017 Quarter.",
174 "PGL.K 2017 PEC Bronze",
175 "PGL.K 2017 PEC Silver",
176 "PGL.K 2017 PEC Gold",
177 "E.Boston 2018 Champ",
178 "E.Boston 2018 Finalist",
179 "E.Boston 2018 Semif.",
180 "E.Boston 2018 Quarter.",
181 "E.Boston 2018 PEC Bronze",
182 "E.Boston 2018 PEC Silver",
183 "E.Boston 2018 PEC Gold",
184
185 /*** Operation ***/
186 "Payback Chall.",
187 "Payback Silver",
188 "Payback Gold",
189 "Bravo Chall.",
190 "Bravo Silver",
191 "Bravo Gold",
192 "Pheonix Chall.",
193 "Pheonix Silver",
194 "Pheonix Gold",
195 "Breakout Chall.",
196 "Breakout Silver",
197 "Breakout Gold",
198 "Vanguard Chall.",
199 "Vanguard Silver",
200 "Vanguard Gold",
201 "Bloodh. Chall.",
202 "Bloodh. Silver",
203 "Bloodh. Gold",
204 "Wildfire Chall.",
205 "Wildfire Silver",
206 "Wildfire Gold",
207 "Hydra Chall.",
208 "Hydra Silver",
209 "Hydra Gold",
210 "Hydra Diamond",
211
212 /*** Collectible Pin ***/
213 "C-Pin.O Dust II",
214 "C-Pin.O Guar. Elite",
215 "C-Pin.O Mirage",
216 "C-Pin.O Inferno",
217 "C-Pin.O Italy",
218 "C-Pin.O Victory",
219 "C-Pin.O Militia",
220 "C-Pin.O Nuke",
221 "C-Pin.O Train",
222 "C-Pin.O Guar.",
223 "C-Pin.O Tactics",
224 "C-Pin.O Guar. 2",
225 "C-Pin.O Bravo",
226 "C-Pin.O Baggage",
227 "C-Pin.O Phoenix",
228 "C-Pin.O Office",
229 "C-Pin.O Cobblestone",
230 "C-Pin.O Overpass",
231 "C-Pin.O Bloodh.",
232 "C-Pin.O Cache",
233 "C-Pin.O Valeria Phoenix",
234 "C-Pin.O Chrome",
235 "C-Pin.O Guar. 3",
236 "C-Pin.O Canals",
237 "C-Pin.O Welcome to the Clutch",
238 "C-Pin.O Death Sentence",
239 "C-Pin.O Inferno 2",
240 "C-Pin.O Wildfire",
241 "C-Pin.O Easy Peasy",
242 "C-Pin.O Aces High",
243 "C-Pin.O Hydra",
244 "C-Pin.O Howl",
245 "C-Pin.O Brigadier General",
246 "C-Pin Dust II",
247 "C-Pin Guar. Elite",
248 "C-Pin Mirage",
249 "C-Pin Inferno",
250 "C-Pin Italy",
251 "C-Pin Victory",
252 "C-Pin Militia",
253 "C-Pin Nuke",
254 "C-Pin Train",
255 "C-Pin Guar.",
256 "C-Pin Tactics",
257 "C-Pin Guar. 2",
258 "C-Pin Bravo",
259 "C-Pin Baggage",
260 "C-Pin Pheonix",
261 "C-Pin Office",
262 "C-Pin Cobblestone",
263 "C-Pin Overpass",
264 "C-Pin Bloodh.",
265 "C-Pin Cache",
266 "C-Pin Valeria Phoenix",
267 "C-Pin Chrome",
268 "C-Pin Guar. 3",
269 "C-Pin Canals",
270 "C-Pin Welcome to the Clutch",
271 "C-Pin Death Sentence",
272 "C-Pin Inferno 2",
273 "C-Pin Wildfire",
274 "C-Pin Easy Peasy",
275 "C-Pin Aces High",
276 "C-Pin Hydra",
277 "C-Pin Howl",
278 "C-Pin Brigadier General",
279
280
281 /*** Community ***/
282 "CCoin 2015 - 1",
283 "CCoin 2015 - 2",
284 "CCoin 2016 - 1",
285 "CCoin 2016 - 2",
286 "CCoin 2016 - 3",
287 "CCoin 2016 - 4",
288 "CCoin 2016 - 5",
289 "CCoin 2016 - 6",
290 "CCoin 2017 - 1",
291 "CCoin 2017 - 2",
292 "CCoin 2017 - 3",
293 "CCoin 2017 - 4",
294 "CCoin 2017 - 5",
295 "CCoin 2017 - 6",
296 "CCoin 2017 - 7",
297 "CCoin 2018 - 1",
298 "CCoin 2018 - 2",
299 "CCoin 2018 - 3",
300 "CCoin 2018 - 4",
301 "CCoin 2018 - 5",
302 "CCoin 2018 - 6"
303};
304
305int g_iCoins[PINS_COUNT + 1] =
306{
307 0,
308 874,
309
310 /*** Major ***/
311 875,
312 876,
313 877,
314 878,
315 879,
316 880,
317 881,
318 882,
319 883,
320 884,
321 885,
322 886,
323 887,
324 888,
325 889,
326 890,
327 891,
328 892,
329 893,
330 894,
331 895,
332 896,
333 897,
334 898,
335 899,
336 900,
337 901,
338 902,
339 903,
340 904,
341 905,
342 906,
343 907,
344 908,
345 909,
346 910,
347 911,
348 912,
349 913,
350 914,
351 915,
352 916,
353 917,
354 918,
355 919,
356 920,
357 921,
358 922,
359 923,
360 924,
361 925,
362 926,
363 927,
364 928,
365 929,
366 930,
367 931,
368 932,
369 933,
370 934,
371 935,
372 936,
373 937,
374 938,
375 939,
376 940,
377 941,
378 942,
379 943,
380 944,
381 945,
382 946,
383 947,
384 948,
385 949,
386 950,
387 951,
388 952,
389 953,
390 954,
391 955,
392 956,
393 957,
394 958,
395 959,
396 960,
397 961,
398
399
400 /*** Operation ***/
401 1001,
402 1002,
403 1003,
404 1013,
405 1014,
406 1015,
407 1024,
408 1025,
409 1026,
410 1028,
411 1029,
412 1030,
413 1316,
414 1317,
415 1318,
416 1327,
417 1328,
418 1329,
419 1336,
420 1337,
421 1338,
422 4353,
423 4534,
424 4535,
425 4536,
426
427
428 /*** Collectible ***/
429 6001,
430 6002,
431 6003,
432 6004,
433 6005,
434 6006,
435 6007,
436 6008,
437 6009,
438 6010,
439 6011,
440 6012,
441 6013,
442 6014,
443 6015,
444 6016,
445 6017,
446 6018,
447 6019,
448 6020,
449 6021,
450 6022,
451 6023,
452 6024,
453 6025,
454 6026,
455 6027,
456 6028,
457 6029,
458 6030,
459 6031,
460 6032,
461 6033,
462 6101,
463 6102,
464 6103,
465 6104,
466 6105,
467 6106,
468 6107,
469 6108,
470 6109,
471 6110,
472 6111,
473 6112,
474 6113,
475 6114,
476 6115,
477 6116,
478 6117,
479 6118,
480 6119,
481 6120,
482 6121,
483 6122,
484 6123,
485 6124,
486 6125,
487 6126,
488 6127,
489 6128,
490 6129,
491 6130,
492 6131,
493 6132,
494 6133,
495
496
497 /*** Community ***/
498 1331,
499 1332,
500 1339,
501 1340,
502 1341,
503 1342,
504 1343,
505 1344,
506 1357,
507 1358,
508 1359,
509 1360,
510 1361,
511 1362,
512 1363,
513 1367,
514 1368,
515 1369,
516 1370,
517 1371,
518 1372
519};
520
521ConVar g_cvForumName;
522ConVar g_cvVipFlag;
523ConVar g_cvPunktyWarmupEnabled;
524ConVar g_cvMinimalnaIloscGraczy;
525ConVar g_cvPunktyKill;
526ConVar g_cvPunktyKillVip;
527ConVar g_cvPunktyHs;
528ConVar g_cvPunktyHsVip;
529ConVar g_cvPunktyBombEnabled;
530ConVar g_cvPunktyBombPlanted;
531ConVar g_cvPunktyBombPlantedVip;
532ConVar g_cvPunktyBombDefused;
533ConVar g_cvPunktyBombDefusedVip;
534ConVar g_cvPunktyWygranaRunda;
535ConVar g_cvPunktyWygranaRundaVip;
536ConVar g_cvPunktyMvpEnabled;
537ConVar g_cvPunktyMvpPlayer;
538ConVar g_cvPunktyMvpPlayerVip;
539ConVar g_cvPunktyKnifeEnabled;
540ConVar g_cvPunktyKnifeKill;
541ConVar g_cvPunktyKnifeKillVip;
542ConVar g_cvTraceniePKTEnabled;
543ConVar g_cvPunktyPrzegranaRunda;
544ConVar g_cvPunktyPrzegranaRundaVip;
545ConVar g_cvPunktyDeath;
546ConVar g_cvPunktyDeathVip;
547ConVar g_cvWygranaRundaEnabled;
548ConVar g_cvPrzegranaRundaEnabled;
549ConVar g_Cvar_CoinEnable;
550
551
552/*
553
554Ciało główne. NIE RUSZAĆ
555
556*/
557
558public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max)
559{
560 CreateNative("Rangi_GetPoints", Native_GetPoints);
561 CreateNative("Rangi_GetRank", Native_GetRank);
562 CreateNative("Rangi_GetRankName", Native_GetRankName);
563 CreateNative("Rangi_GetCoinName", Native_GetCoinName);
564 CreateNative("Rangi_GetCoin", Native_GetCoin);
565 CreateNative("Rangi_SetPoints", Native_SetPoints);
566 CreateNative("Rangi_AddPoints", Native_AddPoints);
567 CreateNative("Rangi_SetCoin", Native_SetCoin);
568
569 RegPluginLibrary("ranks");
570
571 return APLRes_Success;
572}
573
574public Plugin myinfo =
575{
576 name = "Rank System",
577 author = "Charlie W.",
578 description = "Rank System H2K dla Mesharsky",
579 version = "4.0.4.3",
580 url = "https://how2kill.pl"
581};
582
583public void OnPluginStart()
584{
585 RegAdminCmd("sm_ranksreload", CmdGetRanks, ADMFLAG_ROOT);
586
587 RegConsoleCmd("sm_mm", CmdMenu);
588 RegConsoleCmd("sm_lvl", CmdMenu);
589 RegConsoleCmd("sm_ranga", CmdMenu);
590
591 RegConsoleCmd("sm_coin", CmdPins);
592 RegConsoleCmd("sm_coins", CmdPins);
593 RegConsoleCmd("sm_pin", CmdPins);
594 RegConsoleCmd("sm_pins", CmdPins);
595
596 HookEvent("round_end", EventRoundEnd);
597 HookEvent("round_mvp", EventRoundMvp);
598 HookEvent("player_death", EventPlayerDeath);
599 HookEvent("bomb_planted", EventBombPlanted);
600 HookEvent("bomb_defused", EventBombDefused);
601
602 HookEvent("announce_phase_end", EventAnnouncePhaseEnd);
603
604 DbConnect();
605
606 g_cvForumName = CreateConVar("rangi_forum", "How2Kill.pl", "Nazwa twojej sieci / forum");
607 g_cvVipFlag = CreateConVar("vip_flag", "o", "Flaga dla gracza VIP, pozostaw puste by każdy miał Vipa.");
608 g_cvPunktyWarmupEnabled = CreateConVar("rangi_Warmup", "0", "Czy naliczać punkty podczas rozgrzewki?", _, true, 0.0, true, 1.0);
609 g_cvPunktyBombEnabled = CreateConVar("rangi_bomb_enabled", "0", "Czy włączyć naliczanie punktów za podłożenie/rozbrojenie bomby?", _, true, 0.0, true, 1.0);
610 g_cvPunktyMvpEnabled = CreateConVar("rangi_mvp_enabled", "0", "Czy włączyć naliczanie punktów za bycie graczem MVP?", _, true, 0.0, true, 1.0);
611 g_cvPunktyKnifeEnabled = CreateConVar("rangi_knife_enabled", "1", "Czy włączyć naliczanie punktów za zabójstwo z noża?", _, true, 0.0, true, 1.0);
612 g_cvTraceniePKTEnabled = CreateConVar("rangi_tracenie_pkt", "1", "Czy włączyć możliwość tracenia punktów?", _, true, 0.0, true, 1.0);
613 g_cvWygranaRundaEnabled = CreateConVar("rangi_win_round", "0", "Czy naliczać punkty za wygraną rundę?", _, true, 0.0, true, 1.0);
614 g_cvPrzegranaRundaEnabled = CreateConVar("rangi_lost_round", "0", "Czy odejmować punkty za przegraną rundę?", _, true, 0.0, true, 1.0);
615 g_cvMinimalnaIloscGraczy = CreateConVar("rangi_ilosc_graczy", "2", "Od ilu graczy włączyć naliczanie punktów.", _, true, 0.0, true, 10.0);
616 g_cvPunktyKill = CreateConVar("rangi_kill", "1", "Ile dodawać punktów za zabójstwo", _, true, 1.0, true, 20.0);
617 g_cvPunktyKillVip = CreateConVar("rangi_kill_vip", "2", "Ile dodawać punktów za zabójstwo (VIP)", _, true, 1.0, true, 20.0);
618 g_cvPunktyDeath = CreateConVar("rangi_death", "2", "Ile tracisz punktów za to że ktoś cię zabije", _, true, 1.0, true, 20.0);
619 g_cvPunktyDeathVip = CreateConVar("rangi_death_vip", "1", "Ile tracisz punktów za to że ktoś cię zabije (VIP)", _, true, 1.0, true, 20.0);
620 g_cvPunktyHs = CreateConVar("rangi_kill_hs", "3", "Ile dodawać punktów za headshot'a?", _, true, 1.0, true, 20.0);
621 g_cvPunktyHsVip = CreateConVar("rangi_kill_hs_vip", "5", "Ile dodawać punktów za headshot'a (VIP)", _, true, 1.0, true, 20.0);
622 g_cvPunktyBombPlanted = CreateConVar("rangi_bomb_planted", "2", "Ile dodawać punktów za podłożenie bomby", _, true, 1.0, true, 20.0);
623 g_cvPunktyBombPlantedVip = CreateConVar("rangi_bomb_planted_vip", "5", "Ile dodawać pkt za podłożenie bomby (VIP)", _, true, 1.0, true, 20.0);
624 g_cvPunktyBombDefused = CreateConVar("rangi_bomb_defused", "2", "Ile dodawać punktów za rozbrojenie bomby", _, true, 1.0, true, 20.0);
625 g_cvPunktyBombDefusedVip = CreateConVar("rangi_bomb_defused_vip", "5", "Ile dodawać pkt za rozbrojenie bomby (VIP)", _, true, 1.0, true, 20.0);
626 g_cvPunktyWygranaRunda = CreateConVar("wygrana_runda", "2", "Ile dodawać punktów za wygranie rundy", _, true, 1.0, true, 20.0);
627 g_cvPunktyWygranaRundaVip = CreateConVar("wygrana_runda_vip", "4", "Ile dodawać punktów za wygranie rundy (VIP)", _, true, 1.0, true, 20.0);
628 g_cvPunktyPrzegranaRunda = CreateConVar("przegrana_runda", "4", "Ile gracz traci punktów za przegranie rundy", _, true, 1.0, true, 20.0);
629 g_cvPunktyPrzegranaRundaVip = CreateConVar("przegrana_runda_vip", "2", "Ile gracz traci punktów za przegranie rundy (VIP)", _, true, 1.0, true, 20.0);
630 g_cvPunktyMvpPlayer = CreateConVar("mvp_player", "3", "Ile dostanie punktów gracz MVP?", _, true, 1.0, true, 20.0);
631 g_cvPunktyMvpPlayerVip = CreateConVar("mvp_player_vip", "5", "Ile dostanie punktów gracz MVP (VIP)?", _, true, 1.0, true, 20.0);
632 g_cvPunktyKnifeKill = CreateConVar("rangi_kill_knife", "4", "Ile dostanie punktów gracz za zabójstwo z noża?", _, true, 1.0, true, 20.0);
633 g_cvPunktyKnifeKillVip = CreateConVar("rangi_kill_knife_vip", "7", "Ile dostanie punktów gracz za zabójstwo z noża (VIP)?", _, true, 1.0, true, 20.0);
634 g_Cvar_CoinEnable = CreateConVar("coin_enable", "1", "[MODUŁ - ODZNAKI] 1 - System odznak włączony | 0 - System odznak wyłączony", _, true, 0.0, true, 1.0);
635
636 AutoExecConfig(true, "RankSystem_Config_4.0");
637}
638
639public void OnMapStart()
640{
641 GetRanks();
642 SDKHook(FindEntityByClassname(MaxClients + 1, "cs_player_manager"), SDKHook_ThinkPost, OnThinkPost);
643
644 char sBuffer[64];
645 static const char sRanksPath[] = "materials/panorama/images/icons/skillgroups/skillgroup%i.svg";
646
647 for (int i = 1; i < 19; i++) //rangi z Wingmana.
648 {
649 FormatEx(sBuffer, sizeof(sBuffer), sRanksPath, i + 50);
650 AddFileToDownloadsTable(sBuffer);
651 }
652}
653
654public void OnMapEnd()
655{
656 LoopClients(i)
657 DbSaveInfo(i);
658}
659
660public void OnClientPutInServer(int client)
661{
662 DbLoadInfo(client);
663}
664
665public Action OnPlayerRunCmd(int client, int &buttons, int &impulse, float vel[3], float angles[3], int &weapon)
666{
667 if (buttons & IN_SCORE && !(GetEntProp(client, Prop_Data, "m_nOldButtons") & IN_SCORE))
668 ServerRankRevealAll();
669}
670
671public void ServerRankRevealAll()
672{
673 Handle buffer = StartMessageAll("ServerRankRevealAll");
674 if (buffer == INVALID_HANDLE)
675 PrintToServer("ServerRankRevealAll = INVALID_HANDLE");
676 else
677 EndMessage();
678}
679
680/*
681
682DataBases
683
684*/
685
686public void DbConnect()
687{
688 char error[255];
689 DBResultSet rs;
690
691 if (SQL_CheckConfig("h2k_rangi"))
692 {
693 db = SQL_Connect("h2k_rangi", true, error, 255);
694
695 if (db == null)
696 SetFailState("Error on start. Reason: %s", error);
697 }
698 else
699 SetFailState("Cant find `h2k_rangi` on database.cfg");
700
701 if ((rs = SQL_Query(db, g_sMySQLCreate)) == null)
702 {
703 SQL_GetError(db, error, sizeof(error));
704 LogError("Error: %s", error);
705 LogError("Query: %s", g_sMySQLCreate);
706 }
707
708 delete rs;
709}
710
711public void DbLoadInfo(int client)
712{
713 if(!IsValidClient(client))
714 return;
715
716 char error[255];
717 char query[512];
718 char authid[64];
719 DBResultSet rs;
720
721 GetClientAuthId(client, AuthId_SteamID64, authid, sizeof(authid));
722 Format(query, sizeof(query), g_sMySQLLoad, authid);
723
724 if ((rs = SQL_Query(db, query)) == null)
725 LogError("Error: %s", error);
726 else if(rs.FetchRow())
727 {
728 g_iPoints[client] = rs.FetchInt(0);
729 g_iRank[client] = rs.FetchInt(1);
730 g_iCoin[client] = rs.FetchInt(2);
731 CheckRank(client);
732 }
733 else
734 {
735 delete rs;
736 char name[MAX_NAME_LENGTH];
737
738 GetClientName(client, name, sizeof(name));
739 Format(query, sizeof(query), g_sMySQLInsert, authid, name, 0, 0, 0, g_sRanksNames[0]);
740
741 g_iPoints[client] = 0;
742 g_iRank[client] = 0;
743 g_iCoin[client] = 0;
744 CheckRank(client);
745
746 if ((rs = SQL_Query(db, query)) == null)
747 {
748 SQL_GetError(db, error, sizeof(error));
749 LogError("Error: %s", error);
750 LogError("Query: %s", g_sMySQLCreate);
751 }
752 }
753
754 delete rs;
755}
756
757public void DbSaveInfo(int client)
758{
759 char error[255];
760 char query[512];
761 char authid[64];
762 char name[MAX_NAME_LENGTH];
763 DBResultSet rs;
764
765 GetClientName(client, name, MAX_NAME_LENGTH);
766 int len = ((strlen(name) * 2) + 1);
767 char[] escapeName = new char[len];
768 db.Escape(name, escapeName, len);
769
770 if(GetClientAuthId(client, AuthId_SteamID64, authid, sizeof(authid)))
771 {
772 Format(query, sizeof(query), g_sMySQLSave, escapeName, g_iPoints[client], g_iRank[client], g_iCoin[client], g_sRanksNames[g_iRank[client]], authid);
773 if ((rs = SQL_Query(db, query)) == null)
774 {
775 SQL_GetError(db, error, sizeof(error));
776 LogError("Error (disconnect): %s", error);
777 LogError("Query: %s", g_sMySQLCreate);
778 }
779 }
780
781 delete rs;
782}
783
784public void OnClientDisconnect(int client)
785{
786 if (!IsValidClient(client) || IsFakeClient(client))
787 return;
788
789 DbSaveInfo(client);
790}
791
792/*
793
794HOOKI
795
796*/
797
798public Action EventAnnouncePhaseEnd(Handle event, const char[] name, bool dontBroadcast)
799{
800 ServerRankRevealAll();
801}
802
803public void OnThinkPost(int entity)
804{
805 int iRank[MAXPLAYERS+1];
806 int iCoin[MAXPLAYERS+1];
807 int m_iCompetitiveRanking = -1;
808 int m_nActiveCoinRank = -1;
809
810 if(m_iCompetitiveRanking == -1)
811 m_iCompetitiveRanking = FindSendPropInfo("CCSPlayerResource", "m_iCompetitiveRanking");
812
813 if (m_nActiveCoinRank == -1)
814 m_nActiveCoinRank = FindSendPropInfo("CCSPlayerResource", "m_nActiveCoinRank");
815
816 //Ranks
817 GetEntDataArray(entity, m_iCompetitiveRanking, iRank, MaxClients+1);
818 LoopClients(i)
819 {
820 if(g_iRank[i] == 0)
821 iRank[i] = g_iRank[i];
822 else
823 iRank[i] = g_iRank[i] + g_iWingmanRanks;
824 }
825 SetEntDataArray(entity, m_iCompetitiveRanking, iRank, MaxClients+1);
826
827 //Coins
828 GetEntDataArray(entity, m_nActiveCoinRank, iCoin, MaxClients+1);
829 LoopClients(i)
830 {
831 if(g_iCoin[i] != 0)
832 iCoin[i] = g_iCoins[g_iCoin[i]];
833 }
834 SetEntDataArray(entity, m_nActiveCoinRank, iCoin, MaxClients+1);
835}
836
837public Action EventRoundEnd(Event event, const char[] name, bool dontBroadcast)
838{
839 if(!IsMinimalPlayers() || !IsEnableOnWarmup())
840 return;
841
842 int winnerTeam = event.GetInt("winner");
843
844 LoopClients(i)
845 {
846 if(GetClientTeam(i) == winnerTeam)
847 {
848 //podwójny if dlatemu aby uniknąć sytuacji że zabierze pkt graczowi z wygranej drużyny (jeżeli cvar będzie false)
849 if(g_cvWygranaRundaEnabled.BoolValue)
850 GivePoints(i, IsPlayerVip(i) ? g_cvPunktyWygranaRundaVip.IntValue : g_cvPunktyWygranaRunda.IntValue);
851 }
852 else if (g_cvTraceniePKTEnabled.BoolValue && g_cvPrzegranaRundaEnabled.BoolValue)
853 TakePoints(i, IsPlayerVip(i) ? g_cvPunktyPrzegranaRundaVip.IntValue : g_cvPunktyPrzegranaRunda.IntValue);
854
855 DbSaveInfo(i);
856 CheckRank(i);
857 }
858}
859
860public Action EventRoundMvp(Event event, char[] name, bool bDontBroadcast)
861{
862 if (!g_cvPunktyMvpEnabled.BoolValue || !IsMinimalPlayers())
863 return;
864
865 int client = GetClientOfUserId(event.GetInt("userid"));
866
867 if (!IsValidClient(client))
868 return;
869
870 GivePoints(client, IsPlayerVip(client) ? g_cvPunktyMvpPlayerVip.IntValue : g_cvPunktyMvpPlayer.IntValue);
871}
872
873public Action EventPlayerDeath(Event event, const char[] name, bool bDontBroadcast)
874{
875 if(!IsMinimalPlayers() || !IsEnableOnWarmup())
876 return;
877
878 bool headshot = event.GetBool("headshot", false);
879 int attacker = GetClientOfUserId(event.GetInt("attacker"));
880 int client = GetClientOfUserId(event.GetInt("userid"));
881
882 int attackerPoints = 0;
883 int clientPoints = 0;
884
885 if(!IsValidClient(attacker) || !IsValidClient(client) || attacker == client)
886 return;
887
888 char weapon[64];
889 event.GetString("weapon", weapon, sizeof(weapon));
890 bool knife = (StrContains(weapon, "knife", false) != -1 || StrContains(weapon, "bayonet", false) != -1) && g_cvPunktyKnifeEnabled.BoolValue;
891
892 if(IsPlayerVip(attacker))
893 {
894 attackerPoints += headshot ? g_cvPunktyHsVip.IntValue:g_cvPunktyKillVip.IntValue;
895
896 if(knife)
897 attackerPoints += g_cvPunktyKnifeKillVip.IntValue;
898 }
899 else
900 {
901 attackerPoints += headshot ? g_cvPunktyHs.IntValue:g_cvPunktyKill.IntValue;
902
903 if(knife)
904 attackerPoints += g_cvPunktyKnifeKill.IntValue;
905 }
906
907 if (g_cvTraceniePKTEnabled.BoolValue)
908 clientPoints += IsPlayerVip(client) ? g_cvPunktyDeathVip.IntValue : g_cvPunktyDeath.IntValue;
909
910 GivePoints(attacker, attackerPoints);
911 TakePoints(client, clientPoints);
912}
913
914public Action EventBombPlanted(Event event, const char[] name, bool bDontBroadcast)
915{
916 if (!g_cvPunktyBombEnabled.BoolValue || !IsMinimalPlayers())
917 return;
918
919 int client = GetClientOfUserId(event.GetInt("userid"));
920
921 if (!IsValidClient(client))
922 return;
923
924 GivePoints(client, IsPlayerVip(client) ? g_cvPunktyBombPlantedVip.IntValue:g_cvPunktyBombPlanted.IntValue);
925}
926
927public Action EventBombDefused(Event event, const char[] name, bool bDontBroadcast)
928{
929 if (!g_cvPunktyBombEnabled.BoolValue || !IsMinimalPlayers())
930 return;
931
932 int client = GetClientOfUserId(event.GetInt("userid"));
933
934 if (!IsValidClient(client))
935 return;
936
937 GivePoints(client, IsPlayerVip(client) ? g_cvPunktyBombDefusedVip.IntValue:g_cvPunktyBombDefused.IntValue);
938}
939
940/*
941
942HELPERS
943
944*/
945
946public void CheckRank(int client)
947{
948 if(!IsValidClient(client))
949 return;
950
951 bool bLvlDown = false;
952 bool bLvlUP = false;
953
954 while(g_iPoints[client] >= g_iRanks[g_iRank[client]] && g_iRank[client] < sizeof(g_iRanks)-1)
955 {
956 g_iRank[client]++;
957 bLvlUP = true;
958 }
959
960 if(g_iRank[client] > 0)
961 {
962 while(g_iPoints[client] < g_iRanks[g_iRank[client]-1])
963 {
964 g_iRank[client]--;
965 bLvlDown = true;
966 if(g_iRank[client] == 0)
967 break;
968 }
969 }
970
971 if(bLvlDown || bLvlUP)
972 {
973 if(bLvlUP)
974 {
975 if(g_iRank[client] == sizeof(g_iRanks)-1)
976 PrintToChat(client, " %s \x07Osiagnałeś maksymalny stopień. Twoja ranga to : %s.", PREFIX_NORMAL, g_sRanksNames[g_iRank[client]]);
977 else
978 PrintToChat(client, " %s \x06Awansowałeś do rangi \x03%s\x06 !", PREFIX_NORMAL, g_sRanksNames[g_iRank[client]]);
979 }
980
981 if(bLvlDown)
982 PrintToChat(client, " %s \x06Spadłeś do rangi \x03%s", PREFIX_NORMAL, g_sRanksNames[g_iRank[client]]);
983 }
984}
985
986public void TakePoints(int client, int value)
987{
988 g_iPoints[client] -= value;
989
990 if(g_iPoints[client] < 0)
991 g_iPoints[client] = 0;
992
993 CheckRank(client);
994}
995
996public void GivePoints(int client, int value)
997{
998 g_iPoints[client] += value;
999 CheckRank(client);
1000}
1001
1002public bool IsMinimalPlayers()
1003{
1004 if((GetTeamClientCount(CS_TEAM_T) + GetTeamClientCount(CS_TEAM_CT)) >= g_cvMinimalnaIloscGraczy.IntValue)
1005 return true;
1006 return false;
1007}
1008
1009public bool IsEnableOnWarmup()
1010{
1011 return (GameRules_GetProp("m_bWarmupPeriod") != 0 && !g_cvPunktyWarmupEnabled.BoolValue);
1012}
1013
1014public bool IsPlayerVip(int client)
1015{
1016 char flag[10];
1017 g_cvVipFlag.GetString(flag, sizeof(flag));
1018
1019 if (GetUserFlagBits(client) & ReadFlagString(flag) || GetAdminFlag(GetUserAdmin(client), Admin_Root))
1020 return true;
1021 return false;
1022}
1023
1024/*
1025
1026KV
1027
1028*/
1029
1030public void GetRanks()
1031{
1032 delete g_hRanks;
1033 int i = 1;
1034 g_iWingmanRanks = 0;
1035 g_hRanks = CreateKeyValues("Rangi");
1036
1037 BuildPath(Path_SM, sPath, sizeof(sPath), "configs/h2k_rangi.cfg");
1038
1039 if (!FileExists(sPath))
1040 SetFailState("File Not Found: %s", sPath);
1041
1042 g_hRanks.ImportFromFile(sPath);
1043 if (!g_hRanks.GotoFirstSubKey())
1044 return;
1045
1046 //Klucz "type" oraz wartość "value" muszę być 1 w KV.
1047 if(g_hRanks.GetNum("value") == 1)
1048 g_iWingmanRanks = 50;
1049
1050 if(!g_hRanks.GotoNextKey())
1051 return;
1052
1053 for(;;)
1054 {
1055 char sName[128];
1056 int iPoints;
1057
1058 g_hRanks.GetSectionName(sName, sizeof(sName));
1059 iPoints = g_hRanks.GetNum("points");
1060
1061 g_sRanksNames[i] = sName;
1062 g_iRanks[i-1] = iPoints;
1063
1064 if(!g_hRanks.GotoNextKey() || i == 18)
1065 break;
1066
1067 i++;
1068 }
1069
1070 return;
1071}
1072
1073/*
1074
1075KOMENDY
1076
1077*/
1078
1079public Action CmdGetRanks(int client, int args)
1080{
1081 if(!IsValidClient(client))
1082 return Plugin_Handled;
1083
1084 GetRanks();
1085
1086 LoopClients(i)
1087 {
1088 if(IsValidClient(i))
1089 CheckRank(i);
1090 }
1091
1092 PrintToChat(client, " \x06Przeładowano ustawienia rang.");
1093 return Plugin_Handled;
1094}
1095
1096public Action CmdMenu(int client, int args)
1097{
1098 CheckRank(client);
1099 char title[128];
1100 g_cvForumName.GetString(title, sizeof(title));
1101
1102
1103 if(g_iRank[client] == sizeof(g_iRanks)-1)
1104 Format(title, sizeof(title), "%s \n \n* Osiagnales maksymalny stopień.\n* Ranga: [%s]\n \n", title, g_sRanksNames[g_iRank[client]]);
1105 else
1106 Format(title, sizeof(title), "%s \n \n* Ranga: [%s] \n* Punkty [%d/%d]\n \n", title, g_sRanksNames[g_iRank[client]], g_iPoints[client], g_iRanks[g_iRank[client]]);
1107
1108
1109 Menu menu = new Menu(MainMenuHandler);
1110 menu.SetTitle(title);
1111 menu.AddItem("Item_1", "Wyświetl wymagania na poszczególne rangi");
1112 menu.AddItem("Item_2", "Może coś tu kiedyś będzie, essa :D", ITEMDRAW_DISABLED);
1113 menu.ExitButton = true;
1114 menu.Display(client, MENU_TIME_FOREVER);
1115 return Plugin_Handled;
1116}
1117
1118public Action CmdPins(int client, int args)
1119{
1120 if (!g_Cvar_CoinEnable.BoolValue || !IsValidClient(client))
1121 return;
1122
1123 char buffer[310];
1124 Menu menu = new Menu(PinsMenuHandler);
1125
1126 menu.SetTitle("Wybierz odznake:\n- Aktualna: [ %s ]\n", g_sCoinsNames[g_iCoin[client]]);
1127
1128 if (g_iCoin[client] == 0)
1129 {
1130 Format(buffer, sizeof(buffer), "> %s <", g_sCoinsNames[0]);
1131 menu.AddItem("0", buffer, ITEMDRAW_DISABLED);
1132 }
1133 else
1134 menu.AddItem("0", g_sCoinsNames[0], ITEMDRAW_DEFAULT);
1135
1136 if (g_iCoin[client] == 1)
1137 {
1138 Format(buffer, sizeof(buffer), "> %s <", g_sCoinsNames[1]);
1139 menu.AddItem("1", buffer, ITEMDRAW_DISABLED);
1140 }
1141 else
1142 menu.AddItem("1", g_sCoinsNames[1], ITEMDRAW_DEFAULT);
1143
1144 menu.AddItem("2", "Major Pin");
1145 menu.AddItem("3", "Operation Pin");
1146 menu.AddItem("4", "Collectible Pin");
1147 menu.AddItem("5", "Community Coin");
1148
1149 menu.Display(client, MENU_TIME_FOREVER);
1150}
1151
1152public Action CmdAddPoints(int client, int args)
1153{
1154 if (args < 1)
1155 {
1156 ReplyToCommand(client, "[SM] Usage: sm_addpoints <#userid|name> [points]");
1157 return Plugin_Handled;
1158 }
1159
1160 int amount = 0;
1161 char arg[65];
1162 GetCmdArg(1, arg, sizeof(arg));
1163
1164 if (args > 1)
1165 {
1166 char arg2[20];
1167 GetCmdArg(2, arg2, sizeof(arg2));
1168 if (StringToIntEx(arg2, amount) < 0)
1169 {
1170 ReplyToCommand(client, "[SM] Serio?");
1171 return Plugin_Handled;
1172 }
1173 }
1174
1175 char target_name[MAX_TARGET_LENGTH];
1176 int target_list[MAXPLAYERS], target_count;
1177 bool tn_is_ml;
1178
1179 if ((target_count = ProcessTargetString(arg, client, target_list, MAXPLAYERS, COMMAND_FILTER_CONNECTED, target_name, sizeof(target_name), tn_is_ml)) <= 0)
1180 {
1181 ReplyToTargetError(client, target_count);
1182 return Plugin_Handled;
1183 }
1184
1185 for (int i = 0; i < target_count; i++)
1186 AddPoints(i, amount);
1187
1188 return Plugin_Handled;
1189}
1190
1191/*
1192
1193MENUS
1194
1195*/
1196
1197public int MainMenuHandler(Menu menu, MenuAction action, int client, int item)
1198{
1199 switch(action)
1200 {
1201 case MenuAction_Select:
1202 {
1203 char buffer[32];
1204 menu.GetItem(item, buffer, sizeof(buffer));
1205
1206 if(StrEqual(buffer, "Item_1"))
1207 HelpMenu(client);
1208 else if(StrEqual(buffer, "Item_2"))
1209 return;
1210 }
1211 case MenuAction_End:
1212 {
1213 delete menu;
1214 }
1215 }
1216}
1217
1218public void HelpMenu(int client)
1219{
1220 Menu menu = new Menu(HelpMenuHandler, MENU_ACTIONS_ALL);
1221 menu.SetTitle("Wymagania poszczególnych rang:\n \n");
1222
1223 LoopRanks(i)
1224 menu.AddItem(g_sRanksNames[i], g_sRanksNames[i]);
1225
1226 menu.ExitButton = true;
1227 menu.Display(client, 0);
1228}
1229
1230public int HelpMenuHandler(Menu menu, MenuAction action, int client, int item)
1231{
1232 switch(action)
1233 {
1234 case MenuAction_Select:
1235 {
1236 char buffer[32];
1237 menu.GetItem(item, buffer, sizeof(buffer));
1238
1239 LoopRanks(i)
1240 {
1241 if(StrEqual(g_sRanksNames[i], buffer))
1242 {
1243 PrintToChat(client, "Wymagane punkty %d/%d", g_iPoints[client], g_iRanks[item]);
1244 HelpMenu(client);
1245 }
1246 }
1247 }
1248 case MenuAction_End:
1249 {
1250 delete menu;
1251 }
1252 }
1253}
1254
1255public int PinsMenuHandler(Menu menu, MenuAction action, int client, int item)
1256{
1257 switch(action)
1258 {
1259 case MenuAction_Select:
1260 {
1261 char buffer[32];
1262 menu.GetItem(item, buffer, sizeof(buffer));
1263
1264 if(StrEqual(buffer, "0"))
1265 g_iCoin[client] = 0;
1266 else if(StrEqual(buffer, "1"))
1267 g_iCoin[client] = 1;
1268 else if(StrEqual(buffer, "2"))
1269 OtherPins(client, 2, 88);
1270 else if(StrEqual(buffer, "3"))
1271 OtherPins(client, 89, 113);
1272 else if(StrEqual(buffer, "4"))
1273 OtherPins(client, 114, 179);
1274 else if(StrEqual(buffer, "5"))
1275 OtherPins(client, 180, 200);
1276 }
1277 case MenuAction_End:
1278 {
1279 delete menu;
1280 }
1281 }
1282}
1283
1284public void OtherPins(int client, int start, int stop)
1285{
1286 Menu menu = new Menu(OtherPinsHandler);
1287 menu.SetTitle("Wybierz odznake:\n- Aktualna: [ %s ]\n", g_sCoinsNames[g_iCoin[client]]);
1288
1289 char infoBuffer[6];
1290 char displayBuffer[310];
1291
1292 for (int i = start; i <= stop; i++)
1293 {
1294 if (i == g_iCoin[client])
1295 {
1296 IntToString(i, infoBuffer, sizeof(infoBuffer));
1297 Format(displayBuffer, sizeof(displayBuffer), "> %s <", g_sCoinsNames[i]);
1298 menu.AddItem(infoBuffer, displayBuffer, ITEMDRAW_DISABLED);
1299 }
1300 else
1301 menu.AddItem(infoBuffer, g_sCoinsNames[i], ITEMDRAW_DEFAULT);
1302 }
1303
1304 menu.ExitButton = true;
1305 menu.Display(client, 0);
1306}
1307
1308public int OtherPinsHandler(Menu menu, MenuAction action, int client, int item)
1309{
1310 switch(action)
1311 {
1312 case MenuAction_Select:
1313 {
1314 char buffer[10];
1315 GetMenuItem(menu, item, buffer, sizeof(buffer));
1316 g_iCoin[client] = StringToInt(buffer);
1317 DbSaveInfo(client);
1318 }
1319 case MenuAction_End:
1320 {
1321 delete menu;
1322 }
1323 }
1324}
1325
1326/*
1327
1328ELSE
1329
1330*/
1331
1332public bool IsValidClient(int client)
1333{
1334 if(client <= 0 ) return false;
1335 if(client > MaxClients) return false;
1336 if(!IsClientConnected(client)) return false;
1337 if(IsClientReplay(client)) return false;
1338 if(IsFakeClient(client)) return false;
1339 if(IsClientSourceTV(client)) return false;
1340 return IsClientInGame(client);
1341}
1342
1343public void SetPoints(int client, int value)
1344{
1345 g_iPoints[client] = value;
1346 CheckRank(client);
1347 DbSaveInfo(client);
1348}
1349
1350public void AddPoints(int client, int value)
1351{
1352 g_iPoints[client] += value;
1353 CheckRank(client);
1354 DbSaveInfo(client);
1355}
1356
1357public void SetCoins(int client, int coin)
1358{
1359 g_iCoin[client] = coin;
1360 DbSaveInfo(client);
1361}
1362
1363/*
1364
1365Natives
1366
1367*/
1368
1369public int Native_GetPoints(Handle plugin, int numParams)
1370{
1371 return g_iPoints[GetNativeCell(1)];
1372}
1373
1374public int Native_GetRank(Handle plugin, int numParams)
1375{
1376 return g_iRanks[GetNativeCell(1)];
1377}
1378
1379public int Native_GetRankName(Handle plugin, int numParams)
1380{
1381 SetNativeString(2, g_sRanksNames[g_iRanks[GetNativeCell(1)]], GetNativeCell(3));
1382}
1383
1384public int Native_GetCoinName(Handle plugin, int numParams)
1385{
1386 SetNativeString(2, g_sCoinsNames[g_iCoin[GetNativeCell(1)]], GetNativeCell(3));
1387}
1388
1389public int Native_GetCoin(Handle plugin, int numParams)
1390{
1391 return g_iCoin[GetNativeCell(1)];
1392}
1393
1394public int Native_SetPoints(Handle plugin, int numParams)
1395{
1396 SetPoints(GetNativeCell(1), GetNativeCell(2));
1397 return true;
1398}
1399
1400public int Native_AddPoints(Handle plugin, int numParams)
1401{
1402 AddPoints(GetNativeCell(1), GetNativeCell(2));
1403 return true;
1404}
1405
1406public int Native_SetCoin(Handle plugin, int numParams)
1407{
1408 SetCoins(GetNativeCell(1), GetNativeCell(2));
1409 return true;
1410}
1411
1412/* © 2019 Coded with ❤ for Rias */
1413/* © 2019 Coded with ❤ for Akame */
1414/* © 2019 Coded with ❤ for Est */
1415/* © 2019 Coded with ❤ for Yoshino */
1416/* © 2019 Coded with ❤ for Koneko */
1417/* © 2019 Coded with ❤ for Erina */
1418/* © 2019 Coded with ❤ for Megumi */
1419/* © 2019 Coded with ❤ for Akeno */
1420/* © 2019 Coded with ❤ for Mero */
1421/* © 2019 Coded with ❤ for Papi */
1422/* © 2019 Coded with ❤ for Suu */
1423/* © 2019 Coded with ❤ for Lilith */
1424/* © 2019 Coded with ❤ for Mitsuha */
1425/* © 2019 Coded with ❤ for Matsuzaka */
1426/* © 2019 Coded with ❤ for Maki */
1427/* © 2019 Coded with ❤ for Alice */
1428/* © 2019 Coded with ❤ for Konno Yuuki (*) Arigato! :< */
1429/* A na koniec jebać Mesharskiego Essa :'( */