View Single Post
Author Message
akn
Junior Member
Join Date: Aug 2009
Old 02-22-2013 , 04:36   [SNIPPET] first person gunpoint (view model attachment)
Reply With Quote #1

Code will post later, let me explain it first

Start at 2009
I saw the plugin “Advanced Weapon Tracers” by ConnorMcLeod about 4 years ago,
http://forums.alliedmods.net/showthread.php?t=62224
It is a good one, however, Attacker can't see his own tracer, Hence, I was planning to create tracer for first person view.

Trace line is drawn by TE_USERTRACER, which require the start point coordinate, so ask for help to get that point,
http://forums.alliedmods.net/showthread.php?t=100920 (including the picture of gunpoint)
Thanks for Arkshine’s help, I tried function “EngFunc_GetAttachment“. In order get attachment from view model (e.g. v_usp.mdl), I have to create an entity with view model, because it don’t exist at server side. But the result coordinate was incorrect.

Progress at 2013
Re-test the code recently, I found “EngFunc_GetAttachment“ only return correct coordinate when entity angle is 0,0,0, and dias’s post had the same conclusion,
http://forums.alliedmods.net/showthread.php?t=183288

Finally, I change my approach:
1. Get attachment coordinate offset with EngFunc_GetAttachment, when angle is 0,0,0
2. Covert the coordinate offset into distance and angle offset (pitch, yaw)
3. Add angle offset to Attacker view angle to get the angle of the gunpoint
4. Calculate the actual coordinate offset with angle and distance of gunpoint

It is tested and working fine. You may argue the yaw angle is an approximate result in my algorithm, I think that is close enough.

PHP Code:
//first person tracer
#include <amxmodx>
#include <cstrike>
#include <fakemeta_stocks>
#include <engine>
#include <hamsandwich>
#include <fakemeta_util>
#include <maths>

#define VERSION "1.0"

#define write_coord_f(%1)    engfunc(EngFunc_WriteCoord,%1) 

enum _:Coord_e Float:xFloat:yFloat:};
#define VectorAdd(%0,%1,%2)    ( %2[ x ] = %0[ x ] + %1[ x ], %2[ y ] = %0[ y ] + %1[ y ], %2[ z ] = %0[ z ] + %1[ z ] )
#define VectorScale(%0,%1,%2)  ( %2[ x ] = %1 * %0[ x ], %2[ y ] = %1 * %0[ y ], %2[ z ] = %1 * %0[ z ] )

#define max_weapon CSW_P90
#define min_weapon CSW_P228
#define weapon_size max_weapon-min_weapon+1
#define Degree2Radian 3.1415926/180.0

new Trie:g_tClassNames
new dummy_ent
new Float:offset_distance[weapon_size]
new 
Float:offset_pitch[weapon_size]
new 
Float:offset_yaw[weapon_size]

public 
plugin_precache()

  for(new 
i=0;i<weapon_size;i++) offset_distance[i]=0;
  
  
dummy_ent=create_entity("worldspawn");
  
set_entity_visibility(dummy_ent,0);
      
    
g_tClassNames TrieCreate()
    
RegisterHam(Ham_TraceAttack"worldspawn""TraceAttack"1)
    
TrieSetCell(g_tClassNames"worldspawn"1)
    
RegisterHam(Ham_TraceAttack"player""TraceAttack"1)
    
TrieSetCell(g_tClassNames"player"1)
    
register_forward(FM_Spawn"Spawn"1)
}

public 
plugin_init()
{
    
register_plugin("First Person Tracers"VERSION"akn")
}

public 
plugin_end()
{
    
TrieDestroy(g_tClassNames)
}

public 
SpawniEnt )
{
    if( 
pev_valid(iEnt) )
    {
        static 
szClassName[32]
        
pev(iEntpev_classnameszClassNamecharsmax(szClassName))
        if( !
TrieKeyExists(g_tClassNamesszClassName) )
        {
            
RegisterHam(Ham_TraceAttackszClassName"TraceAttack"1)
            
TrieSetCell(g_tClassNamesszClassName1)
        }
    }
}


public 
TraceAttack(iEntiAttackerFloat:flDamageFloat:fDir[3], ptriDamageType)
{
    new 
wid get_user_weapon(iAttacker);
    if( 
wid==CSW_KNIFE || wid==CSW_HEGRENADE || wid == CSW_SMOKEGRENADE || wid == CSW_FLASHBANG || wid == CSW_C4 ) return;
  
    new 
Float:end[3]
    
get_tr2(ptrTR_vecEndPosend)
    
    
Draw_from_gunpoint(iAttacker,wid,end);
}

public 
Draw_from_gunpoint(idwid, const Float:end[3])
{
  new 
Float:p_ori[3];
  new 
Float:p_offset[3];
  new 
Float:p_angle[3];
  new 
Float:w_attach[3];
  new 
Float:d_vector[3];
  new 
Float:xy;
  new 
str[64];
  
  
  
entity_get_vector(id,EV_VEC_origin,p_ori);
  if(
get_distance_f(p_oriend) < 50.0) return;
  
pev(id,pev_view_ofs,p_offset);
    
p_ori[2]+=p_offset[2]        //p_ori now is player view point
      
  
wid=wid-min_weapon;
  
    if(
offset_distance[wid]==0)
    {
        
Get_current_weapon_offset(wid);    //calculate offset for each weapon
    
}
    
  
entity_get_vector(1,EV_VEC_v_angle,p_angle);
  
p_angle[0]=-p_angle[0];    
  
p_angle[0]=floatmul(p_angle[0],Degree2Radian)
  
p_angle[1]=floatmul(p_angle[1],Degree2Radian)
  
p_angle[0]=floatadd(p_angle[0],offset_pitch[wid])
  
p_angle[1]=floatadd(p_angle[1],offset_yaw[wid]) //now p_angle is angle of the gunpoint from player view,
                                                                                                  //for righthand tracer, do floatsub for offset_yaw
  
    
w_attach[2]=sin(p_angle[0])*offset_distance[wid];
    
xy=cos(p_angle[0])*offset_distance[wid];
    
w_attach[1]=sin(p_angle[1])*xy;
    
w_attach[0]=cos(p_angle[1])*xy//now w_attach is coordinate offset from player view
    
    
p_ori[0]=floatadd(w_attach[0],p_ori[0]);
    
p_ori[1]=floatadd(w_attach[1],p_ori[1]);
    
p_ori[2]=floatadd(w_attach[2],p_ori[2]); //now p_ori is coordinate of gunpoint

  
d_vector[0]=end[0]-p_ori[0];
  
d_vector[1]=end[1]-p_ori[1];
  
d_vector[2]=p_ori[2]-end[2];
  
vector_to_angle(d_vector,p_angle);
  
angle_vector(p_angleANGLEVECTOR_FORWARDd_vector);
  
VectorScale(d_vector3000 d_vector);
  
Draw_tracer(p_ori,d_vector);      
}

Get_current_weapon_offset(wid)
{
      new 
classname[32];
    
pev(1pev_viewmodel2classnamesizeof(classname)-1);
    
entity_set_model(dummy_ent,classname);    //set current view model
    
    
new Float:empty[3]={0.00.00.0}
    new 
Float:w_attach[3]
    new 
Float:w_angle[3]
    
entity_set_vector(dummy_ent,EV_VEC_origin,empty);
    
set_pev(dummy_entpev_angles, empty);
    
engfunc(EngFunc_GetAttachmentdummy_ent0w_attachw_angle); //get gunpoint coordinate offset when angle is 0,0,0, origin is 0,0,0
    
w_attach[2]-=1.0 //view model is 1.0 lower than player view point
    
    
offset_distance[wid]=get_distance_f(w_attach, empty);    //distance offset from origin to gunpoint
    
offset_pitch[wid]=atan(w_attach[2]/floatsqroot(w_attach[0]*w_attach[0]+w_attach[1]*w_attach[1])) //pitch offset
    
offset_yaw[wid]=atan(w_attach[1]/w_attach[0]) //yaw offset
}
    

Draw_tracer(const Float:Source[3], const Float:Velocity[3])
{
    
message_beginMSG_BROADCASTSVC_TEMPENTITY );
    
write_byteTE_USERTRACER );
    
write_coord_fSource[0] );
    
write_coord_fSource[1] );
    
write_coord_fSource[2] );
    
write_coord_fVelocity[0] );
    
write_coord_fVelocity[1] );
    
write_coord_fVelocity[2] );
    
write_byte);  //life
    
write_byte);  //color
       
write_byte);  //length
    
message_end();   


Last edited by akn; 02-22-2013 at 08:38. Reason: add code
akn is offline