mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-11 15:21:51 +00:00
Merge branch 'zmaster'
This commit is contained in:
commit
bb4bd76257
15 changed files with 261 additions and 118 deletions
107
src/actor.h
107
src/actor.h
|
@ -818,22 +818,28 @@ public:
|
|||
return ( abs(X() - other->X()) < blockdist && abs(Y() - other->Y()) < blockdist);
|
||||
}
|
||||
|
||||
// 'absolute' is reserved for a linked portal implementation which needs
|
||||
// to distinguish between portal-aware and portal-unaware distance calculation.
|
||||
fixed_t AproxDistance(AActor *other, bool absolute = false)
|
||||
{
|
||||
return P_AproxDistance(X() - other->X(), Y() - other->Y());
|
||||
}
|
||||
|
||||
// same with 'ref' here.
|
||||
fixed_t AproxDistance(fixed_t otherx, fixed_t othery, AActor *ref = NULL)
|
||||
fixed_t AproxDistance(fixed_t otherx, fixed_t othery)
|
||||
{
|
||||
return P_AproxDistance(X() - otherx, Y() - othery);
|
||||
}
|
||||
|
||||
fixed_t AngleTo(fixed_t otherx, fixed_t othery)
|
||||
{
|
||||
return R_PointToAngle2(X(), Y(), otherx, othery);
|
||||
}
|
||||
|
||||
// 'absolute' is reserved for a linked portal implementation which needs
|
||||
// to distinguish between portal-aware and portal-unaware distance calculation.
|
||||
fixed_t AproxDistance(AActor *other, bool absolute = false)
|
||||
{
|
||||
fixedvec3 otherpos = absolute ? other->Pos() : other->PosRelative(this);
|
||||
return P_AproxDistance(X() - otherpos.x, Y() - otherpos.y);
|
||||
}
|
||||
|
||||
fixed_t AproxDistance(AActor *other, fixed_t xadd, fixed_t yadd, bool absolute = false)
|
||||
{
|
||||
return P_AproxDistance(X() - other->X() + xadd, Y() - other->Y() + yadd);
|
||||
fixedvec3 otherpos = absolute ? other->Pos() : other->PosRelative(this);
|
||||
return P_AproxDistance(X() - otherpos.x + xadd, Y() - otherpos.y + yadd);
|
||||
}
|
||||
|
||||
fixed_t AproxDistance3D(AActor *other, bool absolute = false)
|
||||
|
@ -844,18 +850,21 @@ public:
|
|||
// more precise, but slower version, being used in a few places
|
||||
fixed_t Distance2D(AActor *other, bool absolute = false)
|
||||
{
|
||||
return xs_RoundToInt(TVector2<double>(X() - other->X(), Y() - other->Y()).Length());
|
||||
fixedvec3 otherpos = absolute ? other->Pos() : other->PosRelative(this);
|
||||
return xs_RoundToInt(TVector2<double>(X() - otherpos.x, Y() - otherpos.y).Length());
|
||||
}
|
||||
|
||||
// a full 3D version of the above
|
||||
fixed_t Distance3D(AActor *other, bool absolute = false)
|
||||
{
|
||||
return xs_RoundToInt(TVector3<double>(X() - other->X(), Y() - other->Y(), Z() - other->Z()).Length());
|
||||
fixedvec3 otherpos = absolute ? other->Pos() : other->PosRelative(this);
|
||||
return xs_RoundToInt(TVector3<double>(X() - otherpos.x, Y() - otherpos.y, Z() - otherpos.z).Length());
|
||||
}
|
||||
|
||||
angle_t AngleTo(AActor *other, bool absolute = false) const
|
||||
angle_t AngleTo(AActor *other, bool absolute = false)
|
||||
{
|
||||
return R_PointToAngle2(X(), Y(), other->X(), other->Y());
|
||||
fixedvec3 otherpos = absolute ? other->Pos() : other->PosRelative(this);
|
||||
return R_PointToAngle2(X(), Y(), otherpos.x, otherpos.y);
|
||||
}
|
||||
|
||||
angle_t AngleTo(AActor *other, fixed_t oxofs, fixed_t oyofs, bool absolute = false) const
|
||||
|
@ -863,53 +872,71 @@ public:
|
|||
return R_PointToAngle2(X(), Y(), other->X() + oxofs, other->Y() + oyofs);
|
||||
}
|
||||
|
||||
fixed_t AngleTo(fixed_t otherx, fixed_t othery, AActor *ref = NULL)
|
||||
{
|
||||
return R_PointToAngle2(X(), Y(), otherx, othery);
|
||||
}
|
||||
|
||||
fixed_t AngleXYTo(fixed_t myx, fixed_t myy, AActor *other, bool absolute = false)
|
||||
{
|
||||
return R_PointToAngle2(myx, myy, other->X(), other->Y());
|
||||
}
|
||||
|
||||
fixedvec2 Vec2To(AActor *other) const
|
||||
{
|
||||
fixedvec2 ret = { other->X() - X(), other->Y() - Y() };
|
||||
fixedvec3 otherpos = other->PosRelative(this);
|
||||
fixedvec2 ret = { otherpos.x - X(), otherpos.y - Y() };
|
||||
return ret;
|
||||
}
|
||||
|
||||
fixedvec3 Vec3To(AActor *other) const
|
||||
{
|
||||
fixedvec3 ret = { other->X() - X(), other->Y() - Y(), other->Z() - Z() };
|
||||
fixedvec3 otherpos = other->PosRelative(this);
|
||||
fixedvec3 ret = { otherpos.x - X(), otherpos.y - Y(), otherpos.z - Z() };
|
||||
return ret;
|
||||
}
|
||||
|
||||
fixedvec2 Vec2Offset(fixed_t dx, fixed_t dy, bool absolute = false) const
|
||||
fixedvec2 Vec2Offset(fixed_t dx, fixed_t dy, bool absolute = false)
|
||||
{
|
||||
fixedvec2 ret = { X() + dx, Y() + dy };
|
||||
return ret;
|
||||
if (absolute)
|
||||
{
|
||||
fixedvec2 ret = { X() + dx, Y() + dy };
|
||||
return ret;
|
||||
}
|
||||
else return P_GetOffsetPosition(this, dx, dy);
|
||||
}
|
||||
|
||||
|
||||
fixedvec2 Vec2Angle(fixed_t length, angle_t angle, bool absolute = false) const
|
||||
fixedvec2 Vec2Angle(fixed_t length, angle_t angle, bool absolute = false)
|
||||
{
|
||||
fixedvec2 ret = { X() + FixedMul(length, finecosine[angle >> ANGLETOFINESHIFT]),
|
||||
Y() + FixedMul(length, finesine[angle >> ANGLETOFINESHIFT]) };
|
||||
return ret;
|
||||
if (absolute)
|
||||
{
|
||||
fixedvec2 ret = { X() + FixedMul(length, finecosine[angle >> ANGLETOFINESHIFT]),
|
||||
Y() + FixedMul(length, finesine[angle >> ANGLETOFINESHIFT]) };
|
||||
return ret;
|
||||
}
|
||||
else return P_GetOffsetPosition(this, FixedMul(length, finecosine[angle >> ANGLETOFINESHIFT]), FixedMul(length, finesine[angle >> ANGLETOFINESHIFT]));
|
||||
}
|
||||
|
||||
fixedvec3 Vec3Offset(fixed_t dx, fixed_t dy, fixed_t dz, bool absolute = false) const
|
||||
fixedvec3 Vec3Offset(fixed_t dx, fixed_t dy, fixed_t dz, bool absolute = false)
|
||||
{
|
||||
fixedvec3 ret = { X() + dx, Y() + dy, Z() + dz };
|
||||
return ret;
|
||||
if (absolute)
|
||||
{
|
||||
fixedvec3 ret = { X() + dx, Y() + dy, Z() + dz };
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
fixedvec2 op = P_GetOffsetPosition(this, dx, dy);
|
||||
fixedvec3 pos = { op.x, op.y, Z() + dz };
|
||||
return pos;
|
||||
}
|
||||
}
|
||||
|
||||
fixedvec3 Vec3Angle(fixed_t length, angle_t angle, fixed_t dz, bool absolute = false) const
|
||||
fixedvec3 Vec3Angle(fixed_t length, angle_t angle, fixed_t dz, bool absolute = false)
|
||||
{
|
||||
fixedvec3 ret = { X() + FixedMul(length, finecosine[angle >> ANGLETOFINESHIFT]),
|
||||
if (absolute)
|
||||
{
|
||||
fixedvec3 ret = { X() + FixedMul(length, finecosine[angle >> ANGLETOFINESHIFT]),
|
||||
Y() + FixedMul(length, finesine[angle >> ANGLETOFINESHIFT]), Z() + dz };
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
fixedvec2 op = P_GetOffsetPosition(this, FixedMul(length, finecosine[angle >> ANGLETOFINESHIFT]), FixedMul(length, finesine[angle >> ANGLETOFINESHIFT]));
|
||||
fixedvec3 pos = { op.x, op.y, Z() + dz };
|
||||
return pos;
|
||||
}
|
||||
}
|
||||
|
||||
void ClearInterpolation();
|
||||
|
@ -1190,7 +1217,7 @@ public:
|
|||
return __pos;
|
||||
}
|
||||
|
||||
fixedvec3 PosRelative(AActor *other) const;
|
||||
fixedvec3 PosRelative(const AActor *other) const;
|
||||
fixedvec3 PosRelative(sector_t *sec) const;
|
||||
fixedvec3 PosRelative(line_t *line) const;
|
||||
|
||||
|
|
|
@ -513,7 +513,7 @@ AActor *P_SpawnKoraxMissile (fixed_t x, fixed_t y, fixed_t z,
|
|||
z -= source->floorclip;
|
||||
th = Spawn (type, x, y, z, ALLOW_REPLACE);
|
||||
th->target = source; // Originator
|
||||
an = source->AngleXYTo(x, y, dest);
|
||||
an = th->AngleTo(dest);
|
||||
if (dest->flags & MF_SHADOW)
|
||||
{ // Invisible target
|
||||
an += pr_kmissile.Random2()<<21;
|
||||
|
@ -522,7 +522,7 @@ AActor *P_SpawnKoraxMissile (fixed_t x, fixed_t y, fixed_t z,
|
|||
an >>= ANGLETOFINESHIFT;
|
||||
th->velx = FixedMul (th->Speed, finecosine[an]);
|
||||
th->vely = FixedMul (th->Speed, finesine[an]);
|
||||
dist = dest->AproxDistance (x, y, source) / th->Speed;
|
||||
dist = dest->AproxDistance (th) / th->Speed;
|
||||
if (dist < 1)
|
||||
{
|
||||
dist = 1;
|
||||
|
|
|
@ -284,8 +284,18 @@ xx(FRandom)
|
|||
xx(Random2)
|
||||
xx(RandomPick)
|
||||
xx(FRandomPick)
|
||||
xx(Exp)
|
||||
xx(Log10)
|
||||
xx(Ceil)
|
||||
xx(ACos)
|
||||
xx(ASin)
|
||||
xx(ATan)
|
||||
xx(Cos)
|
||||
xx(Sin)
|
||||
xx(Tan)
|
||||
xx(CosH)
|
||||
xx(SinH)
|
||||
xx(TanH)
|
||||
xx(Alpha)
|
||||
xx(Angle)
|
||||
xx(Args)
|
||||
|
@ -322,6 +332,7 @@ xx(Radius)
|
|||
xx(ReactionTime)
|
||||
xx(MeleeRange)
|
||||
xx(Speed)
|
||||
xx(Clamp)
|
||||
|
||||
// Various actor names which are used internally
|
||||
xx(MapSpot)
|
||||
|
|
|
@ -856,7 +856,7 @@ bool FMultiBlockLinesIterator::Next(FMultiBlockLinesIterator::CheckResult *item)
|
|||
|
||||
void FMultiBlockLinesIterator::startIteratorForGroup(int group)
|
||||
{
|
||||
offset = Displacements(basegroup, group);
|
||||
offset = Displacements.getOffset(basegroup, group);
|
||||
offset.x += checkpoint.x;
|
||||
offset.y += checkpoint.y;
|
||||
bbox.setBox(offset.x, offset.y, checkpoint.z);
|
||||
|
@ -1088,7 +1088,7 @@ bool FMultiBlockThingsIterator::Next(FMultiBlockThingsIterator::CheckResult *ite
|
|||
if (thing != NULL)
|
||||
{
|
||||
item->thing = thing;
|
||||
item->position = checkpoint + Displacements(basegroup, thing->Sector->PortalGroup);
|
||||
item->position = checkpoint + Displacements.getOffset(basegroup, thing->Sector->PortalGroup);
|
||||
item->portalflags = portalflags;
|
||||
return true;
|
||||
}
|
||||
|
@ -1127,7 +1127,7 @@ bool FMultiBlockThingsIterator::Next(FMultiBlockThingsIterator::CheckResult *ite
|
|||
|
||||
void FMultiBlockThingsIterator::startIteratorForGroup(int group)
|
||||
{
|
||||
fixedvec2 offset = Displacements(basegroup, group);
|
||||
fixedvec2 offset = Displacements.getOffset(basegroup, group);
|
||||
offset.x += checkpoint.x;
|
||||
offset.y += checkpoint.y;
|
||||
bbox.setBox(offset.x, offset.y, checkpoint.z);
|
||||
|
|
|
@ -897,9 +897,9 @@ fixed_t sector_t::HighestCeilingAt(fixed_t x, fixed_t y, sector_t **resultsec)
|
|||
// Continue until we find a blocking portal or a portal below where we actually are.
|
||||
while (!check->PortalBlocksMovement(ceiling) && planeheight < check->SkyBoxes[ceiling]->threshold)
|
||||
{
|
||||
FDisplacement &disp = check->CeilingDisplacement();
|
||||
x += disp.pos.x;
|
||||
y += disp.pos.y;
|
||||
fixedvec2 pos = check->CeilingDisplacement();
|
||||
x += pos.x;
|
||||
y += pos.y;
|
||||
planeheight = check->SkyBoxes[ceiling]->threshold;
|
||||
check = P_PointInSector(x, y);
|
||||
}
|
||||
|
@ -921,9 +921,9 @@ fixed_t sector_t::LowestFloorAt(fixed_t x, fixed_t y, sector_t **resultsec)
|
|||
// Continue until we find a blocking portal or a portal above where we actually are.
|
||||
while (!check->PortalBlocksMovement(floor) && planeheight > check->SkyBoxes[floor]->threshold)
|
||||
{
|
||||
FDisplacement &disp = check->FloorDisplacement();
|
||||
x += disp.pos.x;
|
||||
y += disp.pos.y;
|
||||
fixedvec2 pos = check->FloorDisplacement();
|
||||
x += pos.x;
|
||||
y += pos.y;
|
||||
planeheight = check->SkyBoxes[floor]->threshold;
|
||||
check = P_PointInSector(x, y);
|
||||
}
|
||||
|
@ -960,9 +960,9 @@ fixed_t sector_t::NextHighestCeilingAt(fixed_t x, fixed_t y, fixed_t z, int flag
|
|||
}
|
||||
else
|
||||
{
|
||||
FDisplacement &disp = sec->CeilingDisplacement();
|
||||
x += disp.pos.x;
|
||||
y += disp.pos.y;
|
||||
fixedvec2 pos = sec->CeilingDisplacement();
|
||||
x += pos.x;
|
||||
y += pos.y;
|
||||
planeheight = sec->SkyBoxes[ceiling]->threshold;
|
||||
sec = P_PointInSector(x, y);
|
||||
}
|
||||
|
@ -1003,9 +1003,9 @@ fixed_t sector_t::NextLowestFloorAt(fixed_t x, fixed_t y, fixed_t z, int flags,
|
|||
}
|
||||
else
|
||||
{
|
||||
FDisplacement &disp = sec->FloorDisplacement();
|
||||
x += disp.pos.x;
|
||||
y += disp.pos.y;
|
||||
fixedvec2 pos = sec->FloorDisplacement();
|
||||
x += pos.x;
|
||||
y += pos.y;
|
||||
planeheight = sec->SkyBoxes[floor]->threshold;
|
||||
sec = P_PointInSector(x, y);
|
||||
}
|
||||
|
|
|
@ -786,7 +786,7 @@ int P_Thing_Warp(AActor *caller, AActor *reference, fixed_t xofs, fixed_t yofs,
|
|||
if (flags & WARPF_WARPINTERPOLATION)
|
||||
{
|
||||
// This just translates the movement but doesn't change the vector
|
||||
fixedvec3 displacedold = old + Displacements(oldpgroup, caller->Sector->PortalGroup);
|
||||
fixedvec3 displacedold = old + Displacements.getOffset(oldpgroup, caller->Sector->PortalGroup);
|
||||
caller->PrevX += caller->X() - displacedold.x;
|
||||
caller->PrevY += caller->Y() - displacedold.y;
|
||||
caller->PrevZ += caller->Z() - displacedold.z;
|
||||
|
@ -795,8 +795,8 @@ int P_Thing_Warp(AActor *caller, AActor *reference, fixed_t xofs, fixed_t yofs,
|
|||
else if (flags & WARPF_COPYINTERPOLATION)
|
||||
{
|
||||
// Map both positions of the reference actor to the current portal group
|
||||
fixedvec3 displacedold = old + Displacements(reference->PrevPortalGroup, caller->Sector->PortalGroup);
|
||||
fixedvec3 displacedref = old + Displacements(reference->Sector->PortalGroup, caller->Sector->PortalGroup);
|
||||
fixedvec3 displacedold = old + Displacements.getOffset(reference->PrevPortalGroup, caller->Sector->PortalGroup);
|
||||
fixedvec3 displacedref = old + Displacements.getOffset(reference->Sector->PortalGroup, caller->Sector->PortalGroup);
|
||||
caller->PrevX = caller->X() + displacedold.x - displacedref.x;
|
||||
caller->PrevY = caller->Y() + displacedold.y - displacedref.y;
|
||||
caller->PrevZ = caller->Z() + displacedold.z - displacedref.z;
|
||||
|
|
|
@ -121,6 +121,11 @@ static void BuildBlockmap()
|
|||
{
|
||||
PortalBlockmap.containsLines = true;
|
||||
block.portallines.Push(ld);
|
||||
block.neighborContainsLines = true;
|
||||
if (x > 0) PortalBlockmap(x - 1, y).neighborContainsLines = true;
|
||||
if (y > 0) PortalBlockmap(x, y - 1).neighborContainsLines = true;
|
||||
if (x < PortalBlockmap.dx - 1) PortalBlockmap(x + 1, y).neighborContainsLines = true;
|
||||
if (y < PortalBlockmap.dy - 1) PortalBlockmap(x, y + 1).neighborContainsLines = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -691,15 +696,23 @@ void P_NormalizeVXVY(fixed_t& vx, fixed_t& vy)
|
|||
|
||||
fixedvec2 P_GetOffsetPosition(AActor *actor, fixed_t dx, fixed_t dy)
|
||||
{
|
||||
fixedvec3 dest = { actor->X() + dx, actor->Y() + dy };
|
||||
fixedvec2 dest = { actor->X() + dx, actor->Y() + dy };
|
||||
if (PortalBlockmap.containsLines)
|
||||
{
|
||||
fixed_t actx = actor->X(), acty = actor->Y();
|
||||
// Try some easily discoverable early-out first. If we know that the trace cannot possibly find a portal, this saves us from calling the traverser completely for vast parts of the map.
|
||||
if (dx < 128 * FRACUNIT && dy < 128 * FRACUNIT)
|
||||
{
|
||||
fixed_t blockx = GetSafeBlockX(actx - bmaporgx);
|
||||
fixed_t blocky = GetSafeBlockX(acty - bmaporgy);
|
||||
if (blockx < 0 || blocky < 0 || blockx >= bmapwidth || blocky >= bmapheight || !PortalBlockmap(blockx, blocky).neighborContainsLines) return dest;
|
||||
}
|
||||
|
||||
FLinePortalTraverse it;
|
||||
bool repeat;
|
||||
do
|
||||
{
|
||||
it.init(actx, acty, dx, dy, PT_ADDLINES);
|
||||
it.init(actx, acty, dx, dy, PT_ADDLINES|PT_DELTA);
|
||||
intercept_t *in;
|
||||
|
||||
repeat = false;
|
||||
|
@ -1159,9 +1172,9 @@ bool P_CollectConnectedGroups(int startgroup, const fixedvec3 &position, fixed_t
|
|||
while (!wsec->PortalBlocksMovement(sector_t::ceiling) && upperz > wsec->SkyBoxes[sector_t::ceiling]->threshold)
|
||||
{
|
||||
sector_t *othersec = wsec->SkyBoxes[sector_t::ceiling]->Sector;
|
||||
FDisplacement &disp = Displacements(startgroup, othersec->PortalGroup);
|
||||
fixed_t dx = position.x + disp.pos.x;
|
||||
fixed_t dy = position.y + disp.pos.y;
|
||||
fixedvec2 pos = Displacements.getOffset(startgroup, othersec->PortalGroup);
|
||||
fixed_t dx = position.x + pos.x;
|
||||
fixed_t dy = position.y + pos.y;
|
||||
processMask.setBit(othersec->PortalGroup);
|
||||
out.Add(othersec->PortalGroup|FPortalGroupArray::UPPER);
|
||||
wsec = P_PointInSector(dx, dy); // get upper sector at the exact spot we want to check and repeat
|
||||
|
@ -1171,9 +1184,9 @@ bool P_CollectConnectedGroups(int startgroup, const fixedvec3 &position, fixed_t
|
|||
while (!wsec->PortalBlocksMovement(sector_t::floor) && position.z < wsec->SkyBoxes[sector_t::floor]->threshold)
|
||||
{
|
||||
sector_t *othersec = wsec->SkyBoxes[sector_t::floor]->Sector;
|
||||
FDisplacement &disp = Displacements(startgroup, othersec->PortalGroup);
|
||||
fixed_t dx = position.x + disp.pos.x;
|
||||
fixed_t dy = position.y + disp.pos.y;
|
||||
fixedvec2 pos = Displacements.getOffset(startgroup, othersec->PortalGroup);
|
||||
fixed_t dx = position.x + pos.x;
|
||||
fixed_t dy = position.y + pos.y;
|
||||
processMask.setBit(othersec->PortalGroup|FPortalGroupArray::LOWER);
|
||||
out.Add(othersec->PortalGroup);
|
||||
wsec = P_PointInSector(dx, dy); // get lower sector at the exact spot we want to check and repeat
|
||||
|
|
22
src/portal.h
22
src/portal.h
|
@ -30,10 +30,6 @@ struct FDisplacement
|
|||
bool isSet;
|
||||
BYTE indirect; // just for illustration.
|
||||
|
||||
operator fixedvec2()
|
||||
{
|
||||
return pos;
|
||||
}
|
||||
};
|
||||
|
||||
struct FDisplacementTable
|
||||
|
@ -55,9 +51,18 @@ struct FDisplacementTable
|
|||
|
||||
FDisplacement &operator()(int x, int y)
|
||||
{
|
||||
if (x == y) return data[0]; // shortcut for the most common case
|
||||
return data[x + size*y];
|
||||
}
|
||||
|
||||
fixedvec2 getOffset(int x, int y) const
|
||||
{
|
||||
if (x == y)
|
||||
{
|
||||
fixedvec2 nulvec = { 0,0 };
|
||||
return nulvec; // shortcut for the most common case
|
||||
}
|
||||
return data[x + size*y].pos;
|
||||
}
|
||||
};
|
||||
|
||||
extern FDisplacementTable Displacements;
|
||||
|
@ -72,7 +77,13 @@ extern FDisplacementTable Displacements;
|
|||
|
||||
struct FPortalBlock
|
||||
{
|
||||
bool neighborContainsLines; // this is for skipping the traverser and exiting early if we can quickly decide that there's no portals nearby.
|
||||
TArray<line_t*> portallines;
|
||||
|
||||
FPortalBlock()
|
||||
{
|
||||
neighborContainsLines = false;
|
||||
}
|
||||
};
|
||||
|
||||
struct FPortalBlockmap
|
||||
|
@ -187,5 +198,6 @@ void P_TranslatePortalAngle(line_t* src, line_t* dst, angle_t& angle);
|
|||
void P_TranslatePortalZ(line_t* src, line_t* dst, fixed_t& z);
|
||||
void P_NormalizeVXVY(fixed_t& vx, fixed_t& vy);
|
||||
fixed_t P_PointLineDistance(line_t* line, fixed_t x, fixed_t y);
|
||||
fixedvec2 P_GetOffsetPosition(AActor *actor, fixed_t dx, fixed_t dy);
|
||||
|
||||
#endif
|
18
src/r_defs.h
18
src/r_defs.h
|
@ -838,14 +838,14 @@ struct sector_t
|
|||
}
|
||||
|
||||
// These may only be called if the portal has been validated
|
||||
FDisplacement &FloorDisplacement()
|
||||
fixedvec2 FloorDisplacement()
|
||||
{
|
||||
return Displacements(PortalGroup, SkyBoxes[sector_t::floor]->Sector->PortalGroup);
|
||||
return Displacements.getOffset(PortalGroup, SkyBoxes[sector_t::floor]->Sector->PortalGroup);
|
||||
}
|
||||
|
||||
FDisplacement &CeilingDisplacement()
|
||||
fixedvec2 CeilingDisplacement()
|
||||
{
|
||||
return Displacements(PortalGroup, SkyBoxes[sector_t::ceiling]->Sector->PortalGroup);
|
||||
return Displacements.getOffset(PortalGroup, SkyBoxes[sector_t::ceiling]->Sector->PortalGroup);
|
||||
}
|
||||
|
||||
int GetTerrain(int pos) const;
|
||||
|
@ -1375,24 +1375,24 @@ inline sector_t *P_PointInSector(fixed_t x, fixed_t y)
|
|||
return P_PointInSubsector(x, y)->sector;
|
||||
}
|
||||
|
||||
inline fixedvec3 AActor::PosRelative(AActor *other) const
|
||||
inline fixedvec3 AActor::PosRelative(const AActor *other) const
|
||||
{
|
||||
return __pos + Displacements(Sector->PortalGroup, other->Sector->PortalGroup);
|
||||
return __pos + Displacements.getOffset(Sector->PortalGroup, other->Sector->PortalGroup);
|
||||
}
|
||||
|
||||
inline fixedvec3 AActor::PosRelative(sector_t *sec) const
|
||||
{
|
||||
return __pos + Displacements(Sector->PortalGroup, sec->PortalGroup);
|
||||
return __pos + Displacements.getOffset(Sector->PortalGroup, sec->PortalGroup);
|
||||
}
|
||||
|
||||
inline fixedvec3 AActor::PosRelative(line_t *line) const
|
||||
{
|
||||
return __pos + Displacements(Sector->PortalGroup, line->frontsector->PortalGroup);
|
||||
return __pos + Displacements.getOffset(Sector->PortalGroup, line->frontsector->PortalGroup);
|
||||
}
|
||||
|
||||
inline fixedvec3 PosRelative(const fixedvec3 &pos, line_t *line, sector_t *refsec = NULL)
|
||||
{
|
||||
return pos + Displacements(refsec->PortalGroup, line->frontsector->PortalGroup);
|
||||
return pos + Displacements.getOffset(refsec->PortalGroup, line->frontsector->PortalGroup);
|
||||
}
|
||||
|
||||
inline void AActor::ClearInterpolation()
|
||||
|
|
|
@ -583,7 +583,7 @@ void R_InterpolateView (player_t *player, fixed_t frac, InterpolationViewer *ivi
|
|||
}
|
||||
int oldgroup = R_PointInSubsector(iview->oviewx, iview->oviewy)->sector->PortalGroup;
|
||||
int newgroup = R_PointInSubsector(iview->nviewx, iview->nviewy)->sector->PortalGroup;
|
||||
fixedvec2 disp = Displacements(oldgroup, newgroup);
|
||||
fixedvec2 disp = Displacements.getOffset(oldgroup, newgroup);
|
||||
viewx = iview->oviewx + FixedMul (frac, iview->nviewx - iview->oviewx - disp.x);
|
||||
viewy = iview->oviewy + FixedMul (frac, iview->nviewy - iview->oviewy - disp.y);
|
||||
viewz = iview->oviewz + FixedMul (frac, iview->nviewz - iview->oviewz);
|
||||
|
|
|
@ -323,6 +323,40 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, GetDistance)
|
|||
return 0;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// GetSpawnHealth
|
||||
//
|
||||
//==========================================================================
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, GetSpawnHealth)
|
||||
{
|
||||
if (numret > 0)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_OBJECT(self, AActor);
|
||||
ret->SetInt(self->SpawnHealth());
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// GetGibHealth
|
||||
//
|
||||
//==========================================================================
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, GetGibHealth)
|
||||
{
|
||||
if (numret > 0)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_OBJECT(self, AActor);
|
||||
ret->SetInt(self->GetGibHealth());
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// __decorate_internal_state__
|
||||
|
@ -5147,7 +5181,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_WolfAttack)
|
|||
if (spawnblood)
|
||||
{
|
||||
P_SpawnBlood(bloodpos, angle, newdam > 0 ? newdam : damage, self->target);
|
||||
P_TraceBleed(newdam > 0 ? newdam : damage, self->target, self->AngleTo(dx, dy, self->target), 0);
|
||||
P_TraceBleed(newdam > 0 ? newdam : damage, self->target, self);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,6 +57,7 @@ static FxExpression *ParseRandomPick(FScanner &sc, FName identifier, PClassActor
|
|||
static FxExpression *ParseRandom2(FScanner &sc, PClassActor *cls);
|
||||
static FxExpression *ParseAbs(FScanner &sc, PClassActor *cls);
|
||||
static FxExpression *ParseMinMax(FScanner &sc, FName identifier, PClassActor *cls);
|
||||
static FxExpression *ParseClamp(FScanner &sc, PClassActor *cls);
|
||||
|
||||
//
|
||||
// ParseExpression
|
||||
|
@ -381,6 +382,8 @@ static FxExpression *ParseExpression0 (FScanner &sc, PClassActor *cls)
|
|||
case NAME_Min:
|
||||
case NAME_Max:
|
||||
return ParseMinMax(sc, identifier, cls);
|
||||
case NAME_Clamp:
|
||||
return ParseClamp(sc, cls);
|
||||
case NAME_Abs:
|
||||
return ParseAbs(sc, cls);
|
||||
default:
|
||||
|
@ -521,3 +524,23 @@ static FxExpression *ParseMinMax(FScanner &sc, FName identifier, PClassActor *cl
|
|||
}
|
||||
return new FxMinMax(list, identifier, sc);
|
||||
}
|
||||
|
||||
static FxExpression *ParseClamp(FScanner &sc, PClassActor *cls)
|
||||
{
|
||||
FxExpression *src = ParseExpressionM(sc, cls);
|
||||
sc.MustGetToken(',');
|
||||
FxExpression *min = ParseExpressionM(sc, cls);
|
||||
sc.MustGetToken(',');
|
||||
FxExpression *max = ParseExpressionM(sc, cls);
|
||||
sc.MustGetToken(')');
|
||||
|
||||
// Build clamp(a,x,y) as min(max(a,x),y)
|
||||
TArray<FxExpression *> list(2);
|
||||
list.Reserve(2);
|
||||
list[0] = src;
|
||||
list[1] = min;
|
||||
FxExpression *maxexpr = new FxMinMax(list, NAME_Max, sc);
|
||||
list[0] = maxexpr;
|
||||
list[1] = max;
|
||||
return new FxMinMax(list, NAME_Min, sc);
|
||||
}
|
||||
|
|
|
@ -830,19 +830,19 @@ public:
|
|||
|
||||
//==========================================================================
|
||||
//
|
||||
// FxGlobalFunctionCall
|
||||
// FxFlopFunctionCall
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
class FxGlobalFunctionCall : public FxExpression
|
||||
class FxFlopFunctionCall : public FxExpression
|
||||
{
|
||||
FName Name;
|
||||
int Index;
|
||||
FArgumentList *ArgList;
|
||||
|
||||
public:
|
||||
|
||||
FxGlobalFunctionCall(FName fname, FArgumentList *args, const FScriptPosition &pos);
|
||||
~FxGlobalFunctionCall();
|
||||
FxFlopFunctionCall(int index, FArgumentList *args, const FScriptPosition &pos);
|
||||
~FxFlopFunctionCall();
|
||||
FxExpression *Resolve(FCompileContext&);
|
||||
ExpEmit Emit(VMFunctionBuilder *build);
|
||||
};
|
||||
|
|
|
@ -54,6 +54,36 @@
|
|||
#include "vmbuilder.h"
|
||||
#include "v_text.h"
|
||||
|
||||
struct FLOP
|
||||
{
|
||||
ENamedName Name;
|
||||
int Flop;
|
||||
double (*Evaluate)(double);
|
||||
};
|
||||
|
||||
// Decorate operates on degrees, so the evaluate functions need to convert
|
||||
// degrees to radians for those that work with angles.
|
||||
static const FLOP FxFlops[] =
|
||||
{
|
||||
{ NAME_Exp, FLOP_EXP, [](double v) { return exp(v); } },
|
||||
{ NAME_Log, FLOP_LOG, [](double v) { return log(v); } },
|
||||
{ NAME_Log10, FLOP_LOG10, [](double v) { return log10(v); } },
|
||||
{ NAME_Sqrt, FLOP_SQRT, [](double v) { return sqrt(v); } },
|
||||
{ NAME_Ceil, FLOP_CEIL, [](double v) { return ceil(v); } },
|
||||
{ NAME_Floor, FLOP_FLOOR, [](double v) { return floor(v); } },
|
||||
|
||||
{ NAME_ACos, FLOP_ACOS_DEG, [](double v) { return acos(v) * (180.0 / M_PI); } },
|
||||
{ NAME_ASin, FLOP_ASIN_DEG, [](double v) { return asin(v) * (180.0 / M_PI); } },
|
||||
{ NAME_ATan, FLOP_ATAN_DEG, [](double v) { return atan(v) * (180.0 / M_PI); } },
|
||||
{ NAME_Cos, FLOP_COS_DEG, [](double v) { return cos(v * (M_PI / 180.0)); } },
|
||||
{ NAME_Sin, FLOP_SIN_DEG, [](double v) { return sin(v * (M_PI / 180.0)); } },
|
||||
{ NAME_Tan, FLOP_TAN_DEG, [](double v) { return tan(v * (M_PI / 180.0)); } },
|
||||
|
||||
{ NAME_CosH, FLOP_COSH, [](double v) { return cosh(v); } },
|
||||
{ NAME_SinH, FLOP_SINH, [](double v) { return sinh(v); } },
|
||||
{ NAME_TanH, FLOP_TANH, [](double v) { return tanh(v); } },
|
||||
};
|
||||
|
||||
ExpEmit::ExpEmit(VMFunctionBuilder *build, int type)
|
||||
: RegNum(build->Registers[type].Get(1)), RegType(type), Konst(false), Fixed(false)
|
||||
{
|
||||
|
@ -3146,20 +3176,21 @@ FxFunctionCall::~FxFunctionCall()
|
|||
|
||||
FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx)
|
||||
{
|
||||
// There's currently only 3 global functions.
|
||||
// If this changes later, it won't be here!
|
||||
if (MethodName == NAME_Sin || MethodName == NAME_Cos || MethodName == NAME_Sqrt)
|
||||
for (int i = 0; i < countof(FxFlops); ++i)
|
||||
{
|
||||
if (Self != NULL)
|
||||
if (MethodName == FxFlops[i].Name)
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "Global functions cannot have a self pointer");
|
||||
if (Self != NULL)
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "Global functions cannot have a self pointer");
|
||||
delete this;
|
||||
return NULL;
|
||||
}
|
||||
FxExpression *x = new FxFlopFunctionCall(i, ArgList, ScriptPosition);
|
||||
ArgList = NULL;
|
||||
delete this;
|
||||
return NULL;
|
||||
return x->Resolve(ctx);
|
||||
}
|
||||
FxExpression *x = new FxGlobalFunctionCall(MethodName, ArgList, ScriptPosition);
|
||||
ArgList = NULL;
|
||||
delete this;
|
||||
return x->Resolve(ctx);
|
||||
}
|
||||
|
||||
int min, max, special;
|
||||
|
@ -3483,10 +3514,11 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build, bool tailcall)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
FxGlobalFunctionCall::FxGlobalFunctionCall(FName fname, FArgumentList *args, const FScriptPosition &pos)
|
||||
FxFlopFunctionCall::FxFlopFunctionCall(int index, FArgumentList *args, const FScriptPosition &pos)
|
||||
: FxExpression(pos)
|
||||
{
|
||||
Name = fname;
|
||||
assert(index >= 0 && index < countof(FxFlops) && "FLOP index out of range");
|
||||
Index = index;
|
||||
ArgList = args;
|
||||
}
|
||||
|
||||
|
@ -3496,18 +3528,18 @@ FxGlobalFunctionCall::FxGlobalFunctionCall(FName fname, FArgumentList *args, con
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
FxGlobalFunctionCall::~FxGlobalFunctionCall()
|
||||
FxFlopFunctionCall::~FxFlopFunctionCall()
|
||||
{
|
||||
SAFE_DELETE(ArgList);
|
||||
}
|
||||
|
||||
FxExpression *FxGlobalFunctionCall::Resolve(FCompileContext& ctx)
|
||||
FxExpression *FxFlopFunctionCall::Resolve(FCompileContext& ctx)
|
||||
{
|
||||
CHECKRESOLVED();
|
||||
|
||||
if (ArgList == NULL || ArgList->Size() != 1)
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "%s only has one parameter", Name.GetChars());
|
||||
ScriptPosition.Message(MSG_ERROR, "%s only has one parameter", FName(FxFlops[Index].Name).GetChars());
|
||||
delete this;
|
||||
return NULL;
|
||||
}
|
||||
|
@ -3528,15 +3560,7 @@ FxExpression *FxGlobalFunctionCall::Resolve(FCompileContext& ctx)
|
|||
if ((*ArgList)[0]->isConstant())
|
||||
{
|
||||
double v = static_cast<FxConstant *>((*ArgList)[0])->GetValue().GetFloat();
|
||||
if (Name == NAME_Sqrt)
|
||||
{
|
||||
v = sqrt(v);
|
||||
}
|
||||
else
|
||||
{
|
||||
v *= M_PI / 180.0; // convert from degrees to radians
|
||||
v = (Name == NAME_Sin) ? sin(v) : cos(v);
|
||||
}
|
||||
v = FxFlops[Index].Evaluate(v);
|
||||
FxExpression *x = new FxConstant(v, ScriptPosition);
|
||||
delete this;
|
||||
return x;
|
||||
|
@ -3554,15 +3578,12 @@ FxExpression *FxGlobalFunctionCall::Resolve(FCompileContext& ctx)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
ExpEmit FxGlobalFunctionCall::Emit(VMFunctionBuilder *build)
|
||||
ExpEmit FxFlopFunctionCall::Emit(VMFunctionBuilder *build)
|
||||
{
|
||||
ExpEmit v = (*ArgList)[0]->Emit(build);
|
||||
assert(!v.Konst && v.RegType == REGT_FLOAT);
|
||||
|
||||
build->Emit(OP_FLOP, v.RegNum, v.RegNum,
|
||||
(Name == NAME_Sqrt) ? FLOP_SQRT :
|
||||
(Name == NAME_Sin) ? FLOP_SIN_DEG :
|
||||
FLOP_COS_DEG);
|
||||
build->Emit(OP_FLOP, v.RegNum, v.RegNum, FxFlops[Index].Flop);
|
||||
return v;
|
||||
}
|
||||
|
||||
|
|
|
@ -42,6 +42,8 @@ ACTOR Actor native //: Thinker
|
|||
native bool IsPointerEqual(int ptr_select1, int ptr_select2);
|
||||
native int CountInv(class<Inventory> itemtype, int ptr_select = AAPTR_DEFAULT);
|
||||
native float GetDistance(bool checkz, int ptr = AAPTR_DEFAULT);
|
||||
native int GetSpawnHealth();
|
||||
native int GetGibHealth();
|
||||
|
||||
// Action functions
|
||||
// Meh, MBF redundant functions. Only for DeHackEd support.
|
||||
|
|
Loading…
Reference in a new issue