]> icculus.org git repositories - taylor/freespace2.git/blob - src/fred2/shipgoalsdlg.cpp
fix issue with looping audio streams
[taylor/freespace2.git] / src / fred2 / shipgoalsdlg.cpp
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
6  * the source.
7  */
8
9 /*
10  * $Logfile: /Freespace2/code/fred2/ShipGoalsDlg.cpp $
11  * $Revision$
12  * $Date$
13  * $Author$
14  *
15  * Initial orders editor dialog box handling code.  This dialog is used for both
16  * ship and wing initial orders, and can support more if need be without modification.
17  *
18  * $Log$
19  * Revision 1.3  2002/06/09 04:41:17  relnev
20  * added copyright header
21  *
22  * Revision 1.2  2002/05/07 03:16:44  theoddone33
23  * The Great Newline Fix
24  *
25  * Revision 1.1.1.1  2002/05/03 03:28:08  root
26  * Initial import.
27  *
28  * 
29  * 4     3/26/99 4:49p Dave
30  * Made cruisers able to dock with stuff. Made docking points and paths
31  * visible in fred.
32  * 
33  * 3     3/25/99 3:32p Johnson
34  * HACK: Allow Mycerinus to dock
35  * 
36  * 2     10/07/98 6:28p Dave
37  * Initial checkin. Renamed all relevant stuff to be Fred2 instead of
38  * Fred. Globalized mission and campaign file extensions. Removed Silent
39  * Threat specific code.
40  * 
41  * 1     10/07/98 3:01p Dave
42  * 
43  * 1     10/07/98 3:00p Dave
44  * 
45  * 57    7/06/98 5:12p Hoffoss
46  * Fixed bug where 3-5th orders don't update data listing when object
47  * changes.
48  * 
49  * 56    5/21/98 12:58a Hoffoss
50  * Fixed warnings optimized build turned up.
51  * 
52  * 55    4/06/98 11:34a Hoffoss
53  * Fixed bug caused by change in max ai goals.  Should be able to handle
54  * anything from 0 to 10 ai goals now (i.e. it's more flexible now).
55  * 
56  * 54    11/05/97 4:43p Allender
57  * reworked medal/rank system to read all data from tables.  Made Fred
58  * read medals.tbl.  Changed ai-warp to ai-warp-out which doesn't require
59  * waypoint for activation
60  * 
61  * 53    10/22/97 3:15p Hoffoss
62  * Fixed ai-stay-still initial order to use waypoints instead of waypoint
63  * paths.
64  * 
65  * 52    10/22/97 1:58p Hoffoss
66  * Added support for AI_GOALS_PLAY_DEAD and changed AI_GOALS_STAY_STILL
67  * for Fred.
68  * 
69  * 51    10/10/97 5:03p Allender
70  * started work on ai-stay-still
71  * 
72  * 50    9/18/97 11:28a Duncan
73  * Fixed bug with player objects having wrong name.
74  * 
75  * 49    9/16/97 9:41p Hoffoss
76  * Changed Fred code around to stop using Parse_player structure for
77  * player information, and use actual ships instead.
78  * 
79  * 48    9/09/97 3:39p Sandeep
80  * warning level 4 bugs
81  * 
82  * 47    9/02/97 5:10p Johnson
83  * Fixed bug with wing initial orders available to select from.
84  * 
85  * 46    8/26/97 4:18p Hoffoss
86  * Added error checking to initial orders dialog when ok is clicked.
87  * 
88  * 45    8/19/97 11:59a Duncan
89  * Fixed bug in initial orders set_item().
90  * 
91  * 44    8/16/97 4:51p Hoffoss
92  * Fixed bugs with wing deletion and removing ships from a wing.
93  * 
94  * 43    8/15/97 5:14p Hoffoss
95  * Completely changed around how initial orders dialog worked.  It's
96  * pretty awesome now.
97  * 
98  * 42    8/14/97 7:07p Hoffoss
99  * Changed "guard ship" to "guard", since it can be used with wings now as
100  * well as ships.
101  * 
102  * 41    8/10/97 4:41p Hoffoss
103  * Fixed bugs with docking initial order.
104  * 
105  * 40    8/05/97 10:10p Hoffoss
106  * Made attack and guard orders handle both ships and wings as targets.
107  * 
108  * 39    8/01/97 12:21p Jasen
109  * Fixed bug with docking order (in iinitial orders) where original dockee
110  * was deleted, and so not found when looked up.
111  * 
112  * 38    7/30/97 12:31p Hoffoss
113  * Made improvements to ship goals editor (initial orders) to disallow
114  * illegal orders.
115  * 
116  * 37    7/25/97 4:30p Hoffoss
117  * Changes to ship lookup to include player ships.
118  * 
119  * 36    7/24/97 4:55p Allender
120  * added ai-evade-ship to fred and to Freespace
121  * 
122  * 35    7/22/97 3:40p Allender
123  * Changed the way that attacking subsystem works (for initial orders).
124  * The code was behaving two different ways.  Orders are now model
125  * specific as per which subsystem to attack.
126  * 
127  * 34    7/17/97 4:23p Allender
128  * ai-guard-wing now in both Fred and Freespace
129  * 
130  * 33    7/09/97 1:56p Jasen
131  * Added new case to data mode checkunder save item. 
132  * 
133  * 32    6/11/97 2:13p Hoffoss
134  * Fixed bug in initial order initialization, and made subsystem combo box
135  * use ship specific subsystems.
136  * 
137  * 31    6/04/97 12:00a Allender
138  * added disarm and disable as initial order options
139  * 
140  * 30    5/30/97 4:50p Hoffoss
141  * Added code to allow marked ship editing of data in child dialogs of
142  * ship editor dialog.
143  * 
144  * 29    5/07/97 1:32p Allender
145  * fix bug from previous checkin where undock orders were not persistent
146  * 
147  * 28    5/07/97 1:08p Allender
148  * make undock initial order only accept a priority
149  * 
150  * 27    4/03/97 3:18p Allender
151  * 
152  * 26    3/31/97 6:07p Hoffoss
153  * Fixed several errors, including BG editor not graying fields, BG editor
154  * not updating image when changed, Removed obsolete data from Weapon
155  * editor, priority not being saved when missions saved, priority not
156  * editable in initial orders editor.
157  * 
158  * 25    3/28/97 3:19p Hoffoss
159  * Added chase-any goal to initial orders.
160  * 
161  * 24    3/21/97 4:04p Bernal
162  * fixed crash when initial orders references illegal objects. (Jason)
163  * 
164  * 23    3/21/97 10:29a Hoffoss
165  * forced negative priorities to 50
166  * 
167  * 22    3/19/97 4:53p Hoffoss
168  * fixed bug with unused fields not being cleared.
169  * 
170  * 21    3/13/97 12:20p Hoffoss
171  * fixed bug in docking point specification of initial orders dialog.
172  * 
173  * 20    3/10/97 6:43p Hoffoss
174  * Standardized docking goal usage by fred to use names instead of
175  * indexes.
176  * 
177  * 19    3/10/97 5:37p Hoffoss
178  * fixed bug in dock goal selection.
179  * 
180  * 18    3/10/97 12:54p Hoffoss
181  * Added drop down combo box to toolbar and fixed compiling errors Mark
182  * (maybe Mike?) introduced to code.
183  * 
184  * 17    3/04/97 12:52p Allender
185  * docking styff.  Added dock type to docking structure in model code.
186  * Renamed structure member in ai_goals.  Temporary checkin.  (i.e.
187  * rearming will use rearm dock points)
188  * 
189  * 16    3/03/97 4:32p Hoffoss
190  * Initial orders supports new docking stuff Allender added.
191  * 
192  * 15    2/27/97 3:15p Allender
193  * major wing structure enhancement.  simplified wing code.  All around
194  * better wing support
195  * 
196  * 14    2/26/97 2:45p Hoffoss
197  * Initial orders dialog now only allows 89 as a max on priority.
198  * 
199  * 13    2/21/97 5:34p Hoffoss
200  * Added extensive modification detection and fixed a bug in initial
201  * orders editor.
202  * 
203  * 12    2/17/97 5:28p Hoffoss
204  * Checked RCS headers, added them were missing, changing description to
205  * something better, etc where needed.
206  *
207  * $NoKeywords: $
208  */
209
210 #include "stdafx.h"
211 #include "fred.h"
212 #include "shipgoalsdlg.h"
213 #include "object.h"
214 #include "linklist.h"
215 #include "management.h"
216 #include "aigoals.h"
217 #include "freddoc.h"
218 #include "fredview.h"
219
220 #define TYPE_PATH                       0x1000
221 #define TYPE_SHIP                       0x2000
222 #define TYPE_PLAYER             0x3000
223 #define TYPE_WING                       0x4000
224 #define TYPE_WAYPOINT   0x5000
225 #define TYPE_MASK                       0xf000
226 #define DATA_MASK                       0x0fff
227
228 #ifdef _DEBUG
229 #define new DEBUG_NEW
230 #undef THIS_FILE
231 static char THIS_FILE[] = __FILE__;
232 #endif
233
234 /////////////////////////////////////////////////////////////////////////////
235 // ShipGoalsDlg dialog
236
237 ShipGoalsDlg::ShipGoalsDlg(CWnd* pParent /*=NULL*/)
238         : CDialog(ShipGoalsDlg::IDD, pParent)
239 {
240         int i;
241
242         for (i=0; i<ED_MAX_GOALS; i++) {
243                 m_behavior[i] = -1;
244                 m_object[i] = -1;
245                 m_priority[i] = 0;
246                 m_subsys[i] = -1;
247                 m_dock2[i] = -1;
248                 m_data[i] = 0;
249         }
250
251         //{{AFX_DATA_INIT(ShipGoalsDlg)
252         //}}AFX_DATA_INIT
253         goalp = NULL;
254         self_ship = self_wing = -1;
255 }
256
257 void ShipGoalsDlg::DoDataExchange(CDataExchange* pDX)
258 {
259         CDialog::DoDataExchange(pDX);
260         //{{AFX_DATA_MAP(ShipGoalsDlg)
261         //}}AFX_DATA_MAP
262
263         DDX_CBIndex(pDX, IDC_BEHAVIOR1, m_behavior[0]);
264         DDX_CBIndex(pDX, IDC_BEHAVIOR2, m_behavior[1]);
265         DDX_CBIndex(pDX, IDC_BEHAVIOR3, m_behavior[2]);
266         DDX_CBIndex(pDX, IDC_BEHAVIOR4, m_behavior[3]);
267         DDX_CBIndex(pDX, IDC_BEHAVIOR5, m_behavior[4]);
268         DDX_CBIndex(pDX, IDC_BEHAVIOR6, m_behavior[5]);
269         DDX_CBIndex(pDX, IDC_BEHAVIOR7, m_behavior[6]);
270         DDX_CBIndex(pDX, IDC_BEHAVIOR8, m_behavior[7]);
271         DDX_CBIndex(pDX, IDC_BEHAVIOR9, m_behavior[8]);
272         DDX_CBIndex(pDX, IDC_BEHAVIOR10, m_behavior[9]);
273
274         DDX_CBIndex(pDX, IDC_OBJECT1, m_object[0]);
275         DDX_CBIndex(pDX, IDC_OBJECT2, m_object[1]);
276         DDX_CBIndex(pDX, IDC_OBJECT3, m_object[2]);
277         DDX_CBIndex(pDX, IDC_OBJECT4, m_object[3]);
278         DDX_CBIndex(pDX, IDC_OBJECT5, m_object[4]);
279         DDX_CBIndex(pDX, IDC_OBJECT6, m_object[5]);
280         DDX_CBIndex(pDX, IDC_OBJECT7, m_object[6]);
281         DDX_CBIndex(pDX, IDC_OBJECT8, m_object[7]);
282         DDX_CBIndex(pDX, IDC_OBJECT9, m_object[8]);
283         DDX_CBIndex(pDX, IDC_OBJECT10, m_object[9]);
284
285         DDX_Text(pDX, IDC_PRIORITY1, m_priority[0]);
286         DDV_MinMaxInt(pDX, m_priority[0], 0, 89);
287         DDX_Text(pDX, IDC_PRIORITY2, m_priority[1]);
288         DDV_MinMaxInt(pDX, m_priority[1], 0, 89);
289         DDX_Text(pDX, IDC_PRIORITY3, m_priority[2]);
290         DDV_MinMaxInt(pDX, m_priority[2], 0, 89);
291         DDX_Text(pDX, IDC_PRIORITY4, m_priority[3]);
292         DDV_MinMaxInt(pDX, m_priority[3], 0, 89);
293         DDX_Text(pDX, IDC_PRIORITY5, m_priority[4]);
294         DDV_MinMaxInt(pDX, m_priority[4], 0, 89);
295         DDX_Text(pDX, IDC_PRIORITY6, m_priority[5]);
296         DDV_MinMaxInt(pDX, m_priority[5], 0, 89);
297         DDX_Text(pDX, IDC_PRIORITY7, m_priority[6]);
298         DDV_MinMaxInt(pDX, m_priority[6], 0, 89);
299         DDX_Text(pDX, IDC_PRIORITY8, m_priority[7]);
300         DDV_MinMaxInt(pDX, m_priority[7], 0, 89);
301         DDX_Text(pDX, IDC_PRIORITY9, m_priority[8]);
302         DDV_MinMaxInt(pDX, m_priority[8], 0, 89);
303         DDX_Text(pDX, IDC_PRIORITY10, m_priority[9]);
304         DDV_MinMaxInt(pDX, m_priority[9], 0, 89);
305
306         DDX_CBIndex(pDX, IDC_SUBSYSTEM1, m_subsys[0]);
307         DDX_CBIndex(pDX, IDC_SUBSYSTEM2, m_subsys[1]);
308         DDX_CBIndex(pDX, IDC_SUBSYSTEM3, m_subsys[2]);
309         DDX_CBIndex(pDX, IDC_SUBSYSTEM4, m_subsys[3]);
310         DDX_CBIndex(pDX, IDC_SUBSYSTEM5, m_subsys[4]);
311         DDX_CBIndex(pDX, IDC_SUBSYSTEM6, m_subsys[5]);
312         DDX_CBIndex(pDX, IDC_SUBSYSTEM7, m_subsys[6]);
313         DDX_CBIndex(pDX, IDC_SUBSYSTEM8, m_subsys[7]);
314         DDX_CBIndex(pDX, IDC_SUBSYSTEM9, m_subsys[8]);
315         DDX_CBIndex(pDX, IDC_SUBSYSTEM10, m_subsys[9]);
316
317         DDX_CBIndex(pDX, IDC_DOCK1, m_dock2[0]);
318         DDX_CBIndex(pDX, IDC_DOCK2, m_dock2[1]);
319         DDX_CBIndex(pDX, IDC_DOCK3, m_dock2[2]);
320         DDX_CBIndex(pDX, IDC_DOCK4, m_dock2[3]);
321         DDX_CBIndex(pDX, IDC_DOCK5, m_dock2[4]);
322         DDX_CBIndex(pDX, IDC_DOCK6, m_dock2[5]);
323         DDX_CBIndex(pDX, IDC_DOCK7, m_dock2[6]);
324         DDX_CBIndex(pDX, IDC_DOCK8, m_dock2[7]);
325         DDX_CBIndex(pDX, IDC_DOCK9, m_dock2[8]);
326         DDX_CBIndex(pDX, IDC_DOCK10, m_dock2[9]);
327 }
328
329 BEGIN_MESSAGE_MAP(ShipGoalsDlg, CDialog)
330         //{{AFX_MSG_MAP(ShipGoalsDlg)
331         ON_CBN_SELCHANGE(IDC_BEHAVIOR1, OnSelchangeBehavior1)
332         ON_CBN_SELCHANGE(IDC_BEHAVIOR2, OnSelchangeBehavior2)
333         ON_CBN_SELCHANGE(IDC_BEHAVIOR3, OnSelchangeBehavior3)
334         ON_CBN_SELCHANGE(IDC_BEHAVIOR4, OnSelchangeBehavior4)
335         ON_CBN_SELCHANGE(IDC_BEHAVIOR5, OnSelchangeBehavior5)
336         ON_CBN_SELCHANGE(IDC_BEHAVIOR6, OnSelchangeBehavior6)
337         ON_CBN_SELCHANGE(IDC_BEHAVIOR7, OnSelchangeBehavior7)
338         ON_CBN_SELCHANGE(IDC_BEHAVIOR8, OnSelchangeBehavior8)
339         ON_CBN_SELCHANGE(IDC_BEHAVIOR9, OnSelchangeBehavior9)
340         ON_CBN_SELCHANGE(IDC_BEHAVIOR10, OnSelchangeBehavior10)
341         ON_CBN_SELCHANGE(IDC_OBJECT1, OnSelchangeObject1)
342         ON_CBN_SELCHANGE(IDC_OBJECT2, OnSelchangeObject2)
343         ON_CBN_SELCHANGE(IDC_OBJECT3, OnSelchangeObject3)
344         ON_CBN_SELCHANGE(IDC_OBJECT4, OnSelchangeObject4)
345         ON_CBN_SELCHANGE(IDC_OBJECT5, OnSelchangeObject5)
346         ON_CBN_SELCHANGE(IDC_OBJECT6, OnSelchangeObject6)
347         ON_CBN_SELCHANGE(IDC_OBJECT7, OnSelchangeObject7)
348         ON_CBN_SELCHANGE(IDC_OBJECT8, OnSelchangeObject8)
349         ON_CBN_SELCHANGE(IDC_OBJECT9, OnSelchangeObject9)
350         ON_CBN_SELCHANGE(IDC_OBJECT10, OnSelchangeObject10)
351         //}}AFX_MSG_MAP
352 END_MESSAGE_MAP()
353
354 /////////////////////////////////////////////////////////////////////////////
355 // ShipGoalsDlg message handlers
356
357 BOOL ShipGoalsDlg::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext)
358 {
359         return CDialog::Create(IDD, &Ship_editor_dialog);
360 }
361
362 BOOL ShipGoalsDlg::OnInitDialog() 
363 {
364         int i, j, z, valid[99];
365         object *ptr;
366
367         // set up pointers to all the combo boxes to simplify things a lot
368         m_behavior_box[0] = (CComboBox *) GetDlgItem(IDC_BEHAVIOR1);
369         m_behavior_box[1] = (CComboBox *) GetDlgItem(IDC_BEHAVIOR2);
370         m_behavior_box[2] = (CComboBox *) GetDlgItem(IDC_BEHAVIOR3);
371         m_behavior_box[3] = (CComboBox *) GetDlgItem(IDC_BEHAVIOR4);
372         m_behavior_box[4] = (CComboBox *) GetDlgItem(IDC_BEHAVIOR5);
373         m_behavior_box[5] = (CComboBox *) GetDlgItem(IDC_BEHAVIOR6);
374         m_behavior_box[6] = (CComboBox *) GetDlgItem(IDC_BEHAVIOR7);
375         m_behavior_box[7] = (CComboBox *) GetDlgItem(IDC_BEHAVIOR8);
376         m_behavior_box[8] = (CComboBox *) GetDlgItem(IDC_BEHAVIOR9);
377         m_behavior_box[9] = (CComboBox *) GetDlgItem(IDC_BEHAVIOR10);
378
379         m_object_box[0] = (CComboBox *) GetDlgItem(IDC_OBJECT1);
380         m_object_box[1] = (CComboBox *) GetDlgItem(IDC_OBJECT2);
381         m_object_box[2] = (CComboBox *) GetDlgItem(IDC_OBJECT3);
382         m_object_box[3] = (CComboBox *) GetDlgItem(IDC_OBJECT4);
383         m_object_box[4] = (CComboBox *) GetDlgItem(IDC_OBJECT5);
384         m_object_box[5] = (CComboBox *) GetDlgItem(IDC_OBJECT6);
385         m_object_box[6] = (CComboBox *) GetDlgItem(IDC_OBJECT7);
386         m_object_box[7] = (CComboBox *) GetDlgItem(IDC_OBJECT8);
387         m_object_box[8] = (CComboBox *) GetDlgItem(IDC_OBJECT9);
388         m_object_box[9] = (CComboBox *) GetDlgItem(IDC_OBJECT10);
389
390         m_subsys_box[0] = (CComboBox *) GetDlgItem(IDC_SUBSYSTEM1);
391         m_subsys_box[1] = (CComboBox *) GetDlgItem(IDC_SUBSYSTEM2);
392         m_subsys_box[2] = (CComboBox *) GetDlgItem(IDC_SUBSYSTEM3);
393         m_subsys_box[3] = (CComboBox *) GetDlgItem(IDC_SUBSYSTEM4);
394         m_subsys_box[4] = (CComboBox *) GetDlgItem(IDC_SUBSYSTEM5);
395         m_subsys_box[5] = (CComboBox *) GetDlgItem(IDC_SUBSYSTEM6);
396         m_subsys_box[6] = (CComboBox *) GetDlgItem(IDC_SUBSYSTEM7);
397         m_subsys_box[7] = (CComboBox *) GetDlgItem(IDC_SUBSYSTEM8);
398         m_subsys_box[8] = (CComboBox *) GetDlgItem(IDC_SUBSYSTEM9);
399         m_subsys_box[9] = (CComboBox *) GetDlgItem(IDC_SUBSYSTEM10);
400
401         m_dock2_box[0] = (CComboBox *) GetDlgItem(IDC_DOCK1);
402         m_dock2_box[1] = (CComboBox *) GetDlgItem(IDC_DOCK2);
403         m_dock2_box[2] = (CComboBox *) GetDlgItem(IDC_DOCK3);
404         m_dock2_box[3] = (CComboBox *) GetDlgItem(IDC_DOCK4);
405         m_dock2_box[4] = (CComboBox *) GetDlgItem(IDC_DOCK5);
406         m_dock2_box[5] = (CComboBox *) GetDlgItem(IDC_DOCK6);
407         m_dock2_box[6] = (CComboBox *) GetDlgItem(IDC_DOCK7);
408         m_dock2_box[7] = (CComboBox *) GetDlgItem(IDC_DOCK8);
409         m_dock2_box[8] = (CComboBox *) GetDlgItem(IDC_DOCK9);
410         m_dock2_box[9] = (CComboBox *) GetDlgItem(IDC_DOCK10);
411
412         m_priority_box[0] = (CComboBox *) GetDlgItem(IDC_PRIORITY1);
413         m_priority_box[1] = (CComboBox *) GetDlgItem(IDC_PRIORITY2);
414         m_priority_box[2] = (CComboBox *) GetDlgItem(IDC_PRIORITY3);
415         m_priority_box[3] = (CComboBox *) GetDlgItem(IDC_PRIORITY4);
416         m_priority_box[4] = (CComboBox *) GetDlgItem(IDC_PRIORITY5);
417         m_priority_box[5] = (CComboBox *) GetDlgItem(IDC_PRIORITY6);
418         m_priority_box[6] = (CComboBox *) GetDlgItem(IDC_PRIORITY7);
419         m_priority_box[7] = (CComboBox *) GetDlgItem(IDC_PRIORITY8);
420         m_priority_box[8] = (CComboBox *) GetDlgItem(IDC_PRIORITY9);
421         m_priority_box[9] = (CComboBox *) GetDlgItem(IDC_PRIORITY10);
422
423         // start off with all goals available
424         for (i=0; i<Ai_goal_list_size; i++)
425                 valid[i] = 1;
426
427         // disallow orders if they aren't allowed because of ship type
428         if (self_ship >= 0) {  // editing orders for just one ship
429                 for (i=0; i<Ai_goal_list_size; i++){
430                         if (!(ai_query_goal_valid(self_ship, Ai_goal_list[i].def))){
431                                 valid[i] = 0;
432                         }
433                 }
434         } else if (self_wing >= 0) {  // editing orders for just one wing
435                 for (i=0; i<Wings[self_wing].wave_count; i++){
436                         for (j=0; j<Ai_goal_list_size; j++){
437                                 if (!ai_query_goal_valid(Wings[self_wing].ship_index[i], Ai_goal_list[j].def)){
438                                         valid[j] = 0;
439                                 }
440                         }
441                 }
442
443                 for (i=0; i<Ai_goal_list_size; i++){
444                         if (Ai_goal_list[i].def == AI_GOAL_DOCK){  // a whole wing can't dock with one object..
445                                 valid[i] = 0;
446                         }
447                 }
448         } else {  // editing orders for all marked ships
449                 ptr = GET_FIRST(&obj_used_list);
450                 while (ptr != END_OF_LIST(&obj_used_list)) {
451                         if ((ptr->type == OBJ_SHIP) && (ptr->flags & OF_MARKED)){
452                                 for (i=0; i<Ai_goal_list_size; i++){
453                                         if (!ai_query_goal_valid(ptr->instance, Ai_goal_list[i].def)){
454                                                 valid[i] = 0;
455                                         }
456                                 }
457                         }
458
459                         ptr = GET_NEXT(ptr);
460                 }
461         }
462
463         for (i=0; i<MAX_WAYPOINT_LISTS; i++){
464                 if (Waypoint_lists[i].count){
465                         break;
466                 }
467         }
468
469         if (i == MAX_WAYPOINT_LISTS){
470                 for (i=0; i<Ai_goal_list_size; i++){
471                         switch (Ai_goal_list[i].def) {
472                                 case AI_GOAL_WAYPOINTS:
473                                 case AI_GOAL_WAYPOINTS_ONCE:
474                                 //case AI_GOAL_WARP:
475                                         valid[i] = 0;
476                         }
477                 }
478         }
479
480         z = 0;
481         ptr = GET_FIRST(&obj_used_list);
482         while (ptr != END_OF_LIST(&obj_used_list)) {
483                 if ((ptr->type == OBJ_SHIP) || (ptr->type == OBJ_START)) {
484                         i = ptr->instance;
485
486                         if ((self_ship > 0) && (self_ship != i) && ship_docking_valid(self_ship, i)){
487                                 z = 1;
488                         }
489                 }
490                 ptr = GET_NEXT(ptr);
491         }
492
493         if (!z){
494                 for (i=0; i<Ai_goal_list_size; i++){
495                         if (Ai_goal_list[i].def == AI_GOAL_DOCK){
496                                 valid[i] = 0;
497                         }
498                 }
499         }
500
501         // initialize the behavior boxes (they remain constant) and initialize each goal's data
502         for (i=0; i<ED_MAX_GOALS; i++) {
503                 m_behavior_box[i] -> ResetContent();
504                 z = m_behavior_box[i] -> AddString("None");
505                 m_behavior_box[i] -> SetItemData(z, (DWORD) AI_GOAL_NONE);
506                 for (j=0; j<Ai_goal_list_size; j++){
507                         if (valid[j]) {
508                                 z = m_behavior_box[i] -> AddString(Ai_goal_list[j].name);
509                                 m_behavior_box[i] -> SetItemData(z, (DWORD) Ai_goal_list[j].def);
510                         }
511                 }
512         }
513
514         if (self_ship >= 0){
515                 initialize(Ai_info[Ships[self_ship].ai_index].goals, self_ship);
516         } else if (self_wing >= 0){
517                 initialize(Wings[self_wing].ai_goals);
518         } else {
519                 initialize_multi();
520         }
521
522         for (i=0; i<ED_MAX_GOALS; i++){
523                 set_item(i, 1);
524         }
525
526         CDialog::OnInitDialog();
527
528         // restrict spin controls to a range of 0 - 89
529         ((CSpinButtonCtrl *) GetDlgItem(IDC_SPIN1)) -> SetRange(0, 89);
530         ((CSpinButtonCtrl *) GetDlgItem(IDC_SPIN2)) -> SetRange(0, 89);
531         ((CSpinButtonCtrl *) GetDlgItem(IDC_SPIN3)) -> SetRange(0, 89);
532         ((CSpinButtonCtrl *) GetDlgItem(IDC_SPIN4)) -> SetRange(0, 89);
533         ((CSpinButtonCtrl *) GetDlgItem(IDC_SPIN5)) -> SetRange(0, 89);
534         ((CSpinButtonCtrl *) GetDlgItem(IDC_SPIN6)) -> SetRange(0, 89);
535         ((CSpinButtonCtrl *) GetDlgItem(IDC_SPIN7)) -> SetRange(0, 89);
536         ((CSpinButtonCtrl *) GetDlgItem(IDC_SPIN8)) -> SetRange(0, 89);
537         ((CSpinButtonCtrl *) GetDlgItem(IDC_SPIN9)) -> SetRange(0, 89);
538         ((CSpinButtonCtrl *) GetDlgItem(IDC_SPIN10)) -> SetRange(0, 89);
539
540         return TRUE;
541 }
542
543 void ShipGoalsDlg::initialize_multi()
544 {
545         int i, flag = 0;
546         object *ptr;
547         int behavior[ED_MAX_GOALS];
548         int priority[ED_MAX_GOALS];
549         int subsys[ED_MAX_GOALS];
550         int dock2[ED_MAX_GOALS];
551         int data[ED_MAX_GOALS];
552
553         ptr = GET_FIRST(&obj_used_list);
554         while (ptr != END_OF_LIST(&obj_used_list)) {
555                 if ((ptr->type == OBJ_SHIP) && (ptr->flags & OF_MARKED)) {
556                         initialize(Ai_info[Ships[ptr->instance].ai_index].goals, ptr->instance);
557                         if (!flag) {
558                                 flag = 1;
559                                 for (i=0; i<ED_MAX_GOALS; i++) {
560                                         behavior[i] = m_behavior[i];
561                                         priority[i] = m_priority[i];
562                                         subsys[i] = m_subsys[i];
563                                         dock2[i] = m_dock2[i];
564                                         data[i] = m_data[i];
565                                 }
566
567                         } else {
568                                 for (i=0; i<ED_MAX_GOALS; i++) {
569                                         if (behavior[i] != m_behavior[i]) {
570                                                 behavior[i] = -1;
571                                                 data[i] = -1;
572                                         }
573
574                                         if (data[i] != m_data[i]) {
575                                                 data[i] = -1;
576                                                 subsys[i] = -1;
577                                                 dock2[i] = -1;
578                                         }
579
580                                         if (priority[i] != m_priority[i]){
581                                                 priority[i] = -1;
582                                         }
583                                         if (subsys[i] != m_subsys[i]){
584                                                 subsys[i] = -1;
585                                         }
586                                         if (dock2[i] != m_dock2[i]){
587                                                 dock2[i] = -1;
588                                         }
589                                 }
590                         }
591                 }
592
593                 ptr = GET_NEXT(ptr);
594         }
595
596         goalp = NULL;
597         for (i=0; i<ED_MAX_GOALS; i++) {
598                 m_behavior[i] = behavior[i];
599                 m_priority[i] = priority[i];
600                 m_subsys[i] = subsys[i];
601                 m_dock2[i] = dock2[i];
602                 m_data[i] = data[i];
603         }
604 }
605
606 // perform one-time initialization of data from the goals struct.
607 void ShipGoalsDlg::initialize(ai_goal *goals, int ship)
608 {
609         int i, item, num, inst, flag, mode;
610         object *ptr;
611
612         goalp = goals;
613         for (item=0; item<ED_MAX_GOALS; item++) {
614                 flag = 1;
615                 m_data[item] = 0;
616                 m_priority[item] = 0;
617                 mode = AI_GOAL_NONE;
618                 
619                 if (item < MAX_AI_GOALS) {
620                         m_priority[item] = goalp[item].priority;
621                         mode = goalp[item].ai_mode;
622                 }
623
624                 if (m_priority[item] < 0 || m_priority[item] > 89){
625                         m_priority[item] = 50;
626                 }
627
628                 m_behavior[item] = 0;
629                 if (mode != AI_GOAL_NONE) {
630                         i = m_behavior_box[item] -> GetCount();
631                         while (i-- > 0){
632                                 if (mode & (m_behavior_box[item]->GetItemData(i))) {
633                                         m_behavior[item] = i;
634                                         break;
635                                 }
636                         }
637                 }
638
639                 switch (mode) {
640                         case AI_GOAL_NONE:
641                         case AI_GOAL_CHASE_ANY:
642                         case AI_GOAL_UNDOCK:
643                         case AI_GOAL_KEEP_SAFE_DISTANCE:
644                         case AI_GOAL_PLAY_DEAD:
645                         case AI_GOAL_WARP:
646                                 continue;
647
648                         case AI_GOAL_STAY_STILL:
649                                 flag = 9;  // target is a ship or a waypoint
650                                 break;
651
652                         case AI_GOAL_CHASE:
653                         case AI_GOAL_GUARD:
654                         case AI_GOAL_DISABLE_SHIP:
655                         case AI_GOAL_DISARM_SHIP:
656                         case AI_GOAL_IGNORE:
657                         case AI_GOAL_EVADE_SHIP:
658                         case AI_GOAL_STAY_NEAR_SHIP:
659                                 break;
660
661                         case AI_GOAL_WAYPOINTS:
662                         case AI_GOAL_WAYPOINTS_ONCE:
663                                 flag = 4;  // target is a waypoint
664                                 break;
665
666                         case AI_GOAL_DESTROY_SUBSYSTEM:
667                                 num = ship_name_lookup(goalp[item].ship_name, 1);
668                                 if (num != -1)
669                                         m_subsys[item] = ship_get_subsys_index(&Ships[num], goalp[item].docker.name, 1);
670
671                                 break;
672
673                         case AI_GOAL_DOCK:
674                                 m_subsys[item] = -1;
675                                 num = get_docking_list(Ships[ship].modelnum);
676                                 for (i=0; i<num; i++) {
677                                         SDL_assert(Docking_bay_list[i]);
678                                         if (!stricmp(goalp[item].docker.name, Docking_bay_list[i])) {
679                                                 m_subsys[item] = i;
680                                                 break;
681                                         }
682                                 }
683
684                                 break;
685
686                         case AI_GOAL_CHASE_WING:
687                         case AI_GOAL_GUARD_WING:
688                                 flag = 2;  // target is a wing
689                                 break;
690
691                         default:
692                                 SDL_assert(0);
693                 }
694
695                 if (flag & 0x1) {
696                         ptr = GET_FIRST(&obj_used_list);
697                         while (ptr != END_OF_LIST(&obj_used_list)) {
698                                 if ((ptr->type == OBJ_SHIP) || (ptr->type == OBJ_START)) {
699                                         inst = ptr->instance;
700                                         if (ptr->type == OBJ_SHIP) {
701                                                 SDL_assert(inst >= 0 && inst < MAX_SHIPS);
702                                                 if (!stricmp(goalp[item].ship_name, Ships[inst].ship_name)) {
703                                                         m_data[item] = inst | TYPE_SHIP;
704                                                         break;
705                                                 }
706
707                                         } else {
708                                                 SDL_assert(inst >= 0 && inst < MAX_SHIPS);
709                                                 if (!stricmp(goalp[item].ship_name, Ships[inst].ship_name)) {
710                                                         m_data[item] = inst | TYPE_PLAYER;
711                                                         break;
712                                                 }
713                                         }
714                                 }
715
716                                 ptr = GET_NEXT(ptr);
717                         }
718                 }
719
720                 if (flag & 0x2) {
721                         for (i=0; i<MAX_WINGS; i++)
722                                 if (Wings[i].wave_count) {
723                                         if (!stricmp(goalp[item].ship_name, Wings[i].name)) {
724                                                 m_data[item] = i | TYPE_WING;
725                                                 break;
726                                         }
727                                 }
728                 }
729
730                 if (flag & 0x4) {  // data is a waypoint path name
731                         for (i=0; i<Num_waypoint_lists; i++)
732                                 if (!stricmp(goalp[item].ship_name, Waypoint_lists[i].name)) {
733                                         m_data[item] = i | TYPE_PATH;
734                                         break;
735                                 }
736                 }
737
738                 if (flag & 0x8) {  // data is a waypoint name
739                         i = waypoint_lookup(goalp[item].ship_name);
740                         if (i >= 0)
741                                 m_data[item] = i | TYPE_WAYPOINT;
742                 }
743
744                 switch (mode) {
745                         case AI_GOAL_DOCK:
746                                 m_dock2[item] = -1;
747                                 if (m_data[item]) {
748                                         num = get_docking_list(Ships[m_data[item] & DATA_MASK].modelnum);
749                                         for (i=0; i<num; i++) {
750                                                 SDL_assert(Docking_bay_list[i]);
751                                                 SDL_assert(goalp[item].dockee.name);
752                                                 SDL_assert(goalp[item].dockee.index != -1);
753                                                 if (!stricmp(goalp[item].dockee.name, Docking_bay_list[i])) {
754                                                         m_dock2[item] = i;
755                                                         break;
756                                                 }
757                                         }
758                                 }
759
760                                 break;
761                 }
762
763 //              SDL_assert(m_data[item]);
764         }
765 }
766
767 void ShipGoalsDlg::set_item(int item, int init)
768 {
769         int i, t, z, num, inst, mode;
770         object *ptr;
771
772         if (init)
773                 m_object[item] = -1;
774
775         if (item >= MAX_AI_GOALS)
776                 m_behavior_box[item] -> EnableWindow(FALSE);
777         
778         SDL_assert(item >= 0 && item < ED_MAX_GOALS);
779         m_object_box[item] -> ResetContent();
780         if (m_behavior[item] < 1) {
781                 m_object_box[item] -> EnableWindow(FALSE);
782                 m_subsys_box[item] -> EnableWindow(FALSE);
783                 m_dock2_box[item] -> EnableWindow(FALSE);
784                 m_priority_box[item] -> EnableWindow(FALSE);
785                 m_subsys[item] = -1;
786                 m_dock2[item] = -1;
787                 return;
788         }
789
790         mode = m_behavior_box[item] -> GetItemData(m_behavior[item]);
791         m_priority_box[item] -> EnableWindow(TRUE);
792         if ((mode == AI_GOAL_CHASE_ANY) || (mode == AI_GOAL_UNDOCK) || (mode == AI_GOAL_KEEP_SAFE_DISTANCE) || (mode == AI_GOAL_PLAY_DEAD) || (mode == AI_GOAL_WARP) ) {
793                 m_object_box[item] -> EnableWindow(FALSE);
794                 m_subsys_box[item] -> EnableWindow(FALSE);
795                 m_dock2_box[item] -> EnableWindow(FALSE);
796                 m_subsys[item] = -1;
797                 m_dock2[item] = -1;
798                 return;
799         }
800
801         m_object_box[item] -> EnableWindow(TRUE);
802
803         switch (mode) {
804                 case AI_GOAL_WAYPOINTS:
805                 case AI_GOAL_WAYPOINTS_ONCE:
806                 //case AI_GOAL_WARP:
807                         for (i=0; i<MAX_WAYPOINT_LISTS; i++)
808                                 if (Waypoint_lists[i].count) {
809                                         z = m_object_box[item] -> AddString(Waypoint_lists[i].name);
810                                         m_object_box[item] -> SetItemData(z, i | TYPE_PATH);
811                                         if (init && (m_data[item] == (i | TYPE_PATH)))
812                                                 m_object[item] = z;
813                                 }
814
815                         break;
816
817                 case AI_GOAL_STAY_STILL:
818                         ptr = GET_FIRST(&obj_used_list);
819                         while (ptr != END_OF_LIST(&obj_used_list)) {
820                                 if (ptr->type == OBJ_WAYPOINT) {
821                                         t = TYPE_SHIP;
822                                         z = m_object_box[item] -> AddString(object_name(OBJ_INDEX(ptr)));
823                                         m_object_box[item] -> SetItemData(z, OBJ_INDEX(ptr) | TYPE_WAYPOINT);
824                                         if (init && (m_data[item] == (OBJ_INDEX(ptr) | TYPE_WAYPOINT)))
825                                                 m_object[item] = z;
826                                 }
827
828                                 ptr = GET_NEXT(ptr);
829                         }
830
831                         break;
832         }
833
834         switch (mode) {
835                 case AI_GOAL_DESTROY_SUBSYSTEM:
836                 case AI_GOAL_CHASE | AI_GOAL_CHASE_WING:
837                 case AI_GOAL_DOCK:
838                 case AI_GOAL_GUARD | AI_GOAL_GUARD_WING:
839                 case AI_GOAL_DISABLE_SHIP:
840                 case AI_GOAL_DISARM_SHIP:
841                 case AI_GOAL_EVADE_SHIP:
842                 case AI_GOAL_IGNORE:
843                 case AI_GOAL_STAY_NEAR_SHIP:
844                 case AI_GOAL_STAY_STILL:
845                         ptr = GET_FIRST(&obj_used_list);
846                         while (ptr != END_OF_LIST(&obj_used_list)) {
847                                 if (ptr->type == OBJ_SHIP || ptr->type == OBJ_START) {
848                                         inst = ptr->instance;
849                                         if (ptr->type == OBJ_SHIP)
850                                                 t = TYPE_SHIP;
851                                         else
852                                                 t = TYPE_PLAYER;
853
854                                         SDL_assert(inst >= 0 && inst < MAX_SHIPS);
855                                         // remove all marked ships from list
856                                         if (!goalp && (ptr->flags & OF_MARKED))
857                                                 inst = -1;
858
859                                         // when docking, remove invalid dock targets
860                                         else if (mode == AI_GOAL_DOCK) {
861                                                 if (self_ship < 0 || !ship_docking_valid(self_ship, inst))
862                                                         inst = -1;
863                                         }
864
865                                         // disallow ship being it's own target
866                                         if (inst >= 0 && inst != self_ship) {
867                                                 z = m_object_box[item] -> AddString(Ships[inst].ship_name);
868                                                 m_object_box[item] -> SetItemData(z, inst | t);
869                                                 if (init && (m_data[item] == (inst | t)))
870                                                         m_object[item] = z;
871                                         }
872                                 }
873
874                                 ptr = GET_NEXT(ptr);
875                         }
876
877                         break;
878         }
879
880         switch (mode) {
881                 case AI_GOAL_CHASE | AI_GOAL_CHASE_WING:
882                 case AI_GOAL_GUARD | AI_GOAL_GUARD_WING:
883                         for (i=0; i<MAX_WINGS; i++)
884                                 if (Wings[i].wave_count && i != self_wing) {
885                                         z = m_object_box[item] -> AddString(Wings[i].name);
886                                         m_object_box[item] -> SetItemData(z, i | TYPE_WING);
887                                         if (init && (m_data[item] == (i | TYPE_WING)))
888                                                 m_object[item] = z;
889                                 }
890
891                         break;
892         }
893
894         if (mode == AI_GOAL_DESTROY_SUBSYSTEM) {
895                 m_subsys_box[item] -> EnableWindow(TRUE);
896                 m_dock2_box[item] -> EnableWindow(FALSE);
897                 m_dock2[item] = -1;
898                 set_object(item);
899                 if (!m_behavior[item])
900                         set_item(item, init);
901
902         } else if (mode == AI_GOAL_DOCK) {
903                 num = get_docking_list(Ships[cur_ship].modelnum);
904                 m_subsys_box[item] -> EnableWindow(TRUE);
905                 m_subsys_box[item] -> ResetContent();
906                 for (i=0; i<num; i++) {
907                         SDL_assert(Docking_bay_list[i]);
908                         z = m_subsys_box[item] -> AddString(Docking_bay_list[i]);
909                         m_subsys_box[item] -> SetItemDataPtr(z, Docking_bay_list[i]);
910                 }
911
912                 set_object(item);
913                 if (!m_behavior[item])
914                         set_item(item, init);
915
916         } else {
917                 m_subsys_box[item] -> EnableWindow(FALSE);
918                 m_dock2_box[item] -> EnableWindow(FALSE);
919                 m_subsys[item] = -1;
920                 m_dock2[item] = -1;
921         }
922 }
923
924 void ShipGoalsDlg::OnSelchangeBehavior1() 
925 {
926         UpdateData(TRUE);
927         m_object[0] = 0;
928         m_subsys[0] = m_dock2[0] = 0;
929         set_item(0);
930         UpdateData(FALSE);
931 }
932
933 void ShipGoalsDlg::OnSelchangeBehavior2() 
934 {
935         UpdateData(TRUE);
936         m_object[1] = 0;
937         set_item(1);
938         m_subsys[1] = m_dock2[1] = 0;
939         UpdateData(FALSE);
940 }
941
942 void ShipGoalsDlg::OnSelchangeBehavior3() 
943 {
944         UpdateData(TRUE);
945         m_object[2] = 0;
946         set_item(2);
947         m_subsys[2] = m_dock2[2] = 0;
948         UpdateData(FALSE);
949 }
950
951 void ShipGoalsDlg::OnSelchangeBehavior4() 
952 {
953         UpdateData(TRUE);
954         m_object[3] = 0;
955         set_item(3);
956         m_subsys[3] = m_dock2[3] = 0;
957         UpdateData(FALSE);
958 }
959
960 void ShipGoalsDlg::OnSelchangeBehavior5() 
961 {
962         UpdateData(TRUE);
963         m_object[4] = 0;
964         set_item(4);
965         m_subsys[4] = m_dock2[4] = 0;
966         UpdateData(FALSE);
967 }
968
969 void ShipGoalsDlg::OnSelchangeBehavior6() 
970 {
971         UpdateData(TRUE);
972         m_object[5] = 0;
973         set_item(5);
974         m_subsys[5] = m_dock2[5] = 0;
975         UpdateData(FALSE);
976 }
977
978 void ShipGoalsDlg::OnSelchangeBehavior7() 
979 {
980         UpdateData(TRUE);
981         m_object[6] = 0;
982         set_item(6);
983         m_subsys[6] = m_dock2[6] = 0;
984         UpdateData(FALSE);
985 }
986
987 void ShipGoalsDlg::OnSelchangeBehavior8() 
988 {
989         UpdateData(TRUE);
990         m_object[7] = 0;
991         set_item(7);
992         m_subsys[7] = m_dock2[7] = 0;
993         UpdateData(FALSE);
994 }
995
996 void ShipGoalsDlg::OnSelchangeBehavior9() 
997 {
998         UpdateData(TRUE);
999         m_object[8] = 0;
1000         set_item(8);
1001         m_subsys[8] = m_dock2[8] = 0;
1002         UpdateData(FALSE);
1003 }
1004
1005 void ShipGoalsDlg::OnSelchangeBehavior10() 
1006 {
1007         UpdateData(TRUE);
1008         m_object[9] = 0;
1009         set_item(9);
1010         m_subsys[9] = m_dock2[9] = 0;
1011         UpdateData(FALSE);
1012 }
1013
1014 void ShipGoalsDlg::update()
1015 {
1016         int i;
1017
1018         if (goalp) {
1019                 for (i=0; i<ED_MAX_GOALS; i++)
1020                         update_item(i);
1021
1022                 verify_orders();
1023
1024         } else {
1025                 object *ptr;
1026
1027                 ptr = GET_FIRST(&obj_used_list);
1028                 while (ptr != END_OF_LIST(&obj_used_list)) {
1029                         if ((ptr->type == OBJ_SHIP) && (ptr->flags & OF_MARKED)) {
1030                                 goalp = Ai_info[Ships[ptr->instance].ai_index].goals;
1031                                 for (i=0; i<ED_MAX_GOALS; i++)
1032                                         update_item(i, 1);
1033                         }
1034
1035                         ptr = GET_NEXT(ptr);
1036                 }
1037
1038                 ptr = GET_FIRST(&obj_used_list);
1039                 while (ptr != END_OF_LIST(&obj_used_list)) {
1040                         if ((ptr->type == OBJ_SHIP) && (ptr->flags & OF_MARKED)) {
1041                                 self_ship = ptr->instance;
1042                                 goalp = Ai_info[Ships[self_ship].ai_index].goals;
1043                                 verify_orders(self_ship);
1044                         }
1045
1046                         ptr = GET_NEXT(ptr);
1047                 }
1048         }
1049 }
1050
1051 int ShipGoalsDlg::verify_orders(int ship)
1052 {
1053         char *str, buf[2048];
1054
1055         if ((str = error_check_initial_orders(goalp, self_ship, self_wing))!=NULL) {
1056                 if (*str == '!')
1057                         return 1;
1058                 else if (*str == '*')
1059                         str++;
1060
1061                 if (ship >= 0)
1062                         sprintf(buf, "Initial orders error for ship \"%s\"\n\n%s", Ships[ship].ship_name, str);
1063                 else
1064                         strcpy(buf, str);
1065
1066                 if (MessageBox(buf, "Error", MB_OKCANCEL | MB_ICONEXCLAMATION) != IDOK)
1067                         return 1;
1068         }
1069
1070         return 0;
1071 }
1072
1073 void ShipGoalsDlg::update_item(int item, int multi)
1074 {
1075         char *docker, *dockee, *subsys;
1076         int mode;
1077         char buf[512], save[80];
1078
1079         if (item >= MAX_AI_GOALS)
1080                 return;
1081
1082         if (!multi || m_priority[item] >= 0)
1083                 goalp[item].priority = m_priority[item];
1084
1085         if (m_behavior[item] < 0) {
1086                 if (multi)
1087                         return;
1088                 else
1089                         m_behavior[item] = 0;
1090         }
1091
1092         mode = m_behavior_box[item] -> GetItemData(m_behavior[item]);
1093         switch (mode) {
1094                 case AI_GOAL_NONE:
1095                 case AI_GOAL_CHASE_ANY:
1096                 case AI_GOAL_UNDOCK:
1097                 case AI_GOAL_KEEP_SAFE_DISTANCE:
1098                 case AI_GOAL_PLAY_DEAD:
1099                 case AI_GOAL_WARP:
1100                         MODIFY(goalp[item].ai_mode, mode);
1101                         return;
1102
1103                 case AI_GOAL_WAYPOINTS:
1104                 case AI_GOAL_WAYPOINTS_ONCE:
1105                 case AI_GOAL_DISABLE_SHIP:
1106                 case AI_GOAL_DISARM_SHIP:
1107                 case AI_GOAL_IGNORE:
1108                 case AI_GOAL_EVADE_SHIP:
1109                 case AI_GOAL_STAY_NEAR_SHIP:
1110                 case AI_GOAL_STAY_STILL:
1111                         break;
1112
1113                 case AI_GOAL_DESTROY_SUBSYSTEM:
1114                         subsys = NULL;
1115                         if (!multi || (m_data[item] && (m_subsys[item] >= 0)))
1116                                 subsys = (char *) m_subsys_box[item]->GetItemDataPtr(m_subsys[item]);
1117                                 //MODIFY(goalp[item].ai_submode, m_subsys[item] + 1);
1118
1119                         if (!subsys) {
1120                                 sprintf(buf, "Order #%d doesn't have valid subsystem name.  Order will be removed", item + 1);
1121                                 MessageBox(buf, "Notice");
1122                                 MODIFY(goalp[item].ai_mode, AI_GOAL_NONE);
1123                                 return;
1124
1125                         } else {
1126                                 if (!goalp[item].docker.name || (goalp[item].docker.name && !stricmp(goalp[item].docker.name, subsys)))
1127                                         set_modified();
1128
1129                                 goalp[item].docker.name = subsys;
1130                         }
1131
1132                         break;
1133
1134                 case AI_GOAL_CHASE | AI_GOAL_CHASE_WING:
1135                         switch (m_data[item] & TYPE_MASK) {
1136                                 case TYPE_SHIP:
1137                                 case TYPE_PLAYER:
1138                                         mode = AI_GOAL_CHASE;
1139                                         break;
1140
1141                                 case TYPE_WING:
1142                                         mode = AI_GOAL_CHASE_WING;
1143                                         break;
1144                         }
1145
1146                         break;
1147
1148                 case AI_GOAL_DOCK:
1149                         docker = NULL;
1150                         if (!multi || (m_data[item] && (m_subsys[item] >= 0)))
1151                                 docker = (char *) m_subsys_box[item] -> GetItemDataPtr(m_subsys[item]);
1152
1153                         dockee = NULL;
1154                         if (!multi || (m_data[item] && (m_dock2[item] >= 0)))
1155                                 dockee = (char *) m_dock2_box[item] -> GetItemDataPtr(m_dock2[item]);
1156
1157                         if (docker == (char *) 0xffffffff)
1158                                 docker = NULL;
1159                         if (dockee == (char *) 0xffffffff)
1160                                 dockee = NULL;
1161
1162                         if (!docker || !dockee) {
1163                                 sprintf(buf, "Order #%d doesn't have valid docking points.  Order will be removed", item + 1);
1164                                 MessageBox(buf, "Notice");
1165                                 MODIFY(goalp[item].ai_mode, AI_GOAL_NONE);
1166                                 return;
1167
1168                         } else {
1169                                 if (!goalp[item].docker.name)
1170                                         set_modified();
1171                                 else if (!stricmp(goalp[item].docker.name, docker))
1172                                         set_modified();
1173
1174                                 if (!goalp[item].dockee.name)
1175                                         set_modified();
1176                                 else if (!stricmp(goalp[item].dockee.name, dockee))
1177                                         set_modified();
1178
1179                                 goalp[item].docker.name = docker;
1180                                 goalp[item].dockee.name = dockee;
1181                         }
1182
1183                         break;
1184
1185                 case AI_GOAL_GUARD | AI_GOAL_GUARD_WING:
1186                         switch (m_data[item] & TYPE_MASK) {
1187                                 case TYPE_SHIP:
1188                                 case TYPE_PLAYER:
1189                                         mode = AI_GOAL_GUARD;
1190                                         break;
1191
1192                                 case TYPE_WING:
1193                                         mode = AI_GOAL_GUARD_WING;
1194                                         break;
1195                         }
1196
1197                         break;
1198
1199                 default:
1200                         Warning(LOCATION, "Unknown AI_GOAL type 0x%x", mode);
1201                         MODIFY(goalp[item].ai_mode, AI_GOAL_NONE);
1202                         return;
1203         }
1204
1205         MODIFY(goalp[item].ai_mode, mode);
1206
1207         *save = 0;
1208         if (goalp[item].ship_name)
1209                 strcpy(save, goalp[item].ship_name);
1210
1211         switch (m_data[item] & TYPE_MASK) {
1212                 int not_used;
1213
1214                 case TYPE_SHIP:
1215                 case TYPE_PLAYER:
1216                         goalp[item].ship_name = ai_get_goal_ship_name(Ships[m_data[item] & DATA_MASK].ship_name, &not_used);
1217                         break;
1218
1219                 case TYPE_WING:
1220                         goalp[item].ship_name = ai_get_goal_ship_name(Wings[m_data[item] & DATA_MASK].name, &not_used);
1221                         break;
1222
1223                 case TYPE_PATH:
1224                         goalp[item].ship_name = ai_get_goal_ship_name(Waypoint_lists[m_data[item] & DATA_MASK].name, &not_used);
1225                         break;
1226
1227                 case TYPE_WAYPOINT:
1228                         goalp[item].ship_name = ai_get_goal_ship_name(object_name(m_data[item] & DATA_MASK), &not_used);
1229                         break;
1230
1231                 case 0:
1232                 case -1:
1233                 case (-1 & TYPE_MASK):
1234                         if (multi)
1235                                 return;
1236
1237                         sprintf(buf, "Order #%d doesn't have a valid target.  Order will be removed", item + 1);
1238                         MessageBox(buf, "Notice");
1239                         MODIFY(goalp[item].ai_mode, AI_GOAL_NONE);
1240                         return;
1241
1242                 default:
1243                         SDL_assert(0);
1244         }
1245
1246         if (stricmp(save, goalp[item].ship_name))
1247                 set_modified();
1248 }
1249
1250 void ShipGoalsDlg::OnOK()
1251 {
1252         int i, mode;
1253
1254         UpdateData(TRUE);
1255
1256         for (i=0; i<ED_MAX_GOALS; i++) {
1257                 mode = m_behavior_box[i] -> GetItemData(m_behavior[i]);
1258                 if ((mode != AI_GOAL_NONE) && (mode != AI_GOAL_CHASE_ANY) && (mode != AI_GOAL_UNDOCK) && (mode != AI_GOAL_KEEP_SAFE_DISTANCE) && (mode != AI_GOAL_PLAY_DEAD) && (mode != AI_GOAL_WARP) ) {
1259                         if (!m_object_box[i] -> GetCount())  // no valid objects?
1260                                 m_behavior[i] = 0;
1261                         else
1262                                 m_data[i] = m_object_box[i] -> GetItemData(m_object[i]);
1263                 }
1264         }
1265
1266         update();
1267         CDialog::OnOK();
1268 }
1269
1270 void ShipGoalsDlg::OnSelchangeObject1() 
1271 {
1272         UpdateData(TRUE);
1273         set_object(0);
1274         m_subsys[0] = m_dock2[0] = 0;
1275         UpdateData(FALSE);
1276 }
1277
1278 void ShipGoalsDlg::OnSelchangeObject2() 
1279 {
1280         UpdateData(TRUE);
1281         set_object(1);
1282         m_subsys[1] = m_dock2[1] = 0;
1283         UpdateData(FALSE);
1284 }
1285
1286 void ShipGoalsDlg::OnSelchangeObject3() 
1287 {
1288         UpdateData(TRUE);
1289         set_object(2);
1290         m_subsys[2] = m_dock2[2] = 0;
1291         UpdateData(FALSE);
1292 }
1293
1294 void ShipGoalsDlg::OnSelchangeObject4() 
1295 {
1296         UpdateData(TRUE);
1297         set_object(3);
1298         m_subsys[3] = m_dock2[3] = 0;
1299         UpdateData(FALSE);
1300 }
1301
1302 void ShipGoalsDlg::OnSelchangeObject5() 
1303 {
1304         UpdateData(TRUE);
1305         set_object(4);
1306         m_subsys[4] = m_dock2[4] = 0;
1307         UpdateData(FALSE);
1308 }
1309
1310 void ShipGoalsDlg::OnSelchangeObject6()
1311 {
1312         UpdateData(TRUE);
1313         set_object(5);
1314         m_subsys[5] = m_dock2[5] = 0;
1315         UpdateData(FALSE);
1316 }
1317
1318 void ShipGoalsDlg::OnSelchangeObject7()
1319 {
1320         UpdateData(TRUE);
1321         set_object(6);
1322         m_subsys[6] = m_dock2[6] = 0;
1323         UpdateData(FALSE);
1324 }
1325
1326 void ShipGoalsDlg::OnSelchangeObject8() 
1327 {
1328         UpdateData(TRUE);
1329         set_object(7);
1330         m_subsys[7] = m_dock2[7] = 0;
1331         UpdateData(FALSE);
1332 }
1333
1334 void ShipGoalsDlg::OnSelchangeObject9() 
1335 {
1336         UpdateData(TRUE);
1337         set_object(8);
1338         m_subsys[8] = m_dock2[8] = 0;
1339         UpdateData(FALSE);
1340 }
1341
1342 void ShipGoalsDlg::OnSelchangeObject10() 
1343 {
1344         UpdateData(TRUE);
1345         set_object(9);
1346         m_subsys[9] = m_dock2[9] = 0;
1347         UpdateData(FALSE);
1348 }
1349
1350 void ShipGoalsDlg::set_object(int item)
1351 {
1352         char *str;
1353         int i = 0, z, num, not_used, mode;
1354         ship_subsys *subsys;
1355
1356         if (m_behavior[item] > 0) {
1357                 mode = m_behavior_box[item] -> GetItemData(m_behavior[item]);
1358                 if (!m_object_box[item] -> GetCount())
1359                         m_behavior[item] = m_data[item] = 0;
1360                 else
1361                         m_data[item] = m_object_box[item] -> GetItemData(m_object[item]);
1362
1363                 if ((mode == AI_GOAL_DOCK) && (m_data[item] >= 0)) {
1364                         num = get_docking_list(Ships[m_data[item] & DATA_MASK].modelnum);
1365                         m_dock2_box[item] -> EnableWindow(TRUE);
1366                         m_dock2_box[item] -> ResetContent();
1367                         for (i=0; i<num; i++) {
1368                                 SDL_assert(Docking_bay_list[i]);
1369                                 z = m_dock2_box[item] -> AddString(Docking_bay_list[i]);
1370                                 str = ai_get_goal_ship_name(Docking_bay_list[i], &not_used);
1371                                 m_dock2_box[item] -> SetItemDataPtr(z, str);
1372                         }
1373
1374                 } else if ((mode == AI_GOAL_DESTROY_SUBSYSTEM) && (m_data[item] >= 0)) {
1375                         if (((m_data[item] & TYPE_MASK) == TYPE_SHIP) || ((m_data[item] & TYPE_MASK) == TYPE_PLAYER)) {
1376                                 i = m_data[item] & DATA_MASK;
1377
1378                         } else
1379                                 Int3();
1380
1381                         m_subsys_box[item] -> ResetContent();
1382                         subsys = GET_FIRST(&Ships[i].subsys_list);
1383                         z = 0;
1384                         while (subsys != END_OF_LIST(&Ships[i].subsys_list)) {
1385                                 m_subsys_box[item]->AddString(subsys->system_info->subobj_name);
1386                                 m_subsys_box[item]->SetItemDataPtr(z, subsys->system_info->subobj_name);
1387                                 z++;
1388                                 subsys = GET_NEXT(subsys);
1389                         }
1390                 }
1391         }
1392 }
1393