[Half-Life AMXX] / mpbhops.sma Repository:
ViewVC logotype

Annotation of /mpbhops.sma

Parent Directory Parent Directory | Revision Log Revision Log


Revision 25 - (view) (download)

1 : ian 1 /*
2 :     MultiPlayer Bunny Hops v1.2
3 :     Copyright (C) 2007 Ian (Juan) Cammarata
4 :    
5 : ian 25 This program is free software: you can redistribute it and/or modify
6 :     it under the terms of the GNU Affero General Public License as
7 :     published by the Free Software Foundation, either version 3 of the
8 :     License, or (at your option) any later version.
9 : ian 1
10 : ian 25 This program is distributed in the hope that it will be useful,
11 :     but WITHOUT ANY WARRANTY; without even the implied warranty of
12 :     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 :     GNU Affero General Public License for more details.
14 : ian 1
15 : ian 25 You should have received a copy of the GNU Affero General Public License
16 :     along with this program. If not, see <http://www.gnu.org/licenses/>.
17 : ian 1 --------------------------------------------------------------------------------
18 :    
19 :     http://ian.cammarata.us/projects/mpbhops
20 :     Sep 23 14:06
21 :    
22 :    
23 :     Description:
24 :     This plugin allows clients to jump across sections of bhops without the blocks being triggered. The blocks stay in place all the time making it much more suitable for multiplayer. If a player tries to stand on or jump on a block twice, then they are teleported off to the side. It is intended for bhop maps (Not BCM plugins), and also provides semiclip detection for map blocks as well as BCM blocks.
25 :    
26 :     See it in Action:
27 :     1337bunnies server: 66.55.131.63:27015
28 :    
29 :     Commands:
30 :     Not Applicable.
31 :    
32 :    
33 :     Cvars:
34 :     mpbhops <0|1> Disables/enables bhop handling.
35 :    
36 :    
37 :     Requirements:
38 :     Engine module
39 :    
40 :    
41 :     Notes:
42 :     This is a stand alone version of the code from my climb plugin, for those who don't want all the features it offers.
43 :     http://ian.cammarata.us/projects/climb
44 :    
45 :    
46 :     Credits:
47 :     Thanks to Lola for letting me use her awesome server for testing purposes.
48 :     http://1337bunnies.com
49 :     66.55.131.63:27015
50 :     Thanks to r33d and Woofie for testing.
51 :    
52 :    
53 :     Supported Languages:
54 :     Not Applicable.
55 :    
56 :    
57 :     Change Log:
58 :     Key (+ added | - removed | c changed | f fixed)
59 :    
60 :     v1.2 (SEPT 23, 2007)
61 :     +: Semiclip support for BCM plugins by Emp` and Necro.
62 :    
63 :     v1.1 (SEPT 23, 2007)
64 :     c: Increased fail check time from 0.1 seconds to 0.2 seconds. Should fix some people getting fail when doing a standupbhop.
65 :     f: Teleporting to world origin rarely when hopping back and forth between func_door and world brush.
66 :     f: Touch is detected even when clients aren't solid. (No more semiclip exploit)
67 :    
68 :     v1.0 (SEPT 21, 2007)
69 :     !: Initial release
70 :     */
71 :    
72 :     #include <amxmodx>
73 :     #include <engine>
74 :     #include <fakemeta>
75 :    
76 :     #define VERSION "1.2"
77 :    
78 :     #define MAX_DOORS 500
79 :    
80 :     #define TSK_BHOP 50
81 :     #define TSK_CLEAR_FAIL 100
82 :    
83 :     //func_doors[x]{ id, speed, angles }
84 :     new door_count = 0, func_doors[MAX_DOORS][3], Float:door_tp_pos[MAX_DOORS][3]
85 :     new bhop_failid[32], bool:bhop_fail[32]
86 :     new p_enabled
87 :     new MAXPLAYERS
88 :    
89 :     public plugin_init( )
90 :     {
91 :     MAXPLAYERS = get_maxplayers( )
92 :    
93 :     register_plugin( "MP Bhops", VERSION, "Ian Cammarata" )
94 :     register_cvar( "mpbhops_version", VERSION, FCVAR_SERVER )
95 :    
96 :     p_enabled = register_cvar( "mpbhops", "0", FCVAR_SERVER )
97 :     }
98 :    
99 :     public pfn_keyvalue( ent )
100 :     {
101 :     static last_ent
102 :     new class[31], key[31], val[31]
103 :     copy_keyvalue( class, 30, key, 30, val, 30 )
104 :    
105 :     if( ent != last_ent && func_doors[door_count][0] && door_count < MAX_DOORS )
106 :     door_count++
107 :    
108 :     if( equal( class, "func_door" ) )
109 :     {
110 :     if( ent != last_ent ) func_doors[door_count][0] = ent
111 :    
112 :     if( equal( key, "speed" ) )
113 :     func_doors[door_count][1] = str_to_num(val)
114 :     if( equal( key, "dmg" ) )
115 :     func_doors[door_count][0] = 0
116 :     if( equal( key, "angles" ) )
117 :     {
118 :     new angles[5]
119 :     parse( val, angles, 4 )
120 :     func_doors[door_count][2] = str_to_num( angles )
121 :     }
122 :     last_ent = ent
123 :     }
124 :    
125 :     return PLUGIN_CONTINUE
126 :     }
127 :    
128 :     public plugin_cfg( )
129 :     {
130 :     if( func_doors[door_count][0] && door_count < MAX_DOORS )
131 :     door_count++
132 :    
133 :     new ent, ent2, tmpstr[33]
134 :     new Float:dmins[3], Float:dmaxs[3]
135 :    
136 :     //Find tp spots for doors, in case they're used for bhop
137 :     for( new i = 0; i < door_count; i++ )
138 :     {
139 :     ent = func_doors[i][0]
140 :     if( !is_valid_ent( ent ) ) func_doors[i][0] = 0
141 :     else
142 :     {
143 :     entity_get_vector( ent, EV_VEC_mins, dmins )
144 :     entity_get_vector( ent, EV_VEC_maxs, dmaxs )
145 :    
146 :     new dwid = floatround( dmaxs[0] - dmins[0] )
147 :     new dlen = floatround( dmaxs[1] - dmins[1] )
148 :    
149 :     //If the door moves up, or is thin, remove it's id from the array
150 :     if( func_doors[i][2] < 0 || dwid < 24 || dlen < 24 )
151 :     func_doors[i][0] = 0
152 :     //Otherwise find a safe tp spot in case it's a bhop door
153 :     else
154 :     {
155 :     //If it has a targetname, change the id in array to targeter
156 :     entity_get_string( ent, EV_SZ_targetname, tmpstr, 32 )
157 :     if( strlen( tmpstr ) )
158 :     {
159 :     ent2 = find_ent_by_target( -1, tmpstr )
160 :     if( ent2 )
161 :     {
162 :     func_doors[i][0] = ent2
163 :    
164 :     //If targeter is a button, remove it's id from the array
165 :     entity_get_string( ent2, EV_SZ_classname, tmpstr, 32 )
166 :     if( equal( tmpstr, "func_button" ) )
167 :     func_doors[i][0] = 0
168 :     }
169 :     }
170 :    
171 :     new Float:tmpvec[3], Float:tmpvec2[3]
172 :    
173 :     new Float:dr_tc[3]
174 :     dr_tc[0] = ( dmaxs[0] + dmins[0] ) / 2
175 :     dr_tc[1] = ( dmaxs[1] + dmins[1] ) / 2
176 :     dr_tc[2] = dmaxs[2]
177 :    
178 :     tmpvec[0] = ( dmaxs[0] + dmins[0] ) / 2
179 :     tmpvec[1] = dmaxs[1] + 20
180 :     tmpvec[2] = dmaxs[2] + 20
181 :     trace_line( ent, dr_tc, tmpvec, tmpvec2 )
182 :     if( !trace_hull( tmpvec, HULL_HUMAN ) && tmpvec2[2] == tmpvec[2] )
183 :     door_tp_pos[i] = tmpvec
184 :     else
185 :     {
186 :     tmpvec[1] = dmins[1] - 20
187 :     trace_line( ent, dr_tc, tmpvec, tmpvec2 )
188 :     if( !trace_hull( tmpvec, HULL_HUMAN ) && tmpvec2[2] == tmpvec[2] )
189 :     door_tp_pos[i] = tmpvec
190 :     else
191 :     {
192 :     tmpvec[0] = dmaxs[0] + 20
193 :     tmpvec[1] = ( dmaxs[1] + dmins[1] ) / 2
194 :     trace_line( ent, dr_tc, tmpvec, tmpvec2 )
195 :     if( !trace_hull( tmpvec, HULL_HUMAN ) && tmpvec2[2] == tmpvec[2] )
196 :     door_tp_pos[i] = tmpvec
197 :     else
198 :     {
199 :     tmpvec[0] = dmins[0] - 20
200 :     door_tp_pos[i] = tmpvec
201 :     }
202 :     }
203 :     }
204 :     }
205 :     }
206 :     }
207 :     }
208 :    
209 :     //This is a semiclip fix
210 :     public client_PreThink( id )
211 :     {
212 :     //If they're on the ground and not solid...
213 :     if( ( pev( id, pev_flags ) & FL_ONGROUND ) && !pev( id, pev_solid ) )
214 :     {
215 :     new Float:orig[3]
216 :     entity_get_vector( id, EV_VEC_origin, orig )
217 :    
218 :     //do a hull trace 1 unit below their origin
219 :     orig[2] -= 1
220 :     engfunc( EngFunc_TraceHull, orig, orig, DONT_IGNORE_MONSTERS, HULL_HUMAN, id, 0 )
221 :     new ent = get_tr2( 0, TR_pHit )
222 :    
223 :     //if all we hit is world or another player, who cares, exit
224 :     if( ent <= MAXPLAYERS ) return PLUGIN_CONTINUE
225 :    
226 :     //if we hit a door in the array, send it to the handler then exit
227 :     new dpos = door_in_array( ent )
228 :     if( dpos > -1 )
229 :     {
230 :     bhop_check_fail( id, ent, dpos )
231 :     return PLUGIN_CONTINUE
232 :     }
233 :    
234 :     //if we hit a BCM entity, force touch so the BCM plugin can handle it
235 :     new class[32]
236 :     entity_get_string( ent, EV_SZ_classname, class, 31 )
237 :     if( equal( class, "bcm" ) || equal( class, "bm_block" ) )
238 :     fake_touch( ent, id )
239 :     }
240 :    
241 :     return PLUGIN_CONTINUE
242 :     }
243 :    
244 :     public pfn_touch( ent, id )
245 :     {
246 :     if( !get_pcvar_num( p_enabled ) || !ent || !id )
247 :     return PLUGIN_CONTINUE
248 :    
249 :     //Make sure id is player and ent is object
250 :     if( 0 < ent <= MAXPLAYERS )
251 :     {
252 :     new tmp = id
253 :     id = ent
254 :     ent = tmp
255 :     }
256 :     else if( !( 0 < id <= MAXPLAYERS ) )
257 :     return PLUGIN_CONTINUE
258 :    
259 :     //Bhop stuff
260 :     new dpos = door_in_array( ent )
261 :     if( dpos > -1 )
262 :     {
263 :     bhop_check_fail( id, ent, dpos )
264 :     return PLUGIN_HANDLED
265 :     }
266 :    
267 :     return PLUGIN_CONTINUE
268 :     }
269 :    
270 :     public bhop_check_fail( id, ent, dpos )
271 :     {
272 :     if( bhop_failid[id-1] != ent )
273 :     {
274 :     bhop_failid[id-1] = ent
275 :     bhop_fail[id-1] = false
276 :    
277 :     new tskid = TSK_BHOP + id
278 :     if( task_exists( tskid ) )
279 :     remove_task( tskid )
280 :     set_task( 0.2, "bhop_set_fail", tskid )
281 :     tskid = TSK_CLEAR_FAIL + id
282 :     if( task_exists( tskid ) )
283 :     remove_task( tskid )
284 :     set_task( 0.7, "bhop_clear_fail", tskid )
285 :     }
286 :     else if( bhop_fail[id-1] )
287 :     {
288 :     //Teleport to fail position
289 :     entity_set_vector( id, EV_VEC_velocity, Float:{0.0, 0.0, 0.0} )
290 :     entity_set_vector( id, EV_VEC_origin, door_tp_pos[dpos] )
291 :    
292 :     //Reset fail vars
293 :     bhop_failid[id-1] = 0
294 :     bhop_fail[id-1] = false
295 :     }
296 :     }
297 :    
298 :     public door_in_array( door )
299 :     {
300 :     for( new i = 0; i < door_count; i++ )
301 :     if( func_doors[i][0] == door )
302 :     return i
303 :     return -1
304 :     }
305 :    
306 :     public bhop_set_fail( tskid )
307 :     {
308 :     bhop_fail[ tskid - TSK_BHOP - 1 ] = true
309 :     return PLUGIN_HANDLED
310 :     }
311 :    
312 :     public bhop_clear_fail( tskid )
313 :     {
314 :     new id = tskid - TSK_CLEAR_FAIL
315 :     bhop_failid[id-1] = 0
316 :     bhop_fail[id-1] = false
317 :     return PLUGIN_HANDLED
318 :     }

Contact
ViewVC Help
Powered by ViewVC 1.0.4