gzdoom/wadsrc/static/zscript/shared/fastprojectile.txt
Christoph Oelckers 9099dc600f - fixed the 'frozen level' handling and did some cleanup on the session data in savegames.
The handling for the two frozen flags was totally inconsistent.
Furthermore, these need to be session data, not level data.
The old exported variables for this still exist and shadow the real state, but are deprecated now.
Frozen state should only be checked with "currentSession.isFrozen()" now.

The session data in the savegame was grouped and separated from the global state, which onl consists of server CVARs and RNG state now.
2019-01-12 13:50:15 +01:00

195 lines
4.1 KiB
Text

// Fast projectiles --------------------------------------------------------
class FastProjectile : Actor
{
Default
{
Projectile;
MissileHeight 0;
}
virtual void Effect()
{
class<Actor> trail = MissileName;
if (trail != null)
{
double hitz = pos.z - 8;
if (hitz < floorz)
{
hitz = floorz;
}
// Do not clip this offset to the floor.
hitz += MissileHeight;
Actor act = Spawn (trail, (pos.xy, hitz), ALLOW_REPLACE);
if (act != null)
{
if (bGetOwner && target != null)
act.target = target;
else
act.target = self;
act.angle = angle;
act.pitch = pitch;
}
}
}
//----------------------------------------------------------------------------
//
// AFastProjectile :: Tick
//
// Thinker for the ultra-fast projectiles used by Heretic and Hexen
//
//----------------------------------------------------------------------------
override void Tick ()
{
ClearInterpolation();
double oldz = pos.Z;
if (isFrozen())
return;
// [RH] Ripping is a little different than it was in Hexen
FCheckPosition tm;
tm.DoRipping = bRipper;
int count = 8;
if (radius > 0)
{
while (abs(Vel.X) >= radius * count || abs(Vel.Y) >= radius * count)
{
// we need to take smaller steps.
count += count;
}
}
if (height > 0)
{
while (abs(Vel.Z) >= height * count)
{
count += count;
}
}
// Handle movement
bool ismoved = Vel != (0, 0, 0)
// Check Z position set during previous tick.
// It should be strictly equal to the argument of SetZ() function.
|| ( (pos.Z != floorz ) /* Did it hit the floor? */
&& (pos.Z != ceilingz - Height) /* Did it hit the ceiling? */ );
if (ismoved)
{
// force some lateral movement so that collision detection works as intended.
if (bMissile && Vel.X == 0 && Vel.Y == 0 && !IsZeroDamage())
{
Vel.X = MinVel;
}
Vector3 frac = Vel / count;
int changexy = frac.X != 0 || frac.Y != 0;
int ripcount = count / 8;
for (int i = 0; i < count; i++)
{
if (changexy)
{
if (--ripcount <= 0)
{
tm.ClearLastRipped(); // [RH] Do rip damage each step, like Hexen
}
if (!TryMove (Pos.XY + frac.XY, true, NULL, tm))
{ // Blocked move
if (!bSkyExplode)
{
let l = tm.ceilingline;
if (l &&
l.backsector &&
l.backsector.GetTexture(sector.ceiling) == skyflatnum)
{
let posr = PosRelative(l.backsector);
if (pos.Z >= l.backsector.ceilingplane.ZatPoint(posr.XY))
{
// Hack to prevent missiles exploding against the sky.
// Does not handle sky floors.
Destroy ();
return;
}
}
// [RH] Don't explode on horizon lines.
if (BlockingLine != NULL && BlockingLine.special == Line_Horizon)
{
Destroy ();
return;
}
}
ExplodeMissile (BlockingLine, BlockingMobj);
return;
}
}
AddZ(frac.Z);
UpdateWaterLevel ();
oldz = pos.Z;
if (oldz <= floorz)
{ // Hit the floor
if (floorpic == skyflatnum && !bSkyExplode)
{
// [RH] Just remove the missile without exploding it
// if this is a sky floor.
Destroy ();
return;
}
SetZ(floorz);
HitFloor ();
Destructible.ProjectileHitPlane(self, SECPART_Floor);
ExplodeMissile (NULL, NULL);
return;
}
if (pos.Z + height > ceilingz)
{ // Hit the ceiling
if (ceilingpic == skyflatnum && !bSkyExplode)
{
Destroy ();
return;
}
SetZ(ceilingz - Height);
Destructible.ProjectileHitPlane(self, SECPART_Ceiling);
ExplodeMissile (NULL, NULL);
return;
}
CheckPortalTransition();
if (changexy && ripcount <= 0)
{
ripcount = count >> 3;
// call the 'Effect' method.
Effect();
}
}
}
if (!CheckNoDelay())
return; // freed itself
// Advance the state
if (tics != -1)
{
if (tics > 0) tics--;
while (!tics)
{
if (!SetState (CurState.NextState))
{ // mobj was removed
return;
}
}
}
}
}