/***************************************************************************
* Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, *
* Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. *
* *
* Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael *
* Chastain, Michael Quan, and Mitchell Tse. *
* *
* In order to use any part of this Merc Diku Mud, you must comply with *
* both the original Diku license in 'license.doc' as well the Merc *
* license in 'license.txt'. In particular, you may not remove either of *
* these copyright notices. *
* *
* Much time and thought has gone into this software and you are *
* benefitting. We hope that you share your changes too. What goes *
* around, comes around. *
***************************************************************************/
/***************************************************************************
* ROM 2.4 is copyright 1993-1996 Russ Taylor *
* ROM has been brought to you by the ROM consortium *
* Russ Taylor (rtaylor@efn.org) *
* Gabrielle Taylor *
* Brian Moore (zump@rom.org) *
* By using this code, you have agreed to follow the terms of the *
* ROM license, in the file Rom24/doc/rom.license *
***************************************************************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <time.h>
#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#include <sys/time.h>
#endif
#include "merc.h"
#include "db.h"
#include "tables.h"
#include "lookup.h"
extern int flag_lookup args((const char *name, const struct flag_type *flag_table));
/* values for db2.c
struct social_type social_table [MAX_SOCIALS];
int social_count;
*/
/* snarf a socials file
void load_socials( FILE *fp)
{
for ( ; ; )
{
struct social_type social;
char *temp;
social.char_no_arg = NULL;
social.others_no_arg = NULL;
social.char_found = NULL;
social.others_found = NULL;
social.vict_found = NULL;
social.char_not_found = NULL;
social.char_auto = NULL;
social.others_auto = NULL;
temp = fread_word(fp);
if (!strcmp(temp,"#0"))
return;
#if defined(social_debug)
else
fprintf(stderr,"%s\n\r",temp);
#endif
strcpy(social.name,temp);
fread_to_eol(fp);
temp = fread_string_eol(fp);
if (!strcmp(temp,"$"))
social.char_no_arg = NULL;
else if (!strcmp(temp,"#"))
{
social_table[social_count] = social;
social_count++;
continue;
}
else
social.char_no_arg = temp;
temp = fread_string_eol(fp);
if (!strcmp(temp,"$"))
social.others_no_arg = NULL;
else if (!strcmp(temp,"#"))
{
social_table[social_count] = social;
social_count++;
continue;
}
else
social.others_no_arg = temp;
temp = fread_string_eol(fp);
if (!strcmp(temp,"$"))
social.char_found = NULL;
else if (!strcmp(temp,"#"))
{
social_table[social_count] = social;
social_count++;
continue;
}
else
social.char_found = temp;
temp = fread_string_eol(fp);
if (!strcmp(temp,"$"))
social.others_found = NULL;
else if (!strcmp(temp,"#"))
{
social_table[social_count] = social;
social_count++;
continue;
}
else
social.others_found = temp;
temp = fread_string_eol(fp);
if (!strcmp(temp,"$"))
social.vict_found = NULL;
else if (!strcmp(temp,"#"))
{
social_table[social_count] = social;
social_count++;
continue;
}
else
social.vict_found = temp;
temp = fread_string_eol(fp);
if (!strcmp(temp,"$"))
social.char_not_found = NULL;
else if (!strcmp(temp,"#"))
{
social_table[social_count] = social;
social_count++;
continue;
}
else
social.char_not_found = temp;
temp = fread_string_eol(fp);
if (!strcmp(temp,"$"))
social.char_auto = NULL;
else if (!strcmp(temp,"#"))
{
social_table[social_count] = social;
social_count++;
continue;
}
else
social.char_auto = temp;
temp = fread_string_eol(fp);
if (!strcmp(temp,"$"))
social.others_auto = NULL;
else if (!strcmp(temp,"#"))
{
social_table[social_count] = social;
social_count++;
continue;
}
else
social.others_auto = temp;
social_table[social_count] = social;
social_count++;
}
return;
}
*/
/*
* Snarf a mob section. new style
*/
void load_mobiles( FILE *fp )
{
MOB_INDEX_DATA *pMobIndex;
if ( !area_last ) /* OLC */
{
bug( "Load_mobiles: no #AREA seen yet.", 0 );
exit( 1 );
}
for ( ; ; )
{
sh_int vnum;
char letter;
int iHash;
letter = fread_letter( fp );
if ( letter != '#' )
{
bug( "Load_mobiles: # not found.", 0 );
exit( 1 );
}
vnum = fread_number( fp );
if ( vnum == 0 )
break;
fBootDb = FALSE;
if ( get_mob_index( vnum ) != NULL )
{
bug( "Load_mobiles: vnum %d duplicated.", vnum );
exit( 1 );
}
fBootDb = TRUE;
pMobIndex = alloc_perm( sizeof(*pMobIndex) );
pMobIndex->vnum = vnum;
pMobIndex->area = area_last; /*OLC*/
pMobIndex->new_format = TRUE;
newmobs++;
pMobIndex->player_name = fread_string( fp );
pMobIndex->short_descr = fread_string( fp );
pMobIndex->long_descr = fread_string( fp );
pMobIndex->description = fread_string( fp );
pMobIndex->race = race_lookup(fread_string( fp ));
pMobIndex->long_descr[0] = UPPER(pMobIndex->long_descr[0]);
pMobIndex->description[0] = UPPER(pMobIndex->description[0]);
pMobIndex->act = fread_flag( fp ) | ACT_IS_NPC
| race_table[pMobIndex->race].act;
pMobIndex->affected_by = fread_flag( fp )
| race_table[pMobIndex->race].aff;
pMobIndex->pShop = NULL;
pMobIndex->alignment = fread_number( fp );
pMobIndex->group = fread_number( fp );
pMobIndex->level = fread_number( fp );
pMobIndex->hitroll = fread_number( fp );
/* read hit dice */
pMobIndex->hit[DICE_NUMBER] = fread_number( fp );
/* 'd' */ fread_letter( fp );
pMobIndex->hit[DICE_TYPE] = fread_number( fp );
/* '+' */ fread_letter( fp );
pMobIndex->hit[DICE_BONUS] = fread_number( fp );
/* read mana dice */
pMobIndex->mana[DICE_NUMBER] = fread_number( fp );
fread_letter( fp );
pMobIndex->mana[DICE_TYPE] = fread_number( fp );
fread_letter( fp );
pMobIndex->mana[DICE_BONUS] = fread_number( fp );
/* read damage dice */
pMobIndex->damage[DICE_NUMBER] = fread_number( fp );
fread_letter( fp );
pMobIndex->damage[DICE_TYPE] = fread_number( fp );
fread_letter( fp );
pMobIndex->damage[DICE_BONUS] = fread_number( fp );
pMobIndex->dam_type = attack_lookup(fread_word(fp));
/* read armor class */
pMobIndex->ac[AC_PIERCE] = fread_number( fp ) * 10;
pMobIndex->ac[AC_BASH] = fread_number( fp ) * 10;
pMobIndex->ac[AC_SLASH] = fread_number( fp ) * 10;
pMobIndex->ac[AC_EXOTIC] = fread_number( fp ) * 10;
/* read flags and add in data from the race table */
pMobIndex->off_flags = fread_flag( fp )
| race_table[pMobIndex->race].off;
pMobIndex->imm_flags = fread_flag( fp )
| race_table[pMobIndex->race].imm;
pMobIndex->res_flags = fread_flag( fp )
| race_table[pMobIndex->race].res;
pMobIndex->vuln_flags = fread_flag( fp )
| race_table[pMobIndex->race].vuln;
/* vital statistics */
pMobIndex->start_pos = position_lookup(fread_word(fp));
pMobIndex->default_pos = position_lookup(fread_word(fp));
pMobIndex->sex = sex_lookup(fread_word(fp));
pMobIndex->wealth = fread_number( fp );
pMobIndex->form = fread_flag( fp )
| race_table[pMobIndex->race].form;
pMobIndex->parts = fread_flag( fp )
| race_table[pMobIndex->race].parts;
/* size */
CHECK_POS( pMobIndex->size, size_lookup(fread_word(fp)), "size" );
/* pMobIndex->size = size_lookup(fread_word(fp)); */
pMobIndex->material = str_dup(fread_word( fp ));
for ( ; ; )
{
letter = fread_letter( fp );
if (letter == 'F')
{
char *word;
long vector;
word = fread_word(fp);
vector = fread_flag(fp);
if (!str_prefix(word,"act"))
REMOVE_BIT(pMobIndex->act,vector);
else if (!str_prefix(word,"aff"))
REMOVE_BIT(pMobIndex->affected_by,vector);
else if (!str_prefix(word,"off"))
REMOVE_BIT(pMobIndex->off_flags,vector);
else if (!str_prefix(word,"imm"))
REMOVE_BIT(pMobIndex->imm_flags,vector);
else if (!str_prefix(word,"res"))
REMOVE_BIT(pMobIndex->res_flags,vector);
else if (!str_prefix(word,"vul"))
REMOVE_BIT(pMobIndex->vuln_flags,vector);
else if (!str_prefix(word,"for"))
REMOVE_BIT(pMobIndex->form,vector);
else if (!str_prefix(word,"par"))
REMOVE_BIT(pMobIndex->parts,vector);
else
{
bug("Flag remove: flag not found.",0);
exit(1);
}
}
else if ( letter == 'M' )
{
MPROG_LIST *pMprog;
char *word;
int trigger = 0;
pMprog = alloc_perm(sizeof(*pMprog));
word = fread_word( fp );
if ( !(trigger = flag_lookup( word, mprog_flags )) )
{
bug("MOBprogs: invalid trigger.",0);
exit(1);
}
SET_BIT( pMobIndex->mprog_flags, trigger );
pMprog->trig_type = trigger;
pMprog->vnum = fread_number( fp );
pMprog->trig_phrase = fread_string( fp );
pMprog->next = pMobIndex->mprogs;
pMobIndex->mprogs = pMprog;
}
else
{
ungetc(letter,fp);
break;
}
}
iHash = vnum % MAX_KEY_HASH;
pMobIndex->next = mob_index_hash[iHash];
mob_index_hash[iHash] = pMobIndex;
top_mob_index++;
top_vnum_mob = top_vnum_mob < vnum ? vnum : top_vnum_mob; /* OLC */
assign_area_vnum( vnum ); /* OLC */
kill_table[URANGE(0, pMobIndex->level, MAX_LEVEL-1)].number++;
}
return;
}
/*
* Snarf an obj section. new style
*/
void load_objects( FILE *fp )
{
OBJ_INDEX_DATA *pObjIndex;
if ( !area_last ) /* OLC */
{
bug( "Load_objects: no #AREA seen yet.", 0 );
exit( 1 );
}
for ( ; ; )
{
sh_int vnum;
char letter;
int iHash;
letter = fread_letter( fp );
if ( letter != '#' )
{
bug( "Load_objects: # not found.", 0 );
exit( 1 );
}
vnum = fread_number( fp );
if ( vnum == 0 )
break;
fBootDb = FALSE;
if ( get_obj_index( vnum ) != NULL )
{
bug( "Load_objects: vnum %d duplicated.", vnum );
exit( 1 );
}
fBootDb = TRUE;
pObjIndex = alloc_perm( sizeof(*pObjIndex) );
pObjIndex->vnum = vnum;
pObjIndex->area = area_last; /*OLC*/
pObjIndex->new_format = TRUE;
pObjIndex->reset_num = 0;
newobjs++;
pObjIndex->name = fread_string( fp );
pObjIndex->short_descr = fread_string( fp );
pObjIndex->description = fread_string( fp );
pObjIndex->material = fread_string( fp );
CHECK_POS(pObjIndex->item_type, item_lookup(fread_word( fp )), "item_type" );
pObjIndex->extra_flags = fread_flag( fp );
pObjIndex->wear_flags = fread_flag( fp );
switch(pObjIndex->item_type)
{
case ITEM_WEAPON:
pObjIndex->value[0] = weapon_type(fread_word(fp));
pObjIndex->value[1] = fread_number(fp);
pObjIndex->value[2] = fread_number(fp);
pObjIndex->value[3] = attack_lookup(fread_word(fp));
pObjIndex->value[4] = fread_flag(fp);
break;
case ITEM_CONTAINER:
pObjIndex->value[0] = fread_number(fp);
pObjIndex->value[1] = fread_flag(fp);
pObjIndex->value[2] = fread_number(fp);
pObjIndex->value[3] = fread_number(fp);
pObjIndex->value[4] = fread_number(fp);
break;
case ITEM_DRINK_CON:
case ITEM_FOUNTAIN:
pObjIndex->value[0] = fread_number(fp);
pObjIndex->value[1] = fread_number(fp);
CHECK_POS(pObjIndex->value[2], liq_lookup(fread_word(fp)), "liq_lookup" );
pObjIndex->value[3] = fread_number(fp);
pObjIndex->value[4] = fread_number(fp);
break;
case ITEM_WAND:
case ITEM_STAFF:
pObjIndex->value[0] = fread_number(fp);
pObjIndex->value[1] = fread_number(fp);
pObjIndex->value[2] = fread_number(fp);
pObjIndex->value[3] = skill_lookup(fread_word(fp));
pObjIndex->value[4] = fread_number(fp);
break;
case ITEM_POTION:
case ITEM_PILL:
case ITEM_SCROLL:
pObjIndex->value[0] = fread_number(fp);
pObjIndex->value[1] = skill_lookup(fread_word(fp));
pObjIndex->value[2] = skill_lookup(fread_word(fp));
pObjIndex->value[3] = skill_lookup(fread_word(fp));
pObjIndex->value[4] = skill_lookup(fread_word(fp));
break;
default:
pObjIndex->value[0] = fread_flag( fp );
pObjIndex->value[1] = fread_flag( fp );
pObjIndex->value[2] = fread_flag( fp );
pObjIndex->value[3] = fread_flag( fp );
pObjIndex->value[4] = fread_flag( fp );
break;
}
pObjIndex->level = fread_number( fp );
pObjIndex->weight = fread_number( fp );
pObjIndex->cost = fread_number( fp );
/* condition */
letter = fread_letter( fp );
switch (letter)
{
case ('P') : pObjIndex->condition = 100; break;
case ('G') : pObjIndex->condition = 90; break;
case ('A') : pObjIndex->condition = 75; break;
case ('W') : pObjIndex->condition = 50; break;
case ('D') : pObjIndex->condition = 25; break;
case ('B') : pObjIndex->condition = 10; break;
case ('R') : pObjIndex->condition = 0; break;
default: pObjIndex->condition = 100; break;
}
for ( ; ; )
{
char letter;
letter = fread_letter( fp );
if ( letter == 'A' )
{
AFFECT_DATA *paf;
paf = alloc_perm( sizeof(*paf) );
paf->where = TO_OBJECT;
paf->type = -1;
paf->level = pObjIndex->level;
paf->duration = -1;
paf->location = fread_number( fp );
paf->modifier = fread_number( fp );
paf->bitvector = 0;
paf->next = pObjIndex->affected;
pObjIndex->affected = paf;
top_affect++;
}
else if (letter == 'F')
{
AFFECT_DATA *paf;
paf = alloc_perm( sizeof(*paf) );
letter = fread_letter(fp);
switch (letter)
{
case 'A':
paf->where = TO_AFFECTS;
break;
case 'I':
paf->where = TO_IMMUNE;
break;
case 'R':
paf->where = TO_RESIST;
break;
case 'V':
paf->where = TO_VULN;
break;
default:
bug( "Load_objects: Bad where on flag set.", 0 );
exit( 1 );
}
paf->type = -1;
paf->level = pObjIndex->level;
paf->duration = -1;
paf->location = fread_number(fp);
paf->modifier = fread_number(fp);
paf->bitvector = fread_flag(fp);
paf->next = pObjIndex->affected;
pObjIndex->affected = paf;
top_affect++;
}
else if ( letter == 'E' )
{
EXTRA_DESCR_DATA *ed;
ed = alloc_perm( sizeof(*ed) );
ed->keyword = fread_string( fp );
ed->description = fread_string( fp );
ed->next = pObjIndex->extra_descr;
pObjIndex->extra_descr = ed;
top_ed++;
}
else
{
ungetc( letter, fp );
break;
}
}
iHash = vnum % MAX_KEY_HASH;
pObjIndex->next = obj_index_hash[iHash];
obj_index_hash[iHash] = pObjIndex;
top_obj_index++;
top_vnum_obj = top_vnum_obj < vnum ? vnum : top_vnum_obj; /* OLC */
assign_area_vnum( vnum ); /* OLC */
}
return;
}
/*****************************************************************************
Name: convert_objects
Purpose: Converts all old format objects to new format
+ Called by: boot_db (db.c).
+ Note: Loops over all resets to find the level of the mob
+ loaded before the object to determine the level of
+ the object.
+ It might be better to update the levels in load_resets().
+ This function is not pretty.. Sorry about that :)
+ Author: Hugin
+ ****************************************************************************/
void convert_objects( void )
{
int vnum;
AREA_DATA *pArea;
RESET_DATA *pReset;
MOB_INDEX_DATA *pMob = NULL;
OBJ_INDEX_DATA *pObj;
ROOM_INDEX_DATA *pRoom;
if ( newobjs == top_obj_index ) return; /* all objects in new format */
for ( pArea = area_first; pArea; pArea = pArea->next )
{
for ( vnum = pArea->min_vnum; vnum <= pArea->max_vnum; vnum++ )
{
if ( !( pRoom = get_room_index( vnum ) ) ) continue;
for ( pReset = pRoom->reset_first; pReset; pReset = pReset->next )
{
switch ( pReset->command )
{
case 'M':
if ( !( pMob = get_mob_index( pReset->arg1 ) ) )
bug( "Convert_objects: 'M': bad vnum %d.", pReset->arg1 );
break;
case 'O':
if ( !( pObj = get_obj_index( pReset->arg1 ) ) )
{
bug( "Convert_objects: 'O': bad vnum %d.", pReset->arg1 );
break;
}
if ( pObj->new_format )
continue;
if ( !pMob )
{
bug( "Convert_objects: 'O': No mob reset yet.", 0 );
break;
}
pObj->level = pObj->level < 1 ? pMob->level - 2
: UMIN(pObj->level, pMob->level - 2);
break;
case 'P':
{
OBJ_INDEX_DATA *pObj, *pObjTo;
if ( !( pObj = get_obj_index( pReset->arg1 ) ) )
{
bug( "Convert_objects: 'P': bad vnum %d.", pReset->arg1 );
break;
}
if ( pObj->new_format )
continue;
if ( !( pObjTo = get_obj_index( pReset->arg3 ) ) )
{
bug( "Convert_objects: 'P': bad vnum %d.", pReset->arg3 );
break;
}
pObj->level = pObj->level < 1 ? pObjTo->level
: UMIN(pObj->level, pObjTo->level);
}
break;
case 'G':
case 'E':
if ( !( pObj = get_obj_index( pReset->arg1 ) ) )
{
bug( "Convert_objects: 'E' or 'G': bad vnum %d.", pReset->arg1 );
break;
}
if ( !pMob )
{
bug( "Convert_objects: 'E' or 'G': null mob for vnum %d.",
pReset->arg1 );
break;
}
if ( pObj->new_format )
continue;
if ( pMob->pShop )
{
switch ( pObj->item_type )
{
default:
pObj->level = UMAX(0, pObj->level);
break;
case ITEM_PILL:
case ITEM_POTION:
pObj->level = UMAX(5, pObj->level);
break;
case ITEM_SCROLL:
case ITEM_ARMOR:
case ITEM_WEAPON:
pObj->level = UMAX(10, pObj->level);
break;
case ITEM_WAND:
case ITEM_TREASURE:
pObj->level = UMAX(15, pObj->level);
break;
case ITEM_STAFF:
pObj->level = UMAX(20, pObj->level);
break;
}
}
else
pObj->level = pObj->level < 1 ? pMob->level
: UMIN( pObj->level, pMob->level );
break;
} /* switch ( pReset->command ) */
}
}
}
/* do the conversion: */
for ( pArea = area_first; pArea ; pArea = pArea->next )
for ( vnum = pArea->min_vnum; vnum <= pArea->max_vnum; vnum++ )
if ( (pObj = get_obj_index( vnum )) )
if ( !pObj->new_format )
convert_object( pObj );
return;
}
/*****************************************************************************
+ Name: convert_object
+ Purpose: Converts an old_format obj to new_format
+ Called by: convert_objects (db2.c).
+ Note: Dug out of create_obj (db.c)
+ Author: Hugin
+ ****************************************************************************/
void convert_object( OBJ_INDEX_DATA *pObjIndex )
{
int level;
int number, type; /* for dice-conversion */
if ( !pObjIndex || pObjIndex->new_format ) return;
level = pObjIndex->level;
pObjIndex->level = UMAX( 0, pObjIndex->level ); /* just to be sure */
pObjIndex->cost = 10*level;
switch ( pObjIndex->item_type )
{
default:
bug( "Obj_convert: vnum %d bad type.", pObjIndex->item_type );
break;
case ITEM_LIGHT:
case ITEM_TREASURE:
case ITEM_FURNITURE:
case ITEM_TRASH:
case ITEM_CONTAINER:
case ITEM_DRINK_CON:
case ITEM_KEY:
case ITEM_FOOD:
case ITEM_BOAT:
case ITEM_CORPSE_NPC:
case ITEM_CORPSE_PC:
case ITEM_FOUNTAIN:
case ITEM_MAP:
case ITEM_CLOTHING:
case ITEM_SCROLL:
break;
case ITEM_WAND:
case ITEM_STAFF:
pObjIndex->value[2] = pObjIndex->value[1];
break;
case ITEM_WEAPON:
/*
* The conversion below is based on the values generated
* in one_hit() (fight.c). Since I don't want a lvl 50
* weapon to do 15d3 damage, the min value will be below
* the one in one_hit, and to make up for it, I've made
* the max value higher.
* (I don't want 15d2 because this will hardly ever roll
* 15 or 30, it will only roll damage close to 23.
* I can't do 4d8+11, because one_hit there is no dice-
* bounus value to set...)
*
* The conversion below gives:
level: dice min max mean
1: 1d8 1( 2) 8( 7) 5( 5)
2: 2d5 2( 3) 10( 8) 6( 6)
3: 2d5 2( 3) 10( 8) 6( 6)
5: 2d6 2( 3) 12(10) 7( 7)
10: 4d5 4( 5) 20(14) 12(10)
20: 5d5 5( 7) 25(21) 15(14)
30: 5d7 5(10) 35(29) 20(20)
50: 5d11 5(15) 55(44) 30(30)
*/
number = UMIN(level/4 + 1, 5);
type = (level + 7)/number;
pObjIndex->value[1] = number;
pObjIndex->value[2] = type;
break;
case ITEM_ARMOR:
pObjIndex->value[0] = level / 5 + 3;
pObjIndex->value[1] = pObjIndex->value[0];
pObjIndex->value[2] = pObjIndex->value[0];
break;
case ITEM_POTION:
case ITEM_PILL:
break;
case ITEM_MONEY:
pObjIndex->value[0] = pObjIndex->cost;
break;
}
pObjIndex->new_format = TRUE;
++newobjs;
return;
}
/*****************************************************************************
+ Name: convert_mobile
+ Purpose: Converts an old_format mob into new_format
+ Called by: load_old_mob (db.c).
+ Note: Dug out of create_mobile (db.c)
+ Author: Hugin
+ ****************************************************************************/
void convert_mobile( MOB_INDEX_DATA *pMobIndex )
{
int i;
int type, number, bonus;
int level;
if ( !pMobIndex || pMobIndex->new_format ) return;
level = pMobIndex->level;
pMobIndex->act |= ACT_WARRIOR;
/*
* Calculate hit dice. Gives close to the hitpoints
* of old format mobs created with create_mobile() (db.c)
* A high number of dice makes for less variance in mobiles
* hitpoints.
* (might be a good idea to reduce the max number of dice)
*
* The conversion below gives:
level: dice min max diff mean
1: 1d2+6 7( 7) 8( 8) 1( 1) 8( 8)
2: 1d3+15 16( 15) 18( 18) 2( 3) 17( 17)
3: 1d6+24 25( 24) 30( 30) 5( 6) 27( 27)
5: 1d17+42 43( 42) 59( 59) 16( 17) 51( 51)
10: 3d22+96 99( 95) 162( 162) 63( 67) 131( )
15: 5d30+161 166(159) 311( 311) 145( 150) 239( )
30: 10d61+416 426(419) 1026(1026) 600( 607) 726( )
50: 10d169+920 930(923) 2610(2610) 1680(1688) 1770( )
The values in parenthesis give the values generated in create_mobile.
Diff = max - min. Mean is the arithmetic mean.
(hmm.. must be some roundoff error in my calculations.. smurfette got
1d6+23 hp at level 3 ? -- anyway.. the values above should be
approximately right..)
*/
type = level*level*27/40;
number = UMIN(type/40 + 1, 10); /* how do they get 11 ??? */
type = UMAX(2, type/number);
bonus = UMAX(0, level*(8 + level)*.9 - number*type);
pMobIndex->hit[DICE_NUMBER] = number;
pMobIndex->hit[DICE_TYPE] = type;
pMobIndex->hit[DICE_BONUS] = bonus;
pMobIndex->mana[DICE_NUMBER] = level;
pMobIndex->mana[DICE_TYPE] = 10;
pMobIndex->mana[DICE_BONUS] = 100;
/*
* Calculate dam dice. Gives close to the damage
* of old format mobs in damage() (fight.c)
*/
type = level*7/4;
number = UMIN(type/8 + 1, 5);
type = UMAX(2, type/number);
bonus = UMAX(0, level*9/4 - number*type);
pMobIndex->damage[DICE_NUMBER] = number;
pMobIndex->damage[DICE_TYPE] = type;
pMobIndex->damage[DICE_BONUS] = bonus;
switch ( number_range( 1, 3 ) )
{
case (1): pMobIndex->dam_type = 3; break; /* slash */
case (2): pMobIndex->dam_type = 7; break; /* pound */
case (3): pMobIndex->dam_type = 11; break; /* pierce */
}
for (i = 0; i < 3; i++)
pMobIndex->ac[i] = interpolate( level, 100, -100);
pMobIndex->ac[3] = interpolate( level, 100, 0); /* exotic */
pMobIndex->wealth /= 100;
pMobIndex->size = SIZE_MEDIUM;
pMobIndex->material = str_dup("none");
pMobIndex->new_format = TRUE;
++newmobs;
return;
}