Skip to content

Commit

Permalink
Fixes for essence, index, and magic cap with new races
Browse files Browse the repository at this point in the history
  • Loading branch information
luciensadi committed Dec 9, 2023
1 parent b708b1c commit ed04590
Show file tree
Hide file tree
Showing 14 changed files with 140 additions and 87 deletions.
4 changes: 2 additions & 2 deletions src/act.other.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3306,9 +3306,9 @@ bool process_single_boost(struct char_data *ch, int boost_attribute) {
// If they have an active boost for this attribute, decrement it by one and test.
if (BOOST(ch)[boost_attribute][0] > 0 && (--BOOST(ch)[boost_attribute][0]) == 0) {
send_to_char(ch, msg);
if (power <= racial_limits[(int)GET_RACE(ch)][0][2])
if (power <= racial_limits[(int)GET_RACE(ch)][RACIAL_LIMITS_NORMAL][boost_attribute])
damage = LIGHT;
else if (power < racial_limits[(int)GET_RACE(ch)][1][2])
else if (power < racial_limits[(int)GET_RACE(ch)][RACIAL_LIMITS_150_PCT][boost_attribute])
damage = MODERATE;
else
damage = SERIOUS;
Expand Down
40 changes: 29 additions & 11 deletions src/act.wizard.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3282,7 +3282,7 @@ void restore_character(struct char_data *vict, bool reset_staff_stats) {
set_character_skill(vict, i, 100, FALSE);

// Restore their essence to 6.00.
vict->real_abils.ess = 600;
GET_REAL_ESS(vict) = GET_RACIAL_STARTING_ESSENCE_FOR_RACE(GET_RACE(vict));

// Non-executive staff get 15's in stats. Executives get 50s.
int stat_level = access_level(vict, LVL_EXECUTIVE) ? 50 : 15;
Expand All @@ -3294,7 +3294,7 @@ void restore_character(struct char_data *vict, bool reset_staff_stats) {
GET_REAL_STR(vict) = stat_level;
GET_REAL_BOD(vict) = stat_level;
GET_REAL_CHA(vict) = stat_level;
vict->real_abils.mag = stat_level * 100;
GET_SETTABLE_REAL_MAG(vict) = stat_level * 100;

// Recalculate their affects.
affect_total(vict);
Expand Down Expand Up @@ -4997,6 +4997,7 @@ ACMD(do_set)
{ "noradio", LVL_FIXER, PC, BINARY }, // 85
{ "sitehidden", LVL_PRESIDENT, PC, BINARY },
{ "lifestyle", LVL_PRESIDENT, PC, MISC },
{ "highestindex", LVL_ADMIN, BOTH, NUMBER },
{ "\n", 0, BOTH, MISC }
};

Expand Down Expand Up @@ -5173,8 +5174,8 @@ ACMD(do_set)
if (IS_NPC(vict) || (IS_SENATOR(vict) && access_level(vict, LVL_ADMIN)))
RANGE(1, 1000);
else
RANGE(1, 600);
vict->real_abils.ess = value;
RANGE(1, GET_RACIAL_STARTING_ESSENCE_FOR_RACE(GET_RACE(vict)));
GET_REAL_ESS(vict) = value;
affect_total(vict);
break;
case 11:
Expand Down Expand Up @@ -5495,8 +5496,8 @@ ACMD(do_set)
if (IS_NPC(vict) || (IS_SENATOR(vict) && access_level(vict, LVL_ADMIN)))
RANGE(0, 1000);
else
RANGE(0, 600);
vict->real_abils.bod_index = value;
RANGE(0, 900);
GET_INDEX(vict) = value;
affect_total(vict);
break;
case 55:
Expand Down Expand Up @@ -5570,11 +5571,23 @@ ACMD(do_set)
case 73: /* race */
{
bool successful = FALSE;
for (int i = RACE_HUMAN; i < NUM_RACES; i++) {
if (!str_cmp(pc_race_types[i], val_arg)) {
GET_RACE(vict) = i;
for (int race_idx = RACE_HUMAN; race_idx < NUM_RACES; race_idx++) {
if (!str_cmp(pc_race_types[race_idx], val_arg)) {
// Check to make sure this won't break their essence scores.
int existing_ess_loss = GET_RACIAL_STARTING_ESSENCE_FOR_RACE(GET_RACE(vict)) - GET_REAL_ESS(vict);
int new_ess = GET_RACIAL_STARTING_ESSENCE_FOR_RACE(race_idx) - existing_ess_loss;
if (new_ess <= 0) {
send_to_char(ch, "Changing %s's race to %s would put them at %.2f essence!", GET_CHAR_NAME(vict), pc_race_types[race_idx], new_ess / 100);
SET_CLEANUP(false);
return;
}

// Set their race and essence.
GET_RACE(vict) = race_idx;
GET_REAL_ESS(vict) = new_ess;

successful = TRUE;
snprintf(buf, sizeof(buf), "%s's race set to %s by %s.\r\n", GET_CHAR_NAME(vict), pc_race_types[i], GET_CHAR_NAME(ch));
snprintf(buf, sizeof(buf), "%s's race set to %s by %s.\r\n", GET_CHAR_NAME(vict), pc_race_types[race_idx], GET_CHAR_NAME(ch));
mudlog(buf, ch, LOG_WIZLOG, TRUE);

// Save the new race to disk.
Expand Down Expand Up @@ -5636,7 +5649,7 @@ ACMD(do_set)
mudlog(buf, ch, LOG_WIZLOG, TRUE );
break;
case 81: /* esshole */
RANGE(0, 600);
RANGE(0, GET_RACIAL_STARTING_ESSENCE_FOR_RACE(GET_RACE(vict)));
snprintf(buf, sizeof(buf),"%s changed %s's esshole from %d to %d.", GET_CHAR_NAME(ch), GET_NAME(vict), GET_ESSHOLE(vict), value);
GET_ESSHOLE(vict) = value;
mudlog(buf, ch, LOG_WIZLOG, TRUE );
Expand Down Expand Up @@ -5675,6 +5688,11 @@ ACMD(do_set)
mudlog_vfprintf(ch, LOG_WIZLOG, "%s changed %s's lifestyle to '%s^n'.", GET_CHAR_NAME(ch), GET_CHAR_NAME(vict), val_arg);
strlcpy(buf, "OK.", sizeof(buf));
break;
case 88: /* highestindex */
RANGE(0, 900);
snprintf(buf, sizeof(buf),"%s changed %s's highest bioware index from %d to %d.", GET_CHAR_NAME(ch), GET_NAME(vict), GET_HIGHEST_INDEX(vict), value);
GET_HIGHEST_INDEX(vict) = value;
mudlog(buf, ch, LOG_WIZLOG, TRUE );
default:
snprintf(buf, sizeof(buf), "Can't set that!");
break;
Expand Down
3 changes: 3 additions & 0 deletions src/awake.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3060,6 +3060,9 @@ enum {
#define LIFESTYLE_LUXURY 5
#define NUM_LIFESTYLES 6

#define RACIAL_LIMITS_NORMAL 0
#define RACIAL_LIMITS_150_PCT 1

// This is to flag variables used eg in macros so that the compiler won't complain about unused variables
// when they're actually used. Casting to void does nothing but the compiler will stop thinking it's
// unused. This is the same way Q_UNUSED is used in Qt. -- Nodens
Expand Down
37 changes: 12 additions & 25 deletions src/chargen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ void display_prestige_race_menu(struct descriptor_data *d) {
}

void ccr_race_menu(struct descriptor_data *d) {
SEND_TO_Q("\r\nSelect a race:"
snprintf(buf, sizeof(buf), "\r\nSelect a race:"
"\r\n Base Races (no shop penalties):"
"\r\n [1] Human ( 0 points / slot E)"
"\r\n [2] Dwarf ( 5 points / slot D)"
Expand All @@ -137,12 +137,13 @@ void ccr_race_menu(struct descriptor_data *d) {
"\r\n"
#ifdef ALLOW_PRESTIGE_RACES
"\r\n Special (has prerequisites):"
"\r\n [*] Prestige Race (costs 50 - 500 system points)"
"\r\n [*] Prestige Race (costs %d - %d system points)"
"\r\n"
#endif
"\r\n ?# (for help on a particular race), ex: ?A"
"\r\n"
"\r\nRace: ", d);
"\r\nRace: ", MIN_PRESTIGE_RACE_COST, MAX_PRESTIGE_RACE_COST);
SEND_TO_Q(buf, d);
d->ccr.mode = CCR_RACE;
}

Expand Down Expand Up @@ -436,16 +437,9 @@ void archetype_selection_parse(struct descriptor_data *d, const char *arg) {
#undef NUM_ARCH_GEAR_ENTRIES
}

// Set their index and essence. Everyone starts with 0 bioware index and 6.00 essence.
// Set their index and essence. Everyone starts with 0 bioware index and max natural essence.
GET_INDEX(CH) = 0;
GET_REAL_ESS(CH) = 600;

// Ghouls lose 1.00 essence immediately.
if (IS_GHOUL(CH))
GET_REAL_ESS(CH) -= 100;
// Dragons gain 1.00 essence.
if (IS_DRAGON(CH))
GET_REAL_ESS(CH) += 100;
GET_REAL_ESS(CH) = GET_RACIAL_STARTING_ESSENCE_FOR_RACE(GET_RACE(CH));

// Equip cyberware (deduct essence and modify stats as appropriate)
for (int cyb = 0; cyb < NUM_ARCHETYPE_CYBERWARE; cyb++) {
Expand Down Expand Up @@ -619,16 +613,9 @@ const char *gnome_magic_table[4] = { "None", "Full Shaman", "Aspected Shaman", "

void set_attributes(struct char_data *ch, int magic)
{
// Everyone starts with 0 bioware index and 6.00 essence.
// Everyone starts with 0 bioware index and max natural essence.
GET_INDEX(ch) = 0;
GET_REAL_ESS(ch) = 600;

// Ghouls lose 1.00 essence immediately.
if (IS_GHOUL(ch))
GET_REAL_ESS(ch) -= 100;
// Dragons gain 1.00 essence.
if (IS_DRAGON(ch))
GET_REAL_ESS(ch) += 100;
GET_REAL_ESS(ch) = GET_RACIAL_STARTING_ESSENCE_FOR_RACE(GET_RACE(ch));

// If the character is a magic user, their magic is equal to their essence (this is free).
if (magic) {
Expand Down Expand Up @@ -964,7 +951,7 @@ int parse_assign(struct descriptor_data *d, const char *arg)
break;
}
d->ccr.temp = 0;
GET_PP(d->character) = (IS_GHOUL(CH) ? 500 : 600);
GET_PP(d->character) = (IS_GHOUL(CH) ? 500 : (IS_DRAGON(CH) ? 700 : 600));
return 1;
case 'c':
d->ccr.pr[d->ccr.temp] = PR_NONE;
Expand Down Expand Up @@ -1260,7 +1247,7 @@ int get_minimum_attribute_points_for_race(int race) {
int get_maximum_attribute_points_for_race(int race) {
int amount = 0;
for (int attr = BOD; attr <= WIL; attr++) {
amount += racial_limits[race][0][attr] - (MAX(1, racial_attribute_modifiers[race][attr] + 1));
amount += racial_limits[race][RACIAL_LIMITS_NORMAL][attr] - (MAX(1, racial_attribute_modifiers[race][attr] + 1));
}
return amount;
}
Expand Down Expand Up @@ -1412,7 +1399,7 @@ void create_parse(struct descriptor_data *d, const char *arg)
}
} else if (d->ccr.pr[PO_MAGIC] == CCR_MAGIC_ADEPT) {
GET_TRADITION(CH) = TRAD_ADEPT;
GET_PP(CH) = (IS_GHOUL(CH) ? 500 : 600);
GET_PP(CH) = (IS_GHOUL(CH) ? 500 : (IS_DRAGON(CH) ? 700 : 600));
start_game(d);
} else {
d->ccr.mode = CCR_TRADITION;
Expand Down Expand Up @@ -2109,7 +2096,7 @@ void create_parse(struct descriptor_data *d, const char *arg)
break;
case 'a':
GET_TRADITION(d->character) = TRAD_ADEPT;
GET_PP(CH) = (IS_GHOUL(CH) ? 500 : 600);
GET_PP(CH) = (IS_GHOUL(CH) ? 500 : (IS_DRAGON(CH) ? 700 : 600));
start_game(d);
break;
default:
Expand Down
6 changes: 4 additions & 2 deletions src/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -213,8 +213,8 @@ extern const char *CHARACTER_DELETED_NAME_FOR_SQL;
#define RITUAL_SPELL_COMPONENT_COST 500
#define RITUAL_SPELL_MAX_SUCCESS_MULTIPLIER 1.0

// This stat is x100 when stored, so the cap is 20 * 100 = 2000 aka 20 magic.
#define MAGIC_CAP 2000
// This stat is x100 when stored, so the cap is 26 * 100 = 2000 aka 26 magic. Reduced by cyber/bio in handler.cpp
#define MAGIC_CAP 2600

#define MAX_MOB_COMBAT_MAGIC_FORCE 10
#define MIN_MOB_COMBAT_MAGIC_FORCE 4
Expand Down Expand Up @@ -285,10 +285,12 @@ extern const char *CHARACTER_DELETED_NAME_FOR_SQL;
#define COST_TO_DECORATE_VEH 1500

// Prestige race costs.
#define MIN_PRESTIGE_RACE_COST 25
#define PRESTIGE_RACE_GHOUL_COST 25
#define PRESTIGE_RACE_DRYAD_COST 50
#define PRESTIGE_RACE_DRAKE_COST 500
#define PRESTIGE_RACE_DRAGON_COST 1000
#define MAX_PRESTIGE_RACE_COST 1000

/////////////// OLC permissions configuration /////////////////////////
#define LVL_FOR_SETTING_ZONE_EDITOR_ID_NUMBERS LVL_VICEPRES
Expand Down
2 changes: 1 addition & 1 deletion src/db.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1765,7 +1765,7 @@ void parse_mobile(File &in, long nr)


mob->real_abils.mag = data.GetInt("ATTRIBUTES/Mag", 0) * 100;
mob->real_abils.ess = 600;
mob->real_abils.ess = GET_RACIAL_STARTING_ESSENCE_FOR_RACE(GET_RACE(mob));
mob->real_abils.bod_index = 900;

mob->aff_abils = mob->real_abils;
Expand Down
62 changes: 35 additions & 27 deletions src/handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -860,11 +860,11 @@ void affect_total(struct char_data * ch)
GET_ATT(ch, att) = MAX(1, GET_ATT(ch, att));

// For races that go crazy high, allow them their full amount, then immediately soft cap the remainder.
if (GET_ATT(ch, att) <= racial_limits[(int) GET_RACE(ch)][0][att])
if (GET_ATT(ch, att) <= racial_limits[(int) GET_RACE(ch)][RACIAL_LIMITS_NORMAL][att])
continue;

// Ensure the cap isn't too low.
cap = MAX(cap, racial_limits[(int) GET_RACE(ch)][0][att] * 1.5);
cap = MAX(cap, racial_limits[(int) GET_RACE(ch)][RACIAL_LIMITS_NORMAL][att] * 1.5);

if (GET_ATT(ch, att) > cap)
GET_ATT(ch, att) = cap + ((GET_ATT(ch, att) - cap + 1) >> 1);
Expand All @@ -880,7 +880,7 @@ void affect_total(struct char_data * ch)
}
#endif

int base_essence = IS_GHOUL(ch) ? 500 : 600;
int base_essence = GET_RACIAL_STARTING_ESSENCE_FOR_RACE(GET_RACE(ch));
GET_ESS(ch) = MAX(0, MIN(GET_ESS(ch), base_essence));
GET_ESS(ch) -= GET_TEMP_ESSLOSS(ch);

Expand All @@ -889,31 +889,37 @@ void affect_total(struct char_data * ch)
GET_MAG(ch) -= MIN(GET_MAG(ch), GET_TEMP_MAGIC_LOSS(ch) * 100);
#else
{
// House ruled section here.
// Magic cap is 26, and is doubly impacted by cyber/bio costs, down to a minimum of 20.
// This allows "pure" characters to have a meaningful power level while still leaving some
// flexibility in builds before hitting the "may as well go full borg" cap of 20.
// You can take up to approximately 3 points of magic loss from 'ware before hitting the minimum 20 cap.
int magic_cap = 2600;
int essence_cost = base_essence - GET_ESS(ch);
int index_cost = GET_HIGHEST_INDEX(ch) / 2;
int cap_delta = 2 * (essence_cost + index_cost);
// Cap must be between 20-26 magic.
magic_cap = MIN(2600, MAX(2000, magic_cap - cap_delta));

#ifdef IS_BUILDPORT
if (!IS_NPC(ch) && PRF_FLAGGED(ch, PRF_ROLLS)) {
send_to_char(ch, "^L-- Magic cap debug: m_c %d (from 2600 - (e_c(%d-%d=%d), i_c(%d/2=%d), c_d(2*(%d+%d)=%d); tog rolls to disable^n\r\n",
magic_cap,
base_essence, GET_ESS(ch), essence_cost,
GET_HIGHEST_INDEX(ch) / 2, index_cost,
essence_cost, index_cost, cap_delta);
}
if (!IS_SENATOR(ch)) {
// House ruled section here.
// Magic cap is 26, and is doubly impacted by cyber/bio costs, down to a minimum of 20.
// This allows "pure" characters to have a meaningful power level while still leaving some
// flexibility in builds before hitting the "may as well go full borg" cap of 20.
// You can take up to approximately 3 points of magic loss from 'ware before hitting the minimum 20 cap.
int magic_cap = 2600;
int essence_cost = base_essence - GET_ESS(ch);
int index_cost = GET_HIGHEST_INDEX(ch) / 2;
int cap_delta = 2 * (essence_cost + index_cost);
// Cap must be between 20-26 magic.
magic_cap = MIN(2600, MAX(2000, magic_cap - cap_delta));

// Apply the cap before any temporary magic loss effects. Cap is already x100, just like magic is.
GET_MAG(ch) = MIN(GET_MAG(ch), magic_cap);
GET_MAG(ch) -= MIN(GET_MAG(ch), GET_TEMP_MAGIC_LOSS(ch) * 100);
GET_MAG(ch) = MAX(0, GET_MAG(ch));

#ifdef MAGIC_CAP_DEBUG
if (!IS_NPC(ch) && PRF_FLAGGED(ch, PRF_ROLLS)) {
send_to_char(ch, "^L-- Magic cap debug: m_c %d (from 2600 - (e_c(%d-%d=%d), i_c(%d/2=%d), c_d(2*(%d+%d)=%d); mag now %d (temp loss %d). Tog rolls to disable^n\r\n",
magic_cap,
base_essence, GET_ESS(ch), essence_cost,
GET_HIGHEST_INDEX(ch) / 2, index_cost,
essence_cost, index_cost, cap_delta, GET_MAG(ch), GET_TEMP_MAGIC_LOSS(ch));
}
#endif

// Apply the cap before any temporary magic loss effects. Cap is already x100, just like magic is.
GET_MAG(ch) = MAX(0, MIN(GET_MAG(ch), magic_cap));
GET_MAG(ch) -= MIN(GET_MAG(ch), GET_TEMP_MAGIC_LOSS(ch) * 100);
} else {
GET_MAG(ch) = MAX(0, MIN(GET_MAG(ch), cap * 100));
GET_MAG(ch) -= MIN(GET_MAG(ch), GET_TEMP_MAGIC_LOSS(ch) * 100);
}
}
#endif
GET_MAX_MENTAL(ch) = 1000;
Expand Down Expand Up @@ -978,6 +984,8 @@ void affect_total(struct char_data * ch)
GET_REA(ch) /= 2;
}

// asdf something is wrong - combatsense spell dice?

// Combat pool is derived from current atts, so we calculate it after all att modifiers
GET_COMBAT(ch) += (GET_QUI(ch) + GET_WIL(ch) + GET_INT(ch)) / 2;
if (GET_TOTALBAL(ch) > GET_QUI(ch))
Expand Down
5 changes: 4 additions & 1 deletion src/medit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1416,8 +1416,11 @@ void medit_parse(struct descriptor_data *d, const char *arg)
if ((number < 0) || (number > NUM_RACES) || number == RACE_PC_CONJURED_ELEMENTAL)
medit_disp_class_menu(d);
else {
if (number != 0)
if (number != 0) {
GET_RACE(MOB) = number;
GET_ESS(MOB) = GET_RACIAL_STARTING_ESSENCE_FOR_RACE(GET_RACE(MOB));
MOB->real_abils.ess = GET_RACIAL_STARTING_ESSENCE_FOR_RACE(GET_RACE(MOB));
}
medit_disp_menu(d);
}
break;
Expand Down
12 changes: 6 additions & 6 deletions src/newdb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -462,11 +462,11 @@ bool load_char(const char *name, char_data *ch, bool logon)
if (GET_LEVEL(ch) <= 1) {
for (int i = 0; i <= WIL; i++) {
bool exceeding_limits = FALSE;
if (i == BOD && (GET_REAL_BOD(ch)) > racial_limits[(int)GET_RACE(ch)][0][i]) {
if (i == BOD && (GET_REAL_BOD(ch)) > racial_limits[(int)GET_RACE(ch)][RACIAL_LIMITS_NORMAL][i]) {
exceeding_limits = TRUE;
}

else if (GET_REAL_ATT(ch, i) > racial_limits[(int)GET_RACE(ch)][0][i]) {
else if (GET_REAL_ATT(ch, i) > racial_limits[(int)GET_RACE(ch)][RACIAL_LIMITS_NORMAL][i]) {
exceeding_limits = TRUE;
}

Expand All @@ -475,10 +475,10 @@ bool load_char(const char *name, char_data *ch, bool logon)
GET_CHAR_NAME(ch),
attributes[i],
GET_REAL_ATT(ch, i),
racial_limits[(int)GET_RACE(ch)][0][i]);
racial_limits[(int)GET_RACE(ch)][RACIAL_LIMITS_NORMAL][i]);
mudlog(buf, ch, LOG_SYSLOG, TRUE);

GET_REAL_ATT(ch, i) = racial_limits[(int)GET_RACE(ch)][0][i];
GET_REAL_ATT(ch, i) = racial_limits[(int)GET_RACE(ch)][RACIAL_LIMITS_NORMAL][i];
}
}
}
Expand Down Expand Up @@ -2768,8 +2768,8 @@ void fix_character_essence_after_cybereye_migration(struct char_data *ch) {

// If there's a remainder after essence hole, ensure it won't kill them or wipe their magic.
if (total_essence_delta > 0) {
if (GET_REAL_ESS(ch) + total_essence_delta > 600) {
snprintf(buf, sizeof(buf), "%s refusing to perform cybereye rectification: it would put me above 6 essence!", capitalize(GET_CHAR_NAME(ch)));
if (GET_REAL_ESS(ch) + total_essence_delta > GET_RACIAL_STARTING_ESSENCE_FOR_RACE(GET_RACE(ch))) {
snprintf(buf, sizeof(buf), "%s refusing to perform cybereye rectification: it would put me above %d essence!", capitalize(GET_CHAR_NAME(ch)), (int) (GET_RACIAL_STARTING_ESSENCE_FOR_RACE(GET_RACE(ch)) / 100));
mudlog(buf, ch, LOG_SYSLOG, TRUE);
return;
}
Expand Down
Loading

0 comments on commit ed04590

Please sign in to comment.