uploading remade source code of neons grenadeskin plugin because he never uploaded it. also now has tier support

This commit is contained in:
jenz 2026-06-20 14:14:53 +02:00
parent 9e59258ab0
commit c379458632
3 changed files with 689 additions and 0 deletions

View File

@ -0,0 +1,80 @@
// Angery nut
materials/models/unloze/william/back.vmt
materials/models/unloze/william/back.vtf
materials/models/unloze/william/front.vmt
materials/models/unloze/william/front.vtf
models/unloze/william/angerynut.dx80.vtx
models/unloze/william/angerynut.dx90.vtx
models/unloze/william/angerynut.mdl
models/unloze/william/angerynut.sw.vtx
models/unloze/william/angerynut.vvd
//
//// Eevee
models\unloze\grenades\eevee.dx80.vtx
models\unloze\grenades\eevee.dx90.vtx
models\unloze\grenades\eevee.mdl
models\unloze\grenades\eevee.sw.vtx
models\unloze\grenades\eevee.vvd
materials\models\unloze\grenades\eevee\eevee_body.vtf
materials\models\unloze\grenades\eevee\eevee_body_shiny.vtf
materials\models\unloze\grenades\eevee\eevee_eye.vtf
materials\models\unloze\grenades\eevee\eevee_eye_shiny.vtf
materials\models\unloze\grenades\eevee\eevee_mouth.vtf
materials\models\unloze\grenades\eevee\eevee_mouth_shiny.vtf
materials\models\unloze\grenades\eevee\eievui.vmt
materials\models\unloze\grenades\eevee\eievuieye.vmt
materials\models\unloze\grenades\eevee\eievuieye_shiny.vmt
materials\models\unloze\grenades\eevee\eievuimouth.vmt
materials\models\unloze\grenades\eevee\eievuimouth_shiny.vmt
materials\models\unloze\grenades\eevee\eievui_shiny.vmt
//
//// Holy Grenade
models\unloze\grenades\holy_grenade.dx80.vtx
models\unloze\grenades\holy_grenade.dx90.vtx
models\unloze\grenades\holy_grenade.mdl
models\unloze\grenades\holy_grenade.phy
models\unloze\grenades\holy_grenade.sw.vtx
models\unloze\grenades\holy_grenade.vvd
materials\models\unloze\grenades\holy_grenade\holy_grenade.vmt
materials\models\unloze\grenades\holy_grenade\holy_grenade.vtf
//
//// Lenny
models\unloze\grenades\lenny.dx80.vtx
models\unloze\grenades\lenny.dx90.vtx
models\unloze\grenades\lenny.mdl
models\unloze\grenades\lenny.sw.vtx
models\unloze\grenades\lenny.vvd
models\unloze\grenades\lennysad.dx80.vtx
models\unloze\grenades\lennysad.dx90.vtx
models\unloze\grenades\lennysad.mdl
models\unloze\grenades\lennysad.sw.vtx
models\unloze\grenades\lennysad.vvd
materials\models\unloze\grenades\lenny\black.vmt
//
//// Pokeball
models\unloze\grenades\pokeball.dx80.vtx
models\unloze\grenades\pokeball.dx90.vtx
models\unloze\grenades\pokeball.mdl
models\unloze\grenades\pokeball.phy
models\unloze\grenades\pokeball.sw.vtx
models\unloze\grenades\pokeball.vvd
materials\models\unloze\grenades\pokeball\pokeball.vmt
materials\models\unloze\grenades\pokeball\pokeball.vtf
materials\models\unloze\grenades\pokeball\pokeball_great.vmt
materials\models\unloze\grenades\pokeball\pokeball_great.vtf
materials\models\unloze\grenades\pokeball\pokeball_gs.vmt
materials\models\unloze\grenades\pokeball\pokeball_gs.vtf
materials\models\unloze\grenades\pokeball\pokeball_master.vmt
materials\models\unloze\grenades\pokeball\pokeball_master.vtf
materials\models\unloze\grenades\pokeball\pokeball_ultra.vmt
materials\models\unloze\grenades\pokeball\pokeball_ultra.vtf
//
//// Soccer Ball
materials/models/unloze/soccer/soccerball.vmt
materials/models/unloze/soccer/soccerball_unloze.vtf
models/unloze/soccer/soccerball.dx80.vtx
models/unloze/soccer/soccerball.dx90.vtx
models/unloze/soccer/soccerball.mdl
models/unloze/soccer/soccerball.phy
models/unloze/soccer/soccerball.sw.vtx
models/unloze/soccer/soccerball.vvd

View File

@ -0,0 +1,193 @@
"Skins"
{
"0"
{
"Name" "Hula Doll"
"ModelPath" "models/props_lab/huladoll.mdl"
"Scale" "1.7"
"Tier" "1"
}
"1"
{
"Name" "Banana"
"ModelPath" "models/props/cs_italy/bananna.mdl"
"Tier" "2"
}
"2"
{
"Name" "Melon"
"ModelPath" "models/props_junk/watermelon01.mdl"
"Scale" "0.7"
"Tier" "2"
}
"3"
{
"Name" "Orange"
"ModelPath" "models/props/cs_italy/orange.mdl"
"Scale" "1.5"
"Tier" "3"
}
"4"
{
"Name" "Creepy Doll"
"ModelPath" "models/props_c17/doll01.mdl"
"Scale" "0.8"
"Tier" "3"
}
"5"
{
"Name" "Turtle"
"ModelPath" "models/props/de_tides/vending_turtle.mdl"
"Tier" "4"
}
"6"
{
"Name" "Goldfish"
"ModelPath" "models/props/de_inferno/goldfish.mdl"
"Tier" "5"
}
"7"
{
"Name" "River Fish"
"ModelPath" "models/props/cs_militia/fishriver01.mdl"
"Tier" "5"
}
"8"
{
"Name" "Snowman Head"
"ModelPath" "models/props/cs_office/snowman_face.mdl"
"Scale" "0.7"
"Tier" "6"
}
"9"
{
"Name" "Glass Bottle"
"ModelPath" "models/props/cs_militia/bottle01.mdl"
"Tier" "7"
}
"10"
{
"Name" "Gift"
"ModelPath" "models/items/cs_gift.mdl"
"Scale" "0.6"
"Tier" "8"
}
"11"
{
"Name" "Rollermine"
"ModelPath" "models/roller_spikes.mdl"
"VIP" "1"
"Scale" "0.7"
}
"12"
{
"Name" "Helicopter Bomb"
"ModelPath" "models/combine_helicopter/helicopter_bomb01.mdl"
"VIP" "1"
"Scale" "0.35"
}
"13"
{
"Name" "Explosive Barrel"
"ModelPath" "models/props_c17/oildrum001_explosive.mdl"
"VIP" "1"
"Scale" "0.25"
}
"14"
{
"Name" "Skull"
"ModelPath" "models/gibs/agibs.mdl"
"VIP" "1"
"Scale" "1.3"
}
"15"
{
"Name" "Angery Nut"
"ModelPath" "models/unloze/william/angerynut.mdl"
"VIP" "1"
"Scale" "0.8"
}
"16"
{
"Name" "Holy Grenade"
"ModelPath" "models/unloze/grenades/holy_grenade.mdl"
"Scale" "0.6"
"VIP" "1"
}
"17"
{
"Name" "Lenny Face"
"ModelPath" "models/unloze/grenades/lenny.mdl"
"VIP" "1"
"Scale" "0.8"
}
"18"
{
"Name" "Lenny Sad"
"ModelPath" "models/unloze/grenades/lennysad.mdl"
"VIP" "1"
"Scale" "0.8"
}
"19"
{
"Name" "Soccer Ball"
"ModelPath" "models/unloze/soccer/soccerball.mdl"
"VIP" "1"
"Scale" "0.4"
}
"20"
{
"Name" "Eevee"
"ModelPath" "models/unloze/grenades/eevee.mdl"
"VIP" "1"
"Scale" "0.5"
}
"21"
{
"Name" "Shiny Eevee"
"ModelPath" "models/unloze/grenades/eevee.mdl"
"VIP" "1"
"Skin" "1"
"Scale" "0.5"
}
"22"
{
"Name" "Poke Ball"
"ModelPath" "models/unloze/grenades/pokeball.mdl"
"VIP" "1"
"Scale" "1.5"
}
"23"
{
"Name" "Great Ball"
"ModelPath" "models/unloze/grenades/pokeball.mdl"
"VIP" "1"
"Skin" "1"
"Scale" "1.5"
}
"24"
{
"Name" "Ultra Ball"
"ModelPath" "models/unloze/grenades/pokeball.mdl"
"VIP" "1"
"Skin" "4"
"Scale" "1.5"
}
"25"
{
"Name" "Master Ball"
"ModelPath" "models/unloze/grenades/pokeball.mdl"
"VIP" "1"
"Skin" "3"
"Scale" "1.5"
}
"26"
{
"Name" "GS Ball"
"ModelPath" "models/unloze/grenades/pokeball.mdl"
"VIP" "1"
"Skin" "2"
"Scale" "1.5"
}
}

View File

@ -0,0 +1,416 @@
#pragma semicolon 1
#include <sourcemod>
#include <clientprefs>
#include <sdktools>
#include <sdkhooks>
#include <unloze_playtime>
#pragma newdecls required
#define MAX_SKINS 64
enum struct GrenadeSkin
{
char ModelPath[128];
char Name[128];
int VIP;
int Tier;
float Scale;
int Skin;
}
GrenadeSkin g_aGrenadeSkins[MAX_SKINS];
int g_iSkinCount = 0;
int g_iGrenadeSkin[MAXPLAYERS + 1] = { -1, ... };
bool g_bAdminChecked[MAXPLAYERS + 1];
Handle g_hCookie_GrenadeSkin;
public Plugin myinfo =
{
name = "Grenade Skins",
description = "grenade skins but source code actually provided",
author = "redone by claude ai mostly, slight human adjustments",
version = "1.0",
url = ""
};
public void OnPluginStart()
{
RegConsoleCmd("sm_grenadeskin", Cmd_GrenadeSkinSettings);
RegConsoleCmd("sm_grenadeskins", Cmd_GrenadeSkinSettings);
g_hCookie_GrenadeSkin = RegClientCookie("grenade_skin", "Selected grenade skin", CookieAccess_Protected);
SetCookieMenuItem(MenuHandler_CookieMenu, 0, "Grenade Skin");
for (int i = 1; i <= MaxClients; i++)
{
if (IsValidClient(i, true) && AreClientCookiesCached(i))
{
OnClientCookiesCached(i);
}
}
}
public void OnMapStart()
{
LoadDownloads();
LoadSkinsConfig();
}
void LoadDownloads()
{
char sDownloadsFile[PLATFORM_MAX_PATH];
BuildPath(Path_SM, sDownloadsFile, sizeof(sDownloadsFile), "configs/grenade_skins/downloads.txt");
File hFile = OpenFile(sDownloadsFile, "r");
if (!hFile)
{
SetFailState("Could not open file: configs/grenade_skins/downloads.txt");
}
char sLine[1024];
while (hFile.ReadLine(sLine, sizeof(sLine)))
{
TrimString(sLine);
// Skip empty lines and comment lines (lines starting with "//" with no file extension).
if (sLine[0] == '\0')
continue;
if (StrContains(sLine, ".", false) == -1)
continue;
if (FileExists(sLine, false, "GAME"))
{
AddFileToDownloadsTable(sLine);
}
}
delete hFile;
}
void LoadSkinsConfig()
{
// Clear existing skins.
for (int i = 0; i < MAX_SKINS; i++)
{
g_aGrenadeSkins[i].ModelPath[0] = '\0';
g_aGrenadeSkins[i].Name[0] = '\0';
g_aGrenadeSkins[i].VIP = 0;
g_aGrenadeSkins[i].Tier = 0;
g_aGrenadeSkins[i].Scale = 1.0;
g_aGrenadeSkins[i].Skin = 0;
}
g_iSkinCount = 0;
char sConfigFile[PLATFORM_MAX_PATH];
BuildPath(Path_SM, sConfigFile, sizeof(sConfigFile), "configs/grenade_skins/skins.cfg");
if (!FileExists(sConfigFile, false, "GAME"))
{
SetFailState("Could not find: \"%s\"", sConfigFile);
}
KeyValues kv = new KeyValues("Skins");
if (!kv.ImportFromFile(sConfigFile))
{
delete kv;
SetFailState("ImportFromFile() failed!");
}
if (!kv.GotoFirstSubKey(true))
{
delete kv;
SetFailState("Unable to goto first sub key in: \"%s\"", sConfigFile);
}
int i = 0;
do
{
if (i >= MAX_SKINS)
{
LogError("grenade_skins: skins.cfg has more than %d entries, ignoring the rest.", MAX_SKINS);
break;
}
kv.GetString("ModelPath", g_aGrenadeSkins[i].ModelPath, sizeof(g_aGrenadeSkins[].ModelPath), "error");
if (StrEqual(g_aGrenadeSkins[i].ModelPath, "error", true))
{
SetFailState("Unable to read Path");
}
kv.GetString("Name", g_aGrenadeSkins[i].Name, sizeof(g_aGrenadeSkins[].Name), "error");
if (StrEqual(g_aGrenadeSkins[i].Name, "error", true))
{
SetFailState("Unable to read Name");
}
g_aGrenadeSkins[i].VIP = kv.GetNum("VIP", 0);
g_aGrenadeSkins[i].Tier = kv.GetNum("tier", 0);
g_aGrenadeSkins[i].Scale = kv.GetFloat("Scale", 1.0);
g_aGrenadeSkins[i].Skin = kv.GetNum("Skin", 0);
PrecacheModel(g_aGrenadeSkins[i].ModelPath, false);
i++;
}
while (kv.GotoNextKey(true));
g_iSkinCount = i;
delete kv;
}
public void OnClientCookiesCached(int client)
{
char sBuffer[256];
GetClientCookie(client, g_hCookie_GrenadeSkin, sBuffer, sizeof(sBuffer));
if (sBuffer[0])
{
g_iGrenadeSkin[client] = -1;
for (int i = 0; i < g_iSkinCount; i++)
{
if (StrEqual(g_aGrenadeSkins[i].ModelPath, sBuffer, true))
{
g_iGrenadeSkin[client] = i;
if (g_bAdminChecked[client] && !ClientHasSkinAccess(client, i))
{
g_iGrenadeSkin[client] = -1;
}
break;
}
}
}
else
{
g_iGrenadeSkin[client] = -1;
}
}
public void OnClientDisconnect(int client)
{
g_iGrenadeSkin[client] = -1;
g_bAdminChecked[client] = false;
}
public void OnClientPostAdminCheck(int client)
{
g_bAdminChecked[client] = true;
if (AreClientCookiesCached(client) && g_iGrenadeSkin[client] != -1)
{
if (!ClientHasSkinAccess(client, g_iGrenadeSkin[client]))
{
g_iGrenadeSkin[client] = -1;
}
}
}
/**
* Checks whether a client has access to a given skin index,
* taking both the legacy VIP flag and the new tier requirement into account.
*/
bool ClientHasSkinAccess(int client, int skinIndex)
{
if (g_aGrenadeSkins[skinIndex].VIP && !CheckCommandAccess(client, "", ADMFLAG_RESERVATION, false))
{
return false;
}
if (g_aGrenadeSkins[skinIndex].Tier > 0 && GetPlayerTier_native(client) < g_aGrenadeSkins[skinIndex].Tier)
{
return false;
}
return true;
}
public void OnEntitySpawned(int entity, const char[] sClassname)
{
if (StrContains(sClassname, "_projectile", false) == -1)
{
return;
}
int iOwner = GetEntPropEnt(entity, Prop_Send, "m_hOwnerEntity");
if (!IsValidClient(iOwner, true) || g_iGrenadeSkin[iOwner] == -1)
{
return;
}
int skinIndex = g_iGrenadeSkin[iOwner];
SetEntityRenderMode(entity, RENDER_TRANSALPHA);
float fNadeOrigin[3];
GetEntPropVector(entity, Prop_Send, "m_vecOrigin", fNadeOrigin);
int iNadeProp = CreateEntityAtOrigin("prop_dynamic_override", fNadeOrigin);
DispatchKeyValue(iNadeProp, "disableshadows", "1");
DispatchKeyValue(iNadeProp, "disablereceiveshadows", "1");
DispatchKeyValue(iNadeProp, "DisableBoneFollowers", "1");
DispatchKeyValue(iNadeProp, "solid", "0");
DispatchKeyValue(iNadeProp, "model", g_aGrenadeSkins[skinIndex].ModelPath);
char sScale[32];
FloatToString(g_aGrenadeSkins[skinIndex].Scale, sScale, sizeof(sScale));
DispatchKeyValue(iNadeProp, "modelscale", sScale);
SpawnAndActivate(iNadeProp);
ParentToEntity(iNadeProp, entity);
if (g_aGrenadeSkins[skinIndex].Skin > 0)
{
char sSkinBuf[16];
IntToString(g_aGrenadeSkins[skinIndex].Skin, sSkinBuf, sizeof(sSkinBuf));
SetVariantString(sSkinBuf);
AcceptEntityInput(iNadeProp, "Skin");
}
}
public Action Cmd_GrenadeSkinSettings(int client, int args)
{
ShowSettingsMenu(client);
return Plugin_Handled;
}
public void MenuHandler_CookieMenu(int client, CookieMenuAction action, any info, char[] buffer, int maxlen)
{
switch (action)
{
case CookieMenuAction_DisplayOption:
{
Format(buffer, maxlen, "Grenade Skin");
}
case CookieMenuAction_SelectOption:
{
ShowSettingsMenu(client);
}
}
}
void ShowSettingsMenu(int client)
{
Menu menu = new Menu(MenuHandler_MainMenu);
menu.SetTitle("Grenade Skin");
char sBuffer[128];
Format(sBuffer, sizeof(sBuffer), "No Skin%s", (g_iGrenadeSkin[client] == -1) ? " (Selected)" : "");
menu.AddItem("-1", sBuffer, (g_iGrenadeSkin[client] == -1) ? ITEMDRAW_DISABLED : ITEMDRAW_DEFAULT);
for (int i = 0; i < g_iSkinCount; i++)
{
bool bSelected = (i == g_iGrenadeSkin[client]);
bool bHasAccess = ClientHasSkinAccess(client, i);
bool bUnavailable = bSelected || !bHasAccess;
char sSuffix[32];
sSuffix[0] = '\0';
if (!bHasAccess)
{
if (g_aGrenadeSkins[i].VIP && !CheckCommandAccess(client, "", ADMFLAG_RESERVATION, false))
{
Format(sSuffix, sizeof(sSuffix), " [VIP]");
}
else if (g_aGrenadeSkins[i].Tier > 0 && GetPlayerTier_native(client) < g_aGrenadeSkins[i].Tier)
{
Format(sSuffix, sizeof(sSuffix), " [Tier %i]", g_aGrenadeSkins[i].Tier);
}
}
else if (bSelected)
{
Format(sSuffix, sizeof(sSuffix), " (Selected)");
}
Format(sBuffer, sizeof(sBuffer), "%s%s", g_aGrenadeSkins[i].Name, sSuffix);
char sInfo[8];
IntToString(i, sInfo, sizeof(sInfo));
menu.AddItem(sInfo, sBuffer, bUnavailable ? ITEMDRAW_DISABLED : ITEMDRAW_DEFAULT);
}
menu.ExitBackButton = true;
menu.Display(client, MENU_TIME_FOREVER);
}
public int MenuHandler_MainMenu(Menu menu, MenuAction action, int client, int selection)
{
switch (action)
{
case MenuAction_Select:
{
char sInfo[8];
menu.GetItem(selection, sInfo, sizeof(sInfo));
int chosen = StringToInt(sInfo);
g_iGrenadeSkin[client] = chosen;
if (chosen == -1)
{
SetClientCookie(client, g_hCookie_GrenadeSkin, "");
}
else
{
SetClientCookie(client, g_hCookie_GrenadeSkin, g_aGrenadeSkins[chosen].ModelPath);
}
ShowSettingsMenu(client);
}
case MenuAction_Cancel:
{
if (selection == MenuCancel_ExitBack)
{
// Re-open the cookie/settings menu if desired; original plugin
// routed back into the cookie menu here.
}
}
case MenuAction_End:
{
delete menu;
}
}
return 0;
}
// ---------------------------------------------------------------------
// Helper stocks (ported from decompiled output)
// ---------------------------------------------------------------------
stock bool IsValidClient(int client, bool noBots)
{
if (client <= 0 || client > MaxClients || !IsClientConnected(client) || (noBots && IsFakeClient(client)))
{
return false;
}
return IsClientInGame(client);
}
stock int CreateEntityAtOrigin(const char[] classname, const float origin[3])
{
int entity = CreateEntityByName(classname);
TeleportEntity(entity, origin, NULL_VECTOR, NULL_VECTOR);
return entity;
}
stock void SpawnAndActivate(int entity)
{
DispatchSpawn(entity);
ActivateEntity(entity);
}
stock void ParentToEntity(int entity, int parent)
{
SetVariantString("!activator");
AcceptEntityInput(entity, "SetParent", parent, parent);
}