/* 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");
}
}