/**************************************************************************** * [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. * ****************************************************************************/ // Descriptor2.cpp #include "stdafx.h" #include "smaug.h" #include "SmaugSocket.h" #include "SysData.h" #include "objects.h" #include "rooms.h" #include "character.h" #include "descriptor.h" #include "Smaugx.h" char *GetFightDamageString (CCharacter* ch); void CDescriptor::DisplayPrompt () { CCharacter *ch = m_pCharacter; ASSERT (ch); char buf [MAX_STRING_LENGTH]; CCharacter *och = (m_pOriginal ? m_pOriginal : m_pCharacter); CCharacter *victim = NULL; BOOL ansi = (! och->IsNpc () && och->IsAnsi ()); const char *prompt; char *pbuf = buf; int stat; pc_data &Pc = *ch->GetPcData (); // 1.4add // if (! ch->IsNpc () && !IS_SET(ch->pcdata->flags, PCFLAG_HELPSTART)) // prompt = helpstart; // else if (!ch->IsNpc () && ch->GetSubstate () != SUB_NONE && Pc.HasSubPrompt ()) prompt = Pc.GetSubPrompt (); else if (ch->IsNpc () || (! ch->GetFightWho () && ! Pc.HasPrompt ())) prompt = default_prompt (ch); else if (ch->GetFightWho ()) { if (! Pc.HasFightPrompt ()) prompt = default_prompt (ch); else prompt = Pc.GetFightPrompt (); } else prompt = Pc.GetPrompt (); if (ansi) { strcpy (pbuf, "\033[m"); m_PrevColor = 0x07; pbuf += 3; } // Clear out old color stuff // make_color_sequence (NULL, NULL, NULL); for (; *prompt; prompt++) { // '&' = foreground color/intensity bit // '^' = background color/blink bit // '%' = prompt commands // Note: foreground changes will revert background to 0 (black) if (*prompt != '&' && *prompt != '^' && *prompt != '%') { * (pbuf++) = *prompt; continue; } ++prompt; if (!*prompt) break; if (*prompt == * (prompt-1)) { * (pbuf++) = *prompt; continue; } switch (* (prompt-1)) { default: bug ("DisplayPrompt: bad command char '%c'.", * (prompt-1)); break; case '&': case '^': stat = MakeColorSequence (&prompt [-1], pbuf, this); if (stat < 0) --prompt; else if (stat > 0) pbuf += stat; break; case '%': *pbuf = '\0'; stat = 0x80000000; switch (*prompt) { case '%': *pbuf++ = '%'; *pbuf = '\0'; break; case 'a': if (ch->GetLevel () >= 10) stat = ch->GetAlignment (); else if (ch->IsGood ()) strcpy (pbuf, "good"); else if (ch->IsEvil ()) strcpy (pbuf, "evil"); else strcpy (pbuf, "neutral"); break; case 'A': sprintf (pbuf, "%s%s%s", ch->IsInvis () ? "I" : "", ch->IsHidden () ? "H" : "", ch->IsSneaking () ? "S" : ""); break; case 'f': if (ch->GetPcData ()->deity) stat = ch->GetPcData ()->favor; else strcpy (pbuf, "no favor"); break; case 'F': if (ch->IsImmortal ()) strcpy (pbuf, flag_string (ch->GetInRoom ()->GetRoomFlags (), r_flags)); break; case 'C': // Tank if (ch->IsImmortal ()) { if (! (victim = ch->GetFightWho ())) strcpy (pbuf, "N/A"); else if (! victim->GetFightWho ()) strcpy (pbuf, "N/A"); else strcpy (pbuf, GetFightDamageString (victim)); } break; case 'c': if (ch->IsImmortal ()) { if (! (victim = ch->GetFightWho ())) strcpy (pbuf, "N/A"); else strcpy (pbuf, GetFightDamageString (victim)); } break; case 'h': stat = ch->GetHp (); break; case 'H': stat = ch->GetMaxHp (); break; case 'm': if (ch->IsVampire ()) stat = 0; else stat = ch->GetMana (); break; case 'M': if (ch->IsVampire ()) stat = 0; else stat = ch->GetMaxMana (); break; case 'N': // Tank if (ch->IsImmortal ()) { if (! (victim = ch->GetFightWho ())) strcpy (pbuf, "N/A"); else if (! victim->GetFightWho ()) strcpy (pbuf, "N/A"); else { if (ch == victim) strcpy (pbuf, "You"); else if (victim->IsNpc ()) strcpy (pbuf, victim->GetShortDescr ()); else strcpy (pbuf, victim->GetName ()); pbuf [0] = UPPER (pbuf [0]); } } break; case 'n': if (ch->IsImmortal ()) { if (! (victim = ch->GetFightWho ())) strcpy (pbuf, "N/A"); else { if (ch == victim) strcpy (pbuf, "You"); else if (victim->IsNpc ()) strcpy (pbuf, victim->GetShortDescr ()); else strcpy (pbuf, victim->GetName ()); pbuf [0] = UPPER (pbuf [0]); } } break; case 'T': if (time_info.hour < 5) strcpy (pbuf, "night"); else if (time_info.hour < 6) strcpy (pbuf, "dawn"); else if (time_info.hour < 19) strcpy (pbuf, "day"); else if (time_info.hour < 21) strcpy (pbuf, "dusk"); else strcpy (pbuf, "night"); break; case 'b': if (ch->IsVampire ()) stat = ch->GetPcData ()->condition [COND_BLOODTHIRST]; else stat = 0; break; case 'B': if (ch->IsVampire ()) stat = ch->GetLevel () + 10; else stat = 0; break; case 'u': stat = DList.GetCount (); break; case 'U': stat = SysData.MaxPlayers; break; case 'v': stat = ch->GetMove (); break; case 'V': stat = ch->GetMaxMove (); break; case 'g': stat = ch->GetGold (); break; case 'r': if (och->IsImmortal ()) stat = ch->GetInRoom ()->vnum; break; case 'R': if (och->IsVnums ()) sprintf (pbuf, "<#%d> ", ch->GetInRoom ()->vnum); break; case 'x': stat = ch->GetExp (); break; case 'X': stat = exp_level (ch, ch->GetLevel () + 1) - ch->GetExp (); break; case 'S': if (ch->IsBeserkStyle ()) strcpy (pbuf, "B"); else if (ch->IsAggressiveStyle ()) strcpy (pbuf, "A"); else if (ch->IsFightingStyle ()) strcpy (pbuf, "D"); else if (ch->IsEvasiveStyle ()) strcpy (pbuf, "E"); else strcpy (pbuf, "S"); break; case 'i': if ((! ch->IsNpc () && ch->IsWizInvis ()) || (ch->IsNpc () && ch->IsMobInvis ())) sprintf (pbuf, "(Invis %d) ", ch->IsNpc () ? ch->GetMobInvisLevel () : ch->GetPcData ()->wizinvis); else if (ch->IsInvis ()) sprintf (pbuf, "(Invis) "); break; case 'I': stat = ch->IsNpc () ? (ch->IsMobInvis () ? ch->GetMobInvisLevel () : 0) : (ch->IsWizInvis () ? ch->GetPcData ()->wizinvis : 0); break; } if (stat != 0x80000000) sprintf (pbuf, "%d", stat); pbuf += strlen (pbuf); break; } } *pbuf = '\0'; WriteToBuffer (buf, (pbuf-buf)); } char *GetFightDamageString (CCharacter* ch) { int percent = ch->GetMaxHp () ? 100 * ch->GetHp () / ch->GetMaxHp () : -1; if (percent >= 100) return "perfect health"; else if (percent >= 90) return "slightly scratched"; else if (percent >= 80) return "few bruises"; else if (percent >= 70) return "some cuts"; else if (percent >= 60) return "several wounds"; else if (percent >= 50) return "nasty wounds"; else if (percent >= 40) return "bleeding freely"; else if (percent >= 30) return "covered in blood"; else if (percent >= 20) return "leaking guts"; else if (percent >= 10) return "almost dead"; return "DYING"; } // Low level output function. BOOL CDescriptor::ProcessOutput (BOOL fPrompt) { char buf [MAX_INPUT_LENGTH]; extern BOOL bSmaugDown; try { if (pagepoint) return PagerOutput (); // Bust a prompt. if (fPrompt && !bSmaugDown && m_Connected == CON_PLAYING && ! m_bCloseSocket) { CCharacter *ch; ch = m_pOriginal ? m_pOriginal : m_pCharacter; if (ch->IsBlank ()) WriteToBuffer ("\n\r", 2); if (ch->HasPrompt ()) DisplayPrompt (); if (ch->IsTelenet ()) WriteToBuffer (go_ahead_str, 0); } // Short-circuit if nothing to write. if (m_Outtop == 0) return TRUE; // Snoop-o-rama. if (m_pSnoopBy) { // without check, 'force mortal quit' while snooped caused crash, -h if (m_pCharacter && m_pCharacter->GetName ()) { // Show original snooped names. -- Altrag if (m_pOriginal && m_pOriginal->GetName ()) sprintf (buf, "%s (%s)", m_pCharacter->GetName (), m_pOriginal->GetName ()); else sprintf (buf, "%s", m_pCharacter->GetName ()); m_pSnoopBy->WriteToBuffer (buf, 0); } m_pSnoopBy->WriteToBuffer ("% ", 2); m_pSnoopBy->WriteToBuffer (m_pOutbuf, m_Outtop); } // Wake up Winsock, if necessary if (! m_pSocket->SelectReadWrite ()) { if (m_pCharacter != NULL) save_char_obj (m_pCharacter); m_Outtop = 0; RemoveCharacter (*this); return FALSE; } } catch (...) { int siz = m_Outtop < 40 ? m_Outtop : 40; CSwException ex; ex.SetChar (m_pCharacter); ex.Printf ("ProcessOutput:Exception for %s, on output %-*.*", m_pCharacter->GetName (), siz, siz, m_pOutbuf); m_Outtop = 0; m_Incomm [0] = 0; throw ex; } return TRUE; } void CDescriptor::GetPagerInput () { char *ptr = m_Incomm; while (isspace (*ptr)) ++ptr; pagecmd = *ptr; } BOOL CDescriptor::PagerOutput () { ASSERT (this); char *last; CCharacter *ch; int pclines; int lines; BOOL ret; if (! pagepoint || pagecmd == -1) return TRUE; ch = m_pOriginal ? m_pOriginal : m_pCharacter; pclines = UMAX (ch->GetPcData ()->pagerlen, 5) - 1; switch (LOWER (pagecmd)) { default: lines = 0; break; case 'b': lines = -1-(pclines*2); break; case 'r': lines = -1-pclines; break; case 'q': pagetop = 0; pagepoint = NULL; // pagepoint must be NULL ProcessOutput (TRUE); // to call ProcessOutput from here free (pagebuf); pagebuf = NULL; pagesize = MAX_STRING_LENGTH; return TRUE; } while (lines < 0 && pagepoint >= pagebuf) if (* (--pagepoint) == '\n') ++lines; if (*pagepoint == '\n' && *(++pagepoint) == '\r') ++pagepoint; if (pagepoint < pagebuf) pagepoint = pagebuf; for (lines = 0, last = pagepoint; lines < pclines; ++last) if (! *last) break; else if (*last == '\n') ++lines; if (*last == '\r') ++last; if (last != pagepoint) { if (! WriteToDescriptor (pagepoint, (last - pagepoint))) return FALSE; pagepoint = last; } while (isspace (*last)) ++last; if (! *last) { pagetop = 0; pagepoint = NULL; ProcessOutput (TRUE); free (pagebuf); pagebuf = NULL; pagesize = MAX_STRING_LENGTH; return TRUE; } pagecmd = -1; char buf [32]; int len; int PrevColor = m_PrevColor; // save current color if (ch->IsAnsi ()) { len = MakeColorSequence (AT_CYAN, buf, this); if (! WriteToDescriptor (buf, len)) return FALSE; } ret = WriteToDescriptor ("(C)ontinue, (R)efresh, (B)ack, (Q)uit: [C] "); if (ret) { if (ch->IsAnsi ()) { len = MakeColorSequence (PrevColor, buf, this); ret = WriteToDescriptor (buf, len); } } return ret; }