Login
User Name:

Password:



Register
Forgot your password?
Vote for Us!
tintin++ ogg sound player script for linux
Author: Robert Smith
Submitted by: Vladaar
6Dragons ogg Soundpack
Author: Vladaar
Submitted by: Vladaar
6Dragons 4.4
Author: Vladaar
Submitted by: Vladaar
LoP 1.46
Author: Remcon
Submitted by: Remcon
LOP 1.45
Author: Remcon
Submitted by: Remcon
Users Online
CommonCrawl, Yandex

Members: 0
Guests: 10
Stats
Files
Topics
Posts
Members
Newest Member
481
3,735
19,370
618
Micheal64X
Today's Birthdays
There are no member birthdays today.
Related Links
» SmaugMuds.org » Codebases » SmaugFUSS » Racial Skills Fix
Forum Rules | Mark all | Recent Posts

Racial Skills Fix
< Newer Topic :: Older Topic >

Pages:<< prev 1 next >>
Post is unread #1 Jan 28, 2007, 12:51 am
Go to the top of the page
Go to the bottom of the page

Kayle
Off the Edge of the Map
GroupAdministrators
Posts1,195
JoinedMar 21, 2006

Stock Smaug has all the workings of skills that only the races can use. But none of it is tied together. I sat down, and got to hacking and slashing, and tied it all together. And here are the results for you to enjoy.

db.c
Find:
/* for searching */
short gsn_first_spell;
short gsn_first_skill;
short gsn_first_weapon;
short gsn_first_tongue;
short gsn_top_sn;


Replace with:
/* for searching */
short gsn_first_spell;
short gsn_first_skill;
short gsn_first_weapon;
short gsn_first_tongue;
short gsn_first_ability; /*Fix for racial skills. --Kayle 1-28-07 */
short gsn_top_sn;


Further down, in boot_db.
Find:
gsn_first_spell = 0;
   gsn_first_skill = 0;
   gsn_first_weapon = 0;
   gsn_first_tongue = 0;
   gsn_top_sn = top_sn;

   for( x = 0; x < top_sn; x++ )
      if( !gsn_first_spell && skill_table[x]->type == SKILL_SPELL )
         gsn_first_spell = x;
      else if( !gsn_first_skill && skill_table[x]->type == SKILL_SKILL )
         gsn_first_skill = x;
      else if( !gsn_first_weapon && skill_table[x]->type == SKILL_WEAPON )
         gsn_first_weapon = x;
      else if( !gsn_first_tongue && skill_table[x]->type == SKILL_TONGUE )
         gsn_first_tongue = x;


Replace with:
gsn_first_spell = 0;
   gsn_first_skill = 0;
   gsn_first_weapon = 0;
   gsn_first_tongue = 0;
   gsn_first_ability = 0; /* Fix for racial skills. --Kayle 1-28-07 */
   gsn_top_sn = top_sn;

   for( x = 0; x < top_sn; x++ )
      if( !gsn_first_spell && skill_table[x]->type == SKILL_SPELL )
         gsn_first_spell = x;
      else if( !gsn_first_skill && skill_table[x]->type == SKILL_SKILL )
         gsn_first_skill = x;
      else if( !gsn_first_weapon && skill_table[x]->type == SKILL_WEAPON )
         gsn_first_weapon = x;
      else if( !gsn_first_tongue && skill_table[x]->type == SKILL_TONGUE )
         gsn_first_tongue = x;
      else if( !gsn_first_ability && skill_table[x]->type == SKILL_RACIAL )
         gsn_first_ability = x; /*Fix for racial skills. --Kayle 1-28-07 */


Interp.c
Find:
/*
    * Look for command in skill and socials table.
    */
   if( !found )
   {
      if( !check_skill( ch, command, argument ) && !check_social( ch, command, argument )
#ifdef IMC
          && !imc_command_hook( ch, command, argument )
#endif
          )


Replace with:
/*
    * Look for command in skill and socials table.
    */
   if( !found )
   {
      if( !check_skill( ch, command, argument ) && !check_ability( ch, command, argument ) && !check_social( ch, command, argument )
#ifdef IMC
          && !imc_command_hook( ch, command, argument )
#endif
          )


Magic.c
Find skill_lookup.

Replace the whole function with this:
/*
 * Lookup a skill by name.
 * Fix added for Racial Skills --Kayle 1-28-07
 */
int skill_lookup( const char *name )
{
   int sn;

   if( ( sn = bsearch_skill_exact( name, gsn_first_spell, gsn_first_skill - 1 ) ) == -1 )
      if( ( sn = bsearch_skill_exact( name, gsn_first_skill, gsn_first_weapon - 1 ) ) == -1 )
         if( ( sn = bsearch_skill_exact( name, gsn_first_weapon, gsn_first_tongue - 1 ) ) == -1 )
            if( ( sn = bsearch_skill_exact( name, gsn_first_tongue, gsn_first_ability - 1 ) ) == -1 )
               if( ( sn = bsearch_skill_exact( name, gsn_first_ability, gsn_top_sn - 1 ) ) == -1 )
                  if( ( sn = bsearch_skill_prefix( name, gsn_first_spell, gsn_first_skill - 1 ) ) == -1 )
                     if( ( sn = bsearch_skill_prefix( name, gsn_first_skill, gsn_first_weapon - 1 ) ) == -1 )
                        if( ( sn = bsearch_skill_prefix( name, gsn_first_weapon, gsn_first_tongue - 1 ) ) == -1 )
                           if( ( sn = bsearch_skill_prefix( name, gsn_first_tongue, gsn_first_ability - 1 ) ) == -1 )
                              if( ( sn = bsearch_skill_prefix( name, gsn_first_ability, gsn_top_sn - 1 ) ) == -1
                                    && gsn_top_sn < top_sn )
                                {
                                 for( sn = gsn_top_sn; sn < top_sn; sn++ )
                                  {
                                      if( !skill_table[sn] || !skill_table[sn]->name )
                                         return -1;
                                      if( LOWER( name[0] ) == LOWER( skill_table[sn]->name[0] )
                                          && !str_prefix( name, skill_table[sn]->name ) )
                                         return sn;
                                   }
                                   return -1;
                                }
   return sn;
}


Mud.h
Find:
/* used to do specific lookups */
extern short gsn_first_spell;
extern short gsn_first_skill;
extern short gsn_first_weapon;
extern short gsn_first_tongue;
extern short gsn_top_sn;


Replace with:
/* used to do specific lookups */
extern short gsn_first_spell;
extern short gsn_first_skill;
extern short gsn_first_weapon;
extern short gsn_first_tongue;
extern short gsn_first_ability; /* Fixed racial skills. --Kayle 1-28-07 */
extern short gsn_top_sn;


Further down, Find:
/* skills.c */
bool can_use_skill args( ( CHAR_DATA * ch, int percent, int gsn ) );
bool check_skill args( ( CHAR_DATA * ch, char *command, char *argument ) );
void learn_from_success args( ( CHAR_DATA * ch, int sn ) );
void learn_from_failure args( ( CHAR_DATA * ch, int sn ) );


Replace with:
/* skills.c */
bool can_use_skill args( ( CHAR_DATA * ch, int percent, int gsn ) );
bool check_skill args( ( CHAR_DATA * ch, char *command, char *argument ) );
bool check_ability args( ( CHAR_DATA * ch, char *command, char *argument ) );[b]
void learn_from_success args( ( CHAR_DATA * ch, int sn ) );
void ability_learn_from_success args( ( CHAR_DATA * ch, int sn ) ); /*Allow for seperate handling of racial skills. --Kayle 1-28-07 */
void learn_from_failure args( ( CHAR_DATA * ch, int sn ) );


Save.c
Find
for( sn = 1; sn < top_sn; sn++ )
   {
      if( skill_table[sn]->name && ch->pcdata->learned[sn] > 0 )
         switch ( skill_table[sn]->type )
         {
            default:
               fprintf( fp, "Skill        %d '%s'\n", ch->pcdata->learned[sn], skill_table[sn]->name );
               break;
            case SKILL_SPELL:
               fprintf( fp, "Spell        %d '%s'\n", ch->pcdata->learned[sn], skill_table[sn]->name );
               break;
            case SKILL_WEAPON:
               fprintf( fp, "Weapon       %d '%s'\n", ch->pcdata->learned[sn], skill_table[sn]->name );
               break;
            case SKILL_TONGUE:
               fprintf( fp, "Tongue       %d '%s'\n", ch->pcdata->learned[sn], skill_table[sn]->name );
               break;
         }
   }


Change it to resemble:
   for( sn = 1; sn < top_sn; sn++ )
   {
      if( skill_table[sn]->name && ch->pcdata->learned[sn] > 0 )
         switch ( skill_table[sn]->type )
         {
            default:
               fprintf( fp, "Skill        %d '%s'\n", ch->pcdata->learned[sn], skill_table[sn]->name );
               break;
            case SKILL_RACIAL:
               fprintf( fp, "Ability      %d '%s'\n", ch->pcdata->learned[sn], skill_table[sn]->name );
               break;
            case SKILL_SPELL:
               fprintf( fp, "Spell        %d '%s'\n", ch->pcdata->learned[sn], skill_table[sn]->name );
               break;
            case SKILL_WEAPON:
               fprintf( fp, "Weapon       %d '%s'\n", ch->pcdata->learned[sn], skill_table[sn]->name );
               break;
            case SKILL_TONGUE:
               fprintf( fp, "Tongue       %d '%s'\n", ch->pcdata->learned[sn], skill_table[sn]->name );
               break;
         }
   }


Find fread_char:
In case 'A', Add:
if( !str_cmp( word, "Ability" ) )
            {
               char *ability;
               int sn, value;

               value = fread_number( fp );
               ability = fread_word( fp );
               sn = bsearch_skill_exact( ability, gsn_first_ability, gsn_top_sn - 1 );
               if( sn < 0 )
                  log_printf( "Fread_char: unknown ability: %s", ability );
               else
               {
                  ch->pcdata->learned[sn] = value;
                  if( ch->level < LEVEL_IMMORTAL )
                  {
                     if( skill_table[sn]->race_level[ch->race] >= LEVEL_IMMORTAL )
                     {
                        ch->pcdata->learned[sn] = 0;
                        ch->practice++;
                     }
                  }
               }
               fMatch = TRUE;
               break;
            }


Skills.c
Find check_skills.
Just above, Add:
/* 
 * Racial Skills Handling -- Kayle 1-28-07
 */
bool check_ability( CHAR_DATA * ch, char *command, char *argument )
{
   int sn;
   int first = gsn_first_ability;
   int top = gsn_top_sn - 1;
   int mana, blood;
   struct timeval time_used;

   /*
    * bsearch for the ability
    */
   for( ;; )
   {
      sn = ( first + top ) >> 1;

      if( LOWER( command[0] ) == LOWER( skill_table[sn]->name[0] ) && !str_prefix( command, skill_table[sn]->name )
          && ( skill_table[sn]->skill_fun || skill_table[sn]->spell_fun != spell_null ) && ( can_use_skill( ch, 0, sn ) ) )
         break;

      if( first >= top )
         return FALSE;
      if( strcasecmp( command, skill_table[sn]->name ) < 1 )
         top = sn - 1;
      else
         first = sn + 1;
   }

   if( !check_pos( ch, skill_table[sn]->minimum_position ) )
      return TRUE;

   if( IS_NPC( ch ) && ( IS_AFFECTED( ch, AFF_CHARM ) || IS_AFFECTED( ch, AFF_POSSESS ) ) )
   {
      send_to_char( "For some reason, you seem unable to perform that...\n\r", ch );
      act( AT_GREY, "$n wanders around aimlessly.", ch, NULL, NULL, TO_ROOM );
      return TRUE;
   }

   /*
    * check if mana is required
    */
   if( skill_table[sn]->min_mana )
   {
      mana = IS_NPC( ch ) ? 0 : UMAX( skill_table[sn]->min_mana, 100 / ( 2 + ch->level - skill_table[sn]->race_level[ch->race] ) );
      if( IS_VAMPIRE( ch ) )
      {
         if( ch->pcdata->condition[COND_BLOODTHIRST] < blood )
         {
            send_to_char( "You don't have enough blood power.\r\n", ch );
            return TRUE;
         }
      }
      else if( !IS_NPC( ch ) && ch->mana < mana )
      {
         send_to_char( "You don't have enough mana.\n\r", ch );
         return TRUE;
      }
   }
   else
   {
      mana = 0;
	  blood = 0;
   }

   /*
    * Is this a real do-fun, or a really a spell?
    */
   if( !skill_table[sn]->skill_fun )
   {
      ch_ret retcode = rNONE;
      void *vo = NULL;
      CHAR_DATA *victim = NULL;
      OBJ_DATA *obj = NULL;

      target_name = "";

      switch ( skill_table[sn]->target )
      {
         default:
            bug( "Check_ability: bad target for sn %d.", sn );
            send_to_char( "Something went wrong...\n\r", ch );
            return TRUE;

         case TAR_IGNORE:
            vo = NULL;
            if( !argument || argument[0] == '\0' )
            {
               if( ( victim = who_fighting( ch ) ) != NULL )
                  target_name = victim->name;
            }
            else
               target_name = argument;
            break;

         case TAR_CHAR_OFFENSIVE:
         {
            if( ( !argument || argument[0] == '\0' ) && !( victim = who_fighting( ch ) ) )
            {
               ch_printf( ch, "Confusion overcomes you as your '%s' has no target.\n\r", skill_table[sn]->name );
               return TRUE;
            }
            else if( argument[0] != '\0' && !( victim = get_char_room( ch, argument ) ) )
            {
               send_to_char( "They aren't here.\n\r", ch );
               return TRUE;
            }
         }
            if( is_safe( ch, victim, TRUE ) )
               return TRUE;

            if( ch == victim && SPELL_FLAG( skill_table[sn], SF_NOSELF ) )
            {
               send_to_char( "You can't target yourself!\n\r", ch );
               return TRUE;
            }

            if( !IS_NPC( ch ) )
            {
               if( !IS_NPC( victim ) )
               {
                  if( get_timer( ch, TIMER_PKILLED ) > 0 )
                  {
                     send_to_char( "You have been killed in the last 5 minutes.\n\r", ch );
                     return TRUE;
                  }

                  if( get_timer( victim, TIMER_PKILLED ) > 0 )
                  {
                     send_to_char( "This player has been killed in the last 5 minutes.\n\r", ch );
                     return TRUE;
                  }

                  if( victim != ch )
                     send_to_char( "You really shouldn't do this to another player...\n\r", ch );
               }

               if( IS_AFFECTED( ch, AFF_CHARM ) && ch->master == victim )
               {
                  send_to_char( "You can't do that on your own follower.\n\r", ch );
                  return TRUE;
               }
            }

            if( check_illegal_pk( ch, victim ) )
            {
               send_to_char( "You can't do that to another player!\n\r", ch );
               return TRUE;
            }
            vo = ( void * )victim;
            break;

         case TAR_CHAR_DEFENSIVE:
         {
            if( argument[0] != '\0' && !( victim = get_char_room( ch, argument ) ) )
            {
               send_to_char( "They aren't here.\n\r", ch );
               return TRUE;
            }
            if( !victim )
               victim = ch;
         }

            if( ch == victim && SPELL_FLAG( skill_table[sn], SF_NOSELF ) )
            {
               send_to_char( "You can't target yourself!\n\r", ch );
               return TRUE;
            }
            vo = ( void * )victim;
            break;

         case TAR_CHAR_SELF:
            victim = ch;
            vo = ( void * )ch;
            break;

         case TAR_OBJ_INV:
         {
            if( !( obj = get_obj_carry( ch, argument ) ) )
            {
               send_to_char( "You can't find that.\n\r", ch );
               return TRUE;
            }
         }
            vo = ( void * )obj;
            break;
      }

      /*
       * waitstate
       */
      WAIT_STATE( ch, skill_table[sn]->beats );
      /*
       * check for failure
       */
      if( ( number_percent(  ) + skill_table[sn]->difficulty * 5 ) > ( IS_NPC( ch ) ? 75 : LEARNED( ch, sn ) ) )
      {
         failed_casting( skill_table[sn], ch, victim, obj );
         learn_from_failure( ch, sn );
         if( mana )
         {
            if( IS_VAMPIRE( ch ) )
               gain_condition( ch, COND_BLOODTHIRST, -blood / 2 );
            else
               ch->mana -= mana / 2;
         }
         return TRUE;
      }
      if( mana )
      {
         if( IS_VAMPIRE( ch ) )
            gain_condition( ch, COND_BLOODTHIRST, -blood );
         else
            ch->mana -= mana;
      }
      start_timer( &time_used );
      retcode = ( *skill_table[sn]->spell_fun ) ( sn, ch->level, ch, vo );
      end_timer( &time_used );
      update_userec( &time_used, &skill_table[sn]->userec );

      if( retcode == rCHAR_DIED || retcode == rERROR )
         return TRUE;

      if( char_died( ch ) )
         return TRUE;

      if( retcode == rSPELL_FAILED )
      {
         learn_from_failure( ch, sn );
         retcode = rNONE;
      }
      else
         ability_learn_from_success( ch, sn );

      if( skill_table[sn]->target == TAR_CHAR_OFFENSIVE && victim != ch && !char_died( victim ) )
      {
         CHAR_DATA *vch;
         CHAR_DATA *vch_next;

         for( vch = ch->in_room->first_person; vch; vch = vch_next )
         {
            vch_next = vch->next_in_room;
            if( victim == vch && !victim->fighting && victim->master != ch )
            {
               retcode = multi_hit( victim, ch, TYPE_UNDEFINED );
               break;
            }
         }
      }
      return TRUE;
   }

   if( mana )
   {
      if( IS_VAMPIRE( ch ) )
         gain_condition( ch, COND_BLOODTHIRST, -blood );
      else
         ch->mana -= mana;
   }
   ch->prev_cmd = ch->last_cmd;  /* haus, for automapping */
   ch->last_cmd = skill_table[sn]->skill_fun;
   start_timer( &time_used );
   ( *skill_table[sn]->skill_fun ) ( ch, argument );
   end_timer( &time_used );
   update_userec( &time_used, &skill_table[sn]->userec );

   tail_chain(  );
   return TRUE;
}


Further down, Find learn_from_success.
Below that, Add:
/*
 * Racial Skills Learning -- Kayle 1-28-07
 */
void ability_learn_from_success( CHAR_DATA * ch, int sn )
{
   int adept, gain, sklvl, learn, percent, schance;

   if( IS_NPC( ch ) || ch->pcdata->learned[sn] <= 0 )
      return;

   adept = skill_table[sn]->race_adept[ch->race];

   sklvl = skill_table[sn]->race_level[ch->race];

   if( sklvl == 0 )
      sklvl = ch->level;
   if( ch->pcdata->learned[sn] < adept )
   {
      schance = ch->pcdata->learned[sn] + ( 5 * skill_table[sn]->difficulty );
      percent = number_percent(  );
      if( percent >= schance )
         learn = 2;
      else if( schance - percent > 25 )
         return;
      else
         learn = 1;
      ch->pcdata->learned[sn] = UMIN( adept, ch->pcdata->learned[sn] + learn );
      if( ch->pcdata->learned[sn] == adept ) /* fully learned! */
      {
         gain = 1000 * sklvl;
         set_char_color( AT_WHITE, ch );
         ch_printf( ch, "You are now an adept of %s!  You gain %d bonus experience!\r\n", skill_table[sn]->name, gain );
      }
      else
      {
         gain = 20 * sklvl;
         if( !ch->fighting && sn != gsn_hide && sn != gsn_sneak )
         {
            set_char_color( AT_WHITE, ch );
            ch_printf( ch, "You gain %d experience points from your success!\r\n", gain );
         }
      }
      gain_exp( ch, gain );
   }
}


Tables.c
In: int get_skill( char *skilltype )
Find:
if( !str_cmp( skilltype, "Race" ) )
      return SKILL_RACIAL;


if( !str_cmp( skilltype, "Racial" ) )
      return SKILL_RACIAL;



With all this in place, racial skills are now working properly. And can be configured to adept in a different manner than other skills. With this current setup they adept at the exact same rate, but with minor modifications, they could adept only on failure. Or only on success. This is the basis for the skills, and will have them up and running. What you do with them afterward is up to you.
       
Pages:<< prev 1 next >>