2 * $Logfile: /Freespace2/code/fred2/ShipGoalsDlg.cpp $
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.
11 * Revision 1.1 2002/05/03 03:28:08 root
15 * 4 3/26/99 4:49p Dave
16 * Made cruisers able to dock with stuff. Made docking points and paths
19 * 3 3/25/99 3:32p Johnson
20 * HACK: Allow Mycerinus to dock
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.
27 * 1 10/07/98 3:01p Dave
29 * 1 10/07/98 3:00p Dave
31 * 57 7/06/98 5:12p Hoffoss
32 * Fixed bug where 3-5th orders don't update data listing when object
35 * 56 5/21/98 12:58a Hoffoss
36 * Fixed warnings optimized build turned up.
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).
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
47 * 53 10/22/97 3:15p Hoffoss
48 * Fixed ai-stay-still initial order to use waypoints instead of waypoint
51 * 52 10/22/97 1:58p Hoffoss
52 * Added support for AI_GOALS_PLAY_DEAD and changed AI_GOALS_STAY_STILL
55 * 51 10/10/97 5:03p Allender
56 * started work on ai-stay-still
58 * 50 9/18/97 11:28a Duncan
59 * Fixed bug with player objects having wrong name.
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.
65 * 48 9/09/97 3:39p Sandeep
66 * warning level 4 bugs
68 * 47 9/02/97 5:10p Johnson
69 * Fixed bug with wing initial orders available to select from.
71 * 46 8/26/97 4:18p Hoffoss
72 * Added error checking to initial orders dialog when ok is clicked.
74 * 45 8/19/97 11:59a Duncan
75 * Fixed bug in initial orders set_item().
77 * 44 8/16/97 4:51p Hoffoss
78 * Fixed bugs with wing deletion and removing ships from a wing.
80 * 43 8/15/97 5:14p Hoffoss
81 * Completely changed around how initial orders dialog worked. It's
84 * 42 8/14/97 7:07p Hoffoss
85 * Changed "guard ship" to "guard", since it can be used with wings now as
88 * 41 8/10/97 4:41p Hoffoss
89 * Fixed bugs with docking initial order.
91 * 40 8/05/97 10:10p Hoffoss
92 * Made attack and guard orders handle both ships and wings as targets.
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.
98 * 38 7/30/97 12:31p Hoffoss
99 * Made improvements to ship goals editor (initial orders) to disallow
102 * 37 7/25/97 4:30p Hoffoss
103 * Changes to ship lookup to include player ships.
105 * 36 7/24/97 4:55p Allender
106 * added ai-evade-ship to fred and to Freespace
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.
113 * 34 7/17/97 4:23p Allender
114 * ai-guard-wing now in both Fred and Freespace
116 * 33 7/09/97 1:56p Jasen
117 * Added new case to data mode checkunder save item.
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.
123 * 31 6/04/97 12:00a Allender
124 * added disarm and disable as initial order options
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.
130 * 29 5/07/97 1:32p Allender
131 * fix bug from previous checkin where undock orders were not persistent
133 * 28 5/07/97 1:08p Allender
134 * make undock initial order only accept a priority
136 * 27 4/03/97 3:18p Allender
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.
144 * 25 3/28/97 3:19p Hoffoss
145 * Added chase-any goal to initial orders.
147 * 24 3/21/97 4:04p Bernal
148 * fixed crash when initial orders references illegal objects. (Jason)
150 * 23 3/21/97 10:29a Hoffoss
151 * forced negative priorities to 50
153 * 22 3/19/97 4:53p Hoffoss
154 * fixed bug with unused fields not being cleared.
156 * 21 3/13/97 12:20p Hoffoss
157 * fixed bug in docking point specification of initial orders dialog.
159 * 20 3/10/97 6:43p Hoffoss
160 * Standardized docking goal usage by fred to use names instead of
163 * 19 3/10/97 5:37p Hoffoss
164 * fixed bug in dock goal selection.
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.
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)
175 * 16 3/03/97 4:32p Hoffoss
176 * Initial orders supports new docking stuff Allender added.
178 * 15 2/27/97 3:15p Allender
179 * major wing structure enhancement. simplified wing code. All around
180 * better wing support
182 * 14 2/26/97 2:45p Hoffoss
183 * Initial orders dialog now only allows 89 as a max on priority.
185 * 13 2/21/97 5:34p Hoffoss
186 * Added extensive modification detection and fixed a bug in initial
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.
198 #include "shipgoalsdlg.h"
200 #include "linklist.h"
201 #include "management.h"
204 #include "fredview.h"
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
215 #define new DEBUG_NEW
217 static char THIS_FILE[] = __FILE__;
220 /////////////////////////////////////////////////////////////////////////////
221 // ShipGoalsDlg dialog
223 ShipGoalsDlg::ShipGoalsDlg(CWnd* pParent /*=NULL*/)
224 : CDialog(ShipGoalsDlg::IDD, pParent)
228 for (i=0; i<ED_MAX_GOALS; i++) {
237 //{{AFX_DATA_INIT(ShipGoalsDlg)
240 self_ship = self_wing = -1;
243 void ShipGoalsDlg::DoDataExchange(CDataExchange* pDX)
245 CDialog::DoDataExchange(pDX);
246 //{{AFX_DATA_MAP(ShipGoalsDlg)
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]);
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]);
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);
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]);
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]);
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)
340 /////////////////////////////////////////////////////////////////////////////
341 // ShipGoalsDlg message handlers
343 BOOL ShipGoalsDlg::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext)
345 return CDialog::Create(IDD, &Ship_editor_dialog);
348 BOOL ShipGoalsDlg::OnInitDialog()
350 int i, j, z, valid[99];
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);
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);
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);
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);
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);
409 // start off with all goals available
410 for (i=0; i<Ai_goal_list_size; i++)
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))){
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)){
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..
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)){
449 for (i=0; i<MAX_WAYPOINT_LISTS; i++){
450 if (Waypoint_lists[i].count){
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:
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)) {
472 if ((self_ship > 0) && (self_ship != i) && ship_docking_valid(self_ship, i)){
480 for (i=0; i<Ai_goal_list_size; i++){
481 if (Ai_goal_list[i].def == AI_GOAL_DOCK){
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++){
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);
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);
508 for (i=0; i<ED_MAX_GOALS; i++){
512 CDialog::OnInitDialog();
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);
529 void ShipGoalsDlg::initialize_multi()
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];
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);
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];
554 for (i=0; i<ED_MAX_GOALS; i++) {
555 if (behavior[i] != m_behavior[i]) {
560 if (data[i] != m_data[i]) {
566 if (priority[i] != m_priority[i]){
569 if (subsys[i] != m_subsys[i]){
572 if (dock2[i] != m_dock2[i]){
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];
592 // perform one-time initialization of data from the goals struct.
593 void ShipGoalsDlg::initialize(ai_goal *goals, int ship)
595 int i, item, num, inst, flag, mode;
599 for (item=0; item<ED_MAX_GOALS; item++) {
602 m_priority[item] = 0;
605 if (item < MAX_AI_GOALS) {
606 m_priority[item] = goalp[item].priority;
607 mode = goalp[item].ai_mode;
610 if (m_priority[item] < 0 || m_priority[item] > 89){
611 m_priority[item] = 50;
614 m_behavior[item] = 0;
615 if (mode != AI_GOAL_NONE) {
616 i = m_behavior_box[item] -> GetCount();
618 if (mode & (m_behavior_box[item]->GetItemData(i))) {
619 m_behavior[item] = i;
627 case AI_GOAL_CHASE_ANY:
629 case AI_GOAL_KEEP_SAFE_DISTANCE:
630 case AI_GOAL_PLAY_DEAD:
634 case AI_GOAL_STAY_STILL:
635 flag = 9; // target is a ship or a waypoint
640 case AI_GOAL_DISABLE_SHIP:
641 case AI_GOAL_DISARM_SHIP:
643 case AI_GOAL_EVADE_SHIP:
644 case AI_GOAL_STAY_NEAR_SHIP:
647 case AI_GOAL_WAYPOINTS:
648 case AI_GOAL_WAYPOINTS_ONCE:
649 flag = 4; // target is a waypoint
652 case AI_GOAL_DESTROY_SUBSYSTEM:
653 num = ship_name_lookup(goalp[item].ship_name, 1);
655 m_subsys[item] = ship_get_subsys_index(&Ships[num], goalp[item].docker.name, 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])) {
672 case AI_GOAL_CHASE_WING:
673 case AI_GOAL_GUARD_WING:
674 flag = 2; // target is a wing
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;
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;
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;
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;
724 if (flag & 0x8) { // data is a waypoint name
725 i = waypoint_lookup(goalp[item].ship_name);
727 m_data[item] = i | TYPE_WAYPOINT;
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])) {
749 // Assert(m_data[item]);
753 void ShipGoalsDlg::set_item(int item, int init)
755 int i, t, z, num, inst, mode;
761 if (item >= MAX_AI_GOALS)
762 m_behavior_box[item] -> EnableWindow(FALSE);
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);
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);
787 m_object_box[item] -> EnableWindow(TRUE);
790 case AI_GOAL_WAYPOINTS:
791 case AI_GOAL_WAYPOINTS_ONCE:
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)))
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) {
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)))
821 case AI_GOAL_DESTROY_SUBSYSTEM:
822 case AI_GOAL_CHASE | AI_GOAL_CHASE_WING:
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:
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)
840 Assert(inst >= 0 && inst < MAX_SHIPS);
841 // remove all marked ships from list
842 if (!goalp && (ptr->flags & OF_MARKED))
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))
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)))
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)))
880 if (mode == AI_GOAL_DESTROY_SUBSYSTEM) {
881 m_subsys_box[item] -> EnableWindow(TRUE);
882 m_dock2_box[item] -> EnableWindow(FALSE);
885 if (!m_behavior[item])
886 set_item(item, init);
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]);
899 if (!m_behavior[item])
900 set_item(item, init);
903 m_subsys_box[item] -> EnableWindow(FALSE);
904 m_dock2_box[item] -> EnableWindow(FALSE);
910 void ShipGoalsDlg::OnSelchangeBehavior1()
914 m_subsys[0] = m_dock2[0] = 0;
919 void ShipGoalsDlg::OnSelchangeBehavior2()
924 m_subsys[1] = m_dock2[1] = 0;
928 void ShipGoalsDlg::OnSelchangeBehavior3()
933 m_subsys[2] = m_dock2[2] = 0;
937 void ShipGoalsDlg::OnSelchangeBehavior4()
942 m_subsys[3] = m_dock2[3] = 0;
946 void ShipGoalsDlg::OnSelchangeBehavior5()
951 m_subsys[4] = m_dock2[4] = 0;
955 void ShipGoalsDlg::OnSelchangeBehavior6()
960 m_subsys[5] = m_dock2[5] = 0;
964 void ShipGoalsDlg::OnSelchangeBehavior7()
969 m_subsys[6] = m_dock2[6] = 0;
973 void ShipGoalsDlg::OnSelchangeBehavior8()
978 m_subsys[7] = m_dock2[7] = 0;
982 void ShipGoalsDlg::OnSelchangeBehavior9()
987 m_subsys[8] = m_dock2[8] = 0;
991 void ShipGoalsDlg::OnSelchangeBehavior10()
996 m_subsys[9] = m_dock2[9] = 0;
1000 void ShipGoalsDlg::update()
1005 for (i=0; i<ED_MAX_GOALS; i++)
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++)
1021 ptr = GET_NEXT(ptr);
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);
1032 ptr = GET_NEXT(ptr);
1037 int ShipGoalsDlg::verify_orders(int ship)
1039 char *str, buf[2048];
1041 if ((str = error_check_initial_orders(goalp, self_ship, self_wing))!=NULL) {
1044 else if (*str == '*')
1048 sprintf(buf, "Initial orders error for ship \"%s\"\n\n%s", Ships[ship].ship_name, str);
1052 if (MessageBox(buf, "Error", MB_OKCANCEL | MB_ICONEXCLAMATION) != IDOK)
1059 void ShipGoalsDlg::update_item(int item, int multi)
1061 char *docker, *dockee, *subsys;
1063 char buf[512], save[80];
1065 if (item >= MAX_AI_GOALS)
1068 if (!multi || m_priority[item] >= 0)
1069 goalp[item].priority = m_priority[item];
1071 if (m_behavior[item] < 0) {
1075 m_behavior[item] = 0;
1078 mode = m_behavior_box[item] -> GetItemData(m_behavior[item]);
1081 case AI_GOAL_CHASE_ANY:
1082 case AI_GOAL_UNDOCK:
1083 case AI_GOAL_KEEP_SAFE_DISTANCE:
1084 case AI_GOAL_PLAY_DEAD:
1086 MODIFY(goalp[item].ai_mode, mode);
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:
1099 case AI_GOAL_DESTROY_SUBSYSTEM:
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);
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);
1112 if (!goalp[item].docker.name || (goalp[item].docker.name && !stricmp(goalp[item].docker.name, subsys)))
1115 goalp[item].docker.name = subsys;
1120 case AI_GOAL_CHASE | AI_GOAL_CHASE_WING:
1121 switch (m_data[item] & TYPE_MASK) {
1124 mode = AI_GOAL_CHASE;
1128 mode = AI_GOAL_CHASE_WING;
1136 if (!multi || (m_data[item] && (m_subsys[item] >= 0)))
1137 docker = (char *) m_subsys_box[item] -> GetItemDataPtr(m_subsys[item]);
1140 if (!multi || (m_data[item] && (m_dock2[item] >= 0)))
1141 dockee = (char *) m_dock2_box[item] -> GetItemDataPtr(m_dock2[item]);
1143 if (docker == (char *) 0xffffffff)
1145 if (dockee == (char *) 0xffffffff)
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);
1155 if (!goalp[item].docker.name)
1157 else if (!stricmp(goalp[item].docker.name, docker))
1160 if (!goalp[item].dockee.name)
1162 else if (!stricmp(goalp[item].dockee.name, dockee))
1165 goalp[item].docker.name = docker;
1166 goalp[item].dockee.name = dockee;
1171 case AI_GOAL_GUARD | AI_GOAL_GUARD_WING:
1172 switch (m_data[item] & TYPE_MASK) {
1175 mode = AI_GOAL_GUARD;
1179 mode = AI_GOAL_GUARD_WING;
1186 Warning(LOCATION, "Unknown AI_GOAL type 0x%x", mode);
1187 MODIFY(goalp[item].ai_mode, AI_GOAL_NONE);
1191 MODIFY(goalp[item].ai_mode, mode);
1194 if (goalp[item].ship_name)
1195 strcpy(save, goalp[item].ship_name);
1197 switch (m_data[item] & TYPE_MASK) {
1202 goalp[item].ship_name = ai_get_goal_ship_name(Ships[m_data[item] & DATA_MASK].ship_name, ¬_used);
1206 goalp[item].ship_name = ai_get_goal_ship_name(Wings[m_data[item] & DATA_MASK].name, ¬_used);
1210 goalp[item].ship_name = ai_get_goal_ship_name(Waypoint_lists[m_data[item] & DATA_MASK].name, ¬_used);
1214 goalp[item].ship_name = ai_get_goal_ship_name(object_name(m_data[item] & DATA_MASK), ¬_used);
1219 case (-1 & TYPE_MASK):
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);
1232 if (stricmp(save, goalp[item].ship_name))
1236 void ShipGoalsDlg::OnOK()
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?
1248 m_data[i] = m_object_box[i] -> GetItemData(m_object[i]);
1256 void ShipGoalsDlg::OnSelchangeObject1()
1260 m_subsys[0] = m_dock2[0] = 0;
1264 void ShipGoalsDlg::OnSelchangeObject2()
1268 m_subsys[1] = m_dock2[1] = 0;
1272 void ShipGoalsDlg::OnSelchangeObject3()
1276 m_subsys[2] = m_dock2[2] = 0;
1280 void ShipGoalsDlg::OnSelchangeObject4()
1284 m_subsys[3] = m_dock2[3] = 0;
1288 void ShipGoalsDlg::OnSelchangeObject5()
1292 m_subsys[4] = m_dock2[4] = 0;
1296 void ShipGoalsDlg::OnSelchangeObject6()
1300 m_subsys[5] = m_dock2[5] = 0;
1304 void ShipGoalsDlg::OnSelchangeObject7()
1308 m_subsys[6] = m_dock2[6] = 0;
1312 void ShipGoalsDlg::OnSelchangeObject8()
1316 m_subsys[7] = m_dock2[7] = 0;
1320 void ShipGoalsDlg::OnSelchangeObject9()
1324 m_subsys[8] = m_dock2[8] = 0;
1328 void ShipGoalsDlg::OnSelchangeObject10()
1332 m_subsys[9] = m_dock2[9] = 0;
1336 void ShipGoalsDlg::set_object(int item)
1339 int i = 0, z, num, not_used, mode;
1340 ship_subsys *subsys;
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;
1347 m_data[item] = m_object_box[item] -> GetItemData(m_object[item]);
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], ¬_used);
1357 m_dock2_box[item] -> SetItemDataPtr(z, str);
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;
1367 m_subsys_box[item] -> ResetContent();
1368 subsys = GET_FIRST(&Ships[i].subsys_list);
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);
1374 subsys = GET_NEXT(subsys);