diff --git a/.github/workflows/c-cpp.yml b/.github/workflows/c-cpp.yml index cb26c809e..958b3b4de 100644 --- a/.github/workflows/c-cpp.yml +++ b/.github/workflows/c-cpp.yml @@ -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 @@ -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 }} diff --git a/src/fight.cpp b/src/fight.cpp index f01c6e100..7eaa085e5 100644 --- a/src/fight.cpp +++ b/src/fight.cpp @@ -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; diff --git a/src/handler.cpp b/src/handler.cpp index 34dd2f262..e2563aeb3 100644 --- a/src/handler.cpp +++ b/src/handler.cpp @@ -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) { @@ -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: @@ -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; + 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); @@ -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++) { @@ -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)) @@ -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); diff --git a/src/newmatrix.cpp b/src/newmatrix.cpp index a6b1a09ef..2a4889f50 100644 --- a/src/newmatrix.cpp +++ b/src/newmatrix.cpp @@ -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; }