/* I understand that installing something like this is not a walk in the park, and its * also extremely easy after you get the hang of mudcoding, as long as you can think straight. * This code isn't the best documented, so if you have trouble understanding how I wrote it, * just take some time to think about what is trying to be accomplished. Given the difficulty * of the task I've made it easy to place what goes where by suggesting where to put it. * Some of these locations are definite, others are just suggestions based on my own * expertise. Make a backup before you play with this, if you screw up you'll want to start * over. *DISCLAIMER* This code has been tested to a reasonable degree, and if it fucks * up your mud its probably YOUR fault. It was also designed to work for SWRs only. * Alright, questions and comments, possibly thanks can be directed to ghoulavenger@hotmail.com. * -Arcturus */ /* In Mud.h */ /* under typedef struct skill_type SKILL_TYPE; typedef struct skill_req SKILL_REQ; /* Next section right about struct skill_type */ /* Two different skill requirement types to worry about for now. * Skills account for spells, feats, and any other with a skill sn. * Attributes account for base attributes, like strength rating. * -Arcturus */ #define REQ_SKILL 0 #define REQ_ATTRIBUTE 1 struct skill_req { SKILL_REQ *next_req; SKILL_REQ *prev_req; char *name; sh_int attribute; sh_int prof; sh_int type; }; /* Put this in struct skill_type */ /* For Skill Requirements, by Arcturus */ SKILL_REQ *next_req; SKILL_REQ *prev_req; SKILL_REQ *first_req; SKILL_REQ *last_req; /* Put this right below ability class defines. */ /* Attribute List for Skill Requirements. */ #define ATTRIBUTE_STR 0 #define ATTRIBUTE_INT 1 #define ATTRIBUTE_WIS 2 #define ATTRIBUTE_DEX 3 #define ATTRIBUTE_CON 4 #define ATTRIBUTE_CHA 5 #define ATTRIBUTE_LCK 6 #define ATTRIBUTE_FRC 7 #define MAX_ATTRIBUTE 8 /* Number of attributes. */ /* Under this extern char * const ability_name [MAX_ABILITY]; * Place this */ extern char * const attribute_name [MAX_ATTRIBUTE]; /* tables.c fwrite_skill after minlevel */ if ( skill->first_req ) { SKILL_REQ *requirement; for( requirement = skill->first_req; requirement; requirement = requirement->next_req ) { if(requirement->type == REQ_SKILL ) fprintf(fpout, "REQ %s~ %d\n", requirement->name, requirement->prof ); else if(requirement->type == REQ_ATTRIBUTE ) fprintf(fpout, "REQSTAT %d %d\n", requirement->attribute, requirement->prof ); } } /* fread_skill under case 'R' */ if( !str_cmp( word, "REQ" ) ) { SKILL_REQ *requirement; CREATE( requirement, SKILL_REQ, 1 ); requirement->name = STRALLOC( fread_string( fp ) ); requirement->prof = fread_number( fp ); requirement->type = REQ_SKILL; LINK( requirement , skill->first_req, skill->last_req, next_req, prev_req ); fMatch = TRUE; } if( !str_cmp( word, "REQSTAT" ) ) { SKILL_REQ *requirement; CREATE( requirement, SKILL_REQ, 1 ); requirement->attribute = fread_number( fp ); requirement->prof = fread_number( fp ); requirement->name = str_dup("Attribute"); requirement->type = REQ_ATTRIBUTE; LINK( requirement , skill->first_req, skill->last_req, next_req, prev_req ); fMatch = TRUE; } /* const.c under ability_name */ char * const attribute_name [MAX_ATTRIBUTE] = { "strength", "intelligence", "wisdom", "dexterity", "constitution", "charisma", "luck", "force" }; /* under this ROOM_INDEX_DATA *generate_exit( ROOM_INDEX_DATA *in_room, EXIT_DATA **pexit ); * place this */ bool meets_reqs( CHAR_DATA *ch, int sn ); /* in do_practice after this if ( can_prac && !IS_NPC(ch) && ch->skill_level[skill_table[sn]->guild] < skill_table[sn]->min_level ) { act( AT_TELL, "$n tells you 'You're not ready to learn that yet...'", mob, NULL, ch, TO_VICT ); return; } * place this */ if( !meets_reqs(ch, sn) ) { act( AT_TELL, "$n tells you 'You're not ready to learn that yet...'", mob, NULL, ch, TO_VICT ); return; } /* End of act_info.c */ /* This is for a skill tree type deal, where theres requirements to learn skills. * This goes through the requirement list and compares stuff. * -Arcturus */ bool meets_reqs( CHAR_DATA *ch, int sn ) { SKILL_REQ *requirement; SKILLTYPE *skill; int opsn; if( IS_NPC(ch) ) return TRUE; if( (skill = get_skilltype(sn)) == NULL ) return FALSE; if( !skill->first_req ) return TRUE; for( requirement = skill->first_req; requirement; requirement = requirement->next_req ) { switch(requirement->type) { default: bug("Bad %d requirement type.", requirement->type ); break; case REQ_SKILL: opsn = skill_lookup( requirement->name ); if(opsn < 0) continue; if( ch->pcdata->learned[opsn] < requirement->prof ) return FALSE; break; case REQ_ATTRIBUTE: switch(requirement->attribute) { default: bug("Bad %d attribute skill requirement.", requirement->attribute ); break; case ATTRIBUTE_STR: if( ch->perm_str < requirement->prof ) return FALSE; break; case ATTRIBUTE_INT: if( ch->perm_int < requirement->prof ) return FALSE; break; case ATTRIBUTE_WIS: if( ch->perm_wis < requirement->prof ) return FALSE; break; case ATTRIBUTE_DEX: if( ch->perm_dex < requirement->prof ) return FALSE; break; case ATTRIBUTE_CON: if( ch->perm_con < requirement->prof ) return FALSE; break; case ATTRIBUTE_CHA: if ( ch->perm_cha < requirement->prof ) return FALSE; break; case ATTRIBUTE_LCK: if ( ch->perm_lck < requirement->prof ) return FALSE; break; case ATTRIBUTE_FRC: if ( ch->perm_frc < requirement->prof ) return FALSE; break; } break; } } return TRUE; } /* Skills.c */ /* In do_sset in the field list, add remreq and addreq */ /* in do_sset after this: if ( !str_cmp( arg2, "teachers" ) ) { if ( skill->teachers ) DISPOSE(skill->teachers); if ( str_cmp( argument, "clear" ) ) skill->teachers = str_dup( argument ); send_to_char( "Ok.\n\r", ch ); return; } Place this */ if ( !str_cmp( arg2, "remreq" ) ) { SKILL_REQ *requirement; int num = atoi(argument); if( !skill->first_req ) { send_to_char("No requirements to remove.\n\r", ch); return; } if( !is_number(argument) || argument[0] == '\0') { send_to_char("Remove which requirement?\n\r", ch); return; } if(num == 1) { requirement = skill->first_req; UNLINK(requirement, skill->first_req, skill->last_req, next_req, prev_req ); DISPOSE(requirement); send_to_char( "Ok.\n\r", ch); return; } else { int counter = 0; for( requirement = skill->first_req; requirement; requirement = requirement->next_req ) { ++counter; if(counter == num) { UNLINK( requirement, skill->first_req, skill->last_req, next_req, prev_req ); DISPOSE( requirement ); send_to_char( "Ok.\n\r", ch); return; } } send_to_char("There isn't that many requirements.\n\r", ch); return; } } if( !str_cmp( arg2, "addreq" ) ) { SKILL_REQ *requirement; SKILLTYPE *newskill; int num, typenum = -1; int slot, attribute; bool aFound = FALSE; char location[MAX_INPUT_LENGTH]; char modifier[MAX_INPUT_LENGTH]; char typename[MAX_INPUT_LENGTH]; argument = one_argument( argument, typename ); argument = one_argument( argument, location ); argument = one_argument( argument, modifier ); if( !str_cmp(typename, "attribute") ) typenum = REQ_ATTRIBUTE; else if( !str_cmp(typename, "skill" ) ) typenum = REQ_SKILL; if( typenum == -1 ) { if( is_number(typename) ) typenum = atoi(typename); } switch(typenum) { default: send_to_char("Invalid type argument.\n\r", ch); return; break; case REQ_SKILL: if ( (slot = skill_lookup( location ) ) < 0 ) { if( is_number(location) ) { slot = atoi(location); newskill = get_skilltype( slot ); if(newskill == NULL ) { send_to_char("Invalid sn.\n\r", ch); return; } } } else newskill = get_skilltype( slot ); if(!newskill) { if ( slot <= 0 ) { send_to_char("Invalid skill.\n\r", ch); return; } newskill = get_skilltype( slot ); if( newskill == NULL ) { send_to_char("Invalid skill.\n\r", ch); return; } } if( !(num = atoi(modifier)) ) { send_to_char("Invalid Requirement Level.\n\r", ch); return; } CREATE( requirement, SKILL_REQ, 1 ); requirement->name = str_dup(newskill->name); requirement->prof = num; requirement->type = typenum; LINK( requirement, skill->first_req, skill->last_req, next_req, prev_req ); send_to_char("Ok.\n\r", ch); return; break; case REQ_ATTRIBUTE: for( attribute = 0; attribute < MAX_ATTRIBUTE; attribute++) { if(!str_cmp( attribute_name[attribute], location ) ) { aFound = TRUE; break; } } if(!aFound) { attribute = atoi( location ); if(attribute < 0 || attribute >= MAX_ATTRIBUTE ) { send_to_char("Invalid attribute.\n\r", ch); return; } } if( !(num = atoi(modifier)) ) { send_to_char("Invalid Requirement Level.\n\r", ch); return; } CREATE( requirement, SKILL_REQ, 1 ); requirement->name = str_dup("Attribute"); requirement->prof = num; requirement->type = typenum; requirement->attribute = attribute; LINK( requirement, skill->first_req, skill->last_req, next_req, prev_req ); send_to_char("Ok.\n\r", ch); return; break; } /* in do_slookup */ /* after this if ( skill->participants ) ch_printf( ch, "Participants: %d\n\r", (int) skill->participants ); * place this */ if ( skill->first_req ) { SKILL_REQ *requirement; for( requirement = skill->first_req; requirement; requirement = requirement->next_req ) { if(requirement->type == REQ_SKILL) ch_printf(ch, "%s required at %d%%.\n\r", requirement->name, requirement->prof ); else if(requirement->type == REQ_ATTRIBUTE) ch_printf(ch, "%s required at %d points.\n\r", attribute_name[requirement->attribute], requirement->prof ); else ch_printf(ch, "Unknown Requirement Type.\n\r"); } }