I wrote a fairly well-functioning LOS the other day - also have combat pathing code using it.
I'll paste it here for reference. It essentially draws an angle to the target and checks for blockers.
Code:
bool Mob::CheckCoordLos(float cur_x, float cur_y, float cur_z, float trg_x, float trg_y, float trg_z, float perwalk_x, float perwalk_y, float perwalk_z) {
if (zone->map == 0)
{
return true;
}
float dist_x = cur_x - trg_x;
if (dist_x < 0)
dist_x *= -1;
float dist_y = cur_y - trg_y;
if (dist_y < 0)
dist_y *= -1;
float dist_z = cur_z - trg_z;
if (dist_z < 0)
dist_z *= -1;
if (dist_x <= dist_y && dist_z <= dist_y)
{
perwalk_x /= (dist_y/dist_x);
perwalk_z /= (dist_y/dist_z);
}
else if (dist_y <= dist_x && dist_z <= dist_x)
{
perwalk_y /= (dist_x/dist_y);
perwalk_z /= (dist_x/dist_z);
}
else if (dist_y <= dist_z && dist_x <= dist_z)
{
perwalk_y /= (dist_z/dist_y);
perwalk_x /= (dist_z/dist_x);
}
int steps = 300000; //Just a safety check to prevent endless loops.
while (steps > 0) {
steps--;
//X traj
if (cur_x < trg_x)
{
if (cur_x + perwalk_x < trg_x)
cur_x += perwalk_x;
else
cur_x = trg_x;
}
if (cur_x > trg_x)
{
if (cur_x - perwalk_x > trg_x)
cur_x -= perwalk_x;
else
cur_x = trg_x;
}
//Y traj
if (cur_y < trg_y)
{
if (cur_y + perwalk_y < trg_y)
cur_y += perwalk_y;
else
cur_y = trg_y;
}
if (cur_y > trg_y)
{
if (cur_y - perwalk_y > trg_y)
cur_y -= perwalk_y;
else
cur_y = trg_y;
}
//Z traj
if (cur_z < trg_z)
{
if (cur_z + perwalk_z < trg_z)
cur_z += perwalk_z;
else
cur_z = trg_z;
}
if (cur_z > trg_z)
{
if (cur_z - perwalk_z > trg_z)
cur_z -= perwalk_z;
else
cur_z = trg_z;
}
PNODE pnode = zone->map->SeekNode( zone->map->GetRoot(), cur_x, cur_y );
if (pnode != 0)
{
int *iface = zone->map->SeekFace( pnode, cur_x, cur_y );
if (*iface == -1) {
return false;
}
float tmp_z = 0;
float best_z = -999999;
while(*iface != -1)
{
tmp_z = zone->map->GetFaceHeight( *iface, cur_x, cur_y );
if (tmp_z-1 <= cur_z && tmp_z > best_z)
{
best_z = tmp_z;
}
iface++;
}
if (best_z == -999999)
{
return false;
}
int diff = (best_z) - (cur_z);
if (diff <= 1 && diff >= -1)
{
return false;
}
}
if (cur_y == trg_y && cur_x == trg_x && cur_z == trg_z)
{
return true;
}
}
return true;
}
Rogean should be putting this into the source, but he's lazy.