Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #define IsValidWallObject(%1) (wallplanes[%1][PLANE_POS][0] == 0.0 && wallplanes[%1][PLANE_POS][1] == 0.0)
- enum PlaneEnum {
- Float: PLANE_POS[3], // Position of the plane / of the wall object
- Float: PLANE_COORD[4], // Representation of the plane in coordinate form
- Float: PLANE_BUFFER[4] // Buffers minimum/maximum x and min/max z values for later use
- }
- new wallplanes[400][PlaneEnum];
- CreateWallObject(modelid, Float:x, Float:y, Float:z, Float:rX, Float:rY, Float:rZ)
- {
- // Creating the real object
- new obid = CreateObject(modelid, x, y, z, rX, rY, rZ);
- if (obid == INVALID_OBJECT_ID) {
- return INVALID_OBJECT_ID;
- }
- // Converting the wall to a plane
- // E: x1*a + x2*b + x3*c = d
- // Store position
- wallplanes[obid][PLANE_POS][0] = x;
- wallplanes[obid][PLANE_POS][1] = y;
- wallplanes[obid][PLANE_POS][2] = z;
- // Get params for coordinate representation, a b c d
- wallplanes[obid][PLANE_COORD][0] = floatsin(rZ, degrees);
- wallplanes[obid][PLANE_COORD][1] = floatcos(rZ, degrees);
- wallplanes[obid][PLANE_COORD][2] = 0; // Easy case where walls always are vertical with no x rotation
- wallplanes[obid][PLANE_COORD][3] = x * wallplanes[obid][PLANE_COORD][0] + y * wallplanes[obid][PLANE_COORD][1];
- // Somehow retrieve the size
- new Float:size[4];
- GetWallObjectSize(modelid, size);
- // Buffer some values for boost in checks
- wallplanes[obid][PLANE_BUFFER][0] = x + wallplanes[obid][PLANE_COORD][0] * size[0];
- wallplanes[obid][PLANE_BUFFER][1] = x + wallplanes[obid][PLANE_COORD][0] * size[2];
- // if xmin is greater than xmax (rotation > 180°) swap them
- if (wallplanes[obid][PLANE_BUFFER][0] > wallplanes[obid][PLANE_BUFFER][1]) {
- new Float:temp = wallplanes[obid][PLANE_BUFFER][0];
- wallplanes[obid][PLANE_BUFFER][0] = wallplanes[obid][PLANE_BUFFER][1];
- wallplanes[obid][PLANE_BUFFER][1] = temp;
- }
- wallplanes[obid][PLANE_BUFFER][2] = z + size[1];
- wallplanes[obid][PLANE_BUFFER][3] = z + size[3];
- // Done!
- return obid;
- }
- stock GetWallObjectSize(modelid, Float:size[])
- {
- // Somehow retrive and store the size
- // e.g. with a constant array containing the size for all wall objects
- #pragma unused modelid
- // And NOT this way:
- size[0] = -0.5;
- size[1] = -0.5;
- size[2] = 0.5;
- size[3] = 0.5;
- // Data should look like this:
- // [0],[1]: X/Z-offset from the position pointing to the bottom left corner of the wall
- // [2],[3]: X/Z-offset from the position pointing to the top right corner of the wall
- }
- stock IsLOSFree(Float:x1, Float:y1, Float:z1, Float:x2, Float:y2, Float:z2)
- {
- // Calculate the vector between the two points
- new Float:u, Float:v, Float:w;
- u = x2 - x1;
- v = y2 - y1;
- w = z2 - z1;
- // Preload some used variables
- new Float:lambda;
- new Float:x, /*Float:y,*/ Float:z; // y not needed in this example, just x/z are used for checks
- // Loop through ALL valid wallobjects
- // This could be optimized e.g. by only checking objects in an area around the points etc
- // or at least using foreach instead of IsValidWallObject
- for (new i = 0; i < 400; i++) {
- if (!IsValidWallObject(i)) continue;
- // This actually calculates where the vector cuts the plane
- // lambda = (a*x1 + b*y1 + c*z1 - d) / (u*a + v*b + w*c)
- lambda = (wallplanes[i][PLANE_COORD][0] * x1 + wallplanes[i][PLANE_COORD][1] * y1 + wallplanes[i][PLANE_COORD][2] * z1)
- / (u * wallplanes[i][PLANE_COORD][0] + v * wallplanes[i][PLANE_COORD][1] + w * wallplanes[i][PLANE_COORD][2]);
- // lambda > 1 -> Point of intersection is behind point 2 and so not interesting
- if (lambda > 1.0 || lambda < 0.0) continue;
- // Calculate the actual coordinates of the intersection
- x = x1 + u * lambda;
- //y = y1 + v * lambda; // Not needed as this example just uses x for checking
- z = z1 + w * lambda;
- // Now check if it lies on the wall, or next to it
- // Check x and z areas
- if (x < wallplanes[i][PLANE_BUFFER][0] || x > wallplanes[i][PLANE_BUFFER][1] // < xmin or > xmax
- || z < wallplanes[i][PLANE_BUFFER][2] || z > wallplanes[i][PLANE_BUFFER][3]) // < zmin or > zmax
- continue;
- // Else the point is on the wall, and so the LOS is blocked
- return false;
- }
- // Passed all checks for all walls, so the LOS is free
- return true;
- }
Advertisement
Add Comment
Please, Sign In to add comment