SHOW:
|
|
- or go back to the newest paste.
| 1 | - | #define IsValidWallObject(%1) (wallplanes[%1][PLANE_POS][0] == 0.0 && wallplanes[%1][PLANE_POS][1] == 0.0) |
| 1 | + | #define IsValidWallObject(%1) !(wallplanes[%1][PLANE_POS][0] == 0.0 && wallplanes[%1][PLANE_POS][1] == 0.0) |
| 2 | ||
| 3 | enum PlaneEnum {
| |
| 4 | Float: PLANE_POS[3], // Position of the plane / of the wall object | |
| 5 | Float: PLANE_COORD[4], // Representation of the plane in coordinate form | |
| 6 | Float: PLANE_BUFFER[4] // Buffers minimum/maximum x and min/max z values for later use | |
| 7 | } | |
| 8 | ||
| 9 | new wallplanes[400][PlaneEnum]; | |
| 10 | ||
| 11 | - | CreateWallObject(modelid, Float:x, Float:y, Float:z, Float:rX, Float:rY, Float:rZ) |
| 11 | + | stock CreateWallObject(modelid, Float:x, Float:y, Float:z, Float:rX, Float:rY, Float:rZ) |
| 12 | {
| |
| 13 | // Creating the real object | |
| 14 | new obid = CreateObject(modelid, x, y, z, rX, rY, rZ); | |
| 15 | if (obid == INVALID_OBJECT_ID) {
| |
| 16 | return INVALID_OBJECT_ID; | |
| 17 | } | |
| 18 | ||
| 19 | // Converting the wall to a plane | |
| 20 | // E: x1*a + x2*b + x3*c = d | |
| 21 | // Store position | |
| 22 | wallplanes[obid][PLANE_POS][0] = x; | |
| 23 | wallplanes[obid][PLANE_POS][1] = y; | |
| 24 | wallplanes[obid][PLANE_POS][2] = z; | |
| 25 | ||
| 26 | // Get params for coordinate representation, a b c d | |
| 27 | wallplanes[obid][PLANE_COORD][0] = floatsin(rZ, degrees); | |
| 28 | wallplanes[obid][PLANE_COORD][1] = floatcos(rZ, degrees); | |
| 29 | wallplanes[obid][PLANE_COORD][2] = 0; // Easy case where walls always are vertical with no x rotation | |
| 30 | wallplanes[obid][PLANE_COORD][3] = x * wallplanes[obid][PLANE_COORD][0] + y * wallplanes[obid][PLANE_COORD][1]; | |
| 31 | ||
| 32 | // Somehow retrieve the size | |
| 33 | new Float:size[4]; | |
| 34 | GetWallObjectSize(modelid, size); | |
| 35 | ||
| 36 | // Buffer some values for boost in checks | |
| 37 | wallplanes[obid][PLANE_BUFFER][0] = x + wallplanes[obid][PLANE_COORD][0] * size[0]; | |
| 38 | - | wallplanes[obid][PLANE_BUFFER][1] = x + wallplanes[obid][PLANE_COORD][0] * size[2]; |
| 38 | + | wallplanes[obid][PLANE_BUFFER][1] = x + wallplanes[obid][PLANE_COORD][0] * size[1]; |
| 39 | // if xmin is greater than xmax (rotation > 180°) swap them | |
| 40 | if (wallplanes[obid][PLANE_BUFFER][0] > wallplanes[obid][PLANE_BUFFER][1]) {
| |
| 41 | new Float:temp = wallplanes[obid][PLANE_BUFFER][0]; | |
| 42 | wallplanes[obid][PLANE_BUFFER][0] = wallplanes[obid][PLANE_BUFFER][1]; | |
| 43 | wallplanes[obid][PLANE_BUFFER][1] = temp; | |
| 44 | } | |
| 45 | - | wallplanes[obid][PLANE_BUFFER][2] = z + size[1]; |
| 45 | + | wallplanes[obid][PLANE_BUFFER][2] = z + size[2]; |
| 46 | wallplanes[obid][PLANE_BUFFER][3] = z + size[3]; | |
| 47 | ||
| 48 | // Done! | |
| 49 | return obid; | |
| 50 | } | |
| 51 | ||
| 52 | stock GetWallObjectSize(modelid, Float:size[]) | |
| 53 | {
| |
| 54 | // Somehow retrive and store the size | |
| 55 | // e.g. with a constant array containing the size for all wall objects | |
| 56 | #pragma unused modelid | |
| 57 | // And NOT this way: | |
| 58 | size[0] = -0.5; | |
| 59 | - | size[1] = -0.5; |
| 59 | + | size[1] = 0.5; |
| 60 | - | size[2] = 0.5; |
| 60 | + | size[2] = -0.5; |
| 61 | size[3] = 0.5; | |
| 62 | ||
| 63 | // Data should look like this: | |
| 64 | - | // [0],[1]: X/Z-offset from the position pointing to the bottom left corner of the wall |
| 64 | + | // [0],[1]: X-offset minimum and maximum |
| 65 | - | // [2],[3]: X/Z-offset from the position pointing to the top right corner of the wall |
| 65 | + | // [2],[3]: Z-offset minimum and maximum |
| 66 | } | |
| 67 | ||
| 68 | ||
| 69 | stock IsLOSFree(Float:x1, Float:y1, Float:z1, Float:x2, Float:y2, Float:z2) | |
| 70 | {
| |
| 71 | // Calculate the vector between the two points | |
| 72 | new Float:u, Float:v, Float:w; | |
| 73 | u = x2 - x1; | |
| 74 | v = y2 - y1; | |
| 75 | w = z2 - z1; | |
| 76 | ||
| 77 | // Preload some used variables | |
| 78 | new Float:lambda; | |
| 79 | new Float:x, /*Float:y,*/ Float:z; // y not needed in this example, just x/z are used for checks | |
| 80 | // Loop through ALL valid wallobjects | |
| 81 | // This could be optimized e.g. by only checking objects in an area around the points etc | |
| 82 | // or at least using foreach instead of IsValidWallObject | |
| 83 | for (new i = 0; i < 400; i++) {
| |
| 84 | if (!IsValidWallObject(i)) continue; | |
| 85 | ||
| 86 | // This actually calculates where the vector cuts the plane | |
| 87 | // lambda = (a*x1 + b*y1 + c*z1 - d) / (u*a + v*b + w*c) | |
| 88 | - | lambda = (wallplanes[i][PLANE_COORD][0] * x1 + wallplanes[i][PLANE_COORD][1] * y1 + wallplanes[i][PLANE_COORD][2] * z1) |
| 88 | + | lambda = (wallplanes[i][PLANE_COORD][0] * x1 + wallplanes[i][PLANE_COORD][1] * y1 + wallplanes[i][PLANE_COORD][2] * z1 - wallplanes[i][PLANE_COORD][3]) |
| 89 | / (u * wallplanes[i][PLANE_COORD][0] + v * wallplanes[i][PLANE_COORD][1] + w * wallplanes[i][PLANE_COORD][2]); | |
| 90 | ||
| 91 | // lambda < -1 -> Point of intersection is behind point 2 and so not interesting | |
| 92 | - | // lambda > 1 -> Point of intersection is behind point 2 and so not interesting |
| 92 | + | if (lambda > 0.0 || lambda < -1.0) continue; |
| 93 | - | if (lambda > 1.0 || lambda < 0.0) continue; |
| 93 | + | |
| 94 | // Calculate the actual coordinates of the intersection | |
| 95 | x = x1 + u * lambda; | |
| 96 | //y = y1 + v * lambda; // Not needed as this example just uses x for checking | |
| 97 | z = z1 + w * lambda; | |
| 98 | ||
| 99 | // Now check if it lies on the wall, or next to it | |
| 100 | // Check x and z areas | |
| 101 | if (x < wallplanes[i][PLANE_BUFFER][0] || x > wallplanes[i][PLANE_BUFFER][1] // < xmin or > xmax | |
| 102 | || z < wallplanes[i][PLANE_BUFFER][2] || z > wallplanes[i][PLANE_BUFFER][3]) { // < zmin or > zmax
| |
| 103 | - | || z < wallplanes[i][PLANE_BUFFER][2] || z > wallplanes[i][PLANE_BUFFER][3]) // < zmin or > zmax |
| 103 | + | |
| 104 | } | |
| 105 | ||
| 106 | // Else the point is on the wall, and so the LOS is blocked | |
| 107 | return false; | |
| 108 | } | |
| 109 | // Passed all checks for all walls, so the LOS is free | |
| 110 | return true; | |
| 111 | } |