mirror of
https://github.com/tbamud/tbamud.git
synced 2026-03-19 10:46:33 +01:00
Update gain_skill function with timers
This commit is contained in:
parent
3560427902
commit
cf621e02c1
4 changed files with 66 additions and 11 deletions
56
src/limits.c
56
src/limits.c
|
|
@ -23,6 +23,7 @@
|
|||
#include "fight.h"
|
||||
#include "screen.h"
|
||||
#include "mud_event.h"
|
||||
#include <time.h>
|
||||
|
||||
/* local file scope function prototypes */
|
||||
static int graf(int grafage, int p0, int p1, int p2, int p3, int p4, int p5, int p6);
|
||||
|
|
@ -221,30 +222,65 @@ void run_autowiz(void)
|
|||
#endif /* CIRCLE_UNIX || CIRCLE_WINDOWS */
|
||||
}
|
||||
|
||||
/* Requires: find_skill_num(), GET_WIS(), wis_app[], GET_SKILL(), SET_SKILL(), rand_number()
|
||||
* Cooldown: 1 hour - 5 * WIS bonus minutes (floored at 0)
|
||||
* Rolls: failure -> 1..20, success -> 1..100
|
||||
* Cap: 90% (change MIN(90, ...) if you want a different cap)
|
||||
*/
|
||||
void gain_skill(struct char_data *ch, char *skill, bool success)
|
||||
{
|
||||
int skill_num, base, roll, increase;
|
||||
int wisb, cd_seconds;
|
||||
time_t now;
|
||||
|
||||
if (IS_NPC(ch))
|
||||
return;
|
||||
|
||||
/* Resolve index and validate against table size */
|
||||
skill_num = find_skill_num(skill);
|
||||
if (skill_num <= 0)
|
||||
if (skill_num <= 0 || skill_num > MAX_SKILLS)
|
||||
return;
|
||||
|
||||
base = GET_SKILL(ch, skill_num);
|
||||
/* Respect per-skill cooldown: do nothing if still cooling down */
|
||||
now = time(0);
|
||||
if (GET_SKILL_NEXT_GAIN(ch, skill_num) != 0 &&
|
||||
now < GET_SKILL_NEXT_GAIN(ch, skill_num)) {
|
||||
return;
|
||||
}
|
||||
|
||||
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 */
|
||||
base = GET_SKILL(ch, skill_num);
|
||||
/* If already capped, bail early (and don’t start cooldown) */
|
||||
if (base >= 90)
|
||||
return;
|
||||
|
||||
/* Wisdom bonus from wis_app[] (constants.c). Higher = better learning & shorter cooldown. */
|
||||
wisb = wis_app[GET_WIS(ch)].bonus;
|
||||
|
||||
if (success) {
|
||||
/* Learning from success is harder: 1..100, threshold scales with WIS */
|
||||
roll = rand_number(1, 100);
|
||||
if (roll >= (100 - wis_app[GET_WIS(ch)].bonus)) {
|
||||
/* Old 1..400 with (400 - wisb*4) ⇒ scaled: (100 - wisb) */
|
||||
if (roll >= (100 - wisb)) {
|
||||
increase = base + 1;
|
||||
SET_SKILL(ch, skill_num, MIN(90, increase));
|
||||
|
||||
/* Cooldown only when an increase actually happens */
|
||||
cd_seconds = 3600 - (wisb * 5 * 60); /* 1 hour - 5 * WIS minutes */
|
||||
if (cd_seconds < 0) cd_seconds = 0;
|
||||
GET_SKILL_NEXT_GAIN(ch, skill_num) = now + cd_seconds;
|
||||
}
|
||||
} else {
|
||||
/* Learning from failure is easier: 1..20, threshold scales with WIS */
|
||||
roll = rand_number(1, 20);
|
||||
/* Old 1..100 with (100 - wisb) ⇒ scaled: (20 - wisb) */
|
||||
if (roll >= (20 - wisb)) {
|
||||
increase = base + 1;
|
||||
SET_SKILL(ch, skill_num, MIN(90, increase));
|
||||
|
||||
/* Cooldown only when an increase actually happens */
|
||||
cd_seconds = 3600 - (wisb * 5 * 60); /* 1 hour - 5 * WIS minutes */
|
||||
if (cd_seconds < 0) cd_seconds = 0;
|
||||
GET_SKILL_NEXT_GAIN(ch, skill_num) = now + cd_seconds;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -434,6 +434,14 @@ int load_char(const char *name, struct char_data *ch)
|
|||
if (!strcmp(tag, "Sex ")) GET_SEX(ch) = atoi(line);
|
||||
else if (!strcmp(tag, "ScrW")) GET_SCREEN_WIDTH(ch) = atoi(line);
|
||||
else if (!strcmp(tag, "Skil")) load_skills(fl, ch);
|
||||
else if (!strcmp(tag, "SkGt")) { /* Skill Gain Timers */
|
||||
for (int i = 1; i <= MAX_SKILLS; i++) {
|
||||
long t = 0;
|
||||
if (fscanf(fl, " %ld", &t) != 1)
|
||||
t = 0;
|
||||
GET_SKILL_NEXT_GAIN(ch, i) = (time_t)t;
|
||||
}
|
||||
}
|
||||
else if (!strcmp(tag, "Str ")) load_HMVS(ch, line, LOAD_STRENGTH);
|
||||
break;
|
||||
|
||||
|
|
@ -673,6 +681,12 @@ void save_char(struct char_data * ch)
|
|||
fprintf(fl, "0 0\n");
|
||||
}
|
||||
|
||||
/* Write per-skill next gain times as epoch seconds. */
|
||||
fprintf(fl, "SkGt:"); /* Skill Gain Timer */
|
||||
for (int i = 1; i <= MAX_SKILLS; i++)
|
||||
fprintf(fl, " %ld", (long)GET_SKILL_NEXT_GAIN(ch, i));
|
||||
fputc('\n', fl);
|
||||
|
||||
/* Save affects */
|
||||
if (tmp_aff[0].spell > 0) {
|
||||
fprintf(fl, "Affs:\n");
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
#include "protocol.h" /* Kavir Plugin*/
|
||||
#include "lists.h"
|
||||
#include <time.h>
|
||||
|
||||
/** If you want equipment to be automatically equipped to the same place
|
||||
* it was when players rented, set the define below to 1 because
|
||||
|
|
@ -968,6 +969,7 @@ struct player_special_data_saved
|
|||
int quest_counter; /**< Count of targets left to get */
|
||||
time_t lastmotd; /**< Last time player read motd */
|
||||
time_t lastnews; /**< Last time player read news */
|
||||
time_t next_skill_gain[MAX_SKILLS+1]; /* indexed by skill/spell number */
|
||||
};
|
||||
|
||||
/** Specials needed only by PCs, not NPCs. Space for this structure is
|
||||
|
|
|
|||
|
|
@ -130,7 +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 gain_skill(struct char_data *ch, char *skill, bool success);
|
||||
void point_update(void);
|
||||
void update_pos(struct char_data *victim);
|
||||
void run_autowiz(void);
|
||||
|
|
@ -617,6 +617,9 @@ do \
|
|||
#define GET_SKILL(ch, i) CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->saved.skills[i]))
|
||||
/** Copy the current skill level i of ch to pct. */
|
||||
#define SET_SKILL(ch, i, pct) do { CHECK_PLAYER_SPECIAL((ch), (ch)->player_specials->saved.skills[i]) = pct; } while(0)
|
||||
/** Per-skill next gain time (epoch seconds). Index with a valid skill number. **/
|
||||
#define GET_SKILL_NEXT_GAIN(ch, i) \
|
||||
(CHECK_PLAYER_SPECIAL((ch), (ch)->player_specials->saved.next_skill_gain[(i)]))
|
||||
|
||||
/** The player's default sector type when buildwalking */
|
||||
#define GET_BUILDWALK_SECTOR(ch) CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->buildwalk_sector))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue