示例#1
0
        private bool TraverseIntercepts(Func <Intercept, bool> func, Fixed maxFrac)
        {
            var count = interceptCount;

            Intercept intercept = null;

            while (count-- > 0)
            {
                var dist = Fixed.MaxValue;
                for (var i = 0; i < interceptCount; i++)
                {
                    if (intercepts[i].Frac < dist)
                    {
                        dist      = intercepts[i].Frac;
                        intercept = intercepts[i];
                    }
                }

                if (dist > maxFrac)
                {
                    // Checked everything in range.
                    return(true);
                }

                if (!func(intercept))
                {
                    // Don't bother going farther.
                    return(false);
                }

                intercept.Frac = Fixed.MaxValue;
            }

            // Everything was traversed.
            return(true);
        }
示例#2
0
        /// <summary>
        /// Fire a hitscan bullet along the aiming line.
        /// </summary>
        private bool ShootTraverse(Intercept intercept)
        {
            var mi = world.MapInteraction;
            var pt = world.PathTraversal;

            if (intercept.Line != null)
            {
                var line = intercept.Line;

                if (line.Special != 0)
                {
                    mi.ShootSpecialLine(currentShooter, line);
                }

                if ((line.Flags & LineFlags.TwoSided) == 0)
                {
                    goto hitLine;
                }

                var mc = world.MapCollision;

                // Crosses a two sided line.
                mc.LineOpening(line);

                var dist = currentRange * intercept.Frac;

                if (line.FrontSector.FloorHeight != line.BackSector.FloorHeight)
                {
                    var slope = (mc.OpenBottom - currentShooterZ) / dist;
                    if (slope > currentAimSlope)
                    {
                        goto hitLine;
                    }
                }

                if (line.FrontSector.CeilingHeight != line.BackSector.CeilingHeight)
                {
                    var slope = (mc.OpenTop - currentShooterZ) / dist;
                    if (slope < currentAimSlope)
                    {
                        goto hitLine;
                    }
                }

                // Shot continues.
                return(true);

                // Hit line.
hitLine:

                // Position a bit closer.
                var frac = intercept.Frac - Fixed.FromInt(4) / currentRange;
                var x = pt.Trace.X + pt.Trace.Dx * frac;
                var y = pt.Trace.Y + pt.Trace.Dy * frac;
                var z = currentShooterZ + currentAimSlope * (frac * currentRange);

                if (line.FrontSector.CeilingFlat == world.Map.SkyFlatNumber)
                {
                    // Don't shoot the sky!
                    if (z > line.FrontSector.CeilingHeight)
                    {
                        return(false);
                    }

                    // It's a sky hack wall.
                    if (line.BackSector != null && line.BackSector.CeilingFlat == world.Map.SkyFlatNumber)
                    {
                        return(false);
                    }
                }

                // Spawn bullet puffs.
                SpawnPuff(x, y, z);

                // Don't go any farther.
                return(false);
            }

            {
                // Shoot a thing.
                var thing = intercept.Thing;
                if (thing == currentShooter)
                {
                    // Can't shoot self.
                    return(true);
                }

                if ((thing.Flags & MobjFlags.Shootable) == 0)
                {
                    // Corpse or something.
                    return(true);
                }

                // Check angles to see if the thing can be aimed at.
                var dist          = currentRange * intercept.Frac;
                var thingTopSlope = (thing.Z + thing.Height - currentShooterZ) / dist;

                if (thingTopSlope < currentAimSlope)
                {
                    // Shot over the thing.
                    return(true);
                }

                var thingBottomSlope = (thing.Z - currentShooterZ) / dist;

                if (thingBottomSlope > currentAimSlope)
                {
                    // Shot under the thing.
                    return(true);
                }

                // Hit thing.
                // Position a bit closer.
                var frac = intercept.Frac - Fixed.FromInt(10) / currentRange;

                var x = pt.Trace.X + pt.Trace.Dx * frac;
                var y = pt.Trace.Y + pt.Trace.Dy * frac;
                var z = currentShooterZ + currentAimSlope * (frac * currentRange);

                // Spawn bullet puffs or blod spots, depending on target type.
                if ((intercept.Thing.Flags & MobjFlags.NoBlood) != 0)
                {
                    SpawnPuff(x, y, z);
                }
                else
                {
                    SpawnBlood(x, y, z, currentDamage);
                }

                if (currentDamage != 0)
                {
                    world.ThingInteraction.DamageMobj(thing, currentShooter, currentShooter, currentDamage);
                }

                // Don't go any farther.
                return(false);
            }
        }
示例#3
0
        /// <summary>
        /// Find a thing or wall which is on the aiming line.
        /// Sets lineTaget and aimSlope when a target is aimed at.
        /// </summary>
        private bool AimTraverse(Intercept intercept)
        {
            if (intercept.Line != null)
            {
                var line = intercept.Line;

                if ((line.Flags & LineFlags.TwoSided) == 0)
                {
                    // Stop.
                    return(false);
                }

                var mc = world.MapCollision;

                // Crosses a two sided line.
                // A two sided line will restrict the possible target ranges.
                mc.LineOpening(line);

                if (mc.OpenBottom >= mc.OpenTop)
                {
                    // Stop.
                    return(false);
                }

                var dist = currentRange * intercept.Frac;

                if (line.FrontSector.FloorHeight != line.BackSector.FloorHeight)
                {
                    var slope = (mc.OpenBottom - currentShooterZ) / dist;
                    if (slope > bottomSlope)
                    {
                        bottomSlope = slope;
                    }
                }

                if (line.FrontSector.CeilingHeight != line.BackSector.CeilingHeight)
                {
                    var slope = (mc.OpenTop - currentShooterZ) / dist;
                    if (slope < topSlope)
                    {
                        topSlope = slope;
                    }
                }

                if (topSlope <= bottomSlope)
                {
                    // Stop.
                    return(false);
                }

                // Shot continues.
                return(true);
            }

            // Shoot a thing.
            var thing = intercept.Thing;

            if (thing == currentShooter)
            {
                // Can't shoot self.
                return(true);
            }

            {
                if ((thing.Flags & MobjFlags.Shootable) == 0)
                {
                    // Corpse or something.
                    return(true);
                }

                // Check angles to see if the thing can be aimed at.
                var dist          = currentRange * intercept.Frac;
                var thingTopSlope = (thing.Z + thing.Height - currentShooterZ) / dist;

                if (thingTopSlope < bottomSlope)
                {
                    // Shot over the thing.
                    return(true);
                }

                var thingBottomSlope = (thing.Z - currentShooterZ) / dist;

                if (thingBottomSlope > topSlope)
                {
                    // Shot under the thing.
                    return(true);
                }

                // This thing can be hit!
                if (thingTopSlope > topSlope)
                {
                    thingTopSlope = topSlope;
                }

                if (thingBottomSlope < bottomSlope)
                {
                    thingBottomSlope = bottomSlope;
                }

                currentAimSlope = (thingTopSlope + thingBottomSlope) / 2;
                lineTarget      = thing;

                // Don't go any farther.
                return(false);
            }
        }
示例#4
0
        /// <summary>
        /// Fire a hitscan bullet along the aiming line.
        /// </summary>
        private bool ShootTraverse(Intercept intercept)
        {
            var mi = world.MapInteraction;
            var pt = world.PathTraversal;

            if (intercept.Line != null)
            {
                var line = intercept.Line;

                if (line.Special != 0)
                {
                    mi.ShootSpecialLine(currentShooter, line);
                }

                if ((line.Flags & LineFlags.TwoSided) == 0)
                {
                    goto hitLine;
                }

                var mc = world.MapCollision;

                // Crosses a two sided line.
                mc.LineOpening(line);

                var dist = currentRange * intercept.Frac;

                // Similar to AimTraverse, the code below is imported from Chocolate Doom.
                if (line.BackSector == null)
                {
                    {
                        var slope = (mc.OpenBottom - currentShooterZ) / dist;
                        if (slope > currentAimSlope)
                        {
                            goto hitLine;
                        }
                    }

                    {
                        var slope = (mc.OpenTop - currentShooterZ) / dist;
                        if (slope < currentAimSlope)
                        {
                            goto hitLine;
                        }
                    }
                }
                else
                {
                    if (line.FrontSector.FloorHeight != line.BackSector.FloorHeight)
                    {
                        var slope = (mc.OpenBottom - currentShooterZ) / dist;
                        if (slope > currentAimSlope)
                        {
                            goto hitLine;
                        }
                    }

                    if (line.FrontSector.CeilingHeight != line.BackSector.CeilingHeight)
                    {
                        var slope = (mc.OpenTop - currentShooterZ) / dist;
                        if (slope < currentAimSlope)
                        {
                            goto hitLine;
                        }
                    }
                }

                // Shot continues.
                return(true);

                // Hit line.
hitLine:

                // Position a bit closer.
                var frac = intercept.Frac - Fixed.FromInt(4) / currentRange;
                var x = pt.Trace.X + pt.Trace.Dx * frac;
                var y = pt.Trace.Y + pt.Trace.Dy * frac;
                var z = currentShooterZ + currentAimSlope * (frac * currentRange);

                if (line.FrontSector.CeilingFlat == world.Map.SkyFlatNumber)
                {
                    // Don't shoot the sky!
                    if (z > line.FrontSector.CeilingHeight)
                    {
                        return(false);
                    }

                    // It's a sky hack wall.
                    if (line.BackSector != null && line.BackSector.CeilingFlat == world.Map.SkyFlatNumber)
                    {
                        return(false);
                    }
                }

                // Spawn bullet puffs.
                SpawnPuff(x, y, z);

                // Don't go any farther.
                return(false);
            }

            {
                // Shoot a thing.
                var thing = intercept.Thing;
                if (thing == currentShooter)
                {
                    // Can't shoot self.
                    return(true);
                }

                if ((thing.Flags & MobjFlags.Shootable) == 0)
                {
                    // Corpse or something.
                    return(true);
                }

                // Check angles to see if the thing can be aimed at.
                var dist          = currentRange * intercept.Frac;
                var thingTopSlope = (thing.Z + thing.Height - currentShooterZ) / dist;

                if (thingTopSlope < currentAimSlope)
                {
                    // Shot over the thing.
                    return(true);
                }

                var thingBottomSlope = (thing.Z - currentShooterZ) / dist;

                if (thingBottomSlope > currentAimSlope)
                {
                    // Shot under the thing.
                    return(true);
                }

                // Hit thing.
                // Position a bit closer.
                var frac = intercept.Frac - Fixed.FromInt(10) / currentRange;

                var x = pt.Trace.X + pt.Trace.Dx * frac;
                var y = pt.Trace.Y + pt.Trace.Dy * frac;
                var z = currentShooterZ + currentAimSlope * (frac * currentRange);

                //* implement if(PuffType == MT_BLASTERPUFF1)
                // { // Make blaster big puff
                //  mo = P_SpawnMobj(x, y, z, MT_BLASTERPUFF2);
                //  S_StartSound(mo, sfx_blshit);
                // }
                // else
                // {
                SpawnPuff(x, y, z);
                // }

                if (currentDamage != 0)
                {
                    //* implement if(!(in->d.thing->flags&MF_NOBLOOD) && P_Random() < 192)
                    // {
                    //     P_BloodSplatter(x, y, z, in->d.thing);
                    // }
                    world.ThingInteraction.DamageMobj(thing, currentShooter, currentShooter, currentDamage);
                }

                // Don't go any farther.
                return(false);
            }
        }