here you go after few tests...
PHP Code:
#include <amxmodx>
#include <fakemeta>
#include <fakemeta_util>
#include <hamsandwich>
#include <xs>
#define VERSION "0.0.2"
#define MAX_PLAYERS 32
#define USE_TOGGLE 3
new CAMERA_FORWARD
new CAMERA_RIGHT
new CAMERA_UP
new CAMERA_FRACTION
new g_iPlayerCamera[MAX_PLAYERS+1]
new g_iMaxPlayers;
new sprite_index;
public plugin_precache() sprite_index = precache_model("sprites/laserbeam.spr");
public plugin_init()
{
register_plugin("Camera View AUTOMATIC", VERSION, "ConnorMcLeod")
CAMERA_FORWARD = register_cvar("camera_forward", "-100.0")
CAMERA_RIGHT = register_cvar("camera_right", "0.0")
CAMERA_UP = register_cvar("camera_up", "25.0")
CAMERA_FRACTION = register_cvar("camera_fraction", "-35.0")
RegisterHam(Ham_Spawn, "player", "CBasePlayer_Spawn_Post", 1)
register_forward(FM_SetView, "SetView")
RegisterHam(Ham_Think, "trigger_camera", "Camera_Think")
g_iMaxPlayers = get_maxplayers();
}
public CBasePlayer_Spawn_Post(id)
{
if(!is_user_alive(id))
{
return
}
new iEnt = g_iPlayerCamera[id]
if(!pev_valid(iEnt))
{
static iszTriggerCamera
if(!iszTriggerCamera)
{
iszTriggerCamera = engfunc(EngFunc_AllocString, "trigger_camera")
}
iEnt = engfunc(EngFunc_CreateNamedEntity, iszTriggerCamera)
set_kvd(0, KV_ClassName, "trigger_camera")
set_kvd(0, KV_fHandled, 0)
set_kvd(0, KV_KeyName, "wait")
set_kvd(0, KV_Value, "999999")
dllfunc(DLLFunc_KeyValue, iEnt, 0)
set_pev(iEnt, pev_spawnflags, SF_CAMERA_PLAYER_TARGET|SF_CAMERA_PLAYER_POSITION)
set_pev(iEnt, pev_flags, pev(iEnt, pev_flags) | FL_ALWAYSTHINK)
dllfunc(DLLFunc_Spawn, iEnt)
g_iPlayerCamera[id] = iEnt
new Float:flMaxSpeed, iFlags = pev(id, pev_flags)
pev(id, pev_maxspeed, flMaxSpeed)
ExecuteHam(Ham_Use, iEnt, id, id, USE_TOGGLE, 1.0)
set_pev(id, pev_flags, iFlags)
engfunc(EngFunc_SetClientMaxspeed, id, flMaxSpeed)
set_pev(id, pev_maxspeed, flMaxSpeed)
}
}
public SetView(id, iEnt)
{
if(is_user_alive(id))
{
new iCamera = g_iPlayerCamera[id]
if(iCamera && iEnt != iCamera)
{
new szClassName[16]
pev(iEnt, pev_classname, szClassName, charsmax(szClassName))
if(!equal(szClassName, "trigger_camera")) // should let real cams enabled
{
engfunc(EngFunc_SetView, id, iCamera) // shouldn't be always needed
return FMRES_SUPERCEDE;
}
}
}
return FMRES_IGNORED
}
public client_disconnect(id)
{
new iEnt = g_iPlayerCamera[id]
if(pev_valid(iEnt))
{
engfunc(EngFunc_RemoveEntity, iEnt)
}
g_iPlayerCamera[id] = 0
}
public get_cam_owner(iEnt)
{
static id
for(id = 1; id<=g_iMaxPlayers; id++)
{
if(g_iPlayerCamera[id] == iEnt)
{
return id
}
}
return 0
}
public Camera_Think(iEnt)
{
static id
if(!(id = get_cam_owner(iEnt)))
{
return
}
static Float:fVecPlayerOrigin[3], Float:fVecCameraOrigin[3], Float:fVecAngles[3],
Float:fVecForward[3], Float:fVecRight[3], Float:fVecUp[3]
static iOrigin[3];
get_user_origin(id, iOrigin, 1);
IVecFVec(iOrigin, fVecPlayerOrigin);
pev(id, pev_v_angle, fVecAngles)
angle_vector(fVecAngles, ANGLEVECTOR_FORWARD, fVecForward)
angle_vector(fVecAngles, ANGLEVECTOR_RIGHT, fVecRight)
angle_vector(fVecAngles, ANGLEVECTOR_UP, fVecUp)
fVecCameraOrigin[0] = fVecPlayerOrigin[0] + fVecForward[0] * get_pcvar_float(CAMERA_FORWARD) + fVecRight[0] * get_pcvar_float(CAMERA_RIGHT);
fVecCameraOrigin[1] = fVecPlayerOrigin[1] + fVecForward[1] * get_pcvar_float(CAMERA_FORWARD) + fVecRight[1] * get_pcvar_float(CAMERA_RIGHT);
fVecCameraOrigin[2] = fVecPlayerOrigin[2] + fVecUp[2] * get_pcvar_float(CAMERA_UP) ;
engfunc(EngFunc_TraceLine, fVecPlayerOrigin, fVecCameraOrigin, DONT_IGNORE_MONSTERS, id, 0)
static Float:flFraction
get_tr2(0, TR_flFraction, flFraction)
if(flFraction != 1.0) // adjust camera place if close to a wall
{
flFraction *= get_pcvar_float(CAMERA_FRACTION)
fVecCameraOrigin[0] = fVecPlayerOrigin[0] + (fVecForward[0] * flFraction);
fVecCameraOrigin[1] = fVecPlayerOrigin[1] + (fVecForward[1] * flFraction)
fVecCameraOrigin[2] = fVecPlayerOrigin[2] + (fVecForward[2] * flFraction)
}
set_pev(iEnt, pev_origin, fVecCameraOrigin)
static Float:fEntityEndPosition[3];
getAimEndPosition(id, fEntityEndPosition)
lookAtOrigin(iEnt, fEntityEndPosition)
beam_bet_2origin(fVecPlayerOrigin, fEntityEndPosition);
}
beam_bet_2origin(Float:fOrigin1[3], Float:fOrigin2[3])
{
message_begin(MSG_ALL, SVC_TEMPENTITY, _, 0)
write_byte(TE_BEAMPOINTS)
engfunc(EngFunc_WriteCoord, fOrigin1[0])
engfunc(EngFunc_WriteCoord, fOrigin1[1])
engfunc(EngFunc_WriteCoord, fOrigin1[2])
engfunc(EngFunc_WriteCoord, fOrigin2[0])
engfunc(EngFunc_WriteCoord, fOrigin2[1])
engfunc(EngFunc_WriteCoord, fOrigin2[2])
write_short(sprite_index)
write_byte(0)
write_byte(10)
write_byte(1)
write_byte(5)
write_byte(1)
write_byte(0)
write_byte(255)
write_byte(0)
write_byte(255)
write_byte(1)
message_end()
}
getAimEndPosition(id, Float:fOrigin[3])
{
static Float:fStart[3], Float:fDest[3], tr2;
pev(id, pev_origin, fStart);
pev(id, pev_view_ofs, fDest);
xs_vec_add(fStart, fDest, fStart);
pev(id, pev_v_angle, fDest)
angle_vector(fDest, ANGLEVECTOR_FORWARD, fDest);
xs_vec_mul_scalar(fDest, 4000.0, fDest);
tr2 = create_tr2();
engfunc(EngFunc_TraceLine, fStart, fDest, IGNORE_MONSTERS, id, tr2);
get_tr2(tr2, TR_vecEndPos, fOrigin);
free_tr2(tr2);
}
lookAtOrigin(const id, const Float:fOrigin_dest[3])
{
static Float:fOrigin[3]
pev(id, pev_origin, fOrigin)
if( 1 <= id && id <= 32 )
{
static Float:fVec[3];
pev(id, pev_view_ofs, fVec);
xs_vec_add(fOrigin, fVec, fOrigin);
}
static Float:fLook[3], Float:fLen;
xs_vec_sub(fOrigin_dest, fOrigin, fOrigin)
fLen = xs_vec_len(fOrigin);
fOrigin[0] /= fLen;
fOrigin[1] /= fLen;
fOrigin[2] /= fLen;
vector_to_angle(fOrigin, fLook)
fLook[0] *= -1;
set_pev(id, pev_angles, fLook);
set_pev(id, pev_fixangle, 1);
}
just the bullets decals are invalid but the traceattacks are quite right you need to redirect the bullets hole decals, i failed to do it since the decals are client side but u can block them and make new ones but im not sure how.