Fix critters dying on exit grids

This commit is contained in:
Alexander Batalov 2022-12-13 16:33:19 +03:00
parent 280b55ab05
commit 6f62cfd466
3 changed files with 51 additions and 8 deletions

View File

@ -120,6 +120,15 @@ int actionKnockdown(Object* obj, int* anim, int maxDistance, int rotation, int d
distance--;
break;
}
// CE: Fix to prevent critters (including player) cross an exit grid as
// a result of knockback. Sfall has similar fix done differently and it
// affects the player only. This approach is better since it also
// prevents unreachable (=unlootable) corpses on exit grids.
if (isExitGridAt(tile, obj->elevation)) {
distance--;
break;
}
}
const char* soundEffectName = sfxBuildCharName(obj, *anim, CHARACTER_SOUND_EFFECT_KNOCKDOWN);
@ -349,16 +358,31 @@ void _show_damage_to_object(Object* a1, int damage, int flags, Object* weapon, b
int randomDistance = randomBetween(2, 5);
int randomRotation = randomBetween(0, 5);
while (randomDistance > 0) {
int tile = tileGetTileInDirection(a1->tile, randomRotation, randomDistance);
Object* v35 = NULL;
_make_straight_path(a1, a1->tile, tile, NULL, &v35, 4);
if (v35 == NULL) {
animationRegisterRotateToTile(a1, tile);
animationRegisterMoveToTileStraight(a1, tile, a1->elevation, anim, 0);
// CE: Fix to prevent critters (including player) to cross
// an exit grid as a result of fire dance animation. See
// `actionKnockdown` for notes.
int rotation = randomRotation;
int distance = randomDistance;
while (true) {
int tile = tileGetTileInDirection(a1->tile, (rotation + randomRotation) % ROTATION_COUNT, distance);
if (!isExitGridAt(tile, a1->elevation)) {
Object* obstacle = NULL;
_make_straight_path(a1, a1->tile, tile, NULL, &obstacle, 4);
if (obstacle == NULL) {
animationRegisterRotateToTile(a1, tile);
animationRegisterMoveToTileStraight(a1, tile, a1->elevation, anim, 0);
break;
}
}
if (distance > 0) {
distance--;
} else if (rotation < ROTATION_COUNT) {
rotation++;
distance = randomDistance;
} else {
break;
}
randomDistance--;
}
}

View File

@ -5243,4 +5243,22 @@ Object* objectTypedFindById(int id, int type)
return NULL;
}
bool isExitGridAt(int tile, int elevation)
{
ObjectListNode* objectListNode = gObjectListHeadByTile[tile];
while (objectListNode != NULL) {
Object* obj = objectListNode->obj;
if (obj->elevation == elevation) {
if ((obj->flags & OBJECT_HIDDEN) == 0) {
if (isExitGridPid(obj->pid)) {
return true;
}
}
}
objectListNode = objectListNode->next;
}
return false;
}
} // namespace fallout

View File

@ -100,6 +100,7 @@ int _obj_load_dude(File* stream);
void _obj_fix_violence_settings(int* fid);
Object* objectTypedFindById(int id, int type);
bool isExitGridAt(int tile, int elevation);
} // namespace fallout