/**************************************************************************/
// o_lookup.cpp - see below
/***************************************************************************
* The Dawn of Time v1.69r (c)1997-2004 Michael Garratt *
* >> A number of people have contributed to the Dawn codebase, with the *
* majority of code written by Michael Garratt - www.dawnoftime.org *
* >> To use this source code, you must fully comply with the dawn license *
* in licenses.txt... In particular, you may not remove this copyright *
* notice. *
**************************************************************************/
/***************************************************************************
* FILE: o_lookup.cpp - olc lookup tables *
* Written by Kerenos - March 00 *
***************************************************************************/
#include "include.h"
#include "o_lookup.h"
void check_obj_balance( char_data *ch );
void check_obj_weapon( char_data *ch, OBJ_INDEX_DATA *pObj );
/**************************************************************************/
// weapon damage dice {1, 10} = 1d10 {2, 8} = 2d8 etc....
static const int weapon_balance_table[100][8][2] =
{
{ { 1, 5 }}, // 0
{ { 1, 6 }},
{ { 1, 7 },{ 2, 3 }},
{ { 1, 8 }},
{ { 1, 9 },{ 2, 4 }},
{ { 1, 10 }}, // 5
{ { 1, 11 },{ 2, 5 },{ 3, 3 }},
{ { 1, 12 }},
{ { 1, 13 },{ 2, 6 }},
{ { 1, 14 },{ 3, 4 }},
{ { 1, 15 },{ 2, 7 },{ 4, 3 }}, // 10
{ { 1, 15 },{ 2, 7 },{ 4, 3 }},
{ { 2, 8 },{ 3, 5 }},
{ { 2, 8 },{ 3, 5 }},
{ { 2, 9 },{ 4, 4 },{ 5, 3 }},
{ { 3, 6 }}, // 15
{ { 2, 10 }},
{ { 2, 10 }},
{ { 2, 11 },{ 3, 7 },{ 4, 5 },{ 6, 3 }},
{ { 5, 4 }},
{ { 2, 12 }}, // 20
{ { 3, 8 }},
{ { 2, 13 },{ 4, 6 },{ 7, 3 }},
{ { 2, 13 },{ 4, 6 },{ 7, 3 }},
{ { 2, 14 },{ 3, 9 },{ 5, 5 },{ 6, 4 }},
{ { 2, 14 },{ 3, 9 },{ 5, 5 },{ 6, 4 }}, // 25
{ { 2, 15 },{ 4, 7 },{ 8, 3 }},
{ { 3, 10 }},
{ { 2, 16 }},
{ { 5, 6 },{ 7, 4 }},
{ { 2, 17 },{ 3, 11 },{ 4, 8 },{ 6, 5 },{ 9, 3 }}, // 30
{ { 2, 17 },{ 3, 11 },{ 4, 8 },{ 6, 5 },{ 9, 3 }},
{ { 2, 18 }},
{ { 3, 12 }},
{ { 2, 19 },{ 4, 9 },{ 5, 7 },{ 8, 4 },{10, 3 }},
{ { 2, 19 },{ 4, 9 },{ 5, 7 },{ 8, 4 },{10, 3 }}, // 35
{ { 2, 20 },{ 3, 13 },{ 6, 6 },{ 7, 5 }},
{ { 2, 20 },{ 3, 13 },{ 6, 6 },{ 7, 5 }},
{ { 2, 21 },{ 4, 10 },{11, 3 }},
{ { 3, 14 },{ 5, 8 },{ 9, 4 }},
{ { 2, 22 }}, // 40
{ { 2, 22 }},
{ { 2, 23 },{ 3, 15 },{ 4, 11 },{ 6, 7 },{ 8, 5 },{12, 3 }},
{ { 7, 6 }},
{ { 2, 24 },{ 5, 9 },{10, 4 }},
{ { 3, 16 }}, // 45
{ { 2, 25 },{ 4, 12 },{13, 3 }},
{ { 2, 25 },{ 4, 12 },{13, 3 }},
{ { 2, 26 },{ 3, 17 },{ 6, 8 },{ 9, 5 }},
{ { 5, 10 },{11, 4 }},
{ { 2, 27 },{ 4, 13 },{ 7, 7 },{ 8, 6 },{14, 3 }}, // 50
{ { 3, 18 }},
{ { 2, 28 }},
{ { 2, 28 }},
{ { 2, 29 },{ 3, 19 },{ 4, 14 },{ 5, 11 },{ 6, 9 },{10, 5 },{12, 4 },{15, 3 }},
{ { 2, 29 },{ 3, 19 },{ 4, 14 },{ 5, 11 },{ 6, 9 },{10, 5 },{12, 4 },{15, 3 }}, // 55 YUCK!!!!!
{ { 2, 30 }},
{ { 3, 20 },{ 7, 8 },{ 9, 6 }},
{ { 4, 15 },{ 8, 7 },{16, 3 }},
{ { 5, 12 },{13, 4 }},
{ { 3, 21 },{ 6, 10 },{11, 5 }}, // 60
{ { 3, 21 },{ 6, 10 },{11, 5 }},
{ { 4, 16 },{17, 3 }},
{ { 3, 22 }},
{ { 5, 13 },{ 7, 9 },{10, 6 },{14, 4 }},
{ { 5, 13 },{ 7, 9 },{10, 6 },{14, 4 }}, // 65
{ { 3, 23 },{ 4, 17 },{ 6, 11 },{ 8, 8 },{ 9, 7 },{12, 5 },{18, 3 }},
{ { 3, 23 },{ 4, 17 },{ 6, 11 },{ 8, 8 },{ 9, 7 },{12, 5 },{18, 3 }},
{ { 3, 24 },{ 5, 14 },{15, 4 }},
{ { 3, 24 },{ 5, 14 },{15, 4 }},
{ { 4, 18 },{19, 3 }}, // 70 GETTING BORED!!!!!!!!!!
{ { 7, 10 },{11, 6 }},
{ { 3, 25 },{ 6, 12 },{13, 5 }},
{ { 3, 25 },{ 6, 12 },{13, 5 }},
{ { 4, 19 },{ 5, 15 },{ 8, 9 },{10, 7 },{16, 4 },{20, 3 }},
{ { 3, 26 },{ 9, 8 }}, // 75
{ { 3, 26 },{ 9, 8 }},
{ { 3, 27 },{ 4, 20 },{ 6, 13 },{ 7, 11 },{12, 6 },{14, 5 },{21, 3 }},
{ { 3, 27 },{ 4, 20 },{ 6, 13 },{ 7, 11 },{12, 6 },{14, 5 },{21, 3 }},
{ { 5, 16 },{17, 4 }},
{ { 5, 16 },{17, 4 }}, // 80
{ { 3, 28 }},
{ { 4, 21 },{ 8, 10 },{11, 7 },{22, 3 }},
{ { 4, 21 },{ 8, 10 },{11, 7 },{22, 3 }},
{ { 3, 29 },{ 5, 17 },{ 6, 14 },{ 9, 9 },{10, 8 },{15, 5 },{18, 4 }},
{ { 7, 12 },{13, 6 }}, // 85
{ { 4, 22 },{23, 3 }},
{ { 3, 30 }},
{ { 3, 30 }},
{ { 5, 18 },{19, 4 }},
{ { 3, 31 },{ 4, 23 },{ 6, 15 },{ 8, 11 },{12, 7 },{16, 5 },{24, 3 }}, // 90
{ { 3, 31 },{ 4, 23 },{ 6, 15 },{ 8, 11 },{12, 7 },{16, 5 },{24, 3 }},
{ { 7, 13 },{14, 6 }},
{ { 3, 32 },{ 9, 10 },{11, 8 }},
{ { 4, 24 },{ 5, 19 },{10, 9 },{20, 4 },{25, 3 }},
{ { 4, 24 },{ 5, 19 },{10, 9 },{20, 4 },{25, 3 }}, // 95
{ { 3, 33 },{ 6, 16 },{17, 5 }},
{ { 3, 33 },{ 6, 16 },{17, 5 }},
{ { 4, 25 },{ 8, 12 },{13, 7 },{26, 3 }},
{ { 3, 34 },{ 5, 20 },{ 7, 14 },{15, 6 },{21, 4 }}, // 99 + 0 = 100, strange eh? blah, 3am sucks 4 am sucks more
};
/**************************************************************************/
static const int mob_balance_table[100][7] = {
// stored as 1d4+1hp, 90ac, 1d4+0damage
//
// #hitdie, hitdietype, bonus, armour class, #damdie, damdietype, bonus
{ 1,4,1, 90, 1,4,0 }, // 1
{ 1,4,2, 80, 1,5,0 },
{ 1,5,3, 70, 1,6,0 },
{ 2,4,1, 60, 1,5,1 },
{ 2,5,1, 50, 1,6,1 }, // 5
{ 2,5,4, 40, 1,7,1 },
{ 2,5,5, 40, 1,8,1 },
{ 2,5,8, 30, 1,7,2 },
{ 2,5,12, 20, 1,8,2 },
{ 2,5,18, 10, 2,4,2 }, // 10
{ 2,5,22, 10, 1,10,2 },
{ 2,5,45, 0, 1,10,3 },
{ 2,5,50, -10, 2,5,3 },
{ 2,5,55, -10, 1,12,3 },
{ 3,5,60, -20, 2,6,3 }, // 15
{ 3,5,67, -20, 2,6,4 },
{ 3,5,72, -30, 3,4,4 },
{ 3,5,79, -30, 2,7,4 },
{ 3,5,82, -40, 2,7,5 },
{ 3,5,88, -40, 2,8,5 }, // 20
{ 4,5,90, -50, 4,4,5 },
{ 4,5,95, -50, 4,4,6 },
{ 4,5,100, -60, 3,6,6 },
{ 4,5,105, -60, 2,10,6 },
{ 4,5,110, -70, 2,10,7 }, // 25
{ 4,5,115, -70, 3,7,7 },
{ 4,5,120, -80, 5,4,7 },
{ 5,5,125, -80, 2,12,8 },
{ 5,5,130, -90, 2,12,8 },
{ 5,5,140, -90, 4,6,8 }, // 30
{ 5,6,150, -100, 4,6,9 },
{ 5,6,160, -100, 6,4,9 },
{ 5,6,195, -110, 6,4,10 },
{ 5,6,205, -110, 4,7,10 },
{ 5,6,210, -110, 4,7,11 }, // 35
{ 5,6,215, -120, 3,10,11 },
{ 5,6,220, -120, 3,10,12 },
{ 5,6,225, -130, 5,6,12 },
{ 5,6,230, -130, 5,6,13 },
{ 5,6,235, -130, 4,8,13 }, // 40
{ 5,7,240, -140, 4,8,14 },
{ 5,7,242, -140, 3,12,14 },
{ 5,7,245, -150, 3,12,15 },
{ 5,7,247, -150, 8,4,15 },
{ 5,7,250, -150, 8,4,16 }, // 45
{ 5,8,255, -160, 6,6,16 },
{ 5,8,260, -170, 6,6,17 },
{ 5,8,265, -180, 6,6,18 },
{ 5,8,270, -190, 4,10,18 },
{ 5,9,275, -200, 5,8,19 }, // 50
{ 5,9,280, -210, 5,8,20 },
{ 5,9,285, -220, 6,7,20 },
{ 5,9,290, -230, 6,7,21 },
{ 5,9,295, -240, 7,6,22 },
{ 5,9,300, -250, 10,4,23 }, // 55
{ 6,9,300, -260, 10,4,24 },
{ 6,9,305, -270, 6,8,24 },
{ 6,9,310, -280, 5,10,25 },
{ 6,9,315, -290, 8,6,26 },
{ 6,9,320, -300, 8,6,27 }, // 60
{ 6,10,320, -310, 8,6,28 },
{ 6,10,325, -320, 8,7,28 },
{ 6,10,330, -330, 8,7,29 },
{ 6,10,335, -340, 8,7,30 },
{ 6,10,340, -350, 7,8,32 }, // 65
{ 7,10,340, -360, 7,8,32 },
{ 7,10,345, -370, 7,8,33 },
{ 7,10,350, -380, 7,8,34 },
{ 7,10,355, -390, 8,8,33 },
{ 7,10,360, -400, 8,8,34 }, // 70
{ 7,11,360, -410, 8,8,35 },
{ 7,11,365, -420, 8,8,36 },
{ 7,11,370, -430, 8,9,36 },
{ 7,11,375, -440, 8,9,37 },
{ 7,11,380, -450, 8,9,38 }, // 75
{ 8,11,380, -460, 8,9,39 },
{ 8,11,385, -470, 9,9,38 },
{ 8,11,390, -480, 9,9,39 },
{ 8,11,395, -490, 9,9,40 },
{ 8,11,400, -500, 9,9,41 }, // 80
{ 8,12,400, -510, 9,10,40 },
{ 8,12,405, -520, 9,10,41 },
{ 8,12,410, -530, 9,10,42 },
{ 8,12,415, -540, 9,10,43 },
{ 8,12,420, -550, 10,10,42 }, // 85
{ 9,12,420, -560, 10,10,43 },
{ 9,12,425, -570, 10,10,44 },
{ 9,12,430, -580, 10,10,45 },
{ 9,12,435, -590, 10,11,44 },
{ 9,12,440, -600, 10,11,45 }, // 90
{ 9,13,440, -610, 10,11,46 },
{ 9,13,445, -620, 10,11,47 },
{ 9,13,450, -630, 10,12,48 },
{ 9,13,455, -640, 10,12,49 },
{ 9,13,460, -650, 10,12,50 }, // 95
{ 10,13,460, -660, 10,12,51 },
{ 10,13,465, -670, 10,13,52 },
{ 10,13,470, -680, 10,13,53 },
{ 10,13,475, -690, 10,13,54 },
{ 10,14,480, -700, 10,13,55 } // 100
};
/**************************************************************************/
// The number for the AC_* is the value, based on obj->level / value
// Higher Values = worse AC... MAKE SURE TO CHECK FOR DIVISION BY ZERO!!!
static const int armour_balance_table[MAX_WEAR][5] = {
// ITEM_TYPE, AC_PIERCE, AC_BASH, AC_SLASH, AC_MAGIC
{ WEAR_LIGHT, 0, 0, 0, 0 },
{ WEAR_FINGER_L, 10, 10, 10, 10 },
{ WEAR_FINGER_R, 10, 10, 10, 10 },
{ WEAR_NECK_1, 6, 6, 6, 8 },
{ WEAR_NECK_2, 6, 6, 6, 8 },
{ WEAR_TORSO, 3, 3, 3, 4 },
{ WEAR_HEAD, 4, 4, 4, 5 },
{ WEAR_LEGS, 4, 4, 4, 5 },
{ WEAR_FEET, 5, 5, 5, 6 },
{ WEAR_HANDS, 5, 5, 5, 6 },
{ WEAR_ARMS, 4, 4, 4, 5 },
{ WEAR_SHIELD, 3, 3, 3, 4 },
{ WEAR_ABOUT, 4, 4, 4, 5 },
{ WEAR_WAIST, 5, 5, 5, 7 },
{ WEAR_WRIST_L, 7, 7, 7, 9 },
{ WEAR_WRIST_R, 7, 7, 7, 9 },
{ WEAR_WIELD, 0, 0, 0, 0 },
{ WEAR_HOLD, 0, 0, 0, 0 },
{ WEAR_FLOAT, 0, 0, 0, 0 },
{ WEAR_SECONDARY, 0, 0, 0, 0 },
{ WEAR_LODGED_ARM, 0, 0, 0, 0 },
{ WEAR_LODGED_LEG, 0, 0, 0, 0 },
{ WEAR_LODGED_RIB, 0, 0, 0, 0 },
{ WEAR_SHEATHED, 0, 0, 0, 0 },
{ WEAR_CONCEALED, 0, 0, 0, 0 },
{ WEAR_HAIR, 0, 0, 0, 0 },
{ WEAR_EAR_L, 0, 0, 0, 0 },
{ WEAR_EAR_R, 0, 0, 0, 0 },
{ WEAR_FACE, 0, 0, 0, 0 },
{ WEAR_ANKLE_L, 0, 0, 0, 0 },
{ WEAR_ANKLE_R, 0, 0, 0, 0 },
{ WEAR_BACK, 3, 3, 3, 4 },
// { WEAR_ARMOR, 3, 3, 3, 4 }
};
/**************************************************************************/
// Used to return mob's HP dice (3d5+88)
//
// result!!
int mob_balance_lookup( int level, int field )
{
if ( field < 0 || field >= MOB_BALANCE_MAX )
return 0;
if ( level > 100 ) level = 100;
if ( level < 0 ) level = 0;
return ( mob_balance_table[level][field]);
}
/**************************************************************************/
// returns proper value of weapon_balance_table
int weapon_balance_lookup( int level, int pos, int die )
{
// first off, return 1d4 for anything below level -2
if ( level < -2 )
{
return ( die = 0 ? 1 : 4 );
}
// normalize values and bounds checking, just to be safe!!
if ( pos < 0 ) pos = 0;
if ( pos > 7 ) pos = 0;
if ( level < 0 ) level = 0;
if ( level > 99 ) level = 99;
if ( die < 0 ) die = 0;
if ( die > 1 ) die = 1;
// all safe now, return a number
return ( weapon_balance_table[level][pos][die]);
}
/**************************************************************************/
// Main balance command
void do_checkbalance( char_data *ch, char *argument )
{
if ( !str_cmp( argument, "obj" ))
{
check_obj_balance( ch );
return;
}
ch->println( "Syntax: checkbalance [obj] more to follow." );
return;
}
/**************************************************************************/
// Handles the objects, then goes to specified function per specific item_type
// this had to get modularized like this, otherwise it'd get too huge and
// cumbersome
void check_obj_balance( char_data *ch )
{
int i;
OBJ_INDEX_DATA *pObj;
for ( i = ch->in_room->area->min_vnum; i <= ch->in_room->area->max_vnum; i++)
{
if (( pObj = get_obj_index( i )) == NULL )
continue;
switch ( pObj->item_type )
{
case ( ITEM_WEAPON ):
check_obj_weapon( ch, pObj );
break;
default:
break;
}
}
}
/**************************************************************************/
void check_obj_weapon( char_data *ch, OBJ_INDEX_DATA *pObj )
{
bool balanced = false; // always assume the worst
int vlevel = pObj->level; // virtual level in balance table
int i;
AFFECT_DATA *paf;
/* start adjusting vlevel according to the balance sheet
dagger -8
exotic -5 -20 mana +1
whip -3 +10 mana -1
flail -2 -4 hp +1
sword/mace 0 +2 hp -1
axe/2h staff +3 -2 hit/dam +1
2h mace/2h sword +6 +2 hit/dam -1
polearm +8 +1 attribute -1
2h axes +9 -1 attribute +1
sharp -4 vorpal -4
vampiric -3 flaming -3
freezing -3 empowered -3
poison -3 holy -3
*/
if ( pObj->level > LEVEL_HERO ) {
ch->printlnf( "`c%-5d`x..............`YSKIPPED`x Immortal Level", pObj->vnum );
return;
}
// do weapon types first (easiest) :)
switch (pObj->value[0])
{
case (WEAPON_DAGGER): vlevel -= 8; break;
case (WEAPON_EXOTIC): vlevel -= 5; break;
case (WEAPON_WHIP): vlevel -= 3; break;
case (WEAPON_FLAIL): vlevel -= 2; break;
case (WEAPON_STAFF):
if ( !IS_WEAPON_STAT( pObj, WEAPON_TWO_HANDS ))
vlevel -= 10;
break;
case (WEAPON_POLEARM): vlevel += 8; break;
case (WEAPON_SICKLE):
if ( IS_WEAPON_STAT( pObj, WEAPON_TWO_HANDS )) {
vlevel += 3;
} else {
vlevel -= 3;
}
break;
case (WEAPON_SWORD):
case (WEAPON_SPEAR):
case (WEAPON_MACE):
if ( IS_WEAPON_STAT( pObj, WEAPON_TWO_HANDS ))
vlevel += 6;
break;
case (WEAPON_AXE):
if ( IS_WEAPON_STAT( pObj, WEAPON_TWO_HANDS )) {
vlevel += 9;
} else {
vlevel += 3;
}
break;
default:
break;
}
if ( IS_WEAPON_STAT( pObj, WEAPON_FLAMING )) vlevel -= 3;
if ( IS_WEAPON_STAT( pObj, WEAPON_FROST )) vlevel -= 3;
if ( IS_WEAPON_STAT( pObj, WEAPON_VAMPIRIC )) vlevel -= 3;
if ( IS_WEAPON_STAT( pObj, WEAPON_SHARP )) vlevel -= 4;
if ( IS_WEAPON_STAT( pObj, WEAPON_VORPAL )) vlevel -= 4;
if ( IS_WEAPON_STAT( pObj, WEAPON_SHOCKING )) vlevel -= 3;
if ( IS_WEAPON_STAT( pObj, WEAPON_POISON )) vlevel -= 3;
if ( IS_WEAPON_STAT( pObj, WEAPON_HOLY )) vlevel -= 3;
// if ( IS_WEAPON_STAT( pObj, WEAPON_LIVING )) vlevel -= 0; // VOT?
for ( paf = pObj->affected; paf; paf = paf->next )
{
switch (paf->location)
{
case (APPLY_DAMROLL):
case (APPLY_HITROLL):
vlevel += paf->modifier * -(1/2);
break;
case (APPLY_MANA):
if ( paf->modifier > 0 ) vlevel += paf->modifier * -(1/10);
if ( paf->modifier < 0 ) vlevel += paf->modifier * -(1/20);
break;
case (APPLY_HIT):
if ( paf->modifier > 0 ) vlevel += paf->modifier * -(1/2);
if ( paf->modifier < 0 ) vlevel += paf->modifier * -(1/4);
break;
case (APPLY_AC):
if ( paf->modifier > 0 ) vlevel += paf->modifier * -(2/10);
if ( paf->modifier < 0 ) vlevel += paf->modifier * -(1/10);
break;
case (APPLY_SAVES):
if ( paf->modifier > 0 ) vlevel += paf->modifier * -(4/10);
if ( paf->modifier < 0 ) vlevel += paf->modifier * -(2/10);
break;
case (APPLY_ST):
case (APPLY_QU):
case (APPLY_PR):
case (APPLY_EM):
case (APPLY_IN):
case (APPLY_CO):
case (APPLY_AG):
case (APPLY_SD):
case (APPLY_ME):
case (APPLY_RE):
vlevel -= paf->modifier;
break;
default:
break;
}
}
for ( i=0; i < 8; i++ ) // 8 elements in weapon_balance_table
{
if ( weapon_balance_lookup( vlevel, i, 0 ) >= pObj->value[1]
&& weapon_balance_lookup( vlevel, i, 1 ) >= pObj->value[2] )
{
balanced = true;
break;
}
}
if ( balanced ) {
ch->printlnf( "`c%-5d`x..............`GPASSED`x", pObj->vnum );
} else {
ch->printlnf( "`c%-5d`x..............`RFAILED`x Level: %-3d Dam Level Suggested: %-3d",
pObj->vnum, pObj->level, vlevel );
}
return;
}
/**************************************************************************/
/*
'but you can't use negative mods to just boost up the damage level.'
'you can only use negative mods to counter positive ones.'
'For example adding +20 saves to a weapon and nothing else would
have no affect on the damage roll.'
'Because if the weapon is chaos-laced the +20 saves would disappear,
leaving a really really nice weapon.'
Equip Normal 1 Alliance 2 Alliance
level flag or flag and
magic flag magic flag
0-10 0 0 1
11-20 1 1 2
21-30 2 3 4
31-40 3 4 5
41-50 4 5 6
51-60 5 6 7
61-70 6 7 8
71-80 7 8 9
81-90 8 9 10
91 9 10 11
Table 2: Max modifier based on items lev and alliance restrictions
One Modifier Equals
+1 attribute
+2 hitpoints
+20 mana
+2 hitroll
+2 damage
-2 save
-5 AC
+40 movement
bless flag
*/
/**************************************************************************/
/**************************************************************************/