Basic SMAUG code question

Posted by Blarg on Fri 08 Oct 2004 05:41 PM — 2 posts, 11,427 views.

USA #0
Hi, guys I'm a new imm to a fairly old smaug based mud and our coder is taking a small break. I just have a few questions that I'm sure you'll be able to answer rather quickly.

Can someone explain this save to me? A line by line explanation would be great.

bool saves_spell_staff( int level, CHAR_DATA *victim )
{
int save;

if ( IS_SET( victim->immune, RIS_MAGIC ) )
return TRUE;

if ( IS_NPC( victim ) && level > 10 )
level -= 5;
save = 50 + ( victim->level - level - victim->saving_spell_staff ) * 5;
save = URANGE( 5, save, 95 );
return victim->ChanceRoll( save );
}

I'm also having trouble understanding some spells too. Line by line explanations would be great.

ch_ret spell_magic_missile( int sn, int level, CHAR_DATA *ch, void *vo )
{
CHAR_DATA *victim = (CHAR_DATA *) vo;
static const sh_int dam_each[] =
{
0,
3, 3, 4, 4, 5, 6, 6, 6, 6, 6,
7, 7, 7, 7, 7, 8, 8, 8, 8, 8,
9, 9, 9, 9, 9, 10, 10, 10, 10, 10,
11, 11, 11, 11, 11, 12, 12, 12, 12, 12,
13, 13, 13, 13, 13, 14, 14, 14, 14, 14,
15, 15, 15, 15, 15, 16, 16, 16, 16, 16,
17, 17, 17, 17, 17, 18, 18, 18, 18, 18
};
int dam;

level = UMIN(level, sizeof(dam_each)/sizeof(dam_each[0]) - 1);
level = UMAX(0, level);
dam = number_range( dam_each[level] / 2, dam_each[level] * 2 );
/* What's this? You can't save vs. magic missile! -Thoric
if ( saves_spell( level, victim ) )
dam /= 2;
*/
return damage( ch, victim, dam, sn, 0 );
}

We are currently in the process of trying to balance our classes and we need good information on our spells before we start.

Thanks in advance,
Blarg
USA #1
Heyas Blarg :P I've already answered this question on the Darkstone forum, but figured others might be interested in the explanations.


bool saves_spell_staff( int level, CHAR_DATA *victim )
{
   int save;

   if ( IS_SET( victim->immune, RIS_MAGIC ) )
      return TRUE;


If the victim is immune to magic, then the save vs. spell/staff is automatically successful.


   if ( IS_NPC( victim ) && level > 10 )
      level -= 5;


If the victim is an NPC, and its level is greater than 10, then consider that its level is actually 5 levels smaller. Therefore a level 20 NPC saves as if it was level 15.


   save = 50 + ( victim->level - level - victim->saving_spell_staff ) * 5;
   save = URANGE( 5, save, 95 );

Magic number to first calculate the save chance, then make sure it's between 5 and 95.

   return victim->ChanceRoll( save );
}

This is something you probably won't see in any other version of SMAUG since for it's a result of my conversion of the code to C++ and some other rearrangements. In any case, it means that we roll a 100-sided die for the victim, adjust with modifiers such as deity favor etc., with a chance of 'save' out of 100 to succeed.


ch_ret spell_magic_missile( int sn, int level, CHAR_DATA *ch, void *vo )
{
   CHAR_DATA *victim = (CHAR_DATA *) vo;
   static const sh_int dam_each[] = {
      0,
      3, 3, 4, 4, 5, 6, 6, 6, 6, 6,
      7, 7, 7, 7, 7, 8, 8, 8, 8, 8,
      9, 9, 9, 9, 9, 10, 10, 10, 10, 10,
      11, 11, 11, 11, 11, 12, 12, 12, 12, 12,
      13, 13, 13, 13, 13, 14, 14, 14, 14, 14,
      15, 15, 15, 15, 15, 16, 16, 16, 16, 16,
      17, 17, 17, 17, 17, 18, 18, 18, 18, 18
   };

Initialize a table of 70 entries, presumably the damage per level.

   int dam;

   level = UMIN(level, sizeof(dam_each)/sizeof(dam_each[0]) - 1);

Set level equal to the smallest number between:
- the level passed in as a function argument (presumably, the caster's level)
- or, the size of the array minus one, here, 70
In other words, make sure that level does not exceed the size of the array. (how it could go beyond 65 in the first place is an interesting question.)

   level = UMAX(0, level);

Set level to the largest number between:
- 0
- level
In other words make sure it's at least equal to 0.

   dam = number_range( dam_each[level] / 2, dam_each[level] * 2 );

Set variable dam (damage) to a random number between the table entries divided by two, and the table entry multiplied by two.
   /* What's this? You can't save vs. magic missile! -Thoric
   if ( saves_spell( level, victim ) )
      dam /= 2;
   */
This is Thoric (the head SMAUG coder I believe) who commented out code that breaks the rules of magic missile.
   return damage( ch, victim, dam, sn, 0 );
}

Finally, call the damage function with the appropriate damage and damagetype = skillnumber (=magic missile). This is where damage is dealt, resistances are applied, yada yada yada. It returns the result, which will probably be 'none' for 'nothing special'. (after all such things can't be dodged or parried or some-such.)