Raised This Month: $12 Target: $400
 3% 

Best player in viewcone


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
MrDev
Member
Join Date: Sep 2005
Old 12-27-2006 , 08:45   Best player in viewcone
Reply With Quote #1

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



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.
MrDev is offline
Simon Logic
Senior Member
Join Date: Nov 2006
Location: RF
Old 12-27-2006 , 09:16   Re: Best player in viewcone
Reply With Quote #2

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
Simon Logic is offline
Send a message via Skype™ to Simon Logic
MrDev
Member
Join Date: Sep 2005
Old 12-27-2006 , 09:36   Re: Best player in viewcone
Reply With Quote #3

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?
MrDev is offline
Lord of Destruction
Member
Join Date: Sep 2004
Old 12-27-2006 , 10:28   Re: Best player in viewcone
Reply With Quote #4

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

Last edited by Lord of Destruction; 12-27-2006 at 10:44.
Lord of Destruction is offline
MrDev
Member
Join Date: Sep 2005
Old 12-27-2006 , 10:43   Re: Best player in viewcone
Reply With Quote #5

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?
MrDev is offline
The Specialist
BANNED
Join Date: Nov 2006
Old 12-27-2006 , 10:46   Re: Best player in viewcone
Reply With Quote #6

Quote:
Originally Posted by Simon Logic View Post
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 .
The Specialist is offline
Send a message via AIM to The Specialist
Lord of Destruction
Member
Join Date: Sep 2004
Old 12-27-2006 , 10:48   Re: Best player in viewcone
Reply With Quote #7

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

Last edited by Lord of Destruction; 12-27-2006 at 11:01.
Lord of Destruction is offline
MrDev
Member
Join Date: Sep 2005
Old 12-27-2006 , 10:55   Re: Best player in viewcone
Reply With Quote #8

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

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     }
MrDev is offline
Zenith77
Veteran Member
Join Date: Aug 2005
Old 12-27-2006 , 12:40   Re: Best player in viewcone
Reply With Quote #9

Quote:
Originally Posted by The Specialist View Post
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.
__________________
Quote:
Originally Posted by phorelyph View Post
your retatred
Zenith77 is offline
Emp`
AMX Mod X Plugin Approver
Join Date: Aug 2005
Location: Decapod 10
Old 12-27-2006 , 13:47   Re: Best player in viewcone
Reply With Quote #10

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
 }
Emp` is offline
Send a message via AIM to Emp` Send a message via MSN to Emp` Send a message via Yahoo to Emp` Send a message via Skype™ to Emp`
Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 21:40.


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