Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix reaction/initiative aug/magic compatibility #714

Merged
merged 8 commits into from
Oct 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 7 additions & 22 deletions .github/workflows/c-cpp.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,13 @@ jobs:
steps:
- uses: actions/checkout@v3

# Update apt cache.
- name: Update apt cache.
run: sudo apt update

# Install dependencies.
- name: Install Boost filesystem and libcurl4
run: sudo apt install libboost-filesystem-dev libcurl4-openssl-dev
run: sudo apt install -y libboost-filesystem-dev libcurl4-openssl-dev

# Populate our config file with dummy values.
- name: Write mysql_config.cpp
Expand All @@ -27,27 +31,8 @@ jobs:
const char *mysql_user = "user"; \
const char *mysql_db = "db"; ' \
> mysql_config.cpp

# Restore our built artifact cache, if any available.
- name: Restore cached artifacts
id: cache-artifact-restore
uses: actions/cache/restore@v3
with:
path: |
src/*.d
src/*.o
key: cache-key-${{ github.event.number }}


# Compile the game.
- name: make
working-directory: ./src
run: make

# Save any compiled dependencies for next time.
- name: Save cached artifacts
id: cache-artifact-save
uses: actions/cache/save@v3
with:
path: |
src/*.d
src/*.o
key: ${{ steps.cache-artifact-restore.outputs.cache-primary-key }}
16 changes: 1 addition & 15 deletions src/fight.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5599,21 +5599,7 @@ void roll_individual_initiative(struct char_data *ch)
{
if (AWAKE(ch))
{
// While rigging, riggers receive only the modifications given them by the vehicle control rig (see Vehicles and Drones, p. 130) they are using.
if (IS_RIGGING(ch)) {
// Note: Dice don't explode in initiative rolls. This is your base value.
GET_INIT_ROLL(ch) = GET_REAL_REA(ch) + dice(1, 6);

for (struct obj_data *rig = ch->cyberware; rig; rig = rig->next_content) {
if (GET_CYBERWARE_TYPE(rig) == CYB_VCR) {
// Each level adds +2 to the user’s Reaction and +1D6 Initiative dice while rigging. (SR3 p301)
GET_INIT_ROLL(ch) += (GET_CYBERWARE_RATING(rig) * 2) + dice(GET_CYBERWARE_RATING(rig), 6);
break;
}
}
}
else
GET_INIT_ROLL(ch) = roll_default_initiative(ch);
GET_INIT_ROLL(ch) = roll_default_initiative(ch);
GET_INIT_ROLL(ch) -= damage_modifier(ch, buf, sizeof(buf));
if (AFF_FLAGGED(ch, AFF_ACTION)) {
GET_INIT_ROLL(ch) -= 10;
Expand Down
100 changes: 74 additions & 26 deletions src/handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -765,6 +765,7 @@ void affect_total(struct char_data * ch)
GET_INIT_DICE(ch) += has_wired;
GET_REA(ch) += has_wired * 2;
}

/* effects of bioware */
for (cyber = ch->bioware; cyber; cyber = cyber->next_content)
{
Expand All @@ -777,10 +778,6 @@ void affect_total(struct char_data * ch)
cyber->obj_flags.bitvector, TRUE);
}

for (sust = GET_SUSTAINED(ch); sust; sust = sust->next)
if (!sust->caster)
spell_modify(ch, sust, TRUE);

for (struct obj_data *bio = ch->bioware; bio; bio = bio->next_content) {
switch (GET_BIOWARE_TYPE(bio)) {
case BIO_PAINEDITOR:
Expand All @@ -796,12 +793,21 @@ void affect_total(struct char_data * ch)
}
}

// We want the higher of either cyber+bio or magic/adept
int aug_rea = GET_REA(ch);
int aug_init_dice = GET_INIT_DICE(ch);
GET_REA(ch) = 0;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be GET_REA(ch) = GET_REAL_REA(ch)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The quickness and intelligence contributions to reaction get added in at the very end of all the attribute stuff, so that drugs, capping, and nerve strike modifiers all apply.

There's a question as to how GET_REAL_REA should be calculated though... SR3 rules consider cerebral boosters, muscle toner, and adept improved ability to be natural in most cases.... but not always, since toners (and probably also adept improved qui) don't apply to reaction when rigging.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have a strong opinion on that question myself, so if you're confident in this code as it stands I'm happy to merge it for testing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe leave GET_REAL_REA alone for informational purposes, and then if we're decking or rigging, let's update GET_REA (and GET_INIT_DICE) to the appropriate values.

GET_INIT_DICE(ch) = 0;

/* effects of magic */
for (sust = GET_SUSTAINED(ch); sust; sust = sust->next)
if (!sust->caster)
spell_modify(ch, sust, TRUE);

if (GET_TRADITION(ch) == TRAD_ADEPT)
{
if (GET_INIT_DICE(ch) == 0)
GET_INIT_DICE(ch) += MIN(3, GET_POWER(ch, ADEPT_REFLEXES));
if (GET_REAL_REA(ch) == GET_REA(ch))
GET_REA(ch) += 2*MIN(3, GET_POWER(ch, ADEPT_REFLEXES));
GET_INIT_DICE(ch) += MIN(3, GET_POWER(ch, ADEPT_REFLEXES));
GET_REA(ch) += 2*MIN(3, GET_POWER(ch, ADEPT_REFLEXES));
GET_BOD(ch) += GET_POWER(ch, ADEPT_IMPROVED_BOD);
GET_QUI(ch) += GET_POWER(ch, ADEPT_IMPROVED_QUI);
GET_STR(ch) += GET_POWER(ch, ADEPT_IMPROVED_STR);
Expand All @@ -823,8 +829,24 @@ void affect_total(struct char_data * ch)
}
}

// We want the higher of either cyber+bio or magic/adept
GET_REA(ch) = (GET_REA(ch) > aug_rea) ? GET_REA(ch) : aug_rea;
GET_INIT_DICE(ch) = (GET_INIT_DICE(ch) > aug_init_dice) ? GET_INIT_DICE(ch) : aug_init_dice;

// Except for VCRs, reaction/initiative augmentations don't apply to rigging (R3 pg 27)
int rigger_rea = 0, rigger_init_dice = 0;

// Let drug rea/init mods apply to rigging
// Unclear in SR3 canon, but is consistent with genre fiction
// Subtract current values, then add post-drug values
rigger_rea -= GET_REA(ch);
rigger_init_dice -= GET_INIT_DICE(ch);

apply_drug_modifiers_to_ch(ch);

rigger_rea += GET_REA(ch);
rigger_init_dice += GET_INIT_DICE(ch);

// Min attribute is one, max is soft capped
int cap = ((ch_is_npc || (GET_LEVEL(ch) >= LVL_ADMIN)) ? 50 : 20);
for (int att = BOD; att <= WIL; att++) {
Expand All @@ -851,6 +873,50 @@ void affect_total(struct char_data * ch)
// We don't cap reaction because qui and int are already capped
GET_REA(ch) += (GET_INT(ch) + GET_QUI(ch)) >> 1;

// When rigging, qui mods don't contribute (R3 pg 27)
rigger_rea += (GET_INT(ch) + GET_REAL_QUI(ch)) >> 1;

// Qui bonus from mbw doesn't increase reaction (MM pg 30)
// Also makes sense that mbw DOES protect from disabling via nervestrike
if (has_mbw) {
GET_QUI(ch) += has_mbw;
GET_REA(ch) += has_mbw * 2;
GET_INIT_DICE(ch) += has_mbw;
}

// Matrix pg 18 & 24, assume pure DNI (thus reaction = intelligence)
// No direct reaction/initiative bonuses from cyber/bio apply (assume no bonuses from magic/adept either)
if (PLR_FLAGGED(ch, PLR_MATRIX)) {
GET_REA(ch) = GET_INT(ch);
GET_INIT_DICE(ch) = 0;
}

// Rigging
if (has_rig) {
// a VCR adds to reaction, thus control pool
rigger_rea += 2 * has_rig;
GET_CONTROL(ch) += rigger_rea;

// also adds to initiative dice
rigger_init_dice += has_rig;

// but reduces hacking pool
GET_HACKING(ch) -= has_rig;
if (GET_HACKING(ch) < 0)
GET_HACKING(ch) = 0;
} else {
// direct control with a datajack and no VCR (SR3 pg 140)
rigger_rea += 1;
}

if (AFF_FLAGGED(ch, AFF_RIG) || PLR_FLAGGED(ch, PLR_REMOTE)) {
GET_REA(ch) = rigger_rea;
GET_INIT_DICE(ch) = rigger_init_dice;
}

// Cap init dice
GET_INIT_DICE(ch) = MAX(0, MIN(GET_INIT_DICE(ch), 5));

// 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 Expand Up @@ -967,28 +1033,10 @@ void affect_total(struct char_data * ch)
}
}

if (has_rig)
{
int reaction = GET_REAL_INT(ch) + GET_REAL_QUI(ch);
for (struct obj_data *bio = ch->bioware; bio; bio = bio->next_content)
if (GET_OBJ_VAL(bio, 0) == BIO_CEREBRALBOOSTER)
reaction += GET_OBJ_VAL(bio, 1);
GET_CONTROL(ch) += (reaction / 2) + (int)(2 * has_rig);
GET_HACKING(ch) -= has_rig;
if (GET_HACKING(ch) < 0)
GET_HACKING(ch) = 0;
}

// Restore their max_hacking and rem_hacking, which were wiped out in the earlier aff_abils = real_abils.
GET_REM_HACKING(ch) = MIN(old_rem_hacking, GET_HACKING(ch));
GET_MAX_HACKING(ch) = MIN(old_max_hacking, GET_HACKING(ch));

if (has_mbw) {
GET_QUI(ch) += has_mbw;
GET_REA(ch) += has_mbw * 2;
GET_INIT_DICE(ch) += has_mbw;
}

// Update current vision to match what's being worn.
if (AFF_FLAGGED(ch, AFF_INFRAVISION)) {
set_vision_bit(ch, VISION_THERMOGRAPHIC, VISION_BIT_FROM_EQUIPMENT);
Expand Down
11 changes: 6 additions & 5 deletions src/newmatrix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,19 +197,20 @@ bool spawn_ic(struct matrix_icon *target, vnum_t ic_vnum, int triggerstep) {

void roll_matrix_init(struct matrix_icon *icon)
{
int x = 1;
int init_dice = 1;
if (icon->decker && icon->decker->ch)
{
icon->initiative = GET_REAL_REA(icon->decker->ch) + (icon->decker->response * 2) + (icon->decker->reality ? 2 : 0);
x += icon->decker->response + (icon->decker->reality ? 1 : 0);
// Matrix pg 18 & 24, available bonuses are response increase, reality filter, and hot asist
icon->initiative = GET_REA(icon->decker->ch) + (icon->decker->response * 2) + (icon->decker->reality ? 2 : 0) + (icon->decker->asist[0] ? 2 : 0);
init_dice += GET_INIT_DICE(icon->decker->ch) + icon->decker->response + (icon->decker->reality ? 1 : 0) + (icon->decker->asist[0] ? 1 : 0);
} else
{
icon->initiative = icon->ic.rating;
if (matrix[icon->in_host].shutdown)
icon->initiative--;
x += matrix[icon->in_host].color;
init_dice += matrix[icon->in_host].color;
}
icon->initiative += dice(x, 6);
icon->initiative += dice(init_dice, 6);
icon->initiative -= matrix[icon->in_host].pass * 10;
}

Expand Down