FS2_Open
Open source remastering of the Freespace 2 engine
fredview.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) Volition, Inc. 1999. All rights reserved.
3  *
4  * All source code herein is the property of Volition, Inc. You may not sell
5  * or otherwise commercially exploit the source or things you created based on the
6  * source.
7  *
8 */
9 
10 
11 
12 #include "stdafx.h"
13 #include "FRED.h"
14 
15 #include "FREDDoc.h"
16 #include "FREDView.h"
17 #include "FredRender.h"
18 #include "cfile/cfile.h"
19 #include "Grid.h"
20 #include "MainFrm.h"
21 #include "editor.h"
22 #include "Management.h"
23 #include "graphics/2d.h"
24 #include "render/3d.h"
25 #include "object/object.h"
26 #include "globalincs/linklist.h"
27 #include "math/fvi.h" // For find_plane_line_intersection
28 #include "math/vecmat.h"
29 #include "io/key.h"
30 #include "ai/ai.h"
31 #include "ai/aigoals.h"
32 #include "ship/ship.h" // for ship names
33 #include "MissionGoalsDlg.h"
34 #include "wing.h"
35 #include "ship_select.h"
36 #include "PlayerStartEditor.h"
37 #include "OrientEditor.h"
38 #include "EventEditor.h"
39 #include "MessageEditorDlg.h"
40 #include "starfield/starfield.h"
41 #include "StarfieldEditor.h"
42 #include "math/floating.h"
43 #include "ReinforcementEditorDlg.h"
44 #include "AsteroidEditorDlg.h"
45 #include "CampaignTreeWnd.h"
46 #include "DebriefingEditorDlg.h"
47 #include "AdjustGridDlg.h"
48 #include "ShieldSysDlg.h"
49 #include "CmdBrief.h"
50 #include "jumpnode/jumpnode.h"
51 #include "DumpStats.h"
52 #include "SetGlobalShipFlags.h"
53 #include "VoiceActingManager.h"
54 #include "FictionViewerDlg.h"
55 #include "cmdline/cmdline.h"
56 #include "object/objectdock.h"
58 #include "sound/audiostr.h"
59 
60 #include "osapi/osapi.h"
61 
62 #include "gl/gl.h"
63 #include "gl/glu.h"
64 
65 #ifdef _DEBUG
66 #undef THIS_FILE
67 static char THIS_FILE[] = __FILE__;
68 #endif
69 
71 
72 // the next variable is used for executable stamping -- please leave it alone!!!
73 #define FRED_EXPIRE_TIME (7 * 1000)
76 
77 #define EXPIRE_BAD_CHECKSUM 1
78 #define EXPIRE_BAD_TIME 2
79 
80 #define SHIP_TYPES 8000
81 #define REDUCER 100.0f
82 #define DUP_DRAG_OF_WING 2
83 
85 
88 int Show_ships = 1;
89 int Show_starts = 1;
92 int Show_compass = 1;
95 int Lighting_on = 0;
96 int FullDetail = 0;
98 int viewpoint = 0;
100 int button_down = 0;
101 int Marked = 0, moved = 0;
102 int on_object = -1;
103 int Cursor_over = -1;
104 int Dup_drag = 0;
106 int physics_rot = 20;
107 int box_marking = 0;
109 int Cur_bitmap = -1;
118 
119 // Goober5000 (currently, FS1 retail not implemented)
123 
124 // used by error checker, but needed in more than just one function.
126 int obj_count = 0;
127 int g_err = 0;
128 
130 
131 void view_universe(int just_marked = 0);
132 void select_objects();
134 
136 // CFREDView
137 
139 
140 IMPLEMENT_DYNCREATE(CFREDView, CView)
141 
142 BEGIN_MESSAGE_MAP(CFREDView, CView)
143  ON_MESSAGE(WM_GOODBYE, OnGoodbye)
144  ON_MESSAGE(WM_MENU_POPUP_SHIPS, OnMenuPopupShips)
145  ON_MESSAGE(WM_MENU_POPUP_EDIT, OnMenuPopupEdit)
146 
147  //{{AFX_MSG_MAP(CFREDView)
148  ON_COMMAND(ID_VIEW_GRID, OnViewGrid)
149  ON_UPDATE_COMMAND_UI(ID_VIEW_GRID, OnUpdateViewGrid)
150  ON_COMMAND(ID_SHOW_WAYPOINTS, OnViewWaypoints)
151  ON_UPDATE_COMMAND_UI(ID_SHOW_WAYPOINTS, OnUpdateViewWaypoints)
152  ON_WM_LBUTTONDOWN()
153  ON_COMMAND(ID_EDITORS_SHIPS, OnEditorsShips)
154  ON_WM_KEYDOWN()
155  ON_WM_KEYUP()
156  ON_WM_SETFOCUS()
157  ON_WM_KILLFOCUS()
158  ON_WM_SIZE()
159  ON_WM_MOUSEMOVE()
160  ON_WM_LBUTTONUP()
161  ON_COMMAND(ID_MISCSTUFF_SHOWSHIPSASICONS, OnMiscstuffShowshipsasicons)
162  ON_WM_CONTEXTMENU()
163  ON_COMMAND(ID_EDIT_POPUP_SHOW_SHIP_ICONS, OnEditPopupShowShipIcons)
164  ON_UPDATE_COMMAND_UI(ID_EDIT_POPUP_SHOW_SHIP_ICONS, OnUpdateEditPopupShowShipIcons)
165  ON_COMMAND(ID_EDIT_POPUP_SHOW_SHIP_MODELS, OnEditPopupShowShipModels)
166  ON_UPDATE_COMMAND_UI(ID_EDIT_POPUP_SHOW_SHIP_MODELS, OnUpdateEditPopupShowShipModels)
167  ON_COMMAND(ID_MISC_STATISTICS, OnMiscStatistics)
168  ON_COMMAND(ID_EDIT_POPUP_SHOW_COMPASS, OnEditPopupShowCompass)
169  ON_UPDATE_COMMAND_UI(ID_EDIT_POPUP_SHOW_COMPASS, OnUpdateEditPopupShowCompass)
170  ON_UPDATE_COMMAND_UI(ID_CHANGE_VIEWPOINT_EXTERNAL, OnUpdateChangeViewpointExternal)
171  ON_COMMAND(ID_CHANGE_VIEWPOINT_EXTERNAL, OnChangeViewpointExternal)
172  ON_UPDATE_COMMAND_UI(ID_CHANGE_VIEWPOINT_FOLLOW, OnUpdateChangeViewpointFollow)
173  ON_COMMAND(ID_CHANGE_VIEWPOINT_FOLLOW, OnChangeViewpointFollow)
174  ON_COMMAND(ID_EDITORS_GOALS, OnEditorsGoals)
175  ON_COMMAND(ID_SPEED1, OnSpeed1)
176  ON_COMMAND(ID_SPEED2, OnSpeed2)
177  ON_COMMAND(ID_SPEED5, OnSpeed5)
178  ON_COMMAND(ID_SPEED10, OnSpeed10)
179  ON_UPDATE_COMMAND_UI(ID_SPEED1, OnUpdateSpeed1)
180  ON_COMMAND(ID_SPEED3, OnSpeed3)
181  ON_COMMAND(ID_SPEED8, OnSpeed8)
182  ON_COMMAND(ID_ROT1, OnRot1)
183  ON_COMMAND(ID_ROT2, OnRot2)
184  ON_COMMAND(ID_ROT3, OnRot3)
185  ON_COMMAND(ID_ROT4, OnRot4)
186  ON_COMMAND(ID_ROT5, OnRot5)
187  ON_UPDATE_COMMAND_UI(ID_SPEED2, OnUpdateSpeed2)
188  ON_UPDATE_COMMAND_UI(ID_SPEED3, OnUpdateSpeed3)
189  ON_UPDATE_COMMAND_UI(ID_SPEED5, OnUpdateSpeed5)
190  ON_UPDATE_COMMAND_UI(ID_SPEED8, OnUpdateSpeed8)
191  ON_UPDATE_COMMAND_UI(ID_SPEED10, OnUpdateSpeed10)
192  ON_UPDATE_COMMAND_UI(ID_ROT1, OnUpdateRot1)
193  ON_UPDATE_COMMAND_UI(ID_ROT2, OnUpdateRot2)
194  ON_UPDATE_COMMAND_UI(ID_ROT3, OnUpdateRot3)
195  ON_UPDATE_COMMAND_UI(ID_ROT4, OnUpdateRot4)
196  ON_UPDATE_COMMAND_UI(ID_ROT5, OnUpdateRot5)
197  ON_COMMAND(ID_CONTROL_MODE_CAMERA, OnControlModeCamera)
198  ON_UPDATE_COMMAND_UI(ID_CONTROL_MODE_CAMERA, OnUpdateControlModeCamera)
199  ON_COMMAND(ID_CONTROL_MODE_SHIP, OnControlModeShip)
200  ON_UPDATE_COMMAND_UI(ID_CONTROL_MODE_SHIP, OnUpdateControlModeShip)
201  ON_COMMAND(ID_SHOW_GRID_POSITIONS, OnShowGridPositions)
202  ON_UPDATE_COMMAND_UI(ID_SHOW_GRID_POSITIONS, OnUpdateShowGridPositions)
203  ON_COMMAND(ID_SHOW_COORDINATES, OnShowCoordinates)
204  ON_UPDATE_COMMAND_UI(ID_SHOW_COORDINATES, OnUpdateShowCoordinates)
205  ON_COMMAND(ID_SPEED50, OnSpeed50)
206  ON_UPDATE_COMMAND_UI(ID_SPEED50, OnUpdateSpeed50)
207  ON_COMMAND(ID_SPEED100, OnSpeed100)
208  ON_UPDATE_COMMAND_UI(ID_SPEED100, OnUpdateSpeed100)
209  ON_COMMAND(ID_SELECT, OnSelect)
210  ON_UPDATE_COMMAND_UI(ID_SELECT, OnUpdateSelect)
211  ON_COMMAND(ID_SELECT_AND_MOVE, OnSelectAndMove)
212  ON_UPDATE_COMMAND_UI(ID_SELECT_AND_MOVE, OnUpdateSelectAndMove)
213  ON_COMMAND(ID_SELECT_AND_ROTATE, OnSelectAndRotate)
214  ON_UPDATE_COMMAND_UI(ID_SELECT_AND_ROTATE, OnUpdateSelectAndRotate)
215  ON_COMMAND(ID_CONSTRAIN_X, OnConstrainX)
216  ON_UPDATE_COMMAND_UI(ID_CONSTRAIN_X, OnUpdateConstrainX)
217  ON_COMMAND(ID_CONSTRAIN_Y, OnConstrainY)
218  ON_UPDATE_COMMAND_UI(ID_CONSTRAIN_Y, OnUpdateConstrainY)
219  ON_COMMAND(ID_CONSTRAIN_Z, OnConstrainZ)
220  ON_UPDATE_COMMAND_UI(ID_CONSTRAIN_Z, OnUpdateConstrainZ)
221  ON_COMMAND(ID_CONSTRAIN_XZ, OnConstrainXz)
222  ON_UPDATE_COMMAND_UI(ID_CONSTRAIN_XZ, OnUpdateConstrainXz)
223  ON_COMMAND(ID_SELECTION_LOCK, OnSelectionLock)
224  ON_UPDATE_COMMAND_UI(ID_SELECTION_LOCK, OnUpdateSelectionLock)
225  ON_WM_LBUTTONDBLCLK()
226  ON_COMMAND(ID_DOUBLE_FINE_GRIDLINES, OnDoubleFineGridlines)
227  ON_UPDATE_COMMAND_UI(ID_DOUBLE_FINE_GRIDLINES, OnUpdateDoubleFineGridlines)
228  ON_COMMAND(ID_SHOW_DISTANCES, OnShowDistances)
229  ON_UPDATE_COMMAND_UI(ID_SHOW_DISTANCES, OnUpdateShowDistances)
230  ON_COMMAND(ID_UNIVERSAL_HEADING, OnUniversalHeading)
231  ON_UPDATE_COMMAND_UI(ID_UNIVERSAL_HEADING, OnUpdateUniversalHeading)
232  ON_COMMAND(ID_FLYING_CONTROLS, OnFlyingControls)
233  ON_UPDATE_COMMAND_UI(ID_FLYING_CONTROLS, OnUpdateFlyingControls)
234  ON_COMMAND(ID_ROTATE_LOCALLY, OnRotateLocally)
235  ON_UPDATE_COMMAND_UI(ID_ROTATE_LOCALLY, OnUpdateRotateLocally)
236  ON_COMMAND(ID_CONSTRAIN_XY, OnConstrainXy)
237  ON_UPDATE_COMMAND_UI(ID_CONSTRAIN_XY, OnUpdateConstrainXy)
238  ON_UPDATE_COMMAND_UI(ID_CONSTRAIN_YZ, OnUpdateConstrainYz)
239  ON_COMMAND(ID_CONSTRAIN_YZ, OnConstrainYz)
240  ON_COMMAND(ID_SELECT_LIST, OnSelectList)
241  ON_COMMAND(ID_ZOOM_EXTENTS, OnZoomExtents)
242  ON_COMMAND(ID_ZOOM_SELECTED, OnZoomSelected)
243  ON_UPDATE_COMMAND_UI(ID_ZOOM_SELECTED, OnUpdateZoomSelected)
244  ON_COMMAND(ID_FORM_WING, OnFormWing)
245  ON_UPDATE_COMMAND_UI(ID_FORM_WING, OnUpdateFormWing)
246  ON_COMMAND(ID_DISBAND_WING, OnDisbandWing)
247  ON_UPDATE_COMMAND_UI(ID_DISBAND_WING, OnUpdateDisbandWing)
248  ON_COMMAND(ID_SHOW_HORIZON, OnShowHorizon)
249  ON_UPDATE_COMMAND_UI(ID_SHOW_HORIZON, OnUpdateShowHorizon)
250  ON_COMMAND(ID_EDITORS_WING, OnEditorsWing)
251  ON_COMMAND(ID_EDITORS_PLAYER, OnEditorsPlayer)
252  ON_COMMAND(ID_EDITORS_ORIENT, OnEditorsOrient)
253  ON_COMMAND(ID_EDITORS_EVENTS, OnEditorsEvents)
254  ON_UPDATE_COMMAND_UI(ID_EDITORS_ORIENT, OnUpdateEditorsOrient)
255  ON_COMMAND(ID_EDITORS_MESSAGE, OnEditorsMessage)
256  ON_COMMAND(ID_EDITORS_STARFIELD, OnEditorsStarfield)
257  ON_COMMAND(ID_EDITORS_BG_BITMAPS, OnEditorsBgBitmaps)
258  ON_COMMAND(ID_EDITORS_REINFORCEMENT, OnEditorsReinforcement)
259  ON_COMMAND(ID_ERROR_CHECKER, OnErrorChecker)
260  ON_COMMAND(ID_EDITORS_WAYPOINT, OnEditorsWaypoint)
261  ON_COMMAND(ID_VIEW_OUTLINES, OnViewOutlines)
262  ON_UPDATE_COMMAND_UI(ID_VIEW_OUTLINES, OnUpdateViewOutlines)
263  ON_UPDATE_COMMAND_UI(ID_NEW_SHIP_TYPE, OnUpdateNewShipType)
264  ON_COMMAND(ID_SHOW_STARFIELD, OnShowStarfield)
265  ON_UPDATE_COMMAND_UI(ID_SHOW_STARFIELD, OnUpdateShowStarfield)
266  ON_COMMAND(ID_ASTEROID_EDITOR, OnAsteroidEditor)
267  ON_COMMAND(ID_RUN_FREESPACE, OnRunFreeSpace)
268  ON_COMMAND(ID_EDITOR_CAMPAIGN, OnEditorCampaign)
269  ON_COMMAND(ID_SHOW_SHIPS, OnShowShips)
270  ON_UPDATE_COMMAND_UI(ID_SHOW_SHIPS, OnUpdateShowShips)
271  ON_COMMAND(ID_SHOW_STARTS, OnShowStarts)
272  ON_UPDATE_COMMAND_UI(ID_SHOW_STARTS, OnUpdateShowStarts)
273  ON_COMMAND(ID_SHOW_IFF_0, OnShowIFF0)
274  ON_UPDATE_COMMAND_UI(ID_SHOW_IFF_0, OnUpdateShowIFF0)
275  ON_COMMAND(ID_SHOW_IFF_1, OnShowIFF1)
276  ON_UPDATE_COMMAND_UI(ID_SHOW_IFF_1, OnUpdateShowIFF1)
277  ON_COMMAND(ID_SHOW_IFF_2, OnShowIFF2)
278  ON_UPDATE_COMMAND_UI(ID_SHOW_IFF_2, OnUpdateShowIFF2)
279  ON_COMMAND(ID_SHOW_IFF_3, OnShowIFF3)
280  ON_UPDATE_COMMAND_UI(ID_SHOW_IFF_3, OnUpdateShowIFF3)
281  ON_COMMAND(ID_SHOW_IFF_4, OnShowIFF4)
282  ON_UPDATE_COMMAND_UI(ID_SHOW_IFF_4, OnUpdateShowIFF4)
283  ON_COMMAND(ID_SHOW_IFF_5, OnShowIFF5)
284  ON_UPDATE_COMMAND_UI(ID_SHOW_IFF_5, OnUpdateShowIFF5)
285  ON_COMMAND(ID_SHOW_IFF_6, OnShowIFF6)
286  ON_UPDATE_COMMAND_UI(ID_SHOW_IFF_6, OnUpdateShowIFF6)
287  ON_COMMAND(ID_SHOW_IFF_7, OnShowIFF7)
288  ON_UPDATE_COMMAND_UI(ID_SHOW_IFF_7, OnUpdateShowIFF7)
289  ON_COMMAND(ID_SHOW_IFF_8, OnShowIFF8)
290  ON_UPDATE_COMMAND_UI(ID_SHOW_IFF_8, OnUpdateShowIFF8)
291  ON_COMMAND(ID_SHOW_IFF_9, OnShowIFF9)
292  ON_UPDATE_COMMAND_UI(ID_SHOW_IFF_9, OnUpdateShowIFF9)
293  ON_COMMAND(ID_TOGGLE_VIEWPOINT, OnToggleViewpoint)
294  ON_COMMAND(ID_REVERT, OnRevert)
295  ON_UPDATE_COMMAND_UI(ID_REVERT, OnUpdateRevert)
296  ON_WM_SETCURSOR()
297  ON_COMMAND(ID_HIDE_OBJECTS, OnHideObjects)
298  ON_COMMAND(ID_SHOW_HIDDEN_OBJECTS, OnShowHiddenObjects)
299  ON_COMMAND(ID_EDIT_UNDO, OnEditUndo)
300  ON_UPDATE_COMMAND_UI(ID_EDIT_UNDO, OnUpdateEditUndo)
301  ON_COMMAND(ID_EDITORS_BRIEFING, OnEditorsBriefing)
302  ON_COMMAND(ID_EDITORS_DEBRIEFING, OnEditorsDebriefing)
303  ON_COMMAND(ID_SAVE_CAMERA, OnSaveCamera)
304  ON_COMMAND(ID_RESTORE_CAMERA, OnRestoreCamera)
305  ON_UPDATE_COMMAND_UI(ID_RESTORE_CAMERA, OnUpdateRestoreCamera)
306  ON_COMMAND(ID_SHOW_SEXP_HELP, OnShowSexpHelp)
307  ON_UPDATE_COMMAND_UI(ID_SHOW_SEXP_HELP, OnUpdateShowSexpHelp)
308  ON_COMMAND(ID_LOOKAT_OBJ, OnLookatObj)
309  ON_UPDATE_COMMAND_UI(ID_LOOKAT_OBJ, OnUpdateLookatObj)
310  ON_COMMAND(ID_EDITORS_ADJUST_GRID, OnEditorsAdjustGrid)
311  ON_COMMAND(ID_EDITORS_SHIELD_SYS, OnEditorsShieldSys)
312  ON_COMMAND(ID_LEVEL_OBJ, OnLevelObj)
313  ON_COMMAND(ID_ALIGN_OBJ, OnAlignObj)
314  ON_COMMAND(ID_CONTROL_OBJ, OnControlObj)
315  ON_COMMAND(ID_NEXT_OBJ, OnNextObj)
316  ON_COMMAND(ID_PREV_OBJ, OnPrevObj)
317  ON_COMMAND(ID_EDIT_DELETE_WING, OnEditDeleteWing)
318  ON_COMMAND(ID_MARK_WING, OnMarkWing)
319  ON_UPDATE_COMMAND_UI(ID_CONTROL_OBJ, OnUpdateControlObj)
320  ON_COMMAND(ID_EDIT_DELETE, OnEditDelete)
321  ON_COMMAND(ID_AA_GRIDLINES, OnAaGridlines)
322  ON_UPDATE_COMMAND_UI(ID_AA_GRIDLINES, OnUpdateAaGridlines)
323  ON_COMMAND(ID_EDITORS_CMD_BRIEF, OnCmdBrief)
324  ON_COMMAND(ID_DISABLE_UNDO, OnDisableUndo)
325  ON_UPDATE_COMMAND_UI(ID_DISABLE_UNDO, OnUpdateDisableUndo)
326  ON_UPDATE_COMMAND_UI(ID_EDITORS_CMD_BRIEF, OnUpdateCmdBrief)
327  ON_COMMAND(ID_NEXT_SUBSYS, OnNextSubsys)
328  ON_COMMAND(ID_PREV_SUBSYS, OnPrevSubsys)
329  ON_COMMAND(ID_CANCEL_SUBSYS, OnCancelSubsys)
330  ON_COMMAND(ID_DUMP_STATS, OnDumpStats)
331  ON_COMMAND(ID_SHOW_PATHS, OnShowPaths)
332  ON_UPDATE_COMMAND_UI(ID_SHOW_PATHS, OnUpdateShowPaths)
333  ON_COMMAND(ID_SHOW_DOCK_POINTS, OnShowDockPoints)
334  ON_UPDATE_COMMAND_UI(ID_SHOW_DOCK_POINTS, OnUpdateShowDockPoints)
335  ON_COMMAND(ID_FORMAT_FS2_OPEN, OnFormatFs2Open)
336  ON_UPDATE_COMMAND_UI(ID_FORMAT_FS2_OPEN, OnUpdateFormatFs2Open)
337  ON_COMMAND(ID_FORMAT_FS2_OPEN_COMP, OnFormatFs2OpenComp)
338  ON_UPDATE_COMMAND_UI(ID_FORMAT_FS2_OPEN_COMP, OnUpdateFormatFs2OpenComp)
339  ON_COMMAND(ID_FORMAT_FS2_RETAIL, OnFormatFs2Retail)
340  ON_UPDATE_COMMAND_UI(ID_FORMAT_FS2_RETAIL, OnUpdateFormatFs2Retail)
341  ON_COMMAND(ID_FORMAT_FS1_RETAIL, OnFormatFs1Retail)
342  ON_UPDATE_COMMAND_UI(ID_FORMAT_FS1_RETAIL, OnUpdateFormatFs1Retail)
343  ON_COMMAND(ID_EDITORS_SET_GLOBAL_SHIP_FLAGS, OnEditorsSetGlobalShipFlags)
344  ON_COMMAND(ID_EDITORS_VOICE, OnEditorsVoiceManager)
345  ON_COMMAND(ID_EDITORS_FICTION, OnEditorsFiction)
346  ON_WM_DESTROY()
347  ON_WM_CREATE()
348  ON_WM_ERASEBKGND()
349  ON_COMMAND(ID_VIEW_LIGHTING, OnViewLighting)
350  ON_UPDATE_COMMAND_UI(ID_VIEW_LIGHTING, OnUpdateViewLighting)
351  ON_COMMAND(ID_VIEW_FULL_DETAIL, OnViewFullDetail)
352  ON_UPDATE_COMMAND_UI(ID_VIEW_FULL_DETAIL, OnUpdateViewFullDetail)
353  //}}AFX_MSG_MAP
354  ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
355  ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
356  ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
357  ON_COMMAND_RANGE(ID_GROUP1, ID_GROUP9, OnGroup)
358  ON_COMMAND_RANGE(ID_SET_GROUP1, ID_SET_GROUP9, OnSetGroup)
359 END_MESSAGE_MAP()
360 
362 // CFREDView construction/destruction
363 
364 CFREDView::CFREDView()
365 {
366  //m_ConfirmDeleting = TRUE;
367  //m_ShowCapitalShips = TRUE;
368  //m_ShowElevations = TRUE;
369  //m_ShowFighters = TRUE;
370  //m_ShowGrid = TRUE;
371  //m_ShowMiscObjects = TRUE;
372  //m_ShowPlanets = TRUE;
373  //m_ShowWaypoints = TRUE;
374 
375  // this is stupid
386 
387  m_pGDlg = new CGrid(this);
388 
389  //if (!(int errno = gr_init(640, 480, 32)))
390  // Error(LOCATION, "Hey, gr_init failed! Error code = %i", errno);
391  Fred_view_wnd = this;
392 }
393 
395 {
396  delete m_pGDlg;
397 }
398 
399 void CALLBACK expire_game_proc( HWND wnd, UINT uMsg, UINT idEvent, DWORD dwTime)
400 {
401  KillTimer(wnd, 1);
403  MessageBox (wnd, "Fred can no longer run due to internal overlay error", NULL, MB_OK | MB_ICONERROR |MB_TASKMODAL|MB_SETFOREGROUND);
404  else
405  MessageBox (wnd, "Error: cannot enter DOS mode for 80x40 color text mode display.", NULL, MB_OK | MB_ICONERROR|MB_TASKMODAL|MB_SETFOREGROUND);
406  exit(1);
407 }
408 
410 {
411  BOOL casperl;
412 
413  casperl = CView::PreCreateWindow(cs);
414  cs.y = 0; // doesn't seem to do anything. :(
415 
416 // other miscellaneous initializations
417 
418  if (Cmdline_mod)
420  cfile_chdir("data\\missions");
421 
422 
424  return casperl;
425 }
426 
428 // CFREDView drawing
429 
430 void CFREDView::OnDraw(CDC* pDC)
431 {
432  CRect clip;
433 
434  CFREDDoc* pDoc = GetDocument();
435  ASSERT_VALID(pDoc);
436 
437  Update_window = 1;
438 }
439 
441 // CFREDView printing
442 
444 {
445  // default preparation
446  return DoPreparePrinting(pInfo);
447 }
448 
449 void CFREDView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
450 {
451  // TODO: add extra initialization before printing
452 }
453 
454 void CFREDView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
455 {
456  // TODO: add cleanup after printing
457 }
458 
460 // CFREDView diagnostics
461 
462 #ifdef _DEBUG
463 void CFREDView::AssertValid() const
464 {
465  CView::AssertValid();
466 }
467 
468 void CFREDView::Dump(CDumpContext& dc) const
469 {
470  CView::Dump(dc);
471 }
472 
473 CFREDDoc* CFREDView::GetDocument() // non-debug version is inline
474 {
475  ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CFREDDoc)));
476  return (CFREDDoc*)m_pDocument;
477 }
478 #endif //_DEBUG
479 
481 // CFREDView message handlers
482 
484 {
485  Show_grid = !Show_grid;
486  Update_window = 1;
487 }
488 
489 void CFREDView::OnUpdateViewGrid(CCmdUI* pCmdUI)
490 {
491  pCmdUI->SetCheck(Show_grid);
492 }
493 
495 {
497  Update_window = 1;
498 }
499 
500 void CFREDView::OnUpdateViewWaypoints(CCmdUI* pCmdUI)
501 {
502  pCmdUI->SetCheck(Show_waypoints);
503 }
504 
505 #define MAX_MOVE_DISTANCE 25.0f
506 
507 // If cur_object_index references a valid object, drag it from its current
508 // location to the new cursor location specified by "point".
509 // It is dragged relative to the main grid. Its y coordinate is not changed.
510 // Return value: 0/1 = didn't/did move object all the way to goal.
512 {
513  int z, cobj, flag, rval = 1;
514  float r;
515  float distance_moved = 0.0f;
516  vec3d cursor_dir, int_pnt;
517  vec3d movement_vector;
518  vec3d obj;
519  vec3d vec1, vec2;
520  object *objp, *ptr;
521  // starfield_bitmaps *bmp;
522 
523  /*
524  if (Bg_bitmap_dialog) {
525  if (Cur_bitmap < 0)
526  return -1;
527 
528  bmp = &Starfield_bitmaps[Cur_bitmap];
529  if (Single_axis_constraint && Constraint.z) {
530  bmp->dist *= 1.0f + mouse_dx / -800.0f;
531  calculate_bitmap_points(bmp, 0.0f);
532 
533  } else {
534  g3_point_to_vec_delayed(&bmp->m.fvec, marking_box.x2, marking_box.y2);
535  vm_orthogonalize_matrix(&bmp->m);
536  calculate_bitmap_points(bmp, 0.0f);
537  }
538  return rval;
539  }
540  */
541 
542  if (!query_valid_object())
543  return -1;
544 
545  if ((Dup_drag == 1) && (Briefing_dialog))
546  Dup_drag = 0;
547 
548  if (Dup_drag == 1) {
549  dup_object(NULL); // reset waypoint list
550  cobj = Duped_wing = -1;
551  flag = 0;
552  objp = GET_FIRST(&obj_used_list);
553  while (objp != END_OF_LIST(&obj_used_list)) {
554  Assert(objp->type != OBJ_NONE);
555  if (objp->flags & OF_MARKED) {
556  if ((objp->type == OBJ_SHIP) || (objp->type == OBJ_START)) {
557  z = Ships[objp->instance].wingnum;
558  if (!flag)
559  Duped_wing = z;
560  else if (Duped_wing != z)
561  Duped_wing = -1;
562 
563  } else
564  Duped_wing = -1;
565 
566  flag = 1;
567  z = dup_object(objp);
568  if (z == -1) {
569  cobj = -1;
570  break;
571  }
572 
573  if (cur_object_index == OBJ_INDEX(objp) )
574  cobj = z;
575  }
576 
577  objp = GET_NEXT(objp);
578  }
579 
581  if (cobj == -1) {
582  objp = GET_FIRST(&obj_used_list);
583  while (objp != END_OF_LIST(&obj_used_list)) {
584  ptr = GET_NEXT(objp);
585  if (objp->flags & OF_TEMP_MARKED)
586  delete_object(objp);
587 
588  objp = ptr;
589  }
590 
591  button_down = 0;
592  return -1;
593  }
594 
595  unmark_all();
596 
597  objp = GET_FIRST(&obj_used_list);
598  while (objp != END_OF_LIST(&obj_used_list)) {
599  if (objp->flags & OF_TEMP_MARKED) {
600  objp->flags &= ~OF_TEMP_MARKED;
601  mark_object(OBJ_INDEX(objp));
602  }
603 
604  objp = GET_NEXT(objp);
605  }
606 
607  set_cur_object_index(cobj);
608  if (Duped_wing != -1)
609  Dup_drag = DUP_DRAG_OF_WING; // indication for later that we duped objects in a wing
610  else
611  Dup_drag = 0;
612 
614  set_modified();
615  Update_window = 1;
616  }
617 
618  objp = &Objects[cur_object_index];
619  Assert(objp->type != OBJ_NONE);
620  obj = int_pnt = objp->pos;
621 
622  // Get 3d vector specified by mouse cursor location.
623  g3_point_to_vec_delayed(&cursor_dir, marking_box.x2, marking_box.y2);
625 // if (fvi_ray_plane(&int_pnt, &obj, &view_orient.fvec, &view_pos, &cursor_dir, 0.0f) >= 0.0f ) {
626 // vm_vec_add(&p1, &obj, &Constraint);
627 // find_nearest_point_on_line(&nearest_point, &obj, &p1, &int_pnt);
628 // int_pnt = nearest_point;
629 // distance_moved = vm_vec_dist(&obj, &int_pnt);
630 // }
631 
632  vec3d tmpAnticonstraint = Anticonstraint;
633  vec3d tmpObject = obj;
634 
635  tmpAnticonstraint.xyz.x = 0.0f;
636  r = fvi_ray_plane(&int_pnt, &tmpObject, &tmpAnticonstraint, &view_pos, &cursor_dir, 0.0f);
637 
638  // If intersected behind viewer, don't move. Too confusing, not what user wants.
639  vm_vec_sub(&vec1, &int_pnt, &view_pos);
640  vm_vec_sub(&vec2, &obj, &view_pos);
641  if ((r>=0.0f) && (vm_vec_dot(&vec1, &vec2) >= 0.0f)) {
642  vec3d tmp1;
643  vm_vec_sub( &tmp1, &int_pnt, &obj );
644  tmp1.xyz.x *= Constraint.xyz.x;
645  tmp1.xyz.y *= Constraint.xyz.y;
646  tmp1.xyz.z *= Constraint.xyz.z;
647  vm_vec_add( &int_pnt, &obj, &tmp1 );
648 
649  distance_moved = vm_vec_dist(&obj, &int_pnt);
650  }
651 
652 
653  } else { // Move in x-z plane, defined by grid. Preserve height.
654  r = fvi_ray_plane(&int_pnt, &obj, &Anticonstraint, &view_pos, &cursor_dir, 0.0f);
655 
656  // If intersected behind viewer, don't move. Too confusing, not what user wants.
657  vm_vec_sub(&vec1, &int_pnt, &view_pos);
658  vm_vec_sub(&vec2, &obj, &view_pos);
659  if ((r>=0.0f) && (vm_vec_dot(&vec1, &vec2) >= 0.0f))
660  distance_moved = vm_vec_dist(&obj, &int_pnt);
661  }
662 
663  // If moved too far, then move max distance along vector.
664  vm_vec_sub(&movement_vector, &int_pnt, &obj);
665 /* if (distance_moved > MAX_MOVE_DISTANCE) {
666  vm_vec_normalize(&movement_vector);
667  vm_vec_scale(&movement_vector, MAX_MOVE_DISTANCE);
668  } */
669 
670  if (distance_moved) {
671  objp = GET_FIRST(&obj_used_list);
672  while (objp != END_OF_LIST(&obj_used_list)) {
673  Assert(objp->type != OBJ_NONE);
674  if (objp->flags & OF_MARKED) {
675  vm_vec_add(&objp->pos, &objp->pos, &movement_vector);
676  if (objp->type == OBJ_WAYPOINT) {
678  Assert(wpt != NULL);
679  wpt->set_pos(&objp->pos);
680  }
681  }
682 
683  objp = GET_NEXT(objp);
684  }
685 
686  objp = GET_FIRST(&obj_used_list);
687  while (objp != END_OF_LIST(&obj_used_list)) {
688  if (objp->flags & OF_MARKED)
689  object_moved(objp);
690 
691  objp = GET_NEXT(objp);
692  }
693  }
694 
695  if (Briefing_dialog)
697 
698  set_modified();
699  return rval;
700 }
701 
703 {
704  object *objp;
705 
706  /*
707  if (Cur_bitmap != -1)
708  bitmap_matrix_backup = Starfield_bitmaps[Cur_bitmap].m;
709  */
710 
711  objp = GET_FIRST(&obj_used_list);
712  while (objp != END_OF_LIST(&obj_used_list)) {
713  Assert(objp->type != OBJ_NONE);
714  if (objp->flags & OF_MARKED) {
715  rotation_backup[OBJ_INDEX(objp)].pos = objp->pos;
716  rotation_backup[OBJ_INDEX(objp)].orient = objp->orient;
717  }
718 
719  objp = GET_NEXT(objp);
720  }
721 }
722 
724 {
725  int rval = 1;
726  vec3d int_pnt, obj;
727  angles a;
728  matrix leader_orient, leader_transpose, tmp, newmat, rotmat;
729  object *leader, *objp;
730  // starfield_bitmaps *bmp;
731 
732  Update_window = 1;
733  /*
734  if (Bg_bitmap_dialog) {
735  if (Cur_bitmap < 0)
736  return -1;
737 
738  bmp = &Starfield_bitmaps[Cur_bitmap];
739  calculate_bitmap_points(bmp, mouse_dx / -300.0f);
740  return rval;
741  }
742  */
743 
744  if (!query_valid_object()){
745  return -1;
746  }
747 
748  objp = &Objects[cur_object_index];
749  Assert(objp->type != OBJ_NONE);
750  obj = int_pnt = objp->pos;
751 
752  memset(&a, 0, sizeof(angles));
754  if (Constraint.xyz.x)
755  a.p = mouse_dy / REDUCER;
756  else if (Constraint.xyz.y)
757  a.h = mouse_dx / REDUCER;
758  else if (Constraint.xyz.z)
759  a.b = -mouse_dx / REDUCER;
760 
761  } else {
762  if (!Constraint.xyz.x) { // yz
763  a.b = -mouse_dx / REDUCER;
764  a.h = mouse_dy / REDUCER;
765  } else if (!Constraint.xyz.y) { // xz
766  a.p = mouse_dy / REDUCER;
767  a.b = -mouse_dx / REDUCER;
768  } else if (!Constraint.xyz.z) { // xy
769  a.p = mouse_dy / REDUCER;
770  a.h = mouse_dx / REDUCER;
771  }
772  }
773 
774  leader = &Objects[cur_object_index];
775  leader_orient = leader->orient; // save original orientation
776  vm_copy_transpose(&leader_transpose, &leader_orient);
777 
778  vm_angles_2_matrix(&rotmat, &a);
779  vm_matrix_x_matrix(&newmat, &leader->orient, &rotmat);
780  leader->orient = newmat;
781 
782  objp = GET_FIRST(&obj_used_list);
783  while (objp != END_OF_LIST(&obj_used_list)) {
784  Assert(objp->type != OBJ_NONE);
785  if ((objp->flags & OF_MARKED) && (cur_object_index != OBJ_INDEX(objp) )) {
786  if (Group_rotate) {
787  matrix rot_trans;
788  vec3d tmpv1, tmpv2;
789 
790  // change rotation matrix to rotate in opposite direction. This rotation
791  // matrix is what the leader ship has rotated by.
792  vm_copy_transpose(&rot_trans, &rotmat);
793 
794  // get point relative to our point of rotation (make POR the origin).
795  vm_vec_sub(&tmpv1, &objp->pos, &leader->pos);
796 
797  // convert point from real-world coordinates to leader's relative coordinate
798  // system (z=forward vec, y=up vec, x=right vec
799  vm_vec_rotate(&tmpv2, &tmpv1, &leader_orient);
800 
801  // now rotate the point by the transpose from above.
802  vm_vec_rotate(&tmpv1, &tmpv2, &rot_trans);
803 
804  // convert point back into real-world coordinates
805  vm_vec_rotate(&tmpv2, &tmpv1, &leader_transpose);
806 
807  // and move origin back to real-world origin. Object is now at its correct
808  // position.
809  vm_vec_add(&objp->pos, &leader->pos, &tmpv2);
810 
811  // Now fix the object's orientation to what it should be.
812  vm_matrix_x_matrix(&tmp, &objp->orient, &rotmat);
813  vm_orthogonalize_matrix(&tmp); // safety check
814  objp->orient = tmp;
815 
816  } else {
817  vm_matrix_x_matrix(&tmp, &objp->orient, &rotmat);
818  objp->orient = tmp;
819  }
820  }
821 
822  objp = GET_NEXT(objp);
823  }
824 
825  objp = GET_FIRST(&obj_used_list);
826  while (objp != END_OF_LIST(&obj_used_list)) {
827  if (objp->flags & OF_MARKED)
828  object_moved(objp);
829 
830  objp = GET_NEXT(objp);
831  }
832 
833  set_modified();
834  return rval;
835 }
836 
838 {
839  Update_window = 1;
840 
841  /*
842  if (Bg_bitmap_dialog) {
843  Assert(!vm_check_matrix_for_zeros(&bitmap_matrix_backup));
844  Starfield_bitmaps[Cur_bitmap].m = bitmap_matrix_backup;
845  calculate_bitmap_points(&Starfield_bitmaps[Cur_bitmap], 0.0f);
846  button_down = box_marking = 0;
847  Update_window = 1;
848  return;
849  }
850  */
851 
852  if (button_down) {
853  if (Editing_mode == 1) {
854  vec3d movement_vector;
855  object *objp;
856 
857  if (query_valid_object()) {
858  objp = &Objects[cur_object_index];
859  Assert(objp->type != OBJ_NONE);
860  vm_vec_sub(&movement_vector, &original_pos, &objp->pos);
861 
862  objp = GET_FIRST(&obj_used_list);
863  while (objp != END_OF_LIST(&obj_used_list)) {
864  Assert(objp->type != OBJ_NONE);
865  if (objp->flags & OF_MARKED)
866  vm_vec_add(&objp->pos, &objp->pos, &movement_vector);
867 
868  objp = GET_NEXT(objp);
869  }
870  }
871 
872  } else if (Editing_mode == 2) {
873  object *objp;
874 
875  objp = GET_FIRST(&obj_used_list);
876  while (objp != END_OF_LIST(&obj_used_list)) {
877  Assert(objp->type != OBJ_NONE);
878  if (objp->flags & OF_MARKED) {
879  int obj_index = OBJ_INDEX(objp);
880 
881  if(!IS_VEC_NULL(&rotation_backup[obj_index].orient.vec.rvec) &&
882  !IS_VEC_NULL(&rotation_backup[obj_index].orient.vec.uvec) &&
883  !IS_VEC_NULL(&rotation_backup[obj_index].orient.vec.fvec)){
884 
885  objp->pos = rotation_backup[obj_index].pos;
886  objp->orient = rotation_backup[obj_index].orient;
887  }
888  }
889 
890  objp = GET_NEXT(objp);
891  }
892  }
893  }
894 
895  button_down = box_marking = 0;
896  if (Briefing_dialog)
898 }
899 
900 void CFREDView::OnLButtonDown(UINT nFlags, CPoint point)
901 {
902  // RT point
903 
904  int waypoint_instance = -1;
905 
906  if (!Fred_active) {
907  CView::OnLButtonDown(nFlags, point);
908  return;
909  }
910 
911  if (cur_waypoint != NULL)
912  {
913  Assert(cur_waypoint_list != NULL);
914  waypoint_instance = Objects[cur_waypoint->get_objnum()].instance;
915  }
916 
917  marking_box.x1 = point.x;
918  marking_box.y1 = point.y;
919  Dup_drag = 0;
920 
921  on_object = select_object(point.x, point.y);
922  button_down = 1;
923  SetCapture();
925 
926  if (nFlags & MK_CONTROL) { // add a new object
927  if (!Bg_bitmap_dialog) {
928  if (on_object == -1) {
929  Selection_lock = 0; // force off selection lock
930  on_object = create_object_on_grid(waypoint_instance);
931 
932  } else
933  Dup_drag = 1;
934 
935  } else {
936  /*
937  Selection_lock = 0; // force off selection lock
938  on_object = Cur_bitmap = create_bg_bitmap();
939  Bg_bitmap_dialog->update_data();
940  Update_window = 1;
941  if (Cur_bitmap == -1)
942  MessageBox("Background bitmap limit reached.\nCan't add more.");
943  */
944  }
945 
946  } else if (!Selection_lock) {
947  if (Bg_bitmap_dialog) {
949  Bg_bitmap_dialog -> update_data();
950 
951  } else if ((nFlags & MK_SHIFT) || (on_object == -1) || !(Objects[on_object].flags & OF_MARKED)) {
952  if (!(nFlags & MK_SHIFT))
953  unmark_all();
954 
955  if (on_object != -1) {
956  if (Objects[on_object].flags & OF_MARKED)
958  else
960  }
961  }
962  }
963 
964  if (query_valid_object())
965  original_pos = Objects[cur_object_index].pos;
966 
967  moved = 0;
968  if (Selection_lock) {
969  if (Editing_mode == 1)
970  drag_objects();
971  else if (Editing_mode == 2)
973 
974  Update_window = 1;
975  }
976 
977  if (query_valid_object() && (Marked == 1) && (Objects[cur_object_index].type == OBJ_POINT)) {
980 
981  } else {
982  if (Briefing_dialog)
984  }
985 
986  CView::OnLButtonDown(nFlags, point);
987 }
988 
989 void CFREDView::OnMouseMove(UINT nFlags, CPoint point)
990 {
991  // RT point
992 
993  mouse_dx = point.x - last_mouse_x;
994  mouse_dy = point.y - last_mouse_y;
995  last_mouse_x = marking_box.x2 = point.x;
996  last_mouse_y = marking_box.y2 = point.y;
997  Cursor_over = select_object(point.x, point.y);
998 
999  if (!(nFlags & MK_LBUTTON))
1000  button_down = 0;
1001 
1002  // The following will cancel a drag operation if another program running in memory
1003  // happens to jump in and take over (such as new email has arrived popup boxes).
1004  if (button_down && GetCapture() != this)
1005  cancel_drag();
1006 
1007  if (!button_down && GetCapture() == this)
1008  ReleaseCapture();
1009 
1010  if (button_down) {
1011  if (abs(marking_box.x1 - marking_box.x2) > 1 || abs(marking_box.y1 - marking_box.y2) > 1)
1012  moved = 1;
1013 
1014  if (moved) {
1015  if (on_object != -1 || Selection_lock) {
1016  if (Editing_mode == 1)
1017  drag_objects();
1018  else if (Editing_mode == 2)
1020 
1021  } else if (!Bg_bitmap_dialog)
1022  box_marking = 1;
1023 
1024  if (mouse_dx || mouse_dy)
1025  Update_window = 1;
1026  }
1027  }
1028 
1029  CView::OnMouseMove(nFlags, point);
1030 }
1031 
1032 void CFREDView::OnLButtonUp(UINT nFlags, CPoint point)
1033 {
1034  marking_box.x2 = point.x;
1035  marking_box.y2 = point.y;
1036 
1037  if (button_down && GetCapture() != this)
1038  cancel_drag();
1039 
1040  if (GetCapture() == this)
1041  ReleaseCapture();
1042 
1043  if (button_down) {
1044  if ((abs(marking_box.x1 - marking_box.x2) > 1) || (abs(marking_box.y1 - marking_box.y2) > 1))
1045  moved = 1;
1046 
1047  if (moved) {
1048  if ((on_object != -1) || Selection_lock) {
1049  if (Editing_mode == 1)
1050  drag_objects();
1051  else if ((Editing_mode == 2) || (Editing_mode == 3))
1053 
1054  set_modified();
1055  FREDDoc_ptr->autosave("object move");
1056 
1057  } else
1058  box_marking = 1;
1059  }
1060 
1061  if (Bg_bitmap_dialog) {
1062  box_marking = 0;
1063 
1064  } else {
1065  if (box_marking) {
1066  select_objects();
1067  box_marking = 0;
1068 
1069  } else if ((!moved && on_object != -1) && !Selection_lock && !(nFlags & MK_SHIFT)) {
1070  unmark_all();
1072  }
1073  }
1074 
1075  button_down = 0;
1076  Update_window = 1;
1077  if (Dup_drag == DUP_DRAG_OF_WING) {
1078  char msg[256];
1079  int ship;
1080  object *objp;
1081 
1082  sprintf(msg, "Add cloned ships to wing %s?", Wings[Duped_wing].name);
1083  if (MessageBox(msg, "Query", MB_YESNO) == IDYES) {
1084  objp = GET_FIRST(&obj_used_list);
1085  while (objp != END_OF_LIST(&obj_used_list)) {
1086  if (objp->flags & OF_MARKED) {
1087  if (Wings[Duped_wing].wave_count >= MAX_SHIPS_PER_WING) {
1088  MessageBox("Max ships per wing limit reached");
1089  break;
1090  }
1091 
1092 // Can't do player starts, since only player 1 is currently allowed to be in a wing
1093 
1094  Assert(objp->type == OBJ_SHIP);
1095  ship = objp->instance;
1096  Assert(Ships[ship].wingnum == -1);
1097  wing_bash_ship_name(Ships[ship].ship_name, Wings[Duped_wing].name,
1098  Wings[Duped_wing].wave_count + 1);
1099 
1101  Ships[ship].wingnum = Duped_wing;
1102 
1104  Wings[Duped_wing].wave_count++;
1105  }
1106 
1107  objp = GET_NEXT(objp);
1108  }
1109  }
1110  }
1111  }
1112 
1113  if (query_valid_object() && (Marked == 1) && (Objects[cur_object_index].type == OBJ_POINT)) {
1116 
1117  } else {
1118  if (Briefing_dialog)
1120  }
1121 
1122  CView::OnLButtonUp(nFlags, point);
1123 }
1124 
1125 // This function never gets called because nothing causes
1126 // the WM_GOODBYE event to occur.
1127 // False! When you close the Ship Dialog, this function is called! --MK, 8/30/96
1129 {
1130  Ship_editor_dialog.DestroyWindow();
1131  Wing_editor_dialog.DestroyWindow();
1132 
1133  return 0L;
1134 }
1135 
1137 {
1138  int adjust = 0;
1139 
1140  Assert(Ship_editor_dialog.GetSafeHwnd());
1141  if (!Show_sexp_help)
1142  adjust = -SEXP_HELP_BOX_SIZE;
1143 
1145  return;
1146 
1147  Ship_editor_dialog.SetWindowPos(&wndTop, 0, 0, 0, 0,
1148  SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE);
1149  Ship_editor_dialog.ShowWindow(SW_RESTORE);
1150 }
1151 
1153 {
1154  uint lKeyData;
1155 
1156  lKeyData = lParam & 255; // key data
1157  if (lParam & 256) lKeyData += 0x80;
1158  key_mark(lKeyData, 1, 0);
1159 
1160  CView::OnKeyDown(nChar, nRepCnt, lParam);
1161 }
1162 
1163 void CFREDView::OnKeyUp(UINT nChar, UINT nRepCnt, UINT lParam)
1164 {
1165  uint lKeyData;
1166 
1167  lKeyData = lParam & 255; // key data
1168  if (lParam & 256) lKeyData += 0x80;
1169  key_mark(lKeyData, 0, 0);
1170 
1171  CView::OnKeyUp(nChar, nRepCnt, lParam);
1172 }
1173 
1174 void CFREDView::OnSetFocus(CWnd* pOldWnd)
1175 {
1176  static int flag = 0;
1177 
1178  if (flag)
1179  return;
1180 
1181  flag = 1;
1182  nprintf(("Fred routing", "OnSetFocus() called\n"));
1183  if (Update_ship) {
1185  Update_ship = 0;
1186  }
1187 
1188  if (Update_wing) {
1190  Update_wing = 0;
1191  }
1192 
1193 /* if (Wing_editor_dialog.verify() == -1)
1194  return; // abort
1195 
1196  if (Ship_editor_dialog.verify() == -1)
1197  return; // abort*/
1198 
1199  if (update_dialog_boxes()) {
1200  nprintf(("Fred routing", "OnSetFocus() returned (error occured)\n"));
1201  flag = 0;
1204  return; // abort
1205  }
1206 
1207  if (Local_modified) {
1208  FREDDoc_ptr->autosave("Editing");
1209  Local_modified = 0;
1210  }
1211 
1212  Fred_active = 1;
1213  CView::OnSetFocus(pOldWnd);
1214  nprintf(("Fred routing", "Main window focus accepted\n"));
1215  key_got_focus();
1216 
1217  Cursor_over = -1;
1218  if (GetActiveWindow() != Fred_main_wnd) {
1219 
1220  // If you get this assert make sure code.lib is compiling under the flags FRED and FRED_OGL
1222 
1223  Fred_main_wnd->SetWindowPos(&wndTop, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
1224  nprintf(("Fred routing", "OnSetFocus() had to put main window back on top\n"));
1225  }
1226 
1227  flag = 0;
1228 }
1229 
1230 void CFREDView::OnKillFocus(CWnd* pNewWnd)
1231 {
1232  nprintf(("Fred routing", "OnKillFocus() called\n"));
1233  Fred_active = 0;
1234  Local_modified = 0;
1235  CView::OnKillFocus(pNewWnd);
1236  key_lost_focus();
1237  Cursor_over = -1;
1238 }
1239 
1240 void CFREDView::OnSize(UINT nType, int cx, int cy)
1241 {
1242  CView::OnSize(nType, cx, cy);
1243 
1244  if (cy > 0) {
1245  gr_screen_resize(cx, cy);
1246  RedrawWindow();
1247  }
1248 }
1249 
1250 void do_trackball_stuff(int nFlags, CPoint point)
1251 {
1252  int btn = 0;
1253 
1254  if (nFlags & MK_LBUTTON){
1255  btn |= 1;
1256  }
1257  if (nFlags & MK_RBUTTON){
1258  btn |= 2;
1259  }
1260 
1261  move_mouse(btn, point.x, point.y);
1262 }
1263 
1264 // If add_flag != 0, then add found objects to current wing, else create new wing.
1266 {
1267  int x, y, valid, icon_mode = 0;
1268  vertex v;
1269  object *ptr;
1270 
1271  if (marking_box.x1 > marking_box.x2) {
1272  x = marking_box.x1;
1273  marking_box.x1 = marking_box.x2;
1274  marking_box.x2 = x;
1275  }
1276 
1277  if (marking_box.y1 > marking_box.y2) {
1278  y = marking_box.y1;
1279  marking_box.y1 = marking_box.y2;
1280  marking_box.y2 = y;
1281  }
1282 
1283  ptr = GET_FIRST(&obj_used_list);
1284  while (ptr != END_OF_LIST(&obj_used_list)) {
1285  valid = 1;
1286  if (ptr->flags & OF_HIDDEN)
1287  valid = 0;
1288 
1289  Assert(ptr->type != OBJ_NONE);
1290  switch (ptr->type) {
1291  case OBJ_WAYPOINT:
1292  if (!Show_waypoints)
1293  valid = 0;
1294  break;
1295 
1296  case OBJ_START:
1297  if (!Show_starts || !Show_ships)
1298  valid = 0;
1299  break;
1300 
1301  case OBJ_SHIP:
1302  if (!Show_ships)
1303  valid = 0;
1304 
1305  if (!Show_iff[Ships[ptr->instance].team])
1306  valid = 0;
1307 
1308  break;
1309  }
1310 
1311  g3_rotate_vertex(&v, &ptr->pos);
1312  if (!(v.codes & CC_BEHIND) && valid)
1313  if (!(g3_project_vertex(&v) & PF_OVERFLOW)) {
1314  x = (int) v.screen.xyw.x;
1315  y = (int) v.screen.xyw.y;
1316 
1317  if (x >= marking_box.x1 && x <= marking_box.x2 && y >= marking_box.y1 && y <= marking_box.y2) {
1318  if (ptr->flags & OF_MARKED)
1319  unmark_object(OBJ_INDEX(ptr));
1320  else
1321  mark_object(OBJ_INDEX(ptr));
1322 
1323  if (ptr->type == OBJ_POINT)
1324  icon_mode = 1;
1325  }
1326  }
1327 
1328  ptr = GET_NEXT(ptr);
1329  }
1330 
1331  if (icon_mode) {
1332  ptr = GET_FIRST(&obj_used_list);
1333  while (ptr != END_OF_LIST(&obj_used_list)) {
1334  if ((ptr->flags & OF_MARKED) && (ptr->type != OBJ_POINT))
1335  unmark_object(OBJ_INDEX(ptr));
1336 
1337  ptr = GET_NEXT(ptr);
1338  }
1339  }
1340 
1341  Update_ship = Update_wing = 1;
1342 }
1343 
1345 {
1346  CMenu menu;
1347  CPoint point;
1348 
1349  point = * ((CPoint*) lParam);
1350 
1351  ClientToScreen(&point);
1352 
1353  menu.LoadMenu(IDR_MENU_SHIP_POPUP);
1354  menu.GetSubMenu(0)->TrackPopupMenu(
1355  TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, this);
1356 
1357  return 0L;
1358 }
1359 
1361 {
1362  CMenu menu;
1363  CPoint point;
1364 
1365  point = * ((CPoint*) lParam);
1366 
1367  ClientToScreen(&point);
1368 
1369  menu.LoadMenu(IDR_MENU_EDIT_POPUP);
1370  menu.GetSubMenu(0)->TrackPopupMenu(
1371  TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, this);
1372 
1373  return 0L;
1374 }
1375 
1377 
1379 {
1380  Update_window = 1;
1381  if (g_Ships_as_icons == 0)
1382  g_Ships_as_icons = 1;
1383  else
1384  g_Ships_as_icons = 0;
1385 }
1386 
1387 // right mouse button popup menu stuff
1388 void CFREDView::OnContextMenu(CWnd* /*pWnd*/, CPoint point)
1389 {
1390  // make sure window is active
1391 // GetParentFrame()->ActivateFrame();
1392 
1393  CMenu menu;
1394  int objnum;
1395  CPoint local = point;
1397 
1398  if (button_down) {
1399  cancel_drag();
1400  return;
1401  }
1402 
1403  ScreenToClient(&local);
1404  objnum = select_object(local.x, local.y);
1405 
1406  if (objnum != -1) {
1407  set_cur_object_index(objnum);
1408  if (menu.LoadMenu(IDR_MENU_SHIP_POPUP)) {
1409  int id = ID_EDITORS_SHIPS;
1410  CMenu* pPopup = menu.GetSubMenu(0);
1411 
1412  ASSERT(pPopup != NULL);
1413  if (Marked > 1)
1414  pPopup->ModifyMenu(ID_EDITORS_SHIPS, MF_BYCOMMAND | MF_STRING, ID_EDITORS_SHIPS, "Edit Marked Ships");
1415  else {
1416  CString str;
1417 
1418  if ((Objects[objnum].type == OBJ_START) || (Objects[objnum].type == OBJ_SHIP))
1419  str.Format("Edit %s", Ships[Objects[objnum].instance].ship_name);
1420 
1421  else if (Objects[objnum].type == OBJ_JUMP_NODE) {
1422  id = ID_EDITORS_WAYPOINT;
1423  for (jnp = Jump_nodes.begin(); jnp != Jump_nodes.end(); ++jnp) {
1424  if(jnp->GetSCPObject() == &Objects[objnum])
1425  break;
1426  }
1427  str.Format("Edit %s", jnp->GetName());
1428 
1429  } else if (Objects[objnum].type == OBJ_WAYPOINT) {
1430  int idx;
1431  waypoint_list *wp_list = find_waypoint_list_with_instance(Objects[objnum].instance, &idx);
1432  Assert(wp_list != NULL);
1433 
1434  id = ID_EDITORS_WAYPOINT;
1435  str.Format("Edit %s:%d", wp_list->get_name(), idx + 1);
1436 
1437  } else if (Objects[objnum].type == OBJ_POINT) {
1438  return;
1439 
1440  } else {
1441  Int3();
1442  str = _T("Unknown");
1443  }
1444 
1445  pPopup->ModifyMenu(ID_EDITORS_SHIPS, MF_BYCOMMAND | MF_STRING, id, str);
1446  }
1447 
1448  pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, AfxGetMainWnd()); // use main window for cmds
1449  }
1450 
1451  } else {
1452  if (menu.LoadMenu(IDR_MENU_EDIT_POPUP)) {
1453  int i;
1454  CMenu* pPopup = menu.GetSubMenu(0);
1455  CMenu shipPopup, player_submenu;
1456  CMenu *species_submenu = new CMenu[Species_info.size()];
1457  ASSERT(pPopup != NULL);
1458 
1459  // create a popup menu based on the ship models read in ship.cpp.
1460  shipPopup.CreatePopupMenu();
1461  shipPopup.AppendMenu(MF_STRING | MF_ENABLED, SHIP_TYPES + Id_select_type_waypoint, "Waypoint");
1462  shipPopup.AppendMenu(MF_STRING | MF_ENABLED, SHIP_TYPES + Id_select_type_start, "Player Start");
1463  shipPopup.AppendMenu(MF_STRING | MF_ENABLED, SHIP_TYPES + Id_select_type_jump_node, "Jump Node");
1464  for (i=0; i<(int)Species_info.size(); i++) {
1465  species_submenu[i].CreatePopupMenu();
1466  shipPopup.AppendMenu(MF_STRING | MF_POPUP | MF_ENABLED,
1467  (UINT) species_submenu[i].m_hMenu, Species_info[i].species_name);
1468  }
1469 
1470  for (auto it = Ship_info.cbegin(); it != Ship_info.cend(); ++it)
1471  species_submenu[it->species].AppendMenu(MF_STRING |
1472  MF_ENABLED, SHIP_TYPES + i, it->name);
1473 
1474  pPopup->AppendMenu(MF_STRING | MF_POPUP | MF_ENABLED,
1475  (UINT) shipPopup.m_hMenu, "New Object Type");
1476 
1477  CWnd::DrawMenuBar(); // AppendMenu documentation says to do this.
1478  pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, AfxGetMainWnd());
1479  }
1480  }
1481 }
1482 
1484 {
1487  Update_window = 1;
1488 }
1489 
1491 {
1492  pCmdUI->SetCheck(Show_ship_info);
1493 }
1494 
1496 {
1499  Update_window = 1;
1500 }
1501 
1503 {
1504  pCmdUI->SetCheck(Show_ship_models);
1505 }
1506 
1508 {
1511  Update_window = 1;
1512 }
1513 
1515 {
1516  pCmdUI->SetCheck(Show_compass);
1517 }
1518 
1519 // View implementation file
1521 {
1522  CFrameWnd *pFrame = (CFrameWnd *) (AfxGetApp()->m_pMainWnd);
1523 
1524  CView *pView = pFrame->GetActiveView();
1525 
1526  if (!pView)
1527  return NULL;
1528 
1529  // Fail if view is of wrong kind
1530  // (this could occur with splitter windows, or additional
1531  // views on a single document
1532  if (! pView->IsKindOf(RUNTIME_CLASS(CFREDView)))
1533  return NULL;
1534 
1535  return (CFREDView *) pView;
1536 }
1537 
1538 /*void CFREDView::OnShipType0()
1539 {
1540  cur_model_index = 1;
1541 }
1542 
1543 void CFREDView::OnShipType1()
1544 {
1545  cur_model_index = 2;
1546 }
1547 
1548 void CFREDView::OnShipType2()
1549 {
1550  cur_model_index = 3;
1551 }
1552 
1553 void CFREDView::OnShipType3()
1554 {
1555  cur_model_index = 4;
1556 }
1557 
1558 void CFREDView::OnShipType4()
1559 {
1560  cur_model_index = 5;
1561 }
1562 
1563 void CFREDView::OnShipType5()
1564 {
1565  cur_model_index = 6;
1566 }
1567 
1568 void CFREDView::OnUpdateShipType1(CCmdUI* pCmdUI)
1569 {
1570  pCmdUI->SetCheck(cur_model_index == 2);
1571 }
1572 
1573 void CFREDView::OnUpdateShipType2(CCmdUI* pCmdUI)
1574 {
1575  pCmdUI->SetCheck(cur_model_index == 3);
1576 }
1577 
1578 void CFREDView::OnUpdateShipType3(CCmdUI* pCmdUI)
1579 {
1580  pCmdUI->SetCheck(cur_model_index == 4);
1581 }
1582 
1583 void CFREDView::OnUpdateShipType4(CCmdUI* pCmdUI)
1584 {
1585  pCmdUI->SetCheck(cur_model_index == 5);
1586 }
1587 
1588 void CFREDView::OnUpdateShipType5(CCmdUI* pCmdUI)
1589 {
1590  pCmdUI->SetCheck(cur_model_index == 6);
1591 }
1592 
1593 
1594 void CFREDView::OnUpdateShipType0(CCmdUI* pCmdUI)
1595 {
1596  pCmdUI->SetCheck(cur_model_index == 1);
1597 
1598 }
1599 
1600 void CFREDView::OnEditShipType6()
1601 {
1602  cur_model_index = 7;
1603 
1604 }
1605 
1606 void CFREDView::OnUpdateEditShipType6(CCmdUI* pCmdUI)
1607 {
1608  pCmdUI->SetCheck(cur_model_index == 7);
1609 } */
1610 
1611 
1612 // following code added by MWA 09/04/96
1613 // Implements messages for popup menu built on the fly.
1614 // not sure how stable the code is, but appears to work for now.
1615 // id's for the menu items are simply the model numbers for
1616 // the ships. Shouldn't conflict with any other ID_* thingys.
1617 BOOL CFREDView::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo)
1618 {
1619  int id = (int) nID;
1620 
1621  if (!pHandlerInfo) {
1622  if ((id >= SHIP_TYPES) && (id < SHIP_TYPES + static_cast<int>(Ship_info.size()) + 3)) {
1623  if (nCode == CN_COMMAND) {
1624  cur_model_index = id - SHIP_TYPES;
1626 
1627  } else if (nCode == CN_UPDATE_COMMAND_UI) {
1628  // Update UI element state
1629  ((CCmdUI*) pExtra)->SetCheck(cur_model_index + SHIP_TYPES == id);
1630  ((CCmdUI*) pExtra)->Enable(TRUE);
1631  }
1632 
1633  return TRUE;
1634  }
1635  }
1636 
1637  return CView::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
1638 }
1639 
1641 {
1642  char buf[2048];
1643 
1644  sprintf(buf,
1645  "Number of Objects: %d\n"
1646  "Number of Ships: %d\n"
1647  "Number of Wings: %d\n",
1649 
1650  MessageBox(buf, "FRED Statistics");
1651 }
1652 
1654 {
1655  pCmdUI->SetCheck(!viewpoint);
1656 }
1657 
1659 {
1660  viewpoint = 0;
1661  Update_window = 1;
1662 }
1663 
1665 {
1666  pCmdUI->SetCheck(viewpoint == 1);
1667 }
1668 
1670 {
1671  viewpoint = 1;
1673  Update_window = 1;
1674 }
1675 
1677 {
1678  CMissionGoalsDlg dlg;
1679 
1680  dlg.DoModal();
1681 }
1682 
1684 {
1685  physics_speed = 1;
1687 }
1688 
1690 {
1691  physics_speed = 2;
1693 }
1694 
1696 {
1697  physics_speed = 3;
1699 }
1700 
1702 {
1703  physics_speed = 5;
1705 }
1706 
1708 {
1709  physics_speed = 8;
1711 }
1712 
1714 {
1715  physics_speed = 10;
1717 }
1718 
1720 {
1721  physics_speed = 50;
1723 }
1724 
1726 {
1727  physics_speed = 100;
1729 }
1730 
1732 {
1733  physics_rot = 2;
1735 }
1736 
1738 {
1739  physics_rot = 10;
1741 }
1742 
1744 {
1745  physics_rot = 25;
1747 }
1748 
1750 {
1751  physics_rot = 50;
1753 }
1754 
1756 {
1757  physics_rot = 100;
1759 }
1760 
1761 void CFREDView::OnUpdateSpeed1(CCmdUI* pCmdUI)
1762 {
1763  pCmdUI->SetCheck(physics_speed == 1);
1764 }
1765 
1766 void CFREDView::OnUpdateSpeed2(CCmdUI* pCmdUI)
1767 {
1768  pCmdUI->SetCheck(physics_speed == 2);
1769 }
1770 
1771 void CFREDView::OnUpdateSpeed3(CCmdUI* pCmdUI)
1772 {
1773  pCmdUI->SetCheck(physics_speed == 3);
1774 }
1775 
1776 void CFREDView::OnUpdateSpeed5(CCmdUI* pCmdUI)
1777 {
1778  pCmdUI->SetCheck(physics_speed == 5);
1779 }
1780 
1781 void CFREDView::OnUpdateSpeed8(CCmdUI* pCmdUI)
1782 {
1783  pCmdUI->SetCheck(physics_speed == 8);
1784 }
1785 
1786 void CFREDView::OnUpdateSpeed10(CCmdUI* pCmdUI)
1787 {
1788  pCmdUI->SetCheck(physics_speed == 10);
1789 }
1790 
1791 void CFREDView::OnUpdateSpeed50(CCmdUI* pCmdUI)
1792 {
1793  pCmdUI->SetCheck(physics_speed == 50);
1794 }
1795 
1796 void CFREDView::OnUpdateSpeed100(CCmdUI* pCmdUI)
1797 {
1798  pCmdUI->SetCheck(physics_speed == 100);
1799 }
1800 
1801 void CFREDView::OnUpdateRot1(CCmdUI* pCmdUI)
1802 {
1803  pCmdUI->SetCheck(physics_rot == 2);
1804 }
1805 
1806 void CFREDView::OnUpdateRot2(CCmdUI* pCmdUI)
1807 {
1808  pCmdUI->SetCheck(physics_rot == 10);
1809 }
1810 
1811 void CFREDView::OnUpdateRot3(CCmdUI* pCmdUI)
1812 {
1813  pCmdUI->SetCheck(physics_rot == 25);
1814 }
1815 
1816 void CFREDView::OnUpdateRot4(CCmdUI* pCmdUI)
1817 {
1818  pCmdUI->SetCheck(physics_rot == 50);
1819 }
1820 
1821 void CFREDView::OnUpdateRot5(CCmdUI* pCmdUI)
1822 {
1823  pCmdUI->SetCheck(physics_rot == 100);
1824 }
1825 
1827 {
1828  Control_mode = 0;
1829 }
1830 
1832 {
1833  pCmdUI->SetCheck(!Control_mode);
1834 }
1835 
1837 {
1838  Control_mode = 1;
1839 }
1840 
1842 {
1843  pCmdUI->SetCheck(Control_mode == 1);
1844 }
1845 
1847 {
1850  Update_window = 1;
1851 }
1852 
1854 {
1855  pCmdUI->SetCheck(Show_grid_positions);
1856 }
1857 
1859 {
1862  Update_window = 1;
1863 }
1864 
1866 {
1867  pCmdUI->SetCheck(Show_coordinates);
1868 }
1869 
1871 {
1872  Editing_mode = 0;
1873 }
1874 
1875 void CFREDView::OnUpdateSelect(CCmdUI* pCmdUI)
1876 {
1877  pCmdUI->SetCheck(!Editing_mode);
1878 }
1879 
1881 {
1882  Editing_mode = 1;
1883 }
1884 
1886 {
1887  pCmdUI->SetCheck(Editing_mode == 1);
1888 }
1889 
1891 {
1892  Editing_mode = 2;
1893 }
1894 
1896 {
1897  pCmdUI->SetCheck(Editing_mode == 2);
1898 }
1899 
1901 {
1902  vm_vec_make(&Constraint, 1.0f, 0.0f, 0.0f);
1903  vm_vec_make(&Anticonstraint, 0.0f, 1.0f, 1.0f);
1905 }
1906 
1907 void CFREDView::OnUpdateConstrainX(CCmdUI* pCmdUI)
1908 {
1909  pCmdUI->SetRadio(Constraint.xyz.x && !Constraint.xyz.y && !Constraint.xyz.z);
1910 }
1911 
1913 {
1914  vm_vec_make(&Constraint, 0.0f, 1.0f, 0.0f);
1915  vm_vec_make(&Anticonstraint, 1.0f, 0.0f, 1.0f);
1917 }
1918 
1919 void CFREDView::OnUpdateConstrainY(CCmdUI* pCmdUI)
1920 {
1921  pCmdUI->SetRadio(!Constraint.xyz.x && Constraint.xyz.y && !Constraint.xyz.z);
1922 }
1923 
1925 {
1926  vm_vec_make(&Constraint, 0.0f, 0.0f, 1.0f);
1927  vm_vec_make(&Anticonstraint, 1.0f, 1.0f, 0.0f);
1929 }
1930 
1931 void CFREDView::OnUpdateConstrainZ(CCmdUI* pCmdUI)
1932 {
1933  pCmdUI->SetRadio(!Constraint.xyz.x && !Constraint.xyz.y && Constraint.xyz.z);
1934 }
1935 
1937 {
1938  vm_vec_make(&Constraint, 1.0f, 0.0f, 1.0f);
1939  vm_vec_make(&Anticonstraint, 0.0f, 1.0f, 0.0f);
1941 }
1942 
1943 void CFREDView::OnUpdateConstrainXz(CCmdUI* pCmdUI)
1944 {
1945  pCmdUI->SetRadio(Constraint.xyz.x && !Constraint.xyz.y && Constraint.xyz.z);
1946 }
1947 
1949 {
1950  vm_vec_make(&Constraint, 1.0f, 1.0f, 0.0f);
1951  vm_vec_make(&Anticonstraint, 0.0f, 0.0f, 1.0f);
1953 }
1954 
1955 void CFREDView::OnUpdateConstrainXy(CCmdUI* pCmdUI)
1956 {
1957  pCmdUI->SetRadio(Constraint.xyz.x && Constraint.xyz.y && !Constraint.xyz.z);
1958 }
1959 
1961 {
1962  vm_vec_make(&Constraint, 0.0f, 1.0f, 1.0f);
1963  vm_vec_make(&Anticonstraint, 1.0f, 0.0f, 0.0f);
1965 }
1966 
1967 void CFREDView::OnUpdateConstrainYz(CCmdUI* pCmdUI)
1968 {
1969  pCmdUI->SetRadio(!Constraint.xyz.x && Constraint.xyz.y && Constraint.xyz.z);
1970 }
1971 
1973 {
1975 }
1976 
1978 {
1979  pCmdUI->SetCheck(Selection_lock);
1980 }
1981 
1982 void CFREDView::OnLButtonDblClk(UINT nFlags, CPoint point)
1983 {
1984  CView::OnLButtonDblClk(nFlags, point);
1985  if (Cursor_over != -1) {
1986  switch (Objects[Cursor_over].type) {
1987  case OBJ_SHIP:
1988  case OBJ_START:
1989  OnEditorsShips();
1990  break;
1991 
1992  case OBJ_WAYPOINT:
1993  case OBJ_JUMP_NODE:
1995  break;
1996  }
1997 
1998  } else if (Briefing_dialog)
2000 }
2001 
2003 {
2007  Update_window = 1;
2008 }
2009 
2011 {
2012  pCmdUI->SetCheck(double_fine_gridlines);
2013 }
2014 
2016 {
2019  Update_window = 1;
2020 }
2021 
2023 {
2024  pCmdUI->SetCheck(Show_distances);
2025 }
2026 
2028 {
2030 }
2031 
2033 {
2034  pCmdUI->SetCheck(Universal_heading);
2035 }
2036 
2038 {
2040 }
2041 
2043 {
2044  pCmdUI->SetCheck(Flying_controls_mode);
2045 }
2046 
2048 {
2050 }
2051 
2053 {
2054  pCmdUI->SetCheck(!Group_rotate);
2055 }
2056 
2058 {
2059  ship_select dlg;
2060 
2061  dlg.DoModal();
2062 }
2063 
2064 // position camera to view all objects on the screen at once. Doesn't change orientation.
2065 void view_universe(int just_marked)
2066 {
2067  int i, max = 0, flags[MAX_OBJECTS];
2068  float dist, largest = 20.0f;
2069  vec3d center, p1, p2; // center of all the objects collectively
2070  vertex v;
2071  object *ptr;
2072 
2073  for (i=0; i<MAX_OBJECTS; i++)
2074  flags[i] = 0;
2075 
2076  if (just_marked)
2077  ptr = &Objects[cur_object_index];
2078  else
2079  ptr = GET_FIRST(&obj_used_list);
2080 
2081  p1.xyz.x = p2.xyz.x = ptr->pos.xyz.x;
2082  p1.xyz.y = p2.xyz.y = ptr->pos.xyz.y;
2083  p1.xyz.z = p2.xyz.z = ptr->pos.xyz.z;
2084 
2085  ptr = GET_FIRST(&obj_used_list);
2086  while (ptr != END_OF_LIST(&obj_used_list)) {
2087  if (!just_marked || (ptr->flags & OF_MARKED)) {
2088  center = ptr->pos;
2089  if (center.xyz.x < p1.xyz.x)
2090  p1.xyz.x = center.xyz.x;
2091  if (center.xyz.x > p2.xyz.x)
2092  p2.xyz.x = center.xyz.x;
2093  if (center.xyz.y < p1.xyz.y)
2094  p1.xyz.y = center.xyz.y;
2095  if (center.xyz.y > p2.xyz.y)
2096  p2.xyz.y = center.xyz.y;
2097  if (center.xyz.z < p1.xyz.z)
2098  p1.xyz.z = center.xyz.z;
2099  if (center.xyz.z > p2.xyz.z)
2100  p2.xyz.z = center.xyz.z;
2101  }
2102 
2103  ptr = GET_NEXT(ptr);
2104  }
2105 
2106  vm_vec_avg(&center, &p1, &p2);
2107  ptr = GET_FIRST(&obj_used_list);
2108  while (ptr != END_OF_LIST(&obj_used_list)) {
2109  if (!just_marked || (ptr->flags & OF_MARKED)) {
2110  dist = vm_vec_dist_squared(&center, &ptr->pos);
2111  if (dist > largest)
2112  largest = dist;
2113 
2114  flags[OBJ_INDEX(ptr)] = 1; // flag object as needing on-screen check
2115  if (OBJ_INDEX(ptr) > max)
2116  max = OBJ_INDEX(ptr);
2117  }
2118 
2119  ptr = GET_NEXT(ptr);
2120  }
2121 
2122  dist = fl_sqrt(largest) + 1.0f;
2123  vm_vec_scale_add(&view_pos, &center, &view_orient.vec.fvec, -dist);
2125 
2126  ptr = GET_FIRST(&obj_used_list);
2127  while (ptr != END_OF_LIST(&obj_used_list)) {
2128  if (!just_marked || (ptr->flags & OF_MARKED)) {
2129  g3_rotate_vertex(&v, &ptr->pos);
2130  Assert(!(v.codes & CC_BEHIND));
2131  if (g3_project_vertex(&v) & PF_OVERFLOW)
2132  Int3();
2133 
2134  while (v.codes & CC_OFF) { // is point off screen?
2135  dist += 5.0f; // zoom out a little and check again.
2136  vm_vec_scale_add(&view_pos, &center, &view_orient.vec.fvec, -dist);
2138  g3_rotate_vertex(&v, &ptr->pos);
2139  if (g3_project_vertex(&v) & PF_OVERFLOW)
2140  Int3();
2141  }
2142  }
2143 
2144  ptr = GET_NEXT(ptr);
2145  }
2146 
2147  dist *= 1.1f;
2148  vm_vec_scale_add(&view_pos, &center, &view_orient.vec.fvec, -dist);
2150  Update_window = 1;
2151 }
2152 
2154 {
2155  if (Single_axis_constraint) {
2156  if (Constraint.xyz.x)
2157  OnConstrainY();
2158  else if (Constraint.xyz.y)
2159  OnConstrainZ();
2160  else if (Constraint.xyz.z)
2161  OnConstrainXz();
2162 
2163  } else {
2164  if (!Constraint.xyz.x)
2165  OnConstrainXy();
2166  else if (!Constraint.xyz.y)
2167  OnConstrainYz();
2168  else if (!Constraint.xyz.z)
2169  OnConstrainX();
2170  }
2171 }
2172 
2174 {
2175  view_universe();
2176 }
2177 
2179 {
2180  if (query_valid_object()) {
2181  if (Marked > 1)
2182  view_universe(1);
2183  else
2185  }
2186 
2187  Update_window = 1;
2188 }
2189 
2190 void CFREDView::OnUpdateZoomSelected(CCmdUI* pCmdUI)
2191 {
2192  pCmdUI->Enable(query_valid_object());
2193 }
2194 
2196 {
2197  object *ptr = GET_FIRST(&obj_used_list);
2198  bool found = false;
2199  while (ptr != END_OF_LIST(&obj_used_list)) {
2200  if (( (ptr->type == OBJ_SHIP) || (ptr->type == OBJ_START) ) && (ptr->flags & OF_MARKED)) {
2201  if(Ships[ptr->instance].flags & SF_REINFORCEMENT) {
2202  found = true;
2203  break;
2204  }
2205  }
2206 
2207  ptr = GET_NEXT(ptr);
2208  }
2209 
2210  if(found) {
2211  int ok = MessageBox("Some of the ships you selected to create a wing are marked as reinforcements. Press Ok to clear the flag on all selected ships. Press Cancel to not create the wing.", "Reinforcement conflict", MB_ICONEXCLAMATION | MB_OKCANCEL);
2212  if(ok == IDOK) {
2213  ptr = GET_FIRST(&obj_used_list);
2214  while (ptr != END_OF_LIST(&obj_used_list)) {
2215  if (( (ptr->type == OBJ_SHIP) || (ptr->type == OBJ_START) ) && (ptr->flags & OF_MARKED)) {
2217  }
2218 
2219  ptr = GET_NEXT(ptr);
2220  }
2221  } else {
2222  return;
2223  }
2224  }
2225 
2226  if (!create_wing())
2227  FREDDoc_ptr->autosave("form wing");
2228 }
2229 
2230 void CFREDView::OnUpdateFormWing(CCmdUI* pCmdUI)
2231 {
2232  int count = 0;
2233  object *ptr;
2234 
2235  if (query_valid_object()) {
2236  ptr = GET_FIRST(&obj_used_list);
2237  while (ptr != END_OF_LIST(&obj_used_list)) {
2238  if (ptr->flags & OF_MARKED) {
2239  if (ptr->type == OBJ_SHIP)
2240  {
2241  int ship_type = ship_query_general_type(ptr->instance);
2242  if(ship_type > -1 && (Ship_types[ship_type].ai_bools & STI_AI_CAN_FORM_WING))
2243  {
2244  count++;
2245  }
2246  }
2247 
2248  if (ptr->type == OBJ_START)
2249  count++;
2250  }
2251 
2252  ptr = GET_NEXT(ptr);
2253  }
2254  }
2255 
2256  pCmdUI->Enable(count > 0);
2257 }
2258 
2260 {
2261  int i, obj;
2262 
2263  if (!query_valid_object())
2264  return 0;
2265 
2266  if (cur_wing == -1)
2267  return 0;
2268 
2269  i = Wings[cur_wing].wave_count;
2270  if (Marked != i) // does marked object count match number of ships in wing?
2271  return 0;
2272 
2273  while (i--) {
2274  obj = wing_objects[cur_wing][i];
2275  if ((Objects[obj].type != OBJ_SHIP) && (Objects[obj].type != OBJ_START))
2276  Error(LOCATION, "Invalid objects detected in wing \"%s\"", Wings[cur_wing].name);
2277 
2278 // if (Ships[Objects[obj].instance].wingnum != cur_wing)
2279 // return 0;
2280  Assert(Ships[Objects[obj].instance].wingnum == cur_wing);
2281  if (!(Objects[obj].flags & OF_MARKED)) // ensure all ships in wing.are marked
2282  return 0;
2283  }
2284 
2285  return 1;
2286 }
2287 
2289 {
2290  if (query_single_wing_marked()) {
2292  FREDDoc_ptr->autosave("wing disband");
2293 
2294  } else
2295  MessageBox("One and only one wing must be selected for this operation");
2296 }
2297 
2298 void CFREDView::OnUpdateDisbandWing(CCmdUI* pCmdUI)
2299 {
2300  pCmdUI->Enable(query_single_wing_marked());
2301 }
2302 
2304 {
2307  Update_window = 1;
2308 }
2309 
2310 void CFREDView::OnUpdateShowHorizon(CCmdUI* pCmdUI)
2311 {
2312  pCmdUI->SetCheck(Show_horizon);
2313 }
2314 
2316 {
2317  int adjust = 0;
2318 
2319  Assert(Wing_editor_dialog.GetSafeHwnd());
2320  if (!Show_sexp_help)
2321  adjust = -SEXP_HELP_BOX_SIZE;
2322 
2324  return;
2325 
2326  Wing_editor_dialog.SetWindowPos(&wndTop, 0, 0, 0, 0,
2327  SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE);
2328  Wing_editor_dialog.ShowWindow(SW_RESTORE);
2329 }
2330 
2332 {
2333  player_start_editor dlg;
2334 
2335  dlg.DoModal();
2336 }
2337 
2339 {
2340  orient_editor dlg;
2341 
2342  dlg.DoModal();
2343 }
2344 
2346 {
2347  if (Message_editor_dlg) {
2348  MessageBox("You must close the message editor before opening the event editor");
2349  return;
2350  }
2351 
2352  if (!Event_editor_dlg) {
2355  }
2356 
2357  Event_editor_dlg->SetWindowPos(&wndTop, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE);
2358  Event_editor_dlg->ShowWindow(SW_RESTORE);
2359 }
2360 
2362 {
2363  pCmdUI->Enable(query_valid_object());
2364 }
2365 
2367 {
2368  if (Event_editor_dlg) {
2369  MessageBox("You must close the event editor before opening the message editor");
2370  return;
2371  }
2372 
2373  if (!Message_editor_dlg) {
2376  }
2377 
2378  Message_editor_dlg->SetWindowPos(&wndTop, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE);
2379  Message_editor_dlg->ShowWindow(SW_RESTORE);
2380 }
2381 
2383 {
2384  starfield_editor dlg;
2385 
2386  dlg.DoModal();
2387 }
2388 
2390 {
2391 }
2392 
2394 {
2395  if (!Bg_bitmap_dialog) {
2398  }
2399 
2400  Bg_bitmap_dialog->SetWindowPos(&wndTop, 0, 0, 0, 0,
2401  SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE);
2402  Bg_bitmap_dialog->ShowWindow(SW_RESTORE);
2403 }
2404 
2406 {
2408 
2409  dlg.DoModal();
2410 }
2411 
2413 {
2414  int z;
2415 
2416  z = global_error_check();
2417  if (!z)
2418  MessageBox("No errors were detected in this mission", "Woohoo!");
2419 
2420  for (z=0; z<obj_count; z++)
2421  if (flags[z])
2422  delete [] names[z];
2423 
2424  obj_count = 0;
2425 }
2426 
2428 {
2429  char buf[256], *str;
2430  int bs, i, j, n, s, t, z, ai, count, ship, wing, obj, team, point, multi;
2431  object *ptr;
2432  brief_stage *sp;
2433  int starting_orders;
2434 
2435  g_err = multi = 0;
2437  multi = 1;
2438 
2439 // if (!stricmp(The_mission.name, "Untitled"))
2440 // if (error("You haven't given this mission a title yet.\nThis is done from the Mission Specs Editor (Shift-N)."))
2441 // return 1;
2442 
2443  // cycle though all the objects and verify every possible aspect of them
2444  obj_count = t = 0;
2445  ptr = GET_FIRST(&obj_used_list);
2446  while (ptr != END_OF_LIST(&obj_used_list)) {
2447  names[obj_count] = NULL;
2448  flags[obj_count] = 0;
2449  i = ptr->instance;
2450  if ((ptr->type == OBJ_SHIP) || (ptr->type == OBJ_START)) {
2451  if (i < 0 || i >= MAX_SHIPS){
2452  return internal_error("An object has an illegal ship index");
2453  }
2454 
2455  z = Ships[i].ship_info_index;
2456  if ((z < 0) || (z >= static_cast<int>(Ship_info.size()))){
2457  return internal_error("A ship has an illegal class");
2458  }
2459 
2460  if (ptr->type == OBJ_START) {
2461  t++;
2462  if (!(Ship_info[z].flags & SIF_PLAYER_SHIP)) {
2463  ptr->type = OBJ_SHIP;
2464  Player_starts--;
2465  t--;
2466  if (error("Invalid ship type for a player. Ship has been reset to non-player ship.")){
2467  return 1;
2468  }
2469  }
2470 
2471  for (n=count=0; n<MAX_SHIP_PRIMARY_BANKS; n++){
2472  if (Ships[i].weapons.primary_bank_weapons[n] >= 0){
2473  count++;
2474  }
2475  }
2476 
2477  if (!count){
2478  if (error("Player \"%s\" has no primary weapons. Should have at least 1", Ships[i].ship_name)){
2479  return 1;
2480  }
2481  }
2482 
2483  for (n=count=0; n<MAX_SHIP_SECONDARY_BANKS; n++){
2484  if (Ships[i].weapons.secondary_bank_weapons[n] >= 0){
2485  count++;
2486  }
2487  }
2488  }
2489 
2490  if (Ships[i].objnum != OBJ_INDEX(ptr)){
2491  return internal_error("Object/ship references are corrupt");
2492  }
2493 
2495  wing = Ships[i].wingnum;
2496  if (wing >= 0) { // ship is part of a wing, so check this
2497  if (wing < 0 || wing >= MAX_WINGS){ // completely out of range?
2498  return internal_error("A ship has an illegal wing index");
2499  }
2500 
2501  j = Wings[wing].wave_count;
2502  if (!j){
2503  return internal_error("A ship is in a non-existent wing");
2504  }
2505 
2506  if (j < 0 || j > MAX_SHIPS_PER_WING){
2507  return internal_error("Invalid number of ships in wing \"%s\"", Wings[z].name);
2508  }
2509 
2510  while (j--){
2511  if (wing_objects[wing][j] == OBJ_INDEX(ptr)){ // look for object in wing's table
2512  break;
2513  }
2514  }
2515 
2516  if (j < 0){
2517  return internal_error("Ship/wing references are corrupt");
2518  }
2519 
2520  // wing squad logo check - Goober5000
2521  if (strlen(Wings[wing].wing_squad_filename) > 0) //-V805
2522  {
2524  {
2525  if (error("Wing squad logos are not displayed in multiplayer games."))
2526  {
2527  return 1;
2528  }
2529  }
2530  else
2531  {
2532  if (ptr->type == OBJ_START)
2533  {
2534  if (error("A squad logo was assigned to the player's wing. The player's squad logo will be displayed instead of the wing squad logo on ships in this wing."))
2535  {
2536  return 1;
2537  }
2538  }
2539  }
2540  }
2541  }
2542 
2543  if ( (Ships[i].flags & SF_KILL_BEFORE_MISSION) && (Ships[i].hotkey >= 0) ){
2544  if (error("Ship flagged as \"destroy before mission start\" has a hotkey assignment")){
2545  return 1;
2546  }
2547  }
2548 
2549  if ( (Ships[i].flags & SF_KILL_BEFORE_MISSION) && (ptr->type == OBJ_START) ){
2550  if (error("Player start flagged as \"destroy before mission start\"")){
2551  return 1;
2552  }
2553  }
2554  } else if (ptr->type == OBJ_WAYPOINT) {
2555  int waypoint_num;
2556  waypoint_list *wp_list = find_waypoint_list_with_instance(i, &waypoint_num);
2557 
2558  if (wp_list == NULL) {
2559  return internal_error("Object references an illegal waypoint path number");
2560  }
2561 
2562  if (waypoint_num < 0 || (uint) waypoint_num >= wp_list->get_waypoints().size()) {
2563  return internal_error("Object references an illegal waypoint number in path");
2564  }
2565 
2566  sprintf(buf, "%s:%d", wp_list->get_name(), waypoint_num + 1);
2567  names[obj_count] = new char[strlen(buf) + 1];
2568  strcpy(names[obj_count], buf);
2569  flags[obj_count] = 1;
2570  } else if (ptr->type == OBJ_POINT) {
2571  if (!Briefing_dialog){
2572  return internal_error("Briefing icon detected when not in briefing edit mode");
2573  }
2574  //Shouldn't be needed anymore.
2575  //If we really do need it, call me and I'll write a is_valid function for jumpnodes -WMC
2576  }
2577  else if (ptr->type == OBJ_JUMP_NODE)
2578  {
2579  //nothing needs to be done here, we just need to make sure the else doesn't occur
2580  }
2581  else {
2582  return internal_error("An unknown object type (%d) was detected", ptr->type);
2583  }
2584 
2585  for (i=0; i<obj_count; i++){
2586  if (names[i] && names[obj_count]){
2587  if (!stricmp(names[i], names[obj_count])){
2588  return internal_error("Duplicate object names (%s)", names[i]);
2589  }
2590  }
2591  }
2592 
2593  obj_count++;
2594  ptr = GET_NEXT(ptr);
2595  }
2596 
2597  if (t != Player_starts){
2598  return internal_error("Total number of player ships is incorrect");
2599  }
2600 
2601  if (obj_count != Num_objects){
2602  return internal_error("Num_objects is incorrect");
2603  }
2604 
2605  count = 0;
2606  for (i=0; i<MAX_SHIPS; i++) {
2607  if (Ships[i].objnum >= 0) { // is ship being used?
2608  count++;
2609  if (!query_valid_object(Ships[i].objnum)){
2610  return internal_error("Ship uses an unused object");
2611  }
2612 
2613  z = Objects[Ships[i].objnum].type;
2614  if ((z != OBJ_SHIP) && (z != OBJ_START)){
2615  return internal_error("Object should be a ship, but isn't");
2616  }
2617 
2618  if (fred_check_sexp(Ships[i].arrival_cue, OPR_BOOL, "arrival cue of ship \"%s\"", Ships[i].ship_name)){
2619  return -1;
2620  }
2621 
2622  if (fred_check_sexp(Ships[i].departure_cue, OPR_BOOL, "departure cue of ship \"%s\"", Ships[i].ship_name)){
2623  return -1;
2624  }
2625 
2626  if (Ships[i].arrival_location != ARRIVE_AT_LOCATION) {
2627  if (Ships[i].arrival_anchor < 0){
2628  if (error("Ship \"%s\" requires a valid arrival target", Ships[i].ship_name)){
2629  return 1;
2630  }
2631  }
2632  }
2633 
2634  if (Ships[i].departure_location != DEPART_AT_LOCATION) {
2635  if (Ships[i].departure_anchor < 0){
2636  if (error("Ship \"%s\" requires a valid departure target", Ships[i].ship_name)){
2637  return 1;
2638  }
2639  }
2640  }
2641 
2642  ai = Ships[i].ai_index;
2643  if (ai < 0 || ai >= MAX_AI_INFO){
2644  return internal_error("AI index out of range for ship \"%s\"", Ships[i].ship_name);
2645  }
2646 
2647  if (Ai_info[ai].shipnum != i){
2648  return internal_error("AI/ship references are corrupt");
2649  }
2650 
2651  if ((str = error_check_initial_orders(Ai_info[ai].goals, i, -1))>0) {
2652  if (*str == '*')
2653  return internal_error("Initial orders error for ship \"%s\"\n\n%s", Ships[i].ship_name, str + 1);
2654  else if (*str == '!')
2655  return 1;
2656  else if (error("Initial orders error for ship \"%s\"\n\n%s", Ships[i].ship_name, str))
2657  return 1;
2658  }
2659 
2660 
2661  for (dock_instance *dock_ptr = Objects[Ships[i].objnum].dock_list; dock_ptr != NULL; dock_ptr = dock_ptr->next)
2662  {
2663  obj = OBJ_INDEX(dock_ptr->docked_objp);
2664 
2665  if (!query_valid_object(obj)){
2666  return internal_error("Ship \"%s\" initially docked with non-existant ship", Ships[i].ship_name);
2667  }
2668 
2669  if (Objects[obj].type != OBJ_SHIP && Objects[obj].type != OBJ_START){
2670  return internal_error("Ship \"%s\" initially docked with non-ship object", Ships[i].ship_name);
2671  }
2672 
2673  ship = get_ship_from_obj(obj);
2674  if (!ship_docking_valid(i, ship) && !ship_docking_valid(ship, i)){
2675  return internal_error("Docking illegal between \"%s\" and \"%s\" (initially docked)", Ships[i].ship_name, Ships[ship].ship_name);
2676  }
2677 
2678  z = get_docking_list(Ship_info[Ships[i].ship_info_index].model_num);
2679  point = dock_ptr->dockpoint_used;
2680  if (point < 0 || point >= z){
2681  internal_error("Invalid docker point (\"%s\" initially docked with \"%s\")", Ships[i].ship_name, Ships[ship].ship_name);
2682  }
2683 
2684  z = get_docking_list(Ship_info[Ships[ship].ship_info_index].model_num);
2685  point = dock_find_dockpoint_used_by_object(dock_ptr->docked_objp, &Objects[Ships[i].objnum]);
2686  if (point < 0 || point >= z){
2687  internal_error("Invalid dockee point (\"%s\" initially docked with \"%s\")", Ships[i].ship_name, Ships[ship].ship_name);
2688  }
2689  }
2690 
2691  wing = Ships[i].wingnum;
2692  bool is_in_loadout_screen = (ptr->type == OBJ_START);
2693  if (!is_in_loadout_screen && wing >= 0) {
2695  {
2696  for (n = 0; n < MAX_TVT_WINGS; n++) {
2697  if (!strcmp(Wings[wing].name, TVT_wing_names[n])) {
2698  is_in_loadout_screen = true;
2699  break;
2700  }
2701  }
2702  } else {
2703  for (n = 0; n < MAX_STARTING_WINGS; n++) {
2704  if (!strcmp(Wings[wing].name, Starting_wing_names[n])) {
2705  is_in_loadout_screen = true;
2706  break;
2707  }
2708  }
2709  }
2710  }
2711  if (is_in_loadout_screen) {
2712  int illegal = 0;
2713  z = Ships[i].ship_info_index;
2714  for (n = 0; n < MAX_SHIP_PRIMARY_BANKS; n++){
2715  if (Ships[i].weapons.primary_bank_weapons[n] >= 0 && !Ship_info[z].allowed_weapons[Ships[i].weapons.primary_bank_weapons[n]]){
2716  illegal++;
2717  }
2718  }
2719 
2720  for (n = 0; n < MAX_SHIP_SECONDARY_BANKS; n++){
2721  if (Ships[i].weapons.secondary_bank_weapons[n] >= 0 && !Ship_info[z].allowed_weapons[Ships[i].weapons.secondary_bank_weapons[n]]){
2722  illegal++;
2723  }
2724  }
2725 
2726  if (illegal && error("%d illegal weapon(s) found on ship \"%s\"", illegal, Ships[i].ship_name)) {
2727  return 1;
2728  }
2729  }
2730  }
2731  }
2732 
2733  if (count != ship_get_num_ships()){
2734  return internal_error("num_ships is incorrect");
2735  }
2736 
2737  count = 0;
2738  for (i=0; i<MAX_WINGS; i++) {
2739  team = -1;
2740  j = Wings[i].wave_count;
2741  if (j) { // is wing being used?
2742  count++;
2743  if (j < 0 || j > MAX_SHIPS_PER_WING){
2744  return internal_error("Invalid number of ships in wing \"%s\"", Wings[i].name);
2745  }
2746 
2747  while (j--) {
2748  obj = wing_objects[i][j];
2750  return internal_error("Wing_objects has an illegal object index");
2751  }
2752 
2753  if (!query_valid_object(obj)){
2754  return internal_error("Wing_objects references an unused object");
2755  }
2756 
2757 // Now, at this point, we can assume several things. We have a valid object because
2758 // we passed query_valid_object(), and all valid objects were already checked above,
2759 // so this object has valid information, such as the instance.
2760 
2761  if ((Objects[obj].type == OBJ_SHIP) || (Objects[obj].type == OBJ_START)) {
2762  ship = Objects[obj].instance;
2763  wing_bash_ship_name(buf, Wings[i].name, j + 1);
2764  if (stricmp(buf, Ships[ship].ship_name)){
2765  return internal_error("Ship \"%s\" in wing should be called \"%s\"", Ships[ship].ship_name, buf);
2766  }
2767 
2768  int ship_type = ship_query_general_type(ship);
2769  if(ship_type < 0 || !(Ship_types[ship_type].ai_bools & STI_AI_CAN_FORM_WING))
2770  {
2771  if (error("Ship \"%s\" is an illegal type to be in a wing", Ships[ship].ship_name)){
2772  return 1;
2773  }
2774  }
2775  } else {
2776  return internal_error("Wing_objects of \"%s\" references an illegal object type", Wings[i].name);
2777  }
2778 
2779  if (Ships[ship].wingnum != i){
2780  return internal_error("Wing/ship references are corrupt");
2781  }
2782 
2783  if (ship != Wings[i].ship_index[j]){
2784  return internal_error("Ship/wing references are corrupt");
2785  }
2786 
2787  if (team < 0){
2788  team = Ships[ship].team;
2789  } else if (team != Ships[ship].team && team < 999){
2790  if (error("ship teams mixed within same wing (\"%s\")", Wings[i].name)){
2791  return 1;
2792  }
2793  }
2794  }
2795 
2796  if ((Wings[i].special_ship < 0) || (Wings[i].special_ship >= Wings[i].wave_count)){
2797  return internal_error("Special ship out of range for \"%s\"", Wings[i].name);
2798  }
2799 
2800  if (Wings[i].num_waves < 0){
2801  return internal_error("Number of waves for \"%s\" is negative", Wings[i].name);
2802  }
2803 
2804  if ((Wings[i].threshold < 0) || (Wings[i].threshold >= Wings[i].wave_count)){
2805  return internal_error("Threshold for \"%s\" is invalid", Wings[i].name);
2806  }
2807 
2808  if (Wings[i].threshold + Wings[i].wave_count > MAX_SHIPS_PER_WING) {
2809  Wings[i].threshold = MAX_SHIPS_PER_WING - Wings[i].wave_count;
2810  if(error("Threshold for wing \"%s\" is higher than allowed. Reset to %d", Wings[i].name, Wings[i].threshold)){
2811  return 1;
2812  }
2813  }
2814 
2815  for (j=0; j<obj_count; j++){
2816  if (names[j]){
2817  if (!stricmp(names[j], Wings[i].name)){
2818  return internal_error("Wing name is also used by an object (%s)", names[j]);
2819  }
2820  }
2821  }
2822 
2823  if(fred_check_sexp(Wings[i].arrival_cue, OPR_BOOL, "arrival cue of wing \"%s\"", Wings[i].name)){
2824  return -1;
2825  }
2826 
2827  if(fred_check_sexp(Wings[i].departure_cue, OPR_BOOL, "departure cue of wing \"%s\"", Wings[i].name)){
2828  return -1;
2829  }
2830 
2831  if (Wings[i].arrival_location != ARRIVE_AT_LOCATION) {
2832  if (Wings[i].arrival_anchor < 0)
2833  if (error("Wing \"%s\" requires a valid arrival target", Wings[i].name))
2834  return 1;
2835  }
2836 
2837  if (Wings[i].departure_location != DEPART_AT_LOCATION) {
2838  if (Wings[i].departure_anchor < 0)
2839  if (error("Wing \"%s\" requires a valid departure target", Wings[i].name))
2840  return 1;
2841  }
2842 
2843  if ((str = error_check_initial_orders(Wings[i].ai_goals, -1, i))>0) {
2844  if (*str == '*')
2845  return internal_error("Initial orders error for wing \"%s\"\n\n%s", Wings[i].name, str + 1);
2846  else if (*str == '!')
2847  return 1;
2848  else if (error("Initial orders error for wing \"%s\"\n\n%s", Wings[i].name, str))
2849  return 1;
2850  }
2851 
2852  }
2853  }
2854 
2855  if (count != Num_wings){
2856  return internal_error("Num_wings is incorrect");
2857  }
2858 
2860  for (ii = Waypoint_lists.begin(); ii != Waypoint_lists.end(); ++ii) {
2861  for (z=0; z<obj_count; z++){
2862  if (names[z]){
2863  if (!stricmp(names[z], ii->get_name())){
2864  return internal_error("Waypoint path name is also used by an object (%s)", names[z]);
2865  }
2866  }
2867  }
2868 
2869  for (j = 0; (uint) j < ii->get_waypoints().size(); j++) {
2870  sprintf(buf, "%s:%d", ii->get_name(), j + 1);
2871  for (z=0; z<obj_count; z++){
2872  if (names[z]){
2873  if (!stricmp(names[z], buf)){
2874  break;
2875  }
2876  }
2877  }
2878 
2879  if (z == obj_count){
2880  return internal_error("Waypoint \"%s\" not linked to an object", buf);
2881  }
2882  }
2883  }
2884 
2885  if (Player_starts > MAX_PLAYERS){
2886  return internal_error("Number of player starts exceeds max limit");
2887  }
2888 
2889  if (!multi && (Player_starts > 1)){
2890  if (error("Multiple player starts exist, but this is a single player mission")){
2891  return 1;
2892  }
2893  }
2894 
2896  return internal_error("Number of reinforcements exceeds max limit");
2897  }
2898 
2899  for (i=0; i<Num_reinforcements; i++) {
2900  z = 0;
2901  for (ship=0; ship<MAX_SHIPS; ship++){
2902  if ((Ships[ship].objnum >= 0) && !stricmp(Ships[ship].ship_name, Reinforcements[i].name)) {
2903  z = 1;
2904  break;
2905  }
2906  }
2907 
2908  for (wing=0; wing<MAX_WINGS; wing++){
2909  if (Wings[wing].wave_count && !stricmp(Wings[wing].name, Reinforcements[i].name)) {
2910  z = 1;
2911  break;
2912  }
2913  }
2914 
2915  if (!z){
2916  return internal_error("Reinforcement name not found in ships or wings");
2917  }
2918  }
2919 
2920 /* for (i=0; i<num_messages; i++) {
2921  if (Messages[i].num_times < 0)
2922  return internal_error("Number of times to play message is negative");
2923 
2924  z = Messages[i].who_from;
2925  if (z < -1 || z >= MAX_SHIPS) // hacked! -1 should be illegal..
2926  return internal_error("Message originator index is out of range");
2927 
2928  if (Ships[z].objnum == -1)
2929  return internal_error("Message originator points to nonexistant ship");
2930 
2931  if (fred_check_sexp(Messages[i].sexp, OPR_BOOL,
2932  "Message formula from \"%s\"", Ships[Messages[i].who_from].ship_name))
2933  return -1;
2934  }*/
2935 
2936  Assert((Player_start_shipnum >= 0) && (Player_start_shipnum < MAX_SHIPS) && (Ships[Player_start_shipnum].objnum >= 0));
2937  i = global_error_check_player_wings(multi);
2938  if (i){
2939  return i;
2940  }
2941 
2942  for (i=0; i<Num_mission_events; i++){
2943  if (fred_check_sexp(Mission_events[i].formula, OPR_NULL, "mission event \"%s\"", Mission_events[i].name)){
2944  return -1;
2945  }
2946  }
2947 
2948  for (i=0; i<Num_goals; i++){
2949  if (fred_check_sexp(Mission_goals[i].formula, OPR_BOOL, "mission goal \"%s\"", Mission_goals[i].name)){
2950  return -1;
2951  }
2952  }
2953 
2954  for ( bs = 0; bs < Num_teams; bs++ ) {
2955  for (s=0; s<Briefings[bs].num_stages; s++) {
2956  sp = &Briefings[bs].stages[s];
2957  t = sp->num_icons;
2958  for (i=0; i<t-1; i++){
2959  for (j=i+1; j<t; j++) {
2960  if ((sp->icons[i].id > 0) && (sp->icons[i].id == sp->icons[j].id)){
2961  if (error("Duplicate icon IDs %d in briefing stage %d", sp->icons[i].id, s + 1)){
2962  return 1;
2963  }
2964  }
2965  }
2966  }
2967  }
2968  }
2969 
2970  for ( j = 0; j < Num_teams; j++ ) {
2971  for (i=0; i<Debriefings[j].num_stages; i++) {
2972  if (fred_check_sexp(Debriefings[j].stages[i].formula, OPR_BOOL, "debriefing stage %d", i + 1)){
2973  return -1;
2974  }
2975  }
2976  }
2977 
2978  // for all wings, be sure that the orders accepted for all ships are the same for all ships
2979  // in the wing
2980  starting_orders = -1;
2981  for (i=0; i<MAX_WINGS; i++) {
2982  int default_orders, starting_wing;
2983 
2984  if ( !Wings[i].wave_count ){
2985  continue;
2986  }
2987 
2988  // determine if this wing is a starting wing of the player
2989  starting_wing = (ship_starting_wing_lookup(Wings[i].name) != -1);
2990 
2991  // first, be sure this isn't a reinforcement wing.
2992  if ( starting_wing && (Wings[i].flags & WF_REINFORCEMENT) ) {
2993  if ( error("Starting Wing %s marked as reinforcement. This wing\nshould either be renamed, or unmarked as reinforcement.", Wings[i].name) ){
2994 // Goober5000 return 1;
2995  }
2996  }
2997 
2998  default_orders = 0;
2999  for ( j = 0; j < Wings[i].wave_count; j++ ) {
3000  int orders;
3001 
3002  orders = Ships[Wings[i].ship_index[j]].orders_accepted;
3003  if ( j == 0 ) {
3004  default_orders = orders;
3005  } else if ( default_orders != orders ) {
3006  if (error("%s and %s will accept different orders. All ships in a wing must accept the same Player Orders.", Ships[Wings[i].ship_index[j]].ship_name, Ships[Wings[i].ship_index[0]].ship_name ) ){
3007  return 1;
3008  }
3009  }
3010  }
3011 
3012 /* Goober5000 - this is not necessary
3013  // make sure that these ignored orders are the same for all starting wings of the player
3014  if ( starting_wing ) {
3015  if ( starting_orders == -1 ) {
3016  starting_orders = default_orders;
3017  } else {
3018  if ( starting_orders != default_orders ) {
3019  if ( error("Player starting wing %s has orders which don't match other starting wings\n", Wings[i].name) ){
3020 // Goober5000 return 1;
3021  }
3022  }
3023  }
3024  }
3025 */
3026  }
3027 
3028  //This should never ever be a problem -WMC
3029  /*
3030  if (Num_jump_nodes < 0){
3031  return internal_error("Jump node count is illegal");
3032  }*/
3033 
3035 
3036  return g_err;
3037 }
3038 
3040 {
3041  int i, s, species = -1, mixed = 0;
3042 
3043  for (i=0; i<Wings[w].wave_count; i++) {
3044  s = Wings[w].ship_index[i];
3045  if (species < 0)
3046  species = Ship_info[Ships[s].ship_info_index].species;
3047  else if (Ship_info[Ships[s].ship_info_index].species != species)
3048  mixed = 1;
3049  }
3050 
3051  if (mixed)
3052  if (error("%s wing must all be of the same species", Wings[w].name))
3053  return 1;
3054 
3055  return 0;
3056 }
3057 
3058 int CFREDView::global_error_check_player_wings(int multi)
3059 {
3060  int i, z, err;
3061  int starting_wing_count[MAX_STARTING_WINGS];
3062  int tvt_wing_count[MAX_TVT_WINGS];
3063 
3064  object *ptr;
3065  CString starting_wing_list = "";
3066  CString tvt_wing_list = "";
3067 
3068  // check team wings in tvt
3070  {
3071  for (i=0; i<MAX_TVT_WINGS; i++)
3072  {
3073  if (ship_tvt_wing_lookup(TVT_wing_names[i]) == -1)
3074  {
3075  if (error("%s wing is required for multiplayer team vs. team missions"))
3076  return 1;
3077  }
3078  }
3079  }
3080 
3081 // // player's wing must have a true arrival
3082 // free_sexp2(Wings[z].arrival_cue);
3083 // Wings[z].arrival_cue = Locked_sexp_true;
3084 
3085  // Check to be sure that any player wing doesn't have > 1 wave for multiplayer
3086  if ( multi )
3087  {
3089  {
3090  for (i=0; i<MAX_TVT_WINGS; i++)
3091  {
3092  if (TVT_wings[i] >= 0 && Wings[TVT_wings[i]].num_waves > 1)
3093  {
3094  Wings[TVT_wings[i]].num_waves = 1;
3095  if (error("%s wing must contain only 1 wave.\nThis change has been made for you.", TVT_wing_names[i]))
3096  return 1;
3097  }
3098  }
3099  }
3100  else
3101  {
3102  for (i=0; i<MAX_STARTING_WINGS; i++)
3103  {
3104  if (Starting_wings[i] >= 0 && Wings[Starting_wings[i]].num_waves > 1)
3105  {
3107  if (error("%s wing must contain only 1 wave.\nThis change has been made for you.", Starting_wing_names[i]))
3108  return 1;
3109  }
3110  }
3111  }
3112  }
3113 
3114  // check number of ships in player wing
3116  {
3117  for (i=0; i<MAX_TVT_WINGS; i++)
3118  {
3119  if (TVT_wings[i] >= 0 && Wings[TVT_wings[i]].wave_count > 4)
3120  {
3121  if (error("%s wing has too many ships. Should only have 4 max.", TVT_wing_names[i]))
3122  return 1;
3123  }
3124  }
3125  }
3126  else
3127  {
3128  for (i=0; i<MAX_STARTING_WINGS; i++)
3129  {
3130  if (Starting_wings[i] >= 0 && Wings[Starting_wings[i]].wave_count > 4)
3131  {
3132  if (error("%s wing has too many ships. Should only have 4 max.", Starting_wing_names[i]))
3133  return 1;
3134  }
3135  }
3136  }
3137 
3138  // check arrival delay in tvt
3140  {
3141  for (i=0; i<MAX_TVT_WINGS; i++)
3142  {
3143  if (TVT_wings[i] >= 0 && Wings[TVT_wings[i]].arrival_delay > 0)
3144  {
3145  if (error("%s wing shouldn't have a non-zero arrival delay", TVT_wing_names[i]))
3146  return 1;
3147  }
3148  }
3149  }
3150 
3151  // check mixed-species in a wing for multi missions
3152  if (multi)
3153  {
3155  {
3156  for (i=0; i<MAX_TVT_WINGS; i++)
3157  {
3158  if (TVT_wings[i] >= 0)
3159  {
3161  return 1;
3162  }
3163  }
3164  }
3165  else
3166  {
3167  for (i=0; i<MAX_STARTING_WINGS; i++)
3168  {
3169  if (Starting_wings[i] >= 0)
3170  {
3172  return 1;
3173  }
3174  }
3175  }
3176  }
3177 
3178  for (i=0; i<MAX_STARTING_WINGS; i++)
3179  {
3180  starting_wing_count[i] = 0;
3181 
3182  if (i < MAX_STARTING_WINGS - 1)
3183  {
3184  starting_wing_list += Starting_wing_names[i];
3185  if (MAX_STARTING_WINGS > 2)
3186  starting_wing_list += ",";
3187  starting_wing_list += " ";
3188  }
3189  else
3190  {
3191  starting_wing_list += "or ";
3192  starting_wing_list += Starting_wing_names[i];
3193  }
3194  }
3195  for (i=0; i<MAX_TVT_WINGS; i++)
3196  {
3197  tvt_wing_count[i] = 0;
3198 
3199  if (i < MAX_TVT_WINGS - 1)
3200  {
3201  tvt_wing_list += TVT_wing_names[i];
3202  if (MAX_TVT_WINGS > 2)
3203  tvt_wing_list += ",";
3204  tvt_wing_list += " ";
3205  }
3206  else
3207  {
3208  tvt_wing_list += "or ";
3209  tvt_wing_list += TVT_wing_names[i];
3210  }
3211  }
3212 
3213  // check players in wings
3214  ptr = GET_FIRST(&obj_used_list);
3215  while (ptr != END_OF_LIST(&obj_used_list))
3216  {
3217  int ship_instance = ptr->instance;
3218  err = 0;
3219 
3220  // this ship is a player?
3221  if (ptr->type == OBJ_START)
3222  {
3223  // check if this ship is in a wing
3224  z = Ships[ship_instance].wingnum;
3225  if (z < 0)
3226  {
3227  err = 1;
3228  }
3229  else
3230  {
3231  int in_starting_wing = 0;
3232  int in_tvt_wing = 0;
3233 
3234  // check which wing the player is in
3235  for (i=0; i<MAX_STARTING_WINGS; i++)
3236  {
3237  if (Starting_wings[i] == z)
3238  {
3239  in_starting_wing = 1;
3240  starting_wing_count[i]++;
3241  }
3242  }
3243  for (i=0; i<MAX_TVT_WINGS; i++)
3244  {
3245  if (TVT_wings[i] == z)
3246  {
3247  in_tvt_wing = 1;
3248  tvt_wing_count[i]++;
3249  }
3250  }
3251 
3252  // make sure the player belongs to his proper wing
3254  {
3255  if (!in_tvt_wing)
3256  {
3257  err = 1;
3258  }
3259  }
3260  else
3261  {
3262  if (!in_starting_wing)
3263  {
3264  err = 1;
3265  }
3266  }
3267  }
3268 
3269  if (err)
3270  {
3272  {
3273  if (error("Player %s should be part of %s wing", Ships[ship_instance].ship_name, tvt_wing_list))
3274  return 1;
3275  }
3276  else
3277  {
3278  if (error("Player %s should be part of %s wing", Ships[ship_instance].ship_name, starting_wing_list))
3279  return 1;
3280  }
3281  }
3282  }
3283 
3284  ptr = GET_NEXT(ptr);
3285  }
3286 
3287  // check all wings in tvt have players
3289  {
3290  for (i=0; i<MAX_TVT_WINGS; i++)
3291  {
3292  if (!tvt_wing_count[i])
3293  {
3294  if (error("%s wing doesn't contain any players (which it should)", TVT_wing_names[i]))
3295  return 1;
3296  }
3297  }
3298  }
3299 
3300  return 0;
3301 }
3302 
3303 int CFREDView::error(const char *msg, ...)
3304 {
3305  char buf[2048];
3306  va_list args;
3307 
3308  va_start(args, msg);
3309  vsnprintf(buf, sizeof(buf)-1, msg, args);
3310  va_end(args);
3311  buf[sizeof(buf)-1] = '\0';
3312 
3313  g_err = 1;
3314  if (MessageBox(buf, "Error", MB_OKCANCEL | MB_ICONEXCLAMATION) == IDOK)
3315  return 0;
3316 
3317  return 1;
3318 }
3319 
3320 int CFREDView::internal_error(const char *msg, ...)
3321 {
3322  char buf[2048];
3323  va_list args;
3324 
3325  va_start(args, msg);
3326  vsnprintf(buf, sizeof(buf)-1, msg, args);
3327  va_end(args);
3328  buf[sizeof(buf)-1] = '\0';
3329 
3330  g_err = 1;
3331 
3332 #ifndef NDEBUG
3333  char buf2[2048];
3334 
3335  sprintf(buf2, "%s\n\nThis is an internal error. Please let Jason\n"
3336  "know about this so he can fix it. Click cancel to debug.", buf);
3337 
3338  if (MessageBox(buf2, "Internal Error", MB_OKCANCEL | MB_ICONEXCLAMATION) == IDCANCEL)
3339  Int3(); // drop to debugger so the problem can be analyzed.
3340 
3341 #else
3342  MessageBox(buf, "Error", MB_OK | MB_ICONEXCLAMATION);
3343 #endif
3344 
3345  return -1;
3346 }
3347 
3348 int CFREDView::fred_check_sexp(int sexp, int type, const char *msg, ...)
3349 {
3350  SCP_string buf, sexp_buf, error_buf;
3351  int err = 0, z, faulty_node;
3352  va_list args;
3353 
3354  va_start(args, msg);
3355  vsprintf(buf, msg, args);
3356  va_end(args);
3357 
3358  if (sexp == -1)
3359  return 0;
3360 
3361  z = check_sexp_syntax(sexp, type, 1, &faulty_node);
3362  if (!z)
3363  return 0;
3364 
3366  truncate_message_lines(sexp_buf, 30);
3367  sprintf(error_buf, "Error in %s: %s\n\nIn sexpression: %s\n\n(Error appears to be: %s)", buf.c_str(), sexp_error_message(z), sexp_buf.c_str(), Sexp_nodes[faulty_node].text);
3368 
3369  if (z < 0 && z > -100)
3370  err = 1;
3371 
3372  if (err)
3373  return internal_error(error_buf.c_str());
3374 
3375  if (error(error_buf.c_str()))
3376  return 1;
3377 
3378  return 0;
3379 }
3380 
3382 {
3383  int adjust = 0;
3384 
3385  Assert(Waypoint_editor_dialog.GetSafeHwnd());
3386  if (!Show_sexp_help)
3387  adjust = -SEXP_HELP_BOX_SIZE;
3388 
3390  return;
3391 
3392  Waypoint_editor_dialog.SetWindowPos(&wndTop, 0, 0, 0, 0,
3393  SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE);
3394  Waypoint_editor_dialog.ShowWindow(SW_RESTORE);
3395 }
3396 
3398 {
3399  char *source;
3400  int i, j, num, flag, found, inst, team, team2;
3401  object *ptr;
3402 
3403  if (ship >= 0) {
3404  source = Ships[ship].ship_name;
3405  team = Ships[ship].team;
3406  for (i=0; i<MAX_AI_GOALS; i++)
3407  if (!ai_query_goal_valid(ship, goals[i].ai_mode)) {
3408  if (Fred_view_wnd->error("Order \"%s\" isn't allowed for ship \"%s\"", get_order_name(goals[i].ai_mode), source))
3409  return "!";
3410  }
3411 
3412  } else {
3413  Assert(wing >= 0);
3414  Assert(Wings[wing].wave_count > 0);
3415  source = Wings[wing].name;
3416  team = Ships[Objects[wing_objects[wing][0]].instance].team;
3417  for (j=0; j<Wings[wing].wave_count; j++)
3418  for (i=0; i<MAX_AI_GOALS; i++)
3419  if (!ai_query_goal_valid(Wings[wing].ship_index[j], goals[i].ai_mode)) {
3420  if (Fred_view_wnd->error("Order \"%s\" isn't allowed for ship \"%s\"", get_order_name(goals[i].ai_mode),
3421  Ships[Wings[wing].ship_index[j]].ship_name))
3422  return "!";
3423  }
3424  }
3425 
3426  for (i=0; i<MAX_AI_GOALS; i++) {
3427  switch (goals[i].ai_mode) {
3428  case AI_GOAL_NONE:
3429  case AI_GOAL_CHASE_ANY:
3430  case AI_GOAL_UNDOCK:
3432  case AI_GOAL_PLAY_DEAD:
3433  case AI_GOAL_WARP:
3434  flag = 0;
3435  break;
3436 
3437  case AI_GOAL_WAYPOINTS:
3439  flag = 1;
3440  break;
3441 
3442  case AI_GOAL_DOCK:
3443  if (ship < 0)
3444  return "Wings can't dock";
3445  // fall through..
3446 
3448  case AI_GOAL_CHASE:
3449  case AI_GOAL_GUARD:
3450  case AI_GOAL_DISARM_SHIP:
3451  case AI_GOAL_DISABLE_SHIP:
3452  case AI_GOAL_EVADE_SHIP:
3454  case AI_GOAL_IGNORE:
3455  case AI_GOAL_IGNORE_NEW:
3456  flag = 2;
3457  break;
3458 
3459  case AI_GOAL_CHASE_WING:
3460  case AI_GOAL_GUARD_WING:
3461  flag = 3;
3462  break;
3463 
3464  case AI_GOAL_STAY_STILL:
3465  flag = 4;
3466  break;
3467 
3468  default:
3469  return "*Invalid goal type";
3470  }
3471 
3472  found = 0;
3473  if (flag > 0) {
3474  if (*goals[i].target_name == '<')
3475  return "Invalid target";
3476 
3477  if (!stricmp(goals[i].target_name, source))
3478  if (ship >= 0)
3479  return "Target of ship's goal is itself";
3480  else
3481  return "Target of wing's goal is itself";
3482  }
3483 
3484  inst = team2 = -1;
3485  if (flag == 1) { // target waypoint required
3486  if (find_matching_waypoint_list(goals[i].target_name) == NULL)
3487  return "*Invalid target waypoint path name";
3488 
3489  } else if (flag == 2) { // target ship required
3490  ptr = GET_FIRST(&obj_used_list);
3491  while (ptr != END_OF_LIST(&obj_used_list)) {
3492  if (ptr->type == OBJ_SHIP || ptr->type == OBJ_START) {
3493  inst = ptr->instance;
3494  if (!stricmp(goals[i].target_name, Ships[inst].ship_name)) {
3495  found = 1;
3496  break;
3497  }
3498  }
3499 
3500  ptr = GET_NEXT(ptr);
3501  }
3502 
3503  if (!found)
3504  return "*Invalid target ship name";
3505 
3506  if (wing >= 0) { // check if target ship is in wing
3507  if (Ships[inst].wingnum == wing && Objects[Ships[inst].objnum].type != OBJ_START)
3508  return "Target ship of wing's goal is within said wing";
3509  }
3510 
3511  team2 = Ships[inst].team;
3512 
3513  } else if (flag == 3) { // target wing required
3514  for (j=0; j<MAX_WINGS; j++)
3515  if (Wings[j].wave_count && !stricmp(Wings[j].name, goals[i].target_name))
3516  break;
3517 
3518  if (j >= MAX_WINGS)
3519  return "*Invalid target wing name";
3520 
3521  if (ship >= 0) { // check if ship is in target wing
3522  if (Ships[ship].wingnum == j)
3523  return "Target wing of ship's goal is same wing said ship is part of";
3524  }
3525 
3526  team2 = Ships[Objects[wing_objects[j][0]].instance].team;
3527 
3528  } else if (flag == 4) {
3529  ptr = GET_FIRST(&obj_used_list);
3530  while (ptr != END_OF_LIST(&obj_used_list)) {
3531  if (ptr->type == OBJ_SHIP || ptr->type == OBJ_START) {
3532  inst = ptr->instance;
3533  if (!stricmp(goals[i].target_name, Ships[inst].ship_name)) {
3534  found = 2;
3535  break;
3536  }
3537 
3538  } else if (ptr->type == OBJ_WAYPOINT) {
3539  if (!stricmp(goals[i].target_name, object_name(OBJ_INDEX(ptr)))) {
3540  found = 1;
3541  break;
3542  }
3543  }
3544 
3545  ptr = GET_NEXT(ptr);
3546  }
3547 
3548  if (!found)
3549  return "*Invalid target ship or waypoint name";
3550 
3551  if (found == 2) {
3552  if (wing >= 0) { // check if target ship is in wing
3553  if (Ships[inst].wingnum == wing && Objects[Ships[inst].objnum].type != OBJ_START)
3554  return "Target ship of wing's goal is within said wing";
3555  }
3556 
3557  team2 = Ships[inst].team;
3558  }
3559  }
3560 
3561  switch (goals[i].ai_mode) {
3563  Assert(flag == 2 && inst >= 0);
3564  if (ship_get_subsys_index(&Ships[inst], goals[i].docker.name, 1) < 0)
3565  return "Unknown subsystem type";
3566 
3567  break;
3568 
3569  case AI_GOAL_DOCK: {
3570  int dock1 = -1, dock2 = -1, model1, model2;
3571 
3572  Assert(flag == 2 && inst >= 0);
3573  if (!ship_docking_valid(ship, inst))
3574  return "Docking illegal between given ship types";
3575 
3576  model1 = Ship_info[Ships[ship].ship_info_index].model_num;
3577  num = get_docking_list(model1);
3578  for (j=0; j<num; j++) {
3580  if (!stricmp(goals[i].docker.name, Docking_bay_list[j])) {
3581  dock1 = j;
3582  break;
3583  }
3584  }
3585 
3586  model2 = Ship_info[Ships[inst].ship_info_index].model_num;
3587  num = get_docking_list(model2);
3588  for (j=0; j<num; j++) {
3590  if (!stricmp(goals[i].dockee.name, Docking_bay_list[j])) {
3591  dock2 = j;
3592  break;
3593  }
3594  }
3595 
3596  if (dock1 < 0)
3597  return "Invalid docker point";
3598 
3599  if (dock2 < 0)
3600  return "Invalid dockee point";
3601 
3602  if ((dock1 >= 0) && (dock2 >= 0)) {
3603  if ( !(model_get_dock_index_type(model1, dock1) & model_get_dock_index_type(model2, dock2)) )
3604  return "Dock points are incompatible";
3605  }
3606 
3607  break;
3608  }
3609  }
3610 
3611  switch (goals[i].ai_mode) {
3612  case AI_GOAL_GUARD:
3613  case AI_GOAL_GUARD_WING:
3614  if (team != team2) { // MK, added support for TEAM_NEUTRAL. Won't this work?
3615  if (ship >= 0)
3616  return "Ship assigned to guard a different team";
3617  else
3618  return "Wing assigned to guard a different team";
3619  }
3620 
3621  break;
3622 
3623  case AI_GOAL_CHASE:
3624  case AI_GOAL_CHASE_WING:
3626  case AI_GOAL_DISARM_SHIP:
3627  case AI_GOAL_DISABLE_SHIP:
3628  if (team == team2) {
3629  if (ship >= 0)
3630  return "Ship assigned to attack same team";
3631  else
3632  return "Wings assigned to attack same team";
3633  }
3634 
3635  break;
3636  }
3637  }
3638 
3639  return NULL;
3640 }
3641 
3642 // function (which is called externally from message editor and event editor) so skip through
3643 // the sexpression nodes to look for send-message commands to try to associate message personas
3644 // to ships
3646 {
3647 /*
3648  int i, op, j, ship_index;
3649  char *mname, *who_from;
3650  object *objp;
3651 
3652  // this function is responsible for assigning personas to ships as well as error checking them.
3653  // clear out the persona index on all ship objects
3654  for ( objp = GET_FIRST(&obj_used_list); objp != END_OF_LIST(&obj_used_list); objp = GET_NEXT(objp) ) {
3655  if ( objp->type == OBJ_SHIP ) {
3656  Ships[objp->instance].persona_index = -1;
3657  }
3658  }
3659 
3660 
3661  for (i = 0; i < Num_sexp_nodes; i++ ) {
3662  if ( Sexp_nodes[i].type == SEXP_NOT_USED )
3663  continue;
3664 
3665  // look for only operator nodes
3666  if ( Sexp_nodes[i].subtype != SEXP_ATOM_OPERATOR )
3667  continue;
3668 
3669  // now look for the send-message opeator
3670  op = get_operator_const( Sexp_nodes[i].text );
3671  if ( op != OP_SEND_MESSAGE )
3672  continue;
3673 
3674  // have the message. parse through the message to determine who is sending the message.
3675  who_from = CTEXT(CDR(i));
3676 
3677  // we can ignore messages from any wingman, and allied, or from God.
3678  if ( !stricmp(who_from, "<Any wingman>") || !stricmp(who_from, "<Any allied>") || (who_from[0] == '#') )
3679  continue;
3680 
3681  mname = CTEXT(CDR(CDR(CDR(i))));
3682 
3683  // check to see if who_from is a wing. Don't do processing if so.
3684  if ( wing_name_lookup(who_from, 1) != -1 )
3685  continue;
3686 
3687  ship_index = ship_name_lookup( who_from );
3688  if ( ship_index == -1 ) {
3689  Int3(); // get allender. something funny is up with shipnames in send-message
3690  continue;
3691  }
3692 
3693  for ( j = Num_builtin_messages; j < Num_messages; j++ ) {
3694  if ( !stricmp(mname, Messages[j].name) ) {
3695 
3696  // check to see if there is a persona for this message -- if not, bail
3697  if ( Messages[j].persona_index == -1 )
3698  break;
3699 
3700  // if a ship isn't assigned a persona, and this message says that he is, assign it, and move on
3701  if ( Ships[ship_index].persona_index == -1 ) {
3702  Ships[ship_index].persona_index = Messages[j].persona_index;
3703  continue;
3704  }
3705 
3706  // we must be sure of the following conditions:
3707  // 1) a ship isn't assigned > 1 persona
3708 
3709  if ( Ships[ship_index].persona_index != Messages[j].persona_index )
3710  Fred_view_wnd->error("Ship %s has at least two personas attached to it:\n%s and %s", Ships[ship_index].ship_name, Personas[Ships[ship_index].persona_index].name, Personas[Messages[j].persona_index].name );
3711  }
3712  }
3713  }
3714 
3715  // check that two or more ships are not using the same persona
3716  for (i = 0; i < Num_personas; i++ ) {
3717  int persona_count;
3718  object *objp;
3719 
3720  // move through object list looking for number of shis using this persona
3721  persona_count = 0;
3722  for ( objp = GET_FIRST(&obj_used_list); objp != END_OF_LIST(&obj_used_list); objp = GET_NEXT(objp) ) {
3723  if ( objp->type != OBJ_SHIP )
3724  continue;
3725  if (Ships[objp->instance].persona_index == i )
3726  persona_count++;
3727  }
3728 
3729  if ( persona_count > 1 )
3730  Fred_view_wnd->error("Persona %s used by more than 1 ship", Personas[Messages[j].persona_index].name );
3731  }
3732 */
3733 
3734 }
3735 
3737 {
3740  Update_window = 1;
3741 }
3742 
3743 void CFREDView::OnUpdateViewOutlines(CCmdUI* pCmdUI)
3744 {
3745  pCmdUI->SetCheck(Show_outlines);
3746 }
3747 
3748 void CFREDView::OnUpdateNewShipType(CCmdUI* pCmdUI)
3749 {
3750  int z;
3751  CWnd *bar;
3752 
3754  if (z == CB_ERR)
3756  else
3757  cur_model_index = z;
3758 
3759  bar = GetDlgItem(pCmdUI->m_nID);
3760  if (!bar) {
3761  pCmdUI -> ContinueRouting();
3762  return; // not for us
3763  }
3764 
3765  pCmdUI -> SetCheck((bar->GetStyle() & WS_VISIBLE) != 0);
3766 }
3767 
3769 {
3772  Update_window = 1;
3773 }
3774 
3776 {
3777  pCmdUI->SetCheck(Show_stars);
3778 }
3779 
3781 {
3782  asteroid_editor dlg;
3783 
3784  dlg.DoModal();
3785 }
3786 
3788 {
3789  BOOL r;
3790  STARTUPINFO si;
3791  PROCESS_INFORMATION pi;
3792  char *lpMsgBuf;
3793 
3794  if (!FREDDoc_ptr->SaveModified())
3795  return;
3796 
3797  si.cb = sizeof(si);
3798  si.lpReserved = NULL;
3799  si.lpDesktop = NULL;
3800  si.lpTitle = NULL;
3801  si.dwFlags = 0;
3802  si.cbReserved2 = 0;
3803  si.lpReserved2 = NULL;
3804 
3805  // get the filename of the app and replace FRED2_Open with FS2_Open
3806  std::string processed_name(AfxGetApp()->m_pszExeName);
3807  std::string::size_type fred_index = processed_name.find("fred2_open", 0);
3808  // capitalisation!
3809  if (fred_index == std::string::npos) {
3810  fred_index = processed_name.find("Fred2_Open", 0);
3811  }
3812 
3813  if (fred_index != std::string::npos) {
3814  // delete the fred2_open and add FS2_Open in its place
3815  processed_name.erase(fred_index, 10);
3816  processed_name.insert(fred_index, "FS2_Open");
3817  processed_name.append(".exe");
3818 
3819  //try to start FS2_open
3820  r = CreateProcess(processed_name.c_str(), NULL, NULL, NULL, FALSE, 0, NULL, "./", &si, &pi);
3821  if (r) {
3822  return;
3823  }
3824  }
3825 
3826  r = CreateProcess("start_fs2.bat", NULL, NULL, NULL, FALSE, 0, NULL, "./", &si, &pi);
3827 
3828  if (!r) {
3829  r = CreateProcess("fs2_open.exe", NULL, NULL, NULL, FALSE, 0, NULL, "./", &si, &pi);
3830  }
3831 
3832  if (!r) {
3833  r = CreateProcess("fs2_open_r.exe", NULL, NULL, NULL, FALSE, 0, NULL, "./", &si, &pi);
3834  }
3835 
3836  if (!r) {
3837  FormatMessage(
3838  FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
3839  NULL,
3840  GetLastError(),
3841  MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
3842  (LPTSTR) &lpMsgBuf,
3843  0,
3844  NULL
3845  );
3846 
3847  // Display the string.
3848  MessageBox(lpMsgBuf);
3849 
3850  // Free the buffer.
3851  LocalFree( lpMsgBuf );
3852  }
3853 }
3854 
3856 {
3857  if (!FREDDoc_ptr->SaveModified())
3858  return;
3859 
3860  Assert(!Campaign_wnd);
3862  if (Campaign_wnd->Create(NULL, "Campaign Editor", WS_OVERLAPPEDWINDOW | WS_MAXIMIZE,
3863  CFrameWnd::rectDefault, NULL, "IDR_MENU_CAMPAIGN")) {
3864  Campaign_wnd->ShowWindow(SW_SHOW);
3865  Campaign_wnd->UpdateWindow();
3866  }
3867 }
3868 
3870 {
3871  Show_ships = !Show_ships;
3872  correct_marking();
3873  Update_window = 1;
3874 }
3875 
3876 void CFREDView::OnUpdateShowShips(CCmdUI* pCmdUI)
3877 {
3878  pCmdUI->SetCheck(Show_ships);
3879 }
3880 
3882 {
3884  correct_marking();
3885  Update_window = 1;
3886 }
3887 
3888 void CFREDView::OnUpdateShowStarts(CCmdUI* pCmdUI)
3889 {
3890  pCmdUI->SetCheck(Show_starts);
3891 }
3892 
3894 {
3895  Show_iff[iff] = !Show_iff[iff];
3896  correct_marking();
3897  Update_window = 1;
3898 }
3899 
3900 void CFREDView::OnUpdateShowIFF(int iff, CCmdUI* pCmdUI)
3901 {
3902  pCmdUI->SetCheck(Show_iff[iff]);
3903 }
3904 
3906 {
3907  if (viewpoint || !query_valid_object())
3908  viewpoint = 0;
3909 
3910  else {
3911  viewpoint = 1;
3913  }
3914 
3915  Update_window = 1;
3916 }
3917 
3919 {
3920  if (!FREDDoc_ptr->SaveModified())
3921  return;
3922 
3924  FREDDoc_ptr->OnOpenDocument(NULL);
3925 }
3926 
3927 void CFREDView::OnUpdateRevert(CCmdUI* pCmdUI)
3928 {
3929  pCmdUI->Enable(*Mission_filename);
3930 }
3931 
3933 {
3934  if ((Cursor_over >= 0) || Selection_lock) {
3935  if (Editing_mode == 1) {
3936  SetCursor(h_cursor_move);
3937  return TRUE;
3938 
3939  } else if (Editing_mode == 2) {
3940  SetCursor(h_cursor_rotate);
3941  return TRUE;
3942  }
3943  }
3944 
3945  return CView::OnSetCursor(pWnd, nHitTest, message);
3946 }
3947 
3949 {
3950  object *ptr;
3951 
3952  ptr = GET_FIRST(&obj_used_list);
3953  while (ptr != END_OF_LIST(&obj_used_list)) {
3954  if (ptr->flags & OF_MARKED) {
3955  ptr->flags |= OF_HIDDEN;
3956  unmark_object(OBJ_INDEX(ptr));
3957  }
3958 
3959  ptr = GET_NEXT(ptr);
3960  }
3961 }
3962 
3964 {
3965  object *ptr;
3966 
3967  ptr = GET_FIRST(&obj_used_list);
3968  while (ptr != END_OF_LIST(&obj_used_list)) {
3969  ptr->flags &= ~OF_HIDDEN;
3970  ptr = GET_NEXT(ptr);
3971  }
3972 
3973  Update_window = 1;
3974 }
3975 
3977 {
3978  vec3d viewer_pos;
3979  matrix viewer_orient;
3980 
3981  if (Undo_available) {
3982  viewer_pos = view_pos;
3983  viewer_orient = view_orient;
3984  FREDDoc_ptr->autoload();
3985  view_pos = viewer_pos;
3986  view_orient = viewer_orient;
3987  }
3988 }
3989 
3990 void CFREDView::OnUpdateEditUndo(CCmdUI* pCmdUI)
3991 {
3992  pCmdUI->Enable(Undo_available);
3993 }
3994 
3996 {
3997  if (!Briefing_dialog) {
4000  }
4001 
4002  Briefing_dialog->SetWindowPos(&wndTop, 0, 0, 0, 0,
4003  SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE);
4004  Briefing_dialog->ShowWindow(SW_RESTORE);
4005 }
4006 
4008 {
4010 
4011  dlg.DoModal();
4012 }
4013 
4015 {
4016  saved_cam_pos = view_pos;
4017  saved_cam_orient = view_orient;
4018 }
4019 
4021 {
4024  Update_window = 1;
4025 }
4026 
4028 {
4029  pCmdUI->Enable(!IS_VEC_NULL(&saved_cam_orient.vec.fvec));
4030 }
4031 
4033 {
4034  CRect rect;
4035 
4039 
4040  if (Event_editor_dlg) {
4041  Event_editor_dlg->GetWindowRect(rect);
4042  if (Show_sexp_help)
4043  rect.bottom += SEXP_HELP_BOX_SIZE;
4044  else
4045  rect.bottom -= SEXP_HELP_BOX_SIZE;
4046 
4047  Event_editor_dlg->MoveWindow(rect);
4048  }
4049 }
4050 
4051 void CFREDView::OnUpdateShowSexpHelp(CCmdUI* pCmdUI)
4052 {
4053  pCmdUI->SetCheck(Show_sexp_help);
4054 }
4055 
4057 {
4059  if (Lookat_mode && query_valid_object()) {
4060  vec3d v, loc;
4061  matrix m;
4062 
4063  loc = Objects[cur_object_index].pos;
4064  vm_vec_sub(&v, &loc, &view_pos);
4065 
4066  if (v.xyz.x || v.xyz.y || v.xyz.z) {
4067  vm_vector_2_matrix(&m, &v, NULL, NULL);
4068  view_orient = m;
4069  }
4070  }
4071 }
4072 
4073 void CFREDView::OnUpdateLookatObj(CCmdUI* pCmdUI)
4074 {
4075  pCmdUI->SetCheck(Lookat_mode);
4076 }
4077 
4079 {
4080  int n = 1 << (nID - ID_GROUP1);
4081  object *objp;
4082 
4083  unmark_all();
4084  objp = GET_FIRST(&obj_used_list);
4085  while (objp != END_OF_LIST(&obj_used_list)) {
4086  if (objp->type == OBJ_SHIP) {
4087  if (Ships[objp->instance].group & n)
4088  mark_object(OBJ_INDEX(objp));
4089  }
4090 
4091  objp = GET_NEXT(objp);
4092  }
4093 
4094  Update_window = 1;
4095 }
4096 
4098 {
4099  int i, err = 0, n = 1 << (nID - ID_SET_GROUP1);
4100  object *objp;
4101 
4102  for (i=0; i<MAX_SHIPS; i++)
4103  Ships[i].group &= ~n;
4104 
4105  objp = GET_FIRST(&obj_used_list);
4106  while (objp != END_OF_LIST(&obj_used_list)) {
4107  if (objp->flags & OF_MARKED) {
4108  if (objp->type == OBJ_SHIP) {
4109  Ships[objp->instance].group |= n;
4110 
4111  } else
4112  err = 1;
4113  }
4114 
4115  objp = GET_NEXT(objp);
4116  }
4117 
4118  if (err)
4119  Fred_main_wnd->MessageBox("Only ships can be in groups, and not players or waypoints, etc.\n"
4120  "These illegal objects you marked were not placed in the group");
4121 
4122  Update_window = 1;
4123 }
4124 
4126 {
4127  char *ptr, text[512];
4128 
4129  CView::OnInitialUpdate();
4130 
4131  // check the time/checksum strings.
4132  expire_game = 0;
4133  ptr = &stamp[0];
4134  if ( memcmp(ptr, DEFAULT_CHECKSUM_STRING, strlen(DEFAULT_CHECKSUM_STRING)) ) {
4135  int stamped_checksum, checksum;
4136 
4137  // the checksum is not the default checksum. Calculate the checksum of the string
4138  // and compare it.
4139  memcpy(&stamped_checksum, ptr, sizeof(stamped_checksum) );
4140  ptr = &stamp[0];
4141  ptr += 8; // get us to the actual string to calculate the checksum
4143 
4144  if ( checksum != stamped_checksum ){
4146  }
4147 
4148  // now check the time
4149  ptr = &stamp[0];
4150  ptr += 4;
4151  if ( memcmp( ptr, DEFAULT_TIME_STRING, strlen(DEFAULT_TIME_STRING)) ) {
4152  int expire_time, current_time;
4153 
4154  // not the default time -- check against the current time
4155  memcpy( &expire_time, ptr, sizeof(expire_time) );
4156  time( (time_t*)&current_time );
4157  if ( current_time > expire_time )
4159  }
4160 
4161  // since the default checksum has changed -- put up a message which shows who the program
4162  // is stamped for
4163  ptr = &stamp[0];
4164  ptr += 8;
4165  sprintf(text, "This version of Fred has been compiled for %s", ptr);
4166  MessageBox(text, NULL, MB_OK);
4167 
4168  if ( expire_game )
4169  SetTimer(1, FRED_EXPIRE_TIME, expire_game_proc);
4170  }
4171 }
4172 
4174 {
4175  adjust_grid_dlg dlg;
4176 
4177  dlg.DoModal();
4178  Update_window = 1;
4179 }
4180 
4182 {
4183  shield_sys_dlg dlg;
4184 
4185  dlg.DoModal();
4186 }
4187 
4189 {
4190  level_controlled();
4191  Update_window = 1;
4192 }
4193 
4195 {
4197  Update_window = 1;
4198 }
4199 
4201 {
4202  Control_mode = (Control_mode + 1) % 2;
4203 }
4204 
4206 {
4207  object *ptr;
4208 
4209  if (Bg_bitmap_dialog) {
4210  if (Cur_bitmap == -1)
4211  {
4212  if (stars_get_num_bitmaps())
4213  {
4214  Cur_bitmap = 0;
4215  Bg_bitmap_dialog -> update_data();
4216  }
4217 
4218  return;
4219  }
4220 
4221  Cur_bitmap++;
4223  Cur_bitmap = 0;
4224 
4225  Bg_bitmap_dialog -> update_data();
4226  return;
4227  }
4228 
4229  if (EMPTY(&obj_used_list))
4230  return;
4231 
4232  if (query_valid_object()) {
4233  ptr = Objects[cur_object_index].next;
4234  if (ptr == END_OF_LIST(&obj_used_list))
4235  ptr = GET_NEXT(ptr);
4236 
4237  } else
4238  ptr = GET_FIRST(&obj_used_list);
4239 
4240  if (Marked > 1) { // cycle through marked list
4241  while (!(ptr->flags & OF_MARKED))
4242  {
4243  ptr = GET_NEXT(ptr);
4244  if (ptr == END_OF_LIST(&obj_used_list))
4245  ptr = GET_NEXT(ptr);
4246  }
4247 
4249 
4250  } else {
4251  if (Marked)
4253 
4254  mark_object(OBJ_INDEX(ptr));
4255  }
4256 }
4257 
4259 {
4260  int arr[MAX_OBJECTS], i = 0, n = 0;
4261  object *ptr;
4262 
4263  if (Bg_bitmap_dialog) {
4264  if (Cur_bitmap == -1)
4265  {
4266  if (stars_get_num_bitmaps())
4267  {
4269  Bg_bitmap_dialog -> update_data();
4270  }
4271 
4272  return;
4273  }
4274 
4275  Cur_bitmap--;
4276  if (Cur_bitmap < 0)
4278 
4279  Bg_bitmap_dialog -> update_data();
4280  return;
4281  }
4282 
4283  if (EMPTY(&obj_used_list))
4284  return;
4285 
4286  ptr = GET_FIRST(&obj_used_list);
4287  while (ptr != END_OF_LIST(&obj_used_list)) {
4288  if (cur_object_index == OBJ_INDEX(ptr))
4289  i = n;
4290 
4291  arr[n++] = OBJ_INDEX(ptr);
4292  ptr = GET_NEXT(ptr);
4293  }
4294 
4295  Assert(n);
4296  if (query_valid_object()) {
4297  i--;
4298  if (i < 0)
4299  i = n - 1;
4300 
4301  } else
4302  i = n - 1;
4303 
4304  if (Marked > 1) { // cycle through marked list
4305  while (!(Objects[i].flags & OF_MARKED))
4306  {
4307  i--;
4308  if (i < 0)
4309  i = n - 1;
4310  }
4311 
4313 
4314  } else {
4315  if (Marked)
4317 
4318  mark_object(i);
4319  }
4320 }
4321 
4323 {
4324  if (!button_down && Marked) {
4325  delete_marked();
4326  FREDDoc_ptr->autosave("object delete");
4327  }
4328 
4329  Update_window = 2; // For some strange reason, need to redraw twice for it to take.
4330 }
4331 
4333 {
4334  if (!button_down && (cur_wing >= 0)) {
4335  delete_wing();
4336  FREDDoc_ptr->autosave("wing delete");
4337  cur_wing = -1;
4338  if (!Marked)
4340 
4342  }
4343 
4344  Update_window = 2; // For some strange reason, need to redraw twice for it to take.
4345 }
4346 
4348 {
4349  int i, wing = cur_wing;
4350 
4351  if (wing != -1)
4352  {
4353  unmark_all();
4354  for (i=0; i<Wings[wing].wave_count; i++)
4355  mark_object(wing_objects[wing][i]);
4356 
4357  Assert(Wings[wing].special_ship >= 0 && Wings[wing].special_ship < Wings[wing].wave_count);
4358  set_cur_object_index(wing_objects[wing][Wings[wing].special_ship]);
4359  }
4360 }
4361 
4362 void CFREDView::OnUpdateControlObj(CCmdUI* pCmdUI)
4363 {
4364  pCmdUI->SetCheck(Control_mode != 0);
4365 }
4366 
4368 {
4370 }
4371 
4373 {
4374  pCmdUI->SetCheck(Aa_gridlines);
4375  Update_window = 1;
4376 }
4377 
4379 {
4380  cmd_brief_dlg dlg;
4381 
4382  dlg.DoModal();
4383  Update_window = 1;
4384 }
4385 
4387 {
4389 }
4390 
4391 void CFREDView::OnUpdateDisableUndo(CCmdUI* pCmdUI)
4392 {
4393  pCmdUI->SetCheck(Autosave_disabled);
4394 }
4395 
4396 void CFREDView::OnUpdateCmdBrief(CCmdUI* pCmdUI)
4397 {
4398  pCmdUI->Enable(!(The_mission.game_type & MISSION_TYPE_MULTI));
4399 }
4400 
4402 {
4403  int count = 0;
4404  ship_subsys *cur_subsys;
4405 
4406  for (cur_subsys = GET_FIRST(&shipp->subsys_list); cur_subsys != END_OF_LIST(&shipp->subsys_list); cur_subsys = GET_NEXT(cur_subsys)) {
4407  if (cur_subsys->system_info->subobj_num != -1) {
4408  count++;
4409  }
4410  }
4411 
4412  return count;
4413 }
4414 
4416 {
4417  int count = get_visible_sub_system_count(shipp);
4418 
4419  // return don't try to display
4420  if (count == 0) {
4421  return 0;
4422  }
4423 
4424  // first timer
4425  if (*next_subsys == NULL) {
4426  *next_subsys = &shipp->subsys_list;
4427  }
4428 
4429  // look before wrap
4430  for (*next_subsys = GET_NEXT(*next_subsys); *next_subsys != END_OF_LIST(&shipp->subsys_list); *next_subsys = GET_NEXT(*next_subsys)) {
4431  if ((*next_subsys)->system_info->subobj_num != -1) {
4432  Update_window = 1;
4433  return 1;
4434  }
4435  }
4436 
4437  // look for first after wrap
4438  for (*next_subsys = GET_FIRST(&shipp->subsys_list); *next_subsys != END_OF_LIST(&shipp->subsys_list); *next_subsys = GET_NEXT(*next_subsys)) {
4439  if ((*next_subsys)->system_info->subobj_num != -1) {
4440  Update_window = 1;
4441  return 1;
4442  }
4443  }
4444 
4445  Int3(); // should be impossible to miss
4446  return 0;
4447 }
4448 
4450 {
4451  int count = get_visible_sub_system_count(shipp);
4452 
4453  // return don't try to display
4454  if (count == 0) {
4455  return 0;
4456  }
4457 
4458  // first timer
4459  Assert(*prev_subsys != NULL);
4460 
4461  // look before wrap
4462  for (*prev_subsys = GET_PREV(*prev_subsys); *prev_subsys != END_OF_LIST(&shipp->subsys_list); *prev_subsys = GET_PREV(*prev_subsys)) {
4463  if ((*prev_subsys)->system_info->subobj_num != -1) {
4464  Update_window = 1;
4465  return 1;
4466  }
4467  }
4468 
4469  // look for first after wrap
4470  for (*prev_subsys = GET_LAST(&shipp->subsys_list); *prev_subsys != END_OF_LIST(&shipp->subsys_list); *prev_subsys = GET_PREV(*prev_subsys)) {
4471  if ((*prev_subsys)->system_info->subobj_num != -1) {
4472  Update_window = 1;
4473  return 1;
4474  }
4475  }
4476 
4477  Int3(); // should be impossible to miss
4478  return 0;
4479 }
4480 
4481 // update next subsystem to view
4483 {
4484  object *objp;
4485 
4486  if (cur_object_index < 0) {
4487  OnCancelSubsys();
4488  }
4489 
4490  objp = &Objects[cur_object_index];
4491 
4492  // check if cur object is ship type
4493  if (objp->type == OBJ_SHIP) {
4494 
4495  // check if same ship
4496  if (Render_subsys.ship_obj == objp) {
4497 
4498  // if already on, advance to next
4499  if (Render_subsys.do_render) {
4500  if ( !get_next_visible_subsys(&Ships[objp->instance], &Render_subsys.cur_subsys) ) {
4501  OnCancelSubsys();
4502  }
4503  } else {
4504  Int3();
4505  }
4506  } else {
4507  // clean up
4508  OnCancelSubsys();
4509 
4510  // set up new and advance to first
4511  Render_subsys.do_render = true;
4512  Render_subsys.ship_obj = objp;
4513  if ( !get_next_visible_subsys(&Ships[objp->instance], &Render_subsys.cur_subsys) ) {
4514  OnCancelSubsys();
4515  }
4516  }
4517  } else {
4518  // not ship type
4519  OnCancelSubsys();
4520  }
4521 }
4522 
4524 {
4525  if (!Render_subsys.do_render) {
4526  return;
4527  }
4528 
4529  if ( (cur_object_index < 0) || (Objects[cur_object_index].type != OBJ_SHIP) || (&Objects[cur_object_index] != Render_subsys.ship_obj) ) {
4530  OnCancelSubsys();
4531  return;
4532  }
4533 
4534  if ( !get_prev_visible_subsys(&Ships[Objects[cur_object_index].instance], &Render_subsys.cur_subsys) ) {
4535  OnCancelSubsys();
4536  }
4537 
4538 }
4539 
4541 {
4542  Render_subsys.do_render = false;
4543  Render_subsys.ship_obj = NULL;
4544  Render_subsys.cur_subsys = NULL;
4545  Update_window = 1;
4546 }
4547 
4549 {
4552  Update_window = 1;
4553 }
4554 
4555 void CFREDView::OnUpdateShowPaths(CCmdUI* pCmdUI)
4556 {
4557  pCmdUI->SetCheck(Show_paths_fred);
4558 }
4559 
4561 {
4564  Update_window = 1;
4565 }
4566 
4568 {
4569  pCmdUI->SetCheck(Show_dock_points);
4570 }
4571 
4573 {
4574  DumpStats dlg;
4575 
4576  dlg.DoModal();
4577 }
4578 
4580 {
4582  Format_fs2_retail = 0;
4583  Format_fs1_retail = 0;
4584 
4586  Update_window = 1;
4587 }
4588 
4590 {
4591  pCmdUI->SetCheck(Format_fs2_open == FSO_FORMAT_STANDARD);
4592 }
4593 
4595 {
4597  Format_fs2_retail = 0;
4598  Format_fs1_retail = 0;
4599 
4601  Update_window = 1;
4602 }
4603 
4605 {
4606  pCmdUI->SetCheck(Format_fs2_open == FSO_FORMAT_COMPATIBILITY_MODE);
4607 }
4608 
4610 {
4612  Format_fs2_retail = 1;
4613  Format_fs1_retail = 0;
4614 
4616  Update_window = 1;
4617 }
4618 
4620 {
4621  pCmdUI->SetCheck(Format_fs2_retail);
4622 }
4623 
4625 {
4627  Format_fs2_retail = 0;
4628  Format_fs1_retail = 1;
4629 
4631  Update_window = 1;
4632 }
4633 
4635 {
4636  pCmdUI->SetCheck(Format_fs1_retail);
4637 }
4638 
4640 {
4641  SetGlobalShipFlags dlg;
4642 
4643  dlg.DoModal();
4644 }
4645 
4647 {
4648  VoiceActingManager dlg;
4649 
4650  dlg.DoModal();
4651 }
4652 
4654 {
4655  FictionViewerDlg dlg;
4656 
4657  dlg.DoModal();
4658 }
4659 
4661 {
4663  snd_close();
4664  gr_close();
4665  os_set_window(NULL);
4666 
4667  CView::OnDestroy();
4668 }
4669 
4670 int CFREDView::OnCreate(LPCREATESTRUCT lpCreateStruct)
4671 {
4672  if (CView::OnCreate(lpCreateStruct) == -1)
4673  return -1;
4674 
4675  MoveWindow(0,0,200,300,1);
4676  os_set_window((uint)this->GetSafeHwnd());
4677  if(fred_init() == false)
4678  return -1;
4679 
4680  return 0;
4681 }
4682 
4684 {
4685  return TRUE;
4686 }
4687 
4688 
4690 {
4691 
4693 }
4694 
4695 void CFREDView::OnUpdateViewLighting(CCmdUI* pCmdUI)
4696 {
4697  pCmdUI->SetCheck(Lighting_on);
4698 }
4699 
4701 {
4703 }
4704 
4706 {
4707  pCmdUI->SetCheck(FullDetail);
4708 }
4709 
4711 {
4712  // TODO: Add your specialized code here and/or call the base class
4713  return CView::DestroyWindow();
4714 }
4715 
4717 {
4718  OnShowIFF(0);
4719 }
4720 
4721 void CFREDView::OnUpdateShowIFF0(CCmdUI* pCmdUI)
4722 {
4723  OnUpdateShowIFF(0, pCmdUI);
4724 }
4725 
4727 {
4728  OnShowIFF(1);
4729 }
4730 
4731 void CFREDView::OnUpdateShowIFF1(CCmdUI* pCmdUI)
4732 {
4733  OnUpdateShowIFF(1, pCmdUI);
4734 }
4735 
4737 {
4738  OnShowIFF(2);
4739 }
4740 
4741 void CFREDView::OnUpdateShowIFF2(CCmdUI* pCmdUI)
4742 {
4743  OnUpdateShowIFF(2, pCmdUI);
4744 }
4745 
4747 {
4748  OnShowIFF(3);
4749 }
4750 
4751 void CFREDView::OnUpdateShowIFF3(CCmdUI* pCmdUI)
4752 {
4753  OnUpdateShowIFF(3, pCmdUI);
4754 }
4755 
4757 {
4758  OnShowIFF(4);
4759 }
4760 
4761 void CFREDView::OnUpdateShowIFF4(CCmdUI* pCmdUI)
4762 {
4763  OnUpdateShowIFF(4, pCmdUI);
4764 }
4765 
4767 {
4768  OnShowIFF(5);
4769 }
4770 
4771 void CFREDView::OnUpdateShowIFF5(CCmdUI* pCmdUI)
4772 {
4773  OnUpdateShowIFF(5, pCmdUI);
4774 }
4775 
4777 {
4778  OnShowIFF(6);
4779 }
4780 
4781 void CFREDView::OnUpdateShowIFF6(CCmdUI* pCmdUI)
4782 {
4783  OnUpdateShowIFF(6, pCmdUI);
4784 }
4785 
4787 {
4788  OnShowIFF(7);
4789 }
4790 
4791 void CFREDView::OnUpdateShowIFF7(CCmdUI* pCmdUI)
4792 {
4793  OnUpdateShowIFF(7, pCmdUI);
4794 }
4795 
4797 {
4798  OnShowIFF(8);
4799 }
4800 
4801 void CFREDView::OnUpdateShowIFF8(CCmdUI* pCmdUI)
4802 {
4803  OnUpdateShowIFF(8, pCmdUI);
4804 }
4805 
4807 {
4808  OnShowIFF(9);
4809 }
4810 
4811 void CFREDView::OnUpdateShowIFF9(CCmdUI* pCmdUI)
4812 {
4813  OnUpdateShowIFF(9, pCmdUI);
4814 }
afx_msg void OnZoomExtents()
Definition: fredview.cpp:2173
SCP_string sexp
Definition: sexp.cpp:25556
void key_mark(uint code, int state, uint latency)
Definition: key.cpp:697
afx_msg void OnUpdateFlyingControls(CCmdUI *pCmdUI)
Definition: fredview.cpp:2042
afx_msg void OnUpdateUniversalHeading(CCmdUI *pCmdUI)
Definition: fredview.cpp:2032
afx_msg void OnUpdateShowSexpHelp(CCmdUI *pCmdUI)
Definition: fredview.cpp:4051
#define MB_OKCANCEL
Definition: config.h:180
afx_msg void OnUpdateViewWaypoints(CCmdUI *pCmdUI)
Definition: fredview.cpp:500
afx_msg void OnEditorsPlayer()
Definition: fredview.cpp:2331
int drag_objects()
Definition: fredview.cpp:511
int query_single_wing_marked()
Definition: fredview.cpp:2259
afx_msg void OnSpeed2()
Definition: fredview.cpp:1689
char Starting_wing_names[MAX_STARTING_WINGS][NAME_LENGTH]
Definition: ship.cpp:139
void select_objects()
Definition: fredview.cpp:1265
afx_msg void OnSelectList()
Definition: fredview.cpp:2057
#define ID_EDITORS_ADJUST_GRID
Definition: resource.h:1409
void gr_close()
Definition: 2d.cpp:637
#define ID_ROT1
Definition: resource.h:1294
wing Wings[MAX_WINGS]
Definition: ship.cpp:128
#define ID_DISABLE_UNDO
Definition: resource.h:1432
struct screen3d::@234::@236 xyw
int Show_distances
Definition: fredrender.cpp:86
afx_msg void OnEditorsDebriefing()
Definition: fredview.cpp:4007
void wing_bash_ship_name(char *ship_name, const char *wing_name, int index)
Definition: ship.cpp:12686
void * HWND
Definition: config.h:104
int fred_check_sexp(int sexp, int type, const char *msg,...)
Definition: fredview.cpp:3348
#define ID_EDIT_POPUP_SHOW_SHIP_MODELS
Definition: resource.h:1227
virtual void OnBeginPrinting(CDC *pDC, CPrintInfo *pInfo)
Definition: fredview.cpp:449
int i
Definition: multi_pxo.cpp:466
CFREDApp theApp
Definition: fred.cpp:115
afx_msg void OnDisableUndo()
Definition: fredview.cpp:4386
#define AI_GOAL_UNDOCK
Definition: aigoals.h:36
afx_msg void OnEditorsVoiceManager()
Definition: fredview.cpp:4646
color_combo_box m_new_ship_type_combo_box
Definition: mainfrm.cpp:90
float p
Definition: pstypes.h:111
afx_msg void OnShowDistances()
Definition: fredview.cpp:2015
model_subsystem * system_info
Definition: ship.h:314
int Aa_gridlines
Definition: fredrender.cpp:74
int primary_bank_weapons[MAX_SHIP_PRIMARY_BANKS]
Definition: ship.h:103
int Id_select_type_waypoint
Definition: fredview.cpp:112
afx_msg void OnDestroy()
Definition: fredview.cpp:4660
afx_msg void OnShowIFF2()
Definition: fredview.cpp:4736
afx_msg void OnUpdateFormatFs2Open(CCmdUI *pCmdUI)
Definition: fredview.cpp:4589
afx_msg void OnUpdateFormatFs2OpenComp(CCmdUI *pCmdUI)
Definition: fredview.cpp:4604
afx_msg void OnShowStarts()
Definition: fredview.cpp:3881
#define MAX_SHIP_PRIMARY_BANKS
Definition: globals.h:62
void correct_marking()
#define ID_EDIT_DELETE
Definition: resource.h:1198
afx_msg void OnEditorsReinforcement()
Definition: fredview.cpp:2405
vec3d saved_cam_pos
Definition: fredview.cpp:114
int team
Definition: ship.h:606
int last_mouse_y
Definition: fredview.cpp:108
afx_msg void OnUpdateChangeViewpointFollow(CCmdUI *pCmdUI)
Definition: fredview.cpp:1664
int Show_coordinates
Definition: fredrender.cpp:85
GLbitfield stages
Definition: Glext.h:7177
#define DEPART_AT_LOCATION
Definition: missionparse.h:245
CMessageEditorDlg * Message_editor_dlg
int Num_mission_events
int Show_outlines
Definition: fredrender.cpp:82
#define MB_YESNO
Definition: config.h:182
matrix * vm_matrix_x_matrix(matrix *dest, const matrix *src0, const matrix *src1)
Definition: vecmat.cpp:1006
char * get_name()
Definition: waypoint.cpp:84
#define ID_SPEED10
Definition: resource.h:1292
afx_msg void OnUpdateShowHorizon(CCmdUI *pCmdUI)
Definition: fredview.cpp:2310
afx_msg void OnEditorCampaign()
Definition: fredview.cpp:3855
afx_msg void OnEditorsShips()
Definition: fredview.cpp:1136
int objnum
Definition: ship.h:537
#define SIF_PLAYER_SHIP
Definition: ship.h:875
void vm_vec_scale_add(vec3d *dest, const vec3d *src1, const vec3d *src2, float k)
Definition: vecmat.cpp:266
int game_type
Definition: missionparse.h:138
afx_msg void OnRot3()
Definition: fredview.cpp:1743
#define DEFAULT_CHECKSUM_STRING
Definition: pstypes.h:497
int Player_start_shipnum
afx_msg void OnUpdateRestoreCamera(CCmdUI *pCmdUI)
Definition: fredview.cpp:4027
#define REDUCER
Definition: fredview.cpp:81
#define ID_EDITORS_MESSAGE
Definition: resource.h:1205
afx_msg void OnUpdateCmdBrief(CCmdUI *pCmdUI)
Definition: fredview.cpp:4396
#define ID_EDITORS_FICTION
Definition: resource.h:1463
afx_msg void OnUpdateFormatFs2Retail(CCmdUI *pCmdUI)
Definition: fredview.cpp:4619
Marking_box marking_box
Definition: fredview.cpp:116
int update_dialog_boxes()
void view_universe(int just_marked=0)
Definition: fredview.cpp:2065
CShipEditorDlg Ship_editor_dialog
Definition: fred.cpp:55
virtual void OnDraw(CDC *pDC)
Definition: fredview.cpp:430
matrix saved_cam_orient
Definition: fredview.cpp:115
#define ID_NEW_SHIP_TYPE
Definition: resource.h:1364
ship_weapon weapons
Definition: ship.h:658
window_data Waypoint_wnd_data
Definition: fred.cpp:72
afx_msg void OnSpeed8()
Definition: fredview.cpp:1707
int moved
Definition: fredview.cpp:101
afx_msg void OnGroup(UINT nID)
Definition: fredview.cpp:4078
#define ID_FORMAT_FS2_RETAIL
Definition: resource.h:1443
#define ID_LOOKAT_OBJ
Definition: resource.h:1389
#define OF_TEMP_MARKED
Definition: object.h:126
afx_msg void OnUpdateSpeed50(CCmdUI *pCmdUI)
Definition: fredview.cpp:1791
afx_msg void OnUpdateSelectAndMove(CCmdUI *pCmdUI)
Definition: fredview.cpp:1885
#define SEXP_ERROR_CHECK_MODE
Definition: parselo.h:64
virtual BOOL OnOpenDocument(LPCTSTR lpszPathName)
Definition: freddoc.cpp:143
afx_msg void OnSelect()
Definition: fredview.cpp:1870
int Format_fs1_retail
Definition: fredview.cpp:122
#define AI_GOAL_CHASE_WING
Definition: aigoals.h:37
#define FRED_EXPIRE_TIME
Definition: fredview.cpp:73
void unmark_all()
#define AI_GOAL_DOCK
Definition: aigoals.h:30
afx_msg void OnSaveCamera()
Definition: fredview.cpp:4014
matrix * vm_angles_2_matrix(matrix *m, const angles *a)
Definition: vecmat.cpp:752
#define MAX_WINGS
Definition: globals.h:50
#define AI_GOAL_WAYPOINTS
Definition: aigoals.h:31
#define ID_SHOW_IFF_4
Definition: resource.h:1454
#define MAX_SHIPS
Definition: globals.h:37
char * object_name(int obj)
void object_moved(object *objp)
int model_get_dock_index_type(int modelnum, int index)
Definition: modelread.cpp:5120
int ship_starting_wing_lookup(const char *wing_name)
Definition: ship.cpp:17624
#define AI_GOAL_GUARD
Definition: aigoals.h:38
afx_msg void OnRevert()
Definition: fredview.cpp:3918
afx_msg void OnViewOutlines()
Definition: fredview.cpp:3736
object_orient_pos rotation_backup[MAX_OBJECTS]
Definition: fredview.cpp:117
brief_stage stages[MAX_BRIEF_STAGES]
int error(const char *msg,...)
Definition: fredview.cpp:3303
afx_msg void OnShowIFF7()
Definition: fredview.cpp:4786
#define ID_EDIT_POPUP_SHOW_SHIP_ICONS
Definition: resource.h:1229
void remove_wing(int wing_num)
Definition: wing.cpp:117
afx_msg void OnControlModeCamera()
Definition: fredview.cpp:1826
waypoint_list * find_waypoint_list_with_instance(int waypoint_instance, int *waypoint_index)
Definition: waypoint.cpp:254
int delete_object(int obj)
afx_msg void OnUpdateShowDistances(CCmdUI *pCmdUI)
Definition: fredview.cpp:2022
#define DUP_DRAG_OF_WING
Definition: fredview.cpp:82
vec3d original_pos
Definition: fredview.cpp:114
Assert(pm!=NULL)
#define ID_HIDE_OBJECTS
Definition: resource.h:1380
afx_msg void OnConstrainXz()
Definition: fredview.cpp:1936
#define ID_VIEW_LIGHTING
Definition: resource.h:1448
afx_msg void OnConstrainXy()
Definition: fredview.cpp:1948
afx_msg void OnSetFocus(CWnd *pOldWnd)
Definition: fredview.cpp:1174
int Id_select_type_jump_node
Definition: fredview.cpp:110
int Cur_bitmap
Definition: fredview.cpp:109
Definition: pstypes.h:88
int ship_tvt_wing_lookup(const char *wing_name)
Definition: ship.cpp:17660
int last_mouse_x
Definition: fredview.cpp:108
afx_msg void OnShowPaths()
Definition: fredview.cpp:4548
int init_window(window_data *wndd, CWnd *wnd, int adjust=0, int pre=0)
Definition: fred.cpp:639
int ai_index
Definition: ship.h:538
afx_msg void OnUpdateFormWing(CCmdUI *pCmdUI)
Definition: fredview.cpp:2230
GLuint GLuint * names
Definition: Glext.h:11016
afx_msg void OnHideObjects()
Definition: fredview.cpp:3948
matrix orient
Definition: object.h:193
#define AI_GOAL_STAY_NEAR_SHIP
Definition: aigoals.h:47
int Show_paths_fred
Definition: fredview.cpp:94
afx_msg BOOL OnEraseBkgnd(CDC *pDC)
Definition: fredview.cpp:4683
afx_msg void OnErrorChecker()
Definition: fredview.cpp:2412
#define AI_GOAL_CHASE_ANY
Definition: aigoals.h:41
afx_msg void OnShowGridPositions()
Definition: fredview.cpp:1846
void write_ini_file(int degree=0)
Definition: fred.cpp:552
afx_msg void OnUpdateControlModeCamera(CCmdUI *pCmdUI)
Definition: fredview.cpp:1831
afx_msg void OnEditorsFiction()
Definition: fredview.cpp:4653
void maybe_create_new_grid(grid *gridp, vec3d *pos, matrix *orient, int force)
Definition: missiongrid.cpp:66
afx_msg void OnUpdateConstrainY(CCmdUI *pCmdUI)
Definition: fredview.cpp:1919
#define WM_MENU_POPUP_EDIT
Definition: fredview.h:17
afx_msg void OnSpeed100()
Definition: fredview.cpp:1725
struct vec3d::@225::@227 xyz
#define ID_EDITORS_ORIENT
Definition: resource.h:1356
int Editing_mode
Definition: fredrender.cpp:78
int Dup_drag
Definition: fredview.cpp:104
CButton * team
static CFREDView * GetView()
Definition: fredview.cpp:1520
GLboolean GLuint group
Definition: Glext.h:10591
#define ID_CANCEL_SUBSYS
Definition: resource.h:1438
GLclampf f
Definition: Glext.h:7097
void key_lost_focus()
Definition: key.cpp:917
#define EXPIRE_BAD_TIME
Definition: fredview.cpp:78
#define MAX_OBJECTS
Definition: globals.h:83
afx_msg void OnDoubleFineGridlines()
Definition: fredview.cpp:2002
#define ID_ROT2
Definition: resource.h:1295
int Flying_controls_mode
Definition: fredrender.cpp:92
LOCAL int Duped_wing
Definition: fredview.cpp:84
virtual void OnInitialUpdate()
Definition: fredview.cpp:4125
#define AI_GOAL_WARP
Definition: aigoals.h:33
#define TRUE
Definition: pstypes.h:399
afx_msg void OnShowIFF0()
Definition: fredview.cpp:4716
#define MISSION_TYPE_MULTI
Definition: missionparse.h:62
#define AI_GOAL_IGNORE
Definition: aigoals.h:42
matrix * vm_copy_transpose(matrix *dest, const matrix *src)
Definition: vecmat.cpp:984
ai_info Ai_info[MAX_AI_INFO]
Definition: ai.cpp:23
int box_marking
Definition: fredview.cpp:107
vec3d * vm_vec_rotate(vec3d *dest, const vec3d *src, const matrix *m)
Definition: vecmat.cpp:933
#define ID_EDITORS_PLAYER
Definition: resource.h:1355
#define ID_SHOW_SEXP_HELP
Definition: resource.h:1388
UINT WPARAM wParam
Definition: msacm.h:1064
afx_msg void OnShowShips()
Definition: fredview.cpp:3869
afx_msg void OnUpdateSpeed3(CCmdUI *pCmdUI)
Definition: fredview.cpp:1771
int dock_find_dockpoint_used_by_object(object *objp, object *other_objp)
Definition: objectdock.cpp:116
object obj_used_list
Definition: object.cpp:53
#define ID_CONSTRAIN_XY
Definition: resource.h:1334
int cur_wing
Definition: management.cpp:77
#define ID_FORMAT_FS1_RETAIL
Definition: resource.h:1445
#define ID_ZOOM_EXTENTS
Definition: resource.h:1340
int get_prev_visible_subsys(ship *shipp, ship_subsys **prev_subsys)
Definition: fredview.cpp:4449
#define ID_SELECT_AND_ROTATE
Definition: resource.h:1319
int Universal_heading
Definition: fredrender.cpp:91
afx_msg void OnUpdateEditPopupShowCompass(CCmdUI *pCmdUI)
Definition: fredview.cpp:1514
int create_wing()
Definition: wing.cpp:217
#define AI_GOAL_DISARM_SHIP
Definition: aigoals.h:40
CMainFrame * Fred_main_wnd
Definition: mainfrm.cpp:89
Definition: ship.h:1516
#define ID_UNIVERSAL_HEADING
Definition: resource.h:1329
vec3d Constraint
Definition: fredrender.cpp:106
#define ID_ROT5
Definition: resource.h:1298
#define ID_DUMP_STATS
Definition: resource.h:1441
afx_msg void OnRunFreeSpace()
Definition: fredview.cpp:3787
afx_msg void OnUpdateRevert(CCmdUI *pCmdUI)
Definition: fredview.cpp:3927
afx_msg void OnRotateLocally()
Definition: fredview.cpp:2047
afx_msg void OnToggleViewpoint()
Definition: fredview.cpp:3905
GLenum GLuint GLenum GLsizei const GLchar * message
Definition: Glext.h:5156
UINT WPARAM LPARAM lParam
Definition: msacm.h:1064
int physics_speed
Definition: fredview.cpp:105
uint flags
Definition: ship.h:644
#define ID_SPEED1
Definition: resource.h:1289
#define ID_SHOW_WAYPOINTS
Definition: resource.h:367
int Marked
Definition: fredview.cpp:101
waypoint_list * cur_waypoint_list
Definition: management.cpp:83
#define ID_MARK_WING
Definition: resource.h:1415
#define ID_SHOW_SHIPS
Definition: resource.h:1371
unsigned int UINT
Definition: config.h:82
#define MAX_SHIPS_PER_WING
Definition: globals.h:52
hull_check orient
Definition: lua.cpp:5049
std::basic_string< char, std::char_traits< char >, std::allocator< char > > SCP_string
Definition: vmallocator.h:21
void obj_merge_created_list(void)
Definition: object.cpp:651
#define ID_SHOW_DISTANCES
Definition: resource.h:1328
afx_msg void OnUpdateViewOutlines(CCmdUI *pCmdUI)
Definition: fredview.cpp:3743
object * objp
Definition: lua.cpp:3105
void verticalize_controlled()
Definition: fredrender.cpp:298
#define IDR_MENU_EDIT_POPUP
Definition: resource.h:45
#define ID_SHOW_HIDDEN_OBJECTS
Definition: resource.h:1381
#define Int3()
Definition: pstypes.h:292
#define CC_OFF
Definition: 3d.h:34
void CALLBACK expire_game_proc(HWND wnd, UINT uMsg, UINT idEvent, DWORD dwTime)
Definition: fredview.cpp:399
#define ID_EDITORS_WAYPOINT
Definition: resource.h:1362
afx_msg void OnEditDelete()
Definition: fredview.cpp:4322
void convert_sexp_to_string(SCP_string &dest, int cur_node, int mode)
Definition: sexp.cpp:3904
briefing Briefings[MAX_TVT_TEAMS]
char stamp[STAMP_STRING_LENGTH]
Definition: fredview.cpp:74
void snd_close(void)
Definition: sound.cpp:459
afx_msg void OnLButtonDown(UINT nFlags, CPoint point)
Definition: fredview.cpp:900
#define AI_GOAL_NONE
Definition: ai.h:194
ship * shipp
Definition: lua.cpp:9162
vec3d pos
Definition: object.h:152
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: Glext.h:7308
#define ID_SELECT
Definition: resource.h:1187
#define MAX_TVT_WINGS
Definition: globals.h:59
int get_docking_list(int model_index)
vec3d view_pos
Definition: fredrender.cpp:103
bg_bitmap_dlg * Bg_bitmap_dialog
Definition: fred.cpp:58
mission_goal Mission_goals[MAX_GOALS]
afx_msg void OnUpdateLookatObj(CCmdUI *pCmdUI)
Definition: fredview.cpp:4073
#define ID_VIEW_FULL_DETAIL
Definition: resource.h:1459
#define DEFAULT_TIME_STRING
Definition: pstypes.h:498
int Show_horizon
Definition: fredrender.cpp:87
SCP_list< waypoint_list > Waypoint_lists
Definition: waypoint.cpp:9
#define IS_VEC_NULL(v)
Definition: vecmat.h:28
afx_msg void OnShowHiddenObjects()
Definition: fredview.cpp:3963
#define ID_EDITORS_SHIPS
Definition: resource.h:1208
afx_msg void OnUpdateShowStarts(CCmdUI *pCmdUI)
Definition: fredview.cpp:3888
int subobj_num
Definition: model.h:175
#define ID_EDITORS_STARFIELD
Definition: resource.h:1358
afx_msg void OnUpdateRot3(CCmdUI *pCmdUI)
Definition: fredview.cpp:1811
SCP_list< CJumpNode > Jump_nodes
Definition: jumpnode.cpp:16
int double_fine_gridlines
Definition: missiongrid.cpp:21
GLenum type
Definition: Gl.h:1492
afx_msg void OnShowIFF3()
Definition: fredview.cpp:4746
afx_msg void OnRot5()
Definition: fredview.cpp:1755
ship_subsys * cur_subsys
Definition: fredview.h:28
afx_msg void OnViewFullDetail()
Definition: fredview.cpp:4700
#define EXPIRE_BAD_CHECKSUM
Definition: fredview.cpp:77
afx_msg void OnConstrainYz()
Definition: fredview.cpp:1960
#define ID_LEVEL_OBJ
Definition: resource.h:1414
int Selection_lock
Definition: fredview.cpp:97
reinforcements Reinforcements[MAX_REINFORCEMENTS]
Definition: ship.cpp:165
#define ID_AA_GRIDLINES
Definition: resource.h:1425
afx_msg void OnUpdateViewGrid(CCmdUI *pCmdUI)
Definition: fredview.cpp:489
#define ID_SHOW_IFF_7
Definition: resource.h:1457
#define ID_SAVE_CAMERA
Definition: resource.h:1386
SCP_vector< waypoint > & get_waypoints()
Definition: waypoint.cpp:89
void do_trackball_stuff(int nFlags, CPoint point)
Definition: fredview.cpp:1250
#define ID_CONSTRAIN_Z
Definition: resource.h:1321
int query_valid_object(int index)
afx_msg void OnSpeed3()
Definition: fredview.cpp:1695
int ship_get_num_ships()
Definition: ship.cpp:522
#define ID_SHOW_GRID_POSITIONS
Definition: resource.h:1305
ship_subsys subsys_list
Definition: ship.h:630
LONG OnMenuPopupShips(UINT wParam, LONG lParam)
Definition: fredview.cpp:1344
#define ID_SET_GROUP1
Definition: resource.h:1399
#define ID_EDITOR_CAMPAIGN
Definition: resource.h:1368
void OnUpdateShowIFF(int iff, CCmdUI *pCmdUI)
Definition: fredview.cpp:3900
LONG OnGoodbye(UINT wParam, LONG lParam)
Definition: fredview.cpp:1128
int button_down
Definition: fredview.cpp:100
afx_msg void OnEditorsSetGlobalShipFlags()
Definition: fredview.cpp:4639
brief_icon * icons
int orders_accepted
Definition: ship.h:624
typedef int(SCP_EXT_CALLCONV *SCPDLL_PFVERSION)(SCPDLL_Version *)
#define OBJ_WAYPOINT
Definition: object.h:36
#define MAX_SHIP_SECONDARY_BANKS
Definition: globals.h:63
#define ID_ZOOM_SELECTED
Definition: resource.h:1339
afx_msg void OnUpdateShowIFF8(CCmdUI *pCmdUI)
Definition: fredview.cpp:4801
int instance
Definition: object.h:150
afx_msg void OnFlyingControls()
Definition: fredview.cpp:2037
int Undo_available
Definition: freddoc.cpp:92
afx_msg void OnUpdateAaGridlines(CCmdUI *pCmdUI)
Definition: fredview.cpp:4372
matrix * vm_vector_2_matrix(matrix *m, const vec3d *fvec, const vec3d *uvec, const vec3d *rvec)
Definition: vecmat.cpp:850
int physics_rot
Definition: fredview.cpp:106
#define PF_OVERFLOW
Definition: 3d.h:22
int create_object_on_grid(int waypoint_instance)
Definition: management.cpp:469
#define OBJ_START
Definition: object.h:35
int Show_ship_models
Definition: fredview.cpp:91
afx_msg void OnUpdateSpeed5(CCmdUI *pCmdUI)
Definition: fredview.cpp:1776
#define ID_EDITORS_EVENTS
Definition: resource.h:1357
GLdouble GLdouble GLdouble r
Definition: Glext.h:5337
afx_msg void OnSpeed5()
Definition: fredview.cpp:1701
afx_msg void OnPrevSubsys()
Definition: fredview.cpp:4523
#define ID_CONTROL_MODE_CAMERA
Definition: resource.h:1302
int group
Definition: ship.h:674
#define ID_SHOW_HORIZON
Definition: resource.h:1341
afx_msg void OnMouseMove(UINT nFlags, CPoint point)
Definition: fredview.cpp:989
afx_msg void OnEditorsGoals()
Definition: fredview.cpp:1676
struct matrix::@228::@230 vec