/**************************************************************************** * [S]imulated [M]edieval [A]dventure multi[U]ser [G]ame | \\._.// * * -----------------------------------------------------------| (0...0) * * SMAUG 1.4 (C) 1994, 1995, 1996, 1998 by Derek Snider | ).:.( * * -----------------------------------------------------------| {o o} * * SMAUG code team: Thoric, Altrag, Blodkai, Narn, Haus, | / ' ' \ * * Scryn, Rennard, Swordbearer, Gorog, Grishnakh, Nivek, |~'~.VxvxV.~'~* * Tricops and Fireblade | * * ------------------------------------------------------------------------ * * 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 St{rfeldt, Tom Madsen, and Katja Nyboe. * * ------------------------------------------------------------------------ * * Informational module * ****************************************************************************/ #include <sys/types.h> #include <ctype.h> #include <stdio.h> #include <string.h> #include <time.h> #include <sys/stat.h> #include "mud.h" BOOK_DATA *first_book; BOOK_DATA *last_book; /* handler.c */ extern char *get_room_description(CHAR_DATA *ch, char *descr); /* clan.c */ extern CLAN_MEMBER *get_member(char *name, CLAN_DATA *clan); extern int top_help; char *help_greeting; /* * Local functions. */ void show_char_to_char_0 args( ( CHAR_DATA *victim, CHAR_DATA *ch ) ); void show_char_to_char_1 args( ( CHAR_DATA *victim, CHAR_DATA *ch ) ); void show_char_to_char args( ( CHAR_DATA *list, CHAR_DATA *ch ) ); bool check_blind args( ( CHAR_DATA *ch ) ); void show_condition args( ( CHAR_DATA *ch, CHAR_DATA *victim ) ); char* get_talent_rank args( ( CHAR_DATA *ch) ); /* act_wiz.c */ int get_permit_flag args( ( char *argument ) ); char *format_obj_to_char( OBJ_DATA *obj, CHAR_DATA *ch, bool fShort ) { static char buf[MAX_STRING_LENGTH]; char buf2[MAX_STRING_LENGTH]; buf[0] = '\0'; if (!obj->short_descr) { sprintf(buf, "a bugged item, report to an imm"); return buf; } if ( obj->condition < obj->weight*30 && obj->item_type != ITEM_TREASURE ) strcat( buf, "&Rdamaged&W, "); if (!IS_OBJ_STAT(obj, ITEM_NO_TAKE) && !xIS_EMPTY(obj->parts)) { if (obj->size > ch->height + ch->height * .50) strcat(buf, "huge, "); else if (obj->size < ch->height - ch->height * .50) strcat(buf, "tiny, "); else if (obj->size > ch->height + ch->height * .30) strcat(buf, "large, "); else if (obj->size < ch->height - ch->height * .30) strcat(buf, "small, "); } if (obj->raw_mana > 100 && IS_AFFECTED(ch, AFF_DETECT_MAGIC)) strcat(buf, "&pmagically charged&w, "); if ( IS_OBJ_STAT(obj, ITEM_INVIS) ) strcat( buf, "invisible, "); if ( (IS_AFFECTED(ch, AFF_DETECT_EVIL) ) && IS_OBJ_STAT(obj, ITEM_EVIL) ) strcat( buf, "&Revil&W, " ); if ((IS_AFFECTED(ch, AFF_DETECT_EVIL)) && IS_OBJ_STAT(obj, ITEM_BLESS) ) strcat( buf, "&Bblessed&W, "); if ( IS_AFFECTED(ch, AFF_DETECT_MAGIC) && IS_OBJ_STAT(obj, ITEM_MAGIC) ) strcat( buf, "&Bmagical&w, " ); if ( IS_OBJ_STAT(obj, ITEM_GLOW) ) strcat( buf, "&Yglowing&w, " ); if ( IS_OBJ_STAT(obj, ITEM_DARK)) strcat( buf, "&zshadowed&w, " ); if ( IS_OBJ_STAT(obj, ITEM_HUM) ) strcat( buf, "&Chumming&w, " ); if ( IS_OBJ_STAT(obj, ITEM_HIDDEN) ) strcat( buf, "&ghidden&w, " ); if ( IS_OBJ_STAT(obj, ITEM_BURIED) ) strcat( buf, "&Oburied&w, " ); if ( IS_OBJ_STAT(obj, ITEM_DREAMWORLD)) strcat( buf, "&pimaginary&w, " ); if ( IS_OBJ_STAT(obj, ITEM_PROTOTYPE) ) strcat( buf, "&WPROTOTYPE&w, " ); if ( IS_AFFECTED(ch, AFF_DETECTTRAPS) && is_trapped(obj) ) strcat( buf, "&RTRAPPED&w " ); if (obj->gem) { if (obj->gem->name) { one_argument(obj->gem->name, buf2); } else { sprintf(buf2, "gem-studded"); } sprintf(buf2, "%s-studded ", buf2); strcat(buf, buf2 ); } if ( fShort ) { if ( obj->short_descr ) strcat( buf, myobj(obj) ); sprintf(buf, aoran(buf)); } else { if ( obj->short_descr ) strcat( buf, myobj(obj) ); if (ch->in_obj && ch->in_obj != obj->in_obj) { if (obj != ch->in_obj) { strcat(buf, " is outside the "); strcat(buf, myobj(ch->in_obj)); strcat(buf, "."); } else { strcat(buf, " is carrying you."); } } else strcat(buf, " is here."); sprintf(buf, capitalize(aoran(buf))); } return buf; } /* * Some increasingly freaky hallucinated objects -Thoric * (Hats off to Albert Hoffman's "problem child") */ char *hallucinated_object( int ms, bool fShort ) { int sms = URANGE( 1, (ms+10)/5, 20 ); if ( fShort ) switch( number_range( 6-URANGE(1,sms/2,5), sms ) ) { case 1: return "a sword"; case 2: return "a stick"; case 3: return "something shiny"; case 4: return "something"; case 5: return "something interesting"; case 6: return "something colorful"; case 7: return "something that looks cool"; case 8: return "a nifty thing"; case 9: return "a cloak of flowing colors"; case 10: return "a mystical flaming sword"; case 11: return "a swarm of insects"; case 12: return "&zSto&prmbri&znger&w"; case 13: return "a figment of your imagination"; case 14: return "your gravestone"; case 15: return "the &YApple of D&Oi&Ys&Wc&Yo&Or&Yd&w"; case 16: return "a glowing tome of arcane knowledge"; case 17: return "a long sought secret"; case 18: return "the meaning of it all"; case 19: return "the answer"; case 20: return "the key to life, the universe and everything"; } switch( number_range( 6-URANGE(1,sms/2,5), sms ) ) { case 1: return "A nice looking sword catches your eye."; case 2: return "The ground is covered in small sticks."; case 3: return "Something shiny catches your eye."; case 4: return "Something catches your attention."; case 5: return "Something interesting catches your eye."; case 6: return "Something colorful flows by."; case 7: return "Something that looks cool calls out to you."; case 8: return "A nifty thing of great importance stands here."; case 9: return "A cloak of flowing colors asks you to wear it."; case 10: return "A mystical flaming sword awaits your grasp."; case 11: return "A swarm of insects buzzes in your face!"; case 12: return "A black runesword moans with power and chaotic energy."; case 13: return "A figment of your imagination is at your command."; case 14: return "You notice a gravestone here... upon closer examination, it reads your name."; case 15: return "The most beautiful sparkling apple hangs in the air."; case 16: return "A glowing tome of arcane knowledge hovers in the air before you."; case 17: return "A long sought secret of all mankind is now clear to you."; case 18: return "The meaning of it all, so simple, so clear... of course!"; case 19: return "The answer. One. It's always been One."; case 20: return "The key to life, the universe and everything awaits your hand."; } return "Whoa!!!"; } /* * Show a list to a character. * Can coalesce duplicated items. */ void show_list_to_char( OBJ_DATA *list, CHAR_DATA *ch, bool fShort, bool fShowNothing ) { char **prgpstrShow; int *prgnShow; int *pitShow; char *pstrShow; OBJ_DATA *obj; int nShow; int iShow; int count, offcount, tmp, ms, cnt; bool fCombine; if ( !ch->desc ) return; /* * if there's no list... then don't do all this crap! -Thoric */ if ( !list ) { if ( fShowNothing ) { if ( IS_NPC(ch) || xIS_SET(ch->act, PLR_COMBINE) ) send_to_char( " ", ch ); set_char_color( AT_OBJECT, ch ); send_to_char( "Nothing.\n\r", ch ); } return; } /* * Alloc space for output lines. */ count = 0; for ( obj = list; obj; obj = obj->next_content ) count++; ms = (ch->mental_state ? ch->mental_state : 1) * (IS_NPC(ch) ? 1 : (ch->pcdata->condition[COND_DRUNK] ? (ch->pcdata->condition[COND_DRUNK]/12) : 1)); /* * If not mentally stable... */ if ( abs(ms) > 40 ) { offcount = URANGE( -(count), (count * ms) / 100, count*2 ); if ( offcount < 0 ) offcount += number_range(0, abs(offcount)); else if ( offcount > 0 ) offcount -= number_range(0, offcount); } else offcount = 0; if ( count + offcount <= 0 ) { if ( fShowNothing ) { if ( IS_NPC(ch) || xIS_SET(ch->act, PLR_COMBINE) ) send_to_char( " ", ch ); set_char_color( AT_OBJECT, ch ); send_to_char( "Nothing.\n\r", ch ); } return; } CREATE( prgpstrShow, char*, count + ((offcount > 0) ? offcount : 0) ); CREATE( prgnShow, int, count + ((offcount > 0) ? offcount : 0) ); CREATE( pitShow, int, count + ((offcount > 0) ? offcount : 0) ); nShow = 0; tmp = (offcount > 0) ? offcount : 0; cnt = 0; /* * Format the list of objects. */ for ( obj = list; obj; obj = obj->next_content ) { if ( offcount < 0 && ++cnt > (count + offcount) ) break; if ( tmp > 0 && number_bits(1) == 0 ) { prgpstrShow [nShow] = str_dup( hallucinated_object(ms, fShort) ); prgnShow [nShow] = 1; pitShow [nShow] = number_range( ITEM_LIGHT, ITEM_BOOK ); nShow++; --tmp; } if ( obj->wear_loc == WEAR_NONE && can_see_obj( ch, obj ) && (!obj->carried_by || (obj != obj->carried_by->main_hand && obj != obj->carried_by->off_hand)) && (obj->item_type != ITEM_TRAP || IS_AFFECTED(ch, AFF_DETECTTRAPS) ) ) { pstrShow = format_obj_to_char( obj, ch, fShort ); fCombine = FALSE; if ( IS_NPC(ch) || xIS_SET(ch->act, PLR_COMBINE) ) { /* * Look for duplicates, case sensitive. * Matches tend to be near end so run loop backwords. */ for ( iShow = nShow - 1; iShow >= 0; iShow-- ) { if ( !strcmp( prgpstrShow[iShow], pstrShow ) ) { prgnShow[iShow] += obj->count; fCombine = TRUE; break; } } } pitShow[nShow] = obj->item_type; /* * Couldn't combine, or didn't want to. */ if ( !fCombine ) { prgpstrShow [nShow] = str_dup( pstrShow ); prgnShow [nShow] = obj->count; nShow++; } } } if ( tmp > 0 ) { int x; for ( x = 0; x < tmp; x++ ) { prgpstrShow [nShow] = str_dup( hallucinated_object(ms, fShort) ); prgnShow [nShow] = 1; pitShow [nShow] = number_range( ITEM_LIGHT, ITEM_BOOK ); nShow++; } } /* * Output the formatted list. -Color support by Thoric */ for ( iShow = 0; iShow < nShow; iShow++ ) { switch(pitShow[iShow]) { default: set_char_color( AT_PLAIN, ch ); break; case ITEM_BLOOD: set_char_color( AT_BLOOD, ch ); break; case ITEM_MONEY: case ITEM_TREASURE: set_char_color( AT_YELLOW, ch ); break; case ITEM_COOK: case ITEM_FOOD: set_char_color( AT_HUNGRY, ch ); break; case ITEM_DRINK_CON: case ITEM_FOUNTAIN: set_char_color( AT_THIRSTY, ch ); break; case ITEM_FIRE: set_char_color( AT_FIRE, ch ); break; case ITEM_SCROLL: case ITEM_WAND: case ITEM_STAFF: set_char_color( AT_MAGIC, ch ); break; } if ( fShowNothing ) send_to_char( " ", ch ); send_to_char( prgpstrShow[iShow], ch ); /* if ( IS_NPC(ch) || xIS_SET(ch->act, PLR_COMBINE) ) */ { if ( prgnShow[iShow] != 1 ) ch_printf( ch, " (x %d)", prgnShow[iShow] ); } send_to_char( "\n\r", ch ); DISPOSE( prgpstrShow[iShow] ); } if ( fShowNothing && nShow == 0 ) { if ( IS_NPC(ch) || xIS_SET(ch->act, PLR_COMBINE) ) send_to_char( " ", ch ); set_char_color( AT_OBJECT, ch ); send_to_char( "Nothing.\n\r", ch ); } /* * Clean up. */ DISPOSE( prgpstrShow ); DISPOSE( prgnShow ); DISPOSE( pitShow ); return; } /* * Show fancy descriptions for certain spell affects -Thoric */ void show_visible_affects_to_char( CHAR_DATA *victim, CHAR_DATA *ch ) { char name[MAX_STRING_LENGTH]; if ( IS_NPC( victim ) ) strcpy( name, victim->short_descr); else strcpy( name, victim->name); name[0] = toupper(name[0]); if (!IS_NPC(victim) && ch->curr_talent[TAL_SEEKING] >= 80 && victim->pcdata->name_disguise) ch_printf(ch, "&W...shimmering with the image of %s.\n\r", victim->pcdata->name_disguise); if (victim->shield) ch_printf(ch, "&W...surrounded by a shield of %s.\n\r", magic_table[victim->shield]); if (IS_AFFECTED(victim, AFF_BEAUTY)) send_to_char("...surrounded by an eerie aura of beauty and attraction.\n\r", ch); if (IS_AFFECTED(victim, AFF_FEAR)) send_to_char("...surrounded by an aura of fear and loathing.\n\r", ch); if (IS_AFFECTED(victim, AFF_UNHOLY)) { set_char_color(AT_DGREY, ch); switch(number_range(1,5)) { default: send_to_char("...emanating an unholy aura", ch); break; case 1: send_to_char("...surrounded by the stench of death", ch); break; case 2: send_to_char("...feeling of dread and horror", ch); break; case 3: send_to_char("...shrouded in terrible shadow", ch); break; } send_to_char(".\n\r", ch); } else if (IS_AFFECTED(victim, AFF_HOLY) ) { set_char_color( AT_WHITE, ch ); ch_printf( ch, "...glowing with an aura of divine radiance.\n\r"); } if ( IS_AFFECTED(victim, AFF_HOLD) ) { set_char_color( AT_CYAN, ch); ch_printf(ch, "...held firmly in place.\n\r"); } } void show_char_to_char_0( CHAR_DATA *victim, CHAR_DATA *ch ) { char buf[MAX_STRING_LENGTH]; char buf2[MAX_STRING_LENGTH]; buf[0] = '\0'; if (IS_NPC(victim)) { if ( !IS_NPC(ch) && xIS_SET(ch->act, PLR_HOLYLIGHT) ) if(IS_NPC(victim)) /* ha tagith - i didnt forget this time */ ch_printf(ch, "[%d] ", victim->pIndexData->vnum); if (!xIS_SET(victim->act, ACT_NAMED)) send_to_char("A ", ch); } else send_to_char("The ", ch); set_char_color( AT_PERSON, ch ); if ( !IS_NPC(victim) && !victim->desc ) { if ( !victim->switched ) send_to_char_color( "&PLINK-DEAD&W, ", ch ); else if ( !IS_AFFECTED(victim, AFF_POSSESS) ) strcat( buf, "switched, " ); } if ( (!IS_NPC(victim) && xIS_SET(victim->act, PLR_WIZINVIS)) || (IS_NPC(victim) && xIS_SET(victim->act, ACT_MOBINVIS)) ) { sprintf( buf,"&W&Yinvisible&W, "); } set_char_color( AT_PERSON, ch ); if ( IS_AFFECTED(victim, AFF_GLOW) ) strcat( buf, "&W&Yglowing&W, "); if ( IS_AFFECTED(victim, AFF_DARK) ) strcat( buf, "&W&zshadowed&W, " ); if ( IS_AFFECTED(victim, AFF_FLAMING) ) strcat( buf, "&W&Rflaming&W, " ); if ( IS_AFFECTED(victim, AFF_INVISIBLE) ) strcat( buf, "&W&Yinvisible&W, " ); if ( IS_AFFECTED(victim, AFF_HIDE) ) strcat( buf, "&W&ghidden,&W "); if ( IS_AFFECTED(victim, AFF_PASS_DOOR) ) strcat( buf, "&W&btranslucent&W, "); if ( IS_AFFECTED(victim, AFF_FAERIE_FIRE) ) strcat( buf, "&W&Pfaerie fired&W, "); if ( IS_AFFECTED(victim, AFF_BERSERK) ) strcat( buf, "&W&Rwild-eyed&W, " ); if ( IS_AFFECTED(ch, AFF_DREAMWORLD) && !IS_AFFECTED(victim, AFF_DREAMWORLD) ) { if (!IS_AWAKE(victim)) { strcat( buf, "&W&Bsleeping&W, "); } else strcat( buf, "&W&Cwaking&W, " ); } if ( IS_AFFECTED(victim, AFF_DREAMWORLD) ) strcat( buf, "&W&pdreaming&W, " ); if ( victim->desc && victim->desc->connected == CON_EDITING ) strcat( buf, "&W&Cwriting&W " ); if (!IS_NPC(victim)) { if (victim->species) { strcat( buf, victim->species); } } else { strcat(buf, victim->short_descr); } if (IS_AFFECTED(ch, AFF_VOID) && !IS_AFFECTED(victim, AFF_VOID) && !IS_AFFECTED(victim, AFF_DREAMWORLD)) strcat( buf, "&W&C, in the real world&W" ); if ( IS_AFFECTED(victim, AFF_VOID) ) strcat( buf, "&b&z, in the Void&W" ); if ( xIS_SET(victim->act, ACT_PROTOTYPE) ) strcat( buf, "&W&Y PROTOTYPE&W"); if ( ch->mount && ch->mount == victim && ch->in_room == ch->mount->in_room ) strcat( buf, "&W, which you are riding&W" ); if ( !IS_NPC(victim) && xIS_SET(victim->act, PLR_AFK) ) strcat( buf, "&G, who is idle&W"); if (!IS_NPC(victim)) { strcat( buf, ", "); strcat( buf, PERS(victim, ch)); } switch ( victim->position ) { case POS_DEAD: strcat( buf, " is &RDEAD&W!!" ); break; case POS_MORTAL: strcat( buf, " is &rmortally wounded&W." ); break; case POS_INCAP: strcat( buf, " is &rincapacitated&W." ); break; case POS_STUNNED: strcat( buf, " is lying here &Runconscious&W." ); break; case POS_SLEEPING: if (ch->position == POS_SITTING || ch->position == POS_RESTING ) strcat( buf, " is sleeping nearby." ); else strcat( buf, " is deep in slumber here." ); break; case POS_RESTING: if (ch->position == POS_RESTING) strcat ( buf, " is sprawled out alongside you." ); else if (ch->position == POS_MOUNTED) strcat ( buf, " is sprawled out at the foot of your mount." ); else strcat (buf, " is sprawled out here." ); break; case POS_SITTING: if ((ch->position == POS_SITTING) || (ch->position == POS_KNEELING)) strcat( buf, " sits here with you." ); else if (ch->position == POS_RESTING) strcat( buf, " sits nearby as you lie around." ); else strcat( buf, " sits upright here." ); break; case POS_KNEELING: if ((ch->position == POS_KNEELING) || (ch->position == POS_SITTING)) strcat( buf, " is kneeling beside you." ); else strcat( buf, " is kneeling here." ); break; case POS_SQUATTING: strcat( buf, " is squatted down here." ); break; case POS_SWIMMING: strcat( buf, " is swimming here." ); break; case POS_FLYING: strcat( buf, " is flying here." ); break; case POS_STANDING: if (victim->in_obj) { strcat( buf, " is in " ); strcat(buf, aoran(myobj(victim->in_obj))); } else if ( ( victim->in_room->sector_type == SECT_UNDERWATER ) && !IS_AFFECTED(victim, AFF_AQUA_BREATH) && !IS_NPC(victim)) strcat( buf, " is &Rdrowning here&W" ); else if ( IS_UNDERWATER(victim) ) strcat( buf, " is here in the water" ); else if ( ( victim->in_room->sector_type == SECT_OCEANFLOOR ) && !IS_AFFECTED(victim, AFF_AQUA_BREATH) && !IS_NPC(victim) ) strcat( buf, " is&R drowning here&W" ); else if (victim->wait && victim->last_taken) { strcat(buf, " is "); strcat(buf, victim->last_taken); strcat(buf, " here"); } else if (IS_AFFECTED(victim, AFF_FLYING) ) strcat( buf, " is hovering here" ); else strcat( buf, " is standing here" ); if (IS_SET(victim->mood, MOOD_READY)) strcat(buf, " ready to fight!"); else strcat(buf, "."); break; case POS_SHOVE: strcat( buf, " is being shoved around." ); break; case POS_DRAG: strcat( buf, " is being dragged around." ); break; case POS_MOUNTED: strcat( buf, " is here, upon " ); if ( !victim->mount ) strcat( buf, "thin air???" ); else if ( victim->mount == ch ) strcat( buf, "your back." ); else if ( victim->in_room == victim->mount->in_room ) { strcat( buf, PERS( victim->mount, ch ) ); strcat( buf, "." ); } else strcat( buf, "someone who left??" ); break; } if (victim->fur_pos > FURNITURE_NONE) { if (victim->on) sprintf (buf2, " %s %s %s %s.", PERS(victim, ch), pos_string(victim), fur_pos_string(victim->fur_pos), victim->on->short_descr ); strcat (buf, buf2); } strcat( buf, "\n\r" ); send_to_char( buf, ch ); if (!xIS_SET(ch->act, PLR_BRIEF)) show_visible_affects_to_char( victim, ch ); return; } void show_char_to_char_2(CHAR_DATA *ch, CHAR_DATA *victim) { show_race_line(ch, victim); if ( victim->description != NULL ) { send_to_char (victim->description, ch); } else { if ( IS_NPC( victim ) ) act( AT_PLAIN, "You see nothing special about $M.", ch, NULL, victim, TO_CHAR); else if ( ch != victim ) act( AT_PLAIN, "$E isn't much to look at...", ch, NULL, victim, TO_CHAR); else act( AT_PLAIN, "You're not much to look at...", ch, NULL, NULL, TO_CHAR); } /* Format a coloring description of the character. */ if (!IS_NPC(victim)) { ch_printf(ch, "%s with", capitalize(aoran(victim->nation->name))); if (victim->pcdata->eyes) ch_printf(ch, " %s eyes", victim->pcdata->eyes); if (victim->pcdata->hair) ch_printf(ch, ", %s hair", victim->pcdata->hair); if (victim->pcdata->skin_color) { ch_printf(ch, ", %s", victim->pcdata->skin_color); if (victim->pcdata->skin_type) ch_printf(ch, " %s", victim->pcdata->skin_type); else send_to_char(" skin", ch); } if (victim->pcdata->extra_color) { ch_printf(ch, ", and %s", victim->pcdata->extra_color); if (victim->pcdata->extra_type) ch_printf(ch, " %s", victim->pcdata->extra_type); else send_to_char(" spots", ch); } send_to_char(".\n\r", ch); } } void show_char_to_char_1( CHAR_DATA *victim, CHAR_DATA *ch ) { char buf2[MAX_STRING_LENGTH]; if ( can_see( victim, ch ) && !IS_NPC( ch ) && !xIS_SET( ch->act, PLR_WIZINVIS ) && (ch->curr_talent[TAL_SEEKING] < 70 || victim->curr_talent[TAL_SEEKING] > 70) ) { act( AT_ACTION, "$n looks at you.", ch, NULL, victim, TO_VICT ); if ( victim != ch ) act( AT_ACTION, "$n looks at $N.", ch, NULL, victim, TO_NOTVICT ); else act( AT_ACTION, "$n looks at $mself.", ch, NULL, victim, TO_NOTVICT ); } show_char_to_char_2(ch, victim); if (victim->fur_pos > FURNITURE_NONE) { if (victim->on) sprintf (buf2, "%s %s %s %s.\n", PERS(victim, ch), pos_string(victim), fur_pos_string(victim->fur_pos), victim->on->short_descr ); send_to_char (buf2, ch ); } show_condition( ch, victim ); if ( victim != ch ) act( AT_PLAIN, "$N is using:", ch, NULL, victim, TO_CHAR ); else act( AT_PLAIN, "You are using:", ch, NULL, NULL, TO_CHAR ); show_equip(victim, ch); /* * Crash fix here by Thoric */ if ( IS_NPC(ch) || victim == ch ) return; if ( number_percent( ) < ch->curr_talent[TAL_SEEKING] ) { ch_printf( ch, "\n\rYou peek at %s inventory:\n\r", victim->sex == 1 ? "his" : victim->sex == 2 ? "her" : "its" ); show_list_to_char( victim->first_carrying, ch, TRUE, TRUE ); use_magic(ch, TAL_SEEKING, 1); } return; } void show_char_to_char( CHAR_DATA *list, CHAR_DATA *ch ) { CHAR_DATA *rch; for ( rch = list; rch; rch = rch->next_in_room ) { if ( rch == ch ) continue; if ( can_see( ch, rch ) != FALSE ) { show_char_to_char_0( rch, ch ); } } return; } bool check_blind( CHAR_DATA *ch ) { if ( !IS_NPC(ch) && xIS_SET(ch->act, PLR_HOLYLIGHT) ) return TRUE; if ( IS_AFFECTED(ch, AFF_TRUESIGHT) ) return TRUE; if ( IS_AFFECTED(ch, AFF_BLIND) || (!can_use_bodypart(ch, BP_REYE) && !can_use_bodypart(ch, BP_LEYE))) { send_to_char( "You can't see a thing!\n\r", ch ); return FALSE; } return TRUE; } /* * Returns classical DIKU door direction based on text in arg -Thoric */ int get_door( char *arg ) { int door; if ( !str_cmp( arg, "n" ) || !str_cmp( arg, "north" ) ) door = 0; else if ( !str_cmp( arg, "e" ) || !str_cmp( arg, "east" ) ) door = 1; else if ( !str_cmp( arg, "s" ) || !str_cmp( arg, "south" ) ) door = 2; else if ( !str_cmp( arg, "w" ) || !str_cmp( arg, "west" ) ) door = 3; else if ( !str_cmp( arg, "u" ) || !str_cmp( arg, "up" ) ) door = 4; else if ( !str_cmp( arg, "d" ) || !str_cmp( arg, "down" ) ) door = 5; else if ( !str_cmp( arg, "ne" ) || !str_cmp( arg, "northeast" ) ) door = 6; else if ( !str_cmp( arg, "nw" ) || !str_cmp( arg, "northwest" ) ) door = 7; else if ( !str_cmp( arg, "se" ) || !str_cmp( arg, "southeast" ) ) door = 8; else if ( !str_cmp( arg, "sw" ) || !str_cmp( arg, "southwest" ) ) door = 9; else door = -1; return door; } void do_look( CHAR_DATA *ch, char *argument ) { char arg [MAX_INPUT_LENGTH]; char arg1 [MAX_INPUT_LENGTH]; char arg2 [MAX_INPUT_LENGTH]; char arg3 [MAX_INPUT_LENGTH]; char roomdesc[MAX_STRING_LENGTH]; /* Generated Descs -- Scion */ EXIT_DATA *pexit; CHAR_DATA *victim; OBJ_DATA *obj; ROOM_INDEX_DATA *original; char *pdesc; bool doexaprog; sh_int door; int number, cnt; if ( !ch->desc ) return; if ( ch->position < POS_SLEEPING ) { send_to_char( "You can't see anything but stars!\n\r", ch ); return; } if ( ch->position == POS_SLEEPING ) { send_to_char( "You can't see anything, you're sleeping!\n\r", ch ); return; } if ( !check_blind( ch ) ) return; if ( !IS_NPC(ch) && !xIS_SET(ch->act, PLR_HOLYLIGHT) && !IS_AFFECTED(ch, AFF_TRUESIGHT) && !IS_AFFECTED(ch, AFF_INFRARED) && room_is_dark( ch->in_room ) ) { set_char_color( AT_DGREY, ch ); send_to_char( "It is pitch black ... \n\r", ch ); show_char_to_char( ch->in_room->first_person, ch ); return; } argument = one_argument( argument, arg1 ); argument = one_argument( argument, arg2 ); argument = one_argument( argument, arg3 ); doexaprog = str_cmp( "noprog", arg2 ) && str_cmp( "noprog", arg3 ); if ( arg1[0] == '\0' || !str_cmp( arg1, "auto" ) ) { /* 'look' or 'look auto' */ set_char_color( AT_WHITE, ch ); /* make life easier - shogar */ if ( !IS_NPC(ch) && IS_SET(ch->pcdata->permissions, PERMIT_BUILD) ) ch_printf(ch,"[%d] ",ch->in_room->vnum); /* let's show your position here -keo */ if (ch->in_obj) { send_to_char("Riding", ch); } else if (IS_UNDERWATER(ch)) { send_to_char("Swimming", ch); } else if (IS_AFFECTED(ch, AFF_FLYING)) { send_to_char("Flying", ch); } else if (IS_SET(ch->in_room->room_flags, ROOM_NOFLOOR)) { send_to_char("Falling", ch); } else { switch (ch->position) { case POS_RESTING: send_to_char("Resting", ch); break; case POS_SITTING: send_to_char("Sitting", ch); break; case POS_KNEELING: send_to_char("Kneeling", ch); break; case POS_SQUATTING: send_to_char("Squatting", ch); break; case POS_STANDING: send_to_char("Standing", ch); break; case POS_MOUNTED: send_to_char("Riding", ch); break; default: send_to_char("Walking", ch); } } send_to_char(" in ", ch); if (IS_AFFECTED(ch, AFF_VOID)) send_to_char("the Void", ch); else send_to_char( ch->in_room->name, ch ); if (IS_AFFECTED(ch, AFF_DREAMWORLD)) send_to_char(" &P[&pDreamworld&P]&W", ch); send_to_char( "\n\r", ch ); /* Room Desc Colors, to make things more interesting -keo */ if (!IS_OUTSIDE(ch)) { if (ch->in_room->sector_type == SECT_LAVA) set_char_color(AT_RED, ch); else if (ch->in_room->sector_type == SECT_DUNNO) set_char_color(AT_DGREY, ch); else if (!IS_UNDERWATER(ch)) set_char_color(AT_GREY, ch); else set_char_color(AT_BLUE, ch); } else if (time_info.hour>6 && time_info.hour<=18 && !IS_SET(sysdata.quest, QUEST_ETERNAL_NIGHT)) { /* Day Colors */ switch(ch->in_room->sector_type) { default: set_char_color(AT_YELLOW, ch); break; case SECT_FOREST: case SECT_SWAMP: set_char_color(AT_GREEN, ch); break; case SECT_MOUNTAIN: case SECT_ICE: set_char_color(AT_WHITE, ch); break; case SECT_WATER_SWIM: case SECT_WATER_NOSWIM: set_char_color(AT_BLUE, ch); break; case SECT_AIR: set_char_color(AT_LBLUE, ch); break; case SECT_DUNNO: set_char_color(AT_PURPLE, ch); break; } } else { /* Night colors */ switch(ch->in_room->sector_type) { default: set_char_color(AT_BLUE, ch); break; case SECT_FOREST: case SECT_SWAMP: set_char_color(AT_DGREEN, ch); break; case SECT_MOUNTAIN: set_char_color(AT_DGREY, ch); break; case SECT_WATER_SWIM: case SECT_WATER_NOSWIM: set_char_color(AT_DBLUE, ch); break; case SECT_AIR: set_char_color(AT_CYAN, ch); break; case SECT_DUNNO: set_char_color(AT_DGREY, ch); break; } } /* Generated Descriptions -- Scion */ if ((!IS_NPC(ch) && !xIS_SET(ch->act, PLR_BRIEF)) || IS_NPC(ch)) { strcpy(roomdesc, get_room_description(ch, roomdesc)); send_to_char(roomdesc, ch); } if (!IS_NPC(ch) && xIS_SET(ch->act, PLR_LONG_EXIT)) do_exits(ch, "" ); else if ( !IS_NPC(ch) && xIS_SET(ch->act, PLR_AUTOEXIT) ) do_exits( ch, "auto" ); if (!ch->in_room->pShop) show_list_to_char( ch->in_room->first_content, ch, FALSE, FALSE ); if (ch->in_obj) show_list_to_char(ch->in_obj->first_content, ch, FALSE,FALSE); show_char_to_char( ch->in_room->first_person, ch ); return; } if ( !str_cmp( arg1, "under" ) ) { int count; /* 'look under' */ if ( arg2[0] == '\0' ) { send_to_char( "Look beneath what?\n\r", ch ); return; } if ( ( obj = get_obj_here( ch, arg2 ) ) == NULL ) { send_to_char( "You do not see that here.\n\r", ch ); return; } if ( ch->carry_weight + obj->weight > can_carry_w( ch ) ) { send_to_char( "It's too heavy for you to look under.\n\r", ch ); return; } count = obj->count; obj->count = 1; act( AT_PLAIN, "You lift $p and look beneath it:", ch, obj, NULL, TO_CHAR ); act( AT_PLAIN, "$n lifts $p and looks beneath it.", ch, obj, NULL, TO_ROOM ); obj->count = count; if ( IS_OBJ_STAT( obj, ITEM_COVERING ) ) show_list_to_char( obj->first_content, ch, TRUE, TRUE ); else send_to_char( "Nothing.\n\r", ch ); if ( doexaprog ) oprog_examine_trigger( ch, obj ); return; } if ( !str_cmp( arg1, "i" ) || !str_cmp( arg1, "in" ) ) { int count; /* 'look in' */ if ( arg2[0] == '\0' ) { send_to_char( "Look in what?\n\r", ch ); return; } if ( ( obj = get_obj_here( ch, arg2 ) ) == NULL ) { send_to_char( "You do not see that here.\n\r", ch ); return; } switch ( obj->item_type ) { default: send_to_char( "That is not a container.\n\r", ch ); break; case ITEM_DRINK_CON: if ( obj->value[1] <= 0 ) { send_to_char( "It is empty.\n\r", ch ); if ( doexaprog ) oprog_examine_trigger( ch, obj ); break; } ch_printf( ch, "It's %s full of a %s liquid.\n\r", obj->value[1] < obj->value[0] / 4 ? "less than" : obj->value[1] < 3 * obj->value[0] / 4 ? "about" : "more than", liq_table[obj->value[2]].liq_color ); if ( doexaprog ) oprog_examine_trigger( ch, obj ); break; case ITEM_PORTAL: for ( pexit = ch->in_room->first_exit; pexit; pexit = pexit->next ) { if ( pexit->vdir == DIR_PORTAL && IS_SET(pexit->exit_info, EX_PORTAL) ) { if ( room_is_private( pexit->to_room )) { set_char_color( AT_WHITE, ch ); send_to_char( "That room is private buster!\n\r", ch ); return; } original = ch->in_room; char_from_room( ch ); char_to_room( ch, pexit->to_room ); do_look( ch, "auto" ); char_from_room( ch ); char_to_room( ch, original ); return; } } send_to_char( "You see swirling chaos...\n\r", ch ); break; case ITEM_CONTAINER: case ITEM_QUIVER: if ( IS_SET(obj->value[1], CONT_CLOSED) ) { send_to_char( "It is closed.\n\r", ch ); break; } case ITEM_CORPSE_NPC: case ITEM_CORPSE_PC: case ITEM_FURNITURE: case ITEM_VEHICLE: case ITEM_KEYRING: count = obj->count; obj->count = 1; if ( obj->item_type == ITEM_CONTAINER ) act( AT_PLAIN, "$p contains:", ch, obj, NULL, TO_CHAR ); else act( AT_PLAIN, "$p holds:", ch, obj, NULL, TO_CHAR ); obj->count = count; show_list_to_char( obj->first_content, ch, TRUE, TRUE ); if ( doexaprog ) oprog_examine_trigger( ch, obj ); break; } return; } if ( (pdesc=get_extra_descr(arg1, ch->in_room->first_extradesc)) != NULL ) { send_to_char_color( pdesc, ch ); return; } door = get_door(arg1); if ( (pexit=find_door(ch, arg1, TRUE)) != NULL ) { if ( IS_SET(pexit->exit_info, EX_CLOSED) && !IS_SET(pexit->exit_info, EX_WINDOW) ) { if ( (IS_SET(pexit->exit_info, EX_SECRET) || IS_SET(pexit->exit_info, EX_DIG)) && door != -1 ) send_to_char( "Nothing special there.\n\r", ch ); else act( AT_PLAIN, "The $d is closed.", ch, NULL, pexit->keyword, TO_CHAR ); return; } if ( IS_SET( pexit->exit_info, EX_BASHED ) ) act(AT_RED, "The $d has been bashed from its hinges!",ch, NULL, pexit->keyword, TO_CHAR); if ( pexit->description && pexit->description[0] != '\0' ) send_to_char( pexit->description, ch ); else send_to_char( "Nothing special there.\n\r", ch ); /* * Ability to look into the next room -Thoric */ if ( pexit->to_room && ( TALENT(ch, TAL_SEEKING) >= 10 || IS_SET( pexit->exit_info, EX_xLOOK ) ) ) { original = ch->in_room; char_from_room( ch ); char_to_room( ch, pexit->to_room ); do_look( ch, "auto" ); char_from_room( ch ); char_to_room( ch, original ); } return; } else if ( door != -1 ) { send_to_char( "Nothing special there.\n\r", ch ); return; } if ( (victim = get_char_room(ch, arg1)) != NULL ) { if (doexaprog) show_char_to_char_1( victim, ch ); else show_char_to_char_2( ch, victim ); return; } /* finally fixed the annoying look 2.obj desc bug -Thoric */ number = number_argument( arg1, arg ); for ( cnt = 0, obj = ch->last_carrying; obj; obj = obj->prev_content ) { if ( can_see_obj( ch, obj ) ) { if ( (pdesc=get_extra_descr(arg, obj->first_extradesc)) != NULL ) { if ( (cnt += obj->count) < number ) continue; send_to_char_color( pdesc, ch ); if ( doexaprog ) oprog_examine_trigger( ch, obj ); return; } if ( (pdesc=get_extra_descr(arg, obj->pIndexData->first_extradesc)) != NULL ) { if ( (cnt += obj->count) < number ) continue; send_to_char_color( pdesc, ch ); if ( doexaprog ) oprog_examine_trigger( ch, obj ); return; } if ( nifty_is_name_prefix( arg, obj->name ) ) { if ( (cnt += obj->count) < number ) continue; send_to_char(obj->description, ch); send_to_char("\n\r", ch); pdesc = get_extra_descr( obj->name, obj->pIndexData->first_extradesc ); if ( !pdesc ) pdesc = get_extra_descr( obj->name, obj->first_extradesc ); if ( !pdesc ) { int diff=obj->weight-(obj->condition / 50); if (diff < -32) act(AT_PLAIN, "$p is in the best condition it could possibly be.", ch, obj, NULL, TO_CHAR); else if (diff < -16) act(AT_PLAIN, "$p has been enhanced to withstand much damage.", ch, obj, NULL, TO_CHAR); else if (diff < -8) act(AT_PLAIN, "$p looks very strong.", ch, obj, NULL, TO_CHAR); else if (diff < -4) act(AT_PLAIN, "$p seems like it would be able to withstand significant damage.", ch, obj, NULL, TO_CHAR); else if (diff < -2) act(AT_PLAIN, "$p looks somewhat stronger than normal.", ch, obj, NULL, TO_CHAR); else if (diff < 1) act(AT_PLAIN, "$p is in perfect condition.", ch, obj, NULL, TO_CHAR); else if (diff < 2) act(AT_PLAIN, "$p is slightly damaged.", ch, obj, NULL, TO_CHAR); else if (diff < 4) act(AT_PLAIN, "$p is somewhat damaged.", ch, obj, NULL, TO_CHAR); else if (diff < 8) act(AT_PLAIN, "$p is pretty damaged.", ch, obj, NULL, TO_CHAR); else if (diff < 16) act(AT_PLAIN, "$p is damaged.", ch, obj, NULL, TO_CHAR); else if (diff < 32) act(AT_PLAIN, "$p is severly damaged.", ch, obj, NULL, TO_CHAR); else act(AT_PLAIN, "$p is falling apart!", ch, obj, NULL, TO_CHAR); } else send_to_char_color( pdesc, ch ); if (obj->item_type == ITEM_BOOK) { EXTRA_DESCR_DATA *ed; send_to_char( "Contents:\n\r", ch ); for ( ed = obj->first_extradesc; ed; ed = ed->next ) { send_to_char( ed->keyword, ch ); if ( ed->next ) send_to_char( "\n\r", ch ); } send_to_char( "\n\r", ch ); } if ( doexaprog ) oprog_examine_trigger( ch, obj ); return; } } } for ( obj = ch->in_room->last_content; obj; obj = obj->prev_content ) { if ( can_see_obj( ch, obj ) ) { if ( (pdesc=get_extra_descr(arg, obj->first_extradesc)) != NULL ) { if ( (cnt += obj->count) < number ) continue; send_to_char_color( pdesc, ch ); if ( doexaprog ) oprog_examine_trigger( ch, obj ); return; } if ( (pdesc=get_extra_descr(arg, obj->pIndexData->first_extradesc)) != NULL ) { if ( (cnt += obj->count) < number ) continue; send_to_char_color( pdesc, ch ); if ( doexaprog ) oprog_examine_trigger( ch, obj ); return; } if ( nifty_is_name_prefix( arg, obj->name ) ) { if ( (cnt += obj->count) < number ) continue; pdesc = get_extra_descr( obj->name, obj->pIndexData->first_extradesc ); if ( !pdesc ) pdesc = get_extra_descr( obj->name, obj->first_extradesc ); if ( !pdesc ) send_to_char( "You see nothing special.\r\n", ch ); else send_to_char_color( pdesc, ch ); if ( doexaprog ) oprog_examine_trigger( ch, obj ); return; } } } send_to_char( "You do not see that here.\n\r", ch ); return; } void show_race_line( CHAR_DATA *ch, CHAR_DATA *victim ) { char buf[MAX_STRING_LENGTH]; int feet, inches; if (!IS_NPC(victim)) ch_printf(ch, "%s is %s %s.\n\r", PERS(victim, ch), aoran(victim->pcdata->type), victim->species); if ( !IS_NPC(victim) && (victim != ch) ) { feet = victim->height / 12; inches = victim->height % 12; sprintf( buf, "%s is %d'%d\" and weighs %d pounds.\n\r", PERS(victim, ch), feet, inches, victim->weight ); send_to_char( buf, ch); return; } if ( !IS_NPC(victim) && (victim == ch) ) { feet = victim->height / 12; inches = victim->height % 12; sprintf( buf, "You are %d'%d\" and weigh %d pounds.\n\r", feet, inches, victim->weight ); send_to_char( buf, ch); return; } } void show_condition( CHAR_DATA *ch, CHAR_DATA *victim ) { char buf[MAX_STRING_LENGTH]; int percent; if ( victim->max_hit > 0 ) percent = ( 100 * victim->hit ) / victim->max_hit; else percent = -1; if ( victim != ch ) { strcpy( buf, PERS(victim, ch) ); if ( percent >= 100 ) strcat( buf, " is in perfect health.\n\r" ); else if ( percent >= 90 ) strcat( buf, " is slightly scratched.\n\r" ); else if ( percent >= 80 ) strcat( buf, " has a few bruises.\n\r" ); else if ( percent >= 70 ) strcat( buf, " has some cuts.\n\r" ); else if ( percent >= 60 ) strcat( buf, " has several wounds.\n\r" ); else if ( percent >= 50 ) strcat( buf, " has many nasty wounds.\n\r" ); else if ( percent >= 40 ) strcat( buf, " is bleeding freely.\n\r" ); else if ( percent >= 30 ) strcat( buf, " is covered in blood.\n\r" ); else if ( percent >= 20 ) strcat( buf, " is leaking guts.\n\r" ); else if ( percent >= 10 ) strcat( buf, " is almost dead.\n\r" ); else strcat( buf, " is DYING.\n\r" ); } else { strcpy( buf, "You" ); if ( percent >= 100 ) strcat( buf, " are in perfect health.\n\r" ); else if ( percent >= 90 ) strcat( buf, " are slightly scratched.\n\r"); else if ( percent >= 80 ) strcat( buf, " have a few bruises.\n\r" ); else if ( percent >= 70 ) strcat( buf, " have some cuts.\n\r" ); else if ( percent >= 60 ) strcat( buf, " have several wounds.\n\r" ); else if ( percent >= 50 ) strcat( buf, " have many nasty wounds.\n\r"); else if ( percent >= 40 ) strcat( buf, " are bleeding freely.\n\r" ); else if ( percent >= 30 ) strcat( buf, " are covered in blood.\n\r" ); else if ( percent >= 20 ) strcat( buf, " are leaking guts.\n\r" ); else if ( percent >= 10 ) strcat( buf, " are almost dead.\n\r" ); else strcat( buf, " are DYING.\n\r" ); } buf[0] = UPPER(buf[0]); send_to_char( buf, ch ); return; } /* A much simpler version of look, this function will show you only the condition of a mob or pc, or if used without an argument, the same you would see if you enter the room and have config +brief. -- Narn, winter '96 */ void do_glance( CHAR_DATA *ch, char *argument ) { char arg1 [MAX_INPUT_LENGTH]; CHAR_DATA *victim; bool brief; if ( !ch->desc ) return; if ( ch->position < POS_SLEEPING ) { send_to_char( "You can't see anything but stars!\n\r", ch ); return; } if ( ch->position == POS_SLEEPING ) { send_to_char( "You can't see anything, you're sleeping!\n\r", ch ); return; } if ( !check_blind( ch ) ) return; set_char_color( AT_ACTION, ch ); argument = one_argument( argument, arg1 ); if ( arg1[0] == '\0' ) { if ( xIS_SET(ch->act, PLR_BRIEF) ) brief = TRUE; else brief = FALSE; xSET_BIT( ch->act, PLR_BRIEF ); do_look( ch, "auto" ); if ( !brief ) xREMOVE_BIT(ch->act, PLR_BRIEF); return; } if ( ( victim = get_char_room( ch, arg1 ) ) == NULL ) { send_to_char( "They're not here.\n\r", ch ); return; } else { if ( can_see( victim, ch ) ) { act( AT_ACTION, "$n glances at you.", ch, NULL, victim, TO_VICT ); act( AT_ACTION, "$n glances at $N.", ch, NULL, victim, TO_NOTVICT ); } show_char_to_char_2(ch,victim); } show_condition( ch, victim ); return; } void do_examine( CHAR_DATA *ch, char *argument ) { char buf[MAX_STRING_LENGTH]; char arg[MAX_INPUT_LENGTH]; OBJ_DATA *obj; sh_int dam; if ( !argument ) { bug( "do_examine: null argument.", 0); return; } if ( !ch ) { bug( "do_examine: null ch.", 0); return; } one_argument( argument, arg ); if ( arg[0] == '\0' ) { send_to_char( "Examine what?\n\r", ch ); return; } sprintf( buf, "%s noprog", arg ); do_look( ch, buf ); /* * Support for looking at boards, checking equipment conditions, * and support for trigger positions by Thoric */ if ( (obj = get_obj_here(ch, arg)) != NULL ) { ch_printf(ch, "%s\n\r", obj->description); switch (obj->item_type) { case ITEM_COOK: strcpy( buf, "As you examine it carefully you notice that it " ); dam = obj->value[2]; if (dam >= 3) strcat( buf, "is burned to a crisp."); else if (dam == 1) strcat( buf, "is a little over cooked."); else if (dam == 1) strcat( buf, "is perfectly roasted."); else strcat( buf, "is raw."); strcat( buf, "\n\r" ); send_to_char( buf, ch ); case ITEM_FOOD: if ( obj->timer > 0 && obj->value[1] > 0 ) dam = (obj->timer * 10) / obj->value[1]; else dam = 10; if ( obj->item_type == ITEM_FOOD ) strcpy( buf, "As you examine it carefully you notice that it " ); else strcpy( buf, "Also it " ); if (dam >= 10) strcat( buf, "is fresh."); else if (dam == 9) strcat( buf, "is nearly fresh."); else if (dam == 8) strcat( buf, "is perfectly fine."); else if (dam == 7) strcat( buf, "looks good."); else if (dam == 6) strcat( buf, "looks ok."); else if (dam == 5) strcat( buf, "is a little stale."); else if (dam == 4) strcat( buf, "is a bit stale."); else if (dam == 3) strcat( buf, "smells slightly off."); else if (dam == 2) strcat( buf, "smells quite rank."); else if (dam == 1) strcat( buf, "smells revolting!"); else if (dam <= 0) strcat( buf, "is crawling with maggots!"); strcat( buf, "\n\r" ); send_to_char( buf, ch ); break; case ITEM_SWITCH: case ITEM_LEVER: case ITEM_PULLCHAIN: if ( IS_SET( obj->value[0], TRIG_UP ) ) send_to_char( "You notice that it is in the up position.\n\r", ch ); else send_to_char( "You notice that it is in the down position.\n\r", ch ); break; case ITEM_BUTTON: if ( IS_SET( obj->value[0], TRIG_UP ) ) send_to_char( "You notice that it is depressed.\n\r", ch ); else send_to_char( "You notice that it is not depressed.\n\r", ch ); break; case ITEM_CORPSE_PC: case ITEM_CORPSE_NPC: { sh_int timerfrac = obj->timer; if ( obj->item_type == ITEM_CORPSE_PC ) timerfrac = (int)obj->timer / 8 + 1; switch (timerfrac) { default: send_to_char( "This corpse has recently been slain.\n\r", ch ); break; case 4: send_to_char( "This corpse was slain a little while ago.\n\r", ch ); break; case 3: send_to_char( "A foul smell rises from the corpse, and it is covered in flies.\n\r", ch ); break; case 2: send_to_char( "A writhing mass of maggots and decay, you can barely go near this corpse.\n\r", ch ); break; case 1: case 0: send_to_char( "Little more than bones, there isn't much left of this corpse.\n\r", ch ); break; } } case ITEM_CONTAINER: if ( IS_OBJ_STAT( obj, ITEM_COVERING ) ) break; case ITEM_DRINK_CON: case ITEM_FURNITURE: case ITEM_QUIVER: send_to_char( "When you look inside, you see:\n\r", ch ); case ITEM_KEYRING: sprintf( buf, "in %s noprog", arg ); do_look( ch, buf ); break; } if ( IS_OBJ_STAT( obj, ITEM_COVERING ) ) { sprintf( buf, "under %s noprog", arg ); do_look( ch, buf ); } oprog_examine_trigger( ch, obj ); if ( char_died(ch) || obj_extracted(obj) ) return; check_for_trap( ch, obj, TRAP_EXAMINE ); } return; } void do_exits( CHAR_DATA *ch, char *argument ) { char buf[MAX_STRING_LENGTH]; EXIT_DATA *pexit; bool found; bool fAuto; set_char_color( AT_EXITS, ch ); buf[0] = '\0'; fAuto = !str_cmp( argument, "auto" ); if ( !check_blind(ch) ) return; strcpy( buf, fAuto ? "Exits:" : "Obvious exits:\n\r" ); found = FALSE; for ( pexit = ch->in_room->first_exit; pexit; pexit = pexit->next ) { if ( pexit->to_room && (!IS_SET(pexit->exit_info, EX_HIDDEN) || ch->curr_talent[TAL_SEEKING] >= 65 ) ) { found = TRUE; if ( fAuto ) { strcat( buf, " " ); /* make life easier - shogar */ if ( !IS_NPC(ch) && xIS_SET(ch->act, PLR_HOLYLIGHT) ) sprintf(buf+strlen(buf),"[%d]-",pexit->to_room->vnum); if (!IS_SET(pexit->exit_info, EX_SECRET) || ch->curr_talent[TAL_SEEKING] >= 80) { if (IS_SET(pexit->exit_info, EX_CLOSED)) strcat( buf, "&O#&w"); strcat( buf, dir_name[pexit->vdir] ); } } else { if ( !IS_NPC(ch) && xIS_SET(ch->act, PLR_HOLYLIGHT) ) sprintf( buf + strlen(buf), "[%-5d] %-1s%-5s - %s\n\r", pexit->to_room->vnum, IS_SET(pexit->exit_info, EX_CLOSED) ? "&O#&w" : "&w", capitalize( dir_name[pexit->vdir] ), pexit->to_room->name ); else sprintf( buf + strlen(buf), "%-1s%-5s - %s\n\r", IS_SET(pexit->exit_info, EX_CLOSED) ? "&O#&w" : "&w", capitalize( dir_name[pexit->vdir] ), pexit->to_room->name ); } } } if ( !found ) strcat( buf, fAuto ? " none.\n\r" : "None.\n\r" ); else if ( fAuto ) strcat( buf, ".\n\r" ); send_to_char( buf, ch ); return; } /* To: Scion From: Keolah Date: Thu Jul 29 16:40:35 1999 Subject: months and days Days: Vannes (Sun), Kelivan (mountain), Vesevan (star), Tativan (tree), Retivan (water), Daltavan (song), Vestivan (wind) Months: Brykena (change), Relithoves (sleet), Vestejen (gale), Tatarmyr (bloom), Sesiddet (traveling), Heygavan (summer), Veseveret (blue star), Vankampa (glitter), Dalteyves (thunder), Nastarmath (autumn), Retsoves (rain), Kinrelth (snow) */ char * const day_name [] = { "Kelivan", "Vesevan", "Tativan", "Retivan", "Daltevan", "Vestivan", "Vannes" }; char * const month_name [] = { "Brykena", "Relithoves", "Vestejan", "Tatarmyr", "Sesiddet", "Heygavan", "Veseveret", "Vankampa", "Dalteyves", "Nastarmath", "Retsoves", "Kinrelth" }; void do_time( CHAR_DATA *ch, char *argument ) { extern char str_boot_time[]; extern char reboot_time[]; char *suf; int day; day = time_info.day + 1; if ( day > 4 && day < 20 ) suf = "th"; else if ( day % 10 == 1 ) suf = "st"; else if ( day % 10 == 2 ) suf = "nd"; else if ( day % 10 == 3 ) suf = "rd"; else suf = "th"; set_char_color( AT_YELLOW, ch ); ch_printf( ch, "It is %d o'clock %s on %s, the %d%s of the Month of %s, the year %d.\n\r" "The mud started up at: %s\r" "The system time (E.S.T.): %s\r" "Next Reboot is set for: %s\r", (time_info.hour % 12 == 0) ? 12 : time_info.hour % 12, time_info.hour >= 12 ? "pm" : "am", day_name[day % 7], day, suf, month_name[time_info.month], time_info.year, str_boot_time, (char *) ctime( ¤t_time ), reboot_time ); return; } /* * Produce a description of the weather based on area weather using * the following sentence format: * <combo-phrase> and <single-phrase>. * Where the combo-phrase describes either the precipitation and * temperature or the wind and temperature. The single-phrase * describes either the wind or precipitation depending upon the * combo-phrase. * Last Modified: July 31, 1997 * Fireblade - Under Construction */ void do_weather(CHAR_DATA *ch, char *argument) { int climate; AREA_DATA *tarea = ch->in_room->area; char *combo, *single; char buf[MAX_INPUT_LENGTH]; int temp, precip, wind, mana; MOON_DATA *moon; if (!argument || argument[0] == '\0') { temp = (ch->in_room->area->weather->temp + 3*weath_unit - 1)/ weath_unit; precip = (ch->in_room->area->weather->precip + 3*weath_unit - 1)/ weath_unit; wind = (ch->in_room->area->weather->wind + 3*weath_unit - 1)/ weath_unit; mana = (ch->in_room->area->weather->mana + 3*weath_unit -1)/ weath_unit; if ( IS_OUTSIDE(ch) ) { if ( precip >= 3 ) { combo = preciptemp_msg[precip][temp]; single = wind_msg[wind]; } else { combo = windtemp_msg[wind][temp]; single = precip_msg[precip]; } sprintf(buf, "%s and %s.\n\r", combo, single); set_char_color(AT_BLUE, ch); ch_printf(ch, buf); if (IS_SET(sysdata.quest, QUEST_ETERNAL_NIGHT)) { sprintf(buf, "The sky lies black under eternal night.\n\r"); } else { if (precip >= 3) sprintf(buf, "%s\n\r", cloudyday_msg[(int) time_info.hour/4]); else sprintf(buf, "%s\n\r", clearday_msg[(int) time_info.hour/4]); } ch_printf(ch, buf); moon = first_moon; while (moon) { if ((moon->up) && (!str_cmp(moon->world, ch->in_room->area->resetmsg))) { sprintf(buf, "%s %s moon hangs in the sky.\n\r", capitalize(aoran(moon->color)), moon_phase[moon->phase]); ch_printf(ch, buf); } moon= moon->next; } } else ch_printf(ch, "You can't see the sky from here.\n\r"); mana = URANGE(0, mana, 5); temp = URANGE(0, temp, 5); if (ch->mana > (int)ch->max_mana/20) { sprintf(buf, "%s.\r\n", manatemp_msg[mana][temp]); ch_printf(ch, buf); } return; } /* Let you alter the weather in one area based on * your effectivity in the appropriate talent */ if (!str_cmp(argument, "warmer") && ch->curr_talent[TAL_FIRE] >= 30) { climate = tarea->weather->climate_temp * 100 - 200; if (tarea->weather->temp >= climate + TALENT(ch, TAL_FIRE)) { send_to_char("You can't make this area any hotter.\n\r", ch); return; } tarea->weather->temp += 10; send_to_char("&RYou heat up the area a bit.\n\r", ch); use_magic(ch, TAL_FIRE, 250); return; } else if (!str_cmp(argument, "colder") && ch->curr_talent[TAL_FROST] >= 30) { climate = tarea->weather->climate_temp * 100 - 200; if (tarea->weather->temp <= climate - TALENT(ch, TAL_FROST)) { send_to_char("You can't make this area any colder.\n\r", ch); return; } tarea->weather->temp -= 10; send_to_char("&CYou bring a winter chill to the region.\n\r", ch); use_magic(ch, TAL_FROST, 250); return; } else if (!str_cmp(argument, "windier") && ch->curr_talent[TAL_WIND] >= 30) { climate = tarea->weather->climate_wind * 100 - 200; if (tarea->weather->wind >= climate + TALENT(ch, TAL_WIND)) { send_to_char("You can't make this area any windier.\n\r", ch); return; } tarea->weather->wind += 10; send_to_char("&cYou whip up the winds in the area.\n\r", ch); use_magic(ch, TAL_WIND, 250); return; } else if (!str_cmp(argument, "stiller") && ch->curr_talent[TAL_WIND] >= 50) { climate = tarea->weather->climate_precip * 100 - 200; if (tarea->weather->precip <= climate - TALENT(ch, TAL_WIND)) { send_to_char("You can't make the wind in this area any stiller.\n\r", ch); return; } tarea->weather->precip += 10; send_to_char("&cYou calm the winds in the region.\n\r", ch); use_magic(ch, TAL_WIND, 250); return; } else if (!str_cmp(argument, "wetter") && ch->curr_talent[TAL_WATER] >= 30) { climate = tarea->weather->climate_precip * 100 - 200; if (tarea->weather->precip >= climate + TALENT(ch, TAL_WATER)) { send_to_char("You can't make this area any wetter.\n\r", ch); return; } tarea->weather->precip += 10; send_to_char("&BYou build up moisture in the air.\n\r", ch); use_magic(ch, TAL_WATER, 250); return; } else if (!str_cmp(argument, "drier") && ch->curr_talent[TAL_FIRE] >= 60) { climate = tarea->weather->climate_precip * 100 - 200; if (tarea->weather->precip <= climate - TALENT(ch, TAL_FIRE)) { send_to_char("You can't make this area any drier.\n\r", ch); return; } tarea->weather->precip -= 10; send_to_char("&YYou evaporate moisture in the air.\n\r", ch); use_magic(ch, TAL_FIRE, 250); return; } else { send_to_char("You can do no such thing to the weather.\n\r", ch); return; } } /* A more internal version of do_weather that returns the weather * string instead of sending it to the char. Used for generated * room descriptions -- Scion */ char *get_weather_string(CHAR_DATA *ch, char *weather) { char *combo, *single; char buf[MAX_INPUT_LENGTH]; char magic[MAX_INPUT_LENGTH]; int temp, precip, wind, mana; MOON_DATA *moon; temp = (ch->in_room->area->weather->temp + 3*weath_unit - 1)/ weath_unit; precip = (ch->in_room->area->weather->precip + 3*weath_unit - 1)/ weath_unit; wind = (ch->in_room->area->weather->wind + 3*weath_unit - 1)/ weath_unit; mana = (ch->in_room->area->weather->mana + 3*weath_unit -1)/ weath_unit; if ( IS_OUTSIDE(ch) ) { if ( precip >= 3 ) { combo = preciptemp_msg[precip][temp]; single = wind_msg[wind]; } else { combo = windtemp_msg[wind][temp]; single = precip_msg[precip]; } sprintf(buf, "%s and %s.\n\r", combo, single); if (IS_SET(sysdata.quest, QUEST_ETERNAL_NIGHT)) { sprintf(magic, "The sky lies black under eternal night.\n\r"); } else { if (precip >= 3) sprintf(magic, "%s\n\r", cloudyday_msg[(int) time_info.hour/4]); else sprintf(magic, "%s\n\r", clearday_msg[(int) time_info.hour/4]); } strcat(buf, magic); moon = first_moon; while (moon) { if ((moon->up) && (!str_cmp(moon->world, ch->in_room->area->resetmsg))) { sprintf(magic, "%s %s moon hangs in the sky.\n\r", capitalize(aoran(moon->color)), moon_phase[moon->phase]); strcat(buf, magic); } moon= moon->next; } } else strcpy(buf, ""); /* Were getting crashes when this hit 6 for some reason -- Scion */ mana = URANGE(0, mana, 5); if (ch->mana > (int)ch->max_mana/20) { sprintf(magic, " %s.\r\n", manatemp_msg[mana][temp]); } strcat(buf, magic); weather = STRALLOC(buf); return weather; } /* * Moved into a separate function so it can be used for other things * ie: online help editing -Thoric */ HELP_DATA *get_help( CHAR_DATA *ch, char *argument ) { char argall[MAX_INPUT_LENGTH]; char argone[MAX_INPUT_LENGTH]; char argnew[MAX_INPUT_LENGTH]; HELP_DATA *pHelp; int lev; if ( argument[0] == '\0' ) argument = "summary"; if ( isdigit(argument[0]) ) { lev = number_argument( argument, argnew ); argument = argnew; } else lev = -2; /* * Tricky argument handling so 'help a b' doesn't match a. */ argall[0] = '\0'; while ( argument[0] != '\0' ) { argument = one_argument( argument, argone ); if ( argall[0] != '\0' ) strcat( argall, " " ); strcat( argall, argone ); } for ( pHelp = first_help; pHelp; pHelp = pHelp->next ) { if ( pHelp->permit && !IS_SET(ch->pcdata->permissions, pHelp->permit )) continue; if ( is_name( argall, pHelp->keyword ) ) return pHelp; } return NULL; } /* * LAWS command */ void do_laws( CHAR_DATA *ch, char *argument ) { char buf[1024]; if ( argument == NULL) do_new_help( ch, "rules" ); else { sprintf( buf, "rules_%s", argument ); do_new_help( ch, buf ); } } void do_who( CHAR_DATA *ch, char *argument ) { char buf[MAX_STRING_LENGTH]; char invis_str[MAX_INPUT_LENGTH]; char rank_text[MAX_INPUT_LENGTH]; DESCRIPTOR_DATA *d; int nMatch = 0; CHAR_DATA *wch; char *rank; send_to_pager( "\n\r&Y Elkandu in the Planes\n\r\n\r", ch); for (d = first_descriptor;d;d = d->next) { if (d->connected != CON_PLAYING && d->connected != CON_EDITING) continue; if (!d->character) continue; wch = d->character; sprintf( rank_text, "%s", (get_talent_rank(wch)) ); rank = rank_text; if (get_char_worth(wch) >= 2000 && ( wch->pcdata->rank && wch->pcdata->rank[0] != '\0' )) rank = wch->pcdata->rank; else if (IS_SET( wch->pcdata->flags, PCFLAG_ANONYMOUS)) rank = "&zAnonymous"; if ( xIS_SET(wch->act, PLR_WIZINVIS) ) sprintf( invis_str, " &R(&WInvis %d&R)&w", wch->pcdata->wizinvis); else invis_str[0] = '\0'; sprintf( buf, "^x&C[&W%s&C] &w%s %s%s%s%s%s%s%s\n\r", const_color_align( rank, 12, ALIGN_CENTER ), wch->pcdata->title, invis_str, (wch->desc && wch->desc->connected) ? " &Y[&WWRITING&Y]&w " : "", IS_AFFECTED(wch, AFF_DREAMWORLD) ? "&P[&pDreamworld&P]&w " : "", IS_AFFECTED(wch, AFF_VOID) ? " &b[&zVoid&b]&w " : "", xIS_SET(wch->act, PLR_OOC) ? " &Y[&WOOC&Y]&w " : "", xIS_SET(wch->act, PLR_AFK) ? " &Y[&WIDLE&Y]&w " : "", xIS_SET(wch->act, PLR_BOUNTY) ? " &R(&WBOUNTY&R)&w " : "" ); nMatch++; send_to_char(buf, ch); } send_to_pager( "&x\n\r", ch ); set_char_color( AT_YELLOW, ch ); ch_printf( ch, "&Y[&WThere %s &Y%d player%s&W on %s.&Y]&w\n\r", nMatch == 1 ? "is" : "are", nMatch, nMatch == 1 ? "" : "s", sysdata.mud_name ); return; } /* This command SUCKS! It's misleading enough to be dangerous to morts. -- Scion * Re-written Jan 25, 2001 by Keolah */ void do_compare( CHAR_DATA *ch, char *argument ) { char arg1[MAX_INPUT_LENGTH]; char arg2[MAX_INPUT_LENGTH]; OBJ_DATA *obj1; OBJ_DATA *obj2; int diff; int value1; int value2; char *msg; argument = one_argument( argument, arg1 ); argument = one_argument( argument, arg2 ); if ( arg1[0] == '\0' ) { send_to_char( "Compare what to what?\n\r", ch ); return; } if ( ( obj1 = get_obj_carry( ch, arg1 ) ) == NULL ) { send_to_char( "You do not have that item.\n\r", ch ); return; } if ( arg2[0] == '\0' ) { for ( obj2 = ch->first_carrying; obj2; obj2 = obj2->next_content ) { if ( obj2->wear_loc != WEAR_NONE && can_see_obj( ch, obj2 ) && obj1->item_type == obj2->item_type ) break; } if ( !obj2 ) { send_to_char( "You aren't wearing anything comparable.\n\r", ch ); return; } } else { if ( ( obj2 = get_obj_carry( ch, arg2 ) ) == NULL ) { send_to_char( "You do not have that item.\n\r", ch ); return; } } msg = NULL; value1 = 0; value2 = 0; if ( obj1 == obj2 ) { msg = "You compare $p to itself. It looks about the same."; } else if ( obj1->item_type != obj2->item_type ) { msg = "You can't compare $p and $P."; } else { switch ( obj1->item_type ) { default: msg = "You can't compare $p and $P."; break; case ITEM_ARMOR: value1 = obj1->cost; value2 = obj2->cost; break; case ITEM_WEAPON: value1 = obj1->cost; value2 = obj2->cost; break; } } diff = abs(value1 - value2); if ( !msg ) { if ( diff < 100000 ) msg = "$p and $P look about the same value."; else if ( value1 > value2 ) { if (diff > 500000 ) { msg = "$p looks far more valuable than $P."; } else { msg = "$p looks more valuable than $P."; } } else { if (diff > 500000 ) { msg = "$p looks far less valuable than $P."; } else { msg = "$p looks less valuable than $P."; } } } act( AT_PLAIN, msg, ch, obj1, obj2, TO_CHAR ); return; } void do_where( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; DESCRIPTOR_DATA *d; bool found; if (ch->curr_talent[TAL_SEEKING] < 40) { ch_printf(ch, "You are in %s.", ch->in_room->name); return; } set_pager_color( AT_PERSON, ch ); pager_printf( ch, "Elkandu who you can Seek right now:\n\r" ); found = FALSE; for ( d = first_descriptor; d; d = d->next ) if ( (d->connected == CON_PLAYING || d->connected == CON_EDITING ) && ( victim = d->character ) != NULL && !IS_NPC(victim) && victim->in_room && (victim->in_room->area == ch->in_room->area || ch->curr_talent[TAL_SEEKING] >= 60) && (!str_cmp(victim->in_room->area->resetmsg, ch->in_room->area->resetmsg) || ch->curr_talent[TAL_SEEKING] >= 80) && (!IS_SET(victim->in_room->room_flags, ROOM_NO_ASTRAL) || ch->curr_talent[TAL_SEEKING] >= 90) && can_see( ch, victim ) ) { found = TRUE; pager_printf_color( ch, "%-15s&P ", PERS(victim, ch) ); pager_printf_color( ch, "%-20s ", victim->in_room->name); pager_printf_color( ch, "%-15s ", victim->in_room->area->name); pager_printf_color( ch, "%-10s\n\r", victim->in_room->area->resetmsg); } if ( !found ) send_to_char( "None\n\r", ch ); return; } /* Recoded by Keolah Oct 12 2000 */ void do_consider( CHAR_DATA *ch, char *argument ) { char arg[MAX_INPUT_LENGTH]; CHAR_DATA *victim; char *msg; int diff; one_argument( argument, arg ); if ( arg[0] == '\0' ) { send_to_char( "Consider killing whom?\n\r", ch ); return; } if ( ( victim = get_char_room( ch, arg ) ) == NULL ) { send_to_char( "They're not here.\n\r", ch ); return; } diff = get_char_worth(victim); if ( diff < 200 ) msg = "$N is probably not worth killing."; else if ( diff < 500 ) msg = "$N appears inexperienced."; else if ( diff < 1000) msg = "$N seems to move with confidence."; else if ( diff < 1500) msg = "$N appears experienced and confident."; else if ( diff < 2000) msg = "$N moves with a deadly grace and power."; else msg = "$N radiates an aura of power and command."; /* diff = get_char_worth(victim) - get_char_worth(ch); if ( diff < -150) msg = "$N is as weak as a feather!"; else if ( diff < -100) msg = "You could kill $N with your hands tied!"; else if ( diff < -50) msg = "Piece of cake."; else if ( diff < -20) msg = "$N is a wimp."; else if ( diff < 0) msg = "$N looks weaker than you."; else if ( diff < 20) msg = "$N looks about as strong as you."; else if ( diff < 50) msg = "It would take a bit of luck..."; else if ( diff < 100) msg = "It would take a lot of luck, and great equipment!"; else if ( diff < 150) msg = "Why don't you dig a grave for yourself first?"; else msg = "It'd be easier to kill Keolah with your head chopped off."; */ act( AT_CONSIDER, msg, ch, NULL, victim, TO_CHAR ); act( AT_CONSIDER, "$n looks at you very closely...", ch, NULL, victim, TO_VICT ); act( AT_CONSIDER, "$n looks at $N very closely.", ch, NULL, victim, TO_NOTVICT ); return; } void do_practice( CHAR_DATA *ch, char *argument ) { char buf[MAX_STRING_LENGTH]; int sn; if ( IS_NPC(ch) ) return; if ( argument[0] == '\0' ) { int col; sh_int lasttype, cnt; col = cnt = 0; lasttype = SKILL_SPELL; set_pager_color( AT_MAGIC, ch ); for ( sn = 0; sn < top_sn; sn++ ) { if ( !skill_table[sn]->name ) break; if ( strcmp(skill_table[sn]->name, "reserved") == 0 && ( CAN_CAST(ch) ) ) { if ( col % 3 != 0 ) send_to_pager( "\n\r", ch ); set_pager_color( AT_MAGIC, ch ); send_to_pager_color( " ----------------------------------[&CSpells&B]----------------------------------\n\r", ch); col = 0; } if ( skill_table[sn]->type != lasttype ) { if ( !cnt ) send_to_pager( " (none)\n\r", ch ); else if ( col % 3 != 0 ) send_to_pager( "\n\r", ch ); set_pager_color( AT_MAGIC, ch ); pager_printf_color( ch, " ----------------------------------&C%ss&B----------------------------------\n\r", skill_tname[skill_table[sn]->type]); col = cnt = 0; } lasttype = skill_table[sn]->type; if (skill_available(ch, sn) == FALSE) continue; if ((LEARNED(ch, sn) < 1) && SPELL_FLAG(skill_table[sn], SF_SECRETSKILL)) continue; if (lasttype != SKILL_SPELL && LEARNED(ch, sn) < 1) continue; ++cnt; set_pager_color( AT_MAGIC, ch ); pager_printf( ch, "%20.20s", skill_table[sn]->name ); if ( LEARNED(ch, sn) > 0 ) set_pager_color( AT_SCORE, ch ); pager_printf( ch, " %3d%% ", LEARNED(ch, sn) ); if ( ++col % 3 == 0 ) send_to_pager( "\n\r", ch ); } if ( col % 3 != 0 ) send_to_pager( "\n\r", ch ); set_pager_color( AT_MAGIC, ch ); } else { CHAR_DATA *mob; bool can_prac = TRUE; if ( !IS_AWAKE(ch) ) { send_to_char( "In your dreams, or what?\n\r", ch ); return; } for ( mob = ch->in_room->first_person; mob; mob = mob->next_in_room ) if ( IS_NPC(mob) && xIS_SET(mob->act, ACT_PRACTICE) ) break; if ( !mob ) { send_to_char( "You can't do that here.\n\r", ch ); return; } sn = skill_lookup( argument ); can_prac = skill_available(ch, sn); if (can_prac == FALSE) { act( AT_TELL, "$n tells you 'You cannot learn any such skill...'", mob, NULL, ch, TO_VICT ); return; } /* * Skill requires a special teacher */ if ( skill_table[sn]->teachers && skill_table[sn]->teachers[0] != '\0' ) { sprintf( buf, "%d", mob->pIndexData->vnum ); if ( !is_name( buf, skill_table[sn]->teachers ) ) { act( AT_TELL, "$n tells you, 'I know not know how to teach that.'", mob, NULL, ch, TO_VICT ); return; } } if ( LEARNED(ch, sn) >= 1 ) { sprintf( buf, "$n tells you, 'I've taught you everything I can about %s.'", skill_table[sn]->name ); act( AT_TELL, buf, mob, NULL, ch, TO_VICT ); } else { ch->pcdata->learned[sn]+= number_range(1, 15); act( AT_ACTION, "You practice $T.", ch, NULL, skill_table[sn]->name, TO_CHAR ); act( AT_ACTION, "$n practices $T.", ch, NULL, skill_table[sn]->name, TO_ROOM ); } } return; } void do_password( CHAR_DATA *ch, char *argument ) { char arg1[MAX_INPUT_LENGTH]; char arg2[MAX_INPUT_LENGTH]; char *pwdnew; char *p; if ( IS_NPC(ch) ) return; argument = one_argument_retain_case(argument, arg1); argument = one_argument_retain_case(argument, arg2); if ( arg1[0] == '\0' || arg2[0] == '\0' ) { send_to_char( "Syntax: password <new> <again>.\n\r", ch ); return; } /* This should stop all the mistyped password problems --Shaddai */ if ( strcmp( arg1, arg2 )) { send_to_char("Passwords don't match try again.\n\r", ch ); return; } if ( strlen(arg2) < 5 ) { send_to_char( "New password must be at least five characters long.\n\r", ch ); return; } /* * No tilde allowed because of player file format. */ pwdnew = crypt( arg2, ch->name ); for ( p = pwdnew; *p != '\0'; p++ ) { if ( *p == '~' ) { send_to_char( "New password not acceptable, try again.\n\r", ch ); return; } } DISPOSE( ch->pcdata->pwd ); ch->pcdata->pwd = str_dup( pwdnew ); if ( IS_SET(sysdata.save_flags, SV_PASSCHG) ) save_char_obj( ch ); send_to_char( "Ok.\n\r", ch ); return; } void do_socials( CHAR_DATA *ch, char *argument ) { int iHash; int col = 0; SOCIALTYPE *social; set_pager_color( AT_PLAIN, ch ); for ( iHash = 0; iHash < 27; iHash++ ) for ( social = social_index[iHash]; social; social = social->next ) { pager_printf( ch, "%-12s", social->name ); if ( ++col % 6 == 0 ) send_to_pager( "\n\r", ch ); } if ( col % 6 != 0 ) send_to_pager( "\n\r", ch ); return; } void do_commands( CHAR_DATA *ch, char *argument ) { int col; bool found; int hash; CMDTYPE *command; col = 0; set_pager_color( AT_PLAIN, ch ); if ( argument[0] == '\0' ) { for ( hash = 0; hash < 126; hash++ ) for ( command = command_hash[hash]; command; command = command->next ) if ( command->permit == 0 ) { pager_printf( ch, "%-12s", command->name ); if ( ++col % 6 == 0 ) send_to_pager( "\n\r", ch ); } if ( col % 6 != 0 ) send_to_pager( "\n\r", ch ); } else { found = FALSE; for ( hash = 0; hash < 126; hash++ ) for ( command = command_hash[hash]; command; command = command->next ) if ( command->permit == 0 && !str_prefix(argument, command->name) ) { pager_printf( ch, "%-12s", command->name ); found = TRUE; if ( ++col % 6 == 0 ) send_to_pager( "\n\r", ch ); } if ( col % 6 != 0 ) send_to_pager( "\n\r", ch ); if ( !found ) ch_printf( ch, "No command found under %s.\n\r", argument); } return; } /* * Contributed by Grodyn. * Display completely overhauled, 2/97 -- Blodkai */ void do_config( CHAR_DATA *ch, char *argument ) { char arg[MAX_INPUT_LENGTH]; if ( IS_NPC(ch) ) return; one_argument( argument, arg ); set_char_color( AT_GREEN, ch ); if ( arg[0] == '\0' ) { set_char_color( AT_DGREEN, ch ); send_to_char( "\n\rConfigurations ", ch ); set_char_color( AT_GREEN, ch ); send_to_char( "(use 'config +/- <keyword>' to toggle, see 'help config')\n\r\n\r", ch ); set_char_color( AT_DGREEN, ch ); send_to_char( "Display: ", ch ); set_char_color( AT_GREY, ch ); ch_printf( ch, "%-12s %-12s %-12s %-12s\n\r %-12s %-12s %-12s %-12s\n\r %-12s %-12s %-12s %-12s", IS_SET( ch->pcdata->flags, PCFLAG_PAGERON ) ? "[+] PAGER" : "[-] pager", IS_SET( ch->pcdata->flags, PCFLAG_GAG ) ? "[+] GAG" : "[-] gag", xIS_SET(ch->act, PLR_BRIEF ) ? "[+] BRIEF" : "[-] brief", xIS_SET(ch->act, PLR_COMBINE ) ? "[+] COMBINE" : "[-] combine", xIS_SET(ch->act, PLR_BLANK ) ? "[+] BLANK" : "[-] blank", xIS_SET(ch->act, PLR_PROMPT ) ? "[+] PROMPT" : "[-] prompt", xIS_SET(ch->act, PLR_ANSI ) ? "[+] ANSI" : "[-] ansi", IS_SET( ch->pcdata->flags, PCFLAG_NOBEEP ) ? "[+] NOBEEP" : "[-] nobeep", IS_SET( ch->pcdata->flags, PCFLAG_ANONYMOUS) ? "[+] ANONYMOUS" : "[-] anonymous", xIS_SET(ch->act, PLR_NOHUNGER ) ? "[+] NOHUNGER" : "[-] nohunger", xIS_SET(ch->act, PLR_OOC ) ? "[+] OOC" : "[-] ooc", xIS_SET(ch->act, PLR_LONG_EXIT ) ? "[+] LONGEXIT" : "[-] longexit"); set_char_color( AT_DGREEN, ch ); send_to_char( "\n\r\n\rAuto: ", ch ); set_char_color( AT_GREY, ch ); ch_printf( ch, "%-12s %-12s %-12s %-12s", xIS_SET(ch->act, PLR_AUTOSEX ) ? "[+] AUTOSEX" : "[-] autosex", xIS_SET(ch->act, PLR_AUTOGOLD ) ? "[+] AUTOGOLD" : "[-] autogold", xIS_SET(ch->act, PLR_AUTOLOOT ) ? "[+] AUTOLOOT" : "[-] autoloot", xIS_SET(ch->act, PLR_AUTOEXIT ) ? "[+] AUTOEXIT" : "[-] autoexit" ); set_char_color( AT_DGREEN, ch ); send_to_char( "\n\r\n\rSafeties: ", ch ); set_char_color( AT_GREY, ch ); ch_printf( ch, "%-12s %-12s ", IS_SET(ch->pcdata->flags, PCFLAG_SPAR ) ? "[+] SPAR" : "[-] spar", xIS_SET(ch->act, PLR_DEFENSE ) ? "[+] DEFENSE" : "[-] defense" ); set_char_color( AT_DGREEN, ch ); send_to_char( "\n\r\n\rMisc: ", ch ); set_char_color( AT_GREY, ch ); ch_printf( ch, "%-12s %-12s", xIS_SET(ch->act, PLR_TELNET_GA ) ? "[+] TELNETGA" : "[-] telnetga", IS_SET( ch->pcdata->flags, PCFLAG_NOINTRO ) ? "[+] NOINTRO" : "[-] nointro" ); set_char_color( AT_DGREEN, ch ); send_to_char( "\n\r\n\rSettings: ", ch ); set_char_color( AT_GREY, ch ); ch_printf_color( ch, "Pager Length (%d)", ch->pcdata->pagerlen ); if ( IS_SET(ch->pcdata->permissions, PERMIT_BUILD) ) { set_char_color( AT_DGREEN, ch ); send_to_char( "\n\r\n\rImmortal toggles: ", ch ); set_char_color( AT_GREY, ch ); ch_printf( ch, "%-12s\n\r ", xIS_SET( ch->act, PLR_ROOMVNUM ) ? "[+] VNUM" : "[-] vnum" ); } set_char_color( AT_DGREEN, ch ); send_to_char( "\n\r\n\rTalent toggles: ", ch ); if ( ch->curr_talent[TAL_ILLUSION] >= 70 ) { set_char_color( AT_GREY, ch ); ch_printf( ch, "%-12s ", IS_SET( ch->pcdata->flags, PCFLAG_MASK ) ? "[+] AURAMASK" : "[-] auramask" ); } if ( ch->curr_talent[TAL_MIND] >= 90 ) { set_char_color( AT_GREY, ch ); ch_printf( ch, "%-12s ", IS_SET( ch->pcdata->flags, PCFLAG_SHIELD ) ? "[+] MINDSHIELD" : "[-] mindshield" ); } ch_printf(ch, "\n\r"); set_char_color( AT_DGREEN, ch ); send_to_char( "\n\r\n\rSentences imposed on you (if any):", ch ); set_char_color( AT_YELLOW, ch ); ch_printf( ch, "\n\r%s%s%s%s%s%s", xIS_SET(ch->act, PLR_SILENCE ) ? " For your abuse of channels, you are currently silenced.\n\r" : "", xIS_SET(ch->act, PLR_NO_EMOTE ) ? " The gods have removed your emotes.\n\r" : "", xIS_SET(ch->act, PLR_NO_TELL ) ? " You are not permitted to send 'tells' to others.\n\r" : "", xIS_SET(ch->act, PLR_LITTERBUG )? " A convicted litterbug. You cannot drop anything.\n\r" : "", xIS_SET(ch->act, PLR_THIEF ) ? " A proven thief, you will be hunted by the authorities.\n\r" : "", xIS_SET(ch->act, PLR_KILLER ) ? " For the crime of murder you are sentenced to death...\n\r" : "" ); } else { bool fSet; int bit = 0; if ( arg[0] == '+' ) fSet = TRUE; else if ( arg[0] == '-' ) fSet = FALSE; else { send_to_char( "Config -option or +option?\n\r", ch ); return; } if ( !str_prefix( arg+1, "autoexit" ) ) bit = PLR_AUTOEXIT; else if ( !str_prefix( arg+1, "autoloot" ) ) bit = PLR_AUTOLOOT; else if ( !str_prefix( arg+1, "autosex") ) bit = PLR_AUTOSEX; else if ( !str_prefix( arg+1, "longexit" ) ) bit = PLR_LONG_EXIT; else if ( !str_prefix( arg+1, "nohunger" ) ) bit = PLR_NOHUNGER; else if ( !str_prefix( arg+1, "defense" ) ) bit = PLR_DEFENSE; else if ( !str_prefix( arg+1, "autogold" ) ) bit = PLR_AUTOGOLD; else if ( !str_prefix( arg+1, "blank" ) ) bit = PLR_BLANK; else if ( !str_prefix( arg+1, "brief" ) ) bit = PLR_BRIEF; else if ( !str_prefix( arg+1, "combine" ) ) bit = PLR_COMBINE; else if ( !str_prefix( arg+1, "prompt" ) ) bit = PLR_PROMPT; else if ( !str_prefix( arg+1, "ooc" ) ) bit = PLR_OOC; else if ( !str_prefix( arg+1, "telnetga" ) ) bit = PLR_TELNET_GA; else if ( !str_prefix( arg+1, "ansi" ) ) bit = PLR_ANSI; else if ( !str_prefix( arg+1, "vnum" ) ) bit = PLR_ROOMVNUM; if (bit) { if ( fSet ) xSET_BIT (ch->act, bit); else xREMOVE_BIT(ch->act, bit); send_to_char( "Ok.\n\r", ch ); return; } else { if ( !str_prefix( arg+1, "norecall" ) ) bit = PCFLAG_NORECALL; else if ( !str_prefix( arg+1, "nointro" ) ) bit = PCFLAG_NOINTRO; else if ( !str_prefix( arg+1, "nosummon" ) ) bit = PCFLAG_NOSUMMON; else if ( !str_prefix( arg+1, "gag" ) ) bit = PCFLAG_GAG; else if ( !str_prefix( arg+1, "pager" ) ) bit = PCFLAG_PAGERON; else if ( !str_prefix( arg+1, "spar" ) ) bit = PCFLAG_SPAR; else if ( !str_prefix( arg+1, "nobeep" ) ) bit = PCFLAG_NOBEEP; else if ( !str_prefix( arg+1, "anonymous" ) ) bit = PCFLAG_ANONYMOUS; else if ( ch->curr_talent[TAL_ILLUSION] >= 70 && !str_prefix( arg+1, "auramask" ) ) bit = PCFLAG_MASK; else if ( ch->curr_talent[TAL_MIND] >= 90 && !str_prefix( arg+1, "mindshield")) bit = PCFLAG_SHIELD; else { send_to_char( "Config which option?\n\r", ch ); return; } if ( fSet ) SET_BIT (ch->pcdata->flags, bit); else REMOVE_BIT (ch->pcdata->flags, bit); send_to_char( "Ok.\n\r", ch ); return; } } return; } void do_credits( CHAR_DATA *ch, char *argument ) { do_new_help( ch, "credits" ); } extern int top_area; /* * New do_areas, written by Fireblade, last modified - 4/27/97 * * Syntax: area -> lists areas in alphanumeric order * area <world> -> lists areas on a given world * area old -> list areas in order loaded * */ void do_areas( CHAR_DATA *ch, char *argument ) { char *header_string1 = "\n\r Author | Area" " | " "World\n\r"; char *header_string2 = "-------------+-----------------" "---------------------+----" "---------+-----------\n\r"; char *print_string = "%-12s | %-36s | %11s | \n\r"; AREA_DATA *pArea; bool fWorld; if(!argument || argument[0] != '\0') { if(!strcmp(argument,"all")) { set_pager_color( AT_PLAIN, ch ); send_to_pager(header_string1, ch); send_to_pager(header_string2, ch); for (pArea = first_area; pArea;pArea = pArea->next) { pager_printf(ch, print_string, pArea->author, pArea->name, pArea->resetmsg); } return; } else { fWorld = TRUE; } } set_pager_color( AT_PLAIN, ch ); send_to_pager(header_string1, ch); send_to_pager(header_string2, ch); for (pArea = first_area_name; pArea; pArea = pArea->next_sort_name) { if (!fWorld || !str_cmp(argument, pArea->resetmsg)) { pager_printf(ch, print_string, pArea->author, pArea->name, pArea->resetmsg); } } return; } void do_afk( CHAR_DATA *ch, char *argument ) { if ( IS_NPC(ch) ) return; if xIS_SET(ch->act, PLR_AFK) { xREMOVE_BIT(ch->act, PLR_AFK); send_to_char( "You are no longer idle.\n\r", ch ); act(AT_GREY,"$n is no longer idle.", ch, NULL, NULL, TO_CANSEE); } else { xSET_BIT(ch->act, PLR_AFK); send_to_char( "You are idling.\n\r", ch ); act(AT_GREY,"$n is idling.", ch, NULL, NULL, TO_CANSEE); return; } } void do_whois( CHAR_DATA *ch, char *argument) { CHAR_DATA *victim; char buf[MAX_STRING_LENGTH]; char buf2[MAX_STRING_LENGTH]; CLAN_DATA *clan; CLAN_MEMBER *chm; DESCRIPTOR_DATA *d; buf[0] = '\0'; if(IS_NPC(ch)) return; if(argument[0] == '\0') { send_to_pager("You must input the name of an online character.\n\r", ch); return; } for (d = first_descriptor;d;d = d->next) { if (!d->character) continue; if (!str_prefix(argument, d->character->name)) break; } if (!d) { send_to_char("No such person is online.\n\r", ch); return; } victim = d->character; set_pager_color( AT_GREY, ch ); pager_printf(ch, "\n\r%s %s\n\r %s is a %s %s %s, %d years of age, with %d hours of playing time.\n\r", victim->name, victim->pcdata->family ? victim->pcdata->family : "", victim->sex == SEX_MALE ? "He" : victim->sex == SEX_FEMALE ? "She" : victim->sex == SEX_HERMAPH ? "Shi" : "It", victim->sex == SEX_MALE ? "male" : victim->sex == SEX_FEMALE ? "female" : victim->sex == SEX_HERMAPH ? "hermaphrodite" : "neuter", victim->pcdata->type ? victim->pcdata->type : "normal", victim->species, victim->pcdata->age_adjust, ((victim->played + (current_time - victim->logon)) / 3600)); if(victim->pcdata->homepage && victim->pcdata->homepage[0] != '\0') pager_printf(ch, " %s homepage can be found at %s\n\r", victim->sex == SEX_MALE ? "His" : victim->sex == SEX_FEMALE ? "Her" : victim->sex == SEX_HERMAPH ? "Hir" : "Its", show_tilde( victim->pcdata->homepage ) ); if (xIS_SET(victim->act, PLR_BOUNTY)) { pager_printf(ch, " %s has a total bounty of %d coins.\r\n", victim->sex == SEX_MALE ? "He" : victim->sex == SEX_FEMALE ? "She" : victim->sex == SEX_HERMAPH ? "Shi" : "It", victim->pcdata->bounty); } pager_printf(ch, "%s has killed %d mobiles, and been killed by a mobile %d times.\n\r", victim->name, victim->pcdata->mkills, victim->pcdata->mdeaths ); if ( victim->pcdata->pkills || victim->pcdata->pdeaths ) pager_printf(ch, "%s has won %d spars, and lost %d.\n\r", victim->name, victim->pcdata->pkills, victim->pcdata->pdeaths ); if ( victim->pcdata->rkills || victim->pcdata->rdeaths ) pager_printf(ch, "%s has killed %d players, and been killed by a player %d times.\n\r", victim->name, victim->pcdata->rkills, victim->pcdata->rdeaths ); for (clan = first_clan;clan;clan = clan->next) { if ((chm = get_member(victim->name, clan)) == NULL) continue; if ((!xIS_SET(chm->flags, CL_SECRET) && clan->ext_sec <= 3) || IS_SET(ch->pcdata->permissions, PERMIT_SECURITY)) pager_printf(ch, "%s&w of %s&w.\n\r", chm->title, clan->title); } if(victim->pcdata->bio && victim->pcdata->bio[0] != '\0') pager_printf(ch, " %s's personal bio:\n\r%s", victim->name, victim->pcdata->bio); else pager_printf(ch, " %s has yet to create a bio.\n\r", victim->name ); pager_printf(ch, "---------\n\r", ch); if (victim->first_abit) { BIT_DATA *bit; for (bit = victim->first_abit; bit; bit = bit->next) { if (strlen(bit->desc) > 3) pager_printf(ch, "%s\r\n", bit->desc); } } if (victim->pcdata->first_qbit) { BIT_DATA *bit; for (bit = victim->pcdata->first_qbit; bit; bit = bit->next) { if (strlen(bit->desc) > 3) pager_printf(ch, "%s\r\n", bit->desc); } } if(IS_SET(ch->pcdata->permissions, PERMIT_CHANNEL)) { send_to_pager("-------------------\n\r", ch); pager_printf(ch, "%s is %shelled at the moment.\n\r", victim->name, (victim->pcdata->release_date == 0) ? "not " : ""); if(victim->pcdata->release_date != 0) pager_printf(ch, "%s was helled by %s, and will be released on %24.24s.\n\r", victim->sex == SEX_MALE ? "He" : victim->sex == SEX_FEMALE ? "She" : "It", victim->pcdata->helled_by, ctime(&victim->pcdata->release_date)); if(xIS_SET(victim->act, PLR_NO_CHANNEL) || xIS_SET(victim->act, PLR_NO_EMOTE) || xIS_SET(victim->act, PLR_NO_TELL) || xIS_SET(victim->act, PLR_THIEF) || xIS_SET(victim->act, PLR_KILLER) ) { sprintf(buf2, "This player has the following flags set:"); if(xIS_SET(victim->act, PLR_NO_CHANNEL)) strcat(buf2, " nochannel"); if(xIS_SET(victim->act, PLR_NO_EMOTE)) strcat(buf2, " noemote"); if(xIS_SET(victim->act, PLR_NO_TELL) ) strcat(buf2, " notell"); if(xIS_SET(victim->act, PLR_THIEF) ) strcat(buf2, " thief"); if(xIS_SET(victim->act, PLR_KILLER) ) strcat(buf2, " killer"); strcat(buf2, ".\n\r"); send_to_pager(buf2, ch); } if ( victim->desc && victim->desc->host[0]!='\0' ) /* added by Gorog */ { sprintf (buf2, "%s's IP info: %s ", victim->name, victim->desc->host); strcat (buf2, victim->desc->user); strcat (buf2, "\n\r"); send_to_pager(buf2, ch); } } } void do_pager( CHAR_DATA *ch, char *argument ) { char arg[MAX_INPUT_LENGTH]; if ( IS_NPC(ch) ) return; set_char_color( AT_NOTE, ch ); argument = one_argument(argument, arg); if ( !*arg ) { if ( IS_SET(ch->pcdata->flags, PCFLAG_PAGERON) ) { send_to_char( "Pager disabled.\n\r", ch ); do_config(ch, "-pager"); } else { ch_printf( ch, "Pager is now enabled at %d lines.\n\r", ch->pcdata->pagerlen ); do_config(ch, "+pager"); } return; } if ( !is_number(arg) ) { send_to_char( "Set page pausing to how many lines?\n\r", ch ); return; } ch->pcdata->pagerlen = atoi(arg); if ( ch->pcdata->pagerlen < 5 ) ch->pcdata->pagerlen = 5; ch_printf( ch, "Page pausing set to %d lines.\n\r", ch->pcdata->pagerlen ); return; } char *get_talent_rank(CHAR_DATA *ch) { int max = 0; int i; if (ch->pcdata->inborn > -1) { if (ch->curr_talent[ch->pcdata->inborn] < 10) return capitalize(ch->species); return talent_rank[ch->pcdata->inborn][(int) (UMIN(ch->curr_talent[ch->pcdata->inborn], 120)-10)/10]; } else { for (i = 0;i < MAX_DEITY;i++) { if (ch->curr_talent[i] >= ch->curr_talent[max]) max = i; } if (ch->curr_talent[max] < 10) return capitalize(ch->species); return talent_rank[max][(int) (UMIN(ch->curr_talent[max], 120)-10)/10]; } } /* RANDOM BOOKS */ #if defined(KEY) #undef KEY #endif #define KEY( literal, field, value ) \ if ( !str_cmp( word, literal ) ) \ { \ field = value; \ fMatch = TRUE; \ break; \ } \ void add_book(BOOK_DATA *book) { BOOK_DATA *temp_book; if (!book && !book->name) return; book->next = NULL; book->prev = NULL; temp_book = NULL; for(temp_book = first_book; temp_book; temp_book = temp_book->next) { if(strcasecmp(book->name, temp_book->name) < 0) { INSERT(book, temp_book, first_book, next, prev); break; } } if (!temp_book) { LINK(book, first_book, last_book, next, prev); } } void delete_book(BOOK_DATA *book) { UNLINK(book, first_book, last_book, next, prev); STRFREE(book->name); STRFREE(book->title); STRFREE(book->text); DISPOSE(book); } void save_books() { FILE *fpout; BOOK_DATA *book; if ( (fpout=fopen( BOOK_FILE, "w" )) == NULL ) { perror( BOOK_FILE ); return; } for (book = first_book;book;book = book->next) { fprintf( fpout, "\n#BOOK\n" ); fprintf( fpout, "Name %s~\n", book->name ); fprintf( fpout, "Title %s~\n", book->title ); fprintf( fpout, "Text %s~\n", book->text ); } fprintf( fpout, "#END\n" ); fclose( fpout ); } void load_books( void ) { FILE *fp; BOOK_DATA *book; char *word; bool done=FALSE; bool fMatch=FALSE; if ((fp=fopen(BOOK_FILE, "r"))==NULL) { bug( "Load_books: no books found!", 0); return; } first_book = NULL; book = NULL; while (!done) { if (feof( fp )) { break; } else { word=fread_word( fp ); } switch(UPPER(word[0])) { case '#': if (!str_cmp("#BOOK", word)) { if (book) add_book(book); CREATE(book, BOOK_DATA, 1); book->title = NULL; book->text = NULL; book->name = NULL; continue; } else if (!str_cmp(word, "#END")) { add_book(book); done=TRUE; continue; } case 'N': KEY( "Name", book->name, fread_string(fp)); break; case 'T': KEY( "Text", book->text, fread_string(fp)); KEY( "Title", book->title, fread_string(fp)); break; default: bug("Unknown book keyword: %s", word); } } fclose(fp); return; } void do_set_book(CHAR_DATA *ch, char *argument) { char buf[MAX_STRING_LENGTH]; char arg1[MAX_INPUT_LENGTH]; char arg2[MAX_INPUT_LENGTH]; BOOK_DATA *book; BOOK_DATA *temp_book; int i, n; bool found; switch( ch->substate ) { default: break; case SUB_HELP_EDIT: if ( (book = ch->dest_buf) == NULL ) { bug( "set_help: sub_help_edit: NULL ch->dest_buf", 0 ); stop_editing( ch ); return; } STRFREE( book->text ); book->text = copy_buffer( ch ); stop_editing( ch ); return; case SUB_OBJ_EXTRA: if ( (book = ch->dest_buf) == NULL ) { bug( "set_help: sub_help_edit: NULL ch->dest_buf", 0 ); stop_editing( ch ); return; } STRFREE( book->title ); book->title = copy_buffer( ch ); stop_editing( ch ); return; } argument = one_argument(argument, arg1); argument = one_argument(argument, arg2); if (!str_cmp(arg1, "add")) { if (str_cmp(arg2, "book")) { send_to_char("Syntax: setbook add book <title>\n\r", ch); return; } if (!argument) { send_to_char("Name the book what?\n\r", ch); return; } CREATE (book, BOOK_DATA, 1); book->name = STRALLOC(argument); add_book(book); i = 0; for (temp_book = first_book;temp_book;temp_book = temp_book->next) { i++; if (temp_book == book) break; } sprintf(buf, "Book %s created - number %d.\n\r", book->name, i); send_to_char(buf, ch); log_string(buf); return; } else if (!str_cmp(arg1, "list")) { if (!first_book) { send_to_char("There are no books.\n\r", ch); return; } i = 0; for (book = first_book;book;book = book->next) { i++; ch_printf(ch, "&C%d&c: %s\n\r", i, book->name); } return; } else if (!str_cmp(arg1, "count")) { if (!first_book) { send_to_char("There are no books.\n\r", ch); return; } i = 0; for (book = first_book;book;book = book->next) i++; ch_printf(ch, "&cThere are &C%d &cbooks.\n\r", i); return; } else if (!str_cmp(arg1, "find")) { found = FALSE; i = 0; for (book = first_book;book;book = book->next) { i++; if (is_name(arg2, book->name) || is_name(argument, book->name)) { ch_printf(ch, "&C%d&c: %s\n\r", i, book->name); found = TRUE; } } if (!found) send_to_char("No matching books found.\n\r", ch); return; } else if (!str_cmp(arg1, "save")) { save_books(); send_to_char("Books saved.\n\r", ch); return; } else if (!str_cmp(arg1, "load")) { load_books(); send_to_char("Books loaded.\n\r", ch); return; } if (arg2 && arg2[0] != '\0') { i = atoi(arg2); n = 0; for (book = first_book;book;book = book->next) { n++; if (n == i) break; } if (!book) { ch_printf(ch, "&cBook &C%d &cnot found.\n\r", i); return; } if (!str_cmp(arg1, "edit")) { ch->substate = SUB_HELP_EDIT; ch->dest_buf = book; start_editing( ch, book->text ); return; } if (!str_cmp(arg1, "show")) { ch_printf(ch, "&C%d: %s\n\r", i, book->name); ch_printf(ch, "&C&c%s", book->title); ch_printf(ch, "&z&W%s\n\r", book->text); return; } if (!str_cmp(arg1, "name")) { UNLINK(book, first_book, last_book, next, prev); STRFREE(book->name); book->name = STRALLOC(argument); add_book(book); i = 0; for (temp_book = first_book;temp_book;temp_book = temp_book->next) { i++; if (temp_book == book) break; } ch_printf(ch, "&cBook name changed to &C%s&c, number is now %d.\n\r", book->name,i); return; } if (!str_cmp(arg1, "title")) { ch->substate = SUB_OBJ_EXTRA; ch->dest_buf = book; start_editing( ch, book->title ); return; } if (!str_cmp(arg1, "delete")) { delete_book(book); ch_printf(ch, "&cBook &C%d &cdeleted.\n\r", i); return; } } send_to_char("\n\rSyntax: setbook <add|edit|delete|text|title> <number>", ch); send_to_char("\n\r setbook <save|list>\n\r", ch); } /* NEW SERRIYAN DREAMS HELP FILE SYSTEM */ /* Compares two strings and returns how many letters match */ int best_match(const char *astr, const char *bstr) { int match, a, b; if (!astr) return 0; if (!bstr) return 0; match = 0; for (a = 0;astr[a] != '\0';a++) { for (b = a;bstr[b] != '\0';b++) { if (astr[a] == bstr[b]) { match++; if (a == b) match++; break; } } } return match; } /* Add a help file to the help hash table */ void add_new_help(NEW_HELP_DATA *help) { int hash, x; NEW_HELP_DATA *tmp; if ( !help ) return; if ( !help->name ) return; for (x = 0; help->name[x] != '\0'; x++) help->name[x] = LOWER(help->name[x]); hash = help->name[0] % 126; if ((tmp = help_hash[hash]) == NULL) { help->next = help_hash[hash]; help_hash[hash] = help; return; } for (; tmp; tmp = tmp->next) if (!tmp->next) { tmp->next = help; help->next = NULL; } top_help++; return; } void free_new_help(NEW_HELP_DATA *help) { STRFREE(help->name); STRFREE(help->text); DISPOSE(help); } void unlink_new_help(NEW_HELP_DATA *help ) { NEW_HELP_DATA *tmp, *tmp_next; int hash; if (!help) return; hash = help->name[0] % 126; if (help == (tmp=help_hash[hash])) { help_hash[hash] = tmp->next; return; } for (;tmp;tmp = tmp_next) { tmp_next = tmp->next; if (help == tmp_next) { tmp->next = tmp_next->next; return; } } top_help--; } void save_new_helps() { FILE *fpout; NEW_HELP_DATA *help; int x; if ( (fpout=fopen( HELP_FILE, "w" )) == NULL ) { perror( HELP_FILE ); return; } for (x = 0; x < 126; x++) { for (help = help_hash[x]; help; help = help->next) { if (!help->name || help->name[0] == '\0') continue; fprintf( fpout, "\n#HELP\n" ); fprintf( fpout, "Name %s~\n", help->name ); fprintf( fpout, "Text %s~\n", help->text ); fprintf( fpout, "End\n\n" ); } } fprintf( fpout, "#END\n" ); fclose( fpout ); } void load_new_helps( void ) { FILE *fp; NEW_HELP_DATA *help; char *word; bool done=FALSE; bool fMatch=FALSE; if ((fp=fopen(HELP_FILE, "r"))==NULL) { bug( "Load_helps: no helps found!", 0); return; } while (!done) { if (feof( fp )) { break; } else { word=fread_word( fp ); } switch(UPPER(word[0])) { case '#': if (!str_cmp("#HELP", word)) { CREATE(help, NEW_HELP_DATA, 1); help->name = NULL; help->text = NULL; continue; } else if (!str_cmp(word, "#END")) { done=TRUE; continue; } case 'E': if (!str_cmp(word, "End")) { if (!help->name) { free_new_help(help); return; } if ( !str_cmp( help->name, "greeting" ) ) help_greeting = help->text; add_new_help(help); } break; case 'N': KEY( "Name", help->name, fread_string(fp)); break; case 'T': KEY( "Text", help->text, fread_string(fp)); break; default: bug("Unknown help keyword: %s", word); } } fclose(fp); return; } void do_set_help(CHAR_DATA *ch, char *argument) { char buf[MAX_STRING_LENGTH]; char arg1[MAX_INPUT_LENGTH]; char arg2[MAX_INPUT_LENGTH]; NEW_HELP_DATA *help; int hash; switch( ch->substate ) { default: break; case SUB_HELP_EDIT: if ( (help = ch->dest_buf) == NULL ) { bug( "set_help: sub_help_edit: NULL ch->dest_buf", 0 ); stop_editing( ch ); return; } if ( help_greeting == help->text ) help_greeting = NULL; STRFREE( help->text ); help->text = copy_buffer( ch ); if ( !help_greeting ) help_greeting = help->text; stop_editing( ch ); return; } argument = one_argument(argument, arg1); argument = one_argument(argument, arg2); if (!str_cmp(arg1, "add")) { if (arg2 && arg2[0] != '\0') { CREATE (help, NEW_HELP_DATA, 1); help->name = STRALLOC(arg2); add_new_help(help); sprintf(buf, "Help for %s created.\n\r", arg2); send_to_char(buf, ch); log_string(buf); return; } } else if (!str_cmp(arg1, "save")) { save_new_helps(); send_to_char("Help files saved.\n\r", ch); return; } else if (!str_cmp(arg1, "load")) { load_new_helps(); send_to_char("Help files loaded.\n\r", ch); return; } else if (!str_cmp(arg1, "convert")) { HELP_DATA *old_help; for (old_help = first_help;old_help;old_help = old_help->next) { CREATE(help, NEW_HELP_DATA, 1); help->name = STRALLOC(old_help->keyword); help->text = STRALLOC(old_help->text); add_new_help(help); } send_to_char("All help files converted successfully.\n\rPlease double-check to make sure everything went properly.", ch); return; } if (arg2 && arg2[0] != '\0') { hash = LOWER(arg2[0]) % 126; for (help = help_hash[hash];help;help = help->next ) if (!str_cmp(arg2, help->name)) break; if (!help) { ch_printf(ch, "&cNo help found for &C%s.\n\r", arg2); return; } if (!str_cmp(arg1, "edit")) { ch->substate = SUB_HELP_EDIT; ch->dest_buf = help; start_editing( ch, help->text ); return; } if (!str_cmp(arg1, "text")) { sprintf(arg2, "%s\n\r", argument); STRFREE(help->text); help->text = STRALLOC(arg2); ch_printf(ch, "&cHelp text for &C%s &cchanged.\n\r", arg2); return; } if (!str_cmp(arg1, "append")) { sprintf(arg2, "%s%s\n\r", help->text, argument); STRFREE(help->text); help->text = STRALLOC(arg2); ch_printf(ch, "&CHelp text for &C%s &cappended.\n\r", help->name); return; } if (!str_cmp(arg1, "delete")) { unlink_new_help(help); free_new_help(help); ch_printf(ch, "&cHelp for &C%s &cdeleted.\n\r", arg2); return; } if (!str_cmp(arg1, "rename")) { if (!argument || argument[0] == '\0') { send_to_char("Rename it to what?\n\r", ch); return; } unlink_new_help(help); STRFREE(help->name); help->name = STRALLOC(argument); add_new_help(help); ch_printf(ch, "&cHelp for &C%s &crenamed to &C%s.\n\r", arg2, argument); return; } } send_to_char("\n\rSyntax: sethelp <add|edit|rename|delete|text|append> <name>", ch); send_to_char("\n\r sethelp save\n\r", ch); } /* Searches for a help file, and displays the best match */ void do_new_help(CHAR_DATA *ch, char *argument) { int hash, match, i; NEW_HELP_DATA *help, *best; if (!argument || argument[0] == '\0') { send_to_char("&cAll help files:&C\n\r", ch); for (hash = 0; hash < 126; hash++) for (help = help_hash[hash];help;help = help->next ) { ch_printf(ch, "%-15s", help->name); if (++i % 5 == 0) send_to_char("\n\r", ch); } send_to_char("\n\r", ch); return; } if (argument[1] == '\0') { ch_printf(ch, "&cHelp files starting with &C%c:\n\r", argument[0]); for (help = help_hash[LOWER(argument[0]) % 126];help;help = help->next ) { ch_printf(ch, "%-15s", help->name); if (++i % 5 == 0) send_to_char("\n\r", ch); } send_to_char("\n\r", ch); return; } if ( !IS_NPC(ch) && !str_cmp( argument, "newbie" ) ) SET_BIT(ch->pcdata->flags, PCFLAG_HELPSTART); hash = LOWER(argument[0]) % 126; match = i = 0; help = best = NULL; for (help = help_hash[hash];help;help = help->next ) { i = best_match(argument, help->name); if (i > match) { match = i; best = help; if (i >= strlen(argument)) ch_printf(ch, "&cPossible match: &C%s&c, with match quality of &C%d.\n\r", help->name, i); } else if (i >= strlen(argument)*1.5) { ch_printf(ch, "&cPossible match: &C%s&c, with match quality of &C%d.\n\r", help->name, i); } } if (!best) { ch_printf(ch, "&cUnable to find help for &C%s.\n\r", argument); return; } ch_printf(ch, "&cBest match: &C%s&c, with match quality of &C%d.\n\r", best->name, match); ch_printf(ch, "&z&W%s\n\r", best->text); } void do_story(CHAR_DATA *ch, char *argument) { do_new_help(ch, "story"); } void do_news(CHAR_DATA *ch, char *argument) { do_new_help(ch, "news_latest"); }