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