/*************************************************************************** * Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik Stfeldt, 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-1998 Russ Taylor * * ROM has been brought to you by the ROM consortium * * Russ Taylor (rtaylor@hypercube.org) * * Gabrielle Taylor (gtaylor@hypercube.org) * * 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 * ***************************************************************************/ #if defined(macintosh) #include <types.h> #include <time.h> #else #include <sys/types.h> #include <sys/time.h> #endif #include <stdio.h> #include <string.h> #include <stdlib.h> #include "merc.h" #include "interp.h" #include "recycle.h" #include "const.h" bool skedit_new args( ( CHAR_DATA *ch, char *argument ) ); void do_skills(CHAR_DATA *ch, char *argument) { BUFFER *buffer; char arg[MAX_INPUT_LENGTH]; char skill_list[LEVEL_HERO + 1][MAX_STRING_LENGTH]; char skill_columns[LEVEL_HERO + 1]; int sn, level, min_lev = 1, max_lev = LEVEL_HERO; bool fAll = FALSE, found = FALSE; char buf[MAX_STRING_LENGTH]; if (IS_NPC(ch)) return; if (argument[0] != '\0') { fAll = TRUE; if (str_prefix(argument,"all")) { argument = one_argument(argument,arg); if (!is_number(arg)) { send_to_char("Arguments must be numerical or all.\n\r",ch); return; } max_lev = atoi(arg); if (max_lev < 1 || max_lev > LEVEL_HERO) { sprintf(buf,"Levels must be between 1 and %d.\n\r",LEVEL_HERO); send_to_char(buf,ch); return; } if (argument[0] != '\0') { argument = one_argument(argument,arg); if (!is_number(arg)) { send_to_char("Arguments must be numerical or all.\n\r",ch); return; } min_lev = max_lev; max_lev = atoi(arg); if (max_lev < 1 || max_lev > LEVEL_HERO) { sprintf(buf, "Levels must be between 1 and %d.\n\r",LEVEL_HERO); send_to_char(buf,ch); return; } if (min_lev > max_lev) { send_to_char("That would be silly.\n\r",ch); return; } } } } /* initialize data */ for (level = 0; level < LEVEL_HERO + 1; level++) { skill_columns[level] = 0; skill_list[level][0] = '\0'; } for (sn = 0; sn < MAX_SKILL; sn++) { if (skill_table[sn].name == NULL ) break; if ( (level = skill_level(ch, sn)) < LEVEL_HERO + 1 && (fAll || level <= ch->level) && level >= min_lev && level <= max_lev && ch->pcdata->learned[sn] > 0) { found = TRUE; level = skill_level(ch, sn); if (ch->level < level) sprintf(buf,"%-18s n/a ", skill_table[sn].name); else sprintf(buf,"%-18s %3d%% ",skill_table[sn].name, ch->pcdata->learned[sn]); if (skill_list[level][0] == '\0') sprintf(skill_list[level],"\n\rLevel %2d: %s",level,buf); else /* append */ { if ( ++skill_columns[level] % 2 == 0) strcat(skill_list[level],"\n\r "); strcat(skill_list[level],buf); } } } /* return results */ if (!found) { send_to_char("No skills found.\n\r",ch); return; } buffer = new_buf(); for (level = 0; level < LEVEL_HERO + 1; level++) if (skill_list[level][0] != '\0') add_buf(buffer,skill_list[level]); add_buf(buffer,"\n\r"); page_to_char(buf_string(buffer),ch); free_buf(buffer); } /* shows skills, groups and costs (only if not bought) */ int exp_per_level(CHAR_DATA *ch, int points) { if (IS_NPC(ch)) return 1000; return UMAX(1, ch->level) * 1000; } int exp_to_level(CHAR_DATA *ch) { long total =1000; int i; if (ch->level == 1 || IS_NPC(ch)) return 1000; for(i = 1; i <= ch->level ; i++) total += i*1000; return total - ch->exp; } /* checks for skill improvement */ void check_improve( CHAR_DATA *ch, int sn, bool success, int multiplier ) { int chance; char buf[100]; if (IS_NPC(ch)) return; if (!can_use_skpell(ch, sn) || skill_rating(ch, sn) < 1 || ch->pcdata->learned[sn] == 0 || ch->pcdata->learned[sn] == 100) return; /* skill is not known */ /* check to see if the character has a chance to learn */ chance = 10 * int_app[get_curr_stat(ch,STAT_INT)].learn; chance /= ( multiplier * skill_rating(ch, sn) * 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) { sprintf(buf,"You have become better at %s!\n\r", skill_table[sn].name); send_to_char(buf,ch); ch->pcdata->learned[sn]++; gain_exp(ch,2 * skill_rating(ch, sn)); } } else { chance = URANGE(5,ch->pcdata->learned[sn]/2,30); if (number_percent() < chance) { sprintf(buf, "You learn from your mistakes, and your %s skill improves.\n\r", skill_table[sn].name); send_to_char(buf,ch); ch->pcdata->learned[sn] += number_range(1,3); ch->pcdata->learned[sn] = UMIN(ch->pcdata->learned[sn],100); gain_exp(ch,2 * skill_rating(ch, sn)); } } } GROUP_DATA *group_lookup( const char *name ) { GROUP_DATA *pGrp; for (pGrp = group_list;pGrp ; pGrp = pGrp->next) { if(LOWER(pGrp->name[0]) == LOWER(name[0]) && !str_prefix(name, pGrp->name) ) return pGrp; } return NULL; } void set_char_groups(CHAR_DATA *ch, int type ) { GROUP_DATA *pGrp; int i, sn; if(IS_NPC(ch)) return; switch (type) { case TYPE_CLAN: if(!is_clan(ch)) return; pGrp = group_lookup(clan_table[ch->clan].name); break; case TYPE_RELIGION: if(!ch->pcdata->religion) return; pGrp = group_lookup(ch->pcdata->religion->name ); break; case TYPE_CLASS: pGrp = group_lookup(class_table[ch->clss].name ); break; case TYPE_RACE: pGrp = group_lookup(pc_race_table[ch->race].name); break; } if(!pGrp) { logf2("Group bad for %s on type %d.", ch->name, type); return; } for( i = 0 ; i < MAX_IN_GROUP ; i++ ) { if(!str_cmp(pGrp->spells[i], "reserved" ) ) continue; if( ( sn = skill_lookup(pGrp->spells[i]) ) == -1 ) { logf2("set_char_groups: Invalid spell! %s",pGrp->spells[i]); continue; } ch->pcdata->learned[sn] = 1; } return; } void strip_group(CHAR_DATA *ch, int type ) { GROUP_DATA *pGrp; int i, sn; if(IS_NPC(ch)) return; switch (type) { case TYPE_CLAN: if(!is_clan(ch)) return; pGrp = group_lookup(clan_table[ch->clan].name); break; case TYPE_RELIGION: if(!ch->pcdata->religion) return; pGrp = group_lookup(ch->pcdata->religion->name ); break; case TYPE_CLASS: pGrp = group_lookup(class_table[ch->clss].name ); break; case TYPE_RACE: pGrp = group_lookup(pc_race_table[ch->race].name); break; } if(!pGrp) { logf2("Group bad for %s on type %d.", ch->name, type); return; } for( i = 0 ; i < MAX_IN_GROUP ; i++ ) { if(!str_cmp(pGrp->spells[i], "reserved" ) ) continue; if( ( sn = skill_lookup(pGrp->spells[i]) ) == -1 ) { logf2("strip_group: Invalid spell! %s",pGrp->spells[i]); continue; } ch->pcdata->learned[sn] = 0; } return; }