mirror of
https://github.com/tbamud/tbamud.git
synced 2026-03-20 03:06:32 +01:00
Prioritize stats during chargen
This commit is contained in:
parent
0e2e80fd09
commit
5d4d724e73
4 changed files with 237 additions and 4 deletions
|
|
@ -43,12 +43,12 @@ 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
|
||||
* Race/species selection and stat ranges (elves have higher dex, dwarves have higher str, etc)
|
||||
* Prioritized stats during character generation
|
||||
|
||||
Features to be implemented in the next few releases:
|
||||
|
||||
* Race/species selection and stat ranges (elves have higher dex, dwarves have higher str, etc)
|
||||
* Subclass selection to personalize character further
|
||||
* Prioritized stats during character generation
|
||||
* Combat is slowed down so it isn't over in < 15 seconds (unless you're far outmatched)
|
||||
* Mounts added to help with long trips
|
||||
* Wagons added to help with caravans
|
||||
|
|
|
|||
103
src/class.c
103
src/class.c
|
|
@ -139,10 +139,103 @@ bool has_save_proficiency(int class_num, int ability) {
|
|||
}
|
||||
}
|
||||
|
||||
static void set_real_ability(struct char_data *ch, int ability, int value)
|
||||
{
|
||||
switch (ability) {
|
||||
case ABIL_STR: ch->real_abils.str = value; break;
|
||||
case ABIL_DEX: ch->real_abils.dex = value; break;
|
||||
case ABIL_CON: ch->real_abils.con = value; break;
|
||||
case ABIL_INT: ch->real_abils.intel = value; break;
|
||||
case ABIL_WIS: ch->real_abils.wis = value; break;
|
||||
case ABIL_CHA: ch->real_abils.cha = value; break;
|
||||
}
|
||||
}
|
||||
|
||||
static void roll_real_abils_preference(struct char_data *ch)
|
||||
{
|
||||
int i, j, temp;
|
||||
int rolls[NUM_ABILITIES];
|
||||
int sorted[NUM_ABILITIES];
|
||||
bool used[NUM_ABILITIES] = { FALSE };
|
||||
bool assigned[NUM_ABILITIES] = { FALSE };
|
||||
static const int default_order[NUM_ABILITIES] = {
|
||||
ABIL_STR, ABIL_DEX, ABIL_CON, ABIL_INT, ABIL_WIS, ABIL_CHA
|
||||
};
|
||||
|
||||
for (i = 0; i < NUM_ABILITIES; i++) {
|
||||
int die[4];
|
||||
|
||||
for (j = 0; j < 4; j++)
|
||||
die[j] = rand_number(1, 6);
|
||||
|
||||
temp = die[0] + die[1] + die[2] + die[3] -
|
||||
MIN(die[0], MIN(die[1], MIN(die[2], die[3])));
|
||||
|
||||
rolls[i] = temp;
|
||||
sorted[i] = temp;
|
||||
}
|
||||
|
||||
for (i = 0; i < NUM_ABILITIES - 1; i++) {
|
||||
for (j = i + 1; j < NUM_ABILITIES; j++) {
|
||||
if (sorted[j] > sorted[i]) {
|
||||
temp = sorted[i];
|
||||
sorted[i] = sorted[j];
|
||||
sorted[j] = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int pref_count = ch->stat_pref_count;
|
||||
if (pref_count > NUM_ABILITIES)
|
||||
pref_count = NUM_ABILITIES;
|
||||
|
||||
for (i = 0; i < pref_count; i++) {
|
||||
int ability = ch->stat_pref_order[i];
|
||||
|
||||
if (ability < 0 || ability >= NUM_ABILITIES)
|
||||
continue;
|
||||
|
||||
set_real_ability(ch, ability, sorted[i]);
|
||||
assigned[ability] = TRUE;
|
||||
|
||||
for (j = 0; j < NUM_ABILITIES; j++) {
|
||||
if (!used[j] && rolls[j] == sorted[i]) {
|
||||
used[j] = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int fifo_idx = 0;
|
||||
for (i = 0; i < NUM_ABILITIES; i++) {
|
||||
int ability = default_order[i];
|
||||
|
||||
if (assigned[ability])
|
||||
continue;
|
||||
|
||||
while (fifo_idx < NUM_ABILITIES && used[fifo_idx])
|
||||
fifo_idx++;
|
||||
if (fifo_idx >= NUM_ABILITIES)
|
||||
break;
|
||||
|
||||
set_real_ability(ch, ability, rolls[fifo_idx]);
|
||||
used[fifo_idx] = TRUE;
|
||||
assigned[ability] = TRUE;
|
||||
fifo_idx++;
|
||||
}
|
||||
|
||||
if (HAS_VALID_SPECIES(ch))
|
||||
apply_species_bonuses(ch);
|
||||
else
|
||||
ch->aff_abils = ch->real_abils;
|
||||
|
||||
ch->stat_pref_use = FALSE;
|
||||
}
|
||||
|
||||
/* Roll the 6 stats for a character... each stat is made of the sum of the best
|
||||
* 3 out of 4 rolls of a 6-sided die. Each class then decides which priority
|
||||
* will be given for the best to worst stats. */
|
||||
void roll_real_abils(struct char_data *ch)
|
||||
static void roll_real_abils_classic(struct char_data *ch)
|
||||
{
|
||||
int i, j, k, temp;
|
||||
ubyte table[6];
|
||||
|
|
@ -238,6 +331,14 @@ void roll_real_abils(struct char_data *ch)
|
|||
ch->aff_abils = ch->real_abils;
|
||||
}
|
||||
|
||||
void roll_real_abils(struct char_data *ch)
|
||||
{
|
||||
if (ch && ch->stat_pref_use)
|
||||
roll_real_abils_preference(ch);
|
||||
else
|
||||
roll_real_abils_classic(ch);
|
||||
}
|
||||
|
||||
/* Per-class skill caps */
|
||||
#define DEFAULT_CLASS_SKILL_MAX 90
|
||||
|
||||
|
|
|
|||
|
|
@ -49,6 +49,10 @@ static bool perform_new_char_dupe_check(struct descriptor_data *d);
|
|||
/* sort_commands utility */
|
||||
static int sort_commands_helper(const void *a, const void *b);
|
||||
static void show_species_menu(struct descriptor_data *d);
|
||||
static bool is_creation_state(int state);
|
||||
static void show_stat_pref_prompt(struct descriptor_data *d);
|
||||
static int ability_from_pref_arg(const char *arg);
|
||||
static bool parse_stat_preference(char *input, ubyte *order, ubyte *count);
|
||||
|
||||
/* globals defined here, used here and elsewhere */
|
||||
int *cmd_sort_info = NULL;
|
||||
|
|
@ -1270,7 +1274,7 @@ static bool perform_new_char_dupe_check(struct descriptor_data *d)
|
|||
/* Do the player names match? */
|
||||
if (!strcmp(GET_NAME(k->character), GET_NAME(d->character))) {
|
||||
/* Check the other character is still in creation? */
|
||||
if ((STATE(k) > CON_PLAYING) && (STATE(k) < CON_QCLASS)) {
|
||||
if (is_creation_state(STATE(k))) {
|
||||
/* Boot the older one */
|
||||
k->character->desc = NULL;
|
||||
k->character = NULL;
|
||||
|
|
@ -1317,6 +1321,107 @@ static void show_species_menu(struct descriptor_data *d)
|
|||
write_to_output(d, "Species: ");
|
||||
}
|
||||
|
||||
static bool is_creation_state(int state)
|
||||
{
|
||||
switch (state) {
|
||||
case CON_GET_NAME:
|
||||
case CON_NAME_CNFRM:
|
||||
case CON_PASSWORD:
|
||||
case CON_NEWPASSWD:
|
||||
case CON_CNFPASSWD:
|
||||
case CON_QSEX:
|
||||
case CON_QSPECIES:
|
||||
case CON_QCLASS:
|
||||
case CON_QSTAT_PREF:
|
||||
case CON_QSHORTDESC:
|
||||
case CON_PLR_DESC:
|
||||
case CON_PLR_BACKGROUND:
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static void show_stat_pref_prompt(struct descriptor_data *d)
|
||||
{
|
||||
write_to_output(d,
|
||||
"\r\nEnter your stat preference, with the first stat being your preferred highest,\r\n"
|
||||
"followed by the others in descending order.\r\n"
|
||||
"If you list fewer than six, those listed get the highest rolls; the rest are FIFO.\r\n"
|
||||
"Example: strength dexterity constitution intelligence wisdom charisma\r\n"
|
||||
" or: str dex con int wis cha\r\n"
|
||||
"Press Enter to skip (first-in, first-out).\r\n"
|
||||
"Stat preference: ");
|
||||
}
|
||||
|
||||
static int ability_from_pref_arg(const char *arg)
|
||||
{
|
||||
if (!arg || !*arg)
|
||||
return -1;
|
||||
if (!str_cmp(arg, "str") || is_abbrev(arg, "strength"))
|
||||
return ABIL_STR;
|
||||
if (!str_cmp(arg, "dex") || is_abbrev(arg, "dexterity"))
|
||||
return ABIL_DEX;
|
||||
if (!str_cmp(arg, "con") || is_abbrev(arg, "constitution"))
|
||||
return ABIL_CON;
|
||||
if (!str_cmp(arg, "int") || is_abbrev(arg, "intelligence"))
|
||||
return ABIL_INT;
|
||||
if (!str_cmp(arg, "wis") || is_abbrev(arg, "wisdom"))
|
||||
return ABIL_WIS;
|
||||
if (!str_cmp(arg, "cha") || is_abbrev(arg, "charisma"))
|
||||
return ABIL_CHA;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static bool parse_stat_preference(char *input, ubyte *order, ubyte *count)
|
||||
{
|
||||
char arg[MAX_INPUT_LENGTH];
|
||||
bool seen[NUM_ABILITIES] = { FALSE };
|
||||
|
||||
if (!order || !count)
|
||||
return FALSE;
|
||||
|
||||
*count = 0;
|
||||
skip_spaces(&input);
|
||||
if (!*input)
|
||||
return TRUE;
|
||||
|
||||
if (!str_cmp(input, "none") || !str_cmp(input, "no") || !str_cmp(input, "skip"))
|
||||
return TRUE;
|
||||
|
||||
while (*input) {
|
||||
size_t len;
|
||||
int ability;
|
||||
|
||||
input = one_argument(input, arg);
|
||||
if (!*arg)
|
||||
break;
|
||||
|
||||
len = strlen(arg);
|
||||
while (len > 0 && (arg[len - 1] == ',' || arg[len - 1] == '.')) {
|
||||
arg[len - 1] = '\0';
|
||||
len--;
|
||||
}
|
||||
|
||||
if (!*arg)
|
||||
continue;
|
||||
|
||||
ability = ability_from_pref_arg(arg);
|
||||
if (ability < 0 || ability >= NUM_ABILITIES)
|
||||
return FALSE;
|
||||
if (seen[ability])
|
||||
return FALSE;
|
||||
if (*count >= NUM_ABILITIES)
|
||||
return FALSE;
|
||||
|
||||
order[*count] = (ubyte)ability;
|
||||
(*count)++;
|
||||
seen[ability] = TRUE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* load the player, put them in the right room - used by copyover_recover too */
|
||||
int enter_player_game (struct descriptor_data *d)
|
||||
{
|
||||
|
|
@ -1912,6 +2017,27 @@ case CON_QCLASS:
|
|||
GET_CLASS(d->character) = load_result;
|
||||
}
|
||||
|
||||
show_stat_pref_prompt(d);
|
||||
STATE(d) = CON_QSTAT_PREF;
|
||||
return;
|
||||
|
||||
case CON_QSTAT_PREF: {
|
||||
ubyte order[NUM_ABILITIES];
|
||||
ubyte count = 0;
|
||||
|
||||
if (!parse_stat_preference(arg, order, &count)) {
|
||||
write_to_output(d,
|
||||
"\r\nInvalid stat list. Please enter a valid order, or press Enter to skip.\r\n");
|
||||
show_stat_pref_prompt(d);
|
||||
return;
|
||||
}
|
||||
|
||||
d->character->stat_pref_use = TRUE;
|
||||
d->character->stat_pref_count = count;
|
||||
for (int i = 0; i < NUM_ABILITIES; i++) {
|
||||
d->character->stat_pref_order[i] = (i < count) ? order[i] : 0;
|
||||
}
|
||||
|
||||
/* Create player entry and initialize character now so file exists */
|
||||
if (d->olc) {
|
||||
free(d->olc);
|
||||
|
|
@ -1958,6 +2084,7 @@ case CON_QCLASS:
|
|||
|
||||
STATE(d) = CON_QSHORTDESC;
|
||||
return;
|
||||
}
|
||||
|
||||
case CON_QSHORTDESC: {
|
||||
skip_spaces(&arg);
|
||||
|
|
|
|||
|
|
@ -347,6 +347,7 @@
|
|||
#define CON_QSEX 7 /**< Choose character sex */
|
||||
#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_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 */
|
||||
|
|
@ -1162,6 +1163,10 @@ struct char_data
|
|||
struct group_data *group; /**< Character's Group */
|
||||
|
||||
long pref; /**< unique session id */
|
||||
|
||||
bool stat_pref_use; /**< Use stat preference ordering when rolling abilities */
|
||||
ubyte stat_pref_count; /**< Number of preferred stats entered */
|
||||
ubyte stat_pref_order[NUM_ABILITIES]; /**< Ability order preferences */
|
||||
|
||||
struct list_data * events;
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue