/* ** AreaEditor - a program for editing SMAUG and ROM area files. ** Author: Nick Gammon ** http://www.gammon.com.au/ ** See Copyright Notice at the end of AreaEditor.h */ #include "stdafx.h" #include "AreaEditor.h" #include "AreaEditorDoc.h" #include "RoomView.h" #include "AddToRoomDlg.h" #include "AreaEditorView.h" #include "defaults.h" #include "MUDProgramView.h" #include "ObjectExtraDescriptionView.h" #include "RoomExitView.h" #include "RoomMapView.h" #include "DeleteXrefDlg.h" // constructor CRoom::CRoom (CRuntimeClass* pViewClass, CAreaEditorDoc * pDoc) : CMUDitem (pViewClass, pDoc) { name = strRoomDefaultName; description = strRoomDefaultDescription; vnum = 0; room_flags = 0; sector_type = 0; // inside tele_vnum = 0; tele_delay = 0; tunnel = 0; heal_rate = 0; // ROM mana_rate = 0; // ROM } // end of constructor void CRoom::ChangeRHview (CAreaEditorView * pLHview, CView * pwhichView) { CRoomView * pView = (CRoomView *) pwhichView; ASSERT(pView->IsKindOf(RUNTIME_CLASS(CRoomView))); pView->m_room = this; pView->m_pLHview = pLHview; pView->CreatePages (); // add the tab control pages pView->ShowPages (m_pDoc); } CString CRoom::Summary (void) { return CFormat ("#%i %s", vnum, (LPCTSTR) name); } CRoom::~CRoom () { // get rid of programs inside room for (POSITION progPos = programlist.GetHeadPosition (); progPos; ) delete programlist.GetNext (progPos); programlist.RemoveAll (); // pointers are deleted, remove list items // get rid of exits inside room for (POSITION exitPos = exitlist.GetHeadPosition (); exitPos; ) delete exitlist.GetNext (exitPos); exitlist.RemoveAll (); // pointers are deleted, remove list items // get rid of maps inside room for (POSITION mapPos = maplist.GetHeadPosition (); mapPos; ) delete maplist.GetNext (mapPos); maplist.RemoveAll (); // pointers are deleted, remove list items // get rid of extra descriptions inside room for (POSITION extraPos = extralist.GetHeadPosition (); extraPos; ) delete extralist.GetNext (extraPos); extralist.RemoveAll (); // pointers are deleted, remove list items } // end of destructor void CRoom::Delete (void) { // look for things that refer to *this* room and tell them about it CDeleteXrefDlg dlg; CMUDitemList xrefList; CMUDitemList xrefOwnerList; CRoom * room; CExit * exit; CMUDitem * noitem = NULL; dlg.m_pxrefList = &xrefList; dlg.m_pxrefOwnerList = &xrefOwnerList; dlg.m_strAboutToDelete = Summary (); for (POSITION RoomPos = m_pDoc->m_RoomList.GetHeadPosition (); RoomPos; ) { room = m_pDoc->m_RoomList.GetNext (RoomPos); if (room == this) continue; // don't delete ourselves twice! for (POSITION ExitPos = room->exitlist.GetHeadPosition (); ExitPos; ) { exit = room->exitlist.GetNext (ExitPos); if (exit->vnum != vnum) continue; // wrong vnum - keep going xrefOwnerList.AddTail (room); // owner of room xrefList.AddTail (exit); // which exit } // end of checking each exit } // end of checking each room for (POSITION ResetPos = m_pDoc->m_ResetList.GetHeadPosition (); ResetPos; ) { CReset * reset = m_pDoc->m_ResetList.GetNext (ResetPos); switch (reset->command) { case 'M': // this reset puts a mob in the room if (reset->arg3 == vnum) { xrefOwnerList.AddTail (noitem); // no owner of reset xrefList.AddTail (reset); // which reset } break; case 'O': // this reset puts an object in the room if (reset->arg3 == vnum) { xrefOwnerList.AddTail (noitem); // no owner of reset xrefList.AddTail (reset); // which reset } break; case 'D': // this reset opens/shuts a door in the room if (reset->arg1 == vnum) { xrefOwnerList.AddTail (noitem); // no owner of reset xrefList.AddTail (reset); // which reset } break; case 'R': // randomize exits in the room if (reset->arg1 == vnum) { xrefOwnerList.AddTail (noitem); // no owner of reset xrefList.AddTail (reset); // which reset } break; } // end of switch } // end of processing each reset if (!xrefList.IsEmpty ()) // don't bother if no references if (dlg.DoModal () != IDOK) return; // they changed their mind (hope it works better!) // delete referencing items for (POSITION refPos = xrefList.GetHeadPosition (); refPos; ) xrefList.GetNext (refPos)->Delete (); // delete programs inside room for (POSITION progPos = programlist.GetHeadPosition (); progPos; ) programlist.GetNext (progPos)->Delete (); programlist.RemoveAll (); // pointers are deleted, remove list items // delete exits inside room for (POSITION exitPos = exitlist.GetHeadPosition (); exitPos; ) exitlist.GetNext (exitPos)->Delete (); exitlist.RemoveAll (); // pointers are deleted, remove list items // delete maps inside room for (POSITION mapPos = maplist.GetHeadPosition (); mapPos; ) maplist.GetNext (mapPos)->Delete (); maplist.RemoveAll (); // pointers are deleted, remove list items // delete extra descriptions inside room for (POSITION extraPos = extralist.GetHeadPosition (); extraPos; ) extralist.GetNext (extraPos)->Delete (); extralist.RemoveAll (); // pointers are deleted, remove list items // delete from list of rooms m_pDoc->m_RoomList.RemoveAt (m_pDoc->m_RoomList.Find (this, NULL)); CMUDitem::Delete (); } // end of CRoom::Delete CMUDitem * CRoom::Add (CAreaEditorView * pView, const bool bSelect) { // add program, affect or extra to this room CAddToRoomDlg dlg; dlg.m_iAddType = 0; if (dlg.DoModal () != IDOK) return NULL; // they cancelled, the bastards! CMUDprogram * prog; HTREEITEM hdlItem; CMUDitem * pItem = NULL; switch (dlg.m_iAddType) { case 0: // Extra description pItem = AddDescription (pView); break; case 1: // Exit pItem = AddExit (pView); break; case 2: // Map pItem = AddMap (pView); break; case 3: // Program prog = new CMUDprogram (RUNTIME_CLASS(CMUDProgramView), m_pDoc); programlist.AddHead (prog); // and add it to our list hdlItem = pView->AddTreeItem (prog, m_hdlTreeItem); m_pDoc->SetModifiedFlag (); pItem = prog; break; } if (bSelect) pItem->GoTo (); return pItem; } // end of CRoom::Add CString CRoom::AddDescription (void) // description of what add does { return "description/exit/map/program"; } // end of CRoom::AddDescription void CRoom::SubItemDeleted (CMUDitem * pItem) { POSITION pos; // a program has been deleted? if (pos = programlist.Find (pItem, NULL)) programlist.RemoveAt (pos); // an exit has been deleted? if (pos = exitlist.Find (pItem, NULL)) exitlist.RemoveAt (pos); // a map been deleted? if (pos = maplist.Find (pItem, NULL)) maplist.RemoveAt (pos); // an extra description has been deleted? if (pos = extralist.Find (pItem, NULL)) extralist.RemoveAt (pos); } // end of CRoom::SubItemDeleted static int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) { CMUDprogram * prog1 = (CMUDprogram *) lParam1; CMUDprogram * prog2 = (CMUDprogram *) lParam2; if (prog1->iSortSeq < prog2->iSortSeq) return -1; else if (prog1->iSortSeq > prog2->iSortSeq) return 1; else return 0; } // end of CompareFunc // add for a program adds one after the current one CMUDprogram * CRoom::AddProgram (CAreaEditorView * pView, CMUDitem * pItem, const bool bSelect) { TV_SORTCB sortCB; int iSeq = 0; CMUDprogram * prog = new CMUDprogram (RUNTIME_CLASS(CMUDProgramView), m_pDoc); if (pItem) { POSITION pos = programlist.Find (pItem, NULL); programlist.InsertAfter (pos, prog); // and add it to our list } else programlist.AddHead (prog); // add at head HTREEITEM hdlprogItem = pView->AddTreeItem (prog, m_hdlTreeItem); sortCB.hParent = m_hdlTreeItem; sortCB.lpfnCompare = CompareFunc; sortCB.lParam = 0; // give each prog a sequence so we can sort them into list order for (POSITION progPos = programlist.GetHeadPosition (); progPos; ) programlist.GetNext (progPos)->iSortSeq = iSeq++; m_pTreeCtrl->SortChildrenCB (&sortCB); // sort into proper order if (bSelect) m_pTreeCtrl->Select (hdlprogItem, TVGN_CARET); // select it m_pDoc->SetModifiedFlag (); return prog; } // end of CRoom::AddProgram // add for a new exit CExit * CRoom::AddExit (CAreaEditorView * pView) { CExit * exit = new CExit (RUNTIME_CLASS(CRoomExitView), m_pDoc); exitlist.AddTail (exit); // and add it to our list pView->AddTreeItem (exit, m_hdlTreeItem); m_pDoc->SetModifiedFlag (); return exit; } // end of CRoom::AddExit // add for a new description CExtraDescription * CRoom::AddDescription (CAreaEditorView * pView) { CExtraDescription * extra = new CExtraDescription (RUNTIME_CLASS(CObjectExtraDescriptionView), m_pDoc); extralist.AddHead (extra); // and add it to our list pView->AddTreeItem (extra, m_hdlTreeItem); m_pDoc->SetModifiedFlag (); return extra; } // end of CRoom::AddDescription // add for a new map CRoomMap * CRoom::AddMap (CAreaEditorView * pView) { CRoomMap * map = new CRoomMap (RUNTIME_CLASS(CRoomMapView), m_pDoc); maplist.AddHead (map); // and add it to our list pView->AddTreeItem (map, m_hdlTreeItem); m_pDoc->SetModifiedFlag (); return map; } // end of CRoom::AddMap // do a search for this item BOOL CRoom::Search (const CString strWanted, const int iFindType, const BOOL bMatchCase) { CString strFound; // switch on find type switch (iFindType) { case eFindVnum: if (isalpha (strWanted [0])) { if (strWanted [0] != 'R') return FALSE; // they aren't looking for rooms return atoi (strWanted.Mid (1)) == vnum; } return atoi (strWanted) == vnum; case eFindDetail: SEARCH (name); SEARCH (description); SEARCH (convert_room_flags (room_flags)); SEARCH (RoomSectorList.ReturnName (sector_type, false)); return FALSE; default: return CMUDitem::Search (strWanted, iFindType, bMatchCase); } // end of switch } // end of CRoom::Search void CRoom::Duplicate (CAreaEditorView * pView) { CRoom * room = m_pDoc->AddRoom (pView, false); if (!room) return; // could not create a new room (no vnums available?) room->Copy (this); room->m_pTreeCtrl->SetItemText (room->m_hdlTreeItem, room->Summary ()); // now duplicate programs in the room CMUDprogram * oldProg, * newProg; CString strMessage; for (POSITION progPos = programlist.GetHeadPosition (); progPos; ) { oldProg = programlist.GetNext (progPos); // get a program newProg = new CMUDprogram (RUNTIME_CLASS(CMUDProgramView), m_pDoc); // make a new one room->programlist.AddTail (newProg); // add to new room pView->AddTreeItem (newProg, room->m_hdlTreeItem); // add to room's tree item newProg->Copy (oldProg); // check syntax so cross-referencing will be correct CheckCommandSyntax (newProg->comlist, strMessage, newProg->xref_rooms, newProg->xref_objects, newProg->xref_rooms); newProg->m_pTreeCtrl->SetItemText (newProg->m_hdlTreeItem, newProg->Summary ()); } // end of processing each program // now duplicate extra descriptions for the room CExtraDescription * oldDesc, * newDesc; for (POSITION DescPos = extralist.GetHeadPosition (); DescPos; ) { oldDesc = extralist.GetNext (DescPos); // get a description newDesc = new CExtraDescription (RUNTIME_CLASS(CObjectExtraDescriptionView), m_pDoc); // make a new one room->extralist.AddTail (newDesc); // add to new room pView->AddTreeItem (newDesc, room->m_hdlTreeItem); // add to room's tree item newDesc->Copy (oldDesc); newDesc->m_pTreeCtrl->SetItemText (newDesc->m_hdlTreeItem, newDesc->Summary ()); } // end of processing each description // now duplicate exits for the room CExit * oldExit, * newExit; for (POSITION ExitPos = exitlist.GetHeadPosition (); ExitPos; ) { oldExit = exitlist.GetNext (ExitPos); // get an exit newExit = new CExit (RUNTIME_CLASS(CRoomExitView), m_pDoc); // make a new one room->exitlist.AddTail (newExit); // add to new room pView->AddTreeItem (newExit, room->m_hdlTreeItem); // add to room's tree item newExit->Copy (oldExit); newExit->m_pTreeCtrl->SetItemText (newExit->m_hdlTreeItem, newExit->Summary ()); } // end of processing each exit // now duplicate maps for the room CRoomMap * oldMap, * newMap; for (POSITION MapPos = maplist.GetHeadPosition (); MapPos; ) { oldMap = maplist.GetNext (MapPos); // get an Map newMap = new CRoomMap (RUNTIME_CLASS(CRoomMapView), m_pDoc); // make a new one room->maplist.AddTail (newMap); // add to new room pView->AddTreeItem (newMap, room->m_hdlTreeItem); // add to room's tree item newMap->Copy (oldMap); newMap->m_pTreeCtrl->SetItemText (newMap->m_hdlTreeItem, newMap->Summary ()); } // end of processing each Map room->GoTo (); // select it now it has been set up } // end of CRoom::Duplicate #define DUPLICATE(arg) arg = RHside->arg // copy function for duplicating rooms void CRoom::Copy (const CRoom * const RHside) { DUPLICATE (name); DUPLICATE (description); // nb - do not duplicate vnum! - that must be unique DUPLICATE (room_flags); DUPLICATE (sector_type); DUPLICATE (tele_vnum); DUPLICATE (tele_delay); DUPLICATE (tunnel); } // end of CRoom::Copy