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);
}
// TODO: move pathfinding into another unit
// 0x415EFC
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
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.
//
// 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) {
Object* obstacle = callback(a1, from, a1->elevation);
Object* obstacle = callback(obj, from, obj->elevation);
if (obstacle != NULL) {
if (obstacle != *obstaclePtr && (a6 != 32 || (obstacle->flags & OBJECT_SHOOT_THRU) == 0)) {
*obstaclePtr = obstacle;
@ -1961,13 +1962,13 @@ int _make_straight_path_func(Object* a1, int from, int to, StraightPathNode* str
int fromX;
int fromY;
tileToScreenXY(from, &fromX, &fromY, a1->elevation);
tileToScreenXY(from, &fromX, &fromY, obj->elevation);
fromX += 16;
fromY += 8;
int toX;
int toY;
tileToScreenXY(to, &toX, &toY, a1->elevation);
tileToScreenXY(to, &toX, &toY, obj->elevation);
toX += 16;
toY += 8;
@ -2005,7 +2006,7 @@ int _make_straight_path_func(Object* a1, int from, int to, StraightPathNode* str
if (ddx <= ddy) {
int middle = ddx - ddy / 2;
while (true) {
tile = tileFromScreenXY(tileX, tileY, a1->elevation);
tile = tileFromScreenXY(tileX, tileY, obj->elevation);
v22 += 1;
if (v22 == a6) {
@ -2016,9 +2017,9 @@ int _make_straight_path_func(Object* a1, int from, int to, StraightPathNode* str
if (straightPathNodeList != NULL) {
StraightPathNode* pathNode = &(straightPathNodeList[pathNodeIndex]);
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->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 (obstaclePtr != NULL) {
Object* obj = callback(a1, tile, a1->elevation);
if (obj != NULL) {
if (obj != *obstaclePtr && (a6 != 32 || (obj->flags & OBJECT_SHOOT_THRU) == 0)) {
*obstaclePtr = obj;
Object* obstacle = callback(obj, tile, obj->elevation);
if (obstacle != NULL) {
if (obstacle != *obstaclePtr && (a6 != 32 || (obstacle->flags & OBJECT_SHOOT_THRU) == 0)) {
*obstaclePtr = obstacle;
break;
}
}
@ -2058,7 +2059,7 @@ int _make_straight_path_func(Object* a1, int from, int to, StraightPathNode* str
} else {
int middle = ddy - ddx / 2;
while (true) {
tile = tileFromScreenXY(tileX, tileY, a1->elevation);
tile = tileFromScreenXY(tileX, tileY, obj->elevation);
v22 += 1;
if (v22 == a6) {
@ -2069,9 +2070,9 @@ int _make_straight_path_func(Object* a1, int from, int to, StraightPathNode* str
if (straightPathNodeList != NULL) {
StraightPathNode* pathNode = &(straightPathNodeList[pathNodeIndex]);
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->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 (obstaclePtr != NULL) {
Object* obj = callback(a1, tile, a1->elevation);
if (obj != NULL) {
if (obj != *obstaclePtr && (a6 != 32 || (obj->flags & OBJECT_SHOOT_THRU) == 0)) {
*obstaclePtr = obj;
Object* obstacle = callback(obj, tile, obj->elevation);
if (obstacle != NULL) {
if (obstacle != *obstaclePtr && (a6 != 32 || (obstacle->flags & OBJECT_SHOOT_THRU) == 0)) {
*obstaclePtr = obstacle;
break;
}
}
@ -2118,9 +2119,9 @@ int _make_straight_path_func(Object* a1, int from, int to, StraightPathNode* str
if (straightPathNodeList != NULL) {
StraightPathNode* pathNode = &(straightPathNodeList[pathNodeIndex]);
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->y = tileY - fromY - 8;
}
@ -2128,7 +2129,7 @@ int _make_straight_path_func(Object* a1, int from, int to, StraightPathNode* str
pathNodeIndex += 1;
} else {
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 _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 _make_straight_path(Object* a1, 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(Object* object, int from, int to, StraightPathNode* straightPathNodeList, Object** obstaclePtr, int a6);
int _make_straight_path_func(Object* object, int from, int to, StraightPathNode* straightPathNodeList, Object** obstaclePtr, int a6, PathBuilderCallback* callback);
void _object_animate();
int _check_move(int* actionPointsPtr);
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 attackComputeCriticalFailure(Attack* attack);
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 _check_for_death(Object* a1, int a2, int* a3);
static void _set_new_results(Object* a1, int a2);
@ -3476,16 +3476,16 @@ void attackInit(Attack* attack, Object* attacker, Object* defender, int hitMode,
}
// 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) {
int fid = buildFid(OBJ_TYPE_CRITTER, a1->fid & 0xFFF, ANIM_KICK_LEG, (a1->fid & 0xF000) >> 12, (a1->fid & 0x70000000) >> 28);
if (attacker != gDude && hitMode == HIT_MODE_PUNCH && randomBetween(1, 4) == 1) {
int fid = buildFid(OBJ_TYPE_CRITTER, attacker->fid & 0xFFF, ANIM_KICK_LEG, (attacker->fid & 0xF000) >> 12, (attacker->fid & 0x70000000) >> 28);
if (artExists(fid)) {
hitMode = HIT_MODE_KICK;
}
}
attackInit(&_main_ctd, a1, a2, hitMode, hitLocation);
attackInit(&_main_ctd, attacker, defender, hitMode, hitLocation);
debugPrint("computing attack...\n");
if (attackCompute(&_main_ctd) == -1) {
@ -3513,7 +3513,7 @@ int _combat_attack(Object* a1, Object* a2, int hitMode, int hitLocation)
bool aiming;
if (_main_ctd.defenderHitLocation == HIT_LOCATION_TORSO || _main_ctd.defenderHitLocation == HIT_LOCATION_UNCALLED) {
if (a1 == gDude) {
if (attacker == gDude) {
interfaceGetCurrentHitMode(&hitMode, &aiming);
} else {
aiming = false;
@ -3522,22 +3522,22 @@ int _combat_attack(Object* a1, Object* a2, int hitMode, int hitLocation)
aiming = true;
}
int actionPoints = weaponGetActionPointCost(a1, _main_ctd.hitMode, aiming);
int actionPoints = weaponGetActionPointCost(attacker, _main_ctd.hitMode, aiming);
debugPrint("sequencing attack...\n");
if (_action_attack(&_main_ctd) == -1) {
return -1;
}
if (actionPoints > a1->data.critter.combat.ap) {
a1->data.critter.combat.ap = 0;
if (actionPoints > attacker->data.critter.combat.ap) {
attacker->data.critter.combat.ap = 0;
} else {
a1->data.critter.combat.ap -= actionPoints;
attacker->data.critter.combat.ap -= actionPoints;
}
if (a1 == gDude) {
interfaceRenderActionPoints(a1->data.critter.combat.ap, _combat_free_move);
_critter_set_who_hit_me(a1, a2);
if (attacker == gDude) {
interfaceRenderActionPoints(attacker->data.critter.combat.ap, _combat_free_move);
_critter_set_who_hit_me(attacker, defender);
}
// SFALL
@ -3545,19 +3545,19 @@ int _combat_attack(Object* a1, Object* a2, int hitMode, int hitLocation)
_combat_call_display = 1;
_combat_cleanup_enabled = 1;
aiInfoSetLastTarget(a1, a2);
aiInfoSetLastTarget(attacker, defender);
debugPrint("running attack...\n");
return 0;
}
// Returns tile one step closer from [a1] to [a2]
// Returns tile one step closer from [attacker] to [target]
//
// 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);
return tileGetTileInDirection(a1->tile, rotation, 1);
int rotation = tileGetRotationTo(attacker->tile, target->tile);
return tileGetTileInDirection(attacker->tile, rotation, 1);
}
// 0x423128
@ -3942,17 +3942,17 @@ static int attackCompute(Attack* attack)
attack->tile = tile;
Object* v25 = attack->defender;
_make_straight_path_func(v25, attack->defender->tile, attack->tile, NULL, &v25, 32, _obj_shoot_blocking_at);
if (v25 != NULL && v25 != attack->defender) {
attack->tile = v25->tile;
Object* accidentalTarget = attack->defender;
_make_straight_path_func(accidentalTarget, attack->defender->tile, attack->tile, NULL, &accidentalTarget, 32, _obj_shoot_blocking_at);
if (accidentalTarget != NULL && accidentalTarget != attack->defender) {
attack->tile = accidentalTarget->tile;
} 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->defender = v25;
attack->defender = accidentalTarget;
attackComputeDamage(attack, 1, 2);
}
}
@ -3974,75 +3974,75 @@ static int attackCompute(Attack* attack)
// compute_explosion_on_extras
// 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) {
attacker = attack->attacker;
if (isFromAttacker) {
targetObj = attack->attacker;
} else {
if ((attack->attackerFlags & DAM_HIT) != 0) {
attacker = attack->defender;
targetObj = attack->defender;
} else {
attacker = NULL;
targetObj = NULL;
}
}
int tile;
if (attacker != NULL) {
tile = attacker->tile;
int explosionTile;
if (targetObj != NULL) {
explosionTile = targetObj->tile;
} else {
tile = attack->tile;
explosionTile = attack->tile;
}
if (tile == -1) {
if (explosionTile == -1) {
debugPrint("\nError: compute_explosion_on_extras: Called with bad target/tileNum");
return;
}
// TODO: The math in this loop is rather complex and hard to understand.
int v20;
int v22 = 0;
int ringTileIdx;
int radius = 0;
int rotation = 0;
int v5 = -1;
int v19 = tile;
int tile = -1;
int ringFirstTile = explosionTile;
// SFALL
int maxTargets = explosionGetMaxTargets();
// Check adjacent tiles for possible targets, going ring-by-ring
while (attack->extrasLength < maxTargets) {
if (v22 != 0 && (v5 == -1 || (v5 = tileGetTileInDirection(v5, rotation, 1)) != v19)) {
v20++;
if (v20 % v22 == 0) {
if (radius != 0 && (tile == -1 || (tile = tileGetTileInDirection(tile, rotation, 1)) != ringFirstTile)) {
ringTileIdx++;
if (ringTileIdx % radius == 0) { // the larger the radius, the slower we rotate
rotation += 1;
if (rotation == ROTATION_COUNT) {
rotation = ROTATION_NE;
}
}
} else {
v22++;
if (isGrenade && weaponGetGrenadeExplosionRadius(attack->weapon) < v22) {
v5 = -1;
} else if (isGrenade || weaponGetRocketExplosionRadius(attack->weapon) >= v22) {
v5 = tileGetTileInDirection(v19, ROTATION_NE, 1);
radius++; // go to the next ring
if (isGrenade && weaponGetGrenadeExplosionRadius(attack->weapon) < radius) {
tile = -1;
} else if (isGrenade || weaponGetRocketExplosionRadius(attack->weapon) >= radius) {
tile = tileGetTileInDirection(ringFirstTile, ROTATION_NE, 1);
} else {
v5 = -1;
tile = -1;
}
v19 = v5;
ringFirstTile = tile;
rotation = ROTATION_SE;
v20 = 0;
ringTileIdx = 0;
}
if (v5 == -1) {
if (tile == -1) {
break;
}
Object* obstacle = _obj_blocking_at(attacker, v5, attack->attacker->elevation);
Object* obstacle = _obj_blocking_at(targetObj, tile, attack->attacker->elevation);
if (obstacle != NULL
&& FID_TYPE(obstacle->fid) == OBJ_TYPE_CRITTER
&& (obstacle->data.critter.combat.results & DAM_DEAD) == 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) {
attack->attackerFlags &= ~DAM_HIT;
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->extras[index] = obstacle;
attackInit(&_explosion_ctd, attack->attacker, obstacle, attack->hitMode, HIT_LOCATION_TORSO);
if (!a4) {
if (!noDamage) {
_explosion_ctd.attackerFlags |= DAM_HIT;
attackComputeDamage(&_explosion_ctd, 1, 2);
}
@ -4282,26 +4282,26 @@ static void _do_random_cripple(int* flagsPtr)
}
// 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
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
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
// 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);
@ -4311,32 +4311,30 @@ static int attackDetermineToHit(Object* attacker, int tile, Object* defender, in
bool isRangedWeapon = false;
int accuracy;
int toHit;
if (weapon == NULL || isUnarmedHitMode(hitMode)) {
accuracy = skillGetValue(attacker, SKILL_UNARMED);
toHit = skillGetValue(attacker, SKILL_UNARMED);
} else {
accuracy = weaponGetSkillValue(attacker, hitMode);
int modifier = 0;
toHit = weaponGetSkillValue(attacker, hitMode);
int attackType = weaponGetAttackTypeForHitMode(weapon, hitMode);
if (attackType == ATTACK_TYPE_RANGED || attackType == ATTACK_TYPE_THROW) {
isRangedWeapon = true;
int v29 = 0;
int v25 = 0;
int perceptionBonusMult = 0;
int minEffectiveDist = 0;
int weaponPerk = weaponGetPerk(weapon);
switch (weaponPerk) {
case PERK_WEAPON_LONG_RANGE:
v29 = 4;
perceptionBonusMult = 4;
break;
case PERK_WEAPON_SCOPE_RANGE:
v29 = 5;
v25 = 8;
perceptionBonusMult = 5;
minEffectiveDist = 8;
break;
default:
v29 = 2;
perceptionBonusMult = 2;
break;
}
@ -4347,71 +4345,72 @@ static int attackDetermineToHit(Object* attacker, int tile, Object* defender, in
perception += 2 * perkGetRank(gDude, PERK_SHARPSHOOTER);
}
int distanceMod = 0;
// SFALL: Fix for `determine_to_hit_func` function taking distance
// into account when called from `determine_to_hit_no_range`.
if (defender != NULL && a6) {
modifier = objectGetDistanceBetweenTiles(attacker, tile, defender, defender->tile);
if (defender != NULL && useDistance) {
distanceMod = objectGetDistanceBetweenTiles(attacker, tile, defender, defender->tile);
} else {
modifier = 0;
distanceMod = 0;
}
if (modifier >= v25) {
int penalty = attacker == gDude
? v29 * (perception - 2)
: v29 * perception;
if (distanceMod >= minEffectiveDist) {
int perceptionBonus = attacker == gDude
? perceptionBonusMult * (perception - 2)
: perceptionBonusMult * perception;
modifier -= penalty;
distanceMod -= perceptionBonus;
} else {
modifier += v25;
distanceMod += minEffectiveDist;
}
if (-2 * perception > modifier) {
modifier = -2 * perception;
if (distanceMod < -2 * perception) {
distanceMod = -2 * perception;
}
if (modifier >= 0) {
if (distanceMod >= 0) {
if ((attacker->data.critter.combat.results & DAM_BLIND) != 0) {
modifier *= -12;
distanceMod *= -12;
} else {
modifier *= -4;
distanceMod *= -4;
}
} else {
modifier *= -4;
distanceMod *= -4;
}
if (a6 || modifier > 0) {
accuracy += modifier;
if (useDistance || distanceMod > 0) {
toHit += distanceMod;
}
modifier = 0;
int numCrittersInLof = 0;
if (defender != NULL && a6) {
_combat_is_shot_blocked(attacker, tile, defender->tile, defender, &modifier);
if (defender != NULL && useDistance) {
_combat_is_shot_blocked(attacker, tile, defender->tile, defender, &numCrittersInLof);
}
accuracy -= 10 * modifier;
toHit -= 10 * numCrittersInLof;
}
if (attacker == gDude && traitIsSelected(TRAIT_ONE_HANDER)) {
if (weaponIsTwoHanded(weapon)) {
accuracy -= 40;
toHit -= 40;
} else {
accuracy += 20;
toHit += 20;
}
}
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) {
modifier -= 3;
minStrengthMod -= 3;
}
if (modifier > 0) {
accuracy -= 20 * modifier;
if (minStrengthMod > 0) {
toHit -= 20 * minStrengthMod;
}
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;
}
accuracy -= armorClass;
toHit -= armorClass;
}
if (isRangedWeapon) {
accuracy += hit_location_penalty[hitLocation];
toHit += hit_location_penalty[hitLocation];
} else {
accuracy += hit_location_penalty[hitLocation] / 2;
toHit += hit_location_penalty[hitLocation] / 2;
}
if (defender != NULL && (defender->flags & OBJECT_MULTIHEX) != 0) {
accuracy += 15;
toHit += 15;
}
if (attacker == gDude) {
@ -4447,45 +4446,45 @@ static int attackDetermineToHit(Object* attacker, int tile, Object* defender, in
}
if (lightIntensity <= 26214)
accuracy -= 40;
toHit -= 40;
else if (lightIntensity <= 39321)
accuracy -= 25;
toHit -= 25;
else if (lightIntensity <= 52428)
accuracy -= 10;
toHit -= 10;
}
if (_gcsd != NULL) {
accuracy += _gcsd->accuracyBonus;
toHit += _gcsd->accuracyBonus;
}
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) {
accuracy += 40;
toHit += 40;
}
if (attacker->data.critter.combat.team != gDude->data.critter.combat.team) {
switch (settings.preferences.combat_difficulty) {
case 0:
accuracy -= 20;
toHit -= 20;
break;
case 2:
accuracy += 20;
toHit += 20;
break;
}
}
if (accuracy > 95) {
accuracy = 95;
if (toHit > 95) {
toHit = 95;
}
if (accuracy < -100) {
if (toHit < -100) {
debugPrint("Whoa! Bad skill value in determine_to_hit!\n");
}
return accuracy;
return toHit;
}
// 0x4247B8
@ -5880,39 +5879,35 @@ void _combat_highlight_change()
_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
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) {
*a5 = 0;
if (numCrittersOnLof != NULL) {
*numCrittersOnLof = 0;
}
Object* obstacle = a1;
Object* obstacle = sourceObj;
int current = from;
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 (FID_TYPE(obstacle->fid) != OBJ_TYPE_CRITTER && obstacle != a4) {
if (FID_TYPE(obstacle->fid) != OBJ_TYPE_CRITTER && obstacle != targetObj) {
return true;
}
if (a5 != NULL) {
if (obstacle != a4) {
if (a4 != NULL) {
if (numCrittersOnLof != NULL && obstacle != targetObj && targetObj != NULL) {
// SFALL: Fix for combat_is_shot_blocked_ engine
// function not taking the flags of critters in the
// line of fire into account when calculating the hit
// chance penalty of ranged attacks in
// determine_to_hit_func_ engine function.
if ((obstacle->data.critter.combat.results & (DAM_DEAD | DAM_KNOCKED_DOWN | DAM_KNOCKED_OUT)) == 0) {
*a5 += 1;
*numCrittersOnLof += 1;
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_turn_run();
void _combat(STRUCT_664980* attack);
void attackInit(Attack* attack, Object* a2, Object* a3, int a4, int a5);
int _combat_attack(Object* a1, Object* a2, int a3, int a4);
int _combat_bullet_start(const Object* a1, const Object* a2);
void _compute_explosion_on_extras(Attack* attack, int a2, bool isGrenade, int a4);
void attackInit(Attack* attack, Object* attacker, Object* defender, int hitMode, int hitLocation);
int _combat_attack(Object* attacker, Object* defender, int hitMode, int hitLocation);
int _combat_bullet_start(const Object* attacker, const Object* target);
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_no_range(Object* a1, Object* a2, int a3, int a4, unsigned char* a5);
int _determine_to_hit_from_tile(Object* a1, int a2, Object* a3, int a4, int 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* attacker, int tile, Object* defender, int hitLocation, int hitMode);
void attackComputeDeathFlags(Attack* attack);
void _apply_damage(Attack* attack, bool animated);
void _combat_display(Attack* attack);
@ -52,7 +52,7 @@ void _combat_attack_this(Object* a1);
void _combat_outline_on();
void _combat_outline_off();
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_explode_scenery(Object* a1, Object* a2);
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
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) {
return -1;
}
int distance = aiGetDistance(a1);
int distance = aiGetDistance(critter);
if (distance == DISTANCE_STAY) {
return -1;
}
if (distance == DISTANCE_STAY_CLOSE) {
if (a2 != gDude) {
int currentDistance = objectGetDistanceBetween(a1, gDude);
if (target != gDude) {
int currentDistance = objectGetDistanceBetween(critter, gDude);
if (currentDistance > 5
&& objectGetDistanceBetween(a2, gDude) > 5
&& objectGetDistanceBetween(target, gDude) > 5
&& currentDistance + actionPoints > 5) {
return -1;
}
}
}
if (objectGetDistanceBetween(a1, a2) <= 1) {
if (objectGetDistanceBetween(critter, target) <= 1) {
return -1;
}
reg_anim_begin(ANIMATION_REQUEST_RESERVED);
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;
if ((a2->flags & OBJECT_MULTIHEX) != 0) {
if ((target->flags & OBJECT_MULTIHEX) != 0) {
shouldUnhide = true;
a2->flags |= OBJECT_HIDDEN;
target->flags |= OBJECT_HIDDEN;
} else {
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;
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
&& PID_TYPE(_moveBlockObj->pid) == OBJ_TYPE_CRITTER) {
if (shouldUnhide) {
a2->flags &= ~OBJECT_HIDDEN;
target->flags &= ~OBJECT_HIDDEN;
}
a2 = _moveBlockObj;
if ((a2->flags & OBJECT_MULTIHEX) != 0) {
target = _moveBlockObj;
if ((target->flags & OBJECT_MULTIHEX) != 0) {
shouldUnhide = true;
a2->flags |= OBJECT_HIDDEN;
target->flags |= OBJECT_HIDDEN;
} else {
shouldUnhide = false;
}
@ -2389,25 +2389,25 @@ static int _ai_move_steps_closer(Object* a1, Object* a2, int actionPoints, bool
}
if (shouldUnhide) {
a2->flags &= ~OBJECT_HIDDEN;
target->flags &= ~OBJECT_HIDDEN;
}
int tile = a2->tile;
if (a2 == v18) {
_cai_retargetTileFromFriendlyFire(a1, a2, &tile);
int tile = target->tile;
if (target == initialTarget) {
_cai_retargetTileFromFriendlyFire(critter, target, &tile);
}
if (actionPoints >= critterGetStat(a1, STAT_MAXIMUM_ACTION_POINTS) / 2 && artCritterFidShouldRun(a1->fid)) {
if ((a2->flags & OBJECT_MULTIHEX) != 0) {
animationRegisterRunToObject(a1, a2, actionPoints, 0);
if (actionPoints >= critterGetStat(critter, STAT_MAXIMUM_ACTION_POINTS) / 2 && artCritterFidShouldRun(critter->fid)) {
if ((target->flags & OBJECT_MULTIHEX) != 0) {
animationRegisterRunToObject(critter, target, actionPoints, 0);
} else {
animationRegisterRunToTile(a1, tile, a1->elevation, actionPoints, 0);
animationRegisterRunToTile(critter, tile, critter->elevation, actionPoints, 0);
}
} else {
if ((a2->flags & OBJECT_MULTIHEX) != 0) {
animationRegisterMoveToObject(a1, a2, actionPoints, 0);
if ((target->flags & OBJECT_MULTIHEX) != 0) {
animationRegisterMoveToObject(critter, target, actionPoints, 0);
} 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
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;
Object* weapon = critterGetItem2(a1);
Object* weapon = critterGetItem2(attacker);
if (weapon != NULL && itemGetType(weapon) != ITEM_TYPE_WEAPON) {
weapon = NULL;
}
int hitMode = _ai_pick_hit_mode(a1, weapon, a2);
int minToHit = aiGetPacket(a1)->min_to_hit;
int hitMode = _ai_pick_hit_mode(attacker, weapon, defender);
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 v42 = 0;
int actionPointsToUse = 0;
if (weapon != NULL
|| (critterGetBodyType(a2) == BODY_TYPE_BIPED
&& ((a2->fid & 0xF000) >> 12 == 0)
&& artExists(buildFid(OBJ_TYPE_CRITTER, a1->fid & 0xFFF, ANIM_THROW_PUNCH, 0, a1->rotation + 1)))) {
|| (critterGetBodyType(defender) == BODY_TYPE_BIPED
&& ((defender->fid & 0xF000) >> 12 == 0)
&& 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
// instead of always the primary weapon hit mode.
if (_combat_safety_invalidate_weapon(a1, weapon, hitMode, a2, &safeDistance)) {
_ai_switch_weapons(a1, &hitMode, &weapon, a2);
if (_combat_safety_invalidate_weapon(attacker, weapon, hitMode, defender, &safeDistance)) {
_ai_switch_weapons(attacker, &hitMode, &weapon, defender);
}
} else {
_ai_switch_weapons(a1, &hitMode, &weapon, a2);
_ai_switch_weapons(attacker, &hitMode, &weapon, defender);
}
unsigned char rotations[800];
@ -2704,37 +2704,37 @@ static int _ai_try_attack(Object* a1, Object* a2)
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) {
// out of ammo
if (aiHaveAmmo(a1, weapon, &ammo)) {
if (aiHaveAmmo(attacker, weapon, &ammo)) {
int remainingAmmoQuantity = weaponReload(weapon, ammo);
if (remainingAmmoQuantity == 0 && ammo != NULL) {
_obj_destroy(ammo);
}
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);
_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.
// CE: There is a commented out code which checks
// available action points before performing reload. Not
// sure why it was commented, probably needs additional
// testing.
int actionPointsRequired = weaponGetActionPointCost(a1, HIT_MODE_RIGHT_WEAPON_RELOAD, false);
if (a1->data.critter.combat.ap >= actionPointsRequired) {
a1->data.critter.combat.ap -= actionPointsRequired;
int actionPointsRequired = weaponGetActionPointCost(attacker, HIT_MODE_RIGHT_WEAPON_RELOAD, false);
if (attacker->data.critter.combat.ap >= actionPointsRequired) {
attacker->data.critter.combat.ap -= actionPointsRequired;
} else {
a1->data.critter.combat.ap = 0;
attacker->data.critter.combat.ap = 0;
}
}
} else {
ammo = _ai_search_environ(a1, ITEM_TYPE_AMMO);
ammo = _ai_search_environ(attacker, ITEM_TYPE_AMMO);
if (ammo != NULL) {
ammo = _ai_retrieve_object(a1, ammo);
ammo = _ai_retrieve_object(attacker, ammo);
if (ammo != NULL) {
int remainingAmmoQuantity = weaponReload(weapon, ammo);
if (remainingAmmoQuantity == 0) {
@ -2742,62 +2742,63 @@ static int _ai_try_attack(Object* a1, Object* a2)
}
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);
_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.
// CE: See note above, probably need to check
// available action points before performing
// reload.
int actionPointsRequired = weaponGetActionPointCost(a1, HIT_MODE_RIGHT_WEAPON_RELOAD, false);
if (a1->data.critter.combat.ap >= actionPointsRequired) {
a1->data.critter.combat.ap -= actionPointsRequired;
int actionPointsRequired = weaponGetActionPointCost(attacker, HIT_MODE_RIGHT_WEAPON_RELOAD, false);
if (attacker->data.critter.combat.ap >= actionPointsRequired) {
attacker->data.critter.combat.ap -= actionPointsRequired;
} else {
a1->data.critter.combat.ap = 0;
attacker->data.critter.combat.ap = 0;
}
}
}
} 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);
_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();
}
_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) {
// 3 - not enough action points
// 6 - crippled one arm for two-handed weapon
// 7 - both hands crippled
if (_ai_switch_weapons(a1, &hitMode, &weapon, a2) == -1) {
if (_ai_switch_weapons(attacker, &hitMode, &weapon, defender) == -1) {
return -1;
}
} else if (reason == COMBAT_BAD_SHOT_OUT_OF_RANGE) {
// target out of range
int accuracy = _determine_to_hit_no_range(a1, a2, HIT_LOCATION_UNCALLED, hitMode, rotations);
if (accuracy < minToHit) {
debugPrint("%s: FLEEING: Can't possibly Hit Target!", critterGetName(a1));
_ai_run_away(a1, a2);
int toHitNoRange = _determine_to_hit_no_range(attacker, defender, HIT_LOCATION_UNCALLED, hitMode, rotations);
if (toHitNoRange < minToHit) {
// hit chance is too low even at point blank range (not taking range into account)
debugPrint("%s: FLEEING: Can't possibly Hit Target!", critterGetName(attacker));
_ai_run_away(attacker, defender);
return 0;
}
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;
}
taunt = false;
} 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.
if (_ai_move_closer(a1, a2, taunt) == -1) {
if (_ai_move_closer(attacker, defender, taunt) == -1) {
return -1;
}
}
@ -2805,66 +2806,66 @@ static int _ai_try_attack(Object* a1, Object* a2)
}
} else if (reason == COMBAT_BAD_SHOT_AIM_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;
}
taunt = false;
} 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 (_ai_move_away(a1, a2, safeDistance) == -1) {
if (_ai_move_away(attacker, defender, safeDistance) == -1) {
return -1;
}
}
if (accuracy < minToHit) {
int accuracyNoRange = _determine_to_hit_no_range(a1, a2, HIT_LOCATION_UNCALLED, hitMode, rotations);
if (accuracyNoRange < minToHit) {
debugPrint("%s: FLEEING: Can't possibly Hit Target!", critterGetName(a1));
_ai_run_away(a1, a2);
int toHitNoRange = _determine_to_hit_no_range(attacker, defender, HIT_LOCATION_UNCALLED, hitMode, rotations);
if (toHitNoRange < minToHit) {
debugPrint("%s: FLEEING: Can't possibly Hit Target!", critterGetName(attacker));
_ai_run_away(attacker, defender);
return 0;
}
if (actionPoints > 0) {
int v24 = pathfinderFindPath(a1, a1->tile, a2->tile, rotations, 0, _obj_blocking_at);
if (v24 == 0) {
v42 = actionPoints;
int pathLength = pathfinderFindPath(attacker, attacker->tile, defender->tile, rotations, 0, _obj_blocking_at);
if (pathLength == 0) {
actionPointsToUse = actionPoints;
} else {
if (v24 < actionPoints) {
actionPoints = v24;
if (pathLength < actionPoints) {
actionPoints = pathLength;
}
int tile = a1->tile;
int tile = attacker->tile;
int index;
for (index = 0; index < actionPoints; index++) {
tile = tileGetTileInDirection(tile, rotations[index], 1);
v42++;
actionPointsToUse++;
int v27 = _determine_to_hit_from_tile(a1, tile, a2, HIT_LOCATION_UNCALLED, hitMode);
if (v27 >= minToHit) {
int toHit = _determine_to_hit_from_tile(attacker, tile, defender, HIT_LOCATION_UNCALLED, hitMode);
if (toHit >= minToHit) {
break;
}
}
if (index == actionPoints) {
v42 = actionPoints;
actionPointsToUse = actionPoints;
}
}
}
if (_ai_move_steps_closer(a1, a2, v42, taunt) == -1) {
debugPrint("%s: FLEEING: Can't possibly get closer to Target!", critterGetName(a1));
_ai_run_away(a1, a2);
if (_ai_move_steps_closer(attacker, defender, actionPointsToUse, taunt) == -1) {
debugPrint("%s: FLEEING: Can't possibly get closer to Target!", critterGetName(attacker));
_ai_run_away(attacker, defender);
return 0;
}
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;
}
} 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;
}
}

View File

@ -1370,7 +1370,7 @@ char* gameSoundBuildInterfaceName(const char* a1)
// 0x451760
char* sfxBuildWeaponName(int effectType, Object* weapon, int hitMode, Object* target)
{
int v6;
int soundVariant;
char weaponSoundCode;
char effectTypeCode;
char materialCode;
@ -1384,12 +1384,12 @@ char* sfxBuildWeaponName(int effectType, Object* weapon, int hitMode, Object* ta
if (hitMode != HIT_MODE_LEFT_WEAPON_PRIMARY
&& hitMode != HIT_MODE_RIGHT_WEAPON_PRIMARY
&& hitMode != HIT_MODE_PUNCH) {
v6 = 2;
soundVariant = 2;
} else {
v6 = 1;
soundVariant = 1;
}
} else {
v6 = 1;
soundVariant = 1;
}
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);
return _sfx_file_name;
}

View File

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

View File

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

View File

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

View File

@ -71,11 +71,11 @@ Object* objectFindFirstAtLocation(int elevation, int tile);
Object* objectFindNextAtLocation();
void objectGetRect(Object* obj, Rect* rect);
bool _obj_occupied(int tile_num, int elev);
Object* _obj_blocking_at(Object* a1, int tile_num, int elev);
Object* _obj_shoot_blocking_at(Object* obj, int tile, int elev);
Object* _obj_ai_blocking_at(Object* a1, int tile, int elevation);
Object* _obj_blocking_at(Object* excludeObj, int tile_num, int elev);
Object* _obj_shoot_blocking_at(Object* excludeObj, int tile, int elev);
Object* _obj_ai_blocking_at(Object* excludeObj, int tile, int elevation);
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 objectGetDistanceBetweenTiles(Object* object1, int tile1, Object* object2, int tile2);
int objectListCreate(int tile, int elevation, int objectType, Object*** objectsPtr);

View File

@ -344,18 +344,19 @@ bool queueHasEvent(Object* owner, int eventType)
int queueProcessEvents()
{
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) {
QueueListNode* queueListNode = gQueueListHead;
if (time < queueListNode->time || v1 != 0) {
if (time < queueListNode->time || stopProcess != 0) {
break;
}
gQueueListHead = queueListNode->next;
EventTypeDescription* eventTypeDescription = &(gEventTypeDescriptions[queueListNode->type]);
v1 = eventTypeDescription->handlerProc(queueListNode->owner, queueListNode->data);
stopProcess = eventTypeDescription->handlerProc(queueListNode->owner, queueListNode->data);
if (eventTypeDescription->freeProc != NULL) {
eventTypeDescription->freeProc(queueListNode->data);
@ -364,7 +365,7 @@ int queueProcessEvents()
internal_free(queueListNode);
}
return v1;
return stopProcess;
}
// 0x4A2748

View File

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