diff --git a/Source/missiles.cpp b/Source/missiles.cpp index ba1e977da..e637204d5 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -547,40 +547,21 @@ void CheckMissileCol(Missile &missile, int mindam, int maxdam, bool shift, Point } } } - if (dObject[mx][my] != 0) { - Object &object = Objects[abs(dObject[mx][my]) - 1]; - if (!object._oMissFlag) { - if (object.IsBreakable()) { - BreakObject(-1, object); - } - if (!nodel) - missile._mirange = 0; - missile._miHitFlag = false; + if (IsMissileBlockedByTile({ mx, my })) { + Object *object = ObjectAtPosition({ mx, my }); + if (object != nullptr && object->IsBreakable()) { + BreakObject(-1, *object); } - } - if (nMissileTable[dPiece[mx][my]]) { + if (!nodel) missile._mirange = 0; missile._miHitFlag = false; } + if (missile._mirange == 0 && MissilesData[missile._mitype].miSFX != -1) PlaySfxLoc(MissilesData[missile._mitype].miSFX, missile.position.tile); } -/** - * @brief Could the missile collide with solid objects? (like walls or closed doors) - */ -bool CouldMissileCollideWithSolidObject(Point tile) -{ - int oid = dObject[tile.x][tile.y]; - if (oid != 0) { - oid = abs(oid) - 1; - if (!Objects[oid]._oMissFlag) - return true; - } - return nMissileTable[dPiece[tile.x][tile.y]]; -} - void MoveMissileAndCheckMissileCol(Missile &missile, int mindam, int maxdam, bool ignoreStart, bool ifCollidesDontMoveToHitTile) { Point prevTile = missile.position.tile; @@ -633,7 +614,7 @@ void MoveMissileAndCheckMissileCol(Missile &missile, int mindam, int maxdam, boo if (missile._mirange != 0) continue; - if ((missile._miHitFlag && MissilesData[missile._mitype].MovementDistribution == MissileMovementDistrubution::Blockable) || CouldMissileCollideWithSolidObject(tile)) { + if ((missile._miHitFlag && MissilesData[missile._mitype].MovementDistribution == MissileMovementDistrubution::Blockable) || IsMissileBlockedByTile(tile)) { missile.position.traveled = traveled; if (ifCollidesDontMoveToHitTile && missile._mirange == 0) { missile.position.traveled -= incVelocity; @@ -839,6 +820,21 @@ void SpawnLightning(Missile &missile, int dam) } // namespace +bool IsMissileBlockedByTile(Point tile) +{ + if (!InDungeonBounds(tile)) { + return true; + } + + if (nMissileTable[dPiece[tile.x][tile.y]]) { + return true; + } + + Object *object = ObjectAtPosition(tile); + // _oMissFlag is true if the object allows missiles to pass through so we need to invert the check here... + return object != nullptr && !object->_oMissFlag; +} + void GetDamageAmt(int i, int *mind, int *maxd) { assert(MyPlayerId >= 0 && MyPlayerId < MAX_PLRS); diff --git a/Source/missiles.h b/Source/missiles.h index ef48baa57..27d546a17 100644 --- a/Source/missiles.h +++ b/Source/missiles.h @@ -168,6 +168,11 @@ void DeleteMissile(int i); bool MonsterTrapHit(int m, int mindam, int maxdam, int dist, missile_id t, bool shift); bool PlayerMHit(int pnum, Monster *monster, int dist, int mind, int maxd, missile_id mtype, bool shift, int earflag, bool *blocked); +/** + * @brief Could the missile collide with solid objects? (like walls or closed doors) + */ +bool IsMissileBlockedByTile(Point position); + /** * @brief Sets the missile sprite to the given sheet frame * @param missile this object diff --git a/Source/objects.h b/Source/objects.h index 5b9e23b70..e080b67ef 100644 --- a/Source/objects.h +++ b/Source/objects.h @@ -33,6 +33,7 @@ struct Object { bool _oDelFlag; int8_t _oBreak; bool _oSolidFlag; + /** True if the object allows missiles to pass through, false if it collides with missiles */ bool _oMissFlag; uint8_t _oSelFlag; bool _oPreFlag; diff --git a/Source/scrollrt.cpp b/Source/scrollrt.cpp index bbaa2bb91..07b1f2340 100644 --- a/Source/scrollrt.cpp +++ b/Source/scrollrt.cpp @@ -106,13 +106,8 @@ bool CouldMissileCollide(Point tile, bool checkPlayerAndMonster) if (dPlayer[tile.x][tile.y] > 0) return true; } - int oid = dObject[tile.x][tile.y]; - if (oid != 0) { - oid = abs(oid) - 1; - if (!Objects[oid]._oMissFlag) - return true; - } - return nMissileTable[dPiece[tile.x][tile.y]]; + + return IsMissileBlockedByTile(tile); } void UpdateMissileRendererData(Missile &m)