From 836bb92e8ed6b602b980ee2393dcf93d66524f6f Mon Sep 17 00:00:00 2001 From: obligaron Date: Thu, 9 Sep 2021 19:43:32 +0200 Subject: [PATCH] MoveMissileAndCheckMissileCol: Call CheckMissileCol only once for a tile and target --- Source/loadsave.cpp | 1 + Source/missiles.cpp | 10 ++++++++++ Source/missiles.h | 4 ++++ 3 files changed, 15 insertions(+) diff --git a/Source/loadsave.cpp b/Source/loadsave.cpp index e9cf45299..1cc3d728e 100644 --- a/Source/loadsave.cpp +++ b/Source/loadsave.cpp @@ -685,6 +685,7 @@ void LoadMissile(LoadHelper *file, Missile &missile) missile.var6 = file->NextLE(); missile.var7 = file->NextLE(); missile.limitReached = file->NextBool32(); + missile.lastCollisionTargetHash = 0; } void LoadObject(LoadHelper &file, Object &object) diff --git a/Source/missiles.cpp b/Source/missiles.cpp index c76f76b28..c13354a2b 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -614,6 +614,15 @@ void MoveMissileAndCheckMissileCol(Missile &missile, int mindam, int maxdam, boo else possibleVisitTiles = prevTile.ManhattanDistance(missile.position.tile); + int16_t tileTargetHash = dMonster[missile.position.tile.x][missile.position.tile.y] ^ dPlayer[missile.position.tile.x][missile.position.tile.y]; + + if (possibleVisitTiles == 0) { + // missile didn't change the tile... check that we perform CheckMissileCol only once for any monster/player to avoid multiple hits for slow missiles + if (missile.lastCollisionTargetHash == tileTargetHash) + return; + } + // remember what target CheckMissileCol was checked against + missile.lastCollisionTargetHash = tileTargetHash; // Did the missile skipped a tile? if (possibleVisitTiles > 1) { // Implementation note: If someone knows the correct math to calculate this without this step for step increase loop, I would really appreciate it. @@ -2883,6 +2892,7 @@ int AddMissile(Point src, Point dst, Direction midir, missile_id mitype, mienemy missile._miAnimType = missileData.mFileNum; missile._miDrawFlag = missileData.mDraw; missile._mlid = NO_LIGHT; + missile.lastCollisionTargetHash = 0; if (missile._miAnimType == MFILE_NONE || MissileSpriteData[missile._miAnimType].animFAmt < 8) SetMissDir(missile, 0); diff --git a/Source/missiles.h b/Source/missiles.h index 8b8c767da..4e96f8d23 100644 --- a/Source/missiles.h +++ b/Source/missiles.h @@ -124,6 +124,10 @@ struct Missile { int var6; int var7; bool limitReached; + /** + * @brief For moving missiles lastCollisionTargetHash contains the last entity (player or monster) that was checked in CheckMissileCol (needed to avoid multiple hits for a entity at the same tile). + */ + int16_t lastCollisionTargetHash; }; extern Missile Missiles[MAXMISSILES];