/*************************************************************************** * Mud20 1.0 by Todd H. Johnson (Kregor) a derivative of the Open Gaming * * License by Wizards of the Coast. All comments referring to D20, OGL, * * and SRD refer to the System Reference Document for the Open Gaming * * system. Any inclusion of these derivatives must include credit to the * * Mud20 system, the full and complete Open Gaming LIcense, and credit to * * the respective authors. See ../doc/srd.txt for more information. * * * * Emud 2.2 by Igor van den Hoven, Michiel Lange, and Martin Bethlehem. * * * * MrMud 1.4 by David Bills, Dug Michael and Martin Gallwey * * * * Merc 2.1 Diku Mud improvments copyright (C) 1992, 1993 by Michael * * Chastain, Michael Quan, and Mitchell Tse. * * * * Original Diku Mud copyright (C) 1990 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik St{rfeld, Tom Madsen, and Katje Nyboe. * ***************************************************************************/ /*************************************************************************** * skills.c: Functions for skills, abilities and skill checks * ***************************************************************************/ #include "mud.h" #define DO_ABILITY(ability) bool ability( int sn, int level, CHAR_DATA *ch, void *vo, int target ) #define turn 10 #define hr 100 #define PARTIAL -1 /* This forces instant incubation of disease in corrupt touch spell */ void disease_update args(( CHAR_DATA *ch )); bool CRIT = FALSE; /* * Return the max uses per day of an ability - Kregor * * This obviously grows longer as more daily use * abilities are added to skill list. */ int get_max_uses( CHAR_DATA *ch, int sn ) { int uses = 0; push_call("get_max_uses(%p,%p)",ch,sn); if (!learned(ch, sn)) { pop_call(); return 0; } if (sn == gsn_lay_hands || sn == gsn_touch_of_courage || sn == gsn_touch_of_grace || sn == gsn_touch_of_profanity || sn == gsn_touch_of_resolve || sn == gsn_touch_of_righteousness || sn == gsn_touch_of_zeal || sn == gsn_corrupt_touch) { uses = (multi_class_level(ch, gsn_lay_hands) + multi_class_level(ch, gsn_corrupt_touch)) / 4; uses += UMAX(0, stat_bonus(FALSE, ch, APPLY_CHA)); } if (sn == gsn_turn_undead || sn == gsn_command_undead || sn == gsn_channeling_attack || sn == gsn_turn_plants || sn == gsn_turn_elemental || sn == gsn_turn_reptiles || sn == gsn_turn_lycanthrope || sn == gsn_turn_outsider) { uses = 3 + UMAX(0, stat_bonus(FALSE, ch, APPLY_CHA)); uses += multi_skill_level(ch, sn) / 5; if (learned(ch, gsn_extra_turning)) uses += 4; } if (sn == gsn_bardic_song) { uses = multi_class_level(ch, sn); uses += UMAX(0, stat_bonus(FALSE, ch, APPLY_CHA)); if (learned(ch, gsn_extra_song)) uses += 4; } if (sn == gsn_stunning_fist) { uses = 1 + UMAX(ch->level/4, class_level(ch, CLASS_MONK)/2); } if (sn == gsn_barbarian_rage) { uses = multi_skill_level(ch, sn) / 4 + 1 + UMAX(0, stat_bonus(FALSE, ch, APPLY_CON)); } if (sn == gsn_defensive_stance) { uses = ROUNDUP(multi_skill_level(ch, sn) / 2); } if (sn == gsn_divine_refuge) { uses = multi_class_level(ch, sn) / 4 + 1; } if (sn == gsn_divine_veil) { uses = ROUNDUP(multi_skill_level(ch, sn) / 2); } if (sn == gsn_divine_location) { uses = ROUNDUP(multi_skill_level(ch, sn) / 2); } if (sn == gsn_wildshape) { uses = multi_skill_level(ch, sn) / 2 + 1; } if (sn == gsn_smite || sn == gsn_destructive_smite || sn == gsn_smite_infidel) { uses = multi_skill_level(ch, sn) / 4 + 1; } if (sn == gsn_retributive_strike) { uses = class_level(ch, CLASS_CLERIC) / 5 + 1; } if (sn == gsn_defensive_roll) { uses = 1; } if (sn == gsn_shadow_companion) { uses = 1; } if (sn == gsn_shadow_jump) { uses = multi_skill_level(ch, gsn_shadow_jump) / 2; } if (sn == gsn_abundant_step || sn == gsn_empty_body) { uses = class_level(ch, CLASS_MONK) >= 20 ? 3 : class_level(ch, CLASS_MONK) >= 16 ? 2 : 1; } if (sn == gsn_shadow_illusion) { uses = multi_skill_level(ch, gsn_shadow_illusion) / 2; } if (sn == gsn_shadow_bolt) { uses = multi_skill_level(ch, gsn_shadow_bolt) / 3 + 1; } if (sn == gsn_energy_arrow) { uses = ((class_level(ch, CLASS_ARCANE_ARCHER) - 6) / 2 + 1); } if (sn == gsn_seeker_arrow) { uses = ((class_level(ch, CLASS_ARCANE_ARCHER) - 4) / 2 + 1); } if (sn == gsn_pilfer_dweomer) { uses = ((class_level(ch, CLASS_ARCANE_TRICKSTER) - 1) / 4 + 1); } if (sn == gsn_impromptu_sneak_attack) { if (class_level(ch, CLASS_ARCANE_TRICKSTER) >= 7) uses = 2; else uses = 1; } if (sn == gsn_death_arrow) { uses = 1; } pop_call(); return uses; } /* * groups enhanced class abilities under parent ability's uses - Kregor */ void add_uses( CHAR_DATA *ch, int sn ) { push_call("add_uses(%p,%p)",ch,sn); if (sn == gsn_turn_undead || sn == gsn_command_undead || sn == gsn_turn_plants || sn == gsn_turn_elemental || sn == gsn_turn_reptiles || sn == gsn_channeling_attack || sn == gsn_turn_lycanthrope || sn == gsn_turn_outsider) { sn = gsn_turn_undead; } ch->uses[sn]++; pop_call(); return; } /* * Check get_max_uses against spent uses of ability - Kregor */ bool CHECK_USES( CHAR_DATA *ch, int sn) { int uses; push_call("CHECK_USES(%p,%p)",ch,sn); if ((uses = get_max_uses(ch, sn)) <= 0) { pop_call(); return TRUE; } if (ch->uses[sn] >= uses) { ch_printf_color( ch, "You can't use your %s ability without resting.\n\r", skill_table[sn].name ); pop_call(); return FALSE; } wiz_printf("check uses (%s): uses %d, max %d.", skill_table[sn].name, ch->uses[sn], uses); pop_call(); return TRUE; } /* * functions to allow for taking 10 and 20 in skill rolls - Kregor */ int take_ten( CHAR_DATA *ch ) { int roll; push_call("take_ten(%p)",ch); roll = dice(1,20); if (IS_AFFECTED( ch, AFF2_FASCINATED)) { pop_call(); return (roll); } if (in_combat(ch)) { pop_call(); return (roll); } if (ch->distracted) { pop_call(); return (roll); } roll = UMAX(10, roll); pop_call(); return (roll); } int take_twenty( CHAR_DATA *ch ) { int roll; push_call("take_twenty(%p)",ch); roll = dice(1,20); if (IS_AFFECTED( ch, AFF2_FASCINATED)) { pop_call(); return (roll); } if (in_combat(ch)) { pop_call(); return (roll); } if (ch->distracted) { pop_call(); return (roll); } pop_call(); return 20; } /* Dupes the same const char as in magic.c for spell like abilities - Kregor */ char * target_name; char * origarg; /* * Trivial hack of original do_cast function for * using class special abilities - Kregor */ void do_activate( CHAR_DATA *ch, char *argument ) { char arg1[MAX_INPUT_LENGTH]; char arg2[MAX_INPUT_LENGTH]; char arg3[MAX_INPUT_LENGTH]; CHAR_DATA *victim; OBJ_DATA *obj, *symbol; void *vo; bool ranged = FALSE; int sn, level, target, dir, range; push_call("do_activate(%p,%p)",ch,argument); if (in_combat(ch) && !is_active(ch)) { ch_printf_color(ch, "Just wait your turn!\n\r"); pop_call(); return; } origarg = argument; argument = snarf_skill_name(argument, arg1); target_name = argument; argument = one_argument( argument, arg2 ); if (arg1[0] == '\0') { send_to_char( "Syntax: activate <ability> [direction] [<target>]\n\r", ch ); pop_call(); return; } sn = skill_lookup( arg1 ); if (skill_table[sn].skilltype == FSKILL_SPELL) { cast_spell(ch, origarg, TRUE); pop_call(); return; } if (skill_table[sn].skilltype != FSKILL_ABILITY && skill_table[sn].skilltype != FSKILL_FEAT) { if (!IS_NPC(ch) && ch->desc == NULL) { log_printf("[%u] using unknown ability: %s", ch->pIndexData->vnum, arg1); } send_to_char( "That is not a special ability.\n\r", ch ); pop_call(); return; } if (!skill_table[sn].spell_fun || skill_table[sn].spell_fun == spell_null) { ch_printf_color(ch, "That ability cannot be activated.\n\r"); pop_call(); return; } if (!learned(ch, sn)) { ch_printf_color(ch, "You are not able to use that ability.\n\r"); pop_call(); return; } if ((level = multi_skill_level(ch, sn)) == -1) { ch_printf_color(ch, "You are not able to use that ability.\n\r"); pop_call(); return; } if (IS_SET(ch->action, ACTION_STANDARD) && skill_table[sn].beats >= CASTING_STANDARD) { ch_printf_color(ch, "You have already made a standard action this round.\n\r"); pop_call(); return; } if (IS_SET(ch->action, ACTION_SWIFT) && skill_table[sn].beats == CASTING_SWIFT) { ch_printf_color(ch, "You have already made a swift action this round.\n\r"); pop_call(); return; } if (is_safe_magic(ch, NULL, sn)) { pop_call(); return; } /* * Determine whether it's a ranged affect or not */ if (*arg2 != '\0' && skill_table[sn].target != TAR_IGNORE && skill_table[sn].target != TAR_CHAR_SELF && skill_table[sn].target != TAR_OBJ_INV && skill_table[sn].target != TAR_OBJ_ROOM && skill_table[sn].target != TAR_OBJ_WIELD) { if ((dir = direction_door(arg2)) != -1) { ranged = TRUE; target_name = argument; argument = one_argument( argument, arg2 ); argument = one_argument( argument, arg3 ); } } else { argument = one_argument( argument, arg3 ); } if (ranged && !is_valid_exit(ch, ch->in_room, dir)) { send_to_char( "You cannot target in that direction.\n\r", ch ); pop_call(); return; } if (ranged && (range = get_spell_range(level, sn)) <= 0) { ch_printf_color(ch, "That ability cannot be activated at that range.\n\r"); pop_call(); return; } if (!CHECK_USES(ch, sn)) { pop_call(); return; } if (IS_SET(skill_table[sn].flags, SF_DIVINEFOCUS) && !IS_NPC(ch) && (!IS_GOD(ch) || !IS_PLR(ch, PLR_HOLYLIGHT))) { if ((symbol = get_obj_wear_type(ch, ITEM_SYMBOL)) == NULL) { send_to_char( "You don't have your holy symbol.\n\r", ch); pop_call(); return; } if (symbol->value[2] != ch->god) { send_to_char( "You need have your OWN deity's symbol!\n\r", ch); pop_call(); return; } } /* Locate targets. */ victim = NULL; obj = NULL; vo = NULL; target = skill_table[sn].target; if (ranged) { switch (target) { default: send_to_char( "That ability cannot be activated at range!\n\r", ch ); pop_call(); return; case TAR_CHAR_OFFENSIVE: case TAR_CHAR_DEFENSIVE: case TAR_UNDEAD_OFF: case TAR_UNDEAD_DEF: case TAR_OBJ_CHAR_OFF: case TAR_OBJ_CHAR_DEF: break; } } switch (target) { default: bug( "do_activate: bad target for sn %d.", sn ); pop_call(); return; case TAR_IGNORE: break; case TAR_CHAR_OFFENSIVE: if (arg2[0] == '\0') { if (who_fighting(ch) == NULL) { send_to_char( "Use this ability on whom?\n\r", ch ); pop_call(); return; } victim = who_fighting(ch); } else { if (ranged) { if ((victim = find_char_dir(ch, dir, arg2)) == NULL) { send_to_char("Your target must have slipped out of sight!\n\r", ch); pop_call(); return; } } else if ((victim = get_char_room(ch, arg2)) == NULL) { send_to_char( "Your target isn't here.\n\r", ch ); pop_call(); return; } } if (is_safe_magic(ch, victim, sn)) { pop_call(); return; } vo = (void *) victim; break; case TAR_UNDEAD_OFF: if (arg2[0] == '\0') { if ((victim = who_fighting(ch)) == NULL || !IS_UNDEAD(who_fighting(ch))) { if (IS_UNDEAD(ch)) { send_to_char( "Use this ability on whom?\n\r", ch ); pop_call(); return; } else { victim = ch; } } } else { if (ranged) { if ((victim = find_char_dir(ch, dir, arg2)) == NULL) { send_to_char("Your target must have slipped out of sight!\n\r", ch); pop_call(); return; } } else if ((victim = get_char_room(ch, arg2)) == NULL) { send_to_char( "Your target isn't here.\n\r", ch ); pop_call(); return; } } if (IS_UNDEAD(victim) && is_safe_magic(ch, victim, sn)) { pop_call(); return; } vo = (void *) victim; if (IS_UNDEAD(victim)) target = TAR_CHAR_OFFENSIVE; else target = TAR_CHAR_DEFENSIVE; break; case TAR_CHAR_DEFENSIVE: if (arg2[0] == '\0') { victim = ch; } else { if (ranged) { if ((victim = find_char_dir(ch, dir, arg2)) == NULL) { send_to_char("Your target must have slipped out of sight!\n\r", ch); pop_call(); return; } } else if ((victim = get_char_room(ch, arg2)) == NULL) { send_to_char( "Your target isn't here.\n\r", ch ); pop_call(); return; } } if (is_safe_magic(ch, victim, sn)) { pop_call(); return; } vo = (void *) victim; break; case TAR_UNDEAD_DEF: if (arg2[0] == '\0') { if ((victim = who_fighting(ch)) == NULL || IS_UNDEAD(who_fighting(ch))) { if (!IS_UNDEAD(ch)) { send_to_char( "Use this ability on whom?\n\r", ch ); pop_call(); return; } else { victim = ch; } } } else { if (ranged) { if ((victim = find_char_dir(ch, dir, arg2)) == NULL) { send_to_char("Your target must have slipped out of sight!\n\r", ch); pop_call(); return; } } else if ((victim = get_char_room(ch, arg2)) == NULL) { send_to_char( "Your target isn't here.\n\r", ch ); pop_call(); return; } } if (!IS_UNDEAD(victim) && is_safe_magic(ch, victim, sn)) { pop_call(); return; } vo = (void *) victim; if (!IS_UNDEAD(victim)) target = TAR_CHAR_OFFENSIVE; else target = TAR_CHAR_DEFENSIVE; break; case TAR_CHAR_SELF: if (ranged) { send_to_char( "You activate this ability at range.\n\r", ch ); pop_call(); return; } if (arg2[0] == '\0' || is_name_short(arg2, ch->name)) { victim = ch; } if (ch != victim && is_safe_magic(ch, victim, sn)) { pop_call(); return; } vo = (void *) victim; break; case TAR_OBJ_INV: if (arg2[0] == '\0') { send_to_char( "What should the ability be activated upon?\n\r", ch ); pop_call(); return; } if ((obj = get_obj_carry(ch, arg2)) == NULL) { if ((obj = get_obj_wear(ch, arg2)) == NULL) { send_to_char( "You are not carrying that.\n\r", ch ); pop_call(); return; } } vo = (void *) obj; break; case TAR_OBJ_WIELD: if (arg2[0] == '\0') { if ((obj = get_wield(ch, FALSE)) == NULL) { send_to_char( "What should the ability be activated upon?\n\r", ch ); pop_call(); return; } } if ((obj = get_obj_wear(ch, arg2)) == NULL) { send_to_char( "You are not holding that.\n\r", ch ); pop_call(); return; } vo = (void *) obj; break; case TAR_OBJ_ROOM: if (arg2[0] == '\0') { send_to_char( "What should the ability be activated upon?\n\r", ch ); pop_call(); return; } if ((obj = get_obj_here(ch, arg2)) == NULL) { send_to_char( "That item does not seem to be here.\n\r", ch ); pop_call(); return; } vo = (void *) obj; break; case TAR_OBJ_CHAR_DEF: if (arg2[0] == '\0') { victim = ch; } else if ((victim = get_char_room(ch, arg2)) == NULL) { if ((obj = get_obj_carry(ch, arg2)) == NULL) { send_to_char( "Who or what should the ability be activated upon?\n\r", ch ); pop_call(); return; } } if (victim) { if (is_safe_magic(ch, victim, sn)) { pop_call(); return; } target = TAR_CHAR_DEFENSIVE; vo = (void *) victim; } else { if (ranged) { send_to_char( "That item does not seem to be here.\n\r", ch ); pop_call(); return; } target = TAR_OBJ_INV; vo = (void *) obj; } break; case TAR_OBJ_CHAR_OFF: if (arg2[0] == '\0') { if (who_fighting(ch) == NULL) { send_to_char("Cast the spell on whom?\n\r", ch); pop_call(); return; } victim = who_fighting(ch); } else if ((victim = get_char_room(ch, arg2)) == NULL) { if ((obj = get_obj_carry(ch, arg2)) == NULL) { send_to_char( "Who or what should the ability be activated upon?\n\r", ch ); pop_call(); return; } } if (victim) { if (is_safe_magic(ch, victim, sn)) { pop_call(); return; } target = TAR_CHAR_OFFENSIVE; vo = (void *) victim; } else { if (ranged) { send_to_char( "That item does not seem to be here.\n\r", ch ); pop_call(); return; } target = TAR_OBJ_INV; vo = (void *) obj; } break; } if (ranged && findpath_search_victim(ch, victim, range) == -1) { send_to_char("That target is out of your reach.\n\r", ch); pop_call(); return; } if (target == TAR_CHAR_OFFENSIVE) { if (!in_combat(ch) || !in_combat(victim)) { fight(ch, victim); } } CHECK_TURN(ch, victim); switch (skill_table[sn].minimum_position) { case POS_FIGHTING: if (ch->position < POS_FIGHTING) { act("You might want to be standing up to do that.", ch, NULL, NULL, TO_CHAR); pop_call(); return; } break; case POS_STANDING: if (in_combat(ch)) { act("You cannot do that in combat.", ch, NULL, NULL, TO_CHAR); pop_call(); return; } if (ch->position < POS_FIGHTING) { act("You might want to be standing up to do that.", ch, NULL, NULL, TO_CHAR); pop_call(); return; } break; default: if (ch->position < skill_table[sn].minimum_position) { act("You're too relaxed to do that.", ch, NULL, NULL, TO_CHAR); pop_call(); return; } break; } // give concentration delay and AoO for spell-like abilities if (IS_SET(skill_table[sn].flags, SF_SPELL_LIKE) && !ch->concentrating) { act( "$n starts to concentrate...", ch, NULL, NULL, TO_ROOM ); act( "You concentrate to activate an ability...", ch, NULL, NULL, TO_CHAR ); ch->concentrating = TRUE; ch->skill_timer = skill_table[sn].beats; ch->timer_fun = do_activate; RESTRING(ch->cmd_argument, origarg); pop_call(); return; } if (IS_SET(skill_table[sn].flags, SF_SPELL_LIKE)) { if (IS_ENTANGLED(ch) || drunk_level(ch) >= DRUNK_TIPSY || is_affected(ch, gsn_insect_plague) || ch->grappling || ch->grappled_by) { int diceroll = concentration_roll(ch); int DC; if (ch->grappled_by) DC = 10 + combat_maneuver_bonus(ch->grappled_by) + skill_table[sn].native_level; else DC = 15 + skill_table[sn].native_level; if (!concentration_check(ch, victim, diceroll, DC)) { send_to_char_color("{138}You lost your concentration!\n\r", ch); ch->uses[sn]++; pop_call(); return; } } } bool fTouch = TRUE; if (victim != NULL && victim != ch && IS_SET(skill_table[sn].flags, SF_TOUCH)) { switch (target) { case TAR_CHAR_OFFENSIVE: if(!check_hit(ch, victim, dice(1,20), 0, sn, NULL, TRUE, FALSE)) { act( "You attempt to touch $N, but miss.", ch, NULL, victim, TO_CHAR); act( "$n attempts to touch $N, but misses.", ch, NULL, victim, TO_NOTVICT); act( "$n attempts to touch you, but misses.", ch, NULL, victim, TO_VICT); fTouch = FALSE; } break; case TAR_CHAR_DEFENSIVE: if((in_combat(victim) || in_combat(ch) || IS_AFFECTED(victim, AFF2_CONFUSION)) && !check_hit(ch, victim, dice(1,20), 0, sn, NULL, TRUE, FALSE)) { act( "You attempt to touch $N, but miss.", ch, NULL, victim, TO_CHAR); act( "$n attempts to touch $N, but misses.", ch, NULL, victim, TO_NOTVICT); act( "$n attempts to touch you, but misses.", ch, NULL, victim, TO_VICT); fTouch = FALSE; } break; } } if (fTouch) { if ((*skill_table[sn].spell_fun) (sn, level, ch, vo, target)) { add_uses(ch, sn); //abilities can trigger cast progs too mprog_cast_trigger(ch, victim, sn); oprog_cast_trigger(ch, obj, sn); rprog_cast_trigger(ch, sn); } else { pop_call(); // if ability errors out, don't expend uses return; } } if (skill_table[sn].beats == CASTING_SWIFT) TAKE_ACTION(ch, ACTION_SWIFT); else if (skill_table[sn].beats == CASTING_STANDARD) TAKE_ACTION(ch, ACTION_STANDARD); else if (skill_table[sn].beats == CASTING_ROUND) TAKE_ACTION(ch, ACTION_FULL); pop_call(); return; } /* * Appraise skill D20 - Kregor 5/12/07 * Kept PFRPG beta mechanic that varies DC based on value, * appraise + detect magic/identify can identify magic items */ void do_appraise( CHAR_DATA *ch, char *argument ) { char arg[MAX_INPUT_LENGTH]; char buf[MAX_INPUT_LENGTH]; OBJ_DATA *obj; int cost, diceroll, DC; push_call("do_value(%p,%p)",ch,argument); one_argument( argument, arg ); if (arg[0] == '\0') { send_to_char("Appraise what?\n\r", ch); pop_call(); return; } if ((obj = get_obj_carry(ch, arg)) == NULL) { send_to_char_color("You don't have that item.\n\r", ch); pop_call(); return; } if (!ch->concentrating) { act( "$n sets to appraising $p.", ch, obj, NULL, TO_ROOM ); act( "You set to appraising $p.", ch, obj, NULL, TO_CHAR ); ch->concentrating = TRUE; ch->skill_timer = 12; ch->timer_fun = do_appraise; RESTRING(ch->cmd_argument, argument); TAKE_ACTION(ch, ACTION_STANDARD); pop_call(); return; } if ((cost = obj->cost) <= 10000) DC = 5; else if (cost <= 50000) DC = 10; else if (cost <= 100000) DC = 15; else if (cost <= 500000) DC = 20; else if (cost <= 1000000) DC = 25; else DC = 30; if (IS_OBJ_STAT(obj,ITEM_MAGIC)) { if(!learned(ch, gsn_appraise)) { act( "{178}You cannot even begin to appraise $p correctly.", ch, obj, NULL, TO_CHAR); pop_call(); return; } if (!domain_apotheosis(ch, DOMAIN_TRADE) && !domain_apotheosis(ch, DOMAIN_MAGIC) && !CAN_SEE_MAGIC(ch) && !is_affected(ch, gsn_analyze_dweomer) && !is_affected(ch, gsn_identify)) { act( "{178}You are not affected with a means to detect magic.", ch, obj, NULL, TO_CHAR); pop_call(); return; } DC = 15 + obj_level_estimate(obj->pIndexData); diceroll = appraise_roll(ch, obj); if (domain_apotheosis(ch, DOMAIN_MAGIC) || is_affected(ch, gsn_identify)) diceroll += 10; diceroll += synergy_bonus(ch, gsn_spellcraft); diceroll += synergy_bonus(ch, gsn_know_arcana); diceroll += multi_class_level(ch, gsn_lore) / 2; if (diceroll < DC && !domain_apotheosis(ch, DOMAIN_TRADE) && !domain_apotheosis(ch, DOMAIN_MAGIC) && !is_affected(ch, gsn_analyze_dweomer)) { act( "{178}You cannot even begin to appraise $p correctly.", ch, obj, NULL, TO_CHAR); pop_call(); return; } if (!obj->identified) obj->identified = TRUE; } else if ((diceroll = appraise_roll(ch,obj)) + 5 < DC) { act( "{178}You cannot even begin to appraise $p correctly.", ch, obj, NULL, TO_CHAR); pop_call(); return; } else if (diceroll < DC) cost = cost * (dice(1, 40) + 80) / 100; show_examine_string(obj, ch); sprintf(buf, "%s {300}is worth approximately %s.\n\r", obj->short_descr, format_coins(cost,TRUE)); if (IS_OBJ_STAT(obj,ITEM_MASTERWORK)) cat_sprintf(buf, "{178}it is a masterwork item.\n\r"); send_to_char_color(buf, ch); pop_call(); return; } /* * AID command uses the First Aid skill. hit points are only * restored with a first aid kit. Only the stabilizing * option can be done while in combat. Each treatment * type takes a separate use of the AID command. - Kregor */ void do_aid( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; AFFECT_DATA *paf; char arg[MAX_INPUT_LENGTH]; bool healed = FALSE; bool HasKit = TRUE; OBJ_DATA *kit; int diceroll, dc; int heal = 0; push_call("do_heal(%p)",ch,argument); one_argument(argument, arg); if (arg[0] == '\0') { send_to_char("Aid whom?\n\r", ch); pop_call(); return; } if ((victim = get_char_room(ch, arg)) == NULL) { send_to_char("That person doesn't seem to be here.\n\r", ch); pop_call(); return; } if (victim->hit >= get_max_hit(victim) && !IS_POISONED(victim) && victim->nonlethal < victim->hit && ch->position > POS_STUNNED && !is_affected(ch, gsn_bleed_damage) && !IS_DISEASED(victim)) { act( "$N does not need your aid.", ch, NULL, victim, TO_CHAR); pop_call(); return; } if ((kit = get_obj_carry_type(ch, ITEM_TOOLS)) == NULL || !TOOL_TYPE(kit, TOOL_FIRSTAID_KIT)) { HasKit = FALSE; if (!is_handy(ch) || hands_full(ch)) { send_to_char( "You have no free hand to do that.\n\r", ch ); pop_call(); return; } } if (in_combat(ch)) { if (victim->position > POS_MORTAL && !IS_AFFECTED(victim, AFF2_BLEEDING)) { act("You may only treat the critically wounded while in combat.", ch, NULL, NULL, TO_CHAR); pop_call(); return; } } CHECK_TURN(ch, victim); // making this a concentration skill means you can get interrupted and spoiled if (!ch->concentrating) { if (ch == victim) { act( "You tend to your health...", ch, NULL, victim, TO_CHAR); act( "$n tends to $s health...", ch, NULL, victim, TO_ROOM); } else { act( "You tend to $N's health...", ch, NULL, victim, TO_CHAR); act( "$n tends to $N health...", ch, NULL, victim, TO_NOTVICT); act( "$n tends to your health...", ch, NULL, victim, TO_VICT); } ch->concentrating = TRUE; ch->skill_timer = in_combat(ch) ? 36 : 8; ch->timer_fun = do_aid; RESTRING(ch->cmd_argument, argument); if (in_combat(ch)) TAKE_ACTION(ch, ACTION_STANDARD); else TAKE_ACTION(ch, ACTION_FULL); pop_call(); return; } diceroll = first_aid_roll(ch); if (victim->position <= POS_INCAP || is_affected(victim, gsn_bleed_damage)) { // DC is harder the more hurt or bleeding the victim is - Kregor dc = 10; if (victim->hit < 0) dc -= victim->hit; if ((paf = get_affect_sn(victim, gsn_bleed_damage)) != NULL) dc += paf->modifier; if ((heal = first_aid_check(ch, NULL, diceroll, dc)) >= 0) { if (ch == victim) { act( "{138}You bind your wounds.",ch, NULL, victim, TO_CHAR); act( "{138}$n binds $s wounds.",ch, NULL, victim, TO_ROOM); } else { act( "{138}You bind $N's wounds.",ch, NULL, victim, TO_CHAR); act( "{138}$n binds $N's wounds.",ch, NULL, victim, TO_NOTVICT); act( "{138}$n binds your wounds.",ch, NULL, victim, TO_VICT); } if (is_affected(victim, gsn_bleed_damage)) { affect_strip(victim, gsn_bleed_damage); healed = TRUE; } if (victim->position <= POS_INCAP) { victim->hit = 0; act( "You are stabilized.", victim, NULL, NULL, TO_CHAR); act( "$n is stabilized.", victim, NULL, NULL, TO_ROOM); healed = TRUE; } if (HasKit) { victim->hit = UMIN(victim->hit + heal, get_max_hit(victim)); victim->nonlethal = UMAX(0, victim->nonlethal - heal); healed = TRUE; } } } else if (ch != victim && IS_AFFECTED(victim, AFF2_STUNNED)) { if (diceroll >= 15) { AFFECT_STRIP(victim, AFF2_STUNNED); act( "{138}You help $N come to.",ch, NULL, victim, TO_CHAR); act( "{138}$n helps $N come to.",ch, NULL, victim, TO_NOTVICT); act( "{138}$n helps you come to.",ch, NULL, victim, TO_VICT); healed = TRUE; } } else if (is_affected(victim, gsn_poison) || victim->poison != NULL) { if (!HasKit) { act("You cannot treat poison without a first aid kit.", ch, NULL, NULL, TO_CHAR); pop_call(); return; } if (is_affected(victim, gsn_poison) && diceroll >= 10 + get_affect_level(victim, gsn_poison)) { affect_strip(victim, gsn_poison); healed = TRUE; } if (victim->poison != NULL) { POISON_DATA *npd, *pd; if (diceroll >= (victim->poison->dc ? victim->poison->dc : poison_table[victim->poison->type].dc)) { pd = victim->poison; victim->poison = NULL; while (pd != NULL) { npd = pd->next; FREEMEM( pd ); pd = npd; } act( "{138}$N's color begins to return as poison cleanses from $M.", victim, NULL, NULL, TO_ROOM); act( "{138}You feel better as poison cleanses from you.", victim, NULL, NULL, TO_CHAR); healed = TRUE; } else if (victim == ch) { act( "{028}You try to cure your poison, with little results.", ch, NULL, victim, TO_CHAR); } else { act( "{028}You try to cure $N's poison, with little results.", ch, NULL, victim, TO_CHAR); } } } else if (IS_DISEASED(victim)) { DISEASE_DATA *dis; if (!HasKit) { act("You cannot treat disease without a first aid kit.", ch, NULL, NULL, TO_CHAR); pop_call(); return; } for (dis = victim->first_disease ; dis != NULL ; dis = dis->next) { if ((dis->dc && diceroll >= dis->dc) || (!dis->dc && diceroll >= disease_table[dis->type].dc)) { disease_from_char(victim, dis); act( "{138}$N shows signs of recovery from $S malady.", victim, NULL, NULL, TO_ROOM); act( "{138}You begin to feel signs of recovery from your malady.", victim, NULL, NULL, TO_CHAR); healed = TRUE; } else if (victim == ch) { act( "{028}Disease still holds fast in your system.", ch, NULL, victim, TO_CHAR); } else { act( "{028}Disease still holds fast in $N's system.", ch, NULL, victim, TO_CHAR); } } } else if (victim->hit < get_max_hit(victim) || victim->nonlethal > 0) { if ((heal = first_aid_check(ch, NULL, diceroll, 20)) >= 0) { if (ch == victim) { act( "{138}You bind your wounds.",ch, NULL, victim, TO_CHAR); act( "{138}$n binds $s wounds.",ch, NULL, victim, TO_ROOM); } else { act( "{138}You bind $N's wounds.",ch, NULL, victim, TO_CHAR); act( "{138}$n binds $N's wounds.",ch, NULL, victim, TO_NOTVICT); act( "{138}$n binds your wounds.",ch, NULL, victim, TO_VICT); } if (HasKit) { victim->hit = UMIN(victim->hit + heal, get_max_hit(victim)); victim->nonlethal = UMAX(0, victim->nonlethal - heal); healed = TRUE; } //only gain long-term care benefit out of combat if (!in_combat(ch) && !in_combat(victim) && !IS_AFFECTED(victim, AFF2_LONGTERM_CARE)) { if (victim != ch) { SET_AFFECT(victim, AFF2_LONGTERM_CARE); send_to_char("You must rest to gain the benefits of long-term care.\n\r", victim); } else { send_to_char("You cannot give yourself long-term care.\n\r", victim); } } } } update_pos(victim,-1); if (!healed) { act( "Your aid does not seem to have offered any benefit.", ch, NULL, victim, TO_CHAR); act( "$n's attempt to aid does not seem to offer any benefit.", ch, NULL, victim, TO_ROOM); } pop_call(); return; } /* * Bluff skill w/ targeted and room options */ void do_bluff( CHAR_DATA *ch, char *argument ) { char arg[MAX_INPUT_LENGTH]; AFFECT_DATA af; CHAR_DATA *victim; CHAR_DATA *fch; int diceroll; push_call("do_bluff(%p,%p)",ch,argument); argument = one_argument(argument, arg); if (arg[0] == '\0') { send_to_char("Syntax: bluff <target|all>\n\r",ch); pop_call(); return; } if (in_combat(ch)) { send_to_char("You can only FEINT or TAUNT when you are fighting.\n\r",ch); pop_call(); return; } diceroll = bluff_roll(ch); if (!strcasecmp(arg, "all")) { act( "You attempt to bluff everyone in the room.", ch, NULL, NULL, TO_CHAR ); for (fch = ch->in_room->first_person ; fch ; fch = fch->next_in_room) { if (ch == fch) continue; if (!in_combat(ch) && in_combat(fch)) { act( "$N is too busy fighting.", ch, NULL, fch, TO_CHAR ); continue; } if (fch->position <= POS_SLEEPING || !can_see(fch, ch)) { act( "$N is not paying attention to you.", ch, NULL, fch, TO_CHAR ); continue; } if (fch->distracted > 0 || is_affected(fch, gsn_bluff)) { act( "$N is already distracted.", ch, NULL, fch, TO_CHAR ); continue; } if (!bluff_check(ch, fch, diceroll, 0)) { act( "$N looks at you very suspiciously.", ch, NULL, fch, TO_CHAR ); act( "You call $n's bluff.", ch, NULL, fch, TO_VICT ); fch->distracted = 0; affect_strip(fch, gsn_bluff); continue; } act( "$n bluffs you with a clever ruse.", ch, NULL, fch, TO_VICT); act( "You bluff $N with a clever ruse.", ch, NULL, fch, TO_CHAR); af.type = gsn_bluff; af.duration = 2; af.location = APPLY_NONE; af.modifier = 0; af.bittype = AFFECT_TO_NONE; af.bitvector = 0; af.level = diceroll; affect_to_char( ch, fch, &af ); wait_state( fch, skill_table[gsn_bluff].beats ); } TAKE_ACTION(ch, ACTION_STANDARD); } else { if ((victim = get_char_room(ch, arg)) == NULL) { send_to_char("They are not here.\n\r",ch); pop_call(); return; } if (victim == ch) { send_to_char_color( "Distract yourself?", ch ); } CHECK_TURN(ch, victim); if (victim->distracted > 0 || is_affected(victim, gsn_bluff)) { act( "$N won't be fooled again.", ch, NULL, victim, TO_CHAR ); pop_call(); return; } if (victim->position <= POS_SLEEPING || !can_see(victim, ch)) { act( "$N is not paying attention to you.", ch, NULL, victim, TO_CHAR ); pop_call(); return; } if (!bluff_check(ch, victim, diceroll, 0)) { act( "$N suddenly looks very suspicious.", ch, NULL, victim, TO_CHAR ); act( "You call $n's bluff!", ch, NULL, victim, TO_VICT); victim->distracted = 0; affect_strip(victim, gsn_bluff); pop_call(); return; } act( "$n bluffs you with a clever ruse.", ch, NULL, victim, TO_VICT); act( "You bluff $N with a clever ruse.", ch, NULL, victim, TO_CHAR); act( "$n bluffs $N with a clever ruse.", ch, NULL, victim, TO_NOTVICT); af.type = gsn_bluff; af.duration = 2; af.location = APPLY_NONE; af.modifier = 0; af.bittype = AFFECT_TO_NONE; af.bitvector = 0; af.level = diceroll; affect_to_char( ch, victim, &af ); wait_state( victim, skill_table[gsn_bluff].beats ); TAKE_ACTION(ch, ACTION_STANDARD); } pop_call(); return; } /* * Check to see if a name is one that can * be used for naming a pet/companion - Kregor */ bool check_legal_name( CHAR_DATA *ch, char *name ) { CHAR_DATA *victim; push_call("check_legal_name(%p,%p)",ch,name); if (!check_parse_name(name, TRUE)) { send_to_char ("That is an illegal name, try another.\n\r",ch); pop_call(); return FALSE; } if ((victim = lookup_char(name)) != NULL) { send_to_char ("That name belongs to a player character.\n\r",ch); pop_call(); return FALSE; } if ((victim = start_partial_load(ch, name)) != NULL) { send_to_char ("That name belongs to a player character.\n\r",ch); clear_partial_load(victim); pop_call(); return FALSE; } pop_call(); return TRUE; } /* * Disguise skill, totally gutted and reworked - Kregor 3/12/07 */ /* * Hack of check_parse_name from nanny to * determine a legal adjective for disguise - Kregor */ bool is_legal_adj(char *name) { push_call("is_legal_adj(%p)",name); /* Reserved Words */ if (is_name(name, "all auto immortal god enemy clan target race class someone north east south west down order chaos open close hours hit mana armor damage castle save bak del dmp hours")) { pop_call(); return FALSE; } if (lookup_god(name) != -1) { pop_call(); return FALSE; } /* Alphanumerics only */ { char *pc; for (pc = name ; *pc != '\0' ; pc++) { if ((*pc < 'a' || *pc > 'z') && *pc != ',' && *pc != ' ' && (*pc < 'A' || *pc > 'Z')) { pop_call(); return FALSE; } } /* No more names containing 'you' */ for (pc = name ; *(pc+2) != '\0' ; pc++) { if ((*(pc+0) == 'Y' || *(pc+0) == 'y') && (*(pc+1) == 'O' || *(pc+1) == 'o') && (*(pc+2) == 'U' || *(pc+2) == 'u')) { pop_call(); return FALSE; } } } pop_call(); return TRUE; } void ed_disguise_desc( CHAR_DATA *ch ) { push_call("ed_disguise_desc(%p)",ch); CHECK_EDITMODE( ch ); if (!ch->desc) { bug( "ed_disguise_desc: no descriptor", 0 ); pop_call(); return; } switch( ch->pcdata->editmode ) { default: bug( "ed_disguise_desc: illegal editmode", 0 ); pop_call(); return; case MODE_RESTRICTED: send_to_char( "You cannot use this command from while editing something else.\n\r",ch); pop_call(); return; case MODE_NONE: ch->pcdata->editmode = MODE_DISGUISE_DESC; ch->pcdata->tempmode = MODE_NONE; start_editing( ch, ch->pcdata->disguise_descr ); pop_call(); return; case MODE_DISGUISE_DESC: STRFREE (ch->pcdata->disguise_descr); ch->pcdata->disguise_descr = copy_buffer( ch ); stop_editing( ch ); pop_call(); return; } pop_call(); return; } void do_disguise( CHAR_DATA *ch, char *argument ) { char arg1[MAX_INPUT_LENGTH]; char arg2[MAX_INPUT_LENGTH]; char adj[MAX_STRING_LENGTH]; char buf[MAX_STRING_LENGTH]; OBJ_DATA *kit; int diceroll, race, sex; push_call("do_disguise(%p,%p)",ch,argument); if (IS_NPC(ch)) { send_to_char("NPCs cannot disguise.\n\r", ch); pop_call(); return; } if (!ch->desc) { pop_call(); return; } if (in_combat(ch)) { send_to_char( "You can't do that while fighting.\n\r", ch ); pop_call(); return; } if (*argument == '\0') { if (is_string(ch->pcdata->disguise)) { if (is_string(ch->pcdata->disguise_descr)) { ch_printf_color(ch, "{300}You're disguised as {178}%s %s.\n\r", a_an(ch->pcdata->disguise), ch->pcdata->disguise); pop_call(); return; } else { ed_disguise_desc(ch); pop_call(); return; } } else { send_to_char("Disguise yourself as what?\n\r", ch); send_to_char("syntax: disguise <sex> <race> <adjective>\n\r", ch); pop_call(); return; } } if (!strcasecmp(argument,"remove")) { STRFREE(ch->pcdata->disguise); ch->pcdata->disguise = STRALLOC(""); STRFREE(ch->pcdata->disguise_descr); ch->pcdata->disguise_descr = STRALLOC(""); ch->pcdata->disguise_roll = 0; affect_strip(ch, gsn_disguise); send_to_char( "You remove your disguise.\n\r", ch ); act( "$n removes $s disguise.", ch, NULL, NULL, TO_ROOM); pop_call(); return; } if (ch->pcdata->disguise != NULL && ch->pcdata->disguise[0] != '\0') { act("You must remove your current disguise before applying a new one.", ch, NULL, NULL, TO_CHAR); pop_call(); return; } if (strstr(argument, "{")) { send_to_char("You cannot use color codes in a disguise.\n\r", ch); pop_call(); return; } smash_tilde( argument ); argument = one_argument( argument, arg1 ); argument = one_argument( argument, arg2 ); strcpy( adj, argument ); if (*arg1 == '\0' || *arg2 == '\0' || *argument == '\0') { send_to_char("syntax: disguise <sex> <race> <adjective>\n\r", ch); pop_call(); return; } if ((sex = get_flag(arg1, sex_types)) == -1) { send_to_char("That is not a valid gender.\n\r", ch); pop_call(); return; } if ((race = lookup_race(arg2)) == -1) { send_to_char("That is not a race.\n\r", ch); pop_call(); return; } if (!is_legal_adj(argument)) { send_to_char("That is not a legal adjective.\n\r", ch); pop_call(); return; } if (strlen(argument) > 30) { send_to_char("Your adjective must be 30 characters or less.\n\r", ch); pop_call(); return; } // Just the dice here, use the check function for adjustments diceroll = dice(1,20); if (!is_polymorph(ch)) { if ((kit = get_obj_carry_type(ch, ITEM_TOOLS)) != NULL) { if (TOOL_TYPE(kit, TOOL_DISGUISE_KIT)) { if (kit->value[1] == 0) { act( "You've used the last of your disguise kit.", ch, NULL, NULL, TO_CHAR); junk_obj(kit); diceroll -= 2; } else { kit->value[1]--; if (IS_OBJ_STAT(kit, ITEM_MASTERWORK)) { if (kit->value[2] > 0) diceroll += kit->value[2]; else diceroll += 2; } } } else { act( "You suffer a penalty for not using a disguise kit.", ch, NULL, NULL, TO_CHAR); diceroll -= 2; } } else { act( "You suffer a penalty for not using a disguise kit.", ch, NULL, NULL, TO_CHAR); diceroll -= 2; } } // suffer -2 penalty for disguise of different race if (race != ch->race) { if (race_table[race].size != get_size(ch)) { send_to_char("You can only disguise youself as a race of the same size.\n\r", ch); pop_call(); return; } if (race_table[race].type != race_type(ch)) { send_to_char("You cannot disguise as another racial type.\n\r", ch); pop_call(); return; } diceroll -= 2; } // suffer -2 penalty for disguise as different gender if (ch->sex != sex) { diceroll -= 2; } sprintf(buf, "%s %s %s", adj, sex_types[sex], race_table[race].race_name); smash_tilde( buf ); if (ch->pcdata->disguise && *ch->pcdata->disguise != '\0') STRFREE(ch->pcdata->disguise); ch->pcdata->disguise = STRALLOC(buf); send_to_char( "You meticulously disguise yourself.\n\r", ch ); act( "$n meticulously disguises $mself.", ch, NULL, NULL, TO_ROOM); ch->pcdata->disguise_roll = diceroll; // to foil pronouns and socials if (sex != ch->sex) { AFFECT_DATA af; af.type = gsn_disguise; af.duration = -1; af.modifier = sex - ch->sex; af.location = APPLY_SEX; af.bittype = AFFECT_TO_NONE; af.bitvector = AFF_NONE; af.level = diceroll; affect_join( ch, ch, &af ); } act("Please set your description for your disguise.", ch, NULL, NULL, TO_CHAR); ed_disguise_desc(ch); TAKE_ACTION(ch, ACTION_FULL); pop_call(); return; } /* * Hide, sneak and vis, modified significantly for Mud20 - Kregor */ /* * Just about triple the original command function's length * Goes through everyone in the room to see if the char's * attempt to hide actually works against them, * also added ability to hide behind furnishings - Kregor */ void do_stealth( CHAR_DATA *ch, char *argument ) { CHAR_DATA *gch, *gch_next; AFFECT_DATA af; bool hips = FALSE; push_call("do_stealth(%p,%p)",ch,argument); if ((hips = learned(ch, gsn_hide_plain_sight)) == FALSE && in_combat(ch)) { send_to_char("You're too busy fighting to run and hide.\n\r", ch); pop_call(); return; } int diceroll = bluff_roll(ch); if (learned(ch, gsn_stealthy)) diceroll += 4; if (!hips) { if (IS_SET(ch->in_room->room_flags, ROOM_NO_COVER)) { send_to_char_color( "You can't find suitable cover.\n\r", ch ); pop_call(); return; } for (gch = ch->in_room->first_person ; gch ; gch = gch_next) { gch_next = gch->next_in_room; if (gch == ch) continue; if (gch->distracted || is_affected(ch, gsn_bluff)) continue; if (!IS_AWAKE(gch)) continue; if (is_same_group(gch, ch)) continue; if (!can_see(gch, ch)) continue; if (!can_see(ch, gch)) continue; // You can't hide with aggro after you if (IS_ACT(gch, ACT_AGGRESSIVE) || (who_fighting(gch) && who_fighting(gch) == ch)) { // -4 penalty to bluff and hide from an active enemy if (!bluff_check(ch, gch, diceroll - 5, sense_motive_roll(gch))) { act( "You cannot hide with enemies aware of you!", ch, NULL, gch, TO_CHAR ); pop_call(); return; } } } } else { if (IS_SET(ch->in_room->room_flags, ROOM_NO_COVER) && get_room_light(ch->in_room) == LIGHT_BRIGHT) { act("You can't find sufficient cover!", ch, NULL, NULL, TO_CHAR); pop_call(); return; } } af.type = gsn_stealth; af.duration = -1; af.location = APPLY_NONE; af.modifier = 0; af.bittype = AFFECT_TO_CHAR; af.bitvector = AFF_HIDE|AFF_SNEAK; af.level = 0; affect_join( ch, ch, &af ); if (learned(ch, gsn_swift_stealth)) ch->speed = UMIN(ch->speed, 1); else ch->speed = 0; if (learned(ch, gsn_trackless_step)) { send_to_char("The wind would leave more trace of it's passage than you.\n\r",ch); } else { send_to_char("You attempt to move stealthily.\n\r",ch); } for (gch = ch->in_room->first_person ; gch ; gch = gch_next) { gch_next = gch->next_in_room; if (!IS_NPC(gch)) { if (IS_NPC(ch)) { if ((!hips && !bluff_check(ch, gch, diceroll, sense_motive_roll(gch))) || can_see(gch, ch)) { act( "$n tries to duck into hiding, but you still see $m.", ch, NULL, gch, TO_VICT ); gch->pcdata->found_vnum[ch->pIndexData->vnum] = 1; } else { act( "You blink and suddenly, $n has ducked away!", ch, NULL, gch, TO_VICT ); gch->pcdata->found_vnum[ch->pIndexData->vnum] = -1; } } else { if ((!hips && !bluff_check(ch, gch, diceroll, sense_motive_roll(gch))) || can_see(gch, ch)) { act( "$n tries to duck into hiding, but you still see $m.", ch, NULL, gch, TO_VICT ); gch->pcdata->found_pvnum[ch->pcdata->pvnum] = 1; } else { act( "You blink and suddenly, $n has ducked away!", ch, NULL, gch, TO_VICT ); gch->pcdata->found_pvnum[ch->pcdata->pvnum] = -1; } } } } pop_call(); return; } /* Contributed by Alander. removed affects that were taken out for Mud20 added greet_trigger so you can't sneak up on a mobile to get around progs - Kregor 2/12/07 */ void do_visible( CHAR_DATA *ch, char *argument ) { bool hidden = FALSE; bool invis = FALSE; int pick = 0; push_call("do_visible(%p,%p)",ch,argument); if (IS_AFFECTED(ch, AFF_INVISIBLE)) { invis = TRUE; pick++; AFFECT_STRIP( ch, AFF_INVISIBLE ); } if (IS_AFFECTED(ch, AFF_HIDE)) { hidden = TRUE; pick++; AFFECT_STRIP( ch, AFF_HIDE ); } if (IS_AFFECTED(ch, AFF_SNEAK)) { act( "Your footfalls become audible once more.", ch, NULL, NULL, TO_CHAR ); pick++; AFFECT_STRIP( ch, AFF_SNEAK ); } if (hidden) { act( "$n steps out of $s concealment.", ch, NULL, NULL, TO_ROOM ); act( "You step out of your concealment.", ch, NULL, NULL, TO_CHAR ); if (ch->furniture && ch->position == POS_CROUCHING) { ch->position = POS_STANDING; user_from_furniture(ch); } } else if (invis) { act( "$n fades slowly into view...", ch, NULL, NULL, TO_ROOM ); act( "You fade slowly into view...", ch, NULL, NULL, TO_CHAR ); } if (!pick) { send_to_char( "You are not concealed in any way.\n\r", ch); } if (!IS_NPC(ch) && (hidden || invis)) { mprog_greet_trigger(ch); } pop_call(); return; } /* * Wizard's familiar - Kregor 3/19/07 */ void do_familiar (CHAR_DATA *ch, char * argument) { char arg[MAX_INPUT_LENGTH]; MOB_INDEX_DATA *pMob; CHAR_DATA *mh; int mob, level, was_room; push_call("do_familiar(%p,%p)",ch,argument); if( IS_NPC( ch ) ) { pop_call(); return; } if ((level = multi_skill_level(ch,gsn_familiar)) <= 0) { send_to_char( "You cannot summon a familiar.\n\r", ch); pop_call(); return; } if (argument[0] == '\0') { if ((mh = get_familiar(ch)) != NULL) { send_to_char( "Syntax: familiar <call|scry|locate>.\n\r", ch); pop_call(); return; } else { send_to_char( "Syntax: familiar <bat|cat|hawk|lizard|owl|rat|raven|snake|toad|weasel> <name> [adjective]\n\r", ch); pop_call(); return; } } argument = one_argument(argument, arg); if ((mh = get_familiar(ch)) != NULL) { if (!strcasecmp(arg, "call")) { if (!mh->in_room && !ch->in_room) { send_to_char( "You cannot seem to reach your familiar.\n\r", ch); pop_call(); return; } if (mh->in_room == ch->in_room) { send_to_char( "Your familiar is already here!\n\r", ch); pop_call(); return; } if (ch->in_room->area != mh->in_room->area || findpath_room(mh, ch->in_room->vnum, 400) == -2) { send_to_char( "You cannot summon your familiar from that far away!\n\r", ch); pop_call(); return; } act( "You send a mental summons to $N.", ch, NULL, mh, TO_CHAR); if (findpath_room(mh, ch->in_room->vnum, 400) == -1) { send_to_char( "Your familiar cannot seem to reach you.\n\r", ch); pop_call(); return; } act( "You sense $N homing $S way to you.", ch, NULL, mh, TO_CHAR); mh->walkto = ch->in_room->vnum; pop_call(); return; } if (!strcasecmp(arg, "locate")) { if (!mh->in_room || mh->in_room->name == NULL || !is_room_good_for_teleport(mh, mh->in_room->vnum)) { send_to_char( "You cannot seem to locate your familiar.\n\r", ch); pop_call(); return; } act( "You sense $N at $t.", ch, mh->in_room->name, mh, TO_CHAR); pop_call(); return; } if (!strcasecmp(arg, "scry")) { if (level < 12) { send_to_char( "You are not high enough level to scry through your familiar.\n\r", ch); pop_call(); return; } if (!mh->in_room || mh->in_room->name == NULL || !is_room_good_for_teleport(mh, mh->in_room->vnum)) { send_to_char( "You cannot seem to scry upon your familiar.\n\r", ch); pop_call(); return; } send_to_char("You attempt to focus in on your familiar's eyes...\n\r", ch); was_room = ch->in_room->vnum; char_from_room(ch); char_to_room(ch, mh->in_room->vnum, FALSE); do_look(ch, ""); char_from_room(ch); char_to_room(ch, was_room, FALSE); pop_call(); return; } send_to_char( "Syntax: familiar <call|scry|locate>.\n\r", ch); pop_call(); return; } else if (!strcasecmp(arg, "scry") || !strcasecmp(arg, "locate") || !strcasecmp(arg, "call")) { send_to_char( "You do not have a familiar.\n\r", ch); pop_call(); return; } if (!strcasecmp(arg, "bat")) mob = MOB_VNUM_COMP_BAT; else if (!strcasecmp(arg, "cat")) mob = MOB_VNUM_COMP_CAT; else if (!strcasecmp(arg, "hawk")) mob = MOB_VNUM_COMP_HAWK; else if (!strcasecmp(arg, "lizard")) mob = MOB_VNUM_COMP_LIZARD; else if (!strcasecmp(arg, "owl")) mob = MOB_VNUM_COMP_OWL; else if (!strcasecmp(arg, "rat")) mob = MOB_VNUM_COMP_RAT; else if (!strcasecmp(arg, "raven")) mob = MOB_VNUM_COMP_RAVEN; else if (!strcasecmp(arg, "snake")) mob = MOB_VNUM_COMP_SNAKE; else if (!strcasecmp(arg, "toad")) mob = MOB_VNUM_COMP_TOAD; else if (!strcasecmp(arg, "weasel")) mob = MOB_VNUM_COMP_WEASEL; else { send_to_char( "Syntax: familiar <bat|cat|hawk|lizard|owl|rat|raven|snake|toad|weasel> <name> [adjective]\n\r", ch); pop_call(); return; } if (argument[0] == '\0') { send_to_char( "You could at least give your familiar a name...\n\r", ch); pop_call(); return; } argument = one_argument(argument, arg); if (!check_legal_name(mh, arg)) { pop_call(); return; } pMob = get_mob_index(mob); mh = create_mobile( pMob ); if (argument[0] != '\0') { RESTRING(mh->name, format("%s %s %s", race_table[mh->race].race_name, arg, argument)); RESTRING(mh->short_descr, format("%s, %s %s %s", capitalize(arg), a_an(argument), argument, race_table[mh->race].race_name)); } else { RESTRING(mh->name, format("%s %s", race_table[mh->race].race_name, arg)); RESTRING(mh->short_descr, format("%s, %s %s", capitalize(arg), a_an(race_table[mh->race].race_name), race_table[mh->race].race_name)); } char_to_room( mh, ch->in_room->vnum, TRUE ); act( "$N answers your call for a familiar.", ch, NULL, mh, TO_CHAR); act( "$N familiar answers $n's call.", ch, NULL, mh, TO_ROOM); mh->max_hit = ch->max_hit / 2; mh->hit = get_max_hit(mh); mh->perm_int = level / 2 + 5; mh->nat_armor = level / 2; SET_BIT(mh->act, ACT_PET|ACT_FAMILIAR|ACT_SENTINEL); add_follower( mh , ch ); pop_call(); return; } /* * The totally gutted, reworked, d20-ized * tracking skill that really works like tracking - Kregor */ void add_tracking (CHAR_DATA *ch, CHAR_DATA *victim) { push_call("add_tracking(%p,%p)",ch,victim); if (ch->pcdata->tracking) { act("You're already tracking someone.", ch, NULL, NULL, TO_CHAR); pop_call(); return; } ch->pcdata->tracking = victim; victim->tracked_by = ch; act ("You are now tracking $N.", ch, NULL, victim, TO_CHAR); pop_call(); return; } void stop_tracking (CHAR_DATA * ch) { push_call("stop_tracking(%p)",ch); if (IS_NPC(ch) || ch->pcdata->tracking == NULL) { pop_call(); return; } ch->pcdata->tracking->tracked_by = NULL; ch->pcdata->tracking = NULL; pop_call(); return; } int track_dc( CHAR_DATA *ch, CHAR_DATA *victim ) { int dc; push_call("track_dc(%p,%p)",ch,victim); switch (ch->in_room->sector_type) { case SECT_DESERT: case SECT_BEACH: case SECT_TUNDRA: dc = 5; break; case SECT_SWAMP: dc = 10; break; case SECT_ROAD: case SECT_FIELD: case SECT_FOREST: case SECT_HILLS: dc = 15; break; case SECT_UNDER_GROUND: case SECT_DEEP_EARTH: case SECT_INSIDE: case SECT_CITY: case SECT_MOUNTAIN: case SECT_RIVER: dc = 20; break; default: dc = 99; break; } if (learned(ch, gsn_scent)) { // give aquatic creatures w scent ability to track in water. if (rspec_req(ch, RSPEC_AQUATIC)) { switch(ch->in_room->sector_type) { case SECT_LAKE: case SECT_RIVER: case SECT_UNDER_WATER: case SECT_OCEAN: dc = UMIN(dc, 10); break; } } else if (dc != 99) { dc = UMIN(dc, 10); } } else // tracking by scent ignores weather, visibility & size { if (mud->time_info->hour > 19 && mud->time_info->hour < 5) { dc += 3; } switch (ch->in_room->area->weather_info->sky) { case 0: dc += 0; break; case 1: dc += 1; break; case 2: dc += 3; break; case 3: dc += 5; break; } if (victim != NULL) { switch (get_size(victim)) { case SIZE_FINE: dc += 8; break; case SIZE_DIMINUTIVE: dc += 4; break; case SIZE_TINY: dc += 2; break; case SIZE_SMALL: dc += 1; break; case SIZE_LARGE: dc -= 1; break; case SIZE_HUGE: dc -= 2; break; case SIZE_GARGANTUAN: dc -= 4; break; case SIZE_COLOSSAL: dc -= 8; break; } } } pop_call(); return dc; } void do_track( CHAR_DATA *ch, char *argument) { int cnt, count; int roll; int TRACK_DIR; CHAR_DATA *victim, *rch; bool fScent = FALSE; push_call("do_track(%p,%p)",ch,argument); if (IS_NPC(ch)) { pop_call(); return; } if ((fScent = learned(ch, gsn_scent)) == FALSE) { if (!learned(ch, gsn_survival)) { send_to_char_color( "You do not have any survival skills.\n\r", ch); pop_call(); return; } if (IS_BLIND(ch) ) { send_to_char_color("You can't see a thing!\n\r",ch); pop_call(); return; } } roll = survival_roll(ch); roll += synergy_bonus(ch, gsn_search); roll += UMAX(1, multi_class_level(ch, gsn_track) / 2); if (argument[0] == '\0') { if (ch->pcdata->tracking) { act("{178}You stop tracking $N.", ch, NULL, ch->pcdata->tracking, TO_CHAR); stop_tracking(ch); pop_call(); return; } if (!learned(ch, gsn_master_hunter) && !ch->concentrating) { if (fScent) { act("$n sniffs at the ground...", ch, NULL, NULL, TO_ROOM); act("You sniff the ground for tracks...", ch, NULL, NULL, TO_CHAR); } else { act("$n studies the ground...", ch, NULL, NULL, TO_ROOM); act("You study the ground for tracks...", ch, NULL, NULL, TO_CHAR); } ch->concentrating = TRUE; ch->skill_timer = learned(ch, gsn_swift_tracker) ? 4 : 12; ch->timer_fun = do_track; RESTRING(ch->cmd_argument, ""); if (!learned(ch, gsn_swift_tracker)) TAKE_ACTION(ch, ACTION_STANDARD); else TAKE_ACTION(ch, ACTION_MOVE); pop_call(); return; } send_to_char_color("{178}You locate the following sets of tracks:\n\r", ch); for (cnt = count = 0 ; cnt < MAX_LAST_LEFT ; cnt++) { if (ch->in_room->last_left_bits[cnt] == 0) continue; if (IS_SET(ch->in_room->last_left_bits[cnt], TRACK_FLY)) continue; TRACK_DIR = UNSHIFT(ch->in_room->last_left_bits[cnt]); if ((rch = get_char_area(ch, ch->in_room->last_left[cnt])) == NULL) { if ((rch = get_char_pvnum(ch->in_room->last_left_pvnum[cnt])) == NULL) { if (survival_check(ch, NULL, roll, track_dc(ch, NULL))) { ch_printf_color(ch, " {300}An unidentifiable set of tracks leading %s.\n\r", dir_name[TRACK_DIR]); count++; } continue; } } if (rch == ch) continue; if (survival_check(ch, rch, roll, track_dc(ch, rch))) { ch_printf_color(ch, " {300}%s leading %s.\n\r", PERS(rch,ch), dir_name[TRACK_DIR]); count++; } } if (!count) { ch_printf_color(ch, " {300}None.\n\r"); } } else { if (!fScent && !learned(ch, gsn_swift_tracker)) { send_to_char_color("Right, maybe if you were a ranger!\n\r", ch); pop_call(); return; } stop_tracking(ch); if (ch->position <= POS_SITTING) { send_to_char_color("You're too relaxed.\n\r", ch); pop_call(); return; } if ((victim = get_char_area(ch, argument)) == NULL) { if ((victim = lookup_char(argument)) == NULL) { send_to_char("You can't find a good enough trail to follow.\n\r", ch); pop_call(); return; } } track_char(ch, victim); } pop_call(); return; } void track_char( CHAR_DATA *ch, CHAR_DATA *victim ) { bool found = FALSE; CHAR_DATA *rch; int dc, cnt, roll, TRACK_DIR; push_call("track_char(%p,%p)",ch,victim); roll = survival_roll(ch); roll += synergy_bonus(ch, gsn_search); dc = track_dc(ch, victim); switch (ch->speed) { case 0: case 1: dc += 0; break; case 2: if (!learned(ch, gsn_master_hunter)) dc += 10; break; default: act("You are traveling too fast to track.", ch, NULL, NULL, TO_CHAR); ch->speed = 2; dc += 10; break; } if (ch->pcdata->tracking) { ch->pcdata->was_in_room = ch->in_room->vnum; if (victim != ch->pcdata->tracking) stop_tracking(ch); } else { for (rch = ch->in_room->first_person ; rch ; rch = rch->next_in_room) { if (!can_see(ch, rch)) { continue; } if (rch == victim) { act( "You're already in the same room as $N.", ch, NULL, rch, TO_CHAR); pop_call(); return; } } } for (cnt = MAX_LAST_LEFT-1 ; cnt >= 0 ; cnt--) { if (ch->in_room->last_left_bits[cnt] == 0) { continue; } if (IS_SET(ch->in_room->last_left_bits[cnt], TRACK_FLY)) { continue; } if (!strcasecmp(ch->in_room->last_left[cnt], victim->name)) { if (survival_check(ch, victim, roll, dc)) { TRACK_DIR = UNSHIFT(ch->in_room->last_left_bits[cnt]); act("{138}You find the tracks of $N leading $t...", ch, dir_name[TRACK_DIR], victim, TO_CHAR); if (!ch->pcdata->tracking) add_tracking(ch, victim); found = TRUE; break; } } } if (found) { TRACK_DIR = UNSHIFT(ch->in_room->last_left_bits[cnt]); if (ch->in_room->exit[TRACK_DIR]->to_room == ch->pcdata->was_in_room) { send_to_char ("{138}Your prey has doubled back!\n\r", ch); stop_tracking(ch); pop_call(); return; } } else { if (!ch->pcdata->tracking) { act("{178}You cannot find any tracks made by $N.", ch, NULL, victim, TO_CHAR); } else { act("{178}$N's tracks end here.", ch, NULL, ch->pcdata->tracking, TO_CHAR); stop_tracking(ch); } } pop_call(); return; } /* * Forage for survival skill, overhauled for D20 - Kregor 12/16/06 */ void do_forage( CHAR_DATA *ch, char *argument ) { CHAR_DATA *gch; push_call("do_forage(%p,%p)",ch,argument); if (IS_NPC(ch)) { pop_call(); return; } if (!learned(ch, gsn_survival)) { send_to_char( "You were never taught to find your own food.\n\r", ch ); pop_call(); return; } if (ch->in_room == NULL || (ch->in_room->sector_type != SECT_FIELD && ch->in_room->sector_type != SECT_FOREST && ch->in_room->sector_type != SECT_HILLS && ch->in_room->sector_type != SECT_MOUNTAIN )) { send_to_char( "There is no food to be found here.\n\r", ch ); pop_call(); return; } if (!ch->concentrating) { act( "You forage about for sustenance...", ch, NULL, NULL, TO_CHAR); act( "$n forages about for sustenance...", ch, NULL, NULL, TO_ROOM); ch->concentrating = TRUE; ch->skill_timer = 16; ch->timer_fun = do_forage; RESTRING(ch->cmd_argument, argument); TAKE_ACTION(ch, ACTION_FULL); pop_call(); return; } int roll, count; roll = survival_roll(ch); if (survival_check(ch, NULL, roll, 10 )) { act( "You find enough food and water to satisfy yourself.", ch, NULL, NULL, TO_CHAR); act( "$n finds enough food and water to satisfy $mself.", ch, NULL, NULL, TO_ROOM); gain_condition( ch, COND_FULL, roll); gain_condition( ch, COND_THIRST, roll); count = (roll - 10)/2; for (gch = ch->in_room->first_person ; gch ; gch = gch->next_in_room) { if (gch == ch) continue; if (count <= 0) { act( "There is no food or water left for anyone else.", ch, NULL, gch, TO_CHAR); act( "There is no food or water left for anyone else.", ch, NULL, gch, TO_ROOM); break; } if (!IS_NPC(gch) && is_same_group(ch, gch)) { if (gch->pcdata->condition[COND_THIRST] < 30 || gch->pcdata->condition[COND_FULL] < 30) { act( "You provide food and water for $N as well.", ch, NULL, gch, TO_CHAR); act( "$n provides enough for you as well.", ch, NULL, gch, TO_VICT); act( "$n provides enough for $N as well.", ch, NULL, gch, TO_NOTVICT); gain_condition( gch, COND_FULL, roll); gain_condition( gch, COND_THIRST, roll); count--; } } } pop_call(); return; } else { send_to_char( "You fail to find any food and water.\n\r", ch ); pop_call(); return; } } /*fishing * * snippet by Hera, of Athens - The Mud athens.boue.ca port 9000 * hera_of_athens@yahoo.com */ void fish_start( CHAR_DATA *ch ) { push_call("fish_start(%p)",ch); OBJ_INDEX_DATA *pObjIndex; OBJ_DATA *fish, *bait; char name[20]; if (IS_NPC(ch)) { pop_call(); return; } for (bait = ch->first_carrying ; bait ; bait = bait->next_content) { if (IS_OBJ_TYPE(bait, ITEM_FOOD)) { break; } } if (!bait) { ch_printf_color(ch, "You need bait!\n\r"); pop_call(); return; } if (!ch->concentrating) { act("You dip your line in to fish...", ch, NULL, NULL, TO_CHAR); act("$n dips his line into the water to fish...", ch, NULL, NULL, TO_ROOM); ch->concentrating = TRUE; ch->skill_timer = dice(2,16); ch->timer_fun = do_fish; RESTRING(ch->cmd_argument, ""); TAKE_ACTION(ch, ACTION_FULL); pop_call(); return; } if ((pObjIndex = get_obj_index(OBJ_VNUM_FISHCATCH)) == NULL) { ch_printf_color(ch, "Try as you might, you can't seem to catch a fish.\n\r"); bug("do_fish: OBJ_VNUM_FISHCATCH non existant."); pop_call(); return; } fish = create_object(pObjIndex,0); switch(dice(1,12)) { case 1: case 7: ch_printf_color(ch, "You get a nibble but the fish leaves without taking the bait.\n\r"); extract_obj(fish); fish = NULL; break; case 2: case 8: ch_printf_color(ch, "A fish steals your bait without getting hooked!\n\r"); extract_obj(bait); extract_obj(fish); fish = NULL; break; case 3: if (ch->in_room->sector_type == SECT_OCEAN) strcpy(name, "tuna"); else strcpy(name, "catfish"); fish->value[0] = 4; extract_obj(bait); break; case 4: if (ch->in_room->sector_type == SECT_OCEAN) strcpy(name, "cod"); else strcpy(name, "bass"); fish->value[0] = 3; extract_obj(bait); break; case 5: if (ch->in_room->sector_type == SECT_OCEAN) strcpy(name, "flounder"); else strcpy(name, "pike"); fish->value[0] = 2; fish->size = SIZE_DIMINUTIVE; extract_obj(bait); break; case 6: if (ch->in_room->sector_type == SECT_OCEAN) strcpy(name, "salmon"); else strcpy(name, "trout"); fish->value[0] = 3; extract_obj(bait); break; case 9: case 10: case 11: case 12: strcpy(name, "tiny fish"); fish->value[0] = 0; fish->size = SIZE_FINE; extract_obj(bait); break; } if (fish != NULL) { RESTRING(fish->long_descr, format("A freshly caught %s lies here.", name)); RESTRING(fish->short_descr, format("a %s", name)); RESTRING(fish->name, format("fish %s", name)); obj_to_char(fish, ch); ch_printf_color(ch, "You caught something!\n\r"); if (fish->value[0] == 0) ch_printf_color(ch, "The fish wouldn't even be a mouthful, but you could use it as bait.\n\r"); act("$n caught a fish!", ch, NULL, NULL, TO_ROOM); } pop_call(); return; } void do_fish( CHAR_DATA *ch, char *argument ) { OBJ_DATA *obj; push_call("do_fish(%p,%p)",ch,argument); if (IS_NPC(ch)) { send_to_char( "NPCs don't need to fish.\n\r", ch ); pop_call(); return; } switch (ch->in_room->sector_type) { case SECT_LAKE: case SECT_RIVER: case SECT_OCEAN: break; default: send_to_char( "You can't fish on dry land.\n\r", ch ); pop_call(); return; } if ((obj = get_obj_wear_type(ch, ITEM_TOOLS)) != NULL && TOOL_TYPE(obj, TOOL_FISHING_POLE)) { fish_start( ch ); pop_call(); return; } send_to_char("You are not holding a fishing pole.\n\r", ch); pop_call(); return; } /* * Camping for survival skill */ void do_camp( CHAR_DATA *ch, char *argument ) { OBJ_DATA *kit; int diceroll; push_call("do_camp(%p,%p)",ch,argument); if(ch->position<=POS_RESTING && in_camp(ch)) { send_to_char("You are already camping.\n\r", ch); pop_call(); return; } if (argument && ch->pcdata->last_combat + 60 > mud->current_time) { ch_printf_color(ch, "{018}Your adrenaline is pumping too hard to set up camp!\n\r"); pop_call(); return; } if (ch->fear_level) { ch_printf_color(ch, "{018}Mind is racing too fast with fear to camp now!\n\r"); pop_call(); return; } if(ch->in_room->sector_type == SECT_CITY) { send_to_char("The city guards would likely arrest you for vagrancy.\n\r", ch); send_to_char("Perhaps you should find an inn instead.\n\r", ch); pop_call(); return; } if(ch->in_room->sector_type == SECT_ROAD) { send_to_char("You should set up camp a little off the beaten path, hm?\n\r", ch); pop_call(); return; } if(ch->position != POS_STANDING) { send_to_char("You must be standing in order to establish a camp.\n\r", ch); pop_call(); return; } diceroll = survival_roll(ch); if ((kit = get_obj_wear_type(ch, ITEM_TOOLS)) != NULL && TOOL_TYPE(kit, TOOL_SURVIVAL_TOOLS)) { if (IS_OBJ_STAT(kit, ITEM_MASTERWORK)) { if (kit->value[2] > 0) diceroll += kit->value[2]; else diceroll += 2; } } if (survival_check(ch, NULL, diceroll, 10)) { if (!can_see_in_room(ch, ch->in_room)) { if (number_percent() > 25) { send_to_char("You fumble around with your tools, but it looks nothing like a camp.\n\r",ch); act( "$n fumbles around with $s tools...\n\r",ch,NULL,NULL,TO_ROOM); } else { send_to_char("You fumble around with your tools, and miraculously you establish a camp!\n\r",ch); act( "$n fumbles around with $s tools, and establishes a camp!\n\r",ch,NULL,NULL,TO_ROOM); ch->position = POS_RESTING; SET_AFFECT(ch, AFF2_CAMPING); } } else { send_to_char("You establish a camp and begin recuperating.\n\r", ch); act( "$n establishes a camp.",ch,NULL,NULL,TO_ROOM); ch->position = POS_RESTING; SET_AFFECT(ch, AFF2_CAMPING); } } else { send_to_char("You fail to establish a good camp.\n\r", ch); } pop_call(); return; } /* * Skin and slice skill from Smaug 1.4a - Kregor 12/16/06 */ void do_skin( CHAR_DATA * ch, char *argument ) { OBJ_DATA *corpse; OBJ_DATA *obj; OBJ_DATA *skin; bool found; char *name = NULL; static char suffix[MAX_INPUT_LENGTH]; found = FALSE; int size; push_call("do_skin(%p,%p)",ch,argument); if (!learned(ch,gsn_survival)) { send_to_char( "You're not that experienced a survivalist.\r\n", ch ); pop_call(); return; } if (argument[0] == '\0') { send_to_char( "What corpse do you wish to skin?\r\n", ch ); pop_call(); return; } if ((corpse = get_obj_here(ch, argument)) == NULL ) { send_to_char( "You cannot find that here.\r\n", ch ); pop_call(); return; } if ((obj = get_obj_wear_type( ch, ITEM_WEAPON )) == NULL || !WEAPON_TYPE(obj, WEAPON_TYPE_KNIFE)) { send_to_char( "You have to wield a knife.\r\n", ch ); pop_call(); return; } if (corpse->item_type != ITEM_CORPSE_NPC && corpse->item_type != ITEM_CORPSE_PC) { send_to_char( "You can only skin corpses.\r\n", ch ); pop_call(); return; } if (corpse->material != MATERIAL_FLESH) { act( "There is no hide to take from $p.", ch, corpse, NULL, TO_CHAR ); pop_call(); return; } if ((size = corpse->value[6]) == 0) { send_to_char( "That corpse has already been skinned.\r\n", ch ); pop_call(); return; } if (get_obj_index(OBJ_VNUM_SKIN) == NULL) { bug( "Vnum %d (OBJ_VNUM_SKIN) not found for do_skin!", OBJ_VNUM_SKIN ); pop_call(); return; } corpse->value[6] = 0; if (!survival_check(ch, NULL, survival_roll(ch), 15)) { act( "You fail to skin $p properly.", ch, corpse, NULL, TO_CHAR ); act( "{018}$n tries to skin $p, and makes a mess.", ch, corpse, NULL, TO_ROOM ); pop_call(); return; } skin = create_object (get_obj_index(OBJ_VNUM_SKIN), 0); sprintf(name, "%s", corpse->short_descr); strcpy(suffix, &name[strlen("the corpse of ")]); RESTRING(skin->name, format("%s%s", skin->name, suffix)); RESTRING(skin->short_descr, format("%s%s", skin->short_descr, suffix)); RESTRING(skin->long_descr, format(skin->long_descr, suffix)); skin->size = size; act( "{018}$n skins the hide from $p.", ch, corpse, NULL, TO_ROOM ); act( "{018}You skins the hide from $p.", ch, corpse, NULL, TO_CHAR ); obj_to_char( skin, ch ); pop_call(); return; } void do_slice( CHAR_DATA * ch, char *argument ) { OBJ_DATA *corpse, *obj, *slice; bool found; found = FALSE; push_call("do_slice(%p,%p)",ch,argument); if (!learned(ch,gsn_survival)) { send_to_char( "You're not that experienced a survivalist.\r\n", ch ); pop_call(); return; } if (argument[0] == '\0') { send_to_char( "What corpse do you wish to slice?\r\n", ch ); pop_call(); return; } if ((corpse = get_obj_here( ch, argument)) == NULL) { send_to_char( "You cannot find that here.\r\n", ch ); pop_call(); return; } if (corpse->item_type != ITEM_CORPSE_NPC && corpse->item_type != ITEM_CORPSE_PC) { send_to_char( "You can only slice corpses.\r\n", ch ); pop_call(); return; } if (corpse->material != MATERIAL_FLESH) { act( "There is no flesh to slice from $p.", ch, corpse, NULL, TO_CHAR ); pop_call(); return; } if ((obj = get_obj_wear_type( ch, ITEM_WEAPON )) == NULL || !WEAPON_TYPE(obj, WEAPON_TYPE_KNIFE)) { send_to_char( "You have to wield a knife.\r\n", ch ); pop_call(); return; } if (corpse->value[5] <= 0) { act( "There's not enough meat left on $p", ch, corpse, NULL, TO_CHAR ); pop_call(); return; } if (get_obj_index(OBJ_VNUM_SLICE) == NULL ) { bug( "Vnum %d (OBJ_VNUM_SLICE) not found for do_slice!", OBJ_VNUM_SKIN ); pop_call(); return; } corpse->value[5]--; if (!survival_check(ch, NULL, survival_roll(ch), 15)) { send_to_char( "{018}You fail to slice the corpse properly.\r\n", ch ); act( "{018}$n tries to slice $p, and makes a mess.", ch, corpse, NULL, TO_ROOM ); corpse->value[5]--; pop_call(); return; } slice = create_object (get_obj_index(OBJ_VNUM_SLICE), 0); act( "{018}$n slices meat from $p.", ch, corpse, NULL, TO_ROOM ); act( "{018}You slice meat from $p.", ch, corpse, NULL, TO_CHAR ); obj_to_room( slice, ch->in_room->vnum ); pop_call(); return; } /* * Locate, urban tracking feat for Streetwise skill - Kregor */ void do_locate( CHAR_DATA *ch, char *argument) { int roll, TRACK_DIR, track_dc, area_size; CHAR_DATA *victim; push_call("do_locate(%p,%p)",ch,argument); if (!learned(ch, gsn_urban_tracking)) { send_to_char_color( "You are not skilled in urban tracking.\n\r", ch); pop_call(); return; } if (IS_NPC(ch)) { pop_call(); return; } if (IS_SET(ch->in_room->area->flags, AFLAG_METROPOLIS)) track_dc = 20; else if (IS_SET(ch->in_room->area->flags, AFLAG_CITY)) track_dc = 15; else if (IS_SET(ch->in_room->area->flags, AFLAG_TOWN)) track_dc = 10; else if (IS_SET(ch->in_room->area->flags, AFLAG_VILLAGE)) track_dc = 5; else { send_to_char("You cannot find enough people to network with here.\n\r", ch); pop_call(); return; } if (mud->time_info->hour > 19 && mud->time_info->hour < 5) { track_dc += 3; } roll = streetwise_roll(ch); area_size = ch->in_room->area->hi_r_vnum - ch->in_room->area->low_r_vnum; if (argument[0] == '\0') { send_to_char("Locate whom?\n\r", ch); pop_call(); return; } if ((victim = get_char_area(ch, argument)) == NULL) { if ((victim = lookup_char(argument)) == NULL) { send_to_char("The local populace can't seem to point you in the right direction.\n\r", ch); act( "$n mills about the local populace, asking many questions about someone.", ch, NULL, NULL, TO_ROOM); pop_call(); return; } } track_dc += synergy_bonus(victim, gsn_bluff); track_dc += multi_class_level(victim, gsn_faceless); if (!streetwise_check(ch, victim, roll, track_dc)) { send_to_char("The local populace can't seem to point you in the right direction.\n\r", ch); act( "$n mills about the local populace, asking many questions about someone.", ch, NULL, NULL, TO_ROOM); pop_call(); return; } if ((TRACK_DIR = findpath_search_victim(ch, victim, area_size)) == -2) { if (can_see(ch, victim)) { act( "You mill about asking about $N, then you find $M in the same room!", ch, NULL, victim, TO_CHAR); act( "$n mills about asking about you, then sees you standing there!", ch, NULL, victim, TO_VICT); act( "$n mills about asking about $N, then finds $M standing there!", ch, NULL, victim, TO_NOTVICT); } else { act( "Someone informs you they saw $M just a moment ago, right here.", ch, NULL, victim, TO_CHAR); } pop_call(); return; } else if (TRACK_DIR == -1) { act( "The local populace says that $N aready left the area.", ch, NULL, victim, TO_CHAR); act( "$n mills about asking residents about $N", ch, NULL, victim, TO_ROOM); pop_call(); return; } act( "The local populace places $N somewhere to the $t of here.", ch, dir_name[TRACK_DIR], victim, TO_CHAR); act( "Some residents point $n somewhere to the $t", ch, dir_name[TRACK_DIR], NULL, TO_ROOM); pop_call(); return; } /* * The much better, totally redone SNATCH command * now turned into a function to wrap into STEAL command * now more checks and includes containers - Kregor */ bool snatch_object( CHAR_DATA *ch, char *arg1, char *arg2 ) { CHAR_DATA *fch; OBJ_DATA *obj, *container; int diceroll, dc; push_call("snatch_object(%p,%p,%p)",ch,arg1,arg2); if (is_string(arg2) && ((container = get_obj_carry(ch, arg2)) != NULL || (container = get_obj_here(ch, arg2)) != NULL)) { if (container->item_type != ITEM_SPELLPOUCH && container->item_type != ITEM_CONTAINER && container->item_type != ITEM_SHEATH && container->item_type != ITEM_CART && container->item_type != ITEM_QUIVER) { act( "$p is not a container.", ch, container, NULL, TO_CHAR ); pop_call(); return FALSE; } if (IS_SET(container->value[1], CONT_CLOSED)) { act( "$p is closed.", ch, container, NULL, TO_CHAR ); pop_call(); return FALSE; } if ((obj = get_obj_list(ch, arg1, container->first_content)) == NULL) { act( "You do not see any $T in $p.", ch, container, arg1, TO_CHAR); pop_call(); return FALSE; } diceroll = sleight_of_hand_roll(ch); dc = get_obj_weight(obj) / 10 + 15; if (get_size(ch) - obj->size < 2) { send_to_char( "That item is too large for you to palm.\n\r", ch ); pop_call(); return FALSE; } if (!get_obj(ch, obj, container, FALSE, FALSE)) { act( "You cannot seem to snatch $p from $P.", ch, obj, container, TO_CHAR); } else { act( "You attempt to snatch $p discreetly from $P.", ch, obj, container, TO_CHAR); if (sleight_of_hand_check(ch, NULL, diceroll, dc)) { for (fch = ch->in_room->first_person ; fch ; fch = fch->next_in_room) { if (ch == fch || fch->position <= POS_SLEEPING) { continue; } if (perception_check(fch, ch, perception_roll(fch, SENSE_SIGHT), diceroll)) { ch_printf_color( fch, "{138}%s tries to snatch %s {138}from %s.", PERS(ch, fch), obj->short_descr, container->short_descr); } } } else { act( "$n gets $p from $P.", ch, obj, container, TO_ROOM); } } TAKE_ACTION(ch, ACTION_STANDARD); pop_call(); return TRUE; } if ((obj = get_obj_list(ch, arg1, ch->in_room->first_content)) == NULL) { pop_call(); return FALSE; } diceroll = sleight_of_hand_roll(ch); dc = get_obj_weight(obj) / 10 + 15; if (get_size(ch) - obj->size < 2) { send_to_char( "That item is too large for you to palm.\n\r", ch ); pop_call(); return FALSE; } if (get_obj(ch, obj, NULL, TRUE, FALSE)) { act( "You attempt to snatch $p unseen.", ch, obj, NULL, TO_CHAR); if (sleight_of_hand_check(ch, NULL, diceroll, dc)) { for (fch = ch->in_room->first_person ; fch ; fch = fch->next_in_room) { if (ch == fch || fch->position <= POS_SLEEPING) { continue; } if (perception_check(fch, ch, perception_roll(fch, SENSE_SIGHT), diceroll)) { act( "{138}You see $N attempt to snatch $p.", fch, obj, ch, TO_CHAR); } } } else { act( "$n gets $p.", ch, obj, NULL, TO_ROOM); } } TAKE_ACTION(ch, ACTION_STANDARD); pop_call(); return TRUE; } /* * Moved pick and steal to skills.c, because even * though they are acts on objects, they are also skills. */ void do_steal( CHAR_DATA *ch, char *argument ) { char buf [MAX_STRING_LENGTH]; char arg1 [MAX_INPUT_LENGTH]; char arg2 [MAX_INPUT_LENGTH]; CHAR_DATA *victim, *fch; OBJ_DATA *obj; bool fCaught = FALSE; bool fSuccess = FALSE; int diceroll, dc; int amount = 0; push_call("do_steal(%p,%p)",ch,argument); if (!learned(ch, gsn_sleight_of_hand)) { send_to_char( "You are not trained in Sleight of Hand.\n\r", ch); pop_call(); return; } if (is_safe(ch, NULL)) { pop_call(); return; } if (!is_handy(ch) || hands_full(ch)) { send_to_char( "You have no free hand to do that.\n\r", ch ); pop_call(); return; } argument = one_argument( argument, arg1 ); argument = one_argument( argument, arg2 ); //allow "from" in command if (!strcasecmp(arg2, "from")) argument = one_argument( argument, arg2 ); if (arg1[0] == '\0') { send_to_char( "Steal what?\n\r", ch ); pop_call(); return; } if (arg2[0] == '\0') { if (!snatch_object(ch, arg1, "")) { send_to_char( "Steal what from whom or what?\n\r", ch ); pop_call(); return; } else { pop_call(); return; } } if ((victim = get_char_room(ch, arg2)) == NULL) { if (!snatch_object(ch, arg1, arg2)) { act( "$t doesn't seem to be here.", ch, arg2, NULL, TO_CHAR ); pop_call(); return; } else { pop_call(); return; } } if (victim == ch) { send_to_char( "Steal from yourself??\n\r", ch ); pop_call(); return; } if (in_combat(victim)) { act( "$N is moving too fast for you to steal from.", ch, NULL, victim, TO_CHAR); pop_call(); return; } if (!can_attack( ch, victim )) { act( "You may not steal from $N at the moment.", ch, NULL, victim, TO_CHAR); pop_call(); return; } diceroll = sleight_of_hand_roll(ch); dc = 20; if (victim->position == POS_SLEEPING) { dc -= 10; } if ( !strcasecmp( arg1, "coin" ) || !strcasecmp( arg1, "coins" ) ) { if (domain_apotheosis(victim, DOMAIN_TRADE) || perception_check(victim, ch, perception_roll(victim, SENSE_TOUCH), diceroll)) { act( "You catch $n reaching for your coin purse.", ch, NULL, victim, TO_VICT); fCaught = TRUE; dc += get_refl_save(victim); } if (!domain_apotheosis(victim, DOMAIN_TRADE) && diceroll >= dc) { amount = victim->gold / number_range(10, 100); if (amount <= 0) { send_to_char("You couldn't grab any coins.\n\r", ch); } else { gold_transaction(ch, amount); gold_transaction(victim, 0 - amount); ch_printf_color(ch, "Bingo! You lift %s from their coin purse.\n\r", format_coins(amount, FALSE)); gain_favor(ch, DOMAIN_TRICKERY, 2); fSuccess = TRUE; } } } else { if ((obj = get_obj_carry_even_invis(victim, arg1)) == NULL) { send_to_char( "You cannot find that.\n\r", ch ); pop_call(); return; } if ( !can_drop_obj( ch, obj ) || IS_SET(obj->extra_flags, ITEM_INVENTORY) || IS_SET(obj->extra_flags, ITEM_NODROP) || obj->item_type == ITEM_QUIVER || obj->item_type == ITEM_SHEATH || obj->item_type == ITEM_SPELLPOUCH || obj->item_type == ITEM_CONTAINER) { send_to_char( "You cannot pry it away from them.\n\r", ch ); pop_call(); return; } if (ch->carry_number >= can_carry_n(ch)) { send_to_char( "You have your hands full.\n\r", ch ); pop_call(); return; } if (get_carry_w(ch) + get_obj_weight( obj ) > can_carry_w( ch ) ) { send_to_char( "That would weigh you down too much to steal it.\n\r", ch ); pop_call(); return; } if (get_size(ch) - obj->size < 2) { send_to_char( "That item is too large for you to palm.\n\r", ch ); pop_call(); return; } diceroll -= UMAX(0, get_obj_weight(obj)/10 - 1); if (domain_apotheosis(victim, DOMAIN_TRADE) || perception_check(victim, ch, perception_roll(victim, SENSE_TOUCH), diceroll)) { act( "{138}You notice $n grabbing for $p.", ch, obj, victim, TO_VICT); fCaught = TRUE; dc += get_refl_save(victim); } if (!domain_apotheosis(victim, DOMAIN_TRADE) && diceroll >= dc) { obj_from_char( obj ); obj_to_char( obj, ch ); act( "You deftly lift $p from $N.", ch, obj, victim, TO_CHAR ); gain_favor(ch, DOMAIN_TRICKERY, 2); fSuccess = TRUE; } } wiz_printf_room( ch, "Sleight of Hand check (%s): diceroll: %d, DC: %d - %s\n\r", get_name(ch), diceroll, dc, diceroll >= dc ? "SUCCESS" : "FAILURE"); if (!IS_NPC(ch)) { if (obj) log_god_printf("STEAL [%s] %s tried to steal %s from %s.", get_time_string(mud->current_time), get_name(ch), obj->name, get_name(victim)); else log_god_printf("STEAL [%s] %s tried to steal coins from %s.", get_time_string(mud->current_time), get_name(ch), get_name(victim)); } if (!fSuccess) { if (fCaught) act ("$N moves suddenly, thwarting your attempt.", ch, NULL, victim, TO_CHAR); else act ("You fail in your attempt to steal.", ch, NULL, victim, TO_CHAR); } for (fch = ch->in_room->first_person ; fch ; fch = fch->next_in_room) { if (ch == fch || victim == fch || fch->position <= POS_SLEEPING) { continue; } if (perception_check(fch, ch, perception_roll(fch, SENSE_SIGHT), diceroll)) { ch_printf_color(fch, "%s tried to steal something from %s.\n\r", capitalize(PERS(ch,fch)), PERS(victim,fch)); if (!IS_NPC(ch) && IS_GUARD(fch) && IS_CITIZEN(victim)) { sprintf(buf, "Alarm! %s is a thief!!", adjective(ch)); do_shout(fch, buf); fight(fch, ch); } } } if (fCaught) { if (IS_NPC(victim)) { if (!IS_NPC(ch)) ch->pcdata->theft_grudge[victim->pIndexData->vnum]++; if (CAN_TALK(victim)) { sprintf(buf, "%s is a bloody thief!", adjective(ch)); do_shout( victim, buf ); } if (IS_CITIZEN(victim)) { check_guard_assist(victim, ch); act( "$n runs off to report the crime.", victim, NULL, NULL, TO_ROOM); set_bounty(victim, ch, CRIME_MUGGING); junk_mob(victim); gain_reputation(ch, -1); } else if (IS_ACT(victim, ACT_WIMPY)) { act( "$n skitters away!", victim, NULL, NULL, TO_ROOM); junk_mob(victim); } else { fight( victim, ch ); } } } TAKE_ACTION(ch, ACTION_STANDARD); pop_call(); return; } /* * Revised PLANT command, with containers, and room, for sleight of hand - Kregor */ void do_plant( CHAR_DATA *ch, char *argument ) { char arg1 [MAX_INPUT_LENGTH]; char arg2 [MAX_INPUT_LENGTH]; CHAR_DATA *victim = NULL; CHAR_DATA *fch; OBJ_DATA *obj, *container; int diceroll, dc; push_call("do_plant(%p,%p)",ch,argument); if (!learned(ch, gsn_sleight_of_hand)) { send_to_char( "You are not trained in Sleight of Hand.\n\r", ch); pop_call(); return; } if (!is_handy(ch) || hands_full(ch)) { send_to_char( "You have no free hand to do that.\n\r", ch ); pop_call(); return; } argument = one_argument( argument, arg1 ); argument = one_argument( argument, arg2 ); if (arg1[0] == '\0' || arg2[0] == '\0') { send_to_char( "Syntax: plant <object> <victim|container|room>\n\r", ch ); pop_call(); return; } if ((obj = get_obj_carry(ch, arg1)) == NULL) { send_to_char( "You do not have that item.\n\r", ch ); pop_call(); return; } if (!IS_CARRIED(obj)) { send_to_char( "You aren't carrying that.\n\r", ch ); pop_call(); return; } if (IS_WORN(obj)) { send_to_char( "You must remove it first.\n\r", ch ); pop_call(); return; } if (!can_drop_obj(ch, obj)) { send_to_char( "You cannot let go of it.\n\r", ch ); pop_call(); return; } if (get_size(ch) - obj->size < 2) { send_to_char( "That item is too large for you to palm.\n\r", ch ); pop_call(); return; } diceroll = sleight_of_hand_roll(ch); diceroll -= UMAX(0, get_obj_weight(obj)/10 - 1); // plant in room if (!strcasecmp(arg2, "room")) { if (IS_OBJ_STAT(obj, ITEM_HIDDEN)) { send_to_char( "You cannot let go of it.\n\r", ch ); pop_call(); return; } if (!ch->in_room || IS_SET(ch->in_room->room_flags, ROOM_NO_COVER)) { send_to_char( "There's nowhere to hide it!\n\r", ch ); pop_call(); return; } if (in_combat(ch)) dc = 20; else dc = 10; if (sleight_of_hand_check(ch, NULL, diceroll, dc)) { obj_from_char(obj); if (IS_OBJ_STAT(obj, ITEM_CONCEALED)) REMOVE_BIT(obj->extra_flags,ITEM_CONCEALED); SET_BIT(obj->extra_flags,ITEM_HIDDEN); obj->value[7] = diceroll; obj_to_room( obj, ch->in_room->vnum ); act( "You attempt to hide $p in your surroundings.",ch,obj,NULL,TO_CHAR); pop_call(); return; for (fch = ch->in_room->first_person ; fch ; fch = fch->next_in_room) { if (ch == fch || fch == victim || !IS_AWAKE(fch)) { continue; } if (perception_check(fch, ch, perception_roll(fch, SENSE_SIGHT), diceroll)) { act( "{138}$N tries to plant $p nearby.", fch, obj, ch, TO_CHAR ); } } } else { if (IS_OBJ_STAT(obj, ITEM_CONCEALED)) REMOVE_BIT(obj->extra_flags,ITEM_CONCEALED); act( "$n tries to plant $p nearby, and fails.", ch, obj, NULL, TO_ROOM); act( "You fail to plant $p in your surroundings.",ch, obj, NULL, TO_CHAR); pop_call(); return; } TAKE_ACTION(ch, ACTION_STANDARD); pop_call(); return; } //plant in container if ((container = get_obj_carry(ch, arg2)) != NULL || (container = get_obj_here(ch, arg2)) != NULL) { if (container->item_type != ITEM_SPELLPOUCH && container->item_type != ITEM_CONTAINER && container->item_type != ITEM_SHEATH && container->item_type != ITEM_CART && container->item_type != ITEM_QUIVER) { act( "$p is not a container.", ch, container, NULL, TO_CHAR ); pop_call(); return; } if (IS_SET(container->value[1], CONT_CLOSED)) { act( "$p is closed.", ch, container, NULL, TO_CHAR ); pop_call(); return; } if (in_combat(ch)) { if (container->carried_by == ch) { dc = 15; } else { dc = 20; } } else dc = 10; if (sleight_of_hand_check(ch, victim, diceroll, dc)) { if (put_obj(ch, obj, container, FALSE, FALSE)) { act( "You attempt to slip $p discreetly into $P.", ch, obj, container, TO_CHAR); for (fch = ch->in_room->first_person ; fch ; fch = fch->next_in_room) { if (ch == fch || fch == victim || !IS_AWAKE(fch)) { continue; } if (perception_check(fch, ch, perception_roll(fch, SENSE_SIGHT), diceroll)) { ch_printf_color( fch, "{138}%s tries to slip %s {138}into %s.\n\r", PERS(ch, fch), obj->short_descr, container->short_descr); } } } else { act( "You cannot seem to plant $p in $P.", ch, obj, container, TO_CHAR); } } else { put_obj(ch, obj, container, TRUE, TRUE); } TAKE_ACTION(ch, ACTION_STANDARD); pop_call(); return; } //plant on person if ((victim = get_char_room(ch, arg2)) == NULL) { send_to_char( "They aren't here.\n\r", ch ); pop_call(); return; } if (find_keeper(ch) == victim) { send_to_char( "You may only sell items to a shop keeper.\n\r", ch ); pop_call(); return; } CHECK_TURN(ch, victim); if (get_carry_w(victim) + get_obj_weight(obj) > can_carry_w(victim)) { act( "That is too heavy to plant on $N.", ch, NULL, victim, TO_CHAR ); pop_call(); return; } if (in_combat(victim) || in_combat(ch)) dc = 30; else dc = 20; if (domain_apotheosis(victim, DOMAIN_TRADE) || perception_check(victim, ch, perception_roll(victim, SENSE_SIGHT), diceroll)) { act( "{138}$n tries to plant something on you!", ch, obj, victim, TO_VICT); dc += get_refl_save(victim); } if (domain_apotheosis(victim, DOMAIN_TRADE) || !sleight_of_hand_check(ch, victim, diceroll, dc)) { act( "$N moves suddenly, thwarting your attempt to plant $p.", ch, obj, victim, TO_CHAR); for (fch = ch->in_room->first_person ; fch ; fch = fch->next_in_room) { if (ch == fch || fch == victim || fch->position <= POS_SLEEPING) { continue; } if (perception_check(fch, ch, perception_roll(fch, SENSE_SIGHT), diceroll)) { ch_printf_color( fch, "{138}%s tries to plant something on %s.\n\r", PERS(ch, fch), PERS(victim, fch)); } } } else { act( "You attempt to plant $p on $N.", ch, obj, victim, TO_CHAR); if (IS_OBJ_STAT(obj, ITEM_CONCEALED)) { REMOVE_BIT(obj->extra_flags, ITEM_CONCEALED); } obj_from_char( obj ); obj_to_char( obj, victim ); if (perception_check(victim, ch, perception_roll(victim, SENSE_TOUCH), diceroll)) { act( "{138}$n attempts to plant $p on you!", ch, obj, victim, TO_VICT); } for (fch = ch->in_room->first_person ; fch ; fch = fch->next_in_room) { if (ch == fch || fch == victim || fch->position <= POS_SLEEPING) { continue; } if (perception_check(fch, ch, perception_roll(fch, SENSE_SIGHT), diceroll)) { ch_printf_color( fch, "{138}%s tries to plant %s {138}on %s.\n\r", PERS(ch, fch), obj->short_descr, PERS(victim, fch)); } } } TAKE_ACTION(ch, ACTION_STANDARD); pop_call(); return; } /* * Pick for the Open Lock skill */ void do_pick( CHAR_DATA *ch, char *argument ) { char arg[MAX_INPUT_LENGTH]; CHAR_DATA *gch; OBJ_DATA *obj; int door, dc, diceroll; push_call("do_pick(%p,%p)",ch,argument); if (!check_blind(ch)) { pop_call(); return; } if (!IS_NPC(ch) && !learned(ch, gsn_pick_lock) && !learned(ch, gsn_jack_of_all_trades)) { act( "You wouldn't even begin to know how to do that!", ch, NULL, NULL, TO_CHAR); pop_call(); return; } if (!is_handy(ch) || hands_full(ch)) { send_to_char( "You have no free hand to do that.\n\r", ch ); pop_call(); return; } one_argument(argument, arg); if (arg[0] == '\0') { send_to_char( "Pick what?\n\r", ch ); pop_call(); return; } if ((door = find_door(ch, arg)) >= 0) { ROOM_INDEX_DATA *to_room; EXIT_DATA *pExit; EXIT_DATA *pExit_rev; pExit = ch->in_room->exit[door]; if (!IS_SET(pExit->exit_info, EX_CLOSED)) { act( "The $d is not closed.", ch, pExit->keyword, NULL, TO_CHAR); pop_call(); return; } if (!IS_SET(pExit->exit_info, EX_LOCKED) || IS_SET(pExit->exit_info, EX_KNOCKED)) { act( "The $d is already unlocked.", ch, pExit->keyword, NULL, TO_CHAR); pop_call(); return; } if (pExit->key == -1) { act( "There is no lock to pick.", ch, NULL, NULL, TO_CHAR); pop_call(); return; } if (pExit->key == -2) { send_to_char("You could just try using the latch to UNLOCK it?\n\r", ch); pop_call(); return; } if (!ch->concentrating) { /* look for guards */ for (gch = ch->in_room->first_person ; gch ; gch = gch->next_in_room) { if (!can_see(ch, gch)) continue; if (IS_GUARD(gch)) { do_say(gch, "You, there! What do you think you are doing?"); act( "$N shoves you away from the lock!", ch, NULL, gch, TO_CHAR ); pop_call(); return; } } act( "You set to work picking the $d...", ch, pExit->keyword, NULL, TO_CHAR); act( "$n sets to work picking the $d...", ch, pExit->keyword, NULL, TO_ROOM); ch->concentrating = TRUE; ch->skill_timer = 16; ch->timer_fun = do_pick; RESTRING(ch->cmd_argument, argument); TAKE_ACTION(ch, ACTION_FULL); pop_call(); return; } if (IS_SET(pExit->exit_info, EX_PICKPROOF) || IS_SET(pExit->exit_info, EX_MAGICAL_LOCK)) { act( "The $d is barred from passage.", ch, pExit->keyword, NULL, TO_CHAR); pop_call(); return; } diceroll = pick_lock_roll(ch); dc = lock_dc(pExit, NULL); if (!pick_lock_check(ch, NULL, diceroll, dc)) { act( "You attempt to pick the $d's lock but fail.", ch, pExit->keyword, NULL, TO_CHAR); act( "$n attempts to pick the $d's lock but fails.", ch, pExit->keyword, NULL, TO_ROOM); pop_call(); return; } REMOVE_BIT(pExit->exit_info, EX_LOCKED); act( "A satisfying 'click' tells you the $d's lock is open.", ch, pExit->keyword, NULL, TO_CHAR); act( "$n picks the $d's lock with a gentle 'click'.", ch, pExit->keyword, NULL, TO_ROOM); /* * pick the other side */ if ((to_room = room_index[pExit->to_room]) != NULL && (pExit_rev = to_room->exit[rev_dir[door]]) != NULL && room_index[pExit_rev->to_room] == ch->in_room) { REMOVE_BIT( pExit_rev->exit_info, EX_LOCKED ); } pop_call(); return; } /* * pick a container */ if ((obj = get_obj_here(ch, arg)) != NULL) { if (obj->item_type == ITEM_CONTAINER) { if (!IS_SET(obj->value[1], CONT_CLOSED)) { act( "$p is not closed.", ch, obj, NULL, TO_CHAR); pop_call(); return; } if (!IS_SET(obj->value[1], CONT_LOCKED) || IS_SET(obj->value[1], CONT_KNOCKED)) { act( "$p is already unlocked.", ch, obj, NULL, TO_CHAR); pop_call(); return; } if (obj->value[2] == -1) { act( "$p has no lock to pick.", ch, obj, NULL, TO_CHAR); pop_call(); return; } if (!ch->concentrating) { act( "You set to work picking the $p...", ch, obj, NULL, TO_CHAR); act( "$n sets to work picking the $p...", ch, obj, NULL, TO_ROOM); ch->concentrating = TRUE; ch->skill_timer = 16; ch->timer_fun = do_pick; RESTRING(ch->cmd_argument, argument); TAKE_ACTION(ch, ACTION_FULL); pop_call(); return; } if (IS_SET(obj->value[1], CONT_PICKPROOF) || IS_SET(obj->value[1], CONT_MAGICAL_LOCK)) { act( "$p's lock cannot be picked.", ch, obj, NULL, TO_CHAR); pop_call(); return; } diceroll = pick_lock_roll(ch); dc = lock_dc(NULL, obj); if (!pick_lock_check(ch, NULL, diceroll, dc)) { act( "You attempt to pick $p's lock but fail.", ch, obj, NULL, TO_CHAR); act( "$n attempts to pick $p's lock but fails.", ch, obj, NULL, TO_ROOM); pop_call(); return; } REMOVE_BIT(obj->value[1], CONT_LOCKED); act( "You pick $p's lock with a satifying 'click'.", ch, obj, NULL, TO_CHAR); act( "$n picks $p's lock with a gentle 'click'.", ch, obj, NULL, TO_ROOM); TAKE_ACTION(ch, ACTION_STANDARD); pop_call(); return; } if (obj->item_type == ITEM_PORTAL) { if (!IS_SET(obj->value[2], PORTAL_CLOSED)) { act( "$p is not closed.", ch, obj, NULL, TO_CHAR); pop_call(); return; } if (!IS_SET(obj->value[2], PORTAL_LOCKED) || IS_SET(obj->value[2], PORTAL_KNOCKED)) { act( "$p is already unlocked.", ch, obj, NULL, TO_CHAR); pop_call(); return; } if (obj->value[1] == -1) { act( "$p has no lock to pick.", ch, obj, NULL, TO_CHAR); pop_call(); return; } if (!ch->concentrating) { act( "You set to work unlocking the $p...", ch, obj, NULL, TO_CHAR); act( "$n sets to work unlocking the $p...", ch, obj, NULL, TO_ROOM); ch->concentrating = TRUE; ch->skill_timer = 16; ch->timer_fun = do_pick; RESTRING(ch->cmd_argument, argument); TAKE_ACTION(ch, ACTION_FULL); pop_call(); return; } if (IS_SET(obj->value[2], PORTAL_PICKPROOF)) { act( "$p's lock cannot be picked.", ch, obj, NULL, TO_CHAR); pop_call(); return; } diceroll = pick_lock_roll(ch); dc = lock_dc(NULL, obj); if (!pick_lock_check(ch, NULL, diceroll, dc)) { act( "You attempt to pick $p's lock but fail.", ch, obj, NULL, TO_CHAR); act( "$n attempts to pick $p's lock but fails.", ch, obj, NULL, TO_ROOM); pop_call(); return; } REMOVE_BIT(obj->value[2], PORTAL_LOCKED); act( "You pick $p's lock with a satifying 'click'.", ch, obj, NULL, TO_CHAR); act( "$n picks $p's lock with a gentle 'click'.", ch, obj, NULL, TO_ROOM); TAKE_ACTION(ch, ACTION_STANDARD); pop_call(); return; } else { act( "$p is not a container or portal.", ch, obj, NULL, TO_CHAR); pop_call(); return; } } else { act( "You see no $T here.", ch, NULL, arg, TO_CHAR ); } pop_call(); return; } /* * For the Disable Device skill */ void do_disable( CHAR_DATA *ch, char *argument ) { char arg[MAX_INPUT_LENGTH]; OBJ_DATA *obj, *trap; int door, diceroll, dc, ranks, check; push_call("do_disable(%p,%p)",ch,argument); if (!check_blind(ch)) { pop_call(); return; } if (!IS_NPC(ch) && !learned(ch, gsn_disable_device) && !learned(ch, gsn_jack_of_all_trades)) { act( "You wouldn't even begin to know how to do that!", ch, NULL, NULL, TO_CHAR); pop_call(); return; } if (!is_handy(ch) || hands_full(ch)) { send_to_char( "You have no free hand to do that.\n\r", ch ); pop_call(); return; } one_argument(argument, arg); if (arg[0] == '\0') { send_to_char( "Disable what?\n\r", ch ); pop_call(); return; } /* disarm a move or door direction */ if ((door = find_door(ch, arg)) >= 0) { EXIT_DATA *pExit; pExit = ch->in_room->exit[door]; if ((trap = get_room_trap(ch->in_room, trap_dir[door]|trap_door[door])) == NULL) { send_to_char( "There is nothing to disable in that direction.\n\r", ch ); pop_call(); return; } dc = trap_dc(trap); if (!ch->concentrating) { act( "You set to work disarming a trap to the $t...", ch, dir_name[door], NULL, TO_CHAR); act( "$n sets to work disarming a trap to the $t...", ch, dir_name[door], NULL, TO_ROOM); ch->concentrating = TRUE; ch->skill_timer = 16; ch->timer_fun = do_disable; RESTRING(ch->cmd_argument, argument); TAKE_ACTION(ch, ACTION_FULL); pop_call(); return; } diceroll = disable_device_roll(ch); if ((ranks = multi_class_level(ch, gsn_trapfinding)) > 0) diceroll += UMAX(1, ranks/2); if ((check = disable_device_check(ch, NULL, diceroll, dc)) <= -5) { if (spring_trap(ch, trap)) { pop_call(); return; } } else if (check < 0) { act( "You fail to disable the trap.", ch, NULL, NULL, TO_CHAR); act( "$n fails to disable the trap.", ch, NULL, NULL, TO_ROOM); pop_call(); return; } act( "You successfully disarm the trap.", ch, NULL, NULL, TO_CHAR); act( "$n successfully disarms trap.", ch, NULL, NULL, TO_ROOM); TRAP_STATE(trap) = TRAP_UNARMED; pop_call(); return; } /* * detrap an object */ if ((obj = get_obj_here(ch, arg)) != NULL) { if ((trap = get_obj_trap(obj)) == NULL) { act( "$p is not trapped.", ch, obj, NULL, TO_CHAR); pop_call(); return; } diceroll = disable_device_roll(ch); if ((ranks = multi_class_level(ch, gsn_trapfinding)) > 0) diceroll += UMAX(1, ranks/2); dc = trap_dc(trap); if (!ch->concentrating) { act( "You set to work detrapping $p...", ch, obj, NULL, TO_CHAR); act( "$n sets to work detrapping $p...", ch, obj, NULL, TO_ROOM); ch->concentrating = TRUE; ch->skill_timer = 12; ch->timer_fun = do_disable; RESTRING(ch->cmd_argument, argument); TAKE_ACTION(ch, ACTION_FULL); pop_call(); return; } if ((check = disable_device_check(ch, NULL, diceroll, dc)) <= -5) { if (spring_trap(ch, trap)) { pop_call(); return; } } if (check < 0) { act( "You fail to disable the trap.", ch, NULL, NULL, TO_CHAR); act( "$n fails to disable the trap.", ch, NULL, NULL, TO_ROOM); pop_call(); return; } act( "You successfully disarm the trap.", ch, NULL, NULL, TO_CHAR); act( "$n successfully disarms trap.", ch, NULL, NULL, TO_ROOM); TRAP_STATE(trap) = TRAP_UNARMED; pop_call(); return; } else { act( "You see no $T here.", ch, NULL, arg, TO_CHAR ); } pop_call(); return; } /* * snagged from GodWars code, but redone for Mud20 standard - Kregor */ void do_tie( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; OBJ_DATA *rope; AFFECT_DATA af; char arg[MAX_INPUT_LENGTH]; int bonus; push_call("do_tie()"); if (*argument == '\0') { send_to_char("Tie up whom?\n\r", ch); pop_call(); return; } argument = one_argument( argument, arg ); if ((victim = get_char_room(ch, arg)) == NULL) { send_to_char("They aren't here.\n\r", ch); pop_call(); return; } if (victim == ch) { send_to_char("You cannot tie yourself up!\n\r", ch); pop_call(); return; } if (IS_AFFECTED(victim, AFF2_TIED_UP)) { act("$N is already tied up.", ch, NULL, victim, TO_CHAR); pop_call(); return; } if (!IS_HELPLESS(victim)) { send_to_char("You can only tie up a defenseless person.\n\r", ch); pop_call(); return; } if (is_safe(ch, victim)) { send_to_char("Wards of peace prevent you from doing that.\n\r", ch); pop_call(); return; } for (rope = ch->first_carrying ; rope ; rope = rope->next) { if (TOOL_TYPE(rope, TOOL_ROPE)) break; if (TOOL_TYPE(rope, TOOL_SHACKLES)) break; } if (!rope) { act("You have nothing to tie $N up with.", ch, NULL, victim, TO_CHAR); pop_call(); return; } if (!ch->concentrating) { act( "You quickly set to tying up $N...", ch, NULL, victim, TO_CHAR); act( "$n quickly sets to tying up $N...", ch, NULL, victim, TO_NOTVICT); act( "$n quickly sets to tying you up...", ch, NULL, victim, TO_VICT); ch->concentrating = TRUE; ch->skill_timer = 16; ch->timer_fun = do_tie; RESTRING(ch->cmd_argument, argument); TAKE_ACTION(ch, ACTION_FULL); pop_call(); return; } if (TOOL_TYPE(rope, TOOL_SHACKLES)) { bonus = 30; } else { bonus = dice(1,20) + combat_maneuver_bonus(ch) + synergy_bonus(ch, gsn_escape_artist); } if (IS_OBJ_STAT(rope, ITEM_MASTERWORK)) { bonus += UMAX(5, rope->value[2]); } af.type = -1; af.duration = -1; af.location = APPLY_NONE; af.modifier = bonus; af.bittype = AFFECT_TO_CHAR; af.bitvector = AFF2_TIED_UP; af.level = ch->level; affect_join( ch, victim, &af ); act("You tightly bind $N.", ch, NULL, victim, TO_CHAR); act("$n binds $N.", ch, NULL, victim, TO_ROOM); send_to_char("You have been tied up!\n\r",victim); obj_from_char(rope); obj_to_char(rope, victim); pop_call(); return; } void do_untie( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; AFFECT_DATA *paf; char arg[MAX_INPUT_LENGTH]; push_call("do_tie()"); if (*argument == '\0') { send_to_char("Untie whom?\n\r", ch); pop_call(); return; } argument = one_argument(argument, arg); if ((victim = get_char_room(ch, arg)) == NULL) { send_to_char("They aren't here.\n\r", ch); pop_call(); return; } for (paf = victim->first_affect ; paf ; paf = paf->next) { if (paf->bitvector == AFF2_TIED_UP) break; } if (!paf) { if (victim == ch) act("You are not tied up.", ch, NULL, NULL, TO_CHAR); else act("$N is not tied up.", ch, NULL, victim, TO_CHAR); pop_call(); return; } if (!ch->concentrating) { if (ch == victim) { act( "You attempt to escape your bonds...", victim, NULL, NULL, TO_CHAR); act( "$n attempts to escape $s bonds...", victim, NULL, NULL, TO_ROOM); } else { act( "You begin untying $N...", ch, NULL, victim, TO_CHAR); act( "$n begins untying $N...", ch, NULL, victim, TO_NOTVICT); act( "$n begins untying you...", ch, NULL, victim, TO_VICT); } ch->concentrating = TRUE; ch->skill_timer = 16; ch->timer_fun = do_untie; RESTRING(ch->cmd_argument, argument); TAKE_ACTION(ch, ACTION_FULL); pop_call(); return; } // added in skill check for escape artist, to allow victim to unbind himself - Kregor. if (victim == ch) { if (!escape_artist_check(ch, NULL, escape_artist_roll(ch), UMAX(20, paf->modifier))) { act("You fail to break free.", victim, NULL, NULL, TO_CHAR); act("$n fails to break free.", victim, NULL, NULL, TO_ROOM); pop_call(); return; } } act("You are untied.", victim, NULL, NULL, TO_CHAR); act("$n in untied.", victim, NULL, NULL, TO_ROOM); affect_from_char(victim, paf); pop_call(); return; } /* * It's cleaner to make this a function - Kregor */ int synergy_bonus( CHAR_DATA *ch, int sn ) { int ranks, bonus; push_call("synergy_bonus(%p)",ch); if ((ranks = learned(ch, sn)) < 5) { pop_call(); return 0; } bonus = ranks / 5 + 1; pop_call(); return bonus; } /* * Skill check functions - Kregor */ int appraise_roll( CHAR_DATA *ch, OBJ_DATA *obj ) { int roll; int ranks = learned(ch, gsn_appraise); push_call("appraise_roll(%p)",ch); if (obj && IS_OBJ_STAT(obj, ITEM_MAGIC) && learned(ch, gsn_scholar)) roll = 20; else roll = dice(1,20); roll += stat_mods(ch, APPLY_INT); if (domain_skill(ch, gsn_divine_mercantilism)) roll += UMIN(class_level(ch, CLASS_CLERIC), stat_bonus(TRUE, ch, APPLY_WIS)); roll += ranks; roll += get_apply(ch, APPLY_APPRAISE); if (learned(ch, gsn_silver_palm)) roll += ranks / 5 + 2; if (has_familiar(ch, RACE_BIRD)) roll += 3; // strip one-shot enhancements if (is_affected(ch, gsn_guidance)) affect_strip(ch, gsn_guidance); if (is_affected(ch, gsn_moment_of_prescience)) affect_strip(ch, gsn_moment_of_prescience); pop_call(); return( roll ); } int bluff_roll( CHAR_DATA *ch ) { int roll; int ranks = learned(ch, gsn_bluff); push_call("bluff_roll(%p)",ch); roll = dice(1,20); if (domain_apotheosis(ch, DOMAIN_TRICKERY)) roll = UMAX(roll, dice(1,20)); roll += stat_mods(ch, APPLY_CHA); roll += ranks; if (domain_skill(ch, gsn_divine_trickery)) roll += UMIN(class_level(ch, CLASS_CLERIC), stat_bonus(TRUE, ch, APPLY_WIS)); roll += multi_class_level(ch, gsn_oratory) / 2; roll += get_apply(ch, APPLY_BLUFF); if (learned(ch, gsn_deceitful)) roll += ranks / 5 + 2; if (has_familiar(ch, RACE_SNAKE)) roll += 3; if (get_monk_style(ch) == STYLE_PASSIVE_WAY) roll += 2; if (learned(ch, gsn_serpents_tongue)) roll += 4; // strip one-shot enhancements if (is_affected(ch, gsn_guidance)) affect_strip(ch, gsn_guidance); if (is_affected(ch, gsn_moment_of_prescience)) affect_strip(ch, gsn_moment_of_prescience); pop_call(); return( roll ); } int feint_roll( CHAR_DATA *ch ) { int roll; int ranks; push_call("feint_roll(%p)",ch); if (learned(ch, gsn_agile_feint)) { roll = dice(1,20); ranks = base_attack(ch); roll += stat_mods(ch, APPLY_DEX); roll += ranks; if (learned(ch, gsn_deceitful)) roll += ranks / 5 + 2; if (domain_skill(ch, gsn_divine_trickery)) roll += UMIN(class_level(ch, CLASS_CLERIC), stat_bonus(TRUE, ch, APPLY_WIS)); if (has_familiar(ch, RACE_SNAKE)) roll += 3; if (get_monk_style(ch) == STYLE_PASSIVE_WAY) roll += 2; // strip one-shot enhancements if (is_affected(ch, gsn_guidance)) affect_strip(ch, gsn_guidance); if (is_affected(ch, gsn_moment_of_prescience)) affect_strip(ch, gsn_moment_of_prescience); } else { roll = bluff_roll(ch); } pop_call(); return( roll ); } int climb_roll( CHAR_DATA *ch ) { int roll; int ranks = learned(ch, gsn_climb); push_call("climb_roll(%p)",ch); roll = take_ten(ch); roll += ranks; /* feat added for races which use dex instead of str to climb */ if (learned(ch, gsn_agile_climber)) roll += stat_mods(ch, APPLY_DEX); else roll += stat_mods(ch, APPLY_STR); roll += get_apply(ch, APPLY_CLIMB); if (IS_BLIND(ch)) roll -= 4; roll -= armor_check_penalty(ch); if (learned(ch, gsn_athletic)) roll += ranks / 5 + 2; if (has_familiar(ch, RACE_LIZARD)) roll += 3; // strip one-shot enhancements if (is_affected(ch, gsn_guidance)) affect_strip(ch, gsn_guidance); if (is_affected(ch, gsn_moment_of_prescience)) affect_strip(ch, gsn_moment_of_prescience); pop_call(); return( roll ); } int concentration_roll( CHAR_DATA *ch ) { int roll; int ranks = learned(ch, gsn_concentration); push_call("concentration_roll(%p)",ch); roll = take_ten(ch); roll += stat_mods(ch, APPLY_CON); roll += ranks; roll += get_apply(ch, APPLY_CONCENTRATE); if (get_monk_style(ch) == STYLE_UNDYING_WAY) roll += 2; // strip one-shot enhancements if (is_affected(ch, gsn_guidance)) affect_strip(ch, gsn_guidance); if (is_affected(ch, gsn_moment_of_prescience)) affect_strip(ch, gsn_moment_of_prescience); pop_call(); return( roll ); } int decipher_script_roll( CHAR_DATA *ch ) { int roll; int ranks; push_call("decipher_script_roll(%p)",ch); if ((ranks = learned(ch, gsn_decipher_script)) <= 0 && !learned(ch, gsn_jack_of_all_trades)) { pop_call(); return( -99 ); } roll = take_ten(ch); roll += stat_mods(ch, APPLY_INT); roll += ranks; roll += get_apply(ch, APPLY_DECIPHER); if (learned(ch, gsn_linguist)) roll += ranks / 5 + 2; roll += multi_class_level(ch, gsn_greater_lore); // strip one-shot enhancements if (is_affected(ch, gsn_guidance)) affect_strip(ch, gsn_guidance); if (is_affected(ch, gsn_moment_of_prescience)) affect_strip(ch, gsn_moment_of_prescience); pop_call(); return( roll ); } int diplomacy_roll( CHAR_DATA *ch ) { int roll; int ranks = learned(ch, gsn_diplomacy); push_call("diplomacy_roll(%p)",ch); roll = dice(1,20); roll += stat_mods(ch, APPLY_CHA); if (domain_skill(ch, gsn_divine_mercantilism)) roll += UMIN(class_level(ch, CLASS_CLERIC), stat_bonus(TRUE, ch, APPLY_WIS)); roll += ranks; roll += multi_class_level(ch, gsn_oratory) / 2; roll += get_apply(ch, APPLY_DIPLOMACY); if (learned(ch, gsn_persuasive)) roll += ranks / 5 + 2; roll += synergy_bonus(ch, gsn_bluff); roll += synergy_bonus(ch, gsn_sense_motive); roll += synergy_bonus(ch, gsn_know_nobility); // strip one-shot enhancements if (is_affected(ch, gsn_guidance)) affect_strip(ch, gsn_guidance); if (is_affected(ch, gsn_moment_of_prescience)) affect_strip(ch, gsn_moment_of_prescience); pop_call(); return( roll ); } int disable_device_roll( CHAR_DATA *ch ) { int roll; int ranks; push_call("disable_device_roll(%p)",ch); if ((ranks = learned(ch, gsn_disable_device)) <= 0 && !learned(ch, gsn_jack_of_all_trades)) { pop_call(); return( -99 ); } roll = take_ten(ch); if (domain_apotheosis(ch, DOMAIN_TRICKERY)) roll = UMAX(roll, dice(1,20)); if (learned(ch, gsn_skill_mastery)) roll = UMAX(10, roll); roll += stat_mods(ch, APPLY_INT); roll += ranks; roll += get_apply(ch, APPLY_DISABLE); if (learned(ch, gsn_deft_hands)) roll += ranks / 5 + 2; roll += synergy_bonus(ch, gsn_craft_traps); if (IS_BLIND(ch)) roll -= 4; // strip one-shot enhancements if (is_affected(ch, gsn_guidance)) affect_strip(ch, gsn_guidance); if (is_affected(ch, gsn_moment_of_prescience)) affect_strip(ch, gsn_moment_of_prescience); pop_call(); return( roll ); } int disguise_roll( CHAR_DATA *ch ) { int roll; int ranks = learned(ch, gsn_disguise); push_call("disguise_roll(%p)",ch); if (!IS_NPC(ch)) { if ((roll = ch->pcdata->disguise_roll) == 0) { roll = dice(1,20); } } else { roll = dice(1,20); } if (domain_apotheosis(ch, DOMAIN_TRICKERY)) roll = UMAX(roll, dice(1,20)); roll += stat_mods(ch, APPLY_CHA); if (domain_skill(ch, gsn_divine_trickery)) roll += UMIN(class_level(ch, CLASS_CLERIC), stat_bonus(TRUE, ch, APPLY_WIS)); roll += ranks; if (learned(ch, gsn_deceitful)) roll += ranks / 5 + 2; roll += synergy_bonus(ch, gsn_bluff); roll += synergy_bonus(ch, gsn_perform); roll += multi_class_level(ch, gsn_faceless); // strip one-shot enhancements if (is_affected(ch, gsn_guidance)) affect_strip(ch, gsn_guidance); if (is_affected(ch, gsn_moment_of_prescience)) affect_strip(ch, gsn_moment_of_prescience); pop_call(); return( roll ); } int escape_artist_roll( CHAR_DATA *ch ) { int roll; int ranks = learned(ch, gsn_escape_artist); push_call("escape_artist_roll(%p)",ch); roll = dice(1,20); roll += stat_mods(ch, APPLY_DEX); roll += ranks; roll += get_apply(ch, APPLY_ESCAPE); roll -= armor_check_penalty(ch); if (learned(ch, gsn_nimble)) roll += ranks / 5 + 2; if (get_monk_style(ch) == STYLE_COBRA_STRIKE) roll += 2; if (IS_BLIND(ch)) roll -= 4; // strip one-shot enhancements if (is_affected(ch, gsn_guidance)) affect_strip(ch, gsn_guidance); if (is_affected(ch, gsn_moment_of_prescience)) affect_strip(ch, gsn_moment_of_prescience); pop_call(); return( roll ); } int first_aid_roll( CHAR_DATA *ch ) { int roll; int ranks = learned(ch, gsn_first_aid); push_call("first_aid_roll(%p)",ch); roll = get_apply(ch, APPLY_FIRST_AID); roll = take_ten(ch); roll += stat_mods(ch, APPLY_WIS); roll += ranks; if (learned(ch, gsn_self_sufficient)) roll += ranks / 5 + 2; // strip one-shot enhancements if (is_affected(ch, gsn_guidance)) affect_strip(ch, gsn_guidance); if (is_affected(ch, gsn_moment_of_prescience)) affect_strip(ch, gsn_moment_of_prescience); pop_call(); return( roll ); } int haggle_roll( CHAR_DATA *ch ) { int roll; int ranks = learned(ch, gsn_haggle); push_call("haggle_roll(%p)",ch); roll = dice(1,20); roll += stat_mods(ch, APPLY_CHA); if (domain_skill(ch, gsn_divine_mercantilism)) roll += UMIN(class_level(ch, CLASS_CLERIC), stat_bonus(TRUE, ch, APPLY_WIS)); roll += ranks; if (learned(ch, gsn_silver_palm)) roll += ranks / 5 + 2; roll += synergy_bonus(ch, gsn_appraise); // strip one-shot enhancements if (is_affected(ch, gsn_guidance)) affect_strip(ch, gsn_guidance); if (is_affected(ch, gsn_moment_of_prescience)) affect_strip(ch, gsn_moment_of_prescience); pop_call(); return( roll ); } int handle_animal_roll( CHAR_DATA *ch ) { int roll; int ranks; push_call("handle_animal_roll(%p)",ch); ranks = learned(ch, gsn_handle_animal); roll = take_ten(ch); roll += stat_mods(ch, APPLY_CHA); roll += ranks; roll += get_apply(ch, APPLY_HANDLE_ANIM); if (learned(ch, gsn_wild_empathy)) roll += UMAX(0, stat_bonus(TRUE, ch, APPLY_WIS)); if (learned(ch, gsn_animal_affinity)) roll += ranks / 5 + 2; // strip one-shot enhancements if (is_affected(ch, gsn_guidance)) affect_strip(ch, gsn_guidance); if (is_affected(ch, gsn_moment_of_prescience)) affect_strip(ch, gsn_moment_of_prescience); pop_call(); return( roll ); } int intimidate_roll( CHAR_DATA *ch ) { int roll; int ranks = learned(ch, gsn_intimidate); push_call("intimidate_roll(%p)",ch); roll = dice(1,20); if (learned(ch, gsn_strongarm_diplomacy)) roll += stat_mods(ch, APPLY_STR); else roll += stat_mods(ch, APPLY_CHA); roll += ranks; roll += multi_class_level(ch, gsn_oratory) / 2; roll += get_apply(ch, APPLY_INTIMIDATE); if (learned(ch, gsn_persuasive)) roll += ranks / 5 + 2; roll += synergy_bonus(ch, gsn_bluff); if (learned(ch, gsn_aura_of_cowardice)) roll += 4; if (domain_apotheosis(ch, DOMAIN_WRATH)) roll += UMAX(1, stat_bonus(TRUE, ch, APPLY_WIS)); // strip one-shot enhancements if (is_affected(ch, gsn_guidance)) affect_strip(ch, gsn_guidance); if (is_affected(ch, gsn_moment_of_prescience)) affect_strip(ch, gsn_moment_of_prescience); pop_call(); return( roll ); } int jump_roll( CHAR_DATA *ch ) { int roll; int ranks = learned(ch, gsn_jump); push_call("jump_roll(%p)",ch); roll = take_ten(ch); if (learned(ch, gsn_agile_climber)) roll += stat_mods(ch, APPLY_DEX); else roll += stat_mods(ch, APPLY_STR); roll += ranks; roll += get_apply(ch, APPLY_JUMP); roll -= armor_check_penalty(ch); if (learned(ch, gsn_acrobatic)) roll += ranks / 5 + 2; if (IS_BLIND(ch)) roll -= 4; roll += synergy_bonus(ch, gsn_tumble); // strip one-shot enhancements if (is_affected(ch, gsn_guidance)) affect_strip(ch, gsn_guidance); if (is_affected(ch, gsn_moment_of_prescience)) affect_strip(ch, gsn_moment_of_prescience); pop_call(); return( roll ); } int mount_roll( CHAR_DATA *ch ) { int roll; int ranks = learned(ch, gsn_mount); push_call("mount_roll(%p)",ch); roll = take_ten(ch); roll += stat_mods(ch, APPLY_DEX); roll += ranks; roll += get_apply(ch, APPLY_MOUNT); if (has_armor_penalty(ch)) roll -= armor_check_penalty(ch); if (learned(ch, gsn_animal_affinity)) roll += ranks / 5 + 2; roll += synergy_bonus(ch, gsn_handle_animal); if (IS_BLIND(ch)) roll -= 4; // strip one-shot enhancements if (is_affected(ch, gsn_guidance)) affect_strip(ch, gsn_guidance); if (is_affected(ch, gsn_moment_of_prescience)) affect_strip(ch, gsn_moment_of_prescience); pop_call(); return( roll ); } int pick_lock_roll( CHAR_DATA *ch ) { int roll; int ranks; push_call("pick_lock_roll(%p)",ch); if ((ranks = learned(ch, gsn_pick_lock)) <= 0 && !learned(ch, gsn_jack_of_all_trades)) { pop_call(); return( -99 ); } roll = take_twenty(ch); if (learned(ch, gsn_skill_mastery)) roll = UMAX(10, roll); roll += stat_mods(ch, APPLY_DEX); roll += ranks; if (has_armor_penalty(ch)) roll -= armor_check_penalty(ch); roll += get_apply(ch, APPLY_OPEN_LOCK); if (learned(ch, gsn_deft_hands)) roll += ranks / 5 + 2; if (IS_BLIND(ch)) roll -= 4; // strip one-shot enhancements if (is_affected(ch, gsn_guidance)) affect_strip(ch, gsn_guidance); if (is_affected(ch, gsn_moment_of_prescience)) affect_strip(ch, gsn_moment_of_prescience); pop_call(); return( roll ); } int perception_roll( CHAR_DATA *ch, int sense ) { int roll; int ranks = learned(ch, gsn_perception); push_call("perception_roll(%p)",ch); if (sense == SENSE_SIGHT && IS_BLIND(ch)) { pop_call(); return -99; } if (sense == SENSE_SOUND && IS_DEAF(ch)) { pop_call(); return -99; } roll = take_ten(ch); roll += stat_mods(ch, APPLY_WIS); roll += ranks; if (learned(ch, gsn_alertness)) roll += ranks / 5 + 2; if (get_monk_style(ch) == STYLE_INVISIBLE_EYE) roll += 2; if (sense == SENSE_SIGHT) { roll += race_skill(ch, gsn_sight_perception); roll += get_apply(ch, APPLY_SIGHT); } else if (sense == SENSE_SOUND) { roll += race_skill(ch, gsn_sound_perception); roll += get_apply(ch, APPLY_LISTEN); } else if (sense == SENSE_TOUCH) roll += race_skill(ch, gsn_touch_perception); else if (sense == SENSE_TASTE) roll += race_skill(ch, gsn_taste_perception); else if (sense == SENSE_SMELL) { roll += race_skill(ch, gsn_smell_perception); if (learned(ch, gsn_scent)) roll += 8; } if (IS_DAZZLED(ch)) roll -= 2; if (sense == SENSE_SIGHT) { if (IS_OUTSIDE(ch)) { if (mud->sunlight != SUN_DARK && has_familiar(ch, RACE_HAWK)) roll += 3; else if (mud->sunlight == SUN_DARK && has_familiar(ch, RACE_OWL)) roll += 3; if (ch->in_room->area->weather_info->sky >= 2 || ch->in_room->area->weather_info->sky >= 8) { roll -= 4; } } else if (has_familiar(ch, RACE_OWL)) roll += 3; } if (sense == SENSE_SOUND) { if (IS_OUTSIDE(ch)) { if (ch->in_room->area->weather_info->sky >= 2 || ch->in_room->area->weather_info->sky >= 8) { roll -= 4; } } if (has_familiar(ch, RACE_BAT)) { roll += 3; } } pop_call(); return( UMAX(0, roll) ); } int perform_roll( CHAR_DATA *ch ) { int roll; int ranks = learned(ch, gsn_perform); push_call("perform_roll(%p)",ch); roll = dice(1,20); if (learned(ch, gsn_magna_alumnus)) roll = UMAX(10, roll); roll += stat_mods(ch, APPLY_CHA); roll += ranks; roll += get_apply(ch, APPLY_PERFORM); // strip one-shot enhancements if (is_affected(ch, gsn_guidance)) affect_strip(ch, gsn_guidance); if (is_affected(ch, gsn_moment_of_prescience)) affect_strip(ch, gsn_moment_of_prescience); pop_call(); return( roll ); } int search_roll( CHAR_DATA *ch ) { int roll; int ranks = learned(ch, gsn_search); push_call("search_roll(%p)",ch); roll = take_ten(ch); roll += stat_mods(ch, APPLY_INT); roll += ranks; roll += get_apply(ch, APPLY_SEARCH); if (learned(ch, gsn_insightful)) roll += ranks / 5 + 2; roll += synergy_bonus(ch, gsn_perception); if (IS_BLIND(ch)) roll -= 4; else if (IS_DAZZLED(ch)) roll -= 1; // strip one-shot enhancements if (is_affected(ch, gsn_guidance)) affect_strip(ch, gsn_guidance); if (is_affected(ch, gsn_moment_of_prescience)) affect_strip(ch, gsn_moment_of_prescience); pop_call(); return( roll ); } int sense_motive_roll( CHAR_DATA *ch ) { int roll; int ranks = learned(ch, gsn_sense_motive); push_call("sense_motive_roll(%p)",ch); roll = wis_roll(ch) + ranks; roll += get_apply(ch, APPLY_SENSE_MOT); if (learned(ch, gsn_negotiator)) roll += ranks / 5 + 2; if (learned(ch, gsn_insightful)) roll += ranks / 5 + 2; // strip one-shot enhancements if (is_affected(ch, gsn_guidance)) affect_strip(ch, gsn_guidance); if (is_affected(ch, gsn_moment_of_prescience)) affect_strip(ch, gsn_moment_of_prescience); pop_call(); return( roll ); } int sleight_of_hand_roll( CHAR_DATA *ch ) { int roll; int ranks; push_call("sleight_of_hand_roll(%p)",ch); ranks = learned(ch, gsn_sleight_of_hand); if (learned(ch, gsn_stealth_mastery)) roll = take_twenty(ch); else roll = take_ten(ch); if (domain_apotheosis(ch, DOMAIN_TRICKERY)) roll = UMAX(roll, dice(1,20)); if (learned(ch, gsn_skill_mastery)) roll = UMAX(10, roll); roll += stat_mods(ch, APPLY_DEX); if (domain_skill(ch, gsn_divine_trickery)) roll += UMIN(class_level(ch, CLASS_CLERIC), stat_bonus(TRUE, ch, APPLY_WIS)); roll += ranks; roll += get_apply(ch, APPLY_SLEIGHT); roll -= armor_check_penalty(ch); if (learned(ch, gsn_nimble)) roll += ranks / 5 + 2; roll += synergy_bonus(ch, gsn_bluff); if (IS_BLIND(ch)) roll -= 4; // strip one-shot enhancements if (is_affected(ch, gsn_guidance)) affect_strip(ch, gsn_guidance); if (is_affected(ch, gsn_moment_of_prescience)) affect_strip(ch, gsn_moment_of_prescience); pop_call(); return( roll ); } int hide_roll( CHAR_DATA *ch ) { int roll = 0; int ranks = learned(ch, gsn_stealth); push_call("hide_roll(%p)",ch); if (!IS_AFFECTED(ch, AFF_HIDE)) { pop_call(); return -99; } if (learned(ch, gsn_stealth_mastery)) roll = take_twenty(ch); else if (learned(ch, gsn_hide_plain_sight)) roll = take_ten(ch); else roll = dice(1,20); roll += stat_mods(ch, APPLY_DEX); roll += ranks; roll += get_apply(ch, APPLY_STEALTH); if (learned(ch, gsn_stealthy)) roll += ranks / 5 + 2; if (get_monk_style(ch) == STYLE_SLEEPING_TIGER) roll += 2; if (has_armor_penalty(ch)) roll -= armor_check_penalty(ch); if (IS_BLIND(ch)) roll -= 4; if (IS_OUTSIDE(ch) && learned(ch, gsn_camouflage)) roll += 5; if (is_affected(ch, gsn_faerie_fire)) roll -= 20; switch (get_size(ch)) { case SIZE_FINE: roll += 16; break; case SIZE_DIMINUTIVE: roll += 12; break; case SIZE_TINY: roll += 8; break; case SIZE_SMALL: roll += 4; break; case SIZE_LARGE: roll -= 4; break; case SIZE_HUGE: roll -= 8; break; case SIZE_GARGANTUAN: roll -= 12; break; case SIZE_COLOSSAL: roll -= 16; break; } // strip one-shot enhancements if (is_affected(ch, gsn_guidance)) affect_strip(ch, gsn_guidance); if (is_affected(ch, gsn_moment_of_prescience)) affect_strip(ch, gsn_moment_of_prescience); pop_call(); return( roll ); } int sneak_roll( CHAR_DATA *ch ) { int roll; int ranks = learned(ch, gsn_stealth); push_call("sneak_roll(%p)",ch); if (!IS_AFFECTED(ch, AFF_SNEAK)) { pop_call(); return -99; } if (learned(ch, gsn_stealth_mastery)) roll = take_twenty(ch); else if (ch->speed == 0) roll = take_ten(ch); else roll = dice(1,20); roll += stat_mods(ch, APPLY_DEX); roll += ranks; if (learned(ch, gsn_stealthy)) roll += ranks / 5 + 2; switch (get_size(ch)) { case SIZE_FINE: roll += 16; break; case SIZE_DIMINUTIVE: roll += 12; break; case SIZE_TINY: roll += 8; break; case SIZE_SMALL: roll += 4; break; case SIZE_LARGE: roll -= 4; break; case SIZE_HUGE: roll -= 8; break; case SIZE_GARGANTUAN: roll -= 12; break; case SIZE_COLOSSAL: roll -= 16; break; } switch (ch->speed) { case 0: roll += 0; break; case 1: if (!learned(ch, gsn_swift_stealth)) roll -= 5; break; default: roll -= 20; break; } if (IS_FLYING(ch)) roll += 20; if (!learned(ch, gsn_woodland_stride) && !IS_FLYING(ch)) //these two bonuses do not stack { if (ch->in_room->sector_type == SECT_FIELD || ch->in_room->sector_type == SECT_HILLS || ch->in_room->sector_type == SECT_MOUNTAIN || ch->in_room->sector_type == SECT_DESERT || ch->in_room->sector_type == SECT_SWAMP || ch->in_room->sector_type == SECT_BEACH) { roll -= 2; } if (ch->in_room->sector_type == SECT_FOREST || ch->in_room->sector_type == SECT_TUNDRA) { roll -= 5; } } roll += get_apply(ch, APPLY_STEALTH); roll -= armor_check_penalty(ch); if (IS_BLIND(ch)) roll -= 4; if (has_familiar(ch, RACE_CAT)) roll += 3; // strip one-shot enhancements if (is_affected(ch, gsn_guidance)) affect_strip(ch, gsn_guidance); if (is_affected(ch, gsn_moment_of_prescience)) affect_strip(ch, gsn_moment_of_prescience); pop_call(); return( roll ); } int spellcraft_roll( CHAR_DATA *ch ) { int roll; int ranks; push_call("spellcraft_roll(%p)",ch); if ((ranks = learned(ch, gsn_spellcraft)) <= 0 && !learned(ch, gsn_jack_of_all_trades) && !learned(ch, gsn_divine_arcana)) { pop_call(); return( -99 ); } roll = take_ten(ch); roll += stat_mods(ch, APPLY_INT); roll += ranks; if (domain_skill(ch, gsn_divine_arcana)) roll += UMIN(class_level(ch, CLASS_CLERIC), stat_bonus(TRUE, ch, APPLY_WIS)); roll += get_apply(ch, APPLY_SPELLCRAFT); if (learned(ch, gsn_magical_aptitude)) roll += ranks / 5 + 2; roll += synergy_bonus(ch, gsn_know_arcana); if (learned(ch, gsn_divine_arcana)) roll += 2; roll += multi_class_level(ch, gsn_greater_lore); // strip one-shot enhancements if (is_affected(ch, gsn_guidance)) affect_strip(ch, gsn_guidance); if (is_affected(ch, gsn_moment_of_prescience)) affect_strip(ch, gsn_moment_of_prescience); pop_call(); return( roll ); } int streetwise_roll( CHAR_DATA *ch ) { int roll; int ranks = learned(ch, gsn_streetwise); push_call("streetwise_roll(%p)",ch); roll = cha_roll(ch) + ranks; roll += get_apply(ch, APPLY_GATHER_INFO); if (learned(ch, gsn_insightful)) roll += ranks / 5 + 2; roll += synergy_bonus(ch, gsn_know_local); // strip one-shot enhancements if (is_affected(ch, gsn_guidance)) affect_strip(ch, gsn_guidance); if (is_affected(ch, gsn_moment_of_prescience)) affect_strip(ch, gsn_moment_of_prescience); pop_call(); return( roll ); } int survival_roll( CHAR_DATA *ch ) { int roll; int ranks = learned(ch, gsn_survival); push_call("survival_roll(%p)",ch); roll = take_ten(ch); roll += stat_mods(ch, APPLY_WIS); roll += ranks; if (learned(ch, gsn_self_sufficient)) roll += ranks / 5 + 2; roll += get_apply(ch, APPLY_SURVIVAL); if (class_level(ch, CLASS_DRUID) > 0) roll += 2; // strip one-shot enhancements if (is_affected(ch, gsn_guidance)) affect_strip(ch, gsn_guidance); if (is_affected(ch, gsn_moment_of_prescience)) affect_strip(ch, gsn_moment_of_prescience); pop_call(); return( roll ); } int swim_roll( CHAR_DATA *ch ) { int roll; int ranks = learned(ch, gsn_swim); push_call("swim_roll(%p)",ch); if (domain_apotheosis(ch, DOMAIN_WATER)) { roll = 20; } else if (CAN_SWIM(ch)) { roll = UMAX(10, dice(1,20)); } else if (!IS_NPC(ch) && ch->pcdata->condition[COND_AIR] <= 0) { roll = dice(1,20); } else { switch (ch->in_room->sector_type) { case SECT_LAKE: roll = take_ten(ch); break; default: roll = dice(1,20); break; } } roll += stat_mods(ch, APPLY_CON); roll += ranks; roll -= armor_check_penalty(ch) * 2; roll -= encumberance(ch) * 3; if (learned(ch, gsn_athletic)) roll += ranks / 5 + 2; if (IS_BLIND(ch)) roll -= 4; roll += get_apply(ch, APPLY_SWIM); // strip one-shot enhancements if (is_affected(ch, gsn_guidance)) affect_strip(ch, gsn_guidance); if (is_affected(ch, gsn_moment_of_prescience)) affect_strip(ch, gsn_moment_of_prescience); pop_call(); return( roll ); } int tumble_roll( CHAR_DATA *ch ) { int roll; int ranks; push_call("tumble_roll(%p)",ch); if ((ranks = learned(ch, gsn_tumble)) <= 0 && !learned(ch, gsn_jack_of_all_trades)) { pop_call(); return( -99 ); } roll = take_ten(ch); roll += stat_mods(ch, APPLY_DEX); roll += ranks; roll += get_apply(ch, APPLY_TUMBLE); roll -= armor_check_penalty(ch); if (learned(ch, gsn_acrobatic)) roll += ranks / 5 + 2; roll += synergy_bonus(ch, gsn_jump); if (get_monk_style(ch) == STYLE_DENYING_STANCE) roll += 2; if (get_monk_style(ch) == STYLE_HAND_AND_FOOT) roll += 2; if (IS_BLIND(ch)) roll -= 4; // strip one-shot enhancements if (is_affected(ch, gsn_guidance)) affect_strip(ch, gsn_guidance); if (is_affected(ch, gsn_moment_of_prescience)) affect_strip(ch, gsn_moment_of_prescience); pop_call(); return( roll ); } int use_magic_roll( CHAR_DATA *ch ) { int roll; int ranks; push_call("use_magic_roll(%p)",ch); if ((ranks = learned(ch, gsn_use_magic)) <= 0 && !learned(ch, gsn_jack_of_all_trades) && !learned(ch, gsn_divine_arcana)) { pop_call(); return( -99 ); } roll = dice(1,20); roll += stat_mods(ch, APPLY_CHA); roll += ranks; if (domain_skill(ch, gsn_divine_arcana)) roll += UMIN(class_level(ch, CLASS_CLERIC), stat_bonus(TRUE, ch, APPLY_WIS)); roll += get_apply(ch, APPLY_USE_MAGIC); if (learned(ch, gsn_magical_aptitude)) roll += ranks / 5 + 2; roll += synergy_bonus(ch, gsn_know_arcana); if (learned(ch, gsn_divine_arcana)) roll += 2; // strip one-shot enhancements if (is_affected(ch, gsn_guidance)) affect_strip(ch, gsn_guidance); if (is_affected(ch, gsn_moment_of_prescience)) affect_strip(ch, gsn_moment_of_prescience); pop_call(); return( roll ); } bool appraise_check( CHAR_DATA *ch, OBJ_DATA *obj, int roll, int dc ) { push_call("appraise_check(%p)",ch); if (obj != NULL) { if (IS_RACE(ch, RACE_DWARF)) { if (obj->item_type == ITEM_ARMOR || obj->item_type == ITEM_WEAPON || obj->item_type == ITEM_TREASURE) roll += 2; } if (IS_RACE(ch, RACE_GNOME) && obj->item_type == ITEM_TREASURE) roll += 2; if (obj->item_type == ITEM_WEAPON) roll += synergy_bonus(ch, gsn_craft_weapons); if (obj->item_type == ITEM_ARMOR) roll += synergy_bonus(ch, gsn_craft_armor); if (obj->item_type == ITEM_TREASURE) roll += synergy_bonus(ch, gsn_craft_jewelry); } else { log_printf("%s appraise_check: No obj.\n\r", capitalize(get_name(ch))); pop_call(); return FALSE; } wiz_printf_room( ch, "Appraise check (%s): diceroll: %d, DC: %d - %s\n\r", get_name(ch), roll, dc, roll >= dc ? "SUCCESS" : "FAILURE"); pop_call(); return( roll >= dc ); } bool bluff_check( CHAR_DATA *ch, CHAR_DATA *och, int roll, int dc ) { push_call("bluff_check(%p,%p,%p,%p)",ch,och,roll,dc); if (och == NULL) { log_printf("%s bluff_check: Must have an opposing char.\n\r", capitalize(get_name(ch))); pop_call(); return FALSE; } dc = sense_motive_roll(och); dc += fave_enemy_bonus(och,ch); roll += fave_enemy_bonus(ch,och); roll += reputation_bonus(ch); if (ch->race == och->race && learned(ch, gsn_noble_birth)) roll += 2; if (is_affected(och, gsn_suggestion)) { roll += 20; affect_strip(och, gsn_suggestion); } else if (is_affected(och, gsn_charm_monster)) { if (get_caster(och, gsn_charm_monster) == ch) roll += 10; } else if (is_affected(och, gsn_charm_person)) { if (get_caster(och, gsn_charm_person) == ch) roll += 10; } else if (is_affected(och, gsn_charm_plant)) { if (get_caster(och, gsn_charm_plant) == ch) roll += 10; } else if (is_affected(och, gsn_charm_animal)) { if (get_caster(och, gsn_charm_animal) == ch) roll += 10; } if (learned(och, gsn_secret_of_truth)) { dc += 2; } wiz_printf_room( ch, "Bluff check (%s): diceroll: %d, DC: %d - %s\n\r", get_name(ch), roll, dc, roll >= dc ? "SUCCESS" : "FAILURE"); if (och && och->in_room != ch->in_room) wiz_printf_room( och, "Bluff check (%s): diceroll: %d, DC: %d - %s\n\r", get_name(ch), roll, dc, roll >= dc ? "SUCCESS" : "FAILURE"); if (roll >= dc) { gain_favor(ch, DOMAIN_TRICKERY, 2); gain_favor(ch, DOMAIN_CHAOS, 2); gain_favor(ch, DOMAIN_CHARM, 2); } pop_call(); return( roll >= dc ); } int climb_check( CHAR_DATA *ch, CHAR_DATA *och, int roll, int dc ) { OBJ_DATA *kit; int mod = 0; push_call("climb_check(%p,%p,%p,%p)",ch,och,roll,dc); if (IS_SET(ch->in_room->room_flags, ROOM_ICE) && !IS_AFFECTED(ch, AFF_WATER_WALK)) { dc += 5; } else if (IS_OUTSIDE(ch) && ch->in_room->area->weather_info->sky == 3) { dc += 5; } else if (IS_OUTSIDE(ch) && ch->in_room->area->weather_info->sky == 2) { dc += 2; } if ((kit = get_obj_carry_type(ch, ITEM_TOOLS)) != NULL) { if (TOOL_TYPE(kit, TOOL_CLIMBERS_KIT)) { if (IS_OBJ_STAT(kit, ITEM_MASTERWORK)) { if (kit->value[2] > 0) mod += kit->value[2]; else mod += 2; } else { mod += 1; } } } if (roll + mod < dc && domain_apotheosis(ch, DOMAIN_STRENGTH)) { roll = UMAX(roll, climb_roll(ch)); } roll += mod; wiz_printf_room( ch, "Climb check (%s): diceroll: %d, DC: %d - %s\n\r", get_name(ch), roll, dc, roll >= dc ? "SUCCESS" : "FAILURE"); if (och && och->in_room != ch->in_room) wiz_printf_room( och, "Climb check (%s): diceroll: %d, DC: %d - %s\n\r", get_name(ch), roll, dc, roll >= dc ? "SUCCESS" : "FAILURE"); if (roll >= dc) { gain_favor(ch, DOMAIN_STRENGTH, 2); gain_favor(ch, DOMAIN_CAVERN, 2); gain_favor(ch, DOMAIN_TRAVEL, 2); } if (dc - roll >= 5) { pop_call(); return -2; } pop_call(); return (roll >= dc); } bool concentration_check( CHAR_DATA *ch, CHAR_DATA *och, int roll, int dc ) { int dc2 = 0; push_call("concentration_check(%p,%p,%p,%p)",ch,och,roll,dc); if (IS_OUTSIDE(ch)) { if (ch->in_room->area->weather_info->wind_speed >= 8) { if (ch->in_room->area->weather_info->sky == 2) { dc2 = 5; } else if (ch->in_room->area->weather_info->sky == 3) { dc2 = 10; } } } if (ch->in_room->sector_type == SECT_OCEAN || ch->in_room->sector_type == SECT_RIVER || ch->in_room->sector_type == SECT_LAKE) { if (!IS_FLYING(ch)) { if (ch->in_room->area->weather_info->wind_speed >= 8) { dc2 = 15; } else if (ch->in_room->area->weather_info->wind_speed >= 6) { dc2 = 10; } } } else if (is_mounting(ch)) { if (in_combat(ch)) { dc2 = 15; } else { dc2 = 10; } } if (ch->casting && learned(ch, gsn_combat_casting)) roll += 4; if (ch->concentrating && learned(ch, gsn_skill_mastery)) if (ch->timer_fun == do_pick || ch->timer_fun == do_disable) roll += 4; if (dc2 > dc) dc = dc2; wiz_printf_room( ch, "Concentration check (%s): diceroll: %d, DC: %d - %s\n\r", get_name(ch), roll, dc, roll >= dc ? "SUCCESS" : "FAILURE"); if (och && och->in_room != ch->in_room) wiz_printf_room( och, "Concentration check (%s): diceroll: %d, DC: %d - %s\n\r", get_name(ch), roll, dc, roll >= dc ? "SUCCESS" : "FAILURE"); pop_call(); return( roll >= dc ); } bool decipher_script_check( CHAR_DATA *ch, CHAR_DATA *och, int roll, int dc ) { push_call("decipher_script_check(%p,%p,%p,%p)",ch,och,roll,dc); if (!learned(ch, gsn_decipher_script) && !learned(ch, gsn_jack_of_all_trades)) { pop_call(); return FALSE; } wiz_printf_room( ch, "Decipher Script check (%s): diceroll: %d, DC: %d - %s\n\r", get_name(ch), roll, dc, roll >= dc ? "SUCCESS" : "FAILURE"); if (och && och->in_room != ch->in_room) wiz_printf_room( och, "Decipher Script check (%s): diceroll: %d, DC: %d - %s\n\r", get_name(ch), roll, dc, roll >= dc ? "SUCCESS" : "FAILURE"); if (roll >= dc) { gain_favor(ch, DOMAIN_KNOWLEDGE, 2); gain_favor(ch, DOMAIN_MAGIC, 2); } pop_call(); return( roll >= dc ); } bool diplomacy_check( CHAR_DATA *ch, CHAR_DATA *och, int roll, int dc ) { push_call("diplomacy_check(%p,%p,%p,%p)",ch,och,roll,dc); if (och == NULL) { log_printf("%s diplomacy_check: Must have an opposing char.\n\r", capitalize(get_name(ch))); pop_call(); return FALSE; } if (IS_ACT(och, ACT_AGGRESSIVE)) dc += 10; if (IS_EVIL(och)) roll += (0 - reputation_bonus(ch)); else roll += reputation_bonus(ch); if (ch->race == och->race && learned(ch, gsn_noble_birth)) roll += 2; if (is_affected(och, gsn_suggestion)) { roll += 20; affect_strip(och, gsn_suggestion); } else if (is_affected(och, gsn_charm_monster)) { if (get_caster(och, gsn_charm_monster) == ch) roll += 10; } else if (is_affected(och, gsn_charm_person)) { if (get_caster(och, gsn_charm_person) == ch) roll += 10; } else if (is_affected(och, gsn_charm_plant)) { if (get_caster(och, gsn_charm_plant) == ch) roll += 10; } else if (is_affected(och, gsn_charm_animal)) { if (get_caster(och, gsn_charm_animal) == ch) roll += 10; } wiz_printf_room( ch, "Diplomacy check (%s): diceroll: %d, DC: %d - %s\n\r", get_name(ch), roll, dc, roll >= dc ? "SUCCESS" : "FAILURE"); if (och && och->in_room != ch->in_room) wiz_printf_room( och, "Diplomacy check (%s): diceroll: %d, DC: %d - %s\n\r", get_name(ch), roll, dc, roll >= dc ? "SUCCESS" : "FAILURE"); if (roll >= dc) { gain_favor(ch, DOMAIN_COMMUNITY, 2); gain_favor(ch, DOMAIN_LAW, 2); } pop_call(); return( roll >= dc ); } int disable_device_check( CHAR_DATA *ch, CHAR_DATA *och, int roll, int dc ) { OBJ_DATA *lockpick; push_call("disable_device_check(%p,%p,%p,%p)",ch,och,roll,dc); if (!learned(ch, gsn_disable_device) && !learned(ch, gsn_jack_of_all_trades)) { pop_call(); return FALSE; } if ((lockpick = get_obj_carry_type(ch, ITEM_TOOLS)) != NULL) { if (TOOL_TYPE(lockpick, TOOL_THIEVES_TOOLS)) { if (lockpick->value[1] == 0) { act( "Your tools are worn from overuse.", ch, NULL, NULL, TO_CHAR); junk_obj(lockpick); dc += 5; } else { lockpick->value[1]--; if (IS_OBJ_STAT(lockpick, ITEM_MASTERWORK)) { if (lockpick->value[2] > 0) roll += lockpick->value[2]; else roll += 2; } } } else { act( "You suffer a penalty for not holding thieves tools.", ch, NULL, NULL, TO_CHAR); dc += 5; } } else { act( "You suffer a penalty for not holding thieves tools.", ch, NULL, NULL, TO_CHAR); dc += 5; } wiz_printf_room( ch, "Disable Device check (%s): diceroll: %d, DC: %d - %s\n\r", get_name(ch), roll, dc, roll >= dc ? "SUCCESS" : "FAILURE"); if (och && och->in_room != ch->in_room) wiz_printf_room( och, "Disable Device check (%s): diceroll: %d, DC: %d - %s\n\r", get_name(ch), roll, dc, roll >= dc ? "SUCCESS" : "FAILURE"); if (roll >= dc) { gain_favor(ch, DOMAIN_TRICKERY, 2); gain_favor(ch, DOMAIN_ARTIFICE, 2); } pop_call(); return( roll - dc ); } int disguise_check( CHAR_DATA *ch, CHAR_DATA *och, int roll, int dc ) { push_call("disguise_check(%p,%p,%p,%p)",ch,och,roll,dc); if (!IS_NPC(ch)) { if (!ch->pcdata->disguise_roll) { pop_call(); return FALSE; } else if (!roll) { roll = disguise_roll(ch); } } else if (roll <= 0) { if (is_polymorph(ch)) { roll = disguise_roll(ch); } else { pop_call(); return FALSE; } } if (och != NULL) { dc = perception_roll(och, SENSE_SIGHT); if (!IS_AFFECTED(och, AFF_TRUESIGHT)) { roll += get_apply(ch, APPLY_DISGUISE); } if (is_affected(och, gsn_suggestion)) { roll += 20; affect_strip(och, gsn_suggestion); } } wiz_printf_room( ch, "Disguise check (%s): diceroll: %d, DC: %d - %s\n\r", get_name(ch), roll, dc, roll >= dc ? "SUCCESS" : "FAILURE"); if (och && och->in_room != ch->in_room) wiz_printf_room( och, "Disguise check (%s): diceroll: %d, DC: %d - %s\n\r", get_name(ch), roll, dc, roll >= dc ? "SUCCESS" : "FAILURE"); if (roll >= dc) { gain_favor(ch, DOMAIN_TRICKERY, 2); gain_favor(ch, DOMAIN_ILLUSION, 2); } pop_call(); return( roll - dc ); } bool escape_artist_check( CHAR_DATA *ch, CHAR_DATA *och, int roll, int dc ) { push_call("escape_artist_check(%p,%p,%p,%p)",ch,och,roll,dc); wiz_printf_room( ch, "Escape Artist check (%s): diceroll: %d, DC: %d - %s\n\r", get_name(ch), roll, dc, roll >= dc ? "SUCCESS" : "FAILURE"); if (och && och->in_room != ch->in_room) wiz_printf_room( och, "Escape Artist check (%s): diceroll: %d, DC: %d - %s\n\r", get_name(ch), roll, dc, roll >= dc ? "SUCCESS" : "FAILURE"); if (roll >= dc) { gain_favor(ch, DOMAIN_TRICKERY, 2); gain_favor(ch, DOMAIN_LIBERATION, 2); } pop_call(); return( roll >= dc ); } int first_aid_check( CHAR_DATA *ch, CHAR_DATA *och, int roll, int dc ) { OBJ_DATA *kit; push_call("first_aid_check(%p,%p,%p,%p)",ch,och,roll,dc); if ((kit = get_obj_carry_type(ch, ITEM_TOOLS)) != NULL) { if (TOOL_TYPE(kit, TOOL_FIRSTAID_KIT)) { kit->value[1]--; if (IS_OBJ_STAT(kit, ITEM_MASTERWORK)) { if (kit->value[2] > 0) roll += kit->value[2]; else roll += 2; } if (kit->value[1] == 0) { act( "You've used the last of your first aid kit.", ch, NULL, NULL, TO_CHAR); junk_obj(kit); } } } if (roll >= dc) { gain_favor(ch, DOMAIN_COMMUNITY, 2); gain_favor(ch, DOMAIN_HEALING, 2); } wiz_printf_room( ch, "First Aid check (%s): diceroll: %d, DC: %d - %s\n\r", get_name(ch), roll, dc, roll >= dc ? "SUCCESS" : "FAILURE"); if (och && och->in_room != ch->in_room) wiz_printf_room( och, "First Aid check (%s): diceroll: %d, DC: %d - %s\n\r", get_name(ch), roll, dc, roll >= dc ? "SUCCESS" : "FAILURE"); pop_call(); return( roll - dc ); } bool streetwise_check( CHAR_DATA *ch, CHAR_DATA *och, int roll, int dc ) { push_call("streetwise_check(%p,%p,%p,%p)",ch,och,roll,dc); if (och && IS_EVIL(och)) roll += 0 - reputation_bonus(ch); else roll += reputation_bonus(ch); if (och && ch->race == och->race && learned(ch, gsn_noble_birth)) roll += 2; wiz_printf_room( ch, "Streetwise check (%s): diceroll: %d, DC: %d - %s\n\r", get_name(ch), roll, dc, roll >= dc ? "SUCCESS" : "FAILURE"); if (och && och->in_room != ch->in_room) wiz_printf_room( och, "Streetwise check (%s): diceroll: %d, DC: %d - %s\n\r", get_name(ch), roll, dc, roll >= dc ? "SUCCESS" : "FAILURE"); pop_call(); return( roll >= dc ); } int haggle_check( CHAR_DATA *ch, CHAR_DATA *och ) { int roll = 0, dc = 0; push_call("haggle_check(%p,%p,%p,%p)",ch,och,roll,dc); if (och == NULL) { log_printf("%s haggle_check: Must have an opposing char.\n\r", capitalize(get_name(ch))); pop_call(); return 0; } roll = haggle_roll(ch); dc = haggle_roll(och); if (is_affected(och, gsn_suggestion)) { roll += 20; affect_strip(och, gsn_suggestion); } else if (is_affected(och, gsn_charm_monster)) { if (get_caster(och, gsn_charm_monster) == ch) roll += 10; } else if (is_affected(och, gsn_charm_plant)) { if (get_caster(och, gsn_charm_plant) == ch) roll += 10; } else if (is_affected(och, gsn_charm_person)) { if (get_caster(och, gsn_charm_person) == ch) roll += 10; } wiz_printf_room( ch, "Haggle check (%s): diceroll: %d, DC: %d - %s\n\r", get_name(ch), roll, dc, roll >= dc ? "SUCCESS" : "FAILURE"); if (och && och->in_room != ch->in_room) wiz_printf_room( och, "Haggle check (%s): diceroll: %d, DC: %d - %s\n\r", get_name(ch), roll, dc, roll >= dc ? "SUCCESS" : "FAILURE"); if (roll >= dc) { gain_favor(ch, DOMAIN_TRADE, 2); } pop_call(); return( dc - roll ); } bool handle_animal_check( CHAR_DATA *ch, CHAR_DATA *och, int roll, int dc ) { push_call("handle_animal_check(%p,%p,%p,$p)",ch,och,roll,dc); if (!learned(ch, gsn_handle_animal) && !learned(ch, gsn_jack_of_all_trades)) { pop_call(); return FALSE; } wiz_printf_room( ch, "Handle Animal check (%s): diceroll: %d, DC: %d - %s\n\r", get_name(ch), roll, dc, roll >= dc ? "SUCCESS" : "FAILURE"); if (och && och->in_room != ch->in_room) wiz_printf_room( och, "Handle Animal check (%s): diceroll: %d, DC: %d - %s\n\r", get_name(ch), roll, dc, roll >= dc ? "SUCCESS" : "FAILURE"); if (roll >= dc) { gain_favor(ch, DOMAIN_ANIMAL, 2); } pop_call(); return( roll >= dc ); } bool hide_check( CHAR_DATA *ch, CHAR_DATA *och, int roll, int dc ) { push_call("hide_check(%p,%p,%p,%p)",ch,och,roll,dc); if (!IS_AFFECTED(ch, AFF_HIDE)) { pop_call(); return FALSE; } if (och != NULL && dc == 0) { dc = perception_roll(och, SENSE_SIGHT); dc += fave_enemy_bonus(och, ch); } wiz_printf_room( ch, "Hide check (%s): diceroll: %d, DC: %d - %s\n\r", get_name(ch), roll, dc, roll >= dc ? "SUCCESS" : "FAILURE"); if (och && och->in_room != ch->in_room) wiz_printf_room( och, "Hide check (%s): diceroll: %d, DC: %d - %s\n\r", get_name(ch), roll, dc, roll >= dc ? "SUCCESS" : "FAILURE"); if (roll >= dc) { gain_favor(ch, DOMAIN_DARKNESS, 2); gain_favor(ch, DOMAIN_ILLUSION, 2); gain_favor(ch, DOMAIN_TRICKERY, 2); } pop_call(); return( roll >= dc ); } int intimidate_check( CHAR_DATA *ch, CHAR_DATA *och, int roll, int dc ) { push_call("intimidate_check(%p,%p,%p,%p)",ch,och,roll,dc); if (och == NULL) { log_printf("%s intimidate_check: Must have an opposing char.\n\r", capitalize(get_name(ch))); pop_call(); return FALSE; } roll += (ch->size - och->size) * 4; if (IS_UNDEAD(och)) { pop_call(); return FALSE; } if (get_curr_int(och) < 3) { if (get_curr_int(och) <= 0 || !learned(ch, gsn_wild_empathy)) { pop_call(); return FALSE; } } //intimidate treats negative REP bonus as positive - Kregor roll += (abs)(reputation_bonus(ch)); if (ch->race == och->race && learned(ch, gsn_noble_birth)) roll += 2; if (is_affected(och, gsn_suggestion)) { roll += 20; affect_strip(och, gsn_suggestion); } else if (is_affected(och, gsn_charm_monster)) { if (get_caster(och, gsn_charm_monster) == ch) roll += 10; } else if (is_affected(och, gsn_charm_person)) { if (get_caster(och, gsn_charm_person) == ch) roll += 10; } else if (is_affected(och, gsn_charm_plant)) { if (get_caster(och, gsn_charm_plant) == ch) roll += 10; } else if (is_affected(och, gsn_charm_animal)) { if (get_caster(och, gsn_charm_animal) == ch) roll += 10; } dc = stat_bonus(TRUE, och, APPLY_WIS) + get_will_save(och) + 10; wiz_printf_room( ch, "Intimidate check (%s): diceroll: %d, DC: %d - %s\n\r", get_name(ch), roll, dc, roll >= dc ? "SUCCESS" : "FAILURE"); if (och && och->in_room != ch->in_room) wiz_printf_room( och, "Intimidate check (%s): diceroll: %d, DC: %d - %s\n\r", get_name(ch), roll, dc, roll >= dc ? "SUCCESS" : "FAILURE"); if (roll >= dc) { gain_favor(ch, DOMAIN_LAW, 2); gain_favor(ch, DOMAIN_WAR, 2); gain_favor(ch, DOMAIN_WRATH, 2); } pop_call(); return( roll - dc ); } int jump_check( CHAR_DATA *ch, CHAR_DATA *och, int roll, int dc ) { push_call("jump_check(%p,%p,%p,%p)",ch,och,roll,dc); if (roll < dc && domain_apotheosis(ch, DOMAIN_STRENGTH)) { roll = UMAX(roll, climb_roll(ch)); } wiz_printf_room( ch, "Jump check (%s): diceroll: %d, DC: %d - %s\n\r", get_name(ch), roll, dc, roll >= dc ? "SUCCESS" : "FAILURE"); if (och && och->in_room != ch->in_room) wiz_printf_room( och, "Jump check (%s): diceroll: %d, DC: %d - %s\n\r", get_name(ch), roll, dc, roll >= dc ? "SUCCESS" : "FAILURE"); if (roll >= dc) { gain_favor(ch, DOMAIN_STRENGTH, 2); gain_favor(ch, DOMAIN_TRAVEL, 2); } pop_call(); return( roll - dc ); } bool mount_check( CHAR_DATA *ch, CHAR_DATA *och, int roll, int dc ) { push_call("mount_check(%p,%p,%p,%p)",ch,och,roll,dc); wiz_printf_room( ch, "Mount check (%s): diceroll: %d, DC: %d - %s\n\r", get_name(ch), roll, dc, roll >= dc ? "SUCCESS" : "FAILURE"); if (och && och->in_room != ch->in_room) wiz_printf_room( och, "Mount check (%s): diceroll: %d, DC: %d - %s\n\r", get_name(ch), roll, dc, roll >= dc ? "SUCCESS" : "FAILURE"); pop_call(); return( roll >= dc ); } bool pick_lock_check( CHAR_DATA *ch, CHAR_DATA *och, int roll, int dc ) { OBJ_DATA *lockpick; push_call("pick_lock_check(%p,%p,%p,%p)",ch,och,roll,dc); if (!learned(ch, gsn_pick_lock) && !learned(ch, gsn_jack_of_all_trades)) { pop_call(); return FALSE; } if ((lockpick = get_obj_carry_type(ch, ITEM_TOOLS)) != NULL) { if (TOOL_TYPE(lockpick, TOOL_THIEVES_TOOLS)) { if (lockpick->value[1] == 0) { act( "Your tools are worn from overuse.", ch, NULL, NULL, TO_CHAR); junk_obj(lockpick); dc += 5; } else { lockpick->value[1]--; if (IS_OBJ_STAT(lockpick, ITEM_MASTERWORK)) { if (lockpick->value[2] > 0) roll += lockpick->value[2]; else roll += 2; } } } else { act( "You suffer a penalty for not holding thieves tools.", ch, NULL, NULL, TO_CHAR); dc += 5; } } else { act( "You suffer a penalty for not holding thieves tools.", ch, NULL, NULL, TO_CHAR); dc += 5; } wiz_printf_room( ch, "Open Lock check (%s): diceroll: %d, DC: %d - %s\n\r", get_name(ch), roll, dc, roll >= dc ? "SUCCESS" : "FAILURE"); if (och && och->in_room != ch->in_room) wiz_printf_room( och, "Open Lock check (%s): diceroll: %d, DC: %d - %s\n\r", get_name(ch), roll, dc, roll >= dc ? "SUCCESS" : "FAILURE"); if (roll >= dc) { gain_favor(ch, DOMAIN_ARTIFICE, 2); gain_favor(ch, DOMAIN_TRICKERY, 2); } pop_call(); return( roll >= dc ); } bool perception_check( CHAR_DATA *ch, CHAR_DATA *och, int roll, int dc ) { push_call("perception_check(%p,%p,%p,%p)",ch,och,roll,dc); if (roll < 0) { pop_call(); return FALSE; } if (och != NULL) { roll += fave_enemy_bonus(ch,och); } wiz_printf_room( ch, "Perception check (%s): diceroll: %d, DC: %d - %s\n\r", get_name(ch), roll, dc, roll >= dc ? "SUCCESS" : "FAILURE"); if (och && och->in_room != ch->in_room) wiz_printf_room( och, "Perception check (%s): diceroll: %d, DC: %d - %s\n\r", get_name(ch), roll, dc, roll >= dc ? "SUCCESS" : "FAILURE"); if (roll >= dc) { gain_favor(ch, DOMAIN_KNOWLEDGE, 1); } pop_call(); return( roll >= dc ); } bool search_check( CHAR_DATA *ch, CHAR_DATA *och, int roll, int dc ) { push_call("search_check(%p,%p,%p,%p)",ch,och,roll,dc); if (ch->in_room->sector_type == SECT_UNDER_GROUND || ch->in_room->sector_type == SECT_DEEP_EARTH) { roll += synergy_bonus(ch, gsn_know_dungeoneering); } wiz_printf_room( ch, "Search check (%s): diceroll: %d, DC: %d - %s\n\r", get_name(ch), roll, dc, roll >= dc ? "SUCCESS" : "FAILURE"); if (och && och->in_room != ch->in_room) wiz_printf_room( och, "Search check (%s): diceroll: %d, DC: %d - %s\n\r", get_name(ch), roll, dc, roll >= dc ? "SUCCESS" : "FAILURE"); if (roll >= dc) { gain_favor(ch, DOMAIN_KNOWLEDGE, 1); } pop_call(); return( roll >= dc ); } bool sense_motive_check( CHAR_DATA *ch, CHAR_DATA *och, int roll, int dc ) { push_call("sense_motive_check(%p,%p,%p,%p)",ch,och,roll,dc); if (och != NULL) { roll += fave_enemy_bonus(ch,och); dc += fave_enemy_bonus(och,ch); } wiz_printf_room( ch, "Sense Motive check (%s): diceroll: %d, DC: %d - %s\n\r", get_name(ch), roll, dc, roll >= dc ? "SUCCESS" : "FAILURE"); if (och && och->in_room != ch->in_room) wiz_printf_room( och, "Sense Motive check (%s): diceroll: %d, DC: %d - %s\n\r", get_name(ch), roll, dc, roll >= dc ? "SUCCESS" : "FAILURE"); if (roll >= dc) { gain_favor(ch, DOMAIN_KNOWLEDGE, 1); } pop_call(); return( roll >= dc ); } bool sleight_of_hand_check( CHAR_DATA *ch, CHAR_DATA *och, int roll, int dc ) { push_call("sleight_of_hand_check(%p,%p,%p,%p)",ch,och,roll,dc); if (!learned(ch, gsn_sleight_of_hand) && !learned(ch, gsn_jack_of_all_trades)) { pop_call(); return FALSE; } if (och != NULL && dc <= 0) { dc = perception_roll(och, SENSE_SIGHT); dc += fave_enemy_bonus(och, ch); } wiz_printf_room( ch, "Sleight of Hand check (%s): diceroll: %d, DC: %d - %s\n\r", get_name(ch), roll, dc, roll >= dc ? "SUCCESS" : "FAILURE"); if (och && och->in_room != ch->in_room) wiz_printf_room( och, "Sleight of Hand check (%s): diceroll: %d, DC: %d - %s\n\r", get_name(ch), roll, dc, roll >= dc ? "SUCCESS" : "FAILURE"); if (roll >= dc) { gain_favor(ch, DOMAIN_CHAOS, 2); gain_favor(ch, DOMAIN_TRICKERY, 2); } pop_call(); return( roll >= dc ); } bool sneak_check( CHAR_DATA *ch, CHAR_DATA *och, int roll, int dc ) { push_call("sneak_check(%p,%p,%p,%p)",ch,och,roll,dc); if (och != NULL && dc <= 0) { dc = perception_roll(och, SENSE_SOUND); dc += fave_enemy_bonus(och, ch); } wiz_printf_room( ch, "Sneak check (%s): diceroll: %d, DC: %d - %s\n\r", get_name(ch), roll, dc, roll >= dc ? "SUCCESS" : "FAILURE"); if (och && och->in_room != ch->in_room) wiz_printf_room( och, "Sneak check (%s): diceroll: %d, DC: %d - %s\n\r", get_name(ch), roll, dc, roll >= dc ? "SUCCESS" : "FAILURE"); pop_call(); return( roll >= dc ); } bool spellcraft_check( CHAR_DATA *ch, CHAR_DATA *och, int sn, int roll, int dc ) { push_call("spellcraft_check(%p,%p,%p,%p,%p)",ch,och,sn,roll,dc); if (!learned(ch, gsn_spellcraft) && !learned(ch, gsn_jack_of_all_trades)) { pop_call(); return FALSE; } if (sn > -1) { if (school_spell(ch, sn)) roll += 2; else if (opposing_school(ch, sn)) roll -= 5; } if (och && learned(och, gsn_furtive_spell) && !learned(ch, gsn_shadow_casting)) { dc += 4; } wiz_printf_room( ch, "Spellcraft check (%s): diceroll: %d, DC: %d - %s\n\r", get_name(ch), roll, dc, roll >= dc ? "SUCCESS" : "FAILURE"); if (och && och->in_room != ch->in_room) wiz_printf_room( och, "Spellcraft check (%s): diceroll: %d, DC: %d - %s\n\r", get_name(ch), roll, dc, roll >= dc ? "SUCCESS" : "FAILURE"); if (roll >= dc) { gain_favor(ch, DOMAIN_KNOWLEDGE, 2); gain_favor(ch, DOMAIN_MAGIC, 2); } pop_call(); return( roll >= dc ); } bool survival_check( CHAR_DATA *ch, CHAR_DATA *och, int roll, int dc ) { push_call("survival_check(%p,%p,%p,%p)",ch,och,roll,dc); if (och != NULL) { roll += fave_enemy_bonus(ch,och); } if (ch->in_room->sector_type == SECT_UNDER_GROUND || ch->in_room->sector_type == SECT_DEEP_EARTH) { roll += synergy_bonus(ch, gsn_know_dungeoneering); } if (ch->in_room->sector_type == SECT_FIELD || ch->in_room->sector_type == SECT_FOREST || ch->in_room->sector_type == SECT_HILLS || ch->in_room->sector_type == SECT_MOUNTAIN || ch->in_room->sector_type == SECT_LAKE || ch->in_room->sector_type == SECT_RIVER || ch->in_room->sector_type == SECT_OCEAN || ch->in_room->sector_type == SECT_DESERT || ch->in_room->sector_type == SECT_SWAMP || ch->in_room->sector_type == SECT_BEACH || ch->in_room->sector_type == SECT_TUNDRA) { roll += synergy_bonus(ch, gsn_know_nature); } wiz_printf_room( ch, "Survival check (%s): diceroll: %d, DC: %d - %s\n\r", get_name(ch), roll, dc, roll >= dc ? "SUCCESS" : "FAILURE"); if (och && och->in_room != ch->in_room) wiz_printf_room( och, "Survival check (%s): diceroll: %d, DC: %d - %s\n\r", get_name(ch), roll, dc, roll >= dc ? "SUCCESS" : "FAILURE"); if (roll >= dc) { gain_favor(ch, DOMAIN_ANIMAL, 2); gain_favor(ch, DOMAIN_CAVERN, 2); gain_favor(ch, DOMAIN_PLANT, 2); gain_favor(ch, DOMAIN_TRAVEL, 2); } pop_call(); return( roll >= dc ); } bool swim_check(CHAR_DATA *ch, int dc) { int roll, swim_dc, stamina; push_call("swim_check(%p)",ch); //immortals cannot drown if (IS_IMMORTAL(ch)) { pop_call(); return TRUE; } switch (ch->in_room->sector_type) { case SECT_LAKE: swim_dc = 10; break; case SECT_OCEAN: case SECT_UNDER_WATER: swim_dc = 15; break; default: pop_call(); return TRUE; } //adjust speed for non-aquatic races to half if (!CAN_SWIM(ch)) ch->speed = 0; swim_dc += dc; //stormy water adds to dc switch (ch->in_room->area->weather_info->sky) { case 0: case 1: swim_dc += 0; break; case 2: swim_dc += 3; break; case 3: swim_dc += 5; break; } if (in_combat(ch)) { swim_dc += 2; } roll = swim_roll(ch); stamina = get_max_move(ch) / (ch->perm_con * 2); wiz_printf_room( ch, "Swim check (%s): diceroll: %d, DC: %d - %s\n\r", get_name(ch), roll, swim_dc, roll >= swim_dc ? "SUCCESS" : "FAILURE"); /* if he's out, he's going down. */ if (!IS_AWAKE(ch)) { gain_condition(ch, COND_AIR, -1); TAKE_ACTION(ch, ACTION_STANDARD); pop_call(); return FALSE; } /* fails the roll by 5 or more, or is exhausted, he goes under */ else if ((ch->move == 0 || roll - swim_dc <= -5) && !CAN_BREATH_WATER(ch) && must_breathe(ch)) { act( "{048}You fail to keep yourself above water, and choke and tire!{300}", ch, NULL, NULL, TO_CHAR); act( "{048}$n fails to swim, and gulps some water!{300}", ch, NULL, NULL, TO_ROOM); ch->move = UMAX(0, ch->move - stamina); gain_condition(ch, COND_AIR, -1); TAKE_ACTION(ch, ACTION_STANDARD); pop_call(); return FALSE; } /* Makes the swim roll, let him take a breath with each success */ if (ch->pcdata->condition[COND_AIR] < max_air(ch)) { gain_condition(ch, COND_AIR, 1); } /* fails the roll by 4 or less, treads the water */ if (roll - swim_dc < 0) { act( "{048}You try to swim, but don't make much progress.{300}", ch, NULL, NULL, TO_CHAR); act( "{048}$n tries to swim, but doesn't make much progress.{300}", ch, NULL, NULL, TO_ROOM); TAKE_ACTION(ch, ACTION_MOVE); pop_call(); return FALSE; } pop_call(); return (roll >= swim_dc); } bool tumble_check( CHAR_DATA *ch, CHAR_DATA *och, int roll, int dc ) { push_call("tumble_check(%p,%p,%p,$p)",ch,och,roll,dc); if (!learned(ch, gsn_tumble) && !learned(ch, gsn_jack_of_all_trades)) { pop_call(); return FALSE; } else if (encumberance(ch) >= VERY_ENCUMBERED) { send_to_char("You cannot perform tumbling acts with so much weight!", ch); pop_call(); return FALSE; } if (IS_ENCUMBERED(ch)) roll -= 6; if (IS_SET(ch->in_room->room_flags, ROOM_ICE) && !IS_AFFECTED(ch, AFF_WATER_WALK)) { dc += 5; } else if (IS_OUTSIDE(ch) && ch->in_room->area->weather_info->sky == 3) { dc += 5; } else if (IS_OUTSIDE(ch) && ch->in_room->area->weather_info->sky == 2) { dc += 2; } if (ch->in_room) { if (ch->in_room->sector_type == SECT_HILLS || ch->in_room->sector_type == SECT_SWAMP || ch->in_room->sector_type == SECT_BEACH) { dc += 2; } if (ch->in_room->sector_type == SECT_FOREST || ch->in_room->sector_type == SECT_MOUNTAIN || ch->in_room->sector_type == SECT_UNDER_GROUND || ch->in_room->sector_type == SECT_DEEP_EARTH || ch->in_room->sector_type == SECT_TUNDRA) { dc += 5; } } wiz_printf_room( ch, "Tumble check (%s): diceroll: %d, DC: %d - %s\n\r", get_name(ch), roll, dc, roll >= dc ? "SUCCESS" : "FAILURE"); if (och && och->in_room != ch->in_room) wiz_printf_room( och, "Tumble check (%s): diceroll: %d, DC: %d - %s\n\r", get_name(ch), roll, dc, roll >= dc ? "SUCCESS" : "FAILURE"); pop_call(); return( roll >= dc ); } bool use_magic_check( CHAR_DATA *ch, CHAR_DATA *och, int roll, int dc ) { push_call("use_magic_check(%p,%p,%p.%p)",ch,och,roll,dc); if (!learned(ch, gsn_use_magic) && !learned(ch, gsn_jack_of_all_trades)) { pop_call(); return FALSE; } wiz_printf_room( ch, "Use Magic Device check (%s): diceroll: %d, DC: %d - %s\n\r", get_name(ch), roll, dc, roll >= dc ? "SUCCESS" : "FAILURE"); if (och && och->in_room != ch->in_room) wiz_printf_room( och, "Use Magic Device check (%s): diceroll: %d, DC: %d - %s\n\r", get_name(ch), roll, dc, roll >= dc ? "SUCCESS" : "FAILURE"); if (roll >= dc) { gain_favor(ch, DOMAIN_KNOWLEDGE, 2); gain_favor(ch, DOMAIN_MAGIC, 2); } pop_call(); return( roll >= dc ); } int craft_alchemy_roll( CHAR_DATA *ch ) { int roll; push_call("craft_alchemy_roll(%p)",ch); roll = dice(1,20); roll += stat_mods(ch, APPLY_INT); if (domain_skill(ch, gsn_divine_craftsmanship)) roll += UMIN(class_level(ch, CLASS_CLERIC), stat_bonus(TRUE, ch, APPLY_WIS)); roll += learned(ch, gsn_craft_alchemy); roll += get_apply(ch, APPLY_CRAFT_ALCHEMY); // strip one-shot enhancements if (is_affected(ch, gsn_guidance)) affect_strip(ch, gsn_guidance); if (is_affected(ch, gsn_moment_of_prescience)) affect_strip(ch, gsn_moment_of_prescience); pop_call(); return( roll ); } int craft_armor_roll( CHAR_DATA *ch ) { int roll; push_call("craft_armor_roll(%p)",ch); roll = dice(1,20); roll += stat_mods(ch, APPLY_INT); if (domain_skill(ch, gsn_divine_craftsmanship)) roll += UMIN(class_level(ch, CLASS_CLERIC), stat_bonus(TRUE, ch, APPLY_WIS)); roll += learned(ch, gsn_craft_armor); roll += get_apply(ch, APPLY_CRAFT_ARMOR); // strip one-shot enhancements if (is_affected(ch, gsn_guidance)) affect_strip(ch, gsn_guidance); if (is_affected(ch, gsn_moment_of_prescience)) affect_strip(ch, gsn_moment_of_prescience); pop_call(); return( roll ); } int craft_bow_roll( CHAR_DATA *ch ) { int roll; push_call("craft_bow_roll(%p)",ch); roll = dice(1,20); roll += stat_mods(ch, APPLY_INT); if (domain_skill(ch, gsn_divine_craftsmanship)) roll += UMIN(class_level(ch, CLASS_CLERIC), stat_bonus(TRUE, ch, APPLY_WIS)); roll += learned(ch, gsn_craft_bows); roll += get_apply(ch, APPLY_CRAFT_BOWS); // strip one-shot enhancements if (is_affected(ch, gsn_guidance)) affect_strip(ch, gsn_guidance); if (is_affected(ch, gsn_moment_of_prescience)) affect_strip(ch, gsn_moment_of_prescience); pop_call(); return( roll ); } int craft_cooking_roll( CHAR_DATA *ch ) { int roll; push_call("craft_cooking_roll(%p)",ch); roll = dice(1,20); roll += stat_mods(ch, APPLY_INT); if (domain_skill(ch, gsn_divine_craftsmanship)) roll += UMIN(class_level(ch, CLASS_CLERIC), stat_bonus(TRUE, ch, APPLY_WIS)); roll += learned(ch, gsn_craft_cooking); roll += get_apply(ch, APPLY_CRAFT_COOKING); // strip one-shot enhancements if (is_affected(ch, gsn_guidance)) affect_strip(ch, gsn_guidance); if (is_affected(ch, gsn_moment_of_prescience)) affect_strip(ch, gsn_moment_of_prescience); pop_call(); return( roll ); } int craft_fletch_roll( CHAR_DATA *ch ) { int roll; push_call("craft_fletch_roll(%p)",ch); roll = dice(1,20); roll += stat_mods(ch, APPLY_INT); if (domain_skill(ch, gsn_divine_craftsmanship)) roll += UMIN(class_level(ch, CLASS_CLERIC), stat_bonus(TRUE, ch, APPLY_WIS)); roll += learned(ch, gsn_craft_fletching); // strip one-shot enhancements if (is_affected(ch, gsn_guidance)) affect_strip(ch, gsn_guidance); if (is_affected(ch, gsn_moment_of_prescience)) affect_strip(ch, gsn_moment_of_prescience); pop_call(); return( roll ); } int craft_jewelry_roll( CHAR_DATA *ch ) { int roll; push_call("craft_jewelry_roll(%p)",ch); roll = dice(1,20); roll += stat_mods(ch, APPLY_INT); if (domain_skill(ch, gsn_divine_craftsmanship)) roll += UMIN(class_level(ch, CLASS_CLERIC), stat_bonus(TRUE, ch, APPLY_WIS)); roll += learned(ch, gsn_craft_jewelry); roll += get_apply(ch, APPLY_CRAFT_JEWELRY); // strip one-shot enhancements if (is_affected(ch, gsn_guidance)) affect_strip(ch, gsn_guidance); if (is_affected(ch, gsn_moment_of_prescience)) affect_strip(ch, gsn_moment_of_prescience); pop_call(); return( roll ); } int craft_leather_roll( CHAR_DATA *ch ) { int roll; push_call("craft_leather_roll(%p)",ch); roll = dice(1,20); roll += stat_mods(ch, APPLY_INT); if (domain_skill(ch, gsn_divine_craftsmanship)) roll += UMIN(class_level(ch, CLASS_CLERIC), stat_bonus(TRUE, ch, APPLY_WIS)); roll += learned(ch, gsn_craft_leather); roll += get_apply(ch, APPLY_CRAFT_LEATHER); // strip one-shot enhancements if (is_affected(ch, gsn_guidance)) affect_strip(ch, gsn_guidance); if (is_affected(ch, gsn_moment_of_prescience)) affect_strip(ch, gsn_moment_of_prescience); pop_call(); return( roll ); } int craft_mining_roll( CHAR_DATA *ch ) { int roll; push_call("craft_mining_roll(%p)",ch); roll = dice(1,20); roll += stat_mods(ch, APPLY_INT); if (domain_skill(ch, gsn_divine_craftsmanship)) roll += UMIN(class_level(ch, CLASS_CLERIC), stat_bonus(TRUE, ch, APPLY_WIS)); roll += learned(ch, gsn_craft_mining); roll += get_apply(ch, APPLY_CRAFT_MINING); // strip one-shot enhancements if (is_affected(ch, gsn_guidance)) affect_strip(ch, gsn_guidance); if (is_affected(ch, gsn_moment_of_prescience)) affect_strip(ch, gsn_moment_of_prescience); pop_call(); return( roll ); } int craft_poison_roll( CHAR_DATA *ch ) { int roll; push_call("craft_poison_roll(%p)",ch); roll = dice(1,20); roll += stat_mods(ch, APPLY_INT); if (domain_skill(ch, gsn_divine_craftsmanship)) roll += UMIN(class_level(ch, CLASS_CLERIC), stat_bonus(TRUE, ch, APPLY_WIS)); roll += learned(ch, gsn_craft_poison); roll += synergy_bonus(ch, gsn_craft_alchemy); roll += get_apply(ch, APPLY_CRAFT_POISON); if (learned(ch, gsn_poison_use)) roll += 4; // strip one-shot enhancements if (is_affected(ch, gsn_guidance)) affect_strip(ch, gsn_guidance); if (is_affected(ch, gsn_moment_of_prescience)) affect_strip(ch, gsn_moment_of_prescience); pop_call(); return( roll ); } int craft_tailor_roll( CHAR_DATA *ch ) { int roll; push_call("craft_tailor_roll(%p)",ch); roll = dice(1,20); roll += stat_mods(ch, APPLY_INT); if (domain_skill(ch, gsn_divine_craftsmanship)) roll += UMIN(class_level(ch, CLASS_CLERIC), stat_bonus(TRUE, ch, APPLY_WIS)); roll += learned(ch, gsn_craft_tailoring); roll += get_apply(ch, APPLY_CRAFT_TAILOR); // strip one-shot enhancements if (is_affected(ch, gsn_guidance)) affect_strip(ch, gsn_guidance); if (is_affected(ch, gsn_moment_of_prescience)) affect_strip(ch, gsn_moment_of_prescience); pop_call(); return( roll ); } int craft_trap_roll( CHAR_DATA *ch ) { int roll; push_call("craft_trap_roll(%p)",ch); roll = dice(1,20); roll += stat_mods(ch, APPLY_INT); if (domain_skill(ch, gsn_divine_craftsmanship)) roll += UMIN(class_level(ch, CLASS_CLERIC), stat_bonus(TRUE, ch, APPLY_WIS)); roll += learned(ch, gsn_craft_traps); roll += get_apply(ch, APPLY_CRAFT_TRAPS); // strip one-shot enhancements if (is_affected(ch, gsn_guidance)) affect_strip(ch, gsn_guidance); if (is_affected(ch, gsn_moment_of_prescience)) affect_strip(ch, gsn_moment_of_prescience); pop_call(); return( roll ); } int craft_weapon_roll( CHAR_DATA *ch ) { int roll; push_call("craft_weapon_roll(%p)",ch); roll = dice(1,20); roll += stat_mods(ch, APPLY_INT); if (domain_skill(ch, gsn_divine_craftsmanship)) roll += UMIN(class_level(ch, CLASS_CLERIC), stat_bonus(TRUE, ch, APPLY_WIS)); roll += learned(ch, gsn_craft_weapons); roll += get_apply(ch, APPLY_CRAFT_WEAPONS); // strip one-shot enhancements if (is_affected(ch, gsn_guidance)) affect_strip(ch, gsn_guidance); if (is_affected(ch, gsn_moment_of_prescience)) affect_strip(ch, gsn_moment_of_prescience); pop_call(); return( roll ); } bool know_arcana_check( CHAR_DATA *ch, int dc ) { int roll, ranks; push_call("know_arcana_roll(%p%p)",ch,dc); if ((ranks = learned(ch, gsn_know_arcana)) <= 0 && !learned(ch, gsn_jack_of_all_trades)) { if (dc > 10 && !learned(ch, gsn_lore)) { pop_call(); return FALSE; } } if (learned(ch, gsn_scholar) && ranks) roll = take_twenty(ch); else if (learned(ch, gsn_lore_mastery)) roll = take_ten(ch); else roll = dice(1,20); roll += ranks + stat_mods(ch, APPLY_INT); roll += multi_class_level(ch, gsn_lore) / 2; if (is_affected(ch, gsn_guidance)) affect_strip(ch, gsn_guidance); if (is_affected(ch, gsn_moment_of_prescience)) affect_strip(ch, gsn_moment_of_prescience); if (dc > 10 && roll >= dc) { gain_favor(ch, DOMAIN_KNOWLEDGE, 2); gain_favor(ch, DOMAIN_MAGIC, 2); } pop_call(); return( roll ); } bool know_dungeoneering_check( CHAR_DATA *ch, int dc ) { int roll, ranks; push_call("know_arcana_roll(%p%p)",ch,dc); if ((ranks = learned(ch, gsn_know_dungeoneering)) <= 0 && !learned(ch, gsn_jack_of_all_trades)) { if (dc > 10 && !learned(ch, gsn_lore)) { pop_call(); return FALSE; } } if (learned(ch, gsn_scholar) && ranks) roll = take_twenty(ch); else if (learned(ch, gsn_lore_mastery)) roll = take_ten(ch); else roll = dice(1,20); roll += ranks + stat_mods(ch, APPLY_INT); roll += multi_class_level(ch, gsn_lore) / 2; if (is_affected(ch, gsn_guidance)) affect_strip(ch, gsn_guidance); if (is_affected(ch, gsn_moment_of_prescience)) affect_strip(ch, gsn_moment_of_prescience); if (dc > 10 && roll >= dc) { gain_favor(ch, DOMAIN_KNOWLEDGE, 2); gain_favor(ch, DOMAIN_CAVERN, 2); gain_favor(ch, DOMAIN_TRAVEL, 2); } pop_call(); return( roll >= dc ); } bool know_geography_check( CHAR_DATA *ch, int dc ) { int roll, ranks; push_call("know_geography_roll(%p%p)",ch,dc); if ((ranks = learned(ch, gsn_know_geography)) <= 0 && !learned(ch, gsn_jack_of_all_trades)) { if (dc > 10 && !learned(ch, gsn_lore)) { pop_call(); return FALSE; } } if (learned(ch, gsn_scholar) && ranks) roll = take_twenty(ch); else if (learned(ch, gsn_lore_mastery)) roll = take_ten(ch); else roll = dice(1,20); roll += ranks + stat_mods(ch, APPLY_INT); roll += multi_class_level(ch, gsn_lore) / 2; if (is_affected(ch, gsn_guidance)) affect_strip(ch, gsn_guidance); if (is_affected(ch, gsn_moment_of_prescience)) affect_strip(ch, gsn_moment_of_prescience); if (dc > 10 && roll >= dc) { gain_favor(ch, DOMAIN_KNOWLEDGE, 2); gain_favor(ch, DOMAIN_TRAVEL, 2); } pop_call(); return( roll >= dc ); } bool know_history_check( CHAR_DATA *ch, int dc ) { int roll, ranks; push_call("know_history_roll(%p%p)",ch,dc); if ((ranks = learned(ch, gsn_know_history)) <= 0 && !learned(ch, gsn_jack_of_all_trades)) { if (dc > 10 && !learned(ch, gsn_lore)) { pop_call(); return FALSE; } } if (learned(ch, gsn_scholar) && ranks) roll = take_twenty(ch); else if (learned(ch, gsn_lore_mastery)) roll = take_ten(ch); else roll = dice(1,20); roll += ranks + stat_mods(ch, APPLY_INT); roll += multi_class_level(ch, gsn_lore) / 2; if (is_affected(ch, gsn_guidance)) affect_strip(ch, gsn_guidance); if (is_affected(ch, gsn_moment_of_prescience)) affect_strip(ch, gsn_moment_of_prescience); if (dc > 10 && roll >= dc) { gain_favor(ch, DOMAIN_KNOWLEDGE, 2); gain_favor(ch, DOMAIN_PLANNING, 2); } pop_call(); return( roll >= dc ); } bool know_local_check( CHAR_DATA *ch, int dc ) { int roll, ranks; push_call("know_local_roll(%p%p)",ch,dc); if ((ranks = learned(ch, gsn_know_local)) <= 0 && !learned(ch, gsn_jack_of_all_trades)) { if (dc > 10 && !learned(ch, gsn_lore)) { pop_call(); return FALSE; } } if (learned(ch, gsn_scholar) && ranks) roll = take_twenty(ch); else if (learned(ch, gsn_lore_mastery)) roll = take_ten(ch); else roll = dice(1,20); roll += ranks + stat_mods(ch, APPLY_INT); roll += multi_class_level(ch, gsn_lore) / 2; if (is_affected(ch, gsn_guidance)) affect_strip(ch, gsn_guidance); if (is_affected(ch, gsn_moment_of_prescience)) affect_strip(ch, gsn_moment_of_prescience); if (dc > 10 && roll >= dc) { gain_favor(ch, DOMAIN_KNOWLEDGE, 2); } pop_call(); return( roll >= dc ); } bool know_nature_check( CHAR_DATA *ch, int dc ) { int roll, ranks; push_call("know_nature_roll(%p%p)",ch,dc); if ((ranks = learned(ch, gsn_know_nature)) <= 0 && !learned(ch, gsn_jack_of_all_trades)) { if (dc > 10 && !learned(ch, gsn_lore)) { pop_call(); return FALSE; } } if (learned(ch, gsn_scholar) && ranks) roll = take_twenty(ch); else if (learned(ch, gsn_lore_mastery)) roll = take_ten(ch); else roll = dice(1,20); roll += ranks + stat_mods(ch, APPLY_INT); roll += multi_class_level(ch, gsn_lore) / 2; if (is_affected(ch, gsn_guidance)) affect_strip(ch, gsn_guidance); if (is_affected(ch, gsn_moment_of_prescience)) affect_strip(ch, gsn_moment_of_prescience); if (dc > 10 && roll >= dc) { gain_favor(ch, DOMAIN_KNOWLEDGE, 2); gain_favor(ch, DOMAIN_ANIMAL, 2); gain_favor(ch, DOMAIN_PLANT, 2); } pop_call(); return( roll >= dc ); } bool know_nobility_check( CHAR_DATA *ch, int dc ) { int roll, ranks; push_call("know_nobility_roll(%p%p)",ch,dc); if ((ranks = learned(ch, gsn_know_nobility)) <= 0 && !learned(ch, gsn_jack_of_all_trades)) { if (dc > 10 && !learned(ch, gsn_lore)) { pop_call(); return FALSE; } } if (learned(ch, gsn_scholar) && ranks) roll = take_twenty(ch); else if (learned(ch, gsn_lore_mastery)) roll = take_ten(ch); else roll = dice(1,20); roll += ranks + stat_mods(ch, APPLY_INT); roll += multi_class_level(ch, gsn_lore) / 2; if (is_affected(ch, gsn_guidance)) affect_strip(ch, gsn_guidance); if (is_affected(ch, gsn_moment_of_prescience)) affect_strip(ch, gsn_moment_of_prescience); if (dc > 10 && roll >= dc) { gain_favor(ch, DOMAIN_KNOWLEDGE, 2); gain_favor(ch, DOMAIN_LAW, 2); gain_favor(ch, DOMAIN_NOBILITY, 2); } pop_call(); return( roll >= dc ); } bool know_religion_check( CHAR_DATA *ch, int dc ) { int roll, ranks; push_call("know_religion_roll(%p%p)",ch,dc); if ((ranks = learned(ch, gsn_know_religion)) <= 0 && !learned(ch, gsn_jack_of_all_trades)) { if (dc > 10 && !learned(ch, gsn_lore)) { pop_call(); return FALSE; } } if (learned(ch, gsn_scholar) && ranks) roll = take_twenty(ch); else if (learned(ch, gsn_lore_mastery)) roll = take_ten(ch); else roll = dice(1,20); if (is_affected(ch, gsn_guidance)) affect_strip(ch, gsn_guidance); if (is_affected(ch, gsn_moment_of_prescience)) affect_strip(ch, gsn_moment_of_prescience); roll += ranks + stat_mods(ch, APPLY_INT); roll += multi_class_level(ch, gsn_lore) / 2; if (dc > 10 && roll >= dc) { gain_favor(ch, DOMAIN_KNOWLEDGE, 2); } pop_call(); return( roll >= dc ); } bool know_planes_check( CHAR_DATA *ch, int dc ) { int roll, ranks; push_call("know_planes_roll(%p%p)",ch,dc); if ((ranks = learned(ch, gsn_know_planes)) <= 0 && !learned(ch, gsn_jack_of_all_trades)) { if (dc > 10 && !learned(ch, gsn_lore)) { pop_call(); return FALSE; } } if (learned(ch, gsn_scholar) && ranks) roll = take_twenty(ch); else if (learned(ch, gsn_lore_mastery)) roll = take_ten(ch); else roll = dice(1,20); roll += ranks + stat_mods(ch, APPLY_INT); roll += multi_class_level(ch, gsn_lore) / 2; if (is_affected(ch, gsn_guidance)) affect_strip(ch, gsn_guidance); if (is_affected(ch, gsn_moment_of_prescience)) affect_strip(ch, gsn_moment_of_prescience); if (dc > 10 && roll >= dc) { gain_favor(ch, DOMAIN_KNOWLEDGE, 2); gain_favor(ch, DOMAIN_TRAVEL, 2); } pop_call(); return( roll >= dc ); } /* * Count the total levels of controlled creatures - Kregor */ int count_minions( CHAR_DATA *ch) { PET_DATA *pet; int cnt = 0; push_call("count_minions(%p)",ch); for (pet = mud->f_pet ; pet ; pet = pet->next) { if (pet->ch->master == ch) { if (IS_ACT(pet->ch, ACT_PET)) continue; if (IS_AFFECTED(pet->ch, AFF_DOMINATE)) cnt++; } } pop_call(); return( cnt ); } /* * Turn undead for paladin/cleric - Kregor 2/16/07 * Added domain support for elemental and plant types - Kregor 11/29/07 * Revised to PFRPG's channel energy mechanic - Kregor 2/10/10 * Added construct and lycan types for domains - Kregor 11/5/10 */ DO_ABILITY(ability_turn_undead) { CHAR_DATA *vch, *vch_next; int turn_dc, turn_dice, turn_dmg, count; bool fUndead = FALSE; bool fElemental = FALSE; bool fPlant = FALSE; bool fOutsider = FALSE; bool fReptile = FALSE; bool fLycan = FALSE; bool fTurned = FALSE; bool fCommand = FALSE; push_call("ability_turn_undead(%p,%p,%p,%p)",sn,level,ch,vo); if (sn == gsn_turn_undead || sn == gsn_command_undead) { fUndead = TRUE; } if (sn == gsn_command_undead) { fUndead = TRUE; fCommand = TRUE; } if (sn == gsn_turn_elemental) { fElemental = TRUE; fCommand = TRUE; } if (sn == gsn_turn_plants) { fPlant = TRUE; fCommand = TRUE; } if (sn == gsn_turn_outsider) { fPlant = TRUE; } if (sn == gsn_turn_reptiles) { fReptile = TRUE; fCommand = TRUE; } if (sn == gsn_turn_lycanthrope) { fLycan = TRUE; } turn_dice = ROUNDUP(level / 2); turn_dc = dice(1,20) + stat_bonus(TRUE, ch, APPLY_CHA) + turn_dice; turn_dc += synergy_bonus(ch, gsn_know_religion); if (learned(ch, gsn_imp_turning)) turn_dc += 2; if (learned(ch, gsn_empower_turning)) { if (fCommand) turn_dc += level/4 + 1; else turn_dice += level/4 + 1; } act( "{138}You brandish your holy symbol and chant...", ch, NULL, NULL, TO_CHAR ); act( "{138}$n brandishes $s holy symbol and chants...", ch, NULL, NULL, TO_ROOM ); for (count = 0, vch = ch->in_room->first_person ; vch ; vch = vch_next) { vch_next = vch->next_in_room; if (is_same_group(vch, ch)) continue; if (fElemental && (!rspec_req(vch, RSPEC_ELEMENTAL) || race_type(vch) != RTYPE_OUTSIDER)) continue; if (fOutsider && race_type(vch) != RTYPE_OUTSIDER) continue; fTurned = FALSE; if (fUndead && IS_UNDEAD(vch)) fTurned = TRUE; if (fPlant && race_type(vch) == RTYPE_PLANT) fTurned = TRUE; if (fReptile && race_type(vch) == RTYPE_ANIMAL && rspec_req(vch, RSPEC_REPTILIAN)) fTurned = TRUE; if (fLycan) { if (rspec_req(vch, RSPEC_SHAPECHANGER)) fTurned = TRUE; if ((IS_GOOD(ch) && IS_EVIL(vch)) || (IS_EVIL(ch) && IS_GOOD(vch))) fCommand = FALSE; else fCommand = TRUE; } if (fElemental) { if ((has_domain(ch, DOMAIN_AIR) && rspec_req(vch, RSPEC_AIR)) || (has_domain(ch, DOMAIN_EARTH) && rspec_req(vch, RSPEC_EARTH)) || (has_domain(ch, DOMAIN_FIRE) && rspec_req(vch, RSPEC_FIRE)) || (has_domain(ch, DOMAIN_WATER) && rspec_req(vch, RSPEC_WATER))) fTurned = TRUE; } if (fOutsider) { if ((has_domain(ch, DOMAIN_GOOD) && rspec_req(vch, RSPEC_EVIL)) || (has_domain(ch, DOMAIN_EVIL) && rspec_req(vch, RSPEC_GOOD)) || (has_domain(ch, DOMAIN_CHAOS) && rspec_req(vch, RSPEC_LAWFUL)) || (has_domain(ch, DOMAIN_LAW) && rspec_req(vch, RSPEC_CHAOTIC))) fTurned = TRUE; } if (!fTurned) continue; if (fCommand) { if (count_minions(ch) + vch->level > level) { act("{118}$N is too strong for you to command!", ch, NULL, vch, TO_CHAR); continue; } if (will_save(vch, ch, turn_dc - get_apply(vch, APPLY_TURN_RESIST), -1)) { act("{118}Your attempt to command $N has no effect!", ch, NULL, vch, TO_CHAR); act("{118}You resist $n's attempt to command you!", ch, NULL, vch, TO_VICT); continue; } AFFECT_DATA af; af.type = sn; af.location = APPLY_NONE; af.modifier = 0; af.duration = turn * turn_dice; af.bittype = AFFECT_TO_CHAR; af.bitvector = AFF_DOMINATE; af.level = level; affect_join( ch, vch, &af ); add_follower(vch, ch); act("{108}$N turns to regard you as master.", ch, NULL, vch, TO_CHAR); act("{108}You turn to regard $n as your master.", ch, NULL, vch, TO_VICT); act("{108}$N turns to regard $n as $S master.", ch, NULL, vch, TO_VICT); continue; } turn_dmg = dice(turn_dice, 6); if (will_save(vch, ch, turn_dc - get_apply(vch, APPLY_TURN_RESIST), -1)) { damage(ch, vch, turn_dmg/2, sn, NULL); } else { damage(ch, vch, turn_dmg, sn, NULL); } if (!valid_fight(ch, vch)) continue; AFFECT_DATA af; af.type = sn; af.location = APPLY_NONE; af.modifier = 0; af.duration = turn_dice; af.bittype = AFFECT_TO_CHAR; af.bitvector = AFF2_PARALYSIS; af.level = level; affect_join( ch, vch, &af ); count += vch->level; } if (count == 0) send_to_char_color( "Your attempt to turn has no effect.\n\r", ch ); pop_call(); return TRUE; } /* * Lay on hands for paladins - Kregor 12/26/07 */ DO_ABILITY(ability_lay_hands) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA *paf, *paf_next; int numdice, heal, paf_type, caster_check; bool dam = FALSE; push_call("ability_lay_hands(%p,%p,%p,%p)",sn,level,ch,vo); if ( stat_bonus(TRUE, ch, APPLY_CHA) < 1 ) { send_to_char( "You lack the command of presence to do that.\n\r", ch ); pop_call(); return FALSE; } numdice = level / 2; heal = dice(numdice, 6); caster_check = dice(1,20) + level + stat_bonus(TRUE, ch, APPLY_CHA); if (!IS_UNDEAD(victim)) { if (!strcasecmp(target_name, "fatigue")) { if (!learned(ch, gsn_layhands_fatigue)) { act("You do not know that divine blessing.", ch, NULL, NULL, TO_CHAR); pop_call(); return FALSE; } heal *= 2; victim->move = UMIN( victim->hit + heal, get_max_move(victim)); } else if (!strcasecmp(target_name, "disease")) { if (!learned(ch, gsn_layhands_disease)) { act("You do not know that divine blessing.", ch, NULL, NULL, TO_CHAR); pop_call(); return FALSE; } if (victim->first_disease != NULL) { DISEASE_DATA *dis, *dis_next; for (dis = victim->first_disease ; dis ; dis = dis_next) { dis_next = dis->next; if ((dis->dc && caster_check >= dis->dc) || (!dis->dc && caster_check >= disease_table[dis->type].dc)) disease_from_char(victim, dis); } } else { act("$N is not diseased.", ch, NULL, NULL, TO_CHAR); pop_call(); return FALSE; } } else if (!strcasecmp(target_name, "poison")) { if (!learned(ch, gsn_layhands_poison)) { act("You do not know that divine blessing.", ch, NULL, NULL, TO_CHAR); pop_call(); return FALSE; } if (victim->poison) { POISON_DATA *pd, *pd_next; if (IS_AFFECTED(victim, AFF_POISON) && caster_check >= 15) AFFECT_STRIP(victim, AFF_POISON); for (pd = victim->poison ; pd ; pd = pd_next) { pd_next = pd->next; if (caster_check >= (pd->dc ? pd->dc : poison_table[pd->type].dc)) { victim->poison = victim->poison->next; FREEMEM( pd ); } } } else { act("$N is not poisoned.", ch, NULL, NULL, TO_CHAR); pop_call(); return FALSE; } } else if (!strcasecmp(target_name, "blindness")) { if (!learned(ch, gsn_layhands_blindness)) { act("You do not know that divine blessing.", ch, NULL, NULL, TO_CHAR); pop_call(); return FALSE; } if (IS_BLIND(victim)) { AFFECT_STRIP(victim, AFF_BLIND); } else { act("$N can see perfectly well.", ch, NULL, NULL, TO_CHAR); pop_call(); return FALSE; } } else if (!strcasecmp(target_name, "curse")) { if (!learned(ch, gsn_layhands_curse)) { act("You do not know that divine blessing.", ch, NULL, NULL, TO_CHAR); pop_call(); return FALSE; } if (!spell_remove_curse(gsn_remove_curse, level, ch, vo, TAR_CHAR_DEFENSIVE)) { pop_call(); return FALSE; } } else if (!strcasecmp(target_name, "fear")) { if (!learned(ch, gsn_layhands_fear)) { act("You do not know that divine blessing.", ch, NULL, NULL, TO_CHAR); pop_call(); return FALSE; } for ( paf_type = 0, paf = victim->first_affect; paf != NULL; paf = paf_next ) { paf_next = paf->next; if (!IS_SET(paf->bitvector, AFF2_FEAR)) continue; paf_type = paf->type; if (caster_check < 11 + paf->level) continue; if (paf->duration >= 0) { if (skill_table[paf->type].msg_off) { act( skill_table[paf->type].msg_off, victim, NULL, NULL, TO_CHAR); } } affect_from_char(victim, paf); victim->fear_level = 0; } if (paf_type == 0) { act("$N does not seem to be frightened.", ch, NULL, victim, TO_CHAR); pop_call(); return FALSE; } } else { if (victim->hit >= get_max_hit(victim)) { act("$N does not need healing.", ch, NULL, victim, TO_CHAR); pop_call(); return FALSE; } victim->hit = UMIN( victim->hit + heal, get_max_hit(victim)); victim->nonlethal = UMAX(0, victim->nonlethal - heal); } } else { dam = TRUE; } if (ch != victim) { act( "{138}You lay your hands on $N and channel healing energy.", ch, NULL, victim, TO_CHAR ); act( "{138}$n lays hands upon you, channeling healing energy.", ch, NULL, victim, TO_VICT ); act( "{138}$n lays hands upon $N, channeling healing energy.", ch, NULL, victim, TO_NOTVICT ); } else { act( "{138}You lay hands upon yourself, channeling healing energy.", ch, NULL, victim, TO_CHAR ); act( "{138}$n lays hands upon $mself, channeling healing energy.", ch, NULL, victim, TO_ROOM ); } if (dam) { spell_damage(ch, victim, heal, sn, level); } update_pos(victim,-1); pop_call(); return TRUE; } /* * Another divine blessing or five - Kregor */ DO_ABILITY(ability_touch_of_courage) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; char col[10]; push_call("ability_touch_of_courage(%p,%p,%p,%p)",sn,level,ch,vo); if ((IS_GOOD(ch) && !IS_GOOD(victim)) || (IS_EVIL(ch) && !IS_EVIL(victim))) { act("You can only share your aura with someone of your alignment.", ch, NULL, victim, TO_CHAR); pop_call(); return FALSE; } if (IS_GOOD(ch)) strcpy(col, "{138}"); else strcpy(col, "{108}"); act("$t$n channels divine energy into $N.", ch, col, victim, TO_NOTVICT); act("$tYou channel your divine courage into $N.", ch, col, victim, TO_CHAR); act("$t$n channels $s divine courage into you.", ch, col, victim, TO_VICT); af.type = sn; af.location = APPLY_IMM_FEAR; af.modifier = 1; af.duration = 10 * level; af.bittype = AFFECT_TO_NONE; af.bitvector = AFF_NONE; affect_to_char( ch, victim, &af ); pop_call(); return TRUE; } DO_ABILITY(ability_touch_of_grace) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; char col[10]; push_call("ability_touch_of_grace(%p,%p,%p,%p)",sn,level,ch,vo); if ((IS_GOOD(ch) && !IS_GOOD(victim)) || (IS_EVIL(ch) && !IS_EVIL(victim))) { act("You can only share your aura with someone of your alignment.", ch, NULL, victim, TO_CHAR); pop_call(); return FALSE; } if (IS_GOOD(ch)) strcpy(col, "{138}"); else strcpy(col, "{108}"); act("$t$n channels divine energy into $N.", ch, col, victim, TO_NOTVICT); act("$tYou channel your divine grace into $N.", ch, col, victim, TO_CHAR); act("$t$n channels $s divine grace into you.", ch, col, victim, TO_VICT); af.type = sn; af.location = APPLY_SAVES; af.modifier = stat_bonus(TRUE, ch, APPLY_CHA); af.duration = 10 * level; af.bittype = AFFECT_TO_NONE; af.bitvector = AFF_NONE; affect_to_char( ch, victim, &af ); pop_call(); return TRUE; } DO_ABILITY(ability_touch_of_resolve) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; char col[10]; push_call("ability_touch_of_resolve(%p,%p,%p,%p)",sn,level,ch,vo); if ((IS_GOOD(ch) && !IS_GOOD(victim)) || (IS_EVIL(ch) && !IS_EVIL(victim))) { act("You can only share your aura with someone of your alignment.", ch, NULL, victim, TO_CHAR); pop_call(); return FALSE; } if (IS_GOOD(ch)) strcpy(col, "{138}"); else strcpy(col, "{108}"); act("$t$n channels divine energy into $N.", ch, col, victim, TO_NOTVICT); act("$tYou channel your divine resolve into $N.", ch, col, victim, TO_CHAR); act("$t$n channels $s divine resolve into you.", ch, col, victim, TO_VICT); af.type = sn; af.location = APPLY_IMM_CHARM; af.modifier = 1; af.duration = 10 * level; af.bittype = AFFECT_TO_NONE; af.bitvector = AFF_NONE; affect_to_char( ch, victim, &af ); pop_call(); return TRUE; } DO_ABILITY(ability_touch_of_zeal) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; char col[10]; push_call("ability_touch_of_zeal(%p,%p,%p,%p)",sn,level,ch,vo); if ((IS_GOOD(ch) && !IS_GOOD(victim)) || (IS_EVIL(ch) && !IS_EVIL(victim))) { act("You can only share your aura with someone of your alignment.", ch, NULL, victim, TO_CHAR); pop_call(); return FALSE; } if (IS_GOOD(ch)) strcpy(col, "{138}"); else strcpy(col, "{108}"); act("$t$n channels divine energy into $N.", ch, col, victim, TO_NOTVICT); act("$tYou channel your divine zeal into $N.", ch, col, victim, TO_CHAR); act("$t$n channels $s divine zeal into you.", ch, col, victim, TO_VICT); af.type = sn; af.location = APPLY_IMM_COMPULSION; af.modifier = 1; af.duration = 10 * level; af.bittype = AFFECT_TO_NONE; af.bitvector = AFF_NONE; affect_to_char( ch, victim, &af ); pop_call(); return TRUE; } DO_ABILITY(ability_touch_of_righteousness) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("ability_touch_of_righteousness(%p,%p,%p,%p)",sn,level,ch,vo); if (!IS_GOOD(victim)) { act("You can only share your aura with someone of your alignment.", ch, NULL, victim, TO_CHAR); pop_call(); return FALSE; } act("{138}$n channels divine energy into $N.", ch, NULL, victim, TO_NOTVICT); act("{138}You channel your divine righteousness into $N.", ch, NULL, victim, TO_CHAR); act("{138}$n channels $s divine righteousness into you.", ch, NULL, victim, TO_VICT); af.type = sn; af.location = APPLY_IMM_EVIL; af.modifier = 1; af.duration = 10 * level; af.bittype = AFFECT_TO_NONE; af.bitvector = AFF_NONE; affect_to_char( ch, victim, &af ); pop_call(); return TRUE; } DO_ABILITY(ability_touch_of_profanity) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("ability_touch_of_profanity(%p,%p,%p,%p)",sn,level,ch,vo); if (!IS_EVIL(victim)) { act("You can only share your aura with someone of your alignment.", ch, NULL, victim, TO_CHAR); pop_call(); return FALSE; } act("{108}$n channels divine energy into $N.", ch, NULL, victim, TO_NOTVICT); act("{108}You channel your divine profanity into $N.", ch, NULL, victim, TO_CHAR); act("{108}$n channels $s divine profanity into you.", ch, NULL, victim, TO_VICT); af.type = sn; af.location = APPLY_IMM_GOOD; af.modifier = 1; af.duration = 10 * level; af.bittype = AFFECT_TO_NONE; af.bitvector = AFF_NONE; affect_to_char( ch, victim, &af ); pop_call(); return TRUE; } /* * Paladin/Blackguard smite */ DO_ABILITY(ability_smite) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("ability_smite(%p,%p,%p,%p)",sn,level,ch,vo); act("{138}You call on the favor of your deity against $N.", ch, NULL, victim, TO_CHAR); act("{138}$n calls on the favor of $s deity against $N.", ch, NULL, victim, TO_NOTVICT); act("{138}$n calls on the favor of $s deity against you.", ch, NULL, victim, TO_VICT); if (sn == gsn_smite) { if ((IS_GOOD(ch) && !IS_EVIL(victim)) || (IS_EVIL(ch) && !IS_GOOD(victim))) { send_to_char("The gods do not answer your call.", ch); pop_call(); return FALSE; } } if (sn == gsn_smite_infidel) { if (!faith_enemies(ch, victim)) { act("$N is not of an opposing faith.", ch, NULL, victim, TO_CHAR); pop_call(); return FALSE; } } af.type = sn; af.location = APPLY_NONE; af.modifier = 0; af.duration = -1; af.bittype = AFFECT_TO_NONE; af.bitvector = AFF_NONE; affect_to_char( ch, victim, &af ); pop_call(); return TRUE; } /* * Corrupt Touch for Blackguards - Kregor 11/27/10 */ DO_ABILITY(ability_corrupt_touch) { CHAR_DATA *victim = (CHAR_DATA *) vo; int numdice, heal, caster_check; bool dam = FALSE; push_call("ability_corrupt_touch(%p,%p,%p,%p)",sn,level,ch,vo); if ( stat_bonus(TRUE, ch, APPLY_CHA) < 1 ) { send_to_char( "You lack the command of presence to do that.\n\r", ch ); pop_call(); return FALSE; } numdice = level / 2; heal = dice(numdice, 6); caster_check = dice(1,20) + level + stat_bonus(TRUE, ch, APPLY_CHA); if (!IS_UNDEAD(victim)) { if (!strcasecmp(target_name, "fatigue")) { if (!learned(ch, gsn_layhands_fatigue)) { act("You do not know that divine blessing.", ch, NULL, NULL, TO_CHAR); pop_call(); return FALSE; } heal *= 2; victim->move = UMAX(0, victim->move - heal); } else if (!strcasecmp(target_name, "disease")) { DISEASE_DATA *dis, *dis_next; if (!learned(ch, gsn_layhands_disease)) { act("You do not know that divine blessing.", ch, NULL, NULL, TO_CHAR); pop_call(); return FALSE; } if (save_resist(ch, victim, gsn_contagion, level)) { pop_call(); return TRUE; } infect_char(ch, victim, DIS_FILTH_FEVER); for (dis = victim->first_disease ; dis ; dis = dis_next) { dis_next = dis->next; if (dis->type != DIS_FILTH_FEVER) continue; if (dis->incubation < disease_table[dis->type].incubation) { dis->incubation = disease_table[dis->type].incubation; disease_update(victim); break; } } pop_call(); return TRUE; } else if (!strcasecmp(target_name, "poison")) { if (!learned(ch, gsn_layhands_poison)) { act("You do not know that divine blessing.", ch, NULL, NULL, TO_CHAR); pop_call(); return FALSE; } if (!spell_poison(gsn_poison, level, ch, vo, TAR_CHAR_OFFENSIVE)) { pop_call(); return FALSE; } } else if (!strcasecmp(target_name, "blindness")) { if (!learned(ch, gsn_layhands_blindness)) { act("You do not know that divine blessing.", ch, NULL, NULL, TO_CHAR); pop_call(); return FALSE; } if (!spell_affect(gsn_blindness, level, ch, vo, TAR_CHAR_OFFENSIVE)) { pop_call(); return FALSE; } } else if (!strcasecmp(target_name, "curse")) { if (!learned(ch, gsn_layhands_curse)) { act("You do not know that divine blessing.", ch, NULL, NULL, TO_CHAR); pop_call(); return FALSE; } if (!spell_affect(gsn_curse, level, ch, vo, TAR_CHAR_OFFENSIVE)) { pop_call(); return FALSE; } } else if (!strcasecmp(target_name, "fear")) { if (!learned(ch, gsn_layhands_fear)) { act("You do not know that divine blessing.", ch, NULL, NULL, TO_CHAR); pop_call(); return FALSE; } if (spell_cause_fear(gsn_cause_fear, level, ch, vo, TAR_CHAR_OFFENSIVE)) { pop_call(); return FALSE; } } else { dam = TRUE; } } else { dam = TRUE; } act( "{108}Your hand pulses with black energy as you touch $N.", ch, NULL, victim, TO_CHAR ); act( "{108}$n lays a blackened hand upon you.", ch, NULL, victim, TO_VICT ); act( "{108}$n lays a darkened hand upon $N.", ch, NULL, victim, TO_NOTVICT ); if (dam) { if (IS_UNDEAD(victim)) { victim->hit = UMIN( victim->hit + heal, get_max_hit(victim)); } else { spell_damage(ch, victim, heal, sn, level); } } update_pos(victim,-1); pop_call(); return TRUE; } /* * Battle Cry feat - aoe intimidate for rage ability - Kregor */ void battle_cry( CHAR_DATA *ch ) { CHAR_DATA *vch, *vch_next; AFFECT_DATA af; int roll; push_call("battle_cry(%p)",ch); if (!in_combat(ch) || !is_affected(ch, gsn_barbarian_rage)) { pop_call(); return; } roll = intimidate_roll(ch); for (vch = ch->in_room->last_person ; vch ; vch = vch_next) { vch_next = vch->prev_in_room; if (is_same_group(ch, vch)) continue; if (!can_mass_cast(ch, vch, gsn_intimidate)) continue; if (IS_AFFECTED(vch, AFF2_FEAR)) continue; if (intimidate_check(ch, vch, roll, 0) < 0) continue; af.type = gsn_intimidate; af.duration = 1; af.location = APPLY_NONE; af.modifier = 0; af.bittype = AFFECT_TO_CHAR; af.bitvector = AFF2_FEAR; af.level = ch->level; affect_to_char( ch, vch, &af ); vch->fear_level++; act( "$N is visibly intimidated by your presence.", ch, NULL, vch, TO_CHAR); act( "You are shaken at $n's intimidating presence.", ch, NULL, vch, TO_VICT); act( "$N is visibly intimidated by $n's presence.", ch, NULL, vch, TO_NOTVICT); } pop_call(); return; } /* * Barbarian Rage, reworked do_berserk - Kregor */ DO_ABILITY(ability_rage) { AFFECT_DATA af; int mod; push_call("ability_rage(%p,%p,%p,%p)",sn,level,ch,vo); if (IS_AFFECTED(ch, AFF2_BERSERK)) { send_to_char("You're already enraged!\n\r", ch); pop_call(); return FALSE; } act( "{118}The din of battle works you into a frenzied rage!",ch, NULL, NULL, TO_CHAR); act( "{118}$n works up into a frenzied rage!",ch, NULL, NULL, TO_ROOM); if (sn == gsn_blood_rage) { af.type = sn; af.duration = -1; af.bittype = AFFECT_TO_CHAR; af.bitvector = AFF2_BERSERK; af.modifier = 2; af.location = APPLY_STR; affect_join( ch, ch, &af ); af.modifier = 2; af.location = APPLY_CON; affect_join( ch, ch, &af ); af.modifier = -2; af.location = APPLY_DODGE; affect_join( ch, ch, &af ); pop_call(); return TRUE; } else if (learned(ch, gsn_mighty_rage)) { mod = 8; } else if (learned(ch, gsn_greater_rage)) { mod = 6; } else { mod = 4; } af.type = sn; af.duration = -1; af.bittype = AFFECT_TO_CHAR; af.bitvector = AFF2_BERSERK; af.modifier = mod; af.location = APPLY_STR; affect_join( ch, ch, &af ); af.modifier = mod / 2; af.location = APPLY_DODGE; affect_join( ch, ch, &af ); af.modifier = mod / 2; af.location = APPLY_MOR_REFL; affect_join( ch, ch, &af ); if (mod < 8) { af.modifier = -2; af.location = APPLY_COMP_TOHIT; affect_join( ch, ch, &af ); } if (learned(ch, gsn_battle_cry)) { battle_cry(ch); } pop_call(); return TRUE; } /* * Retribution domain ability */ DO_ABILITY(ability_retributive_strike) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("ability_retributive_strike(%p,%p,%p,%p)",sn,level,ch,vo); if (!victim->last_attacker) { act("You have not been recently injured in current combat.", ch, NULL, NULL, TO_CHAR); pop_call(); return FALSE; } act("{138}You call upon divine retribution!", ch, NULL, victim, TO_CHAR); act("{138}$n calls upon divine retribution!", ch, NULL, victim, TO_ROOM); af.type = sn; af.location = APPLY_NONE; af.modifier = 0; af.duration = -1; af.bittype = AFFECT_TO_NONE; af.bitvector = AFF_NONE; affect_to_char( ch, victim, &af ); pop_call(); return TRUE; } /* * Shapechange skill for druids */ DO_ABILITY(ability_wildshape) { char buf[MAX_INPUT_LENGTH]; int race; push_call("ability_wildshape(%p,%p,%p,%p)",sn,level,ch,vo); if (!is_string(target_name)) { ch_printf_color(ch, "Wildshape into what?\n\r"); pop_call(); return FALSE; } // if (is_polymorph(ch)) // { // ch_printf_color(ch, "You are already in an alternate form.\n\r"); // pop_call(); // return; // } if ((race = lookup_race(target_name)) == -1) { ch_printf_color(ch, "%s is not a valid race.\n\r", target_name); pop_call(); return FALSE; } sprintf(buf, "%s", race_table[race].race_name); if (race == get_race(ch)) { ch_printf_color(ch, "You are already %s %s.\n\r", a_an(buf), buf); pop_call(); return FALSE; } if (learned(ch, gsn_infinite_wildshape)) { if (race_table[race].type != RTYPE_ANIMAL && race_table[race].type != RTYPE_PLANT && race_table[race].type != RTYPE_VERMIN) { ch_printf_color(ch, "You cannot assume the form of %s %s.\n\r", a_an(buf), buf); pop_call(); return FALSE; } } else if (race_table[race].type != RTYPE_ANIMAL) { if (race_table[race].type == RTYPE_PLANT && !learned(ch, gsn_wildshape_plant)) { ch_printf_color(ch, "You cannot assume the form of %s %s.\n\r", a_an(buf), buf); pop_call(); return FALSE; } else if (!IS_SET(race_table[race].flags, RSPEC_ELEMENTAL)) { if (!learned(ch, gsn_wildshape_elemental)) { ch_printf_color(ch, "You cannot assume the form of %s %s.\n\r", a_an(buf), buf); pop_call(); return FALSE; } if (race_table[race].size < SIZE_SMALL) { ch_printf_color(ch, "%s %s is too small a creature.\n\r", a_an(buf), buf); pop_call(); return FALSE; } else if (race_table[race].size > SIZE_LARGE) { ch_printf_color(ch, "%s %s is too large a creature.\n\r", a_an(buf), buf); pop_call(); return FALSE; } } else { ch_printf_color(ch, "You cannot assume the form of %s %s.\n\r", a_an(buf), buf); pop_call(); return FALSE; } } else { if (race_table[race].size < SIZE_TINY) { ch_printf_color(ch, "%s %s is too small a creature.\n\r", a_an(buf), buf); pop_call(); return FALSE; } else if (race_table[race].size < SIZE_SMALL && !learned(ch, gsn_wildshape_tiny)) { ch_printf_color(ch, "%s %s is too small a creature.\n\r", a_an(buf), buf); pop_call(); return FALSE; } else if (race_table[race].size > SIZE_HUGE) { ch_printf_color(ch, "%s %s is too large a creature.\n\r", a_an(buf), buf); pop_call(); return FALSE; } else if (race_table[race].size > SIZE_LARGE && !learned(ch, gsn_wildshape_huge)) { ch_printf_color(ch, "%s %s is too large a creature.\n\r", a_an(buf), buf); pop_call(); return FALSE; } else if (race_table[race].size > SIZE_MEDIUM && !learned(ch, gsn_wildshape_large)) { ch_printf_color(ch, "%s %s is too large a creature.\n\r", a_an(buf), buf); pop_call(); return FALSE; } } if (level < race_table[race].hit_dice) { ch_printf_color(ch, "%s %s is too strong a creature.\n\r", a_an(buf), buf); pop_call(); return FALSE; } if (!morph(ch, ch, race, gsn_wildshape, level)) { pop_call(); return FALSE; } pop_call(); return TRUE; } /* * Animal companion summoning * for druids and rangers - Kregor 3/19/07 */ DO_ABILITY(ability_companion) { MOB_INDEX_DATA *pMob; CHAR_DATA *mob = NULL; char arg[MAX_INPUT_LENGTH]; char buf[MAX_STRING_LENGTH]; int race, bonus; push_call("ability_companion(%p,%p,%p,%p)",sn,level,ch,vo); if( IS_NPC( ch ) ) { pop_call(); return FALSE; } if (ch->race != get_race(ch)) { send_to_char( "You cannot summon a companion while shapechanged.\r\n", ch ); pop_call(); return FALSE; } if (get_companion(ch) == NULL) { target_name = one_argument( target_name, arg ); if (arg[0] == '\0' || target_name[0] == '\0') { send_to_char( "Syntax: activate companion <animal type> <name> [adjective]\r\n", ch ); pop_call(); return FALSE; } if ((race = lookup_race(arg)) == -1 || race_table[race].type != RTYPE_ANIMAL || race_table[race].hit_dice + 1 >= level) { sprintf(buf, "You may summon one of the following:\n\r"); for (race = 0 ; race < MAX_RACE ; race++) { if (race_table[race].type != RTYPE_ANIMAL || (race_table[race].hit_dice > 2 && race_table[race].hit_dice + 1 >= level)) continue; if (!is_string(race_table[race].race_name)) continue; if (IS_SET(race_table[race].flags, RSPEC_AQUATIC) && !rspec_req(ch, RSPEC_AQUATIC)) continue; cat_sprintf(buf, "'%s' ", race_table[race].race_name); } strcat(buf, "\n\r"); send_to_char(justify(buf, get_page_width(ch)), ch); pop_call(); return FALSE; } if (IS_SET(race_table[race].flags, RSPEC_AQUATIC) && !rspec_req(ch, RSPEC_AQUATIC)) { send_to_char( "Only aquatic characters may have aquatic companions.\r\n", ch ); pop_call(); return FALSE; } pMob = get_mob_index(MOB_VNUM_COMPANION); /* Hard coded in mud.are */ mob = create_mobile( pMob ); mob->race = race; mob->level = UMAX(1, race_table[race].hit_dice); mob->perm_str = 10 + race_table[race].race_mod[0]; mob->perm_int = 10 + race_table[race].race_mod[3]; mob->perm_wis = 10 + race_table[race].race_mod[4]; mob->perm_cha = 10 + race_table[race].race_mod[5]; mob->size = race_table[race].size; mob->height = race_table[race].height; mob->weight = race_table[race].weight; mob->alignment = race_table[race].alignment; mob->ethos = race_table[race].ethos; target_name = one_argument(target_name, arg); if (!check_legal_name(mob, arg)) { junk_mob(mob); pop_call(); return FALSE; } if (target_name[0] != '\0') { RESTRING(mob->name, format("%s %s %s", race_table[race].race_name, arg, target_name)); RESTRING(mob->short_descr, format("%s, %s %s %s", capitalize(arg), a_an(target_name), target_name, race_table[race].race_name)); RESTRING(mob->long_descr, format("%s, %s %s %s is here.", capitalize(arg), a_an(target_name), target_name, race_table[race].race_name)); } else { RESTRING(mob->name, format("%s %s", race_table[race].race_name, arg)); RESTRING(mob->short_descr, format("%s, %s %s", capitalize(arg), a_an(race_table[race].race_name), race_table[race].race_name)); RESTRING(mob->long_descr, format("%s, %s %s is here.", capitalize(arg), a_an(race_table[race].race_name), race_table[race].race_name)); } char_to_room( mob, ch->in_room->vnum, TRUE ); SET_BIT(mob->act, ACT_PET|ACT_COMPANION|ACT_SENTINEL); bonus = UMAX(0, (level - race_table[race].hit_dice) / 3); mob->level = bonus * 2 + UMAX(1, race_table[race].hit_dice); mob->nat_armor = bonus * 2; mob->perm_str = 10 + race_table[race].race_mod[0] + bonus; mob->perm_dex = 10 + race_table[race].race_mod[1] + bonus; mob->max_hit = dice(mob->level, race_type_table[race_type(mob)].hit_die); mob->hit = get_max_hit(mob); } else { if (in_same_room(mob, ch)) { act("$N is already here beside you.", ch, NULL, mob, TO_CHAR); pop_call(); return FALSE; } char_from_room(mob); char_to_room( mob, ch->in_room->vnum, TRUE ); } act( "$N answers your call to the wild.", ch, NULL, mob, TO_CHAR); act( "$N companion answers $n's call to the wild.", ch, NULL, mob, TO_ROOM); add_follower( mob , ch ); pop_call(); return TRUE; } /* * Warhorse summoning for paladins - Kregor 12/05/09 */ DO_ABILITY(ability_warhorse) { MOB_INDEX_DATA *pMob; CHAR_DATA *mob; AFFECT_DATA af; char arg[MAX_INPUT_LENGTH]; push_call("ability_warhorse(%p,%p,%p,%p)",sn,level,ch,vo); if (ch->race != get_race(ch)) { send_to_char( "You cannot summon a warhorse while shapechanged.\r\n", ch ); pop_call(); return FALSE; } if ((mob = get_warhorse(ch)) == NULL) { if( target_name[0] == '\0' ) { send_to_char( "You need to give your mount a name.\r\n", ch ); pop_call(); return FALSE; } pMob = get_mob_index(MOB_VNUM_WARHORSE); /* Hard coded in mud.are */ mob = create_mobile( pMob ); target_name = one_argument(target_name, arg); if (!check_legal_name(mob, arg)) { junk_mob(mob); pop_call(); return FALSE; } char_to_room( mob, ch->in_room->vnum, TRUE ); if (target_name[0] != '\0') { RESTRING(mob->name, format("warhorse horse %s %s", arg, target_name)); RESTRING(mob->short_descr, format("%s, %s %s warhorse", capitalize(arg), a_an(target_name), target_name)); RESTRING(mob->long_descr, format("%s, %s %s warhorse stands here proudly.", capitalize(arg), a_an(target_name), target_name)); } else { RESTRING(mob->name, format("horse warhorse %s", arg)); RESTRING(mob->short_descr, format("%s, a regal warhorse", capitalize(arg))); RESTRING(mob->short_descr, format("%s, a regal warhorse stands here proudly.", capitalize(arg))); } mob->level = (level / 2) + race_table[mob->race].hit_dice; mob->nat_armor = ROUNDUP(level * 2 / 3); mob->perm_str = (level / 5) + 10 + race_table[mob->race].race_mod[0]; mob->perm_int = URANGE(6, level*2/3, 9) ; mob->max_hit = dice(mob->level, race_type_table[race_type(mob)].hit_die); mob->hit = get_max_hit(mob); while (mob->first_affect) { affect_from_char(mob, mob->first_affect); } if (level >= 10) { af.type = gsn_warhorse; af.duration = -1; af.bittype = AFFECT_TO_NONE; af.bitvector = AFF_NONE; af.location = APPLY_SPELL_RES; af.modifier = level + 11; af.level = level; affect_to_char( mob, mob, &af ); } if (level >= 6) { af.type = gsn_warhorse; af.duration = -1; af.level = level; af.bittype = AFFECT_TO_NONE; af.bitvector = AFF_NONE; af.location = APPLY_DR_EVIL; af.modifier = 5; affect_to_char( mob, mob, &af ); af.bitvector = AFF_NONE; af.location = APPLY_DR_COLD; af.modifier = 10; affect_to_char( mob, mob, &af ); af.bitvector = AFF_NONE; af.location = APPLY_DR_ACID; af.modifier = 10; affect_to_char( mob, mob, &af ); af.bitvector = AFF_NONE; af.location = APPLY_DR_ELECTRIC; af.modifier = 10; affect_to_char( mob, mob, &af ); } /* alignment settings for both blackguard and paladin */ if (IS_GOOD(ch)) mob->alignment = mob->ethos = 1000; else mob->alignment = mob->ethos = -1000; SET_BIT(mob->act, ACT_PET|ACT_WARHORSE|ACT_SENTINEL); add_follower( mob, ch ); } else { if (in_same_room(mob, ch)) { act("$N is already here beside you.", ch, NULL, mob, TO_CHAR); pop_call(); return FALSE; } char_from_room(mob); char_to_room( mob, ch->in_room->vnum, TRUE ); } act("$N answers your call from $S $t refuge.", ch, IS_GOOD(ch) ? "celestial" : "fiendish", mob, TO_CHAR); act("$N answers $n's call from $S $t refuge.", ch, IS_GOOD(ch) ? "celestial" : "fiendish", mob, TO_ROOM); pop_call(); return TRUE; } /* * Shadow companions for shadow dancers - Kregor 6/6/11 */ DO_ABILITY(ability_shadow_companion) { MOB_INDEX_DATA *pMob; CHAR_DATA *mob; char arg[MAX_INPUT_LENGTH]; push_call("ability_shadow_companion(%p,%p,%p,%p)",sn,level,ch,vo); if ((mob = get_companion(ch)) == NULL) { if( target_name[0] == '\0' ) { send_to_char( "You need to give your companion a name.\r\n", ch ); pop_call(); return FALSE; } pMob = get_mob_index(MOB_VNUM_SHADOW_BEAST); /* Hard coded in mud.are */ mob = create_mobile( pMob ); target_name = one_argument(target_name, arg); if (!check_legal_name(mob, arg)) { junk_mob(mob); pop_call(); return FALSE; } char_to_room( mob, ch->in_room->vnum, TRUE ); if (target_name[0] != '\0') { RESTRING(mob->name, format("shadow mastiff %s %s", arg, target_name)); RESTRING(mob->short_descr, format("%s, a shadow mastiff", capitalize(arg))); RESTRING(mob->long_descr, format("%s, %s %s shadow mastiff prowls here.", capitalize(arg), a_an(target_name), target_name)); } else { RESTRING(mob->name, format("shadow mastiff %s", arg)); RESTRING(mob->short_descr, format("%s, a shadow mastiff", capitalize(arg))); RESTRING(mob->short_descr, format("%s, {108}a jet black shadow mastiff prowls here.", capitalize(arg))); } int bonus = UMAX(0, (level - race_table[mob->race].hit_dice) / 3); mob->level = bonus * 2 + UMAX(1, race_table[mob->race].hit_dice); mob->nat_armor = bonus * 2; mob->perm_str = 10 + race_table[mob->race].race_mod[0] + bonus; mob->perm_dex = 10 + race_table[mob->race].race_mod[1] + bonus; mob->max_hit = dice(mob->level, race_type_table[race_type(mob)].hit_die); mob->hit = get_max_hit(mob); SET_BIT(mob->act, ACT_PET|ACT_COMPANION|ACT_SENTINEL); add_follower( mob, ch ); } else { if (in_same_room(mob, ch)) { act("$N is already here beside you.", ch, NULL, mob, TO_CHAR); pop_call(); return FALSE; } char_from_room(mob); char_to_room( mob, ch->in_room->vnum, TRUE ); } act("{108}$N answers your call from the shadows.", ch, NULL, mob, TO_CHAR); act("{108}$N answers $n's call from the shadows.", ch, NULL, mob, TO_ROOM); pop_call(); return TRUE; } /* * arcane archer ability functions - Kregor */ DO_ABILITY(ability_imbue_arrow) { CHAR_DATA *victim = (CHAR_DATA *) vo; OBJ_DATA *obj, *wield; AFFECT_DATA af; char arg[MAX_INPUT_LENGTH]; int spell, class, mana; push_call("ability_imbue_arrow(%p,%p,%p,%p)",sn,level,ch,vo); if (!is_string(target_name)) { act("Imbue with what spell?", ch, NULL, NULL, TO_CHAR); pop_call(); return FALSE; } if ((wield = get_wield(ch, FALSE)) == NULL || !is_bow(wield)) { act("You are not wielding a bow.", ch, NULL, NULL, TO_CHAR); pop_call(); return FALSE; } if ((obj = get_ammo(ch, wield)) == NULL) { act("You cannot find any ammo for that weapon.", ch, NULL, NULL, TO_CHAR); pop_call(); return FALSE; } if (IS_OBJ_STAT(obj, ITEM_MAGIC) || WEAPON_FLAG(obj, WFLAG_SPELL_STORING)) { act("$p is already magical.", ch, obj, NULL, TO_CHAR); pop_call(); return FALSE; } target_name = one_argument(target_name, arg); if ((spell = skill_lookup(arg)) == -1) { act("That is not a spell.", ch, NULL, NULL, TO_CHAR); pop_call(); return FALSE; } if ((class = prepared(ch, spell)) == -1) { if ((class = spontaneous_cast(ch, spell)) == -1) { act("You do not have that spell prepared.", ch, NULL, NULL, TO_CHAR); pop_call(); return FALSE; } } if ((mana = get_mana(ch, spell, skill_table[spell].skill_level[class], class)) > ch->mana[class]) { act("You do not have enough mana to imbue that spell.", ch, NULL, NULL, TO_CHAR); pop_call(); return FALSE; } ch->mana[class] -= mana; act( "{158}You imbue $p with $T.", ch, obj, skill_table[spell].name, TO_CHAR); af.type = sn; af.duration = 1; af.location = APPLY_WEAPON_FLAG; af.modifier = WFLAG_SPELL_STORING; af.bittype = AFFECT_TO_OBJ; af.bitvector = ITEM_MAGIC; af.level = level; affect_to_obj( ch,obj, &af); af.location = APPLY_OBJVAL_2; af.modifier = spell; af.bittype = AFFECT_TO_NONE; af.bitvector = AFF_NONE; affect_to_obj( ch,obj, &af); af.location = APPLY_OBJVAL_3; af.modifier = multi_class_level(ch, spell); af.level = level; one_hit(ch, victim, TYPE_UNDEFINED, 0, wield); pop_call(); return TRUE; } DO_ABILITY(ability_seeker_arrow) { CHAR_DATA *victim = (CHAR_DATA *) vo; OBJ_DATA *obj, *wield; AFFECT_DATA af; push_call("ability_seeker_arrow(%p,%p,%p,%p)",sn,level,ch,vo); if ((wield = get_wield(ch, FALSE)) == NULL || !is_bow(wield)) { act("You are not wielding a bow.", ch, NULL, NULL, TO_CHAR); pop_call(); return FALSE; } if ((obj = get_ammo(ch, wield)) == NULL) { act("You cannot find any ammo for that weapon.", ch, NULL, NULL, TO_CHAR); pop_call(); return FALSE; } if (IS_OBJ_STAT(obj, ITEM_MAGIC) || WEAPON_FLAG(obj, WFLAG_SEEKING)) { act("$p is already magical.", ch, obj, NULL, TO_CHAR); pop_call(); return FALSE; } act( "{158}You create an arrow of seeking.", ch, NULL, NULL, TO_CHAR); af.type = sn; af.duration = 1; af.location = APPLY_WEAPON_FLAG; af.modifier = WFLAG_SEEKING; af.bittype = AFFECT_TO_OBJ; af.bitvector = ITEM_MAGIC; af.level = multi_class_level(ch, sn); affect_to_obj( ch,obj, &af); one_hit(ch, victim, TYPE_UNDEFINED, 0, wield); pop_call(); return TRUE; } DO_ABILITY(ability_hail_of_arrows) { CHAR_DATA *victim = (CHAR_DATA *) vo; CHAR_DATA *vch, *vch_next; OBJ_DATA *ammo, *wield; int cnt, count; push_call("ability_hail_of_arrows(%p,%p,%p,%p)",sn,level,ch,vo); if ((wield = get_wield(ch, FALSE)) == NULL || !is_bow(wield)) { act("You are not wielding a bow.", ch, NULL, NULL, TO_CHAR); pop_call(); return FALSE; } if ((ammo = get_ammo(ch, wield)) == NULL) { act("You cannot find any ammo for that weapon.", ch, NULL, NULL, TO_CHAR); pop_call(); return FALSE; } one_hit(ch, victim, TYPE_UNDEFINED, 0, wield); count = class_level(ch, CLASS_ARCANE_ARCHER); for (cnt = 0, vch = victim->in_room->first_person ; vch ; vch = vch_next) { vch_next = vch->next_in_room; if (get_ammo(ch, wield) == NULL) break; if (!can_mass_attack(ch, vch)) continue; if (!is_same_group(victim, vch)) continue; if (vch == victim) continue; one_hit( ch, vch, TYPE_UNDEFINED, 0, wield ); cnt++; if (cnt >= count) break; } TAKE_ACTION(ch, ACTION_FULL); pop_call(); return TRUE; } DO_ABILITY(ability_energy_arrow) { CHAR_DATA *victim = (CHAR_DATA *) vo; OBJ_DATA *obj, *wield; AFFECT_DATA af; char echo[MAX_INPUT_LENGTH]; int flag; push_call("ability_energy_arrow(%p,%p,%p,%p)",sn,level,ch,vo); if ((wield = get_wield(ch, FALSE)) == NULL || !is_bow(wield)) { act("You are not wielding a bow.", ch, NULL, NULL, TO_CHAR); pop_call(); return FALSE; } if ((obj = get_ammo(ch, wield)) == NULL) { act("You cannot find any ammo for that weapon.", ch, NULL, NULL, TO_CHAR); pop_call(); return FALSE; } if (IS_OBJ_STAT(obj, ITEM_MAGIC)) { act("$p is already magical.", ch, obj, NULL, TO_CHAR); pop_call(); return FALSE; } if (!strcasecmp(target_name, "fire")) { flag = WFLAG_FLAMING_BURST; strcpy(echo, "flame"); } else if (!strcasecmp(target_name, "frost")) { flag = WFLAG_ICY_BURST; strcpy(echo, "frost"); } else if (!strcasecmp(target_name, "shock")) { flag = WFLAG_SHOCK_BURST; strcpy(echo, "electricity"); } else { flag = 0; echo[0] = '\0'; } if (!flag) { send_to_char("Which type of energy? fire, frost, or shock?\n\r", ch); pop_call(); return FALSE; } act( "{158}You create an arrow of $t.", ch, echo, NULL, TO_CHAR); af.type = sn; af.duration = 1; af.location = APPLY_WEAPON_FLAG; af.modifier = flag; af.bittype = AFFECT_TO_OBJ; af.bitvector = ITEM_MAGIC; af.level = multi_class_level(ch, sn); affect_to_obj( ch,obj, &af); one_hit(ch, victim, TYPE_UNDEFINED, 0, wield); pop_call(); return TRUE; } DO_ABILITY(ability_death_arrow) { OBJ_DATA *obj, *wield; CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("ability_death_arrow(%p,%p,%p,%p)",sn,level,ch,vo); if ((wield = get_wield(ch, FALSE)) == NULL || !is_bow(wield)) { act("You are not wielding a bow.", ch, NULL, NULL, TO_CHAR); pop_call(); return FALSE; } if ((obj = get_ammo(ch, wield)) == NULL) { act("You cannot find any ammo for that weapon.", ch, NULL, NULL, TO_CHAR); pop_call(); return FALSE; } if (IS_OBJ_STAT(obj, ITEM_MAGIC) || WEAPON_FLAG(obj, WFLAG_SPELL_STORING)) { act("$p is already magical.", ch, obj, NULL, TO_CHAR); pop_call(); return FALSE; } act( "{158}You create an arrow of death against $N!", ch, NULL, victim, TO_CHAR); af.type = sn; af.duration = 1; af.location = APPLY_WEAPON_FLAG; af.modifier = WFLAG_SLAYING; af.bittype = AFFECT_TO_OBJ; af.bitvector = ITEM_MAGIC; af.level = multi_class_level(ch, sn); affect_to_obj( ch,obj, &af); af.location = APPLY_OBJVAL_2; af.modifier = race_table[victim->race].type; af.bittype = AFFECT_TO_NONE; af.bitvector = AFF_NONE; affect_to_obj( ch,obj, &af); af.location = APPLY_OBJVAL_3; af.modifier = race_table[victim->race].flags; affect_to_obj( ch,obj, &af); one_hit(ch, victim, TYPE_UNDEFINED, 0, wield); pop_call(); return TRUE; } /* * Ranger/Druid Wild Empathy */ DO_ABILITY(ability_wild_empathy) { push_call("ability_wild_empathy(%p,%p,%p,%p)",sn,level,ch,vo); do_tame(ch, target_name); pop_call(); return TRUE; } /* * the TAME command is for the Wild Empathy ability per the SRD. * Variant uses the hit dice of the animal as a mod to the DC - Kregor */ void do_tame( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; int level; char *cmd = STRALLOC(argument); push_call("do_tame(%p,%p)",ch,argument); if (IS_SET(ch->action, ACTION_FULL)) { send_to_char("This action takes a full round to perform.\n\r", ch); pop_call(); return; } if ((level = multi_skill_level(ch, gsn_wild_empathy)) <= 0) { send_to_char("You are not skilled enough to tame the wild.\n\r", ch); pop_call(); return; } if (argument[0] == '\0') { send_to_char("Tame who?\n\r", ch); pop_call(); return; } if ((victim = get_char_room(ch, argument)) == NULL) { send_to_char("They aren't here.\n\r", ch); pop_call(); return; } if (!IS_NPC(victim)) { send_to_char("You cannot tame PCs.\n\r", ch); pop_call(); return; } if (!IS_ANIMAL(victim)) { act("$N cannot be tamed.", ch, NULL, victim, TO_CHAR); pop_call(); return; } CHECK_TURN(ch, victim); if (!ch->concentrating) { act( "You attempt to empathize with $N.", ch, NULL, victim, TO_CHAR); act( "$n attempts to empathize with $N.", ch, NULL, victim, TO_NOTVICT); ch->concentrating = TRUE; ch->skill_timer = 12; ch->timer_fun = do_tame; RESTRING(ch->cmd_argument, cmd); TAKE_ACTION(ch, ACTION_FULL); pop_call(); return; } int diceroll, dc; /* chance = handle animal roll vs. DC 15 + creature level */ diceroll = cha_roll(ch); diceroll += level / 2; diceroll += synergy_bonus(ch, gsn_handle_animal); dc = 15; dc += victim->level; if (IS_ACT(victim, ACT_AGGRESSIVE)) dc += 4; if (is_affected(victim, gsn_charm_animal)) { if (get_caster(victim, gsn_charm_animal) == ch) diceroll += 10; } if (!handle_animal_check(ch, victim, diceroll, dc)) { act( "$N reacts to you unfavorably.", ch, NULL, victim, TO_CHAR); act( "$n tries to tame $N, but fails.", ch, NULL, victim, TO_NOTVICT); pop_call(); return; } if (in_combat(victim) || IS_ACT(victim, ACT_AGGRESSIVE)) { if (in_combat(victim)) char_from_combat(victim); REMOVE_BIT(victim->act, ACT_AGGRESSIVE); act( "$n loses $s agression and is calmed.", victim, NULL, NULL, TO_ROOM); act( "You lose your agression and are calmed.", victim, NULL, NULL, TO_CHAR); pop_call(); return; } if (victim->master || IS_AFFECTED(victim, AFF_DOMINATE)) { act( "$N already has a master.", ch, NULL, victim, TO_CHAR); pop_call(); return; } // make effect temporary if too many followers - Kregor if (get_pet_levels(ch) + victim->level >= max_pet_levels(ch)) { AFFECT_DATA af; af.type = gsn_wild_empathy; af.duration = hr * level; af.location = 0; af.modifier = 0; af.bittype = AFFECT_TO_CHAR; af.bitvector = AFF_DOMINATE; af.level = level; affect_to_char( ch, victim, &af ); } else { SET_BIT(victim->act, ACT_PET|ACT_SENTINEL); } act( "$N reacts to you favorably, and follows you.", ch, NULL, victim, TO_CHAR); act( "$N reacts favorably to $n, and follows $m.", ch, NULL, victim, TO_NOTVICT); add_follower(victim, ch); pop_call(); return; } /* * Dwarven Defender class ability */ DO_ABILITY(ability_defensive_stance) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("ability_defensive_stance(%p,%p,%p,%p)",sn,level,ch,vo); if (is_affected(ch, sn)) { act("You are already in a defensive stance.", ch, NULL, NULL, TO_CHAR); pop_call(); return FALSE; } if (IS_AFFECTED(ch, AFF2_BERSERK)) { act("You are not focused enough.", ch, NULL, NULL, TO_CHAR); pop_call(); return FALSE; } if (IS_EXHAUSTED(ch) || (!learned(ch, gsn_tireless_defense) && IS_FATIGUED(ch))) { act("You are too tired to stand your ground.", ch, NULL, NULL, TO_CHAR); pop_call(); return FALSE; } act("{138}You plant your feet, and stand your ground!", ch, NULL, victim, TO_CHAR); act("{138}$n plants $s feet, and stands $s ground!", ch, NULL, victim, TO_ROOM); af.type = sn; af.location = APPLY_STR; af.modifier = 2; af.duration = 3 + stat_bonus(FALSE, victim, APPLY_CON); af.bittype = AFFECT_TO_NONE; af.bitvector = AFF_NONE; affect_join( ch, victim, &af ); af.location = APPLY_CON; af.modifier = 4; affect_join( ch, victim, &af ); af.location = APPLY_RES_SAVES; af.modifier = 2; affect_join( ch, victim, &af ); pop_call(); return TRUE; } /* * Eldritch Knight class ability */ DO_ABILITY(ability_arcane_weapon) { OBJ_DATA *wield; AFFECT_DATA af; lg_int bitv = 0; int mana, lvl; push_call("ability_arcane_weapon(%p,%p,%p,%p)",sn,level,ch,vo); if ((wield = get_wield(ch, FALSE)) == NULL) { act("You are not wielding a weapon.", ch, NULL, NULL, TO_CHAR); pop_call(); return FALSE; } if (IS_OBJ_STAT(wield, ITEM_MAGIC)) { act("$p is already magical.", ch, wield, NULL, TO_CHAR); pop_call(); return FALSE; } lvl = multi_class_level(ch, sn); if (is_string(target_name)) { if (strcasecmp(target_name, "fire")) { if (lvl < 7) { act("You cannot add that effect to $p.", ch, wield, NULL, TO_CHAR); pop_call(); return FALSE; } bitv = WFLAG_FLAMING; } else if (strcasecmp(target_name, "cold")) { if (lvl < 7) { act("You cannot add that effect to $p.", ch, wield, NULL, TO_CHAR); pop_call(); return FALSE; } bitv = WFLAG_FROST; } else if (strcasecmp(target_name, "acid")) { if (lvl < 7) { act("You cannot add that effect to $p.", ch, wield, NULL, TO_CHAR); pop_call(); return FALSE; } bitv = WFLAG_CAUSTIC; } else if (strcasecmp(target_name, "shock")) { if (lvl < 7) { act("You cannot add that effect to $p.", ch, wield, NULL, TO_CHAR); pop_call(); return FALSE; } bitv = WFLAG_SHOCK; } else if (strcasecmp(target_name, "vorpal")) { if (lvl < 9) { act("You cannot add that effect to $p.", ch, wield, NULL, TO_CHAR); pop_call(); return FALSE; } bitv = WFLAG_VORPAL; } else if (strcasecmp(target_name, "wounding")) { if (lvl < 9) { act("You cannot add that effect to $p.", ch, wield, NULL, TO_CHAR); pop_call(); return FALSE; } bitv = WFLAG_WOUNDING; } else if (strcasecmp(target_name, "aligned")) { if (lvl < 9) { act("You cannot add that effect to $p.", ch, wield, NULL, TO_CHAR); pop_call(); return FALSE; } if (IS_NEUTRAL(ch) && IS_UNCONCERNED(ch)) { act("You are too neutral to align $p.", ch, wield, NULL, TO_CHAR); pop_call(); return FALSE; } if (IS_GOOD(ch)) SET_BIT(bitv, WFLAG_HOLY); if (IS_EVIL(ch)) SET_BIT(bitv, WFLAG_UNHOLY); if (IS_LAWFUL(ch)) SET_BIT(bitv, WFLAG_AXIOMATIC); if (IS_CHAOTIC(ch)) SET_BIT(bitv, WFLAG_ANARCHIC); } else { send_to_char("That is not a valid effect.\n\r", ch); pop_call(); return FALSE; } } if (bitv) { if (WEAPON_FLAG(wield, bitv)) { act("$p already possesses that affect.", ch, wield, NULL, TO_CHAR); pop_call(); return FALSE; } switch(bitv) { case WFLAG_FLAMING: case WFLAG_FROST: case WFLAG_CAUSTIC: case WFLAG_SHOCK: mana = 9; break; default: mana = 15; break; } // mana has to come from arcane casting class if (ch->mana[CLASS_WIZARD] < mana) { if (ch->mana[CLASS_SORCERER] < mana) { if (ch->mana[CLASS_BARD] < mana) { act("You do not have enough mana to empower $p.", ch, wield, NULL, TO_CHAR); pop_call(); return FALSE; } else { ch->mana[CLASS_BARD] -= mana; } } else { ch->mana[CLASS_SORCERER] -= mana; } } else { ch->mana[CLASS_WIZARD] -= mana; } } act( "{178}$p crackles with arcane energy!", ch, wield, NULL, TO_CHAR); act( "{178}$p crackles with arcane energy!", ch, wield, NULL, TO_ROOM); af.type = sn; af.duration = 10 * lvl; af.location = APPLY_HITROLL; af.modifier = lvl / 2; af.bittype = AFFECT_TO_OBJ; af.bitvector = ITEM_MAGIC; af.level = lvl; affect_to_obj( ch, wield, &af); if (bitv) { af.location = APPLY_WEAPON_FLAG; af.modifier = bitv; affect_to_obj( ch, wield, &af); } pop_call(); return TRUE; } /* * Divine Trickster undead backstab */ DO_ABILITY(ability_channeling_attack) { AFFECT_DATA af; push_call("ability_channeling_attack(%p,%p,%p,%p)",sn,level,ch,vo); if (is_affected(ch, sn)) { act("You are already using this ability.", ch, NULL, NULL, TO_CHAR); pop_call(); return FALSE; } act("{138}You channel your turning energy into your attacks!", ch, NULL, NULL, TO_CHAR); af.type = sn; af.location = APPLY_NONE; af.modifier = 0; af.duration = UMAX(1, 1+stat_bonus(TRUE, ch, APPLY_CHA)); af.bittype = AFFECT_TO_NONE; af.bitvector = AFF_NONE; affect_to_char( ch, ch, &af ); pop_call(); return TRUE; } /* * Divine Trickster hide bonus */ DO_ABILITY(ability_divine_veil) { AFFECT_DATA af; push_call("ability_divine_veil(%p,%p,%p,%p)",sn,level,ch,vo); act("{138}You pray for divine blessing against detection!", ch, NULL, NULL, TO_CHAR); af.type = sn; af.location = APPLY_STEALTH; af.modifier = level / 2 + 5; af.duration = 10 * UMAX(1, stat_bonus(TRUE, ch, APPLY_CHA)); af.bittype = AFFECT_TO_NONE; af.bitvector = AFF_NONE; affect_to_char( ch, ch, &af ); pop_call(); return TRUE; } /* * Divine Trickster locate spell like ability */ DO_ABILITY(ability_divine_location) { OBJ_DATA *obj; OBJ_DATA *in_obj; char obj_name[MAX_INPUT_LENGTH]; char txt[MAX_STRING_LENGTH]; int count; push_call("ability_divine_location(%p,%p,%p,%p)",sn,level,ch,vo); if (*target_name == '\0') { send_to_char( "What are you trying to locate?\n\r", ch ); pop_call(); return FALSE; } *txt = '\0'; for (count = 0, obj = mud->f_obj ; obj ; obj = obj->next) { if (!is_multi_name_list_short(target_name, obj->short_descr) || !can_see_obj(ch, obj) ) { continue; } if (IS_SET(obj->extra_flags, ITEM_NOSCRY)) { continue; } if (obj->in_room && IS_SET(obj->in_room->room_flags, ROOM_NOSCRY)) { continue; } for (in_obj = obj ; in_obj->in_obj ; in_obj = in_obj->in_obj); if (in_obj->carried_by && !can_see_world(ch, in_obj->carried_by)) { continue; } if (in_obj->carried_by) { if (check_nondetection(ch, in_obj->carried_by, gsn_locate_object)) { continue; } } else if (!obj->in_room) { continue; } if (in_obj->carried_by->in_room && IS_SET(in_obj->carried_by->in_room->room_flags, ROOM_NOSCRY)) { continue; } if (in_obj->material == MATERIAL_LEAD) { continue; } strcpy(obj_name, capitalize(obj->short_descr)); if (in_obj->carried_by != NULL) { cat_sprintf(txt, "%s {300}is carried by %s.\n\r", obj_name, PERS(in_obj->carried_by, ch)); } else { cat_sprintf(txt, "%s {300}is at %s.\n\r", obj_name, in_obj->in_room->name); } if (++count >= UMIN(level/2, 10)) { break; } } if (count == 0) { send_to_char( "You find nothing like that in hell, earth, or heaven.\n\r", ch ); } pop_call(); return TRUE; } /* * Arcane Trickster ability to replace * Ranged Legerdemain (inspired by NWN2 - Kregor */ DO_ABILITY(ability_pilfer_dweomer) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA *paf, *paf_next; int paf_type, diceroll, count, cls; push_call("ability_pilfer_dweomer(%p,%p,%p,%p)",sn,level,ch,vo); if (victim == ch) { if ((victim = who_fighting(ch)) == NULL) { act("You cannot steal your own magic.", ch, NULL, NULL, TO_CHAR); pop_call(); return FALSE; } } // snarf arcane casting class for mana for (cls = 0 ; cls < MAX_CLASS ; cls++) { if (!class_level(ch, cls)) continue; if (class_table[cls].mana_table != MANA_NONE) continue; if (class_table[cls].attr_prime != APPLY_INT || class_table[cls].attr_prime != APPLY_CHA) continue; break; } diceroll = dice(1, 20) + level; count = 0; for ( paf_type = 0, paf = victim->first_affect; paf != NULL; paf = paf_next ) { paf_next = paf->next; if (!is_spell(paf->type)) continue; if (sn == gsn_dispel_magic && IS_SET(paf->bitvector, AFF_CURSE)) continue; if (diceroll < 11 + paf->level) { continue; } if (paf->duration >= 0) { if (skill_table[paf->type].msg_off) { act( skill_table[paf->type].msg_off, victim, NULL, NULL, TO_CHAR); } if (skill_table[paf->type].msg_off_room) { act( skill_table[paf->type].msg_off_room, victim, NULL, NULL, TO_ROOM); } } paf_type = paf->type; ch->mana[cls] += UMAX(1, skill_table[paf->type].native_level * 2 - 1); affect_from_char(victim, paf); break; } if (paf_type == 0) { send_to_char( "You did not succeed in stealing any magic.\n\r", ch ); } pop_call(); return TRUE; } /* * Arcane Trickster sneak attack */ DO_ABILITY(ability_impromptu_sneak_attack) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("ability_impromptu_sneak_attack(%p,%p,%p,%p)",sn,level,ch,vo); if (!in_combat(victim)) { send_to_char( "You are not currently in combat.\n\r", ch ); pop_call(); return FALSE; } act("{108}You prepare to make an impromptu sneak attack.", ch, NULL, victim, TO_CHAR); af.type = sn; af.location = APPLY_NONE; af.modifier = 0; af.duration = -1; af.bittype = AFFECT_TO_NONE; af.bitvector = AFF_NONE; affect_to_char( ch, victim, &af ); pop_call(); return TRUE; } /* * Divine Champion Wrath */ DO_ABILITY(ability_divine_wrath) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("ability_divine_wrath(%p,%p,%p,%p)",sn,level,ch,vo); if (is_affected(ch, sn)) { act("You are already channeling wrath.", ch, NULL, NULL, TO_CHAR); pop_call(); return FALSE; } act("{138}You call upon divine wrath!", ch, NULL, victim, TO_CHAR); act("{138}$n calls upon divine wrath!", ch, NULL, victim, TO_ROOM); af.type = sn; af.location = APPLY_DR_NONE; af.modifier = learned(ch, gsn_divine_paragon) ? 10 : 5; af.duration = 1 + stat_bonus(FALSE, victim, APPLY_CHA); af.bittype = AFFECT_TO_NONE; af.bitvector = AFF_NONE; affect_join( ch, victim, &af ); pop_call(); return TRUE; } /* * Community domain power - Kregor */ DO_ABILITY(ability_divine_refuge) { CHAR_DATA *vch, *vch_next; AFFECT_DATA af; push_call("ability_divine_refuge(%p,%p,%p,%p)",sn,level,ch,vo); for (vch = ch->in_room->last_person ; vch ; vch = vch_next) { vch_next = vch->prev_in_room; if (!is_same_group(ch, vch)) continue; if (IS_AFFECTED(vch, AFF_SANCTUARY)) continue; if (in_combat(vch)) char_from_combat(vch); af.type = gsn_sanctuary; af.duration = level; af.location = APPLY_NONE; af.modifier = 0; af.bittype = AFFECT_TO_CHAR; af.bitvector = AFF_SANCTUARY; af.level = level; affect_to_char( ch, vch, &af ); act( "{178}$n is surrounded by a white aura.", vch, NULL, NULL, TO_ROOM ); act( "{178}You are surrounded by a white aura.", vch, NULL, NULL, TO_CHAR ); } pop_call(); return TRUE; } /* * Halfling Slinger signature ability - Kregor */ DO_ABILITY(ability_skip_rock) { CHAR_DATA *victim = (CHAR_DATA *) vo; CHAR_DATA *vch, *vch_next; OBJ_DATA *ammo, *wield; int diceroll, hit_mod, dam, cnt, dt, threat; push_call("ability_skip_rock(%p,%p,%p,%p)",sn,level,ch,vo); if ((wield = get_wield(ch, FALSE)) == NULL || !WEAPON_TYPE(wield, WEAPON_TYPE_SLING)) { act("You are not wielding a sling.", ch, NULL, NULL, TO_CHAR); pop_call(); return FALSE; } if ((ammo = get_ammo(ch, wield)) == NULL) { act("You cannot find any ammo for that weapon.", ch, NULL, NULL, TO_CHAR); pop_call(); return FALSE; } diceroll = dice(1,20); CRIT = FALSE; dt = TYPE_HIT; hit_mod = 0; if (diceroll == 1 && !WEAPON_FLAG(ammo, WFLAG_SEEKING)) ch_printf_color(ch, "{118}Critical miss!\n\r"); threat = weapon_table[wield->value[0]].threat; if (IS_SET(weapon_skill(ch, wield), WSKILL_IMP_CRITICAL)) { threat = (20 - threat) * 2; threat = 20 - threat; } if (diceroll == 20 || diceroll >= threat) { if (check_hit(ch, victim, dice(1,20), hit_mod, dt, wield, FALSE, TRUE) || learned(ch, gsn_dead_shot)) { CRIT = TRUE; ch_printf_color(ch, "{118}You score a critical threat!\n\r"); } } if (!WEAPON_FLAG(ammo, WFLAG_SEEKING) && diceroll != 20 && !check_hit(ch, victim, diceroll, hit_mod, dt, wield, FALSE, TRUE)) { act( "$p whistles past $N.", ch, ammo, victim, TO_NOTVICT ); act( "$p whistles past you.", ch, ammo, victim, TO_VICT ); act( "$p whistles past $N.", ch, ammo, victim, TO_ROOM ); pop_call(); return TRUE; } else { dam = GET_DAMROLL(ch, victim, dt, wield); if (CRIT && CAN_CRITICAL(victim) && (!is_affected(victim, gsn_defensive_stance) || !learned(victim, gsn_impenetrable_defense))) dam *= weapon_table[ammo->value[0]].critical; if (!deflect_missile(victim, ch, ammo, -1)) { damage(ch, victim, dam, dt, ammo); if (weapon_cast_spell(ammo->value[2], ammo->value[3], ch, victim, ammo)) ammo->value[2] = ammo->value[3] = 0; } else { pop_call(); return TRUE; } } // Here's where the rock ricochets! for (cnt = 0, vch = victim->in_room->first_person ; vch ; vch = vch_next) { vch_next = vch->next_in_room; if (!can_mass_attack(ch, vch)) continue; if (!is_same_group(victim, vch)) continue; if (vch == victim) continue; diceroll = dice(1,20); hit_mod = 0 - 2 - cnt * 2; if (!WEAPON_FLAG(ammo, WFLAG_SEEKING) && diceroll != 20 && !check_hit(ch, vch, diceroll, hit_mod, dt, wield, FALSE, TRUE)) { act( "$p whistles past $N.", ch, ammo, vch, TO_NOTVICT ); act( "$p whistles past you.", ch, ammo, vch, TO_VICT ); act( "$p whistles past $N.", ch, ammo, vch, TO_ROOM ); break; } else { dam = GET_DAMROLL(ch, vch, dt, wield); act( "$p ricochets toward $N.", ch, ammo, vch, TO_NOTVICT ); act( "$p ricochets toward you!", ch, ammo, vch, TO_VICT ); act( "$p ricochets toward $N.", ch, ammo, vch, TO_CHAR ); if (!deflect_missile(vch, ch, ammo, -1)) { damage(ch, vch, dam, dt, ammo); } else { break; } } if (cnt++ >= level) break; } if (ammo) { junk_obj(ammo); } TAKE_ACTION(ch, ACTION_STANDARD); pop_call(); return TRUE; }