/* ....[@@@..[@@@..............[@.................. MUD++ is a written from ....[@..[@..[@..[@..[@..[@@@@@....[@......[@.... scratch multi-user swords and ....[@..[@..[@..[@..[@..[@..[@..[@@@@@..[@@@@@.. sorcery game written in C++. ....[@......[@..[@..[@..[@..[@....[@......[@.... This server is an ongoing ....[@......[@..[@@@@@..[@@@@@.................. development project. All ................................................ contributions are welcome. ....Copyright(C).1995.Melvin.Smith.............. Enjoy. ------------------------------------------------------------------------------ Melvin Smith (aka Fusion) msmith@hom.net MUD++ development mailing list mudpp@van.ml.org ------------------------------------------------------------------------------ editroom.cc */ #include "config.h" #include "string.h" #include "llist.h" #include "index.h" #include "room.h" #include "repop.h" #include "hash.h" #include "server.h" #include "bit.h" #include "edit.h" #include "area.h" #include "pc.h" #include "object.h" #include "global.h" #include "trigs.h" void RoomEditor::command( const String & arg ) { String str; String str2; String arg1; String arg2; String arg3; Area * pArea; Exit *pExit; struct TriggerData * td; int val1; int i; // If in text editor, pass args on to text editor if( text ) { // If text editor is finished, do something with its content // or cancel. text->command( arg ); if( text->done() ) { if( text->getState() == ED_CANCEL ) { delete text; text = 0; state = ED_NONE; return; } switch( state ) { case ED_DESC: room->setDesc( text->asStr() ); room->getArea()->setDirtyBit(); delete text; text = 0; state = ED_NONE; return; default: delete text; text = 0; state = ED_NONE; return; } } return; } else if( (bool)filename ) { char buf[ 8092 ]; InputFile inf( filename ); if( !inf ) { pc->out( "System error. Can't read temp file.\n\r" ); filename.clr(); return; } inf.getstring( buf ); switch ( state ) { case ED_DESC: room->setDesc( buf ); room->getArea()->setDirtyBit(); state = ED_NONE; break; default: state = ED_NONE; break; } inf.close(); remove( filename.chars() ); filename.clr(); return; } if( !(bool)arg || arg == "\n" ) { room->describeItself(str); pc->out( str ); } else { Index index1; Index index2; int dir; int revdir; Room *pRoom; arg.startArgs(); arg1 = arg.getArg(); arg2 = arg.getArgRest(); area = room->getArea(); if( arg1 == "name" ) { room->setName( arg2 ); pc->out( "Name set to '" ); pc->out( arg2 ); pc->out( "'\n\r" ); area->setDirtyBit(); return; } else if( arg1 == "desc" ) { if( arg2[0] == '+' ) { arg2.shiftLeft(); str << room->getDesc() << "\n\r" << arg2; room->setDesc( str ); } else if ( arg2 ) { str << arg2 << "\n\r"; room->setDesc(str); } else { editText( room->getDesc() ); //state = ED_DESC; return; } area->setDirtyBit(); return; } else if( arg1 == "index" ) { area->removeRoom( room ); room->setKey( arg2 ); area->addRoom( room ); area->setDirtyBit(); return; } else if( arg1 == "bitmask" ) { if( !(bool)arg2 ) { pc->out( "Set which bit in bitmask?\n\r" ); return; } if( ( val1 = lookupRoomBit( arg2 ) ) ) { SET_BIT( room_bits, val1 ); pc->out( "Bit toggled in default bitmask.\n\r" ); return; } } else if( arg1 == "copy" ) { if( !(bool)arg2 ) { pc->out( "Copy which room?\n\r" ); return; } if( !( pRoom = lookupRoom( arg2 ) ) ) { pc->out( "No such room to copy.\n\r" ); return; } room->setName( pRoom->getName() ); room->setDesc( pRoom->getDesc() ); area->setDirtyBit(); return; } else if( arg1 == "new" || arg1 == "create" ) { if( !(bool)arg2 ) { pc->out( "Usage: new <index>\n\r" ); return; } index = arg2.getArgRest(); if( (bool)index.getScope() ) { if( !( pArea = lookupArea( index.getScope() ) ) ) { pc->out( "No such area.\n\r" ); return; } } else pArea = area; if( !( pRoom = pArea->lookupRoom( index.getKey() ) ) ) { pRoom = new Room( pArea ); pRoom->setName( "No name" ); pRoom->setDesc( "No description" ); pRoom->setKey( index.getKey() ); // Editor is a friend class of Room memcpy( pRoom->room_bits, room_bits, sizeof( room_bits[0] ) * MAX_ROOM_BIT_FIELDS ); pArea->addRoom( pRoom ); pc->out( "New room created.\n\r" ); pArea->setDirtyBit(); room->rmCharInv( pc ); pRoom->addCharInv( pc ); room = pRoom; area = pArea; } else pc->out( "That room already exists.\n\r" ); return; } else if( arg1 == "save" ) { area->save(); area->rmDirtyBit(); pc->out( "Zone saved.\n\r" ); return; } else if( arg1 == "goto" ) { pc->do_goto( arg2 ); setRoom( pc->inRoom() ); return; } else if( arg1 == "repop" ) { if( !(bool)arg2 || arg2 == "help" ) { pc->out( "repop mob <npc-index> {chance}\n\r" ); pc->out( "repop <#> give <obj-index> {chance}\n\r" ); pc->out( "repop <#> eq <obj-index> {chance}\n\r" ); pc->out( "repop obj <obj-index> {chance}\n\r" ); pc->out( "repop <#> put <obj-index> {chance}\n\r" ); pc->out( "repop <#> nest <obj-index> {chance}\n\r" ); return; } else if( arg2 == "list" || arg2 == "show" ) { pc->do_repops( "list" ); return; } else { parseRepop( arg2 ); return; } } else if( arg1 == "list" ) { /* Room * pRoom; for_each( area->roomIndex, pRoom ) str.sprintfAdd( "%15s - %s\n\r", pRoom->getKey().chars(), pRoom->getName().chars() ); pc->out( str ); */ pc->do_rfind(arg2); return; } else if( arg1 == "help" || arg1 == "?" ) { pc->view( "../help/redit.hlp" ); pc->page( "" ); return; } else if( arg1 == "room-bits" ) { pc->view( "../help/room-bits.hlp" ); pc->page( "" ); return; } else if ( arg1 == "trigadd" ) { void * fun; arg2.startArgs(); arg1 = arg2.getArg(); str2 = arg2.getArg(); val1 = lookupBit( rtrig_types, arg1 ); if ( val1 == 0 ) { pc->out("No such bit.\n\r"); return; } fun = lookupRtrig( val1, str2.chars() ); if ( fun == NULL ) { pc->out("No such function for that type of trigger.\n\r"); return; } for_each(room->triggers, td ) { if ( td->type == val1 ) break; } if ( td != NULL ) { pc->out("Replacing old trigger.\n\r"); room->removeTrigger(td); } td = new (struct TriggerData); td->type = val1; td->fun = fun; room->addTrigger(td); pc->out("Trigger added.\n\r"); return; } else if ( arg1 == "trigdel" ) { val1 = lookupBit( rtrig_types, arg2 ); if ( val1 == 0 ) { pc->out("No such bit.\n\r"); return; } for_each(room->triggers, td ) { if ( td->type == val1 ) break; } if ( td == NULL ) { pc->out("This room has no such trigger.\n\r"); return; } room->removeTrigger(td); pc->out("Trigger removed.\n\r"); return; } else if ( arg1 == "triglist" ) { if ( !(bool)arg2 ) { // list types of triggers str << "Trigger types for Rooms " <<endl; for ( i=1; rtrig_types[i].name; i++ ) { str << rtrig_types[i].name << endl; } pc->out(str); return; } else { // list triggers for given type const char * name; val1 = lookupBit( rtrig_types, arg2 ); if ( val1 == 0 ) { pc->out("No such bit.\n\r"); return; } str << "Triggers for type " << arg2 << ":" << endl; for ( i = 0; ; i++ ) { name = getRtrigName(val1, i); if ( !name ) break; str << name << endl; } pc->out(str); return; } } if( ( dir = getDir( (const char *)arg1 ) ) != DIR_UNDEFINED ) { revdir = getRevDir( dir ); if( !(bool)arg2 ) { if( !( pRoom = room->toRoom( dir ) ) ) { pc->out( "No exit in that direction.\n\r" ); return; } pc->out( "Moving to room " ); pc->out( pRoom->getKey() ); pc->out( ".\n\r" ); room->rmCharInv( pc ); pRoom->addCharInv( pc ); room = pRoom; area = pRoom->getArea(); return; } else { // Break into 3rd arg arg2.startArgs(); arg3 = arg2.getArg(); if( arg3 == "dig" || arg3 == "room" ) { if( ( pRoom = room->toRoom( dir ) ) ) { pc->out( "Already an exit in that direction.\n\r" ); return; } if( !(bool)arg2.getArgRest() ) { pc->out( "No room specified.\n\r" ); return; } index = arg2.getArgRest(); if( (bool)index.getScope() && !( pArea = lookupArea( index.getScope() ) ) ) { pc->out( "No such area.\n\r" ); return; } else pArea = area; index.setScope( pArea->getKey() ); if( !( pRoom = pArea->lookupRoom( index.getKey() ) ) ) { pRoom = new Room( area ); pRoom->setName( "No name" ); pRoom->setDesc( "No description" ); pRoom->setKey( index.getKey() ); // RoomEditor is a friend class of Room memcpy( pRoom->room_bits, room_bits, sizeof( room_bits[0] ) * MAX_ROOM_BIT_FIELDS ); pArea->addRoom( pRoom ); pc->out( "New room created.\n\r" ); } else if( arg3 == "room" ) { pc->out( "Can't create, that room already exists.\n\r" ); return; } else if( pRoom->toRoom( revdir ) ) { pc->out( "Exit exists on other side.\n\r" ); return; } // Convert what was 'e' to 'east' for constructor //arg1 = lookupDirName( dir ); pExit = new Exit( "", index, "", 0, "" ); room->addExit( pExit, dir ); room->hardLink(); // Link reverse side index.setScope( room->getArea()->getKey() ); index.setKey( room->getKey() ); pExit = new Exit( "", index, "", 0, "" ); pRoom->addExit( pExit, revdir ); pRoom->hardLink(); pc->out( "Exit linked.\n\r" ); area->setDirtyBit(); if( arg3 == "dig" ) { room->rmCharInv( pc ); pRoom->addCharInv( pc ); room = pRoom; area = pArea; } return; } if( arg3 == "link" || arg3 == "to" ) { if( ( pRoom = room->toRoom( dir ) ) ) { pc->out( "Already an exit in that direction.\n\r" ); return; } if( !(bool)arg2.getArgRest() ) { pc->out( "No room specified.\n\r" ); return; } index = arg2.getArgRest(); if( (bool)index.getScope() ) { if( !( pArea = lookupArea( index.getScope() ) ) ) { pc->out( "No such area.\n\r" ); return; } } else pArea = area; index.setScope( pArea->getKey() ); if( !( pRoom = pArea->lookupRoom( index.getKey() ) ) ) { pc->out( "No such room.\n\r" ); return; } if( pRoom->toRoom( revdir ) ) { pc->out( "Exit exists on other side.\n\r" ); return; } pExit = new Exit( "", index, "", 0, "" ); room->addExit( pExit, dir ); room->hardLink(); // Link reverse side index.setScope( room->getArea()->getKey() ); index.setKey( room->getKey() ); pExit = new Exit( "", index, "", 0, "" ); pRoom->addExit( pExit, revdir ); pRoom->hardLink(); pc->out( "Exit linked.\n\r" ); area->setDirtyBit(); return; } else if( arg3 == "delete" ) { if( !room->getExit( dir ) ) { pc->out( "No exit in that direction.\n\r" ); return; } room->toRoom( dir )->deleteExit( revdir ); room->deleteExit( dir ); pc->out( "Exit deleted.\n\r" ); area->setDirtyBit(); return; } else if( arg3 == "name" ) { if( !room->getExit( dir ) ) { pc->out( "No exit in that direction.\n\r" ); return; } room->getExit( dir )->setName( arg2.getArgRest() ); area->setDirtyBit(); pc->out( "Exit name set.\n\r" ); return; } else if( arg3 == "desc" || arg3 == "description" ) { if( !room->getExit( dir ) ) { pc->out( "No exit in that direction.\n\r" ); return; } room->getExit( dir )->setDesc( arg2.getArgRest() ); area->setDirtyBit(); pc->out( "Exit description set.\n\r" ); return; } if( ( val1 = lookupExitBit( arg3 ) ) ) { if( !room->getExit( dir ) ) { pc->out( "No exit in that direction.\n\r" ); return; } room->getExit( dir )->toggleExitBit( val1 ); area->setDirtyBit(); pc->out( "Exit bit toggled.\n\r" ); return; } } } if( ( val1 = lookupSector( arg1 ) ) ) { room->setSector( val1 ); pc->out( "Sector type set.\n\r" ); area->setDirtyBit(); return; } if( ( val1 = lookupRoomBit( arg1 ) ) ) { room->toggleRoomBit( val1 ); pc->out( "Room bit toggled.\n\r" ); area->setDirtyBit(); return; } pc->out( "Invalid command.\n\r" ); } } void RoomEditor::parseRepop( const String & arg ) { String str; String arg1; String arg2; String arg3; int chance = 100; int slot = 0; Repop * ptrRepop; arg.startArgs(); arg1 = arg.getArg(); arg2 = arg.getArg(); arg3 = arg.getArg(); if( arg1.isNumber() ) { if( ( slot = arg1.asInt() ) <= 0 ) { pc->out( "Repop slot must be a positive non-zero number.\n\r" ); return; } arg1 = arg2; arg2 = arg3; arg3 = arg.getArg(); if( !(bool)arg1 ) { str << "Current repop slot set to " << slot << ".\n\r"; pc->out( str ); last_slot = slot; return; } } else slot = last_slot + 1; if( arg1 == "del" || arg1 == "delete" || arg1 == "remove" ) { if( !( ptrRepop = room->rmRepop( slot ) ) ) { pc->out( "Invalid repop slot number.\n\r" ); return; } pc->out( "Deleting repop.\n\r" ); if( ptrRepop->getPtr() ) ptrRepop->getPtr()->setRepop( 0 ); ptrRepop->fordelete(); last_slot = slot - 1; return; } if( arg1 == "mob" || arg1 == "mobile" || arg1 == "npc" ) { if( !(bool)arg2 ) { pc->out( "Repop which npc?\n\r" ); return; } if( (bool)arg3 ) chance = arg3.asInt(); ptrRepop = new Repop( 'M', arg2, chance ); room->addRepop( slot, ptrRepop ); area->setDirtyBit(); str << "Added NPC repop at slot " << slot << ".\n\r"; if( !lookupNPC( arg2 ) ) str << "WARNING: NPC prototype '" << arg2 << "' not in database.\n\r"; pc->out( str ); last_slot = slot; return; } else if( arg1 == "give" ) { if( !(bool)arg2 ) { pc->out( "Give which object?\n\r" ); return; } if( (bool)arg3 ) chance = arg3.asInt(); ptrRepop = new Repop( 'G', arg2, chance ); room->addRepop( slot, ptrRepop ); area->setDirtyBit(); str << "Added 'give item to NPC' repop at slot " << slot << ".\n\r"; if( !lookupObj( arg2 ) ) str << "WARNING: Obj prototype '" << arg2 << "' not in database.\n\r"; pc->out( str ); last_slot = slot; return; } else if( arg1 == "eq" || arg1 == "equip" ) { if( !(bool)arg2 ) { pc->out( "Equip which object?\n\r" ); return; } if( (bool)arg3 ) chance = arg3.asInt(); ptrRepop = new Repop( 'E', arg2, chance ); room->addRepop( slot, ptrRepop ); area->setDirtyBit(); str << "Added 'equip NPC with item' repop at slot " << slot << ".\n\r"; if( !lookupObj( arg2 ) ) str << "WARNING: Obj prototype '" << arg2 << "' not in database.\n\r"; pc->out( str ); last_slot = slot; return; } else if( arg1 == "obj" || arg1 == "object" ) { if( arg2.isNumber() ) { slot = arg2.asInt(); arg2 = arg3; arg3 = arg.getArg(); } if( !(bool)arg2 ) { pc->out( "Repop which object?\n\r" ); return; } if( (bool)arg3 ) chance = arg3.asInt(); ptrRepop = new Repop( 'O', arg2, chance ); room->addRepop( slot, ptrRepop ); area->setDirtyBit(); str << "Added Object repop at slot " << slot << ".\n\r"; if( !lookupObj( arg2 ) ) str << "WARNING: Obj prototype '" << arg2 << "' not in database.\n\r"; pc->out( str ); last_slot = slot; return; } else if( arg1 == "put" ) { if( !(bool)arg2 ) { pc->out( "Put which object?\n\r" ); return; } if( (bool) arg3 ) chance = arg3.asInt(); ptrRepop = new Repop( 'P', arg2, chance ); room->addRepop( slot, ptrRepop ); area->setDirtyBit(); str << "Added 'put object in object' repop at slot " << slot << ".\n\r"; if( !lookupObj( arg2 ) ) str << "WARNING: Obj prototype '" << arg2 << "' not in database.\n\r"; pc->out( "str" ); last_slot = slot; return; } else if( arg1 == "nest" ) { if( !(bool)arg2 ) { pc->out( "Nest which object?\n\r" ); return; } if( (bool) arg3 ) chance = arg3.asInt(); ptrRepop = new Repop( 'N', arg2, chance ); room->addRepop( slot, ptrRepop ); area->setDirtyBit(); str << "Added 'nest object in object' repop at slot " << slot << ".\n\r"; if( !lookupObj( arg2 ) ) str << "WARNING: Obj prototype '" << arg2 << "' not in database.\n\r"; pc->out( "str" ); last_slot = slot; return; } pc->out( "Error parsing repop.\n\r" ); pc->out( "Type 'repop help' for syntax info.\n\r" ); }