diff -c -r --new-file ds2.0r19/RELEASE_NOTES ds2.0r20b/RELEASE_NOTES *** ds2.0r19/RELEASE_NOTES Thu Apr 6 22:53:15 2006 --- ds2.0r20b/RELEASE_NOTES Fri Apr 14 18:27:24 2006 *************** *** 1,4 **** ! ---- 2.0r19 (unreleased) --- - Fixed menu item bug in LIB_BARKEEP. - Fixed Ylsrim pub. - Added keepalive pinger tool to wiz chest. --- 1,45 ---- ! ---- 2.0r20 --- ! - (hopefully) Fixed rare and peculiar bug that hosed ! up logins unpredictably. ! - Added the Jonez/Brodbane stargate system. ! - Container bug fixed. It is now possible to put ! amounts of money into containers and onto surfaces. ! - Daemonized snoop system. This permits the logging ! of snoop data, unmanned snoop logs, and snooping ! multiple players at once. Still slightly buggy, so ! please report any problems with it. ! - The encre and decre of non-logged-on users now ! behaves properly. ! - Furnaces now destroy objects almost immediately. ! - Fixed voting system. ! - LIB_GUILD changed to LIB_CLAN. It works, but is ! not actually useful. Proper clan functionality ! is planned post-2.1. ! - Heal command now fixes individual limbs as well. ! - Added ENABLE_ENCUMBRANCE define to config.h to ! toggle the encumbrance combat modifier. ! - Modified combat so it's difficult to fight while ! carrying stuff. Anything worn or wielded doesn't ! affect combat capability. NPC's are unaffected by this. ! - Fixed horrendous carry-capacity leak in all containers. ! - Added "every" token to reload verb, enabling the ! reload of all loaded objects that inherit the specified ! library object, eg "reload every npc". ! - Fixed bugs in invisibility. ! - Enabled QCS to work in /domains directories for ! creators set as domain admins with the ! domainadmin command. ! - Fixed error in RACES_D that dramatically distorted stats. ! - Added sefun: domain_admin. ! - Fixed mudlist cache problem. ! - Added command: switchrouter, domainadmin. ! - Added set_heart_beat to QCS. ! - Fixed bugs in commands: banish, anglicize. ! - Integrated most packet data with network room. ! - Added router room for I3 router debugging. ! - Integrated most I3 packets with router room. ! ! ---- 2.0r19 --- - Fixed menu item bug in LIB_BARKEEP. - Fixed Ylsrim pub. - Added keepalive pinger tool to wiz chest. diff -c -r --new-file ds2.0r19/lib/cfg/timezone.cfg ds2.0r20b/lib/cfg/timezone.cfg *** ds2.0r19/lib/cfg/timezone.cfg Wed Apr 5 19:33:15 2006 --- ds2.0r20b/lib/cfg/timezone.cfg Fri Apr 14 18:27:17 2006 *************** *** 1 **** ! EDT \ No newline at end of file --- 1 ---- ! edt \ No newline at end of file diff -c -r --new-file ds2.0r19/lib/cmds/admins/gate.c ds2.0r20b/lib/cmds/admins/gate.c *** ds2.0r19/lib/cmds/admins/gate.c Wed Dec 31 19:00:00 1969 --- ds2.0r20b/lib/cmds/admins/gate.c Thu Apr 13 21:14:09 2006 *************** *** 0 **** --- 1,52 ---- + /** + * modification of code contributed by daelas + * started 2006-04-04 + */ + #include + #include + #include + + // inherit LIB_DAEMON; + inherit LIB_STARGATE; + + mixed cmd(string str) + { + mapping network; + + if (!archp(previous_object())) return 0; + + network = STARGATE_D->getStargates(); + if (str) + { + if (network[lower_case(str)]) + { + write(str+" is part of the Stargate Network.\n"); + } + else + { + write(str+" is not currently part of the Stargate Network.\n"); + } + + } + else + { + write("These are the current Stargate locations in the Network:\n"); + if (!sizeof(network)) + { + message("info", "No locations found.", this_player()); + } + else + { + string buf = ""; + string name; + class stargate info; + + foreach (name, info in network) + { + buf += sprintf("%:-15s %:-10s %s\n", name, info->status, info->destination); + } + write(buf); + } + } + return 1; + } diff -c -r --new-file ds2.0r19/lib/cmds/creators/anglicize.c ds2.0r20b/lib/cmds/creators/anglicize.c *** ds2.0r19/lib/cmds/creators/anglicize.c Wed Apr 5 19:44:08 2006 --- ds2.0r20b/lib/cmds/creators/anglicize.c Sun Apr 9 23:49:20 2006 *************** *** 5,10 **** --- 5,13 ---- mixed cmd(string str) { object target; + + if(!str || str == "") str = "me"; + if(str == "me") str = this_player()->GetKeyName(); if(!target = present(str, environment(this_player()))){ write("They're not here."); diff -c -r --new-file ds2.0r19/lib/cmds/creators/colors.c ds2.0r20b/lib/cmds/creators/colors.c *** ds2.0r19/lib/cmds/creators/colors.c Wed Dec 7 14:12:58 2005 --- ds2.0r20b/lib/cmds/creators/colors.c Thu Apr 13 21:03:19 2006 *************** *** 3,9 **** inherit LIB_DAEMON; ! void cmd() { write( "%^RED%^RED\n" --- 3,9 ---- inherit LIB_DAEMON; ! int cmd() { write( "%^RED%^RED\n" *************** *** 25,35 **** "%^B_WHITE%^B_WHITE%^RESET%^\n" "%^B_MAGENTA%^B_MAGENTA%^RESET%^\n" ); ! } string GetHelp() { ! return ("Syntax: colors\n\n" ! "Lists all available colors in the corresponding color.\n\n"); } --- 25,36 ---- "%^B_WHITE%^B_WHITE%^RESET%^\n" "%^B_MAGENTA%^B_MAGENTA%^RESET%^\n" ); ! return 1; } string GetHelp() { ! return("Syntax: colors\n\n" ! "Lists all available colors in the corresponding color." ! "\n\n"); } diff -c -r --new-file ds2.0r19/lib/cmds/players/inventory.c ds2.0r20b/lib/cmds/players/inventory.c *** ds2.0r19/lib/cmds/players/inventory.c Mon Nov 7 13:28:39 2005 --- ds2.0r20b/lib/cmds/players/inventory.c Sun Apr 9 23:49:20 2006 *************** *** 38,46 **** i = sizeof(shorts = keys(borg)); while(i--) ret += capitalize(consolidate(borg[shorts[i]], shorts[i]))+"\n"; message("look", ret, this_player()); ! message("other_action", (string)this_player()->GetName() + " checks " + ! possessive(this_player()) + " possessions.", ! environment(this_player()), ({ this_player() })); } void help() { --- 38,47 ---- i = sizeof(shorts = keys(borg)); while(i--) ret += capitalize(consolidate(borg[shorts[i]], shorts[i]))+"\n"; message("look", ret, this_player()); ! if(!this_player()->GetInvis()) ! message("other_action", (string)this_player()->GetName() + " checks " + ! possessive(this_player()) + " possessions.", ! environment(this_player()), ({ this_player() })); } void help() { diff -c -r --new-file ds2.0r19/lib/daemon/banish.c ds2.0r20b/lib/daemon/banish.c *** ds2.0r19/lib/daemon/banish.c Mon Jan 16 23:01:42 2006 --- ds2.0r20b/lib/daemon/banish.c Wed Apr 12 23:47:49 2006 *************** *** 5,10 **** --- 5,11 ---- */ #include + #include #include #include #include *************** *** 67,73 **** } static private int valid_access(object ob) { ! return (int)master()->valid_apply( ({ "LAW", "SUPERUSER" }) ); } int valid_cap_name(string cap, string nom) { --- 68,74 ---- } static private int valid_access(object ob) { ! return (int)master()->valid_apply( ({ "ASSIST" }) ); } int valid_cap_name(string cap, string nom) { diff -c -r --new-file ds2.0r19/lib/daemon/include/stargate.h ds2.0r20b/lib/daemon/include/stargate.h *** ds2.0r19/lib/daemon/include/stargate.h Wed Dec 31 19:00:00 1969 --- ds2.0r20b/lib/daemon/include/stargate.h Thu Apr 13 21:14:09 2006 *************** *** 0 **** --- 1,19 ---- + #include "/include/stargate.h" + + #ifndef daemon_stargate_h + #define daemon_stargate_h + + void load(); + void save(); + int setStargate(string address, string destination); + class stargate getStargate(string address); + int delStargate(string address); + mapping getStargates(); + int setStatus(string address, string status); + string getStatus(string address); + string getDestination(string address); + string getEndpoint(string address); + int connect(string from, string to); + int disconnect(string from); + + #endif diff -c -r --new-file ds2.0r19/lib/daemon/intermud.c ds2.0r20b/lib/daemon/intermud.c *** ds2.0r19/lib/daemon/intermud.c Tue Mar 28 23:54:03 2006 --- ds2.0r20b/lib/daemon/intermud.c Wed Apr 12 23:47:49 2006 *************** *** 31,39 **** Password = 0; Tries = 0; Banned = ([]); - // There is only one known I3 router as of - // Feb 2006: us-1.i3.intermud.org - //Nameservers = ({ ({ "*gjs", "198.144.203.194 9000" }) }); Nameservers = ({ ({ "*yatmim", "149.152.218.102 23" }) }); MudList = new(class list); ChannelList = new(class list); --- 31,36 ---- *************** *** 44,49 **** --- 41,47 ---- if( file_size( SAVE_INTERMUD __SAVE_EXTENSION__ ) > 0 ) unguarded( (: restore_object, SAVE_INTERMUD, 1 :) ); SetNoClean(1); + tn("INTERMUD_D reloaded."); SetDestructOnClose(1); SetSocketType(MUD); if(DISABLE_INTERMUD == 1){ *************** *** 66,71 **** --- 64,76 ---- mudlib() + " " + mudlib_version(), version(), "LPMud", MUD_STATUS, ADMIN_EMAIL, (mapping)SERVICES_D->GetServices(), ([]) }) ); + tn("INTERMUD_D setup: "+identify( ({ + "startup-req-3", 5, mud_name(), 0, Nameservers[0][0], 0, + Password, MudList->ID, ChannelList->ID, query_host_port(), + PORT_OOB, PORT_UDP, mudlib() + " " + mudlib_version(), + mudlib() + " " + mudlib_version(), version(), "LPMud", + MUD_STATUS, ADMIN_EMAIL, + (mapping)SERVICES_D->GetServices(), ([]) }) ), "red");; } static void eventRead(mixed *packet) { *************** *** 86,93 **** //default : tc("Packet: "+identify(packet)); case "startup-reply": log_file("intermud",identify(packet)); ! if( sizeof(packet) != 8 ) return; /* should send error */ ! if( !sizeof(packet[6]) ) return; if( packet[6][0][0] == Nameservers[0][0] ) { Nameservers = packet[6]; Connected = Nameservers[0][0]; --- 91,105 ---- //default : tc("Packet: "+identify(packet)); case "startup-reply": log_file("intermud",identify(packet)); ! tn("INTERMUD_D: "+identify(packet),"red"); ! if( sizeof(packet) != 8 ) { ! tn("We don't like the mudlist packet size.","red"); ! return; ! } ! if( !sizeof(packet[6]) ) { ! tn("We don't like an absence of packet element 6.","red"); ! return; ! } if( packet[6][0][0] == Nameservers[0][0] ) { Nameservers = packet[6]; Connected = Nameservers[0][0]; *************** *** 100,110 **** } return; case "mudlist": ! if( sizeof(packet) != 8 ) return; ! if( packet[6] == MudList->ID ) return; ! if( packet[2] != Nameservers[0][0] ) return; MudList->ID = packet[6]; foreach(cle, val in packet[7]) { if( !val && MudList->List[cle] != 0 ) map_delete(MudList->List, cle); else if( val ) MudList->List[cle] = val; --- 112,137 ---- } return; case "mudlist": ! tn("INTERMUD_D mudlist received.","red"); ! log_file("mudlist_packet",identify(packet),1); ! if( sizeof(packet) != 8 ) { ! tn("We don't like the mudlist packet size.","red"); ! return; ! } ! if( packet[6] == MudList->ID ) { ! tn("We don't like packet element 6. It is: "+identify(packet[6]),"red"); ! //return; ! tn("We will continue anyway.","red"); ! } ! if( packet[2] != Nameservers[0][0] ) { ! tn("We don't like packet element 2. It is: "+identify(packet[2]),"red"); ! return; ! } ! MudList->ID = packet[6]; foreach(cle, val in packet[7]) { + if(cle) tn("Procesing cle: "+identify(cle),"cyan"); + if(val) tn("Procesing val: "+identify(val)+"\n--\n","cyan"); if( !val && MudList->List[cle] != 0 ) map_delete(MudList->List, cle); else if( val ) MudList->List[cle] = val; *************** *** 166,171 **** --- 193,199 ---- SERVICES_D->eventReceiveTell(packet); break; case "chan-user-reply": + tn("INTERMUD_D: chan-user-reply received.","red"); case "ucache-update": SERVICES_D->eventReceiveUcacheUpdate(packet); break; *************** *** 185,190 **** --- 213,219 ---- SERVICES_D->eventReceiveMailOk(packet); break; case "file": + tn("INTERMUD_D: file packet received.","red"); break; case "error": SERVICES_D->eventReceiveError(packet); *************** *** 205,210 **** --- 234,240 ---- static void eventConnectionFailure() { if( Connected ) return; + tn("INTERMUD_D: CONNECTION FAILED","red"); error("Failed to find a useful name server.\n"); } diff -c -r --new-file ds2.0r19/lib/daemon/races.c ds2.0r20b/lib/daemon/races.c *** ds2.0r19/lib/daemon/races.c Fri Mar 24 14:36:35 2006 --- ds2.0r20b/lib/daemon/races.c Sun Apr 9 23:49:20 2006 *************** *** 158,164 **** //tc("hellow"); res = new(class Race); - s = new (class Stat); res->Resistance = ([]); res->Skills = ([]); --- 158,163 ---- *************** *** 255,264 **** break; case "STATS": tmp = explode(replace_string(line, "STATS ",""), ":"); ! s->Average = to_int(tmp[1]); ! s->Class = to_int(tmp[2]); res->Stats[tmp[0]] = s; break; case "LIMB": --- 254,268 ---- break; case "STATS": + tmp = ({}); + s = new (class Stat); tmp = explode(replace_string(line, "STATS ",""), ":"); ! //tc("stat: "+identify(tmp),"yellow"); ! s->Average = copy(to_int(tmp[1])); ! s->Class = copy(to_int(tmp[2])); res->Stats[tmp[0]] = s; + //tc("ihnfcaa: "+(res->Stats[tmp[0]])->Average,"yellow"); + //tc("ihnfcaax2: "+(res->Stats[tmp[0]])->Class,"yellow"); break; case "LIMB": *************** *** 406,411 **** --- 410,417 ---- void SetCharacterRace(string race, mixed array args) { class Race res = Races[race]; mixed array tmp; + mapping StatMap; + string schluss; if( !res || !res->Complete || sizeof(args) != 5 ) return; tmp = ({}); *************** *** 413,420 **** tmp = ({ tmp..., ({ key, val }) }); args[0] = tmp; tmp = ({}); ! foreach(string key, class Stat stat in res->Stats) ! tmp = ({ tmp..., ({ key, stat->Average, stat->Class }) }); args[1] = tmp; args[2] = res->Language; //args[3] = ({ res->Sensitivity[0], res->Sensitivity[1] }); --- 419,434 ---- tmp = ({ tmp..., ({ key, val }) }); args[0] = tmp; tmp = ({}); ! //foreach(string key, class Stat stat in res->Stats){ ! StatMap = copy(res->Stats); ! schluss = ""; ! foreach(schluss in keys(StatMap)){ ! //tc("key: "+identify(StatMap[schluss]),"green"); ! //tc("Average: "+identify(StatMap[schluss]->Average),"green"); ! //tc("Class: "+identify(StatMap[schluss]->Class),"green"); ! tmp = ({ tmp..., ({ schluss, StatMap[schluss]->Average, StatMap[schluss]->Class }) }); ! //tc("SetCharacterRace: "+identify(tmp)); ! } args[1] = tmp; args[2] = res->Language; //args[3] = ({ res->Sensitivity[0], res->Sensitivity[1] }); diff -c -r --new-file ds2.0r19/lib/daemon/services/auth.c ds2.0r20b/lib/daemon/services/auth.c *** ds2.0r19/lib/daemon/services/auth.c Wed Apr 5 19:33:16 2006 --- ds2.0r20b/lib/daemon/services/auth.c Wed Apr 12 23:47:49 2006 *************** *** 34,40 **** if(!grepp(mudlist,packet[2]) || packet[2] == "DeadSoulsNew" || packet[2] == "DeadSoulsWin"){ write_file("/tmp/muds.txt",packet[2]+"\n"); ! tc("We have a new mud! "+packet[2]+" has joined intermud.","red"); tn("We have a new mud! "+packet[2]+" has joined intermud.","red"); } --- 34,40 ---- if(!grepp(mudlist,packet[2]) || packet[2] == "DeadSoulsNew" || packet[2] == "DeadSoulsWin"){ write_file("/tmp/muds.txt",packet[2]+"\n"); ! //tc("We have a new mud! "+packet[2]+" has joined intermud.","red"); tn("We have a new mud! "+packet[2]+" has joined intermud.","red"); } diff -c -r --new-file ds2.0r19/lib/daemon/services/channel.c ds2.0r20b/lib/daemon/services/channel.c *** ds2.0r19/lib/daemon/services/channel.c Wed Apr 5 19:33:16 2006 --- ds2.0r20b/lib/daemon/services/channel.c Sun Apr 9 23:49:20 2006 *************** *** 106,115 **** varargs void eventSendChannel(string who, string ch, string msg, int emote, string target, string targmsg) { mixed array packet; string targpl, where; // targpl is target keyname ! tn("eventSendChannel. ","green"); if( emote ) { if( target && targmsg ) { --- 106,116 ---- varargs void eventSendChannel(string who, string ch, string msg, int emote, string target, string targmsg) { mixed array packet; + mixed array packet_thing = ({ who, ch, msg, emote || "", target || "", targmsg || "" }); string targpl, where; // targpl is target keyname ! tn("eventSendChannel raw: "+identify( packet_thing ),"green"); if( emote ) { if( target && targmsg ) { *************** *** 136,141 **** --- 137,143 ---- else packet = ({ "channel-m", 5, mud_name(), convert_name(who), 0, 0, ch, who, msg }); INTERMUD_D->eventWrite(packet); + tn("eventSendChannel processed: "+identify(packet),"green"); } void eventSendChannelWhoRequest(string channel, string mud) { *************** *** 144,157 **** pl = (string)this_player(1)->GetKeyName(); INTERMUD_D->eventWrite(({ "chan-who-req", 5, mud_name(), pl, mud, 0, channel })); } void eventRegisterChannels(mapping list) { mixed array val; string channel, ns; - tn("eventRegisterChannels: "+identify(list),"green"); - if( file_name(previous_object()) != INTERMUD_D ) return; ns = (string)INTERMUD_D->GetNameserver(); foreach(channel, val in list) { --- 146,158 ---- pl = (string)this_player(1)->GetKeyName(); INTERMUD_D->eventWrite(({ "chan-who-req", 5, mud_name(), pl, mud, 0, channel })); + tn("eventSendChannelWhoRequest: "+identify( ({ "chan-who-req", 5, mud_name(), pl, mud, 0, channel })) , "green"); } void eventRegisterChannels(mapping list) { mixed array val; string channel, ns; if( file_name(previous_object()) != INTERMUD_D ) return; ns = (string)INTERMUD_D->GetNameserver(); foreach(channel, val in list) { *************** *** 167,172 **** --- 168,175 ---- else INTERMUD_D->eventWrite(({ "channel-listen", 5, mud_name(), 0, ns, 0, channel, 1 })); } + tn("eventRegisterChannels: "+identify(list),"green"); + } int eventAdministerChannel(string channel, string array additions, *************** *** 180,190 **** (string)this_player(1)->GetKeyName(), (string)INTERMUD_D->GetNameserver(), 0, channel, additions, subs })); return 1; } int AddChannel(string channel, int privee) { ! tn("eventAdministerChannel. ","green"); if( !((int)master()->valid_apply( ({}) )) ){ return 0; --- 183,195 ---- (string)this_player(1)->GetKeyName(), (string)INTERMUD_D->GetNameserver(), 0, channel, additions, subs })); + + tn("eventAdministerChannel: "+channel+" "+identify(additions)+" "+identify(subs),"green"); return 1; } int AddChannel(string channel, int privee) { ! tn("eventAdministerChannel: "+channel+", "+privee,"green"); if( !((int)master()->valid_apply( ({}) )) ){ return 0; diff -c -r --new-file ds2.0r19/lib/daemon/services/emoteto.c ds2.0r20b/lib/daemon/services/emoteto.c *** ds2.0r19/lib/daemon/services/emoteto.c Mon Nov 7 13:29:14 2005 --- ds2.0r20b/lib/daemon/services/emoteto.c Sun Apr 9 23:49:20 2006 *************** *** 12,17 **** --- 12,18 ---- object ob; string who; + tn("eventReceiveEmote: "+identify(packet), "green"); if( file_name(previous_object()) != INTERMUD_D ) return; who = convert_name(packet[5]); if( !(ob = find_player(who)) || (int)ob->GetInvis() ) { *************** *** 34,39 **** --- 35,41 ---- where = (string)INTERMUD_D->GetMudName(where); INTERMUD_D->eventWrite(({ "emoteto", 5, mud_name(), pl, where, convert_name(who), plc, msg })); + tn("eventSendEmote: "+identify( "emoteto", 5, mud_name(), pl, where,convert_name(who), plc, msg ),"green"); } diff -c -r --new-file ds2.0r19/lib/daemon/services/error.c ds2.0r20b/lib/daemon/services/error.c *** ds2.0r19/lib/daemon/services/error.c Mon Nov 7 13:29:14 2005 --- ds2.0r20b/lib/daemon/services/error.c Sun Apr 9 23:49:20 2006 *************** *** 8,13 **** --- 8,15 ---- object ob; string error_code, mud, target, msg; + tn("ERROR RECEIVED: "+identify(packet)); + if( packet[5] ) { target = convert_name(packet[5]); if( !(ob = find_player(target)) ) return; diff -c -r --new-file ds2.0r19/lib/daemon/services/finger.c ds2.0r20b/lib/daemon/services/finger.c *** ds2.0r19/lib/daemon/services/finger.c Sat Mar 11 11:14:53 2006 --- ds2.0r20b/lib/daemon/services/finger.c Sun Apr 9 23:49:20 2006 *************** *** 26,31 **** --- 26,32 ---- ret = ({ "finger-reply", 5, mud_name(), 0, packet[2], packet[3] }) + ret; INTERMUD_D->eventWrite(ret); tell_room(ROOM_ARCH,"The Arch Room loudspeaker announces: \"%^BOLD%^CYAN%^"+capitalize(packet[3])+" at "+packet[2]+" has requested finger information about "+capitalize(ret[6])+".%^RESET%^\""); + tn("eventReceiveFingerRequest: "+identify(packet),"cyan"); } *************** *** 52,57 **** --- 53,59 ---- fing += "Site: " + (packet[12] ? packet[12] : "Confidential") + "\n"; fing += (packet[14] ? packet[14] : "\n"); ob->eventPrint(fing, MSG_SYSTEM); + tn("eventReceiveFingerReply: "+identify(packet),"cyan"); } void eventSendFingerRequest(string who, string where) { *************** *** 60,63 **** --- 62,66 ---- if( !(pl = (string)this_player(1)->GetKeyName()) ) return; INTERMUD_D->eventWrite( ({ "finger-req", 5, mud_name(), pl, where, 0, who }) ); + tn("eventSendFingerRequest: "+identify( ({ "finger-req", 5, mud_name(), pl, where, 0,who }) ),"cyan"); } diff -c -r --new-file ds2.0r19/lib/daemon/services/locate.c ds2.0r20b/lib/daemon/services/locate.c *** ds2.0r19/lib/daemon/services/locate.c Wed Feb 22 15:29:50 2006 --- ds2.0r20b/lib/daemon/services/locate.c Sun Apr 9 23:49:20 2006 *************** *** 19,24 **** --- 19,25 ---- if( file_name(previous_object()) != INTERMUD_D ) return; tell_room(ROOM_ARCH,"The Arch Room loudspeaker announces: \"%^BOLD%^CYAN%^"+capitalize(packet[3])+" at "+packet[2]+" has issued a locate request for %^BOLD%^YELLOW%^"+capitalize(packet[6])+".%^RESET%^\""); + tn("Locate request received: "+identify(packet),"white"); if( !(ob = find_player(packet[6])) || ob->GetInvis()) return; if( interactive(ob) ) { string array tmp = ({ }); *************** *** 43,48 **** --- 44,50 ---- if( file_name(previous_object()) != INTERMUD_D ) return; if( !stringp(packet[5]) || !(ob = find_player(convert_name(packet[5]))) ) return; + tn("Locate reply received: "+identify(packet),"white"); m = packet[7] + " was just located on " + packet[6] + "."; if( (idl = (int)packet[8]) > 60 ) m += sprintf(" (idle %02d:%02d:%02d)", idl/3600, (idl/60)%60, idl%60); *************** *** 53,59 **** void eventSendLocateRequest(string who) { string pl; ! if( !(pl = (string)this_player(1)->GetKeyName()) ) return; INTERMUD_D->eventWrite( ({ "locate-req", 5, mud_name(), pl, 0, 0, who }) ); } --- 55,62 ---- void eventSendLocateRequest(string who) { string pl; ! mixed *locate_request = ({ "locate-req", 5, mud_name(), pl, 0, 0, who }); if( !(pl = (string)this_player(1)->GetKeyName()) ) return; INTERMUD_D->eventWrite( ({ "locate-req", 5, mud_name(), pl, 0, 0, who }) ); + tn("Locate request being sent: "+identify(locate_request),"white"); } diff -c -r --new-file ds2.0r19/lib/daemon/services/tell.c ds2.0r20b/lib/daemon/services/tell.c *** ds2.0r19/lib/daemon/services/tell.c Fri Mar 24 14:36:35 2006 --- ds2.0r20b/lib/daemon/services/tell.c Sun Apr 9 23:49:20 2006 *************** *** 14,19 **** --- 14,20 ---- string who; string adverb = ""; + tn("eventReceiveTell: "+identify(packet),"yellow"); if( file_name(previous_object()) != INTERMUD_D ) return; who = convert_name(packet[5]); if( !(ob = find_player(who)) || (int)ob->GetInvis() ) { *************** *** 59,64 **** --- 60,66 ---- this_player(1)->eventPrint("%^BOLD%^RED%^You tell " + capitalize(who) + "@" + where + ":%^RESET%^ " + msg, MSG_CONV); + tn("eventSendTell: "+identify( ({ "tell", 5, mud_name(), pl, where, convert_name(who), plc, msg }) ), "yellow"); } diff -c -r --new-file ds2.0r19/lib/daemon/services/who.c ds2.0r20b/lib/daemon/services/who.c *** ds2.0r19/lib/daemon/services/who.c Fri Mar 24 14:36:35 2006 --- ds2.0r20b/lib/daemon/services/who.c Sun Apr 9 23:49:20 2006 *************** *** 19,24 **** --- 19,25 ---- foreach(who in packet[6]) list += ({ who[0] + " (" + who[1] + " idle): " + who[2] }); ob->eventPage(list); + tn("eventReceiveWhoReply: "+identify(packet),"blue"); } void eventReceiveWhoRequest(mixed *packet) { *************** *** 34,40 **** ret += entry[0]+", "; } ret = truncate(ret,2); ! tell_room(ROOM_ARCH,"The Arch Room loudspeaker announces: \"%^BOLD%^CYAN%^"+capitalize(packet[3])+" at "+packet[2]+" has requested a list of users currently logged on. Replying with: %^BOLD%^YELLOW%^"+ret+".%^RESET%^\""); } --- 35,41 ---- ret += entry[0]+", "; } ret = truncate(ret,2); ! tn("eventReceiveWhoRequest: "+identify(packet),"blue"); tell_room(ROOM_ARCH,"The Arch Room loudspeaker announces: \"%^BOLD%^CYAN%^"+capitalize(packet[3])+" at "+packet[2]+" has requested a list of users currently logged on. Replying with: %^BOLD%^YELLOW%^"+ret+".%^RESET%^\""); } *************** *** 43,48 **** --- 44,50 ---- who = (string)this_player(1)->GetName(); INTERMUD_D->eventWrite(({ "who-req", 5, mud_name(), who, mud, 0 })); + tn("eventSendWhoRequest: "+identify( ({ "who-req", 5, mud_name(), who, mud, 0 })), "blue"); } diff -c -r --new-file ds2.0r19/lib/daemon/stargate.c ds2.0r20b/lib/daemon/stargate.c *** ds2.0r19/lib/daemon/stargate.c Wed Dec 31 19:00:00 1969 --- ds2.0r20b/lib/daemon/stargate.c Thu Apr 13 21:14:09 2006 *************** *** 0 **** --- 1,185 ---- + /** + * stargate_d : stargate daemon. tracks the entire stargate network. + * started 2006-03-23 by jonez + * + * 2006-03-24, jonez + * - with help from cratylus, changed the daemon so it saves it's state + * whenever there is a change, and tries to load from disk at create + * time. + * 2006-03-28, jonez + * - gate is status is now "idle", "outbound", or "inbound". gate cannot be entered from the inbound side. + */ + + #include + #include + #include "/daemon/include/stargate.h" + + inherit LIB_DAEMON; + + private mapping stargates = ([]); + + static void create() + { + daemon::create(); + SetNoClean(1); + load(); + if (!stargates) stargates = ([]); + } + + void save() + { + unguarded( (: save_object, SAVE_STARGATE, 1 :) ); + tell_player("jonez", "stargate daemon saved itself"); + return; + } + + void load() + { + if (file_size(SAVE_STARGATE __SAVE_EXTENSION__) > 0) + { + tc("stargate save file exists"); + unguarded( (: restore_object, SAVE_STARGATE :) ); + } + tell_player("jonez", "stargate daemon loaded itself"); + return; + } + + int setStargate(string address, string destination) + { + class stargate s = new(class stargate); + + if (address == "" || destination == "") return 1; + + s->status = "idle"; + s->destination = destination; + s->endpoint = 0; + stargates[address] = s; + save(); + return 0; + } + + class stargate getStargate(string address) + { + class stargate s = stargates[address]; + if (!s) return 0; + + tell_player("jonez", sprintf("get: address=%s, status=%s destination=%s endpoint=%s", address, s->status, s->destination, s->endpoint)); + return (class stargate)stargates[address]; + } + + int delStargate(string address) + { + map_delete(stargates, address); + save(); + return 0; + } + + mapping getStargates() + { + /* + string buf = ""; + + foreach(string n, class stargate g in stargates) + { + buf += sprintf("name=%s, status=%s, destination=%s, endpoint=%s; ", n, g->status, g->destination, g->endpoint); + } + return buf; + */ + return copy(stargates); + } + + int setStatus(string address, string status) + { + class stargate s; + s = stargates[address]; + if (!s) return 1; + + s->status = status; + save(); + return 0; + } + + string getStatus(string address) + { + class stargate s = stargates[address]; + if (!s) return ""; + + return s->status; + } + + string getDestination(string address) + { + class stargate s = stargates[address]; + if (!s) return ""; + return s->destination; + } + + string getEndpoint(string address) + { + class stargate s = stargates[address]; + if (!s) return ""; + return s->endpoint; + } + + // return 1 on success, 0 on error + int connect(string from, string to) + { + class stargate t, f; + + tell_player("jonez", sprintf("stargate_d->connect(%s, %s)", from, to)); + + if (from == to) return 0; + + f = stargates[from]; + if (!f) + { + tell_player("jonez", "failed to lookup status of outbound gate"); + return 0; + } + + t = stargates[to]; + if (!t) + { + tell_player("jonez", "failed to lookup status of inbound gate"); + return 0; + } + + tell_player("jonez", sprintf("%s->status=%s, %s->status=%s", from, f->status, to, t->status)); + + if (f->status == "idle" && t->status == "idle") + { + f->endpoint = to; + f->status = "outbound"; + + t->endpoint = from; + t->status = "inbound"; + + save(); + + return 1; + } + return 0; + } + + // return 1 on success, 0 on error + int disconnect(string from) + { + class stargate f; + string endpoint; + + tell_player("jonez", sprintf("stargate_d->disconnect(%s)", from)); + + f = stargates[from]; + if (!f) return 0; + + endpoint = stargates[from]->endpoint; + if (!endpoint) return 0; + + stargates[endpoint]->endpoint = ""; + stargates[endpoint]->status = "idle"; + + stargates[from]->endpoint = ""; + stargates[from]->status = "idle"; + save(); + return 1; + } diff -c -r --new-file ds2.0r19/lib/doc/RELEASE_NOTES ds2.0r20b/lib/doc/RELEASE_NOTES *** ds2.0r19/lib/doc/RELEASE_NOTES Thu Apr 6 22:53:15 2006 --- ds2.0r20b/lib/doc/RELEASE_NOTES Fri Apr 14 18:27:24 2006 *************** *** 1,4 **** ! ---- 2.0r19 (unreleased) --- - Fixed menu item bug in LIB_BARKEEP. - Fixed Ylsrim pub. - Added keepalive pinger tool to wiz chest. --- 1,45 ---- ! ---- 2.0r20 --- ! - (hopefully) Fixed rare and peculiar bug that hosed ! up logins unpredictably. ! - Added the Jonez/Brodbane stargate system. ! - Container bug fixed. It is now possible to put ! amounts of money into containers and onto surfaces. ! - Daemonized snoop system. This permits the logging ! of snoop data, unmanned snoop logs, and snooping ! multiple players at once. Still slightly buggy, so ! please report any problems with it. ! - The encre and decre of non-logged-on users now ! behaves properly. ! - Furnaces now destroy objects almost immediately. ! - Fixed voting system. ! - LIB_GUILD changed to LIB_CLAN. It works, but is ! not actually useful. Proper clan functionality ! is planned post-2.1. ! - Heal command now fixes individual limbs as well. ! - Added ENABLE_ENCUMBRANCE define to config.h to ! toggle the encumbrance combat modifier. ! - Modified combat so it's difficult to fight while ! carrying stuff. Anything worn or wielded doesn't ! affect combat capability. NPC's are unaffected by this. ! - Fixed horrendous carry-capacity leak in all containers. ! - Added "every" token to reload verb, enabling the ! reload of all loaded objects that inherit the specified ! library object, eg "reload every npc". ! - Fixed bugs in invisibility. ! - Enabled QCS to work in /domains directories for ! creators set as domain admins with the ! domainadmin command. ! - Fixed error in RACES_D that dramatically distorted stats. ! - Added sefun: domain_admin. ! - Fixed mudlist cache problem. ! - Added command: switchrouter, domainadmin. ! - Added set_heart_beat to QCS. ! - Fixed bugs in commands: banish, anglicize. ! - Integrated most packet data with network room. ! - Added router room for I3 router debugging. ! - Integrated most I3 packets with router room. ! ! ---- 2.0r19 --- - Fixed menu item bug in LIB_BARKEEP. - Fixed Ylsrim pub. - Added keepalive pinger tool to wiz chest. diff -c -r --new-file ds2.0r19/lib/doc/RELEASE_NOTES_HTTP ds2.0r20b/lib/doc/RELEASE_NOTES_HTTP *** ds2.0r19/lib/doc/RELEASE_NOTES_HTTP Thu Apr 6 22:53:15 2006 --- ds2.0r20b/lib/doc/RELEASE_NOTES_HTTP Wed Apr 12 23:47:49 2006 *************** *** 1,4 **** ! ---- 2.0r19 (unreleased) --- - Added Brodbane's New and Improved cp command. - Added Brodbane's sefuns: wild_card, remove_dots. - Elision bug in pager.c fixed by Brodbane. --- 1,43 ---- ! ---- 2.0r20 (unreleased) --- ! - The encre and decre of non-logged-on users now ! behaves properly. ! - Furnaces now destroy objects almost immediately. ! - Fixed voting system. ! - LIB_GUILD changed to LIB_CLAN. It works, but is ! not actually useful. Proper clan functionality ! is planned post-2.1. ! - Heal command now fixes individual limbs as well. ! - Added ENABLE_ENCUMBRANCE define to config.h to ! toggle the encumbrance combat modifier. ! - Modified combat so it's difficult to fight while ! carrying stuff. Anything worn or wielded doesn't ! affect combat capability. NPC's are unaffected by this. ! - Fixed horrendous carry-capacity leak in all containers. ! - Added "every" token to reload verb, enabling the ! reload of all loaded objects that inherit the specified ! library object, eg "reload every npc". ! - Fixed bugs in invisibility. ! - Enabled QCS to work in /domains directories for ! creators set as domain admins with the ! domainadmin command. ! - Fixed error in RACES_D that dramatically distorted stats. ! - Added sefun: domain_admin. ! - Fixed mudlist cache problem. ! - Added command: switchrouter, domainadmin. ! - Added set_heart_beat to QCS. ! - Fixed bugs in commands: banish, anglicize. ! - Integrated most packet data with network room. ! - Added router room for I3 router debugging. ! - Integrated most I3 packets with router room. ! ! ---- 2.0r19 --- ! - Fixed menu item bug in LIB_BARKEEP. ! - Fixed Ylsrim pub. ! - Added keepalive pinger tool to wiz chest. ! - Added commands: anglicize, debug, expel, resetpasswd. ! - Fixed first boot problem with /secure/daemon/letters.c. ! - Driver: set heart_beat to approximately one per second. ! - Driver: added locale workaround to startmud script. - Added Brodbane's New and Improved cp command. - Added Brodbane's sefuns: wild_card, remove_dots. - Elision bug in pager.c fixed by Brodbane. diff -c -r --new-file ds2.0r19/lib/doc/efun/all/explode ds2.0r20b/lib/doc/efun/all/explode *** ds2.0r19/lib/doc/efun/all/explode Mon Jan 23 09:17:12 2006 --- ds2.0r20b/lib/doc/efun/all/explode Thu Apr 13 21:03:32 2006 *************** *** 11,16 **** --- 11,17 ---- by spaces) in the string 'str'. See also: + implode, sscanf, replace_string, strsrch diff -c -r --new-file ds2.0r19/lib/doc/efun/strings/explode ds2.0r20b/lib/doc/efun/strings/explode *** ds2.0r19/lib/doc/efun/strings/explode Mon Jan 23 09:17:12 2006 --- ds2.0r20b/lib/doc/efun/strings/explode Thu Apr 13 21:03:32 2006 *************** *** 11,16 **** --- 11,17 ---- by spaces) in the string 'str'. See also: + implode, sscanf, replace_string, strsrch diff -c -r --new-file ds2.0r19/lib/domains/Ylsrim/obj/stargate.c ds2.0r20b/lib/domains/Ylsrim/obj/stargate.c *** ds2.0r19/lib/domains/Ylsrim/obj/stargate.c Wed Dec 31 19:00:00 1969 --- ds2.0r20b/lib/domains/Ylsrim/obj/stargate.c Thu Apr 13 21:12:48 2006 *************** *** 0 **** --- 1,28 ---- + #include + #include + #include "/lib/include/stargate.h" + + inherit LIB_STARGATE; + + int readScreen(); + + void create() + { + ::create(); + setOrigin("tower", "/domains/Ylsrim/room/tower"); + SetRead(([ ({ "screen" }) : (: readScreen :) ]) ); + SetItems(([ ({ "screen" }) : "a computer screen which shows the status of the gate network" ]) ); + } + + void init() + { + ::init(); + } + + int readScreen() + { + write("stargate network status\n"); + write("-----------------------\n"); + write("\n"); + + } diff -c -r --new-file ds2.0r19/lib/domains/Ylsrim/room/furnace.c ds2.0r20b/lib/domains/Ylsrim/room/furnace.c *** ds2.0r19/lib/domains/Ylsrim/room/furnace.c Mon Jan 23 09:15:29 2006 --- ds2.0r20b/lib/domains/Ylsrim/room/furnace.c Wed Apr 12 23:47:49 2006 *************** *** 7,24 **** room::create(); SetAmbientLight(30); SetShort("the furnace"); ! SetLong("The furnace. Things that arrive here are periodically "+ "incinerated. You probably shouldn't be here. Go down to get out."); SetProperties(([ "no attack" : 1, ])); SetExits( ([ "down" : ROOM_START ]) ); ! call_out((: reload_room :), 360, load_object(base_name(this_object()))); SetNoModify(1); } int CanReceive(object ob){ return 1; } void init(){ ::init(); } --- 7,36 ---- room::create(); SetAmbientLight(30); SetShort("the furnace"); ! SetLong("The furnace. Things that arrive here are "+ "incinerated. You probably shouldn't be here. Go down to get out."); SetProperties(([ "no attack" : 1, ])); SetExits( ([ "down" : ROOM_START ]) ); ! call_out((: reload_room :), 600, load_object(base_name(this_object()))); ! set_heart_beat(1); SetNoModify(1); } int CanReceive(object ob){ + if(interactive(ob)){ + tell_object(ob, "You fail to enter the furnace."); + return 0; + } return 1; } void init(){ ::init(); } + void heart_beat(){ + if(sizeof(all_inventory(this_object()))){ + foreach(object ob in deep_inventory(this_object())){ + ob->eventDestruct(); + } + } + } diff -c -r --new-file ds2.0r19/lib/domains/Ylsrim/room/pub.c ds2.0r20b/lib/domains/Ylsrim/room/pub.c *** ds2.0r19/lib/domains/Ylsrim/room/pub.c Thu Apr 6 22:53:15 2006 --- ds2.0r20b/lib/domains/Ylsrim/room/pub.c Sun Apr 9 23:49:20 2006 *************** *** 13,18 **** --- 13,19 ---- // the menu int readMenu(object who, string str) { + string array tmp2 = ({}); string array tmp = ({ sprintf("%:-20s %:-7s", "Drink", "Cost") }); object ob = present("lars"); *************** *** 24,29 **** --- 25,35 ---- tmp += ({ sprintf("%:-20s %d electrum", capitalize(item[0]), to_int(ob->GetCost(item))) }); } + foreach(string element in tmp){ + element = translate(element, this_player()->GetLanguageLevel("Edhellen")); + tmp2 += ({ element }); + } + tmp = tmp2; // show the menu a page at a time this_player()->eventPage(tmp, MSG_SYSTEM); // MSG_SYSTEM means ignore blocking return 1; *************** *** 40,45 **** --- 46,52 ---- "with a hodge-podge of writing in all different languages " "covering the wall. A menu of drinks is about the only " "readable thing on the wall. If you read Edhellen."); + SetLanguage("Edhellen"); SetInventory(([ "/domains/Ylsrim/npc/lars" : 1, ])); diff -c -r --new-file ds2.0r19/lib/domains/Ylsrim/room/tower.c ds2.0r20b/lib/domains/Ylsrim/room/tower.c *** ds2.0r19/lib/domains/Ylsrim/room/tower.c Mon Nov 7 13:29:44 2005 --- ds2.0r20b/lib/domains/Ylsrim/room/tower.c Thu Apr 13 21:03:39 2006 *************** *** 26,40 **** "heart of the hall." ]) ); SetObviousExits("d"); SetExits( ([ "down" : "/domains/Ylsrim/room/"+ "adv_hall" ]) ); - //AddJump("road", "/domains/Ylsrim/room/"+ "kaliid4", JUMP_INTO); - //AddJump("kaliid road", "/domains/Ylsrim/room/"+ "kaliid4", JUMP_INTO); - //AddJump("tower", "/domains/Ylsrim/room/"+ "kaliid4", JUMP_FROM); - SetJump( ([ - "road" : ({ "/domains/Ylsrim/room/kaliid4", JUMP_INTO }), - "kaliid road" : ({ "/domains/Ylsrim/room/kaliid4", JUMP_INTO }), - "tower" : ({ "/domains/Ylsrim/room/kaliid4", JUMP_FROM }), - ]) ); } void init(){ ::init(); --- 26,35 ---- "heart of the hall." ]) ); SetObviousExits("d"); SetExits( ([ "down" : "/domains/Ylsrim/room/"+ "adv_hall" ]) ); + SetInventory(([ + "/domains/Ylsrim/obj/stargate" : 1, + ])); } void init(){ ::init(); diff -c -r --new-file ds2.0r19/lib/domains/default/armor/robe.c ds2.0r20b/lib/domains/default/armor/robe.c *** ds2.0r19/lib/domains/default/armor/robe.c Wed Apr 5 19:33:16 2006 --- ds2.0r20b/lib/domains/default/armor/robe.c Sun Apr 9 23:49:20 2006 *************** *** 15,21 **** "no steal" : 1, ])); SetCanClose(1); ! SetMaxCarry(500); SetMass(200); SetBaseCost("silver",100); SetDamagePoints(100); --- 15,21 ---- "no steal" : 1, ])); SetCanClose(1); ! SetMaxCarry(5000); SetMass(200); SetBaseCost("silver",100); SetDamagePoints(100); diff -c -r --new-file ds2.0r19/lib/domains/default/room/furnace.c ds2.0r20b/lib/domains/default/room/furnace.c *** ds2.0r19/lib/domains/default/room/furnace.c Fri Mar 24 14:36:36 2006 --- ds2.0r20b/lib/domains/default/room/furnace.c Wed Apr 12 23:47:49 2006 *************** *** 7,24 **** room::create(); SetAmbientLight(30); SetShort("the furnace"); ! SetLong("The furnace. Things that arrive here are periodically "+ "incinerated. You probably shouldn't be here. Go down to get out."); SetProperties(([ "no attack" : 1, ])); SetExits( ([ "down" : ROOM_START ]) ); ! call_out((: reload_room :), 60, load_object(base_name(this_object()))); SetNoModify(1); } int CanReceive(object ob){ return 1; } void init(){ ::init(); } --- 7,36 ---- room::create(); SetAmbientLight(30); SetShort("the furnace"); ! SetLong("The furnace. Things that arrive here are "+ "incinerated. You probably shouldn't be here. Go down to get out."); SetProperties(([ "no attack" : 1, ])); SetExits( ([ "down" : ROOM_START ]) ); ! call_out((: reload_room :), 600, load_object(base_name(this_object()))); ! set_heart_beat(1); SetNoModify(1); } int CanReceive(object ob){ + if(interactive(ob)){ + tell_object(ob, "You fail to enter the furnace."); + return 0; + } return 1; } void init(){ ::init(); } + void heart_beat(){ + if(sizeof(all_inventory(this_object()))){ + foreach(object ob in deep_inventory(this_object())){ + ob->eventDestruct(); + } + } + } diff -c -r --new-file ds2.0r19/lib/domains/town/obj/fleas.c ds2.0r20b/lib/domains/town/obj/fleas.c *** ds2.0r19/lib/domains/town/obj/fleas.c Sat Mar 11 11:15:11 2006 --- ds2.0r20b/lib/domains/town/obj/fleas.c Wed Apr 12 23:47:50 2006 *************** *** 63,70 **** int eventSuffer(){ int x; x=random(500); ! if(x < 2) environment()->eventForce("sneeze"); ! else if(x < 5) damage1(); else if(x < 10) damage2(); else if(x < 15) damage3(); else if(x < 20) damage4(); --- 63,69 ---- int eventSuffer(){ int x; x=random(500); ! if(x < 5) damage1(); else if(x < 10) damage2(); else if(x < 15) damage3(); else if(x < 20) damage4(); *************** *** 94,106 **** int damage2(){ tell_object(victim,"You involuntarily start scratching at the maddening itch."); ! tell_room(environment(victim),victimname+" scratches desperately at "+objective(this_player())+"self.", ({victim}) ); return 1; } int damage3(){ ! tell_room(environment(victim),victimname+" scratches at "+objective(this_player())+"self in a frenzy, ripping "+ ! possessive(this_player())+" flesh and drawing blood.", ({victim}) ); tell_object(victim,"You scratch at yourself in a mad frenzy, ripping flesh and drawing blood."); if(DangerLevel() != 100) victim->eventReceiveDamage(this_object(),DISEASE,random(5)+4,0,"torso"); return 1; --- 93,105 ---- int damage2(){ tell_object(victim,"You involuntarily start scratching at the maddening itch."); ! tell_room(environment(victim),victimname+" scratches desperately at "+reflexive(victim)+".", ({victim}) ); return 1; } int damage3(){ ! tell_room(environment(victim),victimname+" scratches at "+reflexive(victim)+" in a frenzy, ripping "+ ! possessive(victim)+" flesh and drawing blood.", ({victim}) ); tell_object(victim,"You scratch at yourself in a mad frenzy, ripping flesh and drawing blood."); if(DangerLevel() != 100) victim->eventReceiveDamage(this_object(),DISEASE,random(5)+4,0,"torso"); return 1; diff -c -r --new-file ds2.0r19/lib/domains/town/obj/lice.c ds2.0r20b/lib/domains/town/obj/lice.c *** ds2.0r19/lib/domains/town/obj/lice.c Sat Mar 11 11:15:11 2006 --- ds2.0r20b/lib/domains/town/obj/lice.c Wed Apr 12 23:47:50 2006 *************** *** 61,68 **** int eventSuffer(){ int x; x=random(500); ! if(x < 2) environment()->eventForce("sneeze"); ! else if(x < 5) damage1(); else if(x < 10) damage2(); else if(x < 15) damage3(); else if(x < 20) damage4(); --- 61,67 ---- int eventSuffer(){ int x; x=random(500); ! if(x < 5) damage1(); else if(x < 10) damage2(); else if(x < 15) damage3(); else if(x < 20) damage4(); *************** *** 92,104 **** int damage2(){ tell_object(victim,"You involuntarily start scratching at the maddening itch."); ! tell_room(environment(victim),victimname+" scratches desperately at "+objective(this_player())+"self.", ({victim}) ); return 1; } int damage3(){ ! tell_room(environment(victim),victimname+" scratches at "+objective(this_player())+"self in a frenzy, ripping "+ ! possessive(this_player())+" flesh and drawing blood.", ({victim}) ); tell_object(victim,"You scratch at yourself in a mad frenzy, ripping flesh and drawing blood."); if(DangerLevel() != 100) victim->eventReceiveDamage(this_object(),DISEASE,random(5)+4,0,"torso"); return 1; --- 91,103 ---- int damage2(){ tell_object(victim,"You involuntarily start scratching at the maddening itch."); ! tell_room(environment(victim),victimname+" scratches desperately at "+reflexive(victim)+".", ({victim}) ); return 1; } int damage3(){ ! tell_room(environment(victim),victimname+" scratches at "+reflexive(victim)+" in a frenzy, ripping "+ ! possessive(victim)+" flesh and drawing blood.", ({victim}) ); tell_object(victim,"You scratch at yourself in a mad frenzy, ripping flesh and drawing blood."); if(DangerLevel() != 100) victim->eventReceiveDamage(this_object(),DISEASE,random(5)+4,0,"torso"); return 1; diff -c -r --new-file ds2.0r19/lib/domains/town/room/furnace.c ds2.0r20b/lib/domains/town/room/furnace.c *** ds2.0r19/lib/domains/town/room/furnace.c Fri Mar 24 14:36:38 2006 --- ds2.0r20b/lib/domains/town/room/furnace.c Wed Apr 12 23:47:50 2006 *************** *** 7,24 **** room::create(); SetAmbientLight(30); SetShort("the furnace"); ! SetLong("The furnace. Things that arrive here are periodically "+ "incinerated. You probably shouldn't be here. Go down to get out."); SetProperties(([ "no attack" : 1, ])); SetExits( ([ "down" : ROOM_START ]) ); ! call_out((: reload_room :), 60, load_object(base_name(this_object()))); SetNoModify(1); } int CanReceive(object ob){ return 1; } void init(){ ::init(); } --- 7,36 ---- room::create(); SetAmbientLight(30); SetShort("the furnace"); ! SetLong("The furnace. Things that arrive here are "+ "incinerated. You probably shouldn't be here. Go down to get out."); SetProperties(([ "no attack" : 1, ])); SetExits( ([ "down" : ROOM_START ]) ); ! call_out((: reload_room :), 600, load_object(base_name(this_object()))); ! set_heart_beat(1); SetNoModify(1); } int CanReceive(object ob){ + if(interactive(ob)){ + tell_object(ob, "You fail to enter the furnace."); + return 0; + } return 1; } void init(){ ::init(); } + void heart_beat(){ + if(sizeof(all_inventory(this_object()))){ + foreach(object ob in deep_inventory(this_object())){ + ob->eventDestruct(); + } + } + } diff -c -r --new-file ds2.0r19/lib/domains/town/room/voters.c ds2.0r20b/lib/domains/town/room/voters.c *** ds2.0r19/lib/domains/town/room/voters.c Mon Dec 12 19:51:56 2005 --- ds2.0r20b/lib/domains/town/room/voters.c Wed Apr 12 23:47:50 2006 *************** *** 28,35 **** SetInventory(([ ])); AddExit("west", "/domains/town/room/thall"); - //funs - //snuf } mixed ReadList() { --- 28,33 ---- *************** *** 47,58 **** if( VOTING_D->GetStatus() == VOTE_NOT_RUNNING ) { ! this_player()->eventPrint("\nSince the elections are not " ! "currently running, the list is blank."); return 1; } ! msg = "\n\tCandidates for Dead Souls Offices\n\n"; foreach( string sClass in CLASSES_D->GetClasses() ) { msg += capitalize( sClass ) + " : "; --- 45,56 ---- if( VOTING_D->GetStatus() == VOTE_NOT_RUNNING ) { ! this_player()->eventPrint(VOTING_D->GetCurrentCouncil()); return 1; } ! msg = VOTING_D->GetCurrentCouncil(); ! msg += "\n\tCandidates for Dead Souls Offices\n\n"; foreach( string sClass in CLASSES_D->GetClasses() ) { msg += capitalize( sClass ) + " : "; *************** *** 121,128 **** break; case VOTE_MODE_CANDIDATES : ! this_player()->eventPrint("Voting has not yet started, " ! "nominate a candidate instead."); break; case VOTE_NOT_PRIMARY : --- 119,127 ---- break; case VOTE_MODE_CANDIDATES : ! this_player()->eventPrint("Voting has not yet started. We are " ! "still nominating candidates. Please nominate a candidate " ! "instead."); break; case VOTE_NOT_PRIMARY : diff -c -r --new-file ds2.0r19/lib/domains/town/weap/gstaff.c ds2.0r20b/lib/domains/town/weap/gstaff.c *** ds2.0r19/lib/domains/town/weap/gstaff.c Mon Nov 7 13:30:39 2005 --- ds2.0r20b/lib/domains/town/weap/gstaff.c Wed Apr 12 23:47:50 2006 *************** *** 3,8 **** --- 3,9 ---- #include inherit LIB_ITEM; + inherit LIB_CLAN; static void create(){ item::create(); SetKeyName("golden staff"); diff -c -r --new-file ds2.0r19/lib/include/stargate.h ds2.0r20b/lib/include/stargate.h *** ds2.0r19/lib/include/stargate.h Wed Dec 31 19:00:00 1969 --- ds2.0r20b/lib/include/stargate.h Thu Apr 13 21:14:09 2006 *************** *** 0 **** --- 1,20 ---- + /** + * + * $Id: stargate.h,v 1.1 2006/04/05 05:48:39 jam Exp $ + * + */ + + #ifndef startgate_h + #define stargate_h + + #define GATE_TIMEOUT (10+random(5)) + + // address (i.e. "sgc") is a key in a mapping in the stargate daemon so it is not included here + class stargate + { + string status; + string destination; + string endpoint; + } + + #endif diff -c -r --new-file ds2.0r19/lib/lib/blank_pile.c ds2.0r20b/lib/lib/blank_pile.c *** ds2.0r19/lib/lib/blank_pile.c Mon Nov 7 13:28:59 2005 --- ds2.0r20b/lib/lib/blank_pile.c Fri Apr 14 18:27:24 2006 *************** *** 6,12 **** --- 6,16 ---- int PileAmount = 0; static void create() { + string *saveds; item::create(); + saveds = item::GetSave(); + saveds += ({ "PileType", "PileAmount" }); + AddSave( saveds ); SetKeyName("money"); } diff -c -r --new-file ds2.0r19/lib/lib/body.c ds2.0r20b/lib/lib/body.c *** ds2.0r19/lib/lib/body.c Wed Apr 5 19:33:17 2006 --- ds2.0r20b/lib/lib/body.c Wed Apr 12 23:47:53 2006 *************** *** 8,13 **** --- 8,14 ---- */ #include + #include #include #include #include *************** *** 31,37 **** private float StaminaPoints; private string Torso, Biter; private mapping Fingers, Limbs, MissingLimbs; ! private static int Dying, LastHeal; private static function Protect; private static mapping WornItems; private static class MagicProtection *Protection; --- 32,38 ---- private float StaminaPoints; private string Torso, Biter; private mapping Fingers, Limbs, MissingLimbs; ! private static int Dying, LastHeal, Encumbrance; private static function Protect; private static mapping WornItems; private static class MagicProtection *Protection; *************** *** 66,71 **** --- 67,85 ---- ExtraChannels = ({}); } + int GetEncumbrance(){ + int encumbrance = 0; + object *stuff = filter(all_inventory(this_object()), (: !($1->GetWorn()) :) ); + + //tc("ENABLE_ENCUMBRANCE: "+ENABLE_ENCUMBRANCE,"cyan"); + if(!(ENABLE_ENCUMBRANCE) || inherits(LIB_NPC,this_object()) ) return encumbrance; + //tc("bad encumbrance","red"); + if(sizeof(stuff)) foreach(object item in stuff) + encumbrance += item->GetMass(); + if(sizeof(stuff)) encumbrance *= sizeof(stuff); + return encumbrance; + } + string SetBodyComposition(string str){ if(!str) return ""; else BodyComposition = str; *************** *** 991,996 **** --- 1005,1015 ---- return 1; } + int HealLimb(string limb){ + Limbs[limb]["health"] = GetMaxHealthPoints(limb); + return Limbs[limb]["health"]; + } + int RestoreLimb(string limb) { if( !MissingLimbs[limb] ) return 0; Limbs[limb] = MissingLimbs[limb]; diff -c -r --new-file ds2.0r19/lib/lib/clan.c ds2.0r20b/lib/lib/clan.c *** ds2.0r19/lib/lib/clan.c Wed Dec 31 19:00:00 1969 --- ds2.0r20b/lib/lib/clan.c Wed Apr 12 23:56:45 2006 *************** *** 0 **** --- 1,162 ---- + #include + #include "include/clan.h" + + private class ClanClass Clan; + + private int isWelcomed; + + static void create() { + Clan = new(class ClanClass); + Clan->leader = 0; + Clan->name = 0; + Clan->objectName = 0; + Clan->skill = 0; + isWelcomed = 0; + } + + static void init() { + if(!present(this_object(), this_player())) return; + if((string)this_player()->GetClan() != (string)GetClanName()) return; + if((string)this_player()->GetKeyName() == (string)GetLeader()) { + add_action("eventBring", "bring"); + add_action("eventInitiate", "initiate"); + add_action("eventRetire", "retire"); + } + this_player()->eventPrint("\n"); + if(!isWelcomed) { + this_player()->AddChannel(GetClanName()); + eventWelcome(this_player()); + isWelcomed = 1; + } + } + + mixed CanJoin(object ob) { return 1; } + + string GetAffectLong(object ob) { + if(!ob || !living(ob)) return 0; + return ob->GetName() + " is a member of the " + + pluralize(GetClanName()) + "."; + } + + string SetLeader(string str) { + if(!user_exists(str)) error("No such user: " + str + + ". You must have a real leader."); + if(!stringp(Clan->leader)) + Clan->leader = str; + return Clan->leader; + } + + string GetLeader() { return Clan->leader; } + + string SetClanName(string str) { + if(!stringp(Clan->name)) Clan->name = str; + return Clan->name; + } + + string GetClanName() { return Clan->name; } + + string SetClanObject(string str) { + if(!stringp(Clan->objectName)) Clan->objectName = str; + return Clan->objectName; + } + + string GetClanObject() { return Clan->objectName; } + + string SetClanSkill(string str) { + if(!stringp(Clan->skill)) Clan->skill = str; + return Clan->skill; + } + + string GetClanSkill() { return Clan->skill; } + + int eventBring(string str) { + object who; + + if(!str) return notify_fail("Bring whom?\n"); + who = find_player(lower_case(str)); + if(!who) + return notify_fail(who->GetName() + " is nowhere to be found.\n"); + if((string)who->GetClan() != (string)GetClanName()) + return notify_fail(who->GetName() + " is not one of you!\n"); + if( environment(who)->GetProperty("no teleport") + || environment(this_player())->GetProperty("no teleport") + || environment(this_player())->GetProperty("no magic")) + return notify_fail("A magic force blocks your powers.\n"); + if(present(who, environment(this_player()))) + return notify_fail(capitalize(str) + " is here.\n"); + if((int)this_player()->GetMagicPoints() < 70) + return notify_fail("Too low on magic power.\n"); + this_player()->AddMagicPoints(-70); + who->eventPrint("%^CYAN%^Your clan leader summons you.%^RESET%^"); + who->eventMoveLiving(environment(this_player())); + if(!present(who, environment(this_player()))) + this_player()->eventPrint("%^CYAN%^" + capitalize(str) + + " is beyond your reach.%^RESET%^"); + return 1; + } + + int eventInitiate(string str) { + object initiate; + object clanObject; + mixed ret; + + if(!str) return notify_fail("Initiate whom?\n"); + initiate = present(lower_case(str), environment(this_player())); + if(!initiate || !living(initiate)) + return notify_fail("No one of that nature here.\n"); + if(stringp(ret = CanJoin(initiate))) return notify_fail(ret); + else if(!ret) return ret; + if((int)this_player()->GetMagicPoints() < 300) + return notify_fail("Too low on magic power.\n"); + if(initiate->GetClan()) + return notify_fail("You may only initiate people without clan " + + "affiliation.\n"); + initiate->SetClan((string)GetClanName()); + initiate->SetSkill(GetClanSkill(), 1, 1); + if(clanObject = new((string)GetClanObject())) + clanObject->eventMove(initiate); + this_player()->AddMagicPoints(-300); + eventJoin(initiate); + return 1; + } + + void eventJoin(object ob) { + ob->eventPrint("%^YELLOW%^You are now a member of the " + + pluralize((string)GetClanName()) + ".%^RESET%^"); + environment(ob)->eventPrint("%^YELLOW%^" +(string)ob->GetName() + + " is now a member of the " + + pluralize((string)GetClanName()) + ".%^RESET%^", ob); + } + + int eventRetire(string str) { + object retiree; + object clanObject; + + if(!str) return notify_fail("Retire whom?\n"); + retiree = present(lower_case(str), environment(this_player())); + if(!retiree || !living(retiree)) + return notify_fail("No one of that nature here.\n"); + if((string)retiree->GetClan() != (string)GetClanName()) + return notify_fail(retiree->GetName() + " is not one of us!\n"); + clanObject = present(GetClanName() + "_clan_object", retiree); + if(!clanObject) error("Problem with clan object."); + clanObject->eventDestruct(); + retiree->SetClan(0); + // retiree->SetSkill(GetClanSkill(), 1, 1); We need to remove skill here. + eventUnjoin(retiree); + return 1; + } + + void eventUnjoin(object ob) { + ob->eventPrint("%^RED%^You are no longer a member of the " + + pluralize((string)GetClanName()) + ".%^RESET%^"); + environment(ob)->eventPrint("%^RED%^" + (string)ob->GetName() + + " is no longer a member of the " + + pluralize((string)GetClanName()) + ".%^RESET%^", ob); + } + + void eventWelcome(object ob) { + ob->eventPrint("%^YELLOW%^Welcome, fellow " + (string)GetClanName() + + ".%^RESET%^"); + } + diff -c -r --new-file ds2.0r19/lib/lib/classes.c ds2.0r20b/lib/lib/classes.c *** ds2.0r19/lib/lib/classes.c Mon Jan 16 23:03:04 2006 --- ds2.0r20b/lib/lib/classes.c Wed Apr 12 23:48:35 2006 *************** *** 1,6 **** /* /lib/classes.c * from the Dead Souls LPC Library ! * classes and guild handling object * created by Descartes of Borg 950123 * Version: @(#) classes.c 1.4@(#) * Last modified: 96/12/13 --- 1,6 ---- /* /lib/classes.c * from the Dead Souls LPC Library ! * classes and clan handling object * created by Descartes of Borg 950123 * Version: @(#) classes.c 1.4@(#) * Last modified: 96/12/13 *************** *** 13,19 **** inherit LIB_ABILITIES; private int Morality; ! private string Class, Guild; private mapping SkillModifiers; private string *Religion; --- 13,19 ---- inherit LIB_ABILITIES; private int Morality; ! private string Class, Clan; private mapping SkillModifiers; private string *Religion; *************** *** 22,28 **** SkillModifiers = ([]); Religion = allocate(2); Class = 0; ! Guild = 0; Morality = 0; } --- 22,28 ---- SkillModifiers = ([]); Religion = allocate(2); Class = 0; ! Clan = 0; Morality = 0; } *************** *** 107,115 **** return (int)CLASSES_D->ClassMember(Class, class_name); } ! string SetGuild(string guild) { return (Guild = guild); } ! string GetGuild() { return Guild; } int GetBaseStatLevel(string stat) { return 0; } --- 107,115 ---- return (int)CLASSES_D->ClassMember(Class, class_name); } ! string SetClan(string clan) { return (Clan = clan); } ! string GetClan() { return Clan; } int GetBaseStatLevel(string stat) { return 0; } diff -c -r --new-file ds2.0r19/lib/lib/combat.c ds2.0r20b/lib/lib/combat.c *** ds2.0r19/lib/lib/combat.c Thu Apr 6 22:53:30 2006 --- ds2.0r20b/lib/lib/combat.c Wed Apr 12 23:48:35 2006 *************** *** 407,412 **** --- 407,413 ---- else { TargetLimb = limb; } + //tc("chance: "+chance); return chance; } *************** *** 433,438 **** --- 434,440 ---- else { TargetLimb = limb; } + //tc("chance: "+chance); return chance; } else { *************** *** 455,460 **** --- 457,463 ---- else { TargetLimb = limb; } + //tc("chance: "+chance); return chance; } } *************** *** 626,639 **** SendWeaponMessages(target, -1, weapon, TargetLimb); } else { // I hit, but how hard did I hit? ! int damage_type, damage, weapon_damage, actual_damage; eventTrainSkill(weapon_type + " attack", pro*2, con, 1, bonus); damage_type = weapon->GetDamageType(); damage = (weapon->eventStrike(target) * pro)/(GetLevel()*2); damage = GetDamage(damage, weapon_type + " attack"); actual_damage = target->eventReceiveDamage(this_object(), damage_type, damage, 0, TargetLimb); ! if( actual_damage < 1 ) { actual_damage = 0; } weapon_damage = damage - actual_damage; --- 629,650 ---- SendWeaponMessages(target, -1, weapon, TargetLimb); } else { // I hit, but how hard did I hit? ! int damage_type, damage, weapon_damage, actual_damage, encumbrance; ! encumbrance = this_object()->GetEncumbrance(); ! //tc("encumbrance: "+encumbrance,"white"); ! if(encumbrance > 30){ ! //tc("feep","yellow"); ! tell_object(this_object(),"You struggle to fight while heavily encumbered."); ! } eventTrainSkill(weapon_type + " attack", pro*2, con, 1, bonus); damage_type = weapon->GetDamageType(); damage = (weapon->eventStrike(target) * pro)/(GetLevel()*2); damage = GetDamage(damage, weapon_type + " attack"); + damage -= encumbrance; + if(damage < 0) damage = 0; actual_damage = target->eventReceiveDamage(this_object(), damage_type, damage, 0, TargetLimb); ! if( actual_damage < 0 ) { actual_damage = 0; } weapon_damage = damage - actual_damage; *************** *** 711,723 **** GetCombatBonus(target->GetLevel())); } else { ! int x; ! // I hit, how hard? eventTrainSkill("melee attack", pro, con, 1, GetCombatBonus(target->GetLevel())); if(this_object()->GetMelee()) x = GetDamage(3*chance/4, "melee attack"); else x = GetDamage(3*chance/20, "melee attack"); x = target->eventReceiveDamage(this_object(), BLUNT, x, 0, TargetLimb); if( !target->GetDying() ) { --- 722,741 ---- GetCombatBonus(target->GetLevel())); } else { ! int x, encumbrance; ! encumbrance = this_object()->GetEncumbrance(); ! //tc("encumbrance: "+encumbrance,"white"); ! if(encumbrance > 30){ ! //tc("feep","blue"); ! tell_object(this_object(),"You struggle to fight while heavily encumbered."); ! } // I hit, how hard? eventTrainSkill("melee attack", pro, con, 1, GetCombatBonus(target->GetLevel())); if(this_object()->GetMelee()) x = GetDamage(3*chance/4, "melee attack"); else x = GetDamage(3*chance/20, "melee attack"); + x -= encumbrance; + if(x < 0) x = 0; x = target->eventReceiveDamage(this_object(), BLUNT, x, 0, TargetLimb); if( !target->GetDying() ) { *************** *** 898,905 **** varargs int eventReceiveDamage(object agent, int type, int x, int internal, mixed limbs) { ! int hp; ! x = race::eventReceiveDamage(agent, type, x, internal, limbs); if( !Wimpy ) return x; if( (hp = GetHealthPoints()) < 1 ) return x; --- 916,928 ---- varargs int eventReceiveDamage(object agent, int type, int x, int internal, mixed limbs) { ! int hp,encumbrance; ! encumbrance = this_object()->GetEncumbrance(); ! //tc("encumbrance: "+encumbrance,"white"); ! if(encumbrance > 30){ ! //tc("feep","green"); ! tell_object(this_object(),"You try to dodge while weighed down."); ! } x = race::eventReceiveDamage(agent, type, x, internal, limbs); if( !Wimpy ) return x; if( (hp = GetHealthPoints()) < 1 ) return x; diff -c -r --new-file ds2.0r19/lib/lib/command.c ds2.0r20b/lib/lib/command.c *** ds2.0r19/lib/lib/command.c Tue Mar 28 23:23:41 2006 --- ds2.0r20b/lib/lib/command.c Wed Apr 12 23:48:35 2006 *************** *** 26,32 **** apostrophe_exceptions += ({"say","speak","yell","whisper","shout"}); //Fix here courtesy of Jonez apostrophe_exceptions += ({"ping", "reply"}); ! SearchPath = ({ DIR_PLAYER_CMDS, DIR_SECURE_PLAYER_CMDS, DIR_GUILD_CMDS, DIR_COMMON_CMDS, DIR_SECURE_COMMON_CMDS }); } --- 26,32 ---- apostrophe_exceptions += ({"say","speak","yell","whisper","shout"}); //Fix here courtesy of Jonez apostrophe_exceptions += ({"ping", "reply"}); ! SearchPath = ({ DIR_PLAYER_CMDS, DIR_SECURE_PLAYER_CMDS, DIR_CLAN_CMDS, DIR_COMMON_CMDS, DIR_SECURE_COMMON_CMDS }); } diff -c -r --new-file ds2.0r19/lib/lib/comp/holder.c ds2.0r20b/lib/lib/comp/holder.c *** ds2.0r19/lib/lib/comp/holder.c Mon Nov 7 13:31:06 2005 --- ds2.0r20b/lib/lib/comp/holder.c Sun Apr 9 23:49:20 2006 *************** *** 82,87 **** --- 82,88 ---- return tmp; } AddCarriedMass(ob->GetMass()); + this_object()->SetMass(this_object()->GetMass() + ob->GetMass()); parse_refresh(); return 1; } *************** *** 90,96 **** int x; x = container::eventReleaseObject(ob); ! call_out((: parse_refresh :), 0); return x; } --- 91,100 ---- int x; x = container::eventReleaseObject(ob); ! //call_out((: parse_refresh :), 0); ! AddCarriedMass(-(ob->GetMass())); ! this_object()->SetMass(this_object()->GetMass() - ob->GetMass()); ! parse_refresh(); return x; } diff -c -r --new-file ds2.0r19/lib/lib/creator.c ds2.0r20b/lib/lib/creator.c *** ds2.0r19/lib/lib/creator.c Wed Apr 5 19:33:17 2006 --- ds2.0r20b/lib/lib/creator.c Wed Apr 12 23:48:35 2006 *************** *** 178,184 **** laston = GetLoginTime(); if( !player::Setup() ) return 0; ! AddChannel(({"cre", "newbie", "gossip", "ds", "death","intergossip","intercre" })); AddChannel((string array)CLASSES_D->GetClasses()); if( archp() ) AddChannel( ({ "admin", "error" }) ); AddSearchPath( ({ DIR_CREATOR_CMDS, DIR_SECURE_CREATOR_CMDS }) ); --- 178,184 ---- laston = GetLoginTime(); if( !player::Setup() ) return 0; ! AddChannel(({"cre", "newbie", "gossip", "ds", "ds_test", "lpuni", "death","intergossip","intercre" })); AddChannel((string array)CLASSES_D->GetClasses()); if( archp() ) AddChannel( ({ "admin", "error" }) ); AddSearchPath( ({ DIR_CREATOR_CMDS, DIR_SECURE_CREATOR_CMDS }) ); diff -c -r --new-file ds2.0r19/lib/lib/donate.c ds2.0r20b/lib/lib/donate.c *** ds2.0r19/lib/lib/donate.c Thu Jan 5 00:17:58 2006 --- ds2.0r20b/lib/lib/donate.c Wed Apr 12 23:48:35 2006 *************** *** 16,22 **** static void init() { if( (string)this_player()->ClassMember((string)GetOwner()) || ! (string)this_player()->GetGuild() == (string)GetOwner() ) { add_action( (: eventDonate :) , "donate" ); } } --- 16,22 ---- static void init() { if( (string)this_player()->ClassMember((string)GetOwner()) || ! (string)this_player()->GetClan() == (string)GetOwner() ) { add_action( (: eventDonate :) , "donate" ); } } diff -c -r --new-file ds2.0r19/lib/lib/events/put.c ds2.0r20b/lib/lib/events/put.c *** ds2.0r19/lib/lib/events/put.c Wed Dec 7 14:03:05 2005 --- ds2.0r20b/lib/lib/events/put.c Thu Apr 13 21:03:52 2006 *************** *** 24,35 **** mixed tmp; if( (tmp = CanDrop(who)) != 1 ) return tmp; if( !environment() ) { destruct(this_object()); return 1; } ! if( environment() != this_player() ) return 0; if( !PreventPut ) return 1; if( stringp(PreventPut) && PreventPut == "PERMIT" ) return 1; if( intp(PreventPut) ) return 0; if( stringp(PreventPut) ) return PreventPut; if( objectp(PreventPut) ) { if( PreventPut == who ) return "You cannot put " + GetShort() + " anywhere."; --- 24,43 ---- mixed tmp; if( (tmp = CanDrop(who)) != 1 ) return tmp; + //debug("i dunno 1"); if( !environment() ) { destruct(this_object()); return 1; } ! //debug("i dunno 2"); ! if( environment() != this_player() && ! environment() != environment(this_player())) return 0; ! //debug("i dunno 3"); if( !PreventPut ) return 1; + //debug("i dunno 4"); if( stringp(PreventPut) && PreventPut == "PERMIT" ) return 1; + //debug("i dunno 5"); if( intp(PreventPut) ) return 0; + //debug("i dunno 6"); if( stringp(PreventPut) ) return PreventPut; + //debug("i dunno 7"); if( objectp(PreventPut) ) { if( PreventPut == who ) return "You cannot put " + GetShort() + " anywhere."; *************** *** 80,82 **** --- 88,94 ---- return CanPut(this_player()); } + mixed direct_put_wrd_wrd_word_obj(){ + return CanPut(this_player()); + } + diff -c -r --new-file ds2.0r19/lib/lib/genetics.c ds2.0r20b/lib/lib/genetics.c *** ds2.0r19/lib/lib/genetics.c Sat Mar 11 11:16:11 2006 --- ds2.0r20b/lib/lib/genetics.c Sun Apr 9 23:49:20 2006 *************** *** 99,111 **** varargs void AddStat(string stat, int base, int cls) { int level; ! if( userp(this_object()) ) level = 1; else level = GetLevel(); if( !stat || cls < 1 || cls > 5 ) return; base += ((5 - cls) * random(10)) + (3 * (level + 1))/(cls * 4); if( userp(this_object()) && base > 90 ) base = 90; else if( base > 100 ) base = 100; SetStat(stat, base, cls); } --- 99,112 ---- varargs void AddStat(string stat, int base, int cls) { int level; ! //tc("stat: "+stat+", base: "+base+", cls: "+cls,"red"); if( userp(this_object()) ) level = 1; else level = GetLevel(); if( !stat || cls < 1 || cls > 5 ) return; base += ((5 - cls) * random(10)) + (3 * (level + 1))/(cls * 4); if( userp(this_object()) && base > 90 ) base = 90; else if( base > 100 ) base = 100; + //tc("stat: "+stat+", base: "+base+", cls: "+cls,"green"); SetStat(stat, base, cls); } diff -c -r --new-file ds2.0r19/lib/lib/guild.c ds2.0r20b/lib/lib/guild.c *** ds2.0r19/lib/lib/guild.c Wed Dec 7 14:03:18 2005 --- ds2.0r20b/lib/lib/guild.c Wed Dec 31 19:00:00 1969 *************** *** 1,165 **** - - #include - #include "include/guild.h" - - class GuildClass Guild; - - //private static class GuildClass; - private int isWelcomed; - class Guild = new(class GuildClass); - - static void create() { - Guild = new(class GuildClass); - Guild->leader = 0; - Guild->name = 0; - Guild->objectName = 0; - Guild->skill = 0; - isWelcomed = 0; - } - - static void init() { - if(!present(this_object(), this_player())) return; - if((string)this_player()->GetGuild() != (string)GetGuildName()) return; - if((string)this_player()->GetKeyName() == (string)GetLeader()) { - add_action((:eventBring:), "bring"); - add_action((:eventInitiate:), "initiate"); - add_action((:eventRetire:), "retire"); - } - this_player()->eventPrint("\n"); - if(!isWelcomed) { - this_player()->AddChannel(GetGuildName()); - eventWelcome(this_player()); - isWelcomed = 1; - } - } - - mixed CanJoin(object ob) { return 1; } - - string GetAffectLong(object ob) { - if(!ob || !living(ob)) return 0; - return ob->GetName() + " is a member of the " - + pluralize(GetGuildName()) + "."; - } - - string SetLeader(string str) { - if(!user_exists(str)) error("No such user: " + str - + ". You must have a real leader."); - if(!stringp(Guild->leader)) - Guild->leader = str; - return Guild->leader; - } - - string GetLeader() { return Guild->leader; } - - string SetGuildName(string str) { - if(!stringp(Guild->name)) Guild->name = str; - return Guild->name; - } - - string GetGuildName() { return Guild->name; } - - string SetGuildObject(string str) { - if(!stringp(Guild->objectName)) Guild->objectName = str; - return Guild->objectName; - } - - string GetGuildObject() { return Guild->objectName; } - - string SetGuildSkill(string str) { - if(!stringp(Guild->skill)) Guild->skill = str; - return Guild->skill; - } - - string GetGuildSkill() { return Guild->skill; } - - int eventBring(string str) { - object who; - - if(!str) return notify_fail("Bring whom?\n"); - who = find_player(lower_case(str)); - if(!who) - return notify_fail(who->GetName() + " is nowhere to be found.\n"); - if((string)who->GetGuild() != (string)GetGuildName()) - return notify_fail(who->GetName() + " is not one of you!\n"); - if( environment(who)->GetProperty("no teleport") - || environment(this_player())->GetProperty("no teleport") - || environment(this_player())->GetProperty("no magic")) - return notify_fail("A magic force blocks your powers.\n"); - if(present(who, environment(this_player()))) - return notify_fail(capitalize(str) + " is here.\n"); - if((int)this_player()->GetMagicPoints() < 70) - return notify_fail("Too low on magic power.\n"); - this_player()->AddMagicPoints(-70); - who->eventPrint("%^CYAN%^Your guild leader summons you.%^RESET%^"); - who->eventMoveLiving(environment(this_player())); - if(!present(who, environment(this_player()))) - this_player()->eventPrint("%^CYAN%^" + capitalize(str) - + " is beyond your reach.%^RESET%^"); - return 1; - } - - int eventInitiate(string str) { - object initiate; - object guildObject; - mixed ret; - - if(!str) return notify_fail("Initiate whom?\n"); - initiate = present(lower_case(str), environment(this_player())); - if(!initiate || !living(initiate)) - return notify_fail("No one of that nature here.\n"); - if(stringp(ret = CanJoin(initiate))) return notify_fail(ret); - else if(!ret) return ret; - if((int)this_player()->GetMagicPoints() < 300) - return notify_fail("Too low on magic power.\n"); - if(initiate->GetGuild()) - return notify_fail("You may only initiate people without guild " - + "affiliation.\n"); - initiate->SetGuild((string)GetGuildName()); - initiate->SetSkill(GetGuildSkill(), 1, 1); - if(guildObject = new((string)GetGuildObject())) - guildObject->eventMove(initiate); - this_player()->AddMagicPoints(-300); - eventJoin(initiate); - return 1; - } - - void eventJoin(object ob) { - ob->eventPrint("%^YELLOW%^You are now a member of the " - + pluralize((string)GetGuildName()) + ".%^RESET%^"); - environment(ob)->eventPrint("%^YELLOW%^" +(string)ob->GetName() - + " is now a member of the " - + pluralize((string)GetGuildName()) + ".%^RESET%^", ob); - } - - int eventRetire(string str) { - object retiree; - object guildObject; - - if(!str) return notify_fail("Retire whom?\n"); - retiree = present(lower_case(str), environment(this_player())); - if(!retiree || !living(retiree)) - return notify_fail("No one of that nature here.\n"); - if((string)retiree->GetGuild() != (string)GetGuildName()) - return notify_fail(retiree->GetName() + " is not one of us!\n"); - guildObject = present(GetGuildName() + "_guild_object", retiree); - if(!guildObject) error("Problem with guild object."); - guildObject->eventDestruct(); - retiree->SetGuild(0); - // retiree->SetSkill(GetGuildSkill(), 1, 1); We need to remove skill here. - eventUnjoin(retiree); - return 1; - } - - void eventUnjoin(object ob) { - ob->eventPrint("%^RED%^You are no longer a member of the " - + pluralize((string)GetGuildName()) + ".%^RESET%^"); - environment(ob)->eventPrint("%^RED%^" + (string)ob->GetName() - + " is no longer a member of the " - + pluralize((string)GetGuildName()) + ".%^RESET%^", ob); - } - - void eventWelcome(object ob) { - ob->eventPrint("%^YELLOW%^Welcome, fellow " + (string)GetGuildName() - + ".%^RESET%^"); - } - --- 0 ---- diff -c -r --new-file ds2.0r19/lib/lib/include/clan.h ds2.0r20b/lib/lib/include/clan.h *** ds2.0r19/lib/lib/include/clan.h Wed Dec 31 19:00:00 1969 --- ds2.0r20b/lib/lib/include/clan.h Wed Apr 12 23:56:45 2006 *************** *** 0 **** --- 1,38 ---- + + + #ifndef l_clan_h + #define l_clan_h + + + class ClanClass { + string leader; + string name; + string objectName; + string skill; + } + + static void create(); + static void init(); + + mixed CanJoin(object ob); + string GetAffectLong(object ob); + string SetLeader(string str); + string GetLeader(); + string SetClanName(string str); + string GetClanName(); + string SetClanObject(string str); + string GetClanObject(); + string SetClanSkill(string str); + string GetClanSkill(); + + int eventBring(string str); + int eventInitiate(string str); + void eventJoin(object ob); + int eventRetire(string str); + void eventUnjoin(object ob); + void eventWelcome(object ob); + + + #endif /* l_clan_h */ + + diff -c -r --new-file ds2.0r19/lib/lib/include/classes.h ds2.0r20b/lib/lib/include/classes.h *** ds2.0r19/lib/lib/include/classes.h Wed Sep 28 19:34:11 2005 --- ds2.0r20b/lib/lib/include/classes.h Wed Apr 12 23:48:44 2006 *************** *** 10,17 **** string GetSkillModifier(string skill); string SetClass(string classes); string GetClass(); ! string SetGuild(string guild); ! string GetGuild(); int GetBaseStatLevel(string stat); int SetMorality(int x); int GetMorality(); --- 10,17 ---- string GetSkillModifier(string skill); string SetClass(string classes); string GetClass(); ! string SetClan(string clan); ! string GetClan(); int GetBaseStatLevel(string stat); int SetMorality(int x); int GetMorality(); diff -c -r --new-file ds2.0r19/lib/lib/include/guild.h ds2.0r20b/lib/lib/include/guild.h *** ds2.0r19/lib/lib/include/guild.h Wed Sep 28 19:34:11 2005 --- ds2.0r20b/lib/lib/include/guild.h Wed Dec 31 19:00:00 1969 *************** *** 1,38 **** - - - #ifndef l_guild_h - #define l_guild_h - - - class GuildClass { - string leader; - string name; - string objectName; - string skill; - } - - static void create(); - static void init(); - - mixed CanJoin(object ob); - string GetAffectLong(object ob); - string SetLeader(string str); - string GetLeader(); - string SetGuildName(string str); - string GetGuildName(); - string SetGuildObject(string str); - string GetGuildObject(); - string SetGuildSkill(string str); - string GetGuildSkill(); - - int eventBring(string str); - int eventInitiate(string str); - void eventJoin(object ob); - int eventRetire(string str); - void eventUnjoin(object ob); - void eventWelcome(object ob); - - - #endif /* l_guild_h */ - - --- 0 ---- diff -c -r --new-file ds2.0r19/lib/lib/include/player.h ds2.0r20b/lib/lib/include/player.h *** ds2.0r19/lib/lib/include/player.h Wed Sep 28 19:34:11 2005 --- ds2.0r20b/lib/lib/include/player.h Wed Apr 12 23:48:52 2006 *************** *** 57,63 **** string GetCapName(); int ResetLevel(); string SetClass(string str); ! string SetGuild(string guild); varargs static int AddHealthPoints(int x, string limb, object agent); int GetLanguageLevel(string lang); int is_living(); --- 57,63 ---- string GetCapName(); int ResetLevel(); string SetClass(string str); ! string SetClan(string clan); varargs static int AddHealthPoints(int x, string limb, object agent); int GetLanguageLevel(string lang); int is_living(); diff -c -r --new-file ds2.0r19/lib/lib/include/stargate.h ds2.0r20b/lib/lib/include/stargate.h *** ds2.0r19/lib/lib/include/stargate.h Wed Dec 31 19:00:00 1969 --- ds2.0r20b/lib/lib/include/stargate.h Thu Apr 13 21:14:09 2006 *************** *** 0 **** --- 1,18 ---- + /** + * + * $Id: stargate.h,v 1.1 2006/04/05 05:48:39 jam Exp $ + * + */ + + #include "/include/stargate.h" + + #ifndef lib_stargate_h + #define lib_stargate_h + + void setOrigin(string o, string d); + string getOrigin(); + void connect(string destination); + int disconnect(); + string status(); + + #endif diff -c -r --new-file ds2.0r19/lib/lib/interactive.c ds2.0r20b/lib/lib/interactive.c *** ds2.0r19/lib/lib/interactive.c Wed Apr 5 19:33:18 2006 --- ds2.0r20b/lib/lib/interactive.c Thu Apr 13 21:03:57 2006 *************** *** 152,157 **** --- 152,158 ---- get_livings(load_object("/secure/room/control"))->eventPrint("[" + GetKeyName()+ " goes net-dead]", MSG_SYSTEM); } + SNOOP_D->ReportLinkDeath(this_object()->GetKeyName()); eventMove(ROOM_FREEZER); if(query_snoop(this_object())) query_snoop(this_object())->eventPrint(GetCapName() + " has gone " *************** *** 208,216 **** if(desc && desc != "") desc = capitalize((string)env->GetShort() || "") + " [" + desc + "]\n"; ! else desc = capitalize((string)env->GetShort() || ""); } ! else desc = ""; if( i == VISION_CLEAR || i == VISION_LIGHT || i == VISION_DIM ) desc += (string)env->GetLong(); if(functionp(tmp = (mixed)env->GetSmell("default"))) --- 209,217 ---- if(desc && desc != "") desc = capitalize((string)env->GetShort() || "") + " [" + desc + "]\n"; ! else desc = capitalize((string)env->GetShort()+"\n" || "\n"); } ! else desc = "\n"; if( i == VISION_CLEAR || i == VISION_LIGHT || i == VISION_DIM ) desc += (string)env->GetLong(); if(functionp(tmp = (mixed)env->GetSmell("default"))) *************** *** 228,235 **** desc = (string)env->GetShort(); if( (tmp = (string)env->GetObviousExits()) && tmp != "" ) desc += " [" + tmp + "]"; } ! else desc = ""; } if( desc ) eventPrint(desc, MSG_ROOMDESC); if( smell ) eventPrint("%^GREEN%^" + smell, MSG_ROOMDESC); --- 229,237 ---- desc = (string)env->GetShort(); if( (tmp = (string)env->GetObviousExits()) && tmp != "" ) desc += " [" + tmp + "]"; + else desc += "\n"; } ! else desc = "\n"; } if( desc ) eventPrint(desc, MSG_ROOMDESC); if( smell ) eventPrint("%^GREEN%^" + smell, MSG_ROOMDESC); diff -c -r --new-file ds2.0r19/lib/lib/persist.c ds2.0r20b/lib/lib/persist.c *** ds2.0r19/lib/lib/persist.c Wed Apr 5 19:33:18 2006 --- ds2.0r20b/lib/lib/persist.c Wed Apr 12 23:48:53 2006 *************** *** 15,21 **** string *flat = ({}); mixed *tmp; ! tc("Hit eventConvertObject","red"); if( val[0] != base_name(this_object()) ) error("Invalid save string.\n"); tmp = map(Saved, (: functionp($1) ? evaluate($1, "loading") : $1 :)); foreach(mixed elem in tmp) { --- 15,21 ---- string *flat = ({}); mixed *tmp; ! //tc("Hit eventConvertObject","red"); if( val[0] != base_name(this_object()) ) error("Invalid save string.\n"); tmp = map(Saved, (: functionp($1) ? evaluate($1, "loading") : $1 :)); foreach(mixed elem in tmp) { diff -c -r --new-file ds2.0r19/lib/lib/pile.c ds2.0r20b/lib/lib/pile.c *** ds2.0r19/lib/lib/pile.c Mon Nov 7 13:29:00 2005 --- ds2.0r20b/lib/lib/pile.c Fri Apr 14 18:27:24 2006 *************** *** 14,20 **** --- 14,24 ---- private int PileAmount = 0; static void create() { + string *saveds; item::create(); + saveds = item::GetSave(); + saveds += ({ "PileType", "PileAmount" }); + AddSave( saveds ); SetKeyName("pile"); } diff -c -r --new-file ds2.0r19/lib/lib/player.c ds2.0r20b/lib/lib/player.c *** ds2.0r19/lib/lib/player.c Wed Apr 5 19:33:18 2006 --- ds2.0r20b/lib/lib/player.c Wed Apr 12 23:48:53 2006 *************** *** 438,443 **** --- 438,444 ---- object jeans, shirt, book; if(ENGLISH_ONLY) this_object()->SetNativeLanguage("English"); + PLAYERS_D->AddPlayerInfo(this_object()); jeans = new("/domains/default/armor/jeans"); shirt = new("/domains/default/armor/shirt"); diff -c -r --new-file ds2.0r19/lib/lib/props/description.c ds2.0r20b/lib/lib/props/description.c *** ds2.0r19/lib/lib/props/description.c Sat Mar 11 11:16:12 2006 --- ds2.0r20b/lib/lib/props/description.c Sun Apr 9 23:49:21 2006 *************** *** 41,46 **** --- 41,49 ---- mixed direct_reload() { return 1; } mixed indirect_reload() { return 1; } + mixed direct_reload_every_str() { return 1; } + mixed indirect_reload_every_str() { return 1; } + mixed direct_copy_obj_to_obj() { return 1; } mixed direct_copy_obj_str() { return 1; } diff -c -r --new-file ds2.0r19/lib/lib/race.c ds2.0r20b/lib/lib/race.c *** ds2.0r19/lib/lib/race.c Wed Apr 5 19:33:18 2006 --- ds2.0r20b/lib/lib/race.c Sun Apr 9 23:49:21 2006 *************** *** 103,108 **** --- 103,109 ---- } foreach(tmp in args[1]) { mixt = copy(args[1]); + //tc("mixt: "+identify(mixt),"blue"); AddStat(tmp...); } if( stringp(args[2]) ) { diff -c -r --new-file ds2.0r19/lib/lib/stargate.c ds2.0r20b/lib/lib/stargate.c *** ds2.0r19/lib/lib/stargate.c Wed Dec 31 19:00:00 1969 --- ds2.0r20b/lib/lib/stargate.c Thu Apr 13 21:14:09 2006 *************** *** 0 **** --- 1,244 ---- + #include + #include + #include "/lib/include/stargate.h" + + /** + * 2006-03-28, jonez + * - based on a suggestion from rhk, changed so that one cannot enter the + * gate unless status is "outbound". this makes the object closer to the + * (theoretical) math and also to what happens on the show. + */ + + /** + * based on portal.c by Brodbane - March 2006 + * + * $Id: stargate.c,v 1.1 2006/04/05 05:48:39 jam Exp $ + * + * The desired functionality is much like a "star gate": users dialed + * letters or full words that lined up with destinations. A portal opens to + * that destination briefly. To define destinations you must setup a + * constant below then add it to the switch statement in the cmdDial + * function. This object is crude and basic, but gets the job done. + * + * 2006-03-22, jonez + * - original version of this file is from Daelas@Moraelinost + * 2006-03-23, jonez + * - altered so code uses existing verbs (touch, enter) where possible. last add_action is for dial command. + * - added single mapping called "database" and made the "dial" command use it. + * - dial command no longer uses switch/case, making adding a new destination simpler + * - made use of SetPreventGet() / SetPreventPut() + * - made use of new stargate daemon + * - made use of LIB_STARGATE + * - made use of STARGATE_D + * + * IDEAS: + * - create a daemon that holds the stargate network [DONE] + * - allow for stargate failure + * - add dhd object + * - change the code so that it uses a single mapping of names and + * destinations, perhaps in a database file. currently an update to the + * object requires an update for all the objects. [DONE] + * - dhd skill (thanks plato) + * - delay when dialing gate. destination dhd lights up? + * - player should not be able to dial earth if earth is already connected elsewhere (need daemon) [DONE] + * - make use of existing verbs (enter, touch) instead of doing our own thing. [DONE] + * - daemon should contain a class that maps the various gates to each other. see lib/include/door.h [DONE] + * - shout "off world activation" into the gateroom when the gate engages. + * - track status as "incoming" or "outgoing".. you can only "enter" an outgoing gate (rhk) [DONE] + * - if room is empty, shut down the gate (rhk) + * - change callout time when someone goes through the gate (rhk) + */ + + inherit LIB_ITEM; + + static private string origin; + + string displayLong(); + string displayShort(); + + void create() + { + item::create(); + + SetKeyName("stargate"); + SetId(({"stargate", "gate", "portal", "ring"})); + SetAdjectives(({"stargate"})); + SetShort( (: displayShort :) ); + + SetLong( (: displayLong :) ); + + AddItem( "inner ring", "The second ring - the inner ring - is placed " + "inside the larger ring and seems to be able to move."); + SetMass(1000); + SetBaseCost("silver",50); + SetPreventGet("The gate is pure naquadah and cannot be moved"); + SetPreventPut("The gate is pure naquadah and cannot be moved"); + SetTouch("You feel the stargate beneath your hand humming with energy."); + } + + void init() + { + ::init(); + add_action( "cmdDial", "dial" ); + add_action( "cmdEnter", "enter"); + } + + + void setOrigin(string o, string d) + { + if (o == "" || d == "") return; + origin = lower_case(o); + STARGATE_D->setStargate(origin, d); + } + + string getOrigin() + { + return origin; + } + + void connect(string destination) + { + int ret; + + destination = lower_case(destination); + + if (origin == destination) + { + write("You attempt to dial the gate, but the last chevron does not engage"); + say(this_player()->GetName() + " tries to dial the gate but the last chevron does not engage"); + return; + } + + ret = STARGATE_D->connect(origin, destination); + if (ret) + { + string d = STARGATE_D->getDestination(destination); + write("The ancient rings lock into place and a portal forms in an explosion of energy."); + say("The ancient rings lock into place and a portal forms in an explosion of energy."); + tell_room(d, "The ancient rings lock into place and a portal forms in an explosion of energy"); + call_out("disconnect", 10+random(5)); + return; + } + + write("You attempt to dial the stargate, but nothing happens."); + say(this_player()->GetName() + " tries to dial the gate but fails."); + + return; + } + + int disconnect() + { + string e = STARGATE_D->getEndpoint(origin); + string d = STARGATE_D->getDestination(e); + + debug(sprintf("stargate_lib->disconnect(%s), e=%s, d=%s", origin, e, d)); + + // FIX: does the player get a message if they come through the gate and then leave the room? + write("The chevrons on the stargate disengage and the portal disappears."); + say("The chevrons on the stargate disengage and the portal disappears."); + tell_room(d, "The chevrons on the stargate disengage and the portal disappears", ({ this_player() })); + + return STARGATE_D->disconnect(origin); + } + + string status() + { + return STARGATE_D->getStatus(origin); + } + + mixed cmdDial(string s) + { + if (s) + { + connect(s); + return 1; + } + + return 0; + + } + + int cmdEnter(string what) + { + string endpoint, destination; + object who; + + if (what != "gate" && what != "stargate") + { + return 0; + } + + if (status() != "outbound") + { + return 0; + } + + who = this_player(); + endpoint = STARGATE_D->getEndpoint(origin); + destination = STARGATE_D->getDestination(endpoint); + debug("endpoint=" + endpoint); + debug("destination=" + destination); + who->eventPrint("You step through the event horizon of the stargate."); + who->eventMoveLiving(destination, + "$N steps into the event horizon and disappears", + "$N steps out of the event horizon"); + return 1; + + } + + int eventEnter(object who) + { + string endpoint; + + if (!who) return 0; + + endpoint = STARGATE_D->getEndpoint(origin); + if (status() == "connected") + { + who->eventPrint("You step through the event horizon of the stargate."); + who->eventMoveLiving(endpoint, + "$N steps into the event horizon and disappears", + "$N steps out of the event horizon"); + } + return 1; + } + + string displayLong() + { + string buf, stat; + + buf = "This is the Stargate of legend. The Stargate was created " + "from naquadah ore, similar to black quartz. It is a perfectly " + "circular device approximately ten meters in diameter and " + "comprised of two sets of rings and nine chevrons placed " + "equidistant along its outer circumfrence."; + + stat = status(); + + if (stat == "outbound" || stat == "inbound") + { + buf += " There is an event horizon in the center of the ring that looks like shimmering water."; + } + else if (stat == "idle") + { + buf += " This gate is currently idle."; + } + return buf; + } + + string displayShort() + { + string stat; + stat = status(); + switch (stat) + { + case "inbound": + return "an inbound stargate"; + case "outbound": + return "an outbound stargate"; + case "idle": + return "an idle stargate"; + default: + return "a broken stargate"; + } + } diff -c -r --new-file ds2.0r19/lib/obj/stargate.c ds2.0r20b/lib/obj/stargate.c *** ds2.0r19/lib/obj/stargate.c Wed Dec 31 19:00:00 1969 --- ds2.0r20b/lib/obj/stargate.c Thu Apr 13 21:14:11 2006 *************** *** 0 **** --- 1,83 ---- + #include + #include + #include "/lib/include/stargate.h" + + /** + * based on portal.c by Brodbane - March 2006 + * + * $Id: stargate.c,v 1.1 2006/04/05 05:48:39 jam Exp $ + * + * The desired functionality is much like a "star gate": users dialed + * letters or full words that lined up with destinations. A portal opens to + * that destination briefly. To define destinations you must setup a + * constant below then add it to the switch statement in the cmdDial + * function. This object is crude and basic, but gets the job done. + * + * 2006-03-22, jonez + * - original version of this file is from Daelas@Moraelinost + * 2006-03-23, jonez + * - altered so code uses existing verbs (touch, enter) where possible. last add_action is for dial command. + * - added single mapping called "database" and made the "dial" command use it. + * - dial command no longer uses switch/case, making adding a new destination simpler + * - made use of SetPreventGet() / SetPreventPut() + * - made use of new stargate daemon + * - made use of LIB_STARGATE + * - made use of STARGATE_D + * + * IDEAS: + * - create a daemon that holds the stargate network [DONE] + * - allow for stargate failure + * - add dhd object + * - change the code so that it uses a single mapping of names and + * destinations, perhaps in a database file. currently an update to the + * object requires an update for all the objects. [DONE] + * - dhd skill (thanks plato) + * - delay when dialing gate. destination dhd lights up? + * - player should not be able to dial earth if earth is already connected elsewhere (need daemon) [DONE] + * - make use of existing verbs (enter, touch) instead of doing our own thing. [DONE] + * - daemon should contain a class that maps the various gates to each other. see lib/include/door.h [DONE] + * - shout "off world activation" into the gateroom when the gate engages. + * - track status as "incoming" or "outgoing".. you can only "enter" an outgoing gate (rhk) [DONE] + * - if room is empty, shut down the gate (rhk) + * - change callout time when someone goes through the gate (rhk) + */ + + /* + Cratylus@Dead Souls but let me give you a quick outline + Cratylus@Dead Souls i type dial thing + Cratylus@Dead Souls the thing inherits LIB_DIAL + Cratylus@Dead Souls which is in /lib/events/dial.c + Cratylus@Dead Souls and all that contains is like direct_dial_ob() return 1; this kind of thing + Cratylus@Dead Souls take a look at LIB_TURN + Cratylus@Dead Souls what LIB_DIAL does is provide the object with hooks, so it *can* be dialed + Cratylus@Dead Souls so, when i type dial thing, the thing goes, yeah i + can be dialed, and then the parser enters the can_dial and do_dial funcs + in the verb + Cratylus@Dead Souls tellya what. i'd like to work with you on this one. i think it's less straightforward than it + seems, and i need to test some ideas before i can say "do it this way" + + */ + inherit LIB_STARGATE; + + int readScreen(); + + void create() + { + ::create(); + setOrigin("default", "/obj/room"); + // SetRead(([ ({ "screen" }) : (: readScreen :) ]) ); + // SetItems(([ ({ "screen" }) : "a computer screen which shows the status of the gate network" ]) ); + } + + void init() + { + ::init(); + } + + int readScreen() + { + write("stargate network status\n"); + write("-----------------------\n"); + write("\n"); + + } diff -c -r --new-file ds2.0r19/lib/secure/cfg/preload.cfg ds2.0r20b/lib/secure/cfg/preload.cfg *** ds2.0r19/lib/secure/cfg/preload.cfg Fri Mar 24 14:37:42 2006 --- ds2.0r20b/lib/secure/cfg/preload.cfg Wed Apr 12 23:49:14 2006 *************** *** 9,14 **** --- 9,15 ---- #/secure/daemon/remote #/secure/daemon/inet /secure/daemon/log + /secure/daemon/snoop /secure/room/arch /secure/room/control /secure/daemon/update diff -c -r --new-file ds2.0r19/lib/secure/cmds/admins/banish.c ds2.0r20b/lib/secure/cmds/admins/banish.c *** ds2.0r19/lib/secure/cmds/admins/banish.c Wed Dec 31 19:00:00 1969 --- ds2.0r20b/lib/secure/cmds/admins/banish.c Sun Apr 9 23:40:55 2006 *************** *** 0 **** --- 1,36 ---- + // /bin/dev/_banish.c + // from the Dead Souls Mudlib + // prevents a name being used by a new player + // created by Descartes of Borg ??? + + #include + #include + + inherit LIB_DAEMON; + + int cmd(string str) { + if(!str || str == ""){ + write("Syntax: banish "); + return 1; + } + if(!user_exists(str = lower_case(str))) { + write(capitalize(str)+" is now banished.\n"); + catch(call_other(BANISH_D, "banish_name", str)); + } + else { + write("A player by that name already exists.\n"); + this_player()->eventPrint((string)FINGER_D->GetFinger(str)); + } + return 1; + } + + void help() { + write("Syntax: \n\n" + "Protects a name from being used by a new player.\n" + "For example, if you have created a monster named Cassandra, in order\n" + "to avoid problems with player complaining \"I typed 'kill\n" + "cassandra' meaning to kill the evil enchantress, but Cassandra\n" + "walked in and I accidentally killed her.\" It is also to be\n" + "used to keep people from using offensive names.\n" + ); + } diff -c -r --new-file ds2.0r19/lib/secure/cmds/admins/decre.c ds2.0r20b/lib/secure/cmds/admins/decre.c *** ds2.0r19/lib/secure/cmds/admins/decre.c Sat Mar 11 11:16:43 2006 --- ds2.0r20b/lib/secure/cmds/admins/decre.c Thu Apr 13 21:04:27 2006 *************** *** 6,11 **** --- 6,12 ---- #include #include + #include inherit LIB_DAEMON; *************** *** 23,35 **** --- 24,47 ---- possessive_noun(mud_name()) + " reality."; if( !strsrch(file = save_file(nom), DIR_PLAYERS) ) return "You cannot make "+capitalize(args)+" a player."; + + if(!ob = find_player(nom)){ + PLAYERS_D->RemovePendingEncre(lower_case(nom)); + PLAYERS_D->AddPendingDecre(lower_case(nom)); + write(capitalize(nom)+" will be demoted on their next login."); + return 1; + } + if( file_size(DIR_PLAYERS+"/"+nom[0..0]) != -2) mkdir(DIR_PLAYERS+"/"+nom[0..0]); if(rename(file+__SAVE_EXTENSION__, DIR_PLAYERS+"/"+nom[0..0]+"/"+nom+__SAVE_EXTENSION__)) return "You failed due to lack of write access to "+DIR_PLAYERS+"."; + PLAYERS_D->eventDecre(lower_case(nom)); + if( ob = find_player(nom) ) { PlayerName = nom; inv = deep_inventory(ob); + ob->eventMove(ROOM_FURNACE); if(sizeof(inv)) inv->eventMove(ROOM_FURNACE); catch(player_ob = (object)master()->player_object(nom)); PlayerName = 0; *************** *** 51,56 **** --- 63,69 ---- this_player()); if( file_size(file+__SAVE_EXTENSION__) > -1 ) rm(file+__SAVE_EXTENSION__); } + player_ob->eventMove(ROOM_START); return 1; } diff -c -r --new-file ds2.0r19/lib/secure/cmds/admins/domainadmin.c ds2.0r20b/lib/secure/cmds/admins/domainadmin.c *** ds2.0r19/lib/secure/cmds/admins/domainadmin.c Wed Dec 31 19:00:00 1969 --- ds2.0r20b/lib/secure/cmds/admins/domainadmin.c Sun Apr 9 23:54:48 2006 *************** *** 0 **** --- 1,127 ---- + #include + #include + + inherit LIB_DAEMON; + + mixed cmd(string args) { + string rep, flag, domain, person; + string write_perms = read_file("/secure/cfg/write.cfg"); + string *tmp_array = explode(write_perms, "\n"); + string *admin_array = ({}); + mapping DomainsMap = ([]); + + + if(!archp(this_player()) || this_player()->GetForced()){ + return "No."; + } + + //tc("tp_array: "+identify(tmp_array),"white"); + + if(!args || args == ""){ + write(this_object()->GetHelp()); + return 1; + } + + if(sscanf(args,"%s %s %s", flag, domain, person) != 3){ + write(this_object()->GetHelp()); + return 1; + } + + person = lower_case(person); + + if(!user_exists(person)){ + write("Invalid person."); + return 1; + } + + if(!directory_exists("/domains/"+domain)){ + write("Invalid domain."); + return 1; + } + + write_perms = replace_string(write_perms, "\n",";\n"); + + foreach(string line in tmp_array){ + string where, admins; + if(sscanf(line,"(/domains/%s/) %s", where, admins)){ + DomainsMap[where] = admins; + if(sizeof(DomainsMap[domain])) admin_array = explode(DomainsMap[domain],":"); + } + } + + if(flag == "-a"){ + + if(member_array(person, admin_array) != -1){ + write("That person already administers that domain."); + return 1; + } + + else admin_array += ({ person }); + + rep = "(/domains/"+domain+"/) "+implode(admin_array, ":"); + + //tc("rep: "+rep,"blue"); + + if(grepp(write_perms, "(/domains/"+domain+"/)")){ + write_perms = replace_matching_line(write_perms, "/domains/"+domain, rep); + write_perms = replace_string(write_perms, ";\n","\n"); + //tc("write_perms: "+write_perms, "yellow"); + } + else{ + write_perms = replace_string(write_perms, ";\n","\n"); + write_perms = newline_trim(write_perms); + write_perms += "\n(/domains/"+domain+"/) "+person+"\n"; + //tc("write_perms: "+write_perms); + } + } + + else if(flag == "-d"){ + if(member_array(person, admin_array) == -1){ + write("That person does not administer that domain."); + return 1; + } + + else admin_array -= ({ person }); + //tc("admin_array: "+identify(admin_array),"cyan"); + //tc("domain: "+domain,"cyan"); + //tc("erite_terms: "+write_perms,"cyan"); + + if(!sizeof(admin_array)){ + write_perms = remove_matching_line(write_perms, "(/domains/"+domain+"/)",1); + write_perms = replace_string(write_perms, ";\n","\n"); + //tc("write_perms: "+write_perms); + } + else { + rep = "(/domains/"+domain+"/) "+implode(admin_array, ":"); + //tc("rep: "+rep,"blue"); + write_perms = replace_matching_line(write_perms, "/domains/"+domain, rep); + write_perms = replace_string(write_perms, ";\n","\n"); + //tc("write_perms: "+write_perms); + } + } + + else { + write("Invalid flag."); + return 1; + } + + //tc("write_perms: "+write_perms,"green"); + write_file("/secure/cfg/write.cfg", write_perms, 1); + update("/secure/daemon/master"); + return 1; + } + + string GetHelp(string args) { + return ("Syntax: domainadmin [-a | -d] \n\n" + "This command manages the write permissions to a specified " + "domain. For example, to give a creator named Snuffy write " + "privileges to /domains/SnuffLand, you would type: " + "\ndomainadmin -a SnuffLand snuffy\n" + "To revoke those privileges:\n" + "\domainadmin -d SnuffLand snuffy\n" + "This permits the creator to use QCS within the domain's " + "directories. " + "Write privileges are listed in /secure/cfg/write.cfg" + "\n\n" + "See also: admintool"); + } diff -c -r --new-file ds2.0r19/lib/secure/cmds/admins/encre.c ds2.0r20b/lib/secure/cmds/admins/encre.c *** ds2.0r19/lib/secure/cmds/admins/encre.c Wed Feb 22 15:33:33 2006 --- ds2.0r20b/lib/secure/cmds/admins/encre.c Thu Apr 13 21:04:27 2006 *************** *** 4,9 **** --- 4,10 ---- */ #include + #include #include inherit LIB_DAEMON; *************** *** 21,29 **** --- 22,43 ---- possessive_noun(mud_name()) + " reality."; if( !strsrch(file = save_file(nom), DIR_CRES) ) return "You cannot make "+capitalize(args)+" a creator."; + + if(!ob=find_player(nom)){ + if(member_array(nom, PLAYERS_D->GetPendingEncres()) != -1){ + write("That person is already pending creatorship."); + return 1; + } + PLAYERS_D->RemovePendingDecre(lower_case(nom)); + PLAYERS_D->AddPendingEncre(lower_case(nom)); + write(capitalize(nom)+" will be a creator next time they log in."); + return 1; + } + if( file_size(DIR_CRES+"/"+nom[0..0]) != -2) mkdir(DIR_CRES+"/"+nom[0..0]); if(rename(file+__SAVE_EXTENSION__, DIR_CRES+"/"+nom[0..0]+"/"+nom+__SAVE_EXTENSION__)) return "You failed due to lack of write access to "+DIR_CRES+"."; + PLAYERS_D->eventEncre(lower_case(nom)); if( ob = find_player(nom) ) { ob->SetProperty("brand_spanking_new",0); PlayerName = nom; *************** *** 62,67 **** --- 76,82 ---- book = new("/domains/default/obj/manual"); if(book && !present("manual",cre_ob)) book->eventMove(cre_ob); else if(book) book->eventMove(ROOM_FURNACE); + cre_ob->save_player((string)cre_ob->GetKeyName()); //message("system", "You will now be logged off.", cre_ob); //message("system", "Please log back in to use your new powers.", cre_ob); //cre_ob->eventForce("quit"); diff -c -r --new-file ds2.0r19/lib/secure/cmds/admins/switchrouter.c ds2.0r20b/lib/secure/cmds/admins/switchrouter.c *** ds2.0r19/lib/secure/cmds/admins/switchrouter.c Wed Dec 31 19:00:00 1969 --- ds2.0r20b/lib/secure/cmds/admins/switchrouter.c Sun Apr 9 23:54:57 2006 *************** *** 0 **** --- 1,70 ---- + #include + #include + + inherit LIB_DAEMON; + + string file; + + mixed cmd(string args) { + string ip, name; + int port, octet1, octet2, octet3, octet4; + + if(!archp(this_player())) return "No."; + + find_object(INTERMUD_D)->eventDestruct(); + rm("/save/intermud.o"); + + if(!args || args == ""){ + write("No argument provided. Reloading intermud daemon."); + if( load_object(INTERMUD_D) ) write("Intermud daemon reloaded."); + else write("Failed to reload intermud daemon."); + return 1; + } + + if(sscanf(args,"%s %s %d", name, ip, port) != 3 || port > 65534 || + sscanf(ip,"%d.%d.%d.%d", octet1, octet2, octet3, octet4) != 4){ + write("Invalid router reference. \nTry: switchrouter "); + write("For example: switchrouter yatmim 149.152.218.102 23"); + if( load_object(INTERMUD_D) ) write("Intermud daemon reloaded."); + else write("Failed to reload intermud daemon."); + return 1; + } + + file = read_file(INTERMUD_D+".c"); + //write_file("/tmp/1.txt",file,1); + + file = replace_matching_line(file, "//Nameservers", ""); + + //write_file("/tmp/2.txt",file,1); + if(first(name,1) != "*") name = "*"+name; + + file = replace_matching_line(file, "Nameservers = ({", + " Nameservers = ({ ({ \""+name+"\", \""+ip+" "+port+"\" }) });", 1); + + //write_file("/tmp/3.txt",file,1); + + unguarded( (: write_file(INTERMUD_D+".c",file,1) :) ); + + if( load_object(INTERMUD_D) ) write("Intermud daemon reloaded."); + else write("Failed to reload intermud daemon."); + + write("Done."); + return 1; + } + + + string GetHelp(string args) { + return ("Syntax: switchrouter \n\n" + "Stops the intermud daemon, changes the default intermud " + "router to the ip and port you specify, wipes the previous " + "router data, and reloads INTERMUD_D. Without arguments, " + "this command will clear your intermud cache and reload " + "the daemon. Known routers are:\n" + "*gjs 198.144.203.194 9000 (The \"official\" intermud.org router)\n" + "*yatmim 149.152.218.102 23 (The \"official\" Dead Souls router)\n" + "The official current Dead Souls router's IP will always be " + "available at:\n" + "http://dead-souls.net/router.html" + "\n\n" + "See also: router, mudlist"); + } diff -c -r --new-file ds2.0r19/lib/secure/cmds/admins/unmonitor.c ds2.0r20b/lib/secure/cmds/admins/unmonitor.c *** ds2.0r19/lib/secure/cmds/admins/unmonitor.c Wed Dec 31 19:00:00 1969 --- ds2.0r20b/lib/secure/cmds/admins/unmonitor.c Wed Apr 12 23:56:45 2006 *************** *** 0 **** --- 1,34 ---- + #include + #include + + inherit LIB_DAEMON; + + int cmd(string str) { + object ob; + + if(!archp(this_player())) { + write("Only an arch may halt a monitoring process."); + return 0; + } + if( !str || str == "" ) { + write("Unmonitor whom?\n"); + } + else if(!user_exists(str)) + write(str+": no such player.\n"); + else{ + SNOOP_D->RemoveMonitor(this_player()->GetKeyName(), str); + write("The snoop daemon has received your request."); + } + return 1; + } + + int help() + { + write( @EndText + Syntax: unmonitor + Effect: Stops the logging of a user's input and output. + See also: monitor, snoop, unsnoop + EndText + ); + return 1; + } diff -c -r --new-file ds2.0r19/lib/secure/cmds/creators/banish.c ds2.0r20b/lib/secure/cmds/creators/banish.c *** ds2.0r19/lib/secure/cmds/creators/banish.c Mon Nov 7 13:32:16 2005 --- ds2.0r20b/lib/secure/cmds/creators/banish.c Wed Dec 31 19:00:00 1969 *************** *** 1,34 **** - // /bin/dev/_banish.c - // from the Dead Souls Mudlib - // prevents a name being used by a new player - // created by Descartes of Borg ??? - - #include - #include - - inherit LIB_DAEMON; - - int cmd(string str) { - if(!user_exists(str = lower_case(str))) { - write(capitalize(str)+" is now banished.\n"); - //seteuid(UID_BANISH); - catch(call_other(BANISH_D, "banish_name", str)); - //seteuid(getuid()); - } - else { - write("A player by that name already exists.\n"); - this_player()->eventPrint((string)FINGER_D->GetFinger(str)); - } - return 1; - } - - void help() { - write("Syntax: \n\n" - "Protects a name from being used by a new player.\n" - "For example, if you have created a monster named Cassandra, in order\n" - "to avoid problems with player complaining \"I typed 'kill\n" - "cassandra' meaning to kill the evil enchantress, but Cassandra\n" - "walked in and I accidentally killed her.\" It is also to be\n" - "used to keep people from using offensive names.\n" - ); - } --- 0 ---- diff -c -r --new-file ds2.0r19/lib/secure/cmds/creators/eval.c ds2.0r20b/lib/secure/cmds/creators/eval.c *** ds2.0r19/lib/secure/cmds/creators/eval.c Fri Mar 24 14:38:48 2006 --- ds2.0r20b/lib/secure/cmds/creators/eval.c Wed Apr 12 23:49:46 2006 *************** *** 28,33 **** --- 28,34 ---- file = ""+ "#include \n"+ + "#include \n"+ "#include \n"+ "#include \n"+ "#include \n"+ diff -c -r --new-file ds2.0r19/lib/secure/cmds/creators/heal.c ds2.0r20b/lib/secure/cmds/creators/heal.c *** ds2.0r19/lib/secure/cmds/creators/heal.c Wed Dec 7 14:24:50 2005 --- ds2.0r20b/lib/secure/cmds/creators/heal.c Sun Apr 9 23:51:07 2006 *************** *** 18,23 **** --- 18,24 ---- string cmd = args; object who; mapping stumps; + string *limb_arr = ({}); int i, mhp, msp, mmp, self; if( !cmd || cmd == "" ) { *************** *** 50,55 **** --- 51,60 ---- who->AddMagicPoints(mmp); if(who->GetPoison() > 0) who->AddPoison(0 - who->GetPoison()); eventRegenerate(who); + limb_arr = who->GetLimbs(); + foreach(string limb in limb_arr) { + who->HealLimb(limb); + } return 1; } diff -c -r --new-file ds2.0r19/lib/secure/cmds/creators/monitor.c ds2.0r20b/lib/secure/cmds/creators/monitor.c *** ds2.0r19/lib/secure/cmds/creators/monitor.c Wed Dec 31 19:00:00 1969 --- ds2.0r20b/lib/secure/cmds/creators/monitor.c Wed Apr 12 23:56:45 2006 *************** *** 0 **** --- 1,31 ---- + #include + #include + + inherit LIB_DAEMON; + + int cmd(string str) { + object ob; + + if( !str || str == "" ) { + write("Monitor whom?\n"); + } + else if(!user_exists(str)) + write(str+": no such player.\n"); + else{ + SNOOP_D->AddMonitor(this_player()->GetKeyName(), str); + write("The snoop daemon has received your request."); + } + return 1; + } + + int help() + { + write( @EndText + Syntax: monitor + Effect: Logs to a file everything sees or types. + To stop monitoring, an admin must type "unmonitor " + See also: unmonitor, snoop, unsnoop + EndText + ); + return 1; + } diff -c -r --new-file ds2.0r19/lib/secure/cmds/creators/snoop.c ds2.0r20b/lib/secure/cmds/creators/snoop.c *** ds2.0r19/lib/secure/cmds/creators/snoop.c Mon Nov 7 13:32:17 2005 --- ds2.0r20b/lib/secure/cmds/creators/snoop.c Wed Apr 12 23:49:53 2006 *************** *** 5,10 **** --- 5,11 ---- */ #include + #include inherit LIB_DAEMON; *************** *** 12,26 **** object ob; if( !str || str == "" ) { ! if(snoop(this_player())) ! write("Ok.\n"); ! else write("Couldn't stop snoop\n"); } else if(!(ob=find_player(str=lower_case(str)))) write(str+": no such player.\n"); else ! write(snoop(this_player(), ob)?"Now snooping.\n":str+": snoop failed.\n"); ! return 1; } --- 13,29 ---- object ob; if( !str || str == "" ) { ! write("Snoop whom?\n"); ! } ! else if(str == this_player()->GetKeyName()){ ! write("That would be very foolish."); ! return 1; } else if(!(ob=find_player(str=lower_case(str)))) write(str+": no such player.\n"); else ! SNOOP_D->AddWatcher(this_player()->GetKeyName(), str); ! write("The snoop daemon has received your request."); return 1; } *************** *** 28,36 **** { write( @EndText Syntax: snoop ! Effect: Echos to your screen everything sees or types. ! To stop snooping, type just "snoop" ! See also: snoopable EndText ); return 1; --- 31,39 ---- { write( @EndText Syntax: snoop ! Effect: Echoes to your screen everything sees or types. ! To stop snooping, type just "unsnoop " ! See also: unsnoop, monitor, unmonitor EndText ); return 1; diff -c -r --new-file ds2.0r19/lib/secure/cmds/creators/unsnoop.c ds2.0r20b/lib/secure/cmds/creators/unsnoop.c *** ds2.0r19/lib/secure/cmds/creators/unsnoop.c Wed Dec 31 19:00:00 1969 --- ds2.0r20b/lib/secure/cmds/creators/unsnoop.c Wed Apr 12 23:56:45 2006 *************** *** 0 **** --- 1,29 ---- + #include + #include + + inherit LIB_DAEMON; + + int cmd(string str) { + object ob; + + if( !str || str == "" ) { + write("Unsnoop whom?\n"); + } + else if(!(ob=find_player(str=lower_case(str)))) + write(str+": no such player.\n"); + else + SNOOP_D->RemoveWatcher(this_player()->GetKeyName(), str); + write("The snoop daemon has received your request."); + return 1; + } + + int help() + { + write( @EndText + Syntax: unsnoop + Effect: Stops snooping the specified user. + See also: snoop, monitor, unmonitor + EndText + ); + return 1; + } diff -c -r --new-file ds2.0r19/lib/secure/cmds/players/suicide.c ds2.0r20b/lib/secure/cmds/players/suicide.c *** ds2.0r19/lib/secure/cmds/players/suicide.c Sun Dec 18 01:59:08 2005 --- ds2.0r20b/lib/secure/cmds/players/suicide.c Fri Apr 14 19:45:32 2006 *************** *** 83,88 **** --- 83,90 ---- static private void EndSuicide(string who) { string tmp, file, newfile; object *ob; + + if(!directory_exists(DIR_TMP + "/suicide/")) mkdir (DIR_TMP + "/suicide/"); file = DIR_TMP + "/" + who; newfile = DIR_TMP + "/suicide/" + who; diff -c -r --new-file ds2.0r19/lib/secure/cmds/router.c ds2.0r20b/lib/secure/cmds/router.c *** ds2.0r19/lib/secure/cmds/router.c Wed Apr 5 19:44:19 2006 --- ds2.0r20b/lib/secure/cmds/router.c Wed Dec 31 19:00:00 1969 *************** *** 1,44 **** - #include - #include - - inherit LIB_DAEMON; - - mixed cmd(string args) { - string subcmd, arg1, arg2; - - if(find_object(ROUTER_D)) - write("I3 router daemon is loaded."); - else { - write("I3 router daemon is not loaded."); - return 1; - } - - if(!args || args == ""){ - return 1; - } - - if(args == "show"){ - write("Router config: \n"+ROUTER_D->get_info()); - return 1; - } - - if(sscanf(args,"%s %s",subcmd, arg1) != 2){ - write("Invalid router subcommand."); - return 1; - } - - if(arg1 == "mudlist"){ - mapping mudlist = ROUTER_D->query_mudinfo(); - write("Mudlist: \n"+identify(mudlist)); - } - - - write("Router command completed."); - return 1; - } - - string GetHelp(string args) { - return ("Syntax: \n\n" - "\n\n" - ""); - } --- 0 ---- diff -c -r --new-file ds2.0r19/lib/secure/daemon/chat.c ds2.0r20b/lib/secure/daemon/chat.c *** ds2.0r19/lib/secure/daemon/chat.c Wed Apr 5 19:33:19 2006 --- ds2.0r20b/lib/secure/daemon/chat.c Wed Apr 12 23:50:02 2006 *************** *** 140,159 **** object ob = 0; int emote; ! //tc("verb: "+verb); ! //tc("str: "+str); ! ! if(first(str,1) == ":"){ if(!grepp(verb,"emote")) verb += "emote"; str = trim(replace_string(str,":","",1)); } if(grepp(verb, "emote")) varb = replace_string(verb,"emote",""); ! else if(grepp(verb, ":")) varb = replace_string(verb,":",""); else varb = verb; - //tc("varb: "+varb); - if( verb == "hist" ) { if( !Channels[str] ) return 0; if( member_array(this_player(), Channels[str]) == -1 ) return 0; --- 140,154 ---- object ob = 0; int emote; ! if(first(str,1) == ":" && sizeof(str) > 3){ if(!grepp(verb,"emote")) verb += "emote"; str = trim(replace_string(str,":","",1)); } if(grepp(verb, "emote")) varb = replace_string(verb,"emote",""); ! else if(last(verb, 1) == ":") varb = replace_string(verb,":",""); else varb = verb; if( verb == "hist" ) { if( !Channels[str] ) return 0; if( member_array(this_player(), Channels[str]) == -1 ) return 0; diff -c -r --new-file ds2.0r19/lib/secure/daemon/finger.c ds2.0r20b/lib/secure/daemon/finger.c *** ds2.0r19/lib/secure/daemon/finger.c Mon Jan 16 23:04:22 2006 --- ds2.0r20b/lib/secure/daemon/finger.c Wed Apr 12 23:50:02 2006 *************** *** 17,23 **** private int LoginTime, Level, BirthTime, CreatorBirth, WhereBlock; private string CurrentUser, Short, CapName, RealName, Email; private string Town, Race, Gender, HostSite; ! private string Class, Guild, Long; private string Rank, WebPage; private string array Titles, Religion; private class marriage array Marriages; --- 17,23 ---- private int LoginTime, Level, BirthTime, CreatorBirth, WhereBlock; private string CurrentUser, Short, CapName, RealName, Email; private string Town, Race, Gender, HostSite; ! private string Class, Clan, Long; private string Rank, WebPage; private string array Titles, Religion; private class marriage array Marriages; *************** *** 100,106 **** int yr; ret += CapName+" the "+Gender+" "+Race+" "+(Class || "drifter"); ! if( Guild ) ret += " of the " + pluralize(Guild); if( creatorp(this_player()) && Level ) ret += " ("+Level+")"; ret += " is a " + Rank+" of " + Town + ".%^BR%^\n"; BirthTime = BirthTime - (18 * YEAR); --- 100,106 ---- int yr; ret += CapName+" the "+Gender+" "+Race+" "+(Class || "drifter"); ! if( Clan ) ret += " of the " + pluralize(Clan); if( creatorp(this_player()) && Level ) ret += " ("+Level+")"; ret += " is a " + Rank+" of " + Town + ".%^BR%^\n"; BirthTime = BirthTime - (18 * YEAR); diff -c -r --new-file ds2.0r19/lib/secure/daemon/i3router/broadcast_chanlist.h ds2.0r20b/lib/secure/daemon/i3router/broadcast_chanlist.h *** ds2.0r19/lib/secure/daemon/i3router/broadcast_chanlist.h Wed Apr 5 18:44:57 2006 --- ds2.0r20b/lib/secure/daemon/i3router/broadcast_chanlist.h Sun Apr 9 23:51:25 2006 *************** *** 5,13 **** string name; // channel name in first loop, then mud name in later loop #ifdef SEND_WHOLE_CHANLIST mapping out=([]); // only used if whole chanlist is sent ! #endif ! Debug("broadcasting chanlist to let them know about "+channame); ! #ifdef SEND_WHOLE_CHANLIST foreach(name in keys(channel_updates)){ if(!channels[channame]) out[name]=0; --- 5,11 ---- string name; // channel name in first loop, then mud name in later loop #ifdef SEND_WHOLE_CHANLIST mapping out=([]); // only used if whole chanlist is sent ! trr("broadcasting chanlist to let them know about "+channame); foreach(name in keys(channel_updates)){ if(!channels[channame]) out[name]=0; *************** *** 21,33 **** out = ([ channame:({ channels[channame][1], channels[channame][0] }) ]); #endif foreach(name in keys(connected_muds)){ ! Debug("inside loop with "+name); if(member_array("channel", keys(mudinfo[name]["services"]))!=-1){ // only tell muds that have the "channel" service... write_data(connected_muds[name], ({ "chanlist-reply",5,router_name,0,name,0,channel_update_counter,out })); } ! Debug("done with: "+name); } } --- 19,31 ---- out = ([ channame:({ channels[channame][1], channels[channame][0] }) ]); #endif foreach(name in keys(connected_muds)){ ! trr("inside loop with "+name); if(member_array("channel", keys(mudinfo[name]["services"]))!=-1){ // only tell muds that have the "channel" service... write_data(connected_muds[name], ({ "chanlist-reply",5,router_name,0,name,0,channel_update_counter,out })); } ! trr("done with: "+name); } } diff -c -r --new-file ds2.0r19/lib/secure/daemon/i3router/broadcast_mudlist.h ds2.0r20b/lib/secure/daemon/i3router/broadcast_mudlist.h *** ds2.0r19/lib/secure/daemon/i3router/broadcast_mudlist.h Wed Apr 5 18:44:57 2006 --- ds2.0r20b/lib/secure/daemon/i3router/broadcast_mudlist.h Sun Apr 9 23:51:25 2006 *************** *** 1,11 **** // This file written completely by Tim Johnson (Tim@TimMUD) // broadcast the mudlist when a mud just now got changed... ! static void broadcast_mudlist(string mudname){ string targ_mudname; mixed *packet1; // for muds that use protocol 1 or 2 mixed *packet3; // for muds that use protocol 3 ! Debug("broadcasting mudlist to let them know about "+mudname); packet1 = ({ "mudlist", 5, router_name, 0, "dummy", 0, mudinfo_update_counter,([ mudname:({ connected_muds[mudname] ? -1 : 0, --- 1,11 ---- // This file written completely by Tim Johnson (Tim@TimMUD) // broadcast the mudlist when a mud just now got changed... ! void broadcast_mudlist(string mudname){ string targ_mudname; mixed *packet1; // for muds that use protocol 1 or 2 mixed *packet3; // for muds that use protocol 3 ! trr("broadcasting mudlist to let them know about "+mudname,"red"); packet1 = ({ "mudlist", 5, router_name, 0, "dummy", 0, mudinfo_update_counter,([ mudname:({ connected_muds[mudname] ? -1 : 0, diff -c -r --new-file ds2.0r19/lib/secure/daemon/i3router/core_stuff.h ds2.0r20b/lib/secure/daemon/i3router/core_stuff.h *** ds2.0r19/lib/secure/daemon/i3router/core_stuff.h Wed Apr 5 18:44:57 2006 --- ds2.0r20b/lib/secure/daemon/i3router/core_stuff.h Sun Apr 9 23:51:25 2006 *************** *** 13,49 **** if(!channels) channels = ([]); if(!channel_updates) channel_updates = ([]); if(!channel_update_counter) channel_update_counter = 1; ! if(!router_name) router_name = "*yatmim"; ! if(!router_list) router_list = ({ ({"*yatmim", "149.152.218.102 23"}) }); log_file("server", "Created when uptime = " + uptime() + "\n"); ! Debug("server got created",DEB_OTHER); call_out("setup", 5); } static void setup(){ ! Debug("setup got called"); if ((router_socket = socket_create(MUD, "read_callback", "close_callback")) < 0){ log_file("server", "setup: Failed to create socket.\n"); return; } if (socket_bind(router_socket, MYSERVER) < 0) { socket_close(router_socket); log_file("server", "setup: Failed to bind socket to port.\n"); return; } if (socket_listen(router_socket, "listen_callback") < 0) { socket_close(router_socket); log_file("server", "setup: Failed to listen to socket.\n"); } ! Debug("setup ended"); } void remove(){ string mudname; log_file("server", "Being removed by: "+identify(previous_object())+"\n"); log_file("server", "sockets:"+identify(sockets)+"\n"); ! log_file("server", "Starting to destruct at uptime = " + uptime() + "\n"); mudinfo_update_counter++; // just increment once... all the connected muds // getting simultaneously disconnected is okay to count as one change :) foreach(mudname in keys(connected_muds)){ --- 13,62 ---- if(!channels) channels = ([]); if(!channel_updates) channel_updates = ([]); if(!channel_update_counter) channel_update_counter = 1; ! if(!router_name) router_name = "*test"; ! //if(!router_list) router_list = ({ ({"*yatmim", "149.152.218.102 23"}) }); ! if(!router_list) router_list = ({ ({"*test", "192.168.0.201 9000"}) }); log_file("server", "Created when uptime = " + uptime() + "\n"); ! trr("server got created"); call_out("setup", 5); + set_heart_beat(10); } + void heart_beat(){ + trr("BING!","white"); + this_object()->clear_discs(); + } + + static void setup(){ ! trr("setup got called"); if ((router_socket = socket_create(MUD, "read_callback", "close_callback")) < 0){ log_file("server", "setup: Failed to create socket.\n"); + trr("setup: Failed to create socket.\n"); return; } if (socket_bind(router_socket, MYSERVER) < 0) { socket_close(router_socket); log_file("server", "setup: Failed to bind socket to port.\n"); + trr("setup: Failed to bind socket to port.\n"); return; } if (socket_listen(router_socket, "listen_callback") < 0) { socket_close(router_socket); log_file("server", "setup: Failed to listen to socket.\n"); + trr("setup: Failed to listen to socket.\n"); } ! trr("setup ended"); } void remove(){ string mudname; log_file("server", "Being removed by: "+identify(previous_object())+"\n"); + trr("Being removed by: "+identify(previous_object())+"\n"); log_file("server", "sockets:"+identify(sockets)+"\n"); ! trr("sockets:"+identify(sockets)+"\n"); log_file("server", "Starting to destruct at uptime = " + uptime() + "\n"); + trr("Starting to destruct at uptime = " + uptime() + "\n"); mudinfo_update_counter++; // just increment once... all the connected muds // getting simultaneously disconnected is okay to count as one change :) foreach(mudname in keys(connected_muds)){ *************** *** 52,57 **** --- 65,71 ---- map_delete(connected_muds,mudname); // unneeded: connected_muds isn't saved anyway } log_file("server", "Successfully destructed when uptime = " + uptime() + "\n"); + trr("Successfully destructed when uptime = " + uptime() + "\n"); destruct(this_object()); } int query_prevent_shadow(object ob){ return 1; } diff -c -r --new-file ds2.0r19/lib/secure/daemon/i3router/debug.h ds2.0r20b/lib/secure/daemon/i3router/debug.h *** ds2.0r19/lib/secure/daemon/i3router/debug.h Wed Apr 5 18:44:57 2006 --- ds2.0r20b/lib/secure/daemon/i3router/debug.h Sun Apr 9 23:51:25 2006 *************** *** 4,23 **** if(find_player(DEBUGGER_GUY)) switch(level){ case DEB_IN: ! message("Debug", "%^BOLD%^%^WHITE%^SERVER INCOMING: %^MAGENTA%^"+str+"%^RESET%^\n", find_player(DEBUGGER_GUY)); break; case DEB_OUT: ! message("Debug", "%^BOLD%^%^WHITE%^SERVER OUTGOING: %^CYAN%^"+str+"%^RESET%^\n", find_player(DEBUGGER_GUY)); break; case DEB_INVALID: ! message("Debug", "%^BOLD%^%^WHITE%^SERVER THINKS THIS IS INVALID: %^RED%^"+str+"%^RESET%^\n", find_player(DEBUGGER_GUY)); break; case DEB_OTHER: default: ! message("Debug", "%^BOLD%^%^WHITE%^SERVER INFO: %^GREEN%^"+str+"%^RESET%^\n", find_player(DEBUGGER_GUY)); break; } --- 4,23 ---- if(find_player(DEBUGGER_GUY)) switch(level){ case DEB_IN: ! message("trr", "%^BOLD%^%^WHITE%^SERVER INCOMING: %^MAGENTA%^"+str+"%^RESET%^\n", find_player(DEBUGGER_GUY)); break; case DEB_OUT: ! message("trr", "%^BOLD%^%^WHITE%^SERVER OUTGOING: %^CYAN%^"+str+"%^RESET%^\n", find_player(DEBUGGER_GUY)); break; case DEB_INVALID: ! message("trr", "%^BOLD%^%^WHITE%^SERVER THINKS THIS IS INVALID: %^RED%^"+str+"%^RESET%^\n", find_player(DEBUGGER_GUY)); break; case DEB_OTHER: default: ! message("trr", "%^BOLD%^%^WHITE%^SERVER INFO: %^GREEN%^"+str+"%^RESET%^\n", find_player(DEBUGGER_GUY)); break; } diff -c -r --new-file ds2.0r19/lib/secure/daemon/i3router/process_channel.h ds2.0r20b/lib/secure/daemon/i3router/process_channel.h *** ds2.0r19/lib/secure/daemon/i3router/process_channel.h Wed Apr 5 18:44:57 2006 --- ds2.0r20b/lib/secure/daemon/i3router/process_channel.h Sun Apr 9 23:51:25 2006 *************** *** 2,13 **** static void process_channel(int fd, mixed *info){ string mudname; ! Debug("extra stuff is ["+info[0][8..]+"]"); switch(info[0][8..]){ // what is after the "channel-" case "m": // message case "e": // emote case "t": // targetted emote ! Debug("they want to do a message..."); // (drop-through from m/e is intentional) // Probably should check if the target is 0@0 like it should be, // and give a warning if it's not... I don't carethough, I'll just --- 2,13 ---- static void process_channel(int fd, mixed *info){ string mudname; ! trr("extra stuff is ["+info[0][8..]+"]"); switch(info[0][8..]){ // what is after the "channel-" case "m": // message case "e": // emote case "t": // targetted emote ! trr("they want to do a message..."); // (drop-through from m/e is intentional) // Probably should check if the target is 0@0 like it should be, // and give a warning if it's not... I don't carethough, I'll just *************** *** 81,87 **** // IS from chan owner, just broadcast it... // drop through and broadcast like the other types do... } ! Debug("CHAN: I think it's a good message at this point..."); // at this point, they're wanting to do a message on a // selective banned/allowed channel, or else are the owner // of a filtered channel and they have not been --- 81,87 ---- // IS from chan owner, just broadcast it... // drop through and broadcast like the other types do... } ! trr("CHAN: I think it's a good message at this point..."); // at this point, they're wanting to do a message on a // selective banned/allowed channel, or else are the owner // of a filtered channel and they have not been *************** *** 107,113 **** channel_update_counter++; channels[info[6]]=({ info[7], info[2], ({}) }); channel_updates[info[6]] = channel_update_counter; ! Debug(info[3]+"@"+info[2]+" created the channel: "+info[6]); // broadcast an update saying that this channel is added or changed now // chanlist-reply packet to everybody (who has a channel service?) broadcast_chanlist(info[6]); --- 107,113 ---- channel_update_counter++; channels[info[6]]=({ info[7], info[2], ({}) }); channel_updates[info[6]] = channel_update_counter; ! trr(info[3]+"@"+info[2]+" created the channel: "+info[6]); // broadcast an update saying that this channel is added or changed now // chanlist-reply packet to everybody (who has a channel service?) broadcast_chanlist(info[6]); *************** *** 139,145 **** channel_update_counter++; map_delete(channels,info[6]); channel_updates[info[6]] = channel_update_counter; ! Debug(info[3]+"@"+info[2]+" deleted the channel: "+info[6]); // broadcast an update saying that this channel is gone now return; case "admin": --- 139,145 ---- channel_update_counter++; map_delete(channels,info[6]); channel_updates[info[6]] = channel_update_counter; ! trr(info[3]+"@"+info[2]+" deleted the channel: "+info[6]); // broadcast an update saying that this channel is gone now return; case "admin": *************** *** 176,182 **** if(member_array(info[2],listening[info[6]])==-1) return; // already NOT listening, ignore them } ! Debug("listening change on chan:"+info[6]+", mud="+info[2]+", on_or_off="+info[7]); // only CHANGES should get to this point switch(channels[info[6]][0]){ case 0: // selectively banned --- 176,182 ---- if(member_array(info[2],listening[info[6]])==-1) return; // already NOT listening, ignore them } ! trr("listening change on chan:"+info[6]+", mud="+info[2]+", on_or_off="+info[7]); // only CHANGES should get to this point switch(channels[info[6]][0]){ case 0: // selectively banned *************** *** 225,232 **** default: // trying to do "channel-blah" send_error(info[2],info[3],"unk-type","I don't know what "+info[0]+ " means.",info); ! Debug("Don't know what the ["+info[0]+"] packet means.", DEB_INVALID); return; } ! Debug("can't get here?"); } --- 225,232 ---- default: // trying to do "channel-blah" send_error(info[2],info[3],"unk-type","I don't know what "+info[0]+ " means.",info); ! trr("Don't know what the ["+info[0]+"] packet means.", DEB_INVALID); return; } ! trr("can't get here?"); } diff -c -r --new-file ds2.0r19/lib/secure/daemon/i3router/process_startup_req.h ds2.0r20b/lib/secure/daemon/i3router/process_startup_req.h *** ds2.0r19/lib/secure/daemon/i3router/process_startup_req.h Wed Apr 5 18:44:57 2006 --- ds2.0r20b/lib/secure/daemon/i3router/process_startup_req.h Sun Apr 9 23:51:25 2006 *************** *** 8,18 **** string site_ip, junk; // router name is info[4], I'll just pretend I'm every router though, ha-ha! // also, should verify that all the fields are the right type ! tn("info: "+identify(info)); ! tn("process_startup_req: protocol="+protocol+", mud="+info[2],"green"); if(sizeof(info)<18){ // smallest protocol is protocol 1/2 which have size 18 ! tn("THIS SHOULDNT BE HERE"); write_data(fd,({ "error", 5, --- 8,20 ---- string site_ip, junk; // router name is info[4], I'll just pretend I'm every router though, ha-ha! // also, should verify that all the fields are the right type ! ! trr("info: "+identify(info)); ! trr("process_startup_req: protocol="+protocol+", mud="+info[2]); ! if(sizeof(info)<18){ // smallest protocol is protocol 1/2 which have size 18 ! trr("THIS SHOULDNT BE HERE"); write_data(fd,({ "error", 5, *************** *** 31,45 **** //site_ip = path_prefix(socket_status(fd)[4],"."); //if(!site_ip || site_ip == "" || site_ip == "*"){ //if(true()){ ! tn("bad ip "+site_ip+" from "+info[2]); //socket_close(fd); //return; //} //junk = "foo"; ! tn("fd is:" +fd); site_ip=socket_address(fd); ! tn("site_ip: "+site_ip,"red"); newinfo = ([ "ip":site_ip, "connect_time":time(), --- 33,47 ---- //site_ip = path_prefix(socket_status(fd)[4],"."); //if(!site_ip || site_ip == "" || site_ip == "*"){ //if(true()){ ! trr("bad ip "+site_ip+" from "+info[2]); //socket_close(fd); //return; //} //junk = "foo"; ! trr("fd is:" +fd); site_ip=socket_address(fd); ! trr("site_ip: "+site_ip); newinfo = ([ "ip":site_ip, "connect_time":time(), *************** *** 58,69 **** "protocol":protocol, "restart_delay":-1, ]); ! tn("newinfo: "+identify(newinfo),"yellow"); switch(protocol){ case 1: case 2: if(sizeof(info)!=18){ ! tn("error","red"); write_data(fd,({ "error", 5, --- 60,71 ---- "protocol":protocol, "restart_delay":-1, ]); ! trr("newinfo: "+identify(newinfo)); switch(protocol){ case 1: case 2: if(sizeof(info)!=18){ ! trr("error"); write_data(fd,({ "error", 5, *************** *** 83,89 **** break; case 3: if(sizeof(info)!=20){ ! tn("error","blue"); write_data(fd,({ "error", --- 85,91 ---- break; case 3: if(sizeof(info)!=20){ ! trr("error"); write_data(fd,({ "error", *************** *** 103,109 **** newinfo["other_data"]=info[19]; break; default: ! tn("error","green"); write_data(fd,({ "error", --- 105,111 ---- newinfo["other_data"]=info[19]; break; default: ! trr("error"); write_data(fd,({ "error", *************** *** 150,156 **** } if(connected_muds[info[2]]){ // if MUD is already connected ! tn("mud already connected","cyan"); write_data(fd,({ "error", 5, --- 152,158 ---- } if(connected_muds[info[2]]){ // if MUD is already connected ! trr("mud already connected"); write_data(fd,({ "error", 5, *************** *** 178,184 **** })); } else{ ! tn("wrong password, and from a new IP","yellow"); write_data(fd,({ "error", 5, --- 180,186 ---- })); } else{ ! trr("wrong password, and from a new IP"); write_data(fd,({ "error", 5, *************** *** 199,208 **** // Change this maybe... see if the password is supposed to be in a certain range } // MUD should be okay at this point. ! Debug("about to update the mudinfo..."); mudinfo[info[2]]=newinfo; // update the mudinfo connected_muds[info[2]] = fd; // add this MUD to list of connected muds ! Debug("about to send the startup reply..."); send_startup_reply(info[2]); // reply to MUD mudinfo_update_counter++; mudinfo_updates[info[2]]=mudinfo_update_counter; --- 201,210 ---- // Change this maybe... see if the password is supposed to be in a certain range } // MUD should be okay at this point. ! trr("about to update the mudinfo..."); mudinfo[info[2]]=newinfo; // update the mudinfo connected_muds[info[2]] = fd; // add this MUD to list of connected muds ! trr("about to send the startup reply..."); send_startup_reply(info[2]); // reply to MUD mudinfo_update_counter++; mudinfo_updates[info[2]]=mudinfo_update_counter; diff -c -r --new-file ds2.0r19/lib/secure/daemon/i3router/read_callback.h ds2.0r20b/lib/secure/daemon/i3router/read_callback.h *** ds2.0r19/lib/secure/daemon/i3router/read_callback.h Wed Apr 5 18:44:57 2006 --- ds2.0r20b/lib/secure/daemon/i3router/read_callback.h Sun Apr 9 23:51:25 2006 *************** *** 23,29 **** string mudname; int i; ! tn("Received from fd("+fd+"), fd("+socket_address(fd)+")\n"+identify(info),"red"); // Base info in a packet is of size 6. if(sizeof(info)<6 || !stringp(info[0]) || --- 23,29 ---- string mudname; int i; ! trr("Received from fd("+fd+"), fd("+socket_address(fd)+")\n"+identify(info)); // Base info in a packet is of size 6. if(sizeof(info)<6 || !stringp(info[0]) || *************** *** 55,66 **** "destination unknown", // same as I3 info })); ! Debug("Error [unk-dst], because target is "+info[4]+" and thus invalid."); return; } if(sscanf(info[0],"startup-req-%d",i)==1){ // special condition for startup-req... ! tn("calling process_startup_req, i="+i+", fd="+fd+" which is: "+socket_address(fd),"blue"); //call_other(this_object(),"process_startup_req",i,info,fd); this_object()->process_startup_req(i,info,fd); return; --- 55,66 ---- "destination unknown", // same as I3 info })); ! trr("Error [unk-dst], because target is "+info[4]+" and thus invalid."); return; } if(sscanf(info[0],"startup-req-%d",i)==1){ // special condition for startup-req... ! trr("calling process_startup_req, i="+i+", fd="+fd+" which is: "+socket_address(fd)); //call_other(this_object(),"process_startup_req",i,info,fd); this_object()->process_startup_req(i,info,fd); return; *************** *** 78,90 **** "Your MUD hasn't registered as "+info[2]+" yet", // Error message info })); ! Debug("They have not done a startup-req for fd="+fd+", mudname="+info[2]); return; } // at this point, I guess it has a valid origin and stuff if(sscanf(info[0],"channel-%*s")==1){ // command has a "channel-" prefix // special case for channel stuff ! Debug("calling process_channel..."); process_channel(fd,info); return; } --- 78,90 ---- "Your MUD hasn't registered as "+info[2]+" yet", // Error message info })); ! trr("They have not done a startup-req for fd="+fd+", mudname="+info[2]); return; } // at this point, I guess it has a valid origin and stuff if(sscanf(info[0],"channel-%*s")==1){ // command has a "channel-" prefix // special case for channel stuff ! trr("calling process_channel..."); process_channel(fd,info); return; } *************** *** 129,135 **** if(info[4]==router_name) { // Something meant for the router but not handled by now! send_error(info[2],info[3],"not-imp","Unknown command sent to router: "+info[0],info); ! Debug("unhandled command meant for router: "+info[0]); log_file("server","UNHANDLED PACKET:\n"+identify(info)+"\n"); return; } --- 129,135 ---- if(info[4]==router_name) { // Something meant for the router but not handled by now! send_error(info[2],info[3],"not-imp","Unknown command sent to router: "+info[0],info); ! trr("unhandled command meant for router: "+info[0]); log_file("server","UNHANDLED PACKET:\n"+identify(info)+"\n"); return; } diff -c -r --new-file ds2.0r19/lib/secure/daemon/i3router/remove_mud.h ds2.0r20b/lib/secure/daemon/i3router/remove_mud.h *** ds2.0r19/lib/secure/daemon/i3router/remove_mud.h Wed Apr 5 18:44:57 2006 --- ds2.0r20b/lib/secure/daemon/i3router/remove_mud.h Sun Apr 9 23:51:25 2006 *************** *** 2,12 **** static void remove_mud(string mudname){ if(connected_muds[mudname]){ ! Debug("Cannot remove mud ["+mudname+"] because it is still online right now.\n"); return; } if(!mudinfo[mudname]){ ! Debug("Cannot remove mud ["+mudname+"] because it is not in the mudinfo list.\n"); return; } map_delete(mudinfo, mudname); --- 2,12 ---- static void remove_mud(string mudname){ if(connected_muds[mudname]){ ! trr("Cannot remove mud ["+mudname+"] because it is still online right now.\n"); return; } if(!mudinfo[mudname]){ ! trr("Cannot remove mud ["+mudname+"] because it is not in the mudinfo list.\n"); return; } map_delete(mudinfo, mudname); diff -c -r --new-file ds2.0r19/lib/secure/daemon/i3router/send_chanlist_reply.h ds2.0r20b/lib/secure/daemon/i3router/send_chanlist_reply.h *** ds2.0r19/lib/secure/daemon/i3router/send_chanlist_reply.h Wed Apr 5 18:44:57 2006 --- ds2.0r20b/lib/secure/daemon/i3router/send_chanlist_reply.h Sun Apr 9 23:51:25 2006 *************** *** 5,11 **** // string *output; // array of which channel names to tell them about mapping out=([ ]); // mapping to send int i; // counter ! Debug("send_chanlist_reply, mudname="+mudname+", old_chanid="+old_chanid); foreach(channame in keys(channel_updates)){ #ifndef SEND_WHOLE_CHANLIST if(channel_updates[channame]>old_chanid){ // needs updating --- 5,11 ---- // string *output; // array of which channel names to tell them about mapping out=([ ]); // mapping to send int i; // counter ! trr("send_chanlist_reply, mudname="+mudname+", old_chanid="+old_chanid); foreach(channame in keys(channel_updates)){ #ifndef SEND_WHOLE_CHANLIST if(channel_updates[channame]>old_chanid){ // needs updating diff -c -r --new-file ds2.0r19/lib/secure/daemon/i3router/send_error.h ds2.0r20b/lib/secure/daemon/i3router/send_error.h *** ds2.0r19/lib/secure/daemon/i3router/send_error.h Wed Apr 5 18:44:57 2006 --- ds2.0r20b/lib/secure/daemon/i3router/send_error.h Sun Apr 9 23:51:25 2006 *************** *** 2,8 **** static void send_error(string mud, string user, string errcode, string errmsg, mixed *info){ if(!connected_muds[mud]){ ! Debug("Can't send error to "+mud+" because they're not connected."); return; } write_data(connected_muds[mud],({ --- 2,8 ---- static void send_error(string mud, string user, string errcode, string errmsg, mixed *info){ if(!connected_muds[mud]){ ! trr("Can't send error to "+mud+" because they're not connected."); return; } write_data(connected_muds[mud],({ diff -c -r --new-file ds2.0r19/lib/secure/daemon/i3router/send_mudlist_updates.h ds2.0r20b/lib/secure/daemon/i3router/send_mudlist_updates.h *** ds2.0r19/lib/secure/daemon/i3router/send_mudlist_updates.h Wed Apr 5 18:44:57 2006 --- ds2.0r20b/lib/secure/daemon/i3router/send_mudlist_updates.h Sun Apr 9 23:51:25 2006 *************** *** 5,11 **** string *kys; // array of strings for keys that need to be sent mapping out=([ ]); // mapping to send int i; // counter ! Debug("send_mudlist_updates, updating_mudname="+updating_mudname+", old_mudlist_id="+old_mudlist_id); foreach(mudname in keys(mudinfo_updates)){ #ifndef SEND_WHOLE_MUDLIST if(mudinfo_updates[mudname]>old_mudlist_id){ // needs updating --- 5,13 ---- string *kys; // array of strings for keys that need to be sent mapping out=([ ]); // mapping to send int i; // counter ! trr("old_mudlist_id: "+old_mudlist_id,"blue"); ! trr("updating_mudname: "+updating_mudname,"blue"); ! trr("send_mudlist_updates, updating_mudname="+updating_mudname+", old_mudlist_id="+old_mudlist_id,"blue"); foreach(mudname in keys(mudinfo_updates)){ #ifndef SEND_WHOLE_MUDLIST if(mudinfo_updates[mudname]>old_mudlist_id){ // needs updating *************** *** 61,67 **** // take an idea from /cmds/std/_semote.c kys=keys(out); for(i=0;i #include #include ! #define DEB_IN 1 // Debug-Incoming ! #define DEB_OUT 2 // Debug-Outgoing ! #define DEB_INVALID 3 // Debug-Invalid ! #define DEB_OTHER 0 // Debug-Other #define MYSERVER 9000 // Port to accept connections on. ! #define DEBUGGER_GUY "cratylus" // Name of who to display Debugging info to. #undef DEBUGGER_GUY #define DEBUGGER_GUY "guest" #define MAXIMUM_RETRIES 5 --- 5,16 ---- #include #include #include ! #define DEB_IN 1 // trr-Incoming ! #define DEB_OUT 2 // trr-Outgoing ! #define DEB_INVALID 3 // trr-Invalid ! #define DEB_OTHER 0 // trr-Other #define MYSERVER 9000 // Port to accept connections on. ! #define DEBUGGER_GUY "cratylus" // Name of who to display trrging info to. #undef DEBUGGER_GUY #define DEBUGGER_GUY "guest" #define MAXIMUM_RETRIES 5 *************** *** 101,107 **** ! // Debugging stuff... mapping query_mudinfo(){ return copy(mudinfo); } mapping query_mud(string str){ return copy(mudinfo[str]); } void get_info() { --- 101,107 ---- ! // trrging stuff... mapping query_mudinfo(){ return copy(mudinfo); } mapping query_mud(string str){ return copy(mudinfo[str]); } void get_info() { *************** *** 117,122 **** "\nmudinfo_updates:"+identify(mudinfo_updates)+ "\nconnected:"+identify(connected_muds)+"\n"); } ! void clear(){ string mudname; foreach(mudname in keys(mudinfo)) remove_mud(mudname); } --- 117,142 ---- "\nmudinfo_updates:"+identify(mudinfo_updates)+ "\nconnected:"+identify(connected_muds)+"\n"); } ! void clear(){ string mudname; foreach(mudname in keys(mudinfo)) remove_mud(mudname); ! } ! ! mapping GetConnectedMuds(){ ! return copy(connected_muds); ! } + void clear_discs(){ + string mudname; + foreach(mudname in keys(mudinfo)) { + if(query_mud(mudname)["disconnect_time"] && + time() - query_mud(mudname)["disconnect_time"] > 60 && + time() - query_mud(mudname)["disconnect_time"] < 80){ + //trr("Removing mud: "+identify(mudname),"red"); + //remove_mud(mudname); + trr("Broadcasting updated mudlist.","white"); + broadcast_mudlist(mudname); + + } + } + } + diff -c -r --new-file ds2.0r19/lib/secure/daemon/i3router/socket_stuff.h ds2.0r20b/lib/secure/daemon/i3router/socket_stuff.h *** ds2.0r19/lib/secure/daemon/i3router/socket_stuff.h Wed Apr 5 18:44:57 2006 --- ds2.0r20b/lib/secure/daemon/i3router/socket_stuff.h Sun Apr 9 23:51:26 2006 *************** *** 2,10 **** static void close_callback(int fd){ string mudname; ! tn("close_callback: fd="+fd+"\n"); foreach(mudname in keys(muds_on_this_fd(fd))){ ! tn("Removing mud from connected_muds list: "+mudname); mudinfo[mudname]["disconnect_time"] = time(); map_delete(connected_muds, mudname); broadcast_mudlist(mudname); --- 2,10 ---- static void close_callback(int fd){ string mudname; ! trr("close_callback: fd="+fd+"\n"); foreach(mudname in keys(muds_on_this_fd(fd))){ ! trr("Removing mud from connected_muds list: "+mudname); mudinfo[mudname]["disconnect_time"] = time(); map_delete(connected_muds, mudname); broadcast_mudlist(mudname); *************** *** 48,59 **** break; case EESEND: if (counter < MAXIMUM_RETRIES) { ! tn("retry hit","cyan"); call_out("retry_write", 2, ({fd, data, counter + 1})); return; } default: ! tn("write_data_retry: " + socket_error(rc) + "yellow"); close_connection(fd); break; } --- 48,59 ---- break; case EESEND: if (counter < MAXIMUM_RETRIES) { ! trr("retry hit"); call_out("retry_write", 2, ({fd, data, counter + 1})); return; } default: ! trr("write_data_retry: " + socket_error(rc)); close_connection(fd); break; } *************** *** 63,69 **** int sockerr; map_delete(sockets, fd); sockerr = socket_close(fd); ! tn("closing sockerr:"+sockerr,"green"); } static void write_data(int fd, mixed data){ --- 63,69 ---- int sockerr; map_delete(sockets, fd); sockerr = socket_close(fd); ! trr("closing sockerr:"+sockerr); } static void write_data(int fd, mixed data){ diff -c -r --new-file ds2.0r19/lib/secure/daemon/master.c ds2.0r20b/lib/secure/daemon/master.c *** ds2.0r19/lib/secure/daemon/master.c Sat Mar 11 11:17:32 2006 --- ds2.0r20b/lib/secure/daemon/master.c Sun Apr 9 23:51:45 2006 *************** *** 572,578 **** string *parse_command_prepos_list() { return ({ "in", "with", "without", "into", "for", "on", "under", "against", "out", "within", "of", "from", "between", "at", "to", "over", "near", ! "inside", "onto", "off", "through", "across", "up", "down", "around", "about", "only", "here", "room", "exit", "enter", "-r"}); } --- 572,578 ---- string *parse_command_prepos_list() { return ({ "in", "with", "without", "into", "for", "on", "under", "against", "out", "within", "of", "from", "between", "at", "to", "over", "near", ! "inside", "onto", "off", "through", "across", "up", "down", "every", "around", "about", "only", "here", "room", "exit", "enter", "-r"}); } diff -c -r --new-file ds2.0r19/lib/secure/daemon/player.c ds2.0r20b/lib/secure/daemon/player.c *** ds2.0r19/lib/secure/daemon/player.c Mon Jan 16 23:04:14 2006 --- ds2.0r20b/lib/secure/daemon/player.c Wed Dec 31 19:00:00 1969 *************** *** 1,74 **** - // /adm/daemon/player_d.c - // from the Dead Souls Mudlib - // a daemon to keep track of player progress - // created by Descartes of Borg 10 july 1993 - - #include - #include - - string *monsters; - mapping *player_list; - - void create() { - monsters = ({}); - player_list = ({}); - if(unguarded((: file_exists, SAVE_PLAYER_LIST+__SAVE_EXTENSION__ :))) - unguarded((: restore_object, SAVE_PLAYER_LIST :)); - } - - mapping *query_player_list() { return player_list; } - - void add_player_info() { - int x; - object ob; - int i; - - if(!(ob = previous_object()) || !userp(ob)) return; - if(creatorp(ob)) { - i = sizeof(player_list); - while(i--) - if(player_list[i]["name"] == (string)ob->GetKeyName() && creatorp(ob)) - player_list -= ({ player_list[i] }); - return; - } - x = -1; - i = sizeof(player_list); - while(i--) if(player_list[i]["name"] == (string)ob->GetKeyName()) x = i; - if((sizeof(player_list) == 20) && (x == -1) && - (((int)ob->query_exp()) < player_list[19]["experience"])) - return; - if(x > -1) player_list -= ({ player_list[x] }); - player_list += ({ ([ "name":(string)ob->GetKeyName(), "experience":(int)ob->query_exp(), - "kills":sizeof((string *)ob->query_kills()), - "deaths": sizeof((mixed *)ob->query_deaths()), - "quests": sizeof((string *)ob->query_quests()), - "major accomplishments": sizeof((mixed *)ob->query_mini_quests()), - "level": (int)ob->query_level(), - "class": (string)ob->query_class(), - "guild": (string)ob->query_guild() - ]) }); - player_list = sort_array(player_list, "sort_list", this_object()); - if(sizeof(player_list) > 20) player_list = player_list[0..19]; - unguarded((: save_object, SAVE_PLAYER_LIST :)); - } - - int sort_list(mapping alpha, mapping beta) { - if(alpha["experience"] > beta["experience"]) return -1; - else if(alpha["experience"] < beta["experience"]) return 1; - else return strcmp(alpha["name"], beta["name"]); - } - - int add_kill(string str) { - int x; - - if(!userp(previous_object(0)) || !stringp(str)) return -1; - if(!monsters) monsters = ({}); - if((x=member_array(str, monsters)) == -1) { - monsters += ({ str }); - x = member_array(str, monsters); - unguarded((: save_object, SAVE_PLAYER_LIST :)); - } - return x; - } - - string query_monster(int x) { return monsters[x]; } --- 0 ---- diff -c -r --new-file ds2.0r19/lib/secure/daemon/players.c ds2.0r20b/lib/secure/daemon/players.c *** ds2.0r19/lib/secure/daemon/players.c Mon Nov 7 13:32:07 2005 --- ds2.0r20b/lib/secure/daemon/players.c Thu Apr 13 21:04:28 2006 *************** *** 1,43 **** ! /* /secure/daemon/players.c ! * from the Dead Soulsr1 Object Library ! * a player management system ! * created by Descartes of Borg 950926 ! * Version: @(#) players.c 1.2@(#) ! * Last modified: 96/10/12 ! */ ! ! #include ! #include ! #include "players.h" ! ! inherit LIB_DAEMON; ! ! static void create() { } ! ! varargs int RemovePlayer(string str) { ! object who; ! ! if( !str ) { /* this is for suicide and undead death */ ! string file, backup; ! ! if( !(who = previous_object()) || creatorp(who) ) return 0; ! file = save_file((string)who->GetKeyName()) + __SAVE_EXTENSION__; ! backup = DIR_SECURE_SAVE "/backup/" + who->GetKeyName() + "." + time(); ! return unguarded( (: rename($(file), $(backup)) :) ); } - else { - string file; ! if( !user_exists(str) ) return 0; ! if( member_group(str, PRIV_SECURE) || member_group(str, PRIV_ASSIST) ) ! return 0; ! who = find_player(str); ! file = save_file(str) + __SAVE_EXTENSION__; ! if( who ) { ! message("system", "You have been removed from " + mud_name() + ".", ! who); ! who->eventDestruct(); } ! return rm(file); } } --- 1,140 ---- ! #include ! #include ! #include ! ! mapping PlayerDataMap = ([]); ! string *PendingEncres = ({}); ! string *PendingDecres = ({}); ! string *players = ({}); ! string *creators = ({}); ! string *user_list = ({}); ! ! string player_save_file; ! ! void create() { ! if(unguarded((: file_exists, SAVE_PLAYER_LIST+__SAVE_EXTENSION__ :))) ! unguarded((: restore_object, SAVE_PLAYER_LIST :)); ! } ! ! string *eventCre(string str){ ! str = lower_case(str); ! if(member_array(str,creators) == -1) creators += ({ str }); ! if(member_array(str,players) != -1) players -= ({ str }); ! unguarded((: save_object, SAVE_PLAYER_LIST :)); ! return creators; ! } ! ! string *eventDecre(string str){ ! str = lower_case(str); ! if(member_array(str,creators) != -1) creators -= ({ str }); ! if(member_array(str,players) == -1) players += ({ str }); ! unguarded((: save_object, SAVE_PLAYER_LIST :)); ! return players; ! } ! ! void AddPlayerInfo(mixed arg) { ! ! if(!objectp(arg) && !stringp(arg)) return ; ! ! if(objectp(arg)){ ! if(!interactive(arg)) return; ! else player_save_file = base_name(arg)+".o"; } ! else { ! arg = lower_case(arg); ! if(last(arg,2) != ".o") arg += ".o"; ! if(!grepp(arg,"/")){ ! string initial = arg[0..0]; ! player_save_file = DIR_CRES +"/"+initial+"/"+arg; ! if(!file_exists(player_save_file)) ! player_save_file = DIR_PLAYERS +"/"+initial+"/"+arg; ! if(!file_exists(player_save_file)) return; } ! else player_save_file = arg; ! if(grepp(DIR_CRES, player_save_file)) creators += ({ replace_string(last_string_element(player_save_file,"/"),".o","") }) ; ! else players += ({ replace_string(last_string_element(player_save_file,"/"),".o","") }) ; ! if(!file_exists(player_save_file)) return; ! } ! ! tc("player_save_file: "+player_save_file); ! user_list += ({ replace_string(last_string_element(player_save_file,"/"),".o","") }) ; ! unguarded((: save_object, SAVE_PLAYER_LIST :)); ! } ! ! string *GetPlayerList(){ ! return players; ! } ! ! string *GetCreatorList(){ ! return creators; ! } ! ! string *GetUserList(){ ! return user_list; ! } ! ! string *AddPendingEncre(string str){ ! if(catch((int)master()->valid_apply()) || ! !(int)master()->valid_apply(({ "SECURE", "ASSIST", "LIB_CONNECT" })) ){ ! string offender = identify(previous_object(-1)); ! debug("SECURITY VIOLATION: "+offender+" ",get_stack(),"red"); ! log_file("security", "\n"+timestamp()+" AddPendingEncre breach: "+offender+" "+get_stack()); ! return ({}); } + if(str && str != "") PendingEncres += ({ lower_case(str) }); + unguarded((: save_object, SAVE_PLAYER_LIST :)); + return PendingEncres; } + + string *RemovePendingEncre(string str){ + if(catch((int)master()->valid_apply()) || + !(int)master()->valid_apply(({ "SECURE", "ASSIST", "LIB_CONNECT" })) ){ + string offender = identify(previous_object(-1)); + debug("SECURITY VIOLATION: "+offender+" ",get_stack(),"red"); + log_file("security","\n"+ timestamp()+" RemovePendingEncre breach: "+offender+" "+get_stack()); + return ({}); + } + if(!str || str == "") return PendingEncres; + str = lower_case(str); + if(member_array(str, PendingEncres) != -1) PendingEncres -= ({ lower_case(str) }); + unguarded((: save_object, SAVE_PLAYER_LIST :)); + return PendingEncres; + } + + string *GetPendingEncres(){ + return PendingEncres; + } + + string *AddPendingDecre(string str){ + if(catch((int)master()->valid_apply()) || + !(int)master()->valid_apply(({ "SECURE", "ASSIST", "LIB_CONNECT" })) ){ + string offender = identify(previous_object(-1)); + debug("SECURITY VIOLATION: "+offender+" ",get_stack(),"red"); + log_file("security", "\n"+timestamp()+" AddPendingDecre breach: "+offender+" "+get_stack()); + return ({}); + } + if(str && str != "") PendingDecres += ({ lower_case(str) }); + unguarded((: save_object, SAVE_PLAYER_LIST :)); + return PendingDecres; + } + + string *RemovePendingDecre(string str){ + if(catch((int)master()->valid_apply()) || + !(int)master()->valid_apply(({ "SECURE", "ASSIST", "LIB_CONNECT" })) ){ + string offender = identify(previous_object(-1)); + debug("SECURITY VIOLATION: "+offender+" ",get_stack(),"red"); + log_file("security", "\n"+timestamp()+" RemovePendingDecre breach: "+offender+" "+get_stack()); + return ({}); + } + if(!str || str == "") return PendingDecres; + str = lower_case(str); + if(member_array(str, PendingDecres) != -1) PendingDecres -= ({ lower_case(str) }); + unguarded((: save_object, SAVE_PLAYER_LIST :)); + return PendingDecres; + } + + string *GetPendingDecres(){ + return PendingDecres; + } + diff -c -r --new-file ds2.0r19/lib/secure/daemon/players.h ds2.0r20b/lib/secure/daemon/players.h *** ds2.0r19/lib/secure/daemon/players.h Wed Sep 28 19:34:12 2005 --- ds2.0r20b/lib/secure/daemon/players.h Wed Dec 31 19:00:00 1969 *************** *** 1,7 **** - #ifndef l_players_h - #define l_players_h - - static void create(); - varargs int RemovePlayer(string str); - - #endif /* l_players_h */ --- 0 ---- diff -c -r --new-file ds2.0r19/lib/secure/daemon/snoop.c ds2.0r20b/lib/secure/daemon/snoop.c *** ds2.0r19/lib/secure/daemon/snoop.c Wed Dec 31 19:00:00 1969 --- ds2.0r20b/lib/secure/daemon/snoop.c Wed Apr 12 23:56:45 2006 *************** *** 0 **** --- 1,206 ---- + #include + #include + #include + #include + + inherit LIB_DAEMON; + + string *snooped = ({}); + object *snoopers = ({}); + string *monitored = ({}); + mapping Watchers = ([]); + object *prevusers; + + void eventLoadRogues(); + + static void create() { + daemon::create(); + debug("SNOOP_D restarted.","red"); + if( file_size( SAVE_SNOOP __SAVE_EXTENSION__ ) > 0 ) + unguarded( (: restore_object, SAVE_SNOOP, 1 :) ); + SetNoClean(1); + set_heart_beat(60); + if(GLOBAL_MONITOR == 0 && sizeof(monitored)){ + call_out( (: eventLoadRogues :), 1); + } + snoopers = filter(objects(), (: base_name($1) == "/secure/obj/snooper" :) ); + } + + void eventLoadRogues(){ + foreach(string rogue in monitored) this_object()->CheckBot(rogue); + snoopers = filter(objects(), (: base_name($1) == "/secure/obj/snooper" :) ); + } + + int AddSnooper(){ + if(base_name(previous_object()) == "/secure/obj/snooper" && + member_array(previous_object(), snoopers) == -1){ + snoopers += ({ previous_object() }); + unguarded( (: save_object, SAVE_SNOOP, 1 :) ); + return 1; + } + return 0; + } + + int RemoveSnooper(){ + if(base_name(previous_object()) == "/secure/obj/snooper" && + member_array(previous_object(), snoopers) != -1){ + snoopers -= ({ previous_object() }); + unguarded( (: save_object, SAVE_SNOOP, 1 :) ); + return 1; + } + return 0; + } + + int CheckBot(string str){ + object cloan, foo; + int allset; + string *immune; + string name; + + //tc("str: "+str); + + foreach(object snoopbox in snoopers){ + if(snoopbox->GetSnooped() == str) foo = find_player(str); + } + + //if(foo && environment(foo)) tc("environment("+identify(foo)+"): "+identify(environment(foo))); + if(!foo && GLOBAL_MONITOR > 0){ + if(archp(find_player(str)) && GLOBAL_MONITOR == 2) return 0; + //tc("cloning: "); + cloan=new("/secure/obj/snooper"); + //tc("vloan: "+identify(cloan)); + cloan->eventStartSnoop(str); + //tc("cloning: "+identify(cloan)+" to snoop "+str); + } + unguarded( (: save_object, SAVE_SNOOP, 1 :) ); + return 1; + } + + void CheckSnooped(){ + object *users; + users = users(); + if(users && users != prevusers ){ + foreach(object user in users){ + CheckBot(lower_case(user->GetKeyName())); + } + prevusers = users; + } + } + + void heart_beat(){ + CheckSnooped(); + } + + void reset(){ + if(query_heart_beat(this_object()) < 1) set_heart_beat(60); + CheckSnooped(); + } + + int GetSnoop(string target, string msg){ + //if(target != "cratylus") { + //tc(target+" "+msg+"\n\n","green"); + //tc("snooper: "+identify(previous_object())); + //} + if(base_name(previous_object()) != "/secure/obj/snooper") return 0; + else if(sizeof(Watchers[target])) { + foreach(string watcher in Watchers[target]){ + tell_player(watcher, target+"% "+msg); + } + } + else Watchers[target] = ({}); + return 1; + } + + int AddWatcher(string watcher, string target){ + if(!valid_snoop(find_player(watcher), find_player(target))) { + return 0; + } + if(Watchers[target] && member_array(watcher,Watchers[target]) != -1){ + return 0; + } + if(!Watchers[target] || !sizeof(Watchers[target])) { + Watchers[target] = ({ watcher }); + } + else { + Watchers[target] += ({ watcher }); + } + unguarded( (: save_object, SAVE_SNOOP, 1 :) ); + return 1; + } + + int RemoveWatcher(string watcher, string target){ + if(!valid_snoop(find_player(watcher), find_player(target))) return 0; + if(this_player() && interactive(this_player())){ + if(this_player()->GetKeyName() != watcher && !archp(this_player())) return 0; + } + else return 0; + + if(!Watchers[target] || !sizeof(Watchers[target])) return 0; + else if(member_array(watcher, Watchers[target]) != -1) + Watchers[target] -= ({ watcher }); + if((!Watchers[target] || !sizeof(Watchers[target])) && + member_array(target, monitored) == -1) { + foreach(object snoopbox in snoopers){ + if(snoopbox->GetSnooped() == target) snoopbox->eventDestruct(); + } + } + if(Watchers[target] && !sizeof(Watchers[target])) map_delete(Watchers, target); + unguarded( (: save_object, SAVE_SNOOP, 1 :) ); + return 1; + } + + int AddMonitor(string requestor, string target){ + if(member_array(target, monitored) == -1) monitored += ({ target }); + unguarded( (: save_object, SAVE_SNOOP, 1 :) ); + CheckBot(target); + return 1; + } + + int RemoveMonitor(object requestor, string target){ + if(!archp(requestor)) return 0; + monitored -= ({ target }); + unguarded( (: save_object, SAVE_SNOOP, 1 :) ); + if(Watchers[target] && sizeof(Watchers[target])) return 1; + foreach(object snoopbox in snoopers){ + if(snoopbox->GetSnooped() == target) snoopbox->eventDestruct(); + } + if(Watchers[target] && !sizeof(Watchers[target])) map_delete(Watchers, target); + unguarded( (: save_object, SAVE_SNOOP, 1 :) ); + return 1; + } + + int ReportLinkDeath(string str){ + if(!find_player(str)){ + foreach(object snoopbox in snoopers){ + if(snoopbox->GetSnooped() == str) snoopbox->eventDestruct(); + } + map_delete(Watchers, str); + unguarded( (: save_object, SAVE_SNOOP, 1 :) ); + return 1; + } + return 0; + } + + int ReportReconnect(string str){ + if(base_name(previous_object()) == LIB_CONNECT){ + foreach(object snoopbox in snoopers){ + if(snoopbox->GetSnooped() == str) snoopbox->eventDestruct(); + } + map_delete(Watchers, str); + CheckBot(str); + unguarded( (: save_object, SAVE_SNOOP, 1 :) ); + return 1; + } + return 0; + } + + int Report(){ + if(!archp(previous_object(2))){ + return 0; + } + tc("Watchers: "+identify(Watchers)); + tc("snoopers: "+identify(snoopers)); + tc("prevusers: "+identify(prevusers)); + return 1; + } + diff -c -r --new-file ds2.0r19/lib/secure/daemon/voting.c ds2.0r20b/lib/secure/daemon/voting.c *** ds2.0r19/lib/secure/daemon/voting.c Mon Jan 16 23:04:14 2006 --- ds2.0r20b/lib/secure/daemon/voting.c Wed Apr 12 23:50:19 2006 *************** *** 157,163 **** mixed eventNextDay() { mapVoting["daycount"]--; ! if( ! mapVoting["daycount"] ) { if( mapVoting["mode"] == VOTE_MODE_CANDIDATES ) { mapVoting["mode"] = VOTE_MODE_VOTING; mapVoting["daycount"] = VOTE_DAY_COUNT; --- 157,163 ---- mixed eventNextDay() { mapVoting["daycount"]--; ! if( !mapVoting["daycount"] ) { if( mapVoting["mode"] == VOTE_MODE_CANDIDATES ) { mapVoting["mode"] = VOTE_MODE_VOTING; mapVoting["daycount"] = VOTE_DAY_COUNT; *************** *** 167,173 **** eventSave(); return VOTE_SUCCESS; } ! eventEndVoting(); return VOTE_SUCCESS; } --- 167,173 ---- eventSave(); return VOTE_SUCCESS; } ! //tc("mapVoting[\"daycount\"]: "+mapVoting["daycount"]); eventEndVoting(); return VOTE_SUCCESS; } *************** *** 189,197 **** mapCouncil = ([]); foreach( string sClass in CLASSES_D->GetClasses() ) { mapWho = mapVoting["votes"][lower_case(sClass)]; ! if( ! ( sizeof( asWho = keys( mapWho ) ) ) ) ! return VOTE_SUCCESS; while( sizeof( asWho ) >= 2 ) { string player1, player2; --- 189,203 ---- mapCouncil = ([]); foreach( string sClass in CLASSES_D->GetClasses() ) { + //tc("sClass: "+sClass); mapWho = mapVoting["votes"][lower_case(sClass)]; ! //tc("mapVoting: "+identify(mapVoting),"red"); ! //tc("mapWho: "+identify(mapWho)); ! if( ! ( sizeof( asWho = keys( mapWho ) ) ) ){ ! //tc("?"); ! //return VOTE_SUCCESS; ! } ! //tc("asWho: "+identify(asWho)); while( sizeof( asWho ) >= 2 ) { string player1, player2; *************** *** 204,211 **** else asWho -= ({ player1 }); } ! mapCouncil[lower_case(sClass)] = asWho[0]; } eventSave(); --- 210,219 ---- else asWho -= ({ player1 }); } + //tc("asWho: "+identify(asWho)); ! if(asWho && sizeof(asWho)) mapCouncil[lower_case(sClass)] = asWho[0]; ! //tc("mapCouncil["+lower_case(sClass)+"]: "+identify(mapCouncil[lower_case(sClass)])); } eventSave(); *************** *** 230,236 **** return asWho; } ! string GetCouncilMember( string sClass ) { return mapCouncil[sClass]; } int GetVoteStatus( object ob ) { string sVoter; --- 238,258 ---- return asWho; } ! string GetCouncilMember( string sClass ) { ! if(mapCouncil[sClass]) return mapCouncil[sClass]; ! else return ""; ! } ! ! string GetCurrentCouncil(){ ! string ret = "Current council:\n"; ! foreach( string sClass in CLASSES_D->GetClasses() ){ ! string councillor; ! if(mapCouncil[sClass]) councillor = mapCouncil[sClass]; ! else councillor = "NONE"; ! ret += capitalize(sClass)+": "+capitalize(councillor)+"\n"; ! } ! return ret; ! } int GetVoteStatus( object ob ) { string sVoter; diff -c -r --new-file ds2.0r19/lib/secure/include/config.h ds2.0r20b/lib/secure/include/config.h *** ds2.0r19/lib/secure/include/config.h Thu Apr 6 10:33:38 2006 --- ds2.0r20b/lib/secure/include/config.h Wed Apr 12 23:51:01 2006 *************** *** 42,51 **** #define EXTRA_TIME_OFFSET 0 #define RESET_INTERMUD 0 - #define ENGLISH_ONLY 0 #define HUMANS_ONLY 0 - #define PINGING_MUDS ({"Frontiers","Dead Souls"}) #endif /* s_config_h */ --- 42,51 ---- #define EXTRA_TIME_OFFSET 0 #define RESET_INTERMUD 0 #define ENGLISH_ONLY 0 #define HUMANS_ONLY 0 #define PINGING_MUDS ({"Frontiers","Dead Souls"}) + #define ENABLE_ENCUMBRANCE 1 + #define GLOBAL_MONITOR 0 #endif /* s_config_h */ diff -c -r --new-file ds2.0r19/lib/secure/include/daemons.h ds2.0r20b/lib/secure/include/daemons.h *** ds2.0r19/lib/secure/include/daemons.h Wed Apr 5 19:33:19 2006 --- ds2.0r20b/lib/secure/include/daemons.h Thu Apr 13 21:05:37 2006 *************** *** 38,46 **** #define ROUTER_D DIR_SECURE_DAEMONS "/i3router/server" #define SEASONS_D DIR_DAEMONS "/seasons" #define SERVICES_D DIR_DAEMONS "/services" #define SOUL_D DIR_DAEMONS "/soul" ! #define SPELLS_D DIR_DAEMONS "/spells" #define STATISTICS_D DIR_DAEMONS "/statistics" #define TERMINAL_D DIR_DAEMONS "/terminal" #define TIME_D DIR_DAEMONS "/time" #ifdef Dead SoulsLPMud --- 38,48 ---- #define ROUTER_D DIR_SECURE_DAEMONS "/i3router/server" #define SEASONS_D DIR_DAEMONS "/seasons" #define SERVICES_D DIR_DAEMONS "/services" + #define SNOOP_D DIR_SECURE_DAEMONS "/snoop" #define SOUL_D DIR_DAEMONS "/soul" ! #define SPELLS_D DIR_DAEMONS "/spells" #define STATISTICS_D DIR_DAEMONS "/statistics" + #define STARGATE_D DIR_DAEMONS "/stargate" #define TERMINAL_D DIR_DAEMONS "/terminal" #define TIME_D DIR_DAEMONS "/time" #ifdef Dead SoulsLPMud diff -c -r --new-file ds2.0r19/lib/secure/include/dirs.h ds2.0r20b/lib/secure/include/dirs.h *** ds2.0r19/lib/secure/include/dirs.h Wed Sep 28 19:34:12 2005 --- ds2.0r20b/lib/secure/include/dirs.h Wed Apr 12 23:51:12 2006 *************** *** 80,86 **** #define DIR_SECURE_COMMON_CMDS DIR_SECURE_CMDS "/common" #define DIR_CREATOR_CMDS DIR_CMDS "/creators" #define DIR_SECURE_CREATOR_CMDS DIR_SECURE_CMDS "/creators" ! #define DIR_GUILD_CMDS DIR_CMDS "/guild" #define DIR_HM_CMDS DIR_CMDS "/hm" #define DIR_PLAYER_CMDS DIR_CMDS "/players" #define DIR_SECURE_PLAYER_CMDS DIR_SECURE_CMDS "/players" --- 80,86 ---- #define DIR_SECURE_COMMON_CMDS DIR_SECURE_CMDS "/common" #define DIR_CREATOR_CMDS DIR_CMDS "/creators" #define DIR_SECURE_CREATOR_CMDS DIR_SECURE_CMDS "/creators" ! #define DIR_CLAN_CMDS DIR_CMDS "/clan" #define DIR_HM_CMDS DIR_CMDS "/hm" #define DIR_PLAYER_CMDS DIR_CMDS "/players" #define DIR_SECURE_PLAYER_CMDS DIR_SECURE_CMDS "/players" diff -c -r --new-file ds2.0r19/lib/secure/include/lib.h ds2.0r20b/lib/secure/include/lib.h *** ds2.0r19/lib/secure/include/lib.h Wed Apr 5 19:33:19 2006 --- ds2.0r20b/lib/secure/include/lib.h Thu Apr 13 21:05:37 2006 *************** *** 11,23 **** --- 11,28 ---- #include #define LIB_AUTH DIR_SECURE_LIB "/auth" + #define LIB_BATTERY DIR_LIB "/battery" + #define LIB_BLANK_PILE DIR_LIB "/blank_pile" #define LIB_BODY DIR_LIB "/body" #define LIB_BURN DIR_LIB "/burn" #define LIB_CAPTURE DIR_LIB "/capture" #define LIB_CHAPEL DIR_LIB "/chapel" #define LIB_CHAT DIR_LIB "/chat" #define LIB_CLASSES DIR_LIB "/classes" + #define LIB_CLAY DIR_LIB "/clay" + #define LIB_CLERK DIR_LIB "/clerk" #define LIB_CLIENT DIR_SECURE_LIB "/net/client" + #define LIB_CLIP DIR_LIB "/clip" #define LIB_COMBAT DIR_LIB "/combat" #define LIB_COMBATMSG DIR_LIB "/combatmsg" #define LIB_COMMAND DIR_LIB "/command" *************** *** 36,58 **** #define LIB_FILES DIR_LIB "/files" #define LIB_FISH DIR_LIB "/fish" #define LIB_FISHING DIR_LIB "/fishing" #define LIB_FOLLOW DIR_LIB "/follow" #define LIB_FUEL DIR_LIB "/fuel" #define LIB_GENETICS DIR_LIB "/genetics" ! #define LIB_GUILD DIR_LIB "/guild" #define LIB_HELP DIR_LIB "/help" #define LIB_HISTORY DIR_LIB "/history" ! #define LIB_INTERACTIVE DIR_LIB "/interactive" ! #define LIB_INTERFACE DIR_LIB "/interface" ! #define LIB_LAMP DIR_LIB "/lamp" ! #define LIB_LANGUAGE DIR_LIB "/language" ! #define LIB_LEAD DIR_LIB "/lead" ! #define LIB_LEADER DIR_LIB "/leader" ! #define LIB_LIGHT DIR_LIB "/light" ! #define LIB_LIVING DIR_LIB "/living" #define LIB_LOGIN DIR_SECURE_LIB "/login" #define LIB_MAGIC DIR_LIB "/magic" #define LIB_MATCH DIR_LIB "/match" #define LIB_MEAL DIR_LIB "/meal" #define LIB_MESSAGES DIR_LIB "/messages" #define LIB_MONEY DIR_LIB "/money" --- 41,68 ---- #define LIB_FILES DIR_LIB "/files" #define LIB_FISH DIR_LIB "/fish" #define LIB_FISHING DIR_LIB "/fishing" + #define LIB_FLASHLIGHT DIR_LIB "/flashlight" #define LIB_FOLLOW DIR_LIB "/follow" + #define LIB_FTP_DATA_CONN DIR_SECURE_LIB "/net/ftp_data_connection" #define LIB_FUEL DIR_LIB "/fuel" #define LIB_GENETICS DIR_LIB "/genetics" ! #define LIB_GUN DIR_LIB "/gun" ! #define LIB_CLAN DIR_LIB "/clan" #define LIB_HELP DIR_LIB "/help" #define LIB_HISTORY DIR_LIB "/history" ! #define LIB_INTERACTIVE DIR_LIB "/interactive" ! #define LIB_INTERFACE DIR_LIB "/interface" ! #define LIB_LAMP DIR_LIB "/lamp" ! #define LIB_LANGUAGE DIR_LIB "/language" ! #define LIB_LEAD DIR_LIB "/lead" ! #define LIB_LEADER DIR_LIB "/leader" ! #define LIB_LIGHT DIR_LIB "/light" ! #define LIB_LIVING DIR_LIB "/living" #define LIB_LOGIN DIR_SECURE_LIB "/login" #define LIB_MAGIC DIR_LIB "/magic" + #define LIB_MANYCOINS DIR_LIB "/manycoins" #define LIB_MATCH DIR_LIB "/match" + #define LIB_MAYOR DIR_LIB "/mayor" #define LIB_MEAL DIR_LIB "/meal" #define LIB_MESSAGES DIR_LIB "/messages" #define LIB_MONEY DIR_LIB "/money" *************** *** 61,105 **** #define LIB_PAGER DIR_LIB "/pager" #define LIB_PERSIST DIR_LIB "/persist" #define LIB_PILE DIR_LIB "/pile" #define LIB_PLAYER DIR_LIB "/player" #define LIB_POLE DIR_LIB "/pole" #define LIB_POST_OFFICE DIR_LIB "/post_office" #define LIB_RACE DIR_LIB "/race" #define LIB_REMOTE DIR_LIB "/remote" #define LIB_SCROLL DIR_LIB "/scroll" #define LIB_SENTIENT DIR_LIB "/sentient" #define LIB_SERVER DIR_SECURE_LIB "/net/server" #define LIB_SOCKET DIR_SECURE_LIB "/net/socket" #define LIB_SPELL DIR_LIB "/spell" #define LIB_STEAL DIR_LIB "/steal" #define LIB_TALK DIR_LIB "/talk" #define LIB_TELLER DIR_LIB "/teller" #define LIB_TORCH DIR_LIB "/torch" #define LIB_TRAINER DIR_LIB "/trainer" - #ifdef Dead SoulsLPMud #define LIB_UNDEAD DIR_LIB "/undead" - #endif #define LIB_VEHICLE DIR_LIB "/vehicle" #define LIB_VERB DIR_LIB "/verb" #define LIB_VIRTUAL DIR_LIB "/virtual" - #define LIB_BATTERY DIR_LIB "/battery" - #define LIB_SHADOW DIR_LIB "/shadow" - #define LIB_SHOP DIR_LIB "/shop" - #define LIB_FLASHLIGHT DIR_LIB "/flashlight" - #define LIB_GUN DIR_LIB "/gun" - #define LIB_PISTOL DIR_LIB "/pistol" - #define LIB_RIFLE DIR_LIB "/rifle" - #define LIB_ROUND DIR_LIB "/round" - #define LIB_SHELL DIR_LIB "/shell" - #define LIB_CLIP DIR_LIB "/clip" - #define LIB_MANYCOINS DIR_LIB "/manycoins" - #define LIB_BLANK_PILE DIR_LIB "/blank_pile" - #define LIB_MONEY DIR_LIB "/money" - #define LIB_MAYOR DIR_LIB "/mayor" - #define LIB_CLERK DIR_LIB "/clerk" - #define LIB_CLAY DIR_LIB "/clay" - #define LIB_TEACHER DIR_LIB "/teacher" - #define LIB_FTP_DATA_CONNECTION "/secure/lib/net/ftp_data_connection" - #endif /* s_lib_h */ --- 71,102 ---- #define LIB_PAGER DIR_LIB "/pager" #define LIB_PERSIST DIR_LIB "/persist" #define LIB_PILE DIR_LIB "/pile" + #define LIB_PISTOL DIR_LIB "/pistol" #define LIB_PLAYER DIR_LIB "/player" #define LIB_POLE DIR_LIB "/pole" #define LIB_POST_OFFICE DIR_LIB "/post_office" #define LIB_RACE DIR_LIB "/race" #define LIB_REMOTE DIR_LIB "/remote" + #define LIB_RIFLE DIR_LIB "/rifle" + #define LIB_ROUND DIR_LIB "/round" #define LIB_SCROLL DIR_LIB "/scroll" #define LIB_SENTIENT DIR_LIB "/sentient" #define LIB_SERVER DIR_SECURE_LIB "/net/server" + #define LIB_SHADOW DIR_LIB "/shadow" + #define LIB_SHELL DIR_LIB "/shell" + #define LIB_SHOP DIR_LIB "/shop" #define LIB_SOCKET DIR_SECURE_LIB "/net/socket" #define LIB_SPELL DIR_LIB "/spell" + #define LIB_STARGATE DIR_LIB "/stargate" #define LIB_STEAL DIR_LIB "/steal" #define LIB_TALK DIR_LIB "/talk" + #define LIB_TEACHER DIR_LIB "/teacher" #define LIB_TELLER DIR_LIB "/teller" #define LIB_TORCH DIR_LIB "/torch" #define LIB_TRAINER DIR_LIB "/trainer" #define LIB_UNDEAD DIR_LIB "/undead" #define LIB_VEHICLE DIR_LIB "/vehicle" #define LIB_VERB DIR_LIB "/verb" #define LIB_VIRTUAL DIR_LIB "/virtual" #endif /* s_lib_h */ diff -c -r --new-file ds2.0r19/lib/secure/include/rooms.h ds2.0r20b/lib/secure/include/rooms.h *** ds2.0r19/lib/secure/include/rooms.h Wed Apr 5 19:33:20 2006 --- ds2.0r20b/lib/secure/include/rooms.h Sun Apr 9 23:52:20 2006 *************** *** 11,15 **** --- 11,16 ---- #define ROOM_WIZ DIR_STANDARD_DOMAIN "/room/wiz_hall" #define ROOM_ARCH "/secure/room/arch" #define ROOM_NETWORK "/secure/room/network" + #define ROOM_ROUTER "/secure/room/router" #endif /* s_rooms_h */ diff -c -r --new-file ds2.0r19/lib/secure/include/save.h ds2.0r20b/lib/secure/include/save.h *** ds2.0r19/lib/secure/include/save.h Wed Jan 11 23:07:30 2006 --- ds2.0r20b/lib/secure/include/save.h Thu Apr 13 21:05:37 2006 *************** *** 17,28 **** #define SAVE_NAMESERVER DIR_SAVE "/network" #define SAVE_NOTIFY DIR_SAVE "/notify" #define SAVE_QUESTS DIR_SECURE_SAVE "/quests" ! #define SAVE_RACES DIR_SAVE "/races" #define SAVE_PLAYER_LIST DIR_SAVE "/player_list" #define SAVE_POLITICS DIR_SECURE_SAVE "/politics" #define SAVE_RACES DIR_SAVE "/races" #define SAVE_SERVICES DIR_SAVE "/services" #define SAVE_SOUL DIR_SAVE "/soul" #define SAVE_UNIQUE DIR_SAVE "/unique" #define SAVE_IMC2 DIR_SAVE "/imc2" --- 17,30 ---- #define SAVE_NAMESERVER DIR_SAVE "/network" #define SAVE_NOTIFY DIR_SAVE "/notify" #define SAVE_QUESTS DIR_SECURE_SAVE "/quests" ! #define SAVE_RACES DIR_SAVE "/races" #define SAVE_PLAYER_LIST DIR_SAVE "/player_list" #define SAVE_POLITICS DIR_SECURE_SAVE "/politics" #define SAVE_RACES DIR_SAVE "/races" #define SAVE_SERVICES DIR_SAVE "/services" + #define SAVE_SNOOP DIR_SECURE_SAVE "/snoop" #define SAVE_SOUL DIR_SAVE "/soul" + #define SAVE_STARGATE DIR_SAVE "/stargate" #define SAVE_UNIQUE DIR_SAVE "/unique" #define SAVE_IMC2 DIR_SAVE "/imc2" diff -c -r --new-file ds2.0r19/lib/secure/lib/connect.c ds2.0r20b/lib/secure/lib/connect.c *** ds2.0r19/lib/secure/lib/connect.c Fri Apr 7 00:13:55 2006 --- ds2.0r20b/lib/secure/lib/connect.c Wed Apr 12 23:52:12 2006 *************** *** 133,141 **** tmp = read_file("/secure/include/config.h"); if(sizeof(tmp)){ ! rm("/secure/include/config.h"); ! tmp = replace_string(tmp, "DEBUG_NAME", Name); ! write_file("/secure/include/config.h", tmp); } if( ob = find_object(LIB_CONNECT) ) destruct(ob); --- 133,141 ---- tmp = read_file("/secure/include/config.h"); if(sizeof(tmp)){ ! rm("/secure/include/config.h"); ! tmp = replace_string(tmp, "DEBUG_NAME", Name); ! write_file("/secure/include/config.h", tmp); } if( ob = find_object(LIB_CONNECT) ) destruct(ob); *************** *** 157,162 **** --- 157,163 ---- else { receive("Mud name unchanged.\n"); } + PLAYERS_D->AddPlayerInfo(Name); shutdown(); destruct(this_object()); diff -c -r --new-file ds2.0r19/lib/secure/lib/connect.first ds2.0r20b/lib/secure/lib/connect.first *** ds2.0r19/lib/secure/lib/connect.first Fri Apr 7 00:14:02 2006 --- ds2.0r20b/lib/secure/lib/connect.first Wed Apr 12 23:52:12 2006 *************** *** 133,141 **** tmp = read_file("/secure/include/config.h"); if(sizeof(tmp)){ ! rm("/secure/include/config.h"); ! tmp = replace_string(tmp, "DEBUG_NAME", Name); ! write_file("/secure/include/config.h", tmp); } if( ob = find_object(LIB_CONNECT) ) destruct(ob); --- 133,141 ---- tmp = read_file("/secure/include/config.h"); if(sizeof(tmp)){ ! rm("/secure/include/config.h"); ! tmp = replace_string(tmp, "DEBUG_NAME", Name); ! write_file("/secure/include/config.h", tmp); } if( ob = find_object(LIB_CONNECT) ) destruct(ob); *************** *** 157,162 **** --- 157,163 ---- else { receive("Mud name unchanged.\n"); } + PLAYERS_D->AddPlayerInfo(Name); shutdown(); destruct(this_object()); diff -c -r --new-file ds2.0r19/lib/secure/lib/connect.first.c ds2.0r20b/lib/secure/lib/connect.first.c *** ds2.0r19/lib/secure/lib/connect.first.c Fri Apr 7 00:14:06 2006 --- ds2.0r20b/lib/secure/lib/connect.first.c Wed Apr 12 23:52:17 2006 *************** *** 133,141 **** tmp = read_file("/secure/include/config.h"); if(sizeof(tmp)){ ! rm("/secure/include/config.h"); ! tmp = replace_string(tmp, "DEBUG_NAME", Name); ! write_file("/secure/include/config.h", tmp); } if( ob = find_object(LIB_CONNECT) ) destruct(ob); --- 133,141 ---- tmp = read_file("/secure/include/config.h"); if(sizeof(tmp)){ ! rm("/secure/include/config.h"); ! tmp = replace_string(tmp, "DEBUG_NAME", Name); ! write_file("/secure/include/config.h", tmp); } if( ob = find_object(LIB_CONNECT) ) destruct(ob); *************** *** 157,162 **** --- 157,163 ---- else { receive("Mud name unchanged.\n"); } + PLAYERS_D->AddPlayerInfo(Name); shutdown(); destruct(this_object()); diff -c -r --new-file ds2.0r19/lib/secure/lib/connect.real ds2.0r20b/lib/secure/lib/connect.real *** ds2.0r19/lib/secure/lib/connect.real Wed Apr 5 19:36:51 2006 --- ds2.0r20b/lib/secure/lib/connect.real Thu Apr 13 21:06:23 2006 *************** *** 24,29 **** --- 24,31 ---- static private int *Screen; static private int rescue; + int eventCheckPending(string str); + static void create(int binary) { CrackCount = 0; Name = ""; *************** *** 117,123 **** } receive("Password: \n"); input_to((: InputPassword :), I_NOECHO | I_NOESC, name); ! name = ""; } static void InputPassword(string pass, string cap) { --- 119,125 ---- } receive("Password: \n"); input_to((: InputPassword :), I_NOECHO | I_NOESC, name); ! //name = ""; } static void InputPassword(string pass, string cap) { *************** *** 128,133 **** --- 130,141 ---- Destruct(); return; } + if(!cap || cap == "") { + receive("\nAn unusual error has occurred. Please try again.\n"); + Destruct(); + return; + } + control = (string)Player->GetPassword(); if( control != crypt(pass, control) ) { receive("\nInvalid password.\n"); *************** *** 147,152 **** --- 155,163 ---- input_to( (: InputPassword :), I_NOECHO | I_NOESC, cap); return; } + + call_out( (: eventCheckPending, lower_case(Name) :), 3); + if( !NetDead ) eventEnterGame(); else eventReEnterGame(cap); } *************** *** 200,205 **** --- 211,217 ---- if(sizeof(deep_inventory(Player))) deep_inventory(Player)->eventMove(ROOM_FURNACE); log_file("enter", cap + " (exec): " + ctime(time()) + "\n"); Player->eventReconnect(); + SNOOP_D->ReportReconnect(Player->GetKeyName()); } receive("\nProblem reconnecting.\n"); Destruct(); *************** *** 233,239 **** static private void eventEnterGame() { if(!exec(Player, this_object())) { ! //tc("problem connecting"); receive("\nProblem connecting.\n"); Player->eventDestruct(); destruct(this_object()); --- 245,251 ---- static private void eventEnterGame() { if(!exec(Player, this_object())) { ! debug("problem connecting"); receive("\nProblem connecting.\n"); Player->eventDestruct(); destruct(this_object()); *************** *** 246,251 **** --- 258,264 ---- file_size(user_path(Player->GetKeyName())+".profile") > 0){ Player->eventForce("source "+user_path(Player->GetKeyName())+".profile"); } + SNOOP_D->CheckBot(Player->GetKeyName()); //if(!(Player->GetProperty("brand_spanking_new"))) destruct(this_object()); call_out( (: destruct(this_object()) :), 10); *************** *** 403,418 **** int eventCre(string str){ mixed mixt; - //tc("made it in"); if(AUTO_WIZ == 1){ mixt = load_object("/secure/cmds/admins/encre")->cmd(str); - //tc("mixt: "+identify(mixt)); } destruct(this_object()); - //Destruct(); return 1; } static void cmdPick(string args) { if( !args || args == "" ) { receive("You must specify a race to pick.\n\nRace: \n"); --- 416,443 ---- int eventCre(string str){ mixed mixt; if(AUTO_WIZ == 1){ mixt = load_object("/secure/cmds/admins/encre")->cmd(str); } destruct(this_object()); return 1; } + int eventCheckPending(string str){ + mixed mixt; + if(member_array(lower_case(str),PLAYERS_D->GetPendingEncres()) != -1){ + PLAYERS_D->RemovePendingEncre(lower_case(str)); + mixt = load_object("/secure/cmds/admins/encre")->cmd(str); + } + else if(member_array(lower_case(str),PLAYERS_D->GetPendingDecres()) != -1){ + PLAYERS_D->RemovePendingDecre(lower_case(str)); + mixt = load_object("/secure/cmds/admins/decre")->cmd(str); + } + destruct(this_object()); + return 1; + } + + static void cmdPick(string args) { if( !args || args == "" ) { receive("You must specify a race to pick.\n\nRace: \n"); *************** *** 506,512 **** int *GetScreen() { if( Screen ) return Screen; ! else return ({ 79, 24 }); } void SetLastError(mapping m) { --- 531,537 ---- int *GetScreen() { if( Screen ) return Screen; ! else return ({ 79, 25 }); } void SetLastError(mapping m) { diff -c -r --new-file ds2.0r19/lib/secure/lib/net/server.c ds2.0r20b/lib/secure/lib/net/server.c *** ds2.0r19/lib/secure/lib/net/server.c Wed Apr 5 19:33:20 2006 --- ds2.0r20b/lib/secure/lib/net/server.c Wed Apr 12 23:52:56 2006 *************** *** 109,115 **** static int Destruct() { if( daemon::Destruct() ) { foreach(int fd, class server socket in Sockets) { ! tc("server:Destruct: fd: "+fd+", "+socket_address(fd),"green"); socket->Owner->evenShutdown(); } eventClose(Listen); --- 109,115 ---- static int Destruct() { if( daemon::Destruct() ) { foreach(int fd, class server socket in Sockets) { ! trr("server:Destruct: fd: "+fd+", "+socket_address(fd),"green"); socket->Owner->evenShutdown(); } eventClose(Listen); *************** *** 137,143 **** } static void eventServerAbortCallback(int fd) { ! tc("server:eventServerAbortCallback: fd: "+fd+", "+socket_address(fd),"green"); eventClose(fd); } --- 137,143 ---- } static void eventServerAbortCallback(int fd) { ! trr("server:eventServerAbortCallback: fd: "+fd+", "+socket_address(fd),"green"); eventClose(fd); } *************** *** 152,158 **** static void eventServerListenCallback(int fd) { int x; ! tc("server:eventServerListenCallback: fd: "+fd+", "+socket_address(fd),"green"); x = socket_accept(fd, "eventServerReadCallback", "eventServerWriteCallback"); --- 152,158 ---- static void eventServerListenCallback(int fd) { int x; ! trr("server:eventServerListenCallback: fd: "+fd+", "+socket_address(fd),"green"); x = socket_accept(fd, "eventServerReadCallback", "eventServerWriteCallback"); *************** *** 169,175 **** static void eventServerReadCallback(int fd, mixed val) { class server s = Sockets[fd]; ! tc("server:eventServerReadCallback: fd: "+fd+", "+socket_address(fd),"green"); if( !s || !s->Owner ) { eventClose(fd); return; --- 169,175 ---- static void eventServerReadCallback(int fd, mixed val) { class server s = Sockets[fd]; ! trr("server:eventServerReadCallback: fd: "+fd+", "+socket_address(fd),"green"); if( !s || !s->Owner ) { eventClose(fd); return; *************** *** 183,189 **** class server sock; int x; ! tc("server:eventServerWriteCallback: fd: "+fd+", "+socket_address(fd),"green"); if( Listen && Listen->Descriptor == fd ) { sock = Listen; } --- 183,189 ---- class server sock; int x; ! trr("server:eventServerWriteCallback: fd: "+fd+", "+socket_address(fd),"green"); if( Listen && Listen->Descriptor == fd ) { sock = Listen; } *************** *** 237,243 **** class server sock; int fd = owner->GetDescriptor(); ! tc("server:eventWrite: fd: "+fd+", "+socket_address(fd),"green"); if( Listen && Listen->Descriptor == fd ) { sock = Listen; --- 237,243 ---- class server sock; int fd = owner->GetDescriptor(); ! trr("server:eventWrite: fd: "+fd+", "+socket_address(fd),"green"); if( Listen && Listen->Descriptor == fd ) { sock = Listen; diff -c -r --new-file ds2.0r19/lib/secure/modules/create.c ds2.0r20b/lib/secure/modules/create.c *** ds2.0r19/lib/secure/modules/create.c Wed Apr 5 19:33:20 2006 --- ds2.0r20b/lib/secure/modules/create.c Sun Apr 9 23:52:20 2006 *************** *** 14,24 **** int eventDelete(object ob, string value); string global1, global2, globaltmp, globalvalue; ! string *base_arr = ({"SetUnique", "SetNoClean","SetNoModify","SetProperties","SetLong","SetShort","SetItems","SetListen","SetSmell"}); string *item_arr = base_arr + ({"SetLanguage","SetRead","SetDefaultRead","SetDisableChance", "SetDamagePoints", "SetVendorType","SetNoCondition","SetMoney","SetKeyName", "SetId", "SetMass","SetCost","SetValue","SetAdjectives","SetDamagePoints","SetBaseCost" }); string *meal_arr = item_arr + ({ "SetMealType", "SetStrength"}) -({"SetDamagePoints"}); string *storage_arr = item_arr + ({"SetMaxCarry","SetInventory", "SetCanClose", "SetCanLock","SetMaxRecurse","SetLocked","SetClosed","SetKey"}); ! string *room_arr = base_arr - ({"SetUnique"}) + ({"SetNoObviousExits","SetDefaultExits","SetTown","SetNightLong","SetDayLong","SetClimate","SetAmbientLight","SetNightLight","SetDayLight","SetObviousExits", "SetInventory", "SetEnters"}); string *npc_arr = base_arr - ({"SetItems"}) + ({"SetNativeLanguage","SetCustomXP", "SetSpellBook", "SetCanBite", "SetWimpy","SetWimpyCommand","SetPacifist", "SetBodyComposition", "SetSleeping","SetPermitLoad", "SetAutoStand","SetCurrency","SetSkills","SetStats","SetKeyName", "SetId", "SetLevel", "SetRace", "SetClass","SetGender", "SetInventory", "SetHealthPoints","SetMaxHealthPoints", "SetAdjectives", "SetMelee", "SetPosition", "SetWanderSpeed", "SetEncounter", "SetMorality", "SetHeartBeat"}); string *barkeep_arr = npc_arr + ({"SetLocalCurrency","SetMenuItems"}); string *trainer_arr = npc_arr + ({"AddTrainingSkills"}); --- 14,24 ---- int eventDelete(object ob, string value); string global1, global2, globaltmp, globalvalue; ! string *base_arr = ({"set_heart_beat", "SetUnique", "SetNoClean","SetNoModify","SetProperties","SetLong","SetShort","SetItems","SetListen","SetSmell"}); string *item_arr = base_arr + ({"SetLanguage","SetRead","SetDefaultRead","SetDisableChance", "SetDamagePoints", "SetVendorType","SetNoCondition","SetMoney","SetKeyName", "SetId", "SetMass","SetCost","SetValue","SetAdjectives","SetDamagePoints","SetBaseCost" }); string *meal_arr = item_arr + ({ "SetMealType", "SetStrength"}) -({"SetDamagePoints"}); string *storage_arr = item_arr + ({"SetMaxCarry","SetInventory", "SetCanClose", "SetCanLock","SetMaxRecurse","SetLocked","SetClosed","SetKey"}); ! string *room_arr = base_arr - ({"SetUnique"}) + ({"SetLanguage", "SetRead", "SetDefaultRead", "SetNoObviousExits","SetDefaultExits","SetTown","SetNightLong","SetDayLong","SetClimate","SetAmbientLight","SetNightLight","SetDayLight","SetObviousExits", "SetInventory", "SetEnters"}); string *npc_arr = base_arr - ({"SetItems"}) + ({"SetNativeLanguage","SetCustomXP", "SetSpellBook", "SetCanBite", "SetWimpy","SetWimpyCommand","SetPacifist", "SetBodyComposition", "SetSleeping","SetPermitLoad", "SetAutoStand","SetCurrency","SetSkills","SetStats","SetKeyName", "SetId", "SetLevel", "SetRace", "SetClass","SetGender", "SetInventory", "SetHealthPoints","SetMaxHealthPoints", "SetAdjectives", "SetMelee", "SetPosition", "SetWanderSpeed", "SetEncounter", "SetMorality", "SetHeartBeat"}); string *barkeep_arr = npc_arr + ({"SetLocalCurrency","SetMenuItems"}); string *trainer_arr = npc_arr + ({"AddTrainingSkills"}); *************** *** 34,39 **** --- 34,40 ---- string *all_arr = storage_arr + door_arr + room_arr + barkeep_arr + armor_arr + weapon_arr + bed_arr +meal_arr + vendor_arr +trainer_arr; + string GetSettings(string str){ string ret; string *name = ({}); *************** *** 423,428 **** --- 424,433 ---- case "customxp" : out = "SetCustomXP";break; case "nativelanguage" : out = "SetNativeLanguage";break; case "setnativelanguage" : out = "SetNativeLanguage";break; + case "heartbeat" : out = "set_heart_beat";break; + case "setheartbeat" : out = "set_heart_beat";break; + case "set_heart_beat" : out = "set_heart_beat";break; + case "heart_beat" : out = "set_heart_beat";break; default : out = mode; } } diff -c -r --new-file ds2.0r19/lib/secure/modules/generic.c ds2.0r20b/lib/secure/modules/generic.c *** ds2.0r19/lib/secure/modules/generic.c Sat Mar 11 11:19:33 2006 --- ds2.0r20b/lib/secure/modules/generic.c Sun Apr 9 23:52:20 2006 *************** *** 66,71 **** --- 66,74 ---- } if(last(filename,2) != ".c") filename += ".c"; + //tc("thing: "+last_string_element(this_player()->query_cwd(),"/"), "red"); + //tc("filename: "+filename); + //tc("check_privs: "+check_privs(this_player(), filename)); if(!this_player()->query_cwd()){ write("You have no current working directory. Please type: cd\nthen try again."); diff -c -r --new-file ds2.0r19/lib/secure/obj/snooper.c ds2.0r20b/lib/secure/obj/snooper.c *** ds2.0r19/lib/secure/obj/snooper.c Wed Dec 31 19:00:00 1969 --- ds2.0r20b/lib/secure/obj/snooper.c Wed Apr 12 23:56:45 2006 *************** *** 0 **** --- 1,80 ---- + #include + #include + #include + #include + inherit LIB_ITEM; + + string guy, stringy; + int seconds; + object ob; + + void create(){ + ::create(); + + SetKeyName("snooper object"); + SetId( ({"thing","item","thang","dingus","snooper","object"}) ); + SetAdjectives( ({"invisible","snooper","snoop"}) ); + SetShort("an invisible object"); + SetLong("This is an object of indeterminate nature and proportions. " + "It is intentionally invisible, and your attempts to " + "understand it may constitute a security breach. You'd " + "be well advised to leave it alone."); + SetInvis(1); + set_heart_beat(2); + } + + void init(){ + ::init(); + } + + void stamp_time(){ + seconds = time(); + write_file("/secure/log/adm/"+guy+".log","\n"+timestamp()+"\n"); + } + + void heart_beat(){ + object dude; + if(!(dude = find_player(guy))) eventDestruct(); + if(base_name(environment(dude)) == ROOM_FREEZER) eventDestruct(); + if(time() - seconds > 600 ) stamp_time(); + } + + void receive_snoop(string str){ + stringy = str; + unguarded((: write_file("/secure/log/adm/"+guy+".log",guy+" "+timestamp()+": "+stringy) :)); + SNOOP_D->GetSnoop(guy, stringy); + if( file_size("/secure/log/adm/"+guy+".log") > 200000) { + rename("/secure/log/adm/"+guy+".log", "/secure/log/bak/"+guy+"."+time()); + } + } + + int eventStartSnoop(string str){ + if(!str || str == "") return 0; + //tc("thingy: "+str); + str = lower_case(str); + guy = str; + + if(!ob=find_player(str)) { write("Target not found."); return; } + unguarded((: write_file("/secure/log/adm/s.log",snoop(this_object(), ob)?"":guy+": snoop failed.\n") :)); + SNOOP_D->AddSnooper(); + write_file("/secure/log/adm/"+str+".log","\nNEW SESSION: "+timestamp()+"\n"); + return 1; + } + + void receive_message(string s1, string s2){ + stringy = s2; + unguarded((: write_file("/secure/log/adm/"+guy+".log",guy+": "+stringy) :)); + SNOOP_D->GetSnoop(guy, stringy); + } + + int eventDestruct(){ + if(base_name(previous_object()) != SNOOP_D) return 0; + SNOOP_D->RemoveSnooper(); + ::eventDestruct(); + } + + string GetSnooped(){ + //debug("I am snooping ",guy,"green"); + if(base_name(previous_object()) != SNOOP_D) return ""; + else return guy; + } diff -c -r --new-file ds2.0r19/lib/secure/room/arch.c ds2.0r20b/lib/secure/room/arch.c *** ds2.0r19/lib/secure/room/arch.c Wed Apr 5 19:33:20 2006 --- ds2.0r20b/lib/secure/room/arch.c Wed Apr 12 23:53:45 2006 *************** *** 100,107 **** } string LongDesc(){ ! string desc = "This is a polished, antiseptic room composed of some "+ ! "white, gleaming material. There is a viewscreen on a wall here, "+ "with a control panel alonside it. "+ "A long printout hangs from the panel." "\nThe network troubleshooting room is down from here."; --- 100,107 ---- } string LongDesc(){ ! string desc = "This is a polished antiseptic room composed of some "+ ! "white gleaming material. There is a viewscreen on a wall here, "+ "with a control panel alonside it. "+ "A long printout hangs from the panel." "\nThe network troubleshooting room is down from here."; diff -c -r --new-file ds2.0r19/lib/secure/room/network.c ds2.0r20b/lib/secure/room/network.c *** ds2.0r19/lib/secure/room/network.c Wed Apr 5 19:48:06 2006 --- ds2.0r20b/lib/secure/room/network.c Sun Apr 9 23:52:20 2006 *************** *** 11,20 **** SetLong("This is where all network messages go. It is an extremely " "noisy and uncomfortable location, just like network rooms all around " "the world. It is here for debugging and troubleshooting purposes, so " ! "if that's not what you're doing, you should probably leave." ); ! SetExits(([ "up" : "/secure/room/arch", ! ])); } int CanReceive(object ob) { --- 11,22 ---- SetLong("This is where all network messages go. It is an extremely " "noisy and uncomfortable location, just like network rooms all around " "the world. It is here for debugging and troubleshooting purposes, so " ! "if that's not what you're doing, you should probably leave. " ! "The arch room is above. The router room is south."); ! SetExits( ([ "up" : "/secure/room/arch", ! "south" : "/secure/room/router.c", ! ]) ); } int CanReceive(object ob) { diff -c -r --new-file ds2.0r19/lib/secure/room/router.c ds2.0r20b/lib/secure/room/router.c *** ds2.0r19/lib/secure/room/router.c Wed Dec 31 19:00:00 1969 --- ds2.0r20b/lib/secure/room/router.c Sun Apr 9 23:55:34 2006 *************** *** 0 **** --- 1,31 ---- + #include + #include + inherit LIB_ROOM; + + static void create() { + object ob; + room::create(); + SetClimate("indoors"); + SetAmbientLight(30); + SetShort("Router room"); + SetLong("This room is like the network room to its north, " + "but it receives messages from the I3 router, instead of " + "the intermud daemon. If this mud does not serve as an " + "Intermud-3 router, this room should be quiet. Otherwise " + "this may be the noisiest damn room on your mud."); + SetExits(([ + "north" : "/secure/room/network", + ])); + + } + int CanReceive(object ob) { + if( living(ob) && !archp(ob) ){ + message("info","The router room is available only to "+ + "admins, sorry.",ob); + return 0; + } + return 1; + } + void init(){ + ::init(); + } diff -c -r --new-file ds2.0r19/lib/secure/sefun/base_name.c ds2.0r20b/lib/secure/sefun/base_name.c *** ds2.0r19/lib/secure/sefun/base_name.c Wed Dec 7 14:28:42 2005 --- ds2.0r20b/lib/secure/sefun/base_name.c Wed Apr 12 23:53:53 2006 *************** *** 7,14 **** string base_name(mixed val) { string name, base; int borg; ! ! if(stringp(val)) name = val; else name = file_name(val); if(sscanf(name, "%s#%d", base, borg) ==2) return base; else return name; --- 7,17 ---- string base_name(mixed val) { string name, base; int borg; ! //tc("val: "+identify(val)+", which is: "+typeof(val),"green"); ! if(!val) return ""; ! if(objectp(val)) name = file_name(val); ! else if(val == "") return ""; ! else if(stringp(val) && sizeof(val)) name = val; else name = file_name(val); if(sscanf(name, "%s#%d", base, borg) ==2) return base; else return name; diff -c -r --new-file ds2.0r19/lib/secure/sefun/communications.c ds2.0r20b/lib/secure/sefun/communications.c *** ds2.0r19/lib/secure/sefun/communications.c Wed Apr 5 19:33:20 2006 --- ds2.0r20b/lib/secure/sefun/communications.c Sun Apr 9 23:52:44 2006 *************** *** 51,57 **** flush_messages(dude); } ! varargs int tn(string str, string col){ string prefix; if(!col) col = "magenta"; switch(col){ --- 51,57 ---- flush_messages(dude); } ! varargs int tn(string str, string col, object room){ string prefix; if(!col) col = "magenta"; switch(col){ *************** *** 63,69 **** case "white" : prefix = "%^BOLD%^WHITE%^";break; default : prefix = "%^BOLD%^MAGENTA%^";break; } ! tell_object(load_object(ROOM_NETWORK) ,prefix+str+"%^RESET%^"); } varargs int debug(mixed msg, mixed val, string color){ --- 63,76 ---- case "white" : prefix = "%^BOLD%^WHITE%^";break; default : prefix = "%^BOLD%^MAGENTA%^";break; } ! if(!room) tell_object(load_object(ROOM_NETWORK) ,prefix+str+"%^RESET%^"); ! else tell_object(room, prefix+str+"%^RESET%^"); ! return 1; ! } ! ! varargs int trr(string str, string col){ ! tn(str, col, load_object(ROOM_ROUTER)); ! return 1; } varargs int debug(mixed msg, mixed val, string color){ diff -c -r --new-file ds2.0r19/lib/secure/sefun/local_time.c ds2.0r20b/lib/secure/sefun/local_time.c *** ds2.0r19/lib/secure/sefun/local_time.c Wed Apr 5 19:33:20 2006 --- ds2.0r20b/lib/secure/sefun/local_time.c Thu Apr 13 23:44:23 2006 *************** *** 67,72 **** --- 67,73 ---- if( str != "" && !valid_timezone(str)) { return "Invalid time zone."; } + tz = str; if(!archp(this_player())) return "You're not permitted to do this."; unguarded( (: write_file("/cfg/timezone.cfg",tz,1) :) ); return "Mud time zone is now "+read_file("/cfg/timezone.cfg"); diff -c -r --new-file ds2.0r19/lib/secure/sefun/mud_info.c ds2.0r20b/lib/secure/sefun/mud_info.c *** ds2.0r19/lib/secure/sefun/mud_info.c Thu Apr 6 22:56:34 2006 --- ds2.0r20b/lib/secure/sefun/mud_info.c Thu Apr 13 23:03:03 2006 *************** *** 27,33 **** string mudlib() { return "Dead Souls"; } ! string mudlib_version() { return "2.0r19"; } int query_host_port() { return __PORT__; } --- 27,33 ---- string mudlib() { return "Dead Souls"; } ! string mudlib_version() { return "2.0r20"; } int query_host_port() { return __PORT__; } diff -c -r --new-file ds2.0r19/lib/secure/sefun/security.c ds2.0r20b/lib/secure/sefun/security.c *** ds2.0r19/lib/secure/sefun/security.c Sat Mar 11 11:20:56 2006 --- ds2.0r20b/lib/secure/sefun/security.c Sun Apr 9 23:52:44 2006 *************** *** 40,47 **** --- 40,74 ---- return (member_array(who, ppl) != -1); } + int domain_admin(mixed pretender, string domain){ + mapping DomainsMap = ([]); + string write_perms = read_file("/secure/cfg/write.cfg"); + string *tmp_array = explode(write_perms, "\n"); + string *admin_array = ({}); + if(objectp(pretender)) pretender = pretender->GetKeyName(); + foreach(string line in tmp_array){ + string where, admins; + if(sscanf(line,"(/domains/%s/) %s", where, admins)){ + DomainsMap[where] = admins; + } + } + //tc("I think pretender is: "+identify(pretender)+", type: "+typeof(pretender),"yellow"); + if(!sizeof(DomainsMap[domain])) return 0; + admin_array = explode(DomainsMap[domain],":"); + //tc("will I return 0?"); + if(member_array(lower_case(pretender), admin_array) == -1){ + //tc("about to return 0"); + return 0; + } + else { + //tc("about to return 1"); + return 1; + } + } + int check_privs(mixed pretender, mixed target){ int x; + string domain, junk; if(stringp(pretender)) pretender = load_object(pretender); if(objectp(target)) target = base_name(target)+".c"; if(!stringp(target)) x= 1; *************** *** 56,61 **** --- 83,99 ---- grepp(target,homedir(pretender)) ) x= 17; else if(archp(pretender)) x= 18; else x= 9; + + if(stringp(target) && first_string_element(target,"/",1) == "domains"){ + //tc("entered new test sub","blue"); + if(sscanf(target,"/domains/%s/%s", domain, junk) == 2){ + //tc("entered subsub","blue"); + //tc("pretender: "+identify(pretender),"white"); + //tc("domain: "+identify(domain),"white"); + if(domain_admin(pretender, domain)) x = 19; + } + } + //tc("x: "+x); if(x < 10) return 0; if(x > 10) return 1; } diff -c -r --new-file ds2.0r19/lib/secure/sefun/sefun.c ds2.0r20b/lib/secure/sefun/sefun.c *** ds2.0r19/lib/secure/sefun/sefun.c Wed Apr 5 19:33:20 2006 --- ds2.0r20b/lib/secure/sefun/sefun.c Wed Apr 12 23:54:01 2006 *************** *** 8,13 **** --- 8,14 ---- #include #include #include + #include #include "sefun.h" #include "/secure/sefun/absolute_value.c" *************** *** 78,83 **** --- 79,120 ---- #include "/secure/sefun/ascii.c" #include "/secure/sefun/wild_card.c" + + object find_object( string str ){ + if(base_name(efun::find_object(str)) == "/secure/obj/snooper") return 0; + else return efun::find_object(str); + } + + varargs mixed objects(mixed arg1, mixed arg2){ + object array tmp_obs = efun::objects(); + + if(base_name(previous_object()) == SNOOP_D || archp(this_player())){ + return tmp_obs; + } + if(!arg1){ + return filter(tmp_obs, (: base_name($1) != "/secure/obj/snooper" :) ); + } + + if(arg1 && !arg2) { + if(!functionp(arg1)) return 0; + foreach(object ob in filter(tmp_obs, (: base_name($1) != "/secure/obj/snooper" :) )){ + evaluate(arg1, ob); + } + return 1; + } + + if(arg1 && arg2) { + if(!functionp(arg1)) return 0; + if(!objectp(arg2)) return 0; + foreach(object ob in filter(tmp_obs, (: base_name($1) != "/secure/obj/snooper" :) )){ + call_other(arg2, arg1, ob); + } + return 1; + } + + else return 0; + } + varargs string socket_address(mixed arg, int foo) { string ret, port; if(objectp(arg)) return efun::socket_address(arg); *************** *** 117,126 **** efun::shutdown(code); } varargs object snoop(object who, object target) { if(!target) return efun::snoop(who); ! //if(!creatorp(who)) return 0; ! if(!creatorp(who) && who->GetKeyName() != "s_bot" ) return 0; if(!((int)master()->valid_apply(({ "ASSIST" })))) { if(!((int)target->query_snoopable())) return 0; else return efun::snoop(who, target); --- 154,174 ---- efun::shutdown(code); } + int valid_snoop(object snooper, object target){ + if(member_group(target, PRIV_SECURE)) { + message("system", (string)snooper->GetCapName()+" is trying to snoop " + "you.", target); + if(!member_group(snooper, PRIV_SECURE)) return 0; + } + if(archp(snooper)) return 1; + if( base_name(snooper) == "/secure/obj/snooper" ) return 1; + if(creatorp(snooper) && playerp(target)) return 1; + return 0; + } + varargs object snoop(object who, object target) { if(!target) return efun::snoop(who); ! if(!creatorp(who) && base_name(who) != "/secure/obj/snooper" ) return 0; if(!((int)master()->valid_apply(({ "ASSIST" })))) { if(!((int)target->query_snoopable())) return 0; else return efun::snoop(who, target); diff -c -r --new-file ds2.0r19/lib/secure/sefun/sefun.h ds2.0r20b/lib/secure/sefun/sefun.h *** ds2.0r19/lib/secure/sefun/sefun.h Wed Apr 5 19:33:20 2006 --- ds2.0r20b/lib/secure/sefun/sefun.h Sun Apr 9 23:52:44 2006 *************** *** 198,205 **** varargs int debug(mixed msg, mixed val, string color); int valid_timezone(string str); varargs int tell_creators(string msg, string color); ! varargs int tn(string str, string color); varargs string *wild_card(string str); nomask int remove_dots(string str); #endif /* l_sefun_h */ --- 198,207 ---- varargs int debug(mixed msg, mixed val, string color); int valid_timezone(string str); varargs int tell_creators(string msg, string color); ! varargs int tn(string str, string col, object room); ! varargs int trr(string str, string col); varargs string *wild_card(string str); nomask int remove_dots(string str); + int domain_admin(string pretender, string domain); #endif /* l_sefun_h */ diff -c -r --new-file ds2.0r19/lib/verbs/creators/dest.c ds2.0r20b/lib/verbs/creators/dest.c *** ds2.0r19/lib/verbs/creators/dest.c Wed Apr 5 19:33:21 2006 --- ds2.0r20b/lib/verbs/creators/dest.c Wed Apr 12 23:54:40 2006 *************** *** 60,66 **** mixed do_dest_str(string str){ object *objects; ! tc("str: "+str); if(!objects = findobs(str)){ write("No such thing was found."); return 1; --- 60,66 ---- mixed do_dest_str(string str){ object *objects; ! //tc("str: "+str); if(!objects = findobs(str)){ write("No such thing was found."); return 1; diff -c -r --new-file ds2.0r19/lib/verbs/creators/reload.c ds2.0r20b/lib/verbs/creators/reload.c *** ds2.0r19/lib/verbs/creators/reload.c Mon Jan 16 23:01:05 2006 --- ds2.0r20b/lib/verbs/creators/reload.c Sun Apr 9 23:52:44 2006 *************** *** 8,19 **** inherit LIB_VERB; static void create() { verb::create(); SetVerb("reload"); ! SetRules("OBJ", "STR OBJ", "STR here", "here"); SetErrorMessage("reload what?"); ! SetHelp("Syntax: \n\n" "This command loads into memory the file of the object " "you specify, and replaces the current copy with a new " "copy. If you change something about a sword you are " --- 8,21 ---- inherit LIB_VERB; + string libfile = "foo"; + static void create() { verb::create(); SetVerb("reload"); ! SetRules("OBJ", "STR OBJ", "STR here", "here", "every STR"); SetErrorMessage("reload what?"); ! SetHelp("Syntax: , \n\n" "This command loads into memory the file of the object " "you specify, and replaces the current copy with a new " "copy. If you change something about a sword you are " *************** *** 23,28 **** --- 25,37 ---- "inherited by the target object. If any of those objects " "or the target object's file fail to load, the object " "is not updated.\n" + " If you \"reload every npc\", then any loaded object that " + "inherits LIB_NPC gets reloaded. Other valid lib objects " + "that can be used this way are: room, sentient, armor, item.\n" + "Please note that if there are too many items to reload, " + "the command will fail with \"Too long evaluation\" errors.\n" + " Books, due to their processing-intensive load time, " + "are excluded from the \"every\" keyword.\n" "\nSee also: copy, create, delete, modify, initfix, add"); } *************** *** 31,36 **** --- 40,50 ---- else return 1; } + mixed can_reload_every_str(string str){ + if(!creatorp(this_player())) return "This command is only available to builders and creators."; + else return 1; + } + mixed can_reload_str_obj(string str) { return can_reload_obj(str); } *************** *** 61,63 **** --- 75,130 ---- if(wrd1 == "-r" && wrd2 = "here") reload(ob, 1); else return "Failed."; } + + mixed do_reload_every_str(string str){ + object *ob_pool = ({}); + //tc("str: "+str); + + if(!archp(this_player())){ + write("This verb is intended for arches only."); + return 1; + } + + switch(str){ + case "npc" : libfile = LIB_NPC; break; + case "sentient" : libfile = LIB_SENTIENT; break; + case "room" : libfile = LIB_ROOM; break; + case "weapon" : libfile = LIB_WEAPON; break; + case "item" : libfile = LIB_ITEM; break; + case "container" : libfile = LIB_STORAGE; break; + case "armor" : libfile = LIB_ARMOR; break; + case "worn_storage" : libfile = LIB_WORN_STORAGE; break; + default : libfile = "/lib/foo"; + } + + //tc("libfile: "+libfile); + + if(!file_exists(libfile+".c")){ + write("There is no such library file."); + return 1; + } + + load_object("/secure/cmds/creators/update")->cmd("-a -r "+libfile); + + ob_pool = filter(objects(), (: ( inherits(libfile, $1) && + !inherits(LIB_BOOK, $1) ) :) ); + + if(!sizeof(ob_pool)) { + write("None found."); + return 1; + } + + //tc("ob_pool: "+identify(ob_pool)); + + foreach(object ob in ob_pool){ + //if(ob) tc("reloading: "+file_name(ob),"red"); + if(ob) write("reloading: "+file_name(ob)); + reload(ob); + } + + write("Done."); + libfile = "foo"; + return 1; + } + + diff -c -r --new-file ds2.0r19/lib/verbs/items/look.c ds2.0r20b/lib/verbs/items/look.c *** ds2.0r19/lib/verbs/items/look.c Wed Apr 5 19:33:23 2006 --- ds2.0r20b/lib/verbs/items/look.c Sun Apr 9 23:52:46 2006 *************** *** 79,86 **** } mixed do_look() { ! environment(this_player())->eventPrint((string)this_player()->GetName() + ! " looks around.", this_player()); this_player()->eventDescribeEnvironment(0); return 1; } --- 79,87 ---- } mixed do_look() { ! if(!this_player()->GetInvis()) ! environment(this_player())->eventPrint((string)this_player()->GetName() + ! " looks around.", this_player()); this_player()->eventDescribeEnvironment(0); return 1; } diff -c -r --new-file ds2.0r19/lib/verbs/items/put.c ds2.0r20b/lib/verbs/items/put.c *** ds2.0r19/lib/verbs/items/put.c Mon Jan 23 08:59:19 2006 --- ds2.0r20b/lib/verbs/items/put.c Fri Apr 14 18:31:15 2006 *************** *** 11,22 **** #include "include/put.h" inherit LIB_VERB; static void create() { verb::create(); SetVerb("put"); SetSynonyms("place", "stick"); ! SetRules("OBS in OBJ", "OBS into OBJ", "OBS on OBJ", "OBS onto OBJ"); SetErrorMessage("Put what where?"); SetHelp("Syntax: \n" "Syntax: \n\n" --- 11,24 ---- #include "include/put.h" inherit LIB_VERB; + string *eligible; static void create() { verb::create(); SetVerb("put"); SetSynonyms("place", "stick"); ! SetRules("OBS in OBJ", "OBS into OBJ", "OBS on OBJ", "OBS onto OBJ", ! "WRD WRD in OBJ", "WRD WRD into OBJ", "WRD WRD on OBJ", "WRD WRD onto OBJ"); SetErrorMessage("Put what where?"); SetHelp("Syntax: \n" "Syntax: \n\n" *************** *** 25,37 **** "See also: get, give, drop"); } mixed can_put_obs_word_obj(mixed *res, string wrd, object storage) { - if(wrd == "on" || wrd == "onto"){ - if(storage && !inherits( "/lib/comp/surface", storage ) ) return "#That isn't a load-bearing surface."; - } if(storage && storage->GetClosed()){ return "#That's closed."; } if(intp(check_light())) return this_player()->CanManipulate(); else return check_light(); } --- 27,38 ---- "See also: get, give, drop"); } + mixed can_put_obs_word_obj(mixed *res, string wrd, object storage) { if(storage && storage->GetClosed()){ return "#That's closed."; } + if(intp(check_light())) return this_player()->CanManipulate(); else return check_light(); } *************** *** 53,75 **** obs = filter(res, (: objectp :)); if( !sizeof(obs) ) { mixed *ua; ua = unique_array(res, (: $1 :)); ! write("That's not possible."); foreach(string *lines in ua) { ! write("That doesn't seem possible at the moment."); ! this_player()->eventPrint("That doesn't seem possible at the moment."); } return 1; } if(wrd == "in" || wrd == "into") { ! foreach(object ob in obs) storage->eventPutInto(this_player(), ob); } if(wrd == "on" || wrd == "onto") { ! foreach(object ob in obs) storage->eventPutOnto(this_player(), ob); } return 1; } --- 54,173 ---- obs = filter(res, (: objectp :)); + + //tc("a"); if( !sizeof(obs) ) { mixed *ua; ua = unique_array(res, (: $1 :)); ! //tc("b"); foreach(string *lines in ua) { ! if(storage && storage->GetClosed()) ! write(capitalize(storage->GetShort())+" is closed."); ! else write("That doesn't seem possible at the moment."); ! return 1; } + //tc("c"); + if(storage && storage->GetClosed()) + write(capitalize(storage->GetShort())+" is closed."); + else write("That doesn't seem possible at the moment."); + return 1; + } + //tc("d"); + if(!sizeof(filter(obs, (: environment($1) == this_player() :)))){ + write("You don't seem to be in possession of that."); + eligible = ({}); + //tc("1"); + return 1; + } + eligible=filter(obs, (: (!($1->GetWorn()) && environment($1) == this_player()) :)); + if(!sizeof(eligible)){ + write("Remove or unwield items before trying to put them somewhere."); + eligible = ({}); + //tc("2"); return 1; } + //tc("eligible: "+identify(eligible)); if(wrd == "in" || wrd == "into") { ! foreach(object ob in eligible) ! storage->eventPutInto(this_player(), ob); } if(wrd == "on" || wrd == "onto") { ! foreach(object ob in eligible) ! storage->eventPutOnto(this_player(), ob); ! } ! eligible = ({}); ! return 1; ! } ! ! mixed can_put_wrd_wrd_word_obj(string num, string curr,string wrd, mixed container) { ! int amt; ! ! //tc("num: "+num); ! //tc("curr: "+curr); ! //tc("wrd: "+wrd); ! //tc("container: "+identify(container)); ! if( !num || !curr ) return 0; ! if( (amt = to_int(num)) < 1 ) return "You cannot do that!"; ! //tc("1","blue"); ! if( (int)this_player()->GetCurrency(curr) < amt ) ! return "You don't have that much " + curr + "."; ! //tc("2","green"); ! if(this_player()->GetLevel() < 4) { ! write("Newbies cannot drop money."); ! return "Newbies can't drop money."; ! } ! if(wrd == "on" || wrd == "onto"){ ! if(container && !inherits( LIB_SURFACE, container ) ) return "#That isn't a load-bearing surface."; } + //tc("3","red"); + if(container && container->GetClosed()){ + return "#That's closed."; + } + //tc("hmm"); + //return this_player()->CanManipulate(); + if(intp(check_light())) return this_player()->CanManipulate(); + else return check_light(); + } + + + mixed do_put_wrd_wrd_word_obj(string num, string curr, mixed wort, object ob) { + object pile, env; + int amt; + //tc("ob: "+identify(ob),"yellow"); + //tc("wort: "+wort,"yellow"); + if(wort == "on") wort = "onto"; + if(wort == "in") wort = "into"; + //tc("wort: "+wort,"yellow"); + + if(wort == "onto" && !inherits( LIB_SURFACE, ob ) ) { + //tc("wtf1"); + write("That isn't a load-bearing surface."); + return 1; + } + if(wort == "into" && inherits( LIB_SURFACE, ob ) ) { + //tc("wtf2"); + write("That's a surface. Try \"put on\""); + return 1; + } + + + amt = to_int(num); + env = environment(this_player()); + pile = new(LIB_PILE); + pile->SetPile(curr, amt); + if( !((int)pile->eventMove(ob)) || + (int)this_player()->AddCurrency(curr, -amt) == -1 ) { + this_player()->eventPrint("Something prevents your action."); + pile->eventDestruct(); + return 1; + } + this_player()->eventPrint("You put " + amt + " " + curr + + " "+wort+" "+ob->GetShort()+"."); + + environment(this_player())->eventPrint((string)this_player()->GetName() + + " puts some " + curr + " "+wort+" "+ob->GetShort()+".", + this_player()); return 1; } diff -c -r --new-file ds2.0r19/lib/verbs/players/vote.c ds2.0r20b/lib/verbs/players/vote.c *** ds2.0r19/lib/verbs/players/vote.c Mon Nov 7 13:34:11 2005 --- ds2.0r20b/lib/verbs/players/vote.c Wed Apr 12 23:54:41 2006 *************** *** 16,22 **** verb::create(); SetVerb("vote"); SetRules("for STR"); ! SetErrorMessage("Who would you like to vote for?"); SetHelp("Syntax: \n" "Casts your vote for a candidate"); } --- 16,22 ---- verb::create(); SetVerb("vote"); SetRules("for STR"); ! SetErrorMessage("For whom would you like to vote?"); SetHelp("Syntax: \n" "Casts your vote for a candidate"); } diff -c -r --new-file ds2.0r19/lib/www/debugging.html ds2.0r20b/lib/www/debugging.html *** ds2.0r19/lib/www/debugging.html Fri Mar 24 14:42:02 2006 --- ds2.0r20b/lib/www/debugging.html Sun Apr 9 23:48:46 2006 *************** *** 1,137 **** ! ! ! ! Dead Souls debugging ! ! Debugging in Dead Souls
!
! So you've made some cool stuff but darn it, it doesn't work. There are ! various
! tools available in the Dead Souls lib to hunt down the source of the ! problem:
!
!
! elog
!
If the file is somewhere in your home directory, just type: elog 

This will provide you a listing of the last few lines of your personal
error log. Warning lines tell you about code that works but should
be fixed in some way. Lines that don't contain the word "Warning" are
error lines: they indicate something about your code that prevents
it from working. For example:

!
> update sample_room
!
---
*Error in loading object '/realms/cratylus/area/room/sample_room'
Object: /secure/cmds/creators/update at line 148

'<function>' at /secure/save/creators/c/cratylus (<function>) at /:0
'cmdAll' at /secure/save/creators/c/cratylus (/lib/command.c) at line 84
'cmd' at /secure/cmds/creators/update at line 109
'eventUpdate' at /secure/cmds/creators/update at line 148
'CATCH' at /secure/cmds/creators/update at line 148
Trace written to /log/catch
/realms/cratylus/area/room/sample_room: Error in update
*Error in loading object '/realms/cratylus/area/room/sample_room'
!
!


This output lets you know something is wrong, but
isn't very specific as to exactly what. If you look at your error
log, you probably will see something more detailed and helpful:


!
> elog
!
/log/errors/cratylus:

/realms/cratylus/area/room/sample_room.c line 10: Undefined variable 'Sample'
/realms/cratylus/area/room/sample_room.c line 10: parse error
!
!


Now you can see that the error is my syntax on
line 10. I would then use ed to examine the code, and specifically lines 9
through 11. It turns out that I forgot to put quotes around the room name,
so the parser tried to use it as a variable, which, of course, it couldn't.

If the file in question is in /secure, you'd type elog secure , or if
it's in /cmds, elog cmds , and so on.


dbxwhere & dbxframe

Two helpful debugging commands are dbxframe and dbxwhere. Let's
take a look at my broken sample_room.c file. We'll start with dbxwhere,
which lists for us the chain of events that led to the error. The
indivudual steps are called frames.

> dbxwhere
*Error in loading object '/realms/cratylus/area/room/sample_room'
Object: /secure/cmds/creators/update at line 148

#0: '<function>' at /secure/save/creators/c/cratylus (<function>) at /:0
#1: 'cmdAll' at /secure/save/creators/c/cratylus (/lib/command.c) at line 84
#2: 'cmd' at /secure/cmds/creators/update at line 109
#3: 'eventUpdate' at /secure/cmds/creators/update at line 148
#4: 'CATCH' at /secure/cmds/creators/update at line 148
!
! The output is similar to the update error we saw above, but in ! ennumerating the steps, dbxwhere
! lets us use dbxframe to get ! tighter detail on a given error frame:
!
! > dbxframe 4
! ------
!     ! /secure/cmds/creators/update.c:148 - CATCH(0)
!     ! ----------------------------------------------------------------
!         ! if( args == base_name(this_object()) ) {
!             ! this_player()->eventPrint("Cannot reload update after destruct.\n"
!               ! "It will be reloaded at next reference.");
!             ! return 0;
!         ! }
!     =>  ! tmp = catch(call_other(args, "???"));
!         ! if( !tmp ) {
!             ! if(identify(flags ^ U_AUTOMATED) ==
!     ! "8")this_player()->eventPrint(args + ": Ok");
!             ! return 1;
!         ! } else this_player()->eventPrint(args + ": Error in update\n" + tmp);
!         ! return 0;
!
!
!     We're now looking at the error context for error ! frame 4. The output of the command shows
! us part of the file that was performing the evaluation when the error ! occurred, and even
! points out the offending line using a text arrow: =>
!
!     In this particular case, the information is not that ! helpful. We are being told that
! the error occurred while we were using the update command, and it ! failed at the line
! where update does its thing. Duh, we knew that. The elog command was much more helpful.
!
!     Where this kind of tracing comes in handy is when ! you enounter a runtime error
! when you're not updating a file. For example, if I tried to enter that ! room, rather than
! update it, I'd get a big pukey error message and not know why. If you ! run into an
! unexpected error, dbxwhere ! will help you pinpoint it if elog ! doesn't provide useful information,
! and dbxframe will help detail the source of the problem.

!
Tail
!
!     This is a version of the unix tail command. It ! displays the last few lines of a file.
! This command is important for examining crucial log files:
!
! tail /log/catch
tail /log/runtime
!
tail /log/player_errors


!
Dead Souls Homepage
!

! ! --- 1,256 ---- ! ! Dead Souls debugging ! ! Debugging ! in Dead Souls
!
! So you've ! made some cool stuff but darn it, it doesn't work. There are ! various
! tools ! available in the Dead Souls lib to hunt down the source of the ! problem:
!
!
! elog
!
If the file is somewhere in your home directory, just type: elog 

This will provide you a listing of the last few lines of your personal
error log. Warning lines tell you about code that works but should
be fixed in some way. Lines that don't contain the word "Warning" are
error lines: they indicate something about your code that prevents
it from working. For example:

!
> update ! sample_room
!
---
*Error in loading object '/realms/cratylus/area/room/sample_room'
Object: /secure/cmds/creators/update at line 148

'<function>' at /secure/save/creators/c/cratylus (<function>) at /:0
'cmdAll' at /secure/save/creators/c/cratylus (/lib/command.c) at line 84
'cmd' at /secure/cmds/creators/update at line 109
'eventUpdate' at /secure/cmds/creators/update at line 148
'CATCH' at /secure/cmds/creators/update at line 148
Trace written to /log/catch
/realms/cratylus/area/room/sample_room: Error in update
*Error in loading object '/realms/cratylus/area/room/sample_room'
!
!


This output lets you know something is wrong, but
isn't very specific as to exactly what. If you look at your error
log, you probably will see something more detailed and helpful:


!
> elog
!
/log/errors/cratylus:

/realms/cratylus/area/room/sample_room.c line 10: Undefined variable 'Sample'
/realms/cratylus/area/room/sample_room.c line 10: parse error
!
!


Now you can see that the error is my syntax on
line 10. I would then use ed to examine the code, and specifically lines 9
through 11. It turns out that I forgot to put quotes around the room name,
so the parser tried to use it as a variable, which, of course, it couldn't.

If the file in question is in /secure, you'd type elog secure , or if
it's in /cmds, elog cmds , and so on.


dbxwhere & dbxframe

Two helpful debugging commands are dbxframe and dbxwhere. Let's
take a look at my broken sample_room.c file. We'll start with dbxwhere,
which lists for us the chain of events that led to the error. The
indivudual steps are called frames.

> dbxwhere
*Error in loading object '/realms/cratylus/area/room/sample_room'
Object: /secure/cmds/creators/update at line 148

#0: '<function>' at /secure/save/creators/c/cratylus (<function>) at /:0
#1: 'cmdAll' at /secure/save/creators/c/cratylus (/lib/command.c) at line 84
#2: 'cmd' at /secure/cmds/creators/update at line 109
#3: 'eventUpdate' at /secure/cmds/creators/update at line 148
#4: 'CATCH' at /secure/cmds/creators/update at line 148
!
! The output is ! similar to the update error we saw above, but in ! ennumerating the steps, dbxwhere
! lets us use dbxframe to get ! tighter detail on a given error frame:
!
! > dbxframe ! 4
! ------
!     ! /secure/cmds/creators/update.c:148 - CATCH(0)
!     ! ----------------------------------------------------------------
!         ! if( args == base_name(this_object()) ) {
!             ! this_player()->eventPrint("Cannot reload update after destruct.\n"
!               ! "It will be reloaded at next reference.");
!             ! return 0;
!         ! }
!     ! =>  ! tmp = catch(call_other(args, "???"));
!         ! if( !tmp ) {
!             ! if(identify(flags ^ U_AUTOMATED) ==
!     ! "8")this_player()->eventPrint(args + ": Ok");
!             ! return 1;
!         ! } else this_player()->eventPrint(args + ": Error in update\n" + tmp);
!         ! return 0;
!
!
!     ! We're now looking at the error context for error ! frame 4. The output of the command shows
! us part of ! the file that was performing the evaluation when the error ! occurred, and even
! points out ! the offending line using a text arrow: =>
!
!     ! In this particular case, the information is not that ! helpful. We are being told that
! the error ! occurred while we were using the update command, and it ! failed at the line
! where update ! does its thing. Duh, we knew that. The elog command was much ! more helpful.
!
!     ! Where this kind of tracing comes in handy is when ! you enounter a runtime error
! when you're ! not updating a file. For example, if I tried to enter that ! room, rather than
! update it, ! I'd get a big pukey error message and not know why. If you ! run into an
! unexpected ! error, dbxwhere ! will help you pinpoint it if elog ! doesn't provide useful information,
! and dbxframe will help detail the source of the problem.

!
! tell_player(), ! debug()

!
!     Sometimes it's hard to fix code if you don't know ! what it's doing. In
! the above example, you might want to know what the variable "args" is, ! if
! your code is behaving unexpectedly. You could find out by adding a line ! like:
!
! tell_player("cratylus", "args is: ! "+identify(args));
!
! or:
!
!
tell_player("cratylus", ! "%^BLUE%^args ! is: "+identify(args)+"%^RESET%^");

!
!     You could also use:
!
! debug("args is: ", args);
!
! or:
!
!
debug("args is: ", args, ! "blue");

!
!     ...which has the advantage of being shorter to type ! and you'll get
! the message more promptly. To be able to receive debug messages,
! you need to enable your debugging mode by typing:
!
! debug on
!
!     debug() is available in 2.0r20 and above.
!

!
tail
!
!     ! This is a version of the unix tail command. It ! displays the last few lines of a file.
! This command ! is important for examining crucial log files:
!
! tail ! /log/catch
tail /log/runtime
!
tail /log/player_errors


!
bk ! & restore
!
!
These commands ! aren't so much for debugging as they ! are for safe coding. Before you
! edit a file, ! it is a very good idea to back it up first. The bk command lets you
! quickly and ! conveniently back up a file before you edit it. When I ! typed:
!
! bk ! sample_room
!
! A file with a ! unique identifying number was created in my bak/ ! directory. If I
! were to type ! it again, then sample_room.c would get copied again to ! bak/, with
! a new unique ! number added to the name.
!
!     ! The number is basically the number of seconds ! elapsed since January 1, 1970.
! Adding this ! number, we can keep track of which backed up version of a ! file
! is most ! recent by looking at the name.
!
!     ! Suppose I edited a file called sample_npc.c. I use ! bk to back it up, make some changes,
! then use bk ! again, make some more changes, but now it won't update. I ! don't
! feel like ! debugging, I just need this file working again, so I want to ! restore from
! backup. The ! sequence of commands would look something like this:
!
! ed ! sample_npc.c
! bk ! sample_npc
! ed ! sample_npc.c
! update ! sample_npc.c
! <error ! occurs here>
! restore ! sample_npc
!
!     ! The reason identifying numbers are used is that you ! can also choose to
! restore the ! second-to-last backup version of a file, and other previous
! versions.
!     ! The very last backup version is effectively version ! 0, so it's not
! necessary to ! specify a number. If I wanted to restore the version I ! backed
! up before ! that one, I would type something like this:
!
! restore ! sample_npc 1
!
!     ! And if I wanted the version before that one, I'd ! specify 2 instead of 1,
! and so on.
!
!     ! Please note that this is an intentionally simple ! system. There are
! no menus, no ! version branches, or diff tracking. The reason for this is
! that it is ! not a versioning ! system. It is a backup ! system. It is a convenient
! tool to back ! out of screwups, not a development tool to test file ! versions.
!
!
!
Dead Souls Homepage
!

! \ No newline at end of file diff -c -r --new-file ds2.0r19/lib/www/ds-admin-faq.html ds2.0r20b/lib/www/ds-admin-faq.html *** ds2.0r19/lib/www/ds-admin-faq.html Fri Mar 24 14:34:51 2006 --- ds2.0r20b/lib/www/ds-admin-faq.html Sun Apr 9 23:48:46 2006 *************** *** 1,243 **** ! ! ! ! Dead Souls Admin FAQ ! !
Dead Souls Admin FAQ, v2.4

Written by Cratylus @ Frontiers, October 2005
Updated March 2006

Note: commands are displayed in boldface, like this: ls -a

What's this FAQ about?


The point of this document is to orient a new admin in
Dead Souls 2. Starting a MUD with a lib that is completely new to
you can be confusing and discouraging. Hopefully this FAQ will
make the experience less difficult.


How do I start?

Start by reading the Dead Souls FAQ for some background
on where this lib came from and what you can do with it.


What's the QCS?

Please see the QCS example page for an explanation of this
important Dead Souls system.


Is there a MUD somewhere running Dead Souls I can log into?

As a convenience to the curious, I have set up a "demo" mud
at dead-souls.net, port 6666. To connect, either click on
this link with your browser, or open a terminal window
(or for windows users, Start -> Run ) and
type: telnet
dead-souls.net 6666

When you log in, the system will read your playerfile for
a few seconds and then it will turn you into a creator. This
is so that you can examine code, try out the QCS, etc.

Please note that in the regular, non-demo version of the
mud, people are NOT automatically given creator status.

On the regular non-demo version of the mud, Only
the admin (basically, the first person to log on to the new mud)
gets automatic creatorship.

After logging in, you will be transported
to your workroom. Some useful commands:

look
look at me
look at chest
open chest
look in chest
get tricorder from chest
read index in handbook
read chapter 1 in handbook
who
stat
wiz
create new npc generic
look at board
read 1 on board
home


I like Dead Souls and I want to use it, but I don't want to run a mud.

Being a mud admin is very different from being just a coder
or builder, and many people just don't feel like dealing with
the hassle of running a mud.
There are a few Dead Souls muds out there that could
use help from you. Telnet to the Dead Souls development mud
and type: mudlist -m dead to see a list of Dead Souls muds
that might be hiring.
You can also just code on the Dead Souls development
mud. You're welcome to create as you please, and if your
building gets to the point where you'd like it included in
the lib, let me know and I'll inspect it for approval.
Please note that anything you code on the Dead Souls
development is automatically eligible for inclusion in the
standard Dead Souls mudlib distribution, so if you want
to prevent your code from being used that way, don't code
on my mud.


I want to invite my friends to help me code. How do I
promote them to creator status?

As admin, you have access to the admintool
command. This opens a menu-driven admin system you
can use to manage some basic aspects of your new MUD.

Everything on admintool can be done with
commands, system calls, or file editing, but until
you get the hang of all that stuff, admintool
is a convenient shortcut.
In this example, you would type: admintool ,
then select option 3, then option l (that's a lowercase "L").

The oldfashioned way, if the new creator
were named dude, would be: encre dude

I know. But people like menus, so I made it.


What about intermud? How do I talk on that?

The intermud3 (or i3) network is available
to you, and you are probably already connected to it. Type
mudlist to see a list of other muds on the network.

By default, the "Dead Souls intermud channel" is
enabled for creators. Type: ds blah blah
and other Dead Souls muds on the i3 network will see
your message like this:

You@YourMud <ds> blah blah

To enable intergossip and intercre, read
/doc/README for instructions.

Please note that intercre is where you ask coding
and technical questions only. Random chatting is not
tolerated on that channel. Newbie questions that are
Dead Souls specific or that obviously have answers in
Dead Souls documentation will meet a hostile reception on
intercre.

Conversely, intergossip is mostly chat. Please
be warned that discussions on intergossip are usually
offensive, argumentative, and generally aggressive.
This hostility is especially sharp when you
are identified as a "newbie". You will almost certainly
be mocked and insulted no matter what you say, but
especially if your first messages betray you as
ignorant of intergossip standards and traditions. I
strongly recommend you lurk on this channel for a few
days before saying anything.

Really, I recommend you avoid the intergossip channel entirely.


I talk on intermud but nobody replies. What's up with that?

I3 uses a hub topology. All muds communicating on intermud
connect to the router to do so. If that router is down all
i3 communication stops, until it comes back up. To check
network status, ping Frontiers or Dead Souls. If the
ping command gets no answer, i3 is probably down, or
your connection to it has been interrupted. Your mud will
be aware of this and retry to connect to i3 every
fifteen minutes or so.

There's also the possibility that nobody who wants to
chat is listening.


How did you know my mud started up?

The same way your mud knows that i3 is up or
down. A while ago I noticed that i3 can be very
unreliable, and sometimes when it goes down and
comes back up, people's muds don't refresh their
connection, and they can be off intermud for days
without realizing it.

I implemented a "keepalive" system which
uses the intermud "auth" packets as pings. Every
fifteen minutes or so, you mud tries to ping Frontiers
and Dead Souls. If it gets a reply from at least one,
then it's happy. If neither reply, then your mud
alerts the Arch room that intermud is down, and it
will reload the intermud daemon every 15 minutes
in an attempt to reconnect. Once i3 is back up and
you are reconnected, you go back to pinging.

This means that Frontiers and Dead Souls
get a bunch of pings all the time. When a mud we've
never heard of before pings us, we get a message
about it, and so we know a new mud is online.

If this makes you feel like Big Brother
is watching you, you can probably just delete
the file /daemon/services/auth.c and then update
the file /daemon/services.c without causing harm
to your mud.


What's this about a manual on Frontiers?

It's no longer relevant. All the docs
we were making available on Frontiers are now included
in Dead Souls, starting from version 1.9r9.

In your workroom is a chest. Open the
chest and the new Dead Souls Creators Manual is
inside. The text files are in /doc/manual .


How do I add limbs to a race?

Edit /secure/cfg/races/<race> and make the changes
you want. Then use admintool to remove the race from the
races daemon, then add re-add the race.


How do I make my friend an admin?

Use the groups menu in admintool, and select
"Modify a group". Select the ASSIST or SECURE group,
and enter the names of all the members it should have. If
I wanted to make xyzzy an assistant admin, I would
make him a creator, then I would edit the
ASSIST group and make the contents look like this:

cratylus:xyzzy

Xyzzy then needs to log out and log back in.


I don't like how the who command output looks! How can I change it?

Believe it or not, I actually get questions like this. I also
get stuff like "my workroom is broken! fix it!"

If there is something broken about the lib itself, such as
an insta-death bug or a command that crashes the mud, I am
happy and eager to hear about it, so I can implement the fix
in the next lib release.
However, if the problem you're having is that the lib,
by design, behaves in a way not to your liking, this isn't something
I'm likely to "fix" for you. For example, if you want a "who"
command with a cooler look, that's up to you to make. You're
the one coding a mud, so you need to take it upon yourself to
understand the code and modify it to suit your tastes.
Similarly, "orcs are too strong!" or "advancing levels
should increase your eyesight" are issues you need to deal
with on your own, using the coding skills learned from reading the
Creators Manual.


Can you please make the FAQ easier to read? It's too long and complicated.

I'm a lib coder, not a web designer. Cut me slack. Or, edit it
for me and show me how it's done.


Most of the file headers have only Descartes's name on them. Did
you really develop this lib or did he?

Both. The lib he released in 1997 was his, and so almost every
file on it had his name. I've been working on it since, but
I am very lazy about headers. I work on lots of files at the
same time, and authorship attribution tends to rank very low
on my priority list. Therefore, even though a great majority
of the files in the lib have been either heavily modified or
created by me, my name is on very few.

I haven't bothered to go back and revise headers either,
because, honestly, what a pain in the butt that would be. I'm
satisfied knowing there's little doubt who has made the many
changes on the lib.


How can I change the colors of the channel messages?

The colors are specified in /secure/daemon/chat.c


How do I know what other muds use Dead Souls?


Go to the arch room. Type: arch

Then type
: read screen

This shows a list of muds that used Dead Souls and
joined intermud at some point. To see a list that
also includes obvious test muds, type: read printout

See the creator's FAQ for more intermud command info.


I was hanging out in the Arch room and the loudspeaker went off. WTF?

Your mud receives all sorts of network requests from the
intermud network, such are remote who (asking who is logged on),
remote finger (info on users), locate (trying to find a user
somewhere on i3), etc. Whenever your mud receives such a request,
it is announced in the Arch room. Note that these are normal,
and do not represent an attempt to undermine your security.


I want to test the intermud channel but I don't want to spam the ds line.

Type: call me->AddChannel("ds_test")
Then type: ds_test test

The ds_test channel is specifically for communication
testing so that ds can remain spam free.


The web server and FTP server don't work

To enable them at mud boot time, uncomment the "inet" line in
/secure/cfg/preload.cfg

To enable it temporarily, type: update /secure/daemon/inet

These servers do not use the standard ports. The internet standard
http port is 80 and for ftp it is 21. Your mud ftp and web servers
do not use these.
Instead, the network port for your web server is 5 less
than your mud's port, and the ftp port is 1 less.
This means that if your mud is reached by telnetting
to port 6666, your ftp server will be at 6665 and your web server
will be at 6661.

Please note that the web and ftp server are not supported. They work,
but whatever security risk they pose is entirely on you.


I tried to log in to the FTP server but I can't!

Make sure you use your mud name and mud password, not the
username and password of the computer you are on.


I can't do anything with FTP. It just hangs there.

FTP is a funny sort of protocol. If you don't have a direct
connection to an FTP server (for example, you are behind a
firewall), you have to use PASV (or passive) mode. Unfortunately,
at this time, PASV is not implemented in the mud FTP server.


The web server gives me a 404 but I know the directory is there.

Like the FTP server, the web server is a very simple program.
It does not do directory listings at all. If you request
a directory, and it can't find an "index.html" file, it
just errors out.

It will also barf if a file you try to serve is
unusually large.

Let me make this point one final, excruciatingly clear time:
If you need a webserver, use apache. The mud www server is available
as a convenience, not as a production-quality standards-compliant
intarweb server.


I'm using an external FTP server, but the files I transfer
become read only!

You need to make sure that the FTP server you use
runs as the same user as the mud driver does, otherwise
you'll have permissions conflicts.


I moved a command from one directory to another. How do I get the new location recognized?

First, run update on the command in question.
then:
If it's not a verb: update /daemon/command
If it's a verb: update /daemon/verbs


The mudtime is all wrong!

The mudtime command tells you what time it is in the game, not what time
it is in the real world.


The time of day is all wrong!

If you used admintool to change your timezone and the time of day is still
wrong, you may be using an OS with timekeeping that Dead Souls doesn't
understand. If this is so, figure out how many hours off you are, and
enter that value into the EXTRA_TIME_OFFSET parameter in /secure/include/config.h


What happened to the roommaker and thingmaker?

They produced code that was often incompatible with QCS. They are no
longer supported.


I keep getting 'Connection to address server (localhost 9999) refused.'

This is a harmless error. Dead Souls uses a program called addr_server to
try to resolve hostnames. However, hostname resolution is not important
to running the mud, so it's not automatically configured. If you run
addr_server with a specific port as an argument, and edit mudos.cfg to
point to that port for the addr_server, then reboot the mud, then you
will probably have hostname resolution in your mud.

However, not all OS'es handle name resolution the same, so this may not
work, even if you do everything exactly right. Either way, it doesn't
affect the mud.


Can I charge players a fee for playing on my mud?

NO.

Dead Souls uses MudOS, and MudOS has a license that specifically
and strictly forbids its use in a commercial way. I don't care how
you use the lib, but if you use it with MudOS, you need to comply
with MudOS licensing. If you were to port Dead Souls to some other
driver that allows commercial use, then you'd be all set.

Can people donate money to me for the mud?

Yes.

So long as there is no quid-pro-quo, or anything
about the transaction that is legally regarded as "commercial",
receiving money from people for the purpose of running the
mud is ok. However, I am not a lawyer, so read the MudOS
license yourself.

You should not try to bend the rules. For
example, public television channels often give trinkets to
donors as a token of their appreciation. If someone donates
money to you for your mud and they get a "thank you gift",
this is a quid-pro-quo, or "something for something", and
it's not right.

This is a MudOS thing, not a Dead Souls thing.
If you can't abide by MudOS licensing, just port Dead
Souls to some driver that lets you do commercial stuff.
Then please tell me how you did it, so I can pass on the
leetness to others.


I found a bug. For real. Can you please fix it?

Email me: <put my name here>@users.sourceforge.net

Please include a detailed description of the bug, and the exact
error text and commands that produced it. A log file or
screencap would be helpful.


Where would I edit to change how long someone can be idle before they get disconnected?

1) Modify IDLE_TIMEOUT in /secure/include/config.h
Don't do this with a Windows editor.

2) update /secure/daemon/master

3) update -r /lib/player

Instead of the updates you can reboot the mud.


How do I permit all users who log in to become creators automatically?

1) Set AUTO_WIZ
in /secure/include/config.h to 1
Don't do this with a Windows editor.

2) update /secure/daemon/master

3) update /secure/lib/connect

Instead of the updates you can reboot the mud.


How do I limit the use of intermud channels?

1) Set RESTRICTED_INTERMUD in /secure/include/config.h to 1
Don't do this with a Windows editor.

2) Add the players who are allowd to use intermud channels to
the intermud group using admintool.

3) update /secure/daemon/master

4) update /daemon/services/*

5) update /daemon/services

6) update /daemon/intermud

7) update /secure/daemon/chat

Instead of these updates, you could just reboot the mud.


How do I get off intermud completely?

1) Set DISABLE_INTERMUD in /secure/include/config.h to 1
Don't do this with a Windows editor.

2) update /secure/daemon/master

3) update /daemon/intermud


How do I change the start room for the mud?

1) change ROOM_START in /secure/include/rooms.h
Don't do this with a Windows editor.

2) reboot the mud


I don't like having newbies get special treatment.

1) Set MAX_NEWBIE_LEVEL in /secure/include/config.h to 0
Don't do this with a Windows editor.

2) reboot the mud


I made a change to /lib/player.c and updated it, but I'm
not seeing a difference in my character.


If an object (you) is loaded into memory, it contains
the features and functions of its file and inherited files
at the time it was loaded.

Changing those files and updating them doesn't do
anything to an object that is already loaded using the
old code.

In a case like this, what you want to do is
recursively update the file of the object in question,
then reload the object.

Let's say you modified /lib/npc.c so that
npc's sit down by default. Say you want the fighter in
your test room to possess this new functionality.

If you type: reload -r fighter

then the fighter's file is recursively updated,
the current version of the fighter is whisked away, and
a new version of the fighter is created, incorporating
the new auto-sit feature.

If the change in question is to lib/player.c
or some other file inherited by you, you would
type:

update -r /lib/creator

But you are still using that same old body as
before, so you'll need to quit and log back in to
get a new body using the new code.


How do I change the items new players receive?

Look in /lib/player.c for the function that gives
new players jeans and a t-shirt. Modify this
function to suit you. Make absolutely sure that
the objects you put there actually clone
correctly.

Remember to bk /lib/player before editing this file,
because if you screw it, then log off without
restoring a working copy, you will be sad.


Hey, there's no <foo> class! What's up with that?

True, there is no samurai class, and in fact, as of
this writing there is no cleric, acrobat, frombotzer,
or basketweaver.

The reason for this is that the Dead Souls
mudlib distribution isn't intended to be 100% ready for
players to show up and start doing quests.

What quests there are, what races, classes,
areas, objects, rooms, and NPC's you find in the
distribution are examples. If you open your mud
to players and what you've got is the Orcslayer and
newbie mansion quests, you might as well just close down.
In fact, please do.

Dead Souls is a starting point for a mud.
I have no way of knowing if you're going to have
mermen in an aquatic-theme mud. I have no clue
whether your space aliens will have 8 tentacles or
16 (they like base2, dontcha know).

So, no, there's no <foo>, because the
responsibility for making the mud in your creative
vision is yours, not mine. My job is to give you
a lib with enough working examples and enough
documentation so that you can code your own
basketweaving bugblatter beasts.



Where can I get a Dead Souls mud hosted?

That's a heck of a good question. There are many mud hosting services
out there. I hear good things about Kyndig, but that isn't specific
to Dead Souls. A good host will have a high level of service, shell
and file transfer access, etc, for which you obviously will need
to pay money.

There is at least one free mud hosting service I'm
aware of, and that's FrostMud. It's basically a guy and a Linux
server with room on it for muds. If you beg adequately, he might
let you put your mud on his server for free. I tested it and
Dead Souls installed and ran there without any problems. However,
he doesn't support anything, you're on your own, and bandwidth is
on a "you'll get it when it's there" basis.

There's no such thing as a free lunch. If you want
a reliably solid, well supported, feature-rich platform for your
mud, quit being a cheapskate and cough up the $20/mo. That's
like, what, one espresso every couple of days.

If you have a DSL or cable modem, and your computer is
up all the time, you can just use that, too. Your IP may be
dynamic, making it tough for people to find you, but there are
dynamic-dns services out there that help keep your ip
tied to a specific name.

If you're really hard up you can email me and beg for
me to host you for free, but expect me to be hostile about it,
and you'll get no fancy schmutz like a web page or shell access.
And if your mud gets on my nerves (being inactive for a long
time is enough to do that) I'll just wipe it. Possibly without
even warning you. It's not that I'm a jerk or I like being mean.
I just don't have a lot of time for nonsense.


Your LIB_MXLPLX system is all screwy. I changed it and it works. Wanna see?

Hell yes. I'm not just in this for my health. I want
more people coding in LPC so I can look at the fresh ideas and
new perspectives of other people (read: swipe code).

Send me an invitation to your mud by email or <ds>. I'd
love to look at your work.

If it is code you are willing to donate to Dead Souls, I
will gladly accept its submission, also by email. There's no
guarantee it will make it into any future release, but it just might.

Please be aware that by doing so, you release your normal
copyright to the code and license it GPL, allowing me to publish it and
preventing you from revoking my right to distribute it.

You also represent that you *have* copyright to do this
in the first place, and hold me harmless in any subsequent
dispute between you and any other third party.

If you want to email me code but wish to retain normal
copyright, please state so clearly in the body of your email. I
will honor that request
(and it's the law so I don't really
have a choice). Just be aware I will not put code into Dead
Souls that anyone has non-GPL'ed copyright to.

Also, I don't want to hear from anyone about my
use of legal terms of art. I know damn well it's more complicated
than I make it sound. My phrasing is sufficient to make
the legal practical transaction of ideas possible here.


How are files organized in Dead Souls?

cd / and ls to view the top level directory. The
list may be largely meaningless to you, so let's review it here:

cfg/

General configuration files for timezone and such.

cmds/

Main location of commands that don't require special access
privileges. Commands are different from verbs in that they tend
not to manipulate your environment, but rather deal with
the player's relationship to the system and/or files.


daemon/

Daemons are files that provide access to data files in an
organized way. For example, adding an occupational class
(like, say, assassin) to the game needs to be done in a
precise way in order for it not to break things. By sending
the data to the daemon first, you can be sure that the
new system configuration is entered properly. Daemons also
provide a means to access data, like "how much is silver
worth compared to gold", that is uniform across the mud, and
prevents accidental overwrites of data files by multiple
editors.


doc/

General documentation.


domains/

This is where MUD game areas go when they are complete
and ready for general play by the public. Once here, only
admins have write access to the files.


ftp/

The base for the MUD ftpd. Using the ftpd is probably dangerous
in terms of your system security, and I discourage it, but if
you are determined to have mud ftp access for your creators,
this is one way. See /secure/lib/net for the actual server. It
may or may not work. I won't support it.


include/

Include files provide a set of constants for your files. For
example, if you include <damage_types.h>, you can specify in
the code for your chainmail that it protects against
the damage type "BLADE" at a certain level.


lib/

This is the heart of the Dead Souls lib. This is the location
of the files that your objects, be they swords, shoes, or
handguns, will use as their configuration base.


log/

Log files.


news/

Announcements are made here. For example, in /news/creator
you can post a notice that you have added a teleportation
spell, and when your creators log on, they will see the message.


obj/

Contains some important templates, especially some for the QCS.

open/

Legacy directory. Kept for compatibility. Historically this
directory has served as a place where creators can put code
for others to freely modify.


realms/

This is where creator home directories are.


save/

Files that describe properties of the MUD's systems live
here. The number of limbs that a bat has, for example,
is in races.o. In classes.o you'll find the skill ranges
for fighters. Do not edit these files. They must be
modified by daemons only, or you risk corrupting them.


secure/

This directory will be described in a separate section below.


shadows/

Shadows are a controversial feature of LPC. This directory
is designed for shadow objects, but they should be very
rarely, if ever used. Basically shadow objects are objects
that attach themselves to another object, intercepting
function calls. For obvious reasons this is a security
risk, so unless you really really know what you're doing,
avoid them.


spells/

Pretty self explanatory. The spells daemon looks for spells here.


tmp/

A directory anyone can write to. Generally for swapping
data between objects, systems, or people.


verbs/

Another controversial topic. Verbs are a kind of command. For
example, go and sit and open are verbs. Specifically, verbs
are commands that interact with the user's environment. The
idea is that throw my first red rock at the green goblin
should work, and should work the same everywhere on the
MUD. Verbs are a source of debate among some people, because
to folks accustomed to add_action commands, verbs seem
excessively complex.

www/

Like the ftp directory, but for the MUD webserver.


Ok now let's take a quick look at the /secure directory: ls /secure
As you can see, /secure seems to have many of the same directories
that the root filesystem has.
The reason a /secure directory is needed is that
there are files that should not be readable by everyone, and
there are files that must be writable only by a few. The MUD security
system uses the /secure directory as a means to control access to
such files.
For example, the average creator has no business
accessing the player data files of other creators or players. Therefore
/secure/save/creators and /secure/save/players is offlimits to them.

A directory without a counterpart in / is /secure/sefun. This
is where simulated external functions reside.


What are sefuns and efuns?

First let me explain that the driver has built-in
functions that are available to the mud. For example,
type eval return find_player("cratylus") , but replace my name
with yours. Your player object pointer will be found and returned
to you (more or less. strictly speaking it's more complicated).
The driver provides this function. Because it is "external"
to the mudlib, that is, it's in the driver and not the lib,
it is called an external function, or more commonly, "efun". The
idea is that certain actions you ask the mud to perform are
so common that they are made available MUD-wide.

Efuns are ridiculously useful and powerful, and because
they are in the driver as compiled code, very fast. A near-complete
set of efun documentation is available in /doc/efun.

However, the driver does not contain every possible
MUD-wide function you might want. For example, there is a
tell_object() efun, which lets you send a message to an object
such as a player. The syntax is something like this:

tell_object(find_player("cratylus"),"Hi.");

Which doesn't look like much, but believe me, this
kind of stuff adds up. I wanted to make this simpler, so I
used what is called a sefun, or a simulated efun. It is
a function that is available lib-wide, but it isn't in
the driver. Instead it is provided by the lib itself (the
master daemon, specifically). By adding the appropriate code
in /secure/sefun/ I have now made available a tell_player() sefun,
which works like this:

tell_player("cratylus","Hi.")

This simplification of code will become more obviously
useful to you as you get more coding under your belt. Most
sefuns are documented in /doc/sefun.



Whew! Ok now I know where stuff is. What's next?

You probably want to examine how objects are written.
Type goto /domains/town/room/road and wander around town
a bit. If you want to see the code for something, for example,
the beggar, about beggar should do it, provided the beggar is
in the room.

To see the filenames of the objects around you,
type scan here, or scan me to scan your own inventory.

If you've never coded before, this is the hard part.
To understand what you're looking at when you run commands like
more /domains/town/weap/orcslayer.c you need to get comfortable
with LPC.
The brute force way of doing this is copying stuff
and then changing the descriptions, thus making new stuff.
This will work, but you'll waste time looking for examples of
exactly what you want to do..and you may not find them.
Instead, learning LPC will let you create whatever
you want, without relying on templates.

This means that now you must read the LPC Basic
manual, then the LPC Intermediate manual. As admin, your
creators will expect you to know what's in there.

On your person or in the chest in your workroom is
the Creators Manual. Read both the Players Handbook and
the Creators Manual from cover to cover.


Oh, man, you're kidding! Those are, like, books! Can't I
just start making stuff?

Well...ok. But you need to go through the docs
soon, ok? In the meantime, read the QCS chapters in the
Creators Manual to get you quick-started in the creation
process. Remember you need to be holding your Creator
Staff in order to access the QCS commands.

Other useful tools in your chest are a remote
control and a medical tricorder.


Everything is su-u-u-u-p-e-e-r-r-r s-s-l-o-o-o-o-w-w-w

First, make sure you are using the latest available version of
Dead Souls (check here or here). Older versions of Dead Souls
are known to have nasty memory leaks.

Next, see if you have runaway objects. An object can be coded
to do really unpleasant stuff like replicate itself over and
over until it brings the mud to its knees. Find out how many
objects are loaded by typing: eval return sizeof(objects())

If the count is in the thousands, and only a few people are
logged on, you may have a runaway. Most often this involves
NPC's doing stuff you didn't expect. Reset all loaded rooms
with the following command:

resetall

perhaps followed by a:

flushobs

If the lag clears up, you found the culprit. If not, see if
the callouts list is clogged with the command: callouts

If all else fails, reboot the mud and ask for help on the ds line.

Please note that the rage virus (especially if unleashed
in the menagerie) is notorious for redlining the mud. Having
hundreds of NPC's all engaging in simultaneous combat
while infecting each other with a rapidly spreading hostility
virus can be expected to impact overall performance. So please try
to avoid the rage virus unless you are specifically stress testing
your system.


Dude! One of my creators just kicked me off my own mud!

One of the virtues of LPC is that it is flexible and powerful.
One of the drawbacks of LPC is that it is flexible and powerful.

It is not possible to make an LPC mud that is
immune to abuse from creators. You just can't. The MudOS
function set is just too complex and sophisticated to eliminate
every possibility of abuse.

You will therefore *always* be vulnerable to things
like people coding objects that crash the mud on purpose (I
won't detail how that can be done, but anyone with intermediate
LPC skill can do it, and utter newbies can even do it with
a stupid enough mistake), finding a way to dest admins, or
continually updating recursively the /lib filesystem. A
jackass will always find a way to expose you to her jackassery.

This means that you need to know who is coding on your
mud and what they are doing. Your job as an admin is to
immediately deal with coders who pose a discipline problem.
If they fool you once, shame on them. If they fool you
twice..the..they...they shouldn't fool you twice is what I'm
saying.

This does not mean that Dead Souls is somehow
impossible to secure. You can easily prevent unauthorized
access to lib data. See the next section for how this works.

What you can't prevent is some dude off the internet
you just met and made a creator from wreaking havoc on your
mud and creating a nuisance of himself. You have to know who
these people are and you have to have a level of trust and
confidence in them, otherwise you need to use the decre
command.


Is Dead Souls secure?

The short answer is no, nothing I know of is "secure" in the
sense that you don't need to continually pay attention to it. If the
question is "Is Dead Souls particularly unsafe to run?" then the
answer is no. Just like any other Internet program you use, Dead Souls
is not an obvious security risk, so long as it is not used carelessly.
And, obviously, games of any kind, including Dead Souls, should never
be installed on any mission-critical, national security, public
safety, or health care server.

Dead Souls security involves two separate spheres:

1) The binary executable and the system that runs it.

2) The mudlib and the code that you use and create.

The first sphere is probably most important. Presumably
you plan to run a mud on a computer that does other things too,
and you want to keep those things separate from your mud. The
most important thing to do is to avoid running Dead Souls as a
privileged user. In the case of Windows, this means that the
program should not be run by Administrator or anyone in the
Administrator group.
For unix users, this means that the driver should not run
under uid 0 (root).

The reason for this precaution is that if some genius
hacker manages to exploit some unknown weakness in the program,
it is better that the process they hack doesn't have full admin
privileges to the box.
This caution has little to do with Dead Souls specifically.
It is a warning I'd give to anyone planning to run any kind of network
server. You should take your own security seriously, and
if you do not understand your own security situation, you need to take
a step back and ask yourself if running a mud at all is a good idea.

Sphere 2 is lib security. In older muds, file and directory
privileges were handled by attributes on the files. If a file's
user id (UID) matched a user's UID, then that user had full access
to it. Such systems often had complex systems that evaluated
effective UID (EUID) based on the file's attributes, its parent
directory, the user's ID, possibly group id, etc. This is an
entirely valid security model, but because of its complexity,
it tended to be exploited easily and often. If you don't
stay 100% on top of such a system (just like any OS), there's
no way to be sure you won't rooted.

With stack security, privilege management is much, much
easier. A file's privilege is based solely on its location. If
a user doesn't have read access to /foo/bar/ then she can't read
or modify /foo/bar/file.c. If someone with privs to that location
copies the file to somewhere else, then the privs of that new location
are in force on the file.
The "stack" part of stack security comes from the mud
evaluating the privileges of all the objects involved in the
access request. If you're unprivileged and you manage to get a
privileged object to make the access request for you, the access
will fail, because you are unprivileged, and you are still part
of the function call stack (i.e., the list of instructions that
form a chain between the command and the intended event).

Granular (more detailed) modification of user privileges
can be done by changing files in /secure/cfg to grant
users and groups specific privileges.


I sent you my code a week ago. Is it in or out?

How long it takes me to review code submissions has nothing
to do with what I think of you, your skills, or your
code. It takes me a long time because Dead Souls isn't
actually my job, and is not a physical member of my
family, so it has to wait its turn sometimes, for my attention.
Sometimes I will get to someone else's code sooner even
though I received yours first. What can I say. Sometimes
I feel like dealing with a particular thing at a particular
time.


Did you finish the bfd() sefun modification I asked you for last night?

I'm on the ds line a lot, and generally accommodate people's
requests right away if I have time. This makes it seem
sometimes like I can turn orders around in minutes or
hours, like a short-order cook.
This is an illusion. I do this sometimes
for requests that strike my fancy or that are so simple
they are not inconvenient, or maybe because I happen to
be bored at that moment. But my sometimes doing this
doesn't mean folks should expect some sort of prompt
turnaround on special requests.
In general, I am not sitting at my desk waiting
for code orders. I'm doing something else. If I get to
your request right away, then good for you. If I don't,
then I'll get to it when I get to it.


The queeg daemon is a horrendous mess. It's inefficient and frankly offensive.

I'm not an especially gifted programmer. In fact, I view
myself rather as a Pakled from the Star Trek series. I
look for things that make the code go. I look for things
that make the code strong. Sometimes, because I am not
a trained or professional programmer, things are done
in a way that shock the conscience of more sophisticated
practitioners.
If you find such code (and I do hope it is rare),
bringing to my attention that it has been implemented in a
wretched way doesn't help me. I know that. I wrote it. If
you want to help, send me an email with the fixed code.

You implemented my code but didn't give me credit.

Whoops. Send me an email telling me where I goofed and I'll fix it.


Intermud mail doesn't work

No it doesn't. It's actually a pretty complicated system to
implement, so get used to just local mud mail for now. It
is definitely planned for the future, though.


The admintool menus let you pick options that aren't visible

I can't decide whether this is a feature or a bug. I'm
leaning toward "laziness" as the cause.


What does locking the mud do, exactly?

When the mud is locked, only members of the authorized
groups are permitted to log in. By default, these
groups are SECURE, ASSIST, ELDER, and TEST. Anyone
who is not a member of these groups, whether they are
a creator or a player, is prevented from logging in.


The race help output is inadequate for role-playing. How do I change it?

By default, help human will output various characteristics
of the human race, as known to the race daemon. If you
want instead to provide your own help data on the history and
lore of humans, simply create a file called /doc/help/races/human
and put your information in it. That information will then
be what is displayed when requesting help on that race.


I need to know what features to expect in the next release so I don't
waste time duplicating effort

To find out what the next release will definitely
have, telnet to dead-souls.net 6666. If you don't
already have a character there, your new one will be
made a creator. You can then type:

more /doc/RELEASE_NOTES

to see what the development mud has. That is
what you can definitely expect to see in the next release.
Note that this will differ from the /doc/RELEASE_NOTES
on your mud, because as new stuff is added to the
devel mud, it gets documented in that mud's RELEASE_NOTES.
To find out what I'm working on, or what
I'm planning to work on, log into
dead-souls.net 6666
and type:

finger cratylus

You will see my .plan file, which is basically
the to-do list I work off of. Some of it is written
with the expectation that I'm the only one who needs to
understand it, so it may not all make sense to you.
Anything with an asterisk (*) in front of
it is being currently worked on.


You need a development roadmap and task tracking

No, I don't. If I had developers and teams and
such things, then I'd use all the fancy project
management stuff available on Sourceforge.
But I don't want to manage developers,
I want to lib code. If you want to help develop
the lib, then that's really great. Follow the instructions
from the previous question and look at my plan file
for something that looks interesting and that
doesn't have an asterisk. Tell me you'd like
to take that project, and I'll mark it as yours.
That's it. Send it to me when yer done.
If I get tired of waiting I'll tell you
I'm going to do it myself, like I was planning
all along, and you'll be relieved of that expectation.
Setting up some kind of sophisticated
collaboration tool to get 3 pieces of code from
2 people, and me having to be on people's backs
for results and stuff...this is not what I
signed up for and I'm not doing it.


How do I update a sefun without rebooting the mud?

To have your new nit_pick() sefun take effect in the
running mud, you might do something like this:

update /secure/sefun/nit_pick.c

update /secure/sefun/sefun.c


I had a really great idea that revolutionizes ds and you
refuse to include it. I am forking ds development and
making my dream come true.

Ok then, have fun. All I ask is that you give your
project a name that isn't going to confuse people
as to which lib is which. Confusing your user base
isn't a good way to get started on such an enterprise.
Send us a post card once in a while.


What do the version numbers mean?

2.0r16 means "Major version 2, minor version 0, release number 16".
Releases happen pretty frequently, to add functionality and fix bugs
from the previous release. When the basic functionality of a minor
version is as bug free as reasonably possible, a new minor version
change happens.
Major version number changes are very rare and represent a
vast difference from the old major version. Versions 1 and 2 of
Dead Souls are so different as to be largely incompatible with each
other's code.
As of this writing, the goal of releasing version 2.1 looms.
The significance of this milestone is that Dead Souls 2.1 is
intended to be the fulfillment of the promise that there was in
version 1.1. After the release of Dead Souls 2.1, the focus of
development will be in adding major systems and functionality
that 1.1 was hoped to have, but never did.

- ! Cratylus

! Dead Souls Homepage
! ! --- 1,13 ---- ! ! Dead Souls Admin FAQ ! !
Dead Souls Admin FAQ, v2.6

Written by Cratylus @ Frontiers, October 2005
Updated April 2006

Note: commands are displayed in boldface, like this: ls -a

What's this FAQ about?


The point of this document is to orient a new admin in
Dead Souls 2. Starting a MUD with a lib that is completely new to
you can be confusing and discouraging. Hopefully this FAQ will
make the experience less difficult.


How do I start?

Start by reading the Dead Souls FAQ for some background
on where this lib came from and what you can do with it.


Is there a MUD somewhere running Dead Souls I can log into?

As a convenience to the curious, I have set up a "demo" mud
at rugose.com, port 6666. To connect, either click on
this link with your browser, or open a terminal window
(or for windows users, Start -> Run ) and
type: telnet
rugose.com 6666

When you log in, the system will read your playerfile for
a few seconds and then it will turn you into a creator. This
is so that you can examine code, try out the QCS, etc.

Please note that in the regular, non-demo version of the
mud, people are NOT automatically given creator status.

On the regular non-demo version of the mud, Only
the admin (basically, the first person to log on to the new mud)
gets automatic creatorship.

After logging in, you will be transported
to your workroom. Some useful commands:

look
look at me
look at chest
open chest
look in chest
get tricorder from chest
read index in handbook
read chapter 1 in handbook
who
stat
wiz
create new npc generic
look at board
read 1 on board
home


I like Dead Souls and I want to use it, but I don't want to run a mud.

Being a mud admin is very different from being just a coder
or builder, and many people just don't feel like dealing with
the hassle of running a mud.
There are a few Dead Souls muds out there that could
use help from you. Telnet to the Dead Souls development mud
and type: mudlist -m dead to see a list of Dead Souls muds
that might be hiring.
You can also just code on the Dead Souls development
mud. You're welcome to create as you please, and if your
building gets to the point where you'd like it included in
the lib, let me know and I'll inspect it for approval.
Please note that anything you code on the Dead Souls
development is automatically eligible for inclusion in the
standard Dead Souls mudlib distribution, so if you want
to prevent your code from being used that way, don't code
on my mud.


I want to invite my friends to help me code. How do I
promote them to creator status?

As admin, you have access to the admintool
command. This opens a menu-driven admin system you
can use to manage some basic aspects of your new MUD.

Everything on admintool can be done with
commands, system calls, or file editing, but until
you get the hang of all that stuff, admintool
is a convenient shortcut.
In this example, you would type: admintool ,
then select option 3, then option l (that's a lowercase "L").

The oldfashioned way, if the new creator
were named dude, would be: encre dude

I know. But people like menus, so I made it.


What about intermud? How do I talk on that?

The intermud3 (or i3) network is available
to you, and you are probably already connected to it. Type
mudlist to see a list of other muds on the network.

By default, the "Dead Souls intermud channel" is
enabled for creators. Type: ds blah blah
and other Dead Souls muds on the i3 network will see
your message like this:

You@YourMud <ds> blah blah

To enable intergossip and intercre, read
/doc/README for instructions.

Please note that intercre is where you ask coding
and technical questions only. Random chatting is not
tolerated on that channel. Newbie questions that are
Dead Souls specific or that obviously have answers in
Dead Souls documentation will meet a hostile reception on
intercre.

Conversely, intergossip is mostly chat. Please
be warned that discussions on intergossip are usually
offensive, argumentative, and generally aggressive.
This hostility is especially sharp when you
are identified as a "newbie". You will almost certainly
be mocked and insulted no matter what you say, but
especially if your first messages betray you as
ignorant of intergossip standards and traditions. I
strongly recommend you lurk on this channel for a few
days before saying anything.

Really, I recommend you avoid the intergossip channel entirely.


I talk on intermud but nobody replies. What's up with that?

I3 uses a hub topology. All muds communicating on intermud
connect to the router to do so. If that router is down all
i3 communication stops, until it comes back up. To check
network status, ping Frontiers or Dead Souls. If the
ping command gets no answer, i3 is probably down, or
your connection to it has been interrupted. Your mud will
be aware of this and retry to connect to i3 every
fifteen minutes or so.

There's also the possibility that nobody who wants to
chat is listening.

It's also possible that the Dead Souls I3 router has
changed address or port. Visit this page to get the
latest conenction info:

Dead Souls I3 Router Page



How did you know my mud started up?

The same way your mud knows that i3 is up or
down. A while ago I noticed that i3 can be very
unreliable, and sometimes when it goes down and
comes back up, people's muds don't refresh their
connection, and they can be off intermud for days
without realizing it.

I implemented a "keepalive" system which
uses the intermud "auth" packets as pings. Every
fifteen minutes or so, you mud tries to ping Frontiers
and Dead Souls. If it gets a reply from at least one,
then it's happy. If neither reply, then your mud
alerts the Arch room that intermud is down, and it
will reload the intermud daemon every 15 minutes
in an attempt to reconnect. Once i3 is back up and
you are reconnected, you go back to pinging.

This means that Frontiers and Dead Souls
get a bunch of pings all the time. When a mud we've
never heard of before pings us, we get a message
about it, and so we know a new mud is online.

If this makes you feel like Big Brother
is watching you, you can probably just delete
the file /daemon/services/auth.c and then update
the file /daemon/services.c without causing harm
to your mud.


I heard there's an I3 router included in Dead Souls.

Please see the router page for details.


What's this about a manual on Frontiers?

It's no longer relevant. All the docs
we were making available on Frontiers are now included
in Dead Souls, starting from version 1.9r9.

In your workroom is a chest. Open the
chest and the new Dead Souls Creators Manual is
inside. The text files are in /doc/manual .


How do I add limbs to a race?

Edit /secure/cfg/races/<race> and make the changes
you want. Then use admintool to remove the race from the
races daemon, then add re-add the race.


How do I add a race?

Copy a race in
/secure/cfg/races/ and edit it.
For example:

cp
/secure/cfg/races/bear /secure/cfg/races/wampa

Edit the wampa file to reflect what you think a
wampa is like. If you want new players to be able
to select wampa as their race, make sure the file
has this line in it:

PLAYER_RACE 1

Make especially sure to change the lines RACE and
LANGUAGE. When you're done editing, type:

addrace wampa



How do I make my friend an admin?

Use the groups menu in admintool, and select
"Modify a group". Select the ASSIST or SECURE group,
and enter the names of all the members it should have. If
I wanted to make xyzzy an assistant admin, I would
make him a creator, then I would edit the
ASSIST group and make the contents look like this:

cratylus:xyzzy

Xyzzy then needs to log out and log back in.


I don't like how the who command output looks! How can I change it?

Believe it or not, I actually get questions like this. I also
get stuff like "my workroom is broken! fix it!"

If there is something broken about the lib itself, such as
an insta-death bug or a command that crashes the mud, I am
happy and eager to hear about it, so I can implement the fix
in the next lib release.
However, if the problem you're having is that the lib,
by design, behaves in a way not to your liking, this isn't something
I'm likely to "fix" for you. For example, if you want a "who"
command with a cooler look, that's up to you to make. You're
the one coding a mud, so you need to take it upon yourself to
understand the code and modify it to suit your tastes.
Similarly, "orcs are too strong!" or "advancing levels
should increase your eyesight" are issues you need to deal
with on your own, using the coding skills learned from reading the
Creators Manual.


Can you please make the FAQ easier to read? It's too long and complicated.

I'm a lib coder, not a web designer. Cut me slack. Or, edit it
for me and show me how it's done.


Most of the file headers have only Descartes's name on them. Did
you really develop this lib or did he?

Both. The lib he released in 1997 was his, and so almost every
file on it had his name. I've been working on it since, but
I am very lazy about headers. I work on lots of files at the
same time, and authorship attribution tends to rank very low
on my priority list. Therefore, even though a great majority
of the files in the lib have been either heavily modified or
created by me, my name is on very few.

I haven't bothered to go back and revise headers either,
because, honestly, what a pain in the butt that would be. I'm
satisfied knowing there's little doubt who has made the many
changes on the lib.


How can I change the colors of the channel messages?

The colors are specified in /secure/daemon/chat.c


How do I know what other muds use Dead Souls?


Go to the arch room. Type: arch

Then type
: read screen

This shows a list of muds that used Dead Souls and
joined intermud at some point. To see a list that
also includes obvious test muds, type: read printout

See the creator's FAQ for more intermud command info.


I was hanging out in the Arch room and the loudspeaker went off. WTF?

Your mud receives all sorts of network requests from the
intermud network, such are remote who (asking who is logged on),
remote finger (info on users), locate (trying to find a user
somewhere on i3), etc. Whenever your mud receives such a request,
it is announced in the Arch room. Note that these are normal,
and do not represent an attempt to undermine your security.


I want to test the intermud channel but I don't want to spam the ds line.

Type: call me->AddChannel("ds_test")
Then type: ds_test test

The ds_test channel is specifically for communication
testing so that ds can remain spam free.


What's this "Network room"?

There is a room below the Arch room called the network room.
It is intended to facilitate troubleshooting of network
and intermud problems. Unless you're intimately familiar
with Dead Souls network code, I suggest avoiding this
room, as it is very messy and very noisy.


The web server and FTP server don't work

To enable them at mud boot time, uncomment the "inet" line in
/secure/cfg/preload.cfg

To enable it temporarily, type: update /secure/daemon/inet

These servers do not use the standard ports. The internet standard
http port is 80 and for ftp it is 21. Your mud ftp and web servers
do not use these.
Instead, the network port for your web server is 5 less
than your mud's port, and the ftp port is 1 less.
This means that if your mud is reached by telnetting
to port 6666, your ftp server will be at 6665 and your web server
will be at 6661.

Please note that the web and ftp server are not supported. They work,
but whatever security risk they pose is entirely on you.


I tried to log in to the FTP server but I can't!

Make sure you use your mud name and mud password, not the
username and password of the computer you are on.


I can't do anything with FTP. It just hangs there.

FTP is a funny sort of protocol. If you don't have a direct
connection to an FTP server (for example, you are behind a
firewall), you have to use PASV (or passive) mode. Unfortunately,
at this time, PASV is not implemented in the mud FTP server.


The web server gives me a 404 but I know the directory is there.

Like the FTP server, the web server is a very simple program.
It does not do directory listings at all. If you request
a directory, and it can't find an "index.html" file, it
just errors out.

It will also barf if a file you try to serve is
unusually large.

Let me make this point one final, excruciatingly clear time:
If you need a webserver, use apache. The mud www server is available
as a convenience, not as a production-quality standards-compliant
intarweb server.


I'm using an external FTP server, but the files I transfer
become read only!

You need to make sure that the FTP server you use
runs as the same user as the mud driver does, otherwise
you'll have permissions conflicts.


I moved a command from one directory to another. How do I get the new location recognized?

First, run update on the command in question.
then:
If it's not a verb: update /daemon/command
If it's a verb: update /daemon/verbs


The mudtime is all wrong!

The mudtime command tells you what time it is in the game, not what time
it is in the real world.


The time of day is all wrong!

If you used admintool to change your timezone and the time of day is still
wrong, you may be using an OS with timekeeping that Dead Souls doesn't
understand. If this is so, figure out how many hours off you are, and
enter that value into the EXTRA_TIME_OFFSET parameter in /secure/include/config.h

Also make sure to change your timezone during daylight saving
changes. For example, EDT to EST, and vice versa.


What happened to the roommaker and thingmaker?

They produced code that was often incompatible with QCS. They are no
longer supported.


I keep getting 'Connection to address server (localhost 9999) refused.'

This is a harmless error. Dead Souls uses a program called addr_server to
try to resolve hostnames. However, hostname resolution is not important
to running the mud, so it's not automatically configured. If you run
addr_server with a specific port as an argument, and edit mudos.cfg to
point to that port for the addr_server, then reboot the mud, then you
will probably have hostname resolution in your mud.

However, not all OS'es handle name resolution the same, so this may not
work, even if you do everything exactly right. Either way, it doesn't
affect the mud.


Can I charge players a fee for playing on my mud?

NO.

Dead Souls uses MudOS, and MudOS has a license that specifically
and strictly forbids its use in a commercial way. I don't care how
you use the lib, but if you use it with MudOS, you need to comply
with MudOS licensing. If you were to port Dead Souls to some other
driver that allows commercial use, then you'd be all set.

Can people donate money to me for the mud?

Yes.

So long as there is no quid-pro-quo, or anything
about the transaction that is legally regarded as "commercial",
receiving money from people for the purpose of running the
mud is ok. However, I am not a lawyer, so read the MudOS
license yourself.

You should not try to bend the rules. For
example, public television channels often give trinkets to
donors as a token of their appreciation. If someone donates
money to you for your mud and they get a "thank you gift",
this is a quid-pro-quo, or "something for something", and
it's not right.

This is a MudOS thing, not a Dead Souls thing.
If you can't abide by MudOS licensing, just port Dead
Souls to some driver that lets you do commercial stuff.
Then please tell me how you did it, so I can pass on the
leetness to others.


I found a bug. For real. Can you please fix it?

Email me: <put my name here>@users.sourceforge.net

Please include a detailed description of the bug, and the exact
error text and commands that produced it. A log file or
screencap would be helpful.


Where would I edit to change how long someone can be idle before they get disconnected?

1) Modify IDLE_TIMEOUT in /secure/include/config.h
Don't do this with a Windows editor.

2) update /secure/daemon/master

3) update -r /lib/player

Instead of the updates you can reboot the mud.


How do I permit all users who log in to become creators automatically?

1) Set AUTO_WIZ
in /secure/include/config.h to 1
Don't do this with a Windows editor.

2) update /secure/daemon/master

3) update /secure/lib/connect

Instead of the updates you can reboot the mud.


How do I limit the use of intermud channels?

1) Set RESTRICTED_INTERMUD in /secure/include/config.h to 1
Don't do this with a Windows editor.

2) Add the players who are allowd to use intermud channels to
the intermud group using admintool.

3) update /secure/daemon/master

4) update /daemon/services/*

5) update /daemon/services

6) update /daemon/intermud

7) update /secure/daemon/chat

Instead of these updates, you could just reboot the mud.


How do I get off intermud completely?

1) Set DISABLE_INTERMUD in /secure/include/config.h to 1
Don't do this with a Windows editor.

2) update /secure/daemon/master

3) update /daemon/intermud


How do I change the start room for the mud?

1) change ROOM_START in /secure/include/rooms.h
Don't do this with a Windows editor.

2) reboot the mud


I don't like having newbies get special treatment.

1) Set MAX_NEWBIE_LEVEL in /secure/include/config.h to 0
Don't do this with a Windows editor.

2) reboot the mud


I don't want players to be able to pick non-human races.

1) Set HUMANS_ONLY in
/secure/include/config.h to 1
Don't do this with a Windows editor.

2) reboot the mud

* Note that this will not affect players who are
already non-human.


I want everyone to speak the same language.

1) Set ENGLISH_ONLY in /secure/include/config.h to 1
Don't do this with a Windows editor.

2) reboot the mud

* Note that this may not affect players who already
are not native English speakers. To change them,
type:

call players_name_here->SetNativeLanguage("English")



I made a change to /lib/player.c and updated it, but I'm
not seeing a difference in my character.


If an object (you) is loaded into memory, it contains
the features and functions of its file and inherited files
at the time it was loaded.

Changing those files and updating them doesn't do
anything to an object that is already loaded using the
old code.

In a case like this, what you want to do is
recursively update the file of the object in question,
then reload the object.

Let's say you modified /lib/npc.c so that
npc's sit down by default. Say you want the fighter in
your test room to possess this new functionality.

If you type: reload -r fighter

then the fighter's file is recursively updated,
the current version of the fighter is whisked away, and
a new version of the fighter is created, incorporating
the new auto-sit feature.

If the change in question is to lib/player.c
or some other file inherited by you, you would
type:

update -r /lib/creator

But you are still using that same old body as
before, so you'll need to quit and log back in to
get a new body using the new code.


How do I change the items new players receive?

Look in /lib/player.c for the function that gives
new players jeans and a t-shirt. Modify this
function to suit you. Make absolutely sure that
the objects you put there actually clone
correctly.

Remember to bk /lib/player before editing this file,
because if you screw it, then log off without
restoring a working copy, you will be sad.


Hey, there's no <foo> class! What's up with that?

True, there is no samurai class, and in fact, as of
this writing there is no cleric, acrobat, frombotzer,
or basketweaver.

The reason for this is that the Dead Souls
mudlib distribution isn't intended to be 100% ready for
players to show up and start doing quests.

What quests there are, what races, classes,
areas, objects, rooms, and NPC's you find in the
distribution are examples. If you open your mud
to players and what you've got is the Orcslayer and
newbie mansion quests, you might as well just close down.
In fact, please do.

Dead Souls is a starting point for a mud.
I have no way of knowing if you're going to have
mermen in an aquatic-theme mud. I have no clue
whether your space aliens will have 8 tentacles or
16 (they like base2, dontcha know).

So, no, there's no <foo>, because the
responsibility for making the mud in your creative
vision is yours, not mine. My job is to give you
a lib with enough working examples and enough
documentation so that you can code your own
basketweaving bugblatter beasts.



Where can I get a Dead Souls mud hosted?

That's a heck of a good question. There are many mud hosting services
out there. I hear good things about Kyndig, but that isn't specific
to Dead Souls. A good host will have a high level of service, shell
and file transfer access, etc, for which you obviously will need
to pay money.

There is at least one free mud hosting service I'm
aware of, and that's FrostMud. It's basically a guy and a Linux
server with room on it for muds. If you beg adequately, he might
let you put your mud on his server for free. I tested it and
Dead Souls installed and ran there without any problems. However,
he doesn't support anything, you're on your own, and bandwidth is
on a "you'll get it when it's there" basis.

There's no such thing as a free lunch. If you want
a reliably solid, well supported, feature-rich platform for your
mud, quit being a cheapskate and cough up the $20/mo. That's
like, what, one espresso every couple of days.

If you have a DSL or cable modem, and your computer is
up all the time, you can just use that, too. Your IP may be
dynamic, making it tough for people to find you, but there are
dynamic-dns services out there that help keep your ip
tied to a specific name.

If you're really hard up you can email me and beg for
me to host you for free, but expect me to be hostile about it,
and you'll get no fancy schmutz like a web page or shell access.
And if your mud gets on my nerves (being inactive for a long
time is enough to do that) I'll just wipe it. Possibly without
even warning you. It's not that I'm a jerk or I like being mean.
I just don't have a lot of time for nonsense.


Your LIB_MXLPLX system is all screwy. I changed it and it works. Wanna see?

Hell yes. I'm not just in this for my health. I want
more people coding in LPC so I can look at the fresh ideas and
new perspectives of other people (read: swipe code).

Send me an invitation to your mud by email or <ds>. I'd
love to look at your work.

If it is code you are willing to donate to Dead Souls, I
will gladly accept its submission, also by email. There's no
guarantee it will make it into any future release, but it just might.

Please be aware that by doing so, you release your normal
copyright to the code and license it GPL, allowing me to publish it and
preventing you from revoking my right to distribute it.

You also represent that you *have* copyright to do this
in the first place, and hold me harmless in any subsequent
dispute between you and any other third party.

If you want to email me code but wish to retain normal
copyright, please state so clearly in the body of your email. I
will honor that request
(and it's the law so I don't really
have a choice). Just be aware I will not put code into Dead
Souls that anyone has non-GPL'ed copyright to.

Also, I don't want to hear from anyone about my
use of legal terms of art. I know damn well it's more complicated
than I make it sound. My phrasing is sufficient to make
the legal practical transaction of ideas possible here.


How are files organized in Dead Souls?

cd / and ls to view the top level directory. The
list may be largely meaningless to you, so let's review it here:

cfg/

General configuration files for timezone and such.

cmds/

Main location of commands that don't require special access
privileges. Commands are different from verbs in that they tend
not to manipulate your environment, but rather deal with
the player's relationship to the system and/or files.


daemon/

Daemons are files that provide access to data files in an
organized way. For example, adding an occupational class
(like, say, assassin) to the game needs to be done in a
precise way in order for it not to break things. By sending
the data to the daemon first, you can be sure that the
new system configuration is entered properly. Daemons also
provide a means to access data, like "how much is silver
worth compared to gold", that is uniform across the mud, and
prevents accidental overwrites of data files by multiple
editors.


doc/

General documentation.


domains/

This is where MUD game areas go when they are complete
and ready for general play by the public. Once here, only
admins have write access to the files.


ftp/

The base for the MUD ftpd. Using the ftpd is probably dangerous
in terms of your system security, and I discourage it, but if
you are determined to have mud ftp access for your creators,
this is one way. See /secure/lib/net for the actual server. It
may or may not work. I won't support it.


include/

Include files provide a set of constants for your files. For
example, if you include <damage_types.h>, you can specify in
the code for your chainmail that it protects against
the damage type "BLADE" at a certain level.


lib/

This is the heart of the Dead Souls lib. This is the location
of the files that your objects, be they swords, shoes, or
handguns, will use as their configuration base.


log/

Log files.


news/

Announcements are made here. For example, in /news/creator
you can post a notice that you have added a teleportation
spell, and when your creators log on, they will see the message.


obj/

Contains some important templates, especially some for the QCS.

open/

Legacy directory. Kept for compatibility. Historically this
directory has served as a place where creators can put code
for others to freely modify.


realms/

This is where creator home directories are.


save/

Files that describe properties of the MUD's systems live
here. The number of limbs that a bat has, for example,
is in races.o. In classes.o you'll find the skill ranges
for fighters. Do not edit these files. They must be
modified by daemons only, or you risk corrupting them.


secure/

This directory will be described in a separate section below.


shadows/

Shadows are a controversial feature of LPC. This directory
is designed for shadow objects, but they should be very
rarely, if ever used. Basically shadow objects are objects
that attach themselves to another object, intercepting
function calls. For obvious reasons this is a security
risk, so unless you really really know what you're doing,
avoid them.


spells/

Pretty self explanatory. The spells daemon looks for spells here.


tmp/

A directory anyone can write to. Generally for swapping
data between objects, systems, or people.


verbs/

Another controversial topic. Verbs are a kind of command. For
example, go and sit and open are verbs. Specifically, verbs
are commands that interact with the user's environment. The
idea is that throw my first red rock at the green goblin
should work, and should work the same everywhere on the
MUD. Verbs are a source of debate among some people, because
to folks accustomed to add_action commands, verbs seem
excessively complex.

www/

Like the ftp directory, but for the MUD webserver.


Ok now let's take a quick look at the /secure directory: ls /secure
As you can see, /secure seems to have many of the same directories
that the root filesystem has.
The reason a /secure directory is needed is that
there are files that should not be readable by everyone, and
there are files that must be writable only by a few. The MUD security
system uses the /secure directory as a means to control access to
such files.
For example, the average creator has no business
accessing the player data files of other creators or players. Therefore
/secure/save/creators and /secure/save/players is offlimits to them.

A directory without a counterpart in / is /secure/sefun. This
is where simulated external functions reside.


What are sefuns and efuns?

First let me explain that the driver has built-in
functions that are available to the mud. For example,
type eval return find_player("cratylus") , but replace my name
with yours. Your player object pointer will be found and returned
to you (more or less. strictly speaking it's more complicated).
The driver provides this function. Because it is "external"
to the mudlib, that is, it's in the driver and not the lib,
it is called an external function, or more commonly, "efun". The
idea is that certain actions you ask the mud to perform are
so common that they are made available MUD-wide.

Efuns are ridiculously useful and powerful, and because
they are in the driver as compiled code, very fast. A near-complete
set of efun documentation is available in /doc/efun.

However, the driver does not contain every possible
MUD-wide function you might want. For example, there is a
tell_object() efun, which lets you send a message to an object
such as a player. The syntax is something like this:

tell_object(find_player("cratylus"),"Hi.");

Which doesn't look like much, but believe me, this
kind of stuff adds up. I wanted to make this simpler, so I
used what is called a sefun, or a simulated efun. It is
a function that is available lib-wide, but it isn't in
the driver. Instead it is provided by the lib itself (the
master daemon, specifically). By adding the appropriate code
in /secure/sefun/ I have now made available a tell_player() sefun,
which works like this:

tell_player("cratylus","Hi.")

This simplification of code will become more obviously
useful to you as you get more coding under your belt. Most
sefuns are documented in /doc/sefun.



Whew! Ok now I know where stuff is. What's next?

You probably want to examine how objects are written.
Type goto /domains/town/room/road and wander around town
a bit. If you want to see the code for something, for example,
the beggar, about beggar should do it, provided the beggar is
in the room.

To see the filenames of the objects around you,
type scan here, or scan me to scan your own inventory.

If you've never coded before, this is the hard part.
To understand what you're looking at when you run commands like
more /domains/town/weap/orcslayer.c you need to get comfortable
with LPC.
The brute force way of doing this is copying stuff
and then changing the descriptions, thus making new stuff.
This will work, but you'll waste time looking for examples of
exactly what you want to do..and you may not find them.
Instead, learning LPC will let you create whatever
you want, without relying on templates.

This means that now you must read the LPC Basic
manual, then the LPC Intermediate manual. As admin, your
creators will expect you to know what's in there.

On your person or in the chest in your workroom is
the Creators Manual. Read both the Players Handbook and
the Creators Manual from cover to cover.


Oh, man, you're kidding! Those are, like, books! Can't I
just start making stuff?

Well...ok. But you need to go through the docs
soon, ok? In the meantime, read the QCS chapters in the
Creators Manual to get you quick-started in the creation
process. Remember you need to be holding your Creator
Staff in order to access the QCS commands.

Other useful tools in your chest are a remote
control and a medical tricorder.


Everything is su-u-u-u-p-e-e-r-r-r s-s-l-o-o-o-o-w-w-w

First, make sure you are using the latest available version of
Dead Souls (check here or here). Older versions of Dead Souls
are known to have nasty memory leaks.

Next, see if you have runaway objects. An object can be coded
to do really unpleasant stuff like replicate itself over and
over until it brings the mud to its knees. Find out how many
objects are loaded by typing: eval return sizeof(objects())

If the count is in the thousands, and only a few people are
logged on, you may have a runaway. Most often this involves
NPC's doing stuff you didn't expect. Reset all loaded rooms
with the following command:

resetall

perhaps followed by a:

flushobs

If the lag clears up, you found the culprit. If not, see if
the callouts list is clogged with the command: callouts

If all else fails, reboot the mud and ask for help on the ds line.

Please note that the rage virus (especially if unleashed
in the menagerie) is notorious for redlining the mud. Having
hundreds of NPC's all engaging in simultaneous combat
while infecting each other with a rapidly spreading hostility
virus can be expected to impact overall performance. So please try
to avoid the rage virus unless you are specifically stress testing
your system.


Dude! One of my creators just kicked me off my own mud!

One of the virtues of LPC is that it is flexible and powerful.
One of the drawbacks of LPC is that it is flexible and powerful.

It is not possible to make an LPC mud that is
immune to abuse from creators. You just can't. The MudOS
function set is just too complex and sophisticated to eliminate
every possibility of abuse.

You will therefore *always* be vulnerable to things
like people coding objects that crash the mud on purpose (I
won't detail how that can be done, but anyone with intermediate
LPC skill can do it, and utter newbies can even do it with
a stupid enough mistake), finding a way to dest admins, or
continually updating recursively the /lib filesystem. A
jackass will always find a way to expose you to her jackassery.

This means that you need to know who is coding on your
mud and what they are doing. Your job as an admin is to
immediately deal with coders who pose a discipline problem.
If they fool you once, shame on them. If they fool you
twice..the..they...they shouldn't fool you twice is what I'm
saying.

This does not mean that Dead Souls is somehow
impossible to secure. You can easily prevent unauthorized
access to lib data. See the next section for how this works.

What you can't prevent is some dude off the internet
you just met and made a creator from wreaking havoc on your
mud and creating a nuisance of himself. You have to know who
these people are and you have to have a level of trust and
confidence in them, otherwise you need to use the decre
command.


Is Dead Souls secure?

The short answer is no, nothing I know of is "secure" in the
sense that you don't need to continually pay attention to it. If the
question is "Is Dead Souls particularly unsafe to run?" then the
answer is no. Just like any other Internet program you use, Dead Souls
is not an obvious security risk, so long as it is not used carelessly.
And, obviously, games of any kind, including Dead Souls, should never
be installed on any mission-critical, national security, public
safety, or health care server.

Dead Souls security involves two separate spheres:

1) The binary executable and the system that runs it.

2) The mudlib and the code that you use and create.

The first sphere is probably most important. Presumably
you plan to run a mud on a computer that does other things too,
and you want to keep those things separate from your mud. The
most important thing to do is to avoid running Dead Souls as a
privileged user. In the case of Windows, this means that the
program should not be run by Administrator or anyone in the
Administrator group.
For unix users, this means that the driver should not run
under uid 0 (root).

The reason for this precaution is that if some genius
hacker manages to exploit some unknown weakness in the program,
it is better that the process they hack doesn't have full admin
privileges to the box.
This caution has little to do with Dead Souls specifically.
It is a warning I'd give to anyone planning to run any kind of network
server. You should take your own security seriously, and
if you do not understand your own security situation, you need to take
a step back and ask yourself if running a mud at all is a good idea.

Sphere 2 is lib security. In older muds, file and directory
privileges were handled by attributes on the files. If a file's
user id (UID) matched a user's UID, then that user had full access
to it. Such systems often had complex systems that evaluated
effective UID (EUID) based on the file's attributes, its parent
directory, the user's ID, possibly group id, etc. This is an
entirely valid security model, but because of its complexity,
it tended to be exploited easily and often. If you don't
stay 100% on top of such a system (just like any OS), there's
no way to be sure you won't rooted.

With stack security, privilege management is much, much
easier. A file's privilege is based solely on its location. If
a user doesn't have read access to /foo/bar/ then she can't read
or modify /foo/bar/file.c. If someone with privs to that location
copies the file to somewhere else, then the privs of that new location
are in force on the file.
The "stack" part of stack security comes from the mud
evaluating the privileges of all the objects involved in the
access request. If you're unprivileged and you manage to get a
privileged object to make the access request for you, the access
will fail, because you are unprivileged, and you are still part
of the function call stack (i.e., the list of instructions that
form a chain between the command and the intended event).

Granular (more detailed) modification of user privileges
can be done by changing files in /secure/cfg to grant
users and groups specific privileges.


I sent you my code a week ago. Is it in or out?

How long it takes me to review code submissions has nothing
to do with what I think of you, your skills, or your
code. It takes me a long time because Dead Souls isn't
actually my job, and is not a physical member of my
family, so it has to wait its turn sometimes, for my attention.
Sometimes I will get to someone else's code sooner even
though I received yours first. What can I say. Sometimes
I feel like dealing with a particular thing at a particular
time.


Did you finish the bfd() sefun modification I asked you for last night?

I'm on the ds line a lot, and generally accommodate people's
requests right away if I have time. This makes it seem
sometimes like I can turn orders around in minutes or
hours, like a short-order cook.
This is an illusion. I do this sometimes
for requests that strike my fancy or that are so simple
they are not inconvenient, or maybe because I happen to
be bored at that moment. But my sometimes doing this
doesn't mean folks should expect some sort of prompt
turnaround on special requests.
In general, I am not sitting at my desk waiting
for code orders. I'm doing something else. If I get to
your request right away, then good for you. If I don't,
then I'll get to it when I get to it.


The queeg daemon is a horrendous mess. It's inefficient and frankly offensive.

I'm not an especially gifted programmer. In fact, I view
myself rather as a Pakled from the Star Trek series. I
look for things that make the code go. I look for things
that make the code strong. Sometimes, because I am not
a trained or professional programmer, things are done
in a way that shock the conscience of more sophisticated
practitioners.
If you find such code (and I do hope it is rare),
bringing to my attention that it has been implemented in a
wretched way doesn't help me. I know that. I wrote it. If
you want to help, send me an email with the fixed code.

You implemented my code but didn't give me credit.

Whoops. Send me an email telling me where I goofed and I'll fix it.


Intermud mail doesn't work

No it doesn't. It's actually a pretty complicated system to
implement, so get used to just local mud mail for now. It
is definitely planned for the future, though.


The admintool menus let you pick options that aren't visible

I can't decide whether this is a feature or a bug. I'm
leaning toward "laziness" as the cause.


What does locking the mud do, exactly?

When the mud is locked, only members of the authorized
groups are permitted to log in. By default, these
groups are SECURE, ASSIST, ELDER, and TEST. Anyone
who is not a member of these groups, whether they are
a creator or a player, is prevented from logging in.


The race help output is inadequate for role-playing. How do I change it?

By default, help human will output various characteristics
of the human race, as known to the race daemon. If you
want instead to provide your own help data on the history and
lore of humans, simply create a file called /doc/help/races/human
and put your information in it. That information will then
be what is displayed when requesting help on that race.


I need to know what features to expect in the next release so I don't
waste time duplicating effort

Visit http://dead-souls.net/RELEASE_NOTES for information on
the latest releases and what they contain. The topmost
version is usually not yet available for download, and
is listed so that folks know what's coming in the
next release. If this is so the version name will have
"(unreleased)" next to it.



You need a development roadmap and task tracking

No, I don't. If I had developers and teams and
such things, then I'd use all the fancy project
management stuff available on Sourceforge.
But I don't want to manage developers,
I want to lib code. If you want to help develop
the lib, then that's really great. Follow the instructions
from the previous question and look at my plan file
for something that looks interesting and that
doesn't have an asterisk. Tell me you'd like
to take that project, and I'll mark it as yours.
That's it. Send it to me when yer done.
If I get tired of waiting I'll tell you
I'm going to do it myself, like I was planning
all along, and you'll be relieved of that expectation.
Setting up some kind of sophisticated
collaboration tool to get 3 pieces of code from
2 people, and me having to be on people's backs
for results and stuff...this is not what I
signed up for and I'm not doing it.


How do I update a sefun without rebooting the mud?

To have your new nit_pick() sefun take effect in the
running mud, you might do something like this:

update /secure/sefun/nit_pick.c

update /secure/sefun/sefun.c


My new sefun updates but I can't seem to use it.

Make sure the sefun is prototyped in /secure/sefun/sefun.h

If the sefun is in a new file you created, make sure
that /secure/sefun/sefun.c inherits that file.


What's the point of the apostrophe-stripping for args in lib/command.c?

It's a cheap workaround for a parser problem. The full fix
is forthcoming.


How does one achieve 'high mortal' or 'ambassador' positions?

Those are legacy positions from Pre v1 Dead Souls. They are
basically groups, managed by an arch with admintool, which
can be granted privileges not normally enjoyed by mortals.
In the current implementation of Dead Souls, those
positions are vestigial. You can implement them on your
own mud however you please.


I would like XYZ and PDQ to happen every time the mud boots

The most common way to have this happen is to add
your daemon (and typically that's what you'll
want to start at boot) to /secure/cfg/preload.cfg .
This will ensure that it gets loaded
before the mud accepts any connections. It has the
added advantage of being included in the list of daemons
that the mud periodically checks and restarts if they
have died.

If it isn't a daemon, but rather some
specific function you want to happen at boot, simply
add the relevant code to /secure/daemon/autoexec.c


I can't login! I keep getting: "It seems some work is being
done right now, try later."

This is very bad. What this means is that some
files that are needed in order to load your player
object cannot be loaded. It can be any of a very large
number of files, which is the problem. Usually this
happens if you've been, for example, messing around
with player.c, then broke it, and rebooted the mud. Now
since player.c can't be loaded, you're locked out.
It could be any of the files loaded by your
player object, or other daemon files needed by your
login. The only way to narrow down the possible list of
files you corrupted is by examining the output of the
console (the window where you type the command line
to start the mud) and reviewing log/runtime and
log/catch for clues.
Once you've found the culprit, either fix it,
or replace it with the original version from the
Dead Souls distribution package.


I had a really great idea that revolutionizes ds and you
refuse to include it. I am forking ds development and
making my dream come true.

Ok then, have fun. All I ask is that you give your
project a name that isn't going to confuse people
as to which lib is which. Confusing your user base
isn't a good way to get started on such an enterprise.
Send us a post card once in a while.


What do the version numbers mean?

2.0r16 means "Major version 2, minor version 0, release number 16".
Releases happen pretty frequently, to add functionality and fix bugs
from the previous release. When the basic functionality of a minor
version is as bug free as reasonably possible, a new minor version
change happens.
Major version number changes are very rare and represent a
vast difference from the old major version. Versions 1 and 2 of
Dead Souls are so different as to be largely incompatible with each
other's code.
As of this writing, the goal of releasing version 2.1 looms.
The significance of this milestone is that Dead Souls 2.1 is
intended to be the fulfillment of the promise that there was in
version 1.1. After the release of Dead Souls 2.1, the focus of
development will be in adding major systems and functionality
that 1.1 was hoped to have, but never did.

- ! Cratylus

! Dead Souls Homepage
! \ No newline at end of file diff -c -r --new-file ds2.0r19/lib/www/ds-creator-faq.html ds2.0r20b/lib/www/ds-creator-faq.html *** ds2.0r19/lib/www/ds-creator-faq.html Fri Mar 24 14:42:02 2006 --- ds2.0r20b/lib/www/ds-creator-faq.html Sun Apr 9 23:48:47 2006 *************** *** 1,296 **** ! ! ! ! Dead Souls Creator FAQ ! !
Dead Souls Creator FAQ, v2.3

Written by Cratylus @ Frontiers, March 2006

Note: commands are displayed in boldface, like this: ls -a

What's this FAQ about?


There are common issues and questions that crop
up for most new creators. This document is intended to
ease or at least shorten what can be a steep learning
curve.


!
!
Section 1: Getting Started


My question isn't on here. Where can I get an answer?

There are four main ways to get specific answers:

1) Ask your mud's administrator, or other creators on
your mud by using the cre channel, like this:

cre does the flux capacitor use verbs or add_actions?

To know what local channels are available on your
mud, type: lines


2) Your mud is probably on the intermud3 network. If
your administrator has not restricted intermud channels,
you should be able to ask questions on the Dead Souls
intermud channel, with a command like this:

ds hi! can someone tell me what room Leo lives in?

3) If intermud is down, or nobody is answering, or
you have a bug to report, you can also try emailing
me, the author of this doc, at: <my name here>@users.sourceforge.com


4) If intermud is down, you can also log into the
Dead Souls demo/development mud at dead-souls.net 6666
This mud automatically promotes users to
creator status, allowing guests to get a feel for
what developing on Dead Souls is like, and to provide
examples of current and not-yet-released lib code.
You can try to log into that mud and see if anyone
is available to answer your question.


Important note about asking on <ds>:

Part of the reason this FAQ was written is that
people who ask questions on the ds channel often do not
realize that same question has been asked many times
before. If you ask something like "how do I read the
channel messages I missed?" without first bothering to
read this doc and others, you just might get a response
that's less friendly than you might have expected.
People on the channel really want to help you,
but if it seems like you're not willing to put in the
time to try to help yourself, they might choose to
ignore you until you gather some clues on your own.

Something else to remember is that we are not
on your mud and we don't see what you see. "Why won't
my workroom update" lacks enough information to let
anyone try to help, but "when i try to update my
workroom I get <error message>" might.

Similarly, some things don't have an answer
that is suited to ds. "could someone help me
understand the score.c file?" or "how do quests work?"
have answers that are long, complex, and are
already covered in the documentation available
to you.

Some stuff just doesn't have an answer
that can be explained to you unless you already
have the experience you'd need to know the answer.
for example:

- How do I make a stargate that has a dial for
going to different places?

- How do I make it so a player can be on different
planes of existence, and what they see when they
look around depends on what plane they're on?

- How do I add limbs so people can wear stuff
like kneepads on the knee only?

These three questions illustrate things that are
totally doable, but whose explanation is so
complex and full of judgment calls that there
is no way of satisfying the question without
making you magically understand intermediate-level
LPC coding.
That doesn't mean they're bad ideas, or
even that hard to implement. It's just that
the questions can't be answered until you read
and understand the Creator's Manual, and by that
time, you'll know the answer on your own.

Make sure you've read the docs, then ask
the question in a way that makes it clear you aren't
just a lazy person who wants other people to do her
work, but rather a hardworking builder who has
tried to fix something and needs a specific answer
to a specific question that isn't already in the
FAQ's or the docs.

Critiques are welcome, but they should
be constructive. "This combat system is slow and
stupid" is unhelpful and might be taken as a
hostile statement. Instead you could phrase it
in a way such as: "Combat is slower than I
expected. Why? I used to play on LeetFooMud and it
took less than a minute to kill Tiamat." It's still
a bit clueless, but it's a fair question that can
be answered on its own terms without starting
a flamestorm.


The ds channel is too spammy. It's distracting me.

Enable or disable a channel by typing just its name. Like:

ds


All I did was change one thing in a file, and now it won't update. Help!

You should make it a habit to make backup copies of files
before editing them. That way, if you screw up the code, you can
just copy the backup to the original filename.

A convenient way to do this is the bk command. See
the debugging page for an example of its use.

If you are using Windows, you need to be aware of the
linefeed problem. unix text files and DOS text files have different
formatting. If you edit files in Notepad, then try to update them,
you may find that the file no longer updates, no matter what
you do. The difference is usually invisible to you, so you can't
tell why a file that looks exactly the same as before now won't
work.

Dead Souls expects unix-formatted text, and if you feed it
something else, the results aren't likely to be to your
satisfaction. Make sure you use an editor that respects unix
text. In Windows 2000, WordPad seems to do a reasonable job of not
completely screwing things. It does, however, add carriage
returns to your lines, so when you look at them in ed, you'll
see a bunch of "^M"'s all over the place.

If you still have trouble, take a look at the debugging page.


The mud editor is confusing the heck out of me. It's too hard to use.

Check out the MUD Editor tutorial. It should ease the pain a little.



When I log in, everything is screwed up, and I can't do anything!

This happens sometimes when you log out while carrying an object
with broken code. If for example, you are wearing a vest, and then you
edit the code for it, but it doesn't work anymore, then you log out,
what happens is the next time you log in the mud will try to restore an
item in your inventory that throws an error, and your login
gets stuck halfway.

If you find that when you log in things are all screwed up for
you, use the rescue login feature. For me, this means I would
login as cratylus_rescue instead of cratylus. My inventory
will get wiped before my playerfile is loaded, and I'll
be able to log in with no problems.


Ok, I'm a creator now. What am I supposed to do?

Ask your admin.

If you're like most other creators, you have
a creative vision you want to implement and share with others.
you want to create dragons, or spaceships, perhaps dragons
in spaceships. This makes you a "builder".

As a builder, your job is to learn how your mud
works so you can get your neat ideas turned into a
virtual reality. As you might have guessed, nobody is
going to jack into your brain and upload coding ability
into you. You need to learn how to move around, how
the creation system works, and yes, you'll need at least
some passing acquaintance with the stuff your mud is
made of: files written in the LPC language format.

The good news is that it's nowhere near as hard
to learn as C++. LPC is very powerful, but it doesn't
require you to be a master to get simple things done.

Your first steps as a new creator probably should
go something like this:

1) Talk to your admin. Understand what is expected of
you, and what the rules of your mud are.

2) Go to your workroom by typing: home. Read the helpful
notes that are posted there for you.

3) Read the Player's Handbook, cover to cover. It isn't
long, and you will need every bit of information in there.
This is not a suggestion. You need to read the handbook.

4) Open the chest in your workroom, and play around
with the tools and toys in there. Having read the
handbook will help you deal with any issues you have
handling these items.

5) Type wiz to go to the Creator's Hall, and if there
are any posts on the board, read them. To read the
first post: read 1. To read the second, read 2, and so on.
If you decide to write on the board,
remamber that to exit "writing" or "input" mode,
you need to enter a dot on a line all by itself,
like this:

.

6) Once you get a feel for how to move around,
what playing here is like, and how to do stuff, you
can start exploring your creator powers. To get
a grasp of the very basics of navigating through
files and directories, type:

more /doc/BASICS

Yes, you must include capital letters. Dead
Souls distinguishes between upper and lower case
letters in filenames.

To get a feel for what Dead Souls LPC code looks like,
wander about town and use the about command to read
code that compose the objects there. For example:

goto /domains/town/room/road

about here

about beggar

Or move around in your own home
directory and check out the defaults and templates
there:

cd /realms/<yourname>/area/npc

more fighter.c

To bring a copy of that fighter to life:

clone fighter

To make him dance:

force fighter to dance

To kill him:

zap fighter

To get rid of his corpse:

dest corpse

7) Once you're done having fun with your godlike
powers, it's time to start learning how to make
fun stuff of your own.

For a quick start in building, you
can start reading the Creator's Manual at
chapter 31, which is where the QCS section begins:

read chapter 31 in manual

read chapter 32 in manual

and so on.

That's fine to start with, but eventually
you'll need to read the whole Creator's Manual.
If you don't, 90% of the questions you ask about
code could be fairly answered with: "read the manual."


This is weird...where is the online builder? How does
new stuff get compiled?

Dead Souls can be very strange to people used
to non-LPC muds. This is because many other kinds of
muds use a system where the mud is written in C++,
and to make changes, you need to add C++ code to the
source, recompile it, then reboot the mud.
In that kind of system, building is done with
tools where you fill in blanks and code is generated
for you. I presume that some C++ expertise is
required for doing anything unusual or fancy.

If you come from this kind of environment,
you may be in for a little disorientation. On a Dead
Souls mud, there is no need for compiling code. You
don't need to reboot the mud for new stuff to
be available.

You can add your new Orc God of War to the
game (after you code him, of course) with two
simple commands:

update /realms/<you>/area/npc/grimmash.c

clone
/realms/<you>/area/npc/grimmash.c

You're now face to face with him. This makes
Dead Souls, like most LPC muds, very flexible in
what can be done, and very stable in terms of
needing few reboots. Reboots typically are
necessary only when someone breaks important
code, or to implement major mud-wide changes.

So, just write your code, and update it.
It's that simple. There are two main ways to do
this. The easiest way is with the QCS, or quick
creation system. With the QCS, you don't even need
to look at code. You just issue a few commands,
and your new whatever is there. Check out an example
of the QCS here.


To learn the QCS, read the Creator's
Manual starting on chapter 31.

The other way to create on-line is
with the ed command. The ed editor is a powerful
and flexible way of editing files. Some people
find it difficult at first, and you might even
be able to avoid it for a while if you mostly
just use QCS. However, you'll eventually need to
know a little about ed. For a tutorial, go here.

For more detailed documentation,
type: help ed


I explored around in /domains/Ylsrim and <XYZ> is broken

Ylsrim is kept in the distribution as a kind of
sentimental artifact. It's the demo area that the
original Dead Souls shipped with, and although
it's mostly been fixed up to work with Dead SOuls 2,
things can behave unexpectedly.


I explored around in /domains/town and <XYZ> is broken

Please send me an email and let me know, so I
can fix it. Also let me know if something in /domains/default
is hosed up.

!
!
Section 2: Code

What's the QCS?

Please see the QCS example page for an explanation of this
important Dead Souls system.



SetUnique doesn't work.

SetUnique() is probably doing something you
don't expect. When an item is loaded into memory, and
it has an inventory, it first checks each of those items
for whether it's supposed to be unique.
If it is supposed to be unique, then we look
through the list of loaded objects to see if there is
one of these items already cloned. If there is, then
we don't clone a new one.
What this means is that if I kidnap Leo the
archwizard and hold him in my workroom, another one will
not appear in the basement until my Leo is dested.

Note, however, that this does NOT mean that the
mud will never have two Leos. I can clone however many
Leos I want. But as long as one or more cloned Leos
exist, the basement will not make another. That's
what SetUnique means.

Now, if the behavior you're seeing is different
from what I described, maybe SetUnique is broken,
and you should email me with what you're seeing.


I made a magic wand that disappears after 10 minutes.
But if a player logs out and log back in, they have
another 10 minutes! How do I fix this?

What's happening is that you are keeping
track of how old the wand is, perhaps with a
variable named Age. But if the player quits and
logs back in, then the wand gets cloned again, resetting
all its values, including Age, to the original.

The way to make the Age variable survive
logouts is with AddSave. If you give your variable to
AddSave as an argument, that variable gets saved when
the user quits, and when they log back in, it is restored,
preventing cheating.

See /obj/wed_ring.c for an example.


Where is it saved?

In the player's playerfile, along with the values of all
the objects they were carrying when they quit.


How do I add or remove emotes?

That is an admin job. You admin would use the
addemote or removeemote commands.


How can I tell what files something inherits?

Use the showtree command. To know what files
are inherited by your robe, for example:

showtree /domains/default/armor/robe


How can I find the filename of something?

If it's in your environment: scan here
If it's in your possession: scan me

The number sign (#) and numbers at the end are that
object's unique identifier.


What's the largest integer usable by the mud?

2147483647


How can I find out what functions exist in something?

Get its filename and use the functions efun. For example:

eval return functions(load_object("/domains/town/obj/sign"))


object::init() is broken!

It isn't really. Unless you're coding a lib
item, you should not be inheriting LIB_OBJECT for
"tangible things" anyway. You should inherit LIB_ITEM.

The reason
object::init() fails is that LIB_OBJECT
doesn't have an init() function to call.


if(ob->GetFoo()) seems to break, but I don't know why

This function will error if ob does not exist. Unless
you are 100% positive ob will exist (and really, even if so),
it should look like this:

if(ob && ob->GetFoo())

Which means "if ob exists, and it has a foo".
This way, if there is no ob, the check stops right there
without getting hosed up on the next step.


How do I add color to my descriptions?

There are various markup tokens you can use for this. They look like this:

write("%^BOLD%^GREEN%^ This text would be in bold green letters %^RESET%^ and this would not.");

The %^RESET% is important. Without it, unpredictable things can happen.

To know what colors are available, type: colors

You should probably avoid color unless there is a compelling
reason for its use. Many mud admins discourage it because it can
distract from the game and cause uniformity issues: most mud
admins feel their mud text should look more or less
the same everywhere.


How do I turn the integer 42 into the string "forty-two"?

cardinal(42)


Can I use !=NULL as a test?

In theory, I guess so, but I doubt it'll work by default, and I'd
discourage you from doing anything so non-LPC-standard.
Instead try something like one of the following:

if(variable)
if(sizeof(variable))
if(variable != "")


I want to create and test a new command for the mud,
but I'm not admin so I can't put anything in the
normal command paths. What can I do?

Put your new command in your homedir's cmd/
subdirectory. A sample command is there already
to serve as a template. When you add a command, type:

update /daemon/command

for it to show up in your path.


How do skills work?

Skills are generally class-based, meaning that they are
specified in the class files found in /secure/cfg/classes.
Skills are only meaningful in terms of library objects that
understand them.

For example, a fighter's blade attack is useful because
player.c and combat.c make use of this skill as a
modifier.

But adding a basketweaving skill to a class is not
helpful unless there are library objects (looms, perhaps,
or straw) and verbs (weaving, maybe?) that make
use of that skill.

An upcoming feature is race-based skills, such
as poison bite or breath attack. These skills are
specified in /secure/cfg/races.


How do classes work?

Basically, having a class gives you special skills.
That's it. See the above section, "How do skills work?"


How do virtual rooms work?

Virtual rooms are rooms generated on the fly by a
virtual room server. You program that server with
the room descriptions, the number of them,
etc, and the virtual server can make available
a grid of rooms with your descriptions.

This allows you to create, for example,
a vast desert, or a large jungle, comprised of
dozens, or hundreds, or thousands of rooms
without having to manually code each and every
single room.

For an example, take a look at

/domains/town/virtual/



How are files organized in Dead Souls?


See the admin FAQ.


What are lfuns, sefuns and efuns?


Sefuns and efuns are functions available to all objects on the
mud. Any object may need to know what time() it is, so rather
than have a time() function in every file that needs it, which
could be many, there is a time() function built into the
game that any object can use. An efun is built into the
driver, so there is no LPC code to look at. A sefun is a
simulated efun, coded in LPC. Sefuns are kept in /secure/sefun.

Lfuns are functions specific to library objects. A shirt,
for example, has functions that a sword may not need, so
the LIB_ARMOR and LIB_WEAPON files contain their own functions,
not shared by other files (it's more complicated than this,
but that's the idea). These functions are library
functions, or lfuns. Typically they are found in the objects
defined by the files in /lib.

For a lot more detail on efuns and sefuns, see the
admin FAQ.


Why are there more sefun doc files than sefun files?

Sefun files, like /secure/sefun/strings.c, often contain
more than just one sefun. Therefore, there will be more
files documenting individual functions than there are
files containing sefuns.


I edited a file but now the reload command is complaining.

There are two commonly used commands for loading
objects: update and reload.

When you want to load a file into memory, you use
update, for example: update /domains/default/room/road

When you want to replace a cloned object with a
version that uses the latest code in a file, you
use reload, for example: reload my first red sword

reload doesn't work on files.

update doesn't work on cloned objects.


this_player()->GetName() returns "A shadow" when the player is invis.

Use this_player()->GetKeyName() instead.


Is there a sefun for making a whole string uppercase?

upper_case("omgwtfroflmao")


What is the difference between filter() and foreach()? How do I use them?

Both of these efuns can act on the individual members of an array.

For example, if you wanted to have an array named mystuff which
contains the filenames of all objects in your inventory that
inherit LIB_ARMOR:

using filter:

object *stuff = filter(deep_inventory(this_player()), (: inherits(LIB_ARMOR,$1) :) );
string *mystuff = filter(stuff, (: base_name($1)+".c" :) );

using foreach:

string *mystuff = ({});
foreach( object ob in
deep_inventory(this_player())){
if( inherits(LIB_ARMOR, ob) ) mystuff += ({
base_name(ob)+".c" });
}

There are arguments favoring the use of either. I won't get into
it. As far as I can tell, it's really a question of preference.
You can structure these functions more elegantly
than shown here, to best suit you. But this is the idea.


member_array() is returning exactly the wrong thing

It probably isn't. member_array() seems somewhat counterintuitive
at first, because it often returns a 0 as a "hit".

What this function is doing is checking to see whether the
first argument is a member of the array specified in the second
argument, and then tells you *which* element it is. for example:

member_array( "bar", ({ "foo", "bar", "baz" }) ) returns: 1

member_array( "foo", ({ "foo", "bar", "baz" }) ) returns: 0

Why does it return 0? Because "foo" is element 0 of the
array. If this_array ==
({ "foo", "bar", "baz" }), then
this_array[0] is "foo". So member_array("foo", this_array)
would return 0.

If the first argument is not a member of the array, member
array returns -1. So that:

member_array( "shiz", ({ "foo", "bar", "baz" }) ) returns: -1


Example:

Does this player know how to polka? Return 1 for yes:

RIGHT: if(member_array("polka dancing", this_player()->GetSkills()) != -1) return 1;

WRONG:
if(member_array("polka dancing", this_player()->GetSkills()) ) return 1;
 
The first way says "If 'polka dancing'
has an element number that isn't -1,
then it is a member, so let's return 1"

The second way says
"If 'polka dancing' has an element number that isn't 0,
then it is a member, so let's return 1"

The problem with the second way is that it is possible for "polka dancing"
to be element 0 in that array, and if it is, your code will incorrectly
tell you that you can't polka dance. But worse than this is that if
you actually can't polka dance, this second way will incorrectly tell
you that you can. Given random input, the second way would be wrong more than
half the time.


I'm trying to add two mappings together and the results are bizarre

Adding mappings together has to be done just so in order for
it to work the way one might expect. What can happen in
mapping arithmetic is that in the process of trying to
add the values of one mapping to another, you can change the
values of a mapping you didn't intend to. The deal is a
conflict between passing data by reference or by value. To
be sure that you don't accidentally modify an innocent
bystander, use the add_maps() sefun. For example:

MyMap = add_maps(HisMap, HerMap);

or

MyMap = add_maps(MyMap, HerMap);


When str = "abc", str[1] is 98, not "b". What gives?

What you're getting here is the ASCII code of element 1.
If you have to have that element as a string, use the
convert_ascii() sefun, like this:

convert_ascii(str[1])

You can instead use ranges, so that:

str[0..0] == "a"
str[1..1] == "b"
str[1..2] == "bc"

If you use ranges, do not use the convert_ascii() sefun.


How do I make an array1 that is the same as array2 but without an element?

To do this with just the first instance of the element:

array1 = array2 - ({ element });

To avoid any instance of the element:

array1 = filter(array2, (: $1 != element :) );


How do I pass arguments to a pointer in a functional?

With commas, like this:

(: eventKill, player :)

Your arguments will likely need to be global variables.


What should I do or not do in my code?

1) Avoid using call_out() as much as humanly possible.
Use heart_beat() to time things instead.

2) Don't code stuff that replicates itself.

3) Don't code stuff that circumvents security. For
example, knowing that an admin is logged on but
invisible isn't much help to you if he bans you
for coding a tool to find him.

4) foreach() and filter() are faster than for() loops,
and harder to screw up.

5) switch() is faster and more economical than if()
for multiple evaluations.

6) Don't use callouts.

7) Don't use add_action for something that already
has a verb. There is no point in making an add_action
for "throw", for example. It's just going to confuse
players when your "throw" doesn't behave the way
"throw" does everywhere else on the mud.

8) Callouts are bad, mkay?

9) Don't code delays by using loops. This affects the
whole mud. If an action is to be delayed, use heart_beat().


!
Section 3: Intermud and channel stuff


How do I know what other muds are online on intermud?

Type: mudlist

To see online Dead Souls muds type
: mudlist -m dead


Hey, LeetFooMud is online! How can I tell if Biff is logged on?

To see who's logged on: rwho leetfoomud
To tell Biff hello: tell biff@leetfoomud hello
To see if Biff is listening to <ds>: list ds@leetfoomud
To check out Biff's personal info: finger biff@leetfoomud


That's weird...mudlist says LeetFooMud is there but I'm not getting anything back.

The mudlist command reports on data retrieved the last time
the intermud daemon received an update. This means that if
LeetFooMud dropped off, say, 10 minutes ago, or if your own
intermud connection is down, your intermud commands are falling
into the void.

To see if your intermud connection is up, type: wiz
This takes you to the Creator's Hall, where a sign indicates
your mud's intermud connection status. This sign may be up
to 15 minutes out of date.

You can also test your mud's intermud connection with
the ping command, like this:

ping dead souls

ping frontiers


I heard there are intermud channels that talk between other muds,
not just Dead Souls muds. How can I use them?

Ask your admin. Those channels may not be open for
use on your mud.

If you talk on <intercre>, be polite, and use the same rules
of common sense and intelligent questioning that you need
to follow for <ds>. <intercre> is for code and technical
questions ONLY. Do not ever spam it or use it for chatting.

I strongly discourage you from talking on <intergossip>. I
assure you nothing good will come of it.


Howdo I emote on a channel?

Add the word
"emote" to the channel command. For example:


creemote compels your silence.

gets seen on the channel as:
<cre> Cratylus compels your silence.


Howdo I see what I missed on a channel?

To see the recent messages, use hist. For example:

hist ds

To see older stuff, look in /log/chan


I am sick and tired of the intermud network going down. Please fix it.

That's really out of my hands. I don't maintain the router.
I've been toying with the idea of setting up a separate intermud3
network with the Dead Souls site as the router, but I haven't
had much time to invest into it. I'm looking for volunteers to
help me set that up, and also volunteers to help me fix the
Dead Souls imc2 implementation, which is very close to working.

If you can't help with either one, then I'm sorry,
but you'll have to be patient a little longer until I can get
those volunteers.


I just wanna chat. Is there a dschat channel?

No, and there probably won't be one. You can chat to some extent
on the <ds> line, but if you're perceived as being a spammy
chatty source of noise, you may be asked to cool it.
If you really want to just chat, then use <intergossip>,
since that's what it's there for. Ask your admin for how to
do this. I don't recommend it, but I'd rather you expose
<intergossip> to your boredom than <ds>.
Alternately, there's a <ds_test> channel which is
intended specifically for spammy channel tests and such. Add
that channel to yourself and blab away, though not many
people will be listening. See /doc/README for how to add
channels to yourself.


I'll spam if I want to. You're not the boss of me.

It's true, I can't do much if you're determined to be a
jerk. If you consistently abuse channels, your admin may
be asked to limit your channel access. In extreme cases,
your mud may find itself banned from the channel in
question.
I can only appeal to your sense of fair play.
Spamming hurts people who have nothing to do with whatever
you're pissed off about. Please don't make whatever your
problem is with someone a headache for everyone.

!
Section 4: Miscellanea

!

! Someone ! amputated all my limbs and I can't do anything!

If your body ! gets damaged you can restore yourself to your
normal ! physical status by typing:

! heal ! me
!
!
! People are ! talking to me in gibberish, even though it says they're
! speaking English.

If your race is not human, your default language is not English, therefore
someone ! speaking in English would not be understood by you. As a
creator, you ! can avoid players' tedious language learning process
and simply type:

! call ! me->SetLanguage("English",100)

    Obviously this will work for other languages too.
--- 1,93 ---- ! ! Dead Souls Creator FAQ ! !
Dead Souls Creator FAQ, v2.6

Written by Cratylus @ Frontiers, March 2006
Updated April 2006.

Note: commands are displayed in boldface, like this: ls -a

What's this FAQ about?


There are common issues and questions that crop
up for most new creators. This document is intended to
ease or at least shorten what can be a steep learning
curve.


!
!
Section 1: Getting Started


My question isn't on here. Where can I get an answer?

There are four main ways to get specific answers:

1) Ask your mud's administrator, or other creators on
your mud by using the cre channel, like this:

cre does the flux capacitor use verbs or add_actions?

To know what local channels are available on your
mud, type: lines


2) Your mud is probably on the intermud3 network. If
your administrator has not restricted intermud channels,
you should be able to ask questions on the Dead Souls
intermud channel, with a command like this:

ds hi! can someone tell me what room Leo lives in?

3) If intermud is down, or nobody is answering, or
you have a bug to report, you can also try emailing
me, the author of this doc, at: <my name here>@users.sourceforge.com


4) If intermud is down, you can also log into the
Dead Souls demo/development mud at rugose.com 6666
This mud automatically promotes users to
creator status, allowing guests to get a feel for
what developing on Dead Souls is like, and to provide
examples of current and not-yet-released lib code.
You can try to log into that mud and see if anyone
is available to answer your question.


Important note about asking on <ds>:

Part of the reason this FAQ was written is that
people who ask questions on the ds channel often do not
realize that same question has been asked many times
before. If you ask something like "how do I read the
channel messages I missed?" without first bothering to
read this doc and others, you just might get a response
that's less friendly than you might have expected.
People on the channel really want to help you,
but if it seems like you're not willing to put in the
time to try to help yourself, they might choose to
ignore you until you gather some clues on your own.

Something else to remember is that we are not
on your mud and we don't see what you see. "Why won't
my workroom update" lacks enough information to let
anyone try to help, but "when i try to update my
workroom I get <error message>" might.

Similarly, some things don't have an answer
that is suited to ds. "could someone help me
understand the score.c file?" or "how do quests work?"
have answers that are long, complex, and are
already covered in the documentation available
to you.

Some stuff just doesn't have an answer
that can be explained to you unless you already
have the experience you'd need to know the answer.
for example:

- How do I make a stargate that has a dial for
going to different places?

- How do I make it so a player can be on different
planes of existence, and what they see when they
look around depends on what plane they're on?

- How do I add limbs so people can wear stuff
like kneepads on the knee only?

These three questions illustrate things that are
totally doable, but whose explanation is so
complex and full of judgment calls that there
is no way of satisfying the question without
making you magically understand intermediate-level
LPC coding.
That doesn't mean they're bad ideas, or
even that hard to implement. It's just that
the questions can't be answered until you read
and understand the Creator's Manual, and by that
time, you'll know the answer on your own.

Make sure you've read the docs, then ask
the question in a way that makes it clear you aren't
just a lazy person who wants other people to do her
work, but rather a hardworking builder who has
tried to fix something and needs a specific answer
to a specific question that isn't already in the
FAQ's or the docs.

Critiques are welcome, but they should
be constructive. "This combat system is slow and
stupid" is unhelpful and might be taken as a
hostile statement. Instead you could phrase it
in a way such as: "Combat is slower than I
expected. Why? I used to play on LeetFooMud and it
took less than a minute to kill Tiamat." It's still
a bit clueless, but it's a fair question that can
be answered on its own terms without starting
a flamestorm.


The ds channel is too spammy. It's distracting me.

Enable or disable a channel by typing just its name. Like:

ds


All I did was change one thing in a file, and now it won't update. Help!

You should make it a habit to make backup copies of files
before editing them. That way, if you screw up the code, you can
just copy the backup to the original filename.

A convenient way to do this is the bk command. See
the debugging page for an example of its use.

If you are using Windows, you need to be aware of the
linefeed problem. unix text files and DOS text files have different
formatting. If you edit files in Notepad, then try to update them,
you may find that the file no longer updates, no matter what
you do. The difference is usually invisible to you, so you can't
tell why a file that looks exactly the same as before now won't
work.

Dead Souls expects unix-formatted text, and if you feed it
something else, the results aren't likely to be to your
satisfaction. Make sure you use an editor that respects unix
text. In Windows 2000, WordPad seems to do a reasonable job of not
completely screwing things. It does, however, add carriage
returns to your lines, so when you look at them in ed, you'll
see a bunch of "^M"'s all over the place.

If you still have trouble, take a look at the debugging page.


The mud editor is confusing the heck out of me. It's too hard to use.

Check out the MUD Editor tutorial. It should ease the pain a little.


When I log in, everything is screwed up, and I can't do anything!

This happens sometimes when you log out while carrying an object
with broken code. If for example, you are wearing a vest, and then you
edit the code for it, but it doesn't work anymore, then you log out,
what happens is the next time you log in the mud will try to restore an
item in your inventory that throws an error, and your login
gets stuck halfway.

If you find that when you log in things are all screwed up for
you, use the rescue login feature. For me, this means I would
login as cratylus_rescue instead of cratylus. My inventory
will get wiped before my playerfile is loaded, and I'll
be able to log in with no problems.


Ok, I'm a creator now. What am I supposed to do?

Ask your admin.

If you're like most other creators, you have
a creative vision you want to implement and share with others.
you want to create dragons, or spaceships, perhaps dragons
in spaceships. This makes you a "builder".

As a builder, your job is to learn how your mud
works so you can get your neat ideas turned into a
virtual reality. As you might have guessed, nobody is
going to jack into your brain and upload coding ability
into you. You need to learn how to move around, how
the creation system works, and yes, you'll need at least
some passing acquaintance with the stuff your mud is
made of: files written in the LPC language format.

The good news is that it's nowhere near as hard
to learn as C++. LPC is very powerful, but it doesn't
require you to be a master to get simple things done.

Your first steps as a new creator probably should
go something like this:

1) Talk to your admin. Understand what is expected of
you, and what the rules of your mud are.

2) Go to your workroom by typing: home. Read the helpful
notes that are posted there for you.

3) Read the Player's Handbook, cover to cover. It isn't
long, and you will need every bit of information in there.
This is not a suggestion. You need to read the handbook.

4) Open the chest in your workroom, and play around
with the tools and toys in there. Having read the
handbook will help you deal with any issues you have
handling these items.

5) Type wiz to go to the Creator's Hall, and if there
are any posts on the board, read them. To read the
first post: read 1. To read the second, read 2, and so on.
If you decide to write on the board,
remamber that to exit "writing" or "input" mode,
you need to enter a dot on a line all by itself,
like this:

.

6) Once you get a feel for how to move around,
what playing here is like, and how to do stuff, you
can start exploring your creator powers. To get
a grasp of the very basics of navigating through
files and directories, type:

more /doc/BASICS

Yes, you must include capital letters. Dead
Souls distinguishes between upper and lower case
letters in filenames.

To get a feel for what Dead Souls LPC code looks like,
wander about town and use the about command to read
code that compose the objects there. For example:

goto /domains/town/room/road

about here

about beggar

Or move around in your own home
directory and check out the defaults and templates
there:

cd /realms/<yourname>/area/npc

more fighter.c

To bring a copy of that fighter to life:

clone fighter

To make him dance:

force fighter to dance

To kill him:

zap fighter

To get rid of his corpse:

dest corpse

7) Once you're done having fun with your godlike
powers, it's time to start learning how to make
fun stuff of your own.

For a quick start in building, you
can start reading the Creator's Manual at
chapter 31, which is where the QCS section begins:

read chapter 31 in manual

read chapter 32 in manual

and so on.

That's fine to start with, but eventually
you'll need to read the whole Creator's Manual.
If you don't, 90% of the questions you ask about
code could be fairly answered with: "read the manual."


This is weird...where is the online builder? How does
new stuff get compiled?

Dead Souls can be very strange to people used
to non-LPC muds. This is because many other kinds of
muds use a system where the mud is written in C++,
and to make changes, you need to add C++ code to the
source, recompile it, then reboot the mud.
In that kind of system, building is done with
tools where you fill in blanks and code is generated
for you. I presume that some C++ expertise is
required for doing anything unusual or fancy.

If you come from this kind of environment,
you may be in for a little disorientation. On a Dead
Souls mud, there is no need for compiling code. You
don't need to reboot the mud for new stuff to
be available.

You can add your new Orc God of War to the
game (after you code him, of course) with two
simple commands:

update /realms/<you>/area/npc/grimmash.c

clone
/realms/<you>/area/npc/grimmash.c

You're now face to face with him. This makes
Dead Souls, like most LPC muds, very flexible in
what can be done, and very stable in terms of
needing few reboots. Reboots typically are
necessary only when someone breaks important
code, or to implement major mud-wide changes.

So, just write your code, and update it.
It's that simple. There are two main ways to do
this. The easiest way is with the QCS, or quick
creation system. With the QCS, you don't even need
to look at code. You just issue a few commands,
and your new whatever is there. Check out an example
of the QCS here.


To learn the QCS, read the Creator's
Manual starting on chapter 31.

The other way to create on-line is
with the ed command. The ed editor is a powerful
and flexible way of editing files. Some people
find it difficult at first, and you might even
be able to avoid it for a while if you mostly
just use QCS. However, you'll eventually need to
know a little about ed. For a tutorial, go here.

For more detailed documentation,
type: help ed


I explored around in /domains/Ylsrim and <XYZ> is broken

Ylsrim is kept in the distribution as a kind of
sentimental artifact. It's the demo area that the
original Dead Souls shipped with, and although
it's mostly been fixed up to work with Dead SOuls 2,
things can behave unexpectedly.


I explored around in /domains/town and <XYZ> is broken

Please send me an email and let me know, so I
can fix it. Also let me know if something in /domains/default
is hosed up.

!
!
Section 2: Code

What's the QCS?

Please see the QCS example page for an explanation of this
important Dead Souls system.



SetUnique doesn't work.

SetUnique() is probably doing something you
don't expect. When an item is loaded into memory, and
it has an inventory, it first checks each of those items
for whether it's supposed to be unique.
If it is supposed to be unique, then we look
through the list of loaded objects to see if there is
one of these items already cloned. If there is, then
we don't clone a new one.
What this means is that if I kidnap Leo the
archwizard and hold him in my workroom, another one will
not appear in the basement until my Leo is dested.

Note, however, that this does NOT mean that the
mud will never have two Leos. I can clone however many
Leos I want. But as long as one or more cloned Leos
exist, the basement will not make another. That's
what SetUnique means.

Now, if the behavior you're seeing is different
from what I described, maybe SetUnique is broken,
and you should email me with what you're seeing.


I made a magic wand that disappears after 10 minutes.
But if a player logs out and log back in, they have
another 10 minutes! How do I fix this?

What's happening is that you are keeping
track of how old the wand is, perhaps with a
variable named Age. But if the player quits and
logs back in, then the wand gets cloned again, resetting
all its values, including Age, to the original.

The way to make the Age variable survive
logouts is with AddSave. If you give your variable to
AddSave as an argument, that variable gets saved when
the user quits, and when they log back in, it is restored,
preventing cheating.

See /obj/wed_ring.c for an example.


Where is it saved?

In the player's playerfile, along with the values of all
the objects they were carrying when they quit.


How do I add or remove emotes?

That is an admin job. You admin would use the
addemote or removeemote commands.


How can I tell what files something inherits?

Use the showtree command. To know what files
are inherited by your robe, for example:

showtree /domains/default/armor/robe


How can I find the filename of something?

If it's in your environment: scan here
If it's in your possession: scan me

The number sign (#) and numbers at the end are that
object's unique identifier.


What's the largest integer usable by the mud?

2147483647


How can I find out what functions exist in something?

Get its filename and use the functions efun. For example:

eval return functions(load_object("/domains/town/obj/sign"))


object::init() is broken!

It isn't really. Unless you're coding a lib
item, you should not be inheriting LIB_OBJECT for
"tangible things" anyway. You should inherit LIB_ITEM.

The reason
object::init() fails is that LIB_OBJECT
doesn't have an init() function to call.


if(ob->GetFoo()) seems to break, but I don't know why

This function will error if ob does not exist. Unless
you are 100% positive ob will exist (and really, even if so),
it should look like this:

if(ob && ob->GetFoo())

Which means "if ob exists, and it has a foo".
This way, if there is no ob, the check stops right there
without getting hosed up on the next step.


How do I add color to my descriptions?

There are various markup tokens you can use for this. They look like this:

write("%^BOLD%^GREEN%^ This text would be in bold green letters %^RESET%^ and this would not.");

The %^RESET% is important. Without it, unpredictable things can happen.

To know what colors are available, type: colors

You should probably avoid color unless there is a compelling
reason for its use. Many mud admins discourage it because it can
distract from the game and cause uniformity issues: most mud
admins feel their mud text should look more or less
the same everywhere.


How do I turn the integer 42 into the string "forty-two"?

cardinal(42)


Can I use !=NULL as a test?

In theory, I guess so, but I doubt it'll work by default, and I'd
discourage you from doing anything so non-LPC-standard.
Instead try something like one of the following:

if(variable)
if(sizeof(variable))
if(variable != "")


I want to create and test a new command for the mud,
but I'm not admin so I can't put anything in the
normal command paths. What can I do?

Put your new command in your homedir's cmd/
subdirectory. A sample command is there already
to serve as a template. When you add a command, type:

update /daemon/command

for it to show up in your path.


How do skills work?

Skills are generally class-based, meaning that they are
specified in the class files found in /secure/cfg/classes.
Skills are only meaningful in terms of library objects that
understand them.

For example, a fighter's blade attack is useful because
player.c and combat.c make use of this skill as a
modifier.

But adding a basketweaving skill to a class is not
helpful unless there are library objects (looms, perhaps,
or straw) and verbs (weaving, maybe?) that make
use of that skill.

An upcoming feature is race-based skills, such
as poison bite or breath attack. These skills are
specified in /secure/cfg/races.


How do classes work?

Basically, having a class gives you special skills.
That's it. See the above section, "How do skills work?"


How do virtual rooms work?

Virtual rooms are rooms generated on the fly by a
virtual room server. You program that server with
the room descriptions, the number of them,
etc, and the virtual server can make available
a grid of rooms with your descriptions.

This allows you to create, for example,
a vast desert, or a large jungle, comprised of
dozens, or hundreds, or thousands of rooms
without having to manually code each and every
single room.

For an example, take a look at

/domains/town/virtual/



How are files organized in Dead Souls?


See the admin FAQ.


What are lfuns, sefuns and efuns?


Sefuns and efuns are functions available to all objects on the
mud. Any object may need to know what time() it is, so rather
than have a time() function in every file that needs it, which
could be many, there is a time() function built into the
game that any object can use. An efun is built into the
driver, so there is no LPC code to look at. A sefun is a
simulated efun, coded in LPC. Sefuns are kept in /secure/sefun.

Lfuns are functions specific to library objects. A shirt,
for example, has functions that a sword may not need, so
the LIB_ARMOR and LIB_WEAPON files contain their own functions,
not shared by other files (it's more complicated than this,
but that's the idea). These functions are library
functions, or lfuns. Typically they are found in the objects
defined by the files in /lib.

For a lot more detail on efuns and sefuns, see the
admin FAQ.


Why are there more sefun doc files than sefun files?

Sefun files, like /secure/sefun/strings.c, often contain
more than just one sefun. Therefore, there will be more
files documenting individual functions than there are
files containing sefuns.


I edited a file but now the reload command is complaining.

There are two commonly used commands for loading
objects: update and reload.

When you want to load a file into memory, you use
update, for example: update /domains/default/room/road

When you want to replace a cloned object with a
version that uses the latest code in a file, you
use reload, for example: reload my first red sword

reload doesn't work on files.

update doesn't work on cloned objects.


this_player()->GetName() returns "A shadow" when the player is invis.

Use this_player()->GetKeyName() instead.


Is there a sefun for making a whole string uppercase?

upper_case("omgwtfroflmao")


What is the difference between filter() and foreach()? How do I use them?

Both of these efuns can act on the individual members of an array.

For example, if you wanted to have an array named mystuff which
contains the filenames of all objects in your inventory that
inherit LIB_ARMOR:

using filter:

object *stuff = filter(deep_inventory(this_player()), (: inherits(LIB_ARMOR,$1) :) );
string *mystuff = filter(stuff, (: base_name($1)+".c" :) );

using foreach:

string *mystuff = ({});
foreach( object ob in
deep_inventory(this_player())){
if( inherits(LIB_ARMOR, ob) ) mystuff += ({
base_name(ob)+".c" });
}

There are arguments favoring the use of either. I won't get into
it. As far as I can tell, it's really a question of preference.
You can structure these functions more elegantly
than shown here, to best suit you. But this is the idea.


member_array() is returning exactly the wrong thing

It probably isn't. member_array() seems somewhat counterintuitive
at first, because it often returns a 0 as a "hit".

What this function is doing is checking to see whether the
first argument is a member of the array specified in the second
argument, and then tells you *which* element it is. for example:

member_array( "bar", ({ "foo", "bar", "baz" }) ) returns: 1

member_array( "foo", ({ "foo", "bar", "baz" }) ) returns: 0

Why does it return 0? Because "foo" is element 0 of the
array. If this_array ==
({ "foo", "bar", "baz" }), then
this_array[0] is "foo". So member_array("foo", this_array)
would return 0.

If the first argument is not a member of the array, member
array returns -1. So that:

member_array( "shiz", ({ "foo", "bar", "baz" }) ) returns: -1


Example:

Does this player know how to polka? Return 1 for yes:

RIGHT: if(member_array("polka dancing", this_player()->GetSkills()) != -1) return 1;

WRONG:
if(member_array("polka dancing", this_player()->GetSkills()) ) return 1;
 
The first way says "If 'polka dancing'
has an element number that isn't -1,
then it is a member, so let's return 1"

The second way says
"If 'polka dancing' has an element number that isn't 0,
then it is a member, so let's return 1"

The problem with the second way is that it is possible for "polka dancing"
to be element 0 in that array, and if it is, your code will incorrectly
tell you that you can't polka dance. But worse than this is that if
you actually can't polka dance, this second way will incorrectly tell
you that you can. Given random input, the second way would be wrong more than
half the time.


I'm trying to add two mappings together and the results are bizarre

Adding mappings together has to be done just so in order for
it to work the way one might expect. What can happen in
mapping arithmetic is that in the process of trying to
add the values of one mapping to another, you can change the
values of a mapping you didn't intend to. The deal is a
conflict between passing data by reference or by value. To
be sure that you don't accidentally modify an innocent
bystander, use the add_maps() sefun. For example:

MyMap = add_maps(HisMap, HerMap);

or

MyMap = add_maps(MyMap, HerMap);


When str = "abc", str[1] is 98, not "b". What gives?

What you're getting here is the ASCII code of element 1.
If you have to have that element as a string, use the
convert_ascii() sefun, like this:

convert_ascii(str[1])

You can instead use ranges, so that:

str[0..0] == "a"
str[1..1] == "b"
str[1..2] == "bc"

If you use ranges, do not use the convert_ascii() sefun.


How do I make an array1 that is the same as array2 but without an element?

To do this with just the first instance of the element:

array1 = array2 - ({ element });

To avoid any instance of the element:

array1 = filter(array2, (: $1 != element :) );


How do I pass arguments to a pointer in a functional?

With commas, like this:

(: eventKill, player :)

Your arguments will likely need to be global variables.


What does the tc() sefun do?

It's something I coded for myself long ago, basically
a personalized debug(). However, people have been
asking for that funcitonality for themselves, so
the debug() sefun now carries this functionality. For
more information, type:

man debug


How can I find out how many items are in an array quickly?

sizeof(array)


My SetRead isn't working

Make sure there is an item for each read. For example,
SetRead( ([ ({"alpha", "bravo", "charlie"}) : "Delta.", ]) )

Needs something like this *above* it:

SetItems( ([ ({"alpha", "bravo", "charlie"}) : "A thing you can read.", ]) )


My SetEnters/SetSmells/SetListens isn't working

See above.


Can I nest loops?

Can you? Probably. Should you? Almost certainly not.
For loops and while loops are legal LPC, and you may even
see them here or there in onlder lib code. But they
should be avoided because they generate much more
lag than the more efficient foreach() and filter() efuns.


What should I do or not do in my code?

1) Avoid using call_out() as much as humanly possible.
Use heart_beat() to time things instead.

2) Don't code stuff that replicates itself.

3) Don't code stuff that circumvents security. For
example, knowing that an admin is logged on but
invisible isn't much help to you if he bans you
for coding a tool to find him.

4) foreach() and filter() are faster than for() loops,
and harder to screw up.

5) switch() is faster and more economical than if()
for multiple evaluations.

6) Don't use callouts.

7) Don't use add_action for something that already
has a verb. There is no point in making an add_action
for "throw", for example. It's just going to confuse
players when your "throw" doesn't behave the way
"throw" does everywhere else on the mud.

8) Callouts are bad, mkay?

9) Don't code delays by using loops. This affects the
whole mud. If an action is to be delayed, use heart_beat().


How much different or heavily modified is Dead Souls than stock LPC?

This is a difficult question to answer on its own terms. It's
roughly equivalent to:

Is Fedora different from stock UNIX, or will my Solaris programs work on it?

This DVD movie is in NTSC format, so my TV can handle it, right?

The terms used roughly correspond to the same
general thing, but the assumption here is that there is a
"stock" LPC, and you can transplant code from one LP mud to
another.
Sometimes these transplants can be done. Oftentimes not.
This is because LPC has been interpreted and implemented in
many slightly different ways by many slightly different versions
of many different drivers. The end product of the DVD is a movie
playing on your TV, but how it gets there is very different from
how a videocassette does it, even if it's the same movie and its
signal is encoded in NTSC in both cases.

If you have a LPmuds that use different drivers, it
can be much like the difference between a DVD and a videotape.
Sometimes, if the drivers are related, the difference is smaller,
like VHS versus Betamax, but you'll still be embarking on a
major project getting the movies from one to play on the other.

The result is that a coder from Discworld and a coder
from Nightmare can roughly speak the same language, and discuss
solutions to their problems that make sense. And each coder
could probably visit the other mud and work with a very
small learning curve.
But the code itself would probably require substantial
retooling to be interchanged.


!
Section 3: Intermud and channel stuff


How do I know what other muds are online on intermud?

Type: mudlist

To see online Dead Souls muds type
: mudlist -m dead


Hey, LeetFooMud is online! How can I tell if Biff is logged on?

To see who's logged on: rwho leetfoomud
To tell Biff hello: tell biff@leetfoomud hello
To see if Biff is listening to <ds>: list ds@leetfoomud
To check out Biff's personal info: finger biff@leetfoomud


That's weird...mudlist says LeetFooMud is there but I'm not getting anything back.

The mudlist command reports on data retrieved the last time
the intermud daemon received an update. This means that if
LeetFooMud dropped off, say, 10 minutes ago, or if your own
intermud connection is down, your intermud commands are falling
into the void.

To see if your intermud connection is up, type: wiz
This takes you to the Creator's Hall, where a sign indicates
your mud's intermud connection status. This sign may be up
to 15 minutes out of date.

You can also test your mud's intermud connection with
the ping command, like this:

ping dead souls

ping frontiers


I heard there are intermud channels that talk between other muds,
not just Dead Souls muds. How can I use them?

Ask your admin. Those channels may not be open for
use on your mud.

If you talk on <intercre>, be polite, and use the same rules
of common sense and intelligent questioning that you need
to follow for <ds>. <intercre> is for code and technical
questions ONLY. Do not ever spam it or use it for chatting.

I strongly discourage you from talking on <intergossip>. I
assure you nothing good will come of it.


Howdo I emote on a channel?

Add the word
"emote" to the channel command. For example:


creemote compels your silence.

gets seen on the channel as:
<cre> Cratylus compels your silence.


Howdo I see what I missed on a channel?

To see the recent messages, use hist. For example:

hist ds

To see older stuff, look in /log/chan


I am sick and tired of the intermud network going down. Please fix it.

See the Dead Souls Intermud Router page.


I just wanna chat. Is there a dschat channel?

No, and there probably won't be one. You can chat to some extent
on the <ds> line, but if you're perceived as being a spammy
chatty source of noise, you may be asked to cool it.
If you really want to just chat, then use <intergossip>,
since that's what it's there for. Ask your admin for how to
do this. I'd rather you expose <intergossip> to your boredom
than <ds>.
Alternately, there's a <ds_test> channel which is
intended specifically for spammy channel tests and such. Add
that channel to yourself and blab away, though not many
people will be listening. See /doc/README for how to add
channels to yourself.


I'll spam if I want to. You're not the boss of me.

It's true, I can't do much if you're determined to be a
jerk. If you consistently abuse channels, your admin may
be asked to limit your channel access. In extreme cases,
your mud may find itself banned from the channel in
question.
I can only appeal to your sense of fair play.
Spamming hurts people who have nothing to do with whatever
you're pissed off about. Please don't make whatever your
problem is with someone a headache for everyone.

This guy keeps hassling me on an intermud channel

Sometimes people just can't leave well enough alone,
and they spam. Some people just don't have anything
to say that you want to hear. For such situation,
use the earmuff command. For example:

earmuff tatianna

And you will not receive channel messages from
that person. The reverse command is unmuff.
Earmuffing is also good when someone from
a non-European-language mud sends well-meaning
but garbled, escape-code filled gibberish. If
she doesn't understand your English language
requests to stop spamming, you can just earmuff her.


Is there a way to change the "default exit" room messages?

Yes, but it involves some understanding of LPC. See
if Brodbane@Eve is listening on the ds channel. He
may have some tips.

!
Section 4: Miscellanea
+
+
I'm + fighting the beggar with my staff and he's kicking my ass

!     ! For one thing, you're a creator. Quit goofing around. If
! you want to fight monsters and stuff, create a test
! player character.
!
!     Next, you're probably still a Level 1 character. This
! makes you a wimp. Raise your level with this command:
!
! call me->SetLevel(20)
!
!     Now get the medical tricorder from your workroom's
! chest and raise your stats. Give yourself 100 strength.
! Why not?
!
!     Put the staff in your robe and quit using it as
! a weapon. It's a creating tool. Not only is it a
! poor weapon, by default you lack double-handed
! weapon skills, making you really crappy at using
! a really crappy weapon. No wonder the orcs were
! beating you like an animal. Get a carving knife
! from the mansion. Or an orcslayer. Or hell, just
! use the zap command and stop wasting time. You
! should have characters for this.
!
!

! Someone ! amputated all my limbs and I can't do anything!

If your body ! gets damaged you can restore yourself to your
normal ! physical status by typing:

! heal ! me
!
!
! How do I change my class?
!
!
Again ! with the pretending to be a ! player. Seriously,
! you need a test player char so that if you screw something
! up, you don't screw *yourself* up.
!
! But, if you're determined:
!
! call me->ChangeClass("thief")
!
!
Your stats and levels will probably be all weird and
! hosed up. Just raise your player level, that will probably
! fix it.
!

!
! People are ! talking to me in gibberish, even though it says they're
! speaking English.

If your race is not human, your default language is not English, therefore
someone ! speaking in English would not be understood by you. As a
creator, you ! can avoid players' tedious language learning process
and simply type:

! call ! me->SetLanguage("English",100)

    Obviously this will work for other languages too.
*************** *** 305,333 **** since you don't seem logged on.


! How ! do I find the location of a verb or command?

Use the which ! command. For example:

! which zap

! which update

If 'which' ! doesn't find it, the command is probably built into
some object ! you inherit, like the command shell or the
hooks for the chat daemon. Or it may be an add_action bound to a
nearby object. To see what commands objects or inherited
--- 102,123 ---- since you don't seem logged on.


! How ! do I find the location of a verb or command?

Use the which ! command. For example:

! which zap

! which update

If 'which' ! doesn't find it, the command is probably built into
some object ! you inherit, like the command shell or the
hooks for the chat daemon. Or it may be an add_action bound to a
nearby object. To see what commands objects or inherited
*************** *** 336,454 **** localcmds


! How ! do I make a quest?

    ! Think of a quest in terms of the result. The result of a quest is
a player ! receiving quest points and a quest title.

    ! This means that pretty much anything can be a quest. If
you've coded ! a rock to provide quest points and a quest title
when it is ! picked up, well, there's your Rock Quest. However,
you usually ! want to make things a bit more challenging.
    ! A quest can be as boring as "pick up the red rock" or
it can be a ! challenging metaphysical inquiry into the
nature of ! consciousness. If quest points and a quest title are
at the end of ! a series of actions, then that series of actions
! is a quest.

    ! What those actions should be are entirely up to your
imagination. ! Review the orcslayer quest in the Player's
Handbook for an example. You did read the ! Player's Handbook,
! right?
    ! Take a look at Leo the Archwizard's code for an example
of the ! mechanics of solving a quest.

!
! Where's ! Leo?


Read the ! Player's Handbook already, please.

!
My wandering monster escaped from my workroom! How can
I find him?

If its name is jabberwock, try:

findobj jabberwock

You can also probably just:

goto jabberwock
!
! I ! ran findobj on something but it says no environment. Where is it?

Right where ! it says. Some objects create a "master copy" of themselves
when they are ! cloned. This copy remains loaded in memory even if
that cloned ! object goes away. You can distinguish between cloned
objects and ! master copies by the number sign  and number at the end
of cloned ! objects. The master copy has no instance number. It is
simply loaded ! code, and does not "exist" in a way accessible to your player
object on the mud.

Sometimes a ! cloned object will lose its environment. This is usually
caused by an ! error and is not a good thing. Dead Souls runs a
"reaper" ! daemon that periodically searches memory for cloned
objects that lack an environment, and they are destroyed.

--- 126,204 ---- localcmds


! How ! do I make a quest?

    ! Think of a quest in terms of the result. The result of a quest is
a player ! receiving quest points and a quest title.

    ! This means that pretty much anything can be a quest. If
you've coded ! a rock to provide quest points and a quest title
when it is ! picked up, well, there's your Rock Quest. However,
you usually ! want to make things a bit more challenging.
    ! A quest can be as boring as "pick up the red rock" or
it can be a ! challenging metaphysical inquiry into the
nature of ! consciousness. If quest points and a quest title are
at the end of ! a series of actions, then that series of actions
! is a quest.

    ! What those actions should be are entirely up to your
imagination. ! Review the orcslayer quest in the Player's
Handbook for an example. You did read the ! Player's Handbook,
! right?
    ! Take a look at Leo the Archwizard's code for an example
of the ! mechanics of solving a quest.

!
! Where's ! Leo?


Read the ! Player's Handbook already, please.

!
My wandering monster escaped from my workroom! How can
I find him?

If its name is jabberwock, try:

findobj jabberwock

You can also probably just:

goto jabberwock
!
! I ! ran findobj on something but it says no environment. Where is it?

Right where ! it says. Some objects create a "master copy" of themselves
when they are ! cloned. This copy remains loaded in memory even if
that cloned ! object goes away. You can distinguish between cloned
objects and ! master copies by the number sign  and number at the end
of cloned ! objects. The master copy has no instance number. It is
simply loaded ! code, and does not "exist" in a way accessible to your player
object on the mud.

Sometimes a ! cloned object will lose its environment. This is usually
caused by an ! error and is not a good thing. Dead Souls runs a
"reaper" ! daemon that periodically searches memory for cloned
objects that lack an environment, and they are destroyed.

*************** *** 469,476 **** directory with dozens of files in it will cause a noticeable hiccup
in the rest of the mud.

! If you are determined to do this
, though, the command is :

update /path/to/dir/*

--- 219,225 ---- directory with dozens of files in it will cause a noticeable hiccup
in the rest of the mud.

! If you are determined to do this
, though, the command is :

update /path/to/dir/*

*************** *** 487,495 **** Um...I want colors back now please

! Type: terminal ansi

then type: save


--- 236,242 ---- Um...I want colors back now please

!
Type: terminal ansi

then type: save


*************** *** 505,553 **** take you anywhere. But
go north will.


! ZOMG ! this is the best mudlib evar how can I evar thank you?
!
! Writing an ! honest review of the lib at http://www.mudmagic.com/codes/download/lpc/mudos/dead_souls
! would be ! great, along with a rating you feel is appropriate. I seem to have ! pissed
! somebody off ! over there (he knows who he is), and he has made it a project to give
! Dead Souls ! crappy ratings whenever a new release comes out.
!
! Posting your honest opinion and ! rating there would be a lovely way to
! thank me for ! the effort of putting this lib together.
!
! But really, I ! did it for the fun of it, so it's not necessary.

!
Dude this mudlib sux0rz @ss. What a waste of my time.

I'm sure Dead Souls has lots of things that you don't
like, but I can't fix them if I don't know what they are.
Post an honest review and rating at mudmagic so I can
understand the lameness, and so others can benefit
for your suggestions.
- ! Cratylus
!
! Dead ! Souls Homepage
! ! --- 252,293 ---- take you anywhere. But
go north will.

+
+ Why is + there a bunch of stuff in ROOMS_FURNACE?
+
+ The QCS is designed to attempt the graceful handling
+ of unusual events. Sloppy code, non-working objects,
+ etc. Part of this design is avoiding a situation
+ where an object's destruction affects your local
+ environment (and this happens a bit more often than
+ you might think).
+     To avoid some types of unpleasantness, QCS doesn't
+ try to immediately destruct objects when replacing them.
+ Instead, they are moved, along with whatever problems
+ they might have, to ROOMS_FURNACE. That is a room
+ where things go to be destructed quietly. Every 60
+ seconds or so, the contents of that room are destroyed,
+ and their bits recycled.
+     A few other items in the lib use the furnace,
+ notably the recycling bins and the reload command.
+

! ZOMG ! this is the best mudlib evar how can I evar thank you?
!
! Just let me ! know what bugs you find, and how I can
! make the lib better.


!
Dude this mudlib sux0rz @ss. What a waste of my time.

I'm sure Dead Souls has lots of things that you don't
like, but I can't fix them if I don't know what they are.
Email me so that I can understand the lameness, and so
others can benefit for your suggestions.
- ! Cratylus
!
! <my name here>@users.sourceforge.net
!

! Dead ! Souls Homepage
! \ No newline at end of file diff -c -r --new-file ds2.0r19/lib/www/ds-faq.html ds2.0r20b/lib/www/ds-faq.html *** ds2.0r19/lib/www/ds-faq.html Thu Feb 23 15:40:41 2006 --- ds2.0r20b/lib/www/ds-faq.html Sun Apr 9 23:48:48 2006 *************** *** 1,41 **** ! ! ! ! Dead Souls FAQ ! !
Dead Souls FAQ, v2

Written by Cratylus @ Frontiers, October 2005
Updated January 2006

What is Dead Souls?

Primarily Dead Souls is a "mudlib". There is also a Dead Souls
MUD, but this is not what people generally mean when they refer to Dead Souls as a
game. It also happens that a book by the Russian author Nikolai Gogol is named Dead
Souls. That book is wholly unrelated to the Dead Souls software.

What is it for?

It's for building a game. If what you want to do is play a game,
you're looking for something else.

What is a MUD?

A MUD is a computer program that uses text (very rarely do MUDs
use graphics or sound) to describe virtual environments you can manipulate.
You enter a command, the program tells you how the virtual world responds
around you. Typically there are other people connected to the same program
over the Internet, and you can interact with them as well. A MUD can be mostly
social, or mostly game oriented, with quests and puzzles to solve or
villains to defeat. The name MUD is an acronym that originally stood for
"Multi-User Dungeon", in accord with the "Dungeons and Dragons" style of
many early MUDs. Now it stands for different things to different people,
but the basic concept of operation is the same, whether the game is set
on the moon, in Manhattan, or in Middle Earth.

What's a mudlib?

Generally there are two main parts to the MUD program. First is the
"driver". This is an executable program file (in Windows, you'd see the driver
has an .EXE extension) that enables the input and output of data, accepts
network connections, performs basic calculations, etc. The other part
is the mudlib, or, more properly, MUD object library. This is usually a
large set of files in plain text that the driver reads and uses as a
basis for the game. Some files provide information about rooms and
environments, some files provide information about objects or creatures,
etc. When players connect, the driver provides them the world that these
files describe.

When I configure Dead Souls, it says it is a MUD. If it is really a mudlib,
why would that be?

Dead Souls is not intended to be a fully-developed MUD when you
install it. Instead it provides you with the basic framework you need to
make a MUD of your own. After you set up Dead Souls, you should rename it,
and customize the lib (that is, library) files to create your own world. When
 you first run Dead Souls, you will have some rooms available to explore.
This is not your mud. It is just a set of sample places and objects to help
you understand how to build a MUD of your own. So in a way, Dead Souls provides
you a kind of "starter" MUD, but since it's just examples, you can't really
consider it a MUD until you change it to suit your creative vision.

Is Dead Souls really Nightmare in disguise?

Let's break this question down into its components:

What is Nightmare?

Nightmare was a mud. It was part of a branching of mud development
that occurred early in the days of popularized mudding. Some folks
decided to take MUD library development in a particular direction,
and eventually made available what is now known as the Nightmare mudlib.
Nightmare went through a few major changes, most notably from version 3
to version IV. By that time, the development of Nightmare was solely
managed by a coder who called himself Descartes.

What is the relationship between Nightmare and Dead Souls?

It appears that Dead Souls began as a "development" MUD. This means
that while Descartes ran his own MUD, he also worked on improving that MUD's
lib. It is unwise to make major changes to a MUD that people are playing on,
so the Dead Souls development MUD was one which served as a platform to
develop, extend, and improve the Nightmare lib without risking harm to active players.
Sometime after the release of the Nightmare IV mudlib, Descartes decided to
withdraw it from distribution. Based on their interpretation of copyright
law, people now do not distribute the Nightmare mudlib on Internet servers.
However, somewhat inexplicably, Descartes released the mudlib for his
development mud, Dead Souls, into the public domain. This meant that the
Dead Souls mudlib was completely free to be used by anyone in any way they
chose, be it distribution, modification, spindling or folding. Because Dead
Souls was the development mud for Nightmare Mud, which was the base of the
Nightmare mudlib, the relationship between the two is an extremely close one.

How close?

Frankly, almost identical. A close comparison of the Dead Souls lib
that Descartes released (version 1.1pre) against the last released Nightmare
lib (IVr6) reveals that they are very nearly the same thing, file for file.
The main differences between the two are:

* A small number of Nightmare library files aren't on Dead Souls.
* Dead Souls doesn't come with the driver or install script the Nightmare had.
* All documentation files were removed from Dead Souls.
* "Nightmare" in file headers was changed to say "Dead Souls"

This might sound like a lot of difference, but consider this: not counting
documentation, Nightmare IVr6 lib contained 1064 files and directories, and
the Dead Souls 1.1pre lib contains 1082. Dead Souls 1.1pre actually had more
lib material in it than the last release of Nightmare.

Why mess with Dead Souls, then?

The main problem was that Dead Souls was a bear to set up. Because
driver development had not stopped (the driver is a separate software project),
but lib development had, incompatibilities grew in number over time. Using
the original driver from 1997 created a MUD that lacked important features
of modern muds, and risked instability. Using a modern driver required a
modification of fundamental lib systems that required some expertise to
perform. People stopped using Nightmare because they couldn't get it, and
they didn't use Dead Souls because the damn thing didn't work right. My own
Nightmare lib MUD, Frontiers, continued to chug along, quietly fading into
obscurity along with all other Nightmare IV based MUDs, while scrappy young
newcomers like CoffeeMud lib started elbowing their way into the MUD community.

Then a funny thing happened. I really got into lib coding. I mean, full-on
lib obsession. I can't really explain it, other than to say that when I was
younger it seemed hard and impenetrable, but now that I've been working in a
technical field for years, I have the mental tools (and patience) required to
disassemble and understand complex systems. I got turned on by analyzing and
understanding stuff that I'd considered over my head in years past. But I
realized I was living in the past. I couldn't share my exciting lib ideas
and discoveries with anyone else, because the Nightmare LPC community was
in the very last stages of extinction.

I decided to do something about it. Maybe I'd be whistling into the wind,
tilting at windmills, or even worse, just talking to myself. But I decided
I'd make Dead Souls a viable lib for people to use, because it would be fun,
and because it might be nice to have other people to bounce ideas off of and
steal code from. At worst, I'd be doing nothing more pathetic than, say,
building model ships in my basement. At best, I might revive a once-thriving
MUD development community. Either way, it sounded like an enjoyable project,
so I proceeded.

Fine, but what's so special about Nightmare/Dead Souls? Why are you making such a
big deal of wanting people to use it? It isn't better than everything else,
surely. [insert mudlib name here] is newer and has [insert feature here] and [other feature]!

Yes, that may be. My experience with other libs is limited, and I'm sure
that Dead Souls pales in comparison to others in one feature or another. My only
answer to that is, go ahead and use the lib you're comfortable with. I make no
claims of superiority. Hell, I'll be the first to admit there are still things
to fix and systems to implement. But if you are not sure which lib to pick,
Dead Souls is an excellent choice as a solid, stable, flexible and powerful platform
to build your MUD. You can do anything in a MUD with LPC, and I mean anything.
If you happen to have Nightmare experience, Dead Souls will be a homecoming...
like an old comfortable shoe....but without the holes or the stink.

What's LPC?

LPC is a kind of programming language. Dead Souls lib files don't
just contain descriptions of places and things: they have a format that describes
their relationships to the driver and permits you to do fancy stuff...pretty much
any text MUD thing you can think of, you can do in LPC.

How do I get started?

Download the latest version from http://dead-souls.sourceforge.net/
or http://www.mudmagic.com/codes/download/lpc/mudos/dead_souls and
install it. There are versions available for Windows and for Unix. The main
difference between the two is the driver. The Windows driver is a Windows
executable. The Unix driver is in source code form and must be compiled.
The lib files for both versions are identical.

Once you log in, read the Players Handbook and the Creators Manual.


Anything else?

Read the Dead Souls Admin FAQ.
! The end.

! Dead Souls Homepage
! ! --- 1,11 ---- ! ! Dead Souls FAQ ! !
Dead Souls FAQ, v2.1

Written by Cratylus @ Frontiers, October 2005
Updated March 2006

What is Dead Souls?

Primarily Dead Souls is a "mudlib". There is
also a Dead Souls MUD, but this is not what people generally
mean when they refer to Dead Souls as a game.
It also happens that a book by the Russian author
Nikolai Gogol is named Dead Souls. That book is wholly
unrelated to the Dead Souls software.

What is it for?

It's for building a game. If what you want to do
is play a game, you're looking for something else.

What is a MUD?

A MUD is a computer program that uses text (very rarely do MUDs
use graphics or sound) to describe virtual environments you can manipulate.
You enter a command, the program tells you how the virtual world responds
around you. Typically there are other people connected to the same program
over the Internet, and you can interact with them as well. A MUD can be mostly
social, or mostly game oriented, with quests and puzzles to solve or
villains to defeat. The name MUD is an acronym that originally stood for
"Multi-User Dungeon", in accord with the "Dungeons and Dragons" style of
many early MUDs. Now it stands for different things to different people,
but the basic concept of operation is the same, whether the game is set
on the moon, in Manhattan, or in Middle Earth.

See also:
http://www.catb.org/~esr/jargon/html/M/MUD.html


What's a mudlib?

There are many different types of MUD programs. Some are
executable programs, with all of their virtual worlds
defined in one big file. Others are entirely interpreted,
such as java muds, which are composed of thick forests
of folders containing java files.

LP MUDs are something between the two.

Generally there are two main parts to an LP MUD
program. First is the "driver". This is an executable program
file (in Windows, you'd see the driver has an .EXE extension)
that enables the input and output of data, accepts network
connections, performs basic calculations, etc. The other part
is the mudlib, or, more properly, MUD object library. This is
usually a large set of files in plain text that the driver
reads and uses as a basis for the game. Some files provide
information about rooms and environments, some files provide
information about objects or creatures, etc. When players
connect, the driver provides them the world that these
files describe.


When I configure Dead Souls, it says it is a MUD.
If it is really a mudlib,
why would that be?

Dead Souls is not intended to be a fully-developed
MUD when you install it. Instead it provides you with
the basic framework you need to make a MUD of your own.
After you set up Dead Souls, you should rename it, and
customize the lib (that is, library) files to create your
own world. When you first run Dead Souls, you will
have some rooms available to explore. This is not your mud.
It is just a set of sample places and objects to help
you understand how to build a MUD of your own. So in a
way, Dead Souls provides you a kind of "starter" MUD,
but since it's just examples, you can't really
consider it a MUD until you change it to suit
your creative vision.


Is Dead Souls really Nightmare in disguise?

Let's break this question down into its components:

What is Nightmare?

Nightmare was a mud. It was part of a branching of mud development
that occurred early in the days of popularized mudding. Some folks
decided to take MUD library development in a particular direction,
and eventually made available what is now known as the Nightmare mudlib.
Nightmare went through a few major changes, most notably from version 3
to version IV. By that time, the development of Nightmare was solely
managed by a coder who called himself Descartes.

What is the relationship between Nightmare and Dead Souls?

It appears that Dead Souls began as a "development" MUD. This means
that while Descartes ran his own MUD, he also worked on improving that MUD's
lib. It is unwise to make major changes to a MUD that people are playing on,
so the Dead Souls development MUD was one which served as a platform to
develop, extend, and improve the Nightmare lib without risking harm to active players.
Sometime after the release of the Nightmare IV mudlib, Descartes decided to
withdraw it from distribution. Based on their interpretation of copyright
law, people now do not distribute the Nightmare mudlib on Internet servers.
However, somewhat inexplicably, Descartes released the mudlib for his
development mud, Dead Souls, into the public domain. This meant that the
Dead Souls mudlib was completely free to be used by anyone in any way they
chose, be it distribution, modification, spindling or folding. Because Dead
Souls was the development mud for Nightmare Mud, which was the base of the
Nightmare mudlib, the relationship between the two is a very close one.


How close?


The similarity between Nightmare and Dead Souls can
now best be described as close cousins, rather than twins.


At one time it was almost identical. A close comparison of the
Dead Souls lib that Descartes released (version 1.1pre) against the
last released Nightmare lib (IVr6) reveals that they are very
nearly the same thing, file for file.

The main differences between the two are:

* A small number of Nightmare library files aren't on Dead Souls.
* Dead Souls doesn't come with the driver or install script the Nightmare had.
* All documentation files were removed from Dead Souls.
* "Nightmare" in file headers was changed to say "Dead Souls"

This might sound like a lot of difference, but consider this: not counting
documentation, Nightmare IVr6 lib contained 1064 files and directories, and
the Dead Souls 1.1pre lib contains 1082. Dead Souls 1.1pre actually had more
lib material in it than the last release of Nightmare.


Why mess with Dead Souls, then?

The main problem was that Dead Souls was a bear to set up. Because
driver development had not stopped (the driver is a separate software project),
but lib development had, incompatibilities grew in number over time. Using
the original driver from 1997 created a MUD that lacked important features
of modern muds, and risked instability. Using a modern driver required a
modification of fundamental lib systems that required some expertise to
perform. People stopped using Nightmare because they couldn't get it, and
they didn't use Dead Souls because the damn thing didn't work right. My own
Nightmare lib MUD, Frontiers, continued to chug along, quietly fading into
obscurity along with all other Nightmare IV based MUDs, while scrappy young
newcomers like CoffeeMud lib started elbowing their way into the MUD community.

Then a funny thing happened. I really got into lib coding. I mean, full-on
lib obsession. I can't really explain it, other than to say that when I was
younger it seemed hard and impenetrable, but now that I've been working in a
technical field for years, I have the mental tools (and patience) required to
disassemble and understand complex systems. I got turned on by analyzing and
understanding stuff that I'd considered over my head in years past.
But I was living in the past. I couldn't share my exciting lib ideas
and discoveries with anyone else, because the Nightmare LPC community was
in the very last stages of extinction.

I decided to do something about it. Maybe I'd be whistling into the wind,
tilting at windmills, or even worse, just talking to myself. But I decided
I'd make Dead Souls a viable lib for people to use, because it would be fun,
and because it might be nice to have other people to bounce ideas off of and
steal code from. At worst, I'd be doing nothing more pathetic than, say,
building model ships in my basement. At best, I might revive a once-thriving
MUD development community. Either way, it sounded like an enjoyable project,
so I proceeded.


Fine, but what's so special about Nightmare/Dead Souls? Why are you
making such a
big deal of wanting people to use it? It isn't
better than everything else,
surely. [insert mudlib name here]
is newer and has [insert feature here] and [other feature]!


Yes, that may be. My experience with other libs is limited, and I'm sure
that Dead Souls pales in comparison to others in one feature or another. My only
answer to that is, go ahead and use the lib you're comfortable with. I make no
claims of superiority. Hell, I'll be the first to admit there are still things
to fix and systems to implement. But if you are not sure which lib to pick,
Dead Souls is an excellent choice as a solid, stable, flexible and powerful platform
to build your MUD. You can do anything in a MUD with LPC, and I mean anything.
If you happen to have Nightmare experience, Dead Souls will be a homecoming...
like an old comfortable shoe, but without the holes or the stink.


What's LPC?

LPC is a kind of programming language. Dead Souls lib files don't
just contain descriptions of places and things: they have a format that describes
their relationships to the driver and permits you to do fancy stuff...pretty much
any text MUD thing you can think of, you can do in LPC.


How do I get started?

Download the latest version from http://dead-souls.sourceforge.net/
or http://www.mudmagic.com/codes/download/lpc/mudos/dead_souls and
install it. There are versions available for Windows and for Unix. The main
difference between the two is the driver. The Windows driver is a Windows
executable. The Unix driver is in source code form and must be compiled.
The lib files for both versions are identical.

Once you log in, read the Players Handbook and the Creators Manual.


I went to http://dead-souls.net but the connection fails.

I'm just this guy, you know? I don't have the money to
pay for a static IP, so when my IP changes, it can take a day for
dead-souls.net to catch up with it.
In the meantime, you can use:

http://dead-souls.sourceforge.net


Anything else?

Read the Dead Souls Admin FAQ.

Read the Dead Souls Creator's FAQ.

Read the Dead Souls Installation FAQ.

Read the Quick Creation System Example Page.

Read the Debugging Guide.

Read the Editor Tutorial.

! The end.

! Dead Souls Homepage
! \ No newline at end of file diff -c -r --new-file ds2.0r19/lib/www/ds-inst-faq.html ds2.0r20b/lib/www/ds-inst-faq.html *** ds2.0r19/lib/www/ds-inst-faq.html Fri Mar 24 14:34:51 2006 --- ds2.0r20b/lib/www/ds-inst-faq.html Sun Apr 9 23:48:48 2006 *************** *** 1,19 **** ! ! ! ! Dead Souls Installation FAQ ! !
Dead Souls Installation FAQ, v2.2

Written by Cratylus @ Frontiers, February 2006
Updated March 2006


Is this FAQ really necessary?

Normally, no. If you just follow the instructions included in the
Dead Souls packages, you'll be fine 90% of the time. However, a
non-trivial number of folks have run into difficult circumstances. For
those folks, this document is meant to illuminate how the install
process works, why some things are as they are, and suggest some
solutions to the more common obstacles.



Where do I get Dead Souls?

Download the latest version from one of the following:


http://sourceforge.net/project/showfiles.php?group_id=148388

http://www.mudmagic.com/codes/download/lpc/mudos/dead_souls

Should I apply the available patches during an install?

--- 1,26 ---- ! ! Dead Souls Installation FAQ ! !
Dead Souls Installation FAQ, v2.5

Written by Cratylus @ Frontiers, February 2006
Updated April 2006

Is this FAQ really necessary?

Normally, no. If you just follow the instructions included in the
Dead Souls packages, you'll be fine 90% of the time. However, a
non-trivial number of folks have run into difficult circumstances. For
those folks, this document is meant to illuminate how the install
process works, why some things are as they are, and suggest some
solutions to the more common obstacles.



Where do I get Dead Souls?

You should only ever download from the sites listed below.
Some other sites tend to mirror these or copy data from
them, then fail to update their data regularly. The following
will always have the most recent version, and they are the
only ones officially authorized to distribute Dead Souls.

Download the latest version from one of the following:

Mudmagic: http://www.mudmagic.com/codes/download/lpc/mudos/dead_souls

Sourceforge: http://sourceforge.net/project/showfiles.php?group_id=148388

+
+ Where + do I get older patches?
+
+ Mudmagic:
+
+     Windows patches: http://www.mudmagic.com/codes/download/lpc/mudos/dead_souls/windows_patches
+    
+     UNIX patches: http://www.mudmagic.com/codes/download/lpc/mudos/dead_souls/unix_patches
+

+ Sourceforge:
+
+      Both: http://sourceforge.net/project/showfiles.php?group_id=148388&package_id=175140
+
+

+
Should I apply the available patches during an install?

*************** *** 24,32 **** version to another, please read the upgrade section further down in this
document.

!
! What's this Cygwin stuff?

Don't bother with it. The Cygwin files are there strictly for legal reasons, and they
--- 31,38 ---- version to another, please read the upgrade section further down in this
document.

!
! What's this Cygwin stuff?

Don't bother with it. The Cygwin files are there strictly for legal reasons, and they
*************** *** 40,47 **** provide
the source code that these binaries came from.

! Fortunately, the source code doesn't have to be in the distribution. Making
it downloadable from the same page satisfies their licensing. But their
source code is very unlikely to be useful to you, unless you're very --- 46,52 ---- provide
the source code that these binaries came from.

! Fortunately, the source code doesn't have to be in the distribution. Making
it downloadable from the same page satisfies their licensing. But their
source code is very unlikely to be useful to you, unless you're very *************** *** 50,62 **** sources.

So, leave it alone.
!
!
How do I ! install the Windows version of Dead Souls?
!
! Easy.
!
First make sure you are running Windows 2000 or above. Then:

1) unzip the distribution file
--- 55,66 ---- sources.

So, leave it alone.
!

!
How do I ! install the Windows version of Dead Souls?

!
NOTE: If you are using Windows, USE THE WINDOWS VERSION. 
There is no benefit in trying to download Cygwin and
modify the UNIX source code and trying to get it to
compile in Windows, unless you know exactly what you're
doing. Yes, people have tried to do this and complained.
!
First make sure you are running Windows 2000 or above. Then:

1) unzip the distribution file
*************** *** 74,81 ****
5) connect to your Windows computer by telnetting to port 6666. If you are using the command
!     window, type: telnet localhost 6666

6) Enter the name you want your admin to have, and answer the questions provided. Make sure
--- 78,84 ----
5) connect to your Windows computer by telnetting to port 6666. If you are using the command
!     window, type: telnet localhost 6666

6) Enter the name you want your admin to have, and answer the questions provided. Make sure
*************** *** 85,92 **** 7) When you finish entering the admin's info, the mud will automatically shut down.

! 8)
run c:\ds\runmud.bat again

9) log in as your admin --- 88,94 ---- 7) When you finish entering the admin's info, the mud will automatically shut down.

! 8)
run c:\ds\runmud.bat again

9) log in as your admin *************** *** 99,134 ****        (as of this writing, it's option r). Enter the name desired, allow the mud to shut down.

! 11)
run c:\ds\runmud.bat (that's it for the mud reboots. come on, it's windows. you're used to rebooting)

! 12) log in, type: rm /log/chan/ds
!
!
13) start reading the handbook and the manual.


Hold up, these Windows instructions aren't working

There are a few common reasons for this.

! * You need to
rm /log/chan/ds . Dead ! Souls includes a large sample logfile which gets
! rotated soon after installation. Problem is, the new filename is
! incompatible with your Windows filesystem. If you don't issue this
! command, your mud will soon start crapping out, complaining about
! the /log directory. The fix for this will be in a later release.

! * Most Windows PC's these days have firewall software installed. If you try to connect but
aren't able to, there's a good chance your connection is being blocked by your firewall. Disable
--- 101,128 ----        (as of this writing, it's option r). Enter the name desired, allow the mud to shut down.

! 11)
run c:\ds\runmud.bat (that's it for the mud reboots. come on, it's windows. you're used to rebooting)

! 12) log in,
start ! reading the handbook and the manual.

+ * Note: If you use c:\ds\startmud.bat, + you won't need to manually restart each time.
+

Hold up, these Windows instructions aren't working

There are a few common reasons for this.

! * Download only from the sites mentioned above. Those are the only
! ones sure to have the latest version. Other sites can be out of date.

!
* ! Most Windows PC's these days have firewall software installed. If you try to connect but
aren't able to, there's a good chance your connection is being blocked by your firewall. Disable
*************** *** 136,144 **** away, you know now that
you have to somehow configure your firewall to allow incoming TCP connections on port 6666.
!   Note: You may also have to permit outbound UDP connections to ! port 9000 on
! IP address 198.144.203.194 if you want your mud to join the Intermud3 network.

*  You might not be using c:\ds as your base directory. Make sure --- 130,138 ---- away, you know now that
you have to somehow configure your firewall to allow incoming TCP connections on port 6666.
!   Note: You may also have to permit outbound TCP connections to ! port 23 on
! IP address 149.152.218.102 if you want your mud to join the Intermud3 network.

*  You might not be using c:\ds as your base directory. Make sure *************** *** 155,172 **** please let me know by emailing me at <my name>@users.sourcefore.net .

- *  If you've made sure you've followed the directions, avoided the - "don'ts", and it
- still doesn't work, it may be that you have a Cygwin conflict. If you - already
- have Cygwin installed on your PC, the dll's provided in the c:\ds\bin - directory
- might be conflicting with your current version. Try moving the .dll - files in
- c:\ds\bin to some other folder and see if this fixes the problem. If it - doesn't, don't forget
- to put them back.
-
*  If the mud starts but you get lots of bizarre errors, there may be a couple of
reasons for this:
--- 149,154 ---- *************** *** 193,198 **** --- 175,193 ---- reinstalling but with a different
    unzip utility.

+
*  + If you've made sure you've followed the directions, avoided the + "don'ts", and it
+ still doesn't work, it may be that you have a Cygwin conflict. If you + already
+ have Cygwin installed on your PC, the dll's provided in the c:\ds\bin + directory
+ might be conflicting with your current version. Try moving the .dll + files in
+ c:\ds\bin to some other folder and see if this fixes the problem. If it + doesn't, don't forget
+ to put them back.

+

How do I install the UNIX version of Dead Souls?
*************** *** 203,214 **** fileroller (a GUI based app) to decompress the tarball. If
you ignore this warning you are very likely to end up with really
confusing errors and problems. Instead use the normal unix command
! line. For example: tar xzf ds2.0.tar.gz

* Don't use an existing driver ! binary, even if its from a previous
(or even the same) Dead Souls distribution. If you're doing a fresh
install, always, always, always do the complete and exact installation procedure,
--- 198,207 ---- fileroller (a GUI based app) to decompress the tarball. If
you ignore this warning you are very likely to end up with really
confusing errors and problems. Instead use the normal unix command
! line. For example: tar xzf ds2.0.tar.gz

* Don't use an existing driver ! binary, even if it's from a previous
(or even the same) Dead Souls distribution. If you're doing a fresh
install, always, always, always do the complete and exact installation procedure,
*************** *** 226,239 ****
2) cd to v22.2b14

! 3) type: ./configure

! 4) type: make

! 5) type: make install
        If this fails, just manually copy the "driver" file
        into $MUDHOME/bin/
--- 219,229 ----
2) cd to v22.2b14

! 3) type: ./configure

! 4) type: make

! 5) type: make install
        If this fails, just manually copy the "driver" file
        into $MUDHOME/bin/
*************** *** 259,268 ****
9)  telnet to your machine, using the port specified in mudos.cfg. For
! example: telnet ! localhost 6666

10) Create a new user. Just answer the questions. Make sure you are
--- 249,256 ----
9)  telnet to your machine, using the port specified in mudos.cfg. For
! example: telnet ! localhost 6666

10) Create a new user. Just answer the questions. Make sure you are
*************** *** 278,286 **** I'm having trouble getting Dead Souls for UNIX to work

! * first, stop using Fedora. Ha ha just kidding (not really).

! * most of the problems with unix installs involve permissions conflicts. If
you uncompress the tarball as root user, for example, then try to
run it as an unprivileged user, the process won't be able to read
--- 266,279 ---- I'm having trouble getting Dead Souls for UNIX to work

! * first, stop using Fedora. Ha ha just kidding.
!
!
* ! Download only from the sites mentioned above. Those are the only
! ones sure to have the latest version. Other sites can be out of date.

!
* ! most of the problems with unix installs involve permissions conflicts. If
you uncompress the tarball as root user, for example, then try to
run it as an unprivileged user, the process won't be able to read
*************** *** 305,318 **** directory:

cd ! /home/joe/ds2.0

cp bin/mudos.cfg.orig lib/secure/cfg/mudos.cfg

! Then edit
lib/secure/cfg/mudos.cfg to point to the correct bin and
lib directories.

--- 298,309 ---- directory:

cd ! /home/joe/ds2.0

cp bin/mudos.cfg.orig lib/secure/cfg/mudos.cfg

! Then edit
lib/secure/cfg/mudos.cfg to point to the correct bin and
lib directories.

*************** *** 337,355 **** ./configure script as per the current instructions, which you
should follow closely.

- * If you have trouble logging in and the driver complains about
- "Cost" functions and "economy", then you've run into a very odd
- bug that's still a bit mysterious. Somehow your /save/economy.o
- file has been corrupted. Uncompress the tarball into a temporary
- directory and copy the original economy.o over the corrupt
- one. Then please email - me about this. Only one user has ever had
- this problem, but apparently it happened twice, so if it happens
- to someone else, I can at least tell him he's not crazy.
-
* If the driver craps out complaining about a hosed up swap
! file
, you're probably running Fedora, and you probably haven't
changed your hostname from the original "localhost.localdomain"
or whatever nonsense they use.
--- 328,335 ---- ./configure script as per the current instructions, which you
should follow closely.

* If the driver craps out complaining about a hosed up swap
! file
, you're probably running Fedora, and you probably haven't
changed your hostname from the original "localhost.localdomain"
or whatever nonsense they use.
*************** *** 361,369 **** its hostname, that it receive something like
"alpha", and ! not something like "alpha.bravo".
    If your machine is under the impression that its --- 341,347 ---- its hostname, that it receive something like
"alpha", and ! not something like "alpha.bravo".
    If your machine is under the impression that its *************** *** 374,381 **** mudos, which will eventually choke on it.
!     If you're good at C++, you can edit lines 66 and 76 of
v22.2b14/swap.c and correct this behavior. But the common sense fix is
--- 352,358 ---- mudos, which will eventually choke on it.
!     If you're good at C++, you can edit lines 66 and 76 of
v22.2b14/swap.c and correct this behavior. But the common sense fix is
*************** *** 397,403 **** is there a windows-format mudos.cfg in /secure/cfg? I'm running unix.


This is a symptom of my obsession to have the Windows lib distribution
! and the unix lib be absolutely identical. During a fresh install,
this file is overwritten with a unix version, if you follow the
install instructions.


--- 374,381 ---- is there a windows-format mudos.cfg in /secure/cfg? I'm running unix.

This is a symptom of my obsession to have the Windows lib distribution
! and the unix lib be absolutely identical. ! During a fresh install,
this file is overwritten with a unix version, if you follow the
install instructions.


*************** *** 417,423 **** How do I upgrade from one version of Dead Souls to another?


!     For the your convenience, patches are available to move from one minor
revision of Dead Souls to another. But there isn't a patch for every possible
--- 395,401 ---- How do I upgrade from one version of Dead Souls to another?


!     For your convenience, patches are available to move from one minor
revision of Dead Souls to another. But there isn't a patch for every possible
*************** *** 432,438 **** of Dead Souls to another. For example, do not expect a ds2.0 -> ds2.1 patch.

!     The upgrade principle for bot Windows and UNIX is the same. Basically
a Dead Souls patch is a pretty unsophisticated upgrade system. In the case of
--- 410,416 ---- of Dead Souls to another. For example, do not expect a ds2.0 -> ds2.1 patch.

!     The upgrade principle for both Windows and UNIX is the same. Basically
a Dead Souls patch is a pretty unsophisticated upgrade system. In the case of
*************** *** 517,541 **** Ok, it's running. Now what?

! Read the admin FAQ.
!
! Read the creator's FAQ.
!
! Log in and read the Player's Handbook.
!
! Then read the Creator's Manual.
!
! If you run into problems or have questions not addressed in the docs, ! use the <ds> ! channel
! to ask for help. See the
creator's FAQ for proper ! etiquette and form.
!

!
Dead Souls Homepage
! ! --- 495,508 ---- Ok, it's running. Now what?

! Log in and read the in-game Player's Handbook.
!
!
Read the Dead Souls Admin FAQ.

Read the Dead Souls Creator's FAQ.

Read the Dead Souls Installation FAQ.

Read the Quick Creation System Example Page.

Read the Debugging Guide.

Read the Editor Tutorial.
! Read ! the in-game Creator's Manual.
!
!

!
Dead ! Souls Homepage
! \ No newline at end of file diff -c -r --new-file ds2.0r19/lib/www/editor.html ds2.0r20b/lib/www/editor.html *** ds2.0r19/lib/www/editor.html Fri Mar 24 14:42:02 2006 --- ds2.0r20b/lib/www/editor.html Sun Apr 9 23:48:49 2006 *************** *** 1,174 **** ! ! ! ! Mud Editor Tutorial ! !
The ed Editor


This has always been the aspect of coding that new
creators have most trouble with. It's what discourages most
people from creating lots of stuff, in fact.

With Dead Souls, you can get away with avoiding ed
most of the time, by using the room maker and the thing maker.

But to add special functions to your code, like
magic items, smart NPC's (aka mobs), traps, hidden objects,
etc, you need to use ed, if you're going to be editing inside
the mud.

ed is a simple editing program. It is designed to
work on a line-by-line basis, so it is called a "line editor".

Let's start by looking at, and editing, a small file.
We've coded a sword, and we want to change its description
from "short sword" to "plain sword":


!
!

> cd /realms/cratylus/area/weap
1) I changed my working directory to my area weapons dir
/realms/cratylus/area/weap:
> ls
I listed the contents of that dir:
/realms/cratylus/area/weap/:
1 dagger.c 1 nco_sword.c~ 1 std_sword.c~
1 gsword.c 1 sharpsword.c 1 sword.c
001 gsword.c~ 1 staff.c
1 nco_sword.c 1 std_sword.c


> ed sword.c
I ran the ed command on the file sword.c.
/realms/cratylus/area/weap/sword.c, 641 bytes
:n
This makes the editor display line numbers next to the lines.
number on, list off
:1z This lists about 20 lines of text
1 /* /domains/Examples/weapon/sword.c
2 * from the Nightmare IV LPC Library
3 * a simple sword example, nothing fancy
4 * created by Descartes of Borg 950402
5 */
6
7 #include <lib.h>
8 #include <damage_types.h>
9 #include <vendor_types.h>
10
11 inherit LIB_ITEM;
12
13 static void create() {
14 item::create();
15 SetKeyName("short sword");
16 SetId( ({ "sword", "short sword" }) );
17 SetAdjectives( ({ "short" }) );
18 SetShort("a short sword");
19 SetLong("A cheap and rather dull short sword.");
20 SetMass(150);
21 SetDollarCost(50);
22 SetVendorType(VT_WEAPON);
:z
22 SetVendorType(VT_WEAPON);
23 SetClass(20);
24 SetDamageType(BLADE);
25 SetWeaponType("blade");
26 }
:15 I displayed line 15
15 SetKeyName("short sword");
:15c I used 'c' to replace line 15
15. * SetKeyName("plain sword"); I entered my replacement text
16. * . I entered a single dot on a blank line
:
16 SetId( ({ "sword", "short sword" }) );
:1z I listed about 20 lines, starting from line 1
1 /* /domains/Examples/weapon/sword.c
2 * from the Nightmare IV LPC Library
3 * a simple sword example, nothing fancy
4 * created by Descartes of Borg 950402
5 */
6
7 #include <lib.h>
8 #include <damage_types.h>
9 #include <vendor_types.h>
10
11 inherit LIB_ITEM;
12
13 static void create() {
14 item::create();
15 SetKeyName("plain sword");
16 SetId( ({ "sword", "short sword" }) );
17 SetAdjectives( ({ "short" }) );
18 SetShort("a short sword");
19 SetLong("A cheap and rather dull short sword.");
20 SetMass(150);
21 SetDollarCost(50);
22 SetVendorType(VT_WEAPON);
:18 I displayed line 18
18 SetShort("a short sword");
:18c I started the replacement of line 18
18. * SetShort("a plain sword"); I entered my replacement text
19. * . I entered a single dot on a blank line
:1z I displayed about 20 lines starting from line 1
1 /* /domains/Examples/weapon/sword.c
2 * from the Nightmare IV LPC Library
3 * a simple sword example, nothing fancy
4 * created by Descartes of Borg 950402
5 */
6
7 #include <lib.h>
8 #include <damage_types.h>
9 #include <vendor_types.h>
10
11 inherit LIB_ITEM;
12
13 static void create() {
14 item::create();
15 SetKeyName("plain sword");
16 SetId( ({ "sword", "short sword" }) );
17 SetAdjectives( ({ "short" }) );
18 SetShort("a plain sword");
19 SetLong("A cheap and rather dull short sword.");
20 SetMass(150);
21 SetDollarCost(50);
22 SetVendorType(VT_WEAPON);
:x I saved and exited
"/realms/cratylus/area/weap/sword.c" 26 lines 633 bytes
Exit from ed.
> update sword I loaded the file into memory
/realms/cratylus/area/weap/sword: Ok
!
!


Let's take this step by step:

1) I changed my working directory to my area weapons dir:
cd /realms/cratylus/area/weap

2) I listed the contents of that dir: ls

3) I ran the ed command on the file sword.c: ed sword.c

4) Within the editor, I issued the 'n' command. This makes the editor
display line numbers next to the lines.

5) Within the editor, I issued the '1z' command. What 'z' does is display
about 20 lines of the file (the exact number depends on your screen
settings. In my case it's 22). If you happen to be looking at line 1, it
will display lines 1 through to about 20. If you happen to be looking
at line 40, it will display from line 40 to about 60.
If you want to start looking at lines starting at line 15, you
can issue the '15z' command, which basically means "display about 20
lines starting at line 15".
In this case, I wanted to start from the beginning of the file,
so I issued '1z'.

6) '1z' stopped listing the file at line 22, so I entered 'z' again to
list the rest.

7) Since I want to change "short sword" to "plain sword", I examined each
line to find the word "short". I noticed that line 15 has "short" in it,
so to get a look at that line alone, I entered '15'.

8) Now that I'm sure line 15 needs to change, I issue the '15c' command.
'c' indicates that I want to change a line. '15c' means "delete whatever
was in line 15, and replace it with what I am about to type".

9) You can see that my editor prompt changed from ":" to "*". What this
means is that I am now in "input mode". Whatever I type now will be
added to the file. Since my last command in "command mode" was '15c',
I am now replacing that line with what I want the line to contain:
SetKeyName("plain sword");

10) Ok, I replaced the line, but I'm still in input mode. To go back to
command mode, I type a single period and enter, like this:
.

11) I'm back in command mode now. When I list the file contents with
'1z' I can see that line 15 now says what I wanted.

12) Now I see another line that needs changing, so I enter '18' to
get a closer look.

13) Sure enough, 18 needs to change, so I issue '18c'.

14) Like I did for line 15, I enter what the line should be.

15) To return to command mode, I enter a single period on a blank line.

16) I list the file contents, and see that my change was successful.

17) I'm finished making my changes, so I issue the 'x' command. 'x'
means "save the changes I have made, and exit the editor".

18) I am now at my regular command prompt. To load my changes to this
file, I type 'update sword'.


Editor basics, part 2



In the last section you saw what a simple line
replacement looks like in ed. Next we'll talk about some common
ed actions.

ADDING STUFF:

Suppose I want to specify that this sword requires only
one hand to wield it:

!
!

> ed sword.c started the editor
/realms/cratylus/area/weap/sword.c, 633 bytes
:n enabled line number printing
number on, list off
:15,22 listed lines 15 to 22
15 SetKeyName("plain sword");
16 SetId( ({ "sword", "short sword" }) );
17 SetAdjectives( ({ "short" }) );
18 SetShort("a plain sword");
19 SetLong("A cheap and rather dull short sword.");
20 SetMass(150);
21 SetDollarCost(50);
22 SetVendorType(VT_WEAPON);
:20a appended to the file after line 20
21. * SetHands(1); entered my added text
22. * . single dot on a blank line to exit input mode
:18,22 displayed line 18 through 22
18 SetShort("a plain sword");
19 SetLong("A cheap and rather dull short sword.");
20 SetMass(150);
21 SetHands(1);
22 SetDollarCost(50);
:x exited editor and saved
"/realms/cratylus/area/weap/sword.c" 27 lines 646 bytes
Exit from ed.
!
!


Here you can see that instead of 'c', which replaces, I
used 'a', which adds. I decided my new line would go after line
20, so I issued the command '20a'. Once I was done, I typed
a single dot on a blank line to exit "input mode". You'll notice
I didn't use the 'z' command. Instead, since I knew where my
changes would go, I decided to list lines 18 through 22 with
the command '18,22'. I then issued the 'x' command to save my
changes and exit the editor.
If had I wanted my addition to go in front of line 20,
I could have used the '20i' command.

DELETING LINES

Suppose I'm tired of seeing header lines that no
longer apply to this file. We can delete a single line, or
a range of lines, with the 'd' commmand:

!
> ed sword.c
!
/realms/cratylus/area/weap/sword.c, 646 bytes
:n enabled line number printing
number on, list off
:1,10 listed lines 1 to 10
1 /* /domains/Examples/weapon/sword.c
2 * from the Nightmare IV LPC Library
3 * a simple sword example, nothing fancy
4 * created by Descartes of Borg 950402
5 */
6
7 #include <lib.h>
8 #include <damage_types.h>
9 #include <vendor_types.h>
10
:1,5d deleted lines 1 to 5
:1,5 listed (the new) lines 1 to 5
1
2 #include <lib.h>
3 #include <damage_types.h>
4 #include <vendor_types.h>
5
:1d deleted blank line 1
:1z displayed the file starting at line 1
1 #include <lib.h>
2 #include <damage_types.h>
3 #include <vendor_types.h>
4
5 inherit LIB_ITEM;
6
7 static void create() {
8 item::create();
9 SetKeyName("plain sword");
10 SetId( ({ "sword", "short sword" }) );
11 SetAdjectives( ({ "short" }) );
12 SetShort("a plain sword");
13 SetLong("A cheap and rather dull short sword.");
14 SetMass(150);
15 SetHands(1);
16 SetDollarCost(50);
17 SetVendorType(VT_WEAPON);
18 SetClass(20);
19 SetDamageType(BLADE);
20 SetWeaponType("blade");
21 }
:x exited and saved
"/realms/cratylus/area/weap/sword.c" 21 lines 476 bytes
Exit from ed.
!
!


First I deleted lines 1 through 5 with the command '1,5d'.
Then, for good measure, I removed the remaining blank line '1d'.
Voila. Cleaner code.

REPLACING STRINGS

Well now I want to replace all instances of "short" with
"plain", and I don't feel like editing each matching line
manually. I can do a search and replace. First I will list which
lines need to change, then I will change them:

!
> ed sword.c
!
/realms/cratylus/area/weap/sword.c, 476 bytes
:n
enabled line number printing
number on, list off
:g/short/p
searched for and displayed lines containing "short"
10 SetId( ({ "sword", "short sword" }) );
11 SetAdjectives( ({ "short" }) );
13 SetLong("A cheap and rather dull short sword.");
:g/short/s/short/plain
searched for "short" and replaced with "plain"
:g/short/p
searched for "short" again but found none
:1z
listed file from line 1
1 #include <lib.h>
2 #include <damage_types.h>
3 #include <vendor_types.h>
4
5 inherit LIB_ITEM;
6
7 static void create() {
8 item::create();
9 SetKeyName("plain sword");
10 SetId( ({ "sword", "plain sword" }) );
11 SetAdjectives( ({ "plain" }) );
12 SetShort("a plain sword");
13 SetLong("A cheap and rather dull plain sword.");
14 SetMass(150);
15 SetHands(1);
16 SetDollarCost(50);
17 SetVendorType(VT_WEAPON);
18 SetClass(20);
19 SetDamageType(BLADE);
20 SetWeaponType("blade");
21 }
:1
moved to line 1
1 #include <lib.h>
:I
ran automatic indentation
Indenting entire code...
Indentation complete.
:1z
listed file from line 1
#include <lib.h>
#include <damage_types.h>
#include <vendor_types.h>

inherit LIB_ITEM;

static void create() {
item::create();
SetKeyName("plain sword");
SetId( ({ "sword", "plain sword" }) );
SetAdjectives( ({ "plain" }) );
SetShort("a plain sword");
SetLong("A cheap and rather dull plain sword.");
SetMass(150);
SetHands(1);
SetDollarCost(50);
SetVendorType(VT_WEAPON);
SetClass(20);
SetDamageType(BLADE);
SetWeaponType("blade");
}
:x
exited and saved
"/realms/cratylus/area/weap/sword.c" 21 lines 488 bytes
Exit from ed.
!
!


The command g/short/p showed me all the lines
that contained the substring "short". Then I ran the global
search and replace command to substitute "plain" for "short",
:g/short/s/short/plain
Then I searched again for the string "short" and
nothing came up, because it had been replaced.

Finally I went to line number 1 and issued the 'I'
command. This auto-indents the code, making it neater and
easier to read.


Editor basics, part 3



Now let's look at some common problems:


1) Accidental deletion


If you type 1,20d when you meant to type 1,2d you will end
up with a file 18 lines shorter than you intended. ed does not
have an "undo" command, so those lines will never come back.
However, if you quit the editor *without saving*, then that
deletion will not be committed to the file. You can issue the 'Q'
command:

:Q

To force quit without saving. Of course, if those lines
weren't already in the file, this won't help much.


2) Can't leave the editor


You try to write and exit, but get this:

:x
File command failed.

What this means is that for some reason, you can't write
to the file, so you don't exit the editor. What this usually means is that
you tried to edit a file that does not belong to you. Since you do not
have permission to modify the file, ed refuses to commit your changes.

There are two ways around this. If you don't really care
whether your changes are saved or not, you can just force quit the
editor with 'Q':

:Q
Exit from ed.

Your changes will be lost, but you'll be out of the editor.

If you really want to save this file, you'll have to save it
somewhere other than your current working directory (cwd). You can save
it to your home directory with the 'w' command, then force quit:

:w /realms/cratylus/sword.c
"/realms/cratylus/sword.c" 20 lines 478 bytes
:Q
Exit from ed.


3) Indent command fails


You try to auto-indent your code but get an error like this:

:I
Indenting entire code...
Unterminated string in line 13
Indentation halted.

This is pretty self explanatory. Indent relies on a certain
amount of coherence in your code, and if your syntax is sufficiently
munged, it can't figure out how to properly do its thing.
Examine the line that indent complains about, and also the
line before it. Sometimes a good line is accused of being bad, just
because it comes after a bad line.


4) I need to [something] in ed, but don't know how!


While in command mode, type 'h' and enter. You'll get
a handy list of ed commands available to you.


5) My ability/patience/time is limited. I want not to use ed.


I feel your pain. The currently available ways around
this are:

1) Shell account. If you can get shell, or command line access
to the computer that is running the mud, then you can probably
use an editor local to that computer (like vim) to edit files.
Chances are, though, that if you are a regular rank-and-file
creator, you will not be given shell access. Most system admins
consider giving random people off the net shell access
an abomination.

2) Server FTP/SFTP. The server that runs the mud might have an
ftp server or sftpd access. Again, most security-conscious sysadmins
will not permit Just Some Person Off The Internet to have this
kind of access.

3) Mud FTP. I don't like this option. Unix FTPD is a security
concern as it is. Using unsupported, un-warrantied mud network code
to provide ftp access to files seems to me to be equivalent to pulling
down your pants, bending over, and whistling for the Internet to
come visit. But...it's an option.

4) Client upload. This is actually the most sensible option, if
you are truly allergic to ed. You still need to use ed, but what
you can do is write your code in your favorite local editor, like
notepad or gvim or whatever. Then use your mud client (most of them
have an option to "send text") to send the code by running ed,
entering input mode, copying the code from your editor, and
pasting it into your client.
This is a somewhat awkward system, and ill-suited to
making minor changes. But it has the virtue of working well and
being a widely available option.

5) Suck it up. Really, you need to just get used to it. Don't
make me tell you stories about how when I was younger I had to
code using a VT terminal with no cut-and-paste, in an unheated,
locked computer lab 20'x10' in size, at 9600 bps. In a snowstorm.
Uphill both ways.



Dead Souls Homepage



! ! --- 1,23 ---- ! ! Mud Editor Tutorial ! !
The ed Editor


This has always been the aspect of coding that new
creators have most trouble with. It's what discourages most
people from creating lots of stuff, in fact.

With Dead Souls, you can get away with avoiding ed
most of the time, by using the room maker and the thing maker.

But to add special functions to your code, like
magic items, smart NPC's (aka mobs), traps, hidden objects,
etc, you need to use ed, if you're going to be editing inside
the mud.

ed is a simple editing program. It is designed to
work on a line-by-line basis, so it is called a "line editor".

Let's start by looking at, and editing, a small file.
We've coded a sword, and we want to change its description
from "short sword" to "plain sword":


!
!

> cd /realms/cratylus/area/weap
1) I changed my working directory to my area weapons dir
/realms/cratylus/area/weap:
> ls
I listed the contents of that dir:
/realms/cratylus/area/weap/:
1 dagger.c 1 nco_sword.c~ 1 std_sword.c~
1 gsword.c 1 sharpsword.c 1 sword.c
001 gsword.c~ 1 staff.c
1 nco_sword.c 1 std_sword.c


> ed sword.c
I ran the ed command on the file sword.c.
/realms/cratylus/area/weap/sword.c, 641 bytes
:n
This makes the editor display line numbers next to the lines.
number on, list off
:1z This lists about 20 lines of text
1 /* /domains/Examples/weapon/sword.c
2 * from the Nightmare IV LPC Library
3 * a simple sword example, nothing fancy
4 * created by Descartes of Borg 950402
5 */
6
7 #include <lib.h>
8 #include <damage_types.h>
9 #include <vendor_types.h>
10
11 inherit LIB_ITEM;
12
13 static void create() {
14 item::create();
15 SetKeyName("short sword");
16 SetId( ({ "sword", "short sword" }) );
17 SetAdjectives( ({ "short" }) );
18 SetShort("a short sword");
19 SetLong("A cheap and rather dull short sword.");
20 SetMass(150);
21 SetDollarCost(50);
22 SetVendorType(VT_WEAPON);
:z
22 SetVendorType(VT_WEAPON);
23 SetClass(20);
24 SetDamageType(BLADE);
25 SetWeaponType("blade");
26 }
:15 I displayed line 15
15 SetKeyName("short sword");
:15c I used 'c' to replace line 15
15. * SetKeyName("plain sword"); I entered my replacement text
16. * . I entered a single dot on a blank line
:
16 SetId( ({ "sword", "short sword" }) );
:1z I listed about 20 lines, starting from line 1
1 /* /domains/Examples/weapon/sword.c
2 * from the Nightmare IV LPC Library
3 * a simple sword example, nothing fancy
4 * created by Descartes of Borg 950402
5 */
6
7 #include <lib.h>
8 #include <damage_types.h>
9 #include <vendor_types.h>
10
11 inherit LIB_ITEM;
12
13 static void create() {
14 item::create();
15 SetKeyName("plain sword");
16 SetId( ({ "sword", "short sword" }) );
17 SetAdjectives( ({ "short" }) );
18 SetShort("a short sword");
19 SetLong("A cheap and rather dull short sword.");
20 SetMass(150);
21 SetDollarCost(50);
22 SetVendorType(VT_WEAPON);
:18 I displayed line 18
18 SetShort("a short sword");
:18c I started the replacement of line 18
18. * SetShort("a plain sword"); I entered my replacement text
19. * . I entered a single dot on a blank line
:1z I displayed about 20 lines starting from line 1
1 /* /domains/Examples/weapon/sword.c
2 * from the Nightmare IV LPC Library
3 * a simple sword example, nothing fancy
4 * created by Descartes of Borg 950402
5 */
6
7 #include <lib.h>
8 #include <damage_types.h>
9 #include <vendor_types.h>
10
11 inherit LIB_ITEM;
12
13 static void create() {
14 item::create();
15 SetKeyName("plain sword");
16 SetId( ({ "sword", "short sword" }) );
17 SetAdjectives( ({ "short" }) );
18 SetShort("a plain sword");
19 SetLong("A cheap and rather dull short sword.");
20 SetMass(150);
21 SetDollarCost(50);
22 SetVendorType(VT_WEAPON);
:x I saved and exited
"/realms/cratylus/area/weap/sword.c" 26 lines 633 bytes
Exit from ed.
> update sword I loaded the file into memory
/realms/cratylus/area/weap/sword: Ok
!
!


Let's take this step by step:

1) I changed my working directory to my area weapons dir:
cd /realms/cratylus/area/weap

2) I listed the contents of that dir: ls

3) I ran the ed command on the file sword.c: ed sword.c

4) Within the editor, I issued the 'n' command. This makes the editor
display line numbers next to the lines.

5) Within the editor, I issued the '1z' command. What 'z' does is display
about 20 lines of the file (the exact number depends on your screen
settings. In my case it's 22). If you happen to be looking at line 1, it
will display lines 1 through to about 20. If you happen to be looking
at line 40, it will display from line 40 to about 60.
If you want to start looking at lines starting at line 15, you
can issue the '15z' command, which basically means "display about 20
lines starting at line 15".
In this case, I wanted to start from the beginning of the file,
so I issued '1z'.

6) '1z' stopped listing the file at line 22, so I entered 'z' again to
list the rest.

7) Since I want to change "short sword" to "plain sword", I examined each
line to find the word "short". I noticed that line 15 has "short" in it,
so to get a look at that line alone, I entered '15'.

8) Now that I'm sure line 15 needs to change, I issue the '15c' command.
'c' indicates that I want to change a line. '15c' means "delete whatever
was in line 15, and replace it with what I am about to type".

9) You can see that my editor prompt changed from ":" to "*". What this
means is that I am now in "input mode". Whatever I type now will be
added to the file. Since my last command in "command mode" was '15c',
I am now replacing that line with what I want the line to contain:
SetKeyName("plain sword");

10) Ok, I replaced the line, but I'm still in input mode. To go back to
command mode, I type a single period and enter, like this:
.

11) I'm back in command mode now. When I list the file contents with
'1z' I can see that line 15 now says what I wanted.

12) Now I see another line that needs changing, so I enter '18' to
get a closer look.

13) Sure enough, 18 needs to change, so I issue '18c'.

14) Like I did for line 15, I enter what the line should be.

15) To return to command mode, I enter a single period on a blank line.

16) I list the file contents, and see that my change was successful.

17) I'm finished making my changes, so I issue the 'x' command. 'x'
means "save the changes I have made, and exit the editor".

18) I am now at my regular command prompt. To load my changes to this
file, I type 'update sword'.


Editor basics, part 2



In the last section you saw what a simple line
replacement looks like in ed. Next we'll talk about some common
ed actions.

ADDING STUFF:

Suppose I want to specify that this sword requires only
one hand to wield it:

!
!

> ed sword.c started the editor
/realms/cratylus/area/weap/sword.c, 633 bytes
:n enabled line number printing
number on, list off
:15,22 listed lines 15 to 22
15 SetKeyName("plain sword");
16 SetId( ({ "sword", "short sword" }) );
17 SetAdjectives( ({ "short" }) );
18 SetShort("a plain sword");
19 SetLong("A cheap and rather dull short sword.");
20 SetMass(150);
21 SetDollarCost(50);
22 SetVendorType(VT_WEAPON);
:20a appended to the file after line 20
21. * SetHands(1); entered my added text
22. * . single dot on a blank line to exit input mode
:18,22 displayed line 18 through 22
18 SetShort("a plain sword");
19 SetLong("A cheap and rather dull short sword.");
20 SetMass(150);
21 SetHands(1);
22 SetDollarCost(50);
:x exited editor and saved
"/realms/cratylus/area/weap/sword.c" 27 lines 646 bytes
Exit from ed.
!
!


Here you can see that instead of 'c', which replaces, I
used 'a', which adds. I decided my new line would go after line
20, so I issued the command '20a'. Once I was done, I typed
a single dot on a blank line to exit "input mode". You'll notice
I didn't use the 'z' command. Instead, since I knew where my
changes would go, I decided to list lines 18 through 22 with
the command '18,22'. I then issued the 'x' command to save my
changes and exit the editor.
If had I wanted my addition to go in front of line 20,
I could have used the '20i' command.

DELETING LINES

Suppose I'm tired of seeing header lines that no
longer apply to this file. We can delete a single line, or
a range of lines, with the 'd' commmand:

!
> ed sword.c
!
/realms/cratylus/area/weap/sword.c, 646 bytes
:n enabled line number printing
number on, list off
:1,10 listed lines 1 to 10
1 /* /domains/Examples/weapon/sword.c
2 * from the Nightmare IV LPC Library
3 * a simple sword example, nothing fancy
4 * created by Descartes of Borg 950402
5 */
6
7 #include <lib.h>
8 #include <damage_types.h>
9 #include <vendor_types.h>
10
:1,5d deleted lines 1 to 5
:1,5 listed (the new) lines 1 to 5
1
2 #include <lib.h>
3 #include <damage_types.h>
4 #include <vendor_types.h>
5
:1d deleted blank line 1
:1z displayed the file starting at line 1
1 #include <lib.h>
2 #include <damage_types.h>
3 #include <vendor_types.h>
4
5 inherit LIB_ITEM;
6
7 static void create() {
8 item::create();
9 SetKeyName("plain sword");
10 SetId( ({ "sword", "short sword" }) );
11 SetAdjectives( ({ "short" }) );
12 SetShort("a plain sword");
13 SetLong("A cheap and rather dull short sword.");
14 SetMass(150);
15 SetHands(1);
16 SetDollarCost(50);
17 SetVendorType(VT_WEAPON);
18 SetClass(20);
19 SetDamageType(BLADE);
20 SetWeaponType("blade");
21 }
:x exited and saved
"/realms/cratylus/area/weap/sword.c" 21 lines 476 bytes
Exit from ed.
!
!


First I deleted lines 1 through 5 with the command '1,5d'.
Then, for good measure, I removed the remaining blank line '1d'.
Voila. Cleaner code.

REPLACING STRINGS

Well now I want to replace all instances of "short" with
"plain", and I don't feel like editing each matching line
manually. I can do a search and replace. First I will list which
lines need to change, then I will change them:

!
> ed sword.c
!
/realms/cratylus/area/weap/sword.c, 476 bytes
:n
enabled line number printing
number on, list off
:g/short/p
searched for and displayed lines containing "short"
10 SetId( ({ "sword", "short sword" }) );
11 SetAdjectives( ({ "short" }) );
13 SetLong("A cheap and rather dull short sword.");
:g/short/s/short/plain
searched for "short" and replaced with "plain"
:g/short/p
searched for "short" again but found none
:1z
listed file from line 1
1 #include <lib.h>
2 #include <damage_types.h>
3 #include <vendor_types.h>
4
5 inherit LIB_ITEM;
6
7 static void create() {
8 item::create();
9 SetKeyName("plain sword");
10 SetId( ({ "sword", "plain sword" }) );
11 SetAdjectives( ({ "plain" }) );
12 SetShort("a plain sword");
13 SetLong("A cheap and rather dull plain sword.");
14 SetMass(150);
15 SetHands(1);
16 SetDollarCost(50);
17 SetVendorType(VT_WEAPON);
18 SetClass(20);
19 SetDamageType(BLADE);
20 SetWeaponType("blade");
21 }
:1
moved to line 1
1 #include <lib.h>
:I
ran automatic indentation
Indenting entire code...
Indentation complete.
:1z
listed file from line 1
#include <lib.h>
#include <damage_types.h>
#include <vendor_types.h>

inherit LIB_ITEM;

static void create() {
item::create();
SetKeyName("plain sword");
SetId( ({ "sword", "plain sword" }) );
SetAdjectives( ({ "plain" }) );
SetShort("a plain sword");
SetLong("A cheap and rather dull plain sword.");
SetMass(150);
SetHands(1);
SetDollarCost(50);
SetVendorType(VT_WEAPON);
SetClass(20);
SetDamageType(BLADE);
SetWeaponType("blade");
}
:x
exited and saved
"/realms/cratylus/area/weap/sword.c" 21 lines 488 bytes
Exit from ed.
!
!


The command g/short/p showed me all the lines
that contained the substring "short". Then I ran the global
search and replace command to substitute "plain" for "short",
:g/short/s/short/plain
Then I searched again for the string "short" and
nothing came up, because it had been replaced.

Finally I went to line number 1 and issued the 'I'
command. This auto-indents the code, making it neater and
easier to read.


Editor basics, part 3



Now let's look at some common problems:


1) Accidental deletion


If you type 1,20d when you meant to type 1,2d you will end
up with a file 18 lines shorter than you intended. ed does not
have an "undo" command, so those lines will never come back.
However, if you quit the editor *without saving*, then that
deletion will not be committed to the file. You can issue the 'Q'
command:

:Q

To force quit without saving. Of course, if those lines
weren't already in the file, this won't help much.


2) Can't leave the editor


You try to write and exit, but get this:

:x
File command failed.

What this means is that for some reason, you can't write
to the file, so you don't exit the editor. What this usually means is that
you tried to edit a file that does not belong to you. Since you do not
have permission to modify the file, ed refuses to commit your changes.

There are two ways around this. If you don't really care
whether your changes are saved or not, you can just force quit the
editor with 'Q':

:Q
Exit from ed.

Your changes will be lost, but you'll be out of the editor.

If you really want to save this file, you'll have to save it
somewhere other than your current working directory (cwd). You can save
it to your home directory with the 'w' command, then force quit:

:w /realms/cratylus/sword.c
"/realms/cratylus/sword.c" 20 lines 478 bytes
:Q
Exit from ed.


3) Indent command fails


You try to auto-indent your code but get an error like this:

:I
Indenting entire code...
Unterminated string in line 13
Indentation halted.

This is pretty self explanatory. Indent relies on a certain
amount of coherence in your code, and if your syntax is sufficiently
munged, it can't figure out how to properly do its thing.
Examine the line that indent complains about, and also the
line before it. Sometimes a good line is accused of being bad, just
because it comes after a bad line.


4) I need to [something] in ed, but don't know how!


While in command mode, type 'h' and enter. You'll get
a handy list of ed commands available to you.


5) My ability/patience/time is limited. I want not to use ed.


I feel your pain. The currently available ways around
this are:

1) Shell account. If you can get shell, or command line access
to the computer that is running the mud, then you can probably
use an editor local to that computer (like vim) to edit files.
Chances are, though, that if you are a regular rank-and-file
creator, you will not be given shell access. Most system admins
consider giving random people off the net shell access
an abomination.

2) Server FTP/SFTP. The server that runs the mud might have an
ftp server or sftpd access. Again, most security-conscious sysadmins
will not permit Just Some Person Off The Internet to have this
kind of access.

3) Mud FTP. I don't like this option. Unix FTPD is a security
concern as it is. Using unsupported, un-warrantied mud network code
to provide ftp access to files seems to me to be equivalent to pulling
down your pants, bending over, and whistling for the Internet to
come visit. But...it's an option.

4) Client upload. This is actually the most sensible option, if
you are truly allergic to ed. You still need to use ed, but what
you can do is write your code in your favorite local editor, like
notepad or gvim or whatever. Then use your mud client (most of them
have an option to "send text") to send the code by running ed,
entering input mode, copying the code from your editor, and
pasting it into your client.
This is a somewhat awkward system, and ill-suited to
making minor changes. But it has the virtue of working well and
being a widely available option.

5) Suck it up. Really, you need to just get used to it. Don't
make me tell you stories about how when I was younger I had to
code using a VT terminal with no cut-and-paste, in an unheated,
locked computer lab 20'x10' in size, at 9600 bps. In a snowstorm.
Uphill both ways.



Dead Souls Homepage



! \ No newline at end of file diff -c -r --new-file ds2.0r19/lib/www/example.html ds2.0r20b/lib/www/example.html *** ds2.0r19/lib/www/example.html Thu Feb 23 15:40:41 2006 --- ds2.0r20b/lib/www/example.html Sun Apr 9 23:48:50 2006 *************** *** 1,22 **** ! ! ! ! creation example page ! What's the QCS?
!

QCS stands for Quick Creation System. The QCS is a
series of commands and modules that lets you create stuff
easily and quickly. Before the QCS, if you wanted to make
an orc, you would edit the text file by hand, or copy
a template file and use an editor to manually change the
lines you needed to modify. This could be a tiresome
process, as the standard editor can be a bit awkward, and
making dozens of objects this way could be real torture for
beginners.

The QCS changes all of that. Rather than use an
editor to meodify files, the QCS gives you commands that
permit you to modify objects on the fly. This means that
orc creation for example could involve just the following
simple steps (please note "npc" is another word for "mob"):

create npc new_orc

modify npc name orc

modify orc short a mean-looking orc

modify orc long A typical orc: nasty, brutish, and short.

modify orc race orc

And that's it. All your modifications automatically
get written to new_orc.c (usually in your area directory),
and you now have an npc you can add to a room. Adding things
to rooms is just as easy. Creating weapons, armor, and other
objects is done the same way.

For complete details and examples, read the
QCS chapters in the Creators Manual. The QCS section starts
in chapter 31.

This is a log of the creation of some items using the Dead Souls creation system. It has
--- 1,11 ---- ! ! creation example page ! What's the QCS?
!

QCS stands for Quick Creation System. The QCS is a
series of commands and modules that lets you create stuff
easily and quickly. Before the QCS, if you wanted to make
an orc, you would edit the text file by hand, or copy
a template file and use an editor to manually change the
lines you needed to modify. This could be a tiresome
process, as the standard editor can be a bit awkward, and
making dozens of objects this way could be real torture for
beginners.

The QCS changes all of that. Rather than use an
editor to meodify files, the QCS gives you commands that
permit you to modify objects on the fly. This means that
orc creation for example could involve just the following
simple steps (please note "npc" is another word for "mob"):

create npc new_orc

modify npc name orc

modify orc short a mean-looking orc

modify orc long A typical orc: nasty, brutish, and short.

modify orc race orc

And that's it. All your modifications automatically
get written to new_orc.c (usually in your area directory),
and you now have an npc you can add to a room. Adding things
to rooms is just as easy. Creating weapons, armor, and other
objects is done the same way.

For complete details and examples, read the
QCS chapters in the Creators Manual. The QCS section starts
in chapter 31.

This is a log of the creation of some items using the Dead Souls creation system. It has
*************** *** 44,51 **** A simple table is here.
A fighter is standing here.

! //// This is the standard sample room. We're about to create a new room to the east of it.
create room east test1
--- 33,39 ---- A simple table is here.
A fighter is standing here.

! //// This is the standard sample room. We're about to create a new room to the east of it.
create room east test1
*************** *** 72,79 **** A simple table is here.
A fighter is standing here.

! //// We go into the new room and see it is a copy of the old one. Let's change the short description to avoid confusion:
modify here short Room One
--- 60,66 ---- A simple table is here.
A fighter is standing here.

! //// We go into the new room and see it is a copy of the old one. Let's change the short description to avoid confusion:
modify here short Room One
*************** *** 81,88 **** "/tmp/indent.1134436526.tmp.dat" 27 lines 515 bytes
Exit from ed.

! //// We don't need the fighter from the other room here, so we remove him from this new room's inventory.
delete fighter
--- 68,74 ---- "/tmp/indent.1134436526.tmp.dat" 27 lines 515 bytes
Exit from ed.

! //// We don't need the fighter from the other room here, so we remove him from this new room's inventory.
delete fighter
*************** *** 879,884 **** and objects quickly helps you avoid getting bogged down in mechanics when what you really want to do is build.


! Dead Souls Homepage
! ! --- 865,869 ---- and objects quickly helps you avoid getting bogged down in mechanics when what you really want to do is build.


! Dead Souls Homepage
! \ No newline at end of file diff -c -r --new-file ds2.0r19/lib/www/router.html ds2.0r20b/lib/www/router.html *** ds2.0r19/lib/www/router.html Wed Dec 31 19:00:00 1969 --- ds2.0r20b/lib/www/router.html Sun Apr 9 23:48:50 2006 *************** *** 0 **** --- 1,234 ---- + + + + Dead Souls I3 router + + + + +
+ +
+
+
+
+
+
+
The + Dead Souls + Intermud3 Router
+
+
+
This page is for folks + already using Dead Souls and modifying
+
+
+
their intermud configuration. If + this does not apply to you, please
+ return to the main site for general + information:
+
+
+
+ + Or the following FAQs:
+
+
The General FAQ  http://dead-souls.net/ds-faq.html
+
+
The Admin FAQ  http://dead-souls.net/ds-admin-faq.html
+
+
The Creator FAQ: http://dead-souls.net/ds-creator-faq.html
+
+
The Installation FAQ: http://dead-souls.net/ds-inst-faq.html
+

+
+ What is + the Dead Souls router? + It's an intermud protocol version 3
+ router which follows intermud standards ( http://intermud.org + ) and
+ was written by the + legendary Tim@TimMUD.
+
+ What is the IP and port?  + This may occasionally change. Such changes
+ will be posted here when they happen. The current port and address is:
+
+
+
IP: 149.152.218.102 +     port: 23
+
+
+
How + do I set it up?
+
+
If you're + running r18 or higher, you need do nothing.
+ If you're running r17 or r16, upgrading to r18 will
+ be enough.
+
+
+ It doesn't + work
+
+
     There are a few possible reasons for + this, mostly
+ centered around the router being paranoid about
+ security. The router resets frequently, and on that
+ reset, your mud will be authenticated. Just be patient.
+ If it's been more than a day or so, email me at
+ <my name here>@users.sourceforge.net
+

+
+ What's the + point of a new router? Who died and made you intermud king?
+
+     On the morning of 27 March 2006, the intermud.org i3 + router stopped
+ functioning. There had been some talk on the dead_souls channel of how
+ unreliable the i3 router was, and how we should make our own,
+ etc, yakety schmakety.
+     March 27th was the last straw. For Dead Souls + developers, the
+ dead_souls intermud channel was a vital resource for development + discussion
+ and support. After being down for 24 hours, I decided it was time to
+ implement a router that the Dead Souls muds could count on.
+
+
+ Why did + you change it from port 25 to port 23?
+
+     During testing, it was discovered that some ISP's + and hosting services block
+ outbound connections to port 25, presumably for anti-spam reasons. Since
+ port 23 is very often open for outbound connections, and it is rarely
+ spam-firewalled, it seemed like a good choice. It's not like we were + doing
+ anything else with it.
+
+
+ Isn't a + low port a security risk?
+
+     It's not running the way you think.
+
+
+ Hey, XYZ + is broken and ABC works only half the time
+
+     For crying out loud, email me and tell me. I need to + know. I'm still
+ in the early stages of customizing and troubleshooting, so I need all + the
+ bug reports I can get. Please email me at <my name + here>@users.sourceforge.net
+
+
+ There are a + bunch of non-active muds on the mudlist.
+

+     This is a known bug. I'm working on tightening up
+ the mudlist update code.
+

+
+ Is this + router actually any more stable? What's the uptime?
+
+     It looks like there's good potential for this
+ router to be just as stable as the old *gjs, if not
+ more so. The biggest danger comes from the fact that
+ it's running on a computer on the campus of a university
+ I went to 15 years ago, so some bored network admin
+ might notice it and pull the plug. Should that ever
+ happen, the new IP will be posted here.
+
+     The most likely thing to happen is that the machine
+ it's on could lose power, despite being on UPS. If
+ this happens, channel communication will be limited
+ until someone emails me and tells me I need to
+ reload channels. On the todo list is a plan to make
+ channel data persist across server resets.
+
+     In general, however, about every other day or
+  every third day I notice that *gjs is down or has
+ been down for a couple of hours, and our new router
+ is still going strong.
+
+
+ You should + integrate your router with *gjs and enable failover
+
+     I will, just as soon as you send me the network code
+ to do it. Until then, this is what you get.
+
+
+ How does + the router work?
+
+     Tim@TimMUD wrote a swell LPC based router that is
+ basically a bunch of .h files you put into a TMI-2
+ mud. You tinker with the settings a bit, and your TMI-2
+ mud becomes an intermud router.
+     I got rather medieval on his code and shoehorned it
+ into Dead Souls. It's a testament to Tim's skill that
+ my crude fumblings were able to get the thing ported
+ and working.
+
+
+ Is router + code part of Dead Souls?
+
+ With Tim's blessing I've included his I3 router
+ in the Dead Souls distribution, after removing/replacing
+ some non-Tim code. This means that any Dead Souls
+ mud can serve as a router, should it wish to
+ establish its own private intermud network. Eventually
+ these individual routers may be part of a failover
+ network, but there are no firm plans for this in place.
+
+
+ How do I + become my own I3 router?
+
+ Read the code in /secure/daemon/i3router. Understand it.
+ Then modify it to suit you. I won't be posting step-
+ by-step instructions on how to do this, because I believe
+ this is one of those things that you really need to
+ figure out on your own. If you can't figure it out
+ by reading the code, I argue you have no business
+ running the router.
+
+
+ - Cratylus
+
+
+
+
+
+
More technical docs:
+ Creator FAQ             + Debugging FAQ         + Editor Tutorial     +   +   The Quick Creation System         +

+
+
+
+
+
+
+
+
+
+ +