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