AlliedModders

AlliedModders (https://forums.alliedmods.net/index.php)
-   Scripting Help (https://forums.alliedmods.net/forumdisplay.php?f=11)
-   -   Best player in viewcone (https://forums.alliedmods.net/showthread.php?t=49081)

MrDev 12-27-2006 08:45

Best player in viewcone
 
Hi all

I'm currently creating a plugin, and for that i need to create a drain life spell. Like the one in dota (pugna) or wow (warlock). Making the beam is no problem, nor is the damage dealing or animations. What bugs me it's the way I should detect which player will be the target of the spell.

The best would be to target the player most close to the players aim while ignoring the height (z). Like this

http://www.mortengryning.dk/Files/vec_explain.JPG

In the above illustration enemy2 would be the target because the angle to him is less than enemy1.

So i figured, Hey this is easy, it's just to:

1. Normalize the vector from current aim to player (aimvec)
2. Normalize the vector from each enemy to player (enemyvec)
3. Take the dot product between those, since (X dot Y) = |x||y|cos(¤)where ¤ is the angle between the vectors.
4. Find arccos(¤) and compare the angle

But nooo, this doesn't work; I'm pretty sure the problem lies in my understanding about the half-life geometry system.

If you substract 2 origins (points) you end up with a.. what? Origins in half-life seems to match points in geometry but angles seems to be different since they contain pitch, yaw and tilt. I've tryed to modify some code from Lord Of Destruction and it works.. sorta... but it's not always the best match and it sometimes selects the player behind me???

Here's the code
Code:
//Supposed :] - to find the angle betwene //the CoreID and TargetID in the Distance d public Float:Find_Angle(CoreID, TargetID, Float:Distance) {     new Float:CoreAngles[3] = { 0.0, 0.0, 0.0 };     new Float:CoreOrigin[3];     pev(CoreID, pev_origin, CoreOrigin );     new Float:TargetOrigin[3];     pev(TargetID, pev_origin, TargetOrigin );         if (get_distance_f(CoreOrigin,TargetOrigin) > Distance)     {         return 9999.9     }     new anglemode:Mode = degrees;     // >> [ calculate Delta ]     new Float:DeltaOrigin[3];     for ( new i = 0; i < 3; i++ )         DeltaOrigin[i] = CoreOrigin[i] - TargetOrigin[i];     // >> [ calculate angle ]         CoreAngles[x] = floatatan( DeltaOrigin[z] / Distance2D( DeltaOrigin[x], DeltaOrigin[y] ), Mode ) ;     CoreAngles[y] = floatatan( DeltaOrigin[y] / DeltaOrigin[x], Mode );     //Why x?? Isn't this pitch??     ( DeltaOrigin[x] >= 0.0 ) ? ( CoreAngles[y] += 180.0 ) : ( CoreAngles[y] += 0.0 );         //Angles from [-180:180] - We want the closets to our aim so take abs? Not sure about this either     if (CoreAngles[y] < 0.0)     CoreAngles[y] = CoreAngles[y]*(-1)             return CoreAngles[y] }

I really need this for my mod. If anyone could post some suggestions/solutions/info or contact me @ [email protected] (msn) i would be very grateful.

Simon Logic 12-27-2006 09:16

Re: Best player in viewcone
 
HLSDK::combat.cpp
Code:

//=========================================================
// FInViewCone - returns true is the passed vector is in
// the caller's forward view cone. The dot product is performed
// in 2d, making the view cone infinitely tall.
//=========================================================
BOOL CBaseMonster :: FInViewCone ( Vector *pOrigin )
{
        Vector2D        vec2LOS;
        float                flDot;

        UTIL_MakeVectors ( pev->angles );
       
        vec2LOS = ( *pOrigin - pev->origin ).Make2D();
        vec2LOS = vec2LOS.Normalize();

        flDot = DotProduct (vec2LOS , gpGlobals->v_forward.Make2D() );

        if ( flDot > m_flFieldOfView )
        {
                return TRUE;
        }
        else
        {
                return FALSE;
        }
}

m_flFieldOfView = 0 // 180 degrees
m_flFieldOfView = 0.5 // 90 degrees

MrDev 12-27-2006 09:36

Re: Best player in viewcone
 
Thanks for the reply. I have reviewed the function myself and I must admit it didn't really work well. But that doesn't mean the function is wrong ;)

I noticed they didn't normalize the aimvec and I assume the fldot calculation is in radians?

So if i want to extract the angle from all this I would have to add something like:

new anglemode:mode = radians;
float angle = floatacos(fldot,mode)

and then compare the different angles?

I could make the check first (fldot > 0.5) to make sure the player we're trying to find IS in the viewcone. However I think it was stated somewhere else that ViewCone didn't really work well?

Lord of Destruction 12-27-2006 10:28

Re: Best player in viewcone
 
My function was only intended to set the clients aim vector to an origin regardless where this origin is.

btw : there is a much more efficient way
Code:
stock setClientAIM ( Client, Entity ) {     static Float:vecOrigin[ 3 ];     static Float:vecTarget[ 3 ];     static Float:angResult[ 3 ];     entity_get_vector( Client, EV_VEC_origin, vecOrigin );     entity_get_vector( Entity, EV_VEC_origin, vecTarget );     vecOrigin[ 0 ] = vecTarget[ 0 ] - vecOrigin[ 0 ];     vecOrigin[ 1 ] = vecTarget[ 1 ] - vecOrigin[ 1 ];     vecOrigin[ 2 ] = vecTarget[ 2 ] - vecOrigin[ 2 ];     vector_to_angle( vecOrigin, angResult );     entity_set_vector( Client, EV_VEC_angles, angResult );     entity_set_int( Client, EV_INT_fixangle, 1 ); }

but what you need is more like
Code:
stock getNextEnemy ( Client ) {     new end = get_maxplayers();     new Float:minr = float( getTeleportRange( Client ) );     new Ret = 0;     new Float:rang;     for ( new Enemy = 1; Enemy <= end; Enemy++ )     {         if ( !is_user_connected( Enemy ) )             continue;         if ( !is_user_alive( Enemy ) || Enemy == Client )             continue;         if ( getGameMODE() > 0 && getClientTEAM( Enemy ) == getClientTEAM( Client ) )             continue;                     // add in view cone / trace line here         rang = entity_range( Enemy, Client );         if ( rang < minr )         {             Ret = Enemy ;             minr = rang;         }     }     return Ret; }
This finds the closest enemy next to you ( but with z dimension because its actually for the ESF Mod ^^ ) but if you add inviewcone (and traceline?) the origins then you should have reached your goal

Of course you need to get the natives I used mod specific


And for enemy2 you will need also need to add something like the smallest( floatabs(floatacos( dotp( playera, playerb ) ) )) as i did with the distance

for dotp you may consult your favourite math formula collection^^
or use pm's xs library

MrDev 12-27-2006 10:43

Re: Best player in viewcone
 
Thanks for the response. This would select the player closest to me IN my viewcone WHEN we can trace a line to him.. which is almost what i want. However if the player has 3 players in line of sight (viewcone+traceline) it should be obvious to him which one will be the target of the spell. The troubles im having is selecting the best target, i.e the target closest to his aim. I know how to do in teory but i can't get the code to work properly.

I see you're edited your post :) - And yes that's what i want, but im not sure what playera,b is?

The Specialist 12-27-2006 10:46

Re: Best player in viewcone
 
Quote:

Originally Posted by Simon Logic (Post 420488)
HLSDK::combat.cpp
Code:

//=========================================================
// FInViewCone - returns true is the passed vector is in
// the caller's forward view cone. The dot product is performed
// in 2d, making the view cone infinitely tall.
//=========================================================
BOOL CBaseMonster :: FInViewCone ( Vector *pOrigin )
{
    Vector2D    vec2LOS;
    float        flDot;
 
    UTIL_MakeVectors ( pev->angles );
 
    vec2LOS = ( *pOrigin - pev->origin ).Make2D();
    vec2LOS = vec2LOS.Normalize();
 
    flDot = DotProduct (vec2LOS , gpGlobals->v_forward.Make2D() );
 
    if ( flDot > m_flFieldOfView )
    {
        return TRUE;
    }
    else
    {
        return FALSE;
    }
}

m_flFieldOfView = 0 // 180 degrees
m_flFieldOfView = 0.5 // 90 degrees

this is a very stupid thing to do Stop posting cut out sections of C++ files . All your doing is confusing people . And your not even attempting to explaine it .

Lord of Destruction 12-27-2006 10:48

Re: Best player in viewcone
 
upps playera is the <forward>vector of the players angles ( ang_to_vec ) aka his aiming vector
playerb is the enemyorigin - clientorigin ( connectionvector )

so you'll have to find the smallest
floatabs(floatacos( dotp( forwardvector( client.angles ), enemy.origin - client.origin ) ) )
this should result in the closest enemy to your crosshair

MrDev 12-27-2006 10:55

Re: Best player in viewcone
 
Thanks Lod and others

I got it to work with a modified sample of the c++ variant. This code will return a float where 0.0 is furthest away and 1.0 is closests to our aimline. If the player is not in the radius (distance) this function will return 0.0. Now all there is to do is to make a traceline check and people can begin to drain life :P

Code:
public Float:Find_Angle(Core,Target,Float:dist) {     new Float:vec2LOS[2]     new Float:flDot     new Float:CoreOrigin[3]     new Float:TargetOrigin[3]     new Float:CoreAngles[3]         pev(Core,pev_origin,CoreOrigin)     pev(Target,pev_origin,TargetOrigin)         if (get_distance_f(CoreOrigin,TargetOrigin) > dist)         return 0.0         pev(Core,pev_angles, CoreAngles)         for ( new i = 0; i < 2; i++ )         vec2LOS[i] = TargetOrigin[i] - CoreOrigin[i]             new Float:veclength = Vec2DLength(vec2LOS)         //Normalize V2LOS     if (veclength <= 0.0)     {         vec2LOS[x] = 0.0         vec2LOS[y] = 0.0     }     else     {         new Float:flLen = 1.0 / veclength;         vec2LOS[x] = vec2LOS[x]*flLen         vec2LOS[y] = vec2LOS[y]*flLen     }         //Do a makevector to make v_forward right     engfunc(EngFunc_MakeVectors,CoreAngles)         new Float:v_forward[3]     new Float:v_forward2D[2]     get_global_vector(GL_v_forward, v_forward)         v_forward2D[x] = v_forward[x]     v_forward2D[y] = v_forward[y]     //flDot = DotProduct (vec2LOS , gpGlobals->v_forward.Make2D() );     flDot = vec2LOS[x]*v_forward2D[x]+vec2LOS[y]*v_forward2D[y]         //0.5 = 90'     if ( flDot > 0.5 )     {         return flDot     }             return 0.0     }

Zenith77 12-27-2006 12:40

Re: Best player in viewcone
 
Quote:

Originally Posted by The Specialist (Post 420500)
this is a very stupid thing to do Stop posting cut out sections of C++ files . All your doing is confusing people . And your not even attempting to explaine it .

Maybe you, but the thread starter clearly understood as you can see in his response to the post.

Emp` 12-27-2006 13:47

Re: Best player in viewcone
 
what you can do is use the get_distance_to_line stock by KoST (the line being from the player to where they are aiming) and then have it check everyone, and then just target the closest player.

Code:

#include <xs>
//////////////
 stock get_distance_to_line(Float:pos_start[3], Float:pos_end[3], Float:pos_object[3])
 {
        new Float:vec_start_end[3], Float:vec_start_object[3], Float:vec_end_object[3], Float:vec_end_start[3]
        xs_vec_sub(pos_end, pos_start, vec_start_end)                // vector from start to end
        xs_vec_sub(pos_object, pos_start, vec_start_object)        // vector from end to object
        xs_vec_sub(pos_start, pos_end, vec_end_start)                // vector from end to start
        xs_vec_sub(pos_end, pos_object, vec_end_object)                // vector object to end

        new Float:len_start_object = getVecLen(vec_start_object)
        new Float:angle_start = floatacos(xs_vec_dot(vec_start_end, vec_start_object) / (getVecLen(vec_start_end) * len_start_object), degrees) 
        new Float:angle_end = floatacos(xs_vec_dot(vec_end_start, vec_end_object) / (getVecLen(vec_end_start) * getVecLen(vec_end_object)), degrees) 

        if(angle_start <= 90.0 && angle_end <= 90.0)
                return floatround(len_start_object * floatsin(angle_start, degrees))
        return -1
 }
 stock Float:getVecLen(Float:Vec[3])
 {
        new Float:VecNull[3] = {0.0, 0.0, 0.0}
        new Float:len = get_distance_f(Vec, VecNull)
        return len
 }



All times are GMT -4. The time now is 22:24.

Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.