Improve code readability (#315)

This commit is contained in:
Vlad 2023-07-13 12:35:26 +02:00 committed by GitHub
parent c4c2806071
commit ffe90eef49
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 353 additions and 355 deletions

View File

@ -1711,6 +1711,7 @@ int _make_path(Object* object, int from, int to, unsigned char* rotations, int a
return pathfinderFindPath(object, from, to, rotations, a5, _obj_blocking_at); return pathfinderFindPath(object, from, to, rotations, a5, _obj_blocking_at);
} }
// TODO: move pathfinding into another unit
// 0x415EFC // 0x415EFC
int pathfinderFindPath(Object* object, int from, int to, unsigned char* rotations, int a5, PathBuilderCallback* callback) int pathfinderFindPath(Object* object, int from, int to, unsigned char* rotations, int a5, PathBuilderCallback* callback)
{ {
@ -1939,18 +1940,18 @@ static int _tile_idistance(int tile1, int tile2)
} }
// 0x4163AC // 0x4163AC
int _make_straight_path(Object* a1, int from, int to, StraightPathNode* straightPathNodeList, Object** obstaclePtr, int a6) int _make_straight_path(Object* obj, int from, int to, StraightPathNode* straightPathNodeList, Object** obstaclePtr, int a6)
{ {
return _make_straight_path_func(a1, from, to, straightPathNodeList, obstaclePtr, a6, _obj_blocking_at); return _make_straight_path_func(obj, from, to, straightPathNodeList, obstaclePtr, a6, _obj_blocking_at);
} }
// TODO: Rather complex, but understandable, needs testing. // TODO: Rather complex, but understandable, needs testing.
// //
// 0x4163C8 // 0x4163C8
int _make_straight_path_func(Object* a1, int from, int to, StraightPathNode* straightPathNodeList, Object** obstaclePtr, int a6, PathBuilderCallback* callback) int _make_straight_path_func(Object* obj, int from, int to, StraightPathNode* straightPathNodeList, Object** obstaclePtr, int a6, PathBuilderCallback* callback)
{ {
if (obstaclePtr != NULL) { if (obstaclePtr != NULL) {
Object* obstacle = callback(a1, from, a1->elevation); Object* obstacle = callback(obj, from, obj->elevation);
if (obstacle != NULL) { if (obstacle != NULL) {
if (obstacle != *obstaclePtr && (a6 != 32 || (obstacle->flags & OBJECT_SHOOT_THRU) == 0)) { if (obstacle != *obstaclePtr && (a6 != 32 || (obstacle->flags & OBJECT_SHOOT_THRU) == 0)) {
*obstaclePtr = obstacle; *obstaclePtr = obstacle;
@ -1961,13 +1962,13 @@ int _make_straight_path_func(Object* a1, int from, int to, StraightPathNode* str
int fromX; int fromX;
int fromY; int fromY;
tileToScreenXY(from, &fromX, &fromY, a1->elevation); tileToScreenXY(from, &fromX, &fromY, obj->elevation);
fromX += 16; fromX += 16;
fromY += 8; fromY += 8;
int toX; int toX;
int toY; int toY;
tileToScreenXY(to, &toX, &toY, a1->elevation); tileToScreenXY(to, &toX, &toY, obj->elevation);
toX += 16; toX += 16;
toY += 8; toY += 8;
@ -2005,7 +2006,7 @@ int _make_straight_path_func(Object* a1, int from, int to, StraightPathNode* str
if (ddx <= ddy) { if (ddx <= ddy) {
int middle = ddx - ddy / 2; int middle = ddx - ddy / 2;
while (true) { while (true) {
tile = tileFromScreenXY(tileX, tileY, a1->elevation); tile = tileFromScreenXY(tileX, tileY, obj->elevation);
v22 += 1; v22 += 1;
if (v22 == a6) { if (v22 == a6) {
@ -2016,9 +2017,9 @@ int _make_straight_path_func(Object* a1, int from, int to, StraightPathNode* str
if (straightPathNodeList != NULL) { if (straightPathNodeList != NULL) {
StraightPathNode* pathNode = &(straightPathNodeList[pathNodeIndex]); StraightPathNode* pathNode = &(straightPathNodeList[pathNodeIndex]);
pathNode->tile = tile; pathNode->tile = tile;
pathNode->elevation = a1->elevation; pathNode->elevation = obj->elevation;
tileToScreenXY(tile, &fromX, &fromY, a1->elevation); tileToScreenXY(tile, &fromX, &fromY, obj->elevation);
pathNode->x = tileX - fromX - 16; pathNode->x = tileX - fromX - 16;
pathNode->y = tileY - fromY - 8; pathNode->y = tileY - fromY - 8;
} }
@ -2044,10 +2045,10 @@ int _make_straight_path_func(Object* a1, int from, int to, StraightPathNode* str
if (tile != prevTile) { if (tile != prevTile) {
if (obstaclePtr != NULL) { if (obstaclePtr != NULL) {
Object* obj = callback(a1, tile, a1->elevation); Object* obstacle = callback(obj, tile, obj->elevation);
if (obj != NULL) { if (obstacle != NULL) {
if (obj != *obstaclePtr && (a6 != 32 || (obj->flags & OBJECT_SHOOT_THRU) == 0)) { if (obstacle != *obstaclePtr && (a6 != 32 || (obstacle->flags & OBJECT_SHOOT_THRU) == 0)) {
*obstaclePtr = obj; *obstaclePtr = obstacle;
break; break;
} }
} }
@ -2058,7 +2059,7 @@ int _make_straight_path_func(Object* a1, int from, int to, StraightPathNode* str
} else { } else {
int middle = ddy - ddx / 2; int middle = ddy - ddx / 2;
while (true) { while (true) {
tile = tileFromScreenXY(tileX, tileY, a1->elevation); tile = tileFromScreenXY(tileX, tileY, obj->elevation);
v22 += 1; v22 += 1;
if (v22 == a6) { if (v22 == a6) {
@ -2069,9 +2070,9 @@ int _make_straight_path_func(Object* a1, int from, int to, StraightPathNode* str
if (straightPathNodeList != NULL) { if (straightPathNodeList != NULL) {
StraightPathNode* pathNode = &(straightPathNodeList[pathNodeIndex]); StraightPathNode* pathNode = &(straightPathNodeList[pathNodeIndex]);
pathNode->tile = tile; pathNode->tile = tile;
pathNode->elevation = a1->elevation; pathNode->elevation = obj->elevation;
tileToScreenXY(tile, &fromX, &fromY, a1->elevation); tileToScreenXY(tile, &fromX, &fromY, obj->elevation);
pathNode->x = tileX - fromX - 16; pathNode->x = tileX - fromX - 16;
pathNode->y = tileY - fromY - 8; pathNode->y = tileY - fromY - 8;
} }
@ -2097,10 +2098,10 @@ int _make_straight_path_func(Object* a1, int from, int to, StraightPathNode* str
if (tile != prevTile) { if (tile != prevTile) {
if (obstaclePtr != NULL) { if (obstaclePtr != NULL) {
Object* obj = callback(a1, tile, a1->elevation); Object* obstacle = callback(obj, tile, obj->elevation);
if (obj != NULL) { if (obstacle != NULL) {
if (obj != *obstaclePtr && (a6 != 32 || (obj->flags & OBJECT_SHOOT_THRU) == 0)) { if (obstacle != *obstaclePtr && (a6 != 32 || (obstacle->flags & OBJECT_SHOOT_THRU) == 0)) {
*obstaclePtr = obj; *obstaclePtr = obstacle;
break; break;
} }
} }
@ -2118,9 +2119,9 @@ int _make_straight_path_func(Object* a1, int from, int to, StraightPathNode* str
if (straightPathNodeList != NULL) { if (straightPathNodeList != NULL) {
StraightPathNode* pathNode = &(straightPathNodeList[pathNodeIndex]); StraightPathNode* pathNode = &(straightPathNodeList[pathNodeIndex]);
pathNode->tile = tile; pathNode->tile = tile;
pathNode->elevation = a1->elevation; pathNode->elevation = obj->elevation;
tileToScreenXY(tile, &fromX, &fromY, a1->elevation); tileToScreenXY(tile, &fromX, &fromY, obj->elevation);
pathNode->x = tileX - fromX - 16; pathNode->x = tileX - fromX - 16;
pathNode->y = tileY - fromY - 8; pathNode->y = tileY - fromY - 8;
} }
@ -2128,7 +2129,7 @@ int _make_straight_path_func(Object* a1, int from, int to, StraightPathNode* str
pathNodeIndex += 1; pathNodeIndex += 1;
} else { } else {
if (pathNodeIndex > 0 && straightPathNodeList != NULL) { if (pathNodeIndex > 0 && straightPathNodeList != NULL) {
straightPathNodeList[pathNodeIndex - 1].elevation = a1->elevation; straightPathNodeList[pathNodeIndex - 1].elevation = obj->elevation;
} }
} }

View File

@ -145,8 +145,8 @@ int animationRegisterAnimateForever(Object* owner, int anim, int delay);
int animationRegisterPing(int flags, int delay); int animationRegisterPing(int flags, int delay);
int _make_path(Object* object, int from, int to, unsigned char* a4, int a5); int _make_path(Object* object, int from, int to, unsigned char* a4, int a5);
int pathfinderFindPath(Object* object, int from, int to, unsigned char* rotations, int a5, PathBuilderCallback* callback); int pathfinderFindPath(Object* object, int from, int to, unsigned char* rotations, int a5, PathBuilderCallback* callback);
int _make_straight_path(Object* a1, int from, int to, StraightPathNode* straightPathNodeList, Object** obstaclePtr, int a6); int _make_straight_path(Object* object, int from, int to, StraightPathNode* straightPathNodeList, Object** obstaclePtr, int a6);
int _make_straight_path_func(Object* a1, int from, int to, StraightPathNode* straightPathNodeList, Object** obstaclePtr, int a6, PathBuilderCallback* callback); int _make_straight_path_func(Object* object, int from, int to, StraightPathNode* straightPathNodeList, Object** obstaclePtr, int a6, PathBuilderCallback* callback);
void _object_animate(); void _object_animate();
int _check_move(int* actionPointsPtr); int _check_move(int* actionPointsPtr);
int _dude_move(int actionPoints); int _dude_move(int actionPoints);

View File

@ -116,7 +116,7 @@ static int attackComputeCriticalHit(Attack* a1);
static int _attackFindInvalidFlags(Object* a1, Object* a2); static int _attackFindInvalidFlags(Object* a1, Object* a2);
static int attackComputeCriticalFailure(Attack* attack); static int attackComputeCriticalFailure(Attack* attack);
static void _do_random_cripple(int* flagsPtr); static void _do_random_cripple(int* flagsPtr);
static int attackDetermineToHit(Object* attacker, int tile, Object* defender, int hitLocation, int hitMode, bool a6); static int attackDetermineToHit(Object* attacker, int tile, Object* defender, int hitLocation, int hitMode, bool useDistance);
static void attackComputeDamage(Attack* attack, int ammoQuantity, int a3); static void attackComputeDamage(Attack* attack, int ammoQuantity, int a3);
static void _check_for_death(Object* a1, int a2, int* a3); static void _check_for_death(Object* a1, int a2, int* a3);
static void _set_new_results(Object* a1, int a2); static void _set_new_results(Object* a1, int a2);
@ -3476,16 +3476,16 @@ void attackInit(Attack* attack, Object* attacker, Object* defender, int hitMode,
} }
// 0x422F3C // 0x422F3C
int _combat_attack(Object* a1, Object* a2, int hitMode, int hitLocation) int _combat_attack(Object* attacker, Object* defender, int hitMode, int hitLocation)
{ {
if (a1 != gDude && hitMode == HIT_MODE_PUNCH && randomBetween(1, 4) == 1) { if (attacker != gDude && hitMode == HIT_MODE_PUNCH && randomBetween(1, 4) == 1) {
int fid = buildFid(OBJ_TYPE_CRITTER, a1->fid & 0xFFF, ANIM_KICK_LEG, (a1->fid & 0xF000) >> 12, (a1->fid & 0x70000000) >> 28); int fid = buildFid(OBJ_TYPE_CRITTER, attacker->fid & 0xFFF, ANIM_KICK_LEG, (attacker->fid & 0xF000) >> 12, (attacker->fid & 0x70000000) >> 28);
if (artExists(fid)) { if (artExists(fid)) {
hitMode = HIT_MODE_KICK; hitMode = HIT_MODE_KICK;
} }
} }
attackInit(&_main_ctd, a1, a2, hitMode, hitLocation); attackInit(&_main_ctd, attacker, defender, hitMode, hitLocation);
debugPrint("computing attack...\n"); debugPrint("computing attack...\n");
if (attackCompute(&_main_ctd) == -1) { if (attackCompute(&_main_ctd) == -1) {
@ -3513,7 +3513,7 @@ int _combat_attack(Object* a1, Object* a2, int hitMode, int hitLocation)
bool aiming; bool aiming;
if (_main_ctd.defenderHitLocation == HIT_LOCATION_TORSO || _main_ctd.defenderHitLocation == HIT_LOCATION_UNCALLED) { if (_main_ctd.defenderHitLocation == HIT_LOCATION_TORSO || _main_ctd.defenderHitLocation == HIT_LOCATION_UNCALLED) {
if (a1 == gDude) { if (attacker == gDude) {
interfaceGetCurrentHitMode(&hitMode, &aiming); interfaceGetCurrentHitMode(&hitMode, &aiming);
} else { } else {
aiming = false; aiming = false;
@ -3522,22 +3522,22 @@ int _combat_attack(Object* a1, Object* a2, int hitMode, int hitLocation)
aiming = true; aiming = true;
} }
int actionPoints = weaponGetActionPointCost(a1, _main_ctd.hitMode, aiming); int actionPoints = weaponGetActionPointCost(attacker, _main_ctd.hitMode, aiming);
debugPrint("sequencing attack...\n"); debugPrint("sequencing attack...\n");
if (_action_attack(&_main_ctd) == -1) { if (_action_attack(&_main_ctd) == -1) {
return -1; return -1;
} }
if (actionPoints > a1->data.critter.combat.ap) { if (actionPoints > attacker->data.critter.combat.ap) {
a1->data.critter.combat.ap = 0; attacker->data.critter.combat.ap = 0;
} else { } else {
a1->data.critter.combat.ap -= actionPoints; attacker->data.critter.combat.ap -= actionPoints;
} }
if (a1 == gDude) { if (attacker == gDude) {
interfaceRenderActionPoints(a1->data.critter.combat.ap, _combat_free_move); interfaceRenderActionPoints(attacker->data.critter.combat.ap, _combat_free_move);
_critter_set_who_hit_me(a1, a2); _critter_set_who_hit_me(attacker, defender);
} }
// SFALL // SFALL
@ -3545,19 +3545,19 @@ int _combat_attack(Object* a1, Object* a2, int hitMode, int hitLocation)
_combat_call_display = 1; _combat_call_display = 1;
_combat_cleanup_enabled = 1; _combat_cleanup_enabled = 1;
aiInfoSetLastTarget(a1, a2); aiInfoSetLastTarget(attacker, defender);
debugPrint("running attack...\n"); debugPrint("running attack...\n");
return 0; return 0;
} }
// Returns tile one step closer from [a1] to [a2] // Returns tile one step closer from [attacker] to [target]
// //
// 0x423104 // 0x423104
int _combat_bullet_start(const Object* a1, const Object* a2) int _combat_bullet_start(const Object* attacker, const Object* target)
{ {
int rotation = tileGetRotationTo(a1->tile, a2->tile); int rotation = tileGetRotationTo(attacker->tile, target->tile);
return tileGetTileInDirection(a1->tile, rotation, 1); return tileGetTileInDirection(attacker->tile, rotation, 1);
} }
// 0x423128 // 0x423128
@ -3942,17 +3942,17 @@ static int attackCompute(Attack* attack)
attack->tile = tile; attack->tile = tile;
Object* v25 = attack->defender; Object* accidentalTarget = attack->defender;
_make_straight_path_func(v25, attack->defender->tile, attack->tile, NULL, &v25, 32, _obj_shoot_blocking_at); _make_straight_path_func(accidentalTarget, attack->defender->tile, attack->tile, NULL, &accidentalTarget, 32, _obj_shoot_blocking_at);
if (v25 != NULL && v25 != attack->defender) { if (accidentalTarget != NULL && accidentalTarget != attack->defender) {
attack->tile = v25->tile; attack->tile = accidentalTarget->tile;
} else { } else {
v25 = _obj_blocking_at(NULL, attack->tile, attack->defender->elevation); accidentalTarget = _obj_blocking_at(NULL, attack->tile, attack->defender->elevation);
} }
if (v25 != NULL && (v25->flags & OBJECT_SHOOT_THRU) == 0) { if (accidentalTarget != NULL && (accidentalTarget->flags & OBJECT_SHOOT_THRU) == 0) {
attack->attackerFlags |= DAM_HIT; attack->attackerFlags |= DAM_HIT;
attack->defender = v25; attack->defender = accidentalTarget;
attackComputeDamage(attack, 1, 2); attackComputeDamage(attack, 1, 2);
} }
} }
@ -3974,75 +3974,75 @@ static int attackCompute(Attack* attack)
// compute_explosion_on_extras // compute_explosion_on_extras
// 0x423C10 // 0x423C10
void _compute_explosion_on_extras(Attack* attack, int a2, bool isGrenade, int a4) void _compute_explosion_on_extras(Attack* attack, bool isFromAttacker, bool isGrenade, bool noDamage)
{ {
Object* attacker; Object* targetObj;
if (a2) { if (isFromAttacker) {
attacker = attack->attacker; targetObj = attack->attacker;
} else { } else {
if ((attack->attackerFlags & DAM_HIT) != 0) { if ((attack->attackerFlags & DAM_HIT) != 0) {
attacker = attack->defender; targetObj = attack->defender;
} else { } else {
attacker = NULL; targetObj = NULL;
} }
} }
int tile; int explosionTile;
if (attacker != NULL) { if (targetObj != NULL) {
tile = attacker->tile; explosionTile = targetObj->tile;
} else { } else {
tile = attack->tile; explosionTile = attack->tile;
} }
if (tile == -1) { if (explosionTile == -1) {
debugPrint("\nError: compute_explosion_on_extras: Called with bad target/tileNum"); debugPrint("\nError: compute_explosion_on_extras: Called with bad target/tileNum");
return; return;
} }
// TODO: The math in this loop is rather complex and hard to understand. int ringTileIdx;
int v20; int radius = 0;
int v22 = 0;
int rotation = 0; int rotation = 0;
int v5 = -1; int tile = -1;
int v19 = tile; int ringFirstTile = explosionTile;
// SFALL // SFALL
int maxTargets = explosionGetMaxTargets(); int maxTargets = explosionGetMaxTargets();
// Check adjacent tiles for possible targets, going ring-by-ring
while (attack->extrasLength < maxTargets) { while (attack->extrasLength < maxTargets) {
if (v22 != 0 && (v5 == -1 || (v5 = tileGetTileInDirection(v5, rotation, 1)) != v19)) { if (radius != 0 && (tile == -1 || (tile = tileGetTileInDirection(tile, rotation, 1)) != ringFirstTile)) {
v20++; ringTileIdx++;
if (v20 % v22 == 0) { if (ringTileIdx % radius == 0) { // the larger the radius, the slower we rotate
rotation += 1; rotation += 1;
if (rotation == ROTATION_COUNT) { if (rotation == ROTATION_COUNT) {
rotation = ROTATION_NE; rotation = ROTATION_NE;
} }
} }
} else { } else {
v22++; radius++; // go to the next ring
if (isGrenade && weaponGetGrenadeExplosionRadius(attack->weapon) < v22) { if (isGrenade && weaponGetGrenadeExplosionRadius(attack->weapon) < radius) {
v5 = -1; tile = -1;
} else if (isGrenade || weaponGetRocketExplosionRadius(attack->weapon) >= v22) { } else if (isGrenade || weaponGetRocketExplosionRadius(attack->weapon) >= radius) {
v5 = tileGetTileInDirection(v19, ROTATION_NE, 1); tile = tileGetTileInDirection(ringFirstTile, ROTATION_NE, 1);
} else { } else {
v5 = -1; tile = -1;
} }
v19 = v5; ringFirstTile = tile;
rotation = ROTATION_SE; rotation = ROTATION_SE;
v20 = 0; ringTileIdx = 0;
} }
if (v5 == -1) { if (tile == -1) {
break; break;
} }
Object* obstacle = _obj_blocking_at(attacker, v5, attack->attacker->elevation); Object* obstacle = _obj_blocking_at(targetObj, tile, attack->attacker->elevation);
if (obstacle != NULL if (obstacle != NULL
&& FID_TYPE(obstacle->fid) == OBJ_TYPE_CRITTER && FID_TYPE(obstacle->fid) == OBJ_TYPE_CRITTER
&& (obstacle->data.critter.combat.results & DAM_DEAD) == 0 && (obstacle->data.critter.combat.results & DAM_DEAD) == 0
&& (obstacle->flags & OBJECT_SHOOT_THRU) == 0 && (obstacle->flags & OBJECT_SHOOT_THRU) == 0
&& !_combat_is_shot_blocked(obstacle, obstacle->tile, tile, NULL, NULL)) { && !_combat_is_shot_blocked(obstacle, obstacle->tile, explosionTile, NULL, NULL)) {
if (obstacle == attack->attacker) { if (obstacle == attack->attacker) {
attack->attackerFlags &= ~DAM_HIT; attack->attackerFlags &= ~DAM_HIT;
attackComputeDamage(attack, 1, 2); attackComputeDamage(attack, 1, 2);
@ -4060,7 +4060,7 @@ void _compute_explosion_on_extras(Attack* attack, int a2, bool isGrenade, int a4
attack->extrasHitLocation[index] = HIT_LOCATION_TORSO; attack->extrasHitLocation[index] = HIT_LOCATION_TORSO;
attack->extras[index] = obstacle; attack->extras[index] = obstacle;
attackInit(&_explosion_ctd, attack->attacker, obstacle, attack->hitMode, HIT_LOCATION_TORSO); attackInit(&_explosion_ctd, attack->attacker, obstacle, attack->hitMode, HIT_LOCATION_TORSO);
if (!a4) { if (!noDamage) {
_explosion_ctd.attackerFlags |= DAM_HIT; _explosion_ctd.attackerFlags |= DAM_HIT;
attackComputeDamage(&_explosion_ctd, 1, 2); attackComputeDamage(&_explosion_ctd, 1, 2);
} }
@ -4282,26 +4282,26 @@ static void _do_random_cripple(int* flagsPtr)
} }
// 0x42436C // 0x42436C
int _determine_to_hit(Object* a1, Object* a2, int hitLocation, int hitMode) int _determine_to_hit(Object* attacker, Object* defender, int hitLocation, int hitMode)
{ {
return attackDetermineToHit(a1, a1->tile, a2, hitLocation, hitMode, true); return attackDetermineToHit(attacker, attacker->tile, defender, hitLocation, hitMode, true);
} }
// 0x424380 // 0x424380
int _determine_to_hit_no_range(Object* a1, Object* a2, int hitLocation, int hitMode, unsigned char* a5) int _determine_to_hit_no_range(Object* attacker, Object* defender, int hitLocation, int hitMode, unsigned char* a5)
{ {
return attackDetermineToHit(a1, a1->tile, a2, hitLocation, hitMode, false); return attackDetermineToHit(attacker, attacker->tile, defender, hitLocation, hitMode, false);
} }
// 0x424394 // 0x424394
int _determine_to_hit_from_tile(Object* a1, int tile, Object* a3, int hitLocation, int hitMode) int _determine_to_hit_from_tile(Object* attacker, int tile, Object* defender, int hitLocation, int hitMode)
{ {
return attackDetermineToHit(a1, tile, a3, hitLocation, hitMode, true); return attackDetermineToHit(attacker, tile, defender, hitLocation, hitMode, true);
} }
// determine_to_hit // determine_to_hit
// 0x4243A8 // 0x4243A8
static int attackDetermineToHit(Object* attacker, int tile, Object* defender, int hitLocation, int hitMode, bool a6) static int attackDetermineToHit(Object* attacker, int tile, Object* defender, int hitLocation, int hitMode, bool useDistance)
{ {
Object* weapon = critterGetWeaponForHitMode(attacker, hitMode); Object* weapon = critterGetWeaponForHitMode(attacker, hitMode);
@ -4311,32 +4311,30 @@ static int attackDetermineToHit(Object* attacker, int tile, Object* defender, in
bool isRangedWeapon = false; bool isRangedWeapon = false;
int accuracy; int toHit;
if (weapon == NULL || isUnarmedHitMode(hitMode)) { if (weapon == NULL || isUnarmedHitMode(hitMode)) {
accuracy = skillGetValue(attacker, SKILL_UNARMED); toHit = skillGetValue(attacker, SKILL_UNARMED);
} else { } else {
accuracy = weaponGetSkillValue(attacker, hitMode); toHit = weaponGetSkillValue(attacker, hitMode);
int modifier = 0;
int attackType = weaponGetAttackTypeForHitMode(weapon, hitMode); int attackType = weaponGetAttackTypeForHitMode(weapon, hitMode);
if (attackType == ATTACK_TYPE_RANGED || attackType == ATTACK_TYPE_THROW) { if (attackType == ATTACK_TYPE_RANGED || attackType == ATTACK_TYPE_THROW) {
isRangedWeapon = true; isRangedWeapon = true;
int v29 = 0; int perceptionBonusMult = 0;
int v25 = 0; int minEffectiveDist = 0;
int weaponPerk = weaponGetPerk(weapon); int weaponPerk = weaponGetPerk(weapon);
switch (weaponPerk) { switch (weaponPerk) {
case PERK_WEAPON_LONG_RANGE: case PERK_WEAPON_LONG_RANGE:
v29 = 4; perceptionBonusMult = 4;
break; break;
case PERK_WEAPON_SCOPE_RANGE: case PERK_WEAPON_SCOPE_RANGE:
v29 = 5; perceptionBonusMult = 5;
v25 = 8; minEffectiveDist = 8;
break; break;
default: default:
v29 = 2; perceptionBonusMult = 2;
break; break;
} }
@ -4347,71 +4345,72 @@ static int attackDetermineToHit(Object* attacker, int tile, Object* defender, in
perception += 2 * perkGetRank(gDude, PERK_SHARPSHOOTER); perception += 2 * perkGetRank(gDude, PERK_SHARPSHOOTER);
} }
int distanceMod = 0;
// SFALL: Fix for `determine_to_hit_func` function taking distance // SFALL: Fix for `determine_to_hit_func` function taking distance
// into account when called from `determine_to_hit_no_range`. // into account when called from `determine_to_hit_no_range`.
if (defender != NULL && a6) { if (defender != NULL && useDistance) {
modifier = objectGetDistanceBetweenTiles(attacker, tile, defender, defender->tile); distanceMod = objectGetDistanceBetweenTiles(attacker, tile, defender, defender->tile);
} else { } else {
modifier = 0; distanceMod = 0;
} }
if (modifier >= v25) { if (distanceMod >= minEffectiveDist) {
int penalty = attacker == gDude int perceptionBonus = attacker == gDude
? v29 * (perception - 2) ? perceptionBonusMult * (perception - 2)
: v29 * perception; : perceptionBonusMult * perception;
modifier -= penalty; distanceMod -= perceptionBonus;
} else { } else {
modifier += v25; distanceMod += minEffectiveDist;
} }
if (-2 * perception > modifier) { if (distanceMod < -2 * perception) {
modifier = -2 * perception; distanceMod = -2 * perception;
} }
if (modifier >= 0) { if (distanceMod >= 0) {
if ((attacker->data.critter.combat.results & DAM_BLIND) != 0) { if ((attacker->data.critter.combat.results & DAM_BLIND) != 0) {
modifier *= -12; distanceMod *= -12;
} else { } else {
modifier *= -4; distanceMod *= -4;
} }
} else { } else {
modifier *= -4; distanceMod *= -4;
} }
if (a6 || modifier > 0) { if (useDistance || distanceMod > 0) {
accuracy += modifier; toHit += distanceMod;
} }
modifier = 0; int numCrittersInLof = 0;
if (defender != NULL && a6) { if (defender != NULL && useDistance) {
_combat_is_shot_blocked(attacker, tile, defender->tile, defender, &modifier); _combat_is_shot_blocked(attacker, tile, defender->tile, defender, &numCrittersInLof);
} }
accuracy -= 10 * modifier; toHit -= 10 * numCrittersInLof;
} }
if (attacker == gDude && traitIsSelected(TRAIT_ONE_HANDER)) { if (attacker == gDude && traitIsSelected(TRAIT_ONE_HANDER)) {
if (weaponIsTwoHanded(weapon)) { if (weaponIsTwoHanded(weapon)) {
accuracy -= 40; toHit -= 40;
} else { } else {
accuracy += 20; toHit += 20;
} }
} }
int minStrength = weaponGetMinStrengthRequired(weapon); int minStrength = weaponGetMinStrengthRequired(weapon);
modifier = minStrength - critterGetStat(attacker, STAT_STRENGTH); int minStrengthMod = minStrength - critterGetStat(attacker, STAT_STRENGTH);
if (attacker == gDude && perkGetRank(gDude, PERK_WEAPON_HANDLING) != 0) { if (attacker == gDude && perkGetRank(gDude, PERK_WEAPON_HANDLING) != 0) {
modifier -= 3; minStrengthMod -= 3;
} }
if (modifier > 0) { if (minStrengthMod > 0) {
accuracy -= 20 * modifier; toHit -= 20 * minStrengthMod;
} }
if (weaponGetPerk(weapon) == PERK_WEAPON_ACCURATE) { if (weaponGetPerk(weapon) == PERK_WEAPON_ACCURATE) {
accuracy += 20; toHit += 20;
} }
} }
@ -4422,17 +4421,17 @@ static int attackDetermineToHit(Object* attacker, int tile, Object* defender, in
armorClass = 0; armorClass = 0;
} }
accuracy -= armorClass; toHit -= armorClass;
} }
if (isRangedWeapon) { if (isRangedWeapon) {
accuracy += hit_location_penalty[hitLocation]; toHit += hit_location_penalty[hitLocation];
} else { } else {
accuracy += hit_location_penalty[hitLocation] / 2; toHit += hit_location_penalty[hitLocation] / 2;
} }
if (defender != NULL && (defender->flags & OBJECT_MULTIHEX) != 0) { if (defender != NULL && (defender->flags & OBJECT_MULTIHEX) != 0) {
accuracy += 15; toHit += 15;
} }
if (attacker == gDude) { if (attacker == gDude) {
@ -4447,45 +4446,45 @@ static int attackDetermineToHit(Object* attacker, int tile, Object* defender, in
} }
if (lightIntensity <= 26214) if (lightIntensity <= 26214)
accuracy -= 40; toHit -= 40;
else if (lightIntensity <= 39321) else if (lightIntensity <= 39321)
accuracy -= 25; toHit -= 25;
else if (lightIntensity <= 52428) else if (lightIntensity <= 52428)
accuracy -= 10; toHit -= 10;
} }
if (_gcsd != NULL) { if (_gcsd != NULL) {
accuracy += _gcsd->accuracyBonus; toHit += _gcsd->accuracyBonus;
} }
if ((attacker->data.critter.combat.results & DAM_BLIND) != 0) { if ((attacker->data.critter.combat.results & DAM_BLIND) != 0) {
accuracy -= 25; toHit -= 25;
} }
if (targetIsCritter && defender != NULL && (defender->data.critter.combat.results & (DAM_KNOCKED_OUT | DAM_KNOCKED_DOWN)) != 0) { if (targetIsCritter && defender != NULL && (defender->data.critter.combat.results & (DAM_KNOCKED_OUT | DAM_KNOCKED_DOWN)) != 0) {
accuracy += 40; toHit += 40;
} }
if (attacker->data.critter.combat.team != gDude->data.critter.combat.team) { if (attacker->data.critter.combat.team != gDude->data.critter.combat.team) {
switch (settings.preferences.combat_difficulty) { switch (settings.preferences.combat_difficulty) {
case 0: case 0:
accuracy -= 20; toHit -= 20;
break; break;
case 2: case 2:
accuracy += 20; toHit += 20;
break; break;
} }
} }
if (accuracy > 95) { if (toHit > 95) {
accuracy = 95; toHit = 95;
} }
if (accuracy < -100) { if (toHit < -100) {
debugPrint("Whoa! Bad skill value in determine_to_hit!\n"); debugPrint("Whoa! Bad skill value in determine_to_hit!\n");
} }
return accuracy; return toHit;
} }
// 0x4247B8 // 0x4247B8
@ -5880,39 +5879,35 @@ void _combat_highlight_change()
_combat_highlight = targetHighlight; _combat_highlight = targetHighlight;
} }
// Probably calculates line of sight or determines if object can see other object. // Checks if line of fire to the target object is blocked or not. Optionally calculate number of critters on the line of fire.
// //
// 0x426CC4 // 0x426CC4
bool _combat_is_shot_blocked(Object* a1, int from, int to, Object* a4, int* a5) bool _combat_is_shot_blocked(Object* sourceObj, int from, int to, Object* targetObj, int* numCrittersOnLof)
{ {
if (a5 != NULL) { if (numCrittersOnLof != NULL) {
*a5 = 0; *numCrittersOnLof = 0;
} }
Object* obstacle = a1; Object* obstacle = sourceObj;
int current = from; int current = from;
while (obstacle != NULL && current != to) { while (obstacle != NULL && current != to) {
_make_straight_path_func(a1, current, to, 0, &obstacle, 32, _obj_shoot_blocking_at); _make_straight_path_func(sourceObj, current, to, 0, &obstacle, 32, _obj_shoot_blocking_at);
if (obstacle != NULL) { if (obstacle != NULL) {
if (FID_TYPE(obstacle->fid) != OBJ_TYPE_CRITTER && obstacle != a4) { if (FID_TYPE(obstacle->fid) != OBJ_TYPE_CRITTER && obstacle != targetObj) {
return true; return true;
} }
if (a5 != NULL) { if (numCrittersOnLof != NULL && obstacle != targetObj && targetObj != NULL) {
if (obstacle != a4) { // SFALL: Fix for combat_is_shot_blocked_ engine
if (a4 != NULL) { // function not taking the flags of critters in the
// SFALL: Fix for combat_is_shot_blocked_ engine // line of fire into account when calculating the hit
// function not taking the flags of critters in the // chance penalty of ranged attacks in
// line of fire into account when calculating the hit // determine_to_hit_func_ engine function.
// chance penalty of ranged attacks in if ((obstacle->data.critter.combat.results & (DAM_DEAD | DAM_KNOCKED_DOWN | DAM_KNOCKED_OUT)) == 0) {
// determine_to_hit_func_ engine function. *numCrittersOnLof += 1;
if ((obstacle->data.critter.combat.results & (DAM_DEAD | DAM_KNOCKED_DOWN | DAM_KNOCKED_OUT)) == 0) {
*a5 += 1;
if ((obstacle->flags & OBJECT_MULTIHEX) != 0) { if ((obstacle->flags & OBJECT_MULTIHEX) != 0) {
*a5 += 1; *numCrittersOnLof += 1;
}
}
} }
} }
} }

View File

@ -34,13 +34,13 @@ void _combat_over_from_load();
void _combat_give_exps(int exp_points); void _combat_give_exps(int exp_points);
void _combat_turn_run(); void _combat_turn_run();
void _combat(STRUCT_664980* attack); void _combat(STRUCT_664980* attack);
void attackInit(Attack* attack, Object* a2, Object* a3, int a4, int a5); void attackInit(Attack* attack, Object* attacker, Object* defender, int hitMode, int hitLocation);
int _combat_attack(Object* a1, Object* a2, int a3, int a4); int _combat_attack(Object* attacker, Object* defender, int hitMode, int hitLocation);
int _combat_bullet_start(const Object* a1, const Object* a2); int _combat_bullet_start(const Object* attacker, const Object* target);
void _compute_explosion_on_extras(Attack* attack, int a2, bool isGrenade, int a4); void _compute_explosion_on_extras(Attack* attack, bool isFromAttacker, bool isGrenade, bool noDamage);
int _determine_to_hit(Object* a1, Object* a2, int hitLocation, int hitMode); int _determine_to_hit(Object* a1, Object* a2, int hitLocation, int hitMode);
int _determine_to_hit_no_range(Object* a1, Object* a2, int a3, int a4, unsigned char* a5); int _determine_to_hit_no_range(Object* attacker, Object* defender, int hitLocation, int hitMode, unsigned char* a5);
int _determine_to_hit_from_tile(Object* a1, int a2, Object* a3, int a4, int a5); int _determine_to_hit_from_tile(Object* attacker, int tile, Object* defender, int hitLocation, int hitMode);
void attackComputeDeathFlags(Attack* attack); void attackComputeDeathFlags(Attack* attack);
void _apply_damage(Attack* attack, bool animated); void _apply_damage(Attack* attack, bool animated);
void _combat_display(Attack* attack); void _combat_display(Attack* attack);
@ -52,7 +52,7 @@ void _combat_attack_this(Object* a1);
void _combat_outline_on(); void _combat_outline_on();
void _combat_outline_off(); void _combat_outline_off();
void _combat_highlight_change(); void _combat_highlight_change();
bool _combat_is_shot_blocked(Object* a1, int from, int to, Object* a4, int* a5); bool _combat_is_shot_blocked(Object* sourceObj, int from, int to, Object* targetObj, int* numCrittersOnLof);
int _combat_player_knocked_out_by(); int _combat_player_knocked_out_by();
int _combat_explode_scenery(Object* a1, Object* a2); int _combat_explode_scenery(Object* a1, Object* a2);
void _combat_delete_critter(Object* obj); void _combat_delete_critter(Object* obj);

View File

@ -2327,61 +2327,61 @@ static int _ai_pick_hit_mode(Object* attacker, Object* weapon, Object* defender)
} }
// 0x429FC8 // 0x429FC8
static int _ai_move_steps_closer(Object* a1, Object* a2, int actionPoints, bool taunt) static int _ai_move_steps_closer(Object* critter, Object* target, int actionPoints, bool taunt)
{ {
if (actionPoints <= 0) { if (actionPoints <= 0) {
return -1; return -1;
} }
int distance = aiGetDistance(a1); int distance = aiGetDistance(critter);
if (distance == DISTANCE_STAY) { if (distance == DISTANCE_STAY) {
return -1; return -1;
} }
if (distance == DISTANCE_STAY_CLOSE) { if (distance == DISTANCE_STAY_CLOSE) {
if (a2 != gDude) { if (target != gDude) {
int currentDistance = objectGetDistanceBetween(a1, gDude); int currentDistance = objectGetDistanceBetween(critter, gDude);
if (currentDistance > 5 if (currentDistance > 5
&& objectGetDistanceBetween(a2, gDude) > 5 && objectGetDistanceBetween(target, gDude) > 5
&& currentDistance + actionPoints > 5) { && currentDistance + actionPoints > 5) {
return -1; return -1;
} }
} }
} }
if (objectGetDistanceBetween(a1, a2) <= 1) { if (objectGetDistanceBetween(critter, target) <= 1) {
return -1; return -1;
} }
reg_anim_begin(ANIMATION_REQUEST_RESERVED); reg_anim_begin(ANIMATION_REQUEST_RESERVED);
if (taunt) { if (taunt) {
_combatai_msg(a1, NULL, AI_MESSAGE_TYPE_MOVE, 0); _combatai_msg(critter, NULL, AI_MESSAGE_TYPE_MOVE, 0);
} }
Object* v18 = a2; Object* initialTarget = target;
bool shouldUnhide; bool shouldUnhide;
if ((a2->flags & OBJECT_MULTIHEX) != 0) { if ((target->flags & OBJECT_MULTIHEX) != 0) {
shouldUnhide = true; shouldUnhide = true;
a2->flags |= OBJECT_HIDDEN; target->flags |= OBJECT_HIDDEN;
} else { } else {
shouldUnhide = false; shouldUnhide = false;
} }
if (pathfinderFindPath(a1, a1->tile, a2->tile, NULL, 0, _obj_blocking_at) == 0) { if (pathfinderFindPath(critter, critter->tile, target->tile, NULL, 0, _obj_blocking_at) == 0) {
_moveBlockObj = NULL; _moveBlockObj = NULL;
if (pathfinderFindPath(a1, a1->tile, a2->tile, NULL, 0, _obj_ai_blocking_at) == 0 if (pathfinderFindPath(critter, critter->tile, target->tile, NULL, 0, _obj_ai_blocking_at) == 0
&& _moveBlockObj != NULL && _moveBlockObj != NULL
&& PID_TYPE(_moveBlockObj->pid) == OBJ_TYPE_CRITTER) { && PID_TYPE(_moveBlockObj->pid) == OBJ_TYPE_CRITTER) {
if (shouldUnhide) { if (shouldUnhide) {
a2->flags &= ~OBJECT_HIDDEN; target->flags &= ~OBJECT_HIDDEN;
} }
a2 = _moveBlockObj; target = _moveBlockObj;
if ((a2->flags & OBJECT_MULTIHEX) != 0) { if ((target->flags & OBJECT_MULTIHEX) != 0) {
shouldUnhide = true; shouldUnhide = true;
a2->flags |= OBJECT_HIDDEN; target->flags |= OBJECT_HIDDEN;
} else { } else {
shouldUnhide = false; shouldUnhide = false;
} }
@ -2389,25 +2389,25 @@ static int _ai_move_steps_closer(Object* a1, Object* a2, int actionPoints, bool
} }
if (shouldUnhide) { if (shouldUnhide) {
a2->flags &= ~OBJECT_HIDDEN; target->flags &= ~OBJECT_HIDDEN;
} }
int tile = a2->tile; int tile = target->tile;
if (a2 == v18) { if (target == initialTarget) {
_cai_retargetTileFromFriendlyFire(a1, a2, &tile); _cai_retargetTileFromFriendlyFire(critter, target, &tile);
} }
if (actionPoints >= critterGetStat(a1, STAT_MAXIMUM_ACTION_POINTS) / 2 && artCritterFidShouldRun(a1->fid)) { if (actionPoints >= critterGetStat(critter, STAT_MAXIMUM_ACTION_POINTS) / 2 && artCritterFidShouldRun(critter->fid)) {
if ((a2->flags & OBJECT_MULTIHEX) != 0) { if ((target->flags & OBJECT_MULTIHEX) != 0) {
animationRegisterRunToObject(a1, a2, actionPoints, 0); animationRegisterRunToObject(critter, target, actionPoints, 0);
} else { } else {
animationRegisterRunToTile(a1, tile, a1->elevation, actionPoints, 0); animationRegisterRunToTile(critter, tile, critter->elevation, actionPoints, 0);
} }
} else { } else {
if ((a2->flags & OBJECT_MULTIHEX) != 0) { if ((target->flags & OBJECT_MULTIHEX) != 0) {
animationRegisterMoveToObject(a1, a2, actionPoints, 0); animationRegisterMoveToObject(critter, target, actionPoints, 0);
} else { } else {
animationRegisterMoveToTile(a1, tile, a1->elevation, actionPoints, 0); animationRegisterMoveToTile(critter, tile, critter->elevation, actionPoints, 0);
} }
} }
@ -2665,35 +2665,35 @@ static int _ai_attack(Object* attacker, Object* defender, int hitMode)
} }
// 0x42A7D8 // 0x42A7D8
static int _ai_try_attack(Object* a1, Object* a2) static int _ai_try_attack(Object* attacker, Object* defender)
{ {
_critter_set_who_hit_me(a1, a2); _critter_set_who_hit_me(attacker, defender);
CritterCombatData* combatData = &(a1->data.critter.combat); CritterCombatData* combatData = &(attacker->data.critter.combat);
bool taunt = true; bool taunt = true;
Object* weapon = critterGetItem2(a1); Object* weapon = critterGetItem2(attacker);
if (weapon != NULL && itemGetType(weapon) != ITEM_TYPE_WEAPON) { if (weapon != NULL && itemGetType(weapon) != ITEM_TYPE_WEAPON) {
weapon = NULL; weapon = NULL;
} }
int hitMode = _ai_pick_hit_mode(a1, weapon, a2); int hitMode = _ai_pick_hit_mode(attacker, weapon, defender);
int minToHit = aiGetPacket(a1)->min_to_hit; int minToHit = aiGetPacket(attacker)->min_to_hit;
int actionPoints = a1->data.critter.combat.ap; int actionPoints = attacker->data.critter.combat.ap;
int safeDistance = 0; int safeDistance = 0;
int v42 = 0; int actionPointsToUse = 0;
if (weapon != NULL if (weapon != NULL
|| (critterGetBodyType(a2) == BODY_TYPE_BIPED || (critterGetBodyType(defender) == BODY_TYPE_BIPED
&& ((a2->fid & 0xF000) >> 12 == 0) && ((defender->fid & 0xF000) >> 12 == 0)
&& artExists(buildFid(OBJ_TYPE_CRITTER, a1->fid & 0xFFF, ANIM_THROW_PUNCH, 0, a1->rotation + 1)))) { && artExists(buildFid(OBJ_TYPE_CRITTER, attacker->fid & 0xFFF, ANIM_THROW_PUNCH, 0, attacker->rotation + 1)))) {
// SFALL: Check the safety of weapons based on the selected attack mode // SFALL: Check the safety of weapons based on the selected attack mode
// instead of always the primary weapon hit mode. // instead of always the primary weapon hit mode.
if (_combat_safety_invalidate_weapon(a1, weapon, hitMode, a2, &safeDistance)) { if (_combat_safety_invalidate_weapon(attacker, weapon, hitMode, defender, &safeDistance)) {
_ai_switch_weapons(a1, &hitMode, &weapon, a2); _ai_switch_weapons(attacker, &hitMode, &weapon, defender);
} }
} else { } else {
_ai_switch_weapons(a1, &hitMode, &weapon, a2); _ai_switch_weapons(attacker, &hitMode, &weapon, defender);
} }
unsigned char rotations[800]; unsigned char rotations[800];
@ -2704,37 +2704,37 @@ static int _ai_try_attack(Object* a1, Object* a2)
break; break;
} }
int reason = _combat_check_bad_shot(a1, a2, hitMode, false); int reason = _combat_check_bad_shot(attacker, defender, hitMode, false);
if (reason == COMBAT_BAD_SHOT_NO_AMMO) { if (reason == COMBAT_BAD_SHOT_NO_AMMO) {
// out of ammo // out of ammo
if (aiHaveAmmo(a1, weapon, &ammo)) { if (aiHaveAmmo(attacker, weapon, &ammo)) {
int remainingAmmoQuantity = weaponReload(weapon, ammo); int remainingAmmoQuantity = weaponReload(weapon, ammo);
if (remainingAmmoQuantity == 0 && ammo != NULL) { if (remainingAmmoQuantity == 0 && ammo != NULL) {
_obj_destroy(ammo); _obj_destroy(ammo);
} }
if (remainingAmmoQuantity != -1) { if (remainingAmmoQuantity != -1) {
int volume = _gsound_compute_relative_volume(a1); int volume = _gsound_compute_relative_volume(attacker);
const char* sfx = sfxBuildWeaponName(WEAPON_SOUND_EFFECT_READY, weapon, hitMode, NULL); const char* sfx = sfxBuildWeaponName(WEAPON_SOUND_EFFECT_READY, weapon, hitMode, NULL);
_gsound_play_sfx_file_volume(sfx, volume); _gsound_play_sfx_file_volume(sfx, volume);
_ai_magic_hands(a1, weapon, 5002); _ai_magic_hands(attacker, weapon, 5002);
// SFALL: Fix incorrect AP cost when AI reloads a weapon. // SFALL: Fix incorrect AP cost when AI reloads a weapon.
// CE: There is a commented out code which checks // CE: There is a commented out code which checks
// available action points before performing reload. Not // available action points before performing reload. Not
// sure why it was commented, probably needs additional // sure why it was commented, probably needs additional
// testing. // testing.
int actionPointsRequired = weaponGetActionPointCost(a1, HIT_MODE_RIGHT_WEAPON_RELOAD, false); int actionPointsRequired = weaponGetActionPointCost(attacker, HIT_MODE_RIGHT_WEAPON_RELOAD, false);
if (a1->data.critter.combat.ap >= actionPointsRequired) { if (attacker->data.critter.combat.ap >= actionPointsRequired) {
a1->data.critter.combat.ap -= actionPointsRequired; attacker->data.critter.combat.ap -= actionPointsRequired;
} else { } else {
a1->data.critter.combat.ap = 0; attacker->data.critter.combat.ap = 0;
} }
} }
} else { } else {
ammo = _ai_search_environ(a1, ITEM_TYPE_AMMO); ammo = _ai_search_environ(attacker, ITEM_TYPE_AMMO);
if (ammo != NULL) { if (ammo != NULL) {
ammo = _ai_retrieve_object(a1, ammo); ammo = _ai_retrieve_object(attacker, ammo);
if (ammo != NULL) { if (ammo != NULL) {
int remainingAmmoQuantity = weaponReload(weapon, ammo); int remainingAmmoQuantity = weaponReload(weapon, ammo);
if (remainingAmmoQuantity == 0) { if (remainingAmmoQuantity == 0) {
@ -2742,62 +2742,63 @@ static int _ai_try_attack(Object* a1, Object* a2)
} }
if (remainingAmmoQuantity != -1) { if (remainingAmmoQuantity != -1) {
int volume = _gsound_compute_relative_volume(a1); int volume = _gsound_compute_relative_volume(attacker);
const char* sfx = sfxBuildWeaponName(WEAPON_SOUND_EFFECT_READY, weapon, hitMode, NULL); const char* sfx = sfxBuildWeaponName(WEAPON_SOUND_EFFECT_READY, weapon, hitMode, NULL);
_gsound_play_sfx_file_volume(sfx, volume); _gsound_play_sfx_file_volume(sfx, volume);
_ai_magic_hands(a1, weapon, 5002); _ai_magic_hands(attacker, weapon, 5002);
// SFALL: Fix incorrect AP cost when AI reloads a // SFALL: Fix incorrect AP cost when AI reloads a
// weapon. // weapon.
// CE: See note above, probably need to check // CE: See note above, probably need to check
// available action points before performing // available action points before performing
// reload. // reload.
int actionPointsRequired = weaponGetActionPointCost(a1, HIT_MODE_RIGHT_WEAPON_RELOAD, false); int actionPointsRequired = weaponGetActionPointCost(attacker, HIT_MODE_RIGHT_WEAPON_RELOAD, false);
if (a1->data.critter.combat.ap >= actionPointsRequired) { if (attacker->data.critter.combat.ap >= actionPointsRequired) {
a1->data.critter.combat.ap -= actionPointsRequired; attacker->data.critter.combat.ap -= actionPointsRequired;
} else { } else {
a1->data.critter.combat.ap = 0; attacker->data.critter.combat.ap = 0;
} }
} }
} }
} else { } else {
int volume = _gsound_compute_relative_volume(a1); int volume = _gsound_compute_relative_volume(attacker);
const char* sfx = sfxBuildWeaponName(WEAPON_SOUND_EFFECT_OUT_OF_AMMO, weapon, hitMode, NULL); const char* sfx = sfxBuildWeaponName(WEAPON_SOUND_EFFECT_OUT_OF_AMMO, weapon, hitMode, NULL);
_gsound_play_sfx_file_volume(sfx, volume); _gsound_play_sfx_file_volume(sfx, volume);
_ai_magic_hands(a1, weapon, 5001); _ai_magic_hands(attacker, weapon, 5001);
if (_inven_unwield(a1, 1) == 0) { if (_inven_unwield(attacker, 1) == 0) {
_combat_turn_run(); _combat_turn_run();
} }
_ai_switch_weapons(a1, &hitMode, &weapon, a2); _ai_switch_weapons(attacker, &hitMode, &weapon, defender);
} }
} }
} else if (reason == COMBAT_BAD_SHOT_NOT_ENOUGH_AP || reason == COMBAT_BAD_SHOT_ARM_CRIPPLED || reason == COMBAT_BAD_SHOT_BOTH_ARMS_CRIPPLED) { } else if (reason == COMBAT_BAD_SHOT_NOT_ENOUGH_AP || reason == COMBAT_BAD_SHOT_ARM_CRIPPLED || reason == COMBAT_BAD_SHOT_BOTH_ARMS_CRIPPLED) {
// 3 - not enough action points // 3 - not enough action points
// 6 - crippled one arm for two-handed weapon // 6 - crippled one arm for two-handed weapon
// 7 - both hands crippled // 7 - both hands crippled
if (_ai_switch_weapons(a1, &hitMode, &weapon, a2) == -1) { if (_ai_switch_weapons(attacker, &hitMode, &weapon, defender) == -1) {
return -1; return -1;
} }
} else if (reason == COMBAT_BAD_SHOT_OUT_OF_RANGE) { } else if (reason == COMBAT_BAD_SHOT_OUT_OF_RANGE) {
// target out of range // target out of range
int accuracy = _determine_to_hit_no_range(a1, a2, HIT_LOCATION_UNCALLED, hitMode, rotations); int toHitNoRange = _determine_to_hit_no_range(attacker, defender, HIT_LOCATION_UNCALLED, hitMode, rotations);
if (accuracy < minToHit) { if (toHitNoRange < minToHit) {
debugPrint("%s: FLEEING: Can't possibly Hit Target!", critterGetName(a1)); // hit chance is too low even at point blank range (not taking range into account)
_ai_run_away(a1, a2); debugPrint("%s: FLEEING: Can't possibly Hit Target!", critterGetName(attacker));
_ai_run_away(attacker, defender);
return 0; return 0;
} }
if (weapon != NULL) { if (weapon != NULL) {
if (_ai_move_steps_closer(a1, a2, actionPoints, taunt) == -1) { if (_ai_move_steps_closer(attacker, defender, actionPoints, taunt) == -1) {
return -1; return -1;
} }
taunt = false; taunt = false;
} else { } else {
if (_ai_switch_weapons(a1, &hitMode, &weapon, a2) == -1 || weapon == NULL) { if (_ai_switch_weapons(attacker, &hitMode, &weapon, defender) == -1 || weapon == NULL) {
// NOTE: Uninline. // NOTE: Uninline.
if (_ai_move_closer(a1, a2, taunt) == -1) { if (_ai_move_closer(attacker, defender, taunt) == -1) {
return -1; return -1;
} }
} }
@ -2805,66 +2806,66 @@ static int _ai_try_attack(Object* a1, Object* a2)
} }
} else if (reason == COMBAT_BAD_SHOT_AIM_BLOCKED) { } else if (reason == COMBAT_BAD_SHOT_AIM_BLOCKED) {
// aim is blocked // aim is blocked
if (_ai_move_steps_closer(a1, a2, a1->data.critter.combat.ap, taunt) == -1) { if (_ai_move_steps_closer(attacker, defender, attacker->data.critter.combat.ap, taunt) == -1) {
return -1; return -1;
} }
taunt = false; taunt = false;
} else if (reason == COMBAT_BAD_SHOT_OK) { } else if (reason == COMBAT_BAD_SHOT_OK) {
int accuracy = _determine_to_hit(a1, a2, HIT_LOCATION_UNCALLED, hitMode); int accuracy = _determine_to_hit(attacker, defender, HIT_LOCATION_UNCALLED, hitMode);
if (safeDistance != 0) { if (safeDistance != 0) {
if (_ai_move_away(a1, a2, safeDistance) == -1) { if (_ai_move_away(attacker, defender, safeDistance) == -1) {
return -1; return -1;
} }
} }
if (accuracy < minToHit) { if (accuracy < minToHit) {
int accuracyNoRange = _determine_to_hit_no_range(a1, a2, HIT_LOCATION_UNCALLED, hitMode, rotations); int toHitNoRange = _determine_to_hit_no_range(attacker, defender, HIT_LOCATION_UNCALLED, hitMode, rotations);
if (accuracyNoRange < minToHit) { if (toHitNoRange < minToHit) {
debugPrint("%s: FLEEING: Can't possibly Hit Target!", critterGetName(a1)); debugPrint("%s: FLEEING: Can't possibly Hit Target!", critterGetName(attacker));
_ai_run_away(a1, a2); _ai_run_away(attacker, defender);
return 0; return 0;
} }
if (actionPoints > 0) { if (actionPoints > 0) {
int v24 = pathfinderFindPath(a1, a1->tile, a2->tile, rotations, 0, _obj_blocking_at); int pathLength = pathfinderFindPath(attacker, attacker->tile, defender->tile, rotations, 0, _obj_blocking_at);
if (v24 == 0) { if (pathLength == 0) {
v42 = actionPoints; actionPointsToUse = actionPoints;
} else { } else {
if (v24 < actionPoints) { if (pathLength < actionPoints) {
actionPoints = v24; actionPoints = pathLength;
} }
int tile = a1->tile; int tile = attacker->tile;
int index; int index;
for (index = 0; index < actionPoints; index++) { for (index = 0; index < actionPoints; index++) {
tile = tileGetTileInDirection(tile, rotations[index], 1); tile = tileGetTileInDirection(tile, rotations[index], 1);
v42++; actionPointsToUse++;
int v27 = _determine_to_hit_from_tile(a1, tile, a2, HIT_LOCATION_UNCALLED, hitMode); int toHit = _determine_to_hit_from_tile(attacker, tile, defender, HIT_LOCATION_UNCALLED, hitMode);
if (v27 >= minToHit) { if (toHit >= minToHit) {
break; break;
} }
} }
if (index == actionPoints) { if (index == actionPoints) {
v42 = actionPoints; actionPointsToUse = actionPoints;
} }
} }
} }
if (_ai_move_steps_closer(a1, a2, v42, taunt) == -1) { if (_ai_move_steps_closer(attacker, defender, actionPointsToUse, taunt) == -1) {
debugPrint("%s: FLEEING: Can't possibly get closer to Target!", critterGetName(a1)); debugPrint("%s: FLEEING: Can't possibly get closer to Target!", critterGetName(attacker));
_ai_run_away(a1, a2); _ai_run_away(attacker, defender);
return 0; return 0;
} }
taunt = false; taunt = false;
if (_ai_attack(a1, a2, hitMode) == -1 || weaponGetActionPointCost(a1, hitMode, 0) > a1->data.critter.combat.ap) { if (_ai_attack(attacker, defender, hitMode) == -1 || weaponGetActionPointCost(attacker, hitMode, 0) > attacker->data.critter.combat.ap) {
return -1; return -1;
} }
} else { } else {
if (_ai_attack(a1, a2, hitMode) == -1 || weaponGetActionPointCost(a1, hitMode, 0) > a1->data.critter.combat.ap) { if (_ai_attack(attacker, defender, hitMode) == -1 || weaponGetActionPointCost(attacker, hitMode, 0) > attacker->data.critter.combat.ap) {
return -1; return -1;
} }
} }

View File

@ -1370,7 +1370,7 @@ char* gameSoundBuildInterfaceName(const char* a1)
// 0x451760 // 0x451760
char* sfxBuildWeaponName(int effectType, Object* weapon, int hitMode, Object* target) char* sfxBuildWeaponName(int effectType, Object* weapon, int hitMode, Object* target)
{ {
int v6; int soundVariant;
char weaponSoundCode; char weaponSoundCode;
char effectTypeCode; char effectTypeCode;
char materialCode; char materialCode;
@ -1384,12 +1384,12 @@ char* sfxBuildWeaponName(int effectType, Object* weapon, int hitMode, Object* ta
if (hitMode != HIT_MODE_LEFT_WEAPON_PRIMARY if (hitMode != HIT_MODE_LEFT_WEAPON_PRIMARY
&& hitMode != HIT_MODE_RIGHT_WEAPON_PRIMARY && hitMode != HIT_MODE_RIGHT_WEAPON_PRIMARY
&& hitMode != HIT_MODE_PUNCH) { && hitMode != HIT_MODE_PUNCH) {
v6 = 2; soundVariant = 2;
} else { } else {
v6 = 1; soundVariant = 1;
} }
} else { } else {
v6 = 1; soundVariant = 1;
} }
int damageType = weaponGetDamageType(NULL, weapon); int damageType = weaponGetDamageType(NULL, weapon);
@ -1438,7 +1438,7 @@ char* sfxBuildWeaponName(int effectType, Object* weapon, int hitMode, Object* ta
} }
} }
snprintf(_sfx_file_name, sizeof(_sfx_file_name), "W%c%c%1d%cXX%1d", effectTypeCode, weaponSoundCode, v6, materialCode, 1); snprintf(_sfx_file_name, sizeof(_sfx_file_name), "W%c%c%1d%cXX%1d", effectTypeCode, weaponSoundCode, soundVariant, materialCode, 1);
compat_strupr(_sfx_file_name); compat_strupr(_sfx_file_name);
return _sfx_file_name; return _sfx_file_name;
} }

View File

@ -31,13 +31,13 @@ static int _outputStr(char* a1);
static int _checkWait(Program* program); static int _checkWait(Program* program);
static char* programGetCurrentProcedureName(Program* s); static char* programGetCurrentProcedureName(Program* s);
static opcode_t stackReadInt16(unsigned char* data, int pos); static opcode_t stackReadInt16(unsigned char* data, int pos);
static int stackReadInt32(unsigned char* a1, int a2); static int stackReadInt32(unsigned char* data, int pos);
static void stackWriteInt16(int value, unsigned char* a2, int a3); static void stackWriteInt16(int value, unsigned char* data, int pos);
static void stackWriteInt32(int value, unsigned char* stack, int pos); static void stackWriteInt32(int value, unsigned char* data, int pos);
static void stackPushInt16(unsigned char* a1, int* a2, int value); static void stackPushInt16(unsigned char* data, int* pointer, int value);
static void stackPushInt32(unsigned char* a1, int* a2, int value); static void stackPushInt32(unsigned char* data, int* pointer, int value);
static int stackPopInt32(unsigned char* a1, int* a2); static int stackPopInt32(unsigned char* data, int* pointer);
static opcode_t stackPopInt16(unsigned char* a1, int* a2); static opcode_t stackPopInt16(unsigned char* data, int* pointer);
static void _interpretIncStringRef(Program* program, opcode_t opcode, int value); static void _interpretIncStringRef(Program* program, opcode_t opcode, int value);
static void programReturnStackPushInt16(Program* program, int value); static void programReturnStackPushInt16(Program* program, int value);
static opcode_t programReturnStackPopInt16(Program* program); static opcode_t programReturnStackPopInt16(Program* program);
@ -51,7 +51,7 @@ static void opPush(Program* program);
static void opPushBase(Program* program); static void opPushBase(Program* program);
static void opPopBase(Program* program); static void opPopBase(Program* program);
static void opPopToBase(Program* program); static void opPopToBase(Program* program);
static void op802C(Program* program); static void opSetGlobal(Program* program);
static void opDump(Program* program); static void opDump(Program* program);
static void opDelayedCall(Program* program); static void opDelayedCall(Program* program);
static void opConditionalCall(Program* program); static void opConditionalCall(Program* program);
@ -230,17 +230,17 @@ static char* programGetCurrentProcedureName(Program* program)
int procedureCount = stackReadInt32(program->procedures, 0); int procedureCount = stackReadInt32(program->procedures, 0);
unsigned char* ptr = program->procedures + 4; unsigned char* ptr = program->procedures + 4;
int procedureOffset = stackReadInt32(ptr, 16); int procedureOffset = stackReadInt32(ptr, offsetof(Procedure, bodyOffset));
int identifierOffset = stackReadInt32(ptr, 0); int identifierOffset = stackReadInt32(ptr, offsetof(Procedure, nameOffset));
for (int index = 0; index < procedureCount; index++) { for (int index = 0; index < procedureCount; index++) {
int nextProcedureOffset = stackReadInt32(ptr + 24, 16); int nextProcedureOffset = stackReadInt32(ptr + 24, offsetof(Procedure, bodyOffset));
if (program->instructionPointer >= procedureOffset && program->instructionPointer < nextProcedureOffset) { if (program->instructionPointer >= procedureOffset && program->instructionPointer < nextProcedureOffset) {
return (char*)(program->identifiers + identifierOffset); return (char*)(program->identifiers + identifierOffset);
} }
ptr += 24; ptr += 24;
identifierOffset = stackReadInt32(ptr, 0); identifierOffset = stackReadInt32(ptr, offsetof(Procedure, nameOffset));
} }
return _aCouldnTFindPro; return _aCouldnTFindPro;
@ -712,7 +712,7 @@ static void opPopToBase(Program* program)
} }
// 0x467DE0 // 0x467DE0
static void op802C(Program* program) static void opSetGlobal(Program* program)
{ {
program->basePointer = program->stackValues->size(); program->basePointer = program->stackValues->size();
} }
@ -745,10 +745,10 @@ static void opDelayedCall(Program* program)
delay += 1000 * _timerFunc() / _timerTick; delay += 1000 * _timerFunc() / _timerTick;
} }
int flags = stackReadInt32(procedure_ptr, 4); int flags = stackReadInt32(procedure_ptr, offsetof(Procedure, flags));
stackWriteInt32(delay, procedure_ptr, 8); stackWriteInt32(delay, procedure_ptr, offsetof(Procedure, time));
stackWriteInt32(flags | PROCEDURE_FLAG_TIMED, procedure_ptr, 4); stackWriteInt32(flags | PROCEDURE_FLAG_TIMED, procedure_ptr, offsetof(Procedure, flags));
} }
// 0x468034 // 0x468034
@ -761,10 +761,10 @@ static void opConditionalCall(Program* program)
} }
unsigned char* procedure_ptr = program->procedures + 4 + 24 * data[0]; unsigned char* procedure_ptr = program->procedures + 4 + 24 * data[0];
int flags = stackReadInt32(procedure_ptr, 4); int flags = stackReadInt32(procedure_ptr, offsetof(Procedure, flags));
stackWriteInt32(flags | PROCEDURE_FLAG_CONDITIONAL, procedure_ptr, 4); stackWriteInt32(flags | PROCEDURE_FLAG_CONDITIONAL, procedure_ptr, offsetof(Procedure, flags));
stackWriteInt32(data[1], procedure_ptr, 12); stackWriteInt32(data[1], procedure_ptr, offsetof(Procedure, conditionOffset));
} }
// 0x46817C // 0x46817C
@ -788,9 +788,9 @@ static void opCancel(Program* program)
} }
Procedure* proc = (Procedure*)(program->procedures + 4 + data * sizeof(*proc)); Procedure* proc = (Procedure*)(program->procedures + 4 + data * sizeof(*proc));
proc->field_4 = 0; proc->flags = 0;
proc->field_8 = 0; proc->time = 0;
proc->field_C = 0; proc->conditionOffset = 0;
} }
// 0x468330 // 0x468330
@ -802,9 +802,9 @@ static void opCancelAll(Program* program)
// TODO: Original code uses different approach, check. // TODO: Original code uses different approach, check.
Procedure* proc = (Procedure*)(program->procedures + 4 + index * sizeof(*proc)); Procedure* proc = (Procedure*)(program->procedures + 4 + index * sizeof(*proc));
proc->field_4 = 0; proc->flags = 0;
proc->field_8 = 0; proc->time = 0;
proc->field_C = 0; proc->conditionOffset = 0;
} }
} }
@ -2030,12 +2030,12 @@ static void opCall(Program* program)
unsigned char* ptr = program->procedures + 4 + 24 * value; unsigned char* ptr = program->procedures + 4 + 24 * value;
int flags = stackReadInt32(ptr, 4); int flags = stackReadInt32(ptr, offsetof(Procedure, flags));
if ((flags & 4) != 0) { if ((flags & PROCEDURE_FLAG_IMPORTED) != 0) {
// TODO: Incomplete. // TODO: Incomplete.
} else { } else {
program->instructionPointer = stackReadInt32(ptr, 16); program->instructionPointer = stackReadInt32(ptr, offsetof(Procedure, bodyOffset));
if ((flags & 0x10) != 0) { if ((flags & PROCEDURE_FLAG_CRITICAL) != 0) {
program->flags |= PROGRAM_FLAG_CRITICAL_SECTION; program->flags |= PROGRAM_FLAG_CRITICAL_SECTION;
} }
} }
@ -2238,7 +2238,7 @@ static void opFetchProcedureAddress(Program* program)
{ {
int procedureIndex = programStackPopInteger(program); int procedureIndex = programStackPopInteger(program);
int address = stackReadInt32(program->procedures + 4 + sizeof(Procedure) * procedureIndex, 16); int address = stackReadInt32(program->procedures + 4 + sizeof(Procedure) * procedureIndex, offsetof(Procedure, bodyOffset));
programStackPushInteger(program, address); programStackPushInteger(program, address);
} }
@ -2298,8 +2298,8 @@ static void opExportProcedure(Program* program)
unsigned char* proc_ptr = program->procedures + 4 + sizeof(Procedure) * procedureIndex; unsigned char* proc_ptr = program->procedures + 4 + sizeof(Procedure) * procedureIndex;
char* procedureName = programGetIdentifier(program, stackReadInt32(proc_ptr, 0)); char* procedureName = programGetIdentifier(program, stackReadInt32(proc_ptr, offsetof(Procedure, nameOffset)));
int procedureAddress = stackReadInt32(proc_ptr, 16); int procedureAddress = stackReadInt32(proc_ptr, offsetof(Procedure, bodyOffset));
if (externalProcedureCreate(program, procedureName, procedureAddress, argumentCount) != 0) { if (externalProcedureCreate(program, procedureName, procedureAddress, argumentCount) != 0) {
char err[256]; char err[256];
@ -2468,9 +2468,9 @@ static void opCheckProcedureArgumentCount(Program* program)
int expectedArgumentCount = programStackPopInteger(program); int expectedArgumentCount = programStackPopInteger(program);
int procedureIndex = programStackPopInteger(program); int procedureIndex = programStackPopInteger(program);
int actualArgumentCount = stackReadInt32(program->procedures + 4 + 24 * procedureIndex, 20); int actualArgumentCount = stackReadInt32(program->procedures + 4 + 24 * procedureIndex, offsetof(Procedure, argCount));
if (actualArgumentCount != expectedArgumentCount) { if (actualArgumentCount != expectedArgumentCount) {
const char* identifier = programGetIdentifier(program, stackReadInt32(program->procedures + 4 + 24 * procedureIndex, 0)); const char* identifier = programGetIdentifier(program, stackReadInt32(program->procedures + 4 + 24 * procedureIndex, offsetof(Procedure, nameOffset)));
char err[260]; char err[260];
snprintf(err, sizeof(err), "Wrong number of args to procedure %s\n", identifier); snprintf(err, sizeof(err), "Wrong number of args to procedure %s\n", identifier);
programFatalError(err); programFatalError(err);
@ -2491,7 +2491,7 @@ static void opLookupStringProc(Program* program)
// Start with 1 since we've skipped main procedure, which is always at // Start with 1 since we've skipped main procedure, which is always at
// index 0. // index 0.
for (int index = 1; index < procedureCount; index++) { for (int index = 1; index < procedureCount; index++) {
int offset = stackReadInt32(procedurePtr, 0); int offset = stackReadInt32(procedurePtr, offsetof(Procedure, nameOffset));
const char* procedureName = programGetIdentifier(program, offset); const char* procedureName = programGetIdentifier(program, offset);
if (compat_stricmp(procedureName, procedureNameToLookup) == 0) { if (compat_stricmp(procedureName, procedureNameToLookup) == 0) {
programStackPushInteger(program, index); programStackPushInteger(program, index);
@ -2556,7 +2556,7 @@ void interpreterRegisterOpcodeHandlers()
interpreterRegisterOpcode(OPCODE_POP_BASE, opPopBase); interpreterRegisterOpcode(OPCODE_POP_BASE, opPopBase);
interpreterRegisterOpcode(OPCODE_POP_TO_BASE, opPopToBase); interpreterRegisterOpcode(OPCODE_POP_TO_BASE, opPopToBase);
interpreterRegisterOpcode(OPCODE_PUSH_BASE, opPushBase); interpreterRegisterOpcode(OPCODE_PUSH_BASE, opPushBase);
interpreterRegisterOpcode(OPCODE_SET_GLOBAL, op802C); interpreterRegisterOpcode(OPCODE_SET_GLOBAL, opSetGlobal);
interpreterRegisterOpcode(OPCODE_FETCH_PROCEDURE_ADDRESS, opFetchProcedureAddress); interpreterRegisterOpcode(OPCODE_FETCH_PROCEDURE_ADDRESS, opFetchProcedureAddress);
interpreterRegisterOpcode(OPCODE_DUMP, opDump); interpreterRegisterOpcode(OPCODE_DUMP, opDump);
interpreterRegisterOpcode(OPCODE_IF, opIf); interpreterRegisterOpcode(OPCODE_IF, opIf);
@ -2776,9 +2776,9 @@ void _executeProc(Program* program, int procedureIndex)
char err[256]; char err[256];
procedurePtr = program->procedures + 4 + sizeof(Procedure) * procedureIndex; procedurePtr = program->procedures + 4 + sizeof(Procedure) * procedureIndex;
procedureFlags = stackReadInt32(procedurePtr, 4); procedureFlags = stackReadInt32(procedurePtr, offsetof(Procedure, flags));
if ((procedureFlags & PROCEDURE_FLAG_IMPORTED) != 0) { if ((procedureFlags & PROCEDURE_FLAG_IMPORTED) != 0) {
procedureIdentifier = programGetIdentifier(program, stackReadInt32(procedurePtr, 0)); procedureIdentifier = programGetIdentifier(program, stackReadInt32(procedurePtr, offsetof(Procedure, nameOffset)));
externalProgram = externalProcedureGetProgram(procedureIdentifier, &externalProcedureAddress, &externalProcedureArgumentCount); externalProgram = externalProcedureGetProgram(procedureIdentifier, &externalProcedureAddress, &externalProcedureArgumentCount);
if (externalProgram != NULL) { if (externalProgram != NULL) {
if (externalProcedureArgumentCount == 0) { if (externalProcedureArgumentCount == 0) {
@ -2795,7 +2795,7 @@ void _executeProc(Program* program, int procedureIndex)
_setupExternalCall(program, externalProgram, externalProcedureAddress, 28); _setupExternalCall(program, externalProgram, externalProcedureAddress, 28);
procedurePtr = externalProgram->procedures + 4 + sizeof(Procedure) * procedureIndex; procedurePtr = externalProgram->procedures + 4 + sizeof(Procedure) * procedureIndex;
procedureFlags = stackReadInt32(procedurePtr, 4); procedureFlags = stackReadInt32(procedurePtr, offsetof(Procedure, flags));
if ((procedureFlags & PROCEDURE_FLAG_CRITICAL) != 0) { if ((procedureFlags & PROCEDURE_FLAG_CRITICAL) != 0) {
// NOTE: Uninline. // NOTE: Uninline.
@ -2803,7 +2803,7 @@ void _executeProc(Program* program, int procedureIndex)
_interpret(externalProgram, 0); _interpret(externalProgram, 0);
} }
} else { } else {
procedureAddress = stackReadInt32(procedurePtr, 16); procedureAddress = stackReadInt32(procedurePtr, offsetof(Procedure, bodyOffset));
// NOTE: Uninline. // NOTE: Uninline.
_setupCall(program, procedureAddress, 20); _setupCall(program, procedureAddress, 20);
@ -2826,7 +2826,7 @@ int programFindProcedure(Program* program, const char* name)
unsigned char* ptr = program->procedures + 4; unsigned char* ptr = program->procedures + 4;
for (int index = 0; index < procedureCount; index++) { for (int index = 0; index < procedureCount; index++) {
int identifierOffset = stackReadInt32(ptr, offsetof(Procedure, field_0)); int identifierOffset = stackReadInt32(ptr, offsetof(Procedure, nameOffset));
if (compat_stricmp((char*)(program->identifiers + identifierOffset), name) == 0) { if (compat_stricmp((char*)(program->identifiers + identifierOffset), name) == 0) {
return index; return index;
} }
@ -2851,10 +2851,10 @@ void _executeProcedure(Program* program, int procedureIndex)
jmp_buf env; jmp_buf env;
procedurePtr = program->procedures + 4 + sizeof(Procedure) * procedureIndex; procedurePtr = program->procedures + 4 + sizeof(Procedure) * procedureIndex;
procedureFlags = stackReadInt32(procedurePtr, 4); procedureFlags = stackReadInt32(procedurePtr, offsetof(Procedure, flags));
if ((procedureFlags & PROCEDURE_FLAG_IMPORTED) != 0) { if ((procedureFlags & PROCEDURE_FLAG_IMPORTED) != 0) {
procedureIdentifier = programGetIdentifier(program, stackReadInt32(procedurePtr, 0)); procedureIdentifier = programGetIdentifier(program, stackReadInt32(procedurePtr, offsetof(Procedure, nameOffset)));
externalProgram = externalProcedureGetProgram(procedureIdentifier, &externalProcedureAddress, &externalProcedureArgumentCount); externalProgram = externalProcedureGetProgram(procedureIdentifier, &externalProcedureAddress, &externalProcedureArgumentCount);
if (externalProgram != NULL) { if (externalProgram != NULL) {
if (externalProcedureArgumentCount == 0) { if (externalProcedureArgumentCount == 0) {
@ -2872,7 +2872,7 @@ void _executeProcedure(Program* program, int procedureIndex)
_interpretOutput(err); _interpretOutput(err);
} }
} else { } else {
procedureAddress = stackReadInt32(procedurePtr, 16); procedureAddress = stackReadInt32(procedurePtr, offsetof(Procedure, bodyOffset));
// NOTE: Uninline. // NOTE: Uninline.
_setupCall(program, procedureAddress, 24); _setupCall(program, procedureAddress, 24);
@ -2908,14 +2908,14 @@ static void _doEvents()
procedurePtr = programListNode->program->procedures + 4; procedurePtr = programListNode->program->procedures + 4;
for (procedureIndex = 0; procedureIndex < procedureCount; procedureIndex++) { for (procedureIndex = 0; procedureIndex < procedureCount; procedureIndex++) {
procedureFlags = stackReadInt32(procedurePtr, 4); procedureFlags = stackReadInt32(procedurePtr, offsetof(Procedure, flags));
if ((procedureFlags & PROCEDURE_FLAG_CONDITIONAL) != 0) { if ((procedureFlags & PROCEDURE_FLAG_CONDITIONAL) != 0) {
memcpy(env, programListNode->program, sizeof(env)); memcpy(env, programListNode->program, sizeof(env));
oldProgramFlags = programListNode->program->flags; oldProgramFlags = programListNode->program->flags;
oldInstructionPointer = programListNode->program->instructionPointer; oldInstructionPointer = programListNode->program->instructionPointer;
programListNode->program->flags = 0; programListNode->program->flags = 0;
programListNode->program->instructionPointer = stackReadInt32(procedurePtr, 12); programListNode->program->instructionPointer = stackReadInt32(procedurePtr, offsetof(Procedure, conditionOffset));
_interpret(programListNode->program, -1); _interpret(programListNode->program, -1);
if ((programListNode->program->flags & PROGRAM_FLAG_0x04) == 0) { if ((programListNode->program->flags & PROGRAM_FLAG_0x04) == 0) {
@ -2926,16 +2926,16 @@ static void _doEvents()
if (data != 0) { if (data != 0) {
// NOTE: Uninline. // NOTE: Uninline.
stackWriteInt32(0, procedurePtr, 4); stackWriteInt32(0, procedurePtr, offsetof(Procedure, flags));
_executeProc(programListNode->program, procedureIndex); _executeProc(programListNode->program, procedureIndex);
} }
} }
memcpy(programListNode->program, env, sizeof(env)); memcpy(programListNode->program, env, sizeof(env));
} else if ((procedureFlags & PROCEDURE_FLAG_TIMED) != 0) { } else if ((procedureFlags & PROCEDURE_FLAG_TIMED) != 0) {
if ((unsigned int)stackReadInt32(procedurePtr, 8) < time) { if ((unsigned int)stackReadInt32(procedurePtr, offsetof(Procedure, time)) < time) {
// NOTE: Uninline. // NOTE: Uninline.
stackWriteInt32(0, procedurePtr, 4); stackWriteInt32(0, procedurePtr, offsetof(Procedure, flags));
_executeProc(programListNode->program, procedureIndex); _executeProc(programListNode->program, procedureIndex);
} }
} }

View File

@ -133,12 +133,12 @@ enum RawValueType {
typedef unsigned short opcode_t; typedef unsigned short opcode_t;
typedef struct Procedure { typedef struct Procedure {
int field_0; int nameOffset;
int field_4; int flags;
int field_8; int time;
int field_C; int conditionOffset;
int field_10; int bodyOffset;
int field_14; int argCount;
} Procedure; } Procedure;
class ProgramValue { class ProgramValue {

View File

@ -2375,10 +2375,10 @@ bool _obj_occupied(int tile, int elevation)
} }
// 0x48B848 // 0x48B848
Object* _obj_blocking_at(Object* a1, int tile, int elev) Object* _obj_blocking_at(Object* excludeObj, int tile, int elev)
{ {
ObjectListNode* objectListNode; ObjectListNode* objectListNode;
Object* v7; Object* obj;
int type; int type;
if (!hexGridTileIsValid(tile)) { if (!hexGridTileIsValid(tile)) {
@ -2387,14 +2387,14 @@ Object* _obj_blocking_at(Object* a1, int tile, int elev)
objectListNode = gObjectListHeadByTile[tile]; objectListNode = gObjectListHeadByTile[tile];
while (objectListNode != NULL) { while (objectListNode != NULL) {
v7 = objectListNode->obj; obj = objectListNode->obj;
if (v7->elevation == elev) { if (obj->elevation == elev) {
if ((v7->flags & OBJECT_HIDDEN) == 0 && (v7->flags & OBJECT_NO_BLOCK) == 0 && v7 != a1) { if ((obj->flags & OBJECT_HIDDEN) == 0 && (obj->flags & OBJECT_NO_BLOCK) == 0 && obj != excludeObj) {
type = FID_TYPE(v7->fid); type = FID_TYPE(obj->fid);
if (type == OBJ_TYPE_CRITTER if (type == OBJ_TYPE_CRITTER
|| type == OBJ_TYPE_SCENERY || type == OBJ_TYPE_SCENERY
|| type == OBJ_TYPE_WALL) { || type == OBJ_TYPE_WALL) {
return v7; return obj;
} }
} }
} }
@ -2406,15 +2406,15 @@ Object* _obj_blocking_at(Object* a1, int tile, int elev)
if (hexGridTileIsValid(neighboor)) { if (hexGridTileIsValid(neighboor)) {
objectListNode = gObjectListHeadByTile[neighboor]; objectListNode = gObjectListHeadByTile[neighboor];
while (objectListNode != NULL) { while (objectListNode != NULL) {
v7 = objectListNode->obj; obj = objectListNode->obj;
if ((v7->flags & OBJECT_MULTIHEX) != 0) { if ((obj->flags & OBJECT_MULTIHEX) != 0) {
if (v7->elevation == elev) { if (obj->elevation == elev) {
if ((v7->flags & OBJECT_HIDDEN) == 0 && (v7->flags & OBJECT_NO_BLOCK) == 0 && v7 != a1) { if ((obj->flags & OBJECT_HIDDEN) == 0 && (obj->flags & OBJECT_NO_BLOCK) == 0 && obj != excludeObj) {
type = FID_TYPE(v7->fid); type = FID_TYPE(obj->fid);
if (type == OBJ_TYPE_CRITTER if (type == OBJ_TYPE_CRITTER
|| type == OBJ_TYPE_SCENERY || type == OBJ_TYPE_SCENERY
|| type == OBJ_TYPE_WALL) { || type == OBJ_TYPE_WALL) {
return v7; return obj;
} }
} }
} }
@ -2428,7 +2428,7 @@ Object* _obj_blocking_at(Object* a1, int tile, int elev)
} }
// 0x48B930 // 0x48B930
Object* _obj_shoot_blocking_at(Object* obj, int tile, int elev) Object* _obj_shoot_blocking_at(Object* excludeObj, int tile, int elev)
{ {
if (!hexGridTileIsValid(tile)) { if (!hexGridTileIsValid(tile)) {
return NULL; return NULL;
@ -2439,7 +2439,7 @@ Object* _obj_shoot_blocking_at(Object* obj, int tile, int elev)
Object* candidate = objectListItem->obj; Object* candidate = objectListItem->obj;
if (candidate->elevation == elev) { if (candidate->elevation == elev) {
unsigned int flags = candidate->flags; unsigned int flags = candidate->flags;
if ((flags & OBJECT_HIDDEN) == 0 && ((flags & OBJECT_NO_BLOCK) == 0 || (flags & OBJECT_SHOOT_THRU) == 0) && candidate != obj) { if ((flags & OBJECT_HIDDEN) == 0 && ((flags & OBJECT_NO_BLOCK) == 0 || (flags & OBJECT_SHOOT_THRU) == 0) && candidate != excludeObj) {
int type = FID_TYPE(candidate->fid); int type = FID_TYPE(candidate->fid);
// SFALL: Fix to prevent corpses from blocking line of fire. // SFALL: Fix to prevent corpses from blocking line of fire.
if ((type == OBJ_TYPE_CRITTER && !critterIsDead(candidate)) if ((type == OBJ_TYPE_CRITTER && !critterIsDead(candidate))
@ -2464,7 +2464,7 @@ Object* _obj_shoot_blocking_at(Object* obj, int tile, int elev)
unsigned int flags = candidate->flags; unsigned int flags = candidate->flags;
if ((flags & OBJECT_MULTIHEX) != 0) { if ((flags & OBJECT_MULTIHEX) != 0) {
if (candidate->elevation == elev) { if (candidate->elevation == elev) {
if ((flags & OBJECT_HIDDEN) == 0 && (flags & OBJECT_NO_BLOCK) == 0 && candidate != obj) { if ((flags & OBJECT_HIDDEN) == 0 && (flags & OBJECT_NO_BLOCK) == 0 && candidate != excludeObj) {
int type = FID_TYPE(candidate->fid); int type = FID_TYPE(candidate->fid);
// SFALL: Fix to prevent corpses from blocking line of // SFALL: Fix to prevent corpses from blocking line of
// fire. // fire.
@ -2484,7 +2484,7 @@ Object* _obj_shoot_blocking_at(Object* obj, int tile, int elev)
} }
// 0x48BA20 // 0x48BA20
Object* _obj_ai_blocking_at(Object* a1, int tile, int elevation) Object* _obj_ai_blocking_at(Object* excludeObj, int tile, int elevation)
{ {
if (!hexGridTileIsValid(tile)) { if (!hexGridTileIsValid(tile)) {
return NULL; return NULL;
@ -2496,7 +2496,7 @@ Object* _obj_ai_blocking_at(Object* a1, int tile, int elevation)
if (object->elevation == elevation) { if (object->elevation == elevation) {
if ((object->flags & OBJECT_HIDDEN) == 0 if ((object->flags & OBJECT_HIDDEN) == 0
&& (object->flags & OBJECT_NO_BLOCK) == 0 && (object->flags & OBJECT_NO_BLOCK) == 0
&& object != a1) { && object != excludeObj) {
int objectType = FID_TYPE(object->fid); int objectType = FID_TYPE(object->fid);
if (objectType == OBJ_TYPE_CRITTER if (objectType == OBJ_TYPE_CRITTER
|| objectType == OBJ_TYPE_SCENERY || objectType == OBJ_TYPE_SCENERY
@ -2525,7 +2525,7 @@ Object* _obj_ai_blocking_at(Object* a1, int tile, int elevation)
if (object->elevation == elevation) { if (object->elevation == elevation) {
if ((object->flags & OBJECT_HIDDEN) == 0 if ((object->flags & OBJECT_HIDDEN) == 0
&& (object->flags & OBJECT_NO_BLOCK) == 0 && (object->flags & OBJECT_NO_BLOCK) == 0
&& object != a1) { && object != excludeObj) {
int objectType = FID_TYPE(object->fid); int objectType = FID_TYPE(object->fid);
if (objectType == OBJ_TYPE_CRITTER if (objectType == OBJ_TYPE_CRITTER
|| objectType == OBJ_TYPE_SCENERY || objectType == OBJ_TYPE_SCENERY
@ -2571,7 +2571,7 @@ int _obj_scroll_blocking_at(int tile, int elev)
} }
// 0x48BB88 // 0x48BB88
Object* _obj_sight_blocking_at(Object* a1, int tile, int elevation) Object* _obj_sight_blocking_at(Object* excludeObj, int tile, int elevation)
{ {
ObjectListNode* objectListNode = gObjectListHeadByTile[tile]; ObjectListNode* objectListNode = gObjectListHeadByTile[tile];
while (objectListNode != NULL) { while (objectListNode != NULL) {
@ -2579,7 +2579,7 @@ Object* _obj_sight_blocking_at(Object* a1, int tile, int elevation)
if (object->elevation == elevation if (object->elevation == elevation
&& (object->flags & OBJECT_HIDDEN) == 0 && (object->flags & OBJECT_HIDDEN) == 0
&& (object->flags & OBJECT_LIGHT_THRU) == 0 && (object->flags & OBJECT_LIGHT_THRU) == 0
&& object != a1) { && object != excludeObj) {
int objectType = FID_TYPE(object->fid); int objectType = FID_TYPE(object->fid);
if (objectType == OBJ_TYPE_SCENERY || objectType == OBJ_TYPE_WALL) { if (objectType == OBJ_TYPE_SCENERY || objectType == OBJ_TYPE_WALL) {
return object; return object;

View File

@ -71,11 +71,11 @@ Object* objectFindFirstAtLocation(int elevation, int tile);
Object* objectFindNextAtLocation(); Object* objectFindNextAtLocation();
void objectGetRect(Object* obj, Rect* rect); void objectGetRect(Object* obj, Rect* rect);
bool _obj_occupied(int tile_num, int elev); bool _obj_occupied(int tile_num, int elev);
Object* _obj_blocking_at(Object* a1, int tile_num, int elev); Object* _obj_blocking_at(Object* excludeObj, int tile_num, int elev);
Object* _obj_shoot_blocking_at(Object* obj, int tile, int elev); Object* _obj_shoot_blocking_at(Object* excludeObj, int tile, int elev);
Object* _obj_ai_blocking_at(Object* a1, int tile, int elevation); Object* _obj_ai_blocking_at(Object* excludeObj, int tile, int elevation);
int _obj_scroll_blocking_at(int tile_num, int elev); int _obj_scroll_blocking_at(int tile_num, int elev);
Object* _obj_sight_blocking_at(Object* a1, int tile_num, int elev); Object* _obj_sight_blocking_at(Object* excludeObj, int tile_num, int elev);
int objectGetDistanceBetween(Object* object1, Object* object2); int objectGetDistanceBetween(Object* object1, Object* object2);
int objectGetDistanceBetweenTiles(Object* object1, int tile1, Object* object2, int tile2); int objectGetDistanceBetweenTiles(Object* object1, int tile1, Object* object2, int tile2);
int objectListCreate(int tile, int elevation, int objectType, Object*** objectsPtr); int objectListCreate(int tile, int elevation, int objectType, Object*** objectsPtr);

View File

@ -344,18 +344,19 @@ bool queueHasEvent(Object* owner, int eventType)
int queueProcessEvents() int queueProcessEvents()
{ {
unsigned int time = gameTimeGetTime(); unsigned int time = gameTimeGetTime();
int v1 = 0; // TODO: this is 0 or 1, but in some cases -1. Probably needs to be bool.
int stopProcess = 0;
while (gQueueListHead != NULL) { while (gQueueListHead != NULL) {
QueueListNode* queueListNode = gQueueListHead; QueueListNode* queueListNode = gQueueListHead;
if (time < queueListNode->time || v1 != 0) { if (time < queueListNode->time || stopProcess != 0) {
break; break;
} }
gQueueListHead = queueListNode->next; gQueueListHead = queueListNode->next;
EventTypeDescription* eventTypeDescription = &(gEventTypeDescriptions[queueListNode->type]); EventTypeDescription* eventTypeDescription = &(gEventTypeDescriptions[queueListNode->type]);
v1 = eventTypeDescription->handlerProc(queueListNode->owner, queueListNode->data); stopProcess = eventTypeDescription->handlerProc(queueListNode->owner, queueListNode->data);
if (eventTypeDescription->freeProc != NULL) { if (eventTypeDescription->freeProc != NULL) {
eventTypeDescription->freeProc(queueListNode->data); eventTypeDescription->freeProc(queueListNode->data);
@ -364,7 +365,7 @@ int queueProcessEvents()
internal_free(queueListNode); internal_free(queueListNode);
} }
return v1; return stopProcess;
} }
// 0x4A2748 // 0x4A2748

View File

@ -405,7 +405,7 @@ int gameTimeScheduleUpdateEvent()
int gameTimeEventProcess(Object* obj, void* data) int gameTimeEventProcess(Object* obj, void* data)
{ {
int movie_index; int movie_index;
int v4; int stopProcess;
movie_index = -1; movie_index = -1;
@ -421,17 +421,17 @@ int gameTimeEventProcess(Object* obj, void* data)
_scriptsCheckGameEvents(&movie_index, -1); _scriptsCheckGameEvents(&movie_index, -1);
} }
v4 = _critter_check_rads(gDude); stopProcess = _critter_check_rads(gDude);
_queue_clear_type(4, 0); _queue_clear_type(4, 0);
gameTimeScheduleUpdateEvent(); gameTimeScheduleUpdateEvent();
if (movie_index != -1) { if (movie_index != -1) {
v4 = 1; stopProcess = 1;
} }
return v4; return stopProcess;
} }
// 0x4A3690 // 0x4A3690