596 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			SourcePawn
		
	
	
	
	
	
			
		
		
	
	
			596 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			SourcePawn
		
	
	
	
	
	
| #include <sourcemod>
 | |
| #include <sdkhooks>
 | |
| #include <zombiereloaded>
 | |
| #include <sdktools>
 | |
| #include <cstrike>
 | |
| 
 | |
| #pragma semicolon 1
 | |
| #pragma newdecls required
 | |
| 
 | |
| int g_iVelocity;
 | |
| int g_iCurrentTick;
 | |
| int g_iTicksSinceLastAttack;
 | |
| 
 | |
| #define MAX_TURRETS 65
 | |
| 
 | |
| int g_iTurrets[MAX_TURRETS] = {INVALID_ENT_REFERENCE,...};
 | |
| int g_iMarkers[MAX_TURRETS] = {INVALID_ENT_REFERENCE,...};
 | |
| int g_iGunfire[MAX_TURRETS] = {INVALID_ENT_REFERENCE,...};
 | |
| int g_iExplosion[MAX_TURRETS] = {INVALID_ENT_REFERENCE,...};
 | |
| int g_iOwner[MAX_TURRETS];
 | |
| bool g_bCanPlace[MAX_TURRETS];
 | |
| bool g_bPlaced[MAX_TURRETS];
 | |
| 
 | |
| float g_fMaxRange;
 | |
| float g_fMinAccuracy;
 | |
| float g_fMaxAccuracy;
 | |
| float g_fDestroyRange;
 | |
| float g_fKnockback;
 | |
| int g_iDamage;
 | |
| int g_iTicksToSkip;
 | |
| 
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // Purpose:
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| public Plugin myinfo =
 | |
| {
 | |
| 	name         = "Turrets",
 | |
| 	author       = "Neon",
 | |
| 	description  = "",
 | |
| 	version      = "1.0.0",
 | |
| 	url 		= "https://steamcommunity.com/id/n3ontm"
 | |
| };
 | |
| 
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // Purpose:
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| public void OnPluginStart()
 | |
| {
 | |
| 	//RegConsoleCmd("sm_turret", Command_Turret);
 | |
| 	RegAdminCmd("sm_turret", Command_Turret, ADMFLAG_RCON);
 | |
| 	HookEvent("round_end", OnRound);
 | |
| 	HookEvent("round_start", OnRound);
 | |
| 
 | |
| 	ConVar cvar;
 | |
| 	HookConVarChange((cvar = CreateConVar("sm_turrets_max_range", "1500", "")), Cvar_MaxRange);
 | |
| 	g_fMaxRange = cvar.FloatValue;
 | |
| 	HookConVarChange((cvar = CreateConVar("sm_turrets_min_accuracy", "0.7", "")), Cvar_MinAccuracy);
 | |
| 	g_fMinAccuracy = cvar.FloatValue;
 | |
| 	HookConVarChange((cvar = CreateConVar("sm_turrets_max_accuracy", "0.99", "")), Cvar_MaxAccuracy);
 | |
| 	g_fMaxAccuracy = cvar.FloatValue;
 | |
| 	HookConVarChange((cvar = CreateConVar("sm_turrets_destroy_range", "100", "")), Cvar_DestroyRange);
 | |
| 	g_fDestroyRange = cvar.FloatValue;
 | |
| 	HookConVarChange((cvar = CreateConVar("sm_turrets_knockback", "20", "")), Cvar_Knockback);
 | |
| 	g_fKnockback = cvar.FloatValue;
 | |
| 	HookConVarChange((cvar = CreateConVar("sm_turrets_damage", "10", "")), Cvar_Damage);
 | |
| 	g_iDamage = cvar.IntValue;
 | |
| 	HookConVarChange((cvar = CreateConVar("sm_turrets_ticks_to_skip", "3", "")), Cvar_TicksToSkip); // to decrease CPU usage
 | |
| 	g_iTicksToSkip = cvar.IntValue;
 | |
| 	delete cvar;
 | |
| }
 | |
| 
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // Purpose:
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| public void OnMapStart()
 | |
| {
 | |
| 	g_iVelocity = FindDataMapInfo(0, "m_vecAbsVelocity");
 | |
| 
 | |
| 	PrecacheModel("models/unloze/dronegun/dronegun.mdl");
 | |
| 	AddFileToDownloadsTable("models/unloze/dronegun/dronegun.dx90.vtx");
 | |
| 	AddFileToDownloadsTable("models/unloze/dronegun/dronegun.dx80.vtx");
 | |
| 	AddFileToDownloadsTable("models/unloze/dronegun/dronegun.mdl");
 | |
| 	AddFileToDownloadsTable("models/unloze/dronegun/dronegun.phy");
 | |
| 	AddFileToDownloadsTable("models/unloze/dronegun/dronegun.sw.vtx");
 | |
| 	AddFileToDownloadsTable("models/unloze/dronegun/dronegun.vvd");
 | |
| 	AddFileToDownloadsTable("materials/models/unloze/dronegun/dronegun.vmt");
 | |
| 	AddFileToDownloadsTable("materials/models/unloze/dronegun/dronegun.vtf");
 | |
| 	AddFileToDownloadsTable("materials/models/unloze/dronegun/dronegun_laser.vmt");
 | |
| 	AddFileToDownloadsTable("materials/models/unloze/dronegun/dronegun_laser.vtf");
 | |
| 	AddFileToDownloadsTable("materials/models/unloze/dronegun/dronegun_selfillum.vtf");
 | |
| 	AddFileToDownloadsTable("materials/models/unloze/weapons/w_models/w_mach_m249para/m249.vmt");
 | |
| 	AddFileToDownloadsTable("materials/models/unloze/weapons/w_models/w_mach_m249para/m249.vtf");
 | |
| 	AddFileToDownloadsTable("materials/models/unloze/weapons/w_models/w_mach_m249para/m249_exponent.vtf");
 | |
| }
 | |
| 
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // Purpose:
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| public void OnPluginEnd()
 | |
| {
 | |
| 	for (int i = 0; i < MAX_TURRETS; i++)
 | |
| 	{
 | |
| 		if (g_iTurrets[i] == INVALID_ENT_REFERENCE)
 | |
| 			continue;
 | |
| 
 | |
| 		ClearTurret(i);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // Purpose:
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| public void OnRound(Event hEvent, const char[] sEvent, bool bDontBroadcast)
 | |
| {
 | |
| 	for (int i = 0; i < MAX_TURRETS; i++)
 | |
| 	{
 | |
| 		g_iTurrets[i] = INVALID_ENT_REFERENCE;
 | |
| 		g_iMarkers[i] = INVALID_ENT_REFERENCE;
 | |
| 		g_iGunfire[i] = INVALID_ENT_REFERENCE;
 | |
| 		g_iExplosion[i] = INVALID_ENT_REFERENCE;
 | |
| 		g_iOwner[i] = 0;
 | |
| 		g_bCanPlace[i] = false;
 | |
| 		g_bPlaced[i] = false;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // Purpose:
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| public Action Command_Turret(int client, int args)
 | |
| {
 | |
| 	if (!(IsPlayerAlive(client) && ZR_IsClientHuman(client)))
 | |
| 	{
 | |
| 		ReplyToCommand(client, "[ZR] You need to be human to use this command.");
 | |
| 		return Plugin_Handled;
 | |
| 	}
 | |
| 
 | |
| 	// Clear old turret
 | |
| 	for (int j = 0; j < MAX_TURRETS; j++)
 | |
| 	{
 | |
| 		if ((g_iOwner[j] != 0) && (g_iOwner[j] == client))
 | |
| 		{
 | |
| 			ClearTurret(j);
 | |
| 			ReplyToCommand(client, "[ZR] Turret Removed.");
 | |
| 			return Plugin_Handled;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	// find free index
 | |
| 	int i;
 | |
| 	for (i = 0; i < MAX_TURRETS; i++)
 | |
| 	{
 | |
| 		if (g_iTurrets[i] == INVALID_ENT_REFERENCE)
 | |
| 			break;
 | |
| 
 | |
| 		if (i == (MAX_TURRETS -1))
 | |
| 		{
 | |
| 			ReplyToCommand(client, "[ZR] Too many turrets active already.");
 | |
| 			return Plugin_Handled;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	float vecOrigin[3];
 | |
| 	GetClientAbsOrigin(client, vecOrigin);
 | |
| 
 | |
| 	g_iTurrets[i] = CreateEntityAtOrigin("prop_dynamic_override", vecOrigin);
 | |
| 	SetEntityModel(g_iTurrets[i], "models/unloze/dronegun/dronegun.mdl");
 | |
| 	DispatchKeyFormat(g_iTurrets[i], "targetname",            "turret_%d", i);
 | |
| 	DispatchKeyFormat(g_iTurrets[i], "solid",                 "0");
 | |
| 	DispatchKeyFormat(g_iTurrets[i], "modelscale",            "1.0");
 | |
| 	DispatchKeyFormat(g_iTurrets[i], "disableshadows",        "1");
 | |
| 	DispatchKeyFormat(g_iTurrets[i], "disablereceiveshadows", "1");
 | |
| 	DispatchKeyFormat(g_iTurrets[i], "disablebonefollowers",  "1");
 | |
| 	DispatchKeyFormat(g_iTurrets[i], "OnUser1",           	 "gunfire_%d,Kill,,0,1", i);
 | |
| 	DispatchKeyFormat(g_iTurrets[i], "OnUser1",           	 "marker_%d,Kill,,0,1", i);
 | |
| 	DispatchKeyFormat(g_iTurrets[i], "OnUser1",           	 "!self,Kill,,0,1");
 | |
| 	DispatchKeyFormat(g_iTurrets[i], "OnUser2",           	 "explosion_%d,Explode,,0,1", i);
 | |
| 	SpawnAndActivate(g_iTurrets[i]);
 | |
| 
 | |
| 	//traget for env_gunfire to aim at
 | |
| 	g_iMarkers[i] = CreateEntityAtOrigin("path_track", vecOrigin);
 | |
| 	DispatchKeyFormat(g_iMarkers[i], "targetname",            "marker_%d", i);
 | |
| 	SpawnAndActivate(g_iMarkers[i]);
 | |
| 
 | |
| 	vecOrigin[2] += 42.0; // "middle" of turret
 | |
| 	g_iGunfire[i] = CreateEntityAtOrigin("env_gunfire", vecOrigin);
 | |
| 	DispatchKeyFormat(g_iGunfire[i], "targetname",            "gunfire_%d", i);
 | |
| 	DispatchKeyFormat(g_iGunfire[i], "target",                "marker_%d", i);
 | |
| 	DispatchKeyFormat(g_iGunfire[i], "StartDisabled",         "1");
 | |
| 	DispatchKeyFormat(g_iGunfire[i], "spread",         		 "0");
 | |
| 	DispatchKeyFormat(g_iGunfire[i], "collisions",         	 "1");
 | |
| 	DispatchKeyFormat(g_iGunfire[i], "rateoffire",         	 "10");
 | |
| 	SpawnAndActivate(g_iGunfire[i]);
 | |
| 	ParentToEntity(g_iGunfire[i], g_iTurrets[i]);
 | |
| 
 | |
| 	g_iExplosion[i] = CreateEntityAtOrigin("env_explosion", vecOrigin);
 | |
| 	DispatchKeyFormat(g_iExplosion[i], "targetname",				"explosion_%d", i);
 | |
| 	DispatchKeyFormat(g_iExplosion[i], "fireballsprite",			"sprites/zerogxplode.spr");
 | |
| 	DispatchKeyFormat(g_iExplosion[i], "rendermode",			    "0");
 | |
| 	DispatchKeyFormat(g_iExplosion[i], "iMagnitude",         	"100");
 | |
| 	DispatchKeyFormat(g_iExplosion[i], "spawnflags",         	"1");
 | |
| 	SpawnAndActivate(g_iExplosion[i]);
 | |
| 	ParentToEntity(g_iExplosion[i], g_iTurrets[i]);
 | |
| 
 | |
| 	g_iOwner[i] = client;
 | |
| 	ReplyToCommand(client, "[ZR] Press E to place a turret.");
 | |
| 	return Plugin_Handled;
 | |
| }
 | |
| 
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // Purpose:
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| public void OnGameFrame() // Tick Turrets
 | |
| {
 | |
| 	g_iCurrentTick++;
 | |
| 	g_iTicksSinceLastAttack++;
 | |
| 	if (g_iCurrentTick < g_iTicksToSkip)
 | |
| 		return;
 | |
| 
 | |
| 	g_iCurrentTick = 0;
 | |
| 
 | |
| 	bool bAttack = false;
 | |
| 	if (g_iTicksSinceLastAttack > 15)
 | |
| 		bAttack = true;
 | |
| 
 | |
| 	for (int i = 0; i < MAX_TURRETS; i++)
 | |
| 	{
 | |
| 		if (g_iTurrets[i] == INVALID_ENT_REFERENCE)
 | |
| 			continue;
 | |
| 
 | |
| 		if (!g_bPlaced[i]) // not placed yet
 | |
| 		{
 | |
| 			PlaceTurret(i);
 | |
| 			continue;
 | |
| 		}
 | |
| 
 | |
| 		float vecOriginClient[3];
 | |
| 		float vecOriginTurret[3];
 | |
| 		GetEntPropVector(g_iTurrets[i], Prop_Send, "m_vecOrigin", vecOriginTurret);
 | |
| 		vecOriginTurret[2] += 42.0;
 | |
| 
 | |
| 		int iNearestZombie;
 | |
| 		float fNearestDistance;
 | |
| 
 | |
| 		for (int client = 1; client <= MaxClients; client++)
 | |
| 		{
 | |
| 			if (!IsClientInGame(client) || !IsPlayerAlive(client) || !ZR_IsClientZombie(client))
 | |
| 				continue;
 | |
| 
 | |
| 			GetClientAbsOrigin(client, vecOriginClient);
 | |
| 			vecOriginClient[2] += 50.0; //aim for chest
 | |
| 
 | |
| 			Handle hTraceRay = TR_TraceRayFilterEx(vecOriginClient, vecOriginTurret, MASK_ALL, RayType_EndPoint, TraceEntityFilter, g_iTurrets[i]);
 | |
| 
 | |
| 			if(TR_DidHit(hTraceRay))
 | |
| 			{
 | |
| 				delete hTraceRay;
 | |
| 				continue;
 | |
| 			}
 | |
| 			delete hTraceRay;
 | |
| 
 | |
| 			float vecVector[3];
 | |
| 			float vecAngles[3];
 | |
| 			MakeVectorFromPoints(vecOriginTurret, vecOriginClient, vecVector);
 | |
| 			GetVectorAngles(vecVector, vecAngles);
 | |
| 
 | |
| 			if (!((vecAngles[0] <= 45.0) || (vecAngles[0] >= 315.0)))
 | |
| 				continue;
 | |
| 
 | |
| 			float fDistance = GetVectorLength(vecVector, false);
 | |
| 
 | |
| 			if ((fDistance < fNearestDistance) || (iNearestZombie == 0))
 | |
| 			{
 | |
| 				iNearestZombie = client;
 | |
| 				fNearestDistance = fDistance;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		if (iNearestZombie == 0) // no target found
 | |
| 			continue;
 | |
| 
 | |
| 		// ZM too close, destroy turret
 | |
| 		if (fNearestDistance <= g_fDestroyRange)
 | |
| 		{
 | |
| 			ClearTurret(i, true);
 | |
| 			continue;
 | |
| 		}
 | |
| 
 | |
| 		float vecVector[3];
 | |
| 		float vecAngles[3];
 | |
| 		GetClientAbsOrigin(iNearestZombie, vecOriginClient);
 | |
| 		vecOriginClient[2] += 50.0; //aim for chest
 | |
| 		MakeVectorFromPoints(vecOriginTurret, vecOriginClient, vecVector);
 | |
| 		GetVectorAngles(vecVector, vecAngles);
 | |
| 
 | |
| 		float fA = ((vecAngles[1]+180.0)/360.0);
 | |
| 		if (fA > 1.0)
 | |
| 			fA -= 1.0;
 | |
| 
 | |
| 		float fB;
 | |
| 		if (vecAngles[0] <= 45.0)
 | |
| 		{
 | |
| 			fB = ((1.0/90.0) * vecAngles[0]) + 0.5;
 | |
| 		}
 | |
| 		else if (vecAngles[0] >= 315.0)
 | |
| 		{
 | |
| 			fB = ((1.0/90.0) * (vecAngles[0] - 315.0)) + 0.0;
 | |
| 		}
 | |
| 
 | |
| 		// why the fuck can i only set one of those angles????
 | |
| 		//SetEntPropFloat(g_iTurrets[i], Prop_Data, "m_flPoseParameter", fB, 1);
 | |
| 		//SetEntPropFloat(g_iTurrets[i], Prop_Send, "m_flCycle", 1.0);
 | |
| 		SetEntPropFloat(g_iTurrets[i], Prop_Data, "m_flPoseParameter", fA, 0);
 | |
| 		SetEntPropFloat(g_iTurrets[i], Prop_Send, "m_flCycle", 0.0);
 | |
| 
 | |
| 		// randomly spread the bullets
 | |
| 		vecOriginClient[0] += GetRandomFloat(-15.0, 15.0);
 | |
| 		vecOriginClient[1] += GetRandomFloat(-15.0, 15.0);
 | |
| 		vecOriginClient[2] += GetRandomFloat(-20.0, 20.0);
 | |
| 		TeleportEntity(g_iMarkers[i], vecOriginClient, NULL_VECTOR, NULL_VECTOR);
 | |
| 
 | |
| 		if (bAttack)
 | |
| 		{
 | |
| 			g_iTicksSinceLastAttack = 0;
 | |
| 
 | |
| 			// check for max range
 | |
| 			float fDistance = GetVectorDistance(vecOriginClient, vecOriginTurret, false);
 | |
| 			if (fDistance > g_fMaxRange)
 | |
| 			{
 | |
| 				AcceptEntityInput(g_iGunfire[i], "Disable");
 | |
| 				continue;
 | |
| 			}
 | |
| 			AcceptEntityInput(g_iGunfire[i], "Enable");
 | |
| 
 | |
| 			// Accuracy
 | |
| 			float fAccuracy = (((-(g_fMaxAccuracy - g_fMinAccuracy))/g_fMaxRange) * fDistance) + g_fMaxAccuracy;
 | |
| 			float R = GetRandomFloat(0.0, 100.0);
 | |
| 			if (FloatCompare(R, fAccuracy) == -1)
 | |
| 				continue;
 | |
| 
 | |
| 			// DMG
 | |
| 			int iHealth = GetClientHealth(iNearestZombie);
 | |
| 			if(iHealth > g_iDamage)
 | |
| 				SetEntityHealth(iNearestZombie, iHealth - g_iDamage);
 | |
| 			else
 | |
| 				ForcePlayerSuicide(iNearestZombie);
 | |
| 
 | |
| 			// KB
 | |
| 			MakeVectorFromPoints(vecOriginTurret, vecOriginClient, vecVector);
 | |
| 			NormalizeVector(vecVector, vecVector);
 | |
| 			ScaleVector(vecVector, g_fKnockback);
 | |
| 			float fClientVelocity[3];
 | |
| 			GetEntDataVector(iNearestZombie, g_iVelocity, fClientVelocity);
 | |
| 			AddVectors(fClientVelocity, vecVector, fClientVelocity);
 | |
| 			SetEntDataVector(iNearestZombie, g_iVelocity, fClientVelocity);
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // Purpose:
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| public void PlaceTurret(int i)
 | |
| {
 | |
| 	if (g_iTurrets[i] == INVALID_ENT_REFERENCE) // no turret
 | |
| 		return;
 | |
| 
 | |
| 	int client = g_iOwner[i];
 | |
| 	if (!IsValidClient(client))
 | |
| 	{
 | |
| 		ClearTurret(i);
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	if (!(IsPlayerAlive(client) && ZR_IsClientHuman(client)))
 | |
| 	{
 | |
| 		ClearTurret(i);
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	float vecEyeAngles[3];
 | |
| 	float vecEyeOrigin[3];
 | |
| 
 | |
| 	GetClientEyeAngles(client, vecEyeAngles);
 | |
| 	GetClientEyePosition(client, vecEyeOrigin);
 | |
| 
 | |
| 	Handle hTraceRay = TR_TraceRayFilterEx(vecEyeOrigin, vecEyeAngles, MASK_ALL, RayType_Infinite, TraceEntityFilter, client);
 | |
| 
 | |
| 	g_bCanPlace[i] = false;
 | |
| 	if(TR_DidHit(hTraceRay))
 | |
| 	{
 | |
| 		float vecEndPosAim[3];
 | |
| 		TR_GetEndPosition(vecEndPosAim, hTraceRay);
 | |
| 
 | |
| 		float vecDown[3] = {90.0, 0.0, 0.0};
 | |
| 		delete hTraceRay;
 | |
| 		hTraceRay = TR_TraceRayFilterEx(vecEndPosAim, vecDown, MASK_ALL, RayType_Infinite, TraceEntityFilter, client);
 | |
| 
 | |
| 		if(TR_DidHit(hTraceRay))
 | |
| 		{
 | |
| 			float vecEndPosDown[3];
 | |
| 			TR_GetEndPosition(vecEndPosDown, hTraceRay);
 | |
| 			TeleportEntity(g_iTurrets[i], vecEndPosDown, NULL_VECTOR, NULL_VECTOR);
 | |
| 
 | |
| 			if (GetVectorDistance(vecEyeOrigin, vecEndPosDown, false) > 500) // maximum distance to place a turret
 | |
| 			{
 | |
| 				delete hTraceRay;
 | |
| 				SetEntityRenderColor(g_iTurrets[i], 255, 0, 0, 0);
 | |
| 				return;
 | |
| 			}
 | |
| 			vecEndPosDown[2] += 5.0;
 | |
| 			vecEndPosAim[2] += 5.0;
 | |
| 
 | |
| 			float vecMins[3] = {-30.0, -30.0, 0.0};
 | |
| 			float vecMaxs[3] = {30.0, 30.0, 63.0};
 | |
| 
 | |
| 			delete hTraceRay;
 | |
| 			hTraceRay = TR_TraceHullFilterEx(vecEndPosDown, vecEndPosAim, vecMins, vecMaxs, MASK_ALL, TraceEntityFilter, client);
 | |
| 			if(!TR_DidHit(hTraceRay))
 | |
| 				g_bCanPlace[i] = true;
 | |
| 		}
 | |
| 	}
 | |
| 	delete hTraceRay;
 | |
| 
 | |
| 	if(g_bCanPlace[i])
 | |
| 		SetEntityRenderColor(g_iTurrets[i], 0, 255, 0, 0);
 | |
| 	else
 | |
| 		SetEntityRenderColor(g_iTurrets[i], 255, 0, 0, 0);
 | |
| }
 | |
| 
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // Purpose:
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| public void OnPlayerRunCmdPost(int client, int buttons)
 | |
| {
 | |
| 	for (int i = 0; i < MAX_TURRETS; i++)
 | |
| 	{
 | |
| 		if (g_iTurrets[i] == INVALID_ENT_REFERENCE) // no turret
 | |
| 			continue;
 | |
| 
 | |
| 		if (g_bPlaced[i]) // already placed
 | |
| 			continue;
 | |
| 
 | |
| 		if(!g_bCanPlace[i]) // cant be placed atm
 | |
| 			continue;
 | |
| 
 | |
| 		if (g_iOwner[i] == client)
 | |
| 		{
 | |
| 			if (buttons & IN_USE)
 | |
| 			{
 | |
| 				SetEntityRenderColor(g_iTurrets[i], 255, 255, 255, 0);
 | |
| 				//g_iOwner[i] = 0;
 | |
| 				g_bPlaced[i] = true;
 | |
| 			}
 | |
| 			break;
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // Purpose:
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| stock bool TraceEntityFilter(int entity, int contentsMask, int turret)
 | |
| {
 | |
| 	if ((entity == turret) || (0 <= entity <= MaxClients))
 | |
| 		return false;
 | |
| 
 | |
| 	return true;
 | |
| }
 | |
| 
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // Purpose:
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| stock int CreateEntityAtOrigin(const char[] classname, const float origin[3])
 | |
| {
 | |
| 	int entity = CreateEntityByName(classname);
 | |
| 
 | |
| 	TeleportEntity(entity, origin, NULL_VECTOR, NULL_VECTOR);
 | |
| 
 | |
| 	return entity;
 | |
| }
 | |
| 
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // Purpose:
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| stock bool DispatchKeyFormat(int entity, const char[] key, const char[] value, any ...)
 | |
| {
 | |
| 	char buffer[1024];
 | |
| 	VFormat(buffer, sizeof(buffer), value, 4);
 | |
| 
 | |
| 	DispatchKeyValue(entity, key, buffer);
 | |
| }
 | |
| 
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // Purpose:
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| stock void SpawnAndActivate(int entity)
 | |
| {
 | |
| 	DispatchSpawn(entity);
 | |
| 	ActivateEntity(entity);
 | |
| }
 | |
| 
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // Purpose:
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| stock void ParentToEntity(int entity, int parent)
 | |
| {
 | |
| 	SetVariantString("!activator");
 | |
| 	AcceptEntityInput(entity, "SetParent", parent, parent);
 | |
| }
 | |
| 
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // Purpose:
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| void ClearTurret(int index, bool bExplode = false)
 | |
| {
 | |
| 	if (bExplode)
 | |
| 		AcceptEntityInput(g_iTurrets[index], "FireUser2");
 | |
| 
 | |
| 	AcceptEntityInput(g_iTurrets[index], "FireUser1");
 | |
| 	g_iTurrets[index] = INVALID_ENT_REFERENCE;
 | |
| 	g_iMarkers[index] = INVALID_ENT_REFERENCE;
 | |
| 	g_iGunfire[index] = INVALID_ENT_REFERENCE;
 | |
| 	g_iExplosion[index] = INVALID_ENT_REFERENCE;
 | |
| 	g_iOwner[index] = 0;
 | |
| 	g_bCanPlace[index] = false;
 | |
| 	g_bPlaced[index] = false;
 | |
| }
 | |
| 
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // Purpose:
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| stock bool IsValidClient(int client, bool nobots = true)
 | |
| {
 | |
| 	if (client <= 0 || client > MaxClients || !IsClientConnected(client) || (nobots && IsFakeClient(client)))
 | |
| 		return false;
 | |
| 
 | |
| 	return IsClientInGame(client);
 | |
| }
 | |
| 
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // Purpose:
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| public void Cvar_MaxRange(ConVar convar, const char[] oldValue, const char[] newValue)
 | |
| {
 | |
| 	g_fMaxRange = convar.FloatValue;
 | |
| }
 | |
| 
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // Purpose:
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| public void Cvar_MinAccuracy(ConVar convar, const char[] oldValue, const char[] newValue)
 | |
| {
 | |
| 	g_fMinAccuracy = convar.FloatValue;
 | |
| }
 | |
| 
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // Purpose:
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| public void Cvar_MaxAccuracy(ConVar convar, const char[] oldValue, const char[] newValue)
 | |
| {
 | |
| 	g_fMaxAccuracy = convar.FloatValue;
 | |
| }
 | |
| 
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // Purpose:
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| public void Cvar_DestroyRange(ConVar convar, const char[] oldValue, const char[] newValue)
 | |
| {
 | |
| 	g_fDestroyRange = convar.FloatValue;
 | |
| }
 | |
| 
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // Purpose:
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| public void Cvar_Knockback(ConVar convar, const char[] oldValue, const char[] newValue)
 | |
| {
 | |
| 	g_fKnockback = convar.FloatValue;
 | |
| }
 | |
| 
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // Purpose:
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| public void Cvar_Damage(ConVar convar, const char[] oldValue, const char[] newValue)
 | |
| {
 | |
| 	g_iDamage = convar.IntValue;
 | |
| }
 | |
| 
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // Purpose:
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| public void Cvar_TicksToSkip(ConVar convar, const char[] oldValue, const char[] newValue)
 | |
| {
 | |
| 	g_iTicksToSkip = convar.IntValue;
 | |
| }
 |