View Full Version : Find Nearest Object/Wall & Z value of floor @ point?
Xanathol
09-19-2010, 08:37 PM
Forgive me as I am learning my way around the code - I couldn't find a function to identify the closest object / wall / whatever - is there one?
Reason: I am trying to implement the Shadow Knight AA Hate Step in the code. On live, this is an activatable AA that sends the SK forward x distance instantly; think Shadow Step, but always in the direction you are facing, for a fixed distance, unless you run into an object or wall, of course.
Right now, I have the code working for the spell ( no, the client didn't take care of this for me like it does with Shadow Step and yes, I added a break condition to the spell effect code switch ). The only problem is that I can go through walls and at the moment, I can't 'place' the character on the ground should the ground he is facing be lower than what he is on ( much less preventing him from going through a wall when the ground is slanted upwards ), since I don't know of a funciton to find the z value at a given point. So what I think I need is:
1. the ability to find objects / walls 'in the way' along a certain vector.
2. the ability to read the Z value of the map along said vector.
Anyone who knows the code that can point me to the functions I am looking for, if they exist?
Thanks!
joligario
09-20-2010, 05:58 AM
I believe you are looking for the line of sight function. Check LoS to your point?
Derision
09-20-2010, 01:57 PM
Defined in map.h/map.cpp
bool LineIntersectsZone(VERTEX start, VERTEX end, float step, VERTEX *result, FACE **on = NULL) const;
Will check if there are any obstacles in between the points defined by the start and end vertices, returning true if there is an obstacle.
I believe the result vertex is the point of collision, and the face 'on' is the triangle that was hit.
float Map::FindBestZ( NodeRef node_r, VERTEX p1, VERTEX *result, FACE **on) const
Given vertex p1, will return the 'best' Z value for that point. Basically it will cast a ray downwards from point p1 and if it intersects
something, then will return the Z of the face it intersected.
If it finds no ground beneath the given point, it will try again from 10 Z units higher up.
If you look in waypoints.cpp and pathing.cpp, you will find examples of both functions in use.
Xanathol
09-20-2010, 08:18 PM
Thank you both! I must have went right by those - will let you all know how it goes.
Thanks!
Xanathol
10-11-2010, 06:18 PM
Ok, so I gave it a few runs, tried to add in debug messages to figure out what was going wrong, but have to throw in the towel and see if you guys can spot what I am doing wrong here. Here is the sample code I wrote for the Hate Step effect ( recall - warps a character forward in the direction they are facing x distance; its an SK AA on live ).
case SE_ShadowStepDirectional:
{
double look_heading = GetHeading();
look_heading /= 256;
look_heading *= 360;
look_heading += 180;
if(look_heading > 360)
look_heading -= 360;
// note: x and y are backwards
// the -8 is just a multiplier to increase the distance I arbitrarily picked, nothing more
double new_x = ( spells[spell_id].base[i] * -8 ) * sin(double(look_heading * 0.017453289 ));
double new_y = ( spells[spell_id].base[i] * -8 ) * cos(double(look_heading * 0.017453289 ));
double new_z = GetZ( );
// try to see if a zone wall is in the way
VERTEX start, end, result;
FACE *triangle = NULL;
start.x = GetX( );
start.y = GetY( );
start.z = GetZ( );
end.x = GetX( ) + new_x;
end.y = GetY( ) + new_y;
end.z = GetZ( );
bool b = zone->zonemap->LineIntersectsZone( start, end, 1.0f, &result, &triangle );
Message(15, "Debug: result is %s: %lf %lf %lf", ( b == true ? "true" : "false" ), result.x, result.y, result.z );
if( b )
{ // result should give us the point we hit
Message(15, "Debug: intersect @ %lf %lf %lf", result.x, result.y, result.z );
new_x = result.x;
new_y = result.y;
}
else
{ // otherwise, set new_* to values we wanted to use
new_x += GetX( );
new_y += GetY( );
Message(15, "Debug: used2 x,y %lf %lf", new_x, new_y );
}
// now lets find the z-axis value
VERTEX org;
org.x = new_x;
org.y = new_y;
org.z = GetZ( );
Message(15, "Debug: old z %lf", org.z );
//new_z = zone->zonemap->FindBestZ( MAP_ROOT_NODE, org, &result, &triangle );
new_z = org.z - zone->zonemap->FindClosestZ( org );
Message(15, "Debug: new z %lf", new_z );
// I have no idea why, but I had to double the GetHeading return value for this function to work for me, hence the *2
CastToClient()->MovePC( zone->GetZoneID(), zone->GetInstanceID(), new_x, new_y, new_z, GetHeading( ) *2, 0, PCStep );
Message(15, "%s %s", GetName(), spells[spell_id].cast_on_other );
Thus far, I still go into / through walls and seem to always get returned a 0 from FindBestZ ( note - I've been testing int he Arena ), either implementation, while the 'real Z' shown by a #loc command can be vastly different, plus or minus.
I can paste in some of the logs too if that helps, but I figured it may be hard to envision in pure numbers when one is in a wall or not... :)
Anything stand out as to what I am doing wrong? Seems like a rather simple thing to implement but I put no limits as to what I can screw up! :grin:
vBulletin® v3.8.11, Copyright ©2000-2025, vBulletin Solutions Inc.