From 7c9e1ea2fd4fb746d8054d35c44c4462efd7eb76 Mon Sep 17 00:00:00 2001 From: kinther Date: Fri, 3 Oct 2025 19:38:42 -0700 Subject: [PATCH] Migrate to 5e saving throws --- src/act.wizard.c | 25 +- src/class.c | 557 ++------------------------------------------- src/class.h | 1 - src/constants.c | 11 +- src/db.c | 26 ++- src/dg_variables.c | 42 ++-- src/genmob.c | 25 +- src/handler.c | 94 ++------ src/magic.c | 47 ++-- src/medit.c | 183 ++++++++------- src/oasis.h | 11 +- src/spell_parser.c | 6 +- src/spells.c | 4 +- src/spells.h | 14 +- src/structs.h | 27 ++- src/utils.h | 12 +- 16 files changed, 297 insertions(+), 788 deletions(-) diff --git a/src/act.wizard.c b/src/act.wizard.c index b631ffc..ebee5af 100644 --- a/src/act.wizard.c +++ b/src/act.wizard.c @@ -1238,9 +1238,17 @@ static void do_stat_character(struct char_data *ch, struct char_data *k) CCCYN(ch, C_NRM), CCYEL(ch, C_NRM), GET_SCREEN_WIDTH(k), CCNRM(ch, C_NRM), CCYEL(ch, C_NRM), GET_PAGE_LENGTH(k), CCCYN(ch, C_NRM), CCNRM(ch, C_NRM)); - send_to_char(ch, "AC: [%d%+d/10], Saving throws: [%d/%d/%d/%d/%d]\r\n", - GET_AC(k), GET_ABILITY_MOD(GET_DEX(k)), GET_SAVE(k, 0), GET_SAVE(k, 1), GET_SAVE(k, 2), - GET_SAVE(k, 3), GET_SAVE(k, 4)); + send_to_char(ch, + "AC: [%d%+d/10], \r\n" + "Saving throws: STR[%d] DEX[%d] CON[%d] INT[%d] WIS[%d] CHA[%d]\r\n", + GET_AC(k), + GET_ABILITY_MOD(GET_DEX(k)), + GET_SAVE(k, ABIL_STR), + GET_SAVE(k, ABIL_DEX), + GET_SAVE(k, ABIL_CON), + GET_SAVE(k, ABIL_INT), + GET_SAVE(k, ABIL_WIS), + GET_SAVE(k, ABIL_CHA)); sprinttype(GET_POS(k), position_types, buf, sizeof(buf)); send_to_char(ch, "Pos: %s, Fighting: %s", buf, FIGHTING(k) ? GET_NAME(FIGHTING(k)) : "Nobody"); @@ -4018,11 +4026,12 @@ static struct zcheck_affs { {APPLY_GOLD, 0, 0, "gold"}, {APPLY_EXP, 0, 0, "experience"}, {APPLY_AC, -10, 10, "magical AC"}, - {APPLY_SAVING_PARA, -2, 2, "saving throw (paralysis)"}, - {APPLY_SAVING_ROD, -2, 2, "saving throw (rod)"}, - {APPLY_SAVING_PETRI,-2, 2, "saving throw (death)"}, - {APPLY_SAVING_BREATH,-2, 2, "saving throw (breath)"}, - {APPLY_SAVING_SPELL,-2, 2, "saving throw (spell)"} + {APPLY_SAVE_STR, -2, 2, "saving throw (Strength)"}, + {APPLY_SAVE_DEX, -2, 2, "saving throw (Dexterity)"}, + {APPLY_SAVE_CON, -2, 2, "saving throw (Constitution)"}, + {APPLY_SAVE_INT, -2, 2, "saving throw (Intelligence)"}, + {APPLY_SAVE_WIS, -2, 2, "saving throw (Wisdom)"}, + {APPLY_SAVE_CHA, -2, 2, "saving throw (Charisma)"} }; /*room limits*/ diff --git a/src/class.c b/src/class.c index 1f83ab4..1b47826 100644 --- a/src/class.c +++ b/src/class.c @@ -141,14 +141,14 @@ int prac_params[4][NUM_CLASSES] = { struct guild_info_type guild_info[] = { /* Midgaard */ - { CLASS_SORCEROR, 3017, SOUTH }, + { CLASS_SORCEROR, 3017, SOUTH }, { CLASS_CLERIC, 3004, NORTH }, { CLASS_THIEF, 3027, EAST }, { CLASS_FIGHTER, 3021, EAST }, { CLASS_BARBARIAN, 3021, EAST }, { CLASS_RANGER, 3021, EAST }, { CLASS_BARD, 3021, EAST }, - { CLASS_DRUID, 3021, EAST }, + { CLASS_DRUID, 3021, EAST }, /* Brass Dragon */ { -999 /* all */ , 5065, WEST }, @@ -157,550 +157,19 @@ struct guild_info_type guild_info[] = { { -1, NOWHERE, -1} }; -/* 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. */ -byte saving_throws(int class_num, int type, int level) -{ +/* 5e system saving throws per class*/ +bool has_save_proficiency(int class_num, int ability) { switch (class_num) { - case CLASS_SORCEROR: - switch (type) { - case SAVING_PARA: /* Paralyzation */ - switch (level) { - case 0: return 90; - case 1: return 70; - case 2: return 0; - case 3: return 0; - case 4: return 0; - case 5: return 0; - default: - log("SYSERR: Missing level for mage paralyzation saving throw."); - break; - } - case SAVING_ROD: /* Rods */ - switch (level) { - case 0: return 90; - case 1: return 55; - case 2: return 0; - case 3: return 0; - case 4: return 0; - case 5: return 0; - default: - log("SYSERR: Missing level for mage rod saving throw."); - break; - } - case SAVING_PETRI: /* Petrification */ - switch (level) { - case 0: return 90; - case 1: return 65; - case 2: return 0; - case 3: return 0; - case 4: return 0; - case 5: return 0; - default: - log("SYSERR: Missing level for mage petrification saving throw."); - break; - } - case SAVING_BREATH: /* Breath weapons */ - switch (level) { - case 0: return 90; - case 1: return 75; - case 2: return 0; - case 3: return 0; - case 4: return 0; - case 5: return 0; - default: - log("SYSERR: Missing level for mage breath saving throw."); - break; - } - case SAVING_SPELL: /* Generic spells */ - switch (level) { - case 0: return 90; - case 1: return 60; - case 2: return 0; - case 3: return 0; - case 4: return 0; - case 5: return 0; - default: - log("SYSERR: Missing level for mage spell saving throw."); - break; - } - default: - log("SYSERR: Invalid saving throw type."); - break; - } - break; - case CLASS_CLERIC: - switch (type) { - case SAVING_PARA: /* Paralyzation */ - switch (level) { - case 0: return 90; - case 1: return 60; - case 2: return 0; - case 3: return 0; - case 4: return 0; - case 5: return 0; - default: - log("SYSERR: Missing level for cleric paralyzation saving throw."); - break; - } - case SAVING_ROD: /* Rods */ - switch (level) { - case 0: return 90; - case 1: return 70; - case 2: return 0; - case 3: return 0; - case 4: return 0; - case 5: return 0; - default: - log("SYSERR: Missing level for cleric rod saving throw."); - break; - } - case SAVING_PETRI: /* Petrification */ - switch (level) { - case 0: return 90; - case 1: return 65; - case 2: return 0; - case 3: return 0; - case 4: return 0; - case 5: return 0; - default: - log("SYSERR: Missing level for cleric petrification saving throw."); - break; - } - case SAVING_BREATH: /* Breath weapons */ - switch (level) { - case 0: return 90; - case 1: return 80; - case 2: return 0; - case 3: return 0; - case 4: return 0; - case 5: return 0; - default: - log("SYSERR: Missing level for cleric breath saving throw."); - break; - } - case SAVING_SPELL: /* Generic spells */ - switch (level) { - case 0: return 90; - case 1: return 75; - case 2: return 0; - case 3: return 0; - case 4: return 0; - case 5: return 0; - default: - log("SYSERR: Missing level for cleric spell saving throw."); - break; - } - default: - log("SYSERR: Invalid saving throw type."); - break; - } - break; - case CLASS_THIEF: - switch (type) { - case SAVING_PARA: /* Paralyzation */ - switch (level) { - case 0: return 90; - case 1: return 65; - case 2: return 0; - case 3: return 0; - case 4: return 0; - case 5: return 0; - default: - log("SYSERR: Missing level for thief paralyzation saving throw."); - break; - } - case SAVING_ROD: /* Rods */ - switch (level) { - case 0: return 90; - case 1: return 70; - case 2: return 0; - case 3: return 0; - case 4: return 0; - case 5: return 0; - default: - log("SYSERR: Missing level for thief rod saving throw."); - break; - } - case SAVING_PETRI: /* Petrification */ - switch (level) { - case 0: return 90; - case 1: return 60; - case 2: return 0; - case 3: return 0; - case 4: return 0; - case 5: return 0; - default: - log("SYSERR: Missing level for thief petrification saving throw."); - break; - } - case SAVING_BREATH: /* Breath weapons */ - switch (level) { - case 0: return 90; - case 1: return 80; - case 2: return 0; - case 3: return 0; - case 4: return 0; - case 5: return 0; - default: - log("SYSERR: Missing level for thief breath saving throw."); - break; - } - case SAVING_SPELL: /* Generic spells */ - switch (level) { - case 0: return 90; - case 1: return 75; - case 2: return 0; - case 3: return 0; - case 4: return 0; - case 5: return 0; - default: - log("SYSERR: Missing level for thief spell saving throw."); - break; - } - default: - log("SYSERR: Invalid saving throw type."); - break; - } - break; - case CLASS_FIGHTER: - switch (type) { - case SAVING_PARA: /* Paralyzation */ - switch (level) { - case 0: return 90; - case 1: return 70; - case 2: return 0; - case 3: return 0; - case 4: return 0; - case 5: return 0; - default: - log("SYSERR: Missing level for fighter paralyzation saving throw."); - break; - } - case SAVING_ROD: /* Rods */ - switch (level) { - case 0: return 90; - case 1: return 80; - case 2: return 0; - case 3: return 0; - case 4: return 0; - case 5: return 0; - default: - log("SYSERR: Missing level for fighter rod saving throw."); - break; - } - case SAVING_PETRI: /* Petrification */ - switch (level) { - case 0: return 90; - case 1: return 75; - case 2: return 0; - case 3: return 0; - case 4: return 0; - case 5: return 0; - default: - log("SYSERR: Missing level for fighter petrification saving throw."); - break; - } - case SAVING_BREATH: /* Breath weapons */ - switch (level) { - case 0: return 90; - case 1: return 85; - case 2: return 0; - case 3: return 0; - case 4: return 0; - case 5: return 0; - default: - log("SYSERR: Missing level for fighter breath saving throw."); - break; - } - case SAVING_SPELL: /* Generic spells */ - switch (level) { - case 0: return 90; - case 1: return 85; - case 2: return 0; - case 3: return 0; - case 4: return 0; - case 5: return 0; - default: - log("SYSERR: Missing level for fighter spell saving throw."); - break; - } - default: - log("SYSERR: Invalid saving throw type."); - break; - } - case CLASS_BARBARIAN: - switch (type) { - case SAVING_PARA: /* Paralyzation */ - switch (level) { - case 0: return 80; - case 1: return 60; - case 2: return 0; - case 3: return 0; - case 4: return 0; - case 5: return 0; - default: - log("SYSERR: Missing level for barbarian paralyzation saving throw."); - break; - } - case SAVING_ROD: /* Rods */ - switch (level) { - case 0: return 90; - case 1: return 80; - case 2: return 0; - case 3: return 0; - case 4: return 0; - case 5: return 0; - default: - log("SYSERR: Missing level for barbarian rod saving throw."); - break; - } - case SAVING_PETRI: /* Petrification */ - switch (level) { - case 0: return 70; - case 1: return 65; - case 2: return 0; - case 3: return 0; - case 4: return 0; - case 5: return 0; - default: - log("SYSERR: Missing level for barbarian petrification saving throw."); - break; - } - case SAVING_BREATH: /* Breath weapons */ - switch (level) { - case 0: return 90; - case 1: return 85; - case 2: return 0; - case 3: return 0; - case 4: return 0; - case 5: return 0; - default: - log("SYSERR: Missing level for barbarian breath saving throw."); - break; - } - case SAVING_SPELL: /* Generic spells */ - switch (level) { - case 0: return 90; - case 1: return 85; - case 2: return 0; - case 3: return 0; - case 4: return 0; - case 5: return 0; - default: - log("SYSERR: Missing level for barbarian spell saving throw."); - break; - } - default: - log("SYSERR: Invalid saving throw type."); - break; - } - break; - case CLASS_RANGER: - switch (type) { - case SAVING_PARA: /* Paralyzation */ - switch (level) { - case 0: return 75; - case 1: return 70; - case 2: return 0; - case 3: return 0; - case 4: return 0; - case 5: return 0; - default: - log("SYSERR: Missing level for ranger paralyzation saving throw."); - break; - } - case SAVING_ROD: /* Rods */ - switch (level) { - case 0: return 85; - case 1: return 80; - case 2: return 0; - case 3: return 0; - case 4: return 0; - case 5: return 0; - default: - log("SYSERR: Missing level for ranger rod saving throw."); - break; - } - case SAVING_PETRI: /* Petrification */ - switch (level) { - case 0: return 80; - case 1: return 75; - case 2: return 0; - case 3: return 0; - case 4: return 0; - case 5: return 0; - default: - log("SYSERR: Missing level for ranger petrification saving throw."); - break; - } - case SAVING_BREATH: /* Breath weapons */ - switch (level) { - case 0: return 90; - case 1: return 85; - case 2: return 0; - case 3: return 0; - case 4: return 0; - case 5: return 0; - default: - log("SYSERR: Missing level for ranger breath saving throw."); - break; - } - case SAVING_SPELL: /* Generic spells */ - switch (level) { - case 0: return 90; - case 1: return 85; - case 2: return 0; - case 3: return 0; - case 4: return 0; - case 5: return 0; - default: - log("SYSERR: Missing level for ranger spell saving throw."); - break; - } - default: - log("SYSERR: Invalid saving throw type."); - break; - } - break; - case CLASS_BARD: - switch (type) { - case SAVING_PARA: /* Paralyzation */ - switch (level) { - case 0: return 90; - case 1: return 70; - case 2: return 0; - case 3: return 0; - case 4: return 0; - case 5: return 0; - default: - log("SYSERR: Missing level for bard paralyzation saving throw."); - break; - } - case SAVING_ROD: /* Rods */ - switch (level) { - case 0: return 85; - case 1: return 80; - case 2: return 0; - case 3: return 0; - case 4: return 0; - case 5: return 0; - default: - log("SYSERR: Missing level for bard rod saving throw."); - break; - } - case SAVING_PETRI: /* Petrification */ - switch (level) { - case 0: return 85; - case 1: return 75; - case 2: return 0; - case 3: return 0; - case 4: return 0; - case 5: return 0; - default: - log("SYSERR: Missing level for bard petrification saving throw."); - break; - } - case SAVING_BREATH: /* Breath weapons */ - switch (level) { - case 0: return 85; - case 1: return 85; - case 2: return 0; - case 3: return 0; - case 4: return 0; - case 5: return 0; - default: - log("SYSERR: Missing level for bard breath saving throw."); - break; - } - case SAVING_SPELL: /* Generic spells */ - switch (level) { - case 0: return 85; - case 1: return 80; - case 2: return 0; - case 3: return 0; - case 4: return 0; - case 5: return 0; - default: - log("SYSERR: Missing level for bard spell saving throw."); - break; - } - default: - log("SYSERR: Invalid saving throw type."); - break; - } - break; - case CLASS_DRUID: - switch (type) { - case SAVING_PARA: /* Paralyzation */ - switch (level) { - case 0: return 75; - case 1: return 70; - case 2: return 0; - case 3: return 0; - case 4: return 0; - case 5: return 0; - default: - log("SYSERR: Missing level for druid paralyzation saving throw."); - break; - } - case SAVING_ROD: /* Rods */ - switch (level) { - case 0: return 80; - case 1: return 80; - case 2: return 0; - case 3: return 0; - case 4: return 0; - case 5: return 0; - default: - log("SYSERR: Missing level for druid rod saving throw."); - break; - } - case SAVING_PETRI: /* Petrification */ - switch (level) { - case 0: return 90; - case 1: return 75; - case 2: return 0; - case 3: return 0; - case 4: return 0; - case 5: return 0; - default: - log("SYSERR: Missing level for druid petrification saving throw."); - break; - } - case SAVING_BREATH: /* Breath weapons */ - switch (level) { - case 0: return 90; - case 1: return 85; - case 2: return 0; - case 3: return 0; - case 4: return 0; - case 5: return 0; - default: - log("SYSERR: Missing level for druid breath saving throw."); - break; - } - case SAVING_SPELL: /* Generic spells */ - switch (level) { - case 0: return 85; - case 1: return 80; - case 2: return 0; - case 3: return 0; - case 4: return 0; - case 5: return 0; - default: - log("SYSERR: Missing level for druid spell saving throw."); - break; - } - default: - log("SYSERR: Invalid saving throw type."); - break; - } - break; + case CLASS_SORCEROR: return (ability == ABIL_CON || ability == ABIL_CHA); + case CLASS_CLERIC: return (ability == ABIL_WIS || ability == ABIL_CHA); + case CLASS_THIEF: return (ability == ABIL_DEX || ability == ABIL_INT); + case CLASS_FIGHTER: return (ability == ABIL_STR || ability == ABIL_CON); + case CLASS_BARBARIAN: return (ability == ABIL_STR || ability == ABIL_CON); + case CLASS_RANGER: return (ability == ABIL_STR || ability == ABIL_DEX); + case CLASS_BARD: return (ability == ABIL_DEX || ability == ABIL_CHA); + case CLASS_DRUID: return (ability == ABIL_INT || ability == ABIL_WIS); + default: return FALSE; } - - /* Should not get here unless something is wrong. */ - return 100; } /* Roll the 6 stats for a character... each stat is made of the sum of the best diff --git a/src/class.h b/src/class.h index 06266b6..ef12fd4 100644 --- a/src/class.h +++ b/src/class.h @@ -21,7 +21,6 @@ int invalid_class(struct char_data *ch, struct obj_data *obj); int level_exp(int chclass, int level); int parse_class(char arg); void roll_real_abils(struct char_data *ch); -byte saving_throws(int class_num, int type, int level); const char *title_female(int chclass, int level); const char *title_male(int chclass, int level); diff --git a/src/constants.c b/src/constants.c index 0c8e72e..4f4536e 100644 --- a/src/constants.c +++ b/src/constants.c @@ -513,11 +513,12 @@ const char *apply_types[] = { "GOLD", "EXP", "ARMOR", - "SAVING_PARA", - "SAVING_ROD", - "SAVING_PETRI", - "SAVING_BREATH", - "SAVING_SPELL", + "SAVE_STR", + "SAVE_DEX", + "SAVE_CON", + "SAVE_INT", + "SAVE_WIS", + "SAVE_CHA", "\n" }; diff --git a/src/db.c b/src/db.c index efa0c5c..e37c034 100644 --- a/src/db.c +++ b/src/db.c @@ -1658,29 +1658,35 @@ static void interpret_espec(const char *keyword, const char *value, int i, int n mob_proto[i].real_abils.cha = num_arg; } - CASE("SavingPara") { + /* --- New 5e-style saving throw keywords --- */ + CASE("SaveStr") { RANGE(0, 100); - mob_proto[i].char_specials.saved.apply_saving_throw[SAVING_PARA] = num_arg; + mob_proto[i].char_specials.saved.saving_throws[ABIL_STR] = num_arg; } - CASE("SavingRod") { + CASE("SaveDex") { RANGE(0, 100); - mob_proto[i].char_specials.saved.apply_saving_throw[SAVING_ROD] = num_arg; + mob_proto[i].char_specials.saved.saving_throws[ABIL_DEX] = num_arg; } - CASE("SavingPetri") { + CASE("SaveCon") { RANGE(0, 100); - mob_proto[i].char_specials.saved.apply_saving_throw[SAVING_PETRI] = num_arg; + mob_proto[i].char_specials.saved.saving_throws[ABIL_CON] = num_arg; } - CASE("SavingBreath") { + CASE("SaveInt") { RANGE(0, 100); - mob_proto[i].char_specials.saved.apply_saving_throw[SAVING_BREATH] = num_arg; + mob_proto[i].char_specials.saved.saving_throws[ABIL_INT] = num_arg; } - CASE("SavingSpell") { + CASE("SaveWis") { RANGE(0, 100); - mob_proto[i].char_specials.saved.apply_saving_throw[SAVING_SPELL] = num_arg; + mob_proto[i].char_specials.saved.saving_throws[ABIL_WIS] = num_arg; + } + + CASE("SaveCha") { + RANGE(0, 100); + mob_proto[i].char_specials.saved.saving_throws[ABIL_CHA] = num_arg; } if (!matched) { diff --git a/src/dg_variables.c b/src/dg_variables.c index 3aa1abd..01e861b 100644 --- a/src/dg_variables.c +++ b/src/dg_variables.c @@ -970,40 +970,52 @@ void find_replacement(void *go, struct script_data *sc, trig_data *trig, } break; case 's': - if (!str_cmp(field, "saving_breath")) { + if (!str_cmp(field, "save_str")) { if (subfield && *subfield) { int addition = atoi(subfield); - GET_SAVE(c, SAVING_BREATH) += addition; + GET_SAVE(c, ABIL_STR) += addition; } - snprintf(str, slen, "%d", GET_SAVE(c, SAVING_BREATH)); + snprintf(str, slen, "%d", GET_SAVE(c, ABIL_STR)); } - else if (!str_cmp(field, "saving_para")) { + + else if (!str_cmp(field, "save_dex")) { if (subfield && *subfield) { int addition = atoi(subfield); - GET_SAVE(c, SAVING_PARA) += addition; + GET_SAVE(c, ABIL_DEX) += addition; } - snprintf(str, slen, "%d", GET_SAVE(c, SAVING_PARA)); + snprintf(str, slen, "%d", GET_SAVE(c, ABIL_DEX)); } - else if (!str_cmp(field, "saving_petri")) { + + else if (!str_cmp(field, "save_con")) { if (subfield && *subfield) { int addition = atoi(subfield); - GET_SAVE(c, SAVING_PETRI) += addition; + GET_SAVE(c, ABIL_CON) += addition; } - snprintf(str, slen, "%d", GET_SAVE(c, SAVING_PETRI)); + snprintf(str, slen, "%d", GET_SAVE(c, ABIL_CON)); } - else if (!str_cmp(field, "saving_rod")) { + + else if (!str_cmp(field, "save_int")) { if (subfield && *subfield) { int addition = atoi(subfield); - GET_SAVE(c, SAVING_ROD) += addition; + GET_SAVE(c, ABIL_INT) += addition; } - snprintf(str, slen, "%d", GET_SAVE(c, SAVING_ROD)); + snprintf(str, slen, "%d", GET_SAVE(c, ABIL_INT)); } - else if (!str_cmp(field, "saving_spell")) { + + else if (!str_cmp(field, "save_wis")) { if (subfield && *subfield) { int addition = atoi(subfield); - GET_SAVE(c, SAVING_SPELL) += addition; + GET_SAVE(c, ABIL_WIS) += addition; } - snprintf(str, slen, "%d", GET_SAVE(c, SAVING_SPELL)); + snprintf(str, slen, "%d", GET_SAVE(c, ABIL_WIS)); + } + + else if (!str_cmp(field, "save_cha")) { + if (subfield && *subfield) { + int addition = atoi(subfield); + GET_SAVE(c, ABIL_CHA) += addition; + } + snprintf(str, slen, "%d", GET_SAVE(c, ABIL_CHA)); } else if (!str_cmp(field, "sex")) snprintf(str, slen, "%s", genders[(int)GET_SEX(c)]); diff --git a/src/genmob.c b/src/genmob.c index 1b39132..b605971 100644 --- a/src/genmob.c +++ b/src/genmob.c @@ -343,16 +343,21 @@ int write_mobile_espec(mob_vnum mvnum, struct char_data *mob, FILE *fd) fprintf(fd, "Con: %d\n", GET_CON(mob)); if (GET_CHA(mob) != 11) fprintf(fd, "Cha: %d\n", GET_CHA(mob)); - if (GET_SAVE(mob, SAVING_PARA) != 0) - fprintf(fd, "SavingPara: %d\n", GET_SAVE(mob, SAVING_PARA)); - if (GET_SAVE(mob, SAVING_ROD) != 0) - fprintf(fd, "SavingRod: %d\n", GET_SAVE(mob, SAVING_ROD)); - if (GET_SAVE(mob, SAVING_PETRI) != 0) - fprintf(fd, "SavingPetri: %d\n", GET_SAVE(mob, SAVING_PETRI)); - if (GET_SAVE(mob, SAVING_BREATH) != 0) - fprintf(fd, "SavingBreath: %d\n", GET_SAVE(mob, SAVING_BREATH)); - if (GET_SAVE(mob, SAVING_SPELL) != 0) - fprintf(fd, "SavingSpell: %d\n", GET_SAVE(mob, SAVING_SPELL)); + + /* --- New ability-based saving throws --- */ + if (GET_SAVE(mob, ABIL_STR) != 0) + fprintf(fd, "SaveStr: %d\n", GET_SAVE(mob, ABIL_STR)); + if (GET_SAVE(mob, ABIL_DEX) != 0) + fprintf(fd, "SaveDex: %d\n", GET_SAVE(mob, ABIL_DEX)); + if (GET_SAVE(mob, ABIL_CON) != 0) + fprintf(fd, "SaveCon: %d\n", GET_SAVE(mob, ABIL_CON)); + if (GET_SAVE(mob, ABIL_INT) != 0) + fprintf(fd, "SaveInt: %d\n", GET_SAVE(mob, ABIL_INT)); + if (GET_SAVE(mob, ABIL_WIS) != 0) + fprintf(fd, "SaveWis: %d\n", GET_SAVE(mob, ABIL_WIS)); + if (GET_SAVE(mob, ABIL_CHA) != 0) + fprintf(fd, "SaveCha: %d\n", GET_SAVE(mob, ABIL_CHA)); + fputs("E\n", fd); return TRUE; } diff --git a/src/handler.c b/src/handler.c index f82d949..0e75d81 100644 --- a/src/handler.c +++ b/src/handler.c @@ -112,28 +112,16 @@ static void aff_apply_modify(struct char_data *ch, byte loc, sbyte mod, char *ms case APPLY_NONE: break; - case APPLY_STR: - GET_STR(ch) += mod; - break; - case APPLY_DEX: - GET_DEX(ch) += mod; - break; - case APPLY_INT: - GET_INT(ch) += mod; - break; - case APPLY_WIS: - GET_WIS(ch) += mod; - break; - case APPLY_CON: - GET_CON(ch) += mod; - break; - case APPLY_CHA: - GET_CHA(ch) += mod; - break; + /* --- ability scores --- */ + case APPLY_STR: GET_STR(ch) += mod; break; + case APPLY_DEX: GET_DEX(ch) += mod; break; + case APPLY_INT: GET_INT(ch) += mod; break; + case APPLY_WIS: GET_WIS(ch) += mod; break; + case APPLY_CON: GET_CON(ch) += mod; break; + case APPLY_CHA: GET_CHA(ch) += mod; break; /* Do Not Use. */ case APPLY_CLASS: - break; case APPLY_LEVEL: break; @@ -141,64 +129,28 @@ static void aff_apply_modify(struct char_data *ch, byte loc, sbyte mod, char *ms ch->player.time.birth -= (mod * SECS_PER_MUD_YEAR); break; - case APPLY_CHAR_WEIGHT: - GET_WEIGHT(ch) += mod; - break; + case APPLY_CHAR_WEIGHT: GET_WEIGHT(ch) += mod; break; + case APPLY_CHAR_HEIGHT: GET_HEIGHT(ch) += mod; break; + case APPLY_MANA: GET_MAX_MANA(ch) += mod; break; + case APPLY_HIT: GET_MAX_HIT(ch) += mod; break; + case APPLY_MOVE: GET_MAX_MOVE(ch) += mod; break; + case APPLY_GOLD: break; + case APPLY_EXP: break; - case APPLY_CHAR_HEIGHT: - GET_HEIGHT(ch) += mod; - break; + case APPLY_AC: GET_AC(ch) += mod; break; + case APPLY_PROFICIENCY: GET_PROF_MOD(ch) += mod; break; - case APPLY_MANA: - GET_MAX_MANA(ch) += mod; - break; - - case APPLY_HIT: - GET_MAX_HIT(ch) += mod; - break; - - case APPLY_MOVE: - GET_MAX_MOVE(ch) += mod; - break; - - case APPLY_GOLD: - break; - - case APPLY_EXP: - break; - - case APPLY_AC: - GET_AC(ch) += mod; - break; - - case APPLY_PROFICIENCY: - GET_PROF_MOD(ch) += mod; - break; - - case APPLY_SAVING_PARA: - GET_SAVE(ch, SAVING_PARA) += mod; - break; - - case APPLY_SAVING_ROD: - GET_SAVE(ch, SAVING_ROD) += mod; - break; - - case APPLY_SAVING_PETRI: - GET_SAVE(ch, SAVING_PETRI) += mod; - break; - - case APPLY_SAVING_BREATH: - GET_SAVE(ch, SAVING_BREATH) += mod; - break; - - case APPLY_SAVING_SPELL: - GET_SAVE(ch, SAVING_SPELL) += mod; - break; + /* --- new 5e-style saving throws --- */ + case APPLY_SAVE_STR: SAVE_STR(ch) += mod; break; + case APPLY_SAVE_DEX: SAVE_DEX(ch) += mod; break; + case APPLY_SAVE_CON: SAVE_CON(ch) += mod; break; + case APPLY_SAVE_INT: SAVE_INT(ch) += mod; break; + case APPLY_SAVE_WIS: SAVE_WIS(ch) += mod; break; + case APPLY_SAVE_CHA: SAVE_CHA(ch) += mod; break; default: log("SYSERR: Unknown apply adjust %d attempt (%s, affect_modify).", loc, __FILE__); break; - } /* switch */ } diff --git a/src/magic.c b/src/magic.c index 86687fb..10913f4 100644 --- a/src/magic.c +++ b/src/magic.c @@ -42,7 +42,7 @@ int mag_savingthrow(struct char_data *ch, int type, int modifier) if (!IS_NPC(ch)) class_sav = GET_CLASS(ch); - save = saving_throws(class_sav, type, GET_LEVEL(ch)); + save = GET_SAVE(ch, type); save += GET_SAVE(ch, type); save += modifier; @@ -321,10 +321,10 @@ void mag_affects(int level, struct char_data *ch, struct char_data *victim, case SPELL_CHILL_TOUCH: af[0].location = APPLY_STR; - if (mag_savingthrow(victim, savetype, 0)) - af[0].duration = 1; + if (mag_savingthrow(victim, ABIL_CON, savetype)) + af[0].duration = 1; /* resisted: brief weakening */ else - af[0].duration = 4; + af[0].duration = 4; /* failed: longer effect */ af[0].modifier = -1; accum_duration = TRUE; to_vict = "You feel your strength wither!"; @@ -332,19 +332,20 @@ void mag_affects(int level, struct char_data *ch, struct char_data *victim, case SPELL_ARMOR: af[0].location = APPLY_AC; - af[0].modifier = -20; + af[0].modifier = +2; /* +2 AC in 5e terms */ af[0].duration = 24; accum_duration = TRUE; to_vict = "You feel someone protecting you."; break; case SPELL_BLESS: - af[0].location = GET_SPELL_ABILITY_MOD(ch); - af[0].modifier = 2; + af[0].location = APPLY_SAVE_WIS; + af[0].modifier = +1; /* bonus to Wisdom saves */ af[0].duration = 6; - af[1].location = APPLY_SAVING_SPELL; - af[1].modifier = -1; + /* Optional: extend to CHA saves if you want to emulate "morale" boost */ + af[1].location = APPLY_SAVE_CHA; + af[1].modifier = +1; af[1].duration = 6; accum_duration = TRUE; @@ -352,18 +353,19 @@ void mag_affects(int level, struct char_data *ch, struct char_data *victim, break; case SPELL_BLINDNESS: - if (MOB_FLAGGED(victim, MOB_NOBLIND) || GET_LEVEL(victim) >= LVL_IMMORT || mag_savingthrow(victim, savetype, 0)) { + if (MOB_FLAGGED(victim, MOB_NOBLIND) || GET_LEVEL(victim) >= LVL_IMMORT || + mag_savingthrow(victim, ABIL_CON, savetype)) { send_to_char(ch, "You fail.\r\n"); return; } - af[0].location = GET_SPELL_ABILITY_MOD(ch); - af[0].modifier = -4; + af[0].location = APPLY_SAVE_DEX; /* penalize Dex saves */ + af[0].modifier = -2; af[0].duration = 2; SET_BIT_AR(af[0].bitvector, AFF_BLIND); - af[1].location = APPLY_AC; - af[1].modifier = 40; + af[1].location = APPLY_AC; /* easier to hit */ + af[1].modifier = +40; af[1].duration = 2; SET_BIT_AR(af[1].bitvector, AFF_BLIND); @@ -372,17 +374,17 @@ void mag_affects(int level, struct char_data *ch, struct char_data *victim, break; case SPELL_CURSE: - if (mag_savingthrow(victim, savetype, 0)) { + if (mag_savingthrow(victim, ABIL_WIS, savetype)) { send_to_char(ch, "%s", CONFIG_NOEFFECT); return; } - af[0].location = GET_SPELL_ABILITY_MOD(ch); + af[0].location = APPLY_SAVE_WIS; /* harder to resist magic */ af[0].duration = 1 + (GET_LEVEL(ch) / 2); af[0].modifier = -1; SET_BIT_AR(af[0].bitvector, AFF_CURSE); - af[1].location = GET_SPELL_ABILITY_MOD(ch); + af[1].location = APPLY_SAVE_CHA; /* morale/charisma weakened */ af[1].duration = 1 + (GET_LEVEL(ch) / 2); af[1].modifier = -1; SET_BIT_AR(af[1].bitvector, AFF_CURSE); @@ -434,7 +436,7 @@ void mag_affects(int level, struct char_data *ch, struct char_data *victim, victim = ch; af[0].duration = 12 + (GET_LEVEL(ch) / 4); - af[0].modifier = -40; + af[0].modifier = +2; /* ascending AC: harder to hit */ af[0].location = APPLY_AC; SET_BIT_AR(af[0].bitvector, AFF_INVISIBLE); accum_duration = TRUE; @@ -443,7 +445,7 @@ void mag_affects(int level, struct char_data *ch, struct char_data *victim, break; case SPELL_POISON: - if (mag_savingthrow(victim, savetype, 0)) { + if (mag_savingthrow(victim, ABIL_CON, savetype)) { send_to_char(ch, "%s", CONFIG_NOEFFECT); return; } @@ -466,7 +468,6 @@ void mag_affects(int level, struct char_data *ch, struct char_data *victim, case SPELL_SANCTUARY: af[0].duration = 4; SET_BIT_AR(af[0].bitvector, AFF_SANCTUARY); - accum_duration = TRUE; to_vict = "A white aura momentarily surrounds you."; to_room = "$n is surrounded by a white aura."; @@ -477,7 +478,7 @@ void mag_affects(int level, struct char_data *ch, struct char_data *victim, return; if (MOB_FLAGGED(victim, MOB_NOSLEEP)) return; - if (mag_savingthrow(victim, savetype, 0)) + if (mag_savingthrow(victim, ABIL_WIS, savetype)) return; af[0].duration = 4 + (GET_LEVEL(ch) / 4); @@ -496,14 +497,14 @@ void mag_affects(int level, struct char_data *ch, struct char_data *victim, af[0].location = APPLY_STR; af[0].duration = (GET_LEVEL(ch) / 2) + 4; - af[0].modifier = 1 + (level > 18); + af[0].modifier = 2; /* +2 bonus static */ accum_duration = TRUE; accum_affect = TRUE; to_vict = "You feel stronger!"; break; case SPELL_SENSE_LIFE: - to_vict = "Your feel your awareness improve."; + to_vict = "You feel your awareness improve."; af[0].duration = GET_LEVEL(ch); SET_BIT_AR(af[0].bitvector, AFF_SENSE_LIFE); accum_duration = TRUE; diff --git a/src/medit.c b/src/medit.c index dd54567..88e020a 100644 --- a/src/medit.c +++ b/src/medit.c @@ -222,6 +222,7 @@ void medit_setup_existing(struct descriptor_data *d, int rmob_num) /* Ideally, this function should be in db.c, but I'll put it here for portability. */ static void init_mobile(struct char_data *mob) { + int i; clear_char(mob); GET_HIT(mob) = GET_MANA(mob) = 1; @@ -234,11 +235,8 @@ static void init_mobile(struct char_data *mob) mob->real_abils.dex = mob->real_abils.con = mob->real_abils.cha = 11; mob->aff_abils = mob->real_abils; - GET_SAVE(mob, SAVING_PARA) = 0; - GET_SAVE(mob, SAVING_ROD) = 0; - GET_SAVE(mob, SAVING_PETRI) = 0; - GET_SAVE(mob, SAVING_BREATH) = 0; - GET_SAVE(mob, SAVING_SPELL) = 0; + for (i = 0; i < NUM_ABILITIES; i++) + GET_SAVE(mob, i) = 0; SET_BIT_AR(MOB_FLAGS(mob), MOB_ISNPC); mob->player_specials = &dummy_mob; @@ -491,19 +489,32 @@ static void medit_disp_stats_menu(struct descriptor_data *d) if (CONFIG_MEDIT_ADVANCED) { /* Bottom section - non-standard stats, togglable in cedit */ write_to_output(d, - "(%sF%s) Str: %s[%s%2d/%3d%s]%s Saving Throws\r\n" - "(%sG%s) Int: %s[%s%3d%s]%s (%sL%s) Paralysis %s[%s%3d%s]%s\r\n" - "(%sH%s) Wis: %s[%s%3d%s]%s (%sM%s) Rods/Staves %s[%s%3d%s]%s\r\n" - "(%sI%s) Dex: %s[%s%3d%s]%s (%sN%s) Petrification %s[%s%3d%s]%s\r\n" - "(%sJ%s) Con: %s[%s%3d%s]%s (%sO%s) Breath %s[%s%3d%s]%s\r\n" - "(%sK%s) Cha: %s[%s%3d%s]%s (%sP%s) Spells %s[%s%3d%s]%s\r\n\r\n", + " %sAttributes%s %sSaving Throws%s\r\n" + "(%sF%s) Str: %s[%s%2d/%3d%s]%s (%sR%s) Save STR %s[%s%3d%s]%s\r\n" + "(%sG%s) Int: %s[%s%3d%s]%s (%sS%s) Save DEX %s[%s%3d%s]%s\r\n" + "(%sH%s) Wis: %s[%s%3d%s]%s (%sT%s) Save CON %s[%s%3d%s]%s\r\n" + "(%sI%s) Dex: %s[%s%3d%s]%s (%sU%s) Save INT %s[%s%3d%s]%s\r\n" + "(%sJ%s) Con: %s[%s%3d%s]%s (%sV%s) Save WIS %s[%s%3d%s]%s\r\n" + "(%sK%s) Cha: %s[%s%3d%s]%s (%sW%s) Save CHA %s[%s%3d%s]%s\r\n\r\n", + nrm, cyn, nrm, cyn, cyn, nrm, cyn, yel, GET_STR(mob), GET_ADD(mob), cyn, nrm, - cyn, nrm, cyn, yel, GET_INT(mob), cyn, nrm, cyn, nrm, cyn, yel, GET_SAVE(mob, SAVING_PARA), cyn, nrm, - cyn, nrm, cyn, yel, GET_WIS(mob), cyn, nrm, cyn, nrm, cyn, yel, GET_SAVE(mob, SAVING_ROD), cyn, nrm, - cyn, nrm, cyn, yel, GET_DEX(mob), cyn, nrm, cyn, nrm, cyn, yel, GET_SAVE(mob, SAVING_PETRI), cyn, nrm, - cyn, nrm, cyn, yel, GET_CON(mob), cyn, nrm, cyn, nrm, cyn, yel, GET_SAVE(mob, SAVING_BREATH), cyn, nrm, - cyn, nrm, cyn, yel, GET_CHA(mob), cyn, nrm, cyn, nrm, cyn, yel, GET_SAVE(mob, SAVING_SPELL), cyn, nrm - ); + cyn, nrm, cyn, yel, GET_SAVE(mob, ABIL_STR), cyn, nrm, + + cyn, nrm, cyn, yel, GET_INT(mob), cyn, nrm, + cyn, nrm, cyn, yel, GET_SAVE(mob, ABIL_DEX), cyn, nrm, + + cyn, nrm, cyn, yel, GET_WIS(mob), cyn, nrm, + cyn, nrm, cyn, yel, GET_SAVE(mob, ABIL_CON), cyn, nrm, + + cyn, nrm, cyn, yel, GET_DEX(mob), cyn, nrm, + cyn, nrm, cyn, yel, GET_SAVE(mob, ABIL_INT), cyn, nrm, + + cyn, nrm, cyn, yel, GET_CON(mob), cyn, nrm, + cyn, nrm, cyn, yel, GET_SAVE(mob, ABIL_WIS), cyn, nrm, + + cyn, nrm, cyn, yel, GET_CHA(mob), cyn, nrm, + cyn, nrm, cyn, yel, GET_SAVE(mob, ABIL_CHA), cyn, nrm + ); } /* Quit to previous menu option */ @@ -751,45 +762,66 @@ void medit_parse(struct descriptor_data *d, char *arg) write_to_output(d, "Invalid Choice!\r\nEnter Choice : "); return; } - OLC_MODE(d) = MEDIT_PARA; - i++; - break; - case 'm': - case 'M': + case 'r': + case 'R': if (!CONFIG_MEDIT_ADVANCED) { write_to_output(d, "Invalid Choice!\r\nEnter Choice : "); return; - } - OLC_MODE(d) = MEDIT_ROD; + } + OLC_MODE(d) = MEDIT_SAVE_STR; i++; break; - case 'n': - case 'N': + + case 's': + case 'S': if (!CONFIG_MEDIT_ADVANCED) { write_to_output(d, "Invalid Choice!\r\nEnter Choice : "); return; - } - OLC_MODE(d) = MEDIT_PETRI; + } + OLC_MODE(d) = MEDIT_SAVE_DEX; i++; break; - case 'o': - case 'O': + + case 't': + case 'T': if (!CONFIG_MEDIT_ADVANCED) { write_to_output(d, "Invalid Choice!\r\nEnter Choice : "); return; - } - OLC_MODE(d) = MEDIT_BREATH; + } + OLC_MODE(d) = MEDIT_SAVE_CON; i++; break; - case 'p': - case 'P': + + case 'u': + case 'U': if (!CONFIG_MEDIT_ADVANCED) { write_to_output(d, "Invalid Choice!\r\nEnter Choice : "); return; - } - OLC_MODE(d) = MEDIT_SPELL; + } + OLC_MODE(d) = MEDIT_SAVE_INT; i++; break; + + case 'v': + case 'V': + if (!CONFIG_MEDIT_ADVANCED) { + write_to_output(d, "Invalid Choice!\r\nEnter Choice : "); + return; + } + OLC_MODE(d) = MEDIT_SAVE_WIS; + i++; + break; + + case 'w': + case 'W': + if (!CONFIG_MEDIT_ADVANCED) { + write_to_output(d, "Invalid Choice!\r\nEnter Choice : "); + return; + } + OLC_MODE(d) = MEDIT_SAVE_CHA; + i++; + break; + default: medit_disp_stats_menu(d); return; @@ -942,35 +974,29 @@ void medit_parse(struct descriptor_data *d, char *arg) medit_disp_stats_menu(d); return; - case MEDIT_PARA: - GET_SAVE(OLC_MOB(d), SAVING_PARA) = LIMIT(i, 0, 100); - OLC_VAL(d) = TRUE; - medit_disp_stats_menu(d); - return; + case MEDIT_SAVE_STR: + GET_SAVE(OLC_MOB(d), ABIL_STR) = LIMIT(atoi(arg), -20, 20); + break; - case MEDIT_ROD: - GET_SAVE(OLC_MOB(d), SAVING_ROD) = LIMIT(i, 0, 100); - OLC_VAL(d) = TRUE; - medit_disp_stats_menu(d); - return; + case MEDIT_SAVE_DEX: + GET_SAVE(OLC_MOB(d), ABIL_DEX) = LIMIT(atoi(arg), -20, 20); + break; - case MEDIT_PETRI: - GET_SAVE(OLC_MOB(d), SAVING_PETRI) = LIMIT(i, 0, 100); - OLC_VAL(d) = TRUE; - medit_disp_stats_menu(d); - return; + case MEDIT_SAVE_CON: + GET_SAVE(OLC_MOB(d), ABIL_CON) = LIMIT(atoi(arg), -20, 20); + break; - case MEDIT_BREATH: - GET_SAVE(OLC_MOB(d), SAVING_BREATH) = LIMIT(i, 0, 100); - OLC_VAL(d) = TRUE; - medit_disp_stats_menu(d); - return; + case MEDIT_SAVE_INT: + GET_SAVE(OLC_MOB(d), ABIL_INT) = LIMIT(atoi(arg), -20, 20); + break; - case MEDIT_SPELL: - GET_SAVE(OLC_MOB(d), SAVING_SPELL) = LIMIT(i, 0, 100); - OLC_VAL(d) = TRUE; - medit_disp_stats_menu(d); - return; + case MEDIT_SAVE_WIS: + GET_SAVE(OLC_MOB(d), ABIL_WIS) = LIMIT(atoi(arg), -20, 20); + break; + + case MEDIT_SAVE_CHA: + GET_SAVE(OLC_MOB(d), ABIL_CHA) = LIMIT(atoi(arg), -20, 20); + break; case MEDIT_POS: GET_POS(OLC_MOB(d)) = LIMIT(i - 1, 0, NUM_POSITIONS - 1); @@ -1053,27 +1079,28 @@ void medit_autoroll_stats(struct descriptor_data *d) mob_lev = GET_LEVEL(OLC_MOB(d)); mob_lev = GET_LEVEL(OLC_MOB(d)) = LIMIT(mob_lev, 1, LVL_IMPL); - GET_MOVE(OLC_MOB(d)) = mob_lev*10; /* hit point bonus (mobs don't use movement points */ - GET_HIT(OLC_MOB(d)) = mob_lev/5; /* number of hitpoint dice */ - GET_MANA(OLC_MOB(d)) = mob_lev/5; /* size of hitpoint dice */ + GET_MOVE(OLC_MOB(d)) = mob_lev * 10; /* hit point bonus (mobs don't use movement points) */ + GET_HIT(OLC_MOB(d)) = mob_lev / 5; /* number of hitpoint dice */ + GET_MANA(OLC_MOB(d)) = mob_lev / 5; /* size of hitpoint dice */ - GET_NDD(OLC_MOB(d)) = MAX(1, mob_lev/6); /* number damage dice 1-5 */ - GET_SDD(OLC_MOB(d)) = MAX(2, mob_lev/6); /* size of damage dice 2-5 */ + GET_NDD(OLC_MOB(d)) = MAX(1, mob_lev / 6); /* number damage dice 1-5 */ + GET_SDD(OLC_MOB(d)) = MAX(2, mob_lev / 6); /* size of damage dice 2-5 */ /* 'Advanced' stats are only rolled if advanced options are enabled */ if (CONFIG_MEDIT_ADVANCED) { - GET_STR(OLC_MOB(d)) = LIMIT((mob_lev*2)/3, 11, 18); /* 2/3 level in range 11 to 18 */ - GET_INT(OLC_MOB(d)) = LIMIT((mob_lev*2)/3, 11, 18); - GET_WIS(OLC_MOB(d)) = LIMIT((mob_lev*2)/3, 11, 18); - GET_DEX(OLC_MOB(d)) = LIMIT((mob_lev*2)/3, 11, 18); - GET_CON(OLC_MOB(d)) = LIMIT((mob_lev*2)/3, 11, 18); - GET_CHA(OLC_MOB(d)) = LIMIT((mob_lev*2)/3, 11, 18); + GET_STR(OLC_MOB(d)) = LIMIT((mob_lev * 2) / 3, 11, 18); /* 2/3 level in range 11 to 18 */ + GET_INT(OLC_MOB(d)) = LIMIT((mob_lev * 2) / 3, 11, 18); + GET_WIS(OLC_MOB(d)) = LIMIT((mob_lev * 2) / 3, 11, 18); + GET_DEX(OLC_MOB(d)) = LIMIT((mob_lev * 2) / 3, 11, 18); + GET_CON(OLC_MOB(d)) = LIMIT((mob_lev * 2) / 3, 11, 18); + GET_CHA(OLC_MOB(d)) = LIMIT((mob_lev * 2) / 3, 11, 18); - GET_SAVE(OLC_MOB(d), SAVING_PARA) = mob_lev / 4; /* All Saving throws */ - GET_SAVE(OLC_MOB(d), SAVING_ROD) = mob_lev / 4; /* set to a quarter */ - GET_SAVE(OLC_MOB(d), SAVING_PETRI) = mob_lev / 4; /* of the mobs level */ - GET_SAVE(OLC_MOB(d), SAVING_BREATH) = mob_lev / 4; - GET_SAVE(OLC_MOB(d), SAVING_SPELL) = mob_lev / 4; + /* New ability-based saving throws: all default to 1/4 of mob level */ + GET_SAVE(OLC_MOB(d), ABIL_STR) = mob_lev / 4; + GET_SAVE(OLC_MOB(d), ABIL_DEX) = mob_lev / 4; + GET_SAVE(OLC_MOB(d), ABIL_CON) = mob_lev / 4; + GET_SAVE(OLC_MOB(d), ABIL_INT) = mob_lev / 4; + GET_SAVE(OLC_MOB(d), ABIL_WIS) = mob_lev / 4; + GET_SAVE(OLC_MOB(d), ABIL_CHA) = mob_lev / 4; } - } diff --git a/src/oasis.h b/src/oasis.h index 6889396..26c9928 100644 --- a/src/oasis.h +++ b/src/oasis.h @@ -283,11 +283,12 @@ extern const char *nrm, *grn, *cyn, *yel; #define MEDIT_DEX 27 #define MEDIT_CON 28 #define MEDIT_CHA 29 -#define MEDIT_PARA 30 -#define MEDIT_ROD 31 -#define MEDIT_PETRI 32 -#define MEDIT_BREATH 33 -#define MEDIT_SPELL 34 +#define MEDIT_SAVE_STR 30 +#define MEDIT_SAVE_DEX 31 +#define MEDIT_SAVE_CON 32 +#define MEDIT_SAVE_INT 33 +#define MEDIT_SAVE_WIS 34 +#define MEDIT_SAVE_CHA 35 /* Submodes of SEDIT connectedness. */ #define SEDIT_MAIN_MENU 0 diff --git a/src/spell_parser.c b/src/spell_parser.c index 982e20c..ebf54f9 100644 --- a/src/spell_parser.c +++ b/src/spell_parser.c @@ -208,13 +208,13 @@ int call_magic(struct char_data *caster, struct char_data *cvict, case CAST_SCROLL: case CAST_POTION: case CAST_WAND: - savetype = SAVING_ROD; + savetype = SAVING_WIS; break; case CAST_SPELL: - savetype = SAVING_SPELL; + savetype = SAVING_WIS; break; default: - savetype = SAVING_BREATH; + savetype = SAVING_DEX; break; } diff --git a/src/spells.c b/src/spells.c index 42763da..31e42c7 100644 --- a/src/spells.c +++ b/src/spells.c @@ -143,7 +143,7 @@ ASPELL(spell_summon) } if (MOB_FLAGGED(victim, MOB_NOSUMMON) || - (IS_NPC(victim) && mag_savingthrow(victim, SAVING_SPELL, 0))) { + (IS_NPC(victim) && mag_savingthrow(victim, SAVING_CHA, 0))) { send_to_char(ch, "%s", SUMMON_FAIL); return; } @@ -269,7 +269,7 @@ ASPELL(spell_charm) send_to_char(ch, "You fail - shouldn't be doing it anyway.\r\n"); else if (circle_follow(victim, ch)) send_to_char(ch, "Sorry, following in circles is not allowed.\r\n"); - else if (mag_savingthrow(victim, SAVING_PARA, 0)) + else if (mag_savingthrow(victim, SAVING_WIS, 0)) send_to_char(ch, "Your victim resists!\r\n"); else { if (victim->master) diff --git a/src/spells.h b/src/spells.h index c539f36..a7321f1 100644 --- a/src/spells.h +++ b/src/spells.h @@ -155,11 +155,15 @@ /* new attack types can be added here - up to TYPE_SUFFERING */ #define TYPE_SUFFERING 399 -#define SAVING_PARA 0 -#define SAVING_ROD 1 -#define SAVING_PETRI 2 -#define SAVING_BREATH 3 -#define SAVING_SPELL 4 +/* Saving throws for 5e-like system */ +#define SAVING_STR 0 +#define SAVING_DEX 1 +#define SAVING_CON 2 +#define SAVING_INT 3 +#define SAVING_WIS 4 +#define SAVING_CHA 5 + +#define NUM_SAVING_THROWS 6 /*** **Possible Targets: diff --git a/src/structs.h b/src/structs.h index 7c9c9b9..bf4a683 100644 --- a/src/structs.h +++ b/src/structs.h @@ -464,13 +464,15 @@ #define APPLY_EXP 16 /**< Reserved */ #define APPLY_AC 17 /**< Apply to Armor Class */ #define APPLY_PROFICIENCY 18 /**< Apply to Proficiency Bonus */ -#define APPLY_SAVING_PARA 19 /**< Apply to save throw: paralysis */ -#define APPLY_SAVING_ROD 20 /**< Apply to save throw: rods */ -#define APPLY_SAVING_PETRI 21 /**< Apply to save throw: petrif */ -#define APPLY_SAVING_BREATH 22 /**< Apply to save throw: breath */ -#define APPLY_SAVING_SPELL 23 /**< Apply to save throw: spells */ +#define APPLY_SAVE_STR 19 /**< Apply to STR saving throws */ +#define APPLY_SAVE_DEX 20 /**< Apply to DEX saving throws */ +#define APPLY_SAVE_CON 21 /**< Apply to CON saving throws */ +#define APPLY_SAVE_INT 22 /**< Apply to INT saving throws */ +#define APPLY_SAVE_WIS 23 /**< Apply to WIS saving throws */ +#define APPLY_SAVE_CHA 24 /**< Apply to CHA saving throws */ + /** Total number of applies */ -#define NUM_APPLIES 24 +#define NUM_APPLIES 25 /* Equals the total number of SAVING_* defines in spells.h */ #define NUM_OF_SAVING_THROWS 5 @@ -900,6 +902,17 @@ struct char_ability_data sbyte cha; /**< Charisma */ }; +/* Ability score indices for 5e-like system */ +enum ability_scores { + ABIL_STR = 0, + ABIL_DEX = 1, + ABIL_CON = 2, + ABIL_INT = 3, + ABIL_WIS = 4, + ABIL_CHA = 5, + NUM_ABILITIES +}; + /** Character 'points', or health statistics. */ struct char_point_data { @@ -931,7 +944,7 @@ struct char_special_data_saved long idnum; /**< PC's idnum; -1 for mobiles. */ int act[PM_ARRAY_MAX]; /**< act flags for NPC's; player flag for PC's */ int affected_by[AF_ARRAY_MAX]; /**< Bitvector for spells/skills affected by */ - sh_int apply_saving_throw[5]; /**< Saving throw (Bonuses) */ + sh_int saving_throws[NUM_ABILITIES]; /* STR, DEX, CON, INT, WIS, CHA */ }; /** Special playing constants shared by PCs and NPCs which aren't in pfile */ diff --git a/src/utils.h b/src/utils.h index 736a7c3..5c52dd0 100644 --- a/src/utils.h +++ b/src/utils.h @@ -550,6 +550,16 @@ do \ /** Current charisma of ch. */ #define GET_CHA(ch) ((ch)->aff_abils.cha) +/* Definitions for 5e-like saving throws */ +#define GET_SAVE(ch, i) ((ch)->char_specials.saved.saving_throws[(i)]) + +#define SAVE_STR(ch) GET_SAVE(ch, ABIL_STR) +#define SAVE_DEX(ch) GET_SAVE(ch, ABIL_DEX) +#define SAVE_CON(ch) GET_SAVE(ch, ABIL_CON) +#define SAVE_INT(ch) GET_SAVE(ch, ABIL_INT) +#define SAVE_WIS(ch) GET_SAVE(ch, ABIL_WIS) +#define SAVE_CHA(ch) GET_SAVE(ch, ABIL_CHA) + /** Experience points of ch. */ #define GET_EXP(ch) ((ch)->points.exp) /** Armor class of ch. */ @@ -589,7 +599,7 @@ do \ /** Who or what the ch is hunting. */ #define HUNTING(ch) ((ch)->char_specials.hunting) /** Saving throw i for character ch. */ -#define GET_SAVE(ch, i) ((ch)->char_specials.saved.apply_saving_throw[i]) +#define GET_SAVE(ch, i) ((ch)->char_specials.saved.saving_throws[(i)]) /** Alignment value for ch. */ #define GET_ALIGNMENT(ch) ((ch)->char_specials.saved.alignment)