/* /lib/interactive.c * from the Nightmare IVr1 Object Library * an interactive object * created by Descartes of Borg 941001 for the Idea Exchange * Version: @(#) interactive.c 1.17@(#) * Last modified: 97/01/03 */ #include <lib.h> #include <clock.h> #include <privs.h> #include <daemons.h> #include <objects.h> #include <rooms.h> #include <marriage.h> #include <medium.h> #include <position.h> #include <message_class.h> #include <vision.h> #include <voting.h> #include "include/interactive.h" inherit LIB_CONTAINER; inherit LIB_OBJECT; inherit LIB_AUTOSAVE; inherit LIB_FILES; inherit LIB_MOVE; inherit LIB_PAGER; inherit LIB_MESSAGES; inherit LIB_INTERFACE; private int Age, WhereBlock, Brief, LoginTime, BirthTime; private string Password, Email, RealName, Rank, LoginSite, HostSite, WebPage; private mapping News; private class marriage *Marriages; private static int LastAge, Setup; private static object NetDiedHere; private static mapping LastError; private static string *UserId; static void create() { object::create(); messages::create(); interface::create(); SetOpacity(0); Marriages = ({}); HostSite = ""; Brief = 0; Password = 0; Email = 0; RealName = 0; Rank = "citizen"; LoginSite = ROOM_START; BirthTime = time(); LastAge = time(); News = ([]); SetShort("$N the unaccomplished"); SetLong("$N is nondescript."); } /* *************** /lib/interactive.c modal functions *************** */ mixed CanDivorce(object who) { class marriage m; if( !Marriages || !sizeof(Marriages) ) return GetName() + " is not married!"; m = Marriages[0]; if( m->DivorceDate ) return GetName() + " is not married!"; return 1; } mixed CanGet(object ob) { return GetName() + " is a living being!"; } mixed CanMarry(object who, object to_whom) { if( !Marriages ) Marriages = ({}); if( GetSpouse() ) return GetName() + " is currently married!"; return 1; } /* *************** /lib/interactive.c lfuns *************** */ int Setup() { mapping mp; string tmp; if(Setup) return 0; else Setup = 1; set_living_name(GetKeyName()); interface::Setup(); add_action((: cmdQuit :), "quit"); HostSite = query_ip_name(this_object()); LoginTime = time(); SetId(({})); autosave::Setup(); call_out("save_player", 2, GetKeyName()); log_file("enter", GetCapName()+" (enter): "+ctime(time())+ " : "+query_ip_name(this_object())+"\n"); if( VOTING_D->GetStatus() == VOTE_RUNNING ) { if( VOTING_D->GetMode() == VOTE_MODE_CANDIDATES ) eventPrint("%^YELLOW%^Class Elections are in progress! " "Go nominate candidates!%^RESET%^"); if( VOTING_D->GetMode() == VOTE_MODE_VOTING ) eventPrint("%^YELLOW%^Class Elections are in progress! " "Go vote for the candidates!%^RESET%^"); } if( VOTING_D->GetVoteStatus( this_object() ) != VOTE_ALREADY_VOTED ) { eventPrint("%^YELLOW%^You have not yet voted! " "Please vote now.%^RESET%^"); eventMove( VOTING_D->GetVoteRoom() ); } else { object room; catch(room = load_object(LoginSite)); if( room && room->GetMedium() == MEDIUM_AIR ) { } if( !eventMove(LoginSite) ) { eventMove(LoginSite = ROOM_START); } } environment()->eventPrint(tmp, MSG_ENV, this_object()); if( !(tmp = GetMessage("login")) ) tmp = GetName() + " enters " + mud_name() + "."; filter(users(), (: archp :))->eventPrint("[" + GetCapName() + " logs in]", MSG_SYSTEM); if(!catch(mp = (mapping)FOLDERS_D->mail_status(GetKeyName()))) { if(mp["unread"]) { eventPrint("\n>>> " + mp["unread"] + " of your " + (mp["total"] == 1 ? mp["total"] + " letter is" : mp["total"] + " letters remain") + " unread. <<<\n", MSG_SYSTEM); } } NEWS_D->GeneralNews(); return 1; } static void net_dead() { interface::net_dead(); Age += time() - LastAge; LastAge = time(); NetDiedHere = environment(this_object()); save_player(GetKeyName()); log_file("enter", GetCapName() + " (net-dead): " + ctime(time()) + "\n"); environment()->eventPrint(GetName() + " suddenly disappears into " "a sea of irreality.", MSG_ENV, this_object()); filter(users(), (: archp :))->eventPrint("[" + GetCapName() + " goes net-dead]", MSG_SYSTEM); eventMove(ROOM_FREEZER); if(query_snoop(this_object())) query_snoop(this_object())->eventPrint(GetCapName() + " has gone " "net-dead.", MSG_SYSTEM); } void eventReconnect() { string dead_ed; interface::eventReconnect(); LastAge = time(); HostSite = query_ip_name(this_object()); eventPrint("Reconnected.", MSG_SYSTEM); filter(users(), (: archp :))->eventPrint("[" + GetCapName() + " has " "rejoined " + mud_name() + "]", MSG_SYSTEM); if( NetDiedHere ) eventMove(NetDiedHere); else eventMove(ROOM_START); environment()->eventPrint(GetCapName() + " has rejoined this reality.", MSG_ENV, this_object()); NetDiedHere = 0; } void eventDescribeEnvironment(int brief) { object env; mixed tmp; string *shorts; string desc, smell, sound, touch; int i, maxi; if(!(env = environment(this_object()))) { eventPrint("You are nowhere.", MSG_ROOMDESC); return; } switch( i = GetEffectiveVision() ) { case VISION_BLIND: eventPrint("You are blind and can see nothing."); break; case VISION_TOO_DARK: eventPrint("It is much too dark to see."); break; case VISION_DARK: eventPrint("It is too dark to see."); break; case VISION_TOO_BRIGHT: eventPrint("It is much too %^YELLOW%^bright%^RESET%^ to see."); break; case VISION_BRIGHT: eventPrint("It is too %^YELLOW%^bright%^RESET%^ to see."); break; } if( !brief ) { if( i == VISION_CLEAR ) { desc = (string)env->GetObviousExits() || ""; desc = capitalize((string)env->GetShort() || "") + " [" + desc + "]\n"; } else desc = ""; if( i == VISION_CLEAR || i == VISION_LIGHT || i == VISION_DIM ) desc += (string)env->GetLong(); if(functionp(tmp = (mixed)env->GetSmell("default"))) tmp = (string)(*tmp)("default"); smell = tmp; if(functionp(tmp = (mixed)env->GetListen("default"))) tmp = (string)(*tmp)("default"); sound = tmp; if( functionp(tmp = (mixed)env->GetTouch("default")) ) tmp = evaluate(tmp, "default"); touch = tmp; } else { if( i == VISION_CLEAR || i == VISION_LIGHT || i == VISION_DIM ) { 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); if( sound ) eventPrint("%^CYAN%^" + sound, MSG_ROOMDESC); if( touch ) eventPrint("%^YELLOW%^" + touch, MSG_ROOMDESC); desc = ""; if( i == VISION_CLEAR ) { mapping lying = ([]); shorts = map(filter(all_inventory(env), function(object ob) { if( living(ob) ) return 0; if( (int)ob->GetInvis(this_object()) ) return 0; if( (int)ob->isFreshCorpse() ) return 0; return 1; }), (: (string)$1->GetShort() :)); foreach(string s in shorts) { if( s ) { lying[s]++; } } for(i=0, desc = 0, maxi = sizeof(shorts = keys(lying)); i<maxi; i++) { string key = shorts[i]; int val = lying[shorts[i]]; if( val < 2 ) { if( !desc ) desc = "%^MAGENTA%^" + capitalize(key) + "%^RESET%^MAGENTA%^"; else desc += key + "%^RESET%^MAGENTA%^"; } else { if( !desc ) desc = "%^MAGENTA%^" + capitalize(consolidate(val, key)) + "%^RESET%^MAGENTA%^"; else desc += consolidate(val, key) + "%^RESET%^MAGENTA%^"; } if( i == maxi - 1 ) { if( maxi > 1 || val >1 ) desc += " are here.%^RESET%^\n"; else desc += " is here.%^RESET%^\n"; } else if( i == maxi - 2 ) { if( maxi == 2 ) { desc += " and "; } else { desc += ", and "; } } else desc += ", "; } } i = GetEffectiveVision(); if( i == VISION_CLEAR || i == VISION_LIGHT || i == VISION_DIM ) { mapping lying = ([]), sitting = ([]), standing = ([]); object *obs; string key; int val; obs = filter(all_inventory(env), function(object ob) { if( (int)ob->GetInvis(this_object()) ) return 0; if( living(ob) ) return 1; if( (int)ob->isFreshCorpse() ) return 1; }) - ({ this_object() }); maxi = sizeof(shorts = map(obs, (: (string)$1->GetHealthShort() :))); foreach(object liv in obs) { string s = (string)liv->GetHealthShort(); int pos = (int)liv->GetPosition(); if( !s ) continue; if( creatorp(liv) || pos == POSITION_STANDING) standing[s]++; else if( pos == POSITION_LYING || (int)liv->isFreshCorpse() ) lying[s]++; else if( pos == POSITION_SITTING ) sitting[s]++; else lying[s]++; } if( !desc ) { tmp = ""; } else { tmp = desc; } desc = ""; foreach(key, val in lying) { if( val<2 ) desc += capitalize(key) + "%^RESET%^ is lying down."; else desc += capitalize(consolidate(val, key)) + "%^RESET%^ are lying down."; desc += "\n"; } foreach(key, val in sitting) { if( val<2 ) desc += capitalize(key) + "%^RESET%^ is sitting down."; else desc += capitalize(consolidate(val, key)) + "%^RESET%^ are sitting down."; desc += "\n"; } foreach(key, val in standing) { if( val<2 ) desc += capitalize(key) + "%^RESET%^ is standing here."; else desc += capitalize(consolidate(val, key)) + "%^RESET%^ are standing here."; desc += "\n"; } } if( tmp ) { desc = tmp + desc; } if( sizeof(desc) ) { eventPrint(desc + "\n", MSG_ROOMDESC); } } int eventDestruct() { object ob; int i; interface::eventDestruct(); foreach(ob in deep_inventory(this_object())) { if( ob ) catch(ob->eventDestruct()); } return object::eventDestruct(); } mixed eventDivorce(object who) { class marriage m; m = Marriages[0]; m->DivorceDate = time(); return 1; } mixed eventMarry(object who, object to_whom) { class marriage m; object env; if( (env = previous_object()) != environment() ) return 0; m = new(class marriage); m->Spouse = (string)to_whom->GetCapName(); m->WeddingDate = time(); m->DivorceDate = 0; m->Location = file_name(env); Marriages = ({ m }) + Marriages; return 1; } int eventMove(mixed dest) { string str; int x; x = move::eventMove(dest); if( x ) { if( !(str = (string)environment()->GetProperty("login")) ) LoginSite = base_name(environment()); else LoginSite = str; } return x; } int cmdQuit(string str) { string tmp; if( previous_object() && ! ((int)master()->valid_apply( ({ GetKeyName() }) )) ) return 0; if( (int)environment(this_object())->GetProperty("no quit") && ! sizeof(previous_object(-1)) ) { message("system", "You are unable to escape this reality!", this_object()); return 1; } message("system", "Please come back another time!", this_object()); save_player(GetKeyName()); tmp = GetMessage("logout") || (GetName() + " is gone from this reality!"); message("environment", tmp, environment(this_object()), ({this_object()})); log_file("enter", GetCapName()+" (quit): "+ctime(time())+"\n"); message("announce", "["+GetCapName()+" quits]", filter(users(), (: archp :))); eventDestruct(); return 1; } int GetAge() { int x; if(!interactive(this_object())) return Age; x = time() - LastAge; Age += x; LastAge = time(); return Age; } int GetBirth() { return BirthTime - (YEAR * 18); } string query_cwd() { return interface::query_cwd(); } void SetEmail(string str) { if(!((int)master()->valid_apply(({ GetKeyName() })))) return; Email = str; } string GetEmail() { if(!((int)master()->valid_apply(({ GetKeyName() })))) return 0; else return Email; } void SetId(string *bogus) { int i; if(UserId) return; if(!GetCapName()) { UserId = ({ GetKeyName() }); return; } UserId = ({ GetKeyName(), lower_case(GetCapName()) }); if((i=sizeof(bogus = explode(lower_case(GetCapName()), " "))) == 1) return; while(i--) if(!user_exists(bogus[i])) UserId += ({ bogus[i] }); } string *GetId() { return UserId; } int id(string str) { if(!str || !UserId) return 0; else return member_array(lower_case(str), UserId) != -1; } int GetLoginTime() { return LoginTime; } string SetKeyName(string str) { if( previous_object() != master() ) return GetKeyName(); return object::SetKeyName(str); } string GetKeyName() { return object::GetKeyName(); } void SetNews(string type, int sz) { News[type] = sz; } int GetNews(string type) { return News[type]; } void SetPassword(string str) { if(!((int)master()->valid_apply(({ GetKeyName() })))) return; Password = str; save_player(GetKeyName()); } string GetPassword() { if(!((int)master()->valid_apply(({ GetKeyName() })))) return 0; else return Password; } void SetRank(string str) { Rank = str; } string GetRank() { return Rank; } void SetRealName(string str) { if(!((int)master()->valid_apply(({ GetKeyName() })))) return; RealName = str; } string GetRealName() { return RealName; } string GetShort() { string str; str = object::GetShort(str); if( !str ) str = "$N the unaccomplished"; if( strsrch(str, "$N") == -1 ) str = "$N"; str = replace_string(str, "$N", GetName()); if( interactive(this_object()) ) return str; else return str + " (net-dead)"; } varargs string GetLong() { string str; str = object::GetLong(str); if(!str || strsrch(str, "$N") == -1) str = "$N is nondescript."; str = replace_string(str, "$N", GetName()); return str; } int SetBriefMode(int x) { return (Brief = x); } int GetBriefMode() { return Brief; } int SetWhereBlock() { return (WhereBlock = !WhereBlock); } int GetWhereBlock() { return WhereBlock; } string get_path() { log_file("get_path", identify(previous_object())+"\n"); return query_cwd(); } void SetLastError(mapping m) { if (previous_object() != master()) return; LastError = m; } mapping GetLastError() { string caller = file_name(previous_object()); if( caller[0..24] == "/secure/cmds/creators/dbx" || caller[0..23] == "/secure/cmds/players/bug" ) return LastError; error("Privilege Violation: " + caller); } void SetCapName(string str) { if( base_name(previous_object(0)) != LIB_CONNECT ) return; object::SetCapName(str); } void move_or_destruct() { (eventMove(ROOM_START) || eventMove(ROOM_VOID)); } string SetShort(string str) { if( strsrch(str, "$N") == -1 ) return object::GetShort(); else return object::SetShort(str); } string SetLong(string str) { if(strsrch(str, "$N") == -1) return object::GetLong(); else return object::SetLong(str); } string GetName() { return object::GetName(); } varargs int GetInvis(object ob) { return object::GetInvis(ob); } mixed *GetCommands() { if( !((int)master()->valid_apply( ({ GetKeyName() }) )) ) return ({}); else return commands(); } string GetSpouse() { if( !Marriages || !sizeof(Marriages) ) return 0; if( ((class marriage)Marriages[0])->DivorceDate ) return 0; return ((class marriage)Marriages[0])->Spouse; } class marriage *GetMarriages() { return Marriages; } string GetHostSite() { if( WhereBlock ) { if( !((int)master()->valid_access(({ PRIV_ASSIST }))) ) return "Confidential"; else return HostSite; } return HostSite; } void eventLoadObject(mixed *value, int recurse) { } int GetRadiantLight(int ambient) { return (object::GetRadiantLight(ambient) + container::GetRadiantLight(ambient)); } string GetWebPage() { return WebPage; } string SetWebPage(string page) { if( !master()->valid_apply(({ GetKeyName() })) ) { return WebPage; } return (WebPage = page); }