diff --git a/src/combat.cc b/src/combat.cc index f7aafaf..cde7b7d 100644 --- a/src/combat.cc +++ b/src/combat.cc @@ -168,7 +168,7 @@ static bool _combat_call_display = false; // Accuracy modifiers for hit locations. // // 0x510954 -static const int _hit_location_penalty[HIT_LOCATION_COUNT] = { +static int hit_location_penalty_default[HIT_LOCATION_COUNT] = { -40, -30, -30, @@ -180,6 +180,8 @@ static const int _hit_location_penalty[HIT_LOCATION_COUNT] = { 0, }; +static int hit_location_penalty[HIT_LOCATION_COUNT]; + // Critical hit tables for every kill type. // // 0x510978 @@ -2029,6 +2031,7 @@ int combatInit() burstModInit(); unarmedInit(); damageModInit(); + combat_reset_hit_location_penalty(); return 0; } @@ -2058,6 +2061,7 @@ void combatReset() // SFALL criticalsReset(); + combat_reset_hit_location_penalty(); } // 0x420E14 @@ -3831,7 +3835,7 @@ static int attackCompute(Attack* attack) roll = _compute_spray(attack, accuracy, &ammoQuantity, &v26, anim); } else { int chance = critterGetStat(attack->attacker, STAT_CRITICAL_CHANCE); - roll = randomRoll(accuracy, chance - _hit_location_penalty[attack->defenderHitLocation], NULL); + roll = randomRoll(accuracy, chance - hit_location_penalty[attack->defenderHitLocation], NULL); } if (roll == ROLL_FAILURE) { @@ -4417,9 +4421,9 @@ static int attackDetermineToHit(Object* attacker, int tile, Object* defender, in } if (isRangedWeapon) { - accuracy += _hit_location_penalty[hitLocation]; + accuracy += hit_location_penalty[hitLocation]; } else { - accuracy += _hit_location_penalty[hitLocation] / 2; + accuracy += hit_location_penalty[hitLocation] / 2; } if (defender != NULL && (defender->flags & OBJECT_MULTIHEX) != 0) { @@ -6798,4 +6802,27 @@ static void damageModCalculateYaam(DamageCalculationContext* context) } } +int combat_get_hit_location_penalty(int hit_location) +{ + if (hit_location >= 0 && hit_location < HIT_LOCATION_COUNT) { + return hit_location_penalty[hit_location]; + } else { + return 0; + } +} + +void combat_set_hit_location_penalty(int hit_location, int penalty) +{ + if (hit_location >= 0 && hit_location < HIT_LOCATION_COUNT) { + hit_location_penalty[hit_location] = penalty; + } +} + +void combat_reset_hit_location_penalty() +{ + for (int hit_location = 0; hit_location < HIT_LOCATION_COUNT; hit_location++) { + hit_location_penalty[hit_location] = hit_location_penalty_default[hit_location]; + } +} + } // namespace fallout diff --git a/src/combat.h b/src/combat.h index 5775eae..4dc0430 100644 --- a/src/combat.h +++ b/src/combat.h @@ -71,6 +71,9 @@ int unarmedGetKickHitMode(bool isSecondary); bool unarmedIsPenetrating(int hitMode); bool damageModGetBonusHthDamageFix(); bool damageModGetDisplayBonusDamage(); +int combat_get_hit_location_penalty(int hit_location); +void combat_set_hit_location_penalty(int hit_location, int penalty); +void combat_reset_hit_location_penalty(); static inline bool isInCombat() { diff --git a/src/sfall_opcodes.cc b/src/sfall_opcodes.cc index 82807c7..db28fb5 100644 --- a/src/sfall_opcodes.cc +++ b/src/sfall_opcodes.cc @@ -144,6 +144,21 @@ static void op_set_car_current_town(Program* program) wmCarSetCurrentArea(area); } +// get_bodypart_hit_modifier +static void op_get_bodypart_hit_modifier(Program* program) +{ + int hit_location = programStackPopInteger(program); + programStackPushInteger(program, combat_get_hit_location_penalty(hit_location)); +} + +// set_bodypart_hit_modifier +static void op_set_bodypart_hit_modifier(Program* program) +{ + int penalty = programStackPopInteger(program); + int hit_location = programStackPopInteger(program); + combat_set_hit_location_penalty(hit_location, penalty); +} + // get_proto_data static void op_get_proto_data(Program* program) { @@ -413,6 +428,8 @@ void sfallOpcodesInit() interpreterRegisterOpcode(0x819E, opGetGlobalInt); interpreterRegisterOpcode(0x81AF, opGetGameMode); interpreterRegisterOpcode(0x81B6, op_set_car_current_town); + interpreterRegisterOpcode(0x81DF, op_get_bodypart_hit_modifier); + interpreterRegisterOpcode(0x81E0, op_set_bodypart_hit_modifier); interpreterRegisterOpcode(0x8204, op_get_proto_data); interpreterRegisterOpcode(0x8205, op_set_proto_data); interpreterRegisterOpcode(0x820D, opListBegin);