]> icculus.org git repositories - divverent/nexuiz.git/blob - data/qcsrc/server/pathlib.qc
git-svn-id: svn://svn.icculus.org/nexuiz/trunk@4875 f962a42d-fe04-0410-a3ab-8c8b0445ebaa
[divverent/nexuiz.git] / data / qcsrc / server / pathlib.qc
1 .float pathgroup;\r
2 \r
3 .entity path_next;\r
4 .entity path_prev;\r
5 // .entity path_start;\r
6 \r
7 .float(vector start,vector end) path_validate;\r
8 \r
9 float pathlib_stdproc_path_validate(vector start,vector end)\r
10 {\r
11     tracebox(start, self.mins, self.maxs, end, MOVE_NOMONSTERS, self);\r
12 \r
13     if(vlen(trace_endpos - end) < 32)\r
14         return 1;\r
15 \r
16     return 0;\r
17 }\r
18 \r
19 void pathlib_point_use()\r
20 {\r
21     remove(self);\r
22 }\r
23 \r
24 entity pathlib_createpoint(entity parent,entity next,entity first,vector where)\r
25 {\r
26     entity point;\r
27     point = spawn();\r
28     point.classname = "path_node";\r
29 \r
30     //bprint("Create point\n");\r
31 \r
32     traceline(where + '0 0 32' ,where - '0 0 10000',MOVE_NOMONSTERS,self);\r
33     where = trace_endpos + '0 0 32';\r
34 \r
35     setorigin(point,where);\r
36 \r
37     if(first)\r
38         point.owner = parent;\r
39     else\r
40     {\r
41         point.classname = "path_master";\r
42         point.owner = point;\r
43     }\r
44 \r
45     if(parent)\r
46         point.path_prev = parent;\r
47 \r
48     if(next)\r
49         point.path_next = next;\r
50     else\r
51         point.classname = "path_end";\r
52 \r
53     return point;\r
54 }\r
55 \r
56 #define pathib_maxdivide 128\r
57 \r
58 vector pathlib_findsubpath(vector start,vector vcrash,vector end,float maxsize)\r
59 {\r
60     float x,y;//,z;\r
61     float step;\r
62     float clear;\r
63     float dist;\r
64     float pathlength;\r
65     float pathlength_best;\r
66     vector bestpoint;\r
67     vector point;\r
68     //string s;\r
69 \r
70     pathlength_best = 1000000;\r
71 \r
72     step = vlen(self.maxs - self.mins) * 1.5;\r
73     //s = ftos(step);\r
74 \r
75     //bprint("pathlib_findsubpath: step=",s);\r
76     //s = ftos(maxsize);\r
77     //bprint(" size=",s,"\n");\r
78 \r
79     //for(z = -maxsize; z < maxsize; z += step)\r
80     for(y = -maxsize; y < maxsize; y += step)\r
81     for(x = -maxsize; x < maxsize; x += step)\r
82     {\r
83 \r
84         point = vcrash;\r
85         point_x = point_x + x;\r
86         point_y = point_y + y;\r
87 \r
88         traceline(point + '0 0 32' ,point - '0 0 10000',MOVE_NOMONSTERS,self);\r
89         point = trace_endpos + '0 0 32';\r
90 \r
91         clear = self.path_validate(start,point);\r
92 \r
93         if(clear)\r
94         {\r
95             //bprint("Good point\n");\r
96 \r
97             dist = vlen(start - point);\r
98             if(dist > step)\r
99             {\r
100                 pathlength = dist + vlen(point - end);\r
101                 if(pathlength < pathlength_best)\r
102                 {\r
103                     bestpoint = point;\r
104                     pathlength_best = pathlength;\r
105                 }\r
106             }\r
107         }\r
108 \r
109     }\r
110 \r
111     if(pathlength_best != 1000000)\r
112         return bestpoint;\r
113 \r
114     return vcrash;\r
115 }\r
116 \r
117 float pathlib_path(entity start,entity end)\r
118 {\r
119     vector vcrash;\r
120     vector subpath_point;\r
121     entity subpoint;\r
122     //bprint("pathlib_path...\n");\r
123 \r
124     // Fail.\r
125     if(start.cnt > pathib_maxdivide)\r
126         return 0;\r
127 \r
128     if(self.path_validate(start.origin,end.origin))\r
129         return 1;\r
130 \r
131     vcrash = trace_endpos;\r
132 \r
133     subpath_point = pathlib_findsubpath(start.origin,vcrash,end.origin,500);\r
134 \r
135     if(subpath_point == vcrash)\r
136         return 0; // Fail.\r
137 \r
138     subpoint = pathlib_createpoint(start,end,start.owner,subpath_point);\r
139     subpoint.cnt = start.cnt +1;\r
140     start.path_next = subpoint;\r
141     end.path_prev = subpoint;\r
142     if(self.path_validate(start.origin,end.origin))\r
143         return 1;\r
144 \r
145     return pathlib_path(subpoint,end);\r
146 \r
147     /*\r
148     while(!clear)\r
149     {\r
150         ++c;\r
151 \r
152         if(c > pathib_maxdivide)\r
153             return 0;\r
154 \r
155         subpath_point = pathlib_findsubpath(subpoint2.origin,vcrash,end.origin,2000);\r
156         if(subpath_point == vcrash)\r
157             return 0; // Fail.\r
158 \r
159         subpoint = pathlib_createpoint(subpoint2,end,start.owner,subpath_point);\r
160         subpoint.cnt = subpoint2.cnt +1;\r
161         subpoint2.path_next = subpoint;\r
162 \r
163         clear = self.path_validate(subpoint2.origin,end.origin);\r
164         vcrash = trace_endpos;\r
165         if(clear)\r
166             return 1;\r
167         subpoint2 = subpoint;\r
168 \r
169         // Fail.\r
170 \r
171     }*\r
172 \r
173     */\r
174 \r
175 \r
176     return 1;\r
177 }\r
178 \r
179 void pathlib_path_optimize(entity start,entity end)\r
180 {\r
181     entity point,point_tmp;\r
182     point = start.path_next;\r
183     float c;\r
184 \r
185     while(point != end)\r
186     {\r
187         c++;\r
188         if(c > 200)\r
189         {\r
190             //bprint("pathlib_path_optimize runaway!\n");\r
191             return;\r
192         }\r
193         point_tmp = point;\r
194         point = point.path_next;\r
195         if(self.path_validate(point_tmp.path_prev.origin,point_tmp.path_next.origin))\r
196         {\r
197 \r
198             point_tmp.path_next.path_prev = point_tmp.path_prev;\r
199             point_tmp.path_prev.path_next = point_tmp.path_next;\r
200             remove(point_tmp);\r
201         }\r
202     }\r
203 }\r
204 \r
205 void pathlib_deletepath(entity start)\r
206 {\r
207     entity e;\r
208 \r
209     e = findentity(start, owner, start);\r
210     while(e)\r
211     {\r
212         remove(e);\r
213         e = findentity(start, owner, start);\r
214     }\r
215 }\r
216 \r
217 void pathlib_showpath(entity start)\r
218 {\r
219     entity e;\r
220     e = start;\r
221     while(e.path_next)\r
222     {\r
223         te_lightning1(e,e.origin,e.path_next.origin);\r
224         e = e.path_next;\r
225     }\r
226 }\r
227 \r
228 entity dynpath_make(vector from, vector to)\r
229 {\r
230     entity e_start,e_end;\r
231 \r
232     //float t;\r
233     //t = time;\r
234 \r
235     if(!self.path_validate)\r
236         self.path_validate = pathlib_stdproc_path_validate;\r
237 \r
238     e_start = pathlib_createpoint(world,world,world,from);\r
239     e_start.owner = e_start;\r
240     e_end = pathlib_createpoint(e_start,world,e_start,to);\r
241     e_start.path_next = e_end;\r
242     e_start.cnt = 0;\r
243 \r
244     if(!pathlib_path(e_start,e_end))\r
245     {\r
246         //bprint("Crap.\n");\r
247         pathlib_deletepath(e_start);\r
248         remove(e_start);\r
249         return world;\r
250     }\r
251 \r
252     pathlib_path_optimize(e_start,e_end);\r
253 \r
254     //string s;\r
255     //t = time - t;\r
256     //s = ftos(t);\r
257     //bprint("^2Path created in ", s, " seconds\n");\r
258 \r
259     return e_start;\r
260 \r
261 }\r
262 \r
263 void pathlib_test_think()\r
264 {\r
265     //bprint("pathlib_test tink...\n");\r
266     pathlib_showpath(self.enemy);\r
267     self.nextthink = time + 0.5;\r
268 }\r
269 void pathlib_test_dinit()\r
270 {\r
271     entity path;\r
272     entity end;\r
273     // bprint("pathlib_test spawning...\n");\r
274 \r
275     if(self.target == "")\r
276     {\r
277         bprint("^1 ==== ERROR: pathlib_test with no target. ====\n");\r
278         remove(self);\r
279         return;\r
280     }\r
281 \r
282     end = find(world,targetname,self.target);\r
283     if(!end)\r
284     {\r
285         bprint("^1 ==== ERROR: pathlib_test with no valid target. ====\n");\r
286         remove(self);\r
287         return;\r
288     }\r
289 \r
290     setsize(self,'-70 -70 0','70 70 70');\r
291     path = dynpath_make(self.origin,end.origin);\r
292     if(!path)\r
293     {\r
294         bprint("^1 ==== ERROR: pathlib_test pathing fail ====\n");\r
295         remove(self);\r
296         return;\r
297     }\r
298 \r
299     self.enemy = path;\r
300     self.think = pathlib_test_think;\r
301     self.nextthink = time + 0.5;\r
302 \r
303 }\r
304 void spawnfunc_pathlib_test()\r
305 {\r
306     self.think = pathlib_test_dinit;\r
307     self.nextthink = time + 2;\r
308 }\r