GetLOSBetweenPoints
#1

I'm not sure if this is the right section, but since its more a "how-to" discussion I thought it could fit here.

What I am thinking of is a function to get the LOS between to points. It came to my mind after I mapped a whole lot of interiors/houses without teleports and it sucks to be able to read chat of other people through walls.

Since there is no native, I really need some sort of workaround. Kye did it already with 3D-TextLabels, so there is a way, although it seems that I need a plugin.

I have no experience in plugin coding, but maybe my thoughts can help someone realizing it.


1) Is it possible to create invisible 3D-Textlabels and try to get a response from the client; if the client showed it there is nothing in the LOS. Does the client report this to the server? Then there would be no need for a client-plugin, a server plugin could do the whole thing.

If not, how must a client-plugin work? Any thoughts on this?
Reply
#2

Okay, thanks for clearing this.
I might give it a try in my vacations, but it sounds like the chance that Kye implents it in his next update is higher than I got it working.

Thank you though, in case I get something working I'll report back.
Reply
#3

I am not sure if I got it right, but are you talking about something that checks if the player is looking at a range of specific area?
Reply
#4

No. It's to test if an object (i.e. a wall) is in the way of your line-of-sight.

Reply
#5

Theres an internal GTA function for this sure, this should be used and added in some future version, but as it is client-sided and kalcor doesnt like client-sided things itra hard to say if will be added.
Checking it manually by checking object collisions would also work of course, but in opposite to the gta function as part of the engine, it will be extremely slow and I doubt that it could be used efficiently.
Reply
#6

Yeah, I don't see this as a feature an any near releases, UNLESS static objects are added.

Something I've noticed about the 'gameobjects' in SAMP, they're all dynamic! Meaning they have short range of vision, can be moved or destroyed, and have no far-sighted textures.

If we could build static objects (objects that don't move, nor can be destroyed) then I would see a LOS feature being feasible.
Reply
#7

Well here's an idea, you said that you mapped those interiors right? so I am assuming that the walls are mapped too?

If they are.. you could check the direction the player's camera is aiming at, and check if the wall is on the way.

I am not sure how well would it work, but heres an idea for the time being, unless you come up with something better though.
Reply
#8

Just for a sake of conversation this problem is known as ray casting and it is somewhat slow even on client-side.
Reply
#9

Quote:
Originally Posted by Maxips2
View Post
Well here's an idea, you said that you mapped those interiors right? so I am assuming that the walls are mapped too?

If they are.. you could check the direction the player's camera is aiming at, and check if the wall is on the way.

I am not sure how well would it work, but heres an idea for the time being, unless you come up with something better though.
Thats exactly what I want, but please tell me how to "check if the wall is on the way" properly. I just hope that Kye adds the native in the near future, as the internally function already exists (testLOS for 3D Text Labels)
Reply
#10

Basically store the wall as a plane, this could easily be calculated from the rotation and position. Then calculating where the aiming vector, or the vector between player and postion to be checked, cuts the plane is a piece of cake, last step would be checking if that cutting point is on the wall, or next to it (easily using x>wallx etc).
Calculations are all quite lightweighted, especially if you store the plane representation of the wall once you calculated it (e.g. after CreateObject) Things just get nasty when the object is more than a wall, and not plane, then youll need to do tons of checks with this method.
I might also explain this in detail if i find the time/motivation to.
That was my first idea for hitdetection two years ago, until I found a better way.
Reply
#11

Option 1:

*NOTE: I did NOT make this function, I don't know who did make it, but whoever did thank you for this.

pawn Код:
stock Float:GetPointAngleToPoint(Float:x2, Float:y2, Float:X, Float:Y)
{

    new Float:DX, Float:DY;
    new Float:angle;
    DX = floatabs(floatsub(x2,X));
    DY = floatabs(floatsub(y2,Y));
    if (DY == 0.0 || DX == 0.0)
    {
        if(DY == 0 && DX > 0) angle = 0.0;
        else if(DY == 0 && DX < 0) angle = 180.0;
        else if(DY > 0 && DX == 0) angle = 90.0;
        else if(DY < 0 && DX == 0) angle = 270.0;
        else if(DY == 0 && DX == 0) angle = 0.0;
    }
    else
    {
        angle = atan(DX/DY);
        if(X > x2 && Y <= y2) angle += 90.0;
        else if(X <= x2 && Y < y2) angle = floatsub(90.0, angle);
        else if(X < x2 && Y >= y2) angle -= 90.0;
        else if(X >= x2 && Y > y2) angle = floatsub(270.0, angle);
    }
    return floatadd(angle, 90.0);
}

stock GetXYInFrontOfPoint(&Float:x, &Float:y, Float:angle, Float:distance)
{
    x += (distance * floatsin(-angle, degrees));
    y += (distance * floatcos(-angle, degrees));
}

stock IsPlayerAimingAt(playerid, Float:x, Float:y, Float:z, Float:radius)
{
    new Float:camera_x,Float:camera_y,Float:camera_z,Float:vector_x,Float:vector_y,Float:vector_z;
    GetPlayerCameraPos(playerid, camera_x, camera_y, camera_z);
    GetPlayerCameraFrontVector(playerid, vector_x, vector_y, vector_z);
    new Float:vertical, Float:horizontal;
    switch (GetPlayerWeapon(playerid))
    {
        case 34,35,36:
        {
            if (DistanceCameraTargetToLocation(camera_x, camera_y, camera_z, x, y, z, vector_x, vector_y, vector_z) < radius) return true;
            return false;
        }
        case 30,31: {vertical = 4.0; horizontal = -1.6;}
        case 33: {vertical = 2.7; horizontal = -1.0;}
        default: {vertical = 6.0; horizontal = -2.2;}
    }
    new Float:angle = GetPointAngleToPoint(0, 0, floatsqroot(vector_x*vector_x+vector_y*vector_y), vector_z) - 270.0;
    new Float:resize_x, Float:resize_y, Float:resize_z = floatsin(angle+vertical, degrees);
    GetXYInFrontOfPoint(resize_x, resize_y, GetPointAngleToPoint(0, 0, vector_x, vector_y)+horizontal, floatcos(angle+vertical, degrees));
    if (DistanceCameraTargetToLocation(camera_x, camera_y, camera_z, x, y, z, resize_x, resize_y, resize_z) < radius) return true;
    return false;
}

public Float:DistanceCameraTargetToLocation(Float:CamX, Float:CamY, Float:CamZ, Float:ObjX, Float:ObjY, Float:ObjZ, Float:FrX, Float:FrY, Float:FrZ) {

    new Float:TGTDistance;

    TGTDistance = floatsqroot((CamX - ObjX) * (CamX - ObjX) + (CamY - ObjY) * (CamY - ObjY) + (CamZ - ObjZ) * (CamZ - ObjZ));

    new Float:tmpX, Float:tmpY, Float:tmpZ;

    tmpX = FrX * TGTDistance + CamX;
    tmpY = FrY * TGTDistance + CamY;
    tmpZ = FrZ * TGTDistance + CamZ;

    return floatsqroot((tmpX - ObjX) * (tmpX - ObjX) + (tmpY - ObjY) * (tmpY - ObjY) + (tmpZ - ObjZ) * (tmpZ - ObjZ));
}
By the way, this is the ORIGINAL function so I think you would need to remove the weapon check

Put it in your script, to use you would do this:

IsPlayerAimingAt(playerid, x, y, z, range);
The XYZ would be the pos of the object and the range would be the radius form the center of the object.

Option 2:
You could check the distance between the player and the wall object.
You can use this: https://sampwiki.blast.hk/wiki/GetPlayerDistanceFromPoint

And then use the example given here: https://sampwiki.blast.hk/wiki/GetPlayerCameraFrontVector
the fScale would be the distance between you and the object.

Those suggestions aren't very efficient and maybe not so accurate but thats what you could do for now until you get a better way to do it.
Reply
#12

Maxips2: This is about line-of-sight - what a player can actually see.
Reply
#13

Quote:
Originally Posted by Y_Less
Посмотреть сообщение
There is no way AFAIK to do it natively - the client doesn't report any of that information. Off the top of my head, the only thing you could do would be to write a plugin that could read model files (including transparency data) and figure out from there if there is a wall in the way or not.
What about the 'target system'? Only is possible to target a player(enable green arrow) that's on the line of sight, then, I think that grab this 'native' via plugin would be more easily than read model files, right?
Reply
#14

The client reports to the server only what player id it is aiming at.
Reply
#15

I know that, but it was just an idea for a solution to his problem.
Reply
#16

Heres a scripted version of what I explained earlier: http://pastebin.com/hJBauYFA
It checks the "LOS-collision" for all walls created with CreateWallObject. For simplicity it just uses vertical walls with just z rotation. Also I got no idea if it really works, as its completely transcribed from my notes on paper, maybe the angles need to be transformed with the usual
angle = (360 - angle)
way, or whatever else, I hate adapting the mathematical angles to the samp ones In theory it will work, but scripting bugs are a quite sure thing.
The problem is getting the walls sizes in GetWallObjectSize. Probably they have to be measured by hand.

This script runs with a speed of about 1000-2000 LOS checks / second, with 100 created walls. Almost fair enough for checks on chat I guess. Some expensive parts of the calculations are done once while creating the object, instead of again and again for every LOS check. Note that it is extremely unoptimized, I marked some areas that could be optimized. I think just by optimizing the pawn script it could run 3-4 times faster. Transcribing it for a plugin would also make it much faster of course, because the costs are like 80% maths.

This should be an example of how it COULD work, maybe, probably, there are better ways.

Edit: updated to an actually working version, only problem might be the rotation of the wall, as I just tested in the console. Also exact rotations 90, 180, 270, 0 dont work, as I didnt add exceptions for them.
Reply
#17

I've always wanted to see something like this, I spent a while trying to learn how game engines work and how they check collisions with 3D objects (It's bloody confusing) and how the GPU sorts all vertices depending on the distance from the camera, checks if they should be shown etc...

I tried some "2D" versions of this before, where I basically mapped out all the vertices of buildings in a small town, made some deer walk around aimlessly then chase the player if they see him (It worked well, and was scary as fuck, ever had a crazy ravenous hungry deer chase you around a village?)
(and then I added more deer the the lulz)


It's easy for simple 2D maps where point is restricted to 2D movement but as soon as you add another dimension it becomes pretty impossible to do efficiently on the server!


I'd love for this to be added, but I imagine the function would need a playerid parameter because you'd need to pick at least one client to perform the check, and (I assume) they would have to be near the points for the objects to stream etc.

Nice work on that btw Mauzen! I was going to try something like that but it's a bit outside my knowledge!
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)