FS2_Open
Open source remastering of the Freespace 2 engine
waypoint.cpp
Go to the documentation of this file.
1 
2 #include <ctype.h>
3 
4 #include "globalincs/linklist.h"
5 #include "object/object.h"
6 #include "object/waypoint.h"
7 
8 //********************GLOBALS********************
10 
11 // In order to restore ai_info to a plain-old-data struct, ai_info->wp_index
12 // now uses size_t rather than iterator to index into the list. If ai_info
13 // eventually becomes an actual class, we ought to go back to using iterators.
14 //SCP_list<waypoint> dummy_waypoint;
15 //const SCP_list<waypoint>::iterator INVALID_WAYPOINT_POSITION = dummy_waypoint.end();
16 const size_t INVALID_WAYPOINT_POSITION = (size_t) -1;
17 
18 //********************CLASS MEMBERS********************
20 {
21  this->m_position.xyz.x = 0.0f;
22  this->m_position.xyz.y = 0.0f;
23  this->m_position.xyz.z = 0.0f;
24 
25  this->objnum = -1;
26  this->m_parent_list = NULL;
27 }
28 
29 waypoint::waypoint(vec3d *position, waypoint_list *parent_list)
30 {
31  Assert(position != NULL);
32 
33  this->m_position.xyz.x = position->xyz.x;
34  this->m_position.xyz.y = position->xyz.y;
35  this->m_position.xyz.z = position->xyz.z;
36 
37  this->objnum = -1;
38  this->m_parent_list = parent_list;
39 }
40 
42 {
43  // nothing to do
44 }
45 
47 {
48  return &m_position;
49 }
50 
52 {
53  return objnum;
54 }
55 
57 {
58  return m_parent_list;
59 }
60 
62 {
63  Assert(pos != NULL);
64  this->m_position = *pos;
65 }
66 
68 {
69  this->m_name[0] = '\0';
70 }
71 
73 {
74  Assert(name != NULL);
75  Assert(find_matching_waypoint_list(name) == NULL);
76  strcpy_s(this->m_name, name);
77 }
78 
80 {
81  // nothing to do
82 }
83 
85 {
86  return m_name;
87 }
88 
90 {
91  return waypoints;
92 }
93 
94 void waypoint_list::set_name(const char *name)
95 {
96  Assert(name != NULL);
97  strcpy_s(this->m_name, name);
98 }
99 
100 //********************FUNCTIONS********************
102 {
103  Waypoint_lists.clear();
104 }
105 
107 {
108  Waypoint_lists.clear();
109 }
110 
111 int calc_waypoint_instance(int waypoint_list_index, int waypoint_index)
112 {
113  Assert(waypoint_list_index >= 0);
114  Assert(waypoint_index >= 0);
115  return waypoint_list_index * 0x10000 + waypoint_index;
116 }
117 
118 void calc_waypoint_indexes(int waypoint_instance, int &waypoint_list_index, int &waypoint_index)
119 {
120  Assert(waypoint_instance >= 0);
121  waypoint_list_index = calc_waypoint_list_index(waypoint_instance);
122  waypoint_index = calc_waypoint_index(waypoint_instance);
123 }
124 
125 int calc_waypoint_list_index(int waypoint_instance)
126 {
127  Assert(waypoint_instance >= 0);
128  return waypoint_instance / 0x10000;
129 }
130 
131 int calc_waypoint_index(int waypoint_instance)
132 {
133  Assert(waypoint_instance >= 0);
134  return waypoint_instance & 0xffff;
135 }
136 
137 void waypoint_create_game_object(waypoint *wpt, int list_index, int wpt_index)
138 {
139  Assert(wpt != NULL);
140  Assert(list_index >= 0);
141  Assert(wpt_index >= 0);
142  wpt->objnum = obj_create(OBJ_WAYPOINT, -1, calc_waypoint_instance(list_index, wpt_index), NULL, wpt->get_pos(), 0.0f, OF_RENDERS);
143 }
144 
145 // done immediately after mission load; originally found in aicode.cpp
147 {
150 
151  int list = 0;
152  for (ii = Waypoint_lists.begin(); ii != Waypoint_lists.end(); ++ii)
153  {
154  int wpt = 0;
155  for (jj = ii->get_waypoints().begin(); jj != ii->get_waypoints().end(); ++jj)
156  {
157  waypoint_create_game_object(&(*jj), list, wpt);
158  wpt++;
159  }
160  list++;
161  }
162 }
163 
165 {
166  Assert(name != NULL);
168 
169  for (ii = Waypoint_lists.begin(); ii != Waypoint_lists.end(); ++ii)
170  {
171  if (!stricmp(ii->get_name(), name))
172  return &(*ii);
173  }
174 
175  return NULL;
176 }
177 
178 // NOTE: waypoint names are always in the format Name:index
180 {
181  Assert(name != NULL);
183 
184  for (ii = Waypoint_lists.begin(); ii != Waypoint_lists.end(); ++ii)
185  {
186  uint len = strlen(ii->get_name());
187 
188  // the first half (before the :) matches
189  if (!strnicmp(ii->get_name(), name, len))
190  {
191  // this is ok because it could be "Waypoint path 1" vs. "Waypoint path 10"
192  if (*(name + len) != ':')
193  continue;
194 
195  // skip over the : to inspect a new string holding only the index
196  const char *index_str = name + len + 1;
197  if (*index_str == '\0')
198  {
199  nprintf(("waypoints", "possible error with waypoint name '%s': no waypoint number after the colon\n", name));
200  continue;
201  }
202 
203  // make sure it's actually a number
204  bool valid = true;
205  for (const char *ch = index_str; *ch != '\0'; ch++)
206  {
207  if (!isdigit(*ch))
208  {
209  valid = false;
210  break;
211  }
212  }
213  if (!valid)
214  {
215  nprintf(("waypoints", "possible error with waypoint name '%s': string after the colon is not a number\n", name));
216  continue;
217  }
218 
219  // get the number and make sure it's in range
220  uint index = atoi(index_str);
221  if (index < 1 || index > ii->get_waypoints().size())
222  {
223  nprintf(("waypoints", "possible error with waypoint name '%s': waypoint number is out of range\n", name));
224  continue;
225  }
226 
227  return find_waypoint_at_index(&(*ii), index - 1);
228  }
229  }
230 
231  return NULL;
232 }
233 
235 {
236  if (objnum < 0 || Objects[objnum].type != OBJ_WAYPOINT)
237  return NULL;
238 
241 
242  for (ii = Waypoint_lists.begin(); ii != Waypoint_lists.end(); ++ii)
243  {
244  for (jj = ii->get_waypoints().begin(); jj != ii->get_waypoints().end(); ++jj)
245  {
246  if (jj->get_objnum() == objnum)
247  return &(*jj);
248  }
249  }
250 
251  return NULL;
252 }
253 
254 waypoint_list *find_waypoint_list_with_instance(int waypoint_instance, int *waypoint_index)
255 {
256  if (waypoint_instance < 0)
257  {
258  if (waypoint_index != NULL)
259  *waypoint_index = -1;
260  return NULL;
261  }
262 
264  if (wp_list == NULL)
265  {
266  if (waypoint_index != NULL)
267  *waypoint_index = -1;
268  return NULL;
269  }
270 
271  if (waypoint_index != NULL)
272  {
273  *waypoint_index = calc_waypoint_index(waypoint_instance);
274  Assert(*waypoint_index >= 0 && (uint) *waypoint_index < wp_list->get_waypoints().size());
275  }
276  return wp_list;
277 }
278 
279 waypoint *find_waypoint_with_instance(int waypoint_instance)
280 {
281  if (waypoint_instance < 0)
282  return NULL;
283 
285  if (wp_list == NULL)
286  return NULL;
287 
288  return find_waypoint_at_index(wp_list, calc_waypoint_index(waypoint_instance));
289 }
290 
292 {
293  Assert(index >= 0);
294 
295  int i = 0;
297 
298  for (ii = Waypoint_lists.begin(); ii != Waypoint_lists.end(); ++i, ++ii)
299  {
300  if (i == index)
301  return &(*ii);
302  }
303 
304  return NULL;
305 }
306 
308 {
309  Assert(list != NULL);
310  Assert(index >= 0);
311 
312  int i = 0;
314 
315  for (ii = list->get_waypoints().begin(); ii != list->get_waypoints().end(); ++i, ++ii)
316  {
317  if (i == index)
318  return &(*ii);
319  }
320 
321  return NULL;
322 }
323 
325 {
326  Assert(wp_list != NULL);
328 
329  int index = 0;
330  for (ii = Waypoint_lists.begin(); ii != Waypoint_lists.end(); ++ii)
331  {
332  if (&(*ii) == wp_list)
333  return index;
334  index++;
335  }
336 
337  return -1;
338 }
339 
341 {
342  Assert(wp_list != NULL);
343  Assert(wpt != NULL);
345 
346  int index = 0;
347  for (ii = wp_list->get_waypoints().begin(); ii != wp_list->get_waypoints().end(); ++ii)
348  {
349  if (&(*ii) == wpt)
350  return index;
351  index++;
352  }
353 
354  return -1;
355 }
356 
357 void waypoint_find_unique_name(char *dest_name, int start_index)
358 {
359  Assert(dest_name != NULL);
360  Assert(start_index >= 0);
361 
362  int index = start_index;
363  waypoint_list *collision;
364 
365  do {
366  sprintf(dest_name, "Waypoint path %d", index);
367  index++;
368 
369  // valid name if no collision
370  collision = find_matching_waypoint_list(dest_name);
371  } while (collision != NULL);
372 }
373 
374 void waypoint_add_list(const char *name, SCP_vector<vec3d> &vec_list)
375 {
376  Assert(name != NULL);
377 
378  if (find_matching_waypoint_list(name) != NULL)
379  {
380  Warning(LOCATION, "Waypoint list '%s' already exists in this mission! Not adding the new list...", name);
381  return;
382  }
383 
384  waypoint_list new_list(name);
385  Waypoint_lists.push_back(new_list);
386  waypoint_list *wp_list = &Waypoint_lists.back();
387 
388  wp_list->get_waypoints().reserve(vec_list.size());
390  for (ii = vec_list.begin(); ii != vec_list.end(); ++ii)
391  {
392  waypoint new_waypoint(&(*ii), wp_list);
393  wp_list->get_waypoints().push_back(new_waypoint);
394  }
395 
396  // so that masking in the other function works
397  // though if you actually hit this Assert, you have other problems
398  Assert(wp_list->get_waypoints().size() <= 0xffff);
399 }
400 
401 int waypoint_add(vec3d *pos, int waypoint_instance)
402 {
403  Assert(pos != NULL);
404  waypoint_list *wp_list;
405  waypoint *wpt;
406  int i, wp_list_index, wp_index;
407 
408  // find a new list to start
409  if (waypoint_instance < 0)
410  {
411  // get a name for it
412  char buf[NAME_LENGTH];
413  waypoint_find_unique_name(buf, Waypoint_lists.size() + 1);
414 
415  // add new list with that name
416  waypoint_list new_list(buf);
417  Waypoint_lists.push_back(new_list);
418  wp_list = &Waypoint_lists.back();
419 
420  // set up references
421  wp_list_index = Waypoint_lists.size() - 1;
422  wp_index = wp_list->get_waypoints().size();
423  }
424  // create the waypoint on the same list as, and immediately after, waypoint_instance
425  else
426  {
427  calc_waypoint_indexes(waypoint_instance, wp_list_index, wp_index);
428  wp_list = find_waypoint_list_at_index(wp_list_index);
429 
430  // theoretically waypoint_instance points to a current waypoint, so advance past it
431  wp_index++;
432 
433  // it has to be on, or at the end of, an existing list
434  Assert(wp_list != NULL);
435  Assert((uint) wp_index <= wp_list->get_waypoints().size());
436 
437  // iterate through all waypoints that are at this index or later,
438  // and edit their instances so that they point to a waypoint one place higher
440  {
441  if ((objp->type == OBJ_WAYPOINT) && (calc_waypoint_list_index(objp->instance) == wp_list_index) && (calc_waypoint_index(objp->instance) >= wp_index))
442  objp->instance++;
443  }
444  }
445 
446  // so that masking in the other function works
447  // (though if you actually hit this Assert, you have other problems)
448  Assert(wp_index < 0x10000);
449 
450  // create the waypoint object
451  waypoint new_waypoint(pos, wp_list);
452 
453  // add it at its appropriate spot, which may be the end of the list
454  SCP_vector<waypoint>::iterator ii = wp_list->get_waypoints().begin();
455  for (i = 0; i < wp_index; i++)
456  ++ii;
457  wp_list->get_waypoints().insert(ii, new_waypoint);
458  wpt = find_waypoint_at_index(wp_list, wp_index);
459 
460  // apparently we create it in-game too; this is called by both scripting and FRED
461  waypoint_create_game_object(wpt, wp_list_index, wp_index);
462 
463  return wpt->get_objnum();
464 }
465 
467 {
468  int objnum = wpt->get_objnum();
469  waypoint_list *wp_list = wpt->get_parent_list();
470 
471  int this_list = calc_waypoint_list_index(Objects[objnum].instance);
472  int this_index = calc_waypoint_index(Objects[objnum].instance);
473 
474  // special case... this is the only waypoint on its list
475  if (wp_list->get_waypoints().size() == 1)
476  {
477  wp_list->get_waypoints().clear();
478 
479  // special special case... this is the only waypoint list!
480  if (Waypoint_lists.size() == 1)
481  {
482  Waypoint_lists.clear();
483  }
484  // shift the other waypoint lists down
485  else
486  {
487  // remove this particular waypoint list
489  int i;
490  for (i = 0, ii = Waypoint_lists.begin(); ii != Waypoint_lists.end(); ++i, ++ii)
491  {
492  if (i == this_list)
493  {
494  Waypoint_lists.erase(ii);
495  break;
496  }
497  }
498  Assert(ii != Waypoint_lists.end());
499 
500  // iterate through all waypoints that are in lists later than this one,
501  // and edit their instances so that they point to a list one place lower
503  {
504  if ((objp->type == OBJ_WAYPOINT) && (calc_waypoint_list_index(objp->instance) > this_list))
505  objp->instance -= 0x10000;
506  }
507  }
508  }
509  // shift the other waypoints down
510  else
511  {
512  // remove this particular waypoint
514  int i;
515  for (i = 0, ii = wp_list->get_waypoints().begin(); ii != wp_list->get_waypoints().end(); ++i, ++ii)
516  {
517  if (i == this_index)
518  {
519  wp_list->get_waypoints().erase(ii);
520  break;
521  }
522  }
523  Assert(ii != wp_list->get_waypoints().end());
524 
525  // iterate through all waypoints that are later than this one,
526  // and edit their instances so that they point to a waypoint one place lower
528  {
529  if ((objp->type == OBJ_WAYPOINT) && (calc_waypoint_list_index(objp->instance) == this_list) && (calc_waypoint_index(objp->instance) > this_index))
530  objp->instance--;
531  }
532  }
533 
534  // FRED has its own object removal logic
535  if (!Fred_running)
536  obj_delete(objnum);
537 }
int i
Definition: multi_pxo.cpp:466
char * get_name()
Definition: waypoint.cpp:84
waypoint * find_matching_waypoint(const char *name)
Definition: waypoint.cpp:179
void waypoint_add_list(const char *name, SCP_vector< vec3d > &vec_list)
Definition: waypoint.cpp:374
GLuint index
Definition: Glext.h:5608
int calc_waypoint_index(int waypoint_instance)
Definition: waypoint.cpp:131
void waypoint_parse_init()
Definition: waypoint.cpp:101
int Fred_running
Definition: fred.cpp:44
waypoint_list * find_waypoint_list_with_instance(int waypoint_instance, int *waypoint_index)
Definition: waypoint.cpp:254
void _cdecl void void _cdecl void _cdecl Warning(char *filename, int line, SCP_FORMAT_STRING const char *format,...) SCP_FORMAT_STRING_ARGS(3
Assert(pm!=NULL)
int find_index_of_waypoint(waypoint_list *wp_list, waypoint *wpt)
Definition: waypoint.cpp:340
Definition: pstypes.h:88
#define OF_RENDERS
Definition: object.h:103
struct vec3d::@225::@227 xyz
object obj_used_list
Definition: object.cpp:53
void waypoint_create_game_object(waypoint *wpt, int list_index, int wpt_index)
Definition: waypoint.cpp:137
object * objp
Definition: lua.cpp:3105
GLsizeiptr size
Definition: Glext.h:5496
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: Glext.h:7308
SCP_list< waypoint_list > Waypoint_lists
Definition: waypoint.cpp:9
int calc_waypoint_instance(int waypoint_list_index, int waypoint_index)
Definition: waypoint.cpp:111
GLenum type
Definition: Gl.h:1492
waypoint * find_waypoint_with_objnum(int objnum)
Definition: waypoint.cpp:234
SCP_vector< waypoint > & get_waypoints()
Definition: waypoint.cpp:89
waypoint_list * get_parent_list()
Definition: waypoint.cpp:56
#define OBJ_WAYPOINT
Definition: object.h:36
int instance
Definition: object.h:150
void set_name(const char *name)
Definition: waypoint.cpp:94
unsigned int uint
Definition: pstypes.h:64
vec3d * get_pos()
Definition: waypoint.cpp:46
#define nprintf(args)
Definition: pstypes.h:239
int obj_create(ubyte type, int parent_obj, int instance, matrix *orient, vec3d *pos, float radius, uint flags)
Definition: object.cpp:467
#define strnicmp(s1, s2, n)
Definition: config.h:272
sprintf(buf,"(%f,%f,%f)", v3->xyz.x, v3->xyz.y, v3->xyz.z)
void waypoint_find_unique_name(char *dest_name, int start_index)
Definition: waypoint.cpp:357
int waypoint_add(vec3d *pos, int waypoint_instance)
Definition: waypoint.cpp:401
const size_t INVALID_WAYPOINT_POSITION
Definition: waypoint.cpp:16
object Objects[MAX_OBJECTS]
Definition: object.cpp:62
waypoint * find_waypoint_with_instance(int waypoint_instance)
Definition: waypoint.cpp:279
waypoint()
Definition: waypoint.cpp:19
GLuint const GLchar * name
Definition: Glext.h:5608
void calc_waypoint_indexes(int waypoint_instance, int &waypoint_list_index, int &waypoint_index)
Definition: waypoint.cpp:118
void obj_delete(int objnum)
Definition: object.cpp:522
waypoint_list * find_matching_waypoint_list(const char *name)
Definition: waypoint.cpp:164
#define NAME_LENGTH
Definition: globals.h:15
waypoint_list * find_waypoint_list_at_index(int index)
Definition: waypoint.cpp:291
void waypoint_level_close()
Definition: waypoint.cpp:106
int find_index_of_waypoint_list(waypoint_list *wp_list)
Definition: waypoint.cpp:324
#define LOCATION
Definition: pstypes.h:245
hull_check pos
Definition: lua.cpp:5050
void set_pos(vec3d *pos)
Definition: waypoint.cpp:61
GLenum GLsizei len
Definition: Glext.h:6283
int get_objnum()
Definition: waypoint.cpp:51
~waypoint()
Definition: waypoint.cpp:41
waypoint * find_waypoint_at_index(waypoint_list *list, int index)
Definition: waypoint.cpp:307
void waypoint_create_game_objects()
Definition: waypoint.cpp:146
char type
Definition: object.h:146
void waypoint_remove(waypoint *wpt)
Definition: waypoint.cpp:466
#define stricmp(s1, s2)
Definition: config.h:271
int calc_waypoint_list_index(int waypoint_instance)
Definition: waypoint.cpp:125
#define strcpy_s(...)
Definition: safe_strings.h:67