mirror of
https://github.com/tbamud/tbamud.git
synced 2026-03-19 02:36:33 +01:00
Add age and time played functionality
This commit is contained in:
parent
be79603e8f
commit
3344074ea2
14 changed files with 222 additions and 62 deletions
24
README.md
24
README.md
|
|
@ -1,7 +1,9 @@
|
|||
***Files for Miranthas MUD.***
|
||||
***Files for Cataclysm MUD.***
|
||||
|
||||
Miranthas MUD is a continuation of tbaMUD/CircleMUD, which is built on DIKU MUD.
|
||||
The code here is freeware to honor that tradition.
|
||||
Cataclysm MUD is a continuation of tbaMUD/CircleMUD, which is built on DIKU MUD.
|
||||
The code here is freeware to honor that tradition. Licensing and use should be based
|
||||
on what was outlined previously. Any new code added here is released under the same
|
||||
license.
|
||||
|
||||
Due to the sensitive nature of topics found in this setting, all characters and
|
||||
players are 18+. The game world is derived from several inspirational sources,
|
||||
|
|
@ -9,7 +11,7 @@ most notably the former Armageddon MUD.
|
|||
|
||||
Roleplay is highly encouraged, but not enforced.
|
||||
|
||||
Features in Miranthas MUD Alpha release:
|
||||
Features in Cataclysm MUD Alpha release:
|
||||
|
||||
* The city of Caleran is available for exploration
|
||||
* Experience points and levels are removed in favor of skill based progression
|
||||
|
|
@ -43,12 +45,22 @@ Features in Miranthas MUD Alpha release:
|
|||
* PC's now use a short description for identification instead of name
|
||||
* Backgrounds are now available for PC's and NPC's
|
||||
* Account system for tracking players/characters over long periods of time
|
||||
|
||||
Alpha 1.1 release:
|
||||
|
||||
* Cleaned up legacy practice system code
|
||||
* Added skill caps for classes to limit ability of everyone to reach skill leve 100 (and respective proficiency)
|
||||
* Race/species selection and stat ranges (elves have higher dex, dwarves have higher str, etc)
|
||||
* Renamed move to stamina in code to reflect how much energy is used for certain actions
|
||||
* Species have base hit/mana/stamina now, plus their class modifier rolls
|
||||
* Prioritized stats during character generation
|
||||
* Ability to change ldesc of PC/NPC's in some situations
|
||||
* Ability to look in certain directions to see what is 1-3 rooms away
|
||||
* PC's and NPC's can now have an age set between 18-65
|
||||
|
||||
Features to be implemented in the next few releases:
|
||||
|
||||
* "acaudit" command to be "audit ac", allowing for further audit commands in the future
|
||||
* Subclass selection to personalize character further
|
||||
* Combat is slowed down so it isn't over in < 15 seconds (unless you're far outmatched)
|
||||
* Mounts added to help with long trips
|
||||
|
|
@ -78,6 +90,10 @@ Features to be implemented in the next few releases:
|
|||
* Additional zones/cities based on Miranthas world map
|
||||
* Resources on the world map can be claimed by different city-states or independent factions
|
||||
* Claimed resources improve quality of armor/weapons/food/prices available
|
||||
* Death from old age if you roll badly on your birthday after the expected lifespan of a species
|
||||
* Attacks hit different parts of the body and have different damage effects
|
||||
* Armor degradation based on damage taken per body part
|
||||
* Weapon degradation based on damage dealt - potentially shattering weapons
|
||||
|
||||
...and down the road:
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ B
|
|||
|
||||
|
||||
|
||||
|
||||
~
|
||||
6218 0 0 0 0 0 0 0 0 E
|
||||
1 3d20+40
|
||||
|
|
@ -37,17 +38,17 @@ Skill 145 5
|
|||
Skill 146 5
|
||||
Skill 147 5
|
||||
E
|
||||
L 17 127 1
|
||||
L 16 117 1
|
||||
L 15 117 1
|
||||
L 11 111 1
|
||||
L 10 107 1
|
||||
L 9 124 1
|
||||
L 8 115 1
|
||||
L 7 108 1
|
||||
L 6 110 1
|
||||
L 5 131 1
|
||||
L 3 118 1
|
||||
L 5 131 1
|
||||
L 6 110 1
|
||||
L 7 108 1
|
||||
L 8 115 1
|
||||
L 9 124 1
|
||||
L 10 107 1
|
||||
L 11 111 1
|
||||
L 15 117 1
|
||||
L 16 117 1
|
||||
L 17 127 1
|
||||
#101
|
||||
Sally~
|
||||
slim lanky human soldier guard~
|
||||
|
|
@ -70,6 +71,7 @@ B
|
|||
|
||||
|
||||
|
||||
|
||||
~
|
||||
6218 0 0 0 0 0 0 0 0 E
|
||||
1 3d20+40
|
||||
|
|
@ -90,17 +92,17 @@ Skill 152 5
|
|||
Skill 156 5
|
||||
Skill 163 5
|
||||
E
|
||||
L 3 118 1
|
||||
L 5 131 1
|
||||
L 6 110 1
|
||||
L 7 108 1
|
||||
L 8 115 1
|
||||
L 9 124 1
|
||||
L 10 107 1
|
||||
L 11 111 1
|
||||
L 15 117 1
|
||||
L 16 117 1
|
||||
L 17 127 1
|
||||
L 16 117 1
|
||||
L 15 117 1
|
||||
L 11 111 1
|
||||
L 10 107 1
|
||||
L 9 124 1
|
||||
L 8 115 1
|
||||
L 7 108 1
|
||||
L 6 110 1
|
||||
L 5 131 1
|
||||
L 3 118 1
|
||||
#102
|
||||
Baldy~
|
||||
barkeep stocky bald~
|
||||
|
|
@ -123,13 +125,14 @@ B
|
|||
|
||||
|
||||
|
||||
|
||||
~
|
||||
10 0 0 0 0 0 0 0 0 E
|
||||
1 3d12+60
|
||||
8 8 1
|
||||
E
|
||||
L 9 112 1
|
||||
L 14 113 1
|
||||
L 9 112 1
|
||||
#103
|
||||
Lanky~
|
||||
woman lanky scarred~
|
||||
|
|
@ -153,6 +156,7 @@ B
|
|||
|
||||
|
||||
|
||||
|
||||
~
|
||||
10 0 0 0 0 0 0 0 0 E
|
||||
1 3d8+60
|
||||
|
|
@ -186,18 +190,20 @@ B
|
|||
|
||||
|
||||
|
||||
|
||||
It's a rat.
|
||||
~
|
||||
8 0 0 0 0 0 0 0 0 E
|
||||
1 0d0+10
|
||||
8 8 2
|
||||
Str: 2
|
||||
Str: 3
|
||||
Dex: 7
|
||||
Int: 1
|
||||
Int: 3
|
||||
Wis: 8
|
||||
Con: 8
|
||||
Cha: 1
|
||||
Cha: 3
|
||||
Species: 25
|
||||
Age: 42
|
||||
AtkT 4
|
||||
E
|
||||
$
|
||||
|
|
|
|||
|
|
@ -1254,7 +1254,10 @@ ACMD(do_coins)
|
|||
|
||||
ACMD(do_score)
|
||||
{
|
||||
struct time_info_data playing_time;
|
||||
time_t played_seconds;
|
||||
int played_minutes;
|
||||
int played_hours;
|
||||
int played_days;
|
||||
struct ac_breakdown acb;
|
||||
bool ismob = IS_NPC(ch);
|
||||
|
||||
|
|
@ -1299,12 +1302,9 @@ ACMD(do_score)
|
|||
send_to_char(ch, "Stealth Disadvantage: %s\r\n",
|
||||
has_stealth_disadv(ch) ? "Yes" : "No");
|
||||
|
||||
send_to_char(ch, "You are %d years old.", GET_AGE(ch));
|
||||
send_to_char(ch, "You are %d years old.", GET_ROLEPLAY_AGE(ch));
|
||||
|
||||
if (age(ch)->month == 0 && age(ch)->day == 0)
|
||||
send_to_char(ch, " It's your birthday today.\r\n");
|
||||
else
|
||||
send_to_char(ch, "\r\n");
|
||||
send_to_char(ch, "\r\n");
|
||||
|
||||
/* Only players have quest data */
|
||||
if (!ismob) {
|
||||
|
|
@ -1324,11 +1324,15 @@ ACMD(do_score)
|
|||
|
||||
/* Only players have valid playtime data */
|
||||
if (!ismob) {
|
||||
playing_time = *real_time_passed((time(0) - ch->player.time.logon) +
|
||||
ch->player.time.played, 0);
|
||||
send_to_char(ch, "You have been playing for %d day%s and %d hour%s.\r\n",
|
||||
playing_time.day, playing_time.day == 1 ? "" : "s",
|
||||
playing_time.hours, playing_time.hours == 1 ? "" : "s");
|
||||
played_seconds = get_total_played_seconds(ch);
|
||||
played_minutes = (played_seconds / SECS_PER_REAL_MIN) % 60;
|
||||
played_hours = (played_seconds / SECS_PER_REAL_HOUR) % 24;
|
||||
played_days = played_seconds / SECS_PER_REAL_DAY;
|
||||
send_to_char(ch,
|
||||
"You have been playing for %d minute%s, %d hour%s, and %d day%s.\r\n",
|
||||
played_minutes, played_minutes == 1 ? "" : "s",
|
||||
played_hours, played_hours == 1 ? "" : "s",
|
||||
played_days, played_days == 1 ? "" : "s");
|
||||
}
|
||||
|
||||
/* Position */
|
||||
|
|
|
|||
|
|
@ -1793,8 +1793,7 @@ static void do_stat_character(struct char_data *ch, struct char_data *k)
|
|||
zone_table[world[IN_ROOM(k)].zone].number);
|
||||
|
||||
if (!IS_NPC(k)) {
|
||||
char created[64], logon[64], olc[64] = "";
|
||||
strftime(created, sizeof(created), "%b %d %Y", localtime(&(k->player.time.birth)));
|
||||
char logon[64], olc[64] = "";
|
||||
strftime(logon, sizeof(logon), "%b %d %Y", localtime(&(k->player.time.logon)));
|
||||
|
||||
if (GET_LEVEL(k) >= LVL_BUILDER) {
|
||||
|
|
@ -1810,12 +1809,16 @@ static void do_stat_character(struct char_data *ch, struct char_data *k)
|
|||
snprintf(olc, sizeof(olc), ", OLC %d", GET_OLC_ZONE(k));
|
||||
}
|
||||
|
||||
stat_table_row_fmt(ch, "Account", "Created %s, Last %s%s",
|
||||
created, logon, olc);
|
||||
stat_table_row_fmt(ch, "Age/Play", "Age %d, Played %dh %dm",
|
||||
age(k)->year,
|
||||
k->player.time.played / 3600,
|
||||
(k->player.time.played % 3600) / 60);
|
||||
stat_table_row_fmt(ch, "Account", "Last %s%s",
|
||||
logon, olc);
|
||||
{
|
||||
time_t played_seconds = get_total_played_seconds(k);
|
||||
int played_minutes = (played_seconds / SECS_PER_REAL_MIN) % 60;
|
||||
int played_hours = (played_seconds / SECS_PER_REAL_HOUR) % 24;
|
||||
int played_days = played_seconds / SECS_PER_REAL_DAY;
|
||||
stat_table_row_fmt(ch, "Age/Playtime", "Age %d, %dd %dh %dm",
|
||||
GET_ROLEPLAY_AGE(k), played_days, played_hours, played_minutes);
|
||||
}
|
||||
}
|
||||
|
||||
stat_table_row_fmt(ch, "Class", "%s", CLASS_NAME(k));
|
||||
|
|
@ -3864,10 +3867,8 @@ static int perform_set(struct char_data *ch, struct char_data *vict, int mode, c
|
|||
send_to_char(ch, "Ages 2 to 200 accepted.\r\n");
|
||||
return (0);
|
||||
}
|
||||
/* NOTE: May not display the exact age specified due to the integer
|
||||
* division used elsewhere in the code. Seems to only happen for
|
||||
* some values below the starting age (17) anyway. -gg 5/27/98 */
|
||||
vict->player.time.birth = time(0) - ((value - 17) * SECS_PER_MUD_YEAR);
|
||||
GET_ROLEPLAY_AGE(vict) = LIMIT(value, MIN_CHAR_AGE, MAX_CHAR_AGE);
|
||||
GET_ROLEPLAY_AGE_YEAR(vict) = time_info.year;
|
||||
break;
|
||||
case 3: /* align */
|
||||
GET_ALIGNMENT(vict) = RANGE(-1000, 1000);
|
||||
|
|
|
|||
|
|
@ -326,7 +326,9 @@ const char *connected_types[] = {
|
|||
"Get new PW",
|
||||
"Confirm new PW",
|
||||
"Select sex",
|
||||
"Select species",
|
||||
"Select class",
|
||||
"Short description",
|
||||
"Reading MOTD",
|
||||
"Main Menu",
|
||||
"Get descript.",
|
||||
|
|
@ -350,7 +352,18 @@ const char *connected_types[] = {
|
|||
"Preference edit",
|
||||
"IBT edit",
|
||||
"Message edit",
|
||||
"Protocol Detection",
|
||||
"Background/Protocol",
|
||||
"Connect menu",
|
||||
"Get account",
|
||||
"Confirm account",
|
||||
"Account password",
|
||||
"New account PW",
|
||||
"Confirm account PW",
|
||||
"Account email",
|
||||
"Account menu",
|
||||
"Account list",
|
||||
"Stat preference",
|
||||
"Select age",
|
||||
"\n"
|
||||
};
|
||||
|
||||
|
|
|
|||
21
src/db.c
21
src/db.c
|
|
@ -1713,6 +1713,10 @@ static void interpret_espec(const char *keyword, const char *value, int i, int n
|
|||
RANGE(SPECIES_UNDEFINED, NUM_SPECIES - 1);
|
||||
mob_proto[i].player.species = num_arg;
|
||||
}
|
||||
CASE("Age") {
|
||||
RANGE(MIN_CHAR_AGE, MAX_CHAR_AGE);
|
||||
mob_proto[i].player.roleplay_age = num_arg;
|
||||
}
|
||||
|
||||
/* --- 5e-style Saving Throws --- */
|
||||
CASE("SaveStr") {
|
||||
|
|
@ -1963,6 +1967,13 @@ void parse_mobile(FILE *mob_f, int nr)
|
|||
exit(1);
|
||||
}
|
||||
|
||||
if (mob_proto[i].player.time.birth == 0)
|
||||
mob_proto[i].player.time.birth = time(0);
|
||||
if (mob_proto[i].player.roleplay_age == 0)
|
||||
mob_proto[i].player.roleplay_age = MIN_CHAR_AGE;
|
||||
if (mob_proto[i].player.roleplay_age_year == 0)
|
||||
mob_proto[i].player.roleplay_age_year = time_info.year;
|
||||
|
||||
letter = fread_letter(mob_f);
|
||||
while (letter == 'L') {
|
||||
int wpos = -1, vnum = -1, qty = 1;
|
||||
|
|
@ -2757,7 +2768,8 @@ struct char_data *read_mobile(mob_vnum nr, int type) /* and mob_rnum */
|
|||
mob->points.mana = mob->points.max_mana;
|
||||
mob->points.stamina = mob->points.max_stamina;
|
||||
|
||||
mob->player.time.birth = time(0);
|
||||
if (mob->player.time.birth == 0)
|
||||
mob->player.time.birth = time(0);
|
||||
mob->player.time.played = 0;
|
||||
mob->player.time.logon = time(0);
|
||||
|
||||
|
|
@ -3843,7 +3855,12 @@ void init_char(struct char_data *ch)
|
|||
ch->player_specials->saved.completed_quests = NULL;
|
||||
GET_QUEST(ch) = NOTHING;
|
||||
|
||||
ch->player.time.birth = time(0);
|
||||
if (ch->player.time.birth == 0)
|
||||
ch->player.time.birth = time(0);
|
||||
if (GET_ROLEPLAY_AGE(ch) == 0)
|
||||
GET_ROLEPLAY_AGE(ch) = MIN_CHAR_AGE;
|
||||
if (GET_ROLEPLAY_AGE_YEAR(ch) == 0)
|
||||
GET_ROLEPLAY_AGE_YEAR(ch) = time_info.year;
|
||||
ch->player.time.logon = time(0);
|
||||
ch->player.time.played = 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -363,6 +363,14 @@ int write_mobile_espec(mob_vnum mvnum, struct char_data *mob, FILE *fd)
|
|||
fprintf(fd, "Species: %d\n", (int)GET_SPECIES(mob));
|
||||
count++;
|
||||
}
|
||||
{
|
||||
int age_years = GET_ROLEPLAY_AGE(mob);
|
||||
if (age_years >= MIN_CHAR_AGE && age_years <= MAX_CHAR_AGE &&
|
||||
age_years != MIN_CHAR_AGE) {
|
||||
fprintf(fd, "Age: %d\n", age_years);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
/* --- 5e-style saving throws --- */
|
||||
if (GET_SAVE(mob, ABIL_STR) != 0) {
|
||||
|
|
|
|||
|
|
@ -1323,6 +1323,11 @@ static void show_species_menu(struct descriptor_data *d)
|
|||
write_to_output(d, "Species: ");
|
||||
}
|
||||
|
||||
static void show_age_prompt(struct descriptor_data *d)
|
||||
{
|
||||
write_to_output(d, "Age (%d-%d): ", MIN_CHAR_AGE, MAX_CHAR_AGE);
|
||||
}
|
||||
|
||||
static bool is_creation_state(int state)
|
||||
{
|
||||
switch (state) {
|
||||
|
|
@ -1334,6 +1339,7 @@ static bool is_creation_state(int state)
|
|||
case CON_QSEX:
|
||||
case CON_QSPECIES:
|
||||
case CON_QCLASS:
|
||||
case CON_QAGE:
|
||||
case CON_QSTAT_PREF:
|
||||
case CON_QSHORTDESC:
|
||||
case CON_PLR_DESC:
|
||||
|
|
@ -2019,9 +2025,33 @@ case CON_QCLASS:
|
|||
GET_CLASS(d->character) = load_result;
|
||||
}
|
||||
|
||||
show_age_prompt(d);
|
||||
STATE(d) = CON_QAGE;
|
||||
return;
|
||||
|
||||
case CON_QAGE: {
|
||||
if (!is_number(arg)) {
|
||||
write_to_output(d, "\r\nPlease enter a number between %d and %d.\r\n",
|
||||
MIN_CHAR_AGE, MAX_CHAR_AGE);
|
||||
show_age_prompt(d);
|
||||
return;
|
||||
}
|
||||
|
||||
int age_years = atoi(arg);
|
||||
if (age_years < MIN_CHAR_AGE || age_years > MAX_CHAR_AGE) {
|
||||
write_to_output(d, "\r\nAge must be between %d and %d.\r\n",
|
||||
MIN_CHAR_AGE, MAX_CHAR_AGE);
|
||||
show_age_prompt(d);
|
||||
return;
|
||||
}
|
||||
|
||||
GET_ROLEPLAY_AGE(d->character) = age_years;
|
||||
GET_ROLEPLAY_AGE_YEAR(d->character) = time_info.year;
|
||||
|
||||
show_stat_pref_prompt(d);
|
||||
STATE(d) = CON_QSTAT_PREF;
|
||||
return;
|
||||
}
|
||||
|
||||
case CON_QSTAT_PREF: {
|
||||
ubyte order[NUM_ABILITIES];
|
||||
|
|
|
|||
23
src/medit.c
23
src/medit.c
|
|
@ -241,6 +241,9 @@ static void init_mobile(struct char_data *mob)
|
|||
GET_MAX_MANA(mob) = GET_MAX_STAMINA(mob) = 100;
|
||||
GET_WEIGHT(mob) = 200;
|
||||
GET_HEIGHT(mob) = 198;
|
||||
mob->player.time.birth = time(0);
|
||||
mob->player.roleplay_age = MIN_CHAR_AGE;
|
||||
mob->player.roleplay_age_year = time_info.year;
|
||||
|
||||
/* Only assign defaults if the individual stat is unset (zero) */
|
||||
if (!mob->real_abils.str) mob->real_abils.str = 11;
|
||||
|
|
@ -436,6 +439,7 @@ static void medit_disp_menu(struct descriptor_data *d)
|
|||
"%s1%s) Name: %s%s\r\n"
|
||||
"%s2%s) Keywords: %s%s\r\n"
|
||||
"%s3%s) Sex: %s%-7.7s%s\r\n"
|
||||
"%sG%s) Age: %s%d%s\r\n"
|
||||
"%s4%s) S-Desc: %s%s\r\n"
|
||||
"%s5%s) L-Desc:-\r\n%s%s\r\n"
|
||||
"%s6%s) D-Desc:-\r\n%s%s\r\n",
|
||||
|
|
@ -444,6 +448,7 @@ static void medit_disp_menu(struct descriptor_data *d)
|
|||
grn, nrm, yel, GET_NAME(mob),
|
||||
grn, nrm, yel, GET_KEYWORDS(mob),
|
||||
grn, nrm, yel, genders[(int)GET_SEX(mob)], nrm,
|
||||
grn, nrm, yel, GET_ROLEPLAY_AGE(mob), nrm,
|
||||
grn, nrm, yel, GET_SDESC(mob),
|
||||
grn, nrm, yel, GET_LDESC(mob),
|
||||
grn, nrm, yel, GET_DDESC(mob)
|
||||
|
|
@ -764,6 +769,11 @@ void medit_parse(struct descriptor_data *d, char *arg)
|
|||
OLC_MODE(d) = MEDIT_SEX;
|
||||
medit_disp_sex(d);
|
||||
return;
|
||||
case 'g':
|
||||
case 'G':
|
||||
OLC_MODE(d) = MEDIT_AGE;
|
||||
write_to_output(d, "Enter age (%d-%d): ", MIN_CHAR_AGE, MAX_CHAR_AGE);
|
||||
return;
|
||||
case '4':
|
||||
OLC_MODE(d) = MEDIT_S_DESC;
|
||||
i--;
|
||||
|
|
@ -1308,6 +1318,19 @@ void medit_parse(struct descriptor_data *d, char *arg)
|
|||
GET_SEX(OLC_MOB(d)) = LIMIT(i - 1, 0, NUM_GENDERS - 1);
|
||||
break;
|
||||
|
||||
case MEDIT_AGE:
|
||||
if (i < MIN_CHAR_AGE || i > MAX_CHAR_AGE) {
|
||||
write_to_output(d, "Age must be between %d and %d.\r\n",
|
||||
MIN_CHAR_AGE, MAX_CHAR_AGE);
|
||||
write_to_output(d, "Enter age (%d-%d): ", MIN_CHAR_AGE, MAX_CHAR_AGE);
|
||||
return;
|
||||
}
|
||||
GET_ROLEPLAY_AGE(OLC_MOB(d)) = i;
|
||||
GET_ROLEPLAY_AGE_YEAR(OLC_MOB(d)) = time_info.year;
|
||||
OLC_VAL(d) = TRUE;
|
||||
medit_disp_menu(d);
|
||||
return;
|
||||
|
||||
case MEDIT_NUM_HP_DICE:
|
||||
GET_HIT(OLC_MOB(d)) = LIMIT(i, 0, 30);
|
||||
OLC_VAL(d) = TRUE;
|
||||
|
|
|
|||
|
|
@ -274,6 +274,7 @@ extern const char *nrm, *grn, *cyn, *yel;
|
|||
/* Numerical responses. */
|
||||
#define MEDIT_NUMERICAL_RESPONSE 15
|
||||
#define MEDIT_SEX 16
|
||||
#define MEDIT_AGE 44
|
||||
#define MEDIT_NUM_HP_DICE 17
|
||||
#define MEDIT_SIZE_HP_DICE 18
|
||||
#define MEDIT_ADD_HP 19
|
||||
|
|
|
|||
|
|
@ -222,6 +222,20 @@ char *get_name_by_id(long id)
|
|||
return (NULL);
|
||||
}
|
||||
|
||||
static void update_roleplay_age(struct char_data *ch)
|
||||
{
|
||||
if (GET_ROLEPLAY_AGE(ch) == 0)
|
||||
GET_ROLEPLAY_AGE(ch) = MIN_CHAR_AGE;
|
||||
|
||||
if (GET_ROLEPLAY_AGE_YEAR(ch) == 0)
|
||||
GET_ROLEPLAY_AGE_YEAR(ch) = time_info.year;
|
||||
|
||||
if (time_info.year > GET_ROLEPLAY_AGE_YEAR(ch)) {
|
||||
GET_ROLEPLAY_AGE(ch) += (time_info.year - GET_ROLEPLAY_AGE_YEAR(ch));
|
||||
GET_ROLEPLAY_AGE_YEAR(ch) = time_info.year;
|
||||
}
|
||||
}
|
||||
|
||||
/* Stuff related to the save/load player system. */
|
||||
/* New load_char reads ASCII Player Files. Load a char, TRUE if loaded, FALSE
|
||||
* if not. */
|
||||
|
|
@ -260,6 +274,8 @@ int load_char(const char *name, struct char_data *ch)
|
|||
GET_LEVEL(ch) = PFDEF_LEVEL;
|
||||
GET_HEIGHT(ch) = PFDEF_HEIGHT;
|
||||
GET_WEIGHT(ch) = PFDEF_WEIGHT;
|
||||
GET_ROLEPLAY_AGE(ch) = 0;
|
||||
GET_ROLEPLAY_AGE_YEAR(ch) = 0;
|
||||
GET_ALIGNMENT(ch) = PFDEF_ALIGNMENT;
|
||||
for (i = 0; i < NUM_OF_SAVING_THROWS; i++)
|
||||
GET_SAVE(ch, i) = PFDEF_SAVETHROW;
|
||||
|
|
@ -317,6 +333,8 @@ int load_char(const char *name, struct char_data *ch)
|
|||
switch (*tag) {
|
||||
case 'A':
|
||||
if (!strcmp(tag, "Ac ")) GET_AC(ch) = atoi(line);
|
||||
else if (!strcmp(tag, "AgYr")) GET_ROLEPLAY_AGE_YEAR(ch) = atoi(line);
|
||||
else if (!strcmp(tag, "Age ")) GET_ROLEPLAY_AGE(ch) = LIMIT(atoi(line), MIN_CHAR_AGE, MAX_CHAR_AGE);
|
||||
else if (!strcmp(tag, "Acct")) {
|
||||
if (GET_ACCOUNT(ch))
|
||||
free(GET_ACCOUNT(ch));
|
||||
|
|
@ -515,6 +533,8 @@ int load_char(const char *name, struct char_data *ch)
|
|||
}
|
||||
}
|
||||
|
||||
update_roleplay_age(ch);
|
||||
ch->player.time.birth = time(0) - get_total_played_seconds(ch);
|
||||
affect_total(ch);
|
||||
|
||||
/* initialization for imms */
|
||||
|
|
@ -564,6 +584,9 @@ void save_char(struct char_data * ch)
|
|||
}
|
||||
}
|
||||
|
||||
update_roleplay_age(ch);
|
||||
ch->player.time.birth = time(0) - get_total_played_seconds(ch);
|
||||
|
||||
if (!get_filename(filename, sizeof(filename), PLR_FILE, GET_NAME(ch)))
|
||||
return;
|
||||
if (!(fl = fopen(filename, "w"))) {
|
||||
|
|
@ -631,6 +654,8 @@ void save_char(struct char_data * ch)
|
|||
|
||||
fprintf(fl, "Id : %ld\n", GET_IDNUM(ch));
|
||||
fprintf(fl, "Brth: %ld\n", (long)ch->player.time.birth);
|
||||
fprintf(fl, "Age : %d\n", GET_ROLEPLAY_AGE(ch));
|
||||
fprintf(fl, "AgYr: %d\n", GET_ROLEPLAY_AGE_YEAR(ch));
|
||||
fprintf(fl, "Plyd: %d\n", ch->player.time.played);
|
||||
fprintf(fl, "Last: %ld\n", (long)ch->player.time.logon);
|
||||
|
||||
|
|
|
|||
|
|
@ -348,6 +348,7 @@
|
|||
#define CON_QSPECIES 8 /**< Choose character species */
|
||||
#define CON_QCLASS 9 /**< Choose character class */
|
||||
#define CON_QSTAT_PREF 44 /**< Choose character stat preference order */
|
||||
#define CON_QAGE 45 /**< Choose character age */
|
||||
#define CON_QSHORTDESC 10 /**< Enter a new character short description prompt */
|
||||
#define CON_RMOTD 11 /**< Reading the message of the day */
|
||||
#define CON_MENU 12 /**< At the main menu */
|
||||
|
|
@ -906,7 +907,7 @@ struct time_info_data
|
|||
/** Player specific time information. */
|
||||
struct time_data
|
||||
{
|
||||
time_t birth; /**< Represents the PCs birthday, used to calculate age. */
|
||||
time_t birth; /**< Anchor for calculating mechanical age from played time. */
|
||||
time_t logon; /**< Time of the last logon, used to calculate time played */
|
||||
int played; /**< This is the total accumulated time played in secs */
|
||||
};
|
||||
|
|
@ -943,7 +944,9 @@ struct char_player_data
|
|||
byte chclass; /**< PC / NPC class */
|
||||
byte species; /**< PC / NPC species */
|
||||
byte level; /**< PC / NPC level */
|
||||
struct time_data time; /**< PC AGE in days */
|
||||
struct time_data time; /**< Playtime tracking */
|
||||
int roleplay_age; /**< Roleplay age in years */
|
||||
int roleplay_age_year; /**< Last mud year roleplay age was updated */
|
||||
ubyte weight; /**< PC / NPC weight */
|
||||
ubyte height; /**< PC / NPC height */
|
||||
};
|
||||
|
|
|
|||
19
src/utils.c
19
src/utils.c
|
|
@ -570,17 +570,24 @@ time_t mud_time_to_secs(struct time_info_data *now)
|
|||
return (time(NULL) - when);
|
||||
}
|
||||
|
||||
/** Calculate a player's MUD age.
|
||||
* @todo The minimum starting age of 17 is hardcoded in this function. Recommend
|
||||
* changing the minimum age to a property (variable) external to this function.
|
||||
time_t get_total_played_seconds(const struct char_data *ch)
|
||||
{
|
||||
time_t played = ch->player.time.played;
|
||||
|
||||
if (ch->desc && STATE(ch->desc) == CON_PLAYING)
|
||||
played += time(0) - ch->player.time.logon;
|
||||
|
||||
return played;
|
||||
}
|
||||
|
||||
/** Calculate a player's mechanical age based on total played time.
|
||||
* @param ch A valid player character. */
|
||||
struct time_info_data *age(struct char_data *ch)
|
||||
{
|
||||
static struct time_info_data player_age;
|
||||
|
||||
player_age = *mud_time_passed(time(0), ch->player.time.birth);
|
||||
|
||||
player_age.year += 17; /* All players start at 17 */
|
||||
time_t played = get_total_played_seconds(ch);
|
||||
player_age = *mud_time_passed(time(0), time(0) - played);
|
||||
|
||||
return (&player_age);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ void sprintbitarray(int bitvector[], const char *names[], int maxar, char *resul
|
|||
int get_line(FILE *fl, char *buf);
|
||||
int get_filename(char *filename, size_t fbufsize, int mode, const char *orig_name);
|
||||
time_t mud_time_to_secs(struct time_info_data *now);
|
||||
time_t get_total_played_seconds(const struct char_data *ch);
|
||||
struct time_info_data *age(struct char_data *ch);
|
||||
int num_pc_in_room(struct room_data *room);
|
||||
void core_dump_real(const char *who, int line);
|
||||
|
|
@ -236,6 +237,9 @@ void char_from_furniture(struct char_data *ch);
|
|||
* Current calculation ~= 12.4 real life days */
|
||||
#define SECS_PER_MUD_YEAR (17*SECS_PER_MUD_MONTH)
|
||||
|
||||
#define MIN_CHAR_AGE 18
|
||||
#define MAX_CHAR_AGE 65
|
||||
|
||||
/** The number of seconds in a real minute. */
|
||||
#define SECS_PER_REAL_MIN 60
|
||||
/** The number of seconds in a real hour. */
|
||||
|
|
@ -516,6 +520,8 @@ do \
|
|||
#define GET_WAS_IN(ch) ((ch)->was_in_room)
|
||||
/** How old is PC/NPC, at last recorded time? */
|
||||
#define GET_AGE(ch) (age(ch)->year)
|
||||
#define GET_ROLEPLAY_AGE(ch) ((ch)->player.roleplay_age)
|
||||
#define GET_ROLEPLAY_AGE_YEAR(ch) ((ch)->player.roleplay_age_year)
|
||||
|
||||
/** Proper name for PCs and NPCs. */
|
||||
#define GET_NAME(ch) ((ch)->player.name)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue