Make please that BlackHole appeared there where flashgrenade blew up.
Code:
// ==============================================================================================================================
// >>> INCLUDES
// ==============================================================================================================================
#pragma semicolon 1
#include <sourcemod>
#include <sdktools>
#include <sdkhooks>
// ==============================================================================================================================
// >>> PLUGIN INFORMATION
// ==============================================================================================================================
#define PLUGIN_VERSION "1.0"
public Plugin:myinfo =
{
name = "BlackHole Example",
author = "AlexTheRegent",
description = "create blackhole at aim",
version = PLUGIN_VERSION,
url = ""
}
// ==============================================================================================================================
// >>> DEFINES
// ==============================================================================================================================
//#pragma newdecls required
#define MPS MAXPLAYERS+1
#define PMP PLATFORM_MAX_PATH
#define MTF MENU_TIME_FOREVER
#define CID(%0) GetClientOfUserId(%0)
#define UID(%0) GetClientUserId(%0)
#define SZF(%0) %0, sizeof(%0)
#define LC(%0) for (new %0 = 1; %0 <= MaxClients; ++%0) if ( IsClientInGame(%0) )
// ==============================================================================================================================
// >>> CONSOLE VARIABLES
// ==============================================================================================================================
#define BLACKHOLE_RADIUS 800.0 // радиус прит¤гивани¤
// ==============================================================================================================================
// >>> GLOBAL VARIABLES
// ==============================================================================================================================
new Float: g_vBlackHoleOrigin[3]; // расположение черной дыры
new g_iBlackHoleTicks; // сколько тиков таймера будет работать
new g_iLaserModel; // модель дл¤ визуальной части
// ==============================================================================================================================
// >>> FORWARDS
// ==============================================================================================================================
public OnPluginStart()
{
RegConsoleCmd("sm_blackhole", Command_BlackHole); // команда создани¤
}
public OnMapStart()
{
g_iLaserModel = PrecacheModel("materials/sprites/laser.vmt"); // модель дл¤ визуальной части
}
// ==============================================================================================================================
// >>> COMMANDS
// ==============================================================================================================================
public Action:Command_BlackHole(iClient, iArgc)
{
decl Float:vAngles[3];
// получаем позицию прицела
if ( GetClientViewOriginAndAngles(iClient, g_vBlackHoleOrigin, vAngles) ) {
// создаем таймер
CreateTimer(0.1, Timer_BlackHoleTick, 0, TIMER_REPEAT);
g_iBlackHoleTicks = 40;
}
else {
PrintToChat(iClient, "surface not found");
}
return Plugin_Handled;
}
// ==============================================================================================================================
// >>> TIMERS
// ==============================================================================================================================
public Action:Timer_BlackHoleTick(Handle:hTimer)
{
decl Float:vOrigin[3], Float:vDirection[3];
// если дыра заканчиваетс¤
if ( g_iBlackHoleTicks-- <= 0 ) {
// по всем клиентам
LC(i) {
// убираем плавное передвижение, если в радиусе дыры
GetClientAbsOrigin(i, vOrigin);
if ( GetVectorDistance(g_vBlackHoleOrigin, vOrigin) <= BLACKHOLE_RADIUS ) {
if ( GetEntityMoveType(i) == MOVETYPE_FLY ) {
SetEntityMoveType(i, MOVETYPE_WALK);
}
}
}
// останавливаем таймер
return Plugin_Stop;
}
else {
// смотрим, где игрок
LC(i) {
GetClientAbsOrigin(i, vOrigin);
// если в радиусе дыры
if ( GetVectorDistance(g_vBlackHoleOrigin, vOrigin) <= BLACKHOLE_RADIUS ) {
// если не в самом центре
if ( GetVectorDistance(g_vBlackHoleOrigin, vOrigin) > 20.0 ) {
// делаем перемещение плавным (не подверженным гравитации)
if ( GetEntityMoveType(i) != MOVETYPE_FLY ) {
SetEntityMoveType(i, MOVETYPE_FLY);
// чтобы не упиралс¤ в пол
vOrigin[2] += 1.0;
}
// определ¤ем вектор прит¤гивани¤
MakeVectorFromPoints(vOrigin, g_vBlackHoleOrigin, vDirection);
NormalizeVector(vDirection, vDirection);
// сила прит¤гивани¤
ScaleVector(vDirection, 100.0);
// телепортируем
TeleportEntity(i, vOrigin, NULL_VECTOR, vDirection);
}
else {
// в центре, прит¤гивать не нужно
TeleportEntity(i, NULL_VECTOR, NULL_VECTOR, Float:{0.0, 0.0, 0.00001});
}
}
}
}
// визуальный эффект
TE_SetupBeamRingPoint(g_vBlackHoleOrigin, BLACKHOLE_RADIUS, 20.0, g_iLaserModel, 0, 0, 60, 0.1, 40.0, 0.0, {255, 0, 0, 255}, 0, 0);
TE_SendToAll();
// ждем следующего тика
return Plugin_Continue;
}
// ==============================================================================================================================
// Get client view origin and angles
//
// @iClient - target client
// @vOrigin - view origin
// @vAngles - view projection angles
//
// @noreturn
// ==============================================================================================================================
bool:GetClientViewOriginAndAngles(const iClient, Float:vOrigin[3], Float:vAngles[3])
{
// get client eye position and angles
GetClientEyePosition(iClient, vOrigin);
GetClientEyeAngles(iClient, vAngles);
// start trace ray
TR_TraceRayFilter(vOrigin, vAngles, MASK_SOLID, RayType_Infinite, TR_DontHitSelf, iClient);
// if hit something
if ( TR_DidHit(INVALID_HANDLE) )
{
// get collusion origin
TR_GetEndPosition(vOrigin, INVALID_HANDLE);
// get angles
TR_GetPlaneNormal(INVALID_HANDLE, vAngles);
// find projection
GetVectorAngles(vAngles, vAngles);
vAngles[0] += 90.0;
// return true
return true;
}
// return false
return false;
}
// ==============================================================================================================================
// trace ray callback
//
// @iEntity - collusion entity
// @iMask - ?
// @iData - callback data
// ==============================================================================================================================
public bool:TR_DontHitSelf(int iEntity, int iMask, any iData)
{
return ( iEntity != iData );
}