View difference between Paste ID: gsMvHkNw and
SHOW:
|
|
- or go back to the newest paste.
1 | - | |
1 | + | #include <amxmodx> |
2 | #include <engine> | |
3 | #include <fakemeta_util> | |
4 | #include <fun> | |
5 | #include <hamsandwich> | |
6 | #include <nfvault> | |
7 | #include <zombieplague> | |
8 | ||
9 | #pragma semicolon 1 | |
10 | ||
11 | #define DISTANCE 120 | |
12 | ||
13 | new g_Zombie[33]; | |
14 | new bool:g_bSolid[33]; | |
15 | new bool:g_bHasSemiclip[33]; | |
16 | new Float:g_fOrigin[33][3]; | |
17 | new Float:g_fSpawnTime[33]; | |
18 | new stuck[33]; | |
19 | ||
20 | enum SEMICLIP{ | |
21 | SEMICLIP_NULL, | |
22 | SEMICLIP_NONE, | |
23 | SEMICLIP_AUTO, | |
24 | SEMICLIP_ACTIVE, | |
25 | } | |
26 | new SEMICLIP:SemiClipType[33]; | |
27 | new gNotify[33]; | |
28 | ||
29 | new bool:g_bSemiclipEnabled; | |
30 | ||
31 | new g_iForwardId[3]; | |
32 | new g_iMaxPlayers; | |
33 | new g_iCvar[3]; | |
34 | ||
35 | public plugin_init( ) | |
36 | { | |
37 | register_plugin( "(Team-)Semiclip", "1.2", "SchlumPF*" ); | |
38 | ||
39 | g_iCvar[0] = register_cvar( "semiclip_enabled", "1" ); | |
40 | g_iCvar[2] = register_cvar( "semiclip_transparancy", "1" ); | |
41 | set_task(0.1,"checkstuck",0,"",0,"b"); | |
42 | ||
43 | register_forward( FM_ClientCommand, "fwdClientCommand" ); | |
44 | ||
45 | RegisterHam(Ham_Spawn, "player", "fw_PlayerSpawn"); | |
46 | RegisterHam(Ham_Killed, "player", "fw_PlayerKilled"); | |
47 | ||
48 | register_touch("player", "player", "player_touch"); | |
49 | register_clcmd("say /semiclip","semiclip_menu", 0, "- select semiclip mode"); | |
50 | ||
51 | if( get_pcvar_num( g_iCvar[0] ) ) | |
52 | { | |
53 | g_iForwardId[0] = register_forward( FM_PlayerPreThink, "fwdPlayerPreThink" ); | |
54 | g_iForwardId[1] = register_forward( FM_PlayerPostThink, "fwdPlayerPostThink" ); | |
55 | g_iForwardId[2] = register_forward( FM_AddToFullPack, "fwdAddToFullPack_Post", 1 ); | |
56 | ||
57 | g_bSemiclipEnabled = true; | |
58 | } | |
59 | else | |
60 | g_bSemiclipEnabled = false; | |
61 | } | |
62 | ||
63 | public client_connect( id ) | |
64 | { | |
65 | g_iMaxPlayers = max( id, g_iMaxPlayers ); | |
66 | SemiClipType[id] = SEMICLIP_NULL; | |
67 | } | |
68 | public client_authorized( id ) | |
69 | { | |
70 | SemiClipType[id] = SEMICLIP:player_get_num( id, "SemiClip", "Type" ); | |
71 | gNotify[id] = 0; | |
72 | } | |
73 | public client_disconnect( id ) | |
74 | { | |
75 | if( id == g_iMaxPlayers ) | |
76 | { | |
77 | new old = g_iMaxPlayers; | |
78 | for( new i=1; i<old; i++ ) | |
79 | { | |
80 | if( is_user_connected(i) ) | |
81 | g_iMaxPlayers = i; | |
82 | } | |
83 | } | |
84 | } | |
85 | ||
86 | public player_touch(id, tid) | |
87 | { | |
88 | if( SemiClipType[id] == SEMICLIP_NULL ) | |
89 | semiclip_menu(id); | |
90 | ||
91 | if( SemiClipType[tid] == SEMICLIP_NULL ) | |
92 | semiclip_menu(tid); | |
93 | } | |
94 | ||
95 | public semiclip_menu(id) | |
96 | { | |
97 | new trash; | |
98 | if( player_menu_info(id, trash, trash) ) | |
99 | return; | |
100 | ||
101 | new data[32], menu = menu_create( "Select Your SemiClip Mode. Say /semiclip to reselect", "semiclip_handler" ); | |
102 | ||
103 | formatex( data, 31, "%d", SEMICLIP_AUTO ); | |
104 | menu_additem(menu, "\yAuto SemiClip \w(careful around doors)", data); | |
105 | ||
106 | formatex( data, 31, "%d", SEMICLIP_ACTIVE ); | |
107 | menu_additem(menu, "\yActive SemiClip \w(press +use to activate)", data); | |
108 | ||
109 | formatex( data, 31, "%d", SEMICLIP_NONE ); | |
110 | menu_additem(menu, "\yNo SemiClip \w(people can block you)", data); | |
111 | ||
112 | menu_addtext(menu, "^n\ySemiClip is used to prevent blocking.^n\wIf you don't know what to pick, just pick \yAuto SemiClip\w.", 0); | |
113 | ||
114 | menu_display(id, menu); | |
115 | } | |
116 | public semiclip_handler(id, menu, item) | |
117 | { | |
118 | if( item == MENU_EXIT ) | |
119 | { | |
120 | menu_destroy(menu); | |
121 | return PLUGIN_HANDLED; | |
122 | } | |
123 | ||
124 | new access, data[128], iName[1], callback; | |
125 | menu_item_getinfo(menu, item, access, data,127, iName,0, callback); | |
126 | menu_destroy(menu); | |
127 | ||
128 | switch( (SemiClipType[id] = SEMICLIP:str_to_num( data )) ) | |
129 | { | |
130 | case SEMICLIP_NONE: | |
131 | { | |
132 | client_print(id, print_chat, "[SemiClip] No SemiClip. Players will always be solid." ); | |
133 | } | |
134 | case SEMICLIP_AUTO: | |
135 | { | |
136 | client_print(id, print_chat, "[SemiClip] Auto SemiClip. SemiClip will auto activate. Be careful around doors." ); | |
137 | } | |
138 | case SEMICLIP_ACTIVE: | |
139 | { | |
140 | client_print(id, print_chat, "[SemiClip] SemiClip Active. Press +use to activate semiclip." ); | |
141 | } | |
142 | } | |
143 | client_print(id, print_chat, "[SemiClip] Say /semiclip to reselect your SemiClip Mode." ); | |
144 | ||
145 | player_set_num( id, "SemiClip", "Type", _:SemiClipType[id] ); | |
146 | ||
147 | return PLUGIN_HANDLED; | |
148 | } | |
149 | ||
150 | public fw_PlayerSpawn(id) | |
151 | { | |
152 | // Not alive or didn't join a team yet | |
153 | if( !is_user_alive(id) ) | |
154 | return; | |
155 | g_fSpawnTime[id] = get_gametime(); | |
156 | ||
157 | if( !gNotify[id] && SemiClipType[id] != SEMICLIP_NULL ) | |
158 | { | |
159 | gNotify[id] = 1; | |
160 | client_print(id, print_chat, "[SemiClip] Say /semiclip to reselect your SemiClip Mode." ); | |
161 | } | |
162 | } | |
163 | public fw_PlayerKilled(victim, attacker, shouldgib) | |
164 | { | |
165 | if( get_gametime() - g_fSpawnTime[victim] <= 10.0 ) | |
166 | { | |
167 | new Float:hp; | |
168 | pev( victim, pev_health, hp ); | |
169 | if( hp <= 0 ) | |
170 | { | |
171 | set_pev( victim, pev_health, 100.0 ); | |
172 | } | |
173 | ||
174 | new Float:origin[3], Float:temp; | |
175 | pev( victim, pev_origin, origin ); | |
176 | temp = random_float(-100.0,100.0); | |
177 | origin[0] += temp; | |
178 | origin[1] += (temp > 0.0) ? (100.0 - temp) : (100.0 + temp); | |
179 | origin[2] += 100.0; | |
180 | fm_entity_set_origin(victim, origin); | |
181 | ||
182 | client_print(victim, print_center, "Moved to avoid Spawn Kill"); | |
183 | ||
184 | _UnStuck(victim, true); | |
185 | return HAM_SUPERCEDE; | |
186 | } | |
187 | return HAM_IGNORED; | |
188 | } | |
189 | ||
190 | public fwdPlayerPreThink( plr ) | |
191 | { | |
192 | static id, last_think; | |
193 | ||
194 | if( last_think > plr ) | |
195 | { | |
196 | for( id = 1 ; id <= g_iMaxPlayers ; id++ ) | |
197 | { | |
198 | if( is_user_alive( id ) ) | |
199 | { | |
200 | g_Zombie[id] = zp_get_user_zombie( id ); | |
201 | ||
202 | g_bSolid[id] = pev( id, pev_solid ) == SOLID_SLIDEBOX ? true : false; | |
203 | pev( id, pev_origin, g_fOrigin[id] ); | |
204 | } | |
205 | else | |
206 | g_bSolid[id] = false; | |
207 | } | |
208 | } | |
209 | ||
210 | last_think = plr; | |
211 | ||
212 | switch( SemiClipType[plr] ) | |
213 | { | |
214 | case SEMICLIP_NULL, SEMICLIP_NONE: | |
215 | { | |
216 | return FMRES_IGNORED; | |
217 | } | |
218 | case SEMICLIP_AUTO: | |
219 | { | |
220 | } | |
221 | case SEMICLIP_ACTIVE: | |
222 | { | |
223 | if( !(entity_get_int(plr, EV_INT_button) & IN_USE) ) | |
224 | return FMRES_IGNORED; | |
225 | } | |
226 | } | |
227 | ||
228 | if( g_bSolid[plr] && !g_Zombie[plr] ) | |
229 | { | |
230 | for( id = 1 ; id <= g_iMaxPlayers ; id++ ) | |
231 | { | |
232 | if( g_bSolid[id] && get_distance_f( g_fOrigin[plr], g_fOrigin[id] ) <= DISTANCE && id != plr ) | |
233 | { | |
234 | if( g_Zombie[plr] != g_Zombie[id] ) | |
235 | return FMRES_IGNORED; | |
236 | ||
237 | set_pev( id, pev_solid, SOLID_NOT ); | |
238 | g_bHasSemiclip[id] = true; | |
239 | } | |
240 | } | |
241 | } | |
242 | ||
243 | return FMRES_IGNORED; | |
244 | } | |
245 | ||
246 | public fwdPlayerPostThink( plr ) | |
247 | { | |
248 | static id; | |
249 | ||
250 | for( id = 1 ; id <= g_iMaxPlayers ; id++ ) | |
251 | { | |
252 | if( g_bHasSemiclip[id] ) | |
253 | { | |
254 | set_pev( id, pev_solid, SOLID_SLIDEBOX ); | |
255 | g_bHasSemiclip[id] = false; | |
256 | } | |
257 | } | |
258 | } | |
259 | ||
260 | public fwdAddToFullPack_Post( es_handle, e, ent, host, hostflags, player, pset ) | |
261 | { | |
262 | if( player ) | |
263 | { | |
264 | if( g_bSolid[host] && g_bSolid[ent] && !g_Zombie[host] && !g_Zombie[ent] ) | |
265 | { | |
266 | switch( SemiClipType[host] ) | |
267 | { | |
268 | case SEMICLIP_NULL, SEMICLIP_NONE: | |
269 | { | |
270 | return FMRES_IGNORED; | |
271 | } | |
272 | case SEMICLIP_AUTO: | |
273 | { | |
274 | } | |
275 | case SEMICLIP_ACTIVE: | |
276 | { | |
277 | if( !(entity_get_int(host, EV_INT_button) & IN_USE) ) | |
278 | return FMRES_IGNORED; | |
279 | } | |
280 | } | |
281 | ||
282 | if( get_distance_f( g_fOrigin[host], g_fOrigin[ent] ) <= DISTANCE ) | |
283 | { | |
284 | set_es( es_handle, ES_Solid, SOLID_NOT ); // makes semiclip flawless | |
285 | ||
286 | switch( get_pcvar_num( g_iCvar[2] ) ) | |
287 | { | |
288 | case 1: | |
289 | { | |
290 | set_es( es_handle, ES_RenderMode, kRenderTransAlpha ); | |
291 | set_es( es_handle, ES_RenderAmt, 85 ); | |
292 | } | |
293 | case 2: | |
294 | { | |
295 | set_es( es_handle, ES_Effects, EF_NODRAW ); | |
296 | set_es( es_handle, ES_Solid, SOLID_NOT ); | |
297 | } | |
298 | } | |
299 | } | |
300 | } | |
301 | } | |
302 | ||
303 | return FMRES_IGNORED; | |
304 | } | |
305 | ||
306 | // is there a better way to detect changings of g_iCvar[0]? | |
307 | public fwdClientCommand( plr ) | |
308 | { | |
309 | // use the forwards just when needed, for good performance | |
310 | if( !get_pcvar_num( g_iCvar[0] ) && g_bSemiclipEnabled ) | |
311 | { | |
312 | unregister_forward( FM_PlayerPreThink, g_iForwardId[0] ); | |
313 | unregister_forward( FM_PlayerPostThink, g_iForwardId[1] ); | |
314 | unregister_forward( FM_AddToFullPack, g_iForwardId[2], 1 ); | |
315 | ||
316 | g_bSemiclipEnabled = false; | |
317 | } | |
318 | else if( get_pcvar_num( g_iCvar[0] ) && !g_bSemiclipEnabled ) | |
319 | { | |
320 | g_iForwardId[0] = register_forward( FM_PlayerPreThink, "fwdPlayerPreThink" ); | |
321 | g_iForwardId[1] = register_forward( FM_PlayerPostThink, "fwdPlayerPostThink" ); | |
322 | g_iForwardId[2] = register_forward( FM_AddToFullPack, "fwdAddToFullPack_Post", 1 ); | |
323 | ||
324 | g_bSemiclipEnabled = true; | |
325 | } | |
326 | } | |
327 | ||
328 | public checkstuck() | |
329 | { | |
330 | static players[32], pnum, player, i, bool:detect_players; | |
331 | get_players(players, pnum); | |
332 | static Float:origin[3], hull; | |
333 | for( i=0; i<pnum; i++ ) | |
334 | { | |
335 | player = players[i]; | |
336 | if( is_user_alive(player) ) | |
337 | { | |
338 | if( !g_bSolid[player] ) | |
339 | { | |
340 | stuck[player] = 0; | |
341 | continue; | |
342 | } | |
343 | ||
344 | pev(player, pev_origin, origin); | |
345 | hull = pev(player, pev_flags) & FL_DUCKING ? HULL_HEAD : HULL_HUMAN; | |
346 | if( !is_hull_vacant(origin, hull,player) && !get_user_noclip(player) ) | |
347 | { | |
348 | ++stuck[player]; | |
349 | if( stuck[player] >= 10 ) | |
350 | { | |
351 | detect_players = true; | |
352 | if( !g_Zombie[player] ) | |
353 | { | |
354 | switch( SemiClipType[player] ) | |
355 | { | |
356 | case SEMICLIP_NULL, SEMICLIP_NONE: | |
357 | { | |
358 | detect_players = true; | |
359 | } | |
360 | case SEMICLIP_AUTO: | |
361 | { | |
362 | detect_players = false; | |
363 | } | |
364 | case SEMICLIP_ACTIVE: | |
365 | { | |
366 | if( entity_get_int(player, EV_INT_button) & IN_USE ) | |
367 | detect_players = false; | |
368 | else | |
369 | detect_players = true; | |
370 | } | |
371 | } | |
372 | } | |
373 | ||
374 | if( _UnStuck( player, detect_players ) == 1 ) | |
375 | { | |
376 | effects(player); | |
377 | } | |
378 | stuck[player] = 0; | |
379 | } | |
380 | } | |
381 | else | |
382 | { | |
383 | stuck[player] = 0; | |
384 | } | |
385 | } | |
386 | } | |
387 | } | |
388 | stock _UnStuck(id, bool:detect_players) | |
389 | { | |
390 | new hullsize = (pev(id, pev_flags) & FL_DUCKING) ? HULL_HEAD : HULL_HUMAN; | |
391 | ||
392 | new Float:origin[3], tr = 0; | |
393 | pev(id, pev_origin, origin); | |
394 | ||
395 | if( detect_players ) | |
396 | engfunc(EngFunc_TraceHull, origin, origin, 0, hullsize, id, tr); | |
397 | else | |
398 | engfunc(EngFunc_TraceHull, origin, origin, IGNORE_MONSTERS, hullsize, id, tr); | |
399 | ||
400 | if( !get_tr2(tr,TR_StartSolid) && !get_tr2(tr,TR_AllSolid) && get_tr2(tr,TR_InOpen) ) | |
401 | return -1; | |
402 | ||
403 | new Float:new_origin[3], distance, i, trace, Float:fraction; | |
404 | ||
405 | const UNSTUCK_START_DISTANCE = 32; | |
406 | const UNSTUCK_MAX_ATTEMPTS = 128; | |
407 | ||
408 | distance = UNSTUCK_START_DISTANCE; | |
409 | ||
410 | while( distance < 1000 ) { // 1000 is just incase, should never get anywhere near that | |
411 | for( i = 0; i < UNSTUCK_MAX_ATTEMPTS; i++ ){ | |
412 | new_origin[0] = random_float(origin[0]-distance, origin[0]+distance); | |
413 | new_origin[1] = random_float(origin[1]-distance, origin[1]+distance); | |
414 | new_origin[2] = random_float(origin[2]-distance, origin[2]+distance); | |
415 | ||
416 | if ( fm_trace_hull(new_origin, hullsize, id) == 0 ) { | |
417 | engfunc(EngFunc_TraceLine, origin, new_origin, IGNORE_MONSTERS, id, trace); | |
418 | get_tr2(trace, TR_flFraction, fraction); | |
419 | if( fraction == 1.0 ) | |
420 | { | |
421 | fm_entity_set_origin(id, new_origin); | |
422 | return 1; | |
423 | } | |
424 | } | |
425 | } | |
426 | distance += UNSTUCK_START_DISTANCE; | |
427 | } | |
428 | ||
429 | return 0; | |
430 | } | |
431 | bool:is_hull_vacant(const Float:origin[3], hull,id) { | |
432 | static tr; | |
433 | engfunc(EngFunc_TraceHull, origin, origin, 0, hull, id, tr); | |
434 | if( !get_tr2(tr, TR_StartSolid) || !get_tr2(tr, TR_AllSolid) ) //get_tr2(tr, TR_InOpen)) | |
435 | return true; | |
436 | ||
437 | return false; | |
438 | } | |
439 | effects(id) | |
440 | { | |
441 | set_hudmessage(255,150,50, -1.0, 0.65, 0, 6.0, 1.5,0.1,0.7); // HUDMESSAGE | |
442 | show_hudmessage(id,"Automatic Unstuck!"); // HUDMESSAGE | |
443 | message_begin(MSG_ONE_UNRELIABLE,105,{0,0,0},id ); | |
444 | write_short(1<<10); // fade lasts this long duration | |
445 | write_short(1<<10); // fade lasts this long hold time | |
446 | write_short(1<<1); // fade type (in / out) | |
447 | write_byte(20); // fade red | |
448 | write_byte(255); // fade green | |
449 | write_byte(255); // fade blue | |
450 | write_byte(255); // fade alpha | |
451 | message_end(); | |
452 | client_cmd(id,"spk fvox/blip.wav"); | |
453 | } |