/*
Weapon Progression System + Puzzle Drop
CS 1.6 – AMXX
Funkciók:
- Fegyverenként külön kill számláló
- Szintek: 1–5
L2: 100 kill
L3: 500 kill
L4: 1000 kill
L5: 2000 kill
- Szint bónuszok:
L2: +5 HP kill után, HUD aktiv
L3: +5% coin bónusz, kill chat effekt, fegyver név kiemelve
L4: Speciális kill effekt (képernyő villanás / glow), +10% XP
L5: Arany aura (glow), +15% XP, "Weapon Master" jelvény, globális üzenet
- Weapon XP progress bar HUD-on
- Puzzle drop rendszer:
- 0.08% esély killenként
- 6 puzzle = craft skin
- Global üzenet craftnál
- nVault mentés
Ötlet: fórum leírás alapján!
*/
#include <amxmodx>
#include <fakemeta>
#include <hamsandwich>
#include <nvault>
#include <cstrike>
#include <fun>
#define PLUGIN "Weapon Progression System"
#define VERSION "1.0"
#define AUTHOR "Csabika20034"
#define MAX_PLAYERS 32
#define MAX_WEAPONS 32
// Puzzle drop esély (0.08% = 8 / 10000)
#define PUZZLE_CHANCE_NUM 8
#define PUZZLE_CHANCE_DEN 10000
// Puzzle darabok száma a craft-hoz
#define PUZZLE_PIECES_NEED 6
// Szint küszöbök
#define LEVEL2_KILLS 100
#define LEVEL3_KILLS 500
#define LEVEL4_KILLS 1000
#define LEVEL5_KILLS 2000
// Glow színek
#define GLOW_LEGENDARY_R 255
#define GLOW_LEGENDARY_G 215
#define GLOW_LEGENDARY_B 0
new g_vault;
// Per-player, per-weapon kill count
new g_weaponKills[MAX_PLAYERS + 1][MAX_WEAPONS];
// Per-player, per-weapon level
new g_weaponLevel[MAX_PLAYERS + 1][MAX_WEAPONS];
// Puzzle darabok fegyverenként (egyszerűsítve: csak AK47-re mutatok példát, de struktúra általános)
new g_puzzlePieces[MAX_PLAYERS + 1][MAX_WEAPONS];
// HUD sync
new g_hudSync;
// Cvarok
new cvar_puzzle_enable;
new cvar_debug;
// Helper: weapon index mapping (CSW_*)
new const g_weaponNames[MAX_WEAPONS][] = {
"", // 0
"p228", // 1 = CSW_P228
"", // 2
"scout", // 3
"hegrenade",// 4
"xm1014", // 5
"", // 6
"mac10", // 7
"aug", // 8
"", // 9
"elite", // 10
"fiveseven",// 11
"ump45", // 12
"sg550", // 13
"galil", // 14
"famas", // 15
"usp", // 16
"glock18", // 17
"awp", // 18
"mp5navy", // 19
"m249", // 20
"m3", // 21
"m4a1", // 22
"tmp", // 23
"g3sg1", // 24
"", // 25
"deagle", // 26
"sg552", // 27
"ak47", // 28
"knife", // 29
"p90" // 30
// 31, 32 nem kell
};
public plugin_init()
{
register_plugin(PLUGIN, VERSION, AUTHOR);
RegisterHam(Ham_Killed, "player", "fw_PlayerKilled", 1);
register_event("HLTV", "event_NewRound", "a", "1=0", "2=0");
g_hudSync = CreateHudSyncObj();
cvar_puzzle_enable = register_cvar("wp_puzzle_enable", "1");
cvar_debug = register_cvar("wp_debug", "0");
g_vault = nvault_open("weapon_progression");
if (g_vault == INVALID_HANDLE)
{
log_amx("[WP] nVault open failed!");
}
register_clcmd("say /wp", "cmd_ShowWeaponInfo");
register_clcmd("say_team /wp", "cmd_ShowWeaponInfo");
register_clcmd("say /prestige", "cmd_PrestigeReset");
}
public plugin_end()
{
if (g_vault != INVALID_HANDLE)
nvault_close(g_vault);
}
public client_authorized(id)
{
load_player_data(id);
}
public client_disconnect(id)
{
save_player_data(id);
}
// Új kör: friss HUD
public event_NewRound()
{
for (new id = 1; id <= MAX_PLAYERS; id++)
{
if (is_user_connected(id))
{
show_weapon_hud(id);
}
}
}
// Kill event
public fw_PlayerKilled(victim, attacker, shouldgib)
{
if (!is_user_connected(attacker) || attacker == victim)
return HAM_IGNORED;
if (!is_user_alive(attacker))
return HAM_IGNORED;
new weapon = get_user_weapon(attacker);
if (weapon <= 0 || weapon >= MAX_WEAPONS)
return HAM_IGNORED;
// Kill számláló növelése
g_weaponKills[attacker][weapon]++;
// Szint ellenőrzés
check_level_up(attacker, weapon);
// Szint bónuszok alkalmazása
apply_kill_bonuses(attacker, weapon);
// Puzzle drop
if (get_pcvar_num(cvar_puzzle_enable))
{
try_puzzle_drop(attacker, weapon);
}
// HUD frissítés
show_weapon_hud(attacker);
return HAM_IGNORED;
}
// Szint meghatározása kill alapján
stock get_level_from_kills(kills)
{
if (kills >= LEVEL5_KILLS) return 5;
if (kills >= LEVEL4_KILLS) return 4;
if (kills >= LEVEL3_KILLS) return 3;
if (kills >= LEVEL2_KILLS) return 2;
return 1;
}
// Szintlépés ellenőrzés
stock check_level_up(id, weapon)
{
new oldLevel = g_weaponLevel[id][weapon];
new newLevel = get_level_from_kills(g_weaponKills[id][weapon]);
if (newLevel > oldLevel)
{
g_weaponLevel[id][weapon] = newLevel;
new name[32];
get_user_name(id, name, charsmax(name));
new wname[32];
get_weapon_name_by_csw(weapon, wname, charsmax(wname));
// Szintlépés üzenet
client_print_color(0, print_chat, "^4[WP]^1 %s fegyvere (^3%s^1) elérte a ^3%d. szintet!", name, wname, newLevel);
// Legendary szint globális üzenet
if (newLevel == 5)
{
client_print_color(0, print_chat, "^4[WP]^1 %s elérte a ^3LEGENDARY^1 szintet a ^3%s^1 fegyverrel! ^4[Weapon Master]", name, wname);
}
}
}
// Kill bónuszok alkalmazása szint alapján
stock apply_kill_bonuses(id, weapon)
{
new level = g_weaponLevel[id][weapon];
// LEVEL 2 – Trained (100 ölés)
// • +5 HP minden ölés után
if (level >= 2)
{
new hp = get_user_health(id);
set_user_health(id, hp + 5);
}
// LEVEL 3 – Elite (500 ölés)
// • +5% coin bónusz ölésenként
// • Kill chat effekt
// • Fegyver név kiemelve
if (level >= 3)
{
new name[32];
get_user_name(id, name, charsmax(name));
new wname[32];
get_weapon_name_by_csw(weapon, wname, charsmax(wname));
client_print_color(0, print_chat, "^4[WP]^1 Elite kill: ^3%s^1 - ^4%s", name, wname);
// Itt tudod hívni a saját coin rendszeredet, pl:
// wp_add_coins(id, damage * 0.05);
}
// LEVEL 4 – Master (1000 ölés)
// • Speciális kill effekt (villanás / glow)
// • +10% XP bónusz
if (level >= 4)
{
// Képernyő villanás
screen_fade(id, 50, 50, 50, 0, 0, 255, 100);
// Itt tudod hívni az XP rendszeredet, pl:
// wp_add_xp(id, base_xp * 0.10);
}
// LEVEL 5 – Legendary (2000 ölés)
// • Arany aura effekt
// • +15% XP bónusz
// • "Weapon Master" jelvény
// • Globális üzenet eléréskor (szintlépésnél már küldtük)
if (level >= 5)
{
// Arany glow
set_user_rendering(id, kRenderFxGlowShell, GLOW_LEGENDARY_R, GLOW_LEGENDARY_G, GLOW_LEGENDARY_B, kRenderNormal, 16);
// Itt plusz XP:
// wp_add_xp(id, base_xp * 0.15);
}
}
// HUD megjelenítés: Weapon XP Progress Bar + szint
stock show_weapon_hud(id)
{
if (!is_user_connected(id))
return;
new weapon = get_user_weapon(id);
if (weapon <= 0 || weapon >= MAX_WEAPONS)
return;
new kills = g_weaponKills[id][weapon];
new level = g_weaponLevel[id][weapon];
new nextLevelKills;
switch (level)
{
case 1: nextLevelKills = LEVEL2_KILLS;
case 2: nextLevelKills = LEVEL3_KILLS;
case 3: nextLevelKills = LEVEL4_KILLS;
case 4: nextLevelKills = LEVEL5_KILLS;
default: nextLevelKills = LEVEL5_KILLS;
}
new currentLevelBaseKills;
switch (level)
{
case 1: currentLevelBaseKills = 0;
case 2: currentLevelBaseKills = LEVEL2_KILLS;
case 3: currentLevelBaseKills = LEVEL3_KILLS;
case 4: currentLevelBaseKills = LEVEL4_KILLS;
case 5: currentLevelBaseKills = LEVEL5_KILLS;
}
new diff = nextLevelKills - currentLevelBaseKills;
new progress = kills - currentLevelBaseKills;
if (progress < 0) progress = 0;
if (progress > diff) progress = diff;
new Float:percent = diff > 0 ? float(progress) / float(diff) : 1.0;
new bar[32];
make_progress_bar(percent, bar, charsmax(bar));
new wname[32];
get_weapon_name_by_csw(weapon, wname, charsmax(wname));
set_hudmessage(0, 255, 0, 0.02, 0.20, 0, 0.0, 1.0, 0.0, 0.0, -1);
ShowSyncHudMsg(id, g_hudSync, "Fegyver: %s^nSzint: %d^nXP: %d / %d^n%s",
wname, level, kills, nextLevelKills, bar);
}
// Progress bar generálása
stock make_progress_bar(Float:percent, bar[], len)
{
new total = 20;
new filled = floatround(percent * total);
if (filled > total) filled = total;
if (filled < 0) filled = 0;
new i;
new pos = 0;
bar[pos++] = '[';
for (i = 0; i < total; i++)
{
if (i < filled)
bar[pos++] = '#';
else
bar[pos++] = '-';
}
bar[pos++] = ']';
bar[pos] = 0;
}
// Puzzle drop rendszer
stock try_puzzle_drop(id, weapon)
{
// Példa: csak AK47-re legyen puzzle (CSW_AK47 = 28)
if (weapon != CSW_AK47)
return;
new r = random_num(1, PUZZLE_CHANCE_DEN);
if (r <= PUZZLE_CHANCE_NUM)
{
g_puzzlePieces[id][weapon]++;
new name[32];
get_user_name(id, name, charsmax(name));
client_print_color(id, print_chat, "^4[WP]^1 Szerencsés vagy! Szereztél egy ^3AK47 Puzzle^1 darabot. (^3%d/%d^1)",
g_puzzlePieces[id][weapon], PUZZLE_PIECES_NEED);
if (get_pcvar_num(cvar_debug))
{
log_amx("[WP] Puzzle drop: id=%d weapon=%d pieces=%d", id, weapon, g_puzzlePieces[id][weapon]);
}
if (g_puzzlePieces[id][weapon] >= PUZZLE_PIECES_NEED)
{
g_puzzlePieces[id][weapon] -= PUZZLE_PIECES_NEED;
// Itt adhatod a skint, vagy hívhatsz másik plugint
// pl: wp_give_skin(id, "ak47_rare_skin");
new wname[32];
get_weapon_name_by_csw(weapon, wname, charsmax(wname));
client_print_color(0, print_chat, "^4[WP]^1 %s összegyűjtött ^3%d^1 darab ^3%s Puzzle^1-t és kraftolt egy skint!",
name, PUZZLE_PIECES_NEED, wname);
}
}
}
// Prestige reset – minden fegyver reset
public cmd_PrestigeReset(id)
{
if (!is_user_connected(id))
return PLUGIN_HANDLED;
// Egyszerű példa: megerősítés nélkül
for (new w = 0; w < MAX_WEAPONS; w++)
{
g_weaponKills[id][w] = 0;
g_weaponLevel[id][w] = 1;
}
client_print_color(id, print_chat, "^4[WP]^1 Prestige reset: minden fegyver fejlődése nullázva!");
show_weapon_hud(id);
return PLUGIN_HANDLED;
}
// /wp – aktuális fegyver info
public cmd_ShowWeaponInfo(id)
{
if (!is_user_connected(id))
return PLUGIN_HANDLED;
new weapon = get_user_weapon(id);
if (weapon <= 0 || weapon >= MAX_WEAPONS)
{
client_print_color(id, print_chat, "^4[WP]^1 Nincs aktív fegyvered.");
return PLUGIN_HANDLED;
}
new kills = g_weaponKills[id][weapon];
new level = g_weaponLevel[id][weapon];
new wname[32];
get_weapon_name_by_csw(weapon, wname, charsmax(wname));
client_print_color(id, print_chat, "^4[WP]^1 Fegyver: ^3%s^1 | Szint: ^3%d^1 | Ölések: ^3%d", wname, level, kills);
show_weapon_hud(id);
return PLUGIN_HANDLED;
}
// Fegyver név CSW alapján
stock get_weapon_name_by_csw(csw, name[], len)
{
if (csw > 0 && csw < MAX_WEAPONS && g_weaponNames[csw][0])
{
copy(name, len, g_weaponNames[csw]);
}
else
{
copy(name, len, "Ismeretlen");
}
}
// Screen fade effekt
stock screen_fade(id, holdtime, fadetime, r, g, b, alpha)
{
message_begin(MSG_ONE_UNRELIABLE, get_user_msgid("ScreenFade"), _, id);
write_short((holdtime & 0xFFFF));
write_short((fadetime & 0xFFFF));
write_short(0x0000);
write_byte(r);
write_byte(g);
write_byte(b);
write_byte(alpha);
message_end();
}
// nVault mentés / betöltés
stock save_player_data(id)
{
if (g_vault == INVALID_HANDLE || !is_user_connected(id))
return;
new authid[35];
get_user_authid(id, authid, charsmax(authid));
new key[64], value[256];
// Összefűzzük az adatokat: kills;levels;puzzles
// Formátum: weapon:kill,weapon:kill,...|weapon:level,...|weapon:puzzle,...
new killsStr[128], levelsStr[128], puzzleStr[128];
killsStr[0] = 0;
levelsStr[0] = 0;
puzzleStr[0] = 0;
new temp[32];
for (new w = 1; w < MAX_WEAPONS; w++)
{
if (!g_weaponNames[w][0])
continue;
formatex(temp, charsmax(temp), "%d:%d;", w, g_weaponKills[id][w]);
add(killsStr, charsmax(killsStr), temp);
formatex(temp, charsmax(temp), "%d:%d;", w, g_weaponLevel[id][w]);
add(levelsStr, charsmax(levelsStr), temp);
formatex(temp, charsmax(temp), "%d:%d;", w, g_puzzlePieces[id][w]);
add(puzzleStr, charsmax(puzzleStr), temp);
}
formatex(value, charsmax(value), "%s|%s|%s", killsStr, levelsStr, puzzleStr);
formatex(key, charsmax(key), "%s_wp", authid);
nvault_set(g_vault, key, value);
}
stock load_player_data(id)
{
if (g_vault == INVALID_HANDLE || !is_user_connected(id))
return;
new authid[35];
get_user_authid(id, authid, charsmax(authid));
new key[64], value[256];
formatex(key, charsmax(key), "%s_wp", authid);
if (!nvault_get(g_vault, key, value, charsmax(value)))
{
// Nincs adat, alapértékek
for (new w = 0; w < MAX_WEAPONS; w++)
{
g_weaponKills[id][w] = 0;
g_weaponLevel[id][w] = 1;
g_puzzlePieces[id][w] = 0;
}
return;
}
// value: kills|levels|puzzles
new killsStr[128], levelsStr[128], puzzleStr[128];
parse3(value, killsStr, charsmax(killsStr), levelsStr, charsmax(levelsStr), puzzleStr, charsmax(puzzleStr));
// Kills
new item[32], pos;
pos = 0;
while (strlen(killsStr) > 0 && strtok2(killsStr, item, charsmax(item), killsStr, charsmax(killsStr), ';', pos))
{
new w, k;
if (sscanf(item, "d:d", w, k))
continue;
if (w > 0 && w < MAX_WEAPONS)
g_weaponKills[id][w] = k;
}
// Levels
pos = 0;
while (strlen(levelsStr) > 0 && strtok2(levelsStr, item, charsmax(item), levelsStr, charsmax(levelsStr), ';', pos))
{
new w, l;
if (sscanf(item, "d:d", w, l))
continue;
if (w > 0 && w < MAX_WEAPONS)
g_weaponLevel[id][w] = l;
}
// Puzzles
pos = 0;
while (strlen(puzzleStr) > 0 && strtok2(puzzleStr, item, charsmax(item), puzzleStr, charsmax(puzzleStr), ';', pos))
{
new w, p;
if (sscanf(item, "d:d", w, p))
continue;
if (w > 0 && w < MAX_WEAPONS)
g_puzzlePieces[id][w] = p;
}
}
// Segéd: 3 részre bontás '|' alapján
stock parse3(const input[], out1[], len1, out2[], len2, out3[], len3)
{
new tmp[256];
copy(tmp, charsmax(tmp), input);
new p1 = contain(tmp, "|");
if (p1 == -1)
{
copy(out1, len1, tmp);
out2[0] = 0;
out3[0] = 0;
return;
}
tmp[p1] = 0;
copy(out1, len1, tmp);
new p2 = contain(tmp[p1 + 1], "|");
if (p2 == -1)
{
copy(out2, len2, tmp[p1 + 1]);
out3[0] = 0;
return;
}
tmp[p1 + 1 + p2] = 0;
copy(out2, len2, tmp[p1 + 1]);
copy(out3, len3, tmp[p1 + 1 + p2 + 1]);
}