Sunucu tanitimi

Initial release 1.0.0

Browse Source
1.0.0 - Initial release.
Daemon666 committed commit 02163f2ab54eed735af320d4c6dfd57d96962e8b
4 changed files with 275 additions and 0 deletions
+3 -0 CHANGELOG.md A
@@ -0,0 +1,3 @@
1 +## 1.0.0 (2025-05-21)
2 +
3 +1.0.0 - Initial release.
+1 -0 README.md A
@@ -0,0 +1 @@
1 +<p><strong>CSB Grappling Hook</strong> gives players a Spider-Man style grapple bound to a key. Pressing <code>+hook</code> traces from your eyes along your aim to the first solid surface within <code>csb_hook_range</code>; if it hits, a laser beam is drawn to the anchor and you are pulled toward it by setting your velocity every frame in <code>PlayerPreThink</code>. Release the key (or arrive) to detach, which starts a short cooldown.</p><p>Inspired by the classic Hook plugin. Independent GPL re-implementation; no original code is reused.</p><h2>Features</h2><ul><li><code>bind KEY +hook</code> &mdash; grapple to whatever your crosshair is on.</li><li>Max range and pull speed are cvars; a per-use cooldown prevents spam.</li><li>Laser beam drawn to the anchor point while hooking.</li><li>Optional VIP/flag gating via <code>csb_hook_viponly</code>.</li></ul><h2>Installation</h2><ol><li>Enable the <code>fakemeta</code> module in <code>modules.ini</code>.</li><li>Compile <code>csb_grappling_hook.sma</code>, copy it to <code>addons/amxmodx/plugins/</code> and add it to <code>plugins.ini</code>.</li><li>Change the map, then <code>bind mouse4 +hook</code>.</li></ol>
+214 -0 addons/amxmodx/scripting/csb_grappling_hook.sma A
@@ -0,0 +1,214 @@
1 +/*
2 + * CSB Grappling Hook
3 + * Copyright (C) 2026 counter-strike-boost.com
4 + *
5 + * A grappling hook bound to +hook. It traces from the player's eyes along their
6 + * aim to the first solid surface within range, anchors there, draws a laser beam
7 + * to the anchor and pulls the player toward it by setting pev_velocity every
8 + * frame in PlayerPreThink until they release the key or arrive. Includes a max
9 + * range, a per-use cooldown and optional VIP/flag gating.
10 + *
11 + * Inspired by the classic Hook plugin. Independent GPL re-implementation; no
12 + * original code is reused.
13 + *
14 + * This program is free software: you can redistribute it and/or modify it under
15 + * the terms of the GNU General Public License as published by the Free Software
16 + * Foundation, either version 3 of the License, or (at your option) any later
17 + * version. It is distributed in the hope that it will be useful, but WITHOUT
18 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19 + * FOR A PARTICULAR PURPOSE. See <https://www.gnu.org/licenses/> for details.
20 + */
21 +
22 +#include <amxmodx>
23 +#include <fakemeta>
24 +
25 +new const PLUGIN[] = "CSB Grappling Hook"
26 +new const VERSION[] = "1.0.0"
27 +new const AUTHOR[] = "counter-strike-boost.com"
28 +
29 +#define ACCESS_FLAG ADMIN_LEVEL_H
30 +
31 +#if !defined SVC_TEMPENTITY
32 + #define SVC_TEMPENTITY 23
33 +#endif
34 +#define TE_BEAMPOINTS 0
35 +
36 +new g_pEnabled, g_pRange, g_pPull, g_pCooldown, g_pVipOnly
37 +
38 +new bool:g_bHooking[33]
39 +new Float:g_fHook[33][3]
40 +new Float:g_fNextHook[33]
41 +new g_iBeamSpr
42 +
43 +public plugin_init()
44 +{
45 + register_plugin(PLUGIN, VERSION, AUTHOR)
46 +
47 + g_pEnabled = register_cvar("csb_hook_enabled", "1")
48 + g_pRange = register_cvar("csb_hook_range", "1500")
49 + g_pPull = register_cvar("csb_hook_pull", "700")
50 + g_pCooldown = register_cvar("csb_hook_cooldown", "3.0")
51 + g_pVipOnly = register_cvar("csb_hook_viponly", "1")
52 +
53 + register_clcmd("+hook", "cmdHookStart")
54 + register_clcmd("-hook", "cmdHookStop")
55 +
56 + register_forward(FM_PlayerPreThink, "fwPreThink")
57 +}
58 +
59 +public plugin_precache()
60 +{
61 + g_iBeamSpr = precache_model("sprites/laserbeam.spr")
62 +}
63 +
64 +public client_putinserver(id)
65 +{
66 + g_bHooking[id] = false
67 + g_fNextHook[id] = 0.0
68 +}
69 +
70 +public client_disconnected(id)
71 +{
72 + g_bHooking[id] = false
73 +}
74 +
75 +bool:hasAccess(id)
76 +{
77 + if (!get_pcvar_num(g_pVipOnly))
78 + return true
79 +
80 + return (get_user_flags(id) & ACCESS_FLAG) != 0
81 +}
82 +
83 +public cmdHookStart(id)
84 +{
85 + if (!get_pcvar_num(g_pEnabled) || !is_user_alive(id))
86 + return PLUGIN_HANDLED
87 +
88 + if (!hasAccess(id))
89 + {
90 + client_print(id, print_chat, "[CSB] The grappling hook is a VIP feature.")
91 + return PLUGIN_HANDLED
92 + }
93 +
94 + if (get_gametime() < g_fNextHook[id])
95 + {
96 + new left = floatround(g_fNextHook[id] - get_gametime(), floatround_ceil)
97 + client_print(id, print_chat, "[CSB] Hook on cooldown (%d s).", left)
98 + return PLUGIN_HANDLED
99 + }
100 +
101 + static Float:fStart[3], Float:fOfs[3], Float:fAng[3], Float:fFwd[3], Float:fEnd[3]
102 + pev(id, pev_origin, fStart)
103 + pev(id, pev_view_ofs, fOfs)
104 + fStart[0] += fOfs[0]
105 + fStart[1] += fOfs[1]
106 + fStart[2] += fOfs[2]
107 +
108 + pev(id, pev_v_angle, fAng)
109 + angle_vector(fAng, ANGLEVECTOR_FORWARD, fFwd)
110 +
111 + new Float:range = get_pcvar_float(g_pRange)
112 + fEnd[0] = fStart[0] + fFwd[0] * range
113 + fEnd[1] = fStart[1] + fFwd[1] * range
114 + fEnd[2] = fStart[2] + fFwd[2] * range
115 +
116 + engfunc(EngFunc_TraceLine, fStart, fEnd, IGNORE_MONSTERS, id, 0)
117 +
118 + static Float:fFrac, Float:fHit[3]
119 + get_tr2(0, TR_flFraction, fFrac)
120 + get_tr2(0, TR_vecEndPos, fHit)
121 +
122 + if (fFrac >= 1.0)
123 + {
124 + client_print(id, print_chat, "[CSB] Nothing in hook range.")
125 + return PLUGIN_HANDLED
126 + }
127 +
128 + g_fHook[id][0] = fHit[0]
129 + g_fHook[id][1] = fHit[1]
130 + g_fHook[id][2] = fHit[2]
131 + g_bHooking[id] = true
132 + return PLUGIN_HANDLED
133 +}
134 +
135 +public cmdHookStop(id)
136 +{
137 + if (g_bHooking[id])
138 + {
139 + g_bHooking[id] = false
140 + g_fNextHook[id] = get_gametime() + get_pcvar_float(g_pCooldown)
141 + }
142 + return PLUGIN_HANDLED
143 +}
144 +
145 +public fwPreThink(id)
146 +{
147 + if (!g_bHooking[id])
148 + return FMRES_IGNORED
149 +
150 + if (!is_user_alive(id))
151 + {
152 + g_bHooking[id] = false
153 + return FMRES_IGNORED
154 + }
155 +
156 + static Float:fOrigin[3], Float:fDir[3]
157 + pev(id, pev_origin, fOrigin)
158 +
159 + fDir[0] = g_fHook[id][0] - fOrigin[0]
160 + fDir[1] = g_fHook[id][1] - fOrigin[1]
161 + fDir[2] = g_fHook[id][2] - fOrigin[2]
162 +
163 + new Float:dist = vector_distance(fOrigin, g_fHook[id])
164 +
165 + if (dist < 64.0)
166 + {
167 + g_bHooking[id] = false
168 + g_fNextHook[id] = get_gametime() + get_pcvar_float(g_pCooldown)
169 + return FMRES_IGNORED
170 + }
171 +
172 + if (dist > 0.0)
173 + {
174 + fDir[0] /= dist
175 + fDir[1] /= dist
176 + fDir[2] /= dist
177 + }
178 +
179 + new Float:pull = get_pcvar_float(g_pPull)
180 +
181 + static Float:fVel[3]
182 + fVel[0] = fDir[0] * pull
183 + fVel[1] = fDir[1] * pull
184 + fVel[2] = fDir[2] * pull
185 + set_pev(id, pev_velocity, fVel)
186 +
187 + drawBeam(fOrigin, g_fHook[id])
188 + return FMRES_IGNORED
189 +}
190 +
191 +drawBeam(const Float:from[3], const Float:to[3])
192 +{
193 + message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
194 + write_byte(TE_BEAMPOINTS)
195 + write_coord(floatround(from[0]))
196 + write_coord(floatround(from[1]))
197 + write_coord(floatround(from[2]))
198 + write_coord(floatround(to[0]))
199 + write_coord(floatround(to[1]))
200 + write_coord(floatround(to[2]))
201 + write_short(g_iBeamSpr)
202 + write_byte(0)
203 + write_byte(0)
204 + write_byte(1)
205 + write_byte(12)
206 + write_byte(0)
207 + write_byte(200)
208 + write_byte(200)
209 + write_byte(255)
210 + write_byte(200)
211 + write_byte(0)
212 + message_end()
213 + return;
214 +}
+57 -0 csb.json A
@@ -0,0 +1,57 @@
1 +{
2 + "name": "CSB Grappling Hook",
3 + "category": "movement",
4 + "tags": "hook, grapple, movement",
5 + "image": "",
6 + "original_author": "",
7 + "original_url": "",
8 + "license": "GPL-3.0",
9 + "title": "CSB Grappling Hook",
10 + "short_desc": "A +hook grappling hook: traces to a surface, draws a beam and pulls the player toward it, with range, cooldown and VIP gating.",
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",
20 + "install_notes": "1. Enable the fakemeta module in addons/amxmodx/configs/modules.ini\n2. Put csb_grappling_hook.amxx in addons/amxmodx/plugins/ and add it to plugins.ini\n3. Change map\n4. bind a key to +hook",
21 + "known_conflicts": "Other plugins that overwrite pev_velocity every frame (some anti-cheats, other movement mods) will fight the pull.",
22 + "cvars": [
23 + {
24 + "name": "csb_hook_enabled",
25 + "default": "1",
26 + "description": "Enable or disable the grappling hook."
27 + },
28 + {
29 + "name": "csb_hook_range",
30 + "default": "1500",
31 + "description": "Maximum hook range in units."
32 + },
33 + {
34 + "name": "csb_hook_pull",
35 + "default": "700",
36 + "description": "Pull speed applied toward the anchor."
37 + },
38 + {
39 + "name": "csb_hook_cooldown",
40 + "default": "3.0",
41 + "description": "Seconds of cooldown after releasing the hook."
42 + },
43 + {
44 + "name": "csb_hook_viponly",
45 + "default": "1",
46 + "description": "Require the VIP/reservation flag (t) to use the hook."
47 + }
48 + ],
49 + "commands": [
50 + {
51 + "name": "+hook",
52 + "access": "t (ADMIN_LEVEL_H) when viponly=1",
53 + "description": "Hold to grapple toward your crosshair."
54 + }
55 + ],
56 + "main": "addons/amxmodx/scripting/csb_grappling_hook.sma"
57 +}
0 58