/*******************************************************************\
|* This file is support functions for Ammaross Danan's Unlimited *|
|* Bit System. This header is to remain intact. *|
|* - Kirk Johnson aka Ammaross Danan (ammaross@ardenmore.com) *|
|* http://www.ardenmore.com ARDENMOREDOI mud.ardenmore.com:5150 *|
\*******************************************************************/
#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "merc.h"
#include "tables.h"
#include "lookup.h"
#include "olc.h"
/* Moved to here from macro form to solve a read-in problem. */
void STR_COPY_STR( FLAG *a, const FLAG *b, const int size )
{
int i;
for( i = 0; i < size; i++ )
{
a[i] = b[i];
}
}
bool STR_IS_ZERO( FLAG * var, int size )
{
int i;
for( i = 0; i < size; i++ )
{
if( var[i] != 0 )
return FALSE;
}
return TRUE;
}
bool STR_AND( FLAG * var1, FLAG * var2, int size )
{
int i;
for( i = 0; i < size; i++ )
{
if( var1[i] & var2[i] )
return TRUE;
}
return FALSE;
}
/*
* Purpose: Returns the value of the flags entered.
*/
int str_flag_value( const struct flag_type *flag_table, char *argument)
{
char name[MAX_INPUT_LENGTH];
int flag;
argument = one_argument( argument, name );
if ( name[0] == '\0' )
return NO_FLAG;
for (flag = 0; flag_table[flag].name != NULL; flag++)
{
if (LOWER(name[0]) == LOWER(flag_table[flag].name[0])
&& !str_prefix(name,flag_table[flag].name))
return flag_table[flag].bit;
}
return NO_FLAG;
}
/*
* Purpose: Returns string with name(s) of the flags or stat entered.
*/
char *str_flag_string( const struct flag_type *flag_table, FLAG *bits )
{
static char buf[10][MIL];
int flag;
static int toggle;
toggle = (++toggle) % 10;
buf[toggle][0] = '\0';
for (flag = 0; !IS_NULLSTR( flag_table[flag].name ); flag++)
{
if ( STR_IS_SET(bits, flag_table[flag].bit) )
{
strcat( buf[toggle], " " );
strcat( buf[toggle], flag_table[flag].name );
}
}
return (buf[toggle][0] != '\0') ? buf[toggle] + 1 : "none";
}
/*
* Purpose: Used to read in bit arrays.
*/
FLAG *str_fread_flag( FILE *fp, const int size )
{
int i = 0;
int number;
static FLAG flag[MAX_FLAGS];
STR_ZERO_STR( flag, MAX_FLAGS );
while ( (number = fread_number(fp)) != -1 )
{
if ( i < size )
flag[i++] = number;
}
return flag;
}
/*
* Purpose: Used to write flags in the unlimited bit system.
* This setup allows the saved array to expand OR contract
* and still be able to load properly.
*/
char *str_fwrite_flag( FLAG *flags, const int size, char *out )
{
char buf[MIL];
int i;
out[0] = '\0';
for ( i = 0; i < size; i++ )
{
sprintf( buf, "%d ", flags[i] );
strcat( out, buf );
}
sprintf( buf, "-1 " );
strcat( out, buf );
return out;
}
/*
* Purpose: Used to write flags to file in the unlimited bit system.
* This setup allows the saved array to expand OR contract
* and still be able to load properly.
*/
char *str_print_flags( FLAG *flags, const int size )
{
static char buf[MIL];
char buf2[MIL];
int i;
buf[0] = '\0';
for ( i = 0; i < size; i++ )
{
sprintf( buf2, "%d ", flags[i] );
strcat( buf, buf2 );
}
sprintf( buf2, "-1" );
strcat( buf, buf2 );
return buf;
}
/*
* Used to get non-converted flags to work well under the new bit system
*/
void do_flag_norm( CHAR_DATA *ch, CHAR_DATA *victim, char *argument,
char type, long *flag, const struct flag_type *flag_table )
{
char word[MIL];
long old = 0, new = 0, marked = 0, pos;
old = *flag;
victim->zone = NULL;
if ( type != '=' )
new = old;
/* mark the words */
for (;;)
{
argument = one_argument( argument,word );
if ( IS_NULLSTR( word ) )
break;
pos = flag_lookup(word,flag_table);
if (pos == 0)
{
send_to_char("That flag doesn't exist!\n\r",ch);
return;
}
else
SET_BIT(marked,pos);
}
for (pos = 0; flag_table[pos].name != NULL; pos++)
{
if (!flag_table[pos].settable && IS_SET(old,flag_table[pos].bit))
{
SET_BIT(new,flag_table[pos].bit);
continue;
}
if (IS_SET(marked,flag_table[pos].bit))
{
switch(type)
{
case '=':
case '+':
SET_BIT(new,flag_table[pos].bit);
break;
case '-':
REMOVE_BIT(new,flag_table[pos].bit);
break;
default:
if (IS_SET(new,flag_table[pos].bit))
REMOVE_BIT(new,flag_table[pos].bit);
else
SET_BIT(new,flag_table[pos].bit);
}
}
}
*flag = new;
return;
}
/*
* Modified for use with unlimited bit flags
* Expandable if you want to want to convert COMM, RES, etc. over.
*/
void do_flag(CHAR_DATA *ch, char *argument)
{
char arg1[MIL];
char arg2[MIL];
char arg3[MIL];
char word[MIL];
CHAR_DATA *victim;
FLAG *flag = NULL;
FLAG old[MAX_FLAGS];
FLAG new[MAX_FLAGS];
FLAG marked[MAX_FLAGS];
int pos, size;
char type;
const struct flag_type *flag_table;
STR_ZERO_STR( old, MAX_FLAGS );
STR_ZERO_STR( new, MAX_FLAGS );
STR_ZERO_STR( marked, MAX_FLAGS );
argument = one_argument(argument,arg1);
argument = one_argument(argument,arg2);
argument = one_argument(argument,arg3);
type = argument[0];
if (type == '=' || type == '-' || type == '+')
argument = one_argument(argument,word);
if ( IS_NULLSTR( arg1 ) )
{
send_to_char("Syntax:\n\r",ch);
send_to_char(" flag mob <name> <field> <flags>\n\r",ch);
send_to_char(" flag char <name> <field> <flags>\n\r",ch);
send_to_char(" mob flags: act,aff,off,imm,res,vuln,form,part\n\r",ch);
send_to_char(" char flags: plr,comm,aff,imm,res,vuln,\n\r",ch);
send_to_char(" +: add flag, -: remove flag, = set equal to\n\r",ch);
send_to_char(" otherwise flag toggles the flags listed.\n\r",ch);
return;
}
if ( IS_NULLSTR( arg2 ) )
{
send_to_char("What do you wish to set flags on?\n\r",ch);
return;
}
if ( IS_NULLSTR( arg3 ) )
{
send_to_char("You need to specify a flag to set.\n\r",ch);
return;
}
if ( IS_NULLSTR( argument ) )
{
send_to_char("Which flags do you wish to change?\n\r",ch);
return;
}
if (!str_prefix(arg1,"mob") || !str_prefix(arg1,"char"))
{
victim = get_char_world(ch,arg2);
if (victim == NULL)
{
send_to_char("You can't find them.\n\r",ch);
return;
}
/* select a flag to set */
if (!str_prefix(arg3,"act"))
{
if (!IS_NPC(victim))
{
send_to_char("Use plr for PCs.\n\r",ch);
return;
}
do_flag_norm( ch, victim, argument, type, &victim->form, form_flags );
return;
}
else if (!str_prefix(arg3,"plr"))
{
if (IS_NPC(victim))
{
send_to_char("Use act for NPCs.\n\r",ch);
return;
}
do_flag_norm( ch, victim, argument, type, &victim->form, plr_flags );
return;
}
else if (!str_prefix(arg3,"aff"))
{
size = AFF_FLAGS;
flag = victim->affected_by;
flag_table = affect_flags;
}
else if (!str_prefix(arg3,"immunity"))
{
do_flag_norm( ch, victim, argument, type, &victim->imm_flags, imm_flags );
return;
}
else if (!str_prefix(arg3,"resist"))
{
do_flag_norm( ch, victim, argument, type, &victim->res_flags, res_flags );
return;
}
else if (!str_prefix(arg3,"vuln"))
{
do_flag_norm( ch, victim, argument, type, &victim->vuln_flags, vuln_flags );
return;
}
else if (!str_prefix(arg3,"form"))
{
if (!IS_NPC(victim))
{
send_to_char("Form can't be set on PCs.\n\r",ch);
return;
}
do_flag_norm( ch, victim, argument, type, &victim->form, form_flags );
return;
}
else if (!str_prefix(arg3,"parts"))
{
if (!IS_NPC(victim))
{
send_to_char("Parts can't be set on PCs.\n\r",ch);
return;
}
do_flag_norm( ch, victim, argument, type, &victim->parts, part_flags );
return;
}
else if (!str_prefix(arg3,"comm"))
{
if (IS_NPC(victim))
{
send_to_char("Comm can't be set on NPCs.\n\r",ch);
return;
}
do_flag_norm( ch, victim, argument, type, &victim->comm, comm_flags );
return;
}
else
{
send_to_char("That's not an acceptable flag.\n\r",ch);
return;
}
STR_COPY_STR( old, flag, MAX_FLAGS );
victim->zone = NULL;
if (type != '=')
STR_COPY_STR( new, old, MAX_FLAGS );
/* mark the words */
for (; ;)
{
argument = one_argument(argument,word);
if ( IS_NULLSTR( word ) )
break;
pos = flag_lookup(word,flag_table);
if (pos == 0)
{
send_to_char("That flag doesn't exist!\n\r",ch);
return;
}
else
STR_SET_BIT(marked,pos);
}
for (pos = 0; !IS_NULLSTR( flag_table[pos].name ); pos++)
{
if (!flag_table[pos].settable && STR_IS_SET(old,flag_table[pos].bit))
{
STR_SET_BIT(new,flag_table[pos].bit);
continue;
}
if (STR_IS_SET(marked,flag_table[pos].bit))
{
switch(type)
{
case '=':
case '+':
STR_SET_BIT(new,flag_table[pos].bit);
break;
case '-':
STR_REMOVE_BIT(new,flag_table[pos].bit);
break;
default:
if (STR_IS_SET(new,flag_table[pos].bit))
STR_REMOVE_BIT(new,flag_table[pos].bit);
else
STR_SET_BIT(new,flag_table[pos].bit);
}
}
}
STR_COPY_STR( flag, new, size );
return;
}
}
/*
* Return ascii name of an affect bit vector.
*/
char *affect_str_bit_name( FLAG *vector )
{
static char buf[MSL];
buf[0] = '\0';
if (STR_IS_SET(vector, AFF_BLIND) )
strcat( buf, " blind" );
if (STR_IS_SET(vector, AFF_INVISIBLE) )
strcat( buf, " invisible" );
if (STR_IS_SET(vector, AFF_DETECT_EVIL) )
strcat( buf, " detect_evil" );
if (STR_IS_SET(vector, AFF_DETECT_GOOD) )
strcat( buf, " detect_good" );
if (STR_IS_SET(vector, AFF_DETECT_INVIS) )
strcat( buf, " detect_invis" );
if (STR_IS_SET(vector, AFF_DETECT_MAGIC) )
strcat( buf, " detect_magic" );
if (STR_IS_SET(vector, AFF_DETECT_HIDDEN) )
strcat( buf, " detect_hidden" );
if (STR_IS_SET(vector, AFF_SANCTUARY) )
strcat( buf, " sanctuary" );
if (STR_IS_SET(vector, AFF_FAERIE_FIRE) )
strcat( buf, " faerie_fire" );
if (STR_IS_SET(vector, AFF_INFRARED) )
strcat( buf, " infrared" );
if (STR_IS_SET(vector, AFF_CURSE) )
strcat( buf, " curse" );
if (STR_IS_SET(vector, AFF_POISON) )
strcat( buf, " poison" );
if (STR_IS_SET(vector, AFF_PROTECT_EVIL) )
strcat( buf, " prot_evil" );
if (STR_IS_SET(vector, AFF_PROTECT_GOOD) )
strcat( buf, " prot_good" );
if (STR_IS_SET(vector, AFF_SLEEP) )
strcat( buf, " sleep" );
if (STR_IS_SET(vector, AFF_SNEAK) )
strcat( buf, " sneak" );
if (STR_IS_SET(vector, AFF_HIDE) )
strcat( buf, " hide" );
if (STR_IS_SET(vector, AFF_CHARM) )
strcat( buf, " charm" );
if (STR_IS_SET(vector, AFF_FLYING) )
strcat( buf, " flying" );
if (STR_IS_SET(vector, AFF_PASS_DOOR) )
strcat( buf, " pass_door" );
if (STR_IS_SET(vector, AFF_BERSERK) )
strcat( buf, " berserk" );
if (STR_IS_SET(vector, AFF_CALM) )
strcat( buf, " calm" );
if (STR_IS_SET(vector, AFF_HASTE) )
strcat( buf, " haste" );
if (STR_IS_SET(vector, AFF_SLOW) )
strcat( buf, " slow" );
if (STR_IS_SET(vector, AFF_PLAGUE) )
strcat( buf, " plague" );
if (STR_IS_SET(vector, AFF_DARK_VISION) )
strcat( buf, " dark_vision" );
/* Just add any additional AFF flags you may have here.
* Yes, even your AFF2 flags */
return ( buf[0] != '\0' ) ? buf+1 : "none";
}
FLAG *aff_convert_fread_flag( long bits )
{
static FLAG flags[AFF_FLAGS];
long i;
int j;
STR_ZERO_STR( flags, AFF_FLAGS );
if ( bits == 0 )
return flags;
for ( j = 1, i = 1; i <= ee && j < 32; j++, i*=2 )
{
if ( IS_SET( bits, i ) )
STR_SET_BIT( flags, j );
if ( i == ee )
break;
}
return flags;
}
/* Used to convert aff bits read in as bitvectors in affect structs */
int aff_bit_convert_fread_flag( long bits )
{
long i;
int j;
if ( bits == 0 )
return 0;
for ( j = 1, i = 1; i <= ee && j < 32; j++, i*=2 )
{
if ( IS_SET( bits, i ) )
return j;
if ( i == ee )
break;
}
return 0;
}
/*
* If you have an aff2 type snippet added in, put this in:
FLAG *aff2_convert_fread_flag( long bits )
{
static FLAG flags[AFF_FLAGS];
long i;
int j;
STR_ZERO_STR( flags, AFF_FLAGS );
if ( bits == 0 )
return flags;
for ( j = 32, i = 1; i <= ee && j < AFF_FLAGS*FLAG_BITSIZE; j++, i*=2 )
{
if ( IS_SET( bits, i ) )
STR_SET_BIT( flags, j );
if ( i == ee )
break;
}
return flags;
}
*/
/*
* These aff conversions assume that you did a straight A = 1, B = 2, C = 3,
* type changing in your defines in merc.h. If there are any variations,
* here is the function I used when I converted my ACT flags:
FLAG *act_convert_fread_flag( long bits )
{
const int act_convert[32] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0, 0,
13, 14, 15, 16, 17, 18, 19, 20, 21, 0, 22, 0, 23,
24, 25, 26, 27 };
static FLAG flags[ACT_FLAGS];
long i;
int j;
STR_ZERO_STR( flags, ACT_FLAGS );
if ( bits == 0 )
return flags;
for ( j = 1, i = 1; i <= ee && j < 32; j++, i*=2 )
{
if ( IS_SET( bits, i ) )
STR_SET_BIT( flags, act_convert[j] );
if ( i == ee )
break;
}
return flags;
}
*/
/*
* The only thing you will need to change is the flag types of course
* (ACT_FLAGS to COMM_FLAGS for example) and the convert[32] table.
* convert[0] space should always equal 0. The next slots start
* counting A, B, C, D, etc. Just place the in corresponding number.
* IE, if you had AFF_INVISIBLE defined as A, but you defined it as 3
* this time, you would put a 3 in convert[1] spot. This function
* example was used mainly because ACT has gaps in its letter defines
* (filled in by zeroes in the convert[32] table).
*/
/*
* If you wanted to save space while converting over other flags that
* do not have gaps in their old defines (similar to AFF), this is the
* function I used to convert my COMM flags. Note: you do not need to
* add this if you will not be converting your COMM flags.
FLAG *comm_convert_fread_flag( long bits )
{
static FLAG flags[COMM_FLAGS];
STR_ZERO_STR( flags, COMM_FLAGS );
STR_COPY_STR( flags, aff_convert_fread_flag( bits ), COMM_FLAGS );
return flags;
}
*/