Add combat opcodes

This commit is contained in:
Alexander Batalov 2023-04-19 10:03:04 +03:00
parent ef34fdb519
commit 540cc1e08b
3 changed files with 51 additions and 4 deletions

View File

@ -168,7 +168,7 @@ static bool _combat_call_display = false;
// Accuracy modifiers for hit locations. // Accuracy modifiers for hit locations.
// //
// 0x510954 // 0x510954
static const int _hit_location_penalty[HIT_LOCATION_COUNT] = { static int hit_location_penalty_default[HIT_LOCATION_COUNT] = {
-40, -40,
-30, -30,
-30, -30,
@ -180,6 +180,8 @@ static const int _hit_location_penalty[HIT_LOCATION_COUNT] = {
0, 0,
}; };
static int hit_location_penalty[HIT_LOCATION_COUNT];
// Critical hit tables for every kill type. // Critical hit tables for every kill type.
// //
// 0x510978 // 0x510978
@ -2029,6 +2031,7 @@ int combatInit()
burstModInit(); burstModInit();
unarmedInit(); unarmedInit();
damageModInit(); damageModInit();
combat_reset_hit_location_penalty();
return 0; return 0;
} }
@ -2058,6 +2061,7 @@ void combatReset()
// SFALL // SFALL
criticalsReset(); criticalsReset();
combat_reset_hit_location_penalty();
} }
// 0x420E14 // 0x420E14
@ -3831,7 +3835,7 @@ static int attackCompute(Attack* attack)
roll = _compute_spray(attack, accuracy, &ammoQuantity, &v26, anim); roll = _compute_spray(attack, accuracy, &ammoQuantity, &v26, anim);
} else { } else {
int chance = critterGetStat(attack->attacker, STAT_CRITICAL_CHANCE); 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) { if (roll == ROLL_FAILURE) {
@ -4417,9 +4421,9 @@ static int attackDetermineToHit(Object* attacker, int tile, Object* defender, in
} }
if (isRangedWeapon) { if (isRangedWeapon) {
accuracy += _hit_location_penalty[hitLocation]; accuracy += hit_location_penalty[hitLocation];
} else { } else {
accuracy += _hit_location_penalty[hitLocation] / 2; accuracy += hit_location_penalty[hitLocation] / 2;
} }
if (defender != NULL && (defender->flags & OBJECT_MULTIHEX) != 0) { 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 } // namespace fallout

View File

@ -71,6 +71,9 @@ int unarmedGetKickHitMode(bool isSecondary);
bool unarmedIsPenetrating(int hitMode); bool unarmedIsPenetrating(int hitMode);
bool damageModGetBonusHthDamageFix(); bool damageModGetBonusHthDamageFix();
bool damageModGetDisplayBonusDamage(); 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() static inline bool isInCombat()
{ {

View File

@ -144,6 +144,21 @@ static void op_set_car_current_town(Program* program)
wmCarSetCurrentArea(area); 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 // get_proto_data
static void op_get_proto_data(Program* program) static void op_get_proto_data(Program* program)
{ {
@ -413,6 +428,8 @@ void sfallOpcodesInit()
interpreterRegisterOpcode(0x819E, opGetGlobalInt); interpreterRegisterOpcode(0x819E, opGetGlobalInt);
interpreterRegisterOpcode(0x81AF, opGetGameMode); interpreterRegisterOpcode(0x81AF, opGetGameMode);
interpreterRegisterOpcode(0x81B6, op_set_car_current_town); 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(0x8204, op_get_proto_data);
interpreterRegisterOpcode(0x8205, op_set_proto_data); interpreterRegisterOpcode(0x8205, op_set_proto_data);
interpreterRegisterOpcode(0x820D, opListBegin); interpreterRegisterOpcode(0x820D, opListBegin);