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
}