1 /*
2  * Copyright (C) Volition, Inc. 1999.  All rights reserved.
3  *
4  * All source code herein is the property of Volition, Inc. You may not sell
5  * or otherwise commercially exploit the source or things you created based on the
6  * source.
7  *
8 */
9 
10 
11 
12 #include "stdafx.h"
13 #include "FRED.h"
14 #include "WaypointPathDlg.h"
15 #include "Management.h"
16 #include "MainFrm.h"
17 #include "object/object.h"
18 #include "object/waypoint.h"
19 #include "globalincs/linklist.h"
20 #include "ship/ship.h"
21 #include "ai/aigoals.h"
22 #include "starfield/starfield.h"
23 #include "jumpnode/jumpnode.h"
24 #include "iff_defs/iff_defs.h"
25 
26 #define ID_JUMP_NODE_MENU	8000
27 #define ID_WAYPOINT_MENU	9000
28 
29 #ifdef _DEBUG
30 #undef THIS_FILE
31 static char THIS_FILE[] = __FILE__;
32 #endif
33 
34 /////////////////////////////////////////////////////////////////////////////
35 // waypoint_path_dlg dialog
36 
waypoint_path_dlg(CWnd * pParent)37 waypoint_path_dlg::waypoint_path_dlg(CWnd* pParent /*=NULL*/)
38 	: CDialog(waypoint_path_dlg::IDD, pParent)
39 {
40 	//{{AFX_DATA_INIT(waypoint_path_dlg)
41 	m_name = _T("");
42 	//}}AFX_DATA_INIT
43 	bypass_errors = 0;
44 }
45 
DoDataExchange(CDataExchange * pDX)46 void waypoint_path_dlg::DoDataExchange(CDataExchange* pDX)
47 {
48 	CDialog::DoDataExchange(pDX);
49 	//{{AFX_DATA_MAP(waypoint_path_dlg)
50 	DDX_Text(pDX, IDC_NAME, m_name);
51 	//}}AFX_DATA_MAP
52 }
53 
BEGIN_MESSAGE_MAP(waypoint_path_dlg,CDialog)54 BEGIN_MESSAGE_MAP(waypoint_path_dlg, CDialog)
55 	//{{AFX_MSG_MAP(waypoint_path_dlg)
56 	ON_WM_CLOSE()
57 	ON_WM_INITMENU()
58 	//}}AFX_MSG_MAP
59 END_MESSAGE_MAP()
60 
61 /////////////////////////////////////////////////////////////////////////////
62 // waypoint_path_dlg message handlers
63 
64 BOOL waypoint_path_dlg::Create()
65 {
66 	BOOL r;
67 	r = CDialog::Create(IDD, Fred_main_wnd);
68 	initialize_data(1);
69 	return r;
70 }
71 
OnInitMenu(CMenu * pMenu)72 void waypoint_path_dlg::OnInitMenu(CMenu* pMenu)
73 {
74 	int i;
75 	SCP_list<waypoint_list>::iterator ii;
76 	SCP_list<CJumpNode>::iterator jnp;
77 	CMenu *m;
78 
79 	m = pMenu->GetSubMenu(0);
80 	clear_menu(m);
81 
82 	for (i = 0, ii = Waypoint_lists.begin(); ii != Waypoint_lists.end(); ++i, ++ii) {
83 		m->AppendMenu(MF_ENABLED | MF_STRING, ID_WAYPOINT_MENU + i, ii->get_name());
84 	}
85 
86 	i = 0;
87 	for (jnp = Jump_nodes.begin(); jnp != Jump_nodes.end(); ++jnp) {
88 		m->AppendMenu(MF_ENABLED | MF_STRING, ID_JUMP_NODE_MENU + i, jnp->GetName());
89 		if (jnp->GetSCPObjectNumber() == cur_object_index) {
90 			m->CheckMenuItem(ID_JUMP_NODE_MENU + i,  MF_BYCOMMAND | MF_CHECKED);
91 		}
92 		i++;
93 
94 	}
95 
96 	m->DeleteMenu(ID_PLACEHOLDER, MF_BYCOMMAND);
97 	if (cur_waypoint_list != NULL)
98 	{
99 		int index = find_index_of_waypoint_list(cur_waypoint_list);
100 		Assert(index >= 0);
101 		m->CheckMenuItem(ID_WAYPOINT_MENU + index, MF_BYCOMMAND | MF_CHECKED);
102 	}
103 
104 	CDialog::OnInitMenu(pMenu);
105 }
106 
OnOK()107 void waypoint_path_dlg::OnOK()
108 {
109 }
110 
OnClose()111 void waypoint_path_dlg::OnClose()
112 {
113 	if (update_data()) {
114 		SetWindowPos(&wndTop, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE);
115 		bypass_errors = 0;
116 		return;
117 	}
118 
119 	SetWindowPos(Fred_main_wnd, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_HIDEWINDOW);
120 	Fred_main_wnd->SetWindowPos(&wndTop, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
121 }
122 
initialize_data(int full_update)123 void waypoint_path_dlg::initialize_data(int full_update)
124 {
125 	int enable = TRUE;
126 	SCP_list<CJumpNode>::iterator jnp;
127 
128 	if (!GetSafeHwnd())
129 		return;
130 
131 	if (query_valid_object() && Objects[cur_object_index].type == OBJ_WAYPOINT)
132 	{
133 		Assert(cur_waypoint_list == find_waypoint_list_with_instance(Objects[cur_object_index].instance));
134 	}
135 
136 	if (cur_waypoint_list != NULL) {
137 		m_name = _T(cur_waypoint_list->get_name());
138 
139 	} else if (Objects[cur_object_index].type == OBJ_JUMP_NODE) {
140 		for (jnp = Jump_nodes.begin(); jnp != Jump_nodes.end(); ++jnp) {
141 			if(jnp->GetSCPObject() == &Objects[cur_object_index])
142 				break;
143 		}
144 
145 		m_name = _T(jnp->GetName());
146 
147 	} else {
148 		m_name = _T("");
149 		enable = FALSE;
150 	}
151 
152 	if (full_update)
153 		UpdateData(FALSE);
154 
155 	GetDlgItem(IDC_NAME)->EnableWindow(enable);
156 }
157 
update_data(int redraw)158 int waypoint_path_dlg::update_data(int redraw)
159 {
160 	const char *str;
161 	char old_name[255];
162 	int i, z;
163 	object *ptr;
164 	SCP_list<CJumpNode>::iterator jnp;
165 
166 	if (!GetSafeHwnd())
167 		return 0;
168 
169 	UpdateData(TRUE);
170 	UpdateData(TRUE);
171 
172 	if (query_valid_object() && Objects[cur_object_index].type == OBJ_WAYPOINT)
173 	{
174 		Assert(cur_waypoint_list == find_waypoint_list_with_instance(Objects[cur_object_index].instance));
175 	}
176 
177 	if (cur_waypoint_list != NULL) {
178 		for (i=0; i<MAX_WINGS; i++)
179 		{
180 			if (!stricmp(Wings[i].name, m_name)) {
181 				if (bypass_errors)
182 					return 1;
183 
184 				bypass_errors = 1;
185 				z = MessageBox("This waypoint path name is already being used by a wing\n"
186 					"Press OK to restore old name", "Error", MB_ICONEXCLAMATION | MB_OKCANCEL);
187 
188 				if (z == IDCANCEL)
189 					return -1;
190 
191 				m_name = _T(cur_waypoint_list->get_name());
192 				UpdateData(FALSE);
193 			}
194 		}
195 
196 		ptr = GET_FIRST(&obj_used_list);
197 		while (ptr != END_OF_LIST(&obj_used_list)) {
198 			if ((ptr->type == OBJ_SHIP) || (ptr->type == OBJ_START)) {
199 				if (!stricmp(m_name, Ships[ptr->instance].ship_name)) {
200 					if (bypass_errors)
201 						return 1;
202 
203 					bypass_errors = 1;
204 					z = MessageBox("This waypoint path name is already being used by a ship\n"
205 						"Press OK to restore old name", "Error", MB_ICONEXCLAMATION | MB_OKCANCEL);
206 
207 					if (z == IDCANCEL)
208 						return -1;
209 
210 					m_name = _T(cur_waypoint_list->get_name());
211 					UpdateData(FALSE);
212 				}
213 			}
214 
215 			ptr = GET_NEXT(ptr);
216 		}
217 
218 		// We don't need to check teams.  "Unknown" is a valid name and also an IFF.
219 
220 		for ( i=0; i < (int)Ai_tp_list.size(); i++) {
221 			if (!stricmp(m_name, Ai_tp_list[i].name)) {
222 				if (bypass_errors)
223 					return 1;
224 
225 				bypass_errors = 1;
226 				z = MessageBox("This waypoint path name is already being used by a target priority group.\n"
227 					"Press OK to restore old name", "Error", MB_ICONEXCLAMATION | MB_OKCANCEL);
228 
229 				if (z == IDCANCEL)
230 					return -1;
231 
232 				m_name = _T(cur_waypoint_list->get_name());
233 				UpdateData(FALSE);
234 			}
235 		}
236 
237 		SCP_list<waypoint_list>::iterator ii;
238 		for (ii = Waypoint_lists.begin(); ii != Waypoint_lists.end(); ++ii)
239 		{
240 			if (!stricmp(ii->get_name(), m_name) && (&(*ii) != cur_waypoint_list)) {
241 				if (bypass_errors)
242 					return 1;
243 
244 				bypass_errors = 1;
245 				z = MessageBox("This waypoint path name is already being used by another waypoint path\n"
246 					"Press OK to restore old name", "Error", MB_ICONEXCLAMATION | MB_OKCANCEL);
247 
248 				if (z == IDCANCEL)
249 					return -1;
250 
251 				m_name = _T(cur_waypoint_list->get_name());
252 				UpdateData(FALSE);
253 			}
254 		}
255 
256 		if(jumpnode_get_by_name(m_name) != NULL)
257 		{
258 			if (bypass_errors)
259 				return 1;
260 
261 			bypass_errors = 1;
262 			z = MessageBox("This waypoint path name is already being used by a jump node\n"
263 				"Press OK to restore old name", "Error", MB_ICONEXCLAMATION | MB_OKCANCEL);
264 
265 			if (z == IDCANCEL)
266 				return -1;
267 
268 			m_name = _T(cur_waypoint_list->get_name());
269 			UpdateData(FALSE);
270 		}
271 
272 		if (!stricmp(m_name.Left(1), "<")) {
273 			if (bypass_errors)
274 				return 1;
275 
276 			bypass_errors = 1;
277 			z = MessageBox("Waypoint names not allowed to begin with <\n"
278 				"Press OK to restore old name", "Error", MB_ICONEXCLAMATION | MB_OKCANCEL);
279 
280 			if (z == IDCANCEL)
281 				return -1;
282 
283 			m_name = _T(cur_waypoint_list->get_name());
284 			UpdateData(FALSE);
285 		}
286 
287 
288 		strcpy_s(old_name, cur_waypoint_list->get_name());
289 		string_copy(cur_waypoint_list->get_name(), m_name, NAME_LENGTH, 1);
290 
291 		str = (char *) (LPCTSTR) m_name;
292 		if (strcmp(old_name, str)) {
293 			update_sexp_references(old_name, str);
294 			ai_update_goal_references(REF_TYPE_WAYPOINT, old_name, str);
295 			update_texture_replacements(old_name, str);
296 		}
297 
298 	} else if (Objects[cur_object_index].type == OBJ_JUMP_NODE) {
299 		for (jnp = Jump_nodes.begin(); jnp != Jump_nodes.end(); ++jnp) {
300 			if(jnp->GetSCPObject() == &Objects[cur_object_index])
301 				break;
302 		}
303 
304 		for (i=0; i<MAX_WINGS; i++)
305 		{
306 			if (!stricmp(Wings[i].name, m_name)) {
307 				if (bypass_errors)
308 					return 1;
309 
310 				bypass_errors = 1;
311 				z = MessageBox("This jump node name is already being used by a wing\n"
312 					"Press OK to restore old name", "Error", MB_ICONEXCLAMATION | MB_OKCANCEL);
313 
314 				if (z == IDCANCEL)
315 					return -1;
316 
317 				m_name = _T(jnp->GetName());
318 				UpdateData(FALSE);
319 			}
320 		}
321 
322 		ptr = GET_FIRST(&obj_used_list);
323 		while (ptr != END_OF_LIST(&obj_used_list)) {
324 			if ((ptr->type == OBJ_SHIP) || (ptr->type == OBJ_START)) {
325 				if (!stricmp(m_name, Ships[ptr->instance].ship_name)) {
326 					if (bypass_errors)
327 						return 1;
328 
329 					bypass_errors = 1;
330 					z = MessageBox("This jump node name is already being used by a ship\n"
331 						"Press OK to restore old name", "Error", MB_ICONEXCLAMATION | MB_OKCANCEL);
332 
333 					if (z == IDCANCEL)
334 						return -1;
335 
336 					m_name = _T(jnp->GetName());
337 					UpdateData(FALSE);
338 				}
339 			}
340 
341 			ptr = GET_NEXT(ptr);
342 		}
343 
344 		// We don't need to check teams.  "Unknown" is a valid name and also an IFF.
345 
346 		for ( i=0; i < (int)Ai_tp_list.size(); i++) {
347 			if (!stricmp(m_name, Ai_tp_list[i].name)) {
348 				if (bypass_errors)
349 					return 1;
350 
351 				bypass_errors = 1;
352 				z = MessageBox("This jump node name is already being used by a target priority group.\n"
353 					"Press OK to restore old name", "Error", MB_ICONEXCLAMATION | MB_OKCANCEL);
354 
355 				if (z == IDCANCEL)
356 					return -1;
357 
358 				m_name = _T(jnp->GetName());
359 				UpdateData(FALSE);
360 			}
361 		}
362 
363 		if (find_matching_waypoint_list((LPCSTR) m_name) != NULL)
364 		{
365 			if (bypass_errors)
366 				return 1;
367 
368 			bypass_errors = 1;
369 			z = MessageBox("This jump node name is already being used by a waypoint path\n"
370 				"Press OK to restore old name", "Error", MB_ICONEXCLAMATION | MB_OKCANCEL);
371 
372 			if (z == IDCANCEL)
373 				return -1;
374 
375 			m_name = _T(jnp->GetName());
376 			UpdateData(FALSE);
377 		}
378 
379 		if (!stricmp(m_name.Left(1), "<")) {
380 			if (bypass_errors)
381 				return 1;
382 
383 			bypass_errors = 1;
384 			z = MessageBox("Jump node names not allowed to begin with <\n"
385 				"Press OK to restore old name", "Error", MB_ICONEXCLAMATION | MB_OKCANCEL);
386 
387 			if (z == IDCANCEL)
388 				return -1;
389 
390 			m_name = _T(jnp->GetName());
391 			UpdateData(FALSE);
392 		}
393 
394 		CJumpNode* found = jumpnode_get_by_name(m_name);
395 		if(found != NULL && &(*jnp) != found)
396 		{
397 			if (bypass_errors)
398 				return 1;
399 
400 			bypass_errors = 1;
401 			z = MessageBox("This jump node name is already being used by another jump node\n"
402 				"Press OK to restore old name", "Error", MB_ICONEXCLAMATION | MB_OKCANCEL);
403 
404 			if (z == IDCANCEL)
405 				return -1;
406 
407 			m_name = _T(jnp->GetName());
408 			UpdateData(FALSE);
409 		}
410 
411 		strcpy_s(old_name, jnp->GetName());
412 		jnp->SetName((LPCSTR) m_name);
413 
414 		str = (LPCTSTR) m_name;
415 		if (strcmp(old_name, str)) {
416 			update_sexp_references(old_name, str);
417 		}
418 
419 	}
420 
421 	if (redraw)
422 		update_map_window();
423 
424 	return 0;
425 }
426 
OnCommand(WPARAM wParam,LPARAM lParam)427 BOOL waypoint_path_dlg::OnCommand(WPARAM wParam, LPARAM lParam)
428 {
429 	int id, point;
430 	object *ptr;
431 
432 	id = LOWORD(wParam);
433 	if ((id >= ID_WAYPOINT_MENU) && (id < ID_WAYPOINT_MENU + (int) Waypoint_lists.size())) {
434 		if (!update_data()) {
435 			point = id - ID_WAYPOINT_MENU;
436 			unmark_all();
437 			ptr = GET_FIRST(&obj_used_list);
438 			while (ptr != END_OF_LIST(&obj_used_list)) {
439 				if (ptr->type == OBJ_WAYPOINT)
440 					if (calc_waypoint_list_index(ptr->instance) == point)
441 						mark_object(OBJ_INDEX(ptr));
442 
443 				ptr = GET_NEXT(ptr);
444 			}
445 
446 			return 1;
447 		}
448 	}
449 
450 	if ((id >= ID_JUMP_NODE_MENU) && (id < ID_JUMP_NODE_MENU + (int) Jump_nodes.size())) {
451 		if (!update_data()) {
452 			point = id - ID_JUMP_NODE_MENU;
453 			unmark_all();
454 			ptr = GET_FIRST(&obj_used_list);
455 			while ((ptr != END_OF_LIST(&obj_used_list)) && (point > -1)) {
456 				if (ptr->type == OBJ_JUMP_NODE) {
457 					if (point == 0) {
458 						mark_object(OBJ_INDEX(ptr));
459 					}
460 					point--;
461 				}
462 
463 				ptr = GET_NEXT(ptr);
464 			}
465 
466 			return 1;
467 		}
468 	}
469 
470 	return CDialog::OnCommand(wParam, lParam);
471 }
472