View difference between Paste ID: hJBauYFA and C2efQiUu
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
}