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