Improve code readability (#315)
This commit is contained in:
parent
c4c2806071
commit
ffe90eef49
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
273
src/combat.cc
273
src/combat.cc
|
@ -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;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
14
src/combat.h
14
src/combat.h
|
@ -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);
|
||||||
|
|
183
src/combat_ai.cc
183
src/combat_ai.cc
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue