pdirt/data/
pdirt/data/HELP/
pdirt/data/HELP/0/
pdirt/data/HELP/F/
pdirt/data/HELP/G/
pdirt/data/HELP/H/
pdirt/data/HELP/J/
pdirt/data/HELP/K/
pdirt/data/HELP/O/
pdirt/data/HELP/Q/
pdirt/data/HELP/R/
pdirt/data/HELP/U/
pdirt/data/HELP/V/
pdirt/data/HELP/Y/
pdirt/data/HELP/Z/
pdirt/data/MESSAGES/
pdirt/data/POWERINFO/
pdirt/data/WIZ_ZONES/
pdirt/drv/
pdirt/drv/bin/
pdirt/drv/compiler/converter/
pdirt/drv/compiler/libs/
pdirt/drv/compiler/scripts/
pdirt/drv/include/AberChat/
pdirt/drv/include/InterMud/
pdirt/drv/include/machine/
pdirt/drv/src/InterMud/
pdirt/drv/src/Players/
pdirt/drv/utils/UAFPort/
pdirt/drv/utils/dnsresolv/
pdirt/drv/utils/gdbm/
/*****************************************************************************
 ** Project    : pDirt
 ** Module     : party.c
 ** Author     : Peter Eussen (Marty)
 ** Description: A grouping system for dirt based MUDS, with points sharing.
 ** Version    : 1.03
 ** Date       : September 1996
 **
 ** Additions  :
 ** [Marty/10 March/V1.03]
 **   Added premove command.
 ** [Marty/30 Juli/V1.02]
 **   Added fixes and suggestions donated by the Dyrt crew.
 ** [Marty/24 Juli/V1.01]
 **   Fixed a bug in partyname, which would crash the MUD.   
 ** [Marty/V1.00]
 **   Initial release.
 ****************************************************************************/
#define PARTY_C

/****************************************************************************
 ** IMPORT
 ****************************************************************************/
#include "kernel.h"
#include "bprintf.h"
#include "sendsys.h"
#include "parse.h"
#include "log.h"
#include "sflags.h"
#include "communicate.h"
#include "rooms.h"
#include "mobile.h"
#include <stdlib.h>

/****************************************************************************
 ** PROTOTYPES
 ****************************************************************************/
PUBLIC  A_COMMAND(pstatus);       /* Party Status, strength score etc etc */
PUBLIC  A_COMMAND(pcreate);       /* Create a new party object            */
PUBLIC  A_COMMAND(pleave);        /* Leave a party                        */
PUBLIC  A_COMMAND(padd);          /* Add a member to the party            */
PUBLIC  A_COMMAND(pfollow);       /* Hmmm... okay follow leader           */
PUBLIC  A_COMMAND(pshare);        /* Set shares for a player              */
PUBLIC  A_COMMAND(pleader);       /* Set a new leader, and send messages  */
PUBLIC  A_COMMAND(partyname);     /* Set the name of a party              */
PUBLIC  A_COMMAND(premoved);      /* Remove a player from the party group */
PUBLIC  char *whopartytst();      /* test function for use in who         */
PUBLIC  A_COMMAND(psay);          /* Chat line for party members          */
PUBLIC  void partyannounce(char *text);  /* A messaging system for a party*/

PRIVATE char partybuff[MAX_COM_LEN];  /* Common used buffer */


PUBLIC A_COMMAND(partiescom)
{   int plx,i;
    Boolean had_header = False;
    Boolean had_sub = False;

    for (plx = 0; plx < max_players; plx++)
    {
       if (IN_GROUP(plx))
       {   if (P_GROUP_LEADER(plx) == plx)
           {  
               if (had_sub) 
               {  bprintf("&+w     +------------------------------------------------------------------------\n\n");
                  had_sub = False;
               }
               if (!had_header)
               {  bprintf("&+wParty Name            Shares  Total XP\n&+w%s\n",DOUBLELINE);
                  had_header = True;
               }
               bprintf("&+w%-20.20s    %.3d    %-6ld\n",P_GROUP_NAME(plx)[0] == '\0' ?
                       "Unnamed Group" : P_GROUP_NAME(plx),
                       P_GROUP_SHARES(plx),P_GROUP_XP(plx));
               for (i=0; i < max_players; i++)
               {   if (IN_GROUP(i))
                   {   if (P_GROUP(i) == P_GROUP(plx))
                       {    if (!had_sub)
                            {  bprintf("     &+w+-&+w[&+wName&+w]&+w------------&+w[&+wStr&+w]&+w---&+w[&+wDam&+w]&+w-&+w[&+wArm&+w]&+w---&+w[&+wS&+w]&+w-&+w[&+wLocation&+w]&+w-----------------\n");
                               had_sub = True;
                            }
 
                            bprintf("     &+w| &+w%-14.14s   &+w%.3d&+w/&+w%.3d    &+w%.2d    &+w%.2d     %s  %-25.25s\n",
			       pname(i),pstr(i),pmaxstrength(plev(i)),player_damage(i),player_armor(i),
                               (P_GROUP_LEADER(i) == i) ? "&+wL&*" : " ",
                               sdesc(ploc(i)));
                       }
                   }
               }
           }
       }
    }

    if (!had_header)
        bprintf("No groups yet.\n");
    else
       bprintf("&+w%s\n",DOUBLELINE);
}

/*****************************************************************************
 ** PCREATE
 ** Creates a new party and make the creator the leader. 
 ** To create a party it mallocs a piece of mem to put some global definitions
 ** like total amount of shares and name etc. It then sets the leader and a
 ** starting amount of shares.
 ****************************************************************************/
PUBLIC A_COMMAND(pcreate)
{  if (IN_GROUP(mynum))
      bprintf("Leave the other group first.\n");
   else if (plev(mynum) >= LVL_APPREN)
      bprintf("You can no longer take part in parties.\n");
   else
   {  cur_player->party = NEW(PARTY,sizeof(PARTY));  /* Allocate memory */
      if (cur_player->party == NULL)
      {  mudlog("ERROR: couldn't allocate memory for a Party Object");
         bprintf("An internal error occured, party's are not functioning atm. Sorry ;)");
         return;
      }
      cur_player->party->leader = mynum;             /* Set leader            */
      cur_player->share = plev(mynum);               /* Set shares for player */
      cur_player->party->shares = plev(mynum);       /* Set total shares      */
      cur_player->party->name[0] = '\0';             /* Default name is no name */
      cur_player->party->xp = 0;                     /* Total xp given        */
      bprintf("New party created.\n");
   }
}

/***************************************************************************
 ** PSTATUS
 ** Show the party status: party name, party shares, party xp,
 **       name of player,  strength,  shares for player, status
 ** IF the player is in a party off course ;)
 ***************************************************************************/
PUBLIC A_COMMAND(pstatus)
{  int plx,leader;

   if (!IN_GROUP(mynum))         /* We always need this to prevent a */
   {  erreval();                 /* crash caused by assigning values */
      return;                    /* to a NULL pointer                */
   } else
   {  leader = P_GROUP_LEADER(mynum);
      bprintf("&+w%s&*\n"
              "&+wParty name     : &+w%s&*\n",
              DOUBLELINE,
              (P_GROUP_NAME(mynum)[0] != '\0') ? P_GROUP_NAME(mynum) : "None");
      bprintf("&+wParty shares   : &+w%d&*\n"
              "&+wTotal xp gained: &+w%d&*\n",P_GROUP_SHARES(mynum),
              P_GROUP_XP(mynum));
      
      bprintf("&+w==&+w[Name]&+w===========&+w[Strength]&+w==&+w[Shares]&+w==&+w[Score]&+w=&+w[S]&+w=&+w[Location]&+w===============&*\n");
      for (plx = 0; plx < max_players; plx++)
      {  
         if (is_in_game(plx) && IN_GROUP(plx))
         {  if (P_GROUP(plx) == P_GROUP(mynum))
            {   bprintf("%-16s   &+w[&+w%.3d&+w/&+w%.3d&+w]     &+w%.2d       &+w%-6d  &+w%s  &+w%-30.30s\n",
                    pname(plx),pstr(plx),pmaxstrength(plev(plx)), P_SHARE(plx), pscore(plx),
                    (plx == leader) ? "L" : ((players[plx].i_follow == leader) ? "F" : " "),
                    sdesc(ploc(plx)) );
            }
         }
      }
      bprintf("&+w%s\n",DOUBLELINE);
   }
}

/* Small functions used to remove and add players */
PUBLIC void leaveplayer(int plx)
{   P_GROUP_SHARES(plx) -= P_SHARE(plx);
    P_SHARE(plx) = 0;
    if (players[plx].i_follow == P_GROUP_LEADER(plx))
    {   sendf(plx,"You stop following %s.\n",pname(P_GROUP_LEADER(plx)));
        players[plx].i_follow = -1;
    }
    P_GROUP(plx) = NULL;
}

PRIVATE void addplayer(int plx, PARTY *p)
{  P_GROUP(plx) = p;
   P_SHARE(plx) = plev(plx);
   P_GROUP_SHARES(plx) += plev(plx);
}   

/*****************************************************************************
 ** PLEAVE
 ** Let a player leave the group
 *****************************************************************************/
PUBLIC A_COMMAND(pleave)
{  int plx;

   if (!IN_GROUP(mynum))
   {  erreval();
      return;
   }
   else
   {  if (P_GROUP_LEADER(mynum) == mynum)      /* Player is the leader so */
      {                                        /* Drop the whole group.   */
         
         sprintf(partybuff,"Party is disbanned");
         partyannounce(partybuff);
         for (plx =0 ; plx < max_players; plx++)
         {  if (is_in_game(plx) && (P_GROUP(plx) == P_GROUP(mynum)) &&
                plx != mynum)
            {  leaveplayer(plx);
            }
         }  /* Now only the leader is in the group */
         P_GROUP_SHARES(mynum) -= P_SHARE(mynum);
         P_SHARE(mynum) = 0;
         free(P_GROUP(mynum));       /* Loose allocated mem */
         P_GROUP(mynum) = NULL;
      }
      else
      {  /* Lose one player, not the party, We dont have to check if the
            Player is the last player, because the last player is always
            the leader, which is handled in the bit of code above */
         sprintf(partybuff,"%s has left the party",pname(mynum));
         partyannounce(partybuff);
         leaveplayer(mynum);
      }
   }
}

/*****************************************************************************
 ** PREMOVE
 ** Allows the leader to remove players who aren't cooperating with the party.
 ****************************************************************************/
A_COMMAND(premove)
{   if (!P_GROUP(mynum))
    {   erreval();
        return;
    }
    if (P_GROUP_LEADER(mynum) != mynum)
    {   bprintf("Only a leader can remove players.\n");
        return;
    }

    if (brkword() == -1)
    {   bprintf("Remove who?\n");
        return;
    }

    if (pl1 < 0 || pl1 >= max_players)
    {  bprintf("I can't find a player named %s.\n",item1);
       return;
    }

    if (P_GROUP(pl1) != P_GROUP(mynum))
    {   bprintf("%s isn't a member of your party.\n",pname(pl1));
        return;
    }

    sendf(pl1,"&+wYou have been removed from the party&*\n");
    leaveplayer(pl1);
    sprintf(partybuff,"%s has been removed from the party.",pname(pl1));
    partyannounce(partybuff);
}

/****************************************************************************
 ** PADD
 ** Add a player to the party..
 ****************************************************************************/
PUBLIC A_COMMAND(padd)
{  int plx;

   if (!IN_GROUP(mynum))                /* Standard check */
   {  erreval();
      return;
   }
   if (brkword() == -1)                 /* Get the name */
   {  bprintf("Add who?\n");
      return;
   }
   if (P_GROUP_LEADER(mynum) != mynum)  /* Check if player is leader */
   {  bprintf("Only the leader can add players.\n");
      return;
   }
   plx = pl1;
   if (plx >= max_players)             /* Check if new player is mobile */
   {  bprintf("You can't add mobiles to the group\n");
      return;
   }
   if (plx < 0)
   {  bprintf("Who's that?\n");
      return;
   }

   if (plev(plx) >= LVL_APPREN)
   {  bprintf("Sorry... immortals can not join  parties\n");
      return;
   }
   if (ploc(plx) != ploc(mynum))        /* Check if the player is in the same room */
   {  bprintf("%s isn't here.\n",pname(plx));
      return;
   }
   if (players[plx].i_follow != mynum)  /* Player should follow the leader */
   {  bprintf("%s is not following you.\n",pname(plx));
      return;
   }
   if (!IN_GROUP(plx) && is_in_game(plx))
   {  addplayer(plx, P_GROUP(mynum));
      sprintf(partybuff,"%s has joined the party",pname(plx));
      partyannounce(partybuff);
   } 
   else
   {  bprintf("Sorry I can't add %s\n",pname(plx));
   }
}

/***************************************************************************
 ** PARTYNAME
 ** Change the name of the party, shows up in status and who list (later)
 ***************************************************************************/
PUBLIC A_COMMAND(partyname)
{  int len;
   if (!IN_GROUP(mynum))
   {  erreval();
      return;
   }
   getreinput(wordbuf);
   if ((len = strlen(wordbuf)) <= 0 || len > ONAME_LEN)
   {  bprintf("Set the name to what?\n");
   } 
   else
   {   strcpy(cur_player->party->name,wordbuf);
       sprintf(partybuff,"New name is: '%s'",wordbuf);
       partyannounce(partybuff);
   }
}

/*************************************************************************
 ** PFOLLOW
 ** Follow the leader unless you are the leader ;). It makes use of the
 ** standard follow routine, but it should work pretty well.
 *************************************************************************/
PUBLIC A_COMMAND(pfollow)
{  if (!IN_GROUP(mynum))
   {  erreval();
      return;
   } 
   if (P_GROUP_LEADER(mynum) == mynum)
   {  bprintf("You are the leader, you lead the way.\n");
      return;
   }
   else if (cur_player->i_follow != P_GROUP_LEADER(mynum))
   {  bprintf("You now follow your leader %s\n",pname(P_GROUP_LEADER(mynum)));
      cur_player->i_follow = P_GROUP_LEADER(mynum);
      sendf(P_GROUP_LEADER(mynum),"%s starts following you.\n",pname(mynum));
      return;
   } 
   else
   {  bprintf("You stop following %s\n",pname(cur_player->i_follow));
      sendf(P_GROUP_LEADER(mynum),"%s stops following you.\n",pname(mynum));
      cur_player->i_follow = -1;
      return;
   }
}

/****************************************************************************
 ** PSHARE
 ** Set the amount of shares for the player. The amount of shares has a 
 ** boundry relative to the level of the player. Of course this can be 
 ** changed to suit your personal taste
 ****************************************************************************/
PUBLIC A_COMMAND(pshare)
{  int plx= -1, newsh;
   int dif;

   if (!IN_GROUP(mynum))
   {  erreval();
      return;
   }
   if (P_GROUP_LEADER(mynum) != mynum)
   {  bprintf("Only the leader can change the shares.\n");
      return;
   } 
   if (brkword() == -1)
   {  bprintf("Change shares on who?\n");
      return;
   }
   plx = pl1; 
   if (!IN_GROUP(plx))
   {  bprintf("%s isn't in your group\n",pname(plx));
      return;
   } else
   if (P_GROUP(plx) != P_GROUP(mynum))
   {  bprintf("%s isn't in your group\n",item1);
      return;
   }
   if (brkword() == -1)
   {  bprintf("Set shares to what?\n");
      return;
   }
   newsh = atoi(item2);
   if (newsh <= 0 || (newsh < (plev(plx) - 10) || newsh > (plev(plx) + 10)) )
   {  bprintf("%s shares must be between %d and %d\n",pname(plx),
             (plev(plx) - 5) < 1 ? 1 : (plev(plx) -10), plev(plx) + 10);
      return;
   } 
   dif = newsh - P_SHARE(plx);
   P_SHARE(plx) += dif;
   P_GROUP_SHARES(plx) += dif;
   
   sprintf(partybuff,"%s now owns %d shares",pname(plx),newsh);
   partyannounce(partybuff);
}

/****************************************************************************
 ** PLEADER
 ** Change the leader of the party
 ****************************************************************************/
PUBLIC A_COMMAND(pleader)
{  int plx, oldleader;

   if (!IN_GROUP(mynum))
   {  erreval();
      return;
   }
   if (P_GROUP_LEADER(mynum) != mynum)
   {  bprintf("Only the leader can change the leader.\n");
      return;
   }
   if (brkword() == -1)
   {  bprintf("Make who leader?\n");
      return;
   }
   if (pl1 < 0 || pl1 >max_players)
   {  bprintf("I don't know anyone with that name.\n");
      return;
   }
   if (!IN_GROUP(pl1))
   {  bprintf("%s is not in a group, add %s first.\n",pname(pl1),him_or_her(pl1));
      return;
   }
   if (P_GROUP(pl1) != P_GROUP(mynum))
   {  bprintf("%s is not in your group\n",pname(pl1));
      return;
   }
      
   oldleader = mynum;
   P_GROUP_LEADER(mynum) =  pl1;
   bprintf("%s is now the new leader.\n",pname(pl1));
   for (plx = 0; plx < max_players; plx++)
   {  if (IN_GROUP(plx))
      {  if (P_GROUP(plx) == P_GROUP(mynum) && players[plx].i_follow == mynum &&
             plx != pl1)
         {  players[plx].i_follow = pl1;
         }
      }
   }
   /* clear possible follow of new leader */
   players[pl1].i_follow = -1;
   sprintf(partybuff,"New leader is %s",pname(pl1));
   partyannounce(partybuff);
}

/******************************************************************************
 ** WHOPARTYTST
 ** Small function that can be used to show who is in a party, and in which 
 ** party he is. 
 ** This function is called from within the _userlist.
 *****************************************************************************/
PUBLIC char *whopartytst(int plx)
{ 
   if (!IN_GROUP(plx))
   {  return "";
   } else
   {  if (P_GROUP_LEADER(plx) == plx)
         sprintf(partybuff," (Leader of %s)", (P_GROUP_NAME(plx)[0] == '\0') ?
            "a party" : P_GROUP_NAME(plx));
      else
         sprintf(partybuff," (Member of %s)", (P_GROUP_NAME(plx)[0] == '\0') ?
            "a party" : P_GROUP_NAME(plx));
      return partybuff;
   }
   return partybuff;
}

/*****************************************************************************
 ** PSAY 
 ** Communication between party members
 ******************************************************************************/

/* Test function
 * See if the player is on and in a group, then check if the person is in the
 * same group as the sender, and not the sender itself. Then send the message,
 * Else send nothing at all. (standard send_g_msg() testfunction)
 */
PRIVATE char *psay_test(int player, int sender, char *text)
{ static char buff[MAX_COM_LEN];
  char *buffer = NULL;

  if (player < max_players)   
   if (IN_GROUP(player) && is_in_game(player))
   {  if (P_GROUP(sender) == P_GROUP(player) && sender != player)
      {  buffer = build_voice_text(pname(sender),"psays",text,"'",
             COLOR_NORMAL_CYAN,COLOR_HILIGHT_WHITE);
         sprintf(buff,"%s",buffer);
         free(buffer);
         return buff;
      } 
   } 
   return NULL;
} 

/*****************************************************************************
 ** PSAY
 ** Communications channel for everyone who is in a channel. It sends a message
 ** to everyone in the same group as the player is in
 *****************************************************************************/ 
PUBLIC A_COMMAND(psay)
{  char blob[MAX_COM_LEN];
 
    if (!IN_GROUP(mynum))
    {  erreval();
       return;
    }
    
    getreinput(blob);
    if (EMPTY(blob))
       bprintf("What do you want to say\n");
    else
    {  send_g_msg(DEST_ALL,psay_test,mynum,blob);
       if (ststflg(mynum,SFL_SAYBACK))
         bprintf("&+wYou psay &+w'%s'&*\n",blob);
       else
         bprintf("Ok\n");
    }
} 

/* used by partyannounce() */
PRIVATE char *pannounce_test(int player, int sender, char *text)
{  static char buff[MAX_COM_LEN];

  if (player < max_players)   
   if (IN_GROUP(player))
   {  if (P_GROUP(sender) == P_GROUP(player))
      {  sprintf(buff,"&+wParty Info: &+w%s&*\n",text);
         return buff;
      } 
   } 
   return NULL;
} 

/**************************************************************************
 ** This function is used for information that concerns all party members
 ** such as a change of shares, or a change of name etc...
 **************************************************************************/
PUBLIC void partyannounce(char *text)
{  if (text == NULL)
     return;
   else
     send_g_msg(DEST_ALL,pannounce_test,mynum,text);
}