[SNIPPET] first person gunpoint (view model attachment)

For scripting examples for learning how to use AMXX.
User avatar
Archive-Poster
Posts: 1249
Gender:
United States of America

[SNIPPET] first person gunpoint (view model attachment)

Post by Archive-Poster »

Code will post later, let me explain it first

Start at 2009
I saw the plugin “Advanced Weapon Tracers” 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,
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

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.

Code: Select all

//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:x, Float:y, Float:z };
#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 Spawn( iEnt )
{
    if( pev_valid(iEnt) )
    {
        static szClassName[32]
        pev(iEnt, pev_classname, szClassName, charsmax(szClassName))
        if( !TrieKeyExists(g_tClassNames, szClassName) )
        {
            RegisterHam(Ham_TraceAttack, szClassName, "TraceAttack", 1)
            TrieSetCell(g_tClassNames, szClassName, 1)
        }
    }
}


public TraceAttack(iEnt, iAttacker, Float:flDamage, Float:fDir[3], ptr, iDamageType)
{
    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(ptr, TR_vecEndPos, end)
    
    Draw_from_gunpoint(iAttacker,wid,end);
}

public Draw_from_gunpoint(id, wid, 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_ori, end) < 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_angle, ANGLEVECTOR_FORWARD, d_vector);
  VectorScale(d_vector, 3000 , d_vector);
  Draw_tracer(p_ori,d_vector);      
}

Get_current_weapon_offset(wid)
{
      new classname[32];
    pev(1, pev_viewmodel2, classname, sizeof(classname)-1);
    entity_set_model(dummy_ent,classname);    //set current view model
    
    new Float:empty[3]={0.0, 0.0, 0.0}
    new Float:w_attach[3]
    new Float:w_angle[3]
    entity_set_vector(dummy_ent,EV_VEC_origin,empty);
    set_pev(dummy_ent, pev_angles, empty);
    engfunc(EngFunc_GetAttachment, dummy_ent, 0, w_attach, w_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_begin( MSG_BROADCAST, SVC_TEMPENTITY );
    write_byte( TE_USERTRACER );
    write_coord_f( Source[0] );
    write_coord_f( Source[1] );
    write_coord_f( Source[2] );
    write_coord_f( Velocity[0] );
    write_coord_f( Velocity[1] );
    write_coord_f( Velocity[2] );
    write_byte( 5 );  //life
    write_byte( 0 );  //color
       write_byte( 3 );  //length
    message_end();   
} 

Who is online

Users browsing this forum: No registered users and 0 guests