eldhamud/boards/
eldhamud/clans/
eldhamud/classes/
eldhamud/councils/
eldhamud/deity/
eldhamud/doc/
eldhamud/doc/DIKU/
eldhamud/doc/MERC/
eldhamud/doc/mudprogs/
eldhamud/houses/
eldhamud/src/o/CVS/
/*
.-------------------------------------------------------------------------------.
| Title    : MIP (Messaging Interface Protocol) v8.1 Support Module		|
| Author   : Chris Coulter (aka Gabriel Androctus)				|
| Date     : 08.26.02								|
| Dev. MUD : Perils of Quiernin	( perils.org 6000 )				| 
| Platform : SMAUG v1.4a							|
| MUD Page : http://www.perils.org/						|
| Res. Page: http://www.perils.org/goodies/					|
+-------------------------------------------------------------------------------+
| DESCRIPTION:									|
| MIP (Messaging Interface Protocol) enables your mud to communicate specific   |
| text strings to a player using the Portal client software. This module        |
| provides basic support for establishing if the player is using the Portal     |
| client and assigning the appropriate information, as well as a simplified     |
| way to send the strings to trigger specific features on the player's client.  |
|										|
| For more information, visit Portal's web page ( www.gameaxle.com ) and click  |
| on the "Developers" button on the menu bar. From there you can download a PDF |
| file that explains in detail the specifics of the MIP.			|
|										|
| NOTE: If a player is not using the Portal client, the mud will function as    |
| it normally would, and the player would not receive the MIP codes. It will    |
| only function for players who has connected via the Portal mud client         |
| 										|
`-------------------------------------------------------------------------------'
*/
#include <sys/types.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include "mud.h"

/* Parses jumpstart command and assigns sec_code & version information.		-gabe */
void do_mip_start( CHAR_DATA *ch, char *argument )
{
  char arg[MAX_INPUT_LENGTH]; /* version */
  char buf[MAX_STRING_LENGTH];
  int  sec_code;
  
  if ( IS_NPC( ch ) )
  {
    send_to_char( "Huh?\n\r", ch );
    return;
  }
  
  if ( argument[0] == '\0' )
  {
    send_to_char( "Huh?\n\r", ch );
    return;
  }
  
  sscanf( argument, "%d~%s\n\r", &sec_code, arg );
  
  /* pad sec_code with zeros */
       if ( sec_code >= 10000 )
    sprintf( buf, "%d", sec_code );
  else if ( sec_code >= 1000 )
    sprintf( buf, "0%d", sec_code );
  else if ( sec_code >= 100 )
    sprintf( buf, "00%d", sec_code );
  else if ( sec_code >= 10 )
    sprintf( buf, "000%d", sec_code );
  else if ( sec_code >= 0 )
    sprintf( buf, "0000%d", sec_code );
  
  ch->pcdata->sec_code = str_dup( buf );
  ch->pcdata->mip_ver = str_dup( arg );
  
  xSET_BIT( ch->act, PLR_MIP );
}

/* Initial settings are all done here.	-gabe */
void init_mip( CHAR_DATA *ch )
{
  send_mip_mask( ch, CL_HP_MASK, "Hit Points" );
  send_mip_mask( ch, CL_SP_MASK, "Mana" );
  send_mip_mask( ch, CL_GP1_MASK,"Movement" );
  send_mip_mask( ch, CL_GP2_MASK, "Unused" );
}

/* Is the character's client MIP-enhanced?	-gabe */
bool mip_enabled( CHAR_DATA *ch )
{
  if ( IS_NPC( ch ) )
    return FALSE;
  

  if ( ( !ch->pcdata->sec_code 
    || ch->pcdata->sec_code[0] == '\0' )
    && ( !ch->pcdata->mip_ver
    || ch->pcdata->mip_ver[0] == '\0' ) )
    return FALSE;   
  
  if ( xIS_SET( ch->act, PLR_MIP ) )
    return TRUE;

  return FALSE;
}

/* provides the generic prefix for all MIP communication	-gabe */
void send_mip( char *argument, CHAR_DATA *ch )
{
  char buf[MAX_STRING_LENGTH];
  char length2[MAX_STRING_LENGTH];
  int length;
  
  if ( !mip_enabled( ch ) )
    return;
  
  length = strlen( argument );
  
       if ( length >= 1000 )
    sprintf( length2, "999" );
  else if ( length >= 100 )
    sprintf( length2, "%d", length );
  else if ( length >= 10 )
    sprintf( length2, "0%d", length );
  else if ( length >= 0 )
    sprintf( length2, "00%d", length );
  else
    sprintf( length2, "000" );
    
  sprintf( buf, "#K%%%s%s%s", ch->pcdata->sec_code, length2, argument );
  
  send_to_char( buf, ch );
  
  return;
}

void send_mip_2( char *argument, CHAR_DATA *victim )
{
  char buf[MAX_STRING_LENGTH];
  char length2[MAX_STRING_LENGTH];
  int length;
  
  if ( !mip_enabled( victim ) )
    return;
  
  length = strlen( argument );
  
       if ( length >= 1000 )
    sprintf( length2, "999" );
  else if ( length >= 100 )
    sprintf( length2, "%d", length );
  else if ( length >= 10 )
    sprintf( length2, "0%d", length );
  else if ( length >= 0 )
    sprintf( length2, "00%d", length );
  else
    sprintf( length2, "000" );
    
  sprintf( buf, "#K%%%s%s%s", victim->pcdata->sec_code, length2, argument );
  
  send_to_char( buf, victim );
  
  return;
}

void send_mip_3( char *argument, CHAR_DATA *victim )
{
  char buf[MAX_STRING_LENGTH];
  char length2[MAX_STRING_LENGTH];
  int length;
 
  
  length = strlen( argument );
  
       if ( length >= 1000 )
    sprintf( length2, "999" );
  else if ( length >= 100 )
    sprintf( length2, "%d", length );
  else if ( length >= 10 )
    sprintf( length2, "0%d", length );
  else if ( length >= 0 )
    sprintf( length2, "00%d", length );
  else
    sprintf( length2, "000" );
    
  sprintf( buf, "#K%%%s%s%s", victim->pcdata->sec_code, length2, argument );
  
  send_to_char( buf, victim );
  
  return;
}

/* Triggers sound on client's computer.		-gabe
 * Formats: .WAV 
 */
void send_mip_sound( CHAR_DATA *ch, char *filename )
{
  char buf[MAX_STRING_LENGTH];
  
  sprintf( buf, "%s%s", CL_SEND_SOUND, filename );
  send_mip( buf, ch );
  return;
}

/* Triggers music on client's computer.		-gabe
 * Formats: .MID, .RMI, .MP3
 */
void send_mip_music( CHAR_DATA *ch, char *filename, int iterations )
{
  char buf[MAX_STRING_LENGTH];
  
  if ( !filename || filename[0] == '\0' )
    sprintf( buf, "%s", CL_SEND_MUSIC );
  else if ( iterations > 1 )  
    sprintf( buf, "%s%s%s%d", CL_SEND_MUSIC, filename, CL_DELIM, iterations );
  else
    sprintf( buf, "%s%s", CL_SEND_MUSIC, filename );  
    
  send_mip( buf, ch );
  return;
}

/* Displays an image on client's computer.	-gabe
 * Formats: .BMP, .GIF
 */
void send_mip_image( CHAR_DATA *ch, char *filename, char *label )
{
  char buf[MAX_STRING_LENGTH];
  
  sprintf( buf, "%s%s%s%s", CL_SEND_IMAGE, filename, CL_DELIM, label );
  send_mip( buf, ch );
  return;
}

/* Display amount of time remaining (HH:MM) until next reboot.		-gabe */
void send_mip_reboot( CHAR_DATA *ch, char *argument )
{
  char buf[MAX_STRING_LENGTH];
  
  sprintf( buf, "%s%s", CL_SEND_REBOOT, argument );
  send_mip( buf, ch );
  return;
}

/* Display amount of time (HH:MM) the mud has been up since last reboot.	-gabe */
void send_mip_uptime( CHAR_DATA *ch, char *argument )
{
  char buf[MAX_STRING_LENGTH];
  
  sprintf( buf, "%s%s", CL_SEND_UPTIME, argument );
  send_mip( buf, ch );
  return;
}

/* Trigger an .AVI on the client's computer	-gabe */
void send_mip_avi( CHAR_DATA *ch, char *filename, char *label, int height, int width, bool fRepeat )
{
  char buf[MAX_STRING_LENGTH];
  
  sprintf( buf, "%s%s%s%s%s%d%s%d%s%s", 
    CL_SEND_AVI, filename, CL_DELIM, label, CL_DELIM, height, CL_DELIM, width,
    ( fRepeat ) ? CL_DELIM : "",
    ( fRepeat ) ? "1" : "" );
  send_mip( buf, ch );
  return;
}

/* Send a media file to the client's hard disk.		-gabe
 * Formats: .WAV, .MID, .RMI, .MP3, .BMP, .GIF, .AVI 
 */
void mip_download( CHAR_DATA *ch, char *filename )
{
  char buf[MAX_STRING_LENGTH];
  
  sprintf( buf, "%s%s%s%s%s", CL_DOWNLOAD_MEDIA, filename, CL_DELIM, MIP_MEDIA_URL, filename );
  send_mip( buf, ch );
  return;
}

/* Send special information to client in a text string		-gabe 
 * note: haven't found a use for this, but it's part of mip. so here it is. */
void send_mip_special( CHAR_DATA *ch, char *argument )
{
  char buf[MAX_STRING_LENGTH];
  
  sprintf( buf, "%s%s", CL_SEND_SPECIAL, argument );
  send_mip( buf, ch );
  return;
}

/* Send special guild information to client in a text string	-gabe
 * note: haven't found a use for this, but it's a part of mip. so here it is. */
void send_mip_special2( CHAR_DATA *ch, char *argument )
{
  char buf[MAX_STRING_LENGTH];
  
  sprintf( buf, "%s%s", CL_SEND_SPECIAL2, argument );
  send_mip( buf, ch );
  return;
}

/* Send 'tell' information to player's client	-gabe
 * fSender values:
 *  TRUE = ( ch == sender of tell ) + ( victim == receiver of tell )
 *  FALSE = ( ch == receiver of tell ) + ( victim == sender of tell )
 */
void send_mip_tell( CHAR_DATA *ch, CHAR_DATA *victim, char *argument, bool fSender )
{
  char buf[MAX_STRING_LENGTH];    

  /* don't monitor NPC tells */
  if ( IS_NPC( ch ) || IS_NPC( victim ) )
    return;
  
  if ( fSender )
  {
    sprintf( buf, "%sx%s%s%s%s", CL_SEND_TELL, CL_DELIM, victim->name, CL_DELIM, argument );
    send_mip_2( buf, ch );
    return;
  }
  else
  {
    sprintf( buf, "%s%s%s%s%s", CL_SEND_TELL, CL_DELIM, victim->name, CL_DELIM, argument );
  send_mip( buf, victim );
  return;
  }
}

/* Send short description of a room to player's client		-gabe */
void send_mip_room( CHAR_DATA *ch, char *argument )
{
  char buf[MAX_STRING_LENGTH];
  
  sprintf( buf, "%s%s", CL_SEND_ROOM, argument );
  send_mip( buf, ch );
  return;
}

/* Send a metered lag measurement to client	-gabe */
void send_mip_mudlag( CHAR_DATA *ch, char *argument )
{
  char buf[MAX_STRING_LENGTH];
  
  sprintf( buf, "%s%s", CL_SEND_MUDLAG, argument );
  send_mip( buf, ch );
  return;
}

/* Send the current file that is being edited (??)	-gabe */
void send_mip_edit( CHAR_DATA *ch, char *filename )
{
  char buf[MAX_STRING_LENGTH];
  
  sprintf( buf, "%s%s", CL_SEND_EDIT, filename );
  send_mip( buf, ch );
  return;
}

/* Set the appropriate mask names on player's client	-gabe
 * note: for type values, see mip.h */
void send_mip_mask( CHAR_DATA *ch, char *type, char *argument )
{
  char buf[MAX_STRING_LENGTH];
  
  sprintf( buf, "%s%s", type, argument );
  send_mip( buf, ch );
  return;
}

/* Set the caption on the player's client	-gabe */
void send_mip_caption( CHAR_DATA *ch, char *argument )

{
  char buf[MAX_STRING_LENGTH];
  
  sprintf( buf, "%s%s", CL_SEND_CAPTION, argument );
  send_mip( buf, ch );
  return;
}

/* Begin a line-by-line transfer (???)	-gabe */
void send_mip_begin_file( CHAR_DATA *ch, int lines, char *tag )
{
  char buf[MAX_STRING_LENGTH];
  
  sprintf( buf, "%s%d%s%s", CL_SEND_BEGIN_FILE, lines, CL_DELIM, tag );
  send_mip( buf, ch );
  return;
}

/* Continue a line-by-line transfer (???) -gabe */
void send_mip_cont_file( CHAR_DATA *ch, char *line )
{
  char buf[MAX_STRING_LENGTH];
  
  sprintf( buf, "%s%s", CL_SEND_CONT_FILE, line );
  send_mip( buf, ch );
  return;
}

/* End a line-by-line transfer (???) -gabe */
void send_mip_end_file( CHAR_DATA *ch )
{
  char buf[MAX_STRING_LENGTH];
  
  sprintf( buf, "%s", CL_SEND_END_FILE );
  send_mip( buf, ch );
  return;
}

/* Send channel information to player's client	-gabe */
void send_mip_channel( CHAR_DATA *ch, const char *cmd, char *channel, char *source, char *argument )
{
  char buf[MAX_STRING_LENGTH];
  char buf2[MAX_STRING_LENGTH];

  sprintf( buf2, "%s-> %s-> %s", source, channel, argument );
  
  sprintf( buf, "%s%s%s%s%s%s%s%s", CL_SEND_CHAT, cmd, CL_DELIM, channel, 
    CL_DELIM, source, CL_DELIM, buf2 );
  send_mip_3( buf, ch );
  
  return;
}

/* Send exit information to player's client (for room monitor)	-gabe */
void send_mip_exits( CHAR_DATA *ch )
{
  EXIT_DATA *exit_l;
  char ex_buf[MAX_STRING_LENGTH];
  char buf[MAX_STRING_LENGTH];
  
  strcpy( ex_buf, "" );
  
  if ( !ch->in_room )
  {
    bug( "send_mip_exits (%s): ch->in_room == NULL", ch->name );
    return;
  }
  
  for ( exit_l = ch->in_room->first_exit; exit_l; exit_l = exit_l->next )
  {
    if ( exit_l->to_room
      && !IS_SET( exit_l->exit_info, EX_CLOSED )
      && !IS_SET( exit_l->exit_info, EX_HIDDEN )
      && !IS_SET( exit_l->exit_info, EX_WINDOW ) )
    {
      switch( exit_l->vdir )
      {
        default:						break;
        case DIR_NORTH:		strcat( ex_buf, "n " );		break;
        case DIR_EAST:		strcat( ex_buf, "e " );		break;
        case DIR_SOUTH:		strcat( ex_buf, "s " );		break;
        case DIR_WEST:		strcat( ex_buf, "w " );		break;
        case DIR_UP:		strcat( ex_buf, "u " );		break;
        case DIR_DOWN:		strcat( ex_buf, "d " );		break;
        case DIR_NORTHEAST:	strcat( ex_buf, "ne " );	break;
        case DIR_SOUTHEAST:	strcat( ex_buf, "se " );	break;
        case DIR_NORTHWEST:	strcat( ex_buf, "nw " );	break;
        case DIR_SOUTHWEST:	strcat( ex_buf, "sw " );	break;
      }
    }
  }
  
  sprintf( buf, "%s%s", CL_SEND_ROOMCODE, ex_buf );
  send_mip( buf, ch );
  return;
}

/* Send point information (hit points, mana & move points)	-gabe */
void send_mip_points( CHAR_DATA *ch )
{
  char buf[MAX_STRING_LENGTH];
  
  sprintf( buf, "%s%s%d%s%s%d%s%s%d%s%s%d%s%s%d%s%s%d", CL_SEND_COMPOSITE,
    CL_SEND_HP, ch->hit, CL_DELIM,
    CL_SEND_MAXHP, ch->max_hit, CL_DELIM,
    CL_SEND_SP, ch->mana, CL_DELIM,
    CL_SEND_MAXSP, ch->max_mana, CL_DELIM,
    CL_SEND_GP1, ch->move, CL_DELIM,
    CL_SEND_MAXGP1, ch->max_move );
  send_mip( buf, ch );
  return;
}

/* Send combat information (mob condition/name) 	-gabe */
void send_mip_attacker( CHAR_DATA *ch )
{
  CHAR_DATA *victim;
  char buf[MAX_STRING_LENGTH];
  int condition;
  
  if ( !ch->fighting || !(victim = who_fighting( ch ) ) )
  {
    sprintf( buf, "%s%s%s", CL_SEND_COMPOSITE, CL_SEND_ATTACKER, CL_DELIM );
    send_mip( buf, ch );
    sprintf( buf, "%s%s%d", CL_SEND_COMPOSITE, CL_SEND_ATTCOND, 0 );
    send_mip( buf, ch );
    return;
  }
  
  if ( victim->max_hit > 0 && victim->hit > 0 )
    condition = (100 * victim->hit) / victim->max_hit;
  else
    condition = 0;
  
  sprintf( buf, "%s%s%s%s%s%d", CL_SEND_COMPOSITE, CL_SEND_ATTACKER,
    (IS_NPC(victim)) ? capitalize(victim->short_descr) : victim->name, CL_DELIM,
    CL_SEND_ATTCOND, condition );
  
  send_mip( buf, ch );
  return;
}