tfe-1.0/area/
tfe-1.0/files/
tfe-1.0/logs/
tfe-1.0/logs/immortal/
tfe-1.0/logs/mob/
tfe-1.0/logs/object/
tfe-1.0/logs/player/
tfe-1.0/logs/room/
tfe-1.0/notes/clans/
tfe-1.0/player/
tfe-1.0/prev/
tfe-1.0/prev/area/
tfe-1.0/prev/player/
tfe-1.0/prev/rooms/
tfe-1.0/rooms/
tfe-1.0/src-gc/
tfe-1.0/src-msvc/
tfe-1.0/src-unix/
tfe-1.0/www/
tfe-1.0/www/html/
#include <ctype.h>
#include <sys/types.h>
#include <stdio.h>
#include <syslog.h>
#include "define.h"
#include "struct.h"


const char*   condition_prep  ( char_data* );

void          msg_attack      ( char_data*, char_data*, const char*,
                                const char*, char );
void          msg_other       ( char_data*, char_data*, const char*,
                                const char*, char );

/*
 *   GENERAL MESSAGE ROUTINES
 */


void dam_local( char_data* victim, char_data* ch, int damage,
  const char* dt, const char* loc_name )
{
  char               tmp  [ TWO_LINES ];
  char             punct;
  const char*   dam_name;
  char_data*         rch;
  int               flag;

  if( *loc_name == '\0' ) {
    dam_message( victim, ch, damage, dt, lookup( physical_index, damage ) );
    return;
    }

  punct        = ( damage <= 24 ? '.' : '!' );
  dam_name     = lookup( physical_index, damage );
  victim->hit -= damage;

  sprintf( tmp, "%s's %s %s%s%s your %s%c\n\r",
    ch->Name( victim,1, TRUE ),
    dt, to_self( victim ), dam_name, normal( victim ),
    loc_name, punct );
  corrupt( tmp, TWO_LINES, "Dam_Local" );
  *tmp = toupper( *tmp );
  send( victim, tmp );
 
  if( victim->Seen( ch ) ) 
    sprintf( tmp, "Your %s %s%s%s %s's %s%c",
      dt, by_self( ch ), dam_name, normal( ch ),
      victim->Name( ch, 1, TRUE ), loc_name, punct );
  else
    sprintf( tmp, "Your %s %s%s%s someone%c",
      dt, by_self( ch ),
      dam_name, normal( ch ), punct );

  corrupt( tmp, TWO_LINES, "Dam_Local" );
  strcat_cond( tmp, ch, victim );

  flag = ( victim->pcdata == NULL && !is_set( &victim->status, STAT_PET )
    ? MSG_DAMAGE_MOBS : MSG_DAMAGE_PLAYERS );

  for( int i = 0; i < *ch->array; i++ ) {
    if( ( rch = character( ch->array->list[i] ) ) == NULL
      || rch == ch || rch == victim || rch->link == NULL
      || !is_set( &rch->pcdata->message, flag ) || !rch->Can_See( ) )
      continue;
    if( victim->Seen( rch ) ) 
      sprintf( tmp, "%s's %s %s%s%s %s's %s%c",
        ch->Name( rch, 1, TRUE ), dt, damage_color( rch, ch, victim ),
        dam_name, normal( rch ), victim->Seen_Name( rch ),
        loc_name, punct );
    else
      sprintf( tmp, "%s's %s %s%s%s someone%c",
        ch->Name( rch ), dt, damage_color( rch, ch, victim ),
        dam_name, normal( rch ), punct );
    corrupt( tmp, TWO_LINES, "Dam_Local" );
    *tmp = toupper( *tmp );
    strcat_cond( tmp, rch, victim );
    }

  victim->hit += damage;

  return;
}


void dam_message( char_data* victim, char_data* ch, int damage,
  const char* dt, const char* word )
{
  char      tmp  [ ONE_LINE ];
  int         i;
  char    punct;

  victim->hit -= damage;

  strcpy( tmp, dt );
  if( ( i = strlen( tmp ) ) > 2 && tmp[i-2] == '\n' )
    tmp[i-2] = '\0';

  punct = ( damage <= 24 ? '.' : '!' );

  if( ch == NULL || *dt == '*' ) 
    msg_other( victim, ch, *tmp == '*' ? &tmp[1] : tmp, word, punct );
  else 
    msg_attack( victim, ch, tmp, word, punct );

  victim->hit += damage;

  return;
}  
 

void msg_attack( char_data* victim, char_data* ch, const char* dt,
  const char* word, char punct )
{
  char           tmp  [ MAX_INPUT_LENGTH ];
  char_data*     rch;
  int           flag;

  sprintf( tmp, "Your %s %s%s%s %s%c",
    dt, by_self( ch ), word, normal( ch ),
    victim->Name( ch ), punct );
  strcat_cond( tmp, ch, victim );

  sprintf( tmp, "%s's %s %s%s%s you%c\n\r",
    ch->Name( victim ), dt, to_self( victim ),
    word, normal( victim ), punct );
  *tmp = toupper( *tmp );
  send( tmp, victim );

  flag = ( victim->pcdata == NULL && !is_set( &victim->status, STAT_PET )
    ? MSG_DAMAGE_MOBS : MSG_DAMAGE_PLAYERS );

  for( int i = 0; i < *ch->array; i++ ) {
    if( ( rch = character( ch->array->list[i] ) ) == NULL
      || rch == ch || rch == victim || rch->link == NULL
      || !is_set( &rch->pcdata->message, flag ) || !rch->Can_See( ) )
      continue;
    sprintf( tmp, "%s's %s %s%s%s %s%c",
      ch->Name( rch ), dt,
      damage_color( rch, ch, victim ), word, normal( rch ),
      victim->Name( rch ), punct );
    *tmp = toupper( *tmp );
    strcat_cond( tmp, rch, victim );
    }

  return;
}


void msg_other( char_data* victim, char_data* ch, const char* dt,
  const char* word, char punct )
{
  char                tmp  [ TWO_LINES ];
  char_data*          rch;

  sprintf( tmp, "%s %s%s%s you%c\n\r", dt,
    to_self( victim ), word, normal( victim ), punct );
  corrupt( tmp, TWO_LINES, "Msg_Other" );
  *tmp = toupper( *tmp );
  send( tmp, victim );

  for( int i = 0; i < *victim->array; i++ ) {
    if( ( rch = character( victim->array->list[i] ) ) == NULL
      || rch == victim || !rch->Can_See( ) )
      continue;
    sprintf( tmp, "%s %s%s%s %s%c", dt,
      damage_color( rch, ch, victim ), word, normal( rch ),
      victim->Name( rch ), punct );
    corrupt( tmp, TWO_LINES, "Msg_Other" );
    *tmp = toupper( *tmp );
    strcat_cond( tmp, rch, victim );
    }

  return;
}


/*
 *   CONDITION ROUTINES
 */


void strcat_cond( char* tmp, char_data* ch, char_data* victim )
{
  const char*  cond_word  = condition_word( victim ); 
  bool           visible  = TRUE;
  int             length  = 0;
 
  for( int i = 0; tmp[i] != '\0'; i++ ) {
    if( visible ) {
      if( tmp[i] == '' )
        visible = FALSE;
      else
        length++;
      }
    else if( tmp[i] == 'm' )
      visible = TRUE;
    }

  send( ch, "%s%s[ %s ]\n\r", tmp,
    length+strlen( cond_word ) > 74 ? "\n\r" : " ", cond_word );

  return;
}
  

const char* condition_prep( char_data *ch )
{
  int percent = (100*ch->hit)/ch->max_hit;

  if( ch->hit <= -10 )
    return "is";

       if( percent >= 100 ) return "is in";
  else if( percent >=  90 ) return "is";
  else if( percent >=  80 ) return "has a";
  else if( percent >=  70 ) return "has";
  else if( percent >=  60 ) return "has";
  else if( percent >=  50 ) return "is";
  else if( percent >=  40 ) return "has";
  else if( percent >=  30 ) return "is";
  else if( percent >=  20 ) return "is";
  else if( percent >=  10 ) return "is";
  else if( percent >=   0 ) return "is";
                            return "is";
}


const char* condition_word( char_data* ch )
{
  int percent = (100*ch->hit)/ch->max_hit;

  if( ch->hit <= -11 )
    return "DEAD!";

       if( percent >= 100 ) return "perfect health";
  else if( percent >=  90 ) return "slightly scratched";
  else if( percent >=  80 ) return "few bruises";
  else if( percent >=  70 ) return "some cuts";
  else if( percent >=  60 ) return "several wounds";
  else if( percent >=  50 ) return "badly wounded";
  else if( percent >=  40 ) return "many nasty wounds";
  else if( percent >=  30 ) return "bleeding freely";
  else if( percent >=  20 ) return "covered in blood";
  else if( percent >=  10 ) return "leaking guts";
  else if( percent >=   0 ) return "mostly dead";
                            return "dying";

}


const char* condition_short( char_data* ch, char_data* victim )
{
  if( victim == NULL )
    return "-";

  if( victim->array != ch->array || !victim->Seen( ch ) )
    return "??";

  return condition_short( victim );
}


const char* condition_short( char_data* ch )
{
  int percent;

  if( ch->hit <= -11 )
    return "DEAD!";

  percent = (100*ch->hit)/ch->max_hit;

       if( percent >= 100 ) return "perfect";
  else if( percent >=  90 ) return "scratched";
  else if( percent >=  80 ) return "bruised";
  else if( percent >=  70 ) return "cut";
  else if( percent >=  60 ) return "wounded";
  else if( percent >=  50 ) return "badly wounded";
  else if( percent >=  40 ) return "nastily wounded";
  else if( percent >=  30 ) return "bleeding freely";
  else if( percent >=  20 ) return "covered in blood";
  else if( percent >=  10 ) return "leaking guts";
  else if( percent >=   0 ) return "mostly dead";
                            return "dying";
}


/*
 *   GENERAL INFLICT ROUTINE
 */


bool inflict( char_data* victim, char_data* ch, int dam, char* dt )
{
  if( victim->position == POS_DEAD )
    return TRUE;

  if( dam > 1000 ) {
    bug( "Inflict: more than 1000 points!" );
    dam = 1000;
    }
  else if( dam <= 0 )
    return FALSE;

  record_damage( victim, ch, dam );

  victim->hit -= dam;

  update_pos( victim );
  update_max_move( victim );

  set_bit( &victim->status, STAT_WIMPY );

  if( victim->position == POS_SLEEPING ) {
    strip_affect( victim, AFF_SLEEP );
    send( victim, "You are suddenly awakened by the feeling of pain.\n\r" );
    send_seen( victim, "%s wakes up.\n\r", victim );
    victim->position = POS_RESTING;
    renter_combat( victim );
    }

  /*
  if( IS_AFFECTED( victim, AFF_CONFUSED ) && dam > number_range( 0, 100 ) ) {
    strip_affect( victim, AFF_CONFUSED );
    send( "You are knocked to your senses.\n\r", victim );
    act( "$n is knocked to $s senses.", victim, NULL, NULL, TO_ROOM );
    victim->fighting = NULL;
    victim->aggressive = NULL;
    for( rch = victim->in_room->people; rch != NULL; rch = rch->next_in_room )
      if( IS_NPC( rch ) && !IS_SET( rch->status, STAT_PET ) ) {
        if( rch->fighting == ch )
          rch->fighting = NULL;
        if( rch->aggressive == ch )
          rch->aggressive = NULL;
        }
    }
    */
    
  switch( victim->position ) {
    case POS_MORTAL:
      send( victim,
        "You are mortally wounded, and will die soon, if not aided.\n\r" );
      send_seen( victim,
        "%s is mortally wounded, and will die soon, if not aided.\n\r",
        victim );
      break;
 
    case POS_INCAP:
      send( victim, 
        "You are incapacitated and will slowly die, if not aided.\n\r" );
      send_seen( victim,
        "%s is incapacitated and will slowly die, if not aided.\n\r",
        victim );
      break;

    case POS_STUNNED:
      send( victim, "You are stunned, but will probably recover.\n\r" );
      send_seen( victim,
        "%s is stunned, but will probably recover.\n\r",
        victim );
      break;

    case POS_DEAD:
      death_message( victim );
      break;

    default:
      if( dam > victim->max_hit/4 )
        send( "That really did HURT!\n\r", victim );
      if( victim->pcdata != NULL && victim->hit < victim->max_hit/4
        && is_set( &victim->pcdata->message, MSG_BLEEDING ) )
        send( victim, "You sure are BLEEDING!\n\r" );
      break;
    }

  if( victim->rider != NULL && victim->position < POS_FIGHTING ) {
    send( victim->rider,
      "You are thrown to the ground as your mount is %s.\n\r",
      victim->position == POS_DEAD ? "killed" : "incapacitated" );
    victim->rider->position = POS_RESTING;
    victim->rider->mount    = NULL;
    victim->rider           = NULL;
    }

  if( ch != NULL && ch->species != NULL ) 
    ch->species->damage += dam;

  if( victim->position == POS_DEAD ) {
    death( victim, ch, dt );
    return TRUE;
    }

  return FALSE;
} 


/*
 *   GLANCE ROUTINES
 */


void do_glance( char_data* ch, char* argument )
{
  char_data*  victim;

  if( *argument == '\0' ) {
    send( ch, "Who do you want to glance at?\n\r" );
    return;
    }

  if( ( victim = one_character( ch, argument, "glance",
    ch->array ) ) == NULL )
    return;

  glance( ch, victim );

  return;
}


void glance( char_data* ch, char_data* victim )
{
  if( victim == ch ) {
    page( ch, "Your condition is %s.\n\r", condition_word( ch ) );
    return;
    }

  page( ch, "%s %s %s%s%s%c\n\r",
    victim->Seen_Name( ch ), condition_prep( victim ),
    color_scale( ch, 6-6*victim->hit/victim->max_hit ),
    condition_word( victim ),
    normal( ch ), victim->hit > 0 ? '.' : '!' );

  return;
}


/*
 *   SPAM ROUTINES
 */


void spam_char( char_data* ch, const char* text )
{
  if( ch->link == NULL || !is_set( &ch->pcdata->message, MSG_MISSES ) )
    return;

  send( ch, text );

  return;  
}


void spam_room( const char* text, char_data* ch, char_data* victim )
{
  char         tmp  [ TWO_LINES ];
  char_data*   rch;

  for( int i = 0; i < *ch->array; i++ ) {
    if( ( rch = character( ch->array->list[i] ) ) == NULL
      || rch->link == NULL || rch == ch || rch == victim
      || rch->position <= POS_SLEEPING
      || !is_set( &rch->pcdata->message, MSG_MISSES ) )
      continue;
    sprintf( tmp, text, ch->Name( rch ),
      victim == NULL ? "[BUG]" : victim->Name( rch ) );
    corrupt( tmp, TWO_LINES, "Spam_Room" );
    *tmp = toupper( *tmp );
    send( tmp, rch );
    }

  return;
}

 
/*
 *   PHYSICAL DAMAGE ROUTINES
 */


index_data physical_index [] = 
{
  { "misses",               "miss",                  0 },
  { "scratches",            "scratch",               1 },
  { "grazes",               "graze",                 2 },
  { "hits",                 "hit",                   4 },
  { "injures",              "injure",                6 },
  { "wounds",               "wound",                10 },
  { "mauls",                "maul",                 15 },
  { "decimates",            "decimate",             21 },
  { "devastates",           "devastate",            28 },
  { "maims",                "maim",                 35 },
  { "SAVAGES",              "SAVAGE",               45 },
  { "CRIPPLES",             "CRIPPLE",              55 },
  { "MUTILATES",            "MUTILATE",             70 },
  { "DISEMBOWELS",          "DISEMBOWEL",           85 },
  { "* DISMEMBERS *",       "* DISMEMBER *",       100 },
  { "* EVISCERATES *",      "* EVISCERATE *",      120 },
  { "* MASSACRES *",        "* MASSACRE *",        145 },
  { "* PULVERIZES *",       "* PULVERIZE *",       170 },
  { "** DEMOLISHES **",     "** DEMOLISH **",      200 },
  { "** EXTIRPATES **",     "** EXTIRPATE **",     240 },
  { "*** OBLITERATES ***",  "*** OBLITERATE ***",  280 },
  { "*** ERADICATES ***",   "*** ERADICATE ***",   330 },
  { "*** ANNIHILATES ***",  "*** ANNIHILATE ***",   -1 }
};


bool damage_physical( char_data* victim, char_data* ch, int damage,
  const char* string, bool plural )
{
  dam_message( victim, ch, damage, string,
    lookup( physical_index, damage, plural ) );
  
  return inflict( victim, ch, damage, "physical damage" );
}



bool damage_magic( char_data* victim, char_data* ch, int damage,
  const char* string, bool plural )
{
  damage *= 100-victim->shdata->resist[RES_MAGIC];
  damage /= 100;

  dam_message( victim, ch, damage, string,
    lookup( physical_index, damage, plural ) );
  
  return inflict( victim, ch, damage, "shock" );
}


bool damage_mind( char_data* victim, char_data* ch, int damage,
  const char* string, bool plural )
{
  damage *= 100-victim->shdata->resist[RES_MIND];
  damage /= 100;

  dam_message( victim, ch, damage, string,
    lookup( physical_index, damage, plural ) );
  
  return inflict( victim, ch, damage, "shock" );
}