namespace PlayerDataManagement { string SanitizeSteamID(string steamId) { steamId.Replace(":", "_"); steamId.Replace(".", "_"); return steamId; } void SavePlayerData(CBasePlayer@ pPlayer) { if (pPlayer is null) return; CustomKeyvalues@ pCustom = pPlayer.GetCustomKeyvalues(); string steamId = SanitizeSteamID(g_EngineFuncs.GetPlayerAuthId(pPlayer.edict())); dictionary data; g_PlayerFuncs.ClientPrint(pPlayer, HUD_PRINTTALK, "[SavePlayerData] Saving data for Steam ID: " + steamId + "\n"); // Collect all custom keyvalues array keys = { "$i_extradmg", "$i_hookcooldown", "$i_pulldmgitem", "$i_lifestealhookitem", "$i_techiesscope", "$i_coinhook", "$i_agility", "$i_willtowin", "$i_hookspeedupgrade", "$i_pullspeedupgrade", "$i_gold", "$i_techiesScopeEnabled", "$i_grappler", "$i_twirlupgrade", "$i_maxspeed", "$i_maxhp", "$i_barbedwire", "$i_chainmail", "$i_explosivehook", "$i_barricadecount", "$i_healhook", "$i_touchofundeath", "$i_grafterscharm", "$i_bridgecount", "$i_baitcount", "$i_funcoins", "$i_adrenalineboost" }; for (uint i = 0; i < keys.length(); i++) { int value = pCustom.GetKeyvalue(keys[i]).GetInteger(); data[keys[i]] = value; g_PlayerFuncs.ClientPrint(pPlayer, HUD_PRINTTALK, "[SavePlayerData] Key: " + keys[i] + ", Value: " + value + "\n"); } // Store the player frags data["frags"] = pPlayer.pev.frags; // Create or find the info_target entity with a unique name string targetname = "player_data_" + steamId; CBaseEntity@ pInfoTarget = g_EntityFuncs.FindEntityByTargetname(null, targetname); if (pInfoTarget is null) { // Create a new info_target dictionary keysData; keysData["targetname"] = targetname; @pInfoTarget = g_EntityFuncs.CreateEntity("info_target", keysData); g_PlayerFuncs.ClientPrint(pPlayer, HUD_PRINTTALK, "[SavePlayerData] Created new info_target with targetname: " + targetname + "\n"); } else { g_PlayerFuncs.ClientPrint(pPlayer, HUD_PRINTTALK, "[SavePlayerData] Found existing info_target with targetname: " + targetname + "\n"); } // Store the data in the entity's CustomKeyvalues CustomKeyvalues@ pInfoCustom = pInfoTarget.GetCustomKeyvalues(); array dataKeys = data.getKeys(); for (uint i = 0; i < dataKeys.length(); i++) { string key = dataKeys[i]; int value = int(data[key]); pInfoCustom.SetKeyvalue(key, value); } } void RestorePlayerData(CBasePlayer@ pPlayer) { if (pPlayer is null) return; string steamId = SanitizeSteamID(g_EngineFuncs.GetPlayerAuthId(pPlayer.edict())); g_PlayerFuncs.ClientPrint(pPlayer, HUD_PRINTTALK, "[RestorePlayerData] Restoring data for Steam ID: " + steamId + "\n"); string targetname = "player_data_" + steamId; CBaseEntity@ pInfoTarget = g_EntityFuncs.FindEntityByTargetname(null, targetname); CustomKeyvalues@ pCustom = pPlayer.GetCustomKeyvalues(); // List of all items array itemsToCheck = { "$i_grappler", "$i_lifestealhookitem", "$i_techiesscope", "$i_pulldmgitem", "$i_barbedwire", "$i_explosivehook", "$i_chainmail", "$i_healhook", "$i_touchofundeath", "$i_grafterscharm", "$i_adrenalineboost" }; // List of all upgrades array upgradesToCheck = { "$i_extradmg", "$i_hookcooldown", "$i_coinhook", "$i_agility", "$i_willtowin", "$i_hookspeedupgrade", "$i_pullspeedupgrade", "$i_gold", "$i_techiesScopeEnabled", "$i_twirlupgrade", "$i_maxspeed", "$i_maxhp", "$i_barricadecount", "$i_bridgecount", "$i_baitcount", "$i_funcoins" }; dictionary keysDisplayName = { {"$i_grappler", "Grappler"}, {"$i_lifestealhookitem", "Bloodthirster"}, {"$i_techiesscope", "Techies Scopes"}, {"$i_pulldmgitem", "Pullbane"}, {"$i_barbedwire", "Barbed Wire"}, {"$i_explosivehook", "Explosive Hook"}, {"$i_chainmail", "Chainmail"}, {"$i_healhook", "Heal Hook"}, {"$i_touchofundeath", "Touch of Undeath"}, {"$i_grafterscharm", "Grafter's Charm"}, {"$i_extradmg", "Extra Damage"}, {"$i_hookcooldown", "Hook Cooldown"}, {"$i_coinhook", "Coin Hook"}, {"$i_agility", "Agility"}, {"$i_willtowin", "Will to Win"}, {"$i_hookspeedupgrade", "Hook Speed Upgrade"}, {"$i_pullspeedupgrade", "Pull Speed Upgrade"}, {"$i_gold", "Gold"}, {"$i_techiesScopeEnabled", "Techies Scope Enabled"}, {"$i_twirlupgrade", "Twirl Upgrade"}, {"$i_maxspeed", "Max Speed"}, {"$i_maxhp", "Max HP"}, {"$i_barricadecount", "Barricade Count"}, {"$i_bridgecount", "Bridge Count"}, {"$i_baitcount", "Bait Count"}, {"$i_funcoins", "Fun Coins"}, {"$i_adrenalineboost", "Adrenaline Rush"} }; if (pInfoTarget !is null) { g_PlayerFuncs.ClientPrint(pPlayer, HUD_PRINTTALK, "[RestorePlayerData] Found info_target with targetname: " + targetname + "\n"); CustomKeyvalues@ pInfoCustom = pInfoTarget.GetCustomKeyvalues(); // Restore items for (uint i = 0; i < itemsToCheck.length(); i++) { string key = itemsToCheck[i]; CustomKeyvalue kvb = pInfoCustom.GetKeyvalue(key); if (kvb.Exists()) { int value = kvb.GetInteger(); pCustom.SetKeyvalue(key, value); string status = (value == 1) ? "Owned" : "Not Owned"; g_PlayerFuncs.ClientPrint(pPlayer, HUD_PRINTTALK, "[RestorePlayerData] " + string(keysDisplayName[key]) + " : " + status + "\n"); } else { // Initialize missing keys to not owned pCustom.SetKeyvalue(key, 0); g_PlayerFuncs.ClientPrint(pPlayer, HUD_PRINTTALK, "[RestorePlayerData] " + string(keysDisplayName[key]) + " : Not Owned\n"); } } // Restore upgrades for (uint i = 0; i < upgradesToCheck.length(); i++) { string key = upgradesToCheck[i]; CustomKeyvalue kvb = pInfoCustom.GetKeyvalue(key); if (kvb.Exists()) { int value = kvb.GetInteger(); pCustom.SetKeyvalue(key, value); g_PlayerFuncs.ClientPrint(pPlayer, HUD_PRINTTALK, "[RestorePlayerData] " + string(keysDisplayName[key]) + " restored to: " + value + "\n"); } else { // Initialize missing keys to zero pCustom.SetKeyvalue(key, 0); g_PlayerFuncs.ClientPrint(pPlayer, HUD_PRINTTALK, "[RestorePlayerData] " + string(keysDisplayName[key]) + " initialized to: 0\n"); } } // Restore additional value CustomKeyvalue kvFrags = pInfoCustom.GetKeyvalue("frags"); if (kvFrags.Exists()) { pPlayer.pev.frags = kvFrags.GetInteger(); g_PlayerFuncs.ClientPrint(pPlayer, HUD_PRINTTALK, "[RestorePlayerData] Frags restored to: " + pPlayer.pev.frags + "\n"); } else { pPlayer.pev.frags = 0; g_PlayerFuncs.ClientPrint(pPlayer, HUD_PRINTTALK, "[RestorePlayerData] Frags initialized to: 0\n"); } } else { g_PlayerFuncs.ClientPrint(pPlayer, HUD_PRINTTALK, "[RestorePlayerData] No data found for Steam ID: " + steamId + "\n"); // Initialize all items to not owned if no data found for (uint i = 0; i < itemsToCheck.length(); i++) { string key = itemsToCheck[i]; pCustom.SetKeyvalue(key, 0); g_PlayerFuncs.ClientPrint(pPlayer, HUD_PRINTTALK, "[RestorePlayerData] " + string(keysDisplayName[key]) + " : Not Owned\n"); } // Initialize all upgrades to zero if no data found for (uint i = 0; i < upgradesToCheck.length(); i++) { string key = upgradesToCheck[i]; pCustom.SetKeyvalue(key, 0); g_PlayerFuncs.ClientPrint(pPlayer, HUD_PRINTTALK, "[RestorePlayerData] " + string(keysDisplayName[key]) + " initialized to: 0\n"); } // Initialize additional value to default pPlayer.pev.frags = 0; } } HookReturnCode ClientPutInServer(CBasePlayer@ pPlayer) { if (pPlayer is null) return HOOK_CONTINUE; g_PlayerFuncs.ClientPrint(pPlayer, HUD_PRINTTALK, "Player connecting: " + pPlayer.pev.netname + "\n"); RestorePlayerData(pPlayer); CustomKeyvalues@ pCustom = pPlayer.GetCustomKeyvalues(); // Restore armor value if chainmail is active if (pCustom.GetKeyvalue("$i_chainmail").GetInteger() == 1) { pPlayer.pev.armorvalue = Math.max(pPlayer.pev.armorvalue, 25); } // Restore and add maximum health int additionalMaxHealth = pCustom.GetKeyvalue("$i_maxhp").GetInteger(); pPlayer.pev.max_health = pPlayer.pev.max_health + additionalMaxHealth; pPlayer.pev.health = pPlayer.pev.max_health; // Restore maximum speed int additionalMaxSpeed = pCustom.GetKeyvalue("$i_maxspeed").GetInteger(); pPlayer.SetMaxSpeed(270 + additionalMaxSpeed); return HOOK_CONTINUE; } HookReturnCode ClientDisconnect(CBasePlayer@ pPlayer) { if (pPlayer is null) return HOOK_CONTINUE; g_PlayerFuncs.ClientPrint(pPlayer, HUD_PRINTTALK, "Player disconnecting: " + pPlayer.pev.netname + "\n"); SavePlayerData(pPlayer); return HOOK_CONTINUE; } }