LOP/
LOP/area/
LOP/boards/
LOP/channels/
LOP/clans/
LOP/color/
LOP/councils/
LOP/deity/
LOP/src/specials/
/*****************************************************************************
 * DikuMUD (C) 1990, 1991 by:                                                *
 *   Sebastian Hammer, Michael Seifert, Hans Henrik Staefeldt, Tom Madsen,   *
 *   and Katja Nyboe.                                                        *
 *---------------------------------------------------------------------------*
 * MERC 2.1 (C) 1992, 1993 by:                                               *
 *   Michael Chastain, Michael Quan, and Mitchell Tse.                       *
 *---------------------------------------------------------------------------*
 * SMAUG 1.4 (C) 1994, 1995, 1996, 1998 by: Derek Snider.                    *
 *   Team: Thoric, Altrag, Blodkai, Narn, Haus, Scryn, Rennard, Swordbearer, *
 *         gorog, Grishnakh, Nivek, Tricops, and Fireblade.                  *
 *---------------------------------------------------------------------------*
 * SMAUG 1.7 FUSS by: Samson and others of the SMAUG community.              *
 *                    Their contributions are greatly appreciated.           *
 *---------------------------------------------------------------------------*
 * LoP (C) 2006, 2007, 2008, 2009 by: the LoP team.                          *
 *****************************************************************************/

#include <stdio.h>
#include <string.h>
#include "h/mud.h"

void fwrite_paflocation( FILE *fp, AFFECT_DATA *paf )
{
   if( !paf || !fp )
      return;

   if( paf->location >= 0 && paf->location < APPLY_MAX )
      fprintf( fp, " '%s'", a_types[paf->location] );
   else
      fprintf( fp, " '%d'", paf->location );
}

void fwrite_pafmodifier( FILE *fp, AFFECT_DATA *paf )
{
   if( !paf || !fp )
      return;

   if( paf->location == APPLY_EXT_AFFECT && paf->modifier >= 0 && paf->modifier < AFF_MAX )
      fprintf( fp, " '%s'", a_flags[paf->modifier] );
   else if( ( paf->location == APPLY_RESISTANT || paf->location == APPLY_IMMUNE || paf->location == APPLY_SUSCEPTIBLE || paf->location == APPLY_ABSORB )
   && paf->modifier >= 0 && paf->modifier < RIS_MAX )
      fprintf( fp, " '%s'", ris_flags[paf->modifier] );
   else if( ( paf->location == APPLY_WEAPONSPELL || paf->location == APPLY_WEARSPELL || paf->location == APPLY_REMOVESPELL || paf->location == APPLY_STRIPSN )
   && is_valid_sn( paf->modifier ) )
      fprintf( fp, " '%s'", skill_table[paf->modifier]->name );
   else
      fprintf( fp, " '%d'", paf->modifier );
}

void fwrite_pafbitvector( FILE *fp, AFFECT_DATA *paf )
{
   if( !paf || !fp )
      return;

   if( paf->location == APPLY_EXT_AFFECT && !xIS_EMPTY( paf->bitvector ) )
      fprintf( fp, " '%s'", ext_flag_string( &paf->bitvector, a_flags ) );
   else if( paf->location == APPLY_STAT && !xIS_EMPTY( paf->bitvector ) )
      fprintf( fp, " '%s'", ext_flag_string( &paf->bitvector, stattypes ) );
   else
      fprintf( fp, " %s", "'-1'" );
}

void fwrite_objaffects( FILE *fp, AFFECT_DATA *paf )
{
   SKILLTYPE *skill = NULL;

   if( !paf || !fp )
      return;

   for( ; paf; paf = paf->next )
   {
      if( paf->type >= 0 && !( skill = get_skilltype( paf->type ) ) )
         continue;

      /* type/name */
      if( paf->type >= 0 )
         fprintf( fp, "NAffectN     '%s'", skill->name );
      else
         fprintf( fp, "NAffectN     '%d'", paf->type );

      fprintf( fp, " %d", paf->duration );

      fwrite_paflocation( fp, paf );
      fwrite_pafmodifier( fp, paf );
      fwrite_pafbitvector( fp, paf );

      /* Enchantment or extra, Extra is from quest / immortal addition and enchantment is added by enchant spell */
      fprintf( fp, " '%s'", paf->enchantment ? "enchantment" : "extra" );

      fprintf( fp, "%s", "\n" );
   }
}

void fwrite_chaffect( FILE *fp, AFFECT_DATA *paf )
{
   SKILLTYPE *skill = NULL;

   if( !fp || !paf )
      return;

   for( ; paf; paf = paf->next )
   {
      if( paf->type >= 0 && !( skill = get_skilltype( paf->type ) ) )
         continue;

      /* type/name */
      if( paf->type >= 0 )
         fprintf( fp, "Affect         '%s'", skill->name );
      else
         fprintf( fp, "Affect         '%d'", paf->type );

      fprintf( fp, " %d", paf->duration );

      fwrite_paflocation( fp, paf );
      fwrite_pafmodifier( fp, paf );
      fwrite_pafbitvector( fp, paf );

      fprintf( fp, "%s", "\n" );
   }
}

void fwrite_oiaffect( FILE *fp, AFFECT_DATA *paf )
{
   if( !fp || !paf )
      return;

   for( ; paf; paf = paf->next )
   {
      fprintf( fp, "%s", "NAffect   " );

      fwrite_paflocation( fp, paf );
      fwrite_pafmodifier( fp, paf );
      fwrite_pafbitvector( fp, paf );

      fprintf( fp, "%s", "\n" );
   }
}

/* This will read in a ch->affect */
/* The atype is to have it load only what you are wanting it to load */
/*
 * atype == 0 (Loads it all except for enchantment/extra)
 * atype == 1 (Loads it all and enchantment/extra)
 * atype == 2 (Skips loading the type and duration and enchantment/extra)
 */
AFFECT_DATA *fread_chaffect( FILE *fp, int atype, const char *filename, int line )
{
   AFFECT_DATA *paf;
   char *infoflags;
   int sn, value;

   if( !fp )
      return NULL;

   CREATE( paf, AFFECT_DATA, 1 );

   if( atype == 2 )
   {
      paf->type = -1;
      paf->duration = -1;
   }
   else
   {
      infoflags = fread_word( fp );
      if( is_number( infoflags ) )
         paf->type = atoi( infoflags );
      else
      {
         if( ( sn = skill_lookup( infoflags ) ) < 0 )
         {
            if( ( sn = herb_lookup( infoflags ) ) < 0 )
            {
               if( ( sn = pers_lookup( infoflags ) ) < 0 )
               {
                  bug( "%s:%d unknown skill [%s] for char affect.", filename, line, infoflags );
                  fread_to_eol( fp );
                  DISPOSE( paf );
                  return NULL;
               }
               else
                  sn += TYPE_PERS;
            }
            else
               sn += TYPE_HERB;
         }
         paf->type = sn;
      }
      paf->duration = fread_number( fp );
   }


   infoflags = fread_word( fp );
   if( str_cmp( infoflags, "0" ) )
   {
      /* Change blood to mana */
      if( !str_cmp( infoflags, "Blood" ) )
         infoflags = (char *)"Mana";
      value = get_flag( infoflags, a_types, APPLY_MAX );
      if( value < 0 || value >= APPLY_MAX )
      {
         bug( "%s:%d Unknown apply %s",  filename, line, infoflags );
         fread_to_eol( fp );
         DISPOSE( paf );
         return NULL;
      }
      else
         paf->location = value;
   }
   else
      paf->location = 0;

   infoflags = fread_word( fp );
   if( paf->location == APPLY_RESISTANT || paf->location == APPLY_IMMUNE || paf->location == APPLY_SUSCEPTIBLE || paf->location == APPLY_ABSORB )
   {
      value = get_flag( infoflags, ris_flags, RIS_MAX );
      if( value < 0 || value >= RIS_MAX )
      {
         bug( "%s:%d Unknown resistant/immune/susceptible/absorb %s", filename, line, infoflags );
         fread_to_eol( fp );
         DISPOSE( paf );
         return NULL;
      }
      else
         paf->modifier = value;
   }
   else if( paf->location == APPLY_EXT_AFFECT )
   {
      value = get_flag( infoflags, a_flags, AFF_MAX );
      if( value < 0 || value >= AFF_MAX )
      {
         bug( "%s:%d Unknown affected %s", filename, line, infoflags );
         fread_to_eol( fp );
         DISPOSE( paf );
         return NULL;
      }
      else
         paf->modifier = value;
   }
   else if( paf->location == APPLY_WEAPONSPELL || paf->location == APPLY_WEARSPELL
   || paf->location == APPLY_REMOVESPELL || paf->location == APPLY_STRIPSN )
   {
      if( is_number( infoflags ) )
      {
         paf->modifier = slot_lookup( atoi( infoflags ) );
         if( paf->modifier < 0 )
         {
            bug( "%s:%d unknown slot [%s] for weaponspell/wearspell/removespell/stripsn.", filename, line, infoflags );
            fread_to_eol( fp );
            DISPOSE( paf );
            return NULL;
         }
      }
      else
      {
         if( ( paf->modifier = skill_lookup( infoflags ) ) < 0 )
         {
            if( ( paf->modifier = herb_lookup( infoflags ) ) < 0 )
            {
               if( ( paf->modifier = pers_lookup( infoflags ) ) < 0 )
               {
                  bug( "%s:%d unknown skill [%s] for weaponspell/wearspell/removespell/stripsn.", filename, line, infoflags );
                  fread_to_eol( fp );
                  DISPOSE( paf );
                  return NULL;
               }
            }
         }
      }
   }
   else
      paf->modifier = atoi( infoflags );

   xCLEAR_BITS( paf->bitvector );

   infoflags = fread_word( fp );
   if( str_cmp( infoflags, "-1" ) )
   {
      if( paf->location == APPLY_STAT )
      {
         value = get_flag( infoflags, stattypes, STAT_MAX );
         if( value < 0 || value >= STAT_MAX )
         {
            bug( "%s:%d Unknown stat %s", filename, line, infoflags );
            fread_to_eol( fp );
            DISPOSE( paf );
            return NULL;
         }
         else
            xSET_BIT( paf->bitvector, value );
      }
      else if( paf->location == APPLY_EXT_AFFECT )
      {
         value = get_flag( infoflags, a_flags, AFF_MAX );
         if( value < 0 || value >= AFF_MAX )
         {
            bug( "%s:%d Unknown affect %s", filename, line, infoflags );
            fread_to_eol( fp );
            DISPOSE( paf );
            return NULL;
         }
         else
            xSET_BIT( paf->bitvector, value );
      }
   }

   paf->enchantment = false;

   if( atype == 1 )
   {
      infoflags = fread_word( fp );

      if( !str_cmp( infoflags, "enchantment" ) )
         paf->enchantment = true;
   }

   return paf;
}

/* Show an affect verbosely to a character -Thoric */
void showaffect( CHAR_DATA *ch, AFFECT_DATA *paf, bool extdisplay )
{
   char buf[MSL];

   if( !paf )
   {
      bug( "%s: NULL paf", __FUNCTION__ );
      return;
   }

   if( paf->location != APPLY_NONE )
   {
      switch( paf->location )
      {
         default:
            snprintf( buf, sizeof( buf ), "Affects %s by %d.", affect_loc_name( paf->location ), paf->modifier );
            break;

         case APPLY_STAT:
            snprintf( buf, sizeof( buf ), "Affects %s by %d.", ext_flag_string( &paf->bitvector, stattypes ), paf->modifier );
            break;

         case APPLY_EXT_AFFECT:
            snprintf( buf, sizeof( buf ), "Affects %s by %s.", affect_loc_name( paf->location ), a_flags[paf->modifier] );
            break;

         case APPLY_WEAPONSPELL:
         case APPLY_WEARSPELL:
         case APPLY_REMOVESPELL:
            snprintf( buf, sizeof( buf ), "Casts spell '%s'.", is_valid_sn( paf->modifier ) ? skill_table[paf->modifier]->name : "unknown" );
            break;

         case APPLY_RESISTANT:
         case APPLY_IMMUNE:
         case APPLY_ABSORB:
         case APPLY_SUSCEPTIBLE:
            snprintf( buf, sizeof( buf ), "Affects %s by %s.", affect_loc_name( paf->location ), ris_flags[paf->modifier] );
            break;
      }
      if( extdisplay )
         mudstrlcat( buf, " (Extra)\r\n", sizeof( buf ) );
      else
         mudstrlcat( buf, "\r\n", sizeof( buf ) );
      send_to_char( buf, ch );
   }
}