5e-style skills and cleanup

This commit is contained in:
kinther 2025-12-23 07:34:11 -08:00
parent e7450db908
commit 64220bffd6
7 changed files with 98 additions and 177 deletions

File diff suppressed because one or more lines are too long

View file

@ -306,9 +306,7 @@ static bool can_attempt_listen(struct char_data *ch)
static int roll_listen_total(struct char_data *ch)
{
int bonus = GET_ABILITY_MOD(GET_WIS(ch)) +
GET_PROFICIENCY(GET_SKILL(ch, SKILL_PERCEPTION));
int total = rand_number(1, 20) + bonus;
int total = roll_skill_check(ch, SKILL_PERCEPTION, 0, NULL);
if (FIGHTING(ch))
total -= 4;

View file

@ -207,21 +207,15 @@ int get_stealth_skill_value(struct char_data *ch)
int roll_stealth_check(struct char_data *ch)
{
int skill = get_stealth_skill_value(ch);
int bonus = GET_ABILITY_MOD(GET_DEX(ch)) + GET_PROFICIENCY(skill);
bool disadv = has_stealth_disadv(ch) ? TRUE : FALSE;
int rolla = rand_number(1, 20);
int rollb = rand_number(1, 20);
int roll = disadv ? MIN(rolla, rollb) : rolla;
int mode = has_stealth_disadv(ch) ? -1 : 0;
return roll + bonus;
get_stealth_skill_value(ch);
return roll_skill_check(ch, SKILL_STEALTH, mode, NULL);
}
int roll_sleight_check(struct char_data *ch)
{
int skill = GET_SKILL(ch, SKILL_SLEIGHT_OF_HAND);
int bonus = GET_ABILITY_MOD(GET_DEX(ch)) + GET_PROFICIENCY(skill);
int total = rand_number(1, 20) + bonus;
int total = roll_skill_check(ch, SKILL_SLEIGHT_OF_HAND, 0, NULL);
if (FIGHTING(ch))
total -= 4;
@ -229,6 +223,33 @@ int roll_sleight_check(struct char_data *ch)
return total;
}
static int compute_steal_dc(struct char_data *vict, int weight, bool pc_restricted)
{
int dc = SLEIGHT_BASE_DC + MAX(0, weight);
if (!vict)
return dc;
if (pc_restricted || GET_LEVEL(vict) >= LVL_IMMORT || GET_MOB_SPEC(vict) == shop_keeper)
return 1000;
if (GET_POS(vict) < POS_SLEEPING)
return MAX(0, weight);
if (!AWAKE(vict)) {
dc = MAX(0, dc - 5);
return dc;
}
dc += GET_ABILITY_MOD(GET_WIS(vict));
if (GET_SKILL(vict, SKILL_PERCEPTION) > 0)
dc += get_total_proficiency_bonus(vict);
if (FIGHTING(vict))
dc -= 4;
return dc;
}
static struct obj_data *find_container_on_character(struct char_data *viewer,
struct char_data *vict,
const char *name)
@ -306,7 +327,7 @@ static bool sleight_observer_notices(struct char_data *actor,
struct char_data *viewer,
int sleight_total)
{
int roll, bonus = 0, total;
int d20, total;
if (!viewer || viewer == actor)
return FALSE;
@ -318,23 +339,21 @@ static bool sleight_observer_notices(struct char_data *actor,
return TRUE;
}
roll = rand_number(1, 20);
if (can_scan_for_sneak(viewer)) {
total = roll_skill_check(viewer, SKILL_PERCEPTION, 0, &d20);
if (FIGHTING(viewer))
total -= 4;
} else {
d20 = roll_d20();
total = d20;
}
if (roll == 1) {
if (d20 == 1) {
gain_skill(viewer, "perception", FALSE);
return FALSE;
}
if (can_scan_for_sneak(viewer)) {
bonus = GET_ABILITY_MOD(GET_WIS(viewer)) +
GET_PROFICIENCY(GET_SKILL(viewer, SKILL_PERCEPTION));
if (FIGHTING(viewer))
bonus -= 4;
}
total = roll + bonus;
if (roll == 20 || total >= sleight_total) {
if (d20 == 20 || total >= sleight_total) {
gain_skill(viewer, "perception", TRUE);
return TRUE;
}
@ -419,9 +438,7 @@ bool can_scan_for_sneak(struct char_data *ch)
int roll_scan_perception(struct char_data *ch)
{
int bonus = GET_ABILITY_MOD(GET_WIS(ch)) +
GET_PROFICIENCY(GET_SKILL(ch, SKILL_PERCEPTION));
int total = rand_number(1, 20) + bonus;
int total = roll_skill_check(ch, SKILL_PERCEPTION, 0, NULL);
if (FIGHTING(ch))
total -= 4;
@ -710,7 +727,7 @@ static int scan_target_dc(struct char_data *tch)
bool scan_confirm_target(struct char_data *ch, struct char_data *tch)
{
int roll, bonus, total;
int total;
if (!ch || !tch)
return FALSE;
@ -719,10 +736,7 @@ bool scan_confirm_target(struct char_data *ch, struct char_data *tch)
if (!GET_SKILL(ch, SKILL_PERCEPTION))
return FALSE;
bonus = GET_ABILITY_MOD(GET_WIS(ch)) +
GET_PROFICIENCY(GET_SKILL(ch, SKILL_PERCEPTION));
roll = rand_number(1, 20);
total = roll + bonus;
total = roll_skill_check(ch, SKILL_PERCEPTION, 0, NULL);
if (FIGHTING(ch))
total -= 4;
@ -758,7 +772,7 @@ static int scan_effect_duration(struct char_data *ch)
bool perform_scan_sweep(struct char_data *ch)
{
struct char_data *tch;
int roll, bonus, total;
int total;
bool had_targets = FALSE;
bool found_any = FALSE;
@ -786,10 +800,7 @@ bool perform_scan_sweep(struct char_data *ch)
if (!had_targets)
return FALSE;
bonus = GET_ABILITY_MOD(GET_WIS(ch)) +
GET_PROFICIENCY(GET_SKILL(ch, SKILL_PERCEPTION));
roll = rand_number(1, 20);
total = roll + bonus;
total = roll_skill_check(ch, SKILL_PERCEPTION, 0, NULL);
if (FIGHTING(ch))
total -= 4;
@ -827,13 +838,14 @@ ACMD(do_scan)
if (AFF_FLAGGED(ch, AFF_SCAN)) {
affect_from_char(ch, SKILL_PERCEPTION);
affect_from_char(ch, SPELL_SCAN_AFFECT);
send_to_char(ch, "You lower your guard and stop scanning the area.\r\n");
act("$n relaxes, no longer scanning so intently.", TRUE, ch, 0, 0, TO_ROOM);
return;
}
new_affect(&af);
af.spell = SKILL_PERCEPTION;
af.spell = SPELL_SCAN_AFFECT;
af.location = APPLY_NONE;
af.modifier = 0;
af.duration = scan_effect_duration(ch);
@ -858,13 +870,13 @@ ACMD(do_listen)
}
if (AFF_FLAGGED(ch, AFF_LISTEN)) {
affect_from_char(ch, SKILL_LISTEN);
affect_from_char(ch, SPELL_LISTEN_AFFECT);
send_to_char(ch, "You stop actively listening for hushed voices.\r\n");
return;
}
new_affect(&af);
af.spell = SKILL_LISTEN;
af.spell = SPELL_LISTEN_AFFECT;
af.location = APPLY_NONE;
af.modifier = 0;
af.duration = listen_effect_duration(ch);
@ -1034,9 +1046,10 @@ ACMD(do_steal)
struct char_data *vict;
struct obj_data *obj;
char vict_name[MAX_INPUT_LENGTH], obj_name[MAX_INPUT_LENGTH];
int percent, gold, eq_pos, pcsteal = 0, ohoh = 0;
int gold, eq_pos, pcsteal = 0, ohoh = 0;
int sleight_total, dc;
if (!GET_SKILL(ch, SKILL_STEAL)) {
if (!GET_SKILL(ch, SKILL_SLEIGHT_OF_HAND)) {
send_to_char(ch, "You have no idea how to do that.\r\n");
return;
}
@ -1055,21 +1068,10 @@ ACMD(do_steal)
return;
}
/* 101% is a complete failure */
percent = rand_number(1, 101) - GET_ABILITY_MOD(GET_DEX(ch));
if (GET_POS(vict) < POS_SLEEPING)
percent = -1; /* ALWAYS SUCCESS, unless heavy object. */
if (!CONFIG_PT_ALLOWED && !IS_NPC(vict))
pcsteal = 1;
if (!AWAKE(vict)) /* Easier to steal from sleeping people. */
percent -= 50;
/* No stealing if not allowed. If it is no stealing from Imm's or Shopkeepers. */
if (GET_LEVEL(vict) >= LVL_IMMORT || pcsteal || GET_MOB_SPEC(vict) == shop_keeper)
percent = 101; /* Failure */
sleight_total = roll_sleight_check(ch);
if (str_cmp(obj_name, "coins") && str_cmp(obj_name, "gold")) {
@ -1102,14 +1104,14 @@ ACMD(do_steal)
}
} else { /* obj found in inventory */
percent += GET_OBJ_WEIGHT(obj); /* Make heavy harder */
dc = compute_steal_dc(vict, GET_OBJ_WEIGHT(obj), pcsteal);
if (percent > GET_SKILL(ch, SKILL_STEAL)) {
if (sleight_total < dc) {
ohoh = TRUE;
send_to_char(ch, "Oops..\r\n");
act("$n tried to steal something from you!", FALSE, ch, 0, vict, TO_VICT);
act("$n tries to steal something from $N.", TRUE, ch, 0, vict, TO_NOTVICT);
gain_skill(ch, "steal", FALSE);
gain_skill(ch, "sleight of hand", FALSE);
} else { /* Steal the item */
if (IS_CARRYING_N(ch) + 1 < CAN_CARRY_N(ch)) {
if (!give_otrigger(obj, vict, ch) || !receive_mtrigger(ch, vict, obj) ) {
@ -1126,12 +1128,13 @@ ACMD(do_steal)
}
}
} else { /* Steal some coins */
if (AWAKE(vict) && (percent > GET_SKILL(ch, SKILL_STEAL))) {
dc = compute_steal_dc(vict, 0, pcsteal);
if (AWAKE(vict) && (sleight_total < dc)) {
ohoh = TRUE;
send_to_char(ch, "Oops..\r\n");
act("You discover that $n has $s hands in your wallet.", FALSE, ch, 0, vict, TO_VICT);
act("$n tries to steal gold from $N.", TRUE, ch, 0, vict, TO_NOTVICT);
gain_skill(ch, "steal", FALSE);
gain_skill(ch, "sleight of hand", FALSE);
} else {
/* Steal some gold coins */
gold = (GET_GOLD(vict) * rand_number(1, 10)) / 100;
@ -1139,7 +1142,7 @@ ACMD(do_steal)
if (gold > 0) {
increase_gold(ch, gold);
decrease_gold(vict, gold);
gain_skill(ch, "steal", TRUE);
gain_skill(ch, "sleight of hand", TRUE);
if (gold > 1)
send_to_char(ch, "Bingo! You got %d gold coins.\r\n", gold);
else

View file

@ -357,7 +357,6 @@ void grant_class_skills(struct char_data *ch, bool reset)
case CLASS_ROGUE:
SET_SKILL(ch, SKILL_STEALTH, 5);
SET_SKILL(ch, SKILL_TRACK, 5);
SET_SKILL(ch, SKILL_STEAL, 5);
SET_SKILL(ch, SKILL_BACKSTAB, 5);
SET_SKILL(ch, SKILL_PICK_LOCK, 5);
SET_SKILL(ch, SKILL_SLEIGHT_OF_HAND, 5);
@ -400,7 +399,6 @@ void grant_class_skills(struct char_data *ch, bool reset)
break;
case CLASS_RANGER:
SET_SKILL(ch, SKILL_STEALTH, 5);
SET_SKILL(ch, SKILL_BANDAGE, 5);
SET_SKILL(ch, SKILL_TRACK, 5);
SET_SKILL(ch, SKILL_BASH, 5);
@ -415,6 +413,7 @@ void grant_class_skills(struct char_data *ch, bool reset)
SET_SKILL(ch, SKILL_SURVIVAL, 5);
SET_SKILL(ch, SKILL_ATHLETICS, 5);
SET_SKILL(ch, SKILL_PERSUASION, 5);
SET_SKILL(ch, SKILL_STEALTH, 5);
break;
case CLASS_BARD:
@ -683,7 +682,6 @@ void init_spell_levels(void)
/* ROGUES */
spell_level(SKILL_PICK_LOCK, CLASS_ROGUE, 1);
spell_level(SKILL_BACKSTAB, CLASS_ROGUE, 1);
spell_level(SKILL_STEAL, CLASS_ROGUE, 1);
spell_level(SKILL_TRACK, CLASS_ROGUE, 1);
spell_level(SKILL_UNARMED, CLASS_ROGUE, 1);
spell_level(SKILL_PIERCING_WEAPONS, CLASS_ROGUE, 1);

View file

@ -915,6 +915,12 @@ void mag_assign_spells(void) {
spello(SPELL_DG_AFFECT, "Script-inflicted", 0, 0, 0, POS_SITTING,
TAR_IGNORE, TRUE, 0, NULL);
/* Non-castable affects for skill-driven detection */
spello(SPELL_SCAN_AFFECT, "Scanning", 0, 0, 0, POS_SITTING,
TAR_IGNORE, TRUE, 0, NULL);
spello(SPELL_LISTEN_AFFECT, "Listening", 0, 0, 0, POS_SITTING,
TAR_IGNORE, TRUE, 0, NULL);
/* Declaration of skills - this actually doesn't do anything except set it up
* so that immortals can use these skills by default. The min level to use
* the skill for other classes is set up in class.c. */
@ -925,7 +931,6 @@ void mag_assign_spells(void) {
skillo(SKILL_PICK_LOCK, "pick lock");
skillo(SKILL_RESCUE, "rescue");
skillo(SKILL_SNEAK, "sneak");
skillo(SKILL_STEAL, "steal");
skillo(SKILL_TRACK, "track");
skillo(SKILL_WHIRLWIND, "whirlwind");
skillo(SKILL_BANDAGE, "bandage");
@ -936,7 +941,6 @@ void mag_assign_spells(void) {
skillo(SKILL_BLUDGEONING_WEAPONS, "bludgeoning weapons");
skillo(SKILL_PERCEPTION, "perception");
skillo(SKILL_STEALTH, "stealth");
skillo(SKILL_LISTEN, "listen");
skillo(SKILL_SLEIGHT_OF_HAND, "sleight of hand");
skillo(SKILL_ACROBATICS, "acrobatics");
skillo(SKILL_ANIMAL_HANDLING, "animal handling");

View file

@ -105,36 +105,34 @@
#define SKILL_HIDE 133 /* Reserved Skill[] DO NOT CHANGE */
#define SKILL_KICK 134 /* Reserved Skill[] DO NOT CHANGE */
#define SKILL_PICK_LOCK 135 /* Reserved Skill[] DO NOT CHANGE */
#define SKILL_WHIRLWIND 136
#define SKILL_WHIRLWIND 136 /* Performs whirlwind pulse action */
#define SKILL_RESCUE 137 /* Reserved Skill[] DO NOT CHANGE */
#define SKILL_SNEAK 138 /* Reserved Skill[] DO NOT CHANGE */
#define SKILL_STEAL 139 /* Reserved Skill[] DO NOT CHANGE */
#define SKILL_TRACK 140 /* Reserved Skill[] DO NOT CHANGE */
#define SKILL_BANDAGE 141 /* Reserved Skill[] DO NOT CHANGE */
#define SKILL_UNARMED 142 /* Reserved Skill[] DO NOT CHANGE */
#define SKILL_SHIELD_USE 143 /* Reserved Skill[] DO NOT CHANGE */
#define SKILL_PIERCING_WEAPONS 144 /* Reserved Skill[] DO NOT CHANGE */
#define SKILL_SLASHING_WEAPONS 145 /* Reserved Skill[] DO NOT CHANGE */
#define SKILL_BLUDGEONING_WEAPONS 146 /* Reserved Skill[] DO NOT CHANGE */
#define SKILL_PERCEPTION 147 /* Reserved Skill[] DO NOT CHANGE */
#define SKILL_STEALTH 148 /* Shared stealth skill for hide/sneak */
#define SKILL_LISTEN 149 /* Anchor for the listen affect */
#define SKILL_SLEIGHT_OF_HAND 150 /* Sleight of hand for palm/slip */
#define SKILL_ACROBATICS 151 /* DEX */
#define SKILL_ANIMAL_HANDLING 152 /* WIS */
#define SKILL_ARCANA 153 /* INT */
#define SKILL_ATHLETICS 154 /* STR */
#define SKILL_DECEPTION 155 /* CHA */
#define SKILL_HISTORY 156 /* INT */
#define SKILL_INSIGHT 157 /* WIS */
#define SKILL_INTIMIDATION 158 /* CHA */
#define SKILL_INVESTIGATION 159 /* INT */
#define SKILL_MEDICINE 160 /* WIS */
#define SKILL_NATURE 161 /* INT */
#define SKILL_PERFORMANCE 162 /* CHA */
#define SKILL_PERSUASION 163 /* CHA */
#define SKILL_RELIGION 164 /* INT */
#define SKILL_SURVIVAL 165 /* WIS */
#define SKILL_TRACK 139 /* Reserved Skill[] DO NOT CHANGE */
#define SKILL_BANDAGE 140 /* Reserved Skill[] DO NOT CHANGE */
#define SKILL_UNARMED 141 /* Reserved Skill[] DO NOT CHANGE */
#define SKILL_SHIELD_USE 142 /* Reserved Skill[] DO NOT CHANGE */
#define SKILL_PIERCING_WEAPONS 143 /* Reserved Skill[] DO NOT CHANGE */
#define SKILL_SLASHING_WEAPONS 144 /* Reserved Skill[] DO NOT CHANGE */
#define SKILL_BLUDGEONING_WEAPONS 145 /* Reserved Skill[] DO NOT CHANGE */
#define SKILL_PERCEPTION 146 /* Reserved Skill[] DO NOT CHANGE */
#define SKILL_STEALTH 147 /* Shared stealth skill for hide/sneak */
#define SKILL_SLEIGHT_OF_HAND 148 /* Sleight of hand for palm/slip */
#define SKILL_ACROBATICS 149 /* DEX */
#define SKILL_ANIMAL_HANDLING 150 /* WIS */
#define SKILL_ARCANA 151 /* INT */
#define SKILL_ATHLETICS 152 /* STR */
#define SKILL_DECEPTION 153 /* CHA */
#define SKILL_HISTORY 154 /* INT */
#define SKILL_INSIGHT 155 /* WIS */
#define SKILL_INTIMIDATION 156 /* CHA */
#define SKILL_INVESTIGATION 157 /* INT */
#define SKILL_MEDICINE 158 /* WIS */
#define SKILL_NATURE 159 /* INT */
#define SKILL_PERFORMANCE 160 /* CHA */
#define SKILL_PERSUASION 161 /* CHA */
#define SKILL_RELIGION 162 /* INT */
#define SKILL_SURVIVAL 163 /* WIS */
/* New skills may be added here up to MAX_SKILLS (200) */
@ -146,6 +144,8 @@
/* To make an affect induced by dg_affect look correct on 'stat' we need to
* define it with a 'spellname'. */
#define SPELL_SCAN_AFFECT 296
#define SPELL_LISTEN_AFFECT 297
#define SPELL_DG_AFFECT 298
#define TOP_SPELL_DEFINE 299

View file

@ -1736,7 +1736,6 @@ static int skill_to_ability(int skillnum)
case SKILL_PERSUASION: return ABIL_CHA;
/* Legacy overlaps you likely want treated as WIS in the interim */
case SKILL_LISTEN: return ABIL_WIS;
case SKILL_TRACK: return ABIL_WIS;
default: