]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/server/pathlib/path_waypoint.qc
Merge branch 'TimePath/globalforces' into 'master'
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / pathlib / path_waypoint.qc
1 #include "path_waypoint.qh"
2 #include "../bot/api.qh"
3
4 #include "pathlib.qh"
5 #include "main.qh"
6
7 var float pathlib_wpp_open(entity wp, entity child, float cost);
8
9 void pathlib_wpp_close(entity wp)
10 {
11     --pathlib_open_cnt;
12     ++pathlib_closed_cnt;
13
14     wp.pathlib_list = closedlist;
15
16     if(wp == best_open_node)
17         best_open_node = NULL;
18
19     if(wp == goal_node)
20         pathlib_foundgoal = true;
21 }
22
23 float pathlib_wpp_opencb(entity wp, entity child, float cost)
24 {
25
26     if(child.pathlib_list == closedlist)
27         return false;
28
29         // FIXME! wp.wp##mincost is NOT distance. Make it distance or add a field for distance to be used here (for better speed)
30         cost = vlen(child.origin - wp.origin);
31
32     child.path_prev      = wp;
33     child.pathlib_list   = openlist;
34     child.pathlib_node_g = wp.pathlib_node_g + cost;
35     child.pathlib_node_h = pathlib_heuristic(child.origin, goal_node.origin);
36     child.pathlib_node_c = pathlib_wpp_waypointcallback(child, wp);
37     child.pathlib_node_f = child.pathlib_node_g + child.pathlib_node_h + child.pathlib_node_c;
38
39
40     if(child == goal_node)
41         pathlib_foundgoal = true;
42
43     ++pathlib_open_cnt;
44
45     if(best_open_node.pathlib_node_f > child.pathlib_node_f)
46         best_open_node = child;
47
48     return true;
49 }
50
51 float pathlib_wpp_openncb(entity wp, entity child, float cost)
52 {
53
54     if(child.pathlib_list == closedlist)
55         return false;
56
57         // FIXME! wp.wp##mincost is NOT distance. Make it distance or add a field for distance to be used here (for better speed)
58         cost = vlen(child.origin - wp.origin);
59
60     child.path_prev      = wp;
61     child.pathlib_list   = openlist;
62     child.pathlib_node_g = wp.pathlib_node_g + cost;
63     child.pathlib_node_h = pathlib_heuristic(child.origin, goal_node.origin);
64     child.pathlib_node_f = child.pathlib_node_g + child.pathlib_node_h;
65
66     if(child == goal_node)
67         pathlib_foundgoal = true;
68
69     ++pathlib_open_cnt;
70
71     if(best_open_node.pathlib_node_f > child.pathlib_node_f)
72         best_open_node = child;
73
74     return true;
75 }
76
77 float pathlib_wpp_expand(entity wp)
78 {
79     if(wp.wp00) pathlib_wpp_open(wp,wp.wp00,wp.wp00mincost); else return 0;
80     if(wp.wp01) pathlib_wpp_open(wp,wp.wp01,wp.wp01mincost); else return 1;
81     if(wp.wp02) pathlib_wpp_open(wp,wp.wp02,wp.wp02mincost); else return 2;
82     if(wp.wp03) pathlib_wpp_open(wp,wp.wp03,wp.wp03mincost); else return 3;
83     if(wp.wp04) pathlib_wpp_open(wp,wp.wp04,wp.wp04mincost); else return 4;
84     if(wp.wp05) pathlib_wpp_open(wp,wp.wp05,wp.wp05mincost); else return 5;
85     if(wp.wp06) pathlib_wpp_open(wp,wp.wp06,wp.wp06mincost); else return 6;
86     if(wp.wp07) pathlib_wpp_open(wp,wp.wp07,wp.wp07mincost); else return 7;
87     if(wp.wp08) pathlib_wpp_open(wp,wp.wp08,wp.wp08mincost); else return 8;
88     if(wp.wp09) pathlib_wpp_open(wp,wp.wp09,wp.wp09mincost); else return 9;
89     if(wp.wp10) pathlib_wpp_open(wp,wp.wp10,wp.wp10mincost); else return 10;
90     if(wp.wp11) pathlib_wpp_open(wp,wp.wp11,wp.wp11mincost); else return 11;
91     if(wp.wp12) pathlib_wpp_open(wp,wp.wp12,wp.wp12mincost); else return 12;
92     if(wp.wp13) pathlib_wpp_open(wp,wp.wp13,wp.wp13mincost); else return 13;
93     if(wp.wp14) pathlib_wpp_open(wp,wp.wp14,wp.wp14mincost); else return 14;
94     if(wp.wp15) pathlib_wpp_open(wp,wp.wp15,wp.wp15mincost); else return 15;
95     if(wp.wp16) pathlib_wpp_open(wp,wp.wp16,wp.wp16mincost); else return 16;
96     if(wp.wp17) pathlib_wpp_open(wp,wp.wp17,wp.wp17mincost); else return 17;
97     if(wp.wp18) pathlib_wpp_open(wp,wp.wp18,wp.wp18mincost); else return 18;
98     if(wp.wp19) pathlib_wpp_open(wp,wp.wp19,wp.wp19mincost); else return 19;
99     if(wp.wp20) pathlib_wpp_open(wp,wp.wp20,wp.wp20mincost); else return 20;
100     if(wp.wp21) pathlib_wpp_open(wp,wp.wp21,wp.wp21mincost); else return 21;
101     if(wp.wp22) pathlib_wpp_open(wp,wp.wp22,wp.wp22mincost); else return 22;
102     if(wp.wp23) pathlib_wpp_open(wp,wp.wp23,wp.wp23mincost); else return 23;
103     if(wp.wp24) pathlib_wpp_open(wp,wp.wp24,wp.wp24mincost); else return 24;
104     if(wp.wp25) pathlib_wpp_open(wp,wp.wp25,wp.wp25mincost); else return 25;
105     if(wp.wp26) pathlib_wpp_open(wp,wp.wp26,wp.wp26mincost); else return 26;
106     if(wp.wp27) pathlib_wpp_open(wp,wp.wp27,wp.wp27mincost); else return 27;
107     if(wp.wp28) pathlib_wpp_open(wp,wp.wp28,wp.wp28mincost); else return 28;
108     if(wp.wp29) pathlib_wpp_open(wp,wp.wp29,wp.wp29mincost); else return 29;
109     if(wp.wp30) pathlib_wpp_open(wp,wp.wp30,wp.wp30mincost); else return 30;
110     if(wp.wp31) pathlib_wpp_open(wp,wp.wp31,wp.wp31mincost); else return 31;
111
112     return 32;
113 }
114
115 entity pathlib_wpp_bestopen()
116 {
117     if(best_open_node)
118         return best_open_node;
119
120     entity best = NULL;
121
122     FOREACH_ENTITY_ENT(pathlib_list, openlist,
123     {
124         if(!best || it.pathlib_node_f < best.pathlib_node_f)
125             best = it;
126     });
127
128     return best;
129
130 }
131
132 entity pathlib_waypointpath(entity wp_from, entity wp_to, float callback)
133 {
134     float ptime;
135
136     ptime                                       = gettime(GETTIME_REALTIME);
137     pathlib_starttime           = ptime;
138         pathlib_movecost                = 300;
139         pathlib_movecost_diag   = vlen('1 1 0' * pathlib_movecost);
140
141         if (!pathlib_wpp_waypointcallback)
142                 callback = false;
143
144         if (callback)
145                 pathlib_wpp_open = pathlib_wpp_opencb;
146         else
147                 pathlib_wpp_open = pathlib_wpp_openncb;
148
149         pathlib_heuristic = pathlib_h_none;
150
151     if (!openlist)
152         openlist       = spawn();
153
154     if (!closedlist)
155         closedlist     = spawn();
156
157     pathlib_closed_cnt       = 0;
158     pathlib_open_cnt         = 0;
159     pathlib_searched_cnt     = 0;
160     pathlib_foundgoal      = false;
161
162     LOG_TRACE("pathlib_waypointpath init");
163
164     // Initialize waypoint grid
165     IL_EACH(g_waypoints, true,
166     {
167         it.pathlib_list = NULL;
168         it.pathlib_node_g = 0;
169         it.pathlib_node_f = 0;
170         it.pathlib_node_h = 0;
171
172         //setmodel(it, "models/runematch/rune.mdl");
173         //it.effects = EF_LOWPRECISION;
174         //it.colormod = '0 0 0';
175         //it.scale = 1;
176     });
177
178     goal_node  = wp_to;
179     start_node = wp_from;
180
181     start_node.pathlib_list = closedlist;
182     LOG_TRACE("Expanding ",ftos(pathlib_wpp_expand(start_node))," links");
183     if(pathlib_open_cnt <= 0)
184     {
185         LOG_TRACE("pathlib_waypointpath: Start waypoint not linked! aborting.");
186         return NULL;
187     }
188
189     return NULL;
190 }
191
192 entity pathlib_waypointpath_step()
193 {
194     entity n;
195
196     n = pathlib_wpp_bestopen();
197     if(!n)
198     {
199         LOG_TRACE("Cannot find best open node, abort.");
200         return NULL;
201     }
202     pathlib_wpp_close(n);
203         LOG_TRACE("Expanding ",ftos(pathlib_wpp_expand(n))," links");
204
205     if(pathlib_foundgoal)
206     {
207         entity start, end, open, ln;
208
209         LOG_TRACE("Target found. Rebuilding and filtering path...");
210
211                 buildpath_nodefilter = buildpath_nodefilter_none;
212                 start = path_build(NULL, start_node.origin, NULL, NULL);
213                 end   = path_build(NULL, goal_node.origin, NULL, start);
214                 ln    = end;
215
216                 for(open = goal_node; open.path_prev != start_node; open = open.path_prev)
217                 {
218                         n    = path_build(ln,open.origin,open.path_prev,start);
219                         ln.path_prev = n;
220                         ln = n;
221                 }
222                 start.path_next = n;
223                 n.path_prev = start;
224
225         return start;
226     }
227
228     return NULL;
229 }
230 void plas_think(entity this)
231 {
232     pathlib_waypointpath_step();
233     if(pathlib_foundgoal)
234         return;
235     this.nextthink = time + 0.1;
236 }
237
238 void pathlib_waypointpath_autostep()
239 {
240     entity n;
241     n = spawn();
242     setthink(n, plas_think);
243     n.nextthink = time + 0.1;
244 }