/
Archipelago/
Archipelago/doc/
Archipelago/lib/misc/
Archipelago/lib/plrobjs/
Archipelago/lib/plrobjs/P-T/
Archipelago/lib/world/mob/
Archipelago/lib/world/obj/
Archipelago/lib/world/shp/
Archipelago/lib/world/wld/
Archipelago/lib/world/zon/
Archipelago/slave/
/* ************************************************************************
*   File: act.comm.c                                    Part of CircleMUD *
*  Usage: Player-level communication commands                             *
*                                                                         *
*  All rights reserved.  See license.doc for complete information.        *
*                                                                         *
*  Copyright (C) 1993 by the Trustees of the Johns Hopkins University     *
*  CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991.               *
************************* ********************************************** */
/* Archipelago changes by Alastair J. Neil Copyright (C) 1993, 94, 95, 96 */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "structs.h"
#include "utils.h"
#include "comm.h"
#include "interpreter.h"
#include "handler.h"
#include "db.h"
#include "screen.h"
#include "spells.h"

/* extern variables */
extern struct room_data *world;
extern struct descriptor_data *descriptor_list;
extern struct color_list_type colors[];
extern struct char_data *character_list;
int find_track_length(sh_int src, sh_int target, int max);
bool search_info_keyword(struct char_data *target,int *index,char *keywd1,char *keywd2,int mode);
void perform_tell(struct char_data *ch, struct char_data *vict, char *arg);
ACMD(do_respond)
{
  struct char_data *tch = character_list;

  skip_spaces(&argument);

  if (GET_LAST_TELL(ch) == NOBODY)
    send_to_char("You have no-one to respond to!\r\n", ch);
  else if (!*argument)
    send_to_char("What is your response?\r\n", ch);
  else {
    /*
     * Make sure the person you're replying to is still playing by searching
     * for them.  Note, now last tell is stored as player IDnum instead of
     * a pointer, which is much better because it's safer, plus will still
     * work if someone logs out and back in again.
     */

    while (tch != NULL && GET_IDNUM(tch) != GET_LAST_TELL(ch))
      tch = tch->next;

    if (tch == NULL)
      send_to_char("They are no longer playing.\r\n", ch);
    else
      perform_tell(ch, tch, argument);
  }
}


ACMD(do_say)
{
   int	i;
   char *len;

   for (i = 0; *(argument + i) == ' '; i++)
      ;

   if (ch->equipment[WEAR_MOUTH]){
       send_to_char("you can talk with something in your mouth?\r\n", ch);
       return;
   }   

   
   if (!*(argument + i))
      send_to_char("Yes, but WHAT do you want to say?\r\n", ch);
   else {
       for (len = argument +i; *(len) != '\0'; len++)
	   ;
       len--;
       switch (*len){
       case '?':
	   sprintf(buf, "$n asks '%s'", argument + i);
	   sprintf(buf1, "You ask '%s'\r\n", argument + i);
	   break;
       case '!':
	   sprintf(buf, "$n exclaims '%s'", argument + i);
	   sprintf(buf1, "You exclaim '%s'\r\n", argument + i);
	   break;
       default:
	   sprintf(buf, "$n says '%s'", argument + i);
	   sprintf(buf1, "You say '%s'\r\n", argument + i);
	   break;
       }
       act(buf, FALSE, ch, 0, 0, TO_ROOM);
       if (!PRF_FLAGGED(ch, PRF_NOREPEAT)) {
	   send_to_char(buf1, ch);
       } else
	   send_to_char("Ok.\r\n", ch);
   }
}


ACMD(do_gsay)
{
   int	i;
   struct char_data *k;
   struct follow_type *f;

   for (i = 0; *(argument + i) == ' '; i++)
      ;

   if (!IS_AFFECTED(ch, AFF_GROUP)) {
      send_to_char("But you are not the member of a group!\r\n", ch);
      return;
   }

   if (!*(argument + i))
      send_to_char("Yes, but WHAT do you want to group-say?\r\n", ch);
   else {
      if (ch->master)
	 k = ch->master;
      else
	 k = ch;
      sprintf(buf, "%s group-says '%s'\r\n", GET_NAME(ch), argument + i);
      if (IS_AFFECTED(k, AFF_GROUP) && (k != ch))
	 send_to_char(buf, k);
      for (f = k->followers; f; f = f->next)
	 if (IS_AFFECTED(f->follower, AFF_GROUP) && (f->follower != ch))
	    send_to_char(buf, f->follower);
      if (!PRF_FLAGGED(ch, PRF_NOREPEAT)) {
	 sprintf(buf, "You group-say '%s'\r\n", argument + i);
	 send_to_char(buf, ch);
      } else
	 send_to_char("Ok.\r\n", ch);
   }
}



ACMD(do_tell)
{
   struct char_data *vict;

   half_chop(argument, buf, buf2);

   if (!*buf || !*buf2)
     send_to_char("Who do you wish to tell what??\r\n", ch);
   else if (!(vict = get_char_vis(ch, buf)))
     send_to_char("No-one by that name here..\r\n", ch);
   else if (ch == vict)
     send_to_char("You try to tell yourself something.\r\n", ch);
   else if (IS_MOB(vict))
     send_to_char("No-one by that name here..\r\n", ch);
   else 
     perform_tell(ch, vict, buf2);

}

void perform_tell(struct char_data *ch, struct char_data *vict, char *arg)
{
  if (PRF_FLAGGED(ch, PRF_NOTELL))
    send_to_char("You can't tell other people while you have notell on.\r\n", ch);
  else if (!IS_NPC(vict) && !vict->desc) /* linkless */
    act("$E's linkless at the moment.", FALSE, ch, 0, vict, TO_CHAR);
  else if (PLR_FLAGGED(vict, PLR_WRITING))
    act("$E's writing a message right now, try again later.",
	FALSE, ch, 0, vict, TO_CHAR);
  else if (PLR_FLAGGED(vict, PLR_BUILDING))
    act("$E's making part of the universe right now, try again later.",
	FALSE, ch, 0, vict, TO_CHAR);
  else if ((PRF_FLAGGED(vict, PRF_NOTELL)))
    act("$E refuses to hear you.", FALSE, ch, 0, vict, TO_CHAR);
  else if (!AWAKE(vict) && GET_MOVE(vict) > 0)
    act("$E can't hear you, $E's sleeping.", FALSE, ch, 0, vict, TO_CHAR);
  else if (!AWAKE(vict) && GET_MOVE(vict) < 0)
    act("$E can't hear you, $E's in an exhausted slumber.", FALSE, ch, 0, vict, TO_CHAR);
  else {
    sprintf(buf, "%s tells you '%s'%s\r\n", GET_NAME(ch), arg,
	    CCNRM(vict, C_NRM));
    CAP(buf);
    send_to_char(CCRED(vict, C_NRM), vict);
    send_to_char(buf, vict);
    if (!PRF_FLAGGED(ch, PRF_NOREPEAT)) {
      sprintf(buf, "%sYou tell %s '%s'%s\r\n", CCRED(ch, C_CMP),
	      GET_NAME(vict), arg, CCNRM(ch, C_CMP));
      send_to_char(buf, ch);
    } else
      send_to_char("Ok.\r\n", ch);
    vict->specials2.last_tell_id = GET_IDNUM(ch);
  }
}


ACMD(do_whisper)
{
   struct char_data *vict;

   half_chop(argument, buf, buf2);

   if (!*buf || !*buf2)
      send_to_char("Who do you want to whisper to.. and what??\r\n", ch);
   else if (!(vict = get_char_room_vis(ch, buf)))
      send_to_char("No-one by that name here..\r\n", ch);
   else if (vict == ch) {
      act("$n whispers quietly to $mself.", FALSE, ch, 0, 0, TO_ROOM);
      send_to_char("You can't seem to get your mouth close enough to your ear...\r\n", ch);
   } else {
      if (!(vict = get_char_room_vis(ch, buf)))
          send_to_char("No-one by that name here..\r\n", ch);
      
      else {
          sprintf(buf, "$n whispers to you, '%s'", buf2);
          act(buf, FALSE, ch, 0, vict, TO_VICT);
          sprintf(buf, "You whisper '%s' in $N's ear.", buf2);
          act(buf, FALSE, ch, 0, vict, TO_CHAR);      
          act("$N whispers something to $n.", FALSE, vict, 0, ch, TO_NOTVICT);
      }
   }
}


ACMD(do_ask)
{
   struct char_data *vict;

   half_chop(argument, buf, buf2);

   if (ch->equipment[WEAR_MOUTH]){
       send_to_char("you can talk with something in your mouth?\r\n", ch);
       return;
   }   

   if (!*buf2){
       act("Ok ask sure, but ask about what?",FALSE,ch,0,0,TO_CHAR);
       return;}
   if (!(vict = get_char_room_vis(ch, buf)))
      send_to_char("No-one by that name here..\r\n", ch);
   else if (vict == ch) {
      act("$n quietly asks $mself a question.", FALSE, ch, 0, 0, TO_ROOM);
      send_to_char("You think about it for a while...\r\n", ch);
   }
   else {
     if (!(vict = get_char_room_vis(ch, buf)))
       send_to_char("How do you expect an answer when you aren't in the room?\r\n", ch);
     else { 
       sprintf(buf, "$n asks you '%s'", buf2);
       act(buf, FALSE, ch, 0, vict, TO_VICT);
       send_to_char("Ok.\r\n", ch);
       act("$n asks $N a question.", FALSE, ch, 0, vict, TO_NOTVICT);
     }
   }
}


#define MAX_NOTE_LENGTH 1000      /* arbitrary */

ACMD(do_write)
{
   struct obj_data *paper = 0, *pen = 0;
   char	*papername, *penname;

   papername = buf1;
   penname = buf2;

   argument_interpreter(argument, papername, penname);

   if (!ch->desc)
      return;

   if (!*papername)  /* nothing was delivered */ {
      send_to_char("Write?  With what?  ON what?  What are you trying to do?!?\r\n", ch);
      return;
   }
   if (*penname) /* there were two arguments */ {
      if (!(paper = get_obj_in_list_vis(ch, papername, ch->inventory))) {
	 sprintf(buf, "You have no %s.\r\n", papername);
	 send_to_char(buf, ch);
	 return;
      }
      if (!(pen = get_obj_in_list_vis(ch, penname, ch->inventory))) {
	 sprintf(buf, "You have no %s.\r\n", papername);
	 send_to_char(buf, ch);
	 return;
      }
   } else /* there was one arg.let's see what we can find */	 {
      if (!(paper = get_obj_in_list_vis(ch, papername, ch->inventory))) {
	 sprintf(buf, "There is no %s in your inventory.\r\n", papername);
	 send_to_char(buf, ch);
	 return;
      }
      if (paper->obj_flags.type_flag == ITEM_PEN)  /* oops, a pen.. */ {
	 pen = paper;
	 paper = 0;
      } else if (paper->obj_flags.type_flag != ITEM_NOTE) {
	 send_to_char("That thing has nothing to do with writing.\r\n", ch);
	 return;
      }

      /* one object was found. Now for the other one. */
      if (!ch->equipment[HOLD]) {
	 sprintf(buf, "You can't write with a %s alone.\r\n", papername);
	 send_to_char(buf, ch);
	 return;
      }
      if (!CAN_SEE_OBJ(ch, ch->equipment[HOLD])) {
	 send_to_char("The stuff in your hand is invisible!  Yeech!!\r\n", ch);
	 return;
      }

      if (pen)
	 paper = ch->equipment[HOLD];
      else
	 pen = ch->equipment[HOLD];
   }

   /* ok.. now let's see what kind of stuff we've found */
   if (pen->obj_flags.type_flag != ITEM_PEN) {
      act("$p is no good for writing with.", FALSE, ch, pen, 0, TO_CHAR);
   } else if (paper->obj_flags.type_flag != ITEM_NOTE) {
      act("You can't write on $p.", FALSE, ch, paper, 0, TO_CHAR);
   } else if (paper->action_description)
      send_to_char("There's something written on it already.\r\n", ch);
   else {
      /* we can write - hooray! */
      send_to_char("Ok.. go ahead and write.. end the note with a @.\r\n", ch);
      act("$n begins to jot down a note.", TRUE, ch, 0, 0, TO_ROOM);
      ch->desc->str = &paper->action_description;
      ch->desc->max_str = MAX_NOTE_LENGTH;
      act("$n finishes jottting down a note.", TRUE, ch, 0, 0, TO_ROOM);
   }
}



ACMD(do_page)
{
   struct descriptor_data *d;
   struct char_data *vict;

   if (IS_NPC(ch)) {
      send_to_char("Monsters can't page.. go away.\r\n", ch);
      return;
   }

   if (!*argument) {
      send_to_char("Whom do you wish to page?\r\n", ch);
      return;
   }
   half_chop(argument, buf, buf2);
   if (!str_cmp(buf, "all")) {
      if (GET_LEVEL(ch) > LEVEL_GOD) {
	 sprintf(buf, "\007\007*%s* %s\r\n", GET_NAME(ch), buf2);
	 for (d = descriptor_list; d; d = d->next)
	    if (!d->connected)
	       SEND_TO_Q(buf, d);
      } else
	 send_to_char("You will never be godly enough to do that!\r\n", ch);
      return;
   }

   if ((vict = get_char_vis(ch, buf))) {
      sprintf(buf, "\007\007*%s* %s\r\n", GET_NAME(ch), buf2);
      send_to_char(buf, vict);
      if (PRF_FLAGGED(ch, PRF_NOREPEAT))
	 send_to_char("Ok.\r\n", ch);
      else
	 send_to_char(buf, ch);
      return;
   } else
      send_to_char("There is no such person in the game!\r\n", ch);
}


/**********************************************************************
 * generalized communication func, originally by Fred C. Merkel (Torg) *
  *********************************************************************/

ACMD(do_gen_com)
{
   extern int	level_can_shout;
   extern int	holler_move_cost;
   struct descriptor_data *i;
   char	buf3[MAX_STRING_LENGTH];
   char	buf4[MAX_STRING_LENGTH];
   char	buf5[MAX_STRING_LENGTH];
   char	buf6[MAX_STRING_LENGTH];   
   char	name[MAX_NAME_LENGTH+10];
   int col, dist;

   static int	channels[] = {
      0,
      PRF_DEAF,
      PRF_NOGOSS,
      PRF_NOAUCT,
      PRF_NOGRATZ,
      PRF_NOBRAG
   };

   static char	*com_msgs[][4] =  {
      { "You cannot yell!!\r\n",
      "yell",
      "",
      "\7" },
      { "You cannot shout!!\r\n",
      "shout",
      "Turn off your noshout flag first!\r\n",
      "\6" },
      { "You cannot gossip!!\r\n",
      "gossip", 
      "You aren't even on the channel!\r\n",
      "\3" },
      { "You cannot auction!!\r\n", 
      "auction",
      "You aren't even on the channel!\r\n",
      "\3" },
      { "You cannot congratulate!\r\n",
      "congratulate",
      "You aren't even on the channel!\r\n",
      "\5" },
      { "You cannot brag!\r\n",
      "brag",
      "You aren't even on the channel!\r\n",
      "\1" }
   };  


 /*  if (!ch->desc)
      return;
*/
   if (ch->equipment[WEAR_MOUTH]){
       send_to_char("You can talk with something in your mouth?\r\n", ch);
       return;
   }   

   
   if (PLR_FLAGGED(ch, PLR_NOSHOUT)) {
      send_to_char(com_msgs[subcmd][0], ch);
      return;
   }
   if (GET_LEVEL(ch) < level_can_shout) {
      sprintf(buf1, "You must be at least level %d before you can %s.\r\n",
          level_can_shout, com_msgs[subcmd][1]);
      send_to_char(buf1, ch);
      return;
   }

   if (subcmd == SCMD_HOLLER) {
      if (GET_MOVE(ch) < holler_move_cost) {
	 send_to_char("You're too exhausted to yell.\r\n", ch);
	 return;
      } else
	 GET_MOVE(ch) -= holler_move_cost;
   }


   if (PRF_FLAGGED(ch, channels[subcmd])) {
      send_to_char(com_msgs[subcmd][2], ch);
      return;
   }

   for (; *argument == ' '; argument++)
      ;
   if (!(*argument)) {
      sprintf(buf1, "Yes, %s, fine, %s we must, but WHAT???\r\n",
          com_msgs[subcmd][1], com_msgs[subcmd][1]);
      send_to_char(buf1, ch);
      return;
   }

/*   strcpy(colon, com_msgs[subcmd][3]); */
   col =  *com_msgs[subcmd][3];
   if (PRF_FLAGGED(ch, PRF_NOREPEAT))
      send_to_char("Ok.\r\n", ch);
   else {
      if (COLOR_LEV(ch) >= C_CMP)
         sprintf(buf1, "%sYou %s,%s '%s'%s\r\n", colors[col].high, com_msgs[subcmd][1],colors[col].high,
	     argument, KNRM);
      else
	 sprintf(buf1, "You %s, '%s'\r\n", com_msgs[subcmd][1], argument);
      send_to_char(buf1, ch);
   }

   strcpy(name, GET_NAME(ch));
   *name = UPPER(*name);

   sprintf(buf1, "%s %ss, '%s'\r\n", name, com_msgs[subcmd][1], argument);
   sprintf(buf2, "Someone %ss, '%s'\r\n", com_msgs[subcmd][1], argument);
   sprintf(buf3, "%s%s %ss,%s '%s'%s\r\n", colors[col].high, name,com_msgs[subcmd][1],colors[col].low , argument,
       KNRM);
   sprintf(buf4, "%sSomeone %ss,%s '%s'%s\r\n",colors[col].high, com_msgs[subcmd][1],colors[col].low, argument, KNRM);


   for (i = descriptor_list; i; i = i->next) {
       if (!i->connected && i != ch->desc && 
	   !PRF_FLAGGED(i->character, channels[subcmd]) && 
	   !PLR_FLAGGED(i->character, PLR_WRITING) &&
	   !PLR_FLAGGED(i->character, PLR_BUILDING)) {
	   
	 if (subcmd == SCMD_SHOUT && 
	     (world[ch->in_room].zone != world[i->character->in_room].zone))
	   continue;
	 if (subcmd == SCMD_SHOUT) {
	   dist = find_track_length(ch->in_room, i->character->in_room, 10);
	   if (dist >= 10 || dist < 0)
	       continue;
	   else if (dist > 7 && dist < 10) {
	     sprintf(buf1, "You hear someone shouting in the distance.\r\n");
	     sprintf(buf2, "You hear someone shouting in the distance.\r\n");
	     sprintf(buf3, "%sYou hear someone shouting in the distance. %s\r\n", colors[col].high, KNRM);
	     sprintf(buf4, "%sYou hear someone shouting in the distance. %s\r\n", colors[col].high, KNRM);	     
	   }
	   else if ((dist >=  4) && (dist <= 7)) {
	     if (!strncmp(name,"A ",2) || !strncmp(name,"The ",4))
	       *name = LOWER(*name);
	     sprintf(buf1, "You hear %s %sing in the distance.\r\n", name, com_msgs[subcmd][1]);
	     sprintf(buf2, "You hear someone %sing in the distance.\r\n", com_msgs[subcmd][1]);
	     sprintf(buf3, "%sYou hear %s %sing in the distance.%s\r\n", colors[col].high, name,com_msgs[subcmd][1], KNRM);
	     sprintf(buf4, "%sYou hear someone %sing in the distance.%s\r\n", colors[col].high, com_msgs[subcmd][1], KNRM);
	   }
	 }
	 if (subcmd != SCMD_GOSSIP
	     && (GET_POS(i->character) < POSITION_RESTING))
	   continue;

	 if (CAN_SEE(i->character, ch)) {
	   if (COLOR_LEV(i->character) >= C_NRM)
	     send_to_char(buf3, i->character);
	   else
	     send_to_char(buf1, i->character);
	 }
	 else {
	   if (COLOR_LEV(i->character) >= C_NRM)
	     if (GET_LEVEL(ch) > LEVEL_BUILDER)
	       send_to_char(buf4, i->character);
	     else{
	       sprintf(buf4, "%sSomebody %ss,%s '%s'%s\r\n",colors[col].high, com_msgs[subcmd][1],colors[col].low, argument, KNRM);
	       send_to_char(buf4, i->character);
	     }
	   else
	     if (GET_LEVEL(ch) > LEVEL_BUILDER)
	       send_to_char(buf2, i->character);
	     else{
	       sprintf(buf2, "Somebody %ss, '%s'\r\n", com_msgs[subcmd][1], argument);
	       send_to_char(buf2, i->character);
	     }
	 }
       }
   }
}


ACMD(do_qsay)
{
   struct descriptor_data *i;

   if (!PRF_FLAGGED(ch, PRF_QUEST)) {
      send_to_char("You aren't even part of the quest!\r\n", ch);
      return;
   }

   for (; *argument == ' '; argument++)
      ;
   if (!(*argument))
      send_to_char("Quest-say?  Yes!  Fine!  Quest-say we must, but WHAT??\r\n", ch);
   else {
      if (PRF_FLAGGED(ch, PRF_NOREPEAT))
	 send_to_char("Ok.\r\n", ch);
      else {
	 sprintf(buf1, "You quest-say, '%s'\r\n", argument);
	 send_to_char(buf1, ch);
      }

      sprintf(buf1, "$n quest-says, '%s'", argument);
      for (i = descriptor_list; i; i = i->next)
	 if (!i->connected && i != ch->desc && 
	     PRF_FLAGGED(i->character, PRF_QUEST) && 
	     !PLR_FLAGGED(i->character, PLR_WRITING))
	    act(buf1, 0, ch, 0, i->character, TO_VICT);
   }
}