Eos/
Eos/player/
Eos/src/
Eos/src/tmp/lcc/
/*****************************************************************************
 * Room affect stuff.                                                        *
 * Put skills that use room affects in here.                                 *
 * -- Hannibal                                                               *
 *****************************************************************************/
#define unix 1
#if defined( macintosh )
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "merc.h"

/* Globals */
ROOM_AFFECT_DATA *	raffect_free;
POWERED_DATA *		pd_free;
/*
 * Slap a rAffect on a room and update ch->powered.
 */
void raffect_to_room( ROOM_INDEX_DATA *room, 
		      CHAR_DATA *ch, ROOM_AFFECT_DATA *raf )
{
  ROOM_AFFECT_DATA *raf_new;
  POWERED_DATA *pd;

  if ( !raffect_free )
    raf_new	 = alloc_perm( sizeof( *raf_new ) );
  else
  {
    raf_new	 = raffect_free;
    raffect_free = raffect_free->next;
  }

  if ( !pd_free )
    pd		 = alloc_perm( sizeof( *pd ) );
  else
  {
    pd		 = pd_free;
    pd_free	 = pd_free->next;
  }

  *raf_new	 = *raf;
  raf_new->next	 = room->rAffect;
  room->rAffect	 = raf_new;
  pd->room	 = room;
  pd->raf	 = raf_new;
  pd->next	 = ch->powered;
  pd->type	 = raf_new->type;
  pd->cost	 = SPELL_COST( ch, pd->type );

  if ( ch->race == RACE_ELDER || ch->race == RACE_ELF )
    	pd->cost *= .75;

  ch->powered	 = pd;
  obj_to_room( raf->material, room );

  if ( raf_new->location != ROOM_NONE )
	TOGGLE_BIT( room->room_flags, raf->location );

  return;

}
/*
 * Remove and delete a rAffect and update ch->powered.
 */
void raffect_remove( ROOM_INDEX_DATA *room, 
                     CHAR_DATA *ch, ROOM_AFFECT_DATA *raf )
{
  ROOM_AFFECT_DATA *rAf, *prAf;
  POWERED_DATA *pd, *ppd;
  char buf[ MAX_STRING_LENGTH ];

  if ( !room->rAffect )
  {
    bug( "rAffect_remove: no affect.", 0 );
    return;
  }

  if ( raf->location != ROOM_NONE )
    TOGGLE_BIT( room->room_flags, raf->location );

  sprintf( buf, "%s", skill_table[raf->type].room_msg_off );

  if ( ch->in_room == room )
    act( AT_CYAN, buf, ch, NULL, NULL, TO_ROOM );
  else if ( room->people )
    act( AT_CYAN, buf, room->people, NULL, NULL, TO_ROOM );

  ppd = NULL;
  for ( pd = ch->powered; pd; ppd = pd, pd = pd->next )
  {
   if ( pd->room == room && pd->raf == raf )
   {
     if ( !ppd )
	ch->powered = pd->next;
     else
	ppd->next = pd->next;
     if ( MT( ch ) < pd->cost )
     {
        sprintf( buf, "%s %s.\n\r", skill_table[raf->type].msg_off,
		 raf->room->name );
	send_to_char( AT_CYAN, buf, ch );
     }

     break;

   }
  }

  prAf = NULL;
  for ( rAf = room->rAffect; rAf; prAf = rAf, rAf = rAf->next )
  {
    if ( raf == rAf )
    {
      if ( !prAf )
	room->rAffect = rAf->next;
      else
	prAf->next = rAf->next;
    
      break;
    }
  }

  extract_obj( raf->material );
  free_mem( raf, sizeof( *raf ) );
  free_mem( pd, sizeof( *pd ) );

  return;

}
/*
 * Check if room is rAffected by something.
 */
bool is_raffected( ROOM_INDEX_DATA *room, int sn )
{
  ROOM_AFFECT_DATA *raf;

  for ( raf = room->rAffect; raf; raf = raf->next )
  {
    if ( raf->type == sn )
      return TRUE;
  }

  return FALSE;

}
/*
 * To see what you're powering ( imms see room's rAffects as well ).
 */
void do_raffect( CHAR_DATA *ch, char *argument )
{
  POWERED_DATA *pd;
  ROOM_AFFECT_DATA *raf;
  char buf[ MAX_INPUT_LENGTH ];

  if ( IS_NPC( ch ) )
	return;

  if ( !ch->powered )
    send_to_char( AT_CYAN, "You are not powering any room affects.\n\r", ch );

  for ( pd = ch->powered; pd; pd = pd->next )
  {
    sprintf( buf, "%s&w, &cMana Cost&w: &R%d&w, &cRoom&w: &W%s&w.\n\r",
		 skill_table[pd->type].name,
		 pd->cost,
		 pd->room->name );
    buf[0] = UPPER(buf[0]);
    send_to_char( AT_WHITE, buf, ch );

  }

  if ( ch->level >= L_APP )
  {
    send_to_char(AT_CYAN, "This room is affected by:\n\r", ch );
    for ( raf = ch->in_room->rAffect; raf; raf = raf->next )
    {
	sprintf( buf, "%s &cpowered by&w: &W%s&w.\n\r",
		 skill_table[raf->type].name,
		 raf->powered_by->name );
	buf[0] = UPPER(buf[0]);
	send_to_char(AT_WHITE, buf, ch );
    }
  }

  return;

}
/*
 * Remove all rAffects ch is powering. (mostly for quitting)
 */
void raffect_remall( CHAR_DATA *ch )
{
  POWERED_DATA *pd, *pd_next;

  for ( pd = ch->powered; pd; pd = pd_next )
  {
    if ( !pd )
      return;
    pd_next = pd->next;
    raffect_remove( pd->room, ch, pd->raf );

  }

  return;

}
/*
 * Toggle a room's rAffect location. (for asave_area)
 */
void toggle_raffects( ROOM_INDEX_DATA *room )
{
  ROOM_AFFECT_DATA *raf;

  for ( raf = room->rAffect; raf; raf = raf->next )
  {
     if ( !raf )
        break;
     if ( raf->location != ROOM_NONE )
	TOGGLE_BIT( room->room_flags, raf->location );

  }

  return;

}
/*
 * Locate or turn off a specific type of rAffect skill.
 */
void loc_off_raf( CHAR_DATA *ch, int gsn_raf, bool rOff )
{
  POWERED_DATA *pd;
  char buf [ MAX_STRING_LENGTH ];
  bool found = FALSE;

  if ( !rOff ) /* Locate a rAffect of type gsn_raf. */
  {
    for ( pd = ch->powered; pd; pd = pd->next )
    {
      if ( pd->type == gsn_raf )
      {
        sprintf( buf, "%s&w, &W%s&w; &cCost&w: &R%d&w.\n\r", 
		skill_table[gsn_raf].name, pd->room->name, pd->cost );
		send_to_char( AT_WHITE, buf, ch );
		found = TRUE;
      }
    }
      if ( !found )
      {
        sprintf( buf, "You are not sustaining any %s&w.\n\r",
		   skill_table[gsn_raf].name );
	send_to_char( AT_CYAN, buf, ch );
      }

      return;

    }

   /* Delete a rAffect of gsn_raf from room. */
   if ( !is_raffected( ch->in_room, gsn_raf ) )
   {
     sprintf( buf, "There is no %s &cin this room.\n\r",
	      skill_table[gsn_raf].name );
     send_to_char( AT_CYAN, buf, ch );

     return;

   }

   for ( pd = ch->powered; pd; pd = pd->next )
   {
     if ( !pd )
       break;
     if ( pd->type == gsn_raf )
     {
       found = TRUE;
       if ( pd->room == ch->in_room )
       {
	 sprintf( buf, "%s\n\r", skill_table[gsn_raf].noun_damage );
	 send_to_char( AT_WHITE, buf, ch );
         raffect_remove( ch->in_room, ch, pd->raf );
         return;
       }
     }
   }

   if ( !found )
   {
     sprintf( buf, "You are not sustaining any %s&w.\n\r",
		skill_table[gsn_raf].name );
     return;
   }

   sprintf( buf, "You are not powering the %s &cin this room.\n\r",
	      skill_table[gsn_raf].name );
   send_to_char( AT_CYAN, buf, ch ); 

   return;

}
/*
 * Main ward skill.  Does NOTHING if no ward is known by ch.
 */
void do_ward( CHAR_DATA *ch, char *argument )
{
  ROOM_AFFECT_DATA raf;
  OBJ_DATA *ward;
  char arg1[ MAX_INPUT_LENGTH ];
  char buf[ MAX_STRING_LENGTH ];
  char *wname, *shortd, *longd;
  int type = 0;
  int location = ROOM_NONE;

  if ( IS_NPC( ch ) )
    return;

  if ( argument[0] == '\0' )
  {
    send_to_char( AT_WHITE, "Syntax: ward <type> <on|off|locate>\n\r", ch );
    return;
  }

  wname = shortd = longd = "";
  argument = one_argument( argument, arg1 );

  if ( !str_cmp( arg1, "safety" ) )
  {
    type = gsn_ward_safe;
    location = ROOM_SAFE;
    wname = "ward safety";
    shortd = "some Wards of Safety";
    longd = "Some wards of safety have been raised in this room.";
  }
  
  if ( !str_cmp( arg1, "healing" ) )
  {
    type = gsn_ward_heal;
    location = ROOM_NONE;
    wname = "ward heal";
    shortd = "some Wards of Healing";
    longd = "Some wards of healing have been raised in this room.";
  }

  if ( type == 0 )
  {
    send_to_char(AT_GREY, "No such ward.\n\r", ch );
    return;
  }

  if ( !can_use_skpell( ch, type ) )
  {
    sprintf( buf, "You aren't skilled in the ward of %s.\n\r", arg1 );
    send_to_char(AT_GREY, buf, ch );
    return;
  }

  if ( !str_cmp( argument, "locate" ) )
  {
    loc_off_raf( ch, type, FALSE );
    return;
  }

  if ( !str_cmp( argument, "off" ) )
  {
    loc_off_raf( ch, type, TRUE );
    return;
  }

  if ( str_cmp( argument, "on" ) )
  {
    do_ward( ch, "" );
    return;
  }

  if ( ch->pcdata->learned[type] < number_percent( ) )
  {
    sprintf( buf, "You fail in raising your ward of %s.\n\r", arg1 );
    send_to_char(AT_GREY, buf, ch );
    return;
  }

  if ( type == gsn_ward_safe
  && IS_SET( ch->in_room->room_flags, ROOM_SAFE ) )
  {
    send_to_char(AT_WHITE, "This room is already safe.\n\r", ch );
    return;
  }

  if ( type == gsn_ward_heal
  && is_raffected( ch->in_room, gsn_ward_heal ) )
  {
    send_to_char( AT_WHITE, "This room is already warded to heal.\n\r", ch );
    return;
  }

  ward = create_object( get_obj_index( OBJ_VNUM_WARD_PHYS ), 1 );

  free_string( ward->short_descr );
  free_string( ward->description );
  free_string( ward->name );
  ward->name	    = str_dup( wname );
  ward->short_descr = str_dup( shortd );
  ward->description = str_dup( longd );
  raf.type	 = type;
  raf.location	 = location;
  raf.material	 = ward;
  raf.room	 = ch->in_room;
  raf.powered_by = ch;
  raffect_to_room( ch->in_room, ch, &raf );

  sprintf( buf, "You raise a %s.\n\r", skill_table[type].name );
  send_to_char( AT_WHITE, buf, ch );
  act( AT_WHITE, "$n raises a $t.", 
       ch, (char *)skill_table[type].name, NULL, TO_ROOM );

  if ( type == gsn_ward_heal )
    update_skpell( ch, gsn_ward_heal );

  if ( type == gsn_ward_safe )
    update_skpell( ch, gsn_ward_safe );

  return;  
}