Raised This Month: $51 Target: $400
 12% 

Bug on Multiplayer Bhop (SemiclipEx)


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
wAyz
Senior Member
Join Date: Feb 2010
Location: Germany
Old 05-20-2017 , 10:47   Bug on Multiplayer Bhop (SemiclipEx)
Reply With Quote #1

Hello,

So a friend had helped me to make a new version of mpbhops with the module semiclipex.
Unfortunately there's a weird bug, when i touch two or more blocks at once, they don't seem to trigger at all. Also attached a demo. Here's the code:


Code:
#define MAKE_DOORS_SILENT

#include <amxmodx>
#include <amxmisc>
#include <engine>
#include <fakemeta_util>
#include <hamsandwich>
#include <xs>
#include <SemiclipEx>

#if defined CHATCOLOR
#include <chatcolor>
#endif

new const VERSION[] = "1.1.4";

const Float:bhop_timeout = 1.0;

#pragma semicolon 1

#define SetIdBits(%1,%2)		%1 |= 1<<(%2 & 31)
#define ClearIdBits(%1,%2)	%1 &= ~( 1<<(%2 & 31) )
#define GetIdBits(%1,%2)		%1 &  1<<(%2 & 31)

#define SetEntBits(%1,%2)	%1[%2>>5] |=  1<<(%2 & 31)
#define ClearEntBits(%1,%2)	%1[%2>>5] &= ~( 1 << (%2 & 31) )
#define GetEntBits(%1,%2)	%1[%2>>5] &   1<<(%2 & 31)

enum _:BlocksClasses
{
	FUNC_DOOR,
	FUNC_WALL_TOGGLE,
	FUNC_BUTTON,
	TRIGGER_MULTIPLE
}

new const Float:VEC_NULL[3]	= { 0.0, 0.0, 0.0 };

const PLAYERS_ARRAY_SIZE = 33;
const MAX_ENTSARRAYS_SIZE = 64; // x * 32 // 2048 (should be 1800 on default servers settings)

new g_bitPresentClass;

const KEYS = ((1<<0)|(1<<1)|(1<<9));

new Float:g_flJumpOrigin[ PLAYERS_ARRAY_SIZE ][3];
new Float:g_flJumpAngles[ PLAYERS_ARRAY_SIZE ][3];
new Float:g_flJumpGravity[ PLAYERS_ARRAY_SIZE ];

new g_bBlocks[MAX_ENTSARRAYS_SIZE], g_bBlocksByPlugin[MAX_ENTSARRAYS_SIZE];
new g_bOnGround, g_bTeleported, g_bAdmin, g_bNoFall, g_bBlockRenderAmt;

new bool:g_bBlockEntityTouch;
new bool:g_bActive;
new bool:g_bSafeInform = false;

new g_iAdminDoor[PLAYERS_ARRAY_SIZE];
new szConfigFile[64];

new Trie:g_iBlocksClass;

new g_iMaxPlayers, g_iMaxEnts;
#define MaskEnt(%0)	( 1<<(%0 & 31) )
#define IsPlayer(%1)	( 1 <= %1 <= g_iMaxPlayers )

enum _:renderblock
{
	ren_block,
Float:ren_enable,
Float:ren_disable,
bool:ren_onlyren
}

new Array:plrRenderBlock[33];

public plugin_init()
{
	register_plugin("MultiPlayer Bhop", VERSION, "ConnorMcLeod, Garey");
	SCE_RegisterForward(func_PM_ShouldCollide, "PM_ShouldCollide");
	new pCvar = register_cvar("mp_bhop_version", VERSION, FCVAR_SERVER|FCVAR_EXTDLL|FCVAR_SPONLY);
	set_pcvar_string(pCvar, VERSION);

	new const szPossibleBlockClass[][] = {"func_door", "func_wall_toggle", "func_button", "trigger_multiple"};
	g_iBlocksClass = TrieCreate();
	for(new i; i<sizeof(szPossibleBlockClass); i++)
	{
		TrieSetCell(g_iBlocksClass, szPossibleBlockClass[i], i);
	}
	
	g_bNoFall = register_cvar("kz_mpbhop_nofall", "0");
	g_bBlockRenderAmt = register_cvar("kz_mpbhop_renderamt", "50");

	register_concmd("kz_mpbhop", "ConCmd_MpBhop", ADMIN_CFG, "<0/1> set blocks so they can't move when players touch them");
	register_concmd("kz_safe_inform", "ClCmd_SafeInform", ADMIN_CFG, "<0/1> Inform recorders that their demo will be safe or not safe according to plugin state");

	register_clcmd("kz_mpbhopmenu", "ClCmd_BhopMenu", ADMIN_CFG);

	register_clcmd("fullupdate", "ClCmd_FullUpdate");
	
	register_forward(FM_AddToFullPack, "AddToFullPack", 1);
	
	RegisterHam(Ham_TraceAttack, "func_door", "fwd_PlayerTraceAttack_Pre", .Post = 0);

	register_menucmd(register_menuid("MpBhop Menu"), KEYS ,"MpBhopMenuAction");

	g_iMaxPlayers = get_maxplayers();
	g_iMaxEnts = global_get(glb_maxEntities);
	for(new i = 1; i <= g_iMaxPlayers; i++)
	{
		plrRenderBlock[i] = ArrayCreate(renderblock);
	}
	new iCount;

	iCount += Set_Doors();
	iCount += Set_Wall_Toggle();
	iCount += Set_Buttons();

	iCount += SetBlocksByFile();

	server_print("[MPBHOP] %d bhop blocks detected", iCount);

	SetTriggerMultiple();
}

public PM_ShouldCollide(id, iBlock)
{
	if( !(GetEntBits(g_bBlocks, iBlock)) )
	{
		return 1;
	}

	if((pev(iBlock, pev_iuser4) & MaskEnt(id)) && (!(pev(iBlock, pev_iuser3) & MaskEnt(id))))
	return 1;
	
	if((pev(iBlock, pev_iuser3) & MaskEnt(id)))
	return 0;	
	
	return 1;
}

public plugin_cfg()
{
	new szConfigPath[96];
	get_localinfo("amxx_configsdir", szConfigPath, charsmax(szConfigPath));
	format(szConfigPath, charsmax(szConfigPath), "%s/mpbhop.cfg", szConfigPath);

	if( file_exists(szConfigPath) )
	{
		new buffer[2], n;
		read_file(szConfigPath, 0, buffer, charsmax(buffer), n);
		if( buffer[0] == ';' )
		{
			goto ForceWrite;
		}
		server_cmd("exec %s", szConfigPath);
		server_exec();
	}
	else
	{
ForceWrite:
		new fp = fopen(szConfigPath, "wt");
		if( !fp )
		{
			return;
		}
		new szPluginFileName[96], szPluginName[64], szAuthor[32], szVersion[32], szStatus[2];
		new iPlugin = get_plugin(-1,
		szPluginFileName, charsmax(szPluginFileName),
		szPluginName, charsmax(szPluginName),
		szVersion, charsmax(szVersion),
		szAuthor, charsmax(szAuthor),
		szStatus, charsmax(szStatus) );

		// server_print("Plugin id is %d", iPlugin);
		fprintf(fp, "// ^"%s^" configuration file^n", szPluginName);
		fprintf(fp, "// Author : ^"%s^"^n", szAuthor);
		fprintf(fp, "// Version : ^"%s^"^n", szVersion);
		fprintf(fp, "// File : ^"%s^"^n", szPluginFileName);

		new iMax, i, szCommand[64], iCommandAccess, szCmdInfo[128], szFlags[32];
		iMax = get_concmdsnum(-1, -1);
		fprintf(fp, "^n// Console Commands :^n");
		for(i=0; i<iMax; i++)
		{
			if( get_concmd_plid(i, -1, -1) == iPlugin )
			{
				get_concmd(i,
				szCommand, charsmax(szCommand),
				iCommandAccess,
				szCmdInfo, charsmax(szCmdInfo),
				-1, -1);
				get_flags(iCommandAccess, szFlags, charsmax(szFlags));
				fprintf(fp, "// %s | Access:^"%s^" | ^"%s^"^n", szCommand, szFlags, szCmdInfo);
			}
		}

		iMax = get_plugins_cvarsnum();
		new iTempId, iPcvar, szCvarName[256], szCvarValue[128];
		fprintf(fp, "^n// Cvars :^n");
		for(new i; i<iMax; i++)
		{
			get_plugins_cvar(i, szCvarName, charsmax(szCvarName), _, iTempId, iPcvar);
			if( iTempId == iPlugin )
			{
				get_pcvar_string(iPcvar, szCvarValue, charsmax(szCvarValue));
				fprintf(fp, "// %s ^"%s^"^n", szCvarName, szCvarValue);
			}
		}

		fclose(fp);
	}
}

public ClCmd_FullUpdate( id )
{
	if( g_bSafeInform )
	{
		if( g_bActive )
		{
			client_print(id, print_console, "MpBhop is Activated, recording is NOT SAFE");
#if defined CHATCOLOR
			client_print_color(id, Red, "^1 * ^4[MpBhop] ^1MpBhop is ^4Activated^1, recording is ^3NOT SAFE");
#else
			client_print(id, print_chat, "MpBhop is Activated, recording is NOT SAFE");
#endif
		}
		else
		{
			client_print(id, print_console, "MpBhop is De-Activated, recording is SAFE");
#if defined CHATCOLOR
			client_print_color(id, Red, "^1 * ^4[MpBhop] ^1MpBhop is ^3De-Activated^1, recording is ^4SAFE");
#else
			client_print(id, print_chat, "MpBhop is De-Activated, recording is SAFE");
#endif
		}
	}
}

public ClCmd_SafeInform(id, lvl, cid)
{
	if( cmd_access(id, lvl, cid, 2) )
	{
		new szStatus[2];
		read_argv(1, szStatus, charsmax(szStatus));
		g_bSafeInform = !!str_to_num(szStatus);
	}
	return PLUGIN_HANDLED;
}

public client_putinserver(id)
{
	if( get_user_flags(id) & ADMIN_CFG )
	{
		SetIdBits(g_bAdmin, id);
	}
	else
	{
		ClearIdBits(g_bAdmin, id);
	}
	ClearIdBits(g_bOnGround, id);
	ClearIdBits(g_bTeleported, id);
}

public client_disconnect(id)
{
	ClearIdBits(g_bAdmin, id);
	ClearIdBits(g_bOnGround, id);
	ClearIdBits(g_bTeleported, id);
}

public MpBhopMenuAction(id, iKey)
{
	new iEnt = g_iAdminDoor[id];

	switch( iKey )
	{
	case 0:
		{
			if( GetEntBits(g_bBlocks, iEnt) )
			{
				ClearEntBits(g_bBlocks, iEnt);
#if defined CHATCOLOR
				client_print_color(id, id, "^1 * ^4[MpBhop] ^1Block has been set ^4movable^1.");
#else
				client_print(id, print_chat, " * [MpBhop] Block has been set movable.");
#endif
			}
			else
			{
#if defined CHATCOLOR
				client_print_color(id, id, "^1 * ^4[MpBhop] ^1Block is already ^4movable^1.");
#else
				client_print(id, print_chat, " * [MpBhop] Block is already movable.");
#endif
			}
		}
	case 1:
		{
			if( GetEntBits(g_bBlocks, iEnt) )
			{
#if defined CHATCOLOR
				client_print_color(id, Red, "^1 * ^4[MpBhop] ^1Block is already ^3unmovable^1.");
#else
				client_print(id, print_chat, " * [MpBhop] Block is already unmovable.");
#endif
			}
			else
			{
				SetEntBits(g_bBlocks, iEnt);
#if defined CHATCOLOR
				client_print_color(id, Red, "^1 * ^4[MpBhop] ^1Block has been set ^3unmovable^1.");
#else
				client_print(id, print_chat, " * [MpBhop] Block has been set unmovable.");
#endif
				if( g_bActive )
				{
					SetTouch(true);
				}
			}
		}
	}
	return PLUGIN_HANDLED;
}

ShowMpBhopMenu(id, bIsBlocked)
{
	new szMenuBody[150];

	formatex(szMenuBody, charsmax(szMenuBody), "\rMpBhop Menu^n\dThis block is actually \
		\y%smovable \d:^n^n\r1\w. Mark this block as movable^n\r2\w. Mark this block as \
		unmovable^n^n\r0\w. Exit", bIsBlocked ? "un" : "");

	show_menu(id, KEYS, szMenuBody, _, "MpBhop Menu");
}

public ClCmd_BhopMenu(id, level, cid)
{
	if( cmd_access(id, level, cid, 1) )
	{
		new iEnt, crap, iClassType;
		get_user_aiming(id, iEnt, crap);
		if( iEnt && pev_valid(iEnt) )
		{
			new szClassName[32];
			pev(iEnt, pev_classname, szClassName, charsmax(szClassName));
			if( TrieGetCell(g_iBlocksClass, szClassName, iClassType) )
			{
				g_bitPresentClass |= 1<<iClassType;
				g_iAdminDoor[id] = iEnt;
				ShowMpBhopMenu(id, !!(GetEntBits(g_bBlocks, iEnt)));
			}
		}
	}
	return PLUGIN_HANDLED;
}

public fwd_PlayerTraceAttack_Pre(iBlock, id, Float:damage, Float:direction[3], tracehandle, damagebits) 
{
	if(!is_user_alive(id)) 
	return HAM_IGNORED;
	
	if(!(pev(iBlock, pev_iuser4) & MaskEnt(id)))
	{		
		AddOrExtendRender(id, iBlock, 0.0, 0.7, true);
	}
	
	return HAM_IGNORED;
}

public AddToFullPack(es, e, iEnt, id, hostflags, player, pSet)
{
	if(g_bActive && !get_pcvar_num(g_bNoFall) && !player)
	{
		if(is_user_alive(id) && pev_valid(iEnt) && GetEntBits(g_bBlocks, iEnt))
		{
			CheckAlreadyRendering(id, iEnt);
			if(pev(iEnt, pev_iuser3) & MaskEnt(id) || pev(iEnt, pev_iuser4) & MaskEnt(id))
			{
				if(pev(iEnt, pev_iuser3) & MaskEnt(id))
				set_es(es, ES_Solid, SOLID_NOT);
				
				set_es(es, ES_RenderAmt, get_pcvar_num(g_bBlockRenderAmt));
				set_es(es, ES_RenderMode, kRenderTransAdd);
				set_es(es, ES_RenderColor, 0, 0, 0);					
				set_es(es, ES_RenderFx, kRenderFxNone, 0);
				
				CheckAlreadyRendering(id, iEnt);
			}
		}
	}
}

public FindCollide(id)
{
	if(!g_bActive || get_pcvar_num(g_bNoFall) && !(get_user_flags(id)&ADMIN_LEVEL_H))
	return;

	static iBlock;
	static Float:orig[3];
	entity_get_vector( id, EV_VEC_origin, orig );
	if( pev(id, pev_flags) & FL_ONGROUND )
	{
		//do a hull trace 1 unit below their origin
		orig[2] -= 1;
		engfunc( EngFunc_TraceHull, orig, orig, DONT_IGNORE_MONSTERS, HULL_HUMAN, id, 0 );
		iBlock = get_tr2( 0, TR_pHit );
		
		if(!(iBlock > g_iMaxPlayers && GetEntBits(g_bBlocks, iBlock)))
		iBlock = 0;
		else
		{
			// solidbefore, solidafter
			if(CheckAlreadyRendering(id, iBlock) == -1 || pev(iBlock, pev_iuser4) & MaskEnt(id))
			AddOrExtendRender(id, iBlock, 0.21, 0.7, false);
		}
	}
}

public CBasePlayer_PreThink(id)
{
	if( is_user_alive(id) )
	{
		FindCollide(id);
		if( GetIdBits(g_bTeleported, id) )
		{
			ClearIdBits(g_bTeleported, id);
			set_pev(id, pev_velocity, VEC_NULL);
			return;
		}

		static fFlags;
		fFlags = pev(id, pev_flags);
		if( fFlags & FL_ONGROUND )
		{
			static iEnt, Float:flVelocity[3], Float:flVecOrigin[3];
			iEnt = pev(id, pev_groundentity);
			if( !iEnt || !(GetEntBits(g_bBlocks, iEnt)) )
			{
				if( iEnt )
				{
					pev(iEnt, pev_velocity, flVelocity);
					if( flVelocity[0] || flVelocity[1] || flVelocity[2] )
					{
						ClearIdBits(g_bOnGround, id);
						return;
					}
				}

				if( fFlags & FL_DUCKING )
				{
					pev(id, pev_origin, flVecOrigin);
					flVecOrigin[2] += 18.0;
					if( !trace_hull(flVecOrigin, HULL_HUMAN, id, IGNORE_MONSTERS) )
					{
						flVecOrigin[2] -= 18.0;
						xs_vec_copy(flVecOrigin, g_flJumpOrigin[id]);
						SetIdBits(g_bOnGround, id);
					}
					else
					{
						ClearIdBits(g_bOnGround, id);
						return;
					}
				}
				else
				{
					pev(id, pev_origin, g_flJumpOrigin[id]);
					SetIdBits(g_bOnGround, id);
				}
			}
			else
			{
				ClearIdBits(g_bOnGround, id);
			}
		}
		else if( GetIdBits(g_bOnGround, id) )
		{
			ClearIdBits(g_bOnGround, id);
			pev(id, pev_v_angle, g_flJumpAngles[id]);
			pev(id, pev_gravity, g_flJumpGravity[id]);
		}
	}
}

public TriggerMultiple_Touch(iEnt, id)
{
	if( (IsPlayer(id) || g_bBlockEntityTouch) && GetEntBits(g_bBlocks, iEnt) )
	{
		return HAM_SUPERCEDE;
	}
	return HAM_IGNORED;
}

public Touch_Block(iBlock, id)
{
	if( !(GetEntBits(g_bBlocks, iBlock)) )
	{
		return HAM_IGNORED;
	}
	
	return HAM_SUPERCEDE;
}

public ConCmd_MpBhop(id, lvl, cid)
{
	if( cmd_access(id, lvl, cid, 2) )
	{
		new szStatus[2];
		read_argv(1, szStatus, charsmax(szStatus));
		static HamHook:iHhPlayerPreThink;
		switch( szStatus[0] )
		{
		case '0':
			{
				if( !g_bActive )
				{
					return PLUGIN_HANDLED;
				}
				if( iHhPlayerPreThink )
				{
					DisableHamForward( iHhPlayerPreThink );
				}
				SetTouch( false );
				g_bActive = false;

				if( g_bSafeInform )
				{
					client_print(0, print_console, "MpBhop has been De-Activated, recording is now SAFE");
#if defined CHATCOLOR
					client_print_color(0, Red, "^1 * ^4[MpBhop] ^1MpBhop has been ^3De-Activated^1, recording is now ^4SAFE");
#else
					client_print(id, print_chat, " * [MpBhop] MpBhop has been De-Activated, recording is now SAFE");
#endif
				}
			}
		case '1':
			{
				if( g_bActive )
				{
					return PLUGIN_HANDLED;
				}
				if( !iHhPlayerPreThink )
				{
					RegisterHam(Ham_Player_PreThink, "player", "CBasePlayer_PreThink");
				}
				else
				{
					EnableHamForward( iHhPlayerPreThink );
				}
				SetTouch( true );
				g_bActive = true;
				if( g_bSafeInform )
				{
					client_print(0, print_console, "MpBhop has been Activated, recording is now NOT SAFE");
#if defined CHATCOLOR
					client_print_color(0, Red, "^1 * ^4[MpBhop] ^1MpBhop has been ^4Activated^1, recording is now ^3NOT SAFE");
#else
					client_print(id, print_chat, " * MpBhop has been Activated, recording is now NOT SAFE");
#endif
				}
			}
		default:
			{
				client_print(id, print_console, "Usage: kz_mpbhop <0/1>");
			}
		}
	}
	return PLUGIN_HANDLED;
}

public ConCmd_EntityTouch(id, lvl, cid)
{
	if( cmd_access(id, lvl, cid, 2) )
	{
		new szStatus[2];
		read_argv(1, szStatus, charsmax(szStatus));
		g_bBlockEntityTouch = !!str_to_num(szStatus);
	}
	return PLUGIN_HANDLED;
}

Set_Doors()
{
	new iDoor = FM_NULLENT, i;
	new Float:flMovedir[3], szNoise[32], Float:flSize[3], Float:flDmg, Float:flSpeed;
	new const szNull[] = "common/null.wav";
	while( (iDoor = find_ent_by_class( iDoor, "func_door")) )
	{
		// definitly not a bhop block
		pev(iDoor, pev_dmg, flDmg);
		if( flDmg )
		{
#if defined MAKE_DOORS_SILENT
			set_pev(iDoor, pev_noise1, szNull); // while here, set healing doors silent xD
			set_pev(iDoor, pev_noise2, szNull);
			set_pev(iDoor, pev_noise3, szNull);
#endif
			continue;
		}

		// this func_door goes UP, not a bhop block ?
		// or bhop block but let them move up (kz_megabhop for example)
		pev(iDoor, pev_movedir, flMovedir);
		if( flMovedir[2] > 0.0 )
		{
			continue;
		}

		// too small : real door ? could this one be skipped ?
		pev(iDoor, pev_size, flSize);
		if( ( flSize[0] < 24.0 && flSize[1] > 50.0 )
				||( flSize[1] < 24.0 && flSize[0] > 50.0 ) )
		{
			continue;
		}

		// real door ? not all doors make sound though...
		pev(iDoor, pev_noise1, szNoise, charsmax(szNoise));
		if( szNoise[0] && !equal(szNoise, szNull) )
		{
			continue;
		}
		pev(iDoor, pev_noise2, szNoise, charsmax(szNoise));
		if( szNoise[0] && !equal(szNoise, szNull) )
		{
			continue;
		}

		// not a bhop block ? too slow // this at least detects the big ent on kzsca_sewerbhop
		pev(iDoor, pev_speed, flSpeed);
		if( flSpeed < 80.0 )
		{
			continue;
		}

		// Pray for this to be a bhop block
		SetEntBits(g_bBlocksByPlugin, iDoor);
		SetEntBits(g_bBlocks, iDoor);
		g_bitPresentClass |= 1<<FUNC_DOOR;
		i++;
	}
	return i;
}

Set_Wall_Toggle()
{
	new iEnt = FM_NULLENT, i;
	while( (iEnt = find_ent_by_class(iEnt,"func_wall_toggle")) )
	{
		g_bitPresentClass |= 1<<FUNC_WALL_TOGGLE;
		SetEntBits(g_bBlocksByPlugin, iEnt);
		SetEntBits(g_bBlocks, iEnt);
		i++;
	}
	return i;
}

Set_Buttons()
{
	new const szStartStopButtons[][] = {
		"counter_start", "clockstartbutton", "firsttimerelay", "gogogo", "multi_start","counter_start_button", "startcounter", 
		"counter_off", "clockstop", "clockstopbutton", "multi_stop", "stop_counter", "stopcounter" };

	new Trie:tButtons = TrieCreate();

	for(new i; i<sizeof(szStartStopButtons); i++)
	{
		TrieSetCell(tButtons, szStartStopButtons[i], 1);
	}

	new iEnt = FM_NULLENT, i, szTarget[32], spawnflags;
	while( (iEnt = find_ent_by_class(iEnt,"func_button")) )
	{
		
		spawnflags = pev(iEnt, pev_spawnflags);
		if( spawnflags & (SF_BUTTON_DONTMOVE|SF_BUTTON_TOGGLE|SF_BUTTON_TOUCH_ONLY) == SF_BUTTON_TOUCH_ONLY )
		{
			pev(iEnt, pev_target, szTarget, charsmax(szTarget));
			if( !szTarget[0] || !TrieKeyExists(tButtons, szTarget))
			{
				pev(iEnt, pev_targetname, szTarget, charsmax(szTarget));
				if( !szTarget[0] || !TrieKeyExists(tButtons, szTarget))
				{
					g_bitPresentClass |= 1<<FUNC_BUTTON;
					SetEntBits(g_bBlocksByPlugin, iEnt);
					SetEntBits(g_bBlocks, iEnt);
					i++;
				}
			}
		}
#if defined MAKE_DOORS_SILENT
		if( spawnflags & SF_BUTTON_SPARK_IF_OFF )
		{
			set_pev(iEnt, pev_spawnflags, spawnflags & ~SF_BUTTON_SPARK_IF_OFF);
		}
#endif
	}
	TrieDestroy(tButtons);
	return i;
}

SetTouch(bool:bActive)
{
	static HamHook:iHhBlockTouch[BlocksClasses];
	if( bActive )
	{
		static const szClassesAndHandlers[BlocksClasses][][] = {
			{"func_door", "Touch_Block"},
			{"func_wall_toggle", "Touch_Block"},
			{"func_button", "Touch_Block"},
			{"trigger_multiple", "TriggerMultiple_Touch"}
		};
		for(new i; i<sizeof(iHhBlockTouch); i++)
		{
			if( g_bitPresentClass & (1<<i) )
			{
				if( iHhBlockTouch[i] )
				{
					EnableHamForward( iHhBlockTouch[i] );
				}
				else
				{
					iHhBlockTouch[i] = RegisterHam(Ham_Touch, szClassesAndHandlers[i][0], szClassesAndHandlers[i][1]);
				}
			}
		}
	}
	else
	{
		for(new i; i<sizeof(iHhBlockTouch); i++)
		{
			if( g_bitPresentClass & (1<<i) && iHhBlockTouch[i] )
			{
				DisableHamForward( iHhBlockTouch[i] );
			}
		}
	}
}

SetBlocksByFile()
{
	get_localinfo("amxx_datadir", szConfigFile, charsmax(szConfigFile));
	format(szConfigFile, charsmax(szConfigFile), "%s/mpbhop", szConfigFile);
	if( !dir_exists(szConfigFile) )
	{
		mkdir(szConfigFile);
	}

	new szMapName[32];
	get_mapname(szMapName, charsmax(szMapName));
	format(szConfigFile, charsmax(szConfigFile), "%s/%s.dat", szConfigFile, szMapName);

	new iFile = fopen(szConfigFile, "rt"), i;
	if( iFile )
	{
		new szDatas[48], szBrushOrigin[3][13], szType[2], Float:flBrushOrigin[3], i, iEnt;
		new szClassName[32], iClassType;
		while( !feof(iFile) )
		{
			fgets(iFile, szDatas, charsmax(szDatas));
			trim(szDatas);
			if(!szDatas[0] || szDatas[0] == ';' || szDatas[0] == '#' || (szDatas[0] == '/' && szDatas[1] == '/'))
			{
				continue;
			}

			parse(szDatas, szBrushOrigin[0], 12, szBrushOrigin[1], 12, szBrushOrigin[2], 12, szType, charsmax(szType));
			for(i=0; i<3; i++)
			{
				flBrushOrigin[i] = str_to_float( szBrushOrigin[i] );
			}

			iEnt = FindEntByBrushOrigin( flBrushOrigin );
			if( iEnt )
			{
				if( szType[0] == '1' )
				{
					pev(iEnt, pev_classname, szClassName, charsmax(szClassName));
					if( TrieGetCell(g_iBlocksClass, szClassName, iClassType) )
					{
						g_bitPresentClass |= 1<<iClassType;
					}
					if( ~GetEntBits(g_bBlocks, iEnt) )
					{
						i++;
					}
					SetEntBits(g_bBlocks, iEnt);
				}
				else
				{
					if( GetEntBits(g_bBlocks, iEnt) )
					{
						i--;
					}
					ClearEntBits(g_bBlocks, iEnt);
				}
			}
		}
		fclose(iFile);
	}
	return i;
}

FindEntByBrushOrigin(Float:flOrigin[3])
{
	new Float:flBrushOrigin[3];
	for( new iEnt=g_iMaxPlayers+1; iEnt<=g_iMaxEnts; iEnt++ )
	{
		if( pev_valid(iEnt) )
		{
			fm_get_brush_entity_origin(iEnt, flBrushOrigin);
			if( xs_vec_nearlyequal(flBrushOrigin, flOrigin) )
			{
				return iEnt;
			}
		}
	}
	return 0;
}

//fm_get_brush_entity_origin(ent, Float:orig[3])
//{
//	new Float:Min[3], Float:Max[3];
//
//	pev(ent, pev_origin, orig);
//	pev(ent, pev_mins, Min);
//	pev(ent, pev_maxs, Max);
//
//	orig[0] += (Min[0] + Max[0]) * 0.5;
//	orig[1] += (Min[1] + Max[1]) * 0.5;
//	orig[2] += (Min[2] + Max[2]) * 0.5;
//
//	return 1;
//}

SetTriggerMultiple()
{
	new iEnt = FM_NULLENT, szTarget[32], iBlock;
	while( (iEnt = find_ent_by_class(iEnt,"trigger_multiple")) )
	{
		pev(iEnt, pev_target, szTarget, charsmax(szTarget));
		iBlock = find_ent_by_tname(FM_NULLENT, szTarget);
		if( iBlock && GetEntBits(g_bBlocks, iBlock) )
		{
			g_bitPresentClass |= 1<<TRIGGER_MULTIPLE;
			SetEntBits(g_bBlocksByPlugin, iEnt);
			SetEntBits(g_bBlocks, iEnt);
		}
	}
}

public plugin_end()
{
	TrieDestroy(g_iBlocksClass);
	delete_file(szConfigFile);

	new iFile;

	new Float:flBrushOrigin[3], bool:bUnMovable;
	for(new iEnt=g_iMaxPlayers+1; iEnt<=g_iMaxEnts; iEnt++)
	{
		if( pev_valid(iEnt) )
		{
			bUnMovable = !!( GetEntBits(g_bBlocks, iEnt) );
			if(	bUnMovable
					!=	!!( GetEntBits(g_bBlocksByPlugin, iEnt) )	)
			{
				if( !iFile )
				{
					iFile = fopen(szConfigFile, "wt");
				}
				fm_get_brush_entity_origin(iEnt, flBrushOrigin);
				fprintf(iFile, "%f %f %f %d^n",
				flBrushOrigin[0], flBrushOrigin[1], flBrushOrigin[2], bUnMovable);
			}
		}
	}
	if( iFile )
	{
		fclose( iFile );
	}
}

stock CheckAlreadyRendering(id, iBlock)
{
	static tempRender[renderblock];	
	for(new i = 0; i < ArraySize(plrRenderBlock[id]); i++)
	{
		ArrayGetArray(plrRenderBlock[id], i, tempRender);
		if(tempRender[ren_block] == iBlock)
		{				
			if(get_gametime() > tempRender[ren_disable])
			{	
				if(fm_boxents_distance(id, iBlock) < 1.0)
				{
					tempRender[ren_disable] = _:(get_gametime()+bhop_timeout);	
					ArraySetArray(plrRenderBlock[id], i, tempRender);
					return i;
				}
				
				static Float:origin[3];
				pev(id, pev_origin, origin);				
				set_pev(iBlock, pev_iuser3, pev(iBlock, pev_iuser3) & ~MaskEnt(id));
				set_pev(iBlock, pev_iuser4, pev(iBlock, pev_iuser4) & ~MaskEnt(id));
				ArrayDeleteItem(plrRenderBlock[id], i);
				return -1;
			}
			else if(get_gametime() > tempRender[ren_enable])
			{
				if(!tempRender[ren_onlyren])
				{
					set_pev(iBlock, pev_iuser3, pev(iBlock, pev_iuser3) | MaskEnt(id));
				}	
				else
				set_pev(iBlock, pev_iuser4, pev(iBlock, pev_iuser4) | MaskEnt(id));	
				return i;
			}
			else
			{
				if(tempRender[ren_onlyren])
				{
					set_pev(iBlock, pev_iuser4, pev(iBlock, pev_iuser4) | MaskEnt(id));
				}
				return i;
			}			
		}
	}
	return -1;
}

stock AddOrExtendRender(id, iBlock, Float:enable, Float:disable, bool:onlyrender)
{
	static tempRender[renderblock];
	new Found = CheckAlreadyRendering(id, iBlock);
	if(Found == -1)
	{			
		tempRender[ren_onlyren] = onlyrender;
		tempRender[ren_block] = iBlock;
		tempRender[ren_enable] = _:(get_gametime()+enable);
		tempRender[ren_disable] = _:(get_gametime()+disable);	
		ArrayPushArray(plrRenderBlock[id], tempRender);
	}
	else
	{		
		ArrayGetArray(plrRenderBlock[id], Found, tempRender);	
		if(tempRender[ren_onlyren] && !onlyrender)
		{
			tempRender[ren_onlyren] = onlyrender;
			tempRender[ren_enable] = _:(get_gametime()+enable);	
			tempRender[ren_disable] = _:(get_gametime()+disable);	
		}					
		else
		tempRender[ren_disable] = _:(get_gametime()+disable);	
		ArraySetArray(plrRenderBlock[id], Found, tempRender);
		
	}
}
Attached Files
File Type: zip bug.zip (440.6 KB, 38 views)
File Type: zip mpbhop_1.1.4.zip (89.6 KB, 45 views)

Last edited by wAyz; 05-20-2017 at 10:50.
wAyz is offline
Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 04:50.


Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.
Theme made by Freecode