From 6f62cfd46667226752faec6680356b56db6d5767 Mon Sep 17 00:00:00 2001 From: Alexander Batalov Date: Tue, 13 Dec 2022 16:33:19 +0300 Subject: [PATCH] Fix critters dying on exit grids --- src/actions.cc | 40 ++++++++++++++++++++++++++++++++-------- src/object.cc | 18 ++++++++++++++++++ src/object.h | 1 + 3 files changed, 51 insertions(+), 8 deletions(-) diff --git a/src/actions.cc b/src/actions.cc index 1c4daab..416b930 100644 --- a/src/actions.cc +++ b/src/actions.cc @@ -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--; } } diff --git a/src/object.cc b/src/object.cc index 3bf12ea..29f64d4 100644 --- a/src/object.cc +++ b/src/object.cc @@ -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 diff --git a/src/object.h b/src/object.h index c1005e4..c397317 100644 --- a/src/object.h +++ b/src/object.h @@ -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