86 lines
3.2 KiB
Diff
86 lines
3.2 KiB
Diff
# UNDF: UNDF-2026-000000975
|
|
--- a/src/projectiledef.h
|
|
+++ b/src/projectiledef.h
|
|
@@ -22,7 +22,7 @@
|
|
#ifndef __INCLUDED_PROJECTILEDEF_H__
|
|
#define __INCLUDED_PROJECTILEDEF_H__
|
|
|
|
-#include "basedef.h"
|
|
+#include "basedef.h" // SIMPLE_OBJECT, BASE_OBJECT, OBJ_PROJECTILE
|
|
#include "lib/gamelib/gtime.h"
|
|
|
|
-#include <vector>
|
|
+#include <unordered_set>
|
|
|
|
|
|
enum PROJ_STATE
|
|
@@ -49,7 +49,7 @@
|
|
WEAPON_STATS *psWStats; ///< firing weapon stats
|
|
BASE_OBJECT *psSource; ///< what fired the projectile
|
|
BASE_OBJECT *psDest; ///< target of this projectile
|
|
- std::vector<BASE_OBJECT *> psDamaged; ///< the targets that have already been dealt damage to (don't damage the same target twice)
|
|
+ std::unordered_set<BASE_OBJECT *> psDamaged; ///< the targets that have already been dealt damage to (O(1) lookup instead of O(N) linear scan)
|
|
|
|
Vector3i src = Vector3i(0, 0, 0); ///< Where projectile started
|
|
Vector3i dst = Vector3i(0, 0, 0); ///< The target coordinates
|
|
--- a/src/projectile.cpp
|
|
+++ b/src/projectile.cpp
|
|
@@ -376,7 +376,7 @@
|
|
psProj->rot.direction, psProj->rot.pitch, psProj->rot.roll,
|
|
psProj->state,
|
|
(int)psProj->expectedDamageCaused,
|
|
- (int)psProj->psDamaged.size(),
|
|
+ (int)psProj->psDamaged.size(), // unchanged: .size() works on unordered_set
|
|
};
|
|
_syncDebugIntList(function, "%c projectile = p%d;pos(%d,%d,%d),rot(%d,%d,%d),state%d,expectedDamageCaused%d,numberDamaged%u", list, ARRAY_SIZE(list));
|
|
}
|
|
@@ -869,7 +869,7 @@
|
|
BASE_OBJECT *psTempObj = *gi;
|
|
CHECK_OBJECT(psTempObj);
|
|
|
|
- if (std::find(psProj->psDamaged.begin(), psProj->psDamaged.end(), psTempObj) != psProj->psDamaged.end())
|
|
+ if (psProj->psDamaged.count(psTempObj) != 0)
|
|
{
|
|
// Dont damage one target twice
|
|
continue;
|
|
@@ -950,7 +950,7 @@
|
|
asWeap.nStat = psStats - asWeaponStats.data();
|
|
|
|
// Assume we damaged the chosen target
|
|
- psProj->psDamaged.push_back(closestCollisionObject);
|
|
+ psProj->psDamaged.insert(closestCollisionObject);
|
|
|
|
spawnedProjectile = proj_SendProjectileInternal(&asWeap, psProj, psProj->player, psProj->dst, nullptr, true, -1);
|
|
}
|
|
@@ -1290,7 +1290,7 @@
|
|
|
|
if (relativeDamage >= 0) // So long as the target wasn't killed
|
|
{
|
|
- psObj->psDamaged.push_back(psObj->psDest);
|
|
+ psObj->psDamaged.insert(psObj->psDest);
|
|
}
|
|
}
|
|
}
|
|
@@ -1396,7 +1396,10 @@
|
|
setProjectileDestination(psObj, nullptr);
|
|
}
|
|
// Remove dead objects from psDamaged.
|
|
- psDamaged.erase(std::remove_if(psDamaged.begin(), psDamaged.end(), [](const BASE_OBJECT *psObj) { return ::isDead(psObj); }), psDamaged.end());
|
|
+ for (auto it = psDamaged.begin(); it != psDamaged.end(); )
|
|
+ {
|
|
+ it = ::isDead(*it) ? psDamaged.erase(it) : std::next(it);
|
|
+ }
|
|
|
|
// This extra check fixes a crash in cam2, mission1
|
|
if (worldOnMap(psObj->pos.x, psObj->pos.y) == false)
|
|
@@ -1954,9 +1957,9 @@
|
|
checkObject(psProjectile->psSource, location_description, function, recurse - 1);
|
|
}
|
|
|
|
- for (unsigned n = 0; n != psProjectile->psDamaged.size(); ++n)
|
|
+ for (const auto *psObj : psProjectile->psDamaged)
|
|
{
|
|
- checkObject(psProjectile->psDamaged[n], location_description, function, recurse - 1);
|
|
+ checkObject(psObj, location_description, function, recurse - 1);
|
|
}
|
|
}
|