mirror of
https://github.com/ZDoom/Raze.git
synced 2024-11-15 08:51:24 +00:00
- Blood: reworked GetClosestSpriteSectors to use dynamic arrays, deleted unused GetClosestSectors.
# Conflicts: # source/games/blood/src/aibeast.cpp # Conflicts: # source/games/blood/src/aibeast.cpp # source/games/blood/src/gameutil.h
This commit is contained in:
parent
269f2580b9
commit
1bbbeb8f4c
7 changed files with 47 additions and 93 deletions
|
@ -1683,6 +1683,12 @@ public:
|
|||
return !!(bytes[index >> 3] & (1 << (index & 7)));
|
||||
}
|
||||
|
||||
// for when array syntax cannot be used.
|
||||
bool Check(size_t index) const
|
||||
{
|
||||
return !!(bytes[index >> 3] & (1 << (index & 7)));
|
||||
}
|
||||
|
||||
void Set(size_t index, bool set = true)
|
||||
{
|
||||
if (!set) Clear(index);
|
||||
|
|
|
@ -2650,10 +2650,9 @@ int actFloorBounceVector(int* x, int* y, int* z, int nSector, int a5)
|
|||
|
||||
void actRadiusDamage(DBloodActor* source, int x, int y, int z, int nSector, int nDist, int baseDmg, int distDmg, DAMAGE_TYPE dmgType, int flags, int burn)
|
||||
{
|
||||
uint8_t sectmap[(kMaxSectors + 7) >> 3];
|
||||
auto pOwner = source->GetOwner();
|
||||
const bool newSectCheckMethod = !cl_bloodvanillaexplosions && pOwner && pOwner->IsDudeActor() && !VanillaMode(); // use new sector checking logic
|
||||
GetClosestSpriteSectors(nSector, x, y, nDist, sectmap, nullptr, newSectCheckMethod);
|
||||
auto sectorMap = GetClosestSpriteSectors(nSector, x, y, nDist, nullptr, newSectCheckMethod);
|
||||
nDist <<= 4;
|
||||
if (flags & 2)
|
||||
{
|
||||
|
@ -2666,7 +2665,7 @@ void actRadiusDamage(DBloodActor* source, int x, int y, int z, int nSector, int
|
|||
if (act2->hasX())
|
||||
{
|
||||
if (pSprite2->flags & 0x20) continue;
|
||||
if (!TestBitString(sectmap, pSprite2->sectnum)) continue;
|
||||
if (!sectorMap[pSprite2->sectnum]) continue;
|
||||
if (!CheckProximity(act2, x, y, z, nSector, nDist)) continue;
|
||||
|
||||
int dx = abs(x - pSprite2->x);
|
||||
|
@ -2693,7 +2692,7 @@ void actRadiusDamage(DBloodActor* source, int x, int y, int z, int nSector, int
|
|||
auto pSprite2 = &act2->s();
|
||||
|
||||
if (pSprite2->flags & 0x20) continue;
|
||||
if (!TestBitString(sectmap, pSprite2->sectnum)) continue;
|
||||
if (!sectorMap[pSprite2->sectnum]) continue;
|
||||
if (!CheckProximity(act2, x, y, z, nSector, nDist)) continue;
|
||||
|
||||
XSPRITE* pXSprite2 = &act2->x();
|
||||
|
@ -5930,14 +5929,12 @@ static void actCheckExplosion()
|
|||
radius = pXSprite->data4;
|
||||
#endif
|
||||
|
||||
uint8_t sectormap[(kMaxSectors + 7) >> 3];
|
||||
|
||||
// GetClosestSpriteSectors() has issues checking some sectors due to optimizations
|
||||
// the new flag newSectCheckMethod for GetClosestSpriteSectors() does rectify these issues, but this may cause unintended side effects for level scripted explosions
|
||||
// so only allow this new checking method for dude spawned explosions
|
||||
short gAffectedXWalls[kMaxXWalls];
|
||||
const bool newSectCheckMethod = !cl_bloodvanillaexplosions && Owner && Owner->IsDudeActor() && !VanillaMode(); // use new sector checking logic
|
||||
GetClosestSpriteSectors(nSector, x, y, radius, sectormap, gAffectedXWalls, newSectCheckMethod);
|
||||
auto sectorMap = GetClosestSpriteSectors(nSector, x, y, radius, gAffectedXWalls, newSectCheckMethod);
|
||||
|
||||
for (int i = 0; i < kMaxXWalls; i++)
|
||||
{
|
||||
|
@ -5955,7 +5952,7 @@ static void actCheckExplosion()
|
|||
|
||||
if (pDude->flags & 32) continue;
|
||||
|
||||
if (TestBitString(sectormap, pDude->sectnum))
|
||||
if (sectorMap[pDude->sectnum])
|
||||
{
|
||||
if (pXSprite->data1 && CheckProximity(dudeactor, x, y, z, nSector, radius))
|
||||
{
|
||||
|
@ -5984,7 +5981,7 @@ static void actCheckExplosion()
|
|||
|
||||
if (pThing->flags & 32) continue;
|
||||
|
||||
if (TestBitString(sectormap, pThing->sectnum))
|
||||
if (sectorMap[pThing->sectnum])
|
||||
{
|
||||
if (pXSprite->data1 && CheckProximity(thingactor, x, y, z, nSector, radius) && thingactor->hasX())
|
||||
{
|
||||
|
@ -6028,7 +6025,7 @@ static void actCheckExplosion()
|
|||
spritetype* pDebris = &physactor->s();
|
||||
if (pDebris->sectnum < 0 || (pDebris->flags & kHitagFree) != 0) continue;
|
||||
|
||||
if (!TestBitString(sectormap, pDebris->sectnum) || !CheckProximity(physactor, x, y, z, nSector, radius)) continue;
|
||||
if (!sectorMap[pDebris->sectnum] || !CheckProximity(physactor, x, y, z, nSector, radius)) continue;
|
||||
else debrisConcuss(Owner, i, x, y, z, pExplodeInfo->dmgType);
|
||||
}
|
||||
}
|
||||
|
@ -6042,7 +6039,7 @@ static void actCheckExplosion()
|
|||
auto impactactor = gImpactSpritesList[i];
|
||||
if (!impactactor->hasX() || impactactor->s().sectnum < 0 || (impactactor->s().flags & kHitagFree) != 0) continue;
|
||||
|
||||
if (/*pXImpact->state == pXImpact->restState ||*/ !TestBitString(sectormap, impactactor->s().sectnum) || !CheckProximity(impactactor, x, y, z, nSector, radius))
|
||||
if (/*pXImpact->state == pXImpact->restState ||*/ !sectorMap[impactactor->s().sectnum] || !CheckProximity(impactactor, x, y, z, nSector, radius))
|
||||
continue;
|
||||
|
||||
trTriggerSprite(impactactor, kCmdSpriteImpact);
|
||||
|
|
|
@ -1612,9 +1612,8 @@ void aiLookForTarget(DBloodActor* actor)
|
|||
}
|
||||
if (pXSprite->state)
|
||||
{
|
||||
uint8_t sectmap[(kMaxSectors + 7) >> 3];
|
||||
const bool newSectCheckMethod = !cl_bloodvanillaenemies && !VanillaMode(); // use new sector checking logic
|
||||
GetClosestSpriteSectors(pSprite->sectnum, pSprite->x, pSprite->y, 400, sectmap, nullptr, newSectCheckMethod);
|
||||
GetClosestSpriteSectors(pSprite->sectnum, pSprite->x, pSprite->y, 400, nullptr, newSectCheckMethod);
|
||||
|
||||
BloodStatIterator it(kStatDude);
|
||||
while (DBloodActor* actor2 = it.Next())
|
||||
|
|
|
@ -82,7 +82,6 @@ void SlashSeqCallback(int, DBloodActor* actor)
|
|||
|
||||
void StompSeqCallback(int, DBloodActor* actor1)
|
||||
{
|
||||
uint8_t sectmap[(kMaxSectors + 7) >> 3];
|
||||
spritetype* pSprite = &actor1->s();
|
||||
int dx = bcos(pSprite->ang);
|
||||
int dy = bsin(pSprite->ang);
|
||||
|
@ -94,7 +93,7 @@ void StompSeqCallback(int, DBloodActor* actor1)
|
|||
int v1c = 5 + 2 * gGameOptions.nDifficulty;
|
||||
int v10 = 25 + 30 * gGameOptions.nDifficulty;
|
||||
const bool newSectCheckMethod = !cl_bloodvanillaenemies && !VanillaMode(); // use new sector checking logic
|
||||
GetClosestSpriteSectors(nSector, x, y, vc, sectmap, nullptr, newSectCheckMethod);
|
||||
auto sectorMap = GetClosestSpriteSectors(nSector, x, y, vc, nullptr, newSectCheckMethod);
|
||||
int hit = HitScan(actor1, pSprite->z, dx, dy, 0, CLIPMASK1, 0);
|
||||
DBloodActor* actor2 = nullptr;
|
||||
actHitcodeToData(hit, &gHitInfo, &actor2);
|
||||
|
@ -112,7 +111,7 @@ void StompSeqCallback(int, DBloodActor* actor1)
|
|||
continue;
|
||||
if (pSprite2->flags & 32)
|
||||
continue;
|
||||
if (TestBitString(sectmap, pSprite2->sectnum) && CheckProximity(actor2, x, y, z, nSector, vc))
|
||||
if (sectorMap[pSprite2->sectnum] && CheckProximity(actor2, x, y, z, nSector, vc))
|
||||
{
|
||||
int top, bottom;
|
||||
GetActorExtents(actor1, &top, &bottom);
|
||||
|
@ -143,7 +142,7 @@ void StompSeqCallback(int, DBloodActor* actor1)
|
|||
spritetype* pSprite2 = &actor2->s();
|
||||
if (pSprite2->flags & 32)
|
||||
continue;
|
||||
if (TestBitString(sectmap, pSprite2->sectnum) && CheckProximity(actor2, x, y, z, nSector, vc))
|
||||
if (sectorMap[pSprite2->sectnum] && CheckProximity(actor2, x, y, z, nSector, vc))
|
||||
{
|
||||
XSPRITE* pXSprite = &actor2->x();
|
||||
if (pXSprite->locked)
|
||||
|
|
|
@ -751,73 +751,27 @@ unsigned int ClipMove(vec3_t *pos, int *nSector, int xv, int yv, int wd, int cd,
|
|||
return nRes;
|
||||
}
|
||||
|
||||
int GetClosestSectors(int nSector, int x, int y, int nDist, short *pSectors, char *pSectBit)
|
||||
{
|
||||
char sectbits[(kMaxSectors+7)>>3];
|
||||
assert(pSectors != NULL);
|
||||
memset(sectbits, 0, sizeof(sectbits));
|
||||
pSectors[0] = nSector;
|
||||
SetBitString(sectbits, nSector);
|
||||
int n = 1;
|
||||
int i = 0;
|
||||
if (pSectBit)
|
||||
{
|
||||
memset(pSectBit, 0, (kMaxSectors+7)>>3);
|
||||
SetBitString(pSectBit, nSector);
|
||||
}
|
||||
while (i < n)
|
||||
{
|
||||
int nCurSector = pSectors[i];
|
||||
int nStartWall = sector[nCurSector].wallptr;
|
||||
int nEndWall = nStartWall + sector[nCurSector].wallnum;
|
||||
walltype *pWall = &wall[nStartWall];
|
||||
for (int j = nStartWall; j < nEndWall; j++, pWall++)
|
||||
{
|
||||
int nNextSector = pWall->nextsector;
|
||||
if (nNextSector < 0)
|
||||
continue;
|
||||
if (TestBitString(sectbits, nNextSector))
|
||||
continue;
|
||||
SetBitString(sectbits, nNextSector);
|
||||
int dx = abs(wall[pWall->point2].x - x)>>4;
|
||||
int dy = abs(wall[pWall->point2].y - y)>>4;
|
||||
if (dx < nDist && dy < nDist)
|
||||
{
|
||||
if (approxDist(dx, dy) < nDist)
|
||||
{
|
||||
if (pSectBit)
|
||||
SetBitString(pSectBit, nNextSector);
|
||||
pSectors[n++] = nNextSector;
|
||||
}
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
pSectors[n] = -1;
|
||||
return n;
|
||||
}
|
||||
|
||||
int GetClosestSpriteSectors(int nSector, int x, int y, int nDist, uint8_t *pSectBit, short *pWalls, bool newSectCheckMethod)
|
||||
BitArray GetClosestSpriteSectors(int nSector, int x, int y, int nDist, short *pWalls, bool newSectCheckMethod)
|
||||
{
|
||||
// by default this function fails with sectors that linked with wide spans, or there was more than one link to the same sector. for example...
|
||||
// E6M1: throwing TNT on the stone footpath while standing on the brown road will fail due to the start/end points of the span being too far away. it'll only do damage at one end of the road
|
||||
// E1M2: throwing TNT at the double doors while standing on the train platform
|
||||
// by setting newSectCheckMethod to true these issues will be resolved
|
||||
static short pSectors[kMaxSectors];
|
||||
uint8_t sectbits[(kMaxSectors+7)>>3];
|
||||
memset(sectbits, 0, sizeof(sectbits));
|
||||
pSectors[0] = nSector;
|
||||
SetBitString(sectbits, nSector);
|
||||
int n = 1, m = 0;
|
||||
int i = 0;
|
||||
if (pSectBit)
|
||||
|
||||
BitArray sectorMap(numsectors * 2); // first half gets returned to caller, second half is internal work space.
|
||||
sectorMap.Zero();
|
||||
|
||||
unsigned sectorstart = GlobalSectorList.Size();
|
||||
unsigned i = sectorstart;
|
||||
|
||||
GlobalSectorList.Push(nSector);
|
||||
sectorMap.Set(numsectors + nSector);
|
||||
sectorMap.Set(nSector);
|
||||
int m = 0;
|
||||
|
||||
while (i < GlobalSectorList.Size()) // scan through sectors
|
||||
{
|
||||
memset(pSectBit, 0, (kMaxSectors+7)>>3);
|
||||
SetBitString(pSectBit, nSector);
|
||||
}
|
||||
while (i < n) // scan through sectors
|
||||
{
|
||||
const int nCurSector = pSectors[i];
|
||||
const int nCurSector = GlobalSectorList[i];
|
||||
const int nStartWall = sector[nCurSector].wallptr;
|
||||
const int nEndWall = nStartWall + sector[nCurSector].wallnum;
|
||||
for (int j = nStartWall; j < nEndWall; j++) // scan each wall of current sector for new sectors
|
||||
|
@ -826,7 +780,7 @@ int GetClosestSpriteSectors(int nSector, int x, int y, int nDist, uint8_t *pSect
|
|||
const int nNextSector = pWall->nextsector;
|
||||
if (nNextSector < 0) // if next wall isn't linked to a sector, skip
|
||||
continue;
|
||||
if (TestBitString(sectbits, nNextSector)) // if we've already checked this sector, skip
|
||||
if (sectorMap[numsectors + nNextSector]) // if we've already checked this sector, skip
|
||||
continue;
|
||||
bool setSectBit = true;
|
||||
bool withinRange = false;
|
||||
|
@ -876,9 +830,8 @@ int GetClosestSpriteSectors(int nSector, int x, int y, int nDist, uint8_t *pSect
|
|||
if (withinRange) // if new sector is within range, set to current sector and test walls
|
||||
{
|
||||
setSectBit = true; // sector is within range, set the sector as checked
|
||||
if (pSectBit)
|
||||
SetBitString(pSectBit, nNextSector);
|
||||
pSectors[n++] = nNextSector;
|
||||
sectorMap.Set(nNextSector);
|
||||
GlobalSectorList.Push(nNextSector);
|
||||
if (pWalls && pWall->extra > 0)
|
||||
{
|
||||
XWALL *pXWall = &xwall[pWall->extra];
|
||||
|
@ -887,13 +840,14 @@ int GetClosestSpriteSectors(int nSector, int x, int y, int nDist, uint8_t *pSect
|
|||
}
|
||||
}
|
||||
if (setSectBit)
|
||||
SetBitString(sectbits, nNextSector);
|
||||
sectorMap.Set(numsectors + nNextSector);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
pSectors[n] = -1;
|
||||
GlobalSectorList.Resize(sectorstart);
|
||||
if (pWalls) pWalls[m] = -1;
|
||||
return n;
|
||||
sectorMap.Resize(numsectors);
|
||||
return sectorMap;
|
||||
}
|
||||
|
||||
int picWidth(int nPic, int repeat) {
|
||||
|
|
|
@ -58,12 +58,13 @@ enum {
|
|||
|
||||
|
||||
// by NoOne: functions to quickly check range of specifical arrays
|
||||
// todo: get rid of these - renaming must wait because there's still code pending to be merged.
|
||||
inline bool sectRangeIsFine(int nIndex) {
|
||||
return (nIndex >= 0 && nIndex < kMaxSectors);
|
||||
return validSectorIndex(nIndex);
|
||||
}
|
||||
|
||||
inline bool wallRangeIsFine(int nIndex) {
|
||||
return (nIndex >= 0 && nIndex < kMaxWalls);
|
||||
return validWallIndex(nIndex);
|
||||
}
|
||||
///
|
||||
struct Collision;
|
||||
|
@ -83,8 +84,7 @@ void GetZRange(DBloodActor *pSprite, int *ceilZ, Collision *ceilHit, int *floorZ
|
|||
void GetZRangeAtXYZ(int x, int y, int z, int nSector, int *ceilZ, Collision *ceilHit, int *floorZ, Collision *floorHit, int nDist, unsigned int nMask, unsigned int nClipParallax = 0);
|
||||
int GetDistToLine(int x1, int y1, int x2, int y2, int x3, int y3);
|
||||
unsigned int ClipMove(vec3_t* pos, int *nSector, int xv, int yv, int wd, int cd, int fd, unsigned int nMask, int tracecount = 3);
|
||||
int GetClosestSectors(int nSector, int x, int y, int nDist, short *pSectors, char *pSectBit);
|
||||
int GetClosestSpriteSectors(int nSector, int x, int y, int nDist, uint8_t *pSectBit, short *pWalls = nullptr, bool newSectCheckMethod = false);
|
||||
BitArray GetClosestSpriteSectors(int nSector, int x, int y, int nDist, short *pWalls = nullptr, bool newSectCheckMethod = false);
|
||||
int picWidth(int nPic, int repeat);
|
||||
int picHeight(int nPic, int repeat);
|
||||
|
||||
|
|
|
@ -2659,7 +2659,6 @@ void WeaponProcess(PLAYER *pPlayer) {
|
|||
void teslaHit(DBloodActor *missileactor, int a2)
|
||||
{
|
||||
auto pMissile = &missileactor->s();
|
||||
uint8_t sectmap[(kMaxSectors+7)>>3];
|
||||
int x = pMissile->x;
|
||||
int y = pMissile->y;
|
||||
int z = pMissile->z;
|
||||
|
@ -2667,7 +2666,7 @@ void teslaHit(DBloodActor *missileactor, int a2)
|
|||
int nSector = pMissile->sectnum;
|
||||
auto owneractor = missileactor->GetOwner();
|
||||
const bool newSectCheckMethod = !cl_bloodvanillaexplosions && !VanillaMode(); // use new sector checking logic
|
||||
GetClosestSpriteSectors(nSector, x, y, nDist, sectmap, nullptr, newSectCheckMethod);
|
||||
auto sectorMap = GetClosestSpriteSectors(nSector, x, y, nDist, nullptr, newSectCheckMethod);
|
||||
bool v4 = true;
|
||||
DBloodActor* actor = nullptr;
|
||||
actHitcodeToData(a2, &gHitInfo, &actor);
|
||||
|
@ -2681,7 +2680,7 @@ void teslaHit(DBloodActor *missileactor, int a2)
|
|||
spritetype *pHitSprite = &hitactor->s();
|
||||
if (pHitSprite->flags&32)
|
||||
continue;
|
||||
if (TestBitString(sectmap, pHitSprite->sectnum) && CheckProximity(hitactor, x, y, z, nSector, nDist))
|
||||
if (sectorMap[pHitSprite->sectnum] && CheckProximity(hitactor, x, y, z, nSector, nDist))
|
||||
{
|
||||
int dx = pMissile->x-pHitSprite->x;
|
||||
int dy = pMissile->y-pHitSprite->y;
|
||||
|
@ -2698,7 +2697,7 @@ void teslaHit(DBloodActor *missileactor, int a2)
|
|||
spritetype *pHitSprite = &hitactor->s();
|
||||
if (pHitSprite->flags&32)
|
||||
continue;
|
||||
if (TestBitString(sectmap, pHitSprite->sectnum) && CheckProximity(hitactor, x, y, z, nSector, nDist))
|
||||
if (sectorMap[pHitSprite->sectnum] && CheckProximity(hitactor, x, y, z, nSector, nDist))
|
||||
{
|
||||
XSPRITE *pXSprite = &hitactor->x();
|
||||
if (!pXSprite->locked)
|
||||
|
|
Loading…
Reference in a new issue