/**************************************************************************** * [S]imulated [M]edieval [A]dventure multi[U]ser [G]ame | * * -----------------------------------------------------------| \\._.// * * SmaugWiz (C) 1998 by Russ Pillsbury (Windows NT version) | (0...0) * * -----------------------------------------------------------| ).:.( * * SMAUG (C) 1994, 1995, 1996 by Derek Snider | {o o} * * -----------------------------------------------------------| / ' ' \ * * SMAUG code team: Thoric, Altrag, Blodkai, Narn, Haus, |~'~.VxvxV.~'~* * Scryn, Swordbearer, Rennard, Tricops, and Gorog. | * * ------------------------------------------------------------------------ * * Merc 2.1 Diku Mud improvments copyright (C) 1992, 1993 by Michael * * Chastain, Michael Quan, and Mitchell Tse. * * Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik Staerfeldt, Tom Madsen, and Katja Nyboe. * ****************************************************************************/ // nanny.cpp #include "stdafx.h" #include "smaug.h" #include "SysData.h" #include "language.h" #include "skill.h" #include "objects.h" #include "rooms.h" #include "races.h" #include "class.h" #include "SmaugWizDoc.h" #include "descriptor.h" #include "character.h" BOOL check_playing (CDescriptor *d, const char *name); BOOL check_reconnect (CDescriptor *d, BOOL bPwdValid); void SetNextErrorState (CDescriptor& Ds); void AskForClass (CDescriptor &Ds); void ExplainClassChange (CDescriptor &Ds); void ExplainRaceChange (CDescriptor &Ds); BOOL SetNewClass (char *argument, CDescriptor& Ds); BOOL SetNewRace (char *argument, CDescriptor& Ds); void show_title (CDescriptor &Ds); void GetNameForNanny (CDescriptor &Ds, char *argument, BOOL bNewPlayer = FALSE); void AskForRace (CDescriptor &Ds); // Deal with sockets that haven't logged in yet. void nanny (CDescriptor *d, char *argument) { char buf [MAX_STRING_LENGTH]; CCharacter *ch; CString Npass; while (isspace (*argument)) argument++; ch = d->m_pCharacter; switch (d->m_Connected) { default: bug ("Nanny: bad d->m_Connected %d.", d->m_Connected); RemoveCharacter (*d); break; case CON_GET_NAME: case CON_GET_NEW_NAME: if (argument [0] == '\0') RemoveCharacter (*d); else GetNameForNanny (*d, argument, d->m_Connected == CON_GET_NEW_NAME); break; case CON_GET_OLD_PASSWORD: d->WriteToBuffer ("\n\r"); if (strcmp (Crypt (argument, ch->GetName ()), ch->GetPcData ()->GetPassWord ())) { d->WriteToBuffer ("Wrong password.\n\r", 0); RemoveCharacter (*d); return; } d->WriteToBuffer (echo_on_str); if (check_playing (d, ch->GetName ())) return; if (check_reconnect (d, TRUE)) return; sprintf (buf, ch->GetName ()); d->m_pCharacter->SetDesc (NULL); delete d->m_pCharacter; load_char_obj (d, buf, FALSE); ch = d->m_pCharacter; // No ident so no user names // sprintf (log_buf, "%s%s (%s) has connected.", ch->GetName (), // d->m_pHost, d->user); sprintf (log_buf, "%s%s has connected.", ch->GetName (), d->m_pHost); if (ch->GetLevel () < LEVEL_DEMI) { // to_channel (log_buf, CHANNEL_MONITOR, "Monitor", ch->GetLevel ()); gpDoc->LogString (log_buf, LOG_COMM, SysData.LogLevel); } else gpDoc->LogString (log_buf, LOG_COMM, ch->GetLevel ()); SetNextErrorState (*d); break; case CON_CONFIRM_NEW_NAME: switch (*argument) { case 'y': case 'Y': sprintf (buf, "\n\rMake sure to use a password that won't be easily " "guessed by someone else.\n\rPick a good password for " "%s: %s", ch->GetName (), echo_off_str); d->WriteToBuffer (buf); d->m_Connected = CON_GET_NEW_PASSWORD; break; case 'n': case 'N': d->WriteToBuffer ("Ok, what IS it, then? "); // clear descriptor pointer to get rid of bug message in log d->m_pCharacter->SetDesc (NULL); delete d->m_pCharacter; d->m_pCharacter = NULL; d->m_Connected = CON_GET_NEW_NAME; break; default: d->WriteToBuffer ("Please type Yes or No? "); break; } break; case CON_GET_NEW_PASSWORD: if (strlen (argument) < 5) { d->WriteToBuffer ("\n\rPassword must be at least five " "characters long.\n\rPassword: "); return; } Npass = Crypt (argument, ch->GetName ()); if (Npass.Find ('~') >= 0) { d->WriteToBuffer ("\n\rNew password not acceptable, " "try again.\n\rPassword: "); return; } delete ch->GetPcData ()->GetPassWord (); ch->GetPcData ()->SetPassWord (str_dup (Npass)); d->WriteToBuffer ("\n\rPlease retype the password to confirm: "); d->m_Connected = CON_CONFIRM_NEW_PASSWORD; break; case CON_CONFIRM_NEW_PASSWORD: if (strcmp (Crypt (argument, ch->GetName ()), ch->GetPcData ()->GetPassWord ())) { d->WriteToBuffer ("\n\rPasswords don't match.\n\rRetype password: "); d->m_Connected = CON_GET_NEW_PASSWORD; return; } d->WriteToBuffer (echo_on_str); d->WriteToBuffer ("\n\rWhat is your sex (M/F/N)? "); d->m_Connected = CON_GET_NEW_SEX; break; case CON_GET_NEW_SEX: switch (argument [0]) { case 'm': case 'M': ch->SetSex (SEX_MALE); break; case 'f': case 'F': ch->SetSex (SEX_FEMALE); break; case 'n': case 'N': ch->SetSex (SEX_NEUTRAL); break; default: d->WriteToBuffer ("That's not a sex.\n\rWhat IS your sex? "); return; } AskForClass (*d); d->m_Connected = CON_GET_NEW_CLASS; break; case CON_GET_NEW_CLASS: if (SetNewClass (argument, *d)) { AskForRace (*d); d->m_Connected = CON_GET_NEW_RACE; } break; case CON_REDO_CLASS: if (SetNewClass (argument, *d)) { ch->ClrConnectError (CE_BADCLASS); SetNextErrorState (*d); } break; case CON_GET_NEW_RACE: if (SetNewRace (argument, *d)) { d->WriteToBuffer ("\n\rWould you like RIP, ANSI or no " "graphic/color support, (R/A/N)? "); d->m_Connected = CON_GET_WANT_RIPANSI; } break; case CON_REDO_RACE: if (SetNewRace (argument, *d)) { ch->ClrConnectError (CE_BADRACE); SetNextErrorState (*d); } break; case CON_GET_WANT_RIPANSI: switch (argument [0]) { case 'r': case 'R': ch->SetActBit (PLR_RIP); ch->SetActBit (PLR_ANSI); break; case 'a': case 'A': ch->SetActBit (PLR_ANSI); break; case 'n': case 'N': break; default: d->WriteToBuffer ("Invalid selection.\n\rRIP, ANSI or NONE? "); return; } sprintf (log_buf, "%s%s new %s %s.", ch->GetName (), d->m_pHost, RaceTable.GetName (ch->GetRace ()), ClassTable.GetName (ch->GetClass ())); gpDoc->LogString (log_buf, LOG_COMM, SysData.LogLevel); to_channel (log_buf, CHANNEL_MONITOR, "Monitor", LEVEL_IMMORTAL); d->WriteToBuffer ("Press [ENTER] "); show_title (*d); ch->SetLevel (0); ch->SetPosition (POS_STANDING); d->m_Connected = CON_PRESS_ENTER; break; case CON_PRESS_ENTER: if (ch->IsRip ()) send_rip_screen (ch); if (ch->IsAnsi ()) send_to_pager ("\033[2J", ch); else send_to_pager ("\014", ch); set_pager_color (AT_LBLUE, ch); if (ch->IsImmortal ()) do_help (ch, "imotd"); if (ch->GetLevel () == 50) do_help (ch, "amotd"); if (ch->GetLevel () < 50 && ch->GetLevel () > 0) do_help (ch, "motd"); if (ch->GetLevel () == 0) do_help (ch, "nmotd"); send_to_pager ("\n\rPress [ENTER] ", ch); d->m_Connected = CON_READ_MOTD; break; case CON_READ_MOTD: sprintf (buf, "\n\rWelcome to %s...\n\r", SysData.GetLongTitle ()); d->WriteToBuffer (buf); add_char (ch); d->m_Connected = CON_PLAYING; if (ch->GetLevel () == 0) { CObjData *obj; int iLang; ch->GetPcData ()->SetClanName (STRALLOC ("")); ch->GetPcData ()->SetClan (NULL); switch (ClassTable.GetAttrPrime (ch->GetClass ())) { case APPLY_STR: ch->perm_str = 16; break; case APPLY_INT: ch->perm_int = 16; break; case APPLY_WIS: ch->perm_wis = 16; break; case APPLY_DEX: ch->perm_dex = 16; break; case APPLY_CON: ch->perm_con = 16; break; case APPLY_CHA: ch->perm_cha = 16; break; case APPLY_LCK: ch->perm_lck = 16; break; } CRaceData &Ra = *RaceTable.GetRaceData (ch->GetRace ()); ch->SetAffectFlags (Ra.GetAffectFlags ()); ch->SetAttackFlags (Ra.GetAttackFlags ()); ch->SetDefenseFlags (Ra.GetDefenseFlags ()); ch->perm_str += Ra.str_plus; ch->perm_int += Ra.int_plus; ch->perm_wis += Ra.wis_plus; ch->perm_dex += Ra.dex_plus; ch->perm_con += Ra.con_plus; ch->perm_cha += Ra.cha_plus; ch->perm_lck += Ra.lck_plus; ch->AddArmor (Ra.GetAcPlus ()); ch->AddAlignment (Ra.GetAlignment ()); ch->saving_poison_death = Ra.GetSavingPoisonDeath (); ch->saving_wand = Ra.GetSavingWand (); ch->saving_para_petri = Ra.GetSavingParaPetri (); ch->saving_breath = Ra.GetSavingBreath (); ch->saving_spell_staff = Ra.GetSavingSpellstaff (); ch->SetHeight (number_range ((int)(Ra.GetHeight () * .9), (int) (Ra.GetHeight () * 1.1))); ch->SetWeight (number_range ((int) (Ra.GetWeight () * .9), (int) (Ra.GetWeight () * 1.1))); if ((iLang = SkillTable.Lookup ("common")) < 0) bug ("Nanny: cannot find common language."); else ch->GetPcData ()->learned [iLang] = 100; for (int la=1; la < LanguageTable.GetCount (); ++la) { if (Ra.CanSpeak (la)) { int sn = SkillTable.Lookup (LanguageTable.GetName (la)); if (sn < 0) bug ("Nanny: cannot find racial language."); else ch->GetPcData ()->learned [sn] = 100; } } name_stamp_stats (ch); ch->SetLevel (1); ch->SetExp (0); ch->AddMaxHp (RaceTable.GetHp (ch->GetRace ())); ch->AddMaxMana (RaceTable.GetMana (ch->GetRace ())); ch->SetHp (ch->GetMaxHp ()); ch->SetMana (ch->GetMaxMana ()); ch->SetMove (ch->GetMaxMove ()); sprintf (buf, "the %s", ClassTable.GetTitle (ch->GetClass (), ch->GetLevel (), ch->GetSex () == SEX_FEMALE ? 1 : 0)); set_title (ch, buf); // Added by Narn. Start new characters with autoexit and // autogold already turned on. Very few people don't use those. ch->SetActBit (PLR_AUTOGOLD); ch->SetActBit (PLR_AUTOEXIT); // Added by Brittany, Nov 24/96. The object is the adventurer's // guide to the realms of despair, part of Academy.are. CObjIndexData *obj_ind = OIdxTable.GetObj (SysData.m_ObjGuide); if (obj_ind != NULL) { obj = create_object (obj_ind, 0); obj_to_char (obj, ch); equip_char (ch, obj, WEAR_HOLD); } if (SysData.IsImmediateAuth ()) ch->SendToRoom (RoomTable.GetRoom (SysData.m_RoomSchool)); else { ch->SendToRoom (RoomTable.GetRoom (SysData.m_RoomAuthStart)); ch->GetPcData ()->auth_state = 0; ch->SetUnauthed (); } // Display_prompt interprets blank as default ch->GetPcData ()->SetPrompt (STRALLOC ("")); } else if (! ch->IsImmortal () // to hell with 'em && ch->GetPcData ()->release_date > CurrentTime) { ch->SendToRoom (RoomTable.GetRoom (SysData.m_RoomHell)); } else if (ch->GetInRoom () && (ch->IsImmortal () || ! ch->GetInRoom ()->IsPrototype ())) { ch->SendToRoom (ch->GetInRoom ()); } else if (ch->IsImmortal ()) { ch->SendToRoom (RoomTable.GetRoom (SysData.m_RoomChat)); } else { ch->SendToRoom (RoomTable.GetRoom (SysData.m_RoomTemple)); } if (get_timer (ch, TIMER_SHOVEDRAG) > 0) remove_timer (ch, TIMER_SHOVEDRAG); if (get_timer (ch, TIMER_PKILLED) > 0) remove_timer (ch, TIMER_PKILLED); act (AT_ACTION, "$n has entered the game.", ch, NULL, NULL, TO_ROOM); if (ch->HasPet ()) { act (AT_ACTION, "$n returns to $s master from the Void.", ch->GetPet (), NULL, ch, TO_NOTVICT); act (AT_ACTION, "$N returns with you to the realms.", ch, NULL, ch->GetPet (), TO_CHAR); ch->GetPet ()->SendToRoom (ch->GetInRoom ()); } do_look (ch, "auto"); mail_count (ch); if (! ch->GetWasInRoom ()) ch->SetWasInRoom (ch->GetInRoom ()); break; } } void SetNextErrorState (CDescriptor& Ds) { CCharacter *ch = Ds.m_pCharacter; switch (ch->GetConnectError ()) { case CE_BADCLASS: ExplainClassChange (Ds); AskForClass (Ds); Ds.m_Connected = CON_REDO_CLASS; break; case CE_BADRACE: ExplainRaceChange (Ds); AskForRace (Ds); Ds.m_Connected = CON_REDO_RACE; break; case CE_NONE: default: ch->SetConnectError (CE_NONE); show_title (Ds); Ds.m_Connected = CON_PRESS_ENTER; } } void GetNameForNanny (CDescriptor& Ds, char* argument, BOOL bNewPlayer /* = FALSE */) { Ds.GetConnectionInfo (); argument [0] = UPPER (argument [0]); if (! check_parse_name (argument, bNewPlayer)) { Ds.WriteToBuffer ("Illegal name, try another.\n\rName: "); return; } if (!str_cmp (argument, "New")) { if (Ds.newstate == 0) { // New player if (gpDoc->m_bDenyNewPlayers) { Ds.WriteToBuffer ("The mud is currently preparing for a reboot.\n\r"); Ds.WriteToBuffer ("New players are not accepted during this time.\n\r"); Ds.WriteToBuffer ("Please try again in a few minutes.\n\r"); RemoveCharacter (Ds); } else if (SysData.IsDenyNew ()) { Ds.WriteToBuffer ("This mud is currently not accepting new players.\n\r"); Ds.WriteToBuffer ("You may contact the mud adminsitrators to inquire\n\r"); Ds.WriteToBuffer ("as to when the mud will reopen to new players.\n\r"); RemoveCharacter (Ds); } else Ds.WriteToBuffer ( "\n\rChoosing a name is one of the most important parts of this game...\n\r" "Make sure to pick a name appropriate to the character you are going\n\r" "to role play, and be sure that it suits a medieval theme.\n\r" "If the name you select is not acceptable, you will be asked to choose\n\r" "another one.\n\r\n\rPlease choose a name for your character: "); Ds.newstate++; Ds.m_Connected = CON_GET_NEW_NAME; return; } else { Ds.WriteToBuffer ("Illegal name, try another.\n\rName: "); return; } } BOOL bOld = load_char_obj (&Ds, argument, TRUE); if (! Ds.m_pCharacter) { sprintf (log_buf, "Bad player file %s%s.", argument, Ds.m_pHost); gpDoc->LogString (log_buf); Ds.WriteToBuffer ( "Your playerfile is corrupt...Please notify an Imm.\n\r"); RemoveCharacter (Ds); return; } CCharacter *ch = Ds.m_pCharacter; CBanData *pban; // Can't ban site if host name unknown if (Ds.IsHost ()) { for (pban = first_ban; pban; pban = pban->GetNext ()) { // This used to use str_suffix, but in order to do bans by the // first part of the ip, ie "ban 207.136.25" str_prefix must // be used. -- Narn if (!str_prefix (pban->name, &Ds.m_pHost [1]) && pban->level >= ch->GetLevel ()) { Ds.WriteToBuffer ( "Your site has been banned from this Mud.\n\r"); RemoveCharacter (Ds); return; } } } if (ch->IsDenied ()) { sprintf (log_buf, "Denying access to %s%s.", argument, Ds.m_pHost); gpDoc->LogString (log_buf, LOG_COMM, SysData.LogLevel); if (Ds.newstate != 0) { Ds.WriteToBuffer ( "That name is already taken. Please choose another: "); Ds.m_Connected = CON_GET_NEW_NAME; return; } Ds.WriteToBuffer ("You are denied access.\n\r"); RemoveCharacter (Ds); return; } if (check_reconnect (&Ds, FALSE)) bOld = TRUE; else { if (wizlock && ch->IsMortal ()) { Ds.WriteToBuffer ("The game is wizlocked. Only immortals can connect now.\n\r"); Ds.WriteToBuffer ("Please try back later.\n\r"); RemoveCharacter (Ds); return; } } if (bOld) { if (Ds.newstate != 0) { Ds.WriteToBuffer ("That name is already taken. Please choose another: "); Ds.m_Connected = CON_GET_NEW_NAME; return; } // Previously existing player Ds.WriteToBuffer ("Password: "); Ds.WriteToBuffer (echo_off_str); Ds.m_Connected = CON_GET_OLD_PASSWORD; return; } else { if (Ds.newstate == 0) { // No such player Ds.WriteToBuffer ("\n\rNo such player exists.\n\r" "Please check your spelling, or type new to start a new " "player.\n\r\n\rName: "); Ds.m_Connected = CON_GET_NAME; return; } // New player CString Msg; Msg.Format ("Did I get that right, %s (Y/N)? ", argument); Ds.WriteToBuffer (Msg); Ds.m_Connected = CON_CONFIRM_NEW_NAME; } } void AskForClass (CDescriptor &Ds) { char buf [MAX_STRING_LENGTH]; Ds.WriteToBuffer ("\n\rSelect a class, or type help [class] " "to learn more about that class.\n\r["); buf [0] = '\0'; for (int iClass = 0; iClass < ClassTable.GetCount (); ++iClass) { char *pName = ClassTable.GetName (iClass); if (iClass > 0) { if ((strlen (buf) + strlen (pName)) > 77) { strcat (buf, "\n\r"); Ds.WriteToBuffer (buf); buf [0] = '\0'; } else strcat (buf, " "); } strcat (buf, pName); } strcat (buf, "]\n\r: "); Ds.WriteToBuffer (buf); } BOOL SetNewClass (char *argument, CDescriptor& Ds) { char arg [MAX_STRING_LENGTH]; CCharacter *ch = Ds.m_pCharacter; argument = one_argument (argument, arg); if (! str_cmp (arg, "help")) { for (int cl = 0; cl < ClassTable.GetCount (); ++cl) { char *pName = ClassTable.GetName (cl); if (toupper (argument [0]) == toupper (pName [0]) && ! str_prefix (argument, pName)) { do_help (ch, argument); Ds.WriteToBuffer ("Please choose a class: "); return FALSE; } } Ds.WriteToBuffer ("No such help topic. Please choose a class: "); return FALSE; } for (int cl = 0; cl < ClassTable.GetCount (); ++cl) { char *pName = ClassTable.GetName (cl); if (toupper (arg [0]) == toupper (pName [0]) && ! str_prefix (arg, pName)) { ch->SetClass (cl); return TRUE; } } Ds.WriteToBuffer ("That's not a class.\n\rWhat IS your class? "); return FALSE; } void ExplainClassChange (CDescriptor& Ds) { CString s; s.Format ("\n\r Your class is invalid. This is probably\n\r" " due to a change in the classes of %s.\n\r", NCCP SysData.GetLongTitle ()); Ds.WriteToBuffer (s); Ds.WriteToBuffer ("Please Reselect your class:\n\r"); } void AskForRace (CDescriptor &Ds) { Ds.WriteToBuffer ("\n\rYou may choose from the following races, " "or type help [race] to learn more:\n\r["); CString Msg; POSITION pos = RaceTable.GetHeadPosition (); while (pos) { CRaceData &Ra = *RaceTable.GetNext (pos); if (! Ra.IsVampire () && Ra.HasName () && ! Ra.IsClassRestricted (Ds.m_pCharacter->GetClass ())) { int len = Msg.GetLength (); if (len) { if (len + strlen (Ra.GetName ()) > 77) { Msg += "\n\r"; Ds.WriteToBuffer (Msg); Msg.Empty (); } else Msg += ' '; } Msg += Ra.GetName (); } } Msg += "]\n\r: "; Ds.WriteToBuffer (Msg); } BOOL SetNewRace (char *argument, CDescriptor& Ds) { char arg [MAX_STRING_LENGTH]; CCharacter *ch = Ds.m_pCharacter; argument = one_argument (argument, arg); if (! str_cmp (arg, "help")) { CRaceData &Ra = *RaceTable.Find (argument); if (&Ra) { CString name = Ra.GetName (); do_help (ch, NCCP name); } else Ds.WriteToBuffer ( "No help on that topic. Please choose a race:"); AskForRace (Ds); return FALSE; } CRaceData &Ra = *RaceTable.Find (arg); if (! &Ra || ! Ra.HasName () || Ra.IsVampire () || Ra.IsClassRestricted (ch->GetClass ())) { Ds.WriteToBuffer ("That's not a race.\n\rWhat IS your race? "); return FALSE; } ch->SetRace (Ra.GetRace ()); return TRUE; } void ExplainRaceChange (CDescriptor& Ds) { CString s; s.Format ("\n\r Your race is invalid. This is probably\n\r" " due to a change in the races of %s.\n\r", NCCP SysData.GetLongTitle ()); Ds.WriteToBuffer (s); Ds.WriteToBuffer ("Please Reselect your race:\n\r"); } void show_title (CDescriptor &Ds) { CCharacter *ch; ch = Ds.m_pCharacter; if (! ch->IsNoIntro ()) { if (ch->IsRip ()) send_rip_title (ch); else if (ch->IsAnsi ()) send_ansi_title (ch); else send_ascii_title (ch); } else Ds.WriteToBuffer ("Press enter...\n\r"); } // Check if already playing. BOOL check_playing (CDescriptor *d, const char *name) { POSITION pos = DList.GetHeadPosition (); while (pos) { CDescriptor &Dold = *DList.GetNext (pos); if (Dold.IsDisconnecting ()) continue; if (&Dold != d && Dold.m_pCharacter && Dold.m_Connected != CON_GET_NAME && Dold.m_Connected != CON_GET_NEW_NAME && Dold.m_Connected != CON_GET_OLD_PASSWORD && ! str_cmp (name, Dold.m_pOriginal ? Dold.m_pOriginal->GetName () : Dold.m_pCharacter->GetName ())){ delete d->m_pCharacter; CCharacter *ch = Dold.m_pCharacter; d->m_pCharacter = ch; Dold.m_pCharacter = NULL; RemoveCharacter (Dold); ch->SetDesc (d); ch->SetTimer (0); ch->SendText ("Reconnecting.\n\r"); act (AT_ACTION, "$n has lost $s link.", ch, NULL, NULL, TO_ROOM); act (AT_ACTION, "$n has reconnected, kicking off " "old connection.", ch, NULL, NULL, TO_ROOM); // Do not check for ident - Zircon // sprintf (log_buf, "%s%s (%s) reconnected.", ch->GetName(), // d->m_pHost, d->user); sprintf (log_buf, "%s%s has reconnected, kicking off old " "connection.", ch->GetName(), d->m_pHost); gpDoc->LogString (log_buf, LOG_COMM, UMAX ((int) SysData.LogLevel, (int) ch->GetLevel())); d->m_Connected = CON_PLAYING; return TRUE; } } return FALSE; } // Look for link-dead player to reconnect. // The descriptor has been loaded with the player data from // the reconnect, we look for a matching character in the character // list. BOOL check_reconnect (CDescriptor *d, BOOL bPwdValid) { CCharacter *ch; CObjData *obj; const char *name = d->m_pCharacter->GetName (); for (ch = first_char; ch != NULL; ch = ch->GetNext ()) { if (! ch->IsNpc () && (!bPwdValid || ch->GetDesc () == NULL) && ch->GetName () && !str_cmp (name, ch->GetName ())) { // Look at smaug code in comm.c to see about handling // switched characters here. if (bPwdValid == FALSE) { free_string (d->m_pCharacter->GetPcData ()->GetPassWord ()); d->m_pCharacter->GetPcData ()->SetPassWord ( str_dup (ch->GetPcData ()->GetPassWord ())); } else { delete d->m_pCharacter; d->m_pCharacter = ch; ch->SetDesc (d); ch->SetTimer (0); ch->SendText ("Reconnecting.\n\r"); act (AT_ACTION, "$n has reconnected.", ch, NULL, NULL, TO_ROOM); // No user id yet // sprintf (log_buf, "%s%s (%s) reconnected.", ch->GetName (), // d->m_pHost, d->user); sprintf (log_buf, "%s%s reconnected.", ch->GetName (), d->m_pHost); gpDoc->LogString (log_buf, LOG_COMM, UMAX ((int)SysData.LogLevel, (int)ch->GetLevel ())); d->m_Connected = CON_PLAYING; // Contributed by Gene Choi // { If the reconnecting player has a light, add // it to the count of lights in the room. (RCP) } if ((obj = get_eq_char (ch, WEAR_LIGHT)) != NULL && obj->item_type == ITEM_LIGHT && obj->value [2] != 0 && ch->GetInRoom () != NULL) ++ch->GetInRoom ()->light; } return TRUE; } } return FALSE; }