mirror of
https://github.com/ZDoom/Raze.git
synced 2025-01-31 04:20:42 +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;
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -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.
|
||||
// Gonna be fun to globally replace these to finally lift the limit this imposes on map size.
|
||||
// Names taken from DukeGDX
|
||||
enum EHitBits
|
||||
{
|
||||
kHitNone = 0,
|
||||
kHitTypeMask = 0xC000,
|
||||
kHitTypeMaskSW = 0x1C000, // SW has one more relevant bit
|
||||
kHitIndexMask = 0x3FFF,
|
||||
kHitSector = 0x4000,
|
||||
kHitWall = 0x8000,
|
||||
kHitSprite = 0xC000,
|
||||
kHitVoid = 0x10000, // SW only
|
||||
|
||||
|
||||
};
|
||||
|
||||
// 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();
|
||||
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 (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;
|
||||
}
|
||||
|
||||
double factor2;
|
||||
double 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;
|
||||
// the wall factor is needed for doing a texture check.
|
||||
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) return -1;
|
||||
|
||||
result = start + factor * direction;
|
||||
|
||||
|
@ -715,6 +715,182 @@ double intersectSlopeSprite(DCoreActor* actor, const DVector3& start, const DVec
|
|||
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 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 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);
|
||||
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(dx != 0 || dy != 0);
|
||||
gHitInfo.clearObj();
|
||||
int x = actor->int_pos().X;
|
||||
int y = actor->int_pos().Y;
|
||||
auto bakCstat = actor->spr.cstat;
|
||||
actor->spr.cstat &= ~CSTAT_SPRITE_BLOCK_HITSCAN;
|
||||
if (nRange)
|
||||
{
|
||||
hitscangoal.X = x + MulScale(nRange << 4, Cos(actor->int_ang()), 30);
|
||||
hitscangoal.Y = y + MulScale(nRange << 4, Sin(actor->int_ang()), 30);
|
||||
}
|
||||
else
|
||||
{
|
||||
hitscangoal.X = hitscangoal.Y = 0x1fffffff;
|
||||
}
|
||||
hitscan(vec3_t( x, y, z ), actor->sector(), { dx, dy, dz << 4 }, gHitInfo, nMask);
|
||||
DVector2 hitscangoal;
|
||||
if (nRange) hitscangoal = actor->spr.pos.XY() + actor->spr.angle.ToVector() * nRange;
|
||||
else hitscangoal.Zero();
|
||||
hitscan(DVector3(actor->spr.pos.XY(), z * zinttoworld), actor->sector(), DVector3(dx, dy, dz) * inttoworld, gHitInfo, nMask, & hitscangoal);
|
||||
|
||||
hitscangoal.X = hitscangoal.Y = 0x1fffffff;
|
||||
actor->spr.cstat = bakCstat;
|
||||
if (gHitInfo.actor() != nullptr)
|
||||
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 bakCstat = actor->spr.cstat;
|
||||
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;
|
||||
while (nNum--)
|
||||
{
|
||||
|
|
|
@ -2815,7 +2815,7 @@ int ParseState::parse(void)
|
|||
parseifelse( fi.floorspace(g_ac->sector()));
|
||||
break;
|
||||
case concmd_ifnotmoving:
|
||||
parseifelse( (g_ac->movflag&kHitTypeMask) > kHitSector );
|
||||
parseifelse( g_ac->movflag > kHitSector );
|
||||
break;
|
||||
case concmd_respawnhitag:
|
||||
insptr++;
|
||||
|
|
Loading…
Reference in a new issue