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