From 5a2bd1a34020ca3db71d31327e877a7d7bb30d0e Mon Sep 17 00:00:00 2001 From: GickerLDS Date: Fri, 29 Nov 2024 16:05:01 +0000 Subject: [PATCH] -Added gully dwarf race -Added race and level back to who list -Added the following bonus types: spell circles (1-9), spell potency, spell dc, spell duration, spell penetration -Added lastroom command -Added listraces command --- act.informative.c | 16 ++- act.movement.c | 1 - act.offensive.c | 8 ++ backgrounds.c | 70 +----------- constants.c | 3 + craft.c | 8 +- craft.h | 1 + db.c | 3 + depend | 5 +- feats.c | 25 ++++- fight.c | 14 ++- handler.c | 1 + interpreter.c | 4 +- limits.c | 9 ++ magic.c | 13 ++- mobact.c | 2 + players.c | 5 + race.c | 280 +++++++++++++++++++++++++++++++++++++++++++++- race.h | 4 + spec_procs.c | 4 + structs.h | 13 ++- treasure.c | 24 +++- treasure.h | 4 + utils.c | 104 ++++++++++++++++- utils.h | 2 + zedit.c | 8 ++ 26 files changed, 529 insertions(+), 102 deletions(-) diff --git a/act.informative.c b/act.informative.c index 8b3c1b24..8280df01 100755 --- a/act.informative.c +++ b/act.informative.c @@ -2091,6 +2091,8 @@ void perform_cooldowns(struct char_data *ch, struct char_data *k) send_to_char(ch, "Forage - Duration: %d seconds\r\n", GET_FORAGE_COOLDOWN(k) * 6); if (GET_RETAINER_COOLDOWN(k) > 0) send_to_char(ch, "Call Retainer - Duration: %d seconds\r\n", GET_RETAINER_COOLDOWN(k) * 6); + if (GET_SCROUNGE_COOLDOWN(k) > 0) + send_to_char(ch, "Scrounge - Duration: %d seconds\r\n", GET_SCROUNGE_COOLDOWN(k) * 6); list_item_activate_ability_cooldowns(ch); @@ -4205,7 +4207,7 @@ ACMD(do_who) else snprintf(clan_name, sizeof(clan_name), "%s", ((c_n = real_clan(GET_CLAN(tch))) != NO_CLAN && GET_CLANRANK(tch) > 0) ? CLAN_NAME(c_n) : "Adventurer"); length = strlen(clan_name); - padding = 20 - length; + padding = 28 - length; // Move characters to make room for padding at the front for (x = length; x >= 0; x--) @@ -4217,14 +4219,18 @@ ACMD(do_who) clan_name[x] = ' '; } // Append spaces at the end - for (x = length + padding / 2; x < 20; x++) { + for (x = length + padding / 2; x < 28; x++) { clan_name[x] = ' '; } if (padding % 2 != 0) { // If padding is odd, add one more space at the end - clan_name[20] = ' '; + clan_name[28] = ' '; } - send_to_char(ch, "\tC[ %20.20s ]\tn %s", clan_name, GET_TITLE(tch)); + if (GET_LEVEL(tch) >= LVL_IMMORT) + send_to_char(ch, "\tW[\tC%28.28s \tW]\tn %s", clan_name, GET_TITLE(tch)); + else + send_to_char(ch, "\tW[ \tC%2d %-4.4s %-20.20s \tW]\tn %s", GET_LEVEL(tch), race_list[GET_REAL_RACE(tch)].abbrev, + ((c_n = real_clan(GET_CLAN(tch))) != NO_CLAN && GET_CLANRANK(tch) > 0) ? CLAN_NAME(c_n) : "Adventurer", GET_TITLE(tch)); // num_can_see++; if (GET_LEVEL(tch) >= LVL_IMMORT) @@ -4386,6 +4392,8 @@ ACMD(do_who) send_to_char(ch, "Number of unique accounts connected: %d.\r\n", num_accounts); } + send_to_char(ch, "Type 'listraces' to understand race abbreviations.\r\n"); + if (IS_HAPPYHOUR > 0) { send_to_char(ch, "\tWIt's a Happy Hour! Type \tRhappyhour\tW to see the current bonuses.\tn\r\n"); diff --git a/act.movement.c b/act.movement.c index 7eaf6291..611ef7b3 100755 --- a/act.movement.c +++ b/act.movement.c @@ -1169,7 +1169,6 @@ int do_simple_move(struct char_data *ch, int dir, int need_specials_check) /* fleeing: no retreat feat offers free AOO */ if (need_specials_check == 3 && GET_POS(ch) > POS_DEAD) { - /* loop room */ struct char_data *tch, *next_tch; for (tch = world[IN_ROOM(ch)].people; tch; tch = next_tch) diff --git a/act.offensive.c b/act.offensive.c index b4fd0fdd..e490acfb 100755 --- a/act.offensive.c +++ b/act.offensive.c @@ -3449,6 +3449,11 @@ ACMD(do_taunt) send_to_char(ch, "This mob cannot be attacked by you.\r\n"); return; } + if (HAS_FEAT(vict, FEAT_COWARDLY)) + { + act("$n is too cowardly to be goaded by your taunts.", FALSE, vict, 0, ch, TO_VICT); + return; + } if (char_has_mud_event(vict, eTAUNTED)) { send_to_char(ch, "Your target is already taunted...\r\n"); @@ -3476,6 +3481,9 @@ int perform_intimidate(struct char_data *ch, struct char_data *vict) if (HAS_FEAT(vict, FEAT_DEMORALIZE)) resist += 2; + if (HAS_FEAT(vict, FEAT_COWARDLY)) + resist -= 4; + /* Should last one round, plus one second for every point over the resist */ if (attempt >= resist) { diff --git a/backgrounds.c b/backgrounds.c index 459eaa46..fefcb606 100644 --- a/backgrounds.c +++ b/backgrounds.c @@ -927,10 +927,7 @@ ACMD(do_relay) ACMD(do_forage) { - int skill, dc, result, modifier = 2, bonus = 0, roll; - bool food = false; - char ripeness[50], food_desc[150]; - struct obj_data *obj; + int skill, dc, result, roll; if (IS_NPC(ch)) { @@ -964,70 +961,7 @@ ACMD(do_forage) return; } - result /= 10; - - switch (result) - { - case 0: modifier = 2; snprintf(ripeness, sizeof(ripeness), "rather unripe"); break; - case 1: modifier = 3; snprintf(ripeness, sizeof(ripeness), "barely ripe"); break; - case 2: modifier = 4; snprintf(ripeness, sizeof(ripeness), "nicely ripened"); break; - case 3: modifier = 5; snprintf(ripeness, sizeof(ripeness), "very well ripened"); break; - default: modifier = 6; snprintf(ripeness, sizeof(ripeness), "perfectly ripened"); break; - } - - switch (rand_number(0, 18)) - { - case 0: bonus = APPLY_AC_NEW; break; - case 1: bonus = APPLY_STR; break; - case 2: bonus = APPLY_DEX; break; - case 3: bonus = APPLY_CON; break; - case 4: bonus = APPLY_INT; break; - case 5: bonus = APPLY_WIS; break; - case 6: bonus = APPLY_CHA; break; - case 7: bonus = APPLY_DAMROLL; modifier /= 2; break; - case 8: bonus = APPLY_HITROLL; modifier /= 2; break; - case 9: bonus = APPLY_ENCUMBRANCE; break; - case 10: bonus = APPLY_HIT; modifier *= 10; break; - case 11: bonus = APPLY_MOVE; modifier *= 100; break; - case 12: bonus = APPLY_HP_REGEN; break; - case 13: bonus = APPLY_MV_REGEN; break; - case 14: bonus = APPLY_PSP; modifier *= 5; break; - case 15: bonus = APPLY_PSP_REGEN; break; - case 16: bonus = APPLY_SAVING_FORT; break; - case 17: bonus = APPLY_SAVING_REFL; break; - case 18: bonus = APPLY_SAVING_WILL; break; - } - - obj = read_object(FORAGE_FOOD_ITEM_VNUM, VIRTUAL); - - if (!obj) - { - send_to_char(ch, "The forage food item prototype was not found. Please inform a staff with code ERRFOR001.\r\n"); - return; - } - - GET_FORAGE_COOLDOWN(ch) = 100; - - food = apply_type_food_or_drink[bonus]; - - if (!food) - GET_OBJ_TYPE(obj) = ITEM_DRINK; - - obj->affected[0].location = bonus; - obj->affected[0].modifier = modifier; - obj->affected[0].bonus_type = (food) ? BONUS_TYPE_FOOD : BONUS_TYPE_DRINK; - - snprintf(food_desc, sizeof(food_desc), "some %s %s", ripeness, apply_type_food_names[bonus]); - obj->name = strdup(food_desc); - obj->short_description = strdup(food_desc); - snprintf(food_desc, sizeof(food_desc), "Some %s %s lie here.", ripeness, apply_type_food_names[bonus]); - obj->description = strdup(food_desc); - - obj_to_char(obj, ch); - - act("You forage for food and find $p!", TRUE, ch, obj, 0, TO_CHAR); - act("$n forages for food and finds $p!", TRUE, ch, obj, 0, TO_ROOM); - + award_random_food_item(ch, result, 1); } #define RETAINER_SYNTAX ("Proper syntax is:\r\n" \ diff --git a/constants.c b/constants.c index f06646ee..5baa4207 100755 --- a/constants.c +++ b/constants.c @@ -2587,6 +2587,7 @@ const char *apply_types[] = { "Spell-Potency", "Spell-DC", "Spell-Duration", + "Spell-Penetration", "\n" /*73*/ }; CHECK_TABLE_SIZE(apply_types, NUM_APPLIES + 1); @@ -2667,6 +2668,7 @@ const char *apply_type_food_names[] = "", // spell potency "", // spell dc "", // spell duration + "", // spell penetration "\n" }; CHECK_TABLE_SIZE(apply_type_food_names, NUM_APPLIES + 1); @@ -2748,6 +2750,7 @@ const int apply_type_food_or_drink[] = TRUE, // spell potency TRUE, // spell dc TRUE, // spell duration + TRUE, // spell penetration TRUE }; CHECK_TABLE_SIZE(apply_type_food_or_drink, NUM_APPLIES + 1); diff --git a/craft.c b/craft.c index 97135f78..6020a0e6 100644 --- a/craft.c +++ b/craft.c @@ -1603,7 +1603,7 @@ int bonearmor(char *argument, struct obj_data *kit, struct char_data *ch) if (cost == 0) GET_CRAFTING_TICKS(ch) = 1; else - GET_CRAFTING_TICKS(ch) = 5 - fast_craft_bonus; + GET_CRAFTING_TICKS(ch) = MAX(1, 5 - fast_craft_bonus); obj_to_char(obj, ch); save_char(ch, 0); @@ -2816,7 +2816,6 @@ EVENTFUNC(event_crafting) /* resize system check point -Zusuk */ autoquest_trigger_check(ch, NULL, NULL, 0, AQ_CRAFT_RESIZE); - break; case SCMD_REFORGE: @@ -3551,4 +3550,9 @@ void put_mysql_supply_orders_available(struct char_data *ch, int avail) { log("SYSERR: Unable to INSERT INTO player_supply_orders: %s", mysql_error(conn)); } +} + +ACMD(do_need_craft_kit) +{ + send_to_char(ch, "You must be in a room with a crafting station or have a crafting kit in your inventory to perform this action.\r\n"); } \ No newline at end of file diff --git a/craft.h b/craft.h index d7305545..7145f77b 100644 --- a/craft.h +++ b/craft.h @@ -227,6 +227,7 @@ void reset_acraft(struct char_data *ch); /* command functions */ ACMD_DECL(do_harvest); ACMD_DECL(do_disenchant); +ACMD_DECL(do_need_craft_kit); /* end command functions */ int get_mysql_supply_orders_available(struct char_data *ch); diff --git a/db.c b/db.c index d12f3f9f..d730d85d 100755 --- a/db.c +++ b/db.c @@ -679,6 +679,9 @@ void boot_world(void) log("Loading evolutions."); assign_evolutions(); + // we'll sort races alphabetically + sort_races(); + // assign backgrounds assign_backgrounds(); sort_backgrounds(); diff --git a/depend b/depend index 77da1051..44d4258c 100644 --- a/depend +++ b/depend @@ -130,7 +130,7 @@ config.o: config.c conf.h sysdep.h structs.h bool.h protocol.h lists.h \ constants.o: constants.c conf.h sysdep.h structs.h bool.h protocol.h \ lists.h campaign.h utils.h db.h helpers.h perfmon.h interpreter.h \ spells.h craft.h feats.h domains_schools.h handler.h deities.h \ - constants.h + constants.h roleplay.h craft.o: craft.c conf.h sysdep.h structs.h bool.h protocol.h lists.h \ campaign.h mysql.h utils.h db.h helpers.h perfmon.h comm.h spells.h \ interpreter.h constants.h handler.h craft.h mud_event.h dg_event.h \ @@ -449,7 +449,8 @@ redit.o: redit.c conf.h sysdep.h structs.h bool.h protocol.h lists.h \ roleplay.o: roleplay.c conf.h sysdep.h structs.h bool.h protocol.h \ lists.h campaign.h utils.h db.h helpers.h perfmon.h comm.h spells.h \ handler.h interpreter.h constants.h backgrounds.h treasure.h fight.h \ - spec_procs.h clan.h dg_scripts.h feats.h improved-edit.h + spec_procs.h clan.h dg_scripts.h feats.h improved-edit.h roleplay.h \ + deities.h char_descs.h modify.h sedit.o: sedit.c conf.h sysdep.h structs.h bool.h protocol.h lists.h \ campaign.h utils.h db.h helpers.h perfmon.h comm.h interpreter.h shop.h \ genolc.h genshp.h genzon.h oasis.h help.h constants.h diff --git a/feats.c b/feats.c index 1e0068a9..b1d21eef 100644 --- a/feats.c +++ b/feats.c @@ -421,7 +421,23 @@ void assign_feats(void) feato(FEAT_DWARF_RACIAL_ADJUSTMENT, "dwarf racial adjustment", TRUE, FALSE, FALSE, FEAT_TYPE_INNATE_ABILITY, "+2 con", "As a racial adjustment you have +2 to constitution."); -#if defined(CAMAPIGN_DL) +#if defined(CAMPAIGN_DL) + // gully dwarf + feato(FEAT_GULLY_DWARF_RACIAL_ADJUSTMENT, "gully dwarf racial adjustment", TRUE, FALSE, FALSE, FEAT_TYPE_INNATE_ABILITY, + "+4 Con, +4 Dex, -4 Int, -2 Cha", + "+4 racial bonus to dexterity and constituion ability scores. -4 to intelligence and -2 to charisma."); + feato(FEAT_SURVIVAL_INSTINCT, "survival instinct", TRUE, FALSE, FALSE, FEAT_TYPE_INNATE_ABILITY, + "+3 to Stealth and Nature skills. Can use the scrounge ability to find random items virtually anywhere.", + "+3 to Stealth and Nature skills. Can use the scrounge ability to find random items virtually anywhere."); + feato(FEAT_COWARDLY, "cowardly", TRUE, FALSE, FALSE, FEAT_TYPE_INNATE_ABILITY, + "-4 penalty to intimidation attempts on the gully dwarf. Movement speed will not prevent them from fleeing, and they do not need an action to flee. Immune to taunts.", + "-4 penalty to intimidation attempts on the gully dwarf. Movement speed will not prevent them from fleeing, and they do not need an action to flee. Immune to taunts."); + feato(FEAT_PITIABLE, "pitiable", TRUE, FALSE, FALSE, FEAT_TYPE_INNATE_ABILITY, + "Has a 75% chance to avoid aggro attacks by mobs.", + "Has a 75% chance to avoid aggro attacks by mobs."); + feato(FEAT_GRUBBY, "grubby", TRUE, FALSE, FALSE, FEAT_TYPE_INNATE_ABILITY, + "-6 to persuasion and appraise skill checks. 50% resistance to poison and disease damage. +4 saving throw bonus against disease.", + "-6 to persuasion and appraise skill checks. 50% resistance to poison and disease damage. +4 saving throw bonus against disease."); // mountain dwarf feato(FEAT_SHIELD_DWARF_RACIAL_ADJUSTMENT, "mountain dwarf racial adjustment", TRUE, FALSE, FALSE, FEAT_TYPE_INNATE_ABILITY, "+2 str +2 Con", @@ -5058,7 +5074,12 @@ feato(FEAT_MOON_ELF_RACIAL_ADJUSTMENT, "moon elf racial adjustment", TRUE, FALSE /* Pale/Death Master */ feato(FEAT_BONE_ARMOR, "bone armor", TRUE, FALSE, FALSE, FEAT_TYPE_CLASS_ABILITY, "allows creation of bone armor with the bonearmor command, and 10 percent arcane spell failure reduction in per rank, if and only if all armor slots are made of bone (body, arms, legs and head).", - "allows creation of bone armor with the bonearmor command, and 10 percent arcane spell failure reduction in per rank, if and only if all armor slots are made of bone (body, arms, legs and head)."); + "allows creation of bone armor with the bonearmor command, and 10 percent arcane spell failure reduction " + "in per rank, if and only if all armor slots are made of bone (body, arms, legs and head). To do so, ensure " + "that you have a crafting station in your same room or a crafting kit in your inventory. Put the armor piece " + "or shield in the kit and type: bonearmor (new item description) Eg. 'put breastplate kit' then 'bonearmor a " + "bone breast plate'. There will be a gold cost, and then the armor piece will be placed in your inventory with " + "the new description and the item's material now being bone."); feato(FEAT_ESSENCE_OF_UNDEATH, "essence of undeath", TRUE, FALSE, FALSE, FEAT_TYPE_CLASS_ABILITY, "Gives immunity to poison, sleep and death affects, paralysis, sneak attack and critical hits.", "Gives immunity to poison, sleep and death affects, paralysis, sneak attack and critical hits."); diff --git a/fight.c b/fight.c index f022e2d5..035bf8d3 100755 --- a/fight.c +++ b/fight.c @@ -299,7 +299,7 @@ void perform_flee(struct char_data *ch) return; } - if (!is_action_available(ch, atMOVE, TRUE)) + if (!is_action_available(ch, atMOVE, TRUE) && !HAS_FEAT(ch, FEAT_COWARDLY)) { GUI_CMBT_OPEN(ch); send_to_char(ch, "You need a move action to flee!\r\n"); @@ -327,7 +327,8 @@ void perform_flee(struct char_data *ch) } /* cost */ - USE_MOVE_ACTION(ch); + if (!HAS_FEAT(ch, FEAT_COWARDLY)) + USE_MOVE_ACTION(ch); // not fighting? no problems if (!FIGHTING(ch)) @@ -2223,6 +2224,7 @@ void die(struct char_data *ch, struct char_data *killer) REMOVE_BIT_AR(AFF_FLAGS(ch), AFF_SPELLBATTLE); SPELLBATTLE(ch) = 0; wildshape_return(ch); + GET_LAST_ROOM(ch) = 0; } /* clear grapple */ @@ -2449,7 +2451,7 @@ static void solo_gain(struct char_data *ch, struct char_data *victim) /* minimum of 1 xp point */ exp = MAX(exp, 1); -#if defined(CAMAPIGN_DL) +#if defined(CAMPAIGN_DL) if (GET_LEVEL(victim) < 18) if ((GET_LEVEL(victim) + CONFIG_EXP_LEVEL_DIFFERENCE) < GET_LEVEL(ch)) exp /= 2; @@ -3594,6 +3596,8 @@ int compute_damtype_reduction(struct char_data *ch, int dam_type) damtype_reduction += 25; if (HAS_FEAT(ch, FEAT_STOUT_RESILIENCE)) damtype_reduction += 50; + if (HAS_FEAT(ch, FEAT_GRUBBY)) + damtype_reduction += 50; if (HAS_REAL_FEAT(ch, FEAT_ESSENCE_OF_UNDEATH)) damtype_reduction += 100; if (HAS_EVOLUTION(ch, EVOLUTION_UNDEAD_APPEARANCE)) @@ -3644,6 +3648,8 @@ int compute_damtype_reduction(struct char_data *ch, int dam_type) damtype_reduction += 10; if (HAS_FEAT(ch, FEAT_STRONG_AGAINST_DISEASE)) damtype_reduction += 50; + if (HAS_FEAT(ch, FEAT_GRUBBY)) + damtype_reduction += 50; /* npc vulnerabilities/strengths */ if (IS_NPC(ch)) @@ -8607,7 +8613,7 @@ int compute_attack_bonus_full(struct char_data *ch, /* Attacker */ /* Profane bonus */ /* Racial bonus */ -#if !defined(CAMAPIGN_DL) && !defined(CAMPAIGN_FR) +#if !defined(CAMPAIGN_DL) && !defined(CAMPAIGN_FR) if (GET_RACE(ch) == RACE_TRELUX) { bonuses[BONUS_TYPE_RACIAL] += 4; diff --git a/handler.c b/handler.c index 62dd961a..3ca8c6a9 100755 --- a/handler.c +++ b/handler.c @@ -342,6 +342,7 @@ void aff_apply_modify(struct char_data *ch, byte loc, sh_int mod, const char *ms case APPLY_SPELL_POTENCY: case APPLY_SPELL_DC: case APPLY_SPELL_DURATION: + case APPLY_SPELL_PENETRATION: break; /* end Do Not Use */ diff --git a/interpreter.c b/interpreter.c index df767bf3..218fa36c 100755 --- a/interpreter.c +++ b/interpreter.c @@ -221,7 +221,7 @@ cpp_extern const struct command_info cmd_info[] = { {"blank", "blank", POS_RECLINING, do_consign_to_oblivion, 0, SCMD_BLANK, FALSE, ACTION_NONE, {0, 0}, NULL}, {"blooddrain", "blooddrain", POS_RESTING, do_blood_drain, 0, 0, FALSE, ACTION_STANDARD, {0, 0}, NULL}, {"bombs", "bombs", POS_RESTING, do_bombs, 0, 0, FALSE, ACTION_STANDARD, {0, 0}, NULL}, - {"bonearmor", "bonearmor", POS_STANDING, do_not_here, 1, 0, FALSE, ACTION_NONE, {0, 0}, NULL}, + {"bonearmor", "bonearmor", POS_STANDING, do_need_craft_kit, 1, 0, FALSE, ACTION_NONE, {0, 0}, NULL}, {"boosts", "boost", POS_RECLINING, do_boosts, 1, 0, FALSE, ACTION_NONE, {0, 0}, NULL}, {"buck", "buck", POS_FIGHTING, do_buck, 1, 0, FALSE, ACTION_MOVE, {0, 6}, NULL}, {"bodyslam", "bodyslam", POS_FIGHTING, do_bodyslam, 1, 0, FALSE, ACTION_STANDARD | ACTION_MOVE, {6, 6}, can_bodyslam}, @@ -541,6 +541,7 @@ cpp_extern const struct command_info cmd_info[] = { {"levels", "lev", POS_DEAD, do_levels, 0, 0, TRUE, ACTION_NONE, {0, 0}, NULL}, {"lifebond", "lifebond", POS_STANDING, do_gen_tog, 1, SCMD_LIFE_BOND, FALSE, ACTION_NONE, {0, 0}, NULL}, {"listen", "listen", POS_STANDING, do_listen, 1, 0, FALSE, ACTION_NONE, {0, 0}, NULL}, + {"listraces", "listraces", POS_DEAD, do_listraces, 1, 0, FALSE, ACTION_NONE, {0, 0}, NULL}, {"links", "lin", POS_STANDING, do_links, LVL_IMMORT, 0, TRUE, ACTION_NONE, {0, 0}, NULL}, {"lock", "loc", POS_SITTING, do_gen_door, 0, SCMD_LOCK, FALSE, ACTION_NONE, {0, 0}, NULL}, {"load", "load", POS_DEAD, do_load, LVL_BUILDER, 0, TRUE, ACTION_NONE, {0, 0}, NULL}, @@ -749,6 +750,7 @@ cpp_extern const struct command_info cmd_info[] = { {"scan", "sca", POS_RECLINING, do_scan, 0, 0, FALSE, ACTION_NONE, {0, 0}, NULL}, {"scopy", "scopy", POS_DEAD, do_oasis_copy, LVL_STAFF, CON_SEDIT, TRUE, ACTION_NONE, {0, 0}, NULL}, {"scribe", "scribe", POS_RESTING, do_scribe, 0, 0, FALSE, ACTION_NONE, {0, 0}, NULL}, + {"scrounge", "scrounge", POS_STANDING, do_scrounge, 0, 0, FALSE, ACTION_NONE, {0, 0}, NULL}, {"sit", "si", POS_RECLINING, do_sit, 0, 0, FALSE, ACTION_NONE, {0, 0}, NULL}, {"'", "'", POS_RECLINING, do_say, 0, 0, TRUE, ACTION_NONE, {0, 0}, NULL}, {"save", "sav", POS_SLEEPING, do_save, 0, 0, TRUE, ACTION_NONE, {0, 0}, NULL}, diff --git a/limits.c b/limits.c index f508b303..0b97e4e8 100755 --- a/limits.c +++ b/limits.c @@ -1609,6 +1609,15 @@ void update_player_misc(void) } } + if (GET_SCROUNGE_COOLDOWN(ch) > 0) + { + GET_SCROUNGE_COOLDOWN(ch)--; + if (GET_SCROUNGE_COOLDOWN(ch) == 0) + { + send_to_char(ch, "You can now scrounge for supplies again.\r\n"); + } + } + if (IN_ROOM(ch) == 0 || IN_ROOM(ch) == NOWHERE || GET_ROOM_VNUM(IN_ROOM(ch)) == CONFIG_MORTAL_START || GET_ROOM_VNUM(IN_ROOM(ch)) == CONFIG_IMMORTAL_START) ; else diff --git a/magic.c b/magic.c index 90dd5258..32218b56 100755 --- a/magic.c +++ b/magic.c @@ -166,6 +166,7 @@ int mag_resistance(struct char_data *ch, struct char_data *vict, int modifier) challenge += 3; if (!IS_NPC(ch) && HAS_FEAT(ch, FEAT_EPIC_SPELL_PENETRATION)) challenge += 4; + challenge += get_spell_penetration_bonus(ch); if (!IS_NPC(ch) && CLASS_LEVEL(ch, CLASS_SPELLSWORD) > 0 && WEAPON_SPELL_PROC(ch) == TRUE) { @@ -322,6 +323,10 @@ int mag_savingthrow_full(struct char_data *ch, struct char_data *vict, case CAST_INNATE: case CAST_WEAPON_SPELL: challenge += level; + if (HAS_FEAT(vict, FEAT_SPELL_HARDINESS)) + savethrow += 2; + if (HAS_FEAT(vict, FEAT_STRONG_SPELL_HARDINESS)) + savethrow += 4; break; case CAST_WEAPON_POISON: challenge += level; @@ -5995,6 +6000,7 @@ void mag_affects_full(int level, struct char_data *ch, struct char_data *victim, send_to_char(ch, "It seems your opponent is not susceptible to disease.\r\n"); return; } + if (HAS_FEAT(victim, FEAT_GRUBBY)) GET_DC_BONUS(ch) -= 4; switch (rand_number(1, 7)) { case 1: // blinding sickness @@ -6374,6 +6380,7 @@ void mag_affects_full(int level, struct char_data *ch, struct char_data *victim, send_to_char(ch, "It seems your opponent is not susceptible to disease.\r\n"); return; } + if (HAS_FEAT(victim, FEAT_GRUBBY)) GET_DC_BONUS(ch) -= 4; if (mag_resistance(ch, victim, 0)) return; if (HAS_EVOLUTION(victim, EVOLUTION_UNDEAD_APPEARANCE) || HAS_EVOLUTION(victim, EVOLUTION_CELESTIAL_APPEARANCE)) @@ -8689,8 +8696,10 @@ void mag_affects_full(int level, struct char_data *ch, struct char_data *victim, } for (i = 0; i < MAX_SPELL_AFFECTS; i++) { - af[i].duration = af[i].duration * get_spell_duration_bonus(ch) / 100; - af[i].modifier = af[i].modifier * get_spell_potency_bonus(ch) / 100; + if (af[i].duration > 0) + af[i].duration = af[i].duration * get_spell_duration_bonus(ch) / 100; + if (af[i].modifier > 0) + af[i].modifier = af[i].modifier * get_spell_potency_bonus(ch) / 100; } } diff --git a/mobact.c b/mobact.c index f5f2e870..b9511654 100755 --- a/mobact.c +++ b/mobact.c @@ -1727,6 +1727,8 @@ void mobile_activity(void) { continue; } + if (HAS_FEAT(ch, FEAT_COWARDLY) && dice(1, 4) < 4) + continue; if (MOB_FLAGGED(ch, MOB_ENCOUNTER) && ((GET_LEVEL(ch) - GET_LEVEL(vict)) < 2)) { // We don't want abandoned random encounters killing people they weren't meant for diff --git a/players.c b/players.c index 5f6e30b9..7fd86d4c 100755 --- a/players.c +++ b/players.c @@ -462,6 +462,7 @@ int load_char(const char *name, struct char_data *ch) GET_DRAGON_RIDER_DRAGON_TYPE(ch) = 0; GET_FORAGE_COOLDOWN(ch) = 0; GET_RETAINER_COOLDOWN(ch) = 0; + GET_SCROUNGE_COOLDOWN(ch) = 0; for (i = 0; i < MAX_CURRENT_QUESTS; i++) { /* loop through all the character's quest slots */ @@ -1242,6 +1243,8 @@ int load_char(const char *name, struct char_data *ch) } else if (!strcmp(tag, "Scrl")) load_scrolls(fl, ch); + else if (!strcmp(tag, "Scrg")) + GET_SCROUNGE_COOLDOWN(ch) = atoi(line); else if (!strcmp(tag, "ScrW")) GET_SCREEN_WIDTH(ch) = atoi(line); else if (!strcmp(tag, "Skil")) @@ -1861,6 +1864,8 @@ void save_char(struct char_data *ch, int mode) fprintf(fl, "EidC: %d\n", CALL_EIDOLON_COOLDOWN(ch)); if (GET_FORAGE_COOLDOWN(ch) != 0) fprintf(fl, "FrgC: %d\n", GET_FORAGE_COOLDOWN(ch)); + if (GET_SCROUNGE_COOLDOWN(ch) != 0) + fprintf(fl, "Scrg: %d\n", GET_SCROUNGE_COOLDOWN(ch)); if (GET_RETAINER_COOLDOWN(ch) != 0) fprintf(fl, "RetC: %d\n", GET_RETAINER_COOLDOWN(ch)); fprintf(fl, "God : %d\n", GET_DEITY(ch)); diff --git a/race.c b/race.c index 85abc0fa..a243693f 100755 --- a/race.c +++ b/race.c @@ -21,6 +21,9 @@ #include "race.h" #include "feats.h" #include "class.h" +#include "backgrounds.h" +#include "treasure.h" +#include "spec_procs.h" /* defines */ #define Y TRUE @@ -31,7 +34,9 @@ #define IS_EPIC_R 2 /* some pre setup here */ + struct race_data race_list[NUM_EXTENDED_RACES]; +int race_sort_info[NUM_EXTENDED_RACES+1]; /* Zusuk, 02/2016: Start notes here! * RACE_ these are specific race defines, eventually should be a massive list @@ -140,7 +145,7 @@ void initialize_races(void) for (i = 0; i < NUM_EXTENDED_RACES; i++) { /* displaying the race */ - race_list[i].name = NULL; + race_list[i].name = "unknown"; race_list[i].type = NULL; race_list[i].type_color = NULL; race_list[i].abbrev = NULL; @@ -731,7 +736,7 @@ void assign_races(void) /****************************************************************************/ /****************************************************************************/ /* simple-name, no-color-name, color-name, abbrev, color-abbrev*/ - add_race(DL_RACE_KENDER, "Kender", "Kender", "\tCKender\tn", "Kend", "\tCKend\tn", + add_race(DL_RACE_KENDER, "kender", "Kender", "\tCKender\tn", "Kend", "\tCKend\tn", /* race-family, size-class, Is PC?, Lvl-Adj, Unlock, Epic? */ RACE_TYPE_HUMANOID, SIZE_SMALL, TRUE, 0, 0, IS_NORMAL); set_race_details(DL_RACE_KENDER, @@ -884,6 +889,55 @@ void assign_races(void) feat_race_assignment(DL_RACE_HILL_DWARF, FEAT_DWARVEN_WEAPON_PROFICIENCY, 1, N); race_list[DL_RACE_HILL_DWARF].racial_language = SKILL_LANG_DWARVEN; + /****************************************************************************/ + /****************************************************************************/ + /* simple-name, no-color-name, color-name, abbrev, color-abbrev*/ + add_race(DL_RACE_GULLY_DWARF, "gully dwarf", "Gully Dwarf", "\tLGully Dwarf\tn", "GuDw", "\tLGuDw\tn", + /* race-family, size-class, Is PC?, Lvl-Adj, Unlock, Epic? */ + RACE_TYPE_HUMANOID, SIZE_SMALL, TRUE, 0, 0, IS_NORMAL); + set_race_details(DL_RACE_GULLY_DWARF, + // desc + "The Aghar ('Anguished'), or gully dwarves as most " + "races call them, are a misbegotten race of tough " + "survivors. Though gully dwarves themselves have " + "an extensive oral tradition (they love telling stories), " + "no two gully dwarf clans ever agree on the " + "exact details of their origins or history. The commonly " + "accepted tale of how gully dwarves came " + "to be is found within the annals of Astinus’s " + "Iconochronos. According to the Iconochronos, gully " + "dwarves are the result of breeding between " + "gnomes and dwarves in the years following the " + "transformation of the gnomes by the Graygem of " + "Gargath. The gnome-dwarf half-breeds appeared " + "to inherit the worst qualities of both races. The " + "unfortunate half-breeds were driven out of their " + "clans. Humans later christened them 'gully " + "dwarves,' reflecting their lowly status and poor " + "living conditions. ", + /*morph to-char*/ "Your body twists and contorts painfully until your form becomes a Hill Dwarf.", + /*morph to-room*/ "$n's body twists and contorts painfully until $s form becomes a Hill Dwarf."); + set_race_genders(DL_RACE_GULLY_DWARF, N, Y, Y); /* n m f */ + set_race_abilities(DL_RACE_GULLY_DWARF, 0, 4, -4, 0, 4, -4); /* str con int wis dex cha */ + set_race_alignments(DL_RACE_GULLY_DWARF, Y, Y, Y, Y, Y, Y, Y, Y, Y); /* law-good -> cha-evil */ + set_race_attack_types(DL_RACE_GULLY_DWARF, + /* hit sting whip slash bite bludgeon crush pound claw maul thrash pierce */ + Y, N, N, N, N, N, N, N, N, N, N, N, + /* blast punch stab slice thrust hack rake peck smash trample charge gore */ + N, Y, N, N, N, N, N, N, N, N, N, N); + /* feat assignment */ + /* race-num feat lvl stack */ + feat_race_assignment(DL_RACE_GULLY_DWARF, FEAT_ULTRAVISION, 1, N); + feat_race_assignment(DL_RACE_GULLY_DWARF, FEAT_POISON_RESIST, 1, N); + feat_race_assignment(DL_RACE_GULLY_DWARF, FEAT_STABILITY, 1, N); + feat_race_assignment(DL_RACE_GULLY_DWARF, FEAT_SPELL_HARDINESS, 1, N); + feat_race_assignment(DL_RACE_GULLY_DWARF, FEAT_SURVIVAL_INSTINCT, 1, N); + feat_race_assignment(DL_RACE_GULLY_DWARF, FEAT_PITIABLE, 1, N); + feat_race_assignment(DL_RACE_GULLY_DWARF, FEAT_COWARDLY, 1, N); + feat_race_assignment(DL_RACE_GULLY_DWARF, FEAT_GRUBBY, 1, N); + feat_race_assignment(DL_RACE_GULLY_DWARF, FEAT_GULLY_DWARF_RACIAL_ADJUSTMENT, 1, N); + race_list[DL_RACE_GULLY_DWARF].racial_language = SKILL_LANG_GULLYTALK; + /****************************************************************************/ /****************************************************************************/ /* simple-name, no-color-name, color-name, abbrev, color-abbrev*/ @@ -4664,9 +4718,9 @@ int parse_race_long(const char *arg_in) if (is_abbrev(arg, "hill dwarf")) return DL_RACE_HILL_DWARF; if (is_abbrev(arg, "hill-dwarf")) return DL_RACE_HILL_DWARF; if (is_abbrev(arg, "hilldwarf")) return DL_RACE_HILL_DWARF; - // if (is_abbrev(arg, "gully dwarf")) return DL_RACE_GULLY_DWARF; - // if (is_abbrev(arg, "gully-dwarf")) return DL_RACE_GULLY_DWARF; - // if (is_abbrev(arg, "gullydwarf")) return DL_RACE_GULLY_DWARF; + if (is_abbrev(arg, "gully dwarf")) return DL_RACE_GULLY_DWARF; + if (is_abbrev(arg, "gully-dwarf")) return DL_RACE_GULLY_DWARF; + if (is_abbrev(arg, "gullydwarf")) return DL_RACE_GULLY_DWARF; if (is_abbrev(arg, "minotaur")) return DL_RACE_MINOTAUR; if (is_abbrev(arg, "kender")) return DL_RACE_KENDER; if (is_abbrev(arg, "gnome")) return DL_RACE_GNOME; @@ -5291,6 +5345,222 @@ bool race_has_no_hair(int race) return false; } +int compare_races(const void *x, const void *y) +{ + int a = *(const int *)x, + b = *(const int *)y; + + return strcmp(race_list[a].name, race_list[b].name); +} + +/* sort feats called at boot up */ +void sort_races(void) +{ + int a; + + /* initialize array, avoiding reserved. */ + for (a = 0; a < NUM_EXTENDED_RACES; a++) + race_sort_info[a] = a; + + qsort(&race_sort_info[0], NUM_EXTENDED_RACES, sizeof(int), compare_races); + +} + +ACMD(do_listraces) +{ + int i, sortpos; + + send_to_char(ch, "\r\n"); + draw_line(ch, 80, '-', '-'); + text_line(ch, "Races of Krynn", 80, '-', '-'); + draw_line(ch, 80, '-', '-'); + for (sortpos = 0; sortpos < NUM_EXTENDED_RACES; sortpos++) + { + i = race_sort_info[sortpos]; + if (race_list[i].is_pc) + { + send_to_char(ch, " %4.4s - %s\r\n", race_list[i].abbrev, race_list[i].type); + } + } + send_to_char(ch, "\r\n"); + draw_line(ch, 80, '-', '-'); +} + +// awards a random food item. +// result is the result of a skill check vs. a dc +// type determines the output message given +// 1 is forage, 2 is scrounge +void award_random_food_item(struct char_data *ch, int result, int type) +{ + + bool food = false; + char ripeness[50], food_desc[150]; + struct obj_data *obj; + int modifier = 2, bonus = 0; + + result /= 10; + + switch (result) + { + case 0: modifier = 2; snprintf(ripeness, sizeof(ripeness), "rather unripe"); break; + case 1: modifier = 3; snprintf(ripeness, sizeof(ripeness), "barely ripe"); break; + case 2: modifier = 4; snprintf(ripeness, sizeof(ripeness), "nicely ripened"); break; + case 3: modifier = 5; snprintf(ripeness, sizeof(ripeness), "very well ripened"); break; + default: modifier = 6; snprintf(ripeness, sizeof(ripeness), "perfectly ripened"); break; + } + + switch (rand_number(0, 18)) + { + case 0: bonus = APPLY_AC_NEW; break; + case 1: bonus = APPLY_STR; break; + case 2: bonus = APPLY_DEX; break; + case 3: bonus = APPLY_CON; break; + case 4: bonus = APPLY_INT; break; + case 5: bonus = APPLY_WIS; break; + case 6: bonus = APPLY_CHA; break; + case 7: bonus = APPLY_DAMROLL; modifier /= 2; break; + case 8: bonus = APPLY_HITROLL; modifier /= 2; break; + case 9: bonus = APPLY_ENCUMBRANCE; break; + case 10: bonus = APPLY_HIT; modifier *= 10; break; + case 11: bonus = APPLY_MOVE; modifier *= 100; break; + case 12: bonus = APPLY_HP_REGEN; break; + case 13: bonus = APPLY_MV_REGEN; break; + case 14: bonus = APPLY_PSP; modifier *= 5; break; + case 15: bonus = APPLY_PSP_REGEN; break; + case 16: bonus = APPLY_SAVING_FORT; break; + case 17: bonus = APPLY_SAVING_REFL; break; + case 18: bonus = APPLY_SAVING_WILL; break; + } + + obj = read_object(FORAGE_FOOD_ITEM_VNUM, VIRTUAL); + + if (!obj) + { + send_to_char(ch, "The forage food item prototype was not found. Please inform a staff with code ERRFOR00%d.\r\n", type); + return; + } + + GET_FORAGE_COOLDOWN(ch) = 100; + + food = apply_type_food_or_drink[bonus]; + + if (!food) + GET_OBJ_TYPE(obj) = ITEM_DRINK; + + obj->affected[0].location = bonus; + obj->affected[0].modifier = modifier; + obj->affected[0].bonus_type = (food) ? BONUS_TYPE_FOOD : BONUS_TYPE_DRINK; + + snprintf(food_desc, sizeof(food_desc), "some %s %s", ripeness, apply_type_food_names[bonus]); + obj->name = strdup(food_desc); + obj->short_description = strdup(food_desc); + snprintf(food_desc, sizeof(food_desc), "Some %s %s lie here.", ripeness, apply_type_food_names[bonus]); + obj->description = strdup(food_desc); + + obj_to_char(obj, ch); + + if (type == 1) + { + act("You forage for food and find $p!", TRUE, ch, obj, 0, TO_CHAR); + act("$n forages for food and finds $p!", TRUE, ch, obj, 0, TO_ROOM); + } + else if (type == 2) + { + act("You scrounge for supplies and find $p!", TRUE, ch, obj, 0, TO_CHAR); + act("$n scrounges for supplies and finds $p!", TRUE, ch, obj, 0, TO_ROOM); + } +} + +ACMD(do_scrounge) +{ + + int skill, dc, result, roll, scrounge, grade, amount; + + if (IS_NPC(ch)) + { + send_to_char(ch, "NPCs cannot scrounge.\r\n"); + return; + } + + if (!HAS_FEAT(ch, FEAT_SURVIVAL_INSTINCT)) + { + send_to_char(ch, "You don't know how to scrounge.\r\n"); + return; + } + + if (GET_SCROUNGE_COOLDOWN(ch) > 0) + { + send_to_char(ch, "You've recently scrounged for supplies and will have to wait.\r\n"); + return; + } + + skill = compute_ability(ch, ABILITY_NATURE); + dc = 15; + roll = d20(ch); + result = roll + skill - dc; + + send_to_char(ch, "You attempt to scrounge for supplies... Roll %d + %d (nature skill) for total %d vs. dc %d\r\n", + roll, skill, roll + skill, dc); + + if (result < 0) + { + send_to_char(ch, "You fail to find anything of use.\r\n"); + GET_SCROUNGE_COOLDOWN(ch) = 100; + return; + } + + grade = result / 10; + + grade = MAX(GRADE_TYPICAL, grade); + grade = MIN(GRADE_SUPERIOR, grade); + + scrounge = dice(1, 20); + + act("You scrounge the area for useful supplies.", TRUE, ch, 0, 0, TO_CHAR); + act("$n scrounges the area for useful supplies.", TRUE, ch, 0, 0, TO_ROOM); + + ch->char_specials.which_treasure_message = CUSTOM_TREASURE_MESSAGE_SCROUNGE; + switch (scrounge) + { + case 1: // weapon + award_magic_weapon(ch, grade); + break; + case 2: // armor + switch (dice(1, 5)) + { + case 1: award_magic_armor(ch, grade, ITEM_WEAR_BODY); break; + case 2: award_magic_armor(ch, grade, ITEM_WEAR_ARMS); break; + case 3: award_magic_armor(ch, grade, ITEM_WEAR_LEGS); break; + case 4: award_magic_armor(ch, grade, ITEM_WEAR_HEAD); break; + case 5: award_magic_armor(ch, grade, ITEM_WEAR_SHIELD); break; + } + break; + case 3: // misc + award_misc_magic_item(ch, dice(1, 9), grade); + break; + case 4: // consumable + case 5: // consumable + case 6: // consumable + award_expendable_item(ch, grade, dice(1, 2)); + break; + case 7: // food/drink + case 8: // food/drink + case 9: // food/drink + award_random_food_item(ch, result, 2); + break; + case 10: // gold + case 11: // gold + case 12: // gold + amount = award_random_money(ch, result); + send_to_char(ch, "You find a pouch containing %d gold coins.\r\n", amount); + break; + default: // nada + send_to_char(ch, "Your scrounging uncovered nothing of use.\r\n"); + break; + } + ch->char_specials.which_treasure_message = 0; +} + /* int get_size(struct char_data *ch) { int racenum; diff --git a/race.h b/race.h index 916080ca..1bc49ac4 100755 --- a/race.h +++ b/race.h @@ -59,9 +59,13 @@ bool has_scales(int race); bool has_horns(int race); bool is_furry(int race); bool race_has_no_hair(int race); +int compare_races(const void *x, const void *y); +void sort_races(void); /* ACMD */ ACMD_DECL(do_race); +ACMD_DECL(do_listraces); +ACMD_DECL(do_scrounge); /* Global variables */ diff --git a/spec_procs.c b/spec_procs.c index 4a329cbc..22eec4a9 100755 --- a/spec_procs.c +++ b/spec_procs.c @@ -1020,6 +1020,7 @@ int compute_ability_full(struct char_data *ch, int abilityNum, bool recursive) case ABILITY_STEALTH: value += GET_DEX_BONUS(ch); if (HAS_FEAT(ch, FEAT_KENDER_SKILL_MOD)) value += 2; + if (HAS_FEAT(ch, FEAT_SURVIVAL_INSTINCT)) value += 3; if (HAS_FEAT(ch, FEAT_AFFINITY_MOVE_SILENT)) value += 4; if (HAS_FEAT(ch, FEAT_STEALTHY)) @@ -1202,6 +1203,7 @@ int compute_ability_full(struct char_data *ch, int abilityNum, bool recursive) return value; case ABILITY_APPRAISE: value += GET_INT_BONUS(ch); + if (HAS_FEAT(ch, FEAT_GRUBBY)) value -= 6; if (HAS_FEAT(ch, FEAT_DILIGENT)) { /* Unnamed bonus */ @@ -1288,6 +1290,7 @@ int compute_ability_full(struct char_data *ch, int abilityNum, bool recursive) return value; case ABILITY_DIPLOMACY: value += GET_CHA_BONUS(ch); + if (HAS_FEAT(ch, FEAT_GRUBBY)) value -= 6; if (HAS_FEAT(ch, FEAT_NEGOTIATOR)) { /* Unnamed bonus */ @@ -1356,6 +1359,7 @@ int compute_ability_full(struct char_data *ch, int abilityNum, bool recursive) return value; case ABILITY_SURVIVAL: value += GET_WIS_BONUS(ch); + if (HAS_FEAT(ch, FEAT_SURVIVAL_INSTINCT)) value += 3; if (HAS_FEAT(ch, FEAT_SELF_SUFFICIENT)) { /* Unnamed bonus */ diff --git a/structs.h b/structs.h index 69113930..a9916cea 100755 --- a/structs.h +++ b/structs.h @@ -2819,12 +2819,17 @@ #define FEAT_DEAFENING_SONG 1232 #define FEAT_OVERWHELMING_CRITICAL 1233 #define FEAT_DEVASTATING_CRITICAL 1234 +#define FEAT_SURVIVAL_INSTINCT 1235 +#define FEAT_PITIABLE 1236 +#define FEAT_COWARDLY 1237 +#define FEAT_GULLY_DWARF_RACIAL_ADJUSTMENT 1238 +#define FEAT_GRUBBY 1239 /**************/ /** reserved above feat# + 1**/ -#define FEAT_LAST_FEAT 1235 +#define FEAT_LAST_FEAT 1240 /** FEAT_LAST_FEAT + 1 ***/ -#define NUM_FEATS 1236 +#define NUM_FEATS 1241 /** absolute cap **/ #define MAX_FEATS 1500 /*****/ @@ -3358,10 +3363,11 @@ #define APPLY_SPELL_POTENCY 70 #define APPLY_SPELL_DC 71 #define APPLY_SPELL_DURATION 72 +#define APPLY_SPELL_PENETRATION 73 /** Total number of applies */ -#define NUM_APPLIES 73 +#define NUM_APPLIES 74 // maximum number of spells/powers to buff #define MAX_BUFFS 40 @@ -4964,6 +4970,7 @@ struct player_special_data_saved int forage_cooldown; int retainer_cooldown; + int scrounge_cooldown; int character_age; bool character_age_saved; diff --git a/treasure.c b/treasure.c index eca07f8b..57c879f0 100644 --- a/treasure.c +++ b/treasure.c @@ -213,6 +213,13 @@ void say_treasure(struct char_data *ch, struct obj_data *obj) send_to_char(ch, "\tYYour extortion victim also hands you %s!\tn\r\n", obj->short_description); } } + else if (ch->char_specials.which_treasure_message == CUSTOM_TREASURE_MESSAGE_SCROUNGE) + { + if (ch && obj && obj->short_description) + { + send_to_char(ch, "\tYYou scrounge the area for useful items and come across %s!\tn\r\n", obj->short_description); + } + } else if (ch && obj && obj->short_description) { send_to_char(ch, "\tYYou have found %s\tn\tY in a nearby lair (random treasure drop)!\tn\r\n", obj->short_description); @@ -695,7 +702,7 @@ int adjust_bonus_value(int apply_location, int bonus) case APPLY_MOVE: adjusted_bonus = bonus * 120; break; - case APPLY_MOVE_REGEN: + case APPLY_MV_REGEN: adjusted_bonus = bonus * 10; break; case APPLY_SPELL_DC: @@ -709,6 +716,7 @@ int adjust_bonus_value(int apply_location, int bonus) case APPLY_SPELL_CIRCLE_8: case APPLY_SPELL_CIRCLE_9: case APPLY_FAST_HEALING: + case APPLY_SPELL_PENETRATION: adjusted_bonus = bonus / 2; break; case APPLY_RES_FIRE: @@ -945,7 +953,7 @@ int random_apply_value(void) * for example weapons will get hit/dam bonus (the +) and armor will get * ac_apply_new bonus (the +). */ #if defined (CAMPAIGN_DL) - switch (dice(1, 23)) + switch (dice(1, 24)) #else switch (dice(1, 12)) #endif @@ -1017,6 +1025,9 @@ int random_apply_value(void) case 22: val = APPLY_SKILL; break; + case 23: + val = APPLY_SPELL_PENETRATION; + break; #endif default: switch (rand_number(1, 20)) @@ -4598,6 +4609,15 @@ bool proper_feat(struct obj_data *obj, int feat_num) return true; } +int award_random_money(struct char_data *ch, int result) +{ + int amount = MAX(1, dice(1, result * 10)); + + increase_gold(ch, amount); + + return amount; +} + const char *kender_loot[NUM_KENDER_BAUBLES] = { "" // 0 diff --git a/treasure.h b/treasure.h index 06a5d155..73a27fad 100644 --- a/treasure.h +++ b/treasure.h @@ -390,6 +390,7 @@ #define CUSTOM_TREASURE_MESSAGE_PERFORM 3 #define CUSTOM_TREASURE_MESSAGE_TRIBUTE 4 #define CUSTOM_TREASURE_MESSAGE_EXTORTION 5 +#define CUSTOM_TREASURE_MESSAGE_SCROUNGE 6 /* treasure_const.c - list of constant arrays */ extern const char *gemstones[NUM_A_GEMSTONES + 1]; @@ -491,6 +492,9 @@ int determine_rnd_misc_cat(); int cp_convert_grade_enchantment(int grade); /* given a level, determine a random appropriate grade */ int quick_grade_check(int level); +int increase_gold(struct char_data *ch, int amt); +int award_random_money(struct char_data *ch, int result); +void award_random_food_item(struct char_data *ch, int result, int type); // staff tool to load random items ACMD_DECL(do_loadmagic); diff --git a/utils.c b/utils.c index 90897688..6ea384eb 100755 --- a/utils.c +++ b/utils.c @@ -6496,6 +6496,9 @@ bool can_flee_speed(struct char_data *ch) if (HAS_REAL_FEAT(ch, FEAT_NIMBLE_ESCAPE)) return true; + + if (HAS_FEAT(ch, FEAT_COWARDLY)) + return true; struct char_data *tch = NULL; @@ -8395,6 +8398,7 @@ void clear_misc_cooldowns(struct char_data *ch) INCORPOREAL_FORM_TIMER(ch) = 0; GET_MISSION_COOLDOWN(ch) = 0; GET_FORAGE_COOLDOWN(ch) = 0; + GET_SCROUNGE_COOLDOWN(ch) = 0; } bool can_mastermind_power(struct char_data *ch, int spellnum) @@ -9814,7 +9818,7 @@ bool is_valid_apply_location_and_circle(int apply, int circle) int get_bonus_spells_by_circle_and_class(struct char_data *ch, int ch_class, int circle) { if (!ch || IS_NPC(ch) || !ch->desc) - return; + return 0; int i = 0, j = 0; int bonus_circles = 0; @@ -9823,7 +9827,6 @@ int get_bonus_spells_by_circle_and_class(struct char_data *ch, int ch_class, int int max_val_worn_slot[NUM_BONUS_TYPES]; struct obj_data *obj = NULL; struct affected_type *aff = NULL; - char affect_buf[2400], gear_buf[2400], temp_buf[200]; for (i = 0; i < NUM_BONUS_TYPES; i++) { @@ -9904,7 +9907,7 @@ int get_bonus_spells_by_circle_and_class(struct char_data *ch, int ch_class, int int get_spell_potency_bonus(struct char_data *ch) { if (!ch || IS_NPC(ch) || !ch->desc) - return; + return 100; int i = 0, j = 0; int potency_bonus = 100; @@ -9993,7 +9996,7 @@ int get_spell_potency_bonus(struct char_data *ch) int get_spell_dc_bonus(struct char_data *ch) { if (!ch || IS_NPC(ch) || !ch->desc) - return; + return 0; int i = 0, j = 0; int dc_bonus = 0; @@ -10079,10 +10082,99 @@ int get_spell_dc_bonus(struct char_data *ch) return dc_bonus; } +int get_spell_penetration_bonus(struct char_data *ch) +{ + if (!ch || IS_NPC(ch) || !ch->desc) + return 0; + + int i = 0, j = 0; + int penetration_bonus = 0; + int max_value[NUM_BONUS_TYPES]; + int max_val_spell[NUM_BONUS_TYPES]; + int max_val_worn_slot[NUM_BONUS_TYPES]; + struct obj_data *obj = NULL; + struct affected_type *aff = NULL; + + for (i = 0; i < NUM_BONUS_TYPES; i++) + { + max_value[i] = 0; + max_val_spell[i] = -1; + max_val_worn_slot[i] = -1; + } + + // We'll do spells then gear. We want to make sure that bonus + // types don't stack + + // spells + for (aff = ch->affected; aff; aff = aff->next) + { + if (aff->location == APPLY_SPELL_PENETRATION) + { + // some bonus types always stack, so we'll just add this right on now + if (BONUS_TYPE_STACKS(aff->bonus_type)) + { + penetration_bonus += aff->modifier; + } + // penalties and debuffs are always applied + else if (aff->modifier < 0) + { + penetration_bonus -= aff->modifier; + } + // we only want the maximum per bonus type + else if (aff->modifier > max_value[aff->bonus_type]) + { + max_value[aff->bonus_type] = aff->modifier; + max_val_spell[aff->bonus_type] = aff->spell; + max_val_worn_slot[aff->bonus_type] = -1; + } + } + } + + // gear + for (i = 0; i < NUM_WEARS; i++) + { + if (!(obj = GET_EQ(ch, i))) + continue; + for (j = 0; j < MAX_OBJ_AFFECT; j++) + { + if (obj->affected[j].location == APPLY_SPELL_PENETRATION) + { + // some bonus types always stack, so we'll just add this right on now + if (BONUS_TYPE_STACKS(obj->affected[j].bonus_type)) + { + penetration_bonus += obj->affected[j].modifier; + } + // penalties and debuffs are always applied + else if (obj->affected[j].modifier < 0) + { + penetration_bonus -= obj->affected[j].modifier; + } + // we only want the maximum per bonus type + else if (obj->affected->modifier > max_value[obj->affected[j].bonus_type]) + { + max_value[obj->affected[j].bonus_type] = obj->affected[j].modifier; + max_val_spell[obj->affected[j].bonus_type] = -1; + max_val_worn_slot[obj->affected[j].bonus_type] = i; + } + } + } + } + + // now let's add up all of the highest per bonus type from spells and gear + for (i = 0; i < NUM_BONUS_TYPES; i++) + { + if (BONUS_TYPE_STACKS(i)) + continue; + penetration_bonus += max_value[i]; + } + + return penetration_bonus; +} + int get_spell_duration_bonus(struct char_data *ch) { if (!ch || IS_NPC(ch) || !ch->desc) - return; + return 100; int i = 0, j = 0; int duration_bonus = 100; @@ -10165,7 +10257,7 @@ int get_spell_duration_bonus(struct char_data *ch) duration_bonus += max_value[i]; } - return duration_bonus; + return MAX(100, duration_bonus); } int get_random_spellcaster_class(void) diff --git a/utils.h b/utils.h index 8fbb73c6..b09ab7db 100755 --- a/utils.h +++ b/utils.h @@ -127,6 +127,7 @@ bool has_devastating_critical_prereqs(struct char_data *ch, struct obj_data *wie bool can_silence(struct char_data *ch); bool can_daze(struct char_data *ch); bool is_random_chest_in_room(room_rnum rrnum); +int get_spell_penetration_bonus(struct char_data *ch); int get_random_chest_item_level(int level); int get_chest_contents_type(void); bool is_wearing_metal(struct char_data *ch); @@ -2664,6 +2665,7 @@ bool has_reach(struct char_data *ch); #define GET_FORAGE_COOLDOWN(ch) (ch->player_specials->saved.forage_cooldown) #define GET_RETAINER_COOLDOWN(ch) (ch->player_specials->saved.retainer_cooldown) +#define GET_SCROUNGE_COOLDOWN(ch) (ch->player_specials->saved.scrounge_cooldown) #define GET_SAGE_MOB_VNUM(ch) (ch->char_specials.sage_mob_vnum) diff --git a/zedit.c b/zedit.c index ca89233a..7b0e16fc 100755 --- a/zedit.c +++ b/zedit.c @@ -863,7 +863,11 @@ static void zedit_disp_arg3(struct descriptor_data *d) write_to_output(d, "Count maximum (g)lobally, or in (r)oom : "); break; case 'E': +#if defined(CAMPAIGN_DL) || defined(CAMPAIGN_FR) + column_list(d->character, 0, equipment_types, NUM_WEARS, TRUE); +#else column_list(d->character, 0, equipment_types, NUM_WEARS - 4, TRUE); // added -4 to prevent ear/ear/eyes/badge +#endif write_to_output(d, "Location to equip : "); break; case 'P': @@ -1576,7 +1580,11 @@ void zedit_parse(struct descriptor_data *d, char *arg) case 'E': pos = atoi(arg) - 1; /* Count number of wear positions. */ +#if defined(CAMPAIGN_DL) || defined(CAMPAIGN_FR) + if (pos < 0 || pos >= NUM_WEARS) +#else if (pos < 0 || pos >= NUM_WEARS - 4) // added -4 to prevent ear/ear/eyes/badge +#endif write_to_output(d, "Try again : "); else {