Improve some combat functions readability
This commit is contained in:
parent
cb9c72d1db
commit
3168c2ec09
138
src/combat.cc
138
src/combat.cc
|
@ -85,7 +85,7 @@ typedef struct DamageCalculationContext {
|
|||
int combatDifficultyDamageModifier;
|
||||
} DamageCalculationContext;
|
||||
|
||||
static bool _combat_safety_invalidate_weapon_func(Object* critter, Object* weapon, int hitMode, Object* a4, int* a5, Object* a6);
|
||||
static bool _combat_safety_invalidate_weapon_func(Object* attacker, Object* weapon, int hitMode, Object* defender, int* safeDistancePtr, Object* attackerFriend);
|
||||
static void _combatInitAIInfoList();
|
||||
static int aiInfoCopy(int srcIndex, int destIndex);
|
||||
static int _combatAIInfoSetLastMove(Object* object, int move);
|
||||
|
@ -103,8 +103,8 @@ static void _combat_set_move_all();
|
|||
static int _combat_turn(Object* a1, bool a2);
|
||||
static bool _combat_should_end();
|
||||
static bool _check_ranged_miss(Attack* attack);
|
||||
static int _shoot_along_path(Attack* attack, int a2, int a3, int anim);
|
||||
static int _compute_spray(Attack* attack, int accuracy, int* a3, int* a4, int anim);
|
||||
static int _shoot_along_path(Attack* attack, int endTile, int rounds, int anim);
|
||||
static int _compute_spray(Attack* attack, int accuracy, int* roundsHitMainTargetPtr, int* roundsSpentPtr, int anim);
|
||||
static int attackComputeEnhancedKnockout(Attack* attack);
|
||||
static int attackCompute(Attack* attack);
|
||||
static int attackComputeCriticalHit(Attack* a1);
|
||||
|
@ -2247,39 +2247,39 @@ int combatSave(File* stream)
|
|||
}
|
||||
|
||||
// 0x4213E8
|
||||
bool _combat_safety_invalidate_weapon(Object* a1, Object* a2, int hitMode, Object* a4, int* a5)
|
||||
bool _combat_safety_invalidate_weapon(Object* attacker, Object* weapon, int hitMode, Object* defender, int* safeDistancePtr)
|
||||
{
|
||||
return _combat_safety_invalidate_weapon_func(a1, a2, hitMode, a4, a5, NULL);
|
||||
return _combat_safety_invalidate_weapon_func(attacker, weapon, hitMode, defender, safeDistancePtr, NULL);
|
||||
}
|
||||
|
||||
// 0x4213FC
|
||||
static bool _combat_safety_invalidate_weapon_func(Object* critter, Object* weapon, int hitMode, Object* a4, int* a5, Object* a6)
|
||||
static bool _combat_safety_invalidate_weapon_func(Object* attacker, Object* weapon, int hitMode, Object* defender, int* safeDistancePtr, Object* attackerFriend)
|
||||
{
|
||||
if (a5 != NULL) {
|
||||
*a5 = 0;
|
||||
if (safeDistancePtr != NULL) {
|
||||
*safeDistancePtr = 0;
|
||||
}
|
||||
|
||||
if (critter->pid == PROTO_ID_0x10001E0) {
|
||||
if (attacker->pid == PROTO_ID_0x10001E0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int intelligence = critterGetStat(critter, STAT_INTELLIGENCE);
|
||||
int team = critter->data.critter.combat.team;
|
||||
int v41 = weaponGetDamageRadius(weapon, hitMode);
|
||||
int intelligence = critterGetStat(attacker, STAT_INTELLIGENCE);
|
||||
int team = attacker->data.critter.combat.team;
|
||||
int damageRadius = weaponGetDamageRadius(weapon, hitMode);
|
||||
int maxDamage;
|
||||
weaponGetDamageMinMax(weapon, NULL, &maxDamage);
|
||||
int damageType = weaponGetDamageType(critter, weapon);
|
||||
int damageType = weaponGetDamageType(attacker, weapon);
|
||||
|
||||
if (v41 > 0) {
|
||||
if (damageRadius > 0) {
|
||||
if (intelligence < 5) {
|
||||
v41 -= 5 - intelligence;
|
||||
if (v41 < 0) {
|
||||
v41 = 0;
|
||||
damageRadius -= 5 - intelligence;
|
||||
if (damageRadius < 0) {
|
||||
damageRadius = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (a6 != NULL) {
|
||||
if (objectGetDistanceBetween(a4, a6) < v41) {
|
||||
if (attackerFriend != NULL) {
|
||||
if (objectGetDistanceBetween(defender, attackerFriend) < damageRadius) {
|
||||
debugPrint("Friendly was in the way!");
|
||||
return true;
|
||||
}
|
||||
|
@ -2288,11 +2288,11 @@ static bool _combat_safety_invalidate_weapon_func(Object* critter, Object* weapo
|
|||
for (int index = 0; index < _list_total; index++) {
|
||||
Object* candidate = _combat_list[index];
|
||||
if (candidate->data.critter.combat.team == team
|
||||
&& candidate != critter
|
||||
&& candidate != a4
|
||||
&& candidate != attacker
|
||||
&& candidate != defender
|
||||
&& !critterIsDead(candidate)) {
|
||||
int v14 = objectGetDistanceBetween(a4, candidate);
|
||||
if (v14 < v41 && candidate != candidate->data.critter.combat.whoHitMe) {
|
||||
int v14 = objectGetDistanceBetween(defender, candidate);
|
||||
if (v14 < damageRadius && candidate != candidate->data.critter.combat.whoHitMe) {
|
||||
int damageThreshold = critterGetStat(candidate, STAT_DAMAGE_THRESHOLD + damageType);
|
||||
int damageResistance = critterGetStat(candidate, STAT_DAMAGE_RESISTANCE + damageType);
|
||||
if (damageResistance * (maxDamage - damageThreshold) / 100 > 0) {
|
||||
|
@ -2302,11 +2302,9 @@ static bool _combat_safety_invalidate_weapon_func(Object* critter, Object* weapo
|
|||
}
|
||||
}
|
||||
|
||||
int v17 = objectGetDistanceBetween(a4, critter);
|
||||
if (v17 <= v41) {
|
||||
if (a5 != NULL) {
|
||||
int v18 = objectGetDistanceBetween(a4, critter);
|
||||
*a5 = v41 - v18 + 1;
|
||||
if (objectGetDistanceBetween(defender, attacker) <= damageRadius) {
|
||||
if (safeDistancePtr != NULL) {
|
||||
*safeDistancePtr = damageRadius - objectGetDistanceBetween(defender, attacker) + 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2316,22 +2314,22 @@ static bool _combat_safety_invalidate_weapon_func(Object* critter, Object* weapo
|
|||
return false;
|
||||
}
|
||||
|
||||
int v19 = weaponGetAnimationForHitMode(weapon, hitMode);
|
||||
if (v19 != ANIM_FIRE_BURST && v19 != ANIM_FIRE_CONTINUOUS) {
|
||||
int anim = weaponGetAnimationForHitMode(weapon, hitMode);
|
||||
if (anim != ANIM_FIRE_BURST && anim != ANIM_FIRE_CONTINUOUS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Attack attack;
|
||||
attackInit(&attack, critter, a4, hitMode, HIT_LOCATION_TORSO);
|
||||
attackInit(&attack, attacker, defender, hitMode, HIT_LOCATION_TORSO);
|
||||
|
||||
int accuracy = attackDetermineToHit(critter, critter->tile, a4, HIT_LOCATION_TORSO, hitMode, true);
|
||||
int v33;
|
||||
int a4a;
|
||||
_compute_spray(&attack, accuracy, &v33, &a4a, v19);
|
||||
int accuracy = attackDetermineToHit(attacker, attacker->tile, defender, HIT_LOCATION_TORSO, hitMode, true);
|
||||
int roundsHitMainTarget;
|
||||
int roundsSpent;
|
||||
_compute_spray(&attack, accuracy, &roundsHitMainTarget, &roundsSpent, anim);
|
||||
|
||||
if (a6 != NULL) {
|
||||
if (attackerFriend != NULL) {
|
||||
for (int index = 0; index < attack.extrasLength; index++) {
|
||||
if (attack.extras[index] == a6) {
|
||||
if (attack.extras[index] == attackerFriend) {
|
||||
debugPrint("Friendly was in the way!");
|
||||
return true;
|
||||
}
|
||||
|
@ -2341,8 +2339,8 @@ static bool _combat_safety_invalidate_weapon_func(Object* critter, Object* weapo
|
|||
for (int index = 0; index < attack.extrasLength; index++) {
|
||||
Object* candidate = attack.extras[index];
|
||||
if (candidate->data.critter.combat.team == team
|
||||
&& candidate != critter
|
||||
&& candidate != a4
|
||||
&& candidate != attacker
|
||||
&& candidate != defender
|
||||
&& !critterIsDead(candidate)
|
||||
&& candidate != candidate->data.critter.combat.whoHitMe) {
|
||||
int damageThreshold = critterGetStat(candidate, STAT_DAMAGE_THRESHOLD + damageType);
|
||||
|
@ -2357,9 +2355,9 @@ static bool _combat_safety_invalidate_weapon_func(Object* critter, Object* weapo
|
|||
}
|
||||
|
||||
// 0x4217BC
|
||||
bool _combatTestIncidentalHit(Object* a1, Object* a2, Object* a3, Object* a4)
|
||||
bool _combatTestIncidentalHit(Object* attacker, Object* defender, Object* attackerFriend, Object* weapon)
|
||||
{
|
||||
return _combat_safety_invalidate_weapon_func(a1, a4, HIT_MODE_RIGHT_WEAPON_PRIMARY, a2, NULL, a3);
|
||||
return _combat_safety_invalidate_weapon_func(attacker, weapon, HIT_MODE_RIGHT_WEAPON_PRIMARY, defender, NULL, attackerFriend);
|
||||
}
|
||||
|
||||
// 0x4217D4
|
||||
|
@ -3604,39 +3602,39 @@ static bool _check_ranged_miss(Attack* attack)
|
|||
}
|
||||
|
||||
// 0x423284
|
||||
static int _shoot_along_path(Attack* attack, int a2, int a3, int anim)
|
||||
static int _shoot_along_path(Attack* attack, int endTile, int rounds, int anim)
|
||||
{
|
||||
int v5 = a3;
|
||||
int v17 = 0;
|
||||
int v7 = attack->attacker->tile;
|
||||
int remainingRounds = rounds;
|
||||
int roundsHitMainTarget = 0;
|
||||
int currentTile = attack->attacker->tile;
|
||||
|
||||
Object* critter = attack->attacker;
|
||||
while (critter != NULL) {
|
||||
if ((v5 <= 0 && anim != ANIM_FIRE_CONTINUOUS) || v7 == a2 || attack->extrasLength >= 6) {
|
||||
if ((remainingRounds <= 0 && anim != ANIM_FIRE_CONTINUOUS) || currentTile == endTile || attack->extrasLength >= 6) {
|
||||
break;
|
||||
}
|
||||
|
||||
_make_straight_path_func(attack->attacker, v7, a2, NULL, &critter, 32, _obj_shoot_blocking_at);
|
||||
_make_straight_path_func(attack->attacker, currentTile, endTile, NULL, &critter, 32, _obj_shoot_blocking_at);
|
||||
|
||||
if (critter != NULL) {
|
||||
if (FID_TYPE(critter->fid) != OBJ_TYPE_CRITTER) {
|
||||
break;
|
||||
}
|
||||
|
||||
int v8 = attackDetermineToHit(attack->attacker, attack->attacker->tile, critter, HIT_LOCATION_TORSO, attack->hitMode, true);
|
||||
int accuracy = attackDetermineToHit(attack->attacker, attack->attacker->tile, critter, HIT_LOCATION_TORSO, attack->hitMode, true);
|
||||
if (anim == ANIM_FIRE_CONTINUOUS) {
|
||||
v5 = 1;
|
||||
remainingRounds = 1;
|
||||
}
|
||||
|
||||
int a2a = 0;
|
||||
while (randomBetween(1, 100) <= v8 && v5 > 0) {
|
||||
v5 -= 1;
|
||||
a2a += 1;
|
||||
int roundsHit = 0;
|
||||
while (randomBetween(1, 100) <= accuracy && remainingRounds > 0) {
|
||||
remainingRounds -= 1;
|
||||
roundsHit += 1;
|
||||
}
|
||||
|
||||
if (a2a != 0) {
|
||||
if (roundsHit != 0) {
|
||||
if (critter == attack->defender) {
|
||||
v17 += a2a;
|
||||
roundsHitMainTarget += roundsHit;
|
||||
} else {
|
||||
int index;
|
||||
for (index = 0; index < attack->extrasLength; index += 1) {
|
||||
|
@ -3649,7 +3647,7 @@ static int _shoot_along_path(Attack* attack, int a2, int a3, int anim)
|
|||
attack->extras[index] = critter;
|
||||
attackInit(&_shoot_ctd, attack->attacker, critter, attack->hitMode, HIT_LOCATION_TORSO);
|
||||
_shoot_ctd.attackerFlags |= DAM_HIT;
|
||||
attackComputeDamage(&_shoot_ctd, a2a, 2);
|
||||
attackComputeDamage(&_shoot_ctd, roundsHit, 2);
|
||||
|
||||
if (index == attack->extrasLength) {
|
||||
attack->extrasDamage[index] = _shoot_ctd.defenderDamage;
|
||||
|
@ -3666,21 +3664,21 @@ static int _shoot_along_path(Attack* attack, int a2, int a3, int anim)
|
|||
}
|
||||
}
|
||||
|
||||
v7 = critter->tile;
|
||||
currentTile = critter->tile;
|
||||
}
|
||||
}
|
||||
|
||||
if (anim == ANIM_FIRE_CONTINUOUS) {
|
||||
v17 = 0;
|
||||
roundsHitMainTarget = 0;
|
||||
}
|
||||
|
||||
return v17;
|
||||
return roundsHitMainTarget;
|
||||
}
|
||||
|
||||
// 0x423488
|
||||
static int _compute_spray(Attack* attack, int accuracy, int* a3, int* a4, int anim)
|
||||
static int _compute_spray(Attack* attack, int accuracy, int* roundsHitMainTargetPtr, int* roundsSpentPtr, int anim)
|
||||
{
|
||||
*a3 = 0;
|
||||
*roundsHitMainTargetPtr = 0;
|
||||
|
||||
int ammoQuantity = ammoGetQuantity(attack->weapon);
|
||||
int burstRounds = weaponGetBurstRounds(attack->weapon);
|
||||
|
@ -3688,7 +3686,7 @@ static int _compute_spray(Attack* attack, int accuracy, int* a3, int* a4, int an
|
|||
ammoQuantity = burstRounds;
|
||||
}
|
||||
|
||||
*a4 = ammoQuantity;
|
||||
*roundsSpentPtr = ammoQuantity;
|
||||
|
||||
int criticalChance = critterGetStat(attack->attacker, STAT_CRITICAL_CHANCE);
|
||||
int roll = randomRoll(accuracy, criticalChance, NULL);
|
||||
|
@ -3732,17 +3730,17 @@ static int _compute_spray(Attack* attack, int accuracy, int* a3, int* a4, int an
|
|||
|
||||
for (int index = 0; index < mainTargetRounds; index += 1) {
|
||||
if (randomRoll(accuracy, 0, NULL) >= ROLL_SUCCESS) {
|
||||
*a3 += 1;
|
||||
*roundsHitMainTargetPtr += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (*a3 == 0 && _check_ranged_miss(attack)) {
|
||||
*a3 = 1;
|
||||
if (*roundsHitMainTargetPtr == 0 && _check_ranged_miss(attack)) {
|
||||
*roundsHitMainTargetPtr = 1;
|
||||
}
|
||||
|
||||
int range = weaponGetRange(attack->attacker, attack->hitMode);
|
||||
int mainTargetEndTile = _tile_num_beyond(attack->attacker->tile, attack->defender->tile, range);
|
||||
*a3 += _shoot_along_path(attack, mainTargetEndTile, centerRounds - *a3, anim);
|
||||
*roundsHitMainTargetPtr += _shoot_along_path(attack, mainTargetEndTile, centerRounds - *roundsHitMainTargetPtr, anim);
|
||||
|
||||
int centerTile;
|
||||
if (objectGetDistanceBetween(attack->attacker, attack->defender) <= 3) {
|
||||
|
@ -3755,14 +3753,14 @@ static int _compute_spray(Attack* attack, int accuracy, int* a3, int* a4, int an
|
|||
|
||||
int leftTile = tileGetTileInDirection(centerTile, (rotation + 1) % ROTATION_COUNT, 1);
|
||||
int leftEndTile = _tile_num_beyond(attack->attacker->tile, leftTile, range);
|
||||
*a3 += _shoot_along_path(attack, leftEndTile, leftRounds, anim);
|
||||
*roundsHitMainTargetPtr += _shoot_along_path(attack, leftEndTile, leftRounds, anim);
|
||||
|
||||
int rightTile = tileGetTileInDirection(centerTile, (rotation + 5) % ROTATION_COUNT, 1);
|
||||
int rightEndTile = _tile_num_beyond(attack->attacker->tile, rightTile, range);
|
||||
*a3 += _shoot_along_path(attack, rightEndTile, rightRounds, anim);
|
||||
*roundsHitMainTargetPtr += _shoot_along_path(attack, rightEndTile, rightRounds, anim);
|
||||
|
||||
if (roll != ROLL_FAILURE || (*a3 <= 0 && attack->extrasLength <= 0)) {
|
||||
if (roll >= ROLL_SUCCESS && *a3 == 0 && attack->extrasLength == 0) {
|
||||
if (roll != ROLL_FAILURE || (*roundsHitMainTargetPtr <= 0 && attack->extrasLength <= 0)) {
|
||||
if (roll >= ROLL_SUCCESS && *roundsHitMainTargetPtr == 0 && attack->extrasLength == 0) {
|
||||
roll = ROLL_FAILURE;
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -17,8 +17,8 @@ void combatExit();
|
|||
int _find_cid(int a1, int a2, Object** a3, int a4);
|
||||
int combatLoad(File* stream);
|
||||
int combatSave(File* stream);
|
||||
bool _combat_safety_invalidate_weapon(Object* a1, Object* a2, int hitMode, Object* a4, int* a5);
|
||||
bool _combatTestIncidentalHit(Object* a1, Object* a2, Object* a3, Object* a4);
|
||||
bool _combat_safety_invalidate_weapon(Object* attacker, Object* weapon, int hitMode, Object* defender, int* safeDistancePtr);
|
||||
bool _combatTestIncidentalHit(Object* attacker, Object* defender, Object* attackerFriend, Object* weapon);
|
||||
Object* _combat_whose_turn();
|
||||
void _combat_data_init(Object* obj);
|
||||
Object* aiInfoGetFriendlyDead(Object* obj);
|
||||
|
|
|
@ -120,7 +120,7 @@ static int _ai_move_steps_closer(Object* a1, Object* a2, int actionPoints, int a
|
|||
static int _ai_move_closer(Object* a1, Object* a2, int a3);
|
||||
static int _cai_retargetTileFromFriendlyFire(Object* source, Object* target, int* tilePtr);
|
||||
static int _cai_retargetTileFromFriendlyFireSubFunc(AiRetargetData* aiRetargetData, int tile);
|
||||
static bool _cai_attackWouldIntersect(Object* a1, Object* a2, Object* a3, int tile, int* distance);
|
||||
static bool _cai_attackWouldIntersect(Object* attacker, Object* defender, Object* attackerFriend, int tile, int* distance);
|
||||
static int _ai_switch_weapons(Object* a1, int* hitMode, Object** weapon, Object* a4);
|
||||
static int _ai_called_shot(Object* a1, Object* a2, int a3);
|
||||
static int _ai_attack(Object* a1, Object* a2, int a3);
|
||||
|
@ -2421,27 +2421,27 @@ static int _cai_retargetTileFromFriendlyFireSubFunc(AiRetargetData* aiRetargetDa
|
|||
}
|
||||
|
||||
// 0x42A518
|
||||
static bool _cai_attackWouldIntersect(Object* a1, Object* a2, Object* a3, int tile, int* distance)
|
||||
static bool _cai_attackWouldIntersect(Object* attacker, Object* defender, Object* attackerFriend, int tile, int* distance)
|
||||
{
|
||||
int hitMode = HIT_MODE_RIGHT_WEAPON_PRIMARY;
|
||||
bool aiming = false;
|
||||
if (a1 == gDude) {
|
||||
if (attacker == gDude) {
|
||||
interfaceGetCurrentHitMode(&hitMode, &aiming);
|
||||
}
|
||||
|
||||
Object* v8 = critterGetWeaponForHitMode(a1, hitMode);
|
||||
if (v8 == NULL) {
|
||||
Object* weapon = critterGetWeaponForHitMode(attacker, hitMode);
|
||||
if (weapon == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (weaponGetRange(a1, hitMode) < 1) {
|
||||
if (weaponGetRange(attacker, hitMode) < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Object* object = NULL;
|
||||
_make_straight_path_func(a1, a1->tile, a2->tile, NULL, &object, 32, _obj_shoot_blocking_at);
|
||||
if (object != a3) {
|
||||
if (!_combatTestIncidentalHit(a1, a2, a3, v8)) {
|
||||
_make_straight_path_func(attacker, attacker->tile, defender->tile, NULL, &object, 32, _obj_shoot_blocking_at);
|
||||
if (object != attackerFriend) {
|
||||
if (!_combatTestIncidentalHit(attacker, defender, attackerFriend, weapon)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue