· 8 years ago · Mar 10, 2018, 02:26 PM
1// =================================================
2// BEGIN EDITING HERE
3// =================================================
4
5// Should the plugin save player data in SQL database?
6// To save player data in a vault, change "#define USING_SQL" to "//#define USING_SQL"
7// To save player data in SQL, change "//#define USING_SQL" to "#define USING_SQL"
8
9//#define USING_SQL
10
11// The prefix in all of the plugin's messages
12
13new const MESSAGE_TAG[] = "[HNS XP]";
14
15// If the player hasn't ever been to your server, they will get this much xp to start with
16
17#define ENTRY_XP 100
18
19// These determine if these abilities should be enabled or disabled
20// 1 = enabled
21// 0 = disabled
22
23#define ENABLE_GRENADE 1
24#define ENABLE_FLASHBANG_1 1
25#define ENABLE_FLASHBANG_2 1
26#define ENABLE_SMOKEGRENADE 1
27#define ENABLE_TERR_HEALTH 1
28#define ENABLE_CT_HEALTH 1
29#define ENABLE_TERR_ARMOR 1
30#define ENABLE_CT_ARMOR 1
31#define ENABLE_TERR_RESPAWN 1
32#define ENABLE_CT_RESPAWN 1
33#define ENABLE_TERR_NOFALL 1
34#define ENABLE_CT_NOFALL 1
35
36// The maximum level for each ability
37
38#define MAXLEVEL_GRENADE 8
39#define MAXLEVEL_FLASHBANG_1 4
40#define MAXLEVEL_FLASHBANG_2 4
41#define MAXLEVEL_SMOKEGRENADE 4
42#define MAXLEVEL_TERR_HEALTH 10
43#define MAXLEVEL_CT_HEALTH 5
44#define MAXLEVEL_TERR_ARMOR 8
45#define MAXLEVEL_CT_ARMOR 6
46#define MAXLEVEL_TERR_RESPAWN 2
47#define MAXLEVEL_CT_RESPAWN 2
48#define MAXLEVEL_TERR_NOFALL 8
49#define MAXLEVEL_CT_NOFALL 8
50
51// The xp amount required to buy the first level
52
53#define FIRST_XP_GRENADE 100
54#define FIRST_XP_FLASHBANG_1 100
55#define FIRST_XP_FLASHBANG_2 100
56#define FIRST_XP_SMOKEGRENADE 100
57#define FIRST_XP_TERR_HEALTH 100
58#define FIRST_XP_CT_HEALTH 100
59#define FIRST_XP_TERR_ARMOR 100
60#define FIRST_XP_CT_ARMOR 100
61#define FIRST_XP_TERR_RESPAWN 1000
62#define FIRST_XP_CT_RESPAWN 2000
63#define FIRST_XP_TERR_NOFALL 100
64#define FIRST_XP_CT_NOFALL 100
65
66// The maximum chance possible for this ability (happens when player has maximum level)
67
68#define CHANCE_MAX_GRENADE 100
69#define CHANCE_MAX_FLASHBANG_1 100
70#define CHANCE_MAX_FLASHBANG_2 100
71#define CHANCE_MAX_SMOKEGRENADE 100
72#define CHANCE_MAX_TERR_RESPAWN 50
73#define CHANCE_MAX_CT_RESPAWN 50
74#define CHANCE_MAX_TERR_NOFALL 80
75#define CHANCE_MAX_CT_NOFALL 80
76
77// =================================================
78// STOP EDITING HERE
79// =================================================
80
81
82#include <amxmodx>
83#include <amxmisc>
84#include <cstrike>
85#include <hamsandwich>
86#include <fun>
87#include <regex>
88#include <hlsdk_const>
89
90#if defined USING_SQL
91#include <sqlx>
92
93new Handle:g_sql_tuple;
94#else
95#include <nvault>
96
97new g_vault;
98#endif
99
100
101new const VERSION[] = "0.0.1";
102
103
104#pragma semicolon 1
105
106enum _:Grenades
107{
108NADE_HE,
109NADE_FL1,
110NADE_FL2,
111NADE_SM
112};
113
114new const g_nade_enabled[Grenades] =
115{
116ENABLE_GRENADE,
117ENABLE_FLASHBANG_1,
118ENABLE_FLASHBANG_2,
119ENABLE_SMOKEGRENADE
120};
121
122new const g_any_nade_enabled = ENABLE_GRENADE + ENABLE_FLASHBANG_1 + ENABLE_FLASHBANG_2 + ENABLE_SMOKEGRENADE;
123
124new const g_nade_names[Grenades][] =
125{
126"HE Grenade",
127"Flashbang #1",
128"Flashbang #2",
129"Frost Nade"
130};
131
132new const g_nade_classnames[Grenades][] =
133{
134"weapon_hegrenade",
135"weapon_flashbang",
136"weapon_flashbang",
137"weapon_smokegrenade"
138};
139
140new const g_nade_maxlevels[Grenades] =
141{
142MAXLEVEL_GRENADE,
143MAXLEVEL_FLASHBANG_1,
144MAXLEVEL_FLASHBANG_2,
145MAXLEVEL_SMOKEGRENADE
146};
147
148new const g_nade_first_xp[Grenades] =
149{
150FIRST_XP_GRENADE,
151FIRST_XP_FLASHBANG_1,
152FIRST_XP_FLASHBANG_2,
153FIRST_XP_SMOKEGRENADE
154};
155
156new const g_nade_max_chance[Grenades] =
157{
158CHANCE_MAX_GRENADE,
159CHANCE_MAX_FLASHBANG_1,
160CHANCE_MAX_FLASHBANG_2,
161CHANCE_MAX_SMOKEGRENADE
162};
163
164new const g_team_names[CsTeams][] =
165{
166"Spectator",
167"Terrorist",
168"Counter-Terrorist",
169"Spectator"
170};
171
172new const g_health_enabled[CsTeams] =
173{
1740,
175ENABLE_TERR_HEALTH,
176ENABLE_CT_HEALTH,
1770
178};
179
180new const g_any_health_enabled = ENABLE_TERR_HEALTH + ENABLE_CT_HEALTH;
181
182new const g_health_names[CsTeams][] =
183{
184"",
185"T Extra Health",
186"CT Extra Health",
187""
188};
189
190new const g_health_maxamount[CsTeams] =
191{
1920,
193100,
19450,
1950
196};
197
198new const g_health_maxlevels[CsTeams] =
199{
2000,
201MAXLEVEL_TERR_HEALTH,
202MAXLEVEL_CT_HEALTH,
2030
204};
205
206new const g_health_first_xp[CsTeams] =
207{
2080,
209FIRST_XP_TERR_HEALTH,
210FIRST_XP_CT_HEALTH,
2110
212};
213
214new const g_armor_enabled[CsTeams] =
215{
2160,
217ENABLE_TERR_ARMOR,
218ENABLE_CT_ARMOR,
2190
220};
221
222new const g_any_armor_enabled = ENABLE_TERR_ARMOR + ENABLE_CT_ARMOR;
223
224new const g_armor_names[CsTeams][] =
225{
226"",
227"T Armor",
228"CT Armor",
229""
230};
231
232new const g_armor_maxamount[CsTeams] =
233{
2340,
235200,
236150,
2370
238};
239
240new const g_armor_maxlevels[CsTeams] =
241{
2420,
243MAXLEVEL_TERR_ARMOR,
244MAXLEVEL_CT_ARMOR,
2450
246};
247
248new const g_armor_first_xp[CsTeams] =
249{
2500,
251FIRST_XP_TERR_ARMOR,
252FIRST_XP_CT_ARMOR,
2530
254};
255
256new const g_respawn_enabled[CsTeams] =
257{
2580,
259ENABLE_TERR_RESPAWN,
260ENABLE_CT_RESPAWN,
2610
262};
263
264new const g_any_respawn_enabled = ENABLE_TERR_RESPAWN + ENABLE_CT_RESPAWN;
265
266new const g_respawn_names[CsTeams][] =
267{
268"",
269"T Respawn Chance",
270"CT Respawn Chance",
271""
272};
273
274new const g_respawn_maxlevels[CsTeams] =
275{
2760,
277MAXLEVEL_TERR_RESPAWN,
278MAXLEVEL_CT_RESPAWN,
2790
280};
281
282new const g_respawn_first_xp[CsTeams] =
283{
2840,
285FIRST_XP_TERR_RESPAWN,
286FIRST_XP_CT_RESPAWN,
2870
288};
289
290new const g_respawn_max_chance[CsTeams] =
291{
2920,
293CHANCE_MAX_TERR_RESPAWN,
294CHANCE_MAX_CT_RESPAWN,
2950
296};
297
298new const g_nofall_enabled[CsTeams] =
299{
3000,
301ENABLE_TERR_NOFALL,
302ENABLE_CT_NOFALL,
3030
304};
305
306new const g_any_nofall_enabled = ENABLE_TERR_NOFALL + ENABLE_CT_NOFALL;
307
308new const g_nofall_names[CsTeams][] =
309{
310"",
311"T Fall Damage Reducer",
312"CT Fall Damage Reducer",
313""
314};
315
316new const g_nofall_maxlevels[CsTeams] =
317{
3180,
319MAXLEVEL_TERR_NOFALL,
320MAXLEVEL_CT_NOFALL,
3210
322};
323
324new const g_nofall_first_xp[CsTeams] =
325{
3260,
327FIRST_XP_TERR_NOFALL,
328FIRST_XP_CT_NOFALL,
3290
330};
331
332new const g_nofall_max_chance[CsTeams] =
333{
3340,
335CHANCE_MAX_TERR_NOFALL,
336CHANCE_MAX_CT_NOFALL,
3370
338};
339
340#define ANY_ABILITY_ENABLED (g_any_nade_enabled || g_any_health_enabled || g_any_armor_enabled || g_any_respawn_enabled || g_any_nofall_enabled)
341
342new g_authid[33][35];
343
344new g_xp[33];
345
346new g_first_time[33];
347#if defined USING_SQL
348new g_loaded_data[33];
349#endif
350
351new g_used_revive[33];
352
353new g_nade_level[33][Grenades];
354new g_armor_level[33][CsTeams];
355new g_respawn_level[33][CsTeams];
356new g_health_level[33][CsTeams];
357new g_nofall_level[33][CsTeams];
358
359new cvar_xp_suicide;
360new cvar_xp_kill;
361new cvar_xp_headshot;
362new cvar_xp_grenade;
363new cvar_xp_survive;
364new cvar_xp_win;
365new cvar_spawn_nade_delay;
366
367new Float:g_nade_give_time;
368
369new Regex:g_SteamID_pattern;
370new g_regex_return;
371
372new g_first_client;
373new g_max_clients;
374
375new g_msgid_SayText;
376
377#if defined USING_SQL
378public plugin_precache()
379{
380g_sql_tuple = SQL_MakeStdTuple();
381
382SQL_ThreadQuery(g_sql_tuple, "QueryCreateTable", "CREATE TABLE IF NOT EXISTS `hns_xp` ( `name` VARCHAR(32) NOT NULL, `authid` VARCHAR(35) NOT NULL, `data` VARCHAR(256) NOT NULL );" );
383}
384
385public QueryCreateTable(failstate, Handle:query, error[], errnum, data[], size, Float:queuetime)
386{
387if( failstate == TQUERY_CONNECT_FAILED
388|| failstate == TQUERY_QUERY_FAILED )
389{
390set_fail_state(error);
391}
392}
393#endif
394
395public plugin_init()
396{
397register_plugin("HideNSeek XP Mod", VERSION, "Exolent");
398register_cvar("hnsxp_author", "Exolent", FCVAR_SPONLY);
399register_cvar("hnsxp_version", VERSION, FCVAR_SPONLY);
400
401register_clcmd("say /xp", "CmdMainMenu");
402register_clcmd("say /exp", "CmdMainMenu");
403
404register_concmd("hnsxp_give_xp", "CmdGiveXP", ADMIN_RCON, "<nick, #userid, authid> <xp>");
405register_concmd("hnsxp_remove_xp", "CmdRemoveXP", ADMIN_RCON, "<nick, #userid, authid> <xp>");
406
407register_event("HLTV", "EventNewRound", "a", "1=0", "2=0");
408register_event("DeathMsg", "EventDeathMsg", "a");
409register_logevent("EventRoundStart", 2, "1=Round_Start");
410register_logevent("EventRoundEnd", 2, "1=Round_End");
411register_event("TextMsg", "EventRoundRestart", "a", "2&#Game_C", "2&#Game_w");
412
413RegisterHam(Ham_Spawn, "player", "FwdPlayerSpawn", 1);
414RegisterHam(Ham_Killed, "player", "FwdPlayerDeath", 1);
415RegisterHam(Ham_TakeDamage, "player", "FwdPlayerDamage");
416
417cvar_xp_suicide = register_cvar("hnsxp_xp_suicide", "5");
418cvar_xp_kill = register_cvar("hnsxp_xp_kill", "4");
419cvar_xp_headshot = register_cvar("hnsxp_xp_headshot", "3");
420cvar_xp_grenade = register_cvar("hnsxp_xp_grenade", "6");
421cvar_xp_survive = register_cvar("hnsxp_xp_survive", "2");
422cvar_xp_win = register_cvar("hnsxp_xp_win", "3");
423cvar_spawn_nade_delay = register_cvar("hnsxp_spawn_nade_delay", "10");
424
425#if !defined USING_SQL
426g_vault = nvault_open("hnsxp");
427#endif
428
429new err[2];
430g_SteamID_pattern = regex_compile("^^STEAM_0:(0|1):\d+$", g_regex_return, err, sizeof(err) - 1);
431
432g_first_client = 1;
433g_max_clients = get_maxplayers();
434
435g_msgid_SayText = get_user_msgid("SayText");
436}
437
438#if !defined USING_SQL
439public plugin_end()
440{
441nvault_close(g_vault);
442}
443#endif
444
445public plugin_natives()
446{
447register_library("hns_xp");
448register_native("hnsxp_get_user_xp", "_get_xp");
449register_native("hnsxp_set_user_xp", "_set_xp");
450}
451
452public _get_xp(plugin, params)
453{
454return g_xp[get_param(1)];
455}
456
457public _set_xp(plugin, params)
458{
459new client = get_param(1);
460g_xp[client] = max(0, get_param(2));
461Save(client);
462return g_xp[client];
463}
464
465public client_authorized(client)
466{
467if( !is_user_bot(client) && !is_user_hltv(client) )
468{
469/* is this still called in LAN, non-steam, etc? */
470get_user_authid(client, g_authid[client], sizeof(g_authid[]) - 1);
471
472if( !IsValidAuthid(g_authid[client]) )
473{
474g_authid[client][0] = 0;
475}
476else
477{
478Load(client);
479}
480}
481}
482
483public client_disconnect(client)
484{
485Save(client);
486
487g_authid[client][0] = 0;
488g_first_time[client] = 0;
489#if defined USING_SQL
490g_loaded_data[client] = 0;
491#endif
492g_used_revive[client] = 0;
493}
494
495public CmdMainMenu(client)
496{
497ShowMainMenu(client);
498}
499
500public CmdGiveXP(client, level, cid)
501{
502if( !cmd_access(client, level, cid, 3) ) return PLUGIN_HANDLED;
503
504static arg[35];
505read_argv(1, arg, sizeof(arg) - 1);
506
507new target = cmd_target(client, arg, CMDTARGET_OBEY_IMMUNITY|CMDTARGET_NO_BOTS);
508if( !target ) return PLUGIN_HANDLED;
509
510if( !IsUserAuthorized(target) )
511{
512console_print(client, "Target has not authorized with the server.");
513return PLUGIN_HANDLED;
514}
515
516read_argv(2, arg, sizeof(arg) - 1);
517new xp = str_to_num(arg);
518
519if( xp <= 0 )
520{
521console_print(client, "XP must be a value greater than 0!");
522if( xp < 0 )
523{
524console_print(client, "Use hnsxp_remove_xp instead.");
525}
526return PLUGIN_HANDLED;
527}
528
529g_xp[target] += xp;
530
531Save(target);
532
533static name[2][32];
534get_user_name(client, name[0], sizeof(name[]) - 1);
535get_user_name(target, name[1], sizeof(name[]) - 1);
536
537Print(0, "%s gave %i XP to %s.", name[0], xp, name[1]);
538
539static steamid[2][35];
540get_user_authid(client, steamid[0], sizeof(steamid[]) - 1);
541get_user_authid(target, steamid[1], sizeof(steamid[]) - 1);
542
543log_amx("%s (%s) gave %i XP to %s (%s)", name[0], steamid[0], xp, name[1], steamid[1]);
544
545return PLUGIN_HANDLED;
546}
547
548public CmdRemoveXP(client, level, cid)
549{
550if( !cmd_access(client, level, cid, 3) ) return PLUGIN_HANDLED;
551
552static arg[35];
553read_argv(1, arg, sizeof(arg) - 1);
554
555new target = cmd_target(client, arg, CMDTARGET_OBEY_IMMUNITY|CMDTARGET_NO_BOTS);
556if( !target ) return PLUGIN_HANDLED;
557
558if( !IsUserAuthorized(target) )
559{
560console_print(client, "Target has not authorized with the server.");
561return PLUGIN_HANDLED;
562}
563
564read_argv(2, arg, sizeof(arg) - 1);
565new xp = str_to_num(arg);
566
567if( xp <= 0 )
568{
569console_print(client, "XP must be a value greater than 0!");
570if( xp < 0 )
571{
572console_print(client, "Use hnsxp_give_xp instead.");
573}
574return PLUGIN_HANDLED;
575}
576
577g_xp[target] -= xp;
578
579Save(target);
580
581static name[2][32];
582get_user_name(client, name[0], sizeof(name[]) - 1);
583get_user_name(target, name[1], sizeof(name[]) - 1);
584
585Print(0, "%s removed %i XP from %s.", name[0], xp, name[1]);
586
587static steamid[2][35];
588get_user_authid(client, steamid[0], sizeof(steamid[]) - 1);
589get_user_authid(target, steamid[1], sizeof(steamid[]) - 1);
590
591log_amx("%s (%s) removed %i XP from %s (%s)", name[0], steamid[0], xp, name[1], steamid[1]);
592
593return PLUGIN_HANDLED;
594}
595
596public EventNewRound()
597{
598arrayset(g_used_revive, 0, sizeof(g_used_revive));
599
600g_nade_give_time = 9999999.9;
601}
602
603public EventDeathMsg()
604{
605new killer = read_data(1);
606new victim = read_data(2);
607
608if( (g_first_client <= killer <= g_max_clients) && victim != killer )
609{
610if( IsUserAuthorized(killer) )
611{
612// regular kill
613new xp = get_pcvar_num(cvar_xp_kill);
614
615if( read_data(3) )
616{
617// headshot kill
618xp += get_pcvar_num(cvar_xp_headshot);
619}
620else
621{
622static weapon[20];
623read_data(4, weapon, sizeof(weapon) - 1);
624
625if( contain(weapon, "grenade") >= 0 )
626{
627// grenade kill (or frostnade)
628xp += get_pcvar_num(cvar_xp_grenade);
629}
630}
631
632g_xp[killer] += xp;
633
634Print(killer, "You gained %i XP!", xp);
635
636Save(killer);
637}
638}
639else if( IsUserAuthorized(victim) )
640{
641// victim died of map causes or killed self
642new xp = get_pcvar_num(cvar_xp_suicide);
643
644g_xp[victim] -= xp;
645
646Print(victim, "You lost %i XP!", xp);
647
648Save(victim);
649}
650}
651
652public EventRoundStart()
653{
654g_nade_give_time = get_pcvar_float(cvar_spawn_nade_delay);
655
656set_task(g_nade_give_time, "TaskGiveNades", 1234);
657
658g_nade_give_time += get_gametime();
659}
660
661public EventRoundEnd()
662{
663EventRoundRestart();
664
665new hider, seeker, hider_alive;
666
667for( new i = g_first_client; i <= g_max_clients; i++ )
668{
669if( is_user_connected(i) )
670{
671switch( cs_get_user_team(i) )
672{
673case CS_TEAM_CT:
674{
675if( !seeker )
676{
677seeker = i;
678}
679}
680case CS_TEAM_T:
681{
682if( !hider )
683{
684hider = i;
685
686if( !hider_alive && is_user_alive(i) )
687{
688hider_alive = i;
689}
690}
691}
692}
693
694if( seeker && hider && hider_alive )
695{
696break;
697}
698}
699}
700
701if( !hider || !seeker )
702{
703return;
704}
705
706new CsTeams:winner = CS_TEAM_CT;
707
708if( hider_alive )
709{
710winner = CS_TEAM_T;
711
712new survive = get_pcvar_num(cvar_xp_survive);
713for( new client = g_first_client; client <= g_max_clients; client++ )
714{
715if( IsUserAuthorized(client) && is_user_alive(client) && cs_get_user_team(client) == CS_TEAM_T )
716{
717g_xp[client] += survive;
718Save(client);
719
720Print(client, "You gained %i XP for surviving!", survive);
721}
722}
723}
724
725new win = get_pcvar_num(cvar_xp_win);
726for( new client = g_first_client; client <= g_max_clients; client++ )
727{
728if( IsUserAuthorized(client) && is_user_alive(client) && cs_get_user_team(client) == winner )
729{
730g_xp[client] += win;
731Save(client);
732
733Print(client, "You gained %i XP for winning the round!", win);
734}
735}
736}
737
738public EventRoundRestart()
739{
740remove_task(1234);
741
742g_nade_give_time = 9999999.9;
743}
744
745public FwdPlayerSpawn(client)
746{
747if( is_user_alive(client) )
748{
749new CsTeams:team = cs_get_user_team(client);
750if( team == CS_TEAM_T || team == CS_TEAM_CT )
751{
752if( g_first_time[client] )
753{
754Print(client, "It is your first time playing this HideNSeek XP mod, so you are rewarded with %i XP!", ENTRY_XP);
755Print(client, "You earn XP based upon your gameplay, and you can buy more levels in the menu.");
756Print(client, "Type /xp to view what you can get!");
757
758g_first_time[client] = 0;
759}
760else
761{
762if( g_health_enabled[team] )
763{
764new health = g_health_maxamount[team] * g_health_level[client][team] / g_health_maxlevels[team];
765if( health > 0 )
766{
767set_user_health(client, get_user_health(client) + health);
768}
769}
770
771if( g_armor_enabled[team] )
772{
773new armorvalue = g_armor_maxamount[team] * g_armor_level[client][team] / g_armor_maxlevels[team];
774if( armorvalue == 0 )
775{
776cs_set_user_armor(client, armorvalue, CS_ARMOR_NONE);
777}
778else if( armorvalue < 100 )
779{
780cs_set_user_armor(client, armorvalue, CS_ARMOR_KEVLAR);
781}
782else
783{
784cs_set_user_armor(client, armorvalue, CS_ARMOR_VESTHELM);
785}
786}
787}
788
789if( get_gametime() >= g_nade_give_time )
790{
791GiveNades(client);
792}
793}
794}
795}
796
797public FwdPlayerDeath(client, killer, shouldgib)
798{
799if( !g_used_revive[client] )
800{
801new CsTeams:team = cs_get_user_team(client);
802if( team == CS_TEAM_T || team == CS_TEAM_CT )
803{
804if( g_respawn_enabled[team] )
805{
806new percent = g_respawn_max_chance[team] * g_respawn_level[client][team] / g_respawn_maxlevels[team];
807if( random_num(1, 100) <= percent )
808{
809if( HasTeammateAlive(client, team) )
810{
811set_task(0.5, "TaskRespawn", client);
812
813Print(client, "You have been respawned! (%i%% chance)", percent);
814
815g_used_revive[client] = 1;
816}
817}
818}
819}
820}
821}
822
823public FwdPlayerDamage(client, inflictor, attacker, Float:damage, damagebits)
824{
825if( is_user_alive(client) && (damagebits & DMG_FALL) )
826{
827new CsTeams:team = cs_get_user_team(client);
828if( team == CS_TEAM_T || team == CS_TEAM_CT )
829{
830if( g_nofall_enabled[team] )
831{
832new percent = g_nofall_max_chance[team] * g_nofall_level[client][team] / g_nofall_maxlevels[team];
833SetHamParamFloat(4, damage * (1.0 - (float(percent) / 100.0)));
834}
835}
836}
837}
838
839public TaskRespawn(client)
840{
841ExecuteHamB(Ham_CS_RoundRespawn, client);
842}
843
844public TaskGiveNades()
845{
846for( new client = g_first_client; client <= g_max_clients; client++ )
847{
848if( is_user_alive(client) )
849{
850GiveNades(client);
851}
852}
853}
854
855HasTeammateAlive(client, CsTeams:team)
856{
857for( new i = g_first_client; i <= g_max_clients; i++ )
858{
859if( i == client ) continue;
860
861if( is_user_alive(i) && cs_get_user_team(i) == team )
862{
863return 1;
864}
865}
866
867return 0;
868}
869
870GiveNades(client)
871{
872new CsTeams:team = cs_get_user_team(client);
873
874if( team == CS_TEAM_T )
875{
876static percent;
877for( new i = 0; i < Grenades; i++ )
878{
879if( g_nade_enabled[i] )
880{
881percent = g_nade_max_chance[i] * g_nade_level[client][i] / g_nade_maxlevels[i];
882if( percent > 0 && (percent == 100 || random_num(1, 100) <= percent) )
883{
884give_item(client, g_nade_classnames[i]);
885
886if( percent < 100 )
887{
888Print(client, "You received your %s! (%i%% chance)", g_nade_names[i], percent);
889}
890}
891}
892}
893}
894}
895
896ShowMainMenu(client)
897{
898static title[128];
899formatex(title, sizeof(title) - 1, "[HNS XP by Exolent]^nMain Menu^n^nYour XP: \w%i", g_xp[client]);
900new menu = menu_create(title, "MenuMain");
901
902menu_additem(menu, "\yHelp", "*");
903if( g_any_nade_enabled )
904{
905menu_additem(menu, "Grenades Menu", "1");
906}
907if( g_any_health_enabled )
908{
909menu_additem(menu, "Health Menu", "2");
910}
911if( g_any_armor_enabled )
912{
913menu_additem(menu, "Armor Menu", "3");
914}
915if( g_any_respawn_enabled )
916{
917menu_additem(menu, "Respawn Menu", "4");
918}
919if( g_any_nofall_enabled )
920{
921menu_additem(menu, "Fall Damage Menu^n", "5");
922}
923if( ANY_ABILITY_ENABLED )
924{
925menu_additem(menu, "Player Info", "6");
926}
927
928menu_display(client, menu);
929}
930
931public MenuMain(client, menu, item)
932{
933if( item == MENU_EXIT )
934{
935menu_destroy(menu);
936return;
937}
938
939static _access, info[4], callback;
940menu_item_getinfo(menu, item, _access, info, sizeof(info) - 1, _, _, callback);
941menu_destroy(menu);
942
943switch( info[0] )
944{
945case '*':
946{
947static motd[2500];
948new len = formatex(motd, sizeof(motd) - 1, "<body style=^"background-color:#030303; color:#FF8F00^">");
949len += format(motd[len], sizeof(motd) - len - 1, "<p align=^"center^">");
950len += format(motd[len], sizeof(motd) - len - 1, "HideNSeek XP Mod is an experienced based addon for HideNSeek.<br>");
951len += format(motd[len], sizeof(motd) - len - 1, "Players earn experience points by how well they play the game.<br>");
952len += format(motd[len], sizeof(motd) - len - 1, "<br>");
953len += format(motd[len], sizeof(motd) - len - 1, "<table border=0>");
954len += format(motd[len], sizeof(motd) - len - 1, "<tr><th>Action</th><th>XP</th></tr>");
955len += format(motd[len], sizeof(motd) - len - 1, "<tr><td>Kill</td><td>+%i</td></tr>", get_pcvar_num(cvar_xp_kill));
956len += format(motd[len], sizeof(motd) - len - 1, "<tr><td>Grenade</td><td>+%i</td></tr>", get_pcvar_num(cvar_xp_grenade));
957len += format(motd[len], sizeof(motd) - len - 1, "<tr><td>Headshot</td><td>+%i</td></tr>", get_pcvar_num(cvar_xp_headshot));
958len += format(motd[len], sizeof(motd) - len - 1, "<tr><td>Suicide</td><td>-%i</td></tr>", get_pcvar_num(cvar_xp_suicide));
959len += format(motd[len], sizeof(motd) - len - 1, "<tr><td>Survive as a T</td><td>+%i</td></tr>", get_pcvar_num(cvar_xp_survive));
960len += format(motd[len], sizeof(motd) - len - 1, "<tr><td>Win Round</td><td>+%i</td></tr>", get_pcvar_num(cvar_xp_win));
961len += format(motd[len], sizeof(motd) - len - 1, "</table>");
962len += format(motd[len], sizeof(motd) - len - 1, "With these XP points, you can buy upgrades.<br>");
963len += format(motd[len], sizeof(motd) - len - 1, "For a list of these upgrades, type /xp again and view the other menus inside.");
964len += format(motd[len], sizeof(motd) - len - 1, "</p>");
965len += format(motd[len], sizeof(motd) - len - 1, "</body>");
966
967show_motd(client, motd, "HideNSeek XP Mod Info");
968}
969case '1':
970{
971ShowGrenadesMenu(client);
972}
973case '2':
974{
975ShowHealthMenu(client);
976}
977case '3':
978{
979ShowArmorMenu(client);
980}
981case '4':
982{
983ShowRespawnMenu(client);
984}
985case '5':
986{
987ShowNoFallMenu(client);
988}
989case '6':
990{
991ShowPlayerMenu(client);
992}
993}
994}
995
996ShowGrenadesMenu(client)
997{
998static title[128];
999formatex(title, sizeof(title) - 1, "[HNS XP by Exolent]^nGrenades Menu^n^nNote: \wGrenade abilities are for \rT's Only!\y^n^nYour XP: \w%i", g_xp[client]);
1000new menu = menu_create(title, "MenuGrenades");
1001new callback = menu_makecallback("CallbackGrenades");
1002
1003menu_additem(menu, "\yHelp", "*", _, callback);
1004
1005static level, xp, percent, item[128], info[4];
1006for( new i = 0; i < Grenades; i++ )
1007{
1008if( g_nade_enabled[i] )
1009{
1010level = g_nade_level[client][i] + 1;
1011percent = g_nade_max_chance[i] * level / g_nade_maxlevels[i];
1012
1013if( g_nade_level[client][i] < g_nade_maxlevels[i] )
1014{
1015xp = g_nade_first_xp[i] * (1 << (level - 1));
1016formatex(item, sizeof(item) - 1, "%s: \yLevel %i (%i%%) \r[\w%i XP\r]", g_nade_names[i], level, percent, xp);
1017}
1018else
1019{
1020formatex(item, sizeof(item) - 1, "%s: \yLevel %i (%i%%) \r[\wMaxed Out!\r]", g_nade_names[i], level, percent);
1021}
1022
1023num_to_str(i, info, sizeof(info) - 1);
1024
1025menu_additem(menu, item, info, _, callback);
1026}
1027}
1028
1029menu_display(client, menu);
1030}
1031
1032public MenuGrenades(client, menu, item)
1033{
1034if( item == MENU_EXIT )
1035{
1036menu_destroy(menu);
1037ShowMainMenu(client);
1038return;
1039}
1040
1041static _access, info[4], callback;
1042menu_item_getinfo(menu, item, _access, info, sizeof(info) - 1, _, _, callback);
1043menu_destroy(menu);
1044
1045if( info[0] == '*' )
1046{
1047static motd[2500];
1048new len = formatex(motd, sizeof(motd) - 1, "<body style=^"background-color:#030303; color:#FF8F00^">");
1049len += format(motd[len], sizeof(motd) - len - 1, "<p align=^"center^">");
1050len += format(motd[len], sizeof(motd) - len - 1, "The Grenades ability for the XP Mod is for Terrorists only.<br>");
1051len += format(motd[len], sizeof(motd) - len - 1, "The Grenades ability contains the HE Grenade, 2 Flashbangs, and Frost Nade.<br>");
1052len += format(motd[len], sizeof(motd) - len - 1, "These are the grenades you are given when you receive the your items after the hide timer ends.<br>");
1053len += format(motd[len], sizeof(motd) - len - 1, "<br>");
1054len += format(motd[len], sizeof(motd) - len - 1, "<table>");
1055len += format(motd[len], sizeof(motd) - len - 1, "<tr>");
1056len += format(motd[len], sizeof(motd) - len - 1, "<th></th>");
1057for( new i = 0; i < Grenades; i++ )
1058{
1059if( g_nade_enabled[i] )
1060{
1061len += format(motd[len], sizeof(motd) - len - 1, "<th>%s</th>", g_nade_names[i]);
1062}
1063}
1064len += format(motd[len], sizeof(motd) - len - 1, "</tr>");
1065len += format(motd[len], sizeof(motd) - len - 1, "<tr>");
1066len += format(motd[len], sizeof(motd) - len - 1, "<th>Chance Intervals</th>");
1067for( new i = 0; i < Grenades; i++ )
1068{
1069if( g_nade_enabled[i] )
1070{
1071len += format(motd[len], sizeof(motd) - len - 1, "<td>%i%%</td>", (g_nade_max_chance[i] / g_nade_maxlevels[i]));
1072}
1073}
1074len += format(motd[len], sizeof(motd) - len - 1, "</tr>");
1075len += format(motd[len], sizeof(motd) - len - 1, "<tr>");
1076len += format(motd[len], sizeof(motd) - len - 1, "<th>Max Level</th>");
1077for( new i = 0; i < Grenades; i++ )
1078{
1079if( g_nade_enabled[i] )
1080{
1081len += format(motd[len], sizeof(motd) - len - 1, "<td>%i</td>", g_nade_maxlevels[i]);
1082}
1083}
1084len += format(motd[len], sizeof(motd) - len - 1, "</tr>");
1085len += format(motd[len], sizeof(motd) - len - 1, "<th>Max Chance</th>");
1086for( new i = 0; i < Grenades; i++ )
1087{
1088if( g_nade_enabled[i] )
1089{
1090len += format(motd[len], sizeof(motd) - len - 1, "<td>%i%%</td>", g_nade_max_chance[i]);
1091}
1092}
1093len += format(motd[len], sizeof(motd) - len - 1, "</tr>");
1094len += format(motd[len], sizeof(motd) - len - 1, "</table>");
1095len += format(motd[len], sizeof(motd) - len - 1, "</p>");
1096len += format(motd[len], sizeof(motd) - len - 1, "</body>");
1097
1098show_motd(client, motd, "XP Grenades Info");
1099}
1100else
1101{
1102new upgrade = str_to_num(info);
1103
1104new level = g_nade_level[client][upgrade] + 1;
1105new xp = g_nade_first_xp[upgrade] * (1 << (level - 1));
1106new percent = g_nade_max_chance[upgrade] * level / g_nade_maxlevels[upgrade];
1107
1108g_xp[client] -= xp;
1109g_nade_level[client][upgrade] = level;
1110
1111Save(client);
1112
1113Print(client, "You bought %s Level %i (%i%%) for %i XP!", g_nade_names[upgrade], level, percent, xp);
1114}
1115
1116ShowGrenadesMenu(client);
1117}
1118
1119public CallbackGrenades(client, menu, item)
1120{
1121static _access, info[4], callback;
1122menu_item_getinfo(menu, item, _access, info, sizeof(info) - 1, _, _, callback);
1123
1124if( info[0] == '*' ) return ITEM_ENABLED;
1125
1126new upgrade = str_to_num(info);
1127if( g_nade_level[client][upgrade] == g_nade_maxlevels[upgrade] )
1128{
1129return ITEM_DISABLED;
1130}
1131
1132new xp = g_nade_first_xp[upgrade] * (1 << g_nade_level[client][upgrade]);
1133if( g_xp[client] < xp )
1134{
1135return ITEM_DISABLED;
1136}
1137
1138return ITEM_ENABLED;
1139}
1140
1141ShowHealthMenu(client)
1142{
1143static title[128];
1144formatex(title, sizeof(title) - 1, "[HNS XP by Exolent]^nHealth Menu^n^nYour XP: \w%i", g_xp[client]);
1145new menu = menu_create(title, "MenuHealth");
1146new callback = menu_makecallback("CallbackHealth");
1147
1148menu_additem(menu, "\yHelp", "*", _, callback);
1149
1150static level, xp, amount, item[128], info[4];
1151for( new CsTeams:i = CS_TEAM_T; i <= CS_TEAM_CT; i++ )
1152{
1153if( g_health_enabled[i] )
1154{
1155level = g_health_level[client][i] + 1;
1156amount = g_health_maxamount[i] * level / g_health_maxlevels[i];
1157
1158if( g_health_level[client][i] < g_health_maxlevels[i] )
1159{
1160xp = g_health_first_xp[i] * (1 << (level - 1));
1161formatex(item, sizeof(item) - 1, "%s: \yLevel %i (%i HP) \r[\w%i XP\r]", g_health_names[i], level, amount, xp);
1162}
1163else
1164{
1165formatex(item, sizeof(item) - 1, "\w%s: \yLevel %i (%i HP) \r[\wMaxed Out!\r]", g_health_names[i], level, amount);
1166}
1167
1168num_to_str(_:i, info, sizeof(info) - 1);
1169
1170menu_additem(menu, item, info, _, callback);
1171}
1172}
1173
1174menu_display(client, menu);
1175}
1176
1177public MenuHealth(client, menu, item)
1178{
1179if( item == MENU_EXIT )
1180{
1181menu_destroy(menu);
1182ShowMainMenu(client);
1183return;
1184}
1185
1186static _access, info[4], callback;
1187menu_item_getinfo(menu, item, _access, info, sizeof(info) - 1, _, _, callback);
1188menu_destroy(menu);
1189
1190if( info[0] == '*' )
1191{
1192static motd[2500];
1193new len = formatex(motd, sizeof(motd) - 1, "<body style=^"background-color:#030303; color:#FF8F00^">");
1194len += format(motd[len], sizeof(motd) - len - 1, "<p align=^"center^">");
1195len += format(motd[len], sizeof(motd) - len - 1, "The Health ability is the amount of HP that is added to your spawn health.<br>");
1196len += format(motd[len], sizeof(motd) - len - 1, "<br>");
1197len += format(motd[len], sizeof(motd) - len - 1, "<table>");
1198len += format(motd[len], sizeof(motd) - len - 1, "<tr>");
1199len += format(motd[len], sizeof(motd) - len - 1, "<th></th>");
1200for( new CsTeams:i = CS_TEAM_T; i <= CS_TEAM_CT; i++ )
1201{
1202if( g_health_enabled[i] )
1203{
1204len += format(motd[len], sizeof(motd) - len - 1, "<th>%s</th>",g_team_names[i]);
1205}
1206}
1207len += format(motd[len], sizeof(motd) - len - 1, "</tr>");
1208len += format(motd[len], sizeof(motd) - len - 1, "<tr>");
1209len += format(motd[len], sizeof(motd) - len - 1, "<th>Health Intervals</th>");
1210for( new CsTeams:i = CS_TEAM_T; i <= CS_TEAM_CT; i++ )
1211{
1212if( g_health_enabled[i] )
1213{
1214len += format(motd[len], sizeof(motd) - len - 1, "<td>%i</td>", (g_health_maxamount[i] / g_health_maxlevels[i]));
1215}
1216}
1217len += format(motd[len], sizeof(motd) - len - 1, "</tr>");
1218len += format(motd[len], sizeof(motd) - len - 1, "<tr>");
1219len += format(motd[len], sizeof(motd) - len - 1, "<th>Max Level</th>");
1220for( new CsTeams:i = CS_TEAM_T; i <= CS_TEAM_CT; i++ )
1221{
1222if( g_health_enabled[i] )
1223{
1224len += format(motd[len], sizeof(motd) - len - 1, "<td>%i</td>", g_health_maxlevels[i]);
1225}
1226}
1227len += format(motd[len], sizeof(motd) - len - 1, "</tr>");
1228len += format(motd[len], sizeof(motd) - len - 1, "<th>Max Health</th>");
1229for( new CsTeams:i = CS_TEAM_T; i <= CS_TEAM_CT; i++ )
1230{
1231if( g_health_enabled[i] )
1232{
1233len += format(motd[len], sizeof(motd) - len - 1, "<td>%i</td>", g_health_maxamount[i]);
1234}
1235}
1236len += format(motd[len], sizeof(motd) - len - 1, "</tr>");
1237len += format(motd[len], sizeof(motd) - len - 1, "</table>");
1238len += format(motd[len], sizeof(motd) - len - 1, "</p>");
1239len += format(motd[len], sizeof(motd) - len - 1, "</body>");
1240
1241show_motd(client, motd, "XP Health Info");
1242}
1243else
1244{
1245new CsTeams:upgrade = CsTeams:str_to_num(info);
1246
1247new level = g_health_level[client][upgrade] + 1;
1248new xp = g_health_first_xp[upgrade] * (1 << (level - 1));
1249new amount = g_health_maxamount[upgrade] * level / g_health_maxlevels[upgrade];
1250
1251g_xp[client] -= xp;
1252g_health_level[client][upgrade] = level;
1253
1254Save(client);
1255
1256Print(client, "You bought %s Level %i (%i HP) for %i XP!", g_health_names[upgrade], level, amount, xp);
1257}
1258
1259ShowHealthMenu(client);
1260}
1261
1262public CallbackHealth(client, menu, item)
1263{
1264static _access, info[4], callback;
1265menu_item_getinfo(menu, item, _access, info, sizeof(info) - 1, _, _, callback);
1266
1267if( info[0] == '*' ) return ITEM_ENABLED;
1268
1269new CsTeams:upgrade = CsTeams:str_to_num(info);
1270if( g_health_level[client][upgrade] == g_health_maxlevels[upgrade] )
1271{
1272return ITEM_DISABLED;
1273}
1274
1275new xp = g_health_first_xp[upgrade] * (1 << g_health_level[client][upgrade]);
1276if( g_xp[client] < xp )
1277{
1278return ITEM_DISABLED;
1279}
1280
1281return ITEM_ENABLED;
1282}
1283
1284ShowArmorMenu(client)
1285{
1286static title[128];
1287formatex(title, sizeof(title) - 1, "[HNS XP by Exolent]^nArmor Menu^n^nYour XP: \w%i", g_xp[client]);
1288new menu = menu_create(title, "MenuArmor");
1289new callback = menu_makecallback("CallbackArmor");
1290
1291menu_additem(menu, "\yHelp", "*", _, callback);
1292
1293static level, xp, amount, item[128], info[4];
1294for( new CsTeams:i = CS_TEAM_T; i <= CS_TEAM_CT; i++ )
1295{
1296if( g_armor_enabled[i] )
1297{
1298level = g_armor_level[client][i] + 1;
1299amount = g_armor_maxamount[i] * level / g_armor_maxlevels[i];
1300
1301if( g_armor_level[client][i] < g_armor_maxlevels[i] )
1302{
1303xp = g_armor_first_xp[i] * (1 << (level - 1));
1304formatex(item, sizeof(item) - 1, "%s: \yLevel %i (%i AP) \r[\w%i XP\r]", g_armor_names[i], level, amount, xp);
1305}
1306else
1307{
1308formatex(item, sizeof(item) - 1, "\w%s: \yLevel %i (%i AP) \r[\wMaxed Out!\r]", g_armor_names[i], level, amount);
1309}
1310
1311num_to_str(_:i, info, sizeof(info) - 1);
1312
1313menu_additem(menu, item, info, _, callback);
1314}
1315}
1316
1317menu_display(client, menu);
1318}
1319
1320public MenuArmor(client, menu, item)
1321{
1322if( item == MENU_EXIT )
1323{
1324menu_destroy(menu);
1325ShowMainMenu(client);
1326return;
1327}
1328
1329static _access, info[4], callback;
1330menu_item_getinfo(menu, item, _access, info, sizeof(info) - 1, _, _, callback);
1331menu_destroy(menu);
1332
1333if( info[0] == '*' )
1334{
1335static motd[2500];
1336new len = formatex(motd, sizeof(motd) - 1, "<body style=^"background-color:#030303; color:#FF8F00^">");
1337len += format(motd[len], sizeof(motd) - len - 1, "<p align=^"center^">");
1338len += format(motd[len], sizeof(motd) - len - 1, "The Armor ability is the amount of AP that given to you at spawn.<br>");
1339len += format(motd[len], sizeof(motd) - len - 1, "<br>");
1340len += format(motd[len], sizeof(motd) - len - 1, "<table>");
1341len += format(motd[len], sizeof(motd) - len - 1, "<tr>");
1342len += format(motd[len], sizeof(motd) - len - 1, "<th></th>");
1343for( new CsTeams:i = CS_TEAM_T; i <= CS_TEAM_CT; i++ )
1344{
1345if( g_armor_enabled[i] )
1346{
1347len += format(motd[len], sizeof(motd) - len - 1, "<th>%s</th>",g_team_names[i]);
1348}
1349}
1350len += format(motd[len], sizeof(motd) - len - 1, "</tr>");
1351len += format(motd[len], sizeof(motd) - len - 1, "<tr>");
1352len += format(motd[len], sizeof(motd) - len - 1, "<th>Armor Intervals</th>");
1353for( new CsTeams:i = CS_TEAM_T; i <= CS_TEAM_CT; i++ )
1354{
1355if( g_armor_enabled[i] )
1356{
1357len += format(motd[len], sizeof(motd) - len - 1, "<td>%i</td>", (g_armor_maxamount[i] / g_armor_maxlevels[i]));
1358}
1359}
1360len += format(motd[len], sizeof(motd) - len - 1, "</tr>");
1361len += format(motd[len], sizeof(motd) - len - 1, "<tr>");
1362len += format(motd[len], sizeof(motd) - len - 1, "<th>Max Level</th>");
1363for( new CsTeams:i = CS_TEAM_T; i <= CS_TEAM_CT; i++ )
1364{
1365if( g_armor_enabled[i] )
1366{
1367len += format(motd[len], sizeof(motd) - len - 1, "<td>%i</td>", g_armor_maxlevels[i]);
1368}
1369}
1370len += format(motd[len], sizeof(motd) - len - 1, "</tr>");
1371len += format(motd[len], sizeof(motd) - len - 1, "<th>Max Armor</th>");
1372for( new CsTeams:i = CS_TEAM_T; i <= CS_TEAM_CT; i++ )
1373{
1374if( g_armor_enabled[i] )
1375{
1376len += format(motd[len], sizeof(motd) - len - 1, "<td>%i</td>", g_armor_maxamount[i]);
1377}
1378}
1379len += format(motd[len], sizeof(motd) - len - 1, "</tr>");
1380len += format(motd[len], sizeof(motd) - len - 1, "</table>");
1381len += format(motd[len], sizeof(motd) - len - 1, "</p>");
1382len += format(motd[len], sizeof(motd) - len - 1, "</body>");
1383
1384show_motd(client, motd, "XP Armor Info");
1385}
1386else
1387{
1388new CsTeams:upgrade = CsTeams:str_to_num(info);
1389
1390new level = g_armor_level[client][upgrade] + 1;
1391new xp = g_armor_first_xp[upgrade] * (1 << (level - 1));
1392new amount = g_armor_maxamount[upgrade] * level / g_armor_maxlevels[upgrade];
1393
1394g_xp[client] -= xp;
1395g_armor_level[client][upgrade] = level;
1396
1397Save(client);
1398
1399Print(client, "You bought %s Level %i (%i AP) for %i XP!", g_armor_names[upgrade], level, amount, xp);
1400}
1401
1402ShowArmorMenu(client);
1403}
1404
1405public CallbackArmor(client, menu, item)
1406{
1407static _access, info[4], callback;
1408menu_item_getinfo(menu, item, _access, info, sizeof(info) - 1, _, _, callback);
1409
1410if( info[0] == '*' ) return ITEM_ENABLED;
1411
1412new CsTeams:upgrade = CsTeams:str_to_num(info);
1413if( g_armor_level[client][upgrade] == g_armor_maxlevels[upgrade] )
1414{
1415return ITEM_DISABLED;
1416}
1417
1418new xp = g_armor_first_xp[upgrade] * (1 << g_armor_level[client][upgrade]);
1419if( g_xp[client] < xp )
1420{
1421return ITEM_DISABLED;
1422}
1423
1424return ITEM_ENABLED;
1425}
1426
1427ShowRespawnMenu(client)
1428{
1429static title[128];
1430formatex(title, sizeof(title) - 1, "[HNS XP by Exolent]^nRespawn Menu^n^nYour XP: \w%i", g_xp[client]);
1431new menu = menu_create(title, "MenuRespawn");
1432new callback = menu_makecallback("CallbackRespawn");
1433
1434menu_additem(menu, "\yHelp", "*", _, callback);
1435
1436static level, xp, percent, item[128], info[4];
1437for( new CsTeams:i = CS_TEAM_T; i <= CS_TEAM_CT; i++ )
1438{
1439if( g_respawn_enabled[i] )
1440{
1441level = g_respawn_level[client][i] + 1;
1442percent = g_respawn_max_chance[i] * level / g_respawn_maxlevels[i];
1443
1444if( g_respawn_level[client][i] < g_respawn_maxlevels[i] )
1445{
1446xp = g_respawn_first_xp[i] * (1 << (level - 1));
1447formatex(item, sizeof(item) - 1, "%s: \yLevel %i (%i%%) \r[\w%i XP\r]", g_respawn_names[i], level, percent, xp);
1448}
1449else
1450{
1451formatex(item, sizeof(item) - 1, "%s: \yLevel %i (%i%%) \r[\wMaxed Out!\r]", g_respawn_names[i], level, percent);
1452}
1453
1454num_to_str(_:i, info, sizeof(info) - 1);
1455
1456menu_additem(menu, item, info, _, callback);
1457}
1458}
1459
1460menu_display(client, menu);
1461}
1462
1463public MenuRespawn(client, menu, item)
1464{
1465if( item == MENU_EXIT )
1466{
1467menu_destroy(menu);
1468ShowMainMenu(client);
1469return;
1470}
1471
1472static _access, info[4], callback;
1473menu_item_getinfo(menu, item, _access, info, sizeof(info) - 1, _, _, callback);
1474menu_destroy(menu);
1475
1476if( info[0] == '*' )
1477{
1478static motd[2500];
1479new len = formatex(motd, sizeof(motd) - 1, "<body style=^"background-color:#030303; color:#FF8F00^">");
1480len += format(motd[len], sizeof(motd) - len - 1, "<p align=^"center^">");
1481len += format(motd[len], sizeof(motd) - len - 1, "The Respawn ability is chance to be respawned when you die.<br>");
1482len += format(motd[len], sizeof(motd) - len - 1, "<br>");
1483len += format(motd[len], sizeof(motd) - len - 1, "<table>");
1484len += format(motd[len], sizeof(motd) - len - 1, "<tr>");
1485len += format(motd[len], sizeof(motd) - len - 1, "<th></th>");
1486for( new CsTeams:i = CS_TEAM_T; i <= CS_TEAM_CT; i++ )
1487{
1488if( g_respawn_enabled[i] )
1489{
1490len += format(motd[len], sizeof(motd) - len - 1, "<th>%s</th>",g_team_names[i]);
1491}
1492}
1493len += format(motd[len], sizeof(motd) - len - 1, "</tr>");
1494len += format(motd[len], sizeof(motd) - len - 1, "<tr>");
1495len += format(motd[len], sizeof(motd) - len - 1, "<th>Chance Intervals</th>");
1496for( new CsTeams:i = CS_TEAM_T; i <= CS_TEAM_CT; i++ )
1497{
1498if( g_respawn_enabled[i] )
1499{
1500len += format(motd[len], sizeof(motd) - len - 1, "<td>%i%%</td>", (g_respawn_max_chance[i] / g_respawn_maxlevels[i]));
1501}
1502}
1503len += format(motd[len], sizeof(motd) - len - 1, "</tr>");
1504len += format(motd[len], sizeof(motd) - len - 1, "<tr>");
1505len += format(motd[len], sizeof(motd) - len - 1, "<th>Max Level</th>");
1506for( new CsTeams:i = CS_TEAM_T; i <= CS_TEAM_CT; i++ )
1507{
1508if( g_respawn_enabled[i] )
1509{
1510len += format(motd[len], sizeof(motd) - len - 1, "<td>%i</td>", g_respawn_maxlevels[i]);
1511}
1512}
1513len += format(motd[len], sizeof(motd) - len - 1, "</tr>");
1514len += format(motd[len], sizeof(motd) - len - 1, "<th>Max Chance</th>");
1515for( new CsTeams:i = CS_TEAM_T; i <= CS_TEAM_CT; i++ )
1516{
1517if( g_respawn_enabled[i] )
1518{
1519len += format(motd[len], sizeof(motd) - len - 1, "<td>%i%%</td>", g_respawn_max_chance[i]);
1520}
1521}
1522len += format(motd[len], sizeof(motd) - len - 1, "</tr>");
1523len += format(motd[len], sizeof(motd) - len - 1, "</table>");
1524len += format(motd[len], sizeof(motd) - len - 1, "</p>");
1525len += format(motd[len], sizeof(motd) - len - 1, "</body>");
1526
1527show_motd(client, motd, "XP Respawn Info");
1528}
1529else
1530{
1531new CsTeams:upgrade = CsTeams:str_to_num(info);
1532
1533new level = g_respawn_level[client][upgrade] + 1;
1534new xp = g_respawn_first_xp[upgrade] * (1 << (level - 1));
1535new percent = g_respawn_max_chance[upgrade] * level / g_respawn_maxlevels[upgrade];
1536
1537g_xp[client] -= xp;
1538g_respawn_level[client][upgrade] = level;
1539
1540Save(client);
1541
1542Print(client, "You bought %s Level %i (%i%%) for %i XP!", g_respawn_names[upgrade], level, percent, xp);
1543}
1544
1545ShowRespawnMenu(client);
1546}
1547
1548public CallbackRespawn(client, menu, item)
1549{
1550static _access, info[4], callback;
1551menu_item_getinfo(menu, item, _access, info, sizeof(info) - 1, _, _, callback);
1552
1553if( info[0] == '*' ) return ITEM_ENABLED;
1554
1555new CsTeams:upgrade = CsTeams:str_to_num(info);
1556if( g_respawn_level[client][upgrade] == g_respawn_maxlevels[upgrade] )
1557{
1558return ITEM_DISABLED;
1559}
1560
1561new xp = g_respawn_first_xp[upgrade] * (1 << g_respawn_level[client][upgrade]);
1562if( g_xp[client] < xp || g_respawn_level[client][upgrade] == g_respawn_maxlevels[upgrade] )
1563{
1564return ITEM_DISABLED;
1565}
1566
1567return ITEM_ENABLED;
1568}
1569
1570ShowNoFallMenu(client)
1571{
1572static title[128];
1573formatex(title, sizeof(title) - 1, "[HNS XP by Exolent]^nFall Damage Menu^n^nYour XP: \w%i", g_xp[client]);
1574new menu = menu_create(title, "MenuNoFall");
1575new callback = menu_makecallback("CallbackNoFall");
1576
1577menu_additem(menu, "\yHelp", "*", _, callback);
1578
1579static level, xp, percent, item[128], info[4];
1580for( new CsTeams:i = CS_TEAM_T; i <= CS_TEAM_CT; i++ )
1581{
1582if( g_nofall_enabled[i] )
1583{
1584level = g_nofall_level[client][i] + 1;
1585percent = g_nofall_max_chance[i] * level / g_nofall_maxlevels[i];
1586
1587if( g_nofall_level[client][i] < g_nofall_maxlevels[i] )
1588{
1589xp = g_nofall_first_xp[i] * (1 << (level - 1));
1590formatex(item, sizeof(item) - 1, "%s: \yLevel %i (%i%%) \r[\w%i XP\r]", g_nofall_names[i], level, percent, xp);
1591}
1592else
1593{
1594formatex(item, sizeof(item) - 1, "%s: \yLevel %i (%i%%) \r[\wMaxed Out!\r]", g_nofall_names[i], level, percent);
1595}
1596
1597num_to_str(_:i, info, sizeof(info) - 1);
1598
1599menu_additem(menu, item, info, _, callback);
1600}
1601}
1602
1603menu_display(client, menu);
1604}
1605
1606public MenuNoFall(client, menu, item)
1607{
1608if( item == MENU_EXIT )
1609{
1610menu_destroy(menu);
1611ShowMainMenu(client);
1612return;
1613}
1614
1615static _access, info[4], callback;
1616menu_item_getinfo(menu, item, _access, info, sizeof(info) - 1, _, _, callback);
1617menu_destroy(menu);
1618
1619if( info[0] == '*' )
1620{
1621static motd[2500];
1622new len = formatex(motd, sizeof(motd) - 1, "<body style=^"background-color:#030303; color:#FF8F00^">");
1623len += format(motd[len], sizeof(motd) - len - 1, "<p align=^"center^">");
1624len += format(motd[len], sizeof(motd) - len - 1, "The Fall Damage ability reduces the amount of damage inflicted from falling.<br>");
1625len += format(motd[len], sizeof(motd) - len - 1, "<br>");
1626len += format(motd[len], sizeof(motd) - len - 1, "<table>");
1627len += format(motd[len], sizeof(motd) - len - 1, "<tr>");
1628len += format(motd[len], sizeof(motd) - len - 1, "<th></th>");
1629for( new CsTeams:i = CS_TEAM_T; i <= CS_TEAM_CT; i++ )
1630{
1631if( g_nofall_enabled[i] )
1632{
1633len += format(motd[len], sizeof(motd) - len - 1, "<th>%s</th>",g_team_names[i]);
1634}
1635}
1636len += format(motd[len], sizeof(motd) - len - 1, "</tr>");
1637len += format(motd[len], sizeof(motd) - len - 1, "<tr>");
1638len += format(motd[len], sizeof(motd) - len - 1, "<th>Reduction Intervals</th>");
1639for( new CsTeams:i = CS_TEAM_T; i <= CS_TEAM_CT; i++ )
1640{
1641if( g_nofall_enabled[i] )
1642{
1643len += format(motd[len], sizeof(motd) - len - 1, "<td>%i%%</td>", (g_nofall_max_chance[i] / g_nofall_maxlevels[i]));
1644}
1645}
1646len += format(motd[len], sizeof(motd) - len - 1, "</tr>");
1647len += format(motd[len], sizeof(motd) - len - 1, "<tr>");
1648len += format(motd[len], sizeof(motd) - len - 1, "<th>Max Level</th>");
1649for( new CsTeams:i = CS_TEAM_T; i <= CS_TEAM_CT; i++ )
1650{
1651if( g_nofall_enabled[i] )
1652{
1653len += format(motd[len], sizeof(motd) - len - 1, "<td>%i</td>", g_nofall_maxlevels[i]);
1654}
1655}
1656len += format(motd[len], sizeof(motd) - len - 1, "</tr>");
1657len += format(motd[len], sizeof(motd) - len - 1, "<th>Max Chance</th>");
1658for( new CsTeams:i = CS_TEAM_T; i <= CS_TEAM_CT; i++ )
1659{
1660if( g_nofall_enabled[i] )
1661{
1662len += format(motd[len], sizeof(motd) - len - 1, "<td>%i%%</td>", g_nofall_max_chance[i]);
1663}
1664}
1665len += format(motd[len], sizeof(motd) - len - 1, "</tr>");
1666len += format(motd[len], sizeof(motd) - len - 1, "</table>");
1667len += format(motd[len], sizeof(motd) - len - 1, "</p>");
1668len += format(motd[len], sizeof(motd) - len - 1, "</body>");
1669
1670show_motd(client, motd, "XP Fall Damage Info");
1671}
1672else
1673{
1674new CsTeams:upgrade = CsTeams:str_to_num(info);
1675
1676new level = g_nofall_level[client][upgrade] + 1;
1677new xp = g_nofall_first_xp[upgrade] * (1 << (level - 1));
1678new percent = g_nofall_max_chance[upgrade] * level / g_nofall_maxlevels[upgrade];
1679
1680g_xp[client] -= xp;
1681g_nofall_level[client][upgrade] = level;
1682
1683Save(client);
1684
1685Print(client, "You bought %s Level %i (%i%%) for %i XP!", g_nofall_names[upgrade], level, percent, xp);
1686}
1687
1688ShowNoFallMenu(client);
1689}
1690
1691public CallbackNoFall(client, menu, item)
1692{
1693static _access, info[4], callback;
1694menu_item_getinfo(menu, item, _access, info, sizeof(info) - 1, _, _, callback);
1695
1696if( info[0] == '*' ) return ITEM_ENABLED;
1697
1698new CsTeams:upgrade = CsTeams:str_to_num(info);
1699if( g_nofall_level[client][upgrade] == g_nofall_maxlevels[upgrade] )
1700{
1701return ITEM_DISABLED;
1702}
1703
1704new xp = g_nofall_first_xp[upgrade] * (1 << g_nofall_level[client][upgrade]);
1705if( g_xp[client] < xp || g_nofall_level[client][upgrade] == g_nofall_maxlevels[upgrade] )
1706{
1707return ITEM_DISABLED;
1708}
1709
1710return ITEM_ENABLED;
1711}
1712
1713ShowPlayerMenu(client)
1714{
1715new menu = menu_create("Player Info Menu", "MenuPlayer");
1716
1717new name[32], authid[35];
1718for( new i = 1; i <= g_max_clients; i++ )
1719{
1720if( !is_user_connected(i) ) continue;
1721
1722get_user_name(i, name, sizeof(name) - 1);
1723get_user_authid(i, authid, sizeof(authid) - 1);
1724
1725menu_additem(menu, name, authid);
1726}
1727
1728menu_display(client, menu);
1729}
1730
1731public MenuPlayer(client, menu, item)
1732{
1733if( item == MENU_EXIT )
1734{
1735menu_destroy(menu);
1736ShowMainMenu(client);
1737return;
1738}
1739
1740static _access, authid[35], callback;
1741menu_item_getinfo(menu, item, _access, authid, sizeof(authid) - 1, _, _, callback);
1742menu_destroy(menu);
1743
1744new player = find_player("c", authid);
1745if( !is_user_connected(player) )
1746{
1747ShowMainMenu(client);
1748return;
1749}
1750
1751new name[32];
1752get_user_name(player, name, sizeof(name) - 1);
1753
1754static motd[2500];
1755new len = copy(motd, sizeof(motd) - 1, "<html>");
1756len += format(motd[len], sizeof(motd) - len - 1, "<b><font size=^"4^">Name:</font></b> %s<br><br>", name);
1757len += format(motd[len], sizeof(motd) - len - 1, "<b><font size=^"4^">XP:</font></b> %i<br><br>", g_xp[player]);
1758if( g_any_nade_enabled )
1759{
1760len += format(motd[len], sizeof(motd) - len - 1, "<b><font size=^"4^">Grenades Levels:</font></b><br>");
1761for( new i = 0; i < Grenades; i++ )
1762{
1763if( g_nade_enabled[i] )
1764{
1765len += format(motd[len], sizeof(motd) - len - 1, "<b>%s:</b> %i/%i<br>", g_nade_names[i], g_nade_level[player][i], g_nade_maxlevels[i]);
1766}
1767}
1768}
1769if( g_any_health_enabled )
1770{
1771len += format(motd[len], sizeof(motd) - len - 1, "<br><b><font size=^"4^">Health Levels:</font></b><br>");
1772for( new CsTeams:i = CS_TEAM_T; i <= CS_TEAM_CT; i++ )
1773{
1774if( g_health_enabled[i] )
1775{
1776len += format(motd[len], sizeof(motd) - len - 1, "<b>%s:</b> %i/%i (%i/%i HP)<br>",\
1777g_health_names[i], g_health_level[player][i], g_health_maxlevels[i],\
1778(g_health_maxamount[i] * g_health_level[player][i] / g_health_maxlevels[i]), g_health_maxamount[i]);
1779}
1780}
1781}
1782if( g_any_armor_enabled )
1783{
1784len += format(motd[len], sizeof(motd) - len - 1, "<br><b><font size=^"4^">Armor Levels:</font></b><br>");
1785for( new CsTeams:i = CS_TEAM_T; i <= CS_TEAM_CT; i++ )
1786{
1787if( g_armor_enabled[i] )
1788{
1789len += format(motd[len], sizeof(motd) - len - 1, "<b>%s:</b> %i/%i (%i/%i AP)<br>",\
1790g_armor_names[i], g_armor_level[player][i], g_armor_maxlevels[i],\
1791(g_armor_maxamount[i] * g_armor_level[player][i] / g_armor_maxlevels[i]), g_armor_maxamount[i]);
1792}
1793}
1794}
1795if( g_any_respawn_enabled )
1796{
1797len += format(motd[len], sizeof(motd) - len - 1, "<br><b><font size=^"4^">Respawn Levels:</font></b><br>");
1798for( new CsTeams:i = CS_TEAM_T; i <= CS_TEAM_CT; i++ )
1799{
1800if( g_respawn_enabled[i] )
1801{
1802len += format(motd[len], sizeof(motd) - len - 1, "<b>%s:</b> %i/%i (%i/%i %%)<br>",\
1803g_respawn_names[i], g_respawn_level[player][i], g_respawn_maxlevels[i],\
1804(g_respawn_max_chance[i] * g_respawn_level[player][i] / g_respawn_maxlevels[i]), g_respawn_max_chance[i]);
1805}
1806}
1807}
1808if( g_any_nofall_enabled )
1809{
1810len += format(motd[len], sizeof(motd) - len - 1, "<br><b><font size=^"4^">Fall Damage Levels:</font></b><br>");
1811for( new CsTeams:i = CS_TEAM_T; i <= CS_TEAM_CT; i++ )
1812{
1813if( g_nofall_enabled[i] )
1814{
1815len += format(motd[len], sizeof(motd) - len - 1, "<b>%s:</b> %i/%i (%i/%i %%)<br>",\
1816g_nofall_names[i], g_nofall_level[player][i], g_nofall_maxlevels[i],\
1817(g_nofall_max_chance[i] * g_nofall_level[player][i] / g_nofall_maxlevels[i]), g_nofall_max_chance[i]);
1818}
1819}
1820}
1821len += format(motd[len], sizeof(motd) - len - 1, "</html>");
1822
1823show_motd(client, motd, "HNS XP Mod Info");
1824
1825ShowPlayerMenu(client);
1826}
1827
1828IsValidAuthid(authid[])
1829{
1830return (regex_match_c(authid, g_SteamID_pattern, g_regex_return) > 0);
1831}
1832
1833IsUserAuthorized(client)
1834{
1835return g_authid[client][0] != 0;
1836}
1837
1838Print(client, const msg_fmt[], any:...)
1839{
1840static message[192];
1841new len = formatex(message, sizeof(message) - 1, "%s^x03 ", MESSAGE_TAG);
1842vformat(message[len], sizeof(message) - len - 1, msg_fmt, 3);
1843
1844if( client )
1845{
1846message_begin(MSG_ONE_UNRELIABLE, g_msgid_SayText, _, client);
1847write_byte(client);
1848write_string(message);
1849message_end();
1850}
1851else
1852{
1853for( new i = g_first_client; i <= g_max_clients; i++ )
1854{
1855if( is_user_connected(i) )
1856{
1857message_begin(MSG_ONE_UNRELIABLE, g_msgid_SayText, _, i);
1858write_byte(i);
1859write_string(message);
1860message_end();
1861}
1862}
1863}
1864}
1865
1866Load(client)
1867{
1868#if defined USING_SQL
1869static query[128];
1870formatex(query, sizeof(query) - 1, "SELECT `data` FROM `hns_xp` WHERE `authid` = '%s';", g_authid[client]);
1871
1872static data[2];
1873data[0] = client;
1874
1875SQL_ThreadQuery(g_sql_tuple, "QueryLoadData", query, data, sizeof(data));
1876#else
1877static data[256], timestamp;
1878if( nvault_lookup(g_vault, g_authid[client], data, sizeof(data) - 1, timestamp) )
1879{
1880ParseLoadData(client, data);
1881return;
1882}
1883else
1884{
1885NewUser(client);
1886}
1887#endif
1888}
1889
1890#if defined USING_SQL
1891public QueryLoadData(failstate, Handle:query, error[], errnum, data[], size, Float:queuetime)
1892{
1893if( failstate == TQUERY_CONNECT_FAILED
1894|| failstate == TQUERY_QUERY_FAILED )
1895{
1896set_fail_state(error);
1897}
1898else
1899{
1900if( SQL_NumResults(query) )
1901{
1902static sqldata[256];
1903SQL_ReadResult(query, 0, sqldata, sizeof(sqldata) - 1);
1904ParseLoadData(data[0], sqldata);
1905}
1906else
1907{
1908NewUser(data[0]);
1909}
1910}
1911}
1912#endif
1913
1914ParseLoadData(client, data[256])
1915{
1916static num[6];
1917strbreak(data, num, sizeof(num) - 1, data, sizeof(data) - 1);
1918
1919g_xp[client] = str_to_num(num);
1920
1921for( new i = 0; i < Grenades; i++ )
1922{
1923strbreak(data, num, sizeof(num) - 1, data, sizeof(data) - 1);
1924g_nade_level[client][i] = clamp(str_to_num(num), 0, g_nade_maxlevels[i]);
1925}
1926
1927for( new CsTeams:i = CS_TEAM_T; i <= CS_TEAM_CT; i++ )
1928{
1929strbreak(data, num, sizeof(num) - 1, data, sizeof(data) - 1);
1930g_armor_level[client][i] = clamp(str_to_num(num), 0, g_armor_maxlevels[i]);
1931}
1932
1933for( new CsTeams:i = CS_TEAM_T; i <= CS_TEAM_CT; i++ )
1934{
1935strbreak(data, num, sizeof(num) - 1, data, sizeof(data) - 1);
1936g_respawn_level[client][i] = clamp(str_to_num(num), 0, g_respawn_maxlevels[i]);
1937}
1938
1939for( new CsTeams:i = CS_TEAM_T; i <= CS_TEAM_CT; i++ )
1940{
1941strbreak(data, num, sizeof(num) - 1, data, sizeof(data) - 1);
1942g_health_level[client][i] = clamp(str_to_num(num), 0, g_health_maxlevels[i]);
1943}
1944
1945for( new CsTeams:i = CS_TEAM_T; i <= CS_TEAM_CT; i++ )
1946{
1947strbreak(data, num, sizeof(num) - 1, data, sizeof(data) - 1);
1948g_nofall_level[client][i] = clamp(str_to_num(num), 0, g_nofall_maxlevels[i]);
1949}
1950
1951#if defined USING_SQL
1952g_loaded_data[client] = 1;
1953#endif
1954}
1955
1956NewUser(client)
1957{
1958g_first_time[client] = 1;
1959
1960g_xp[client] = ENTRY_XP;
1961arrayset(g_nade_level[client], 0, sizeof(g_nade_level[]));
1962for( new CsTeams:i = CS_TEAM_T; i <= CS_TEAM_CT; i++ )
1963{
1964g_armor_level[client][i] = 0;
1965g_respawn_level[client][i] = 0;
1966g_health_level[client][i] = 0;
1967g_nofall_level[client][i] = 0;
1968}
1969}
1970
1971Save(client)
1972{
1973if( !IsUserAuthorized(client) ) return;
1974
1975static data[256];
1976new len = formatex(data, sizeof(data) - 1, "%i", g_xp[client]);
1977
1978for( new i = 0; i < Grenades; i++ )
1979{
1980len += formatex(data[len], sizeof(data) - len - 1, " %i", g_nade_level[client][i]);
1981}
1982
1983for( new CsTeams:i = CS_TEAM_T; i <= CS_TEAM_CT; i++ )
1984{
1985len += formatex(data[len], sizeof(data) - len - 1, " %i", g_armor_level[client][i]);
1986}
1987
1988for( new CsTeams:i = CS_TEAM_T; i <= CS_TEAM_CT; i++ )
1989{
1990len += formatex(data[len], sizeof(data) - len - 1, " %i", g_respawn_level[client][i]);
1991}
1992
1993for( new CsTeams:i = CS_TEAM_T; i <= CS_TEAM_CT; i++ )
1994{
1995len += formatex(data[len], sizeof(data) - len - 1, " %i", g_health_level[client][i]);
1996}
1997
1998for( new CsTeams:i = CS_TEAM_T; i <= CS_TEAM_CT; i++ )
1999{
2000len += formatex(data[len], sizeof(data) - len - 1, " %i", g_nofall_level[client][i]);
2001}
2002
2003#if defined USING_SQL
2004static name[32];
2005get_user_name(client, name, sizeof(name) - 1);
2006
2007static query[512];
2008if( g_loaded_data[client] )
2009{
2010formatex(query, sizeof(query) - 1, "UPDATE `hns_xp` SET `name` = '%s', `data` = '%s' WHERE `authid` = '%s';", name, data, g_authid[client]);
2011}
2012else
2013{
2014formatex(query, sizeof(query) - 1, "INSERT INTO `hns_xp` ( `name`, `authid`, `data` ) VALUES ( '%s', '%s', '%s' );", name, g_authid[client], data);
2015}
2016
2017SQL_ThreadQuery(g_sql_tuple, "QuerySaveData", query);
2018#else
2019nvault_set(g_vault, g_authid[client], data);
2020#endif
2021}
2022
2023#if defined USING_SQL
2024public QuerySaveData(failstate, Handle:query, error[], errnum, data[], size, Float:queuetime)
2025{
2026if( failstate == TQUERY_CONNECT_FAILED
2027|| failstate == TQUERY_QUERY_FAILED )
2028{
2029set_fail_state(error);
2030}
2031}
2032#endif
2033/* AMXX-Studio Notes - DO NOT MODIFY BELOW HERE
2034*{\\ rtf1\\ ansi\\ deff0{\\ fonttbl{\\ f0\\ fnil Tahoma;}}\n\\ viewkind4\\ uc1\\ pard\\ lang11274\\ f0\\ fs16 \n\\ par }
2035*/