PHP Code:
/*
To do:
T = needs testing
X = done
- = cancelled
[X] custom camera entity instead of using engine's set_view native
v0.1.3
[X] distance the camera a bit towards the player from the entity it hits in traceline to avoid viewing through walls
[X] check if we can use the entity as a camera without it having a model(doesn't work properly without)
[X] fix camera model not being rendered as set on entity creation
v0.1.5
[T] improve origin calculation code
v0.1.6
[T] fix entities out of the real camera origin's pvs not drawing(fake the setview somehow?)
v0.1.7
[T] use an already existing and precached smallest possible file(sprite/model) for the camera model
[X] try to create the camera entity earlier and only set the rendering in plugin_cfg
[T] local variables instead of global since we don't need them anymore
[T] check if user is alive by native in plugin_unpause since while the plugin was paused caching of information was disabled
v0.2.1
[ ] Cvars for custom rendering
[ ] Cvar for custom required access
[ ] fix camera clipping through solids when nearly touching them
[ ] upright camera instead of 3rd person
[ ] (un/re)register the forwards on plugin (un)pause if needed
[ ]
*/
// Modules
#include <amxmodx>
//#include <engine>
#include <fakemeta>
#include <hamsandwich>
// Plug-in APIs
//#include <cs_ham_bots_api>
// Stocks
#include <bitsums>
//#include <D7Debug>
new g_iIDFwFmPrecacheModel, g_iMaxPlayers, g_iBsAlive, g_iBsThirdPerson,// g_iIDFwAddToFullPack,
//g_iRenderMode[33], g_iRenderFx[33], Float:g_fRenderAmount[33], Float:g_fRenderColor[33][3], Float:g_fTaskRenderCacheInterval = 0.1,
g_iIDEntityCamera, Array:g_iIDArrayModel;//, Float:g_fVecCameraOrigin[33][3], Float:g_fVecCameraAngles[33][3]
enum
{
CAMERA_NONE,
CAMERA_3RDPERSON,
CAMERA_UPLEFT,
CAMERA_TOPDOWN
}
set_view(const iID, const iType)
{
if (!iType)
engfunc(EngFunc_SetView, iID, iID)
else
engfunc(EngFunc_SetView, iID, g_iIDEntityCamera)
}
public plugin_precache()
{
g_iIDArrayModel = ArrayCreate(128, 1);
g_iIDFwFmPrecacheModel = register_forward(FM_PrecacheModel, "fwFmPrecacheModel", 1);
}
public fwFmPrecacheModel(const szFile[])
{
static iSizeFileMin;
if (!iSizeFileMin)
iSizeFileMin = 999999999;
static szNameMod[32], szTemp[128];
if (!szNameMod[0])
get_modname(szNameMod, charsmax(szNameMod))
formatex(szTemp, charsmax(szTemp), szFile)
if (!file_exists(szTemp))
{
formatex(szTemp, charsmax(szTemp), "%s/%s", szNameMod, szFile)
if (!file_exists(szTemp))
{
formatex(szTemp, charsmax(szTemp), "../valve/%s", szFile)
}
}
new iSizeFile;
if (!file_exists(szTemp))
{
if (iSizeFileMin == 999999999)
{
//iSizeFileMin++;
iSizeFile = iSizeFileMin - 1;
}
}
else
iSizeFile = file_size(szTemp);
if (iSizeFileMin > iSizeFile)
{
iSizeFileMin = iSizeFile;
if (!ArraySize(g_iIDArrayModel))
ArrayPushString(g_iIDArrayModel, szFile)
else
ArraySetString(g_iIDArrayModel, 0, szFile)
//ftD7Log(_, _, "[fwFmPrecacheModel] szFile: ^"%s^". iSizeFileMin: %d. iSizeFile: %d.", szTemp, iSizeFileMin, iSizeFile)
}
}
public plugin_init()
{
register_plugin("D7 Camera", "0.2.1", "XunTric, D i 5 7 i n c T, schmurgel1983, Klippy")
RegisterHam(Ham_Spawn, "player", "fwHamSpawnPlayer", 1)
RegisterHam(Ham_Killed, "player", "fwHamKilledPlayerPre")
//RegisterHamBots(Ham_Spawn, "fwHamSpawnPlayer", 1)
//RegisterHamBots(Ham_Killed, "fwHamKilledPlayerPre")
register_forward(FM_SetView, "fwFmSetView", true)
register_forward(FM_UpdateClientData, "fwFmUpdateClientDataPre")
//g_iIDFwAddToFullPack = register_forward(FM_AddToFullPack, "fwFmAddToFullPack", 1);
g_iMaxPlayers = get_maxplayers();
unregister_forward(FM_PrecacheModel, g_iIDFwFmPrecacheModel, 1)
g_iIDEntityCamera = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, "trigger_camera"));
engfunc(EngFunc_SetOrigin, g_iIDEntityCamera, Float:{ 0.0, 0.0, 0.0 })
engfunc(EngFunc_SetSize, g_iIDEntityCamera, Float:{ -12.5, -12.5, -12.5 }, Float:{ 12.5, 12.5, 12.5 })
new szModel[128];
ArrayGetString(g_iIDArrayModel, 0, szModel, charsmax(szModel))
ArrayDestroy(g_iIDArrayModel)
engfunc(EngFunc_SetModel, g_iIDEntityCamera, szModel)
//dllfunc(DLLFunc_Spawn, g_iIDEntityCamera)
set_pev(g_iIDEntityCamera, pev_classname, "D7Camera")
set_pev(g_iIDEntityCamera, pev_solid, SOLID_TRIGGER)
new const g_szCommands[][] =
{
"say /camera",
"say_team /camera",
"say /cam",
"say_team /cam",
"say camera",
"say_team camera",
"say cam",
"say_team cam",/*
"say 1st",
"say_team 1st",
"say 3rd",
"say_team 3rd",*/
"camera",
"cam"
}
for (new iID; iID < sizeof g_szCommands; iID++)
register_clcmd(g_szCommands[iID], "fwClCmdCamera")
}
public plugin_cfg()
{
set_pev(g_iIDEntityCamera, pev_rendermode, kRenderTransTexture)
//set_pev(g_iIDEntityCamera, pev_renderfx, kRenderFxNone)
set_pev(g_iIDEntityCamera, pev_renderamt, 0.0)
}
ftFmVelocityByAim(const iID, const Float:fAmount, Float:fVecTemp[3], const iDirection = ANGLEVECTOR_FORWARD)
{
pev(iID, pev_v_angle, fVecTemp)
angle_vector(fVecTemp, iDirection, fVecTemp)
fVecTemp[0] *= fAmount;
fVecTemp[1] *= fAmount;
fVecTemp[2] *= fAmount;
}
public fwFmUpdateClientDataPre(const iID)
{
if (!bitsum_get(g_iBsThirdPerson, iID) || !bitsum_get(g_iBsAlive, iID))
return;
static Float:fVecTemp[3], Float:fVecTemp2[3], Float:fVecTemp3[3];
pev(iID, pev_origin, fVecTemp)
pev(iID, pev_view_ofs, fVecTemp2)
fVecTemp[0] += fVecTemp2[0];
fVecTemp[1] += fVecTemp2[1];
fVecTemp[2] += fVecTemp2[2];
fVecTemp2 = fVecTemp;
ftFmVelocityByAim(iID, -100.0, fVecTemp3)
fVecTemp2[0] += fVecTemp3[0];
fVecTemp2[1] += fVecTemp3[1];
fVecTemp2[2] += fVecTemp3[2];
fVecTemp3 = fVecTemp2;
new iIDTraceHandle = create_tr2();
engfunc(EngFunc_TraceLine, fVecTemp, fVecTemp2, DONT_IGNORE_MONSTERS, iID, iIDTraceHandle)
get_tr2(iIDTraceHandle, TR_vecEndPos, fVecTemp2)
free_tr2(iIDTraceHandle)
if (fVecTemp2[0] != fVecTemp3[0]
|| fVecTemp2[1] != fVecTemp3[1]
|| fVecTemp2[2] != fVecTemp3[2])
{
fVecTemp3[0] = get_distance_f(fVecTemp, fVecTemp2) - 25.0;
ftFmVelocityByAim(iID, -fVecTemp3[0], fVecTemp3)//, floatround_ceil
fVecTemp[0] += fVecTemp3[0];
fVecTemp[1] += fVecTemp3[1];
fVecTemp[2] += fVecTemp3[2];
}
else
{
fVecTemp = fVecTemp2;
}
pev(iID, pev_v_angle, fVecTemp2)
engfunc(EngFunc_SetOrigin, g_iIDEntityCamera, fVecTemp)
//fVecTemp2[0] *= -1;
set_pev(g_iIDEntityCamera, pev_angles, fVecTemp2)
}
public fwFmSetView(const iID, const iIDEnt)
{
if (iID != iIDEnt || !bitsum_get(g_iBsThirdPerson, iID) || !bitsum_get(g_iBsAlive, iID))
return;
set_view(iID, CAMERA_3RDPERSON)
//ftD7Log(_, _, "[fwFmSetView] iID: %d. iIDEnt: %d.", iID, iIDEnt)
}
public plugin_pause()
{
//unregister_forward(FM_AddToFullPack, g_iIDFwAddToFullPack, 1)
for (new iID = 1; iID <= g_iMaxPlayers; iID++)
if (bitsum_get(g_iBsThirdPerson, iID) && bitsum_get(g_iBsAlive, iID))
{
//remove_task(iID)
set_view(iID, CAMERA_NONE)
//ftD7Log(_, _, "[plugin_pause] iID: %d. Camera: CAMERA_NONE.", iID)
}
}
public plugin_unpause()
{
//g_iIDFwAddToFullPack = register_forward(FM_AddToFullPack, "fwFmAddToFullPack", 1);
for (new iID = 1; iID <= g_iMaxPlayers; iID++)
if (bitsum_get(g_iBsThirdPerson, iID))
{
if (!is_user_alive(iID))
{
bitsum_del(g_iBsAlive, iID)
continue;
}
bitsum_add(g_iBsAlive, iID)
//ftTaskRenderCache(iID)
//set_task(g_fTaskRenderCacheInterval, "ftTaskRenderCache", iID, _, _, "b")
set_view(iID, CAMERA_3RDPERSON)
//ftD7Log(_, _, "[plugin_unpause] iID: %d. Camera: CAMERA_3RDPERSON.", iID)
}
}
/*
public client_infochanged(iID)
{
if (!bitsum_get(g_iBsThirdPerson, iID) || get_user_flags(iID) & ADMIN_LEVEL_B)
return;
remove_task(iID)
bitsum_del(g_iBsThirdPerson, iID)
set_view(iID, CAMERA_NONE)
colored_chat(iID, _, "^3The 3rd person camera is for^4 full VIPs^3 only^1!")
}
public client_authorized(iID)
{
if (is_user_bot(iID))
bitsum_add(g_iBsThirdPerson, iID)
}*/
public client_disconnect(iID)
{
//remove_task(iID)
bitsum_del(g_iBsAlive, iID)
bitsum_del(g_iBsThirdPerson, iID)
}
public fwHamSpawnPlayer(const iID)
{
if (!is_user_alive(iID))
return;
bitsum_add(g_iBsAlive, iID)
if (bitsum_get(g_iBsThirdPerson, iID))
{
//ftTaskRenderCache(iID)
//set_task(g_fTaskRenderCacheInterval, "ftTaskRenderCache", iID, _, _, "b")
set_view(iID, CAMERA_3RDPERSON)
//ftD7Log(_, _, "[fwHamSpawnPlayer] iID: %d. Camera: CAMERA_3RDPERSON.", iID)
}
}
public fwHamKilledPlayerPre(const iID)
{
bitsum_del(g_iBsAlive, iID)
if (bitsum_get(g_iBsThirdPerson, iID))
{
//remove_task(iID)
set_view(iID, CAMERA_NONE)
//ftD7Log(_, _, "[fwHamKilledPlayerPre] iID: %d. Camera: CAMERA_NONE.", iID)
}
}
public fwClCmdCamera(const iID)
{
/* if (!(get_user_flags(iID) & ADMIN_LEVEL_B))
{
colored_chat(iID, _, "^3The 3rd person camera is for^4 full VIPs^3 only^1!")
return PLUGIN_CONTINUE;//PLUGIN_HANDLED_MAIN
}
*/
if (!bitsum_get(g_iBsThirdPerson, iID))
{
/* if (!bitsum_get(g_iBsAlive, iID))
{
colored_chat(iID, _, "^3You must be alive to use the 3rd person camera^1!")
return PLUGIN_CONTINUE;
}
*/
bitsum_add(g_iBsThirdPerson, iID)
if (bitsum_get(g_iBsAlive, iID))
{
//ftTaskRenderCache(iID)
//set_task(g_fTaskRenderCacheInterval, "ftTaskRenderCache", iID, _, _, "b")
set_view(iID, CAMERA_3RDPERSON)
//ftD7Log(_, _, "[fwClCmdCamera] iID: %d. Camera: CAMERA_3RDPERSON.", iID)
}
colored_chat(iID, _, "^4Camera switched successfully to 3rd person^1!")
}
else
{
bitsum_del(g_iBsThirdPerson, iID)
if (bitsum_get(g_iBsAlive, iID))
{
//remove_task(iID)
set_view(iID, CAMERA_NONE)
//ftD7Log(_, _, "[fwClCmdCamera] iID: %d. Camera: CAMERA_NONE.", iID)
}
colored_chat(iID, _, "^4Camera switched successfully to 1st person^1!")
}
return PLUGIN_HANDLED_MAIN;
}
/*
public ftTaskRenderCache(const iID)
{
g_iRenderMode[iID] = pev(iID, pev_rendermode);
g_iRenderFx[iID] = pev(iID, pev_renderfx);
pev(iID, pev_renderamt, g_fRenderAmount[iID])
pev(iID, pev_rendercolor, g_fRenderColor[iID])
//ftD7Log(_, iID, "")
//ftD7Log(_, iID, "[ftTaskRenderCache] iID: %d. g_iRenderMode: %d. g_iRenderFx: %d. g_fRenderAmount: %.1f. g_fRenderColor: %.1f %.1f %.1f.",
//iID, g_iRenderMode[iID], g_iRenderFx[iID], g_fRenderAmount[iID], g_fRenderColor[iID][0], g_fRenderColor[iID][1], g_fRenderColor[iID][2])
}*/
/*
public fwFmAddToFullPack(const iIDESHandle, const e, const iIDEnt, const iIDHost, const iBsFlags, const player, const pSet)
{
if (iIDEnt != g_iIDEntityCamera)
return;
//set_es(iIDESHandle, ES_RenderMode, kRenderTransTexture)
//set_es(iIDESHandle, ES_RenderAmt, 0.0)
if (!bitsum_get(g_iBsThirdPerson, iIDHost)
|| !bitsum_get(g_iBsAlive, iIDHost))
return;
//set_es(iIDESHandle, ES_Origin, g_fVecCameraOrigin[iIDHost])
//set_es(iIDESHandle, ES_Angles, g_fVecCameraAngles[iIDHost])
}
public fwFmAddToFullPack(es_handle, e, ent, host, flags, player, pSet)
{
if (!player || host != ent || !bitsum_get(g_iBsThirdPerson, host) || !bitsum_get(g_iBsAlive, host))
return;
//ftD7Log(_, host, "[fwFmAddToFullPack] hst: %d. g_iRenderMode: %d. g_iRenderFx: %d. g_fRenderAmount: %.1f. g_fRenderColor: %.1f %.1f %.1f.",
//host, g_iRenderMode[host], g_iRenderFx[host], g_fRenderAmount[host], g_fRenderColor[host][0], g_fRenderColor[host][1], g_fRenderColor[host][2])
set_es(es_handle, ES_RenderMode, g_iRenderMode[host]) //kRenderTransAdd so that the player can see his model in the dark
set_es(es_handle, ES_RenderFx, g_iRenderFx[host])
set_es(es_handle, ES_RenderAmt, g_fRenderAmount[host]) //157.0 brightness amount for TransAlpha and opacity amount for kRenderTransTexture
set_es(es_handle, ES_RenderColor, g_fRenderColor[host])
}*/
stock colored_chat(const iTarget, const iSender = 0, const szMessage[], any:...)
{
if (iTarget && !is_user_connected(iTarget))
return;
static szBuffer[192];
vformat(szBuffer, charsmax(szBuffer), szMessage, 4)
static const D7_CHAT_TAG[] = "^1[^4D7^1] ";
format(szBuffer, charsmax(szBuffer), "%s%s", D7_CHAT_TAG, szBuffer)
static msgSayText;
if (!msgSayText)
msgSayText = get_user_msgid("SayText");
if (iTarget)
message_begin(MSG_ONE, msgSayText, _, iTarget)
else
message_begin(MSG_ALL, msgSayText)
write_byte(!iSender ? iTarget : iSender)
write_string(szBuffer)
message_end()
}
/*
// Use post to get "after" u zoomed?
public fwHamWeaponSecondaryAttackPost( i_IDEnt )
{
if ( !is_valid_pev( i_IDEnt ) )
{
return HAM_IGNORED;
}
new i_ID = get_pdata_cbase( i_IDEnt, m_pPlayer, m_Item );
if ( !is_user_alive( i_ID ) || !bitsum_get( g_iBsThirdPerson, i_ID ) )
{
return HAM_IGNORED;
}
new i_Zoom = cs_get_user_zoom( i_ID );
// Attach cam to player
if ( i_Zoom >= CS_SET_FIRST_ZOOM )
{
engfunc( EngFunc_SetView, i_ID, i_ID )
}
// Attach camera back to entity
else
{
engfunc( EngFunc_SetView, i_ID, g_iIDEntityCamera )
}
return HAM_IGNORED;
}
public fwHamWeaponHolsterPre( i_IDEnt )
{
if ( !is_valid_pev( i_IDEnt ) )
{
return HAM_IGNORED;
}
new i_ID = get_pdata_cbase( i_IDEnt, m_pPlayer, m_Item );
if ( !is_user_alive( i_ID ) || !bitsum_get( g_iBsThirdPerson, i_ID ) )
{
return HAM_IGNORED;
}
new i_Zoom = cs_get_user_zoom( i_ID );
// Attach cam to player
if ( i_Zoom >= CS_SET_FIRST_ZOOM )
{
engfunc( EngFunc_SetView, i_ID, g_iIDEntityCamera )
}
// Attach camera back to entity
//else
//{
// engfunc( EngFunc_SetView, i_ID, i_ID )
//}
return HAM_IGNORED;
}
*/