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.
//
// 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

View File

@ -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()
{

View File

@ -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);