/* * Descent 3 * Copyright (C) 2024 Parallax Software * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ // PathPadDialog.cpp : implementation file // #include "stdafx.h" #include "editor.h" #include "PathPadDialog.h" #include "EditLineDialog.h" #include "epath.h" #include "object.h" #include "room.h" #include "FindIntersection.h" #include "ebnode.h" #include "boa.h" #include "object.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CPathPadDialog dialog CPathPadDialog::CPathPadDialog(CWnd* pParent /*=NULL*/) : CKeypadDialog(CPathPadDialog::IDD, pParent) { //{{AFX_DATA_INIT(CPathPadDialog) // NOTE: the ClassWizard will add member initialization here //}}AFX_DATA_INIT } void CPathPadDialog::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CPathPadDialog) // NOTE: the ClassWizard will add DDX and DDV calls here //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CPathPadDialog, CDialog) //{{AFX_MSG_MAP(CPathPadDialog) ON_EN_KILLFOCUS(IDC_CURRENT_NODE_EDIT, OnKillfocusCurrentNodeEdit) ON_BN_CLICKED(IDC_PATHPAD_ADD_PATH, OnPathpadAddPath) ON_BN_CLICKED(IDC_PATHPAD_INSERT_NODE, OnPathpadInsertNode) ON_BN_CLICKED(IDC_PATHPAD_DELETE_NODE, OnPathpadDeleteNode) ON_BN_CLICKED(IDC_PATHPAD_MOVE_FORWARD, OnPathpadMoveForward) ON_BN_CLICKED(IDC_PATHPAD_MOVE_BACKWARD, OnPathpadMoveBackward) ON_BN_CLICKED(IDC_PATHPAD_MOVE_LEFT, OnPathpadMoveLeft) ON_BN_CLICKED(IDC_PATHPAD_MOVE_RIGHT, OnPathpadMoveRight) ON_CBN_SELENDOK(IDC_PATHPAD_PULLDOWN, OnSelendokPathpadPulldown) ON_BN_CLICKED(IDC_PATHPAD_CENTER_VIEW, OnPathpadCenterView) ON_BN_CLICKED(IDC_PATHPAD_MOVE_DOWN, OnPathpadMoveDown) ON_BN_CLICKED(IDC_PATHPAD_MOVE_UP, OnPathpadMoveUp) ON_BN_CLICKED(IDC_PATHPAD_PREV_NODE, OnPathpadPrevNode) ON_BN_CLICKED(IDC_PATHPAD_NEXT_NODE, OnPathpadNextNode) ON_BN_CLICKED(IDC_DELETE_PATH, OnDeletePath) ON_BN_CLICKED(IDC_SHOW_NODES_CHECK, OnShowNodesCheck) ON_WM_HELPINFO() ON_BN_CLICKED(IDC_PATH_MOVE_OBJECT_BUTTON, OnPathMoveObjectButton) ON_BN_CLICKED(IDC_PATH_REORIENT_VIEWER_BUTTON, OnPathReorientViewerButton) ON_EN_KILLFOCUS(IDC_PATH_INC_TEXT, OnKillfocusPathIncText) ON_WM_PAINT() ON_BN_CLICKED(IDC_PATH_MOVE_NODE_TO_CURRENT_OBJECT, OnPathMoveNodeToCurrentObject) ON_BN_CLICKED(IDC_PATH_MOVE_OBJ_NO_ORIENT, OnPathMoveObjNoOrient) ON_BN_CLICKED(IDC_PATH_VERIFY_BUTTON, OnPathVerifyButton) ON_BN_CLICKED(IDC_AIN_AUTO_EDGE_NODE, OnAinAutoEdgeNode) ON_BN_CLICKED(IDC_AIN_BACK, OnAinBack) ON_BN_CLICKED(IDC_AIN_CREATE_NODE_AT_VIEWER, OnAinCreateNodeAtViewer) ON_BN_CLICKED(IDC_AIN_CREATE_NODES, OnAinCreateNodes) ON_CBN_SELENDOK(IDC_AIN_CURRENT_NODE, OnSelendokAinCurrentNode) ON_BN_CLICKED(IDC_AIN_DELETE_EDGE, OnAinDeleteEdge) ON_BN_CLICKED(IDC_AIN_DELETE_NODE, OnAinDeleteNode) ON_BN_CLICKED(IDC_AIN_DOWN, OnAinDown) ON_BN_CLICKED(IDC_AIN_FORWARD, OnAinForward) ON_BN_CLICKED(IDC_AIN_INSERT_NODE_ON_EDGE, OnAinInsertNodeOnEdge) ON_BN_CLICKED(IDC_AIN_LEFT, OnAinLeft) ON_BN_CLICKED(IDC_AIN_MAKE_EDGE, OnAinMakeEdge) ON_EN_KILLFOCUS(IDC_AIN_MOVE_AMOUNT, OnKillfocusAinMoveAmount) ON_BN_CLICKED(IDC_AIN_MOVE_NODE_TO_VIEWER, OnAinMoveNodeToViewer) ON_BN_CLICKED(IDC_AIN_MPNS, OnAinMpns) ON_CBN_SELENDOK(IDC_AIN_OTHER_NODE, OnSelendokAinOtherNode) ON_BN_CLICKED(IDC_AIN_RESET_ROOM_NODES, OnAinResetRoomNodes) ON_BN_CLICKED(IDC_AIN_RIGHT, OnAinRight) ON_BN_CLICKED(IDC_AIN_SEL_NODE_EDGES, OnAinSelNodeEdges) ON_BN_CLICKED(IDC_AIN_SEL_ROOM, OnAinSelRoom) ON_BN_CLICKED(IDC_AIN_UP, OnAinUp) ON_BN_CLICKED(IDC_AIN_SEL_ROOM_AND_NEXT_ROOMS, OnAinSelRoomAndNextRooms) ON_BN_CLICKED(IDC_AIN_VERIFY_LEVEL, OnAinVerifyLevel) ON_BN_CLICKED(IDC_AIN_VERIFY_ROOM, OnAinVerifyRoom) ON_BN_CLICKED(IDC_AIN_VIEW_ALL_NODES, OnAinViewAllNodes) ON_BN_CLICKED(IDC_AIN_VIEW_NONE, OnAinViewNone) ON_BN_CLICKED(IDC_AIN_VIEW_ROOM, OnAinViewRoom) ON_BN_CLICKED(IDC_AIN_VIEW_ROOM_AND_NEXT_ROOMS, OnAinViewRoomAndNextRooms) ON_CBN_SETFOCUS(IDC_AIN_CURRENT_NODE, OnSetfocusAinCurrentNode) ON_CBN_SETFOCUS(IDC_AIN_OTHER_NODE, OnSetfocusAinOtherNode) ON_BN_CLICKED(IDC_IENAV_BUTTON, OnIenavButton) ON_BN_CLICKED(IDC_MVTN_BUTTON, OnMvtnButton) ON_BN_CLICKED(IDC_AER_BUTTON, OnAerButton) ON_BN_CLICKED(IDC_ONTVGP_BUTTON, OnOntvgpButton) //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CPathPadDialog message handlers void CPathPadDialog::OnKillfocusCurrentNodeEdit() { CEdit *ebox; char str[20]; int curpath=D3EditState.current_path; if (Num_game_paths<1) { MessageBox ("There are no paths to operate on."); return; } ebox=(CEdit *) GetDlgItem (IDC_CURRENT_NODE_EDIT); ebox->GetWindowText (str,20); // Do the base 1 to base 0 conversion D3EditState.current_node = atoi (str) - 1; if(D3EditState.current_node >= GamePaths[curpath].num_nodes) D3EditState.current_node = GamePaths[curpath].num_nodes - 1; else if(D3EditState.current_node < 0) D3EditState.current_node = 0; UpdateDialog(); } void CPathPadDialog::OnPathpadAddPath() { int curnode; char *namestr; int pathnum; int dup_test; pathnum=AllocGamePath (); if (pathnum < 0) { return; } CEditLineDialog dlg ("Enter path name",this); int ret=dlg.DoModal(); if (ret==IDCANCEL) { FreeGamePath(pathnum); return; } namestr=(char *)dlg.GetText (); dup_test = FindGamePathName(namestr); if(dup_test != -1) { OutrageMessageBox("PATH NOT CREATED: A path named %s already exists.", namestr); FreeGamePath(pathnum); return; } strcpy (GamePaths[pathnum].name,namestr); curnode=InsertNodeIntoPath (pathnum,-1,0); if(curnode < 0) return; D3EditState.current_path=pathnum; D3EditState.current_node=curnode; World_changed=1; UpdateDialog(); } void CPathPadDialog::OnPathpadInsertNode() { int curpath=D3EditState.current_path; int curnode=D3EditState.current_node; if (Num_game_paths<1) { MessageBox ("There are no paths to operate on."); return; } curnode=InsertNodeIntoPath (curpath,curnode,0); if(curnode < 0) return; D3EditState.current_node=curnode; World_changed=1; UpdateDialog(); } void CPathPadDialog::OnPathpadDeleteNode() { int curpath=D3EditState.current_path; int curnode=D3EditState.current_node; if (Num_game_paths<1) { MessageBox ("There are no paths to operate on."); return; } if (GamePaths[curpath].num_nodes==1) { MessageBox ("This is the only node in this path. If you wish to delete this path, click the 'Delete Path' button."); return; } DeleteNodeFromPath (curpath,curnode); // If this was the ending node, move it back one if (curnode==GamePaths[curpath].num_nodes) D3EditState.current_node=curnode-1; State_changed=1; UpdateDialog(); } void CPathPadDialog::OnPathpadMoveForward() { if (Num_game_paths<1) { MessageBox ("There are no paths to operate on."); return; } int p=D3EditState.current_path; int n=D3EditState.current_node; vector delta_movement = Viewer_object->orient.fvec * D3EditState.node_movement_inc; MovePathNode(p, n, &delta_movement); World_changed=1; UpdateDialog(); } void CPathPadDialog::OnPathpadMoveBackward() { if (Num_game_paths<1) { MessageBox ("There are no paths to operate on."); return; } int p=D3EditState.current_path; int n=D3EditState.current_node; vector delta_movement = Viewer_object->orient.fvec * -D3EditState.node_movement_inc; MovePathNode(p, n, &delta_movement); World_changed=1; UpdateDialog(); } void CPathPadDialog::OnPathpadMoveLeft() { if (Num_game_paths<1) { MessageBox ("There are no paths to operate on."); return; } int p=D3EditState.current_path; int n=D3EditState.current_node; vector delta_movement = Viewer_object->orient.rvec * -D3EditState.node_movement_inc; MovePathNode(p, n, &delta_movement); World_changed=1; UpdateDialog(); } void CPathPadDialog::OnPathpadMoveRight() { if (Num_game_paths<1) { MessageBox ("There are no paths to operate on."); return; } int p=D3EditState.current_path; int n=D3EditState.current_node; vector delta_movement = Viewer_object->orient.rvec * D3EditState.node_movement_inc; MovePathNode(p, n, &delta_movement); World_changed=1; UpdateDialog(); } void CPathPadDialog::OnSelendokPathpadPulldown() { int i,cur; char name[200]; cur=SendDlgItemMessage( IDC_PATHPAD_PULLDOWN, CB_GETCURSEL,0,0); SendDlgItemMessage( IDC_PATHPAD_PULLDOWN, CB_GETLBTEXT,cur,(LPARAM) (LPCTSTR)name); i=FindGamePathName (name); D3EditState.current_path=i; D3EditState.current_node=0; State_changed=1; UpdateDialog(); } void CPathPadDialog::OnPathpadCenterView() { if (Num_game_paths<1) { MessageBox ("There are no paths to operate on."); return; } int p=D3EditState.current_path; int n=D3EditState.current_node; game_path *gp=&GamePaths[p]; vector attempted_pos; vector subvec={0.0,0.0,0.0}; // changed for now attempted_pos = gp->pathnodes[n].pos - subvec; fvi_query fq; fvi_info hit_info; fq.p0 = &GamePaths[p].pathnodes[n].pos; fq.startroom = GamePaths[p].pathnodes[n].roomnum; fq.p1 = &attempted_pos; fq.rad = 0.0f; fq.thisobjnum = -1; fq.ignore_obj_list = NULL; fq.flags = FQ_TRANSPOINT | FQ_IGNORE_RENDER_THROUGH_PORTALS; int hit = fvi_FindIntersection(&fq, &hit_info); if (hit != HIT_NONE) Int3(); //what does it mean that we hit something? ObjSetPos(Viewer_object,&hit_info.hit_pnt,hit_info.hit_room,NULL,false); World_changed=1; UpdateDialog(); } void CPathPadDialog::OnPathpadMoveDown() { if (Num_game_paths<1) { MessageBox ("There are no paths to operate on."); return; } int p=D3EditState.current_path; int n=D3EditState.current_node; vector delta_movement = Viewer_object->orient.uvec * -D3EditState.node_movement_inc; MovePathNode(p, n, &delta_movement); World_changed=1; UpdateDialog(); } void CPathPadDialog::OnPathpadMoveUp() { if (Num_game_paths<1) { MessageBox ("There are no paths to operate on."); return; } int p=D3EditState.current_path; int n=D3EditState.current_node; vector delta_movement = Viewer_object->orient.uvec * D3EditState.node_movement_inc; MovePathNode(p, n, &delta_movement); World_changed=1; UpdateDialog(); } void CPathPadDialog::OnPathpadPrevNode() { if (Num_game_paths<1) return; int p=D3EditState.current_path; int n=D3EditState.current_node; n--; if (n<0) n=GamePaths[p].num_nodes-1; D3EditState.current_node=n; World_changed=1; UpdateDialog(); } void CPathPadDialog::OnPathpadNextNode() { if (Num_game_paths<1) return; int p=D3EditState.current_path; int n=D3EditState.current_node; n++; n%=GamePaths[p].num_nodes; D3EditState.current_node=n; World_changed=1; UpdateDialog(); } void CPathPadDialog::UpdateDialog() { int n=D3EditState.current_path; char str[50]; CEdit *ebox; SendDlgItemMessage( IDC_PATHPAD_PULLDOWN, CB_RESETCONTENT,0,0); for (int i=0;iSetWindowText (str); ebox=(CEdit *) GetDlgItem (IDC_PATH_INC_TEXT); sprintf (str,"%f",D3EditState.node_movement_inc); ebox->SetWindowText (str); if(n < Num_game_paths && D3EditState.current_node < GamePaths[n].num_nodes) { ebox=(CEdit *) GetDlgItem (IDC_PATHPAD_CUR_NODE_ROOM); if(!ROOMNUM_OUTSIDE(GamePaths[n].pathnodes[D3EditState.current_node].roomnum)) sprintf (str,"Current Mine Room: %d",GamePaths[n].pathnodes[D3EditState.current_node].roomnum); else sprintf (str,"Current Terrain Cell: %d", (0x7FFFFFFF & GamePaths[n].pathnodes[D3EditState.current_node].roomnum)); ebox->SetWindowText (str); } ebox=(CEdit *) GetDlgItem (IDC_PATHPAD_NUM_NODES); sprintf (str,"Number of nodes: %d",GamePaths[n].num_nodes); ebox->SetWindowText (str); CheckDlgButton (IDC_SHOW_NODES_CHECK,Show_paths?1:0); } void CPathPadDialog::OnDeletePath() { int ret; int n=D3EditState.current_path; if (Num_game_paths<1) return; ret=MessageBox ("Are you sure you want to delete this path?",GamePaths[n].name,MB_YESNO); if (ret==IDNO) return; FreeGamePath(n); D3EditState.current_path=GetNextPath(n); World_changed=1; UpdateDialog(); } void CPathPadDialog::OnShowNodesCheck() { int c=IsDlgButtonChecked(IDC_SHOW_NODES_CHECK); if (c) Show_paths=1; else Show_paths=0; TV_changed=1; } BOOL CPathPadDialog::OnHelpInfo(HELPINFO* pHelpInfo) { WinHelp(HID_PATHSTAB,HELP_CONTEXT); return TRUE; //return CDialog::OnHelpInfo(pHelpInfo); } void CPathPadDialog::OnPathMoveObjectButton() { if (Num_game_paths<1) { MessageBox ("There are no paths to operate on."); return; } if (Cur_object_index != -1) // we have a selected object { int p=D3EditState.current_path; int n=D3EditState.current_node; game_path *gp=&GamePaths[p]; ObjSetPos(&Objects[Cur_object_index],&gp->pathnodes[n].pos,gp->pathnodes[n].roomnum,NULL,false); matrix node_orient; vm_VectorToMatrix(&node_orient, &gp->pathnodes[n].fvec, &gp->pathnodes[n].uvec, NULL); ObjSetOrient(&Objects[Cur_object_index], &node_orient); World_changed=1; } } void CPathPadDialog::OnPathReorientViewerButton() { if (Num_game_paths<1) { MessageBox ("There are no paths to operate on."); return; } int p=D3EditState.current_path; int n=D3EditState.current_node; game_path *gp=&GamePaths[p]; matrix node_orient; vm_VectorToMatrix(&node_orient, &gp->pathnodes[n].fvec, &gp->pathnodes[n].uvec, NULL); ObjSetOrient(Viewer_object, &node_orient); World_changed=1; UpdateDialog(); } void CPathPadDialog::OnKillfocusPathIncText() { CEdit *ebox; char str[20]; ebox=(CEdit *) GetDlgItem (IDC_PATH_INC_TEXT); ebox->GetWindowText (str,20); // Do the base 1 to base 0 conversion sscanf(str, "%f", &D3EditState.node_movement_inc); if(D3EditState.node_movement_inc <= 0.0f || D3EditState.node_movement_inc > 32000.0f) D3EditState.node_movement_inc = 1.0f; UpdateDialog(); } void CPathPadDialog::OnPaint() { CPaintDC dc(this); // device context for painting UpdateDialog(); } void CPathPadDialog::OnPathMoveNodeToCurrentObject() { if (Num_game_paths<1) { MessageBox ("There are no paths to operate on."); return; } if (Cur_object_index != -1) // we have a selected object { int p=D3EditState.current_path; int n=D3EditState.current_node; game_path *gp=&GamePaths[p]; MovePathNodeToPos(p, n, &Objects[Cur_object_index].pos); World_changed=1; UpdateDialog(); } } void CPathPadDialog::OnPathMoveObjNoOrient() { if (Num_game_paths<1) { MessageBox ("There are no paths to operate on."); return; } if (Cur_object_index != -1) // we have a selected object { int p=D3EditState.current_path; int n=D3EditState.current_node; game_path *gp=&GamePaths[p]; ObjSetPos(&Objects[Cur_object_index],&gp->pathnodes[n].pos,gp->pathnodes[n].roomnum, NULL, false); //matrix node_orient; World_changed=1; UpdateDialog(); } } void CPathPadDialog::OnPathVerifyButton() { } int BNode_current_id = 0; int BNode_current_room = 0; int BNode_other_id = 0; int BNode_other_room = 0; float BNode_move_amount = 1.0f; void CPathPadDialog::OnAinAutoEdgeNode() { EBNode_AutoEdgeNode(BNode_current_id, BNode_current_room); EBNode_VerifyGraph(); World_changed = 1; } void CPathPadDialog::OnAinBack() { vector diff = -Viewer_object->orient.fvec * BNode_move_amount; EBNode_Move(true, BNode_current_room, BNode_current_id, &diff); World_changed = 1; } void CPathPadDialog::OnAinCreateNodeAtViewer() { int node = EBNode_AddNode(Viewer_object->roomnum, &Viewer_object->pos, true, true); if(node != -1) { World_changed = 1; } // EBNode_VerifyGraph(); } void CPathPadDialog::OnAinCreateNodes() { MakeBOA(); EBNode_MakeFirstPass(); World_changed = 1; } void CPathPadDialog::OnSelendokAinCurrentNode() { int cur; char name[200]; cur=SendDlgItemMessage( IDC_AIN_CURRENT_NODE, CB_GETCURSEL,0,0); SendDlgItemMessage( IDC_AIN_CURRENT_NODE, CB_GETLBTEXT,cur,(LPARAM) (LPCTSTR)name); if(sscanf(name, "Room %d, Node %d", &BNode_current_room, &BNode_current_id) != 2) { sscanf(name, "Region %d, Node %d", &BNode_current_room, &BNode_current_id); BNode_current_room += Highest_room_index + 1; } BNode_current_id--; } void CPathPadDialog::OnAinDeleteEdge() { EBNode_RemoveEdge(BNode_current_id, BNode_current_room, BNode_other_id, BNode_other_room); World_changed = 1; EBNode_VerifyGraph(); } void CPathPadDialog::OnAinDeleteNode() { EBNode_RemoveNode(BNode_current_room, BNode_current_id); World_changed = 1; EBNode_VerifyGraph(); } void CPathPadDialog::OnAinDown() { vector diff = -Viewer_object->orient.uvec * BNode_move_amount; EBNode_Move(true, BNode_current_room, BNode_current_id, &diff); World_changed = 1; } void CPathPadDialog::OnAinForward() { vector diff = Viewer_object->orient.fvec * BNode_move_amount; EBNode_Move(true, BNode_current_room, BNode_current_id, &diff); World_changed = 1; } void CPathPadDialog::OnAinInsertNodeOnEdge() { EBNode_InsertNodeOnEdge(BNode_current_id, BNode_current_room, BNode_other_id, BNode_other_room); EBNode_VerifyGraph(); World_changed = 1; } void CPathPadDialog::OnAinLeft() { vector diff = -Viewer_object->orient.rvec * BNode_move_amount; EBNode_Move(true, BNode_current_room, BNode_current_id, &diff); World_changed = 1; } void CPathPadDialog::OnAinMakeEdge() { EBNode_AddEdge(BNode_current_id, BNode_current_room, BNode_other_id, BNode_other_room); EBNode_VerifyGraph(); World_changed = 1; } void CPathPadDialog::OnKillfocusAinMoveAmount() { CEdit *ebox; char str[20]; ebox=(CEdit *) GetDlgItem (IDC_AIN_MOVE_AMOUNT); ebox->GetWindowText (str,20); sscanf(str, "%f", &BNode_move_amount); UpdateDialog(); } void CPathPadDialog::OnAinMoveNodeToViewer() { vector diff = Viewer_object->pos; EBNode_Move(false, BNode_current_room, BNode_current_id, &diff); World_changed = 1; } void CPathPadDialog::OnAinMpns() { // TODO: Add your control notification handler code here } void CPathPadDialog::OnSelendokAinOtherNode() { int cur; char name[200]; cur=SendDlgItemMessage( IDC_AIN_OTHER_NODE, CB_GETCURSEL,0,0); SendDlgItemMessage( IDC_AIN_OTHER_NODE, CB_GETLBTEXT,cur,(LPARAM) (LPCTSTR)name); if(sscanf(name, "Room %d, Node %d", &BNode_other_room, &BNode_other_id) != 2) { sscanf(name, "Region %d, Node %d", &BNode_other_room, &BNode_other_id); BNode_other_room += Highest_room_index + 1; } BNode_other_id--; } void CPathPadDialog::OnAinResetRoomNodes() { // TODO: Add your control notification handler code here EBNode_VerifyGraph(); } void CPathPadDialog::OnAinRight() { vector diff = Viewer_object->orient.rvec * BNode_move_amount; EBNode_Move(true, BNode_current_room, BNode_current_id, &diff); World_changed = 1; } #define EBVIEW_ROOM 1 #define EBVIEW_ROOM_AND_NEXT_ROOMS 2 #define EBVIEW_CUR_EDGES 3 char ENode_view_type = EBVIEW_ROOM; void CPathPadDialog::OnAinSelNodeEdges() { ENode_view_type = EBVIEW_CUR_EDGES; ResetNodesForComboBox(IDC_AIN_CURRENT_NODE, ENode_view_type); ResetNodesForComboBox(IDC_AIN_OTHER_NODE ,ENode_view_type); } void CPathPadDialog::OnAinSelRoom() { ENode_view_type = EBVIEW_ROOM; ResetNodesForComboBox(IDC_AIN_CURRENT_NODE, ENode_view_type); ResetNodesForComboBox(IDC_AIN_OTHER_NODE ,ENode_view_type); } void CPathPadDialog::OnAinSelRoomAndNextRooms() { ENode_view_type = EBVIEW_ROOM_AND_NEXT_ROOMS; ResetNodesForComboBox(IDC_AIN_CURRENT_NODE, ENode_view_type); ResetNodesForComboBox(IDC_AIN_OTHER_NODE ,ENode_view_type); } void CPathPadDialog::OnAinUp() { vector diff = Viewer_object->orient.uvec * BNode_move_amount; EBNode_Move(true, BNode_current_room, BNode_current_id, &diff); World_changed = 1; } void CPathPadDialog::OnAinVerifyLevel() { EBNode_VerifyGraph(); } void CPathPadDialog::OnAinVerifyRoom() { EBNode_ClearLevel(); World_changed = 1; } void CPathPadDialog::OnAinViewAllNodes() { EBN_draw_type = EBDRAW_LEVEL; World_changed = 1; } void CPathPadDialog::OnAinViewNone() { EBN_draw_type = EBDRAW_NONE; World_changed = 1; } void CPathPadDialog::OnAinViewRoom() { EBN_draw_type = EBDRAW_ROOM; World_changed = 1; } void CPathPadDialog::OnAinViewRoomAndNextRooms() { EBN_draw_type = EBDRAW_ROOM_AND_NEXT_ROOMS; World_changed = 1; } void CPathPadDialog::ResetNodesForComboBox(int handle, char selection_type) { char message[25]; SendDlgItemMessage(handle, CB_RESETCONTENT, 0, 0); bool f_add = false; int num_next_rooms = 0; int next_rooms[1000]; if(Viewer_object->roomnum >= 0 && Viewer_object->roomnum <= Highest_room_index && Rooms[Viewer_object->roomnum].used) { if(selection_type == EBVIEW_ROOM || selection_type == EBVIEW_ROOM_AND_NEXT_ROOMS) { for (int i = 0; i < Rooms[Viewer_object->roomnum].bn_info.num_nodes; i++) { f_add = true; sprintf(message, "Room %d, Node %d", Viewer_object->roomnum, i + 1); SendDlgItemMessage( handle, CB_ADDSTRING,0,(LPARAM) (LPCTSTR) message); } if(selection_type == EBVIEW_ROOM_AND_NEXT_ROOMS) { int i; int j; int k; for(i = 0; i < Rooms[Viewer_object->roomnum].num_portals; i++) { bool f_found = false; for(j = 0; j < num_next_rooms; j++) { if(next_rooms[j] == Rooms[Viewer_object->roomnum].portals[i].croom) { f_found = true; break; } } if(!f_found && Rooms[Viewer_object->roomnum].portals[i].croom >= 0 && !(Rooms[Rooms[Viewer_object->roomnum].portals[i].croom].flags & RF_EXTERNAL)) { for(k = 0; k < Rooms[Rooms[Viewer_object->roomnum].portals[i].croom].bn_info.num_nodes; k++) { sprintf(message, "Room %d, Node %d", Rooms[Viewer_object->roomnum].portals[i].croom, k + 1); SendDlgItemMessage( handle, CB_ADDSTRING,0,(LPARAM) (LPCTSTR) message); } } } } if(f_add) { sprintf(message, "Room %d, Node %d", Viewer_object->roomnum, 0 + 1); SendDlgItemMessage( handle, CB_SELECTSTRING,0,(LPARAM) (LPCTSTR) message); } else { strcpy(message, "No Nodes in room"); SendDlgItemMessage( handle, CB_SELECTSTRING,0,(LPARAM) (LPCTSTR) message); } } } else if(ROOMNUM_OUTSIDE(Viewer_object->roomnum)) { if(selection_type == EBVIEW_ROOM || selection_type == EBVIEW_ROOM_AND_NEXT_ROOMS) { int room = BOA_INDEX(Viewer_object->roomnum); int tr = room - Highest_room_index - 1; bn_list *bnlist = BNode_GetBNListPtr(Viewer_object->roomnum); for (int i = 0; i < bnlist->num_nodes; i++) { f_add = true; sprintf(message, "Region %d, Node %d", tr, i + 1); SendDlgItemMessage( handle, CB_ADDSTRING,0,(LPARAM) (LPCTSTR) message); } if(selection_type == EBVIEW_ROOM_AND_NEXT_ROOMS) { int i; int j; int k; for(i = 0; i < BOA_num_connect[tr]; i++) { bool f_found = false; for(j = 0; j < num_next_rooms; j++) { if(next_rooms[j] == BOA_connect[tr][i].roomnum) { f_found = true; break; } } if(!f_found && BOA_connect[tr][i].roomnum >= 0 && !(Rooms[BOA_connect[tr][i].roomnum].flags & RF_EXTERNAL)) { for(k = 0; k < Rooms[BOA_connect[tr][i].roomnum].bn_info.num_nodes; k++) { sprintf(message, "Room %d, Node %d", BOA_connect[tr][i].roomnum, k + 1); SendDlgItemMessage( handle, CB_ADDSTRING,0,(LPARAM) (LPCTSTR) message); } } } } if(f_add) { sprintf(message, "Region %d, Node %d", tr, 0 + 1); SendDlgItemMessage( handle, CB_SELECTSTRING,0,(LPARAM) (LPCTSTR) message); } else { strcpy(message, "No Nodes in region"); SendDlgItemMessage( handle, CB_SELECTSTRING,0,(LPARAM) (LPCTSTR) message); } } } } void CPathPadDialog::OnSetfocusAinCurrentNode() { ResetNodesForComboBox(IDC_AIN_CURRENT_NODE, ENode_view_type); } void CPathPadDialog::OnSetfocusAinOtherNode() { ResetNodesForComboBox(IDC_AIN_OTHER_NODE ,ENode_view_type); } void CPathPadDialog::OnIenavButton() { int node = EBNode_InsertNodeOnEdge(BNode_current_id, BNode_current_room, BNode_other_id, BNode_other_room); if(node >= 0) { vector diff = Viewer_object->pos; EBNode_Move(false, BNode_current_room, node, &diff); World_changed = 1; } } void CPathPadDialog::OnMvtnButton() { vector pos; int roomnum; bn_list *bnlist = BNode_GetBNListPtr(BNode_current_room); if(!bnlist) return; pos = bnlist->nodes[BNode_current_id].pos; if(BNode_current_room >= 0 && BNode_current_room <= Highest_room_index) { roomnum = BNode_current_room; } else { roomnum = GetTerrainRoomFromPos(&pos); } BNode_current_id, ObjSetPos(Viewer_object, &pos, roomnum, NULL, false); World_changed = 1; } void CPathPadDialog::OnAerButton() { bn_list *bnlist = BNode_GetBNListPtr(BNode_current_room); if(!bnlist) return; for(int i = 0; i < bnlist->num_nodes; i++) { EBNode_AutoEdgeNode(i, BNode_current_room); } EBNode_VerifyGraph(); World_changed = 1; } void CPathPadDialog::OnOntvgpButton() { if (Num_game_paths<1) { MessageBox ("There are no paths to operate on."); return; } if (Cur_object_index != -1) // we have a selected object { int p=D3EditState.current_path; int n=D3EditState.current_node; game_path *gp=&GamePaths[p]; gp->pathnodes[n].fvec = Viewer_object->orient.fvec; gp->pathnodes[n].uvec = Viewer_object->orient.uvec; World_changed=1; UpdateDialog(); } }