#include "h/mud.h"
#include "h/files.h"
#include "h/languages.h"
#include "h/key.h"
#ifndef WIN32
#include <unistd.h>
#endif
int get_risflag(char *flag);
int get_langflag(char *flag);
int get_langnum(char *flag);
int get_defenseflag(char *flag);
int get_attackflag(char *flag);
extern bool load_race_file(const char *fname);
void write_race_file(int ra);
int MAX_PC_RACE;
RACE_TYPE *race_table[MAX_RACE];
const char *const npc_race[MAX_NPC_RACE] = {
"human", "elf", "dwarf", "halfling", "pixie", "ogre", // 5 with human zero
"orc", "troll", "shade", "goblin", "drow", "gnome", // 11
"centaur", "dragon", "vampire", "celestial", "demon", "mindflayer", // 17
/* Above this line should be all player races */
"ant", "ape", "baboon", "bat", "bear", // 22
"bee", "beetle", "boar", "bugbear", "cat", "dog", // 28
"plant", "ferret", "fly", "gargoyle", "gelatin", "ghoul", // 34
"gnoll", "r29", "golem", "gorgon", "harpy", // 39
"hobgoblin", "kobold", "locust", "lycanthrope", "minotaur", // 44
"mold", "mule", "neanderthal", "ooze", "r43", "rat", // 50
"rustmonster", "shadow", "shapeshifter", "shrew", "shrieker", "skeleton", // 56
"slime", "snake", "spider", "stirge", "thoul", "troglodyte", // 62
"undead", "wight", "wolf", "worm", "zombie", "bovine", // 68
"canine", "feline", "porcine", "mammal", "rodent", "avis", // 74
"reptile", "amphibian", "fish", "crustacean", "insect", "spirit", // 80
"magical", "horse", "animal", "humanoid", "monster", "god", // 86
"avian", "badger", "beaver", "wolverine", "lion" // 92
};
char *const raceflags[] = {
(char *)"advanced"
};
int get_raceflag(char *flag);
void free_all_races(void)
{
int hash, loopa;
for(hash = 0; hash < MAX_RACE; hash++)
{
for(loopa = 0; loopa < MAX_WHERE_NAME; loopa++)
if(race_table[hash]->where_name[loopa])
STRFREE(race_table[hash]->where_name[loopa]);
DISPOSE(race_table[hash]);
}
}
/*
* Create an instance of a new race. -Shaddai
*/
bool create_new_race(int race, char *argument)
{
int i = 0;
if(!VLD_STR(argument))
return FALSE;
if(race >= MAX_RACE || race_table[race] == NULL)
return FALSE;
for(i = 0; i <= MAX_WHERE_NAME; i++)
race_table[race]->where_name[i] = STRALLOC(where_name[i]);
argument[0] = UPPER(argument[0]);
snprintf(race_table[race]->race_name, 16, "%-.16s", argument);
race_table[race]->sdbonus = 0;
race_table[race]->base_str = 0;
race_table[race]->base_dex = 0;
race_table[race]->base_wis = 0;
race_table[race]->base_int = 0;
race_table[race]->base_con = 0;
race_table[race]->base_cha = 0;
race_table[race]->base_lck = 0;
race_table[race]->hit = 0;
race_table[race]->mana = 0;
xCLEAR_BITS(race_table[race]->affected);
race_table[race]->resist = 0;
race_table[race]->suscept = 0;
race_table[race]->language = 0;
race_table[race]->alignment = 0;
race_table[race]->minalign = 0;
race_table[race]->maxalign = 0;
race_table[race]->ac_plus = 0;
race_table[race]->exp_multiplier = 0;
xCLEAR_BITS(race_table[race]->attacks);
xCLEAR_BITS(race_table[race]->defenses);
race_table[race]->height = 0;
race_table[race]->weight = 0;
race_table[race]->hunger_mod = 0;
race_table[race]->thirst_mod = 0;
race_table[race]->mana_regen = 0;
race_table[race]->hp_regen = 0;
race_table[race]->race_recall = 0;
return TRUE;
}
/*
* Load in all the race files.
*/
void load_races()
{
FILE *fpList;
const char *filename;
char racelist[256];
int i;
MAX_PC_RACE = 0;
/*
* Pre-init the race_table with blank races
*/
for(i = 0; i < MAX_RACE; i++)
race_table[i] = NULL;
snprintf(racelist, 256, "%s%s", RACEDIR, RACE_LIST);
if((fpList = FileOpen(racelist, "r")) == NULL)
{
perror(racelist);
exit(1);
}
for(;;)
{
filename = feof(fpList) ? "$" : fread_word(fpList);
if(filename[0] == '$')
break;
if(!load_race_file(filename))
{
bug("Cannot load race file: %s", filename);
}
else
MAX_PC_RACE++;
}
for(i = 0; i < MAX_RACE; i++)
{
if(race_table[i] == NULL)
{
CREATE(race_table[i], struct race_type, 1);
snprintf(race_table[i]->race_name, 16, "%s", "unused");
}
}
FileClose(fpList);
return;
}
void write_race_file(int ra)
{
FILE *fpout;
char filename[MIL];
struct race_type *race = race_table[ra];
int i;
int x, y;
if(!race->race_name)
{
bug("Race %d has null name, not writing .race file.", ra);
return;
}
snprintf(filename, MIL, "%s%s.race", RACEDIR, race->race_name);
if((fpout = FileOpen(filename, "w+")) == NULL)
{
bug("Cannot open: %s for writing", filename);
return;
}
if(VLD_STR(race->race_name))
fprintf(fpout, "Name %s~\n", race->race_name);
fprintf(fpout, "Race %d\n", ra);
fprintf(fpout, "SDbonus %d\n", race->sdbonus);
fprintf(fpout, "Base_Str %d\n", race->base_str);
fprintf(fpout, "Base_Dex %d\n", race->base_dex);
fprintf(fpout, "Base_Wis %d\n", race->base_wis);
fprintf(fpout, "Base_Int %d\n", race->base_int);
fprintf(fpout, "Base_Con %d\n", race->base_con);
fprintf(fpout, "Base_Cha %d\n", race->base_cha);
fprintf(fpout, "Base_Lck %d\n", race->base_lck);
fprintf(fpout, "Hit %d\n", race->hit);
fprintf(fpout, "Mana %d\n", race->mana);
fprintf(fpout, "Affected %s\n", print_bitvector(&race->affected));
fprintf(fpout, "Resist %d\n", race->resist);
fprintf(fpout, "Suscept %d\n", race->suscept);
fprintf(fpout, "Language %d\n", race->language);
fprintf(fpout, "Align %d\n", race->alignment);
fprintf(fpout, "Min_Align %d\n", race->minalign);
fprintf(fpout, "Max_Align %d\n", race->maxalign);
fprintf(fpout, "AC_Plus %d\n", race->ac_plus);
fprintf(fpout, "Exp_Mult %d\n", race->exp_multiplier);
if(!xIS_EMPTY(race->attacks))
fprintf(fpout, "Attacks %s\n", print_bitvector(&race->attacks));
if(!xIS_EMPTY(race->defenses))
fprintf(fpout, "Defenses %s\n", print_bitvector(&race->defenses));
fprintf(fpout, "Height %d\n", race->height);
fprintf(fpout, "Weight %d\n", race->weight);
fprintf(fpout, "Flags %s\n", print_bitvector(&race->flags));
fprintf(fpout, "Hunger_Mod %d\n", race->hunger_mod);
fprintf(fpout, "Thirst_mod %d\n", race->thirst_mod);
fprintf(fpout, "Mana_Regen %d\n", race->mana_regen);
fprintf(fpout, "HP_Regen %d\n", race->hp_regen);
fprintf(fpout, "Race_Recall %d\n", race->race_recall);
for(i = 0; i < MAX_WHERE_NAME; i++)
fprintf(fpout, "WhereName %s~\n", race->where_name[i]);
for(x = 0; x < top_sn; x++)
{
if(!skill_table[x]->name || skill_table[x]->name[0] == '\0')
break;
if((y = skill_table[x]->race_level[ra]) < LEVEL_IMMORTAL)
fprintf(fpout, "Skill '%s' %d %d\n", skill_table[x]->name, y, skill_table[x]->race_adept[ra]);
}
fprintf(fpout, "End\n");
FileClose(fpout);
}
bool load_race_file(const char *fname)
{
char buf[MSL];
const char *word;
char *race_name = NULL;
bool fMatch;
struct race_type *race;
int ra = -1;
FILE *fp;
int i, wear = 0;
snprintf(buf, MSL, "%s%s", RACEDIR, fname);
// snprintf(buf, MSL, "%s", fname);
if((fp = FileOpen(buf, "r")) == NULL)
{
perror(buf);
return FALSE;
}
CREATE(race, struct race_type, 1);
for(i = 0; i < MAX_WHERE_NAME; i++)
race->where_name[i] = STRALLOC(where_name[i]);
for(;;)
{
word = feof(fp) ? "End" : fread_word(fp);
fMatch = FALSE;
switch (UPPER(word[0]))
{
case '*':
fMatch = TRUE;
fread_to_eol(fp);
break;
case 'A':
KEY("Align", race->alignment, fread_number(fp));
KEY("AC_Plus", race->ac_plus, fread_number(fp));
KEY("Affected", race->affected, fread_bitvector(fp));
KEY("Attacks", race->attacks, fread_bitvector(fp));
break;
case 'B':
KEY("Base_Dex", race->base_dex, fread_number(fp));
KEY("Base_Int", race->base_int, fread_number(fp));
KEY("Base_Lck", race->base_lck, fread_number(fp));
KEY("Base_Con", race->base_con, fread_number(fp));
KEY("Base_Cha", race->base_cha, fread_number(fp));
KEY("Base_Wis", race->base_wis, fread_number(fp));
KEY("Base_Str", race->base_str, fread_number(fp));
break;
case 'D':
KEY("Defenses", race->defenses, fread_bitvector(fp));
break;
case 'E':
if(!str_cmp(word, "End"))
{
FileClose(fp);
if(ra < 0 || ra >= MAX_RACE)
{
bug("Load_race_file: Race (%s) bad/not found (%d)", race->race_name ? race->race_name : race_name ? race_name : "name not found", ra);
if(race_name)
STRFREE(race_name);
DISPOSE(race);
return FALSE;
}
race_table[ra] = race;
if(race_name)
STRFREE(race_name);
return TRUE;
}
KEY("Exp_Mult", race->exp_multiplier, fread_number(fp));
break;
case 'F':
KEY("Flags", race->flags, fread_bitvector(fp));
break;
case 'H':
KEY("Height", race->height, fread_number(fp));
KEY("Hit", race->hit, fread_number(fp));
KEY("HP_Regen", race->hp_regen, fread_number(fp));
KEY("Hunger_Mod", race->hunger_mod, fread_number(fp));
break;
case 'L':
KEY("Language", race->language, fread_number(fp));
break;
case 'M':
KEY("Mana", race->mana, fread_number(fp));
KEY("Mana_Regen", race->mana_regen, fread_number(fp));
KEY("Min_Align", race->minalign, fread_number(fp));
KEY("Max_Align", race->maxalign, fread_number(fp));
break;
case 'N':
KEY("Name", race_name, fread_string(fp));
break;
case 'R':
KEY("Race", ra, fread_number(fp));
KEY("Race_Recall", race->race_recall, fread_number(fp));
KEY("Resist", race->resist, fread_number(fp));
break;
case 'S':
KEY("SDbonus", race->sdbonus, fread_number(fp));
KEY("Suscept", race->suscept, fread_number(fp));
if(!str_cmp(word, "Skill"))
{
int sn, lev, adp;
word = fread_word(fp);
lev = fread_number(fp);
adp = fread_number(fp);
sn = skill_lookup(word);
if(ra < 0 || ra >= MAX_RACE)
bug("load_race_file: Skill %s -- race bad/not found (%d)", word, ra);
else if(!IS_VALID_SN(sn))
bug("load_race_file: Skill %s unknown", word);
else
{
skill_table[sn]->race_level[ra] = lev;
skill_table[sn]->race_adept[ra] = adp;
}
fMatch = TRUE;
break;
}
break;
case 'T':
KEY("Thirst_Mod", race->thirst_mod, fread_number(fp));
break;
case 'W':
KEY("Weight", race->weight, fread_number(fp));
if(!str_cmp(word, "WhereName"))
{
if(ra < 0 || ra >= MAX_RACE)
{
bug("load_race_file: Title -- race bad/not found (%d)", ra);
fread_flagstring(fp);
fread_flagstring(fp);
}
else if(wear < MAX_WHERE_NAME)
{
if(VLD_STR(race->where_name[wear]))
STRFREE(race->where_name[wear]);
race->where_name[wear] = fread_string(fp);
++wear;
}
else
bug("%s", "load_race_file: Too many where_names");
fMatch = TRUE;
break;
}
break;
}
if(race_name != NULL)
snprintf(race->race_name, 16, "%-.16s", race_name);
if(!fMatch)
{
bug("load_race_file: no match: %s", word);
fread_to_eol(fp);
}
}
return FALSE;
}
void do_races(CHAR_DATA *ch, char *argument)
{
int iRace = 0;
int counter = 0;
if(!IS_IMMORTAL(ch))
counter = 1;
send_to_pager("\r\n", ch);
for(iRace = 0; iRace < MAX_PC_RACE; iRace++)
{
if(!IS_IMMORTAL(ch) && !VLD_STR(race_table[iRace]->race_name))
continue;
pager_printf(ch, "&g[&G%2d&g]&W %-10s", counter, race_table[iRace]->race_name);
if(IS_IMMORTAL(ch))
pager_printf(ch, "%-1s &gMultiplier:&W %-5d &gHit: &W%-3d &gMana: &W%-3d", "", race_table[iRace]->exp_multiplier, race_table[iRace]->hit, race_table[iRace]->mana);
pager_printf(ch, "\r\n");
counter++;
}
return;
}
void update_racelist(void)
{
char racelist[256];
int i;
FILE *fpList;
snprintf(racelist, 256, "%s%s", RACEDIR, RACE_LIST);
if((fpList = FileOpen(racelist, "w")) == NULL)
{
bug("%s", "Error opening racelist.");
return;
}
for(i = 0; i < MAX_PC_RACE; i++)
fprintf(fpList, "%s.race\n", race_table[i]->race_name);
fprintf(fpList, "%s", "$\n");
FileClose(fpList);
return;
}
/* Modified by Samson to allow setting language by name - 8-6-98 */
void do_setrace(CHAR_DATA *ch, char *argument)
{
struct race_type *race;
char buf[MSL], arg1[MIL], arg2[MIL], arg3[MIL];
int value, v2, ra;
set_char_color(AT_PLAIN, ch);
smash_tilde(argument);
argument = one_argument(argument, arg1);
argument = one_argument(argument, arg2);
if(arg1[0] == '\0' || arg2[0] == '\0')
{
send_to_char("Syntax: setrace <race> <field> <value>\r\n", ch);
send_to_char("Syntax: setrace <race> create\r\n", ch);
send_to_char("Syntax: setrace <race> save\r\n", ch);
send_to_char("\r\nField being one of:\r\n", ch);
send_to_char(" name strplus dexplus wisplus\r\n", ch);
send_to_char(" intplus conplus chaplus lckplus hit\r\n", ch);
send_to_char(" mana affected resist suscept language\r\n", ch);
send_to_char(" attack defense alignment acplus\r\n", ch);
send_to_char(" minalign maxalign height weight\r\n", ch);
send_to_char(" hungermod thirstmod expmultiplier\r\n", ch);
send_to_char(" saving_poison_death saving_wand\r\n", ch);
send_to_char(" saving_para_petri saving_breath\r\n", ch);
send_to_char(" saving_spell_staff\r\n", ch);
send_to_char(" mana_regen hp_regen sdbonus\r\n", ch);
send_to_char(" flags\r\n", ch);
return;
}
if(is_number(arg1) && (ra = atoi(arg1)) >= 0 && ra < MAX_RACE)
race = race_table[ra];
else
{
race = NULL;
for(ra = 0; ra < MAX_RACE && race_table[ra]; ra++)
{
if(!race_table[ra]->race_name)
continue;
if(!str_cmp(race_table[ra]->race_name, arg1))
{
race = race_table[ra];
break;
}
}
}
if(!str_cmp(arg2, "create") && race)
{
send_to_char("That race already exists!\r\n", ch);
return;
}
else if(!race && str_cmp(arg2, "create"))
{
send_to_char("No such race.\r\n", ch);
return;
}
if(!str_cmp(arg2, "create"))
{
if(MAX_PC_RACE >= MAX_RACE)
{
send_to_char("You need to up MAX_RACE in mud.h and make clean.\r\n", ch);
return;
}
if((create_new_race(MAX_PC_RACE, arg1)) == FALSE)
{
send_to_char("Couldn't create a new race.\r\n", ch);
return;
}
MAX_PC_RACE++;
update_racelist();
ra = MAX_PC_RACE;
write_race_file(MAX_PC_RACE);
send_to_char("New race created.\r\n", ch);
return;
}
if(!str_cmp(arg2, "save"))
{
write_race_file(ra);
send_to_char("Saved.\r\n", ch);
return;
}
if(!VLD_STR(argument))
{
send_to_char("You must specify an argument.\r\n", ch);
return;
}
if(!str_cmp(arg2, "name"))
{
snprintf(buf, MSL, "%s%s.race", RACEDIR, race->race_name);
snprintf(race->race_name, 16, "%-.16s", capitalize(argument));
write_race_file(ra);
unlink(buf);
update_racelist();
send_to_char("Race name set.\r\n", ch);
return;
}
if(!str_cmp(arg2, "flags"))
{
value = get_raceflag(argument);
if(value < 0 || value > MAX_BITS)
ch_printf(ch, "Unknown flag: %s\r\n", argument);
else
{
xTOGGLE_BIT(race->flags, value);
send_to_char("Done.\r\n", ch);
}
return;
}
if(!str_cmp(arg2, "sdbonus"))
race->sdbonus = (short)atoi(argument);
else if(!str_cmp(arg2, "basestr"))
race->base_str = (short)atoi(argument);
else if(!str_cmp(arg2, "basedex"))
race->base_dex = (short)atoi(argument);
else if(!str_cmp(arg2, "basewis"))
race->base_wis = (short)atoi(argument);
else if(!str_cmp(arg2, "baseint"))
race->base_int = (short)atoi(argument);
else if(!str_cmp(arg2, "basecon"))
race->base_con = (short)atoi(argument);
else if(!str_cmp(arg2, "basecha"))
race->base_cha = (short)atoi(argument);
else if(!str_cmp(arg2, "baselck"))
race->base_lck = (short)atoi(argument);
else if(!str_cmp(arg2, "hit"))
race->hit = (short)atoi(argument);
else if(!str_cmp(arg2, "mana"))
race->mana = (short)atoi(argument);
else if(!str_cmp(arg2, "affected"))
{
if(!VLD_STR(argument))
{
send_to_char("Usage: setrace <race> affected <flag> [flag]...\r\n", ch);
return;
}
while(VLD_STR(argument))
{
argument = one_argument(argument, arg3);
value = get_aflag(arg3);
if(value < 0 || value > MAX_BITS)
ch_printf(ch, "Unknown flag: %s\r\n", arg3);
else
xTOGGLE_BIT(race->affected, value);
}
}
else if(!str_cmp(arg2, "resist"))
{
if(!VLD_STR(argument))
{
send_to_char("Usage: setrace <race> resist <flag> [flag]...\r\n", ch);
return;
}
while(VLD_STR(argument))
{
argument = one_argument(argument, arg3);
value = get_risflag(arg3);
if(value < 0 || value > 31)
ch_printf(ch, "Unknown flag: %s\r\n", arg3);
else
TOGGLE_BIT(race->resist, 1 << value);
}
}
else if(!str_cmp(arg2, "suscept"))
{
if(!VLD_STR(argument))
{
send_to_char("Usage: setrace <race> suscept <flag> [flag]...\r\n", ch);
return;
}
while(VLD_STR(argument))
{
argument = one_argument(argument, arg3);
value = get_risflag(arg3);
if(value < 0 || value > 31)
ch_printf(ch, "Unknown flag: %s\r\n", arg3);
else
TOGGLE_BIT(race->suscept, 1 << value);
}
}
else if(!str_cmp(arg2, "language"))
{
argument = one_argument(argument, arg3);
value = get_langflag(arg3);
if(value == LANG_UNKNOWN)
{
ch_printf(ch, "Unknown language: %s\r\n", arg3);
return;
}
else
{
if(!(value &= VALID_LANGS))
ch_printf(ch, "Player races may not speak %s.\r\n", arg3);
}
v2 = get_langnum(arg3);
if(v2 == -1)
ch_printf(ch, "Unknown language: %s\r\n", arg3);
else
TOGGLE_BIT(race->language, 1 << v2);
}
else if(!str_cmp(arg2, "acplus"))
race->ac_plus = atoi(argument);
else if(!str_cmp(arg2, "alignment"))
race->alignment = atoi(argument);
else if(!str_cmp(arg2, "defense"))
{
if(!VLD_STR(argument))
{
send_to_char("Usage: setrace <race> defense <flag> [flag]...\r\n", ch);
return;
}
while(VLD_STR(argument))
{
argument = one_argument(argument, arg3);
value = get_defenseflag(arg3);
if(value < 0 || value > MAX_BITS)
ch_printf(ch, "Unknown flag: %s\r\n", arg3);
else
xTOGGLE_BIT(race->defenses, value);
}
}
else if(!str_cmp(arg2, "attack"))
{
if(!VLD_STR(argument))
{
send_to_char("Usage: setrace <race> attack <flag> [flag]...\r\n", ch);
return;
}
while(VLD_STR(argument))
{
argument = one_argument(argument, arg3);
value = get_attackflag(arg3);
if(value < 0 || value > MAX_BITS)
ch_printf(ch, "Unknown flag: %s\r\n", arg3);
else
xTOGGLE_BIT(race->attacks, value);
}
}
else if(!str_cmp(arg2, "minalign"))
race->minalign = atoi(argument);
else if(!str_cmp(arg2, "maxalign"))
race->maxalign = atoi(argument);
else if(!str_cmp(arg2, "height"))
race->height = atoi(argument);
else if(!str_cmp(arg2, "weight"))
race->weight = atoi(argument);
else if(!str_cmp(arg2, "thirstmod"))
race->thirst_mod = atoi(argument);
else if(!str_cmp(arg2, "hungermod"))
race->hunger_mod = atoi(argument);
else if(!str_cmp(arg2, "maxalign"))
race->maxalign = atoi(argument);
else if(!str_cmp(arg2, "expmultiplier"))
race->exp_multiplier = atoi(argument);
else if(!str_cmp(arg2, "saving_poison_death"))
race->saving_poison_death = atoi(argument);
else if(!str_cmp(arg2, "saving_wand"))
race->saving_wand = atoi(argument);
else if(!str_cmp(arg2, "saving_para_petri"))
race->saving_para_petri = atoi(argument);
else if(!str_cmp(arg2, "saving_breath"))
race->saving_breath = atoi(argument);
else if(!str_cmp(arg2, "saving_spell_staff"))
race->saving_spell_staff = atoi(argument);
else if(!str_cmp(arg2, "mana_regen"))
race->mana_regen = atoi(argument);
else if(!str_cmp(arg2, "hp_regen"))
race->hp_regen = atoi(argument);
#ifdef NEW_RACE_STUFF
else if(!str_cmp(arg2, "carry_weight"))
race->acplus = atoi(argument);
else if(!str_cmp(arg2, "carry_number"))
race->acplus = atoi(argument);
#endif
else
{
do_setrace(ch, (char *)"");
return;
}
write_race_file(ra);
ch_printf(ch, "Updated %s on race %s[%d].\r\n", arg2, (race_table[ra] && VLD_STR(race_table[ra]->race_name)) ? race_table[ra]->race_name : "(Unknown)", ra);
return;
}
void do_showrace(CHAR_DATA *ch, char *argument)
{
char arg1[MIL];
struct race_type *race;
int ra;
set_pager_color(AT_PLAIN, ch);
argument = one_argument(argument, arg1);
if(!VLD_STR(arg1))
{
do_races(ch, (char *)"");
return;
}
if(is_number(arg1) && (ra = atoi(arg1)) >= 0 && ra < MAX_RACE)
race = race_table[ra];
else
{
race = NULL;
for(ra = 0; ra < MAX_RACE && race_table[ra]; ra++)
if(!str_cmp(race_table[ra]->race_name, arg1))
{
race = race_table[ra];
break;
}
}
if(!race)
{
send_to_char("No such race.\r\n", ch);
return;
}
if(xIS_SET(race->flags, RACE_ADVANCED))
ch_printf(ch, "ADVANCED RACE: %s\r\n", race->race_name);
else
ch_printf(ch, "RACE: %s\r\n", race->race_name);
ch_printf(ch, "Base: Str: %-3d Dex: %-3d Wis: %-3d Int: %-3d\r\n", race->base_str, race->base_dex, race->base_wis, race->base_int);
ch_printf(ch, " Con: %-3d Cha: %-3d Lck: %-3d\r\n", race->base_con, race->base_cha, race->base_lck);
ch_printf(ch, "Hit Pts: %-3d\tMana: %-3d\tAlign: %-4d\tAC: %-d\r\n", race->hit, race->mana, race->alignment, race->ac_plus);
ch_printf(ch, "Min Align: %d\tMax Align: %-d\t\tXP Mult: %-d%%\r\n", race->minalign, race->maxalign, race->exp_multiplier);
ch_printf(ch, "Height: %3d in.\t\tWeight: %4d lbs.\tHungerMod: %d\tThirstMod: %d\r\n", race->height, race->weight, race->hunger_mod, race->thirst_mod);
ch_printf(ch, "SDBonus: %d\r\n", race->sdbonus);
send_to_char("Affected by: ", ch);
send_to_char(!xIS_EMPTY(race->affected) ? ext_flag_string(&race->affected, a_flags) : "Nothing", ch);
send_to_char("\r\n", ch);
send_to_char("Resistant to: ", ch);
send_to_char(flag_string(race->resist, ris_flags), ch);
send_to_char("\r\n", ch);
send_to_char("Susceptible to: ", ch);
send_to_char(flag_string(race->suscept, ris_flags), ch);
send_to_char("\r\n", ch);
ch_printf(ch, "Saves: (P/D) %d (W) %d (P/P) %d (B) %d (S/S) %d\r\n", race->saving_poison_death, race->saving_wand, race->saving_para_petri, race->saving_breath, race->saving_spell_staff);
send_to_char("Innate Attacks: ", ch);
send_to_char(ext_flag_string(&race->attacks, attack_flags), ch);
send_to_char("\r\n", ch);
send_to_char("Innate Defenses: ", ch);
send_to_char(ext_flag_string(&race->defenses, defense_flags), ch);
send_to_char("\r\n", ch);
ch_printf(ch, "Spoken Language: %s", flag_string(race->language, lang_names));
send_to_char("\r\n", ch);
ch_printf(ch, "Race flags: %s\r\n", ext_flag_string(&race->flags, raceflags));
send_to_char("\r\n", ch);
return;
}
int get_raceflag(char *flag)
{
unsigned int x;
for(x = 0; x < (sizeof(raceflags) / sizeof(raceflags[0])); x++)
if(!str_cmp(flag, raceflags[x]))
return x;
return -1;
}
/*
int get_adv_class(int race)
{
int x;
for(x=0;x<MAX_CLASS;x++)
if(race_table[race] && class_table[x] && !str_cmp(race_table[race]->race_name, class_table[x]->who_name))
return x;
return -1;
}
*/