// mguests.cpp -- Multiguest code originally ported from DarkZone. // Multiguest code rewritten by Matthew J. Leavitt (zenty). // Idea for @list guest from Ashen-Shugar and the great team of RhostMUSH // // $Id: mguests.cpp,v 1.18 2006/01/31 00:16:23 sdennis Exp $ // #include "copyright.h" #include "autoconf.h" #include "config.h" #include "externs.h" #include <stdlib.h> #include "attrs.h" #include "mguests.h" #include "powers.h" #include "comsys.h" #define GUEST_HYSTERESIS 20 CGuests Guest; CGuests::CGuests(void) { Guests = NULL; nGuests = 0; nMaxGuests = 0; } CGuests::~CGuests(void) { if (Guests) { MEMFREE(Guests); Guests = NULL; nGuests = 0; nMaxGuests = 0; } } void CGuests::StartUp(void) { if ( !Good_obj(mudconf.guest_char) || mudconf.number_guests <= 0) { // The guest system is effectively disabled. // return; } // SizeGuests(mudconf.min_guests); // Search the Database for Guest chars and snag em. // dbref thing; DO_WHOLE_DB(thing) { if ( Guest(thing) && isPlayer(thing)) { SizeGuests(nGuests+1); Guests[nGuests] = thing; nGuests++; } } // Create the Minimum # of guests. // for (; nGuests < mudconf.min_guests; nGuests++) { SizeGuests(nGuests+1); Guests[nGuests] = MakeGuestChar(); // If we couldn't create guest character, break out and let later // functions handle it. // if (Guests[nGuests] == NOTHING) { break; } } } void CGuests::SizeGuests(int nMin) { // We must have at least nMin, but if nMin is sufficiently below // nMaxGuests, we can also shrink. // if (nMin < nGuests) { nMin = nGuests; } if ( nMaxGuests <= nMin + GUEST_HYSTERESIS && nMin <= nMaxGuests) { return; } dbref *newGuests = (dbref *)MEMALLOC(nMin * sizeof(dbref)); if (Guests) { memcpy(newGuests, Guests, nGuests * sizeof(dbref)); MEMFREE(Guests); Guests = NULL; } Guests = newGuests; nMaxGuests = nMin; } const char *CGuests::Create(DESC *d) { // We don't have a main guest character, break out. // if (!Good_obj(mudconf.guest_char)) { return NULL; } // If we have a guest character, let's use it // int i; for (i = 0; i < nGuests; i++) { dbref guest_player = Guests[i]; // If we have something in the list that isn't a guest, lets // just drop it and make a new one. // if ( !Good_obj(guest_player) || !isPlayer(guest_player) || !Guest(guest_player)) { guest_player = Guests[i] = MakeGuestChar(); if (guest_player == NOTHING) { return NULL; } else { return Name(guest_player); } } if (!Connected(guest_player)) { // Lets try to grab our own name, if we don't have it. // mux_sprintf(name, sizeof(name), "%s%d", mudconf.guest_prefix, i+1); dbref j = lookup_player(GOD, name, false); if (j == NOTHING) { delete_player_name(guest_player, Name(guest_player)); s_Name(guest_player, name); add_player_name(guest_player, Name(guest_player)); } else { // Release comsys and @mail state. // ReleaseAllResources(guest_player); AddToGuestChannel(guest_player); } // Reset the flags back to the default. // db[guest_player].fs = mudconf.player_flags; // Add the type and remove wizard. // db[guest_player].fs.word[FLAG_WORD1] |= TYPE_PLAYER; db[guest_player].fs.word[FLAG_WORD1] &= ~WIZARD; // Make sure they're a guest. // s_Guest(guest_player); move_object(guest_player, mudconf.start_room); s_Pennies(guest_player, Pennies(mudconf.guest_char)); s_Zone(guest_player, Zone(mudconf.guest_char)); s_Parent(guest_player, Parent(mudconf.guest_char)); // Wipe the attributes. // WipeAttrs(guest_player); ChangePassword(guest_player, GUEST_PASSWORD); // Copy them back. // atr_cpy(guest_player, mudconf.guest_char, true); return Name(guest_player); } } if (nGuests >= mudconf.number_guests) { queue_string(d, "Sorry, All guests are currently busy. Try again later.\n"); return NULL; } dbref newGuest = MakeGuestChar(); if (newGuest == NOTHING) { queue_string(d, "GAME: Error creating guest, please try again later.\n"); return NULL; } SizeGuests(nGuests+1); Guests[nGuests] = newGuest; nGuests++; return Name(newGuest); } void CGuests::CleanUp(void) { // Verify that our existing pool of guests are reasonable. Replace any // unreasonable dbrefs. // int nPool = nGuests; if (mudconf.min_guests < nGuests) { nPool = mudconf.min_guests; } int i; for (i = 0; i < nPool; i++) { if ( !Good_obj(Guests[i]) || !isPlayer(Guests[i]) || !Guest(Guests[i])) { Guests[i] = MakeGuestChar(); } } if (nGuests <= mudconf.min_guests) { return; } // We have more than the minimum number of guests in the pool. Let's // see if there are any guests beyond that minimum number that we can // trim out of the pool. // PASS 1: Move connected guests to the beginning of the list. // int itmp; int currGuest = mudconf.min_guests; for (i = mudconf.min_guests; i < nGuests; i++) { if (Connected(Guests[i])) { if (i > currGuest) { itmp = Guests[currGuest]; Guests[currGuest] = Guests[i]; Guests[i] = itmp; } currGuest++; } } // PASS 2: Destroy unconnected guests. // itmp = nGuests; for (i = mudconf.min_guests; i < itmp;i++) { if (!Connected(Guests[i])) { if (Good_obj(Guests[i])) { DestroyGuestChar(Guests[i]); } nGuests--; } } SizeGuests(nGuests); } dbref CGuests::MakeGuestChar(void) { // Search for the first available name. // int i; dbref player; bool bFound = false; for (i = 0; i < mudconf.number_guests;i++) { mux_sprintf(name, sizeof(name), "%s%d", mudconf.guest_prefix, i + 1); player = lookup_player(GOD, name, false); if (player == NOTHING) { bFound = true; break; } } if (!bFound) { return NOTHING; } // Make the player. // const char *pmsg; player = create_player(name, GUEST_PASSWORD, mudconf.guest_nuker, false, &pmsg); // No Player Created?? Return error. // if (player == NOTHING) { log_text("GUEST: failed in create_player" ENDLINE); return NOTHING; } // Lets make the player a guest, move it into the starting room, // don't let it be a wizard, and setup other basics. // AddToGuestChannel(player); s_Guest(player); move_object(player, mudconf.start_room); db[player].fs.word[FLAG_WORD1] &= ~WIZARD; s_Pennies(player, Pennies(mudconf.guest_char)); s_Zone(player, Zone(mudconf.guest_char)); s_Parent(player, Parent(mudconf.guest_char)); // Copy the attributes. // atr_cpy(player, mudconf.guest_char, true); // Lock em! // do_lock(player, player, player, A_LOCK, 2, tprintf("#%d", player), "=me"); do_lock(player, player, player, A_LENTER, 2, tprintf("#%d", player), "=me"); // return em! // return player; } void CGuests::DestroyGuestChar(dbref guest) { // Don't destroy anything not a guest. // if (!Guest(guest)) { return; } // Make sure the nuker is ok. // if ( !Wizard(mudconf.guest_nuker) || !Good_obj(mudconf.guest_nuker)) { mudconf.guest_nuker = GOD; } // Destroy it! // destroy_player(mudconf.guest_nuker, guest); } void CGuests::WipeAttrs(dbref guest) { olist_push(); int atr; char *as; for (atr = atr_head(guest, &as); atr; atr = atr_next(&as)) { ATTR *ap = atr_num(atr); if (ap) { // Get the attr and make sure we can modify it. // if (bCanSetAttr(GOD, guest, ap)) { atr_clr(guest, ap->number); } } } olist_pop(); } bool CGuests::CheckGuest(dbref player) { int i; for (i = 0; i < nGuests; i++) { if (Guests[i] == player) { return true; } } return false; } // @list guests, thanks Rhost for the idea! // void CGuests::ListAll(dbref player) { notify(player, "--------------------------- Current Guests Listing ---------------------------"); notify(player, "*Guest # : Name dbref Status Last Site"); notify(player, "------------------------------------------------------------------------------");\ char *buff = alloc_lbuf("CGuests-ListAll"); int i; char *LastSite=alloc_lbuf("CGuests-LastSite"); for (i = 0; i < nGuests; i++) { dbref aowner; int aflags; atr_get_str(LastSite, Guests[i], A_LASTSITE, &aowner, &aflags); mux_sprintf(buff, LBUF_SIZE, "%sGuest %-3d: %-15s #%-5d %-10s %s", (i<mudconf.min_guests ? "*" : " "), i, Name(Guests[i]), Guests[i], (Connected(Guests[i]) ? "Online" : "NotOnline"), LastSite); notify(player, buff); if (!Good_obj(Guests[i])) { notify(player, tprintf("*** Guest %d (#%d) is an invalid object!", i, Guests[i])); } } free_lbuf(LastSite); notify(player, tprintf("----------------------------- Total Guests: %-3d -----------------------------", nGuests)); free_lbuf(buff); } void CGuests::AddToGuestChannel(dbref player) { if ( mudconf.guests_channel[0] != '\0' && mudconf.guests_channel_alias[0] != '\0') { do_addcom(player, player, player, 0, 2, mudconf.guests_channel_alias, mudconf.guests_channel); } } char CGuests::name[50];