A few Bug-Fixes and Ideas

This commit is contained in:
JamDog
2010-11-06 15:47:38 +00:00
parent 222be04ec5
commit d4454288b1
9 changed files with 249 additions and 150 deletions

View File

@@ -12,8 +12,8 @@
#define __CLASS_C__ #define __CLASS_C__
/* This file attempts to concentrate most of the code which must be changed /* This file attempts to concentrate most of the code which must be changed
* in order for new classes to be added. If you're adding a new class, you * in order for new classes to be added. If you're adding a new class, you
* should go through this entire file from beginning to end and add the * should go through this entire file from beginning to end and add the
* appropriate new special cases for your new class. */ * appropriate new special cases for your new class. */
#include "conf.h" #include "conf.h"
@@ -53,7 +53,7 @@ const char *class_menu =
" [W]arrior\r\n" " [W]arrior\r\n"
" [M]agic-user\r\n"; " [M]agic-user\r\n";
/* The code to interpret a class letter -- used in interpreter.c when a new /* The code to interpret a class letter -- used in interpreter.c when a new
* character is selecting a class and by 'set class' in act.wizard.c. */ * character is selecting a class and by 'set class' in act.wizard.c. */
int parse_class(char arg) int parse_class(char arg)
{ {
@@ -68,9 +68,9 @@ int parse_class(char arg)
} }
} }
/* bitvectors (i.e., powers of two) for each class, mainly for use in do_who /* bitvectors (i.e., powers of two) for each class, mainly for use in do_who
* and do_users. Add new classes at the end so that all classes use sequential * and do_users. Add new classes at the end so that all classes use sequential
* powers of two (1 << 0, 1 << 1, 1 << 2, 1 << 3, 1 << 4, 1 << 5, etc.) up to * powers of two (1 << 0, 1 << 1, 1 << 2, 1 << 3, 1 << 4, 1 << 5, etc.) up to
* the limit of your bitvector_t, typically 0-31. */ * the limit of your bitvector_t, typically 0-31. */
bitvector_t find_class_bitvector(const char *arg) bitvector_t find_class_bitvector(const char *arg)
{ {
@@ -82,17 +82,17 @@ bitvector_t find_class_bitvector(const char *arg)
return (ret); return (ret);
} }
/* These are definitions which control the guildmasters for each class. /* These are definitions which control the guildmasters for each class.
* The first field (top line) controls the highest percentage skill level a * The first field (top line) controls the highest percentage skill level a
* character of the class is allowed to attain in any skill. (After this * character of the class is allowed to attain in any skill. (After this
* level, attempts to practice will say "You are already learned in this area." * level, attempts to practice will say "You are already learned in this area."
* *
* The second line controls the maximum percent gain in learnedness a character * The second line controls the maximum percent gain in learnedness a character
* is allowed per practice -- in other words, if the random die throw comes out * is allowed per practice -- in other words, if the random die throw comes out
* higher than this number, the gain will only be this number instead. * higher than this number, the gain will only be this number instead.
* *
* The third line controls the minimu percent gain in learnedness a character * The third line controls the minimu percent gain in learnedness a character
* is allowed per practice -- in other words, if the random die throw comes * is allowed per practice -- in other words, if the random die throw comes
* out below this number, the gain will be set up to this number. * out below this number, the gain will be set up to this number.
* *
* The fourth line simply sets whether the character knows 'spells' or 'skills'. * The fourth line simply sets whether the character knows 'spells' or 'skills'.
@@ -117,20 +117,20 @@ int prac_params[4][NUM_CLASSES] = {
}; };
/* The appropriate rooms for each guildmaster/guildguard; controls which types /* The appropriate rooms for each guildmaster/guildguard; controls which types
* of people the various guildguards let through. i.e., the first line shows * of people the various guildguards let through. i.e., the first line shows
* that from room 3017, only MAGIC_USERS are allowed to go south. Don't forget * that from room 3017, only MAGIC_USERS are allowed to go south. Don't forget
* to visit spec_assign.c if you create any new mobiles that should be a guild * to visit spec_assign.c if you create any new mobiles that should be a guild
* master or guard so they can act appropriately. If you "recycle" the * master or guard so they can act appropriately. If you "recycle" the
* existing mobs that are used in other guilds for your new guild, then you * existing mobs that are used in other guilds for your new guild, then you
* don't have to change that file, only here. Guildguards are now implemented * don't have to change that file, only here. Guildguards are now implemented
* via triggers. This code remains as an example. */ * via triggers. This code remains as an example. */
struct guild_info_type guild_info[] = { struct guild_info_type guild_info[] = {
/* Midgaard */ /* Midgaard */
{ CLASS_MAGIC_USER, 3017, SOUTH }, { CLASS_MAGIC_USER, 3017, SOUTH },
{ CLASS_CLERIC, 3004, NORTH }, { CLASS_CLERIC, 3004, NORTH },
{ CLASS_THIEF, 3027, EAST }, { CLASS_THIEF, 3027, EAST },
{ CLASS_WARRIOR, 3021, EAST }, { CLASS_WARRIOR, 3021, EAST },
/* Brass Dragon */ /* Brass Dragon */
{ -999 /* all */ , 5065, WEST }, { -999 /* all */ , 5065, WEST },
@@ -139,7 +139,7 @@ struct guild_info_type guild_info[] = {
{ -1, NOWHERE, -1} { -1, NOWHERE, -1}
}; };
/* Saving throws for : MCTW : PARA, ROD, PETRI, BREATH, SPELL. Levels 0-40. Do /* Saving throws for : MCTW : PARA, ROD, PETRI, BREATH, SPELL. Levels 0-40. Do
* not forget to change extern declaration in magic.c if you add to this. */ * not forget to change extern declaration in magic.c if you add to this. */
byte saving_throws(int class_num, int type, int level) byte saving_throws(int class_num, int type, int level)
{ {
@@ -1344,7 +1344,7 @@ int thaco(int class_num, int level)
/* Roll the 6 stats for a character... each stat is made of the sum of the best /* Roll the 6 stats for a character... each stat is made of the sum of the best
* 3 out of 4 rolls of a 6-sided die. Each class then decides which priority * 3 out of 4 rolls of a 6-sided die. Each class then decides which priority
* will be given for the best to worst stats. */ * will be given for the best to worst stats. */
void roll_real_abils(struct char_data *ch) void roll_real_abils(struct char_data *ch)
{ {
@@ -1456,13 +1456,13 @@ void do_start(struct char_data *ch)
GET_COND(ch, HUNGER) = 24; GET_COND(ch, HUNGER) = 24;
GET_COND(ch, DRUNK) = 0; GET_COND(ch, DRUNK) = 0;
SET_BIT_AR(PRF_FLAGS(ch), PRF_AUTOEXIT); SET_BIT_AR(PRF_FLAGS(ch), PRF_AUTOEXIT);
if (CONFIG_SITEOK_ALL) if (CONFIG_SITEOK_ALL)
SET_BIT_AR(PLR_FLAGS(ch), PLR_SITEOK); SET_BIT_AR(PLR_FLAGS(ch), PLR_SITEOK);
} }
/* This function controls the change to maxmove, maxmana, and maxhp for each /* This function controls the change to maxmove, maxmana, and maxhp for each
* class every time they gain a level. */ * class every time they gain a level. */
void advance_level(struct char_data *ch) void advance_level(struct char_data *ch)
{ {
@@ -1521,8 +1521,8 @@ void advance_level(struct char_data *ch)
} }
/* This simply calculates the backstab multiplier based on a character's level. /* This simply calculates the backstab multiplier based on a character's level.
* This used to be an array, but was changed to be a function so that it would * This used to be an array, but was changed to be a function so that it would
* be easier to add more levels to your MUD. This doesn't really create a big * be easier to add more levels to your MUD. This doesn't really create a big
* performance hit because it's not used very often. */ * performance hit because it's not used very often. */
int backstab_mult(int level) int backstab_mult(int level)
{ {
@@ -1559,8 +1559,8 @@ int invalid_class(struct char_data *ch, struct obj_data *obj)
return FALSE; return FALSE;
} }
/* SPELLS AND SKILLS. This area defines which spells are assigned to which /* SPELLS AND SKILLS. This area defines which spells are assigned to which
* classes, and the minimum level the character must be to use the spell or * classes, and the minimum level the character must be to use the spell or
* skill. */ * skill. */
void init_spell_levels(void) void init_spell_levels(void)
{ {
@@ -1587,6 +1587,7 @@ void init_spell_levels(void)
spell_level(SPELL_FIREBALL, CLASS_MAGIC_USER, 15); spell_level(SPELL_FIREBALL, CLASS_MAGIC_USER, 15);
spell_level(SPELL_CHARM, CLASS_MAGIC_USER, 16); spell_level(SPELL_CHARM, CLASS_MAGIC_USER, 16);
spell_level(SPELL_IDENTIFY, CLASS_MAGIC_USER, 20); spell_level(SPELL_IDENTIFY, CLASS_MAGIC_USER, 20);
spell_level(SPELL_FLY, CLASS_MAGIC_USER, 22);
spell_level(SPELL_ENCHANT_WEAPON, CLASS_MAGIC_USER, 26); spell_level(SPELL_ENCHANT_WEAPON, CLASS_MAGIC_USER, 26);
spell_level(SPELL_CLONE, CLASS_MAGIC_USER, 30); spell_level(SPELL_CLONE, CLASS_MAGIC_USER, 30);
@@ -1637,7 +1638,7 @@ void init_spell_levels(void)
spell_level(SKILL_BASH, CLASS_WARRIOR, 12); spell_level(SKILL_BASH, CLASS_WARRIOR, 12);
} }
/* This is the exp given to implementors -- it must always be greater than the /* This is the exp given to implementors -- it must always be greater than the
* exp required for immortality, plus at least 20,000 or so. */ * exp required for immortality, plus at least 20,000 or so. */
#define EXP_MAX 10000000 #define EXP_MAX 10000000

View File

@@ -27,7 +27,7 @@
/* Utility functions */ /* Utility functions */
/* Thanks to James Long for his assistance in plugging the memory leak that /* Thanks to James Long for his assistance in plugging the memory leak that
* used to be here. - Welcor */ * used to be here. - Welcor */
/* Adds a variable with given name and value to trigger. */ /* Adds a variable with given name and value to trigger. */
void add_var(struct trig_var_data **var_list, const char *name, const char *value, long id) void add_var(struct trig_var_data **var_list, const char *name, const char *value, long id)
@@ -75,8 +75,8 @@ char *skill_percent(struct char_data *ch, char *skill)
return retval; return retval;
} }
/* Search through all the persons items, including containers. 0 if it doesnt /* Search through all the persons items, including containers. 0 if it doesnt
* exist, and greater then 0 if it does! Jamie Nelson. Now also searches by * exist, and greater then 0 if it does! Jamie Nelson. Now also searches by
* vnum and returns the number of matching objects. - Welcor */ * vnum and returns the number of matching objects. - Welcor */
int item_in_list(char *item, obj_data *list) int item_in_list(char *item, obj_data *list)
{ {
@@ -115,8 +115,8 @@ int item_in_list(char *item, obj_data *list)
return count; return count;
} }
/* BOOLEAN return, just check if a player or mob has an item of any sort, /* BOOLEAN return, just check if a player or mob has an item of any sort,
* searched for by name or id. Searching equipment as well as inventory, and * searched for by name or id. Searching equipment as well as inventory, and
* containers. Jamie Nelson */ * containers. Jamie Nelson */
int char_has_item(char *item, struct char_data *ch) int char_has_item(char *item, struct char_data *ch)
{ {
@@ -401,11 +401,11 @@ void find_replacement(void *go, struct script_data *sc, trig_data *trig,
* - count number of objects in room X with this name/id/vnum * - count number of objects in room X with this name/id/vnum
* %findmob.<room vnum X>(<mob vnum Y>)% * %findmob.<room vnum X>(<mob vnum Y>)%
* - count number of mobs in room X with vnum Y * - count number of mobs in room X with vnum Y
* For example you want to check how many PC's are in room with vnum 1204. PC's * For example you want to check how many PC's are in room with vnum 1204. PC's
* have the vnum -1 so: %echo% players in room 1204: %findmob.1204(-1)% * have the vnum -1 so: %echo% players in room 1204: %findmob.1204(-1)%
* Or say you had a bank, and you want a script to check the number of bags of * Or say you had a bank, and you want a script to check the number of bags of
* gold (vnum: 1234). In the vault (vnum: 453). Use: %findobj.453(1234)% and it * gold (vnum: 1234). In the vault (vnum: 453). Use: %findobj.453(1234)% and it
* will return the number of bags of gold. * will return the number of bags of gold.
* Addition inspired by Jamie Nelson */ * Addition inspired by Jamie Nelson */
else if (!str_cmp(var, "findmob")) { else if (!str_cmp(var, "findmob")) {
if (!field || !*field || !subfield || !*subfield) { if (!field || !*field || !subfield || !*subfield) {
@@ -530,7 +530,7 @@ void find_replacement(void *go, struct script_data *sc, trig_data *trig,
} }
if (c) { if (c) {
if (!str_cmp(field, "global")) { /* get global of something else */ if (!str_cmp(field, "global")) { /* get global of something else */
if (IS_NPC(c) && c->script) { if (IS_NPC(c) && c->script) {
find_replacement(go, c->script, NULL, MOB_TRIGGER, find_replacement(go, c->script, NULL, MOB_TRIGGER,
subfield, NULL, NULL, str, slen); subfield, NULL, NULL, str, slen);
@@ -581,8 +581,18 @@ void find_replacement(void *go, struct script_data *sc, trig_data *trig,
} }
snprintf(str, slen, "%d", GET_CHA(c)); snprintf(str, slen, "%d", GET_CHA(c));
} }
else if (!str_cmp(field, "class")) else if (!str_cmp(field, "class")) {
sprinttype(GET_CLASS(c), pc_class_types, str, slen); if (subfield && *subfield) {
int cl = get_class_by_name(subfield);
if (cl != -1) {
GET_CLASS(c) = cl;
snprintf(str, slen, "1");
} else {
snprintf(str, slen, "0");
}
} else
sprinttype(GET_CLASS(c), pc_class_types, str, slen);
}
else if (!str_cmp(field, "con")) { else if (!str_cmp(field, "con")) {
if (subfield && *subfield) { if (subfield && *subfield) {
int addition = atoi(subfield); int addition = atoi(subfield);
@@ -672,14 +682,14 @@ void find_replacement(void *go, struct script_data *sc, trig_data *trig,
else else
snprintf(str, slen, "%d", char_has_item(subfield, c)); snprintf(str, slen, "%d", char_has_item(subfield, c));
} }
else if (!str_cmp(field, "hasattached")) { else if (!str_cmp(field, "hasattached")) {
if (!(subfield && *subfield) || !IS_NPC(c)) if (!(subfield && *subfield) || !IS_NPC(c))
*str = '\0'; *str = '\0';
else { else {
i = atoi(subfield); i = atoi(subfield);
snprintf(str, slen, "%d", trig_is_attached(SCRIPT(c), i)); snprintf(str, slen, "%d", trig_is_attached(SCRIPT(c), i));
} }
} }
else if (!str_cmp(field, "heshe")) else if (!str_cmp(field, "heshe"))
snprintf(str, slen, "%s", HSSH(c)); snprintf(str, slen, "%s", HSSH(c));
else if (!str_cmp(field, "himher")) else if (!str_cmp(field, "himher"))
@@ -766,8 +776,13 @@ void find_replacement(void *go, struct script_data *sc, trig_data *trig,
} }
break; break;
case 'l': case 'l':
if (!str_cmp(field, "level")) if (!str_cmp(field, "level")) {
snprintf(str, slen, "%d", GET_LEVEL(c)); if (subfield && *subfield) {
int lev = atoi(subfield);
GET_LEVEL(c) = MIN(MAX(lev, 0), LVL_IMMORT-1);
} else
snprintf(str, slen, "%d", GET_LEVEL(c));
}
break; break;
case 'm': case 'm':
if (!str_cmp(field, "mana")) { if (!str_cmp(field, "mana")) {
@@ -846,19 +861,19 @@ void find_replacement(void *go, struct script_data *sc, trig_data *trig,
snprintf(str, slen, "%d", GET_PRACTICES(c)); snprintf(str, slen, "%d", GET_PRACTICES(c));
} }
else if (!str_cmp(field, "pref")) { else if (!str_cmp(field, "pref")) {
if (subfield && *subfield) { if (subfield && *subfield) {
int pref = get_flag_by_name(preference_bits, subfield); int pref = get_flag_by_name(preference_bits, subfield);
if (!IS_NPC(c) && pref != NOFLAG && PRF_FLAGGED(c, pref)) if (!IS_NPC(c) && pref != NOFLAG && PRF_FLAGGED(c, pref))
strcpy(str, "1"); strcpy(str, "1");
else else
strcpy(str, "0"); strcpy(str, "0");
} else } else
strcpy(str, "0"); strcpy(str, "0");
} }
break; break;
case 'q': case 'q':
if (!IS_NPC(c) && (!str_cmp(field, "questpoints") || if (!IS_NPC(c) && (!str_cmp(field, "questpoints") ||
!str_cmp(field, "qp") || !str_cmp(field, "qpnts"))) !str_cmp(field, "qp") || !str_cmp(field, "qpnts")))
{ {
if (subfield && *subfield) { if (subfield && *subfield) {
int addition = atoi(subfield); int addition = atoi(subfield);
@@ -866,25 +881,25 @@ void find_replacement(void *go, struct script_data *sc, trig_data *trig,
} }
snprintf(str, slen, "%d", GET_QUESTPOINTS(c)); snprintf(str, slen, "%d", GET_QUESTPOINTS(c));
} }
else if (!str_cmp(field, "quest")) else if (!str_cmp(field, "quest"))
{ {
if (!IS_NPC(c) && (GET_QUEST(c) != NOTHING) && (real_quest(GET_QUEST(c)) != NOTHING)) if (!IS_NPC(c) && (GET_QUEST(c) != NOTHING) && (real_quest(GET_QUEST(c)) != NOTHING))
snprintf(str, slen, "%d", GET_QUEST(c)); snprintf(str, slen, "%d", GET_QUEST(c));
else else
strcpy(str, "0"); strcpy(str, "0");
} }
else if (!str_cmp(field, "questdone")) else if (!str_cmp(field, "questdone"))
{ {
if (!IS_NPC(c) && subfield && *subfield) { if (!IS_NPC(c) && subfield && *subfield) {
int q_num = atoi(subfield); int q_num = atoi(subfield);
if (is_complete(c, q_num)) if (is_complete(c, q_num))
strcpy(str, "1"); strcpy(str, "1");
else else
strcpy(str, "0"); strcpy(str, "0");
} }
else else
strcpy(str, "0"); strcpy(str, "0");
} }
break; break;
case 'r': case 'r':
if (!str_cmp(field, "room")) { /* in NOWHERE, return the void */ if (!str_cmp(field, "room")) { /* in NOWHERE, return the void */
@@ -1058,15 +1073,15 @@ void find_replacement(void *go, struct script_data *sc, trig_data *trig,
*str = '\x1'; *str = '\x1';
switch (LOWER(*field)) { switch (LOWER(*field)) {
case 'a': case 'a':
if (!str_cmp(field, "affects")) { if (!str_cmp(field, "affects")) {
if (subfield && *subfield) { if (subfield && *subfield) {
if (check_flags_by_name_ar(GET_OBJ_AFFECT(o), NUM_AFF_FLAGS, subfield, affected_bits) == TRUE) if (check_flags_by_name_ar(GET_OBJ_AFFECT(o), NUM_AFF_FLAGS, subfield, affected_bits) == TRUE)
snprintf(str, slen, "1"); snprintf(str, slen, "1");
else else
snprintf(str, slen, "0"); snprintf(str, slen, "0");
} else } else
snprintf(str, slen, "0"); snprintf(str, slen, "0");
} }
case 'c': case 'c':
if (!str_cmp(field, "cost")) { if (!str_cmp(field, "cost")) {
if (subfield && *subfield) { if (subfield && *subfield) {
@@ -1127,13 +1142,13 @@ o->contains) ? "1" : "0"));
else else
strcpy(str, "0"); strcpy(str, "0");
} }
else if (!str_cmp(field, "hasattached")) { else if (!str_cmp(field, "hasattached")) {
if (!(subfield && *subfield)) if (!(subfield && *subfield))
*str = '\0'; *str = '\0';
else { else {
i = atoi(subfield); i = atoi(subfield);
snprintf(str, slen, "%d", trig_is_attached(SCRIPT(o), i)); snprintf(str, slen, "%d", trig_is_attached(SCRIPT(o), i));
} }
} }
break; break;
case 'i': case 'i':
@@ -1146,9 +1161,9 @@ o->contains) ? "1" : "0"));
else else
*str = '\0'; *str = '\0';
} }
else if (!str_cmp(field, "is_pc")) { else if (!str_cmp(field, "is_pc")) {
strcpy(str, "-1"); strcpy(str, "-1");
} }
break; break;
case 'n': case 'n':
if (!str_cmp(field, "name")) if (!str_cmp(field, "name"))
@@ -1200,12 +1215,12 @@ o->contains) ? "1" : "0"));
snprintf(str, slen, "%d", GET_OBJ_VAL(o, 3)); snprintf(str, slen, "%d", GET_OBJ_VAL(o, 3));
break; break;
case 'w': case 'w':
if (!str_cmp(field, "wearflag")) { if (!str_cmp(field, "wearflag")) {
if (subfield && *subfield) { if (subfield && *subfield) {
if (can_wear_on_pos(o, find_eq_pos_script(subfield))) if (can_wear_on_pos(o, find_eq_pos_script(subfield)))
snprintf(str, slen, "1"); snprintf(str, slen, "1");
else else
snprintf(str, slen, "0"); snprintf(str, slen, "0");
} else } else
snprintf(str, slen, "0"); snprintf(str, slen, "0");
} }
@@ -1325,27 +1340,27 @@ o->contains) ? "1" : "0"));
else else
*str = '\0'; *str = '\0';
} }
else if (!str_cmp(field, "hasattached")) { else if (!str_cmp(field, "hasattached")) {
if (!(subfield && *subfield)) if (!(subfield && *subfield))
*str = '\0'; *str = '\0';
else { else {
i = atoi(subfield); i = atoi(subfield);
snprintf(str, slen, "%d", trig_is_attached(SCRIPT(r), i)); snprintf(str, slen, "%d", trig_is_attached(SCRIPT(r), i));
} }
} }
else if (!str_cmp(field, "zonenumber")) else if (!str_cmp(field, "zonenumber"))
snprintf(str, slen, "%d", zone_table[r->zone].number); snprintf(str, slen, "%d", zone_table[r->zone].number);
else if (!str_cmp(field, "zonename")) else if (!str_cmp(field, "zonename"))
snprintf(str, slen, "%s", zone_table[r->zone].name); snprintf(str, slen, "%s", zone_table[r->zone].name);
else if (!str_cmp(field, "roomflag")) { else if (!str_cmp(field, "roomflag")) {
if (subfield && *subfield) { if (subfield && *subfield) {
room_rnum thisroom = real_room(r->number); room_rnum thisroom = real_room(r->number);
if (check_flags_by_name_ar(ROOM_FLAGS(thisroom), NUM_ROOM_FLAGS, subfield, room_bits) == TRUE) if (check_flags_by_name_ar(ROOM_FLAGS(thisroom), NUM_ROOM_FLAGS, subfield, room_bits) == TRUE)
snprintf(str, slen, "1"); snprintf(str, slen, "1");
else else
snprintf(str, slen, "0"); snprintf(str, slen, "0");
} else } else
snprintf(str, slen, "0"); snprintf(str, slen, "0");
} }
else if (!str_cmp(field, "north")) { else if (!str_cmp(field, "north")) {
if (R_EXIT(r, NORTH)) { if (R_EXIT(r, NORTH)) {
@@ -1489,10 +1504,10 @@ o->contains) ? "1" : "0"));
} }
} }
/* Now automatically checks if the variable has more then one field in it. And /* Now automatically checks if the variable has more then one field in it. And
* if the field returns a name or a script UID or the like it can recurse. If * if the field returns a name or a script UID or the like it can recurse. If
* you supply a value like, %actor.int.str% it wont blow up on you either. Now * you supply a value like, %actor.int.str% it wont blow up on you either. Now
* also lets subfields have variables parsed inside of them so that: %echo% * also lets subfields have variables parsed inside of them so that: %echo%
* %actor.gold(%actor.gold%)% will double the actors gold every time its called. * %actor.gold(%actor.gold%)% will double the actors gold every time its called.
* - Jamie Nelson */ * - Jamie Nelson */

View File

@@ -413,6 +413,13 @@ void mag_affects(int level, struct char_data *ch, struct char_data *victim,
to_vict = "Your eyes tingle."; to_vict = "Your eyes tingle.";
break; break;
case SPELL_FLY:
af[0].duration = 24;
SET_BIT_AR(af[0].bitvector, AFF_FLYING);
accum_duration = TRUE;
to_vict = "You float above the ground.";
break;
case SPELL_INFRAVISION: case SPELL_INFRAVISION:
af[0].duration = 12 + level; af[0].duration = 12 + level;
SET_BIT_AR(af[0].bitvector, AFF_INFRAVISION); SET_BIT_AR(af[0].bitvector, AFF_INFRAVISION);

View File

@@ -34,6 +34,8 @@ static void medit_save_to_disk(zone_vnum zone_num);
static void medit_disp_positions(struct descriptor_data *d); static void medit_disp_positions(struct descriptor_data *d);
static void medit_disp_sex(struct descriptor_data *d); static void medit_disp_sex(struct descriptor_data *d);
static void medit_disp_attack_types(struct descriptor_data *d); static void medit_disp_attack_types(struct descriptor_data *d);
static bool medit_illegal_mob_flag(int fl);
static int medit_get_mob_flag_by_number(int num);
static void medit_disp_mob_flags(struct descriptor_data *d); static void medit_disp_mob_flags(struct descriptor_data *d);
static void medit_disp_aff_flags(struct descriptor_data *d); static void medit_disp_aff_flags(struct descriptor_data *d);
static void medit_disp_menu(struct descriptor_data *d); static void medit_disp_menu(struct descriptor_data *d);
@@ -328,14 +330,57 @@ static void medit_disp_attack_types(struct descriptor_data *d)
write_to_output(d, "Enter attack type : "); write_to_output(d, "Enter attack type : ");
} }
/* Find mob flags that shouldn't be set by builders */
static bool medit_illegal_mob_flag(int fl)
{
int i;
/* add any other flags you dont want them setting */
const int illegal_flags[] = {
MOB_ISNPC,
MOB_NOTDEADYET,
};
const int num_illegal_flags = sizeof(illegal_flags)/sizeof(int);
for (i=0; i < num_illegal_flags;i++)
if (fl == illegal_flags[i])
return (TRUE);
return (FALSE);
}
/* Due to illegal mob flags not showing in the mob flags list,
we need this to convert the list number back to flag value */
static int medit_get_mob_flag_by_number(int num)
{
int i, count = 0;
for (i = 0; i < NUM_MOB_FLAGS; i++) {
if (medit_illegal_mob_flag(i)) continue;
if ((++count) == num) return i;
}
/* Return 'illegal flag' value */
return -1;
}
/* Display mob-flags menu. */ /* Display mob-flags menu. */
static void medit_disp_mob_flags(struct descriptor_data *d) static void medit_disp_mob_flags(struct descriptor_data *d)
{ {
int i, count = 0, columns = 0;
char flags[MAX_STRING_LENGTH]; char flags[MAX_STRING_LENGTH];
get_char_colors(d->character); get_char_colors(d->character);
clear_screen(d); clear_screen(d);
column_list(d->character, 0, action_bits, NUM_MOB_FLAGS, TRUE);
/* Mob flags has special handling to remove illegal flags from the list */
for (i = 0; i < NUM_MOB_FLAGS; i++) {
if (medit_illegal_mob_flag(i)) continue;
write_to_output(d, "%s%2d%s) %-20.20s %s", grn, ++count, nrm, action_bits[i],
!(++columns % 2) ? "\r\n" : "");
}
sprintbitarray(MOB_FLAGS(OLC_MOB(d)), action_bits, AF_ARRAY_MAX, flags); sprintbitarray(MOB_FLAGS(OLC_MOB(d)), action_bits, AF_ARRAY_MAX, flags);
write_to_output(d, "\r\nCurrent flags : %s%s%s\r\nEnter mob flags (0 to quit) : ", cyn, flags, nrm); write_to_output(d, "\r\nCurrent flags : %s%s%s\r\nEnter mob flags (0 to quit) : ", cyn, flags, nrm);
} }
@@ -478,7 +523,7 @@ static void medit_disp_stats_menu(struct descriptor_data *d)
void medit_parse(struct descriptor_data *d, char *arg) void medit_parse(struct descriptor_data *d, char *arg)
{ {
int i = -1; int i = -1, j;
char *oldtext = NULL; char *oldtext = NULL;
if (OLC_MODE(d) > MEDIT_NUMERICAL_RESPONSE) { if (OLC_MODE(d) > MEDIT_NUMERICAL_RESPONSE) {
@@ -837,8 +882,13 @@ void medit_parse(struct descriptor_data *d, char *arg)
case MEDIT_NPC_FLAGS: case MEDIT_NPC_FLAGS:
if ((i = atoi(arg)) <= 0) if ((i = atoi(arg)) <= 0)
break; break;
else if (i <= NUM_MOB_FLAGS) else if ( (j = medit_get_mob_flag_by_number(i)) == -1) {
write_to_output(d, "Invalid choice!\r\n");
write_to_output(d, "Enter mob flags (0 to quit) :");
return;
} else if (j <= NUM_MOB_FLAGS) {
TOGGLE_BIT_AR(MOB_FLAGS(OLC_MOB(d)), (i - 1)); TOGGLE_BIT_AR(MOB_FLAGS(OLC_MOB(d)), (i - 1));
}
medit_disp_mob_flags(d); medit_disp_mob_flags(d);
return; return;
@@ -1008,7 +1058,7 @@ void medit_parse(struct descriptor_data *d, char *arg)
case MEDIT_ALIGNMENT: case MEDIT_ALIGNMENT:
GET_ALIGNMENT(OLC_MOB(d)) = LIMIT(i, -1000, 1000); GET_ALIGNMENT(OLC_MOB(d)) = LIMIT(i, -1000, 1000);
medit_disp_stats_menu(d); medit_disp_stats_menu(d);
return; return;
case MEDIT_COPY: case MEDIT_COPY:

View File

@@ -21,6 +21,7 @@
#include "boards.h" #include "boards.h"
#include "improved-edit.h" #include "improved-edit.h"
#include "oasis.h" #include "oasis.h"
#include "class.h"
#include "dg_scripts.h" /* for trigedit_string_cleanup */ #include "dg_scripts.h" /* for trigedit_string_cleanup */
#include "modify.h" #include "modify.h"
#include "quest.h" #include "quest.h"
@@ -278,7 +279,7 @@ ACMD(do_skillset)
struct char_data *vict; struct char_data *vict;
char name[MAX_INPUT_LENGTH]; char name[MAX_INPUT_LENGTH];
char buf[MAX_INPUT_LENGTH], helpbuf[MAX_STRING_LENGTH]; char buf[MAX_INPUT_LENGTH], helpbuf[MAX_STRING_LENGTH];
int skill, value, i, qend; int skill, value, i, qend, pc, pl;
argument = one_argument(argument, name); argument = one_argument(argument, name);
@@ -302,6 +303,8 @@ ACMD(do_skillset)
return; return;
} }
skip_spaces(&argument); skip_spaces(&argument);
pc = GET_CLASS(vict);
pl = GET_LEVEL(vict);
/* If there is no chars in argument */ /* If there is no chars in argument */
if (!*argument) { if (!*argument) {
@@ -347,6 +350,13 @@ ACMD(do_skillset)
send_to_char(ch, "You can't set NPC skills.\r\n"); send_to_char(ch, "You can't set NPC skills.\r\n");
return; return;
} }
if ((spell_info[skill].min_level[(pc)] >= LVL_IMMORT) && (pl < LVL_IMMORT)) {
send_to_char(ch, "%s cannot be learned by mortals.\r\n", spell_info[skill].name);
return;
} else if (spell_info[skill].min_level[(pc)] > pl) {
send_to_char(ch, "%s is a level %d %s.\r\n", GET_NAME(vict), pl, pc_class_types[pc]);
send_to_char(ch, "The minimum level for %s is %d for %ss.\r\n", spell_info[skill].name, spell_info[skill].min_level[(pc)], pc_class_types[pc]);
}
/* find_skill_num() guarantees a valid spell_info[] index, or -1, and we /* find_skill_num() guarantees a valid spell_info[] index, or -1, and we
* checked for the -1 above so we are safe here. */ * checked for the -1 above so we are safe here. */

View File

@@ -183,7 +183,7 @@ int find_skill_num(char *name)
/* This function is the very heart of the entire magic system. All invocations /* This function is the very heart of the entire magic system. All invocations
* of all types of magic -- objects, spoken and unspoken PC and NPC spells, the * of all types of magic -- objects, spoken and unspoken PC and NPC spells, the
* works -- all come through this function eventually. This is also the entry * works -- all come through this function eventually. This is also the entry
* point for non-spoken or unrestricted spells. Spellnum 0 is legal but silently * point for non-spoken or unrestricted spells. Spellnum 0 is legal but silently
* ignored here, to make callers simpler. */ * ignored here, to make callers simpler. */
int call_magic(struct char_data *caster, struct char_data *cvict, int call_magic(struct char_data *caster, struct char_data *cvict,
@@ -429,8 +429,8 @@ void mag_objectmagic(struct char_data *ch, struct obj_data *obj,
} }
/* cast_spell is used generically to cast any spoken spell, assuming we already /* cast_spell is used generically to cast any spoken spell, assuming we already
* have the target char/obj and spell number. It checks all restrictions, * have the target char/obj and spell number. It checks all restrictions,
* prints the words, etc. Entry point for NPC casts. Recommended entry point * prints the words, etc. Entry point for NPC casts. Recommended entry point
* for spells cast by NPCs via specprocs. */ * for spells cast by NPCs via specprocs. */
int cast_spell(struct char_data *ch, struct char_data *tch, int cast_spell(struct char_data *ch, struct char_data *tch,
struct obj_data *tobj, int spellnum) struct obj_data *tobj, int spellnum)
@@ -512,12 +512,12 @@ ACMD(do_cast)
} }
t = strtok(NULL, "\0"); t = strtok(NULL, "\0");
skip_spaces(&s); skip_spaces(&s);
/* spellnum = search_block(s, spells, 0); */ /* spellnum = search_block(s, spells, 0); */
spellnum = find_skill_num(s); spellnum = find_skill_num(s);
if ((spellnum < 1) || (spellnum > MAX_SPELLS) || !*s) { if ((spellnum < 1) || (spellnum > MAX_SPELLS) || !*s) {
send_to_char(ch, "Cast what?!?\r\n"); send_to_char(ch, "Cast what?!?\r\n");
return; return;
} }
@@ -710,8 +710,8 @@ void unused_spell(int spl)
* charm, curse), or is otherwise nasty. * charm, curse), or is otherwise nasty.
* routines: A list of magic routines which are associated with this spell * routines: A list of magic routines which are associated with this spell
* if the spell uses spell templates. Also joined with bitwise OR ('|'). * if the spell uses spell templates. Also joined with bitwise OR ('|').
* See the documentation for a more detailed description of these fields. You * See the documentation for a more detailed description of these fields. You
* only need a spello() call to define a new spell; to decide who gets to use * only need a spello() call to define a new spell; to decide who gets to use
* a spell or skill, look in class.c. -JE */ * a spell or skill, look in class.c. -JE */
void mag_assign_spells(void) void mag_assign_spells(void)
{ {
@@ -834,6 +834,10 @@ void mag_assign_spells(void)
TAR_CHAR_ROOM | TAR_FIGHT_VICT, TRUE, MAG_DAMAGE, TAR_CHAR_ROOM | TAR_FIGHT_VICT, TRUE, MAG_DAMAGE,
NULL); NULL);
spello(SPELL_FLY, "fly", 40, 20, 2, POS_FIGHTING,
TAR_CHAR_ROOM, FALSE, MAG_AFFECTS,
"You drift slowly to the ground.");
spello(SPELL_GROUP_HEAL, "group heal", 80, 60, 5, POS_STANDING, spello(SPELL_GROUP_HEAL, "group heal", 80, 60, 5, POS_STANDING,
TAR_IGNORE, FALSE, MAG_GROUPS, TAR_IGNORE, FALSE, MAG_GROUPS,
NULL); NULL);
@@ -936,7 +940,7 @@ void mag_assign_spells(void)
NULL); NULL);
/* Declaration of skills - this actually doesn't do anything except set it up /* Declaration of skills - this actually doesn't do anything except set it up
* so that immortals can use these skills by default. The min level to use * so that immortals can use these skills by default. The min level to use
* the skill for other classes is set up in class.c. */ * the skill for other classes is set up in class.c. */
skillo(SKILL_BACKSTAB, "backstab"); skillo(SKILL_BACKSTAB, "backstab");
skillo(SKILL_BASH, "bash"); skillo(SKILL_BASH, "bash");

View File

@@ -1,13 +1,13 @@
/** /**
* @file spells.h * @file spells.h
* Constants and function prototypes for the spell system. * Constants and function prototypes for the spell system.
* *
* Part of the core tbaMUD source code distribution, which is a derivative * Part of the core tbaMUD source code distribution, which is a derivative
* of, and continuation of, CircleMUD. * of, and continuation of, CircleMUD.
* *
* All rights reserved. See license for complete information. * All rights reserved. See license for complete information.
* Copyright (C) 1993, 94 by the Trustees of the Johns Hopkins University * Copyright (C) 1993, 94 by the Trustees of the Johns Hopkins University
* CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991. * CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991.
*/ */
#ifndef _SPELLS_H_ #ifndef _SPELLS_H_
#define _SPELLS_H_ #define _SPELLS_H_
@@ -82,16 +82,17 @@
#define SPELL_WORD_OF_RECALL 42 /* Reserved Skill[] DO NOT CHANGE */ #define SPELL_WORD_OF_RECALL 42 /* Reserved Skill[] DO NOT CHANGE */
#define SPELL_REMOVE_POISON 43 /* Reserved Skill[] DO NOT CHANGE */ #define SPELL_REMOVE_POISON 43 /* Reserved Skill[] DO NOT CHANGE */
#define SPELL_SENSE_LIFE 44 /* Reserved Skill[] DO NOT CHANGE */ #define SPELL_SENSE_LIFE 44 /* Reserved Skill[] DO NOT CHANGE */
#define SPELL_ANIMATE_DEAD 45 /* Reserved Skill[] DO NOT CHANGE */ #define SPELL_ANIMATE_DEAD 45 /* Reserved Skill[] DO NOT CHANGE */
#define SPELL_DISPEL_GOOD 46 /* Reserved Skill[] DO NOT CHANGE */ #define SPELL_DISPEL_GOOD 46 /* Reserved Skill[] DO NOT CHANGE */
#define SPELL_GROUP_ARMOR 47 /* Reserved Skill[] DO NOT CHANGE */ #define SPELL_GROUP_ARMOR 47 /* Reserved Skill[] DO NOT CHANGE */
#define SPELL_GROUP_HEAL 48 /* Reserved Skill[] DO NOT CHANGE */ #define SPELL_GROUP_HEAL 48 /* Reserved Skill[] DO NOT CHANGE */
#define SPELL_GROUP_RECALL 49 /* Reserved Skill[] DO NOT CHANGE */ #define SPELL_GROUP_RECALL 49 /* Reserved Skill[] DO NOT CHANGE */
#define SPELL_INFRAVISION 50 /* Reserved Skill[] DO NOT CHANGE */ #define SPELL_INFRAVISION 50 /* Reserved Skill[] DO NOT CHANGE */
#define SPELL_WATERWALK 51 /* Reserved Skill[] DO NOT CHANGE */ #define SPELL_WATERWALK 51 /* Reserved Skill[] DO NOT CHANGE */
#define SPELL_IDENTIFY 52 /* Reserved Skill[] DO NOT CHANGE */ #define SPELL_IDENTIFY 52 /* Reserved Skill[] DO NOT CHANGE */
#define SPELL_FLY 53 /* Reserved Skill[] DO NOT CHANGE */
/** Total Number of defined spells */ /** Total Number of defined spells */
#define NUM_SPELLS 52 #define NUM_SPELLS 53
/* Insert new spells here, up to MAX_SPELLS */ /* Insert new spells here, up to MAX_SPELLS */
#define MAX_SPELLS 130 #define MAX_SPELLS 130
@@ -109,13 +110,13 @@
#define SKILL_TRACK 140 /* Reserved Skill[] DO NOT CHANGE */ #define SKILL_TRACK 140 /* Reserved Skill[] DO NOT CHANGE */
/* New skills may be added here up to MAX_SKILLS (200) */ /* New skills may be added here up to MAX_SKILLS (200) */
/* NON-PLAYER AND OBJECT SPELLS AND SKILLS: The practice levels for the spells /* NON-PLAYER AND OBJECT SPELLS AND SKILLS: The practice levels for the spells
* and skills below are _not_ recorded in the players file; therefore, the * and skills below are _not_ recorded in the players file; therefore, the
* intended use is for spells and skills associated with objects (such as * intended use is for spells and skills associated with objects (such as
* SPELL_IDENTIFY used with scrolls of identify) or non-players (such as NPC * SPELL_IDENTIFY used with scrolls of identify) or non-players (such as NPC
* only spells). */ * only spells). */
/* To make an affect induced by dg_affect look correct on 'stat' we need to /* To make an affect induced by dg_affect look correct on 'stat' we need to
* define it with a 'spellname'. */ * define it with a 'spellname'. */
#define SPELL_DG_AFFECT 298 #define SPELL_DG_AFFECT 298

View File

@@ -21,6 +21,7 @@
#include "spells.h" #include "spells.h"
#include "handler.h" #include "handler.h"
#include "interpreter.h" #include "interpreter.h"
#include "class.h"
/** Aportable random number function. /** Aportable random number function.
@@ -1471,3 +1472,12 @@ void new_affect(struct affected_type *af)
for (i=0; i<AF_ARRAY_MAX; i++) af->bitvector[i]=0; for (i=0; i<AF_ARRAY_MAX; i++) af->bitvector[i]=0;
} }
/* Handy function to get class ID number by name (abbreviations allowed) */
int get_class_by_name(char *classname)
{
int i;
for (i=0; i<NUM_CLASSES; i++)
if (is_abbrev(classname, pc_class_types[i])) return(i);
return (-1);
}

View File

@@ -67,6 +67,7 @@ IDXTYPE atoidx( const char *str_to_conv );
char *strfrmt(char *str, int w, int h, int justify, int hpad, int vpad); char *strfrmt(char *str, int w, int h, int justify, int hpad, int vpad);
char *strpaste(char *str1, char *str2, char *joiner); char *strpaste(char *str1, char *str2, char *joiner);
void new_affect(struct affected_type *af); void new_affect(struct affected_type *af);
int get_class_by_name(char *classname);
/* Public functions made available form weather.c */ /* Public functions made available form weather.c */
void weather_and_time(int mode); void weather_and_time(int mode);