mirror of
https://github.com/ZDoom/Raze.git
synced 2025-06-03 18:50:51 +00:00
- hitscan fully rewritten.
No traces of Build code left here! :)
This commit is contained in:
parent
babbad83af
commit
74cf9a2ff2
7 changed files with 194 additions and 237 deletions
|
@ -137,21 +137,7 @@ inline void getzrange(const DVector3& pos, sectortype* sect, double* ceilz, Coll
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
extern vec2_t hitscangoal;
|
|
||||||
|
|
||||||
struct HitInfoBase;
|
struct HitInfoBase;
|
||||||
int hitscan(const vec3_t& start, const sectortype* startsect, const vec3_t& direction, HitInfoBase& hitinfo, unsigned cliptype);
|
|
||||||
inline int hitscan(const DVector3& start, const sectortype* startsect, const DVector3& direction, HitInfoBase& hitinfo, unsigned cliptype)
|
|
||||||
{
|
|
||||||
vec3_t istart(int(start.X * worldtoint), int(start.Y * worldtoint), int(start.Z * zworldtoint) );
|
|
||||||
vec3_t idir( int(direction.X * worldtoint), int(direction.Y * worldtoint), int(direction.Z * zworldtoint) );
|
|
||||||
return hitscan(istart, startsect, idir, hitinfo, cliptype);
|
|
||||||
}
|
|
||||||
inline int hitscan(const DVector3& start, const sectortype* startsect, const vec3_t& direction, HitInfoBase& hitinfo, unsigned cliptype)
|
|
||||||
{
|
|
||||||
vec3_t istart(int(start.X * worldtoint), int(start.Y * worldtoint), int(start.Z * zworldtoint));
|
|
||||||
return hitscan(istart, startsect, direction, hitinfo, cliptype);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int32_t krand(void)
|
inline int32_t krand(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1091,190 +1091,3 @@ void getzrange(const vec3_t& pos, sectortype* sect, int32_t* ceilz, CollisionBas
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void hit_set(HitInfoBase *hit, sectortype* sect, walltype* wal, DCoreActor* actor, int32_t x, int32_t y, int32_t z)
|
|
||||||
{
|
|
||||||
hit->hitSector = sect;
|
|
||||||
hit->hitWall = wal;
|
|
||||||
hit->hitActor = actor;
|
|
||||||
hit->hitpos.X = x * inttoworld;
|
|
||||||
hit->hitpos.Y = y * inttoworld;
|
|
||||||
hit->hitpos.Z = z * zinttoworld;
|
|
||||||
}
|
|
||||||
|
|
||||||
// stat, heinum, z: either ceiling- or floor-
|
|
||||||
// how: -1: behave like ceiling, 1: behave like floor
|
|
||||||
static int32_t hitscan_trysector(const vec3_t *sv, sectortype* sec, HitInfoBase *hit,
|
|
||||||
int32_t vx, int32_t vy, int32_t vz,
|
|
||||||
uint16_t stat, int16_t heinum, int32_t z, int32_t how)
|
|
||||||
{
|
|
||||||
int32_t x1 = INT32_MAX, y1 = 0, z1 = 0;
|
|
||||||
int32_t i;
|
|
||||||
|
|
||||||
if (stat&2)
|
|
||||||
{
|
|
||||||
auto const wal = sec->firstWall();
|
|
||||||
auto const wal2 = wal->point2Wall();
|
|
||||||
int32_t j, dax=wal2->wall_int_pos().X-wal->wall_int_pos().X, day=wal2->wall_int_pos().Y-wal->wall_int_pos().Y;
|
|
||||||
|
|
||||||
i = ksqrt(compat_maybe_truncate_to_int32(uhypsq(dax,day))); if (i == 0) return 1; //continue;
|
|
||||||
i = DivScale(heinum,i, 15);
|
|
||||||
dax *= i; day *= i;
|
|
||||||
|
|
||||||
j = (vz<<8)-DMulScale(dax,vy,-day,vx, 15);
|
|
||||||
if (j != 0)
|
|
||||||
{
|
|
||||||
i = ((z - sv->Z)<<8)+DMulScale(dax,sv->Y-wal->wall_int_pos().Y,-day,sv->X-wal->wall_int_pos().X, 15);
|
|
||||||
if (((i^j) >= 0) && ((abs(i)>>1) < abs(j)))
|
|
||||||
{
|
|
||||||
i = DivScale(i,j, 30);
|
|
||||||
x1 = sv->X + MulScale(vx,i, 30);
|
|
||||||
y1 = sv->Y + MulScale(vy,i, 30);
|
|
||||||
z1 = sv->Z + MulScale(vz,i, 30);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ((how*vz > 0) && (how*sv->Z <= how*z))
|
|
||||||
{
|
|
||||||
z1 = z; i = z1-sv->Z;
|
|
||||||
if ((abs(i)>>1) < vz*how)
|
|
||||||
{
|
|
||||||
i = DivScale(i,vz, 30);
|
|
||||||
x1 = sv->X + MulScale(vx,i, 30);
|
|
||||||
y1 = sv->Y + MulScale(vy,i, 30);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((x1 != INT32_MAX) && (abs(x1-sv->X)+abs(y1-sv->Y) < abs((hit->int_hitpos().X)-sv->X)+abs((hit->int_hitpos().Y)-sv->Y)))
|
|
||||||
{
|
|
||||||
if (inside(x1,y1,sec) == 1)
|
|
||||||
{
|
|
||||||
hit_set(hit, sec, nullptr, nullptr, x1, y1, z1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// hitscan
|
|
||||||
//
|
|
||||||
|
|
||||||
int hitscan(const vec3_t& start, const sectortype* startsect, const vec3_t& direction, HitInfoBase& hitinfo, unsigned cliptype)
|
|
||||||
{
|
|
||||||
auto const sv = &start;
|
|
||||||
int const vx = direction.X, vy = direction.Y, vz = direction.Z;
|
|
||||||
int32_t x1, y1=0, z1=0, x2, y2, intx, inty, intz;
|
|
||||||
int32_t i, k, daz;
|
|
||||||
double hitfactor = DBL_MAX;
|
|
||||||
|
|
||||||
const int32_t dawalclipmask = (cliptype&65535);
|
|
||||||
const int32_t dasprclipmask = (cliptype >> 16);
|
|
||||||
|
|
||||||
hitinfo.clearObj(); // note that this case leaves hitpos untouched.
|
|
||||||
if (startsect == nullptr)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
hitinfo.hitpos.X = hitscangoal.X * inttoworld;
|
|
||||||
hitinfo.hitpos.Y = hitscangoal.Y * inttoworld;
|
|
||||||
|
|
||||||
BFSSectorSearch search(startsect);
|
|
||||||
while (auto sec = search.GetNext())
|
|
||||||
{
|
|
||||||
i = 1;
|
|
||||||
if (hitscan_trysector(sv, sec, &hitinfo, vx,vy,vz, sec->ceilingstat, sec->ceilingheinum, sec->int_ceilingz(), -i))
|
|
||||||
continue;
|
|
||||||
if (hitscan_trysector(sv, sec, &hitinfo, vx,vy,vz, sec->floorstat, sec->floorheinum, sec->int_floorz(), i))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
////////// Walls //////////
|
|
||||||
|
|
||||||
for(auto& w : wallsofsector(sec))
|
|
||||||
{
|
|
||||||
auto wal = &w;
|
|
||||||
auto wal2 = wal->point2Wall();
|
|
||||||
|
|
||||||
auto const nextsect = wal->nextSector();
|
|
||||||
|
|
||||||
x1 = wal->wall_int_pos().X; y1 = wal->wall_int_pos().Y; x2 = wal2->wall_int_pos().X; y2 = wal2->wall_int_pos().Y;
|
|
||||||
|
|
||||||
if (compat_maybe_truncate_to_int32((coord_t)(x1-sv->X)*(y2-sv->Y))
|
|
||||||
< compat_maybe_truncate_to_int32((coord_t)(x2-sv->X)*(y1-sv->Y))) continue;
|
|
||||||
if (rintersect(sv->X,sv->Y,sv->Z, vx,vy,vz, x1,y1, x2,y2, &intx,&inty,&intz) == -1) continue;
|
|
||||||
|
|
||||||
// temporary crutch
|
|
||||||
DVector2 vec(vx, vy);
|
|
||||||
DVector2 newvec(intx - sv->X, inty - sv->Y);
|
|
||||||
double newfactor = newvec.Sum() / vec.Sum();
|
|
||||||
if (newfactor >= hitfactor) continue;
|
|
||||||
|
|
||||||
if ((!wal->twoSided()) || (wal->cstat & EWallFlags::FromInt(dawalclipmask)))
|
|
||||||
{
|
|
||||||
hitfactor = newfactor;
|
|
||||||
hit_set(&hitinfo, sec, wal, nullptr, intx, inty, intz);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t daz2;
|
|
||||||
int_getzsofslopeptr(nextsect,intx,inty,&daz,&daz2);
|
|
||||||
if (intz <= daz || intz >= daz2)
|
|
||||||
{
|
|
||||||
hitfactor = newfactor;
|
|
||||||
hit_set(&hitinfo, sec, wal, nullptr, intx, inty, intz);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
search.Add(nextsect);
|
|
||||||
}
|
|
||||||
|
|
||||||
////////// Sprites //////////
|
|
||||||
|
|
||||||
if (dasprclipmask==0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
DVector3 start(sv->X * inttoworld, sv->Y * inttoworld, sv->Z * zinttoworld);
|
|
||||||
DVector3 vect(vx * inttoworld, vy * inttoworld, vz * zinttoworld);
|
|
||||||
|
|
||||||
TSectIterator<DCoreActor> it(sec);
|
|
||||||
while (auto actor = it.Next())
|
|
||||||
{
|
|
||||||
uint32_t const cstat = actor->spr.cstat;
|
|
||||||
|
|
||||||
if (actor->spr.cstat2 & CSTAT2_SPRITE_NOFIND)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if ((cstat&dasprclipmask) == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
DVector3 v;
|
|
||||||
double hit = -1;
|
|
||||||
// we pass hitfactor to the workers because it can shortcut their calculations a lot.
|
|
||||||
switch (cstat&CSTAT_SPRITE_ALIGNMENT_MASK)
|
|
||||||
{
|
|
||||||
case CSTAT_SPRITE_ALIGNMENT_FACING:
|
|
||||||
hit = intersectSprite(actor, start, vect, v, hitfactor);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CSTAT_SPRITE_ALIGNMENT_WALL:
|
|
||||||
hit = intersectWallSprite(actor, start, vect, v, hitfactor, (picanm[actor->spr.picnum].sf & PICANM_TEXHITSCAN_BIT));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CSTAT_SPRITE_ALIGNMENT_FLOOR:
|
|
||||||
hit = intersectFloorSprite(actor, start, vect, v, hitfactor);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CSTAT_SPRITE_ALIGNMENT_SLOPE:
|
|
||||||
hit = intersectSlopeSprite(actor, start, vect, v, hitfactor);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (hit > 0)
|
|
||||||
{
|
|
||||||
hitfactor = hit;
|
|
||||||
hitinfo.set(sec, nullptr, actor, v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
|
@ -228,20 +228,14 @@ extern TArray<walltype> wall;
|
||||||
|
|
||||||
|
|
||||||
// Masking these into the object index to keep it in 16 bit was probably the single most dumbest and pointless thing Build ever did.
|
// Masking these into the object index to keep it in 16 bit was probably the single most dumbest and pointless thing Build ever did.
|
||||||
// Gonna be fun to globally replace these to finally lift the limit this imposes on map size.
|
|
||||||
// Names taken from DukeGDX
|
// Names taken from DukeGDX
|
||||||
enum EHitBits
|
enum EHitBits
|
||||||
{
|
{
|
||||||
kHitNone = 0,
|
kHitNone = 0,
|
||||||
kHitTypeMask = 0xC000,
|
|
||||||
kHitTypeMaskSW = 0x1C000, // SW has one more relevant bit
|
|
||||||
kHitIndexMask = 0x3FFF,
|
|
||||||
kHitSector = 0x4000,
|
kHitSector = 0x4000,
|
||||||
kHitWall = 0x8000,
|
kHitWall = 0x8000,
|
||||||
kHitSprite = 0xC000,
|
kHitSprite = 0xC000,
|
||||||
kHitVoid = 0x10000, // SW only
|
kHitVoid = 0x10000, // SW only
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// This serves as input/output for all functions dealing with collisions, hits, etc.
|
// This serves as input/output for all functions dealing with collisions, hits, etc.
|
||||||
|
|
|
@ -140,7 +140,7 @@ void calcSlope(const sectortype* sec, double xpos, double ypos, double* pceilz,
|
||||||
double len = wal->Length();
|
double len = wal->Length();
|
||||||
if (len != 0)
|
if (len != 0)
|
||||||
{
|
{
|
||||||
float fac = (wal->delta().X * (ypos - wal->pos.Y) - wal->delta().Y * (xpos - wal->pos.X)) / len * (1. / SLOPEVAL_FACTOR);
|
double fac = (wal->delta().X * (ypos - wal->pos.Y) - wal->delta().Y * (xpos - wal->pos.X)) / len * (1. / SLOPEVAL_FACTOR);
|
||||||
if (pceilz && sec->ceilingstat & CSTAT_SECTOR_SLOPE) *pceilz += (sec->ceilingheinum * fac);
|
if (pceilz && sec->ceilingstat & CSTAT_SECTOR_SLOPE) *pceilz += (sec->ceilingheinum * fac);
|
||||||
if (pflorz && sec->floorstat & CSTAT_SECTOR_SLOPE) *pflorz += (sec->floorheinum * fac);
|
if (pflorz && sec->floorstat & CSTAT_SECTOR_SLOPE) *pflorz += (sec->floorheinum * fac);
|
||||||
}
|
}
|
||||||
|
@ -631,9 +631,9 @@ double intersectWallSprite(DCoreActor* actor, const DVector3& start, const DVect
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
double factor2;
|
// the wall factor is needed for doing a texture check.
|
||||||
double factor = InterceptLineSegments(start.X, start.Y, direction.X, direction.Y, points[0].X, points[0].Y, points[1].X, points[1].Y, &factor2);
|
double factor2, factor = InterceptLineSegments(start.X, start.Y, direction.X, direction.Y, points[0].X, points[0].Y, points[1].X, points[1].Y, &factor2);
|
||||||
if (factor < 0 || factor > maxfactor || factor2 < 0 || factor2 > 1) return -1;
|
if (factor < 0 || factor > maxfactor) return -1;
|
||||||
|
|
||||||
result = start + factor * direction;
|
result = start + factor * direction;
|
||||||
|
|
||||||
|
@ -715,6 +715,182 @@ double intersectSlopeSprite(DCoreActor* actor, const DVector3& start, const DVec
|
||||||
return factor;
|
return factor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
double checkWallHit(walltype* wal, EWallFlags flagmask, const DVector3& start, const DVector3& direction, DVector3& result, double maxfactor)
|
||||||
|
{
|
||||||
|
if (PointOnLineSide(start.XY(), wal) > 0) return -1;
|
||||||
|
|
||||||
|
double factor = InterceptLineSegments(start.X, start.Y, direction.X, direction.Y, wal->pos.X, wal->pos.Y, wal->delta().X, wal->delta().Y);
|
||||||
|
if (factor <= 0 || factor > maxfactor) return -1; // did not connect.
|
||||||
|
|
||||||
|
result = start + factor * direction;
|
||||||
|
if (wal->twoSided() && !(wal->cstat & flagmask))
|
||||||
|
{
|
||||||
|
// check if the trace passes this wall or hits the upper or lower tier.
|
||||||
|
double cz, fz;
|
||||||
|
getzsofslopeptr(wal->nextSector(), result, &cz, &fz);
|
||||||
|
if (result.Z > cz && result.Z < fz) return -2; // trace will pass this wall, i.e. no hit. Return -2 to tell the caller to go on.
|
||||||
|
}
|
||||||
|
return factor;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
double checkSectorPlaneHit(sectortype* sec, const DVector3& start, const DVector3& direction, DVector3& result, double maxfactor)
|
||||||
|
{
|
||||||
|
if (sec->wallnum < 3) return -1;
|
||||||
|
auto wal = sec->firstWall();
|
||||||
|
double len = wal->Length();
|
||||||
|
|
||||||
|
double startcz, startfz;
|
||||||
|
calcSlope(sec, start.X, start.Y, &startcz, &startfz);
|
||||||
|
|
||||||
|
for (int i = 0; i < 2; i++)
|
||||||
|
{
|
||||||
|
int heinum;
|
||||||
|
double factor = -1, z;
|
||||||
|
bool sloped;
|
||||||
|
|
||||||
|
if (i == 0)
|
||||||
|
{
|
||||||
|
if (start.Z <= startcz) continue;
|
||||||
|
heinum = (sec->ceilingstat & CSTAT_SECTOR_SLOPE) && len > 0 ? sec->ceilingheinum : 0;
|
||||||
|
z = sec->ceilingz;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (start.Z >= startfz) continue;
|
||||||
|
heinum = (sec->floorstat & CSTAT_SECTOR_SLOPE) && len > 0 ? sec->floorheinum : 0;
|
||||||
|
z = sec->floorz;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (heinum)
|
||||||
|
{
|
||||||
|
auto delta = wal->delta() * heinum * (1. / SLOPEVAL_FACTOR) / len;
|
||||||
|
|
||||||
|
double den = direction.Z - delta.dot(direction.XY().Rotated90CW());
|
||||||
|
if (den != 0)
|
||||||
|
{
|
||||||
|
auto stdelta = wal->pos - start;
|
||||||
|
factor = (z - start.Z + delta.dot(stdelta.Rotated90CW())) / den;
|
||||||
|
}
|
||||||
|
else continue;
|
||||||
|
}
|
||||||
|
else if (direction.Z != 0)
|
||||||
|
{
|
||||||
|
factor = (z - start.Z) / direction.Z;
|
||||||
|
}
|
||||||
|
if (factor > 0 && factor <= maxfactor)
|
||||||
|
{
|
||||||
|
result = start + factor * direction;
|
||||||
|
return inside(result.X, result.Y, sec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
int hitscan(const DVector3& start, const sectortype* startsect, const DVector3& vect, HitInfoBase& hitinfo, unsigned cliptype, const DVector2* goal)
|
||||||
|
{
|
||||||
|
double hitfactor = DBL_MAX;
|
||||||
|
|
||||||
|
const auto wallflags = EWallFlags::FromInt(cliptype & 65535);
|
||||||
|
const auto spriteflags = ESpriteFlags::FromInt(cliptype >> 16);
|
||||||
|
|
||||||
|
hitinfo.clearObj();
|
||||||
|
if (startsect == nullptr)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (goal)
|
||||||
|
{
|
||||||
|
hitinfo.hitpos.XY() = *goal;
|
||||||
|
hitfactor = (*goal - start.XY()).Sum() / vect.Sum();
|
||||||
|
}
|
||||||
|
else hitinfo.hitpos.X = hitinfo.hitpos.Y = DBL_MAX;
|
||||||
|
|
||||||
|
BFSSectorSearch search(startsect);
|
||||||
|
while (auto sec = search.GetNext())
|
||||||
|
{
|
||||||
|
DVector3 v;
|
||||||
|
double hit = checkSectorPlaneHit(sec, start, vect, v, hitfactor);
|
||||||
|
if (hit > 0)
|
||||||
|
{
|
||||||
|
hitfactor = hit;
|
||||||
|
hitinfo.set(sec, nullptr, nullptr, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
// check all walls in this sector
|
||||||
|
for (auto& w : wallsofsector(sec))
|
||||||
|
{
|
||||||
|
hit = checkWallHit(&w, EWallFlags::FromInt(wallflags), start, vect, v, hitfactor);
|
||||||
|
if (hit > 0)
|
||||||
|
{
|
||||||
|
hitfactor = hit;
|
||||||
|
hitinfo.set(sec, &w, nullptr, v);
|
||||||
|
}
|
||||||
|
else if (hit == -2)
|
||||||
|
search.Add(w.nextSector());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!spriteflags)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
//Check all sprites in this sector
|
||||||
|
TSectIterator<DCoreActor> it(sec);
|
||||||
|
while (auto actor = it.Next())
|
||||||
|
{
|
||||||
|
if (actor->spr.cstat2 & CSTAT2_SPRITE_NOFIND)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!(actor->spr.cstat & spriteflags))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
hit = -1;
|
||||||
|
// we pass hitfactor to the workers because it can shortcut their calculations a lot.
|
||||||
|
switch (actor->spr.cstat & CSTAT_SPRITE_ALIGNMENT_MASK)
|
||||||
|
{
|
||||||
|
case CSTAT_SPRITE_ALIGNMENT_FACING:
|
||||||
|
hit = intersectSprite(actor, start, vect, v, hitfactor);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CSTAT_SPRITE_ALIGNMENT_WALL:
|
||||||
|
hit = intersectWallSprite(actor, start, vect, v, hitfactor, (picanm[actor->spr.picnum].sf & PICANM_TEXHITSCAN_BIT));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CSTAT_SPRITE_ALIGNMENT_FLOOR:
|
||||||
|
hit = intersectFloorSprite(actor, start, vect, v, hitfactor);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CSTAT_SPRITE_ALIGNMENT_SLOPE:
|
||||||
|
hit = intersectSlopeSprite(actor, start, vect, v, hitfactor);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (hit > 0)
|
||||||
|
{
|
||||||
|
hitfactor = hit;
|
||||||
|
hitinfo.set(sec, nullptr, actor, v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
|
|
|
@ -274,8 +274,11 @@ double intersectSprite(DCoreActor* actor, const DVector3& start, const DVector3&
|
||||||
double intersectWallSprite(DCoreActor* actor, const DVector3& start, const DVector3& direction, DVector3& result, double maxfactor, bool checktex = false);
|
double intersectWallSprite(DCoreActor* actor, const DVector3& start, const DVector3& direction, DVector3& result, double maxfactor, bool checktex = false);
|
||||||
double intersectFloorSprite(DCoreActor* actor, const DVector3& start, const DVector3& direction, DVector3& result, double maxfactor);
|
double intersectFloorSprite(DCoreActor* actor, const DVector3& start, const DVector3& direction, DVector3& result, double maxfactor);
|
||||||
double intersectSlopeSprite(DCoreActor* actor, const DVector3& start, const DVector3& direction, DVector3& result, double maxfactor);
|
double intersectSlopeSprite(DCoreActor* actor, const DVector3& start, const DVector3& direction, DVector3& result, double maxfactor);
|
||||||
|
double checkWallHit(walltype* wal, EWallFlags flagmask, const DVector3& start, const DVector3& direction, DVector3& result, double maxfactor);
|
||||||
|
double checkSectorPlaneHit(sectortype* sec, const DVector3& start, const DVector3& direction, DVector3& result, double maxfactor);
|
||||||
void neartag(const DVector3& start, sectortype* sect, DAngle angle, HitInfoBase& result, double neartagrange, int tagsearch);
|
void neartag(const DVector3& start, sectortype* sect, DAngle angle, HitInfoBase& result, double neartagrange, int tagsearch);
|
||||||
int testpointinquad(const DVector2& pt, const DVector2* quad);
|
int testpointinquad(const DVector2& pt, const DVector2* quad);
|
||||||
|
int hitscan(const DVector3& start, const sectortype* startsect, const DVector3& vect, HitInfoBase& hitinfo, unsigned cliptype, const DVector2* goal = nullptr);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -289,22 +289,13 @@ int HitScan(DBloodActor* actor, int z, int dx, int dy, int dz, unsigned int nMas
|
||||||
assert(actor != nullptr);
|
assert(actor != nullptr);
|
||||||
assert(dx != 0 || dy != 0);
|
assert(dx != 0 || dy != 0);
|
||||||
gHitInfo.clearObj();
|
gHitInfo.clearObj();
|
||||||
int x = actor->int_pos().X;
|
|
||||||
int y = actor->int_pos().Y;
|
|
||||||
auto bakCstat = actor->spr.cstat;
|
auto bakCstat = actor->spr.cstat;
|
||||||
actor->spr.cstat &= ~CSTAT_SPRITE_BLOCK_HITSCAN;
|
actor->spr.cstat &= ~CSTAT_SPRITE_BLOCK_HITSCAN;
|
||||||
if (nRange)
|
DVector2 hitscangoal;
|
||||||
{
|
if (nRange) hitscangoal = actor->spr.pos.XY() + actor->spr.angle.ToVector() * nRange;
|
||||||
hitscangoal.X = x + MulScale(nRange << 4, Cos(actor->int_ang()), 30);
|
else hitscangoal.Zero();
|
||||||
hitscangoal.Y = y + MulScale(nRange << 4, Sin(actor->int_ang()), 30);
|
hitscan(DVector3(actor->spr.pos.XY(), z * zinttoworld), actor->sector(), DVector3(dx, dy, dz) * inttoworld, gHitInfo, nMask, & hitscangoal);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
hitscangoal.X = hitscangoal.Y = 0x1fffffff;
|
|
||||||
}
|
|
||||||
hitscan(vec3_t( x, y, z ), actor->sector(), { dx, dy, dz << 4 }, gHitInfo, nMask);
|
|
||||||
|
|
||||||
hitscangoal.X = hitscangoal.Y = 0x1fffffff;
|
|
||||||
actor->spr.cstat = bakCstat;
|
actor->spr.cstat = bakCstat;
|
||||||
if (gHitInfo.actor() != nullptr)
|
if (gHitInfo.actor() != nullptr)
|
||||||
return 3;
|
return 3;
|
||||||
|
@ -340,19 +331,13 @@ int VectorScan(DBloodActor* actor, double nOffset, double nZOffset, const DVecto
|
||||||
auto pos = actor->spr.pos.plusZ(nZOffset) + (actor->spr.angle + DAngle90).ToVector() * nOffset;
|
auto pos = actor->spr.pos.plusZ(nZOffset) + (actor->spr.angle + DAngle90).ToVector() * nOffset;
|
||||||
auto bakCstat = actor->spr.cstat;
|
auto bakCstat = actor->spr.cstat;
|
||||||
actor->spr.cstat &= ~CSTAT_SPRITE_BLOCK_HITSCAN;
|
actor->spr.cstat &= ~CSTAT_SPRITE_BLOCK_HITSCAN;
|
||||||
if (nRange)
|
|
||||||
{
|
|
||||||
auto goal = pos.XY() + actor->spr.angle.ToVector() * nRange;
|
|
||||||
hitscangoal.X = goal.X * worldtoint;
|
|
||||||
hitscangoal.Y = goal.Y * worldtoint;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
hitscangoal.X = hitscangoal.Y = 0x1fffffff;
|
|
||||||
}
|
|
||||||
hitscan(pos, actor->sector(), vel, gHitInfo, CLIPMASK1);
|
|
||||||
|
|
||||||
hitscangoal.X = hitscangoal.Y = 0x1ffffff;
|
DVector2 hitscangoal;
|
||||||
|
if (nRange) hitscangoal = actor->spr.pos.XY() + actor->spr.angle.ToVector() * nRange;
|
||||||
|
else hitscangoal.Zero();
|
||||||
|
|
||||||
|
hitscan(pos, actor->sector(), vel, gHitInfo, CLIPMASK1, &hitscangoal);
|
||||||
|
|
||||||
actor->spr.cstat = bakCstat;
|
actor->spr.cstat = bakCstat;
|
||||||
while (nNum--)
|
while (nNum--)
|
||||||
{
|
{
|
||||||
|
|
|
@ -2815,7 +2815,7 @@ int ParseState::parse(void)
|
||||||
parseifelse( fi.floorspace(g_ac->sector()));
|
parseifelse( fi.floorspace(g_ac->sector()));
|
||||||
break;
|
break;
|
||||||
case concmd_ifnotmoving:
|
case concmd_ifnotmoving:
|
||||||
parseifelse( (g_ac->movflag&kHitTypeMask) > kHitSector );
|
parseifelse( g_ac->movflag > kHitSector );
|
||||||
break;
|
break;
|
||||||
case concmd_respawnhitag:
|
case concmd_respawnhitag:
|
||||||
insptr++;
|
insptr++;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue