Look at the screenshots. Here a fast test plugin.
PHP Code:
#include <amxmodx>
#include <fakemeta>
#include <engine>
new cvarPointerZMax;
new spriteIndexBeam;
enum _:Coordinates { Float:x, Float:y, Float:z };
enum _:Angles { Float:pitch, Float:yaw, Float:roll };
#define message_begin_f(%0,%1,%2) ( engfunc( EngFunc_MessageBegin, %0, %1, %2 ) )
#define write_coord_f(%0) ( engfunc( EngFunc_WriteCoord, %0 ) )
#define VectorAdd(%0,%1,%2) ( %2[ x ] = %0[ x ] + %1[ x ], %2[ y ] = %0[ y ] + %1[ y ], %2[ z ] = %0[ z ] + %1[ z ] )
#define VectorSubtract(%0,%1,%2) ( %2[ x ] = %0[ x ] - %1[ x ], %2[ y ] = %0[ y ] - %1[ y ], %2[ z ] = %0[ z ] - %1[ z ] )
#define VectorMA(%0,%1,%2,%3) ( %3[ x ] = %0[ x ] + %1 * %2[ x ], %3[ y ] = %0[ y ] + %1 * %2[ y ], %3[ z ] = %0[ z ] + %1 * %2[ z ] )
#define VectorLength(%0) ( floatsqroot ( %0[ x ] * %0[ x ] + %0[ y ] * %0[ y ] + %0[ z ] * %0[ z ] ) )
public plugin_precache()
{
spriteIndexBeam = precache_model( "sprites/laserbeam.spr" );
}
public plugin_init()
{
register_clcmd( "say /test", "ClientCommand_Test" );
cvarPointerZMax = get_cvar_pointer( "sv_zmax" );
}
public ClientCommand_Test( const client )
{
new Float:origin [ Coordinates ];
new Float:direction[ Coordinates ];
GetGunPosition( client, origin );
GetForwardDirection( client, direction );
FireBullet( client, origin, direction );
}
FireBullet( const player, const Float:source[ Coordinates ], const Float:direction[ Coordinates ] )
{
new Float:end [ Coordinates ];
new Float:endPos [ Coordinates ];
new Float:endPos2[ Coordinates ];
new Float:start [ Coordinates ];
VectorMA( source, get_pcvar_float( cvarPointerZMax ), direction, end );
// -- T1 : source -> end
trace_line( player, source, end, endPos );
FX_BeamPoints( source, endPos, .red = 0, .green = 214, .blue = 198 );
FX_DecalTrace( endPos );
VectorMA( endPos, 8.0, direction, start );
// -- T2 : End Position #1 + 8 units -> end.
trace_line( player, start, end, endPos2 );
if ( !traceresult( TR_AllSolid ) )
{
new Float:endPos3[ Coordinates ];
new Float:wall [ Coordinates ];
// -- T3 : End Position #2 -> End Position #1.
trace_line( player, endPos2, endPos, endPos3 );
FX_DecalTrace( endPos3 );
VectorSubtract( endPos3, endPos, wall );
client_print( 0, print_chat, "Wall thickness = %f unit(s)", VectorLength( wall ) );
// -- T4 : End Position #3 -> End
trace_line( player, endPos3, end, endPos );
FX_BeamPoints( source, endPos, .red = 0, .green = 214, .blue = 198 );
FX_DecalTrace( endPos );
}
}
GetGunPosition( const player, Float:origin[ Coordinates ] )
{
new Float:viewOfs[ Coordinates ];
pev( player, pev_origin, origin );
pev( player, pev_view_ofs, viewOfs );
VectorAdd( origin, viewOfs, origin );
}
GetForwardDirection( const player, Float:direction[ Coordinates ] )
{
new Float:viewAngles [ Angles ];
new Float:punchAngles[ Angles ];
pev( player, pev_v_angle, viewAngles );
pev( player, pev_punchangle, punchAngles );
VectorAdd( viewAngles, punchAngles, viewAngles );
engfunc( EngFunc_MakeVectors, viewAngles );
global_get( glb_v_forward, direction );
}
FX_DecalTrace( const Float:origin[ Coordinates ] )
{
message_begin( MSG_BROADCAST, SVC_TEMPENTITY );
{
write_byte( TE_WORLDDECAL );
write_coord_f( origin[ x ] );
write_coord_f( origin[ y ] );
write_coord_f( origin[ z ] );
write_byte( get_decal_index( "{shot1" ) - random_num( 0, 4 ) );
}
message_end();
}
FX_BeamPoints( const Float:startPosition[ Coordinates ], const Float:endPosition[ Coordinates ], const red, const green, const blue )
{
message_begin( MSG_BROADCAST, SVC_TEMPENTITY );
{
write_byte( TE_BEAMPOINTS )
write_coord_f( startPosition[ x ] );
write_coord_f( startPosition[ y ] );
write_coord_f( startPosition[ z ] );
write_coord_f( endPosition[ x ] );
write_coord_f( endPosition[ y ] );
write_coord_f( endPosition[ z ] );
write_short( spriteIndexBeam ) ;
write_byte( 0 )
write_byte( 1 );
write_byte( 255 )
write_byte( 4 );
write_byte( 0 );
write_byte( red );
write_byte( green );
write_byte( blue);
write_byte( 64 );
write_byte( 0 );
}
message_end();
}