/**************************************************************************** * [S]imulated [M]edieval [A]dventure multi[U]ser [G]ame | * * -----------------------------------------------------------| \\._.// * * SmaugWiz (C) 1998 by Russ Pillsbury (Windows NT version) | (0...0) * * -----------------------------------------------------------| ).:.( * * SMAUG (C) 1994, 1995, 1996 by Derek Snider | {o o} * * -----------------------------------------------------------| / ' ' \ * * SMAUG code team: Thoric, Altrag, Blodkai, Narn, Haus, |~'~.VxvxV.~'~* * Scryn, Swordbearer, Rennard, Tricops, and Gorog. | * * ------------------------------------------------------------------------ * * Merc 2.1 Diku Mud improvments copyright (C) 1992, 1993 by Michael * * Chastain, Michael Quan, and Mitchell Tse. * * Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik Staerfeldt, Tom Madsen, and Katja Nyboe. * ****************************************************************************/ // rooms.cpp #include "stdafx.h" #include "smaug.h" #include "Smaugx.h" #include "area.h" #include "objects.h" #include "resets.h" #include "rooms.h" #include "Exits.h" // Create a new room (for online building) -Thoric CRoomIndexData *make_room (int vnum) { CRoomIndexData *pRoomIndex; pRoomIndex = new CRoomIndexData (vnum); pRoomIndex->SetName (STRALLOC ("Floating in a void")); pRoomIndex->SetDescription (STRALLOC ("")); pRoomIndex->SetPrototype (); pRoomIndex->sector_type = 1; RoomTable.Add (pRoomIndex, vnum); return pRoomIndex; } void CRoomIndexData::Read (FILE* fp, BOOL bBug) { char *pLine; char ch; pLine = fread_line (fp); m_pName = ParseString (pLine, fp); pLine = fread_line (fp); m_pDescription = ParseString (pLine, fp); pLine = fread_line (fp); int x1 = 0, x2 = 0, x3 = 0, x4 = 0, x5 = 0, x6 = 0; sscanf (pLine, "%d %d %d %d %d", &x1, &x2, &x3, &x4, &x5); m_flags = x1; sector_type = x2; tele_delay = x3; tele_vnum = x4; tunnel = x5; if (sector_type < 0 || sector_type == SECT_MAX) { bug ("CRoomIndexData::Read: vnum %d has bad sector_type %d.", vnum, sector_type); sector_type = 1; } light = 0; first_exit = NULL; last_exit = NULL; for (;;) { pLine = fread_line (fp); int letter = *pLine++; if (letter == 'S') break; if (letter == 'D') { CExitData *pexit; int locks; int door = ParseNumber (pLine); if (door < 0 || door > 10) { bug ("CRoomIndexData::Read: Room %d has bad door number %d.", vnum, door); if (bBug) ThrowSmaugException (SE_ROOM); } else { pexit = make_exit (this, NULL, door); pLine = fread_line (fp); pexit->description = ParseString (pLine, fp); pLine = fread_line (fp); pexit->keyword = ParseString (pLine, fp); pLine = fread_line (fp); x1=x2=x3=x4=x5=x6=0; sscanf (pLine, "%d %d %d %d %d %d", &x1, &x2, &x3, &x4, &x5, &x6); locks = x1; pexit->key = x2; pexit->vnum = x3; pexit->vdir = door; pexit->distance = x4; pexit->pulltype = x5; pexit->pull = x6; switch (locks) { case 1: pexit->SetDoor (); break; case 2: pexit->SetDoor (); pexit->SetPickProof (); break; default: pexit->SetFlags (locks); } } } else if (letter == 'E') { CExtraDescrData *ed = new CExtraDescrData; pLine = fread_line (fp); ed->keyword = ParseString (pLine, fp); pLine = fread_line (fp); ed->description = ParseString (pLine, fp); ExDesList.AddTail (ed); ++top_ed; } else if (letter == 'M'); // ignore maps else if (letter == '>') { --pLine; ReadPrograms (pLine, fp); } else if (letter == 'R') { // resets ch = 0; x1=x2=x3=x4=x5=0; sscanf (pLine, " %c %d %d %d %d %d", &ch, &x1, &x2, &x3, &x4, &x5); CResetData *pReset = new CResetData (ch, x1, x2, x3, x4, x5); ResetList.AddTail (pReset); } else { bug ("CRoomIndexData::Read: vnum %d has flag '%c' not 'DES'.", vnum, letter); shutdown_mud ("Room flag not DES"); ThrowSmaugException (SE_ROOM); } } } // This procedure is responsible for reading any in_file ROOMprograms. void CRoomIndexData::ReadPrograms (char* pLine, FILE *fp) { char letter; BOOL done = FALSE; if ((letter = *pLine++) != '>') { bug ("Load_rooms: vnum %d ROOMPROG char", vnum); ThrowSmaugException (SE_ROOMPROG); } CMobProgData *pRprg = new CMobProgData; RoomPrgList.AddTail (pRprg); while (! done) { pRprg->type = mprog_name_to_type (ParseWord (pLine)); switch (pRprg->type) { case ERROR_PROG: bug ("Load_rooms: vnum %d ROOMPROG type.", vnum); ThrowSmaugException (SE_ROOMPROG); break; case IN_FILE_PROG: bug ("Error: Room %d SmaugWiz does not handle " "file Room Progs.", vnum); ThrowSmaugException (SE_ROOMPROG); break; default: m_Progtypes.SetBit (pRprg->type); pRprg->arglist = ParseString (pLine, fp); pLine = fread_line (fp); pRprg->comlist = ParseString (pLine, fp); pLine = fread_line (fp); switch (letter = *pLine++) { case '>': pRprg = new CMobProgData; RoomPrgList.AddTail (pRprg); break; case '|': done = TRUE; break; default: bug ("Load_rooms: Room %d bad ROOMPROG.", vnum); ThrowSmaugException (SE_ROOMPROG); break; } break; } } } void CRoomIndexData::Write (FILE *fp) { fprintf (fp, "#%d\n", vnum); fprintf (fp, "%s~\n", GetName ()); fprintf (fp, "%s~\n", strip_cr (GetDescription ())); fprintf (fp, "%d %d %d %d %d\n", GetRoomFlags (), sector_type, tele_delay, tele_vnum, tunnel); CExitData *pExit = first_exit; for ( ; pExit; pExit = pExit->GetNext ()) { if (pExit->IsPortal ()) // don't fold portals continue; fprintf (fp, "D%d\n", pExit->vdir); fprintf (fp, "%s~\n", strip_cr (pExit->description)); fprintf (fp, "%s~\n", strip_cr (pExit->keyword)); pExit->ClrBashed (); fprintf (fp, "%s %d %d %d\n", pExit->PrintFlagVector (), pExit->key, pExit->vnum, pExit->distance); } POSITION pos = ExDesList.GetHeadPosition (); while (pos) { CExtraDescrData &Ed = *(CExtraDescrData*) ExDesList.GetNext (pos); fprintf (fp, "E\n%s~\n%s~\n", Ed.keyword, strip_cr (Ed.description)); } if (! RoomPrgList.IsEmpty ()) { POSITION pos = RoomPrgList.GetHeadPosition (); while (pos) { CMobProgData &Rprg = *(CMobProgData*) RoomPrgList.GetNext (pos); fprintf (fp, "> %s %s~\n%s~\n", mprog_type_to_name (Rprg.type), Rprg.arglist, strip_cr (Rprg.comlist)); } fprintf (fp, "|\n"); } if (! ResetList.IsEmpty ()) { POSITION pos = ResetList.GetHeadPosition (); while (pos) { CResetData &Reset = *ResetList.GetNext (pos); fprintf (fp, "R %c %d %d %d %d %d\n", Reset.command, Reset.extra, Reset.mob, Reset.arg1, Reset.arg2, Reset.arg3); } } fprintf (fp, "S\n"); } // clean out a room (leave list pointers intact) -Thoric void CRoomIndexData::Clean () { STRFREE (m_pDescription); m_pDescription = NULL; STRFREE (m_pName); m_pName = NULL; while (! ExDesList.IsEmpty ()) delete (CExtraDescrData*) ExDesList.RemoveTail (); ExDesList.RemoveAll (); ResetList.RemoveAll (); CExitData *pexit, *pexit_next; for (pexit = first_exit; pexit; pexit = pexit_next) { pexit_next = pexit->GetNext (); STRFREE (pexit->keyword); STRFREE (pexit->description); delete pexit; top_exit--; } first_exit = NULL; last_exit = NULL; m_flags = 0; sector_type = 0; light = 0; } void CRoomIndexData::FixExits (BOOL bBoot) { CExitData *pExit, *pNext; BOOL bAllBad = TRUE; for (pExit = first_exit; pExit; pExit = pNext) { pNext = pExit->GetNext (); pExit->rvnum = vnum; CRoomIndexData *pToRoom = RoomTable.GetRoom (pExit->vnum); if (pExit->vnum > 0 && pToRoom) { pExit->SetToRoom (pToRoom); // set exit pointer pExit->ClrDisabled (); bAllBad = FALSE; // found at least 1 good exit } else { if (bBoot) then BootLog ( "Fix_exits: %s, room %d, exit %s leads to bad vnum (%d)", NCCP GetArea ()->GetName (), vnum, dir_name [pExit->vdir], pExit->vnum); bug ("Disabling %s exit in room %d", dir_name [pExit->vdir], vnum); pExit->SetDisabled (); // extract_exit (this, pExit); } } if (bAllBad) SetNoMob (); } CRoomIndexData::~CRoomIndexData () { // Free up the ram for all strings attached to the room. STRFREE (m_pName); STRFREE (m_pDescription); while (! ExDesList.IsEmpty ()) delete (CExtraDescrData*) ExDesList.RemoveTail (); ExDesList.RemoveAll (); CExitData *pNexit, *pExit = first_exit; while (pExit) { pNexit = pExit->GetNext (); delete pExit; pExit = pNexit; } CMobProgActList *pNpact, *pPact = mpact; while (pPact) { pNpact = pPact->GetNext (); delete pPact; pPact = pNpact; } while (! RoomPrgList.IsEmpty ()) delete (CMobProgData*) RoomPrgList.RemoveTail (); RoomPrgList.RemoveAll (); } // Translates room virtual number to its room index struct. // Hash table lookup. CRoomIndexData *CRoomTable::GetRoom (int vnum, BOOL bBug /* = FALSE */) { CRoomIndexData *pIdx; if (vnum < 0) vnum = 0; for (pIdx = GetFirst (vnum); pIdx; pIdx = pIdx->GetNext ()) if (pIdx->vnum == vnum) return pIdx; if (bBug) bug ("OIdxTable.GetObj: bad vnum %d.", vnum); return NULL; } void CRoomTable::Remove (CRoomIndexData *room) { CRoomIndexData *tmp, *prev = NULL; int iHash = GetHash (room->vnum); // Take the room index out of the hash list. for (tmp = m_rt [iHash]; tmp && tmp != room; tmp = tmp->GetNext ()) prev = tmp; if (tmp) { if (prev) prev->SetNext (room->GetNext ()); else m_rt [iHash] = room->GetNext (); --m_Count; } } void CRoomTable::Add (CRoomIndexData *pIndex, int vnum) { pIndex->SetNext (GetFirst (vnum)); SetFirst (GetHash (vnum), pIndex); ++m_Count; } void CRoomTable::RemoveAll () { CRoomIndexData *pNidx, *pIdx; for (int hash = 0; hash < MAX_KEY_HASH; ++hash) { pIdx = GetFirstByHash (hash); while (pIdx) { pNidx = pIdx->GetNext (); delete pIdx; pIdx = pNidx; } } Empty (); // clear pointers and count } #ifdef _DEBUG void CRoomIndexData::Dump (CDumpContext& dc) const { CObject::Dump (dc); dc << "CRoomIndexData Name: " << GetName () << "\n"; } #endif