Add skill gains on skill failures

This commit is contained in:
kinther 2025-08-18 13:06:00 -07:00
parent 00c475736c
commit 944dc92bc9
7 changed files with 104 additions and 37 deletions

View file

@ -570,6 +570,7 @@ static void do_doorcmd(struct char_data *ch, struct obj_data *obj, int door, int
TOGGLE_LOCK(other_room, obj, rev_dir[door]);
send_to_char(ch, "The lock quickly yields to your skills.\r\n");
len = strlcpy(buf, "$n skillfully picks the lock on ", sizeof(buf));
gain_skill(ch, "pick lock", TRUE);
break;
}
@ -597,14 +598,19 @@ static int ok_pick(struct char_data *ch, obj_vnum keynum, int pickproof, int scm
percent = rand_number(1, 101);
skill_lvl = GET_SKILL(ch, SKILL_PICK_LOCK) + dex_app_skill[GET_DEX(ch)].p_locks;
if (keynum == NOTHING)
if (keynum == NOTHING) {
send_to_char(ch, "Odd - you can't seem to find a keyhole.\r\n");
else if (pickproof)
}
else if (pickproof) {
send_to_char(ch, "It resists your attempts to pick it.\r\n");
else if (percent > skill_lvl)
}
else if (percent > skill_lvl) {
send_to_char(ch, "You failed to pick the lock.\r\n");
else
gain_skill(ch, "pick lock", FALSE);
}
else {
return (1);
}
return (0);
}

View file

@ -167,10 +167,13 @@ ACMD(do_backstab)
percent = rand_number(1, 101); /* 101% is a complete failure */
prob = GET_SKILL(ch, SKILL_BACKSTAB);
if (AWAKE(vict) && (percent > prob))
if (AWAKE(vict) && (percent > prob)) {
damage(ch, vict, 0, SKILL_BACKSTAB);
else
gain_skill(ch, "backstab", FALSE);
} else {
hit(ch, vict, SKILL_BACKSTAB);
gain_skill(ch, "backstab", TRUE);
}
WAIT_STATE(ch, 2 * PULSE_VIOLENCE);
}
@ -256,7 +259,7 @@ ACMD(do_flee)
if (was_fighting && ch == FIGHTING(was_fighting))
stop_fighting(was_fighting);
} else {
act("$n tries to flee, but can't!", TRUE, ch, 0, 0, TO_ROOM);
act("$n tries to flee, but can't!", TRUE, ch, 0, 0, TO_ROOM);
}
return;
}
@ -310,6 +313,7 @@ ACMD(do_bash)
if (percent > prob) {
damage(ch, vict, 0, SKILL_BASH);
GET_POS(ch) = POS_SITTING;
gain_skill(ch, "bash", FALSE);
} else {
/*
* If we bash a player and they wimp out, they will move to the previous
@ -319,8 +323,10 @@ ACMD(do_bash)
*/
if (damage(ch, vict, 1, SKILL_BASH) > 0) { /* -1 = dead, 0 = miss */
WAIT_STATE(vict, PULSE_VIOLENCE);
if (IN_ROOM(ch) == IN_ROOM(vict))
if (IN_ROOM(ch) == IN_ROOM(vict)) {
GET_POS(vict) = POS_SITTING;
gain_skill(ch, "bash", TRUE);
}
}
}
WAIT_STATE(ch, PULSE_VIOLENCE * 2);
@ -371,6 +377,7 @@ ACMD(do_rescue)
if (percent > prob) {
send_to_char(ch, "You fail the rescue!\r\n");
gain_skill(ch, "rescue", FALSE);
return;
}
send_to_char(ch, "Banzai! To the rescue...\r\n");
@ -381,8 +388,10 @@ ACMD(do_rescue)
stop_fighting(vict);
if (FIGHTING(tmp_ch))
stop_fighting(tmp_ch);
if (FIGHTING(ch))
if (FIGHTING(ch)) {
stop_fighting(ch);
gain_skill(ch, "rescue", TRUE);
}
set_fighting(ch, tmp_ch);
set_fighting(tmp_ch, ch);
@ -396,6 +405,7 @@ EVENTFUNC(event_whirlwind)
struct mud_event_data *pMudEvent;
struct list_data *room_list;
int count;
int roll;
/* This is just a dummy check, but we'll do it anyway */
if (event_obj == NULL)
@ -432,6 +442,10 @@ EVENTFUNC(event_whirlwind)
for (count = dice(1, 4); count > 0; count--) {
tch = random_from_list(room_list);
hit(ch, tch, TYPE_UNDEFINED);
roll = rand_number(1, 20);
if (roll >= 20) {
gain_skill(ch, "whirlwind", FALSE); /* on a critical success, give whirlwind a chance to gain */
}
}
/* Now that our attack is done, let's free out list */
@ -518,8 +532,11 @@ ACMD(do_kick)
if (percent > prob) {
damage(ch, vict, 0, SKILL_KICK);
} else
gain_skill(ch, "kick", FALSE);
} else {
damage(ch, vict, GET_LEVEL(ch) / 2, SKILL_KICK);
gain_skill(ch, "kick", TRUE);
}
WAIT_STATE(ch, PULSE_VIOLENCE * 3);
}
@ -563,6 +580,7 @@ ACMD(do_bandage)
act("$n tries to bandage $N, but fails miserably.", TRUE, ch,
0, vict, TO_NOTVICT);
damage(vict, vict, 2, TYPE_SUFFERING);
gain_skill(ch, "bandage", FALSE);
return;
}
@ -572,4 +590,5 @@ ACMD(do_bandage)
act("Someone bandages you, and you feel a bit better now.",
FALSE, ch, 0, vict, TO_VICT);
GET_HIT(vict) = 0;
gain_skill(ch, "bandage", TRUE);
}

View file

@ -111,14 +111,17 @@ ACMD(do_sneak)
percent = rand_number(1, 101); /* 101% is a complete failure */
if (percent > GET_SKILL(ch, SKILL_SNEAK) + dex_app_skill[GET_DEX(ch)].sneak)
if (percent > GET_SKILL(ch, SKILL_SNEAK) + dex_app_skill[GET_DEX(ch)].sneak){
gain_skill(ch, "sneak", FALSE);
return;
new_affect(&af);
af.spell = SKILL_SNEAK;
af.duration = GET_LEVEL(ch);
SET_BIT_AR(af.bitvector, AFF_SNEAK);
affect_to_char(ch, &af);
} else {
new_affect(&af);
af.spell = SKILL_SNEAK;
af.duration = GET_LEVEL(ch);
SET_BIT_AR(af.bitvector, AFF_SNEAK);
affect_to_char(ch, &af);
gain_skill(ch, "sneak", TRUE);
}
}
ACMD(do_hide)
@ -137,10 +140,13 @@ ACMD(do_hide)
percent = rand_number(1, 101); /* 101% is a complete failure */
if (percent > GET_SKILL(ch, SKILL_HIDE) + dex_app_skill[GET_DEX(ch)].hide)
if (percent > GET_SKILL(ch, SKILL_HIDE) + dex_app_skill[GET_DEX(ch)].hide){
gain_skill(ch, "hide", FALSE);
return;
SET_BIT_AR(AFF_FLAGS(ch), AFF_HIDE);
} else {
SET_BIT_AR(AFF_FLAGS(ch), AFF_HIDE);
send_to_char(ch, "You hide yourself as best you can.\r\n");
}
}
ACMD(do_steal)
@ -219,16 +225,16 @@ ACMD(do_steal)
percent += GET_OBJ_WEIGHT(obj); /* Make heavy harder */
if (percent > GET_SKILL(ch, SKILL_STEAL)) {
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);
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);
} 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) ) {
send_to_char(ch, "Impossible!\r\n");
return;
if (IS_CARRYING_N(ch) + 1 < CAN_CARRY_N(ch)) {
if (!give_otrigger(obj, vict, ch) || !receive_mtrigger(ch, vict, obj) ) {
send_to_char(ch, "Impossible!\r\n");
return;
}
if (IS_CARRYING_W(ch) + GET_OBJ_WEIGHT(obj) < CAN_CARRY_W(ch)) {
obj_from_char(obj);
@ -245,20 +251,22 @@ ACMD(do_steal)
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);
} else {
/* Steal some gold coins */
gold = (GET_GOLD(vict) * rand_number(1, 10)) / 100;
gold = MIN(1782, gold);
if (gold > 0) {
increase_gold(ch, gold);
decrease_gold(vict, gold);
increase_gold(ch, gold);
decrease_gold(vict, gold);
gain_skill(ch, "steal", TRUE);
if (gold > 1)
send_to_char(ch, "Bingo! You got %d gold coins.\r\n", gold);
else
send_to_char(ch, "You manage to swipe a solitary gold coin.\r\n");
} else {
send_to_char(ch, "You couldn't get any gold...\r\n");
}
send_to_char(ch, "Bingo! You got %d gold coins.\r\n", gold);
else
send_to_char(ch, "You manage to swipe a solitary gold coin.\r\n");
} else {
send_to_char(ch, "You couldn't get any gold...\r\n");
}
}
}

View file

@ -173,11 +173,13 @@ ACMD(do_track)
dir = rand_number(0, DIR_COUNT - 1);
} while (!CAN_GO(ch, dir) && --tries);
send_to_char(ch, "You sense a trail %s from here!\r\n", dirs[dir]);
gain_skill(ch, "track", FALSE);
return;
}
/* They passed the skill check. */
dir = find_first_step(IN_ROOM(ch), IN_ROOM(vict));
gain_skill(ch, "track", TRUE);
switch (dir) {
case BFS_ERROR:

View file

@ -12,6 +12,7 @@
#include "sysdep.h"
#include "structs.h"
#include "utils.h"
#include "constants.h"
#include "spells.h"
#include "comm.h"
#include "db.h"
@ -220,6 +221,34 @@ void run_autowiz(void)
#endif /* CIRCLE_UNIX || CIRCLE_WINDOWS */
}
void gain_skill(struct char_data *ch, char *skill, bool success)
{
int skill_num, base, roll, increase;
if (IS_NPC(ch))
return;
skill_num = find_skill_num(skill);
if (skill_num <= 0)
return;
base = GET_SKILL(ch, skill_num);
if (success) { /* learning from successes is more difficult */
roll = rand_number(1, 400);
if (roll >= (400 - (wis_app[GET_WIS(ch)].bonus) * 4)) {
increase = base + 1;
SET_SKILL(ch, skill_num, MIN(90, increase));
}
} else { /* learning from failures is easier */
roll = rand_number(1, 100);
if (roll >= (100 - wis_app[GET_WIS(ch)].bonus)) {
increase = base + 1;
SET_SKILL(ch, skill_num, MIN(90, increase));
}
}
}
void gain_exp(struct char_data *ch, int gain)
{
int is_altered = FALSE;

View file

@ -627,6 +627,7 @@ ACMD(do_cast) {
/* You throws the dice and you takes your chances.. 101% is total failure */
if (rand_number(0, 101) > GET_SKILL(ch, spellnum)) {
WAIT_STATE(ch, PULSE_VIOLENCE);
gain_skill(ch, s, FALSE);
if (!tch || !skill_message(0, ch, tch, spellnum))
send_to_char(ch, "You lost your concentration!\r\n");
if (mana > 0)
@ -636,6 +637,7 @@ ACMD(do_cast) {
} else { /* cast spell returns 1 on success; subtract mana & set waitstate */
if (cast_spell(ch, tch, tobj, spellnum)) {
WAIT_STATE(ch, PULSE_VIOLENCE);
gain_skill(ch, s, TRUE);
if (mana > 0)
GET_MANA(ch) = MAX(0, MIN(GET_MAX_MANA(ch), GET_MANA(ch) - mana));
}

View file

@ -130,6 +130,7 @@ void set_title(struct char_data *ch, char *title);
void gain_exp(struct char_data *ch, int gain);
void gain_exp_regardless(struct char_data *ch, int gain);
void gain_condition(struct char_data *ch, int condition, int value);
void gain_skill(struct char_data *ch, char *skill, bool failure);
void point_update(void);
void update_pos(struct char_data *victim);
void run_autowiz(void);