Promoveaza serverul

Initial release 1.0.0

Browse Source
1.0.0 - Initial release.
Daemon666 committed commit 069c442fb2e7e7dd14d526bcd27c2125a13554e7
4 changed files with 311 additions and 0 deletions
+3 -0 CHANGELOG.md A
@@ -0,0 +1,3 @@
1 +## 1.0.0 (2025-12-17)
2 +
3 +1.0.0 - Initial release.
+1 -0 README.md A
@@ -0,0 +1 @@
1 +<p><strong>CSB Pets</strong> gives each player a little companion. On spawn a non-solid model entity is created and, on a movement task, glides toward a point just behind and above its owner with smooth interpolation while always turning to face them. Players pick a pet from a menu with <code>/pet</code>; the choice is saved per SteamID in nVault and restored automatically next time. Pets are removed on death and on disconnect so they never linger.</p><h2>Features</h2><ul><li><code>/pet</code> menu to choose or remove a pet.</li><li>Smooth follow with interpolation and facing, non-solid so it never blocks anyone.</li><li>Choice persists per SteamID in nVault.</li><li>Removed cleanly on death and disconnect.</li></ul><h2>Installation</h2><ol><li>Enable the <code>fakemeta</code> and <code>nvault</code> modules in <code>modules.ini</code>.</li><li>Compile <code>csb_pets.sma</code>, copy it to <code>addons/amxmodx/plugins/</code> and add it to <code>plugins.ini</code>.</li><li>Make sure the pet models exist in your <code>models/</code> folder or edit the model list in the source.</li><li>Change the map.</li></ol>
+265 -0 addons/amxmodx/scripting/csb_pets.sma A
@@ -0,0 +1,265 @@
1 +/*
2 + * CSB Pets
3 + * Copyright (C) 2026 counter-strike-boost.com
4 + *
5 + * A cosmetic pet model that follows the player. On spawn a non-solid model
6 + * entity is created and, on a movement task, glides toward a point just behind
7 + * and above its owner with smooth interpolation, always facing the owner. Each
8 + * player picks a pet from a menu; the choice is stored per SteamID in nVault and
9 + * restored on their next spawn. Pets are removed on death and disconnect.
10 + *
11 + * This program is free software: you can redistribute it and/or modify it under
12 + * the terms of the GNU General Public License as published by the Free Software
13 + * Foundation, either version 3 of the License, or (at your option) any later
14 + * version. It is distributed in the hope that it will be useful, but WITHOUT
15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16 + * FOR A PARTICULAR PURPOSE. See <https://www.gnu.org/licenses/> for details.
17 + */
18 +
19 +#include <amxmodx>
20 +#include <fakemeta>
21 +#include <nvault>
22 +
23 +new const PLUGIN[] = "CSB Pets"
24 +new const VERSION[] = "1.0.0"
25 +new const AUTHOR[] = "counter-strike-boost.com"
26 +
27 +new const g_szPetName[][] = { "None", "Scientist", "Chicken", "Robo Grunt" }
28 +new const g_szPetModel[][] =
29 +{
30 + "",
31 + "models/scientist.mdl",
32 + "models/chicken.mdl",
33 + "models/hgrunt.mdl"
34 +}
35 +
36 +new g_pEnabled, g_pSpeed
37 +new g_iVault
38 +new g_iPetEnt[33]
39 +new g_iPetChoice[33]
40 +
41 +public plugin_init()
42 +{
43 + register_plugin(PLUGIN, VERSION, AUTHOR)
44 +
45 + g_pEnabled = register_cvar("csb_pets_enabled", "1")
46 + g_pSpeed = register_cvar("csb_pets_speed", "0.25")
47 +
48 + register_clcmd("say /pet", "cmdMenu")
49 + register_clcmd("say_team /pet", "cmdMenu")
50 +
51 + register_event("ResetHUD", "eventSpawn", "b")
52 + register_event("DeathMsg", "eventDeath", "a", "1>0")
53 +
54 + g_iVault = nvault_open("csb_pets")
55 +
56 + set_task(0.1, "taskFollow", 0, _, _, "b")
57 +}
58 +
59 +public plugin_precache()
60 +{
61 + for (new i = 1; i < sizeof(g_szPetModel); i++)
62 + {
63 + if (g_szPetModel[i][0])
64 + engfunc(EngFunc_PrecacheModel, g_szPetModel[i])
65 + }
66 +}
67 +
68 +public client_putinserver(id)
69 +{
70 + g_iPetEnt[id] = 0
71 + g_iPetChoice[id] = 0
72 +
73 + loadChoice(id)
74 +}
75 +
76 +public client_disconnected(id)
77 +{
78 + removePet(id)
79 + g_iPetChoice[id] = 0
80 +}
81 +
82 +loadChoice(id)
83 +{
84 + new auth[35]
85 + get_user_authid(id, auth, charsmax(auth))
86 +
87 + if (!auth[0])
88 + return
89 +
90 + new data[8], ts
91 + if (nvault_lookup(g_iVault, auth, data, charsmax(data), ts))
92 + g_iPetChoice[id] = clamp(str_to_num(data), 0, sizeof(g_szPetModel) - 1)
93 +}
94 +
95 +saveChoice(id)
96 +{
97 + new auth[35]
98 + get_user_authid(id, auth, charsmax(auth))
99 +
100 + if (!auth[0])
101 + return
102 +
103 + new data[8]
104 + num_to_str(g_iPetChoice[id], data, charsmax(data))
105 + nvault_set(g_iVault, auth, data)
106 +}
107 +
108 +public cmdMenu(id)
109 +{
110 + if (!get_pcvar_num(g_pEnabled))
111 + return PLUGIN_HANDLED
112 +
113 + new menu = menu_create("\yCSB Pets^n\wPick your pet:", "menuHandler")
114 +
115 + new info[8]
116 + for (new i = 0; i < sizeof(g_szPetName); i++)
117 + {
118 + num_to_str(i, info, charsmax(info))
119 + menu_additem(menu, g_szPetName[i], info, 0)
120 + }
121 +
122 + menu_setprop(menu, MPROP_EXIT, MEXIT_ALL)
123 + menu_display(id, menu, 0)
124 + return PLUGIN_HANDLED
125 +}
126 +
127 +public menuHandler(id, menu, item)
128 +{
129 + if (item == MENU_EXIT)
130 + {
131 + menu_destroy(menu)
132 + return PLUGIN_HANDLED
133 + }
134 +
135 + new info[8], name[32], access, callback
136 + menu_item_getinfo(menu, item, access, info, charsmax(info), name, charsmax(name), callback)
137 + menu_destroy(menu)
138 +
139 + g_iPetChoice[id] = clamp(str_to_num(info), 0, sizeof(g_szPetModel) - 1)
140 + saveChoice(id)
141 +
142 + removePet(id)
143 +
144 + if (g_iPetChoice[id] == 0)
145 + {
146 + client_print(id, print_chat, "[CSB] Pet removed.")
147 + }
148 + else
149 + {
150 + client_print(id, print_chat, "[CSB] Pet set to %s.", g_szPetName[g_iPetChoice[id]])
151 + if (is_user_alive(id))
152 + spawnPet(id)
153 + }
154 +
155 + return PLUGIN_HANDLED
156 +}
157 +
158 +public eventSpawn(id)
159 +{
160 + if (is_user_alive(id) && g_iPetChoice[id] > 0)
161 + spawnPet(id)
162 +}
163 +
164 +public eventDeath()
165 +{
166 + new victim = read_data(2)
167 +
168 + if (victim >= 1 && victim <= 32)
169 + removePet(victim)
170 +}
171 +
172 +spawnPet(id)
173 +{
174 + removePet(id)
175 +
176 + new choice = g_iPetChoice[id]
177 +
178 + if (choice <= 0 || !g_szPetModel[choice][0])
179 + return
180 +
181 + new ent = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, "info_target"))
182 +
183 + if (!ent)
184 + return
185 +
186 + set_pev(ent, pev_classname, "csb_pet")
187 + set_pev(ent, pev_owner, id)
188 + set_pev(ent, pev_movetype, MOVETYPE_NOCLIP)
189 + set_pev(ent, pev_solid, SOLID_NOT)
190 +
191 + engfunc(EngFunc_SetModel, ent, g_szPetModel[choice])
192 +
193 + static Float:fOrigin[3]
194 + pev(id, pev_origin, fOrigin)
195 + engfunc(EngFunc_SetOrigin, ent, fOrigin)
196 +
197 + g_iPetEnt[id] = ent
198 +}
199 +
200 +removePet(id)
201 +{
202 + new ent = g_iPetEnt[id]
203 +
204 + if (ent > 0 && pev_valid(ent))
205 + engfunc(EngFunc_RemoveEntity, ent)
206 +
207 + g_iPetEnt[id] = 0
208 +}
209 +
210 +public taskFollow()
211 +{
212 + new players[32], num
213 + get_players(players, num, "a")
214 +
215 + new Float:speed = get_pcvar_float(g_pSpeed)
216 +
217 + if (speed <= 0.0)
218 + speed = 0.25
219 + else if (speed > 1.0)
220 + speed = 1.0
221 +
222 + for (new i = 0; i < num; i++)
223 + {
224 + new id = players[i]
225 + new ent = g_iPetEnt[id]
226 +
227 + if (ent <= 0 || !pev_valid(ent))
228 + continue
229 +
230 + static Float:fOwner[3], Float:fAng[3], Float:fFwd[3], Float:fTarget[3], Float:fPet[3]
231 + pev(id, pev_origin, fOwner)
232 + pev(id, pev_angles, fAng)
233 + fAng[0] = 0.0
234 + angle_vector(fAng, ANGLEVECTOR_FORWARD, fFwd)
235 +
236 + /* point behind and slightly above the owner */
237 + fTarget[0] = fOwner[0] - fFwd[0] * 60.0
238 + fTarget[1] = fOwner[1] - fFwd[1] * 60.0
239 + fTarget[2] = fOwner[2] + 20.0
240 +
241 + pev(ent, pev_origin, fPet)
242 +
243 + static Float:fNew[3]
244 + fNew[0] = fPet[0] + (fTarget[0] - fPet[0]) * speed
245 + fNew[1] = fPet[1] + (fTarget[1] - fPet[1]) * speed
246 + fNew[2] = fPet[2] + (fTarget[2] - fPet[2]) * speed
247 +
248 + engfunc(EngFunc_SetOrigin, ent, fNew)
249 +
250 + /* face the owner */
251 + static Float:fLook[3]
252 + fLook[0] = fOwner[0] - fNew[0]
253 + fLook[1] = fOwner[1] - fNew[1]
254 + fLook[2] = 0.0
255 +
256 + static Float:fYaw
257 + fYaw = floatatan2(fLook[1], fLook[0], degrees)
258 +
259 + static Float:fSet[3]
260 + fSet[0] = 0.0
261 + fSet[1] = fYaw
262 + fSet[2] = 0.0
263 + set_pev(ent, pev_angles, fSet)
264 + }
265 +}
+42 -0 csb.json A
@@ -0,0 +1,42 @@
1 +{
2 + "name": "CSB Pets",
3 + "category": "fun",
4 + "tags": "pets, follow, cosmetic",
5 + "image": "",
6 + "original_author": "",
7 + "original_url": "",
8 + "license": "GPL-3.0",
9 + "title": "CSB Pets",
10 + "short_desc": "A cosmetic pet model that smoothly follows the player, picked from a menu and remembered per SteamID in nVault.",
11 + "version": "1.0.0",
12 + "amxx_min": "1.9",
13 + "amxx_compile_default": "1.9",
14 + "rehlds_ok": true,
15 + "hlds_ok": true,
16 + "regamedll_required": false,
17 + "metamod_flavor": "any",
18 + "reapi_required": false,
19 + "modules": "fakemeta,nvault",
20 + "install_notes": "1. Enable the fakemeta and nvault modules in addons/amxmodx/configs/modules.ini\n2. Put csb_pets.amxx in addons/amxmodx/plugins/ and add it to plugins.ini\n3. Change map",
21 + "known_conflicts": "The bundled model paths (scientist, chicken, hgrunt) must exist on the server; edit the list otherwise.",
22 + "cvars": [
23 + {
24 + "name": "csb_pets_enabled",
25 + "default": "1",
26 + "description": "Enable or disable pets."
27 + },
28 + {
29 + "name": "csb_pets_speed",
30 + "default": "0.25",
31 + "description": "Follow interpolation factor per tick (0-1)."
32 + }
33 + ],
34 + "commands": [
35 + {
36 + "name": "say /pet",
37 + "access": "",
38 + "description": "Open the pet selection menu."
39 + }
40 + ],
41 + "main": "addons/amxmodx/scripting/csb_pets.sma"
42 +}
0 43