/********************************************************** *************** S U N D E R M U D *** 2 . 0 ************** ********************************************************** * The unique portions of the SunderMud code as well as * * the integration efforts for code from other sources is * * based primarily on the efforts of: * * * * Lotherius <aelfwyne@operamail.com> (Alvin W. Brinson) * * and many others, see "help sundermud" in the mud. * **********************************************************/ /* * This File includes non-spell skill functions. */ #include "everything.h" #include "magic.h" DECLARE_DO_FUN ( do_say ); /* command procedures */ /* Zeran - altered to work with skillmaster * reason should be SKILL_flag */ bool skill_available ( int sn, CHAR_DATA * ch, int reason, CHAR_DATA * mob ) { int i; int level; if ( IS_NPC ( ch ) ) return FALSE; /* Currently not setup for NPC use */ for ( i = 0; i < MAX_CLASS; i++ ) { if ( ( pc_race_table[ch->pcdata->pcrace].skills[i] == NULL ) || ( sn < 0 ) ) break; if ( sn == ( skill_lookup( pc_race_table[ch->pcdata->pcrace].skills[i] ) ) ) { return TRUE; } } /* Zeran - altered slightly for skillmaster stuff */ level = skill_table[sn].skill_level[ch->pcdata->pclass]; switch ( reason ) { case SKILL_AVAIL: { if ( ch->level >= level ) return TRUE; return FALSE; } case SKILL_PRAC: { if ( ch->level < level ) return FALSE; if ( level >= 101 ) { send_to_char ( "You must seek a true master to learn that.\n\r", ch ); return FALSE; } return TRUE; } case SKILL_LEARN: { if ( ch->level < level ) return FALSE; if ( level < 101 ) { send_to_char ( "Your guildmaster would be a better choice.\n\r", ch ); return FALSE; } if ( !is_skillmaster_skill ( mob, sn ) ) { do_say ( mob, "I do not have the knowledge to teach you that." ); return FALSE; } return TRUE; } default: { bugf ( "Invalid reason code to skill_available" ); return FALSE; } } /* end switch */ } /* Zeran - added this to call from do_practice and do_learn */ void show_current_prac ( CHAR_DATA * ch ) { int col = 0; int sn; BUFFER *buffer; buffer = buffer_new(1000); for ( sn = 0; sn < MAX_SKILL; sn++ ) { if ( skill_table[sn].name == NULL ) break; if ( skill_available ( sn, ch, SKILL_AVAIL, NULL ) == FALSE ) continue; bprintf ( buffer, "%-18s %3d%% ", skill_table[sn].name, ch->pcdata->learned[sn] ); if ( ++col % 3 == 0 ) bprintf (buffer, "\n\r" ); } if ( col % 3 != 0 ) bprintf( buffer, "\n\r"); bprintf ( buffer, "You have %d practice sessions left.\n\r", ch->pcdata->practice ); page_to_char ( buffer->data, ch ); buffer_free(buffer); return; } bool is_skillmaster_skill ( CHAR_DATA * mob, int sn ) { int count; MOB_INDEX_DATA *mIndex; mIndex = mob->pIndexData; for ( count = 0; count < mIndex->total_teach_skills; count++ ) if ( skill_lookup ( mIndex->teach_skills[count] ) == sn ) return TRUE; return FALSE; } void show_skillmaster_skills ( CHAR_DATA * ch, CHAR_DATA * mob ) { int count; int total; total = mob->pIndexData->total_teach_skills; /* List the skills */ do_say ( mob, "I have knowledge of the following:" ); for ( count = 0; count < total; count++ ) do_say ( mob, mob->pIndexData->teach_skills[count] ); return; } int exp_per_level ( CHAR_DATA * ch, int points ) { int tolev; if ( IS_NPC ( ch ) ) return 1000; tolev = 1200 + (points * 100); if (ch->pcdata->mortal) return tolev; else return (tolev / 4 ) + 7700; } /* checks for skill improvement */ void check_improve ( CHAR_DATA * ch, int sn, bool success, int multiplier ) { int chance; if ( IS_NPC ( ch ) ) return; if ( ch->level < skill_table[sn].skill_level[ch->pcdata->pclass] || ch->pcdata->learned[sn] == 0 || ch->pcdata->learned[sn] == 100 ) return; /* skill is not known or is max */ /* check to see if the character has a chance to learn */ chance = 10 * int_app[get_curr_stat ( ch, STAT_INT )].learn; chance /= ( multiplier * 4 ); chance += ch->level; if ( number_range ( 1, 1000 ) > chance ) return; /* now that the character has a CHANCE to learn, see if they really have */ if ( success ) { chance = URANGE ( 5, 100 - ch->pcdata->learned[sn], 95 ); if ( number_percent ( ) < chance ) { form_to_char ( ch, "You have become better at %s!\n\r", skill_table[sn].name ); ch->pcdata->learned[sn]++; gain_exp ( ch, 4 ); } } else { chance = URANGE ( 5, ch->pcdata->learned[sn] / 2, 30 ); if ( number_percent ( ) < chance ) { form_to_char ( ch, "You learn from your mistakes, and your %s skill improves.\n\r", skill_table[sn].name ); ch->pcdata->learned[sn] += number_range ( 1, 3 ); ch->pcdata->learned[sn] = UMIN ( ch->pcdata->learned[sn], 100 ); gain_exp ( ch, 3 ); } } return; } void do_skills ( CHAR_DATA * ch, char *argument ) { char skill_list[LEVEL_HERO][MAX_STRING_LENGTH]; char skill_columns[LEVEL_HERO]; int sn, lev, i, filter; bool found = FALSE; char buf[MAX_STRING_LENGTH]; BUFFER *outbuf; if ( IS_NPC ( ch ) ) return; outbuf = buffer_new(1000); if ( argument == NULL || argument[0] == '\0' ) /* This character's own list. Normal. */ { filter = -1; } else { filter = class_lookup ( argument ); if ( filter == -1 ) { send_to_char ( "That's not a class.\n\r", ch ); buffer_free(outbuf); return; } else { bprintf( outbuf, "Skills For %s", class_table[filter].name ); } } /* initilize data */ for ( lev = 0; lev < LEVEL_HERO; lev++ ) { skill_columns[lev] = 0; skill_list[lev][0] = '\0'; } for ( sn = 0; sn < MAX_SKILL; sn++ ) { if ( skill_table[sn].name == NULL ) break; if ( ( ( (filter == -1) && ( skill_available ( sn, ch, SKILL_AVAIL, NULL ) == TRUE ) ) || ( (filter >= 0) && (skill_table[sn].skill_level[filter] <= 101) ) ) && skill_table[sn].spell_fun == spell_null ) { found = TRUE; if (filter == -1) lev = skill_table[sn].skill_level[ch->pcdata->pclass]; else lev = skill_table[sn].skill_level[filter]; if (filter == -1) { for ( i = 0; i < 5; i++ ) { if ( ( pc_race_table[ch->pcdata->pcrace].skills[i] == NULL ) || ( sn < 0 ) ) break; if ( sn == ( skill_lookup ( pc_race_table[ch->pcdata->pcrace].skills[i] ) ) ) lev = 1; } } if ( ch->level < lev ) SNP ( buf, "%-18s n/a ", skill_table[sn].name ); else SNP ( buf, "%-18s %3d%% ", skill_table[sn].name, ch->pcdata->learned[sn] ); if ( skill_list[lev][0] == '\0' ) SNP ( skill_list[lev], "\n\rLevel %2d: %s", lev, buf ); else /* append */ { if ( ++skill_columns[lev] % 2 == 0 ) SLCAT ( skill_list[lev], "\n\r " ); SLCAT ( skill_list[lev], buf ); } } } /* return results */ if ( !found ) { send_to_char ( "No skills found.\n\r", ch ); } else { for ( lev = 0; lev < LEVEL_HERO; lev++ ) { if ( skill_list[lev][0] != '\0' ) buffer_strcat ( outbuf, skill_list[lev] ); } buffer_strcat ( outbuf, "\n\r" ); page_to_char ( outbuf->data, ch ); } buffer_free(outbuf); return; } /* * Lookup a skill by name. */ int skill_lookup ( const char *name ) { int sn; for ( sn = 0; sn < MAX_SKILL; sn++ ) { if ( skill_table[sn].name == NULL ) break; if ( LOWER ( name[0] ) == LOWER ( skill_table[sn].name[0] ) && !str_prefix ( name, skill_table[sn].name ) ) return sn; } return -1; } /* * Lookup a skill by slot number. * Used for object loading. */ int slot_lookup ( int slot ) { extern bool fBootDb; extern bool fImportDb; int sn; if ( slot <= 0 ) return -1; for ( sn = 0; sn < MAX_SKILL; sn++ ) { if ( slot == skill_table[sn].slot ) return sn; } if ( fBootDb || fImportDb) { bugf ( "Slot_lookup: bad slot %d.", slot ); abort ( ); } return -1; }