Esempio n. 1
0
        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);
            }
        }
Esempio n. 2
0
            private void UnArchiveThinkers(World world)
            {
                var thinkers = world.Thinkers;
                var ta       = world.ThingAllocation;

                // Remove all the current thinkers.
                foreach (var thinker in thinkers)
                {
                    var mobj = thinker as Mobj;
                    if (mobj != null)
                    {
                        ta.RemoveMobj(mobj);
                    }
                }
                thinkers.Reset();

                // Read in saved thinkers.
                while (true)
                {
                    var tclass = (ThinkerClass)data[ptr++];
                    switch (tclass)
                    {
                    case ThinkerClass.End:
                        // End of list.
                        return;

                    case ThinkerClass.Mobj:
                        PadPointer();
                        var mobj = new Mobj(world);
                        mobj.ThinkerState = ReadThinkerState(data, ptr + 8);
                        mobj.X            = new Fixed(BitConverter.ToInt32(data, ptr + 12));
                        mobj.Y            = new Fixed(BitConverter.ToInt32(data, ptr + 16));
                        mobj.Z            = new Fixed(BitConverter.ToInt32(data, ptr + 20));
                        mobj.Angle        = new Angle(BitConverter.ToInt32(data, ptr + 32));
                        mobj.Sprite       = (Sprite)BitConverter.ToInt32(data, ptr + 36);
                        mobj.Frame        = BitConverter.ToInt32(data, ptr + 40);
                        mobj.FloorZ       = new Fixed(BitConverter.ToInt32(data, ptr + 56));
                        mobj.CeilingZ     = new Fixed(BitConverter.ToInt32(data, ptr + 60));
                        mobj.Radius       = new Fixed(BitConverter.ToInt32(data, ptr + 64));
                        mobj.Height       = new Fixed(BitConverter.ToInt32(data, ptr + 68));
                        mobj.MomX         = new Fixed(BitConverter.ToInt32(data, ptr + 72));
                        mobj.MomY         = new Fixed(BitConverter.ToInt32(data, ptr + 76));
                        mobj.MomZ         = new Fixed(BitConverter.ToInt32(data, ptr + 80));
                        mobj.Type         = (MobjType)BitConverter.ToInt32(data, ptr + 88);
                        mobj.Info         = DoomInfo.MobjInfos[(int)mobj.Type];
                        mobj.Tics         = BitConverter.ToInt32(data, ptr + 96);
                        mobj.State        = DoomInfo.States[BitConverter.ToInt32(data, ptr + 100)];
                        mobj.Flags        = (MobjFlags)BitConverter.ToInt32(data, ptr + 104);
                        mobj.Health       = BitConverter.ToInt32(data, ptr + 108);
                        mobj.MoveDir      = (Direction)BitConverter.ToInt32(data, ptr + 112);
                        mobj.MoveCount    = BitConverter.ToInt32(data, ptr + 116);
                        mobj.ReactionTime = BitConverter.ToInt32(data, ptr + 124);
                        mobj.Threshold    = BitConverter.ToInt32(data, ptr + 128);
                        var playerNumber = BitConverter.ToInt32(data, ptr + 132);
                        if (playerNumber != 0)
                        {
                            mobj.Player      = world.Options.Players[playerNumber - 1];
                            mobj.Player.Mobj = mobj;
                        }
                        mobj.LastLook   = BitConverter.ToInt32(data, ptr + 136);
                        mobj.SpawnPoint = new MapThing(
                            Fixed.FromInt(BitConverter.ToInt16(data, ptr + 140)),
                            Fixed.FromInt(BitConverter.ToInt16(data, ptr + 142)),
                            new Angle(Angle.Ang45.Data * (uint)(BitConverter.ToInt16(data, ptr + 144) / 45)),
                            BitConverter.ToInt16(data, ptr + 146),
                            (ThingFlags)BitConverter.ToInt16(data, ptr + 148));
                        ptr += 154;

                        world.ThingMovement.SetThingPosition(mobj);
                        // mobj.FloorZ = mobj.Subsector.Sector.FloorHeight;
                        // mobj.CeilingZ = mobj.Subsector.Sector.CeilingHeight;
                        thinkers.Add(mobj);
                        break;

                    default:
                        throw new Exception("Unknown thinker class in savegame!");
                    }
                }
            }
Esempio n. 3
0
        public void Reborn()
        {
            Mobj        = null;
            PlayerState = PlayerState.Live;
            Cmd.Clear();

            ViewZ           = Fixed.Zero;
            ViewHeight      = Fixed.Zero;
            DeltaViewHeight = Fixed.Zero;
            Bob             = Fixed.Zero;

            Health      = MAXHEALTH;
            ArmorPoints = 0;
            ArmorType   = 0;

            Array.Clear(Powers, 0, Powers.Length);
            Array.Clear(Cards, 0, Cards.Length);
            Backpack = false;

            Array.Clear(Frags, 0, Frags.Length);

            ReadyWeapon   = WeaponType.Pistol;
            PendingWeapon = WeaponType.Pistol;

            Array.Clear(WeaponOwned, 0, WeaponOwned.Length);
            Array.Clear(Ammo, 0, Ammo.Length);
            Array.Clear(MaxAmmo, 0, MaxAmmo.Length);

            WeaponOwned[(int)WeaponType.Fist]   = true;
            WeaponOwned[(int)WeaponType.Pistol] = true;
            Ammo[(int)AmmoType.Clip]            = 50;
            for (var i = 0; i < (int)AmmoType.Count; i++)
            {
                MaxAmmo[i] = DoomInfo.AmmoInfos.Max[i];
            }

            // don't do anything immediately
            UseDown    = true;
            AttackDown = true;

            Cheats = 0;

            Refire = 0;

            Message = null;

            DamageCount = 0;
            BonusCount  = 0;

            Attacker = null;

            ExtraLight = 0;

            FixedColorMap = 0;

            ColorMap = 0;

            foreach (var psp in PlayerSprites)
            {
                psp.Clear();
            }

            DidSecret = false;
        }
Esempio n. 4
0
        public void CalcHeight(Player player)
        {
            // Regular movement bobbing.
            // It needs to be calculated for gun swing even if not on ground.
            //
            // OPTIMIZE:
            //     Tablify angle.
            //
            // Note:
            //     A LUT allows for effects like a ramp with low health.

            player.Bob   = player.Mobj.MomX * player.Mobj.MomX + player.Mobj.MomY * player.Mobj.MomY;
            player.Bob >>= 2;
            if (player.Bob > maxBob)
            {
                player.Bob = maxBob;
            }

            if ((player.Cheats & CheatFlags.NoMomentum) != 0 || !onGround)
            {
                player.ViewZ = player.Mobj.Z + Player.VIEWHEIGHT;

                if (player.ViewZ > player.Mobj.CeilingZ - Fixed.FromInt(4))
                {
                    player.ViewZ = player.Mobj.CeilingZ - Fixed.FromInt(4);
                }

                player.ViewZ = player.Mobj.Z + player.ViewHeight;

                return;
            }

            var angle = (Trig.FineAngleCount / 20 * world.levelTime) & Trig.FineMask;

            var bob = (player.Bob / 2) * Trig.Sin(angle);

            // Move viewheight.
            if (player.PlayerState == PlayerState.Live)
            {
                player.ViewHeight += player.DeltaViewHeight;

                if (player.ViewHeight > Player.VIEWHEIGHT)
                {
                    player.ViewHeight      = Player.VIEWHEIGHT;
                    player.DeltaViewHeight = Fixed.Zero;
                }

                if (player.ViewHeight < Player.VIEWHEIGHT / 2)
                {
                    player.ViewHeight = Player.VIEWHEIGHT / 2;

                    if (player.DeltaViewHeight <= Fixed.Zero)
                    {
                        player.DeltaViewHeight = new Fixed(1);
                    }
                }

                if (player.DeltaViewHeight != Fixed.Zero)
                {
                    player.DeltaViewHeight += Fixed.One / 4;

                    if (player.DeltaViewHeight == Fixed.Zero)
                    {
                        player.DeltaViewHeight = new Fixed(1);
                    }
                }
            }

            player.ViewZ = player.Mobj.Z + player.ViewHeight + bob;

            if (player.ViewZ > player.Mobj.CeilingZ - Fixed.FromInt(4))
            {
                player.ViewZ = player.Mobj.CeilingZ - Fixed.FromInt(4);
            }
        }
Esempio n. 5
0
        public static Node FromData(byte[] data, int offset)
        {
            var x           = BitConverter.ToInt16(data, offset);
            var y           = BitConverter.ToInt16(data, offset + 2);
            var dx          = BitConverter.ToInt16(data, offset + 4);
            var dy          = BitConverter.ToInt16(data, offset + 6);
            var bbox0Top    = BitConverter.ToInt16(data, offset + 8);
            var bbox0Bottom = BitConverter.ToInt16(data, offset + 10);
            var bbox0Left   = BitConverter.ToInt16(data, offset + 12);
            var bbox0Right  = BitConverter.ToInt16(data, offset + 14);
            var bbox1Top    = BitConverter.ToInt16(data, offset + 16);
            var bbox1Bottom = BitConverter.ToInt16(data, offset + 18);
            var bbox1Left   = BitConverter.ToInt16(data, offset + 20);
            var bbox1Right  = BitConverter.ToInt16(data, offset + 22);
            var children0   = BitConverter.ToInt16(data, offset + 24);
            var children1   = BitConverter.ToInt16(data, offset + 26);

            return(new Node(
                       Fixed.FromInt(x), Fixed.FromInt(y),
                       Fixed.FromInt(dx), Fixed.FromInt(dy),
                       Fixed.FromInt(bbox0Top), Fixed.FromInt(bbox0Bottom), Fixed.FromInt(bbox0Left), Fixed.FromInt(bbox0Right),
                       Fixed.FromInt(bbox1Top), Fixed.FromInt(bbox1Bottom), Fixed.FromInt(bbox1Left), Fixed.FromInt(bbox1Right),
                       children0, children1));
        }
Esempio n. 6
0
        /// <summary>
        /// Spawn a mobj at the mapthing.
        /// </summary>
        public void SpawnMapThing(MapThing mt)
        {
            // Count deathmatch start positions.
            if (mt.Type == 11)
            {
                if (deathmatchStarts.Count < 10)
                {
                    deathmatchStarts.Add(mt);
                }

                return;
            }

            // Check for players specially.
            if (mt.Type <= 4)
            {
                var playerNumber = mt.Type - 1;

                // This check is neccesary in Plutonia MAP12,
                // which contains an unknown thing with type 0.
                if (playerNumber < 0)
                {
                    return;
                }

                // Save spots for respawning in network games.
                playerStarts[playerNumber] = mt;

                if (world.Options.Deathmatch == 0)
                {
                    SpawnPlayer(mt);
                }

                return;
            }

            if (mt.Type == 11 || mt.Type <= 4)
            {
                return;
            }

            // Check for apropriate skill level.
            if (!world.Options.NetGame && ((int)mt.Flags & 16) != 0)
            {
                return;
            }

            int bit;

            if (world.Options.Skill == GameSkill.Baby)
            {
                bit = 1;
            }
            else if (world.Options.Skill == GameSkill.Nightmare)
            {
                bit = 4;
            }
            else
            {
                bit = 1 << ((int)world.Options.Skill - 1);
            }

            if (((int)mt.Flags & bit) == 0)
            {
                return;
            }

            // Find which type to spawn.
            int i;

            for (i = 0; i < DoomInfo.MobjInfos.Length; i++)
            {
                if (mt.Type == DoomInfo.MobjInfos[i].DoomEdNum)
                {
                    break;
                }
            }

            if (i == DoomInfo.MobjInfos.Length)
            {
                throw new Exception("Unknown type!");
            }

            // Don't spawn keycards and players in deathmatch.
            if (world.Options.Deathmatch != 0 &&
                (DoomInfo.MobjInfos[i].Flags & MobjFlags.NotDeathmatch) != 0)
            {
                return;
            }

            // Don't spawn any monsters if -nomonsters.
            if (world.Options.NoMonsters &&
                (i == (int)MobjType.Skull ||
                 (DoomInfo.MobjInfos[i].Flags & MobjFlags.CountKill) != 0))
            {
                return;
            }

            // Spawn it.
            Fixed x = mt.X;
            Fixed y = mt.Y;
            Fixed z;

            if ((DoomInfo.MobjInfos[i].Flags & MobjFlags.SpawnCeiling) != 0)
            {
                z = Mobj.OnCeilingZ;
            }
            else
            {
                z = Mobj.OnFloorZ;
            }

            var mobj = SpawnMobj(x, y, z, (MobjType)i);

            mobj.SpawnPoint = mt;

            if (mobj.Tics > 0)
            {
                mobj.Tics = 1 + (world.Random.Next() % mobj.Tics);
            }

            if ((mobj.Flags & MobjFlags.CountKill) != 0)
            {
                world.TotalKills++;
            }

            if ((mobj.Flags & MobjFlags.CountItem) != 0)
            {
                world.TotalItems++;
            }

            mobj.Angle = mt.Angle;

            if ((mt.Flags & ThingFlags.Ambush) != 0)
            {
                mobj.Flags |= MobjFlags.Ambush;
            }
        }
Esempio n. 7
0
        private void SlideMove(Mobj thing)
        {
            var pt = world.PathTraversal;

            slideThing = thing;

            var hitCount = 0;

retry:
            // Don't loop forever.
            if (++hitCount == 3)
            {
                // The move most have hit the middle, so stairstep.
                StairStep(thing);
                return;
            }

            Fixed leadX;
            Fixed leadY;
            Fixed trailX;
            Fixed trailY;

            // Trace along the three leading corners.
            if (thing.MomX > Fixed.Zero)
            {
                leadX  = thing.X + thing.Radius;
                trailX = thing.X - thing.Radius;
            }
            else
            {
                leadX  = thing.X - thing.Radius;
                trailX = thing.X + thing.Radius;
            }

            if (thing.MomY > Fixed.Zero)
            {
                leadY  = thing.Y + thing.Radius;
                trailY = thing.Y - thing.Radius;
            }
            else
            {
                leadY  = thing.Y - thing.Radius;
                trailY = thing.Y + thing.Radius;
            }

            bestSlideFrac = new Fixed(Fixed.FracUnit + 1);

            pt.PathTraverse(
                leadX, leadY, leadX + thing.MomX, leadY + thing.MomY,
                PathTraverseFlags.AddLines, slideTraverseFunc);

            pt.PathTraverse(
                trailX, leadY, trailX + thing.MomX, leadY + thing.MomY,
                PathTraverseFlags.AddLines, slideTraverseFunc);

            pt.PathTraverse(
                leadX, trailY, leadX + thing.MomX, trailY + thing.MomY,
                PathTraverseFlags.AddLines, slideTraverseFunc);

            // Move up to the wall.
            if (bestSlideFrac == new Fixed(Fixed.FracUnit + 1))
            {
                // The move most have hit the middle, so stairstep.
                StairStep(thing);
                return;
            }

            // Fudge a bit to make sure it doesn't hit.
            bestSlideFrac = new Fixed(bestSlideFrac.Data - 0x800);
            if (bestSlideFrac > Fixed.Zero)
            {
                var newX = thing.MomX * bestSlideFrac;
                var newY = thing.MomY * bestSlideFrac;

                if (!TryMove(thing, thing.X + newX, thing.Y + newY))
                {
                    // The move most have hit the middle, so stairstep.
                    StairStep(thing);
                    return;
                }
            }

            // Now continue along the wall.
            // First calculate remainder.
            bestSlideFrac = new Fixed(Fixed.FracUnit - (bestSlideFrac.Data + 0x800));

            if (bestSlideFrac > Fixed.One)
            {
                bestSlideFrac = Fixed.One;
            }

            if (bestSlideFrac <= Fixed.Zero)
            {
                return;
            }

            slideMoveX = thing.MomX * bestSlideFrac;
            slideMoveY = thing.MomY * bestSlideFrac;

            // Clip the moves.
            HitSlideLine(bestSlideLine);

            thing.MomX = slideMoveX;
            thing.MomY = slideMoveY;

            if (!TryMove(thing, thing.X + slideMoveX, thing.Y + slideMoveY))
            {
                goto retry;
            }
        }
Esempio n. 8
0
 public Vertex(Fixed x, Fixed y)
 {
     this.x = x;
     this.y = y;
 }
Esempio n. 9
0
        // Attempt to move to a new position, crossing special lines unless
        // MobjFlags.Teleport is set.
        public bool TryMove(Mobj thing, Fixed x, Fixed y)
        {
            floatOk = false;

            if (!CheckPosition(thing, x, y))
            {
                // Solid wall or thing.
                return(false);
            }

            if ((thing.Flags & MobjFlags.NoClip) == 0)
            {
                if (currentCeilingZ - currentFloorZ < thing.Height)
                {
                    // Doesn't fit.
                    return(false);
                }

                floatOk = true;

                if ((thing.Flags & MobjFlags.Teleport) == 0 &&
                    currentCeilingZ - thing.Z < thing.Height)
                {
                    // Mobj must lower itself to fit.
                    return(false);
                }

                if ((thing.Flags & MobjFlags.Teleport) == 0 &&
                    currentFloorZ - thing.Z > Fixed.FromInt(24))
                {
                    // Too big a step up.
                    return(false);
                }

                if ((thing.Flags & (MobjFlags.DropOff | MobjFlags.Float)) == 0 &&
                    currentFloorZ - currentDropoffZ > Fixed.FromInt(24))
                {
                    // Don't stand over a dropoff.
                    return(false);
                }
            }

            // The move is ok,
            // so link the thing into its new position.
            UnsetThingPosition(thing);

            var oldx = thing.X;
            var oldy = thing.Y;

            thing.FloorZ   = currentFloorZ;
            thing.CeilingZ = currentCeilingZ;
            thing.X        = x;
            thing.Y        = y;

            SetThingPosition(thing);

            // If any special lines were hit, do the effect.
            if ((thing.Flags & (MobjFlags.Teleport | MobjFlags.NoClip)) == 0)
            {
                while (crossedSpecialCount-- > 0)
                {
                    // See if the line was crossed.
                    var line    = crossedSpecials[crossedSpecialCount];
                    var newSide = Geometry.PointOnLineSide(thing.X, thing.Y, line);
                    var oldSide = Geometry.PointOnLineSide(oldx, oldy, line);
                    if (newSide != oldSide)
                    {
                        if (line.Special != 0)
                        {
                            world.MapInteraction.CrossSpecialLine(line, oldSide, thing);
                        }
                    }
                }
            }

            return(true);
        }
Esempio n. 10
0
        public void XYMovement(Mobj thing)
        {
            if (thing.MomX == Fixed.Zero && thing.MomY == Fixed.Zero)
            {
                if ((thing.Flags & MobjFlags.SkullFly) != 0)
                {
                    // The skull slammed into something.
                    thing.Flags &= ~MobjFlags.SkullFly;
                    thing.MomX   = thing.MomY = thing.MomZ = Fixed.Zero;

                    thing.SetState(thing.Info.SpawnState);
                }

                return;
            }

            var player = thing.Player;

            if (thing.MomX > maxMove)
            {
                thing.MomX = maxMove;
            }
            else if (thing.MomX < -maxMove)
            {
                thing.MomX = -maxMove;
            }

            if (thing.MomY > maxMove)
            {
                thing.MomY = maxMove;
            }
            else if (thing.MomY < -maxMove)
            {
                thing.MomY = -maxMove;
            }

            var moveX = thing.MomX;
            var moveY = thing.MomY;

            do
            {
                Fixed pMoveX;
                Fixed pMoveY;

                if (moveX > maxMove / 2 || moveY > maxMove / 2)
                {
                    pMoveX = thing.X + moveX / 2;
                    pMoveY = thing.Y + moveY / 2;
                    moveX  = new Fixed(moveX.Data >> 1);
                    moveY  = new Fixed(moveY.Data >> 1);
                }
                else
                {
                    pMoveX = thing.X + moveX;
                    pMoveY = thing.Y + moveY;
                    moveX  = moveY = Fixed.Zero;
                }

                if (!TryMove(thing, pMoveX, pMoveY))
                {
                    // Blocked move.
                    if (thing.Player != null)
                    {   // Try to slide along it.
                        SlideMove(thing);
                    }
                    else if ((thing.Flags & MobjFlags.Missile) != 0)
                    {
                        // Explode a missile.
                        if (currentCeilingLine != null &&
                            currentCeilingLine.BackSector != null &&
                            currentCeilingLine.BackSector.CeilingFlat == world.Map.SkyFlatNumber)
                        {
                            // Hack to prevent missiles exploding against the sky.
                            // Does not handle sky floors.
                            world.ThingAllocation.RemoveMobj(thing);
                            return;
                        }
                        world.ThingInteraction.ExplodeMissile(thing);
                    }
                    else
                    {
                        thing.MomX = thing.MomY = Fixed.Zero;
                    }
                }
            }while (moveX != Fixed.Zero || moveY != Fixed.Zero);

            // Slow down.
            if (player != null && (player.Cheats & CheatFlags.NoMomentum) != 0)
            {
                // Debug option for no sliding at all.
                thing.MomX = thing.MomY = Fixed.Zero;
                return;
            }

            if ((thing.Flags & (MobjFlags.Missile | MobjFlags.SkullFly)) != 0)
            {
                // No friction for missiles ever.
                return;
            }

            if (thing.Z > thing.FloorZ)
            {
                // No friction when airborne.
                return;
            }

            if ((thing.Flags & MobjFlags.Corpse) != 0)
            {
                // Do not stop sliding if halfway off a step with some momentum.
                if (thing.MomX > Fixed.One / 4 ||
                    thing.MomX < -Fixed.One / 4 ||
                    thing.MomY > Fixed.One / 4 ||
                    thing.MomY < -Fixed.One / 4)
                {
                    if (thing.FloorZ != thing.Subsector.Sector.FloorHeight)
                    {
                        return;
                    }
                }
            }

            if (thing.MomX > -stopSpeed &&
                thing.MomX < stopSpeed &&
                thing.MomY > -stopSpeed &&
                thing.MomY < stopSpeed &&
                (player == null || (player.Cmd.ForwardMove == 0 && player.Cmd.SideMove == 0)))
            {
                // If in a walking frame, stop moving.
                if (player != null && (player.Mobj.State.Number - (int)MobjState.PlayRun1) < 4)
                {
                    player.Mobj.SetState(MobjState.Play);
                }

                thing.MomX = Fixed.Zero;
                thing.MomY = Fixed.Zero;
            }
            else
            {
                thing.MomX = thing.MomX * friction;
                thing.MomY = thing.MomY * friction;
            }
        }
Esempio n. 11
0
        public bool CheckPosition(Mobj thing, Fixed x, Fixed y)
        {
            var map = world.Map;
            var bm  = map.BlockMap;

            currentThing = thing;
            currentFlags = thing.Flags;

            currentX = x;
            currentY = y;

            currentBox[Box.Top]    = y + currentThing.Radius;
            currentBox[Box.Bottom] = y - currentThing.Radius;
            currentBox[Box.Right]  = x + currentThing.Radius;
            currentBox[Box.Left]   = x - currentThing.Radius;

            var newsubsec = Geometry.PointInSubsector(x, y, map);

            currentCeilingLine = null;

            // The base floor / ceiling is from the subsector that contains the point.
            // Any contacted lines the step closer together will adjust them.
            currentFloorZ   = currentDropoffZ = newsubsec.Sector.FloorHeight;
            currentCeilingZ = newsubsec.Sector.CeilingHeight;

            var validCount = world.GetNewValidCount();

            crossedSpecialCount = 0;

            if ((currentFlags & MobjFlags.NoClip) != 0)
            {
                return(true);
            }

            // Check things first, possibly picking things up.
            // The bounding box is extended by MaxThingRadius because mobj_ts are grouped into
            // mapblocks based on their origin point, and can overlap into adjacent blocks by up
            // to MaxThingRadius units.
            {
                var blockX1 = bm.GetBlockX(currentBox[Box.Left] - GameConstants.MaxThingRadius);
                var blockX2 = bm.GetBlockX(currentBox[Box.Right] + GameConstants.MaxThingRadius);
                var blockY1 = bm.GetBlockY(currentBox[Box.Bottom] - GameConstants.MaxThingRadius);
                var blockY2 = bm.GetBlockY(currentBox[Box.Top] + GameConstants.MaxThingRadius);

                for (var bx = blockX1; bx <= blockX2; bx++)
                {
                    for (var by = blockY1; by <= blockY2; by++)
                    {
                        if (!map.BlockMap.IterateThings(bx, by, checkThingFunc))
                        {
                            return(false);
                        }
                    }
                }
            }

            // Check lines.
            {
                var blockX1 = bm.GetBlockX(currentBox[Box.Left]);
                var blockX2 = bm.GetBlockX(currentBox[Box.Right]);
                var blockY1 = bm.GetBlockY(currentBox[Box.Bottom]);
                var blockY2 = bm.GetBlockY(currentBox[Box.Top]);

                for (var bx = blockX1; bx <= blockX2; bx++)
                {
                    for (var by = blockY1; by <= blockY2; by++)
                    {
                        if (!map.BlockMap.IterateLines(bx, by, checkLineFunc, validCount))
                        {
                            return(false);
                        }
                    }
                }
            }

            return(true);
        }
Esempio n. 12
0
        private bool CheckThing(Mobj thing)
        {
            if ((thing.Flags & (MobjFlags.Solid | MobjFlags.Special | MobjFlags.Shootable)) == 0)
            {
                return(true);
            }

            var blockDist = thing.Radius + currentThing.Radius;

            if (Fixed.Abs(thing.X - currentX) >= blockDist || Fixed.Abs(thing.Y - currentY) >= blockDist)
            {
                // Didn't hit it.
                return(true);
            }

            // Don't clip against self.
            if (thing == currentThing)
            {
                return(true);
            }

            // Check for skulls slamming into things.
            if ((currentThing.Flags & MobjFlags.SkullFly) != 0)
            {
                var damage = ((world.Random.Next() % 8) + 1) * currentThing.Info.Damage;

                world.ThingInteraction.DamageMobj(thing, currentThing, currentThing, damage);

                currentThing.Flags &= ~MobjFlags.SkullFly;
                currentThing.MomX   = currentThing.MomY = currentThing.MomZ = Fixed.Zero;

                currentThing.SetState(currentThing.Info.SpawnState);

                // Stop moving.
                return(false);
            }

            // Missiles can hit other things.
            if ((currentThing.Flags & MobjFlags.Missile) != 0)
            {
                // See if it went over / under.
                if (currentThing.Z > thing.Z + thing.Height)
                {
                    // Overhead.
                    return(true);
                }

                if (currentThing.Z + currentThing.Height < thing.Z)
                {
                    // Underneath.
                    return(true);
                }

                if (currentThing.Target != null &&
                    (currentThing.Target.Type == thing.Type ||
                     (currentThing.Target.Type == MobjType.Knight && thing.Type == MobjType.Bruiser) ||
                     (currentThing.Target.Type == MobjType.Bruiser && thing.Type == MobjType.Knight)))
                {
                    // Don't hit same species as originator.
                    if (thing == currentThing.Target)
                    {
                        return(true);
                    }

                    if (thing.Type != MobjType.Player)
                    {
                        // Explode, but do no damage.
                        // Let players missile other players.
                        return(false);
                    }
                }

                if ((thing.Flags & MobjFlags.Shootable) == 0)
                {
                    // Didn't do any damage.
                    return((thing.Flags & MobjFlags.Solid) == 0);
                }

                // Damage / explode.
                var damage = ((world.Random.Next() % 8) + 1) * currentThing.Info.Damage;
                world.ThingInteraction.DamageMobj(thing, currentThing, currentThing.Target, damage);

                // Don't traverse any more.
                return(false);
            }

            // Check for special pickup.
            if ((thing.Flags & MobjFlags.Special) != 0)
            {
                var solid = (thing.Flags & MobjFlags.Solid) != 0;
                if ((currentFlags & MobjFlags.PickUp) != 0)
                {
                    // Can remove thing.
                    world.ItemPickup.TouchSpecialThing(thing, currentThing);
                }
                return(!solid);
            }

            return((thing.Flags & MobjFlags.Solid) == 0);
        }
Esempio n. 13
0
        private bool CheckLine(LineDef line)
        {
            var mc = world.MapCollision;

            if (currentBox.Right() <= line.Box.Left() ||
                currentBox.Left() >= line.Box.Right() ||
                currentBox.Top() <= line.Box.Bottom() ||
                currentBox.Bottom() >= line.Box.Top())
            {
                return(true);
            }

            if (Geometry.BoxOnLineSide(currentBox, line) != -1)
            {
                return(true);
            }

            // A line has been hit.
            //
            // The moving thing's destination position will cross the given line.
            // If this should not be allowed, return false.
            // If the line is special, keep track of it to process later if the move is proven ok.
            //
            // NOTE:
            //     specials are NOT sorted by order, so two special lines that are only 8 pixels
            //     apart could be crossed in either order.

            if (line.BackSector == null)
            {
                // One sided line.
                return(false);
            }

            if ((currentThing.Flags & MobjFlags.Missile) == 0)
            {
                if ((line.Flags & LineFlags.Blocking) != 0)
                {
                    // Explicitly blocking everything.
                    return(false);
                }

                if (currentThing.Player == null && (line.Flags & LineFlags.BlockMonsters) != 0)
                {
                    // Block monsters only.
                    return(false);
                }
            }

            // Set openrange, opentop, openbottom.
            mc.LineOpening(line);

            // Adjust floor / ceiling heights.
            if (mc.OpenTop < currentCeilingZ)
            {
                currentCeilingZ    = mc.OpenTop;
                currentCeilingLine = line;
            }

            if (mc.OpenBottom > currentFloorZ)
            {
                currentFloorZ = mc.OpenBottom;
            }

            if (mc.LowFloor < currentDropoffZ)
            {
                currentDropoffZ = mc.LowFloor;
            }

            // If contacted a special line, add it to the list.
            if (line.Special != 0)
            {
                crossedSpecials[crossedSpecialCount] = line;
                crossedSpecialCount++;
            }

            return(true);
        }
Esempio n. 14
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);
            }
        }
Esempio n. 15
0
        /// <summary>
        /// Traces a line from x1, y1 to x2, y2, calling the traverser function for each.
        /// Returns true if the traverser function returns true for all lines.
        /// </summary>
        public bool PathTraverse(Fixed x1, Fixed y1, Fixed x2, Fixed y2, PathTraverseFlags flags, Func <Intercept, bool> trav)
        {
            earlyOut = (flags & PathTraverseFlags.EarlyOut) != 0;

            var validCount = world.GetNewValidCount();

            var bm = world.Map.BlockMap;

            interceptCount = 0;

            if (((x1 - bm.OriginX).Data & (BlockMap.BlockSize.Data - 1)) == 0)
            {
                // Don't side exactly on a line.
                x1 += Fixed.One;
            }

            if (((y1 - bm.OriginY).Data & (BlockMap.BlockSize.Data - 1)) == 0)
            {
                // Don't side exactly on a line.
                y1 += Fixed.One;
            }

            trace.X  = x1;
            trace.Y  = y1;
            trace.Dx = x2 - x1;
            trace.Dy = y2 - y1;

            x1 -= bm.OriginX;
            y1 -= bm.OriginY;

            var blockX1 = x1.Data >> BlockMap.FracToBlockShift;
            var blockY1 = y1.Data >> BlockMap.FracToBlockShift;

            x2 -= bm.OriginX;
            y2 -= bm.OriginY;

            var blockX2 = x2.Data >> BlockMap.FracToBlockShift;
            var blockY2 = y2.Data >> BlockMap.FracToBlockShift;

            Fixed stepX;
            Fixed stepY;

            Fixed partial;

            int blockStepX;
            int blockStepY;

            if (blockX2 > blockX1)
            {
                blockStepX = 1;
                partial    = new Fixed(Fixed.FracUnit - ((x1.Data >> BlockMap.BlockToFracShift) & (Fixed.FracUnit - 1)));
                stepY      = (y2 - y1) / Fixed.Abs(x2 - x1);
            }
            else if (blockX2 < blockX1)
            {
                blockStepX = -1;
                partial    = new Fixed((x1.Data >> BlockMap.BlockToFracShift) & (Fixed.FracUnit - 1));
                stepY      = (y2 - y1) / Fixed.Abs(x2 - x1);
            }
            else
            {
                blockStepX = 0;
                partial    = Fixed.One;
                stepY      = Fixed.FromInt(256);
            }

            var interceptY = new Fixed(y1.Data >> BlockMap.BlockToFracShift) + (partial * stepY);


            if (blockY2 > blockY1)
            {
                blockStepY = 1;
                partial    = new Fixed(Fixed.FracUnit - ((y1.Data >> BlockMap.BlockToFracShift) & (Fixed.FracUnit - 1)));
                stepX      = (x2 - x1) / Fixed.Abs(y2 - y1);
            }
            else if (blockY2 < blockY1)
            {
                blockStepY = -1;
                partial    = new Fixed((y1.Data >> BlockMap.BlockToFracShift) & (Fixed.FracUnit - 1));
                stepX      = (x2 - x1) / Fixed.Abs(y2 - y1);
            }
            else
            {
                blockStepY = 0;
                partial    = Fixed.One;
                stepX      = Fixed.FromInt(256);
            }

            var interceptX = new Fixed(x1.Data >> BlockMap.BlockToFracShift) + (partial * stepX);

            // Step through map blocks.
            // Count is present to prevent a round off error from skipping the break.
            var bx = blockX1;
            var by = blockY1;

            for (var count = 0; count < 64; count++)
            {
                if ((flags & PathTraverseFlags.AddLines) != 0)
                {
                    if (!bm.IterateLines(bx, by, lineInterceptFunc, validCount))
                    {
                        // Early out.
                        return(false);
                    }
                }

                if ((flags & PathTraverseFlags.AddThings) != 0)
                {
                    if (!bm.IterateThings(bx, by, thingInterceptFunc))
                    {
                        // Early out.
                        return(false);
                    }
                }

                if (bx == blockX2 && by == blockY2)
                {
                    break;
                }

                if ((interceptY.ToIntFloor()) == by)
                {
                    interceptY += stepY;
                    bx         += blockStepX;
                }
                else if ((interceptX.ToIntFloor()) == bx)
                {
                    interceptX += stepX;
                    by         += blockStepY;
                }
            }

            // Go through the sorted list.
            return(TraverseIntercepts(trav, Fixed.One));
        }
Esempio n. 16
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;

                // The null check of the backsector below is necessary to avoid crash
                // in certain PWADs, which contain two-sided lines with no backsector.
                // These are imported from Chocolate Doom.

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

                if (line.BackSector == null ||
                    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);
            }
        }
Esempio n. 17
0
        //
        // P_TouchSpecialThing
        //
        public void TouchSpecialThing(Mobj special, Mobj toucher)
        {
            var delta = special.Z - toucher.Z;

            if (delta > toucher.Height ||
                delta < Fixed.FromInt(-8))
            {
                // out of reach
                return;
            }

            var sound  = Sfx.ITEMUP;
            var player = toucher.Player;

            // Dead thing touching.
            // Can happen with a sliding player corpse.
            if (toucher.Health <= 0)
            {
                return;
            }

            // Identify by sprite.
            switch (special.Sprite)
            {
            // armor
            case Sprite.ARM1:
                if (!GiveArmor(player, 1))
                {
                    return;
                }
                //player.Message = GOTARMOR;
                break;

            case Sprite.ARM2:
                if (!GiveArmor(player, 2))
                {
                    return;
                }
                //player.Message = GOTMEGA;
                break;

            // bonus items
            case Sprite.BON1:
                player.Health++;     // can go over 100%
                if (player.Health > 200)
                {
                    player.Health = 200;
                }
                player.Mobj.Health = player.Health;
                //player.Message = GOTHTHBONUS;
                break;

            case Sprite.BON2:
                player.ArmorPoints++;     // can go over 100%
                if (player.ArmorPoints > 200)
                {
                    player.ArmorPoints = 200;
                }
                if (player.ArmorType == 0)
                {
                    player.ArmorType = 1;
                }
                //player.Message = GOTARMBONUS;
                break;

            case Sprite.SOUL:
                player.Health += 100;
                if (player.Health > 200)
                {
                    player.Health = 200;
                }
                player.Mobj.Health = player.Health;
                //player.Message = GOTSUPER;
                sound = Sfx.GETPOW;
                break;

            case Sprite.MEGA:
                if (world.Options.GameMode != GameMode.Commercial)
                {
                    return;
                }

                player.Health      = 200;
                player.Mobj.Health = player.Health;
                GiveArmor(player, 2);
                //player.Message = GOTMSPHERE;
                sound = Sfx.GETPOW;
                break;

            // cards
            // leave cards for everyone
            case Sprite.BKEY:
                if (!player.Cards[(int)CardType.BlueCard])
                {
                    //player.Message = GOTBLUECARD;
                }
                GiveCard(player, CardType.BlueCard);
                if (!world.Options.NetGame)
                {
                    break;
                }
                return;

            case Sprite.YKEY:
                if (!player.Cards[(int)CardType.YellowCard])
                {
                    //player.Message = GOTYELWCARD;
                }
                GiveCard(player, CardType.YellowCard);
                if (!world.Options.NetGame)
                {
                    break;
                }
                return;

            case Sprite.RKEY:
                if (!player.Cards[(int)CardType.RedCard])
                {
                    //player.Message = GOTREDCARD;
                }
                GiveCard(player, CardType.RedCard);
                if (!world.Options.NetGame)
                {
                    break;
                }
                return;

            case Sprite.BSKU:
                if (!player.Cards[(int)CardType.BlueSkull])
                {
                    //player.Message = GOTBLUESKUL;
                }
                GiveCard(player, CardType.BlueSkull);
                if (!world.Options.NetGame)
                {
                    break;
                }
                return;

            case Sprite.YSKU:
                if (!player.Cards[(int)CardType.YellowSkull])
                {
                    //player.Message = GOTYELWSKUL;
                }
                GiveCard(player, CardType.YellowSkull);
                if (!world.Options.NetGame)
                {
                    break;
                }
                return;

            case Sprite.RSKU:
                if (!player.Cards[(int)CardType.RedSkull])
                {
                    //player.Message = GOTREDSKULL;
                }
                GiveCard(player, CardType.RedSkull);
                if (!world.Options.NetGame)
                {
                    break;
                }
                return;

            // medikits, heals
            case Sprite.STIM:
                if (!GiveBody(player, 10))
                {
                    return;
                }
                //player.Message = GOTSTIM;
                break;

            case Sprite.MEDI:
                if (!GiveBody(player, 25))
                {
                    return;
                }
                if (player.Health < 25)
                {
                    //player.Message = GOTMEDINEED;
                }
                else
                {
                    //player.Message = GOTMEDIKIT;
                }
                break;


            // power ups
            case Sprite.PINV:
                if (!GivePower(player, PowerType.Invulnerability))
                {
                    return;
                }
                //player.Message = GOTINVUL;
                sound = Sfx.GETPOW;
                break;

            case Sprite.PSTR:
                if (!GivePower(player, PowerType.Strength))
                {
                    return;
                }
                //player.Message = GOTBERSERK;
                if (player.ReadyWeapon != WeaponType.Fist)
                {
                    player.PendingWeapon = WeaponType.Fist;
                }
                sound = Sfx.GETPOW;
                break;

            case Sprite.PINS:
                if (!GivePower(player, PowerType.Invisibility))
                {
                    return;
                }
                //player.Message = GOTINVIS;
                sound = Sfx.GETPOW;
                break;

            case Sprite.SUIT:
                if (!GivePower(player, PowerType.IronFeet))
                {
                    return;
                }
                //player.Message = GOTSUIT;
                sound = Sfx.GETPOW;
                break;

            case Sprite.PMAP:
                if (!GivePower(player, PowerType.AllMap))
                {
                    return;
                }
                //player.Message = GOTMAP;
                sound = Sfx.GETPOW;
                break;

            case Sprite.PVIS:
                if (!GivePower(player, PowerType.Infrared))
                {
                    return;
                }
                //player.Message = GOTVISOR;
                sound = Sfx.GETPOW;
                break;

            // ammo
            case Sprite.CLIP:
                if ((special.Flags & MobjFlags.Dropped) != 0)
                {
                    if (!GiveAmmo(player, AmmoType.Clip, 0))
                    {
                        return;
                    }
                }
                else
                {
                    if (!GiveAmmo(player, AmmoType.Clip, 1))
                    {
                        return;
                    }
                }
                //player.Message = GOTCLIP;
                break;

            case Sprite.AMMO:
                if (!GiveAmmo(player, AmmoType.Clip, 5))
                {
                    return;
                }
                //player.Message = GOTCLIPBOX;
                break;

            case Sprite.ROCK:
                if (!GiveAmmo(player, AmmoType.Missile, 1))
                {
                    return;
                }
                //player.Message = GOTROCKET;
                break;

            case Sprite.BROK:
                if (!GiveAmmo(player, AmmoType.Missile, 5))
                {
                    return;
                }
                //player.Message = GOTROCKBOX;
                break;

            case Sprite.CELL:
                if (!GiveAmmo(player, AmmoType.Cell, 1))
                {
                    return;
                }
                //player.Message = GOTCELL;
                break;

            case Sprite.CELP:
                if (!GiveAmmo(player, AmmoType.Cell, 5))
                {
                    return;
                }
                //player.Message = GOTCELLBOX;
                break;

            case Sprite.SHEL:
                if (!GiveAmmo(player, AmmoType.Shell, 1))
                {
                    return;
                }
                //player.Message = GOTSHELLS;
                break;

            case Sprite.SBOX:
                if (!GiveAmmo(player, AmmoType.Shell, 5))
                {
                    return;
                }
                //player.Message = GOTSHELLBOX;
                break;

            case Sprite.BPAK:
                if (!player.Backpack)
                {
                    for (var i = 0; i < (int)AmmoType.Count; i++)
                    {
                        player.MaxAmmo[i] *= 2;
                    }
                    player.Backpack = true;
                }
                for (var i = 0; i < (int)AmmoType.Count; i++)
                {
                    GiveAmmo(player, (AmmoType)i, 1);
                }
                //player.Message = GOTBACKPACK;
                break;

            // weapons
            case Sprite.BFUG:
                if (!GiveWeapon(player, WeaponType.Bfg, false))
                {
                    return;
                }
                //player.Message = GOTBFG9000;
                sound = Sfx.WPNUP;
                break;

            case Sprite.MGUN:
                if (!GiveWeapon(player, WeaponType.Chaingun, (special.Flags & MobjFlags.Dropped) != 0))
                {
                    return;
                }
                //player.Message = GOTCHAINGUN;
                sound = Sfx.WPNUP;
                break;

            case Sprite.CSAW:
                if (!GiveWeapon(player, WeaponType.Chainsaw, false))
                {
                    return;
                }
                //player.Message = GOTCHAINSAW;
                sound = Sfx.WPNUP;
                break;

            case Sprite.LAUN:
                if (!GiveWeapon(player, WeaponType.Missile, false))
                {
                    return;
                }
                //player.Message = GOTLAUNCHER;
                sound = Sfx.WPNUP;
                break;

            case Sprite.PLAS:
                if (!GiveWeapon(player, WeaponType.Plasma, false))
                {
                    return;
                }
                //player.Message = GOTPLASMA;
                sound = Sfx.WPNUP;
                break;

            case Sprite.SHOT:
                if (!GiveWeapon(player, WeaponType.Shotgun, (special.Flags & MobjFlags.Dropped) != 0))
                {
                    return;
                }
                //player.Message = GOTSHOTGUN;
                sound = Sfx.WPNUP;
                break;

            case Sprite.SGN2:
                if (!GiveWeapon(player, WeaponType.SuperShotgun, (special.Flags & MobjFlags.Dropped) != 0))
                {
                    return;
                }
                //player.Message = GOTSHOTGUN2;
                sound = Sfx.WPNUP;
                break;

            default:
                throw new Exception("P_SpecialThing: Unknown gettable thing");
            }

            if ((special.Flags & MobjFlags.CountItem) != 0)
            {
                player.ItemCount++;
            }

            world.ThingAllocation.RemoveMobj(special);

            player.BonusCount += BONUSADD;

            if (player == world.Players[world.consoleplayer])
            {
                world.StartSound(null, sound);
            }
        }
Esempio n. 18
0
        public static void BuildTicCmd(TicCmd cmd)
        {
            var keyLeft   = Keyboard.IsKeyPressed(Keyboard.Key.Left);
            var keyRight  = Keyboard.IsKeyPressed(Keyboard.Key.Right);
            var keyUp     = Keyboard.IsKeyPressed(Keyboard.Key.Up);
            var keyDown   = Keyboard.IsKeyPressed(Keyboard.Key.Down);
            var keySpeed  = Keyboard.IsKeyPressed(Keyboard.Key.LShift);
            var keyStrafe = Keyboard.IsKeyPressed(Keyboard.Key.LAlt);
            var keyFire   = Keyboard.IsKeyPressed(Keyboard.Key.LControl);
            var keyUse    = Keyboard.IsKeyPressed(Keyboard.Key.Space);

            weaponKeys[0] = Keyboard.IsKeyPressed(Keyboard.Key.Num1);
            weaponKeys[1] = Keyboard.IsKeyPressed(Keyboard.Key.Num2);
            weaponKeys[2] = Keyboard.IsKeyPressed(Keyboard.Key.Num3);
            weaponKeys[3] = Keyboard.IsKeyPressed(Keyboard.Key.Num4);
            weaponKeys[4] = Keyboard.IsKeyPressed(Keyboard.Key.Num5);
            weaponKeys[5] = Keyboard.IsKeyPressed(Keyboard.Key.Num6);
            weaponKeys[6] = Keyboard.IsKeyPressed(Keyboard.Key.Num7);

            cmd.Clear();

            var strafe = keyStrafe;

            var speed = keySpeed ? 1 : 0;

            Fixed forward = Fixed.Zero;
            Fixed side    = Fixed.Zero;

            if (keyLeft || keyRight)
            {
                turnheld++;
            }
            else
            {
                turnheld = 0;
            }

            int tspeed;

            if (turnheld < slowTurnTics)
            {
                tspeed = 2;
            }
            else
            {
                tspeed = speed;
            }

            if (strafe)
            {
                if (keyRight)
                {
                    side += sidemove[speed];
                }
                if (keyLeft)
                {
                    side -= sidemove[speed];
                }
            }
            else
            {
                if (keyRight)
                {
                    cmd.AngleTurn -= (short)angleturn[tspeed].Data;
                }
                if (keyLeft)
                {
                    cmd.AngleTurn += (short)angleturn[tspeed].Data;
                }
            }

            if (keyUp)
            {
                forward += forwardmove[speed];
            }
            if (keyDown)
            {
                forward -= forwardmove[speed];
            }

            if (keyFire)
            {
                cmd.Buttons |= TicCmdButtons.Attack;
            }

            if (keyUse)
            {
                cmd.Buttons |= TicCmdButtons.Use;
            }

            // If the previous or next weapon button is pressed, the
            // next_weapon variable is set to change weapons when
            // we generate a ticcmd.  Choose a new weapon.

            /*
             * if (gamestate == GS_LEVEL && next_weapon != 0)
             * {
             *  i = G_NextWeapon(next_weapon);
             *  cmd->buttons |= BT_CHANGE;
             *  cmd->buttons |= i << BT_WEAPONSHIFT;
             * }
             * else
             */
            {
                // Check weapon keys.
                for (var i = 0; i < weaponKeys.Length; i++)
                {
                    if (weaponKeys[i])
                    {
                        cmd.Buttons |= TicCmdButtons.Change;
                        cmd.Buttons |= (byte)(i << TicCmdButtons.WeaponShift);
                        break;
                    }
                }
            }

            next_weapon = 0;

            if (forward > maxplmove)
            {
                forward = maxplmove;
            }
            else if (forward < -maxplmove)
            {
                forward = -maxplmove;
            }
            if (side > maxplmove)
            {
                side = maxplmove;
            }
            else if (side < -maxplmove)
            {
                side = -maxplmove;
            }

            cmd.ForwardMove += (sbyte)forward.Data;
            cmd.SideMove    += (sbyte)side.Data;
        }
Esempio n. 19
0
 public static Fixed operator /(int a, Fixed b)
 {
     return(Fixed.FromInt(a) / b);
 }
Esempio n. 20
0
        public void Update()
        {
            if (zoomIn)
            {
                zoom += zoom / 16;
            }

            if (zoomOut)
            {
                zoom -= zoom / 16;
            }

            if (zoom < Fixed.One / 2)
            {
                zoom = Fixed.One / 2;
            }
            else if (zoom > Fixed.One * 32)
            {
                zoom = Fixed.One * 32;
            }

            if (left)
            {
                viewX -= 64 / zoom;
            }

            if (right)
            {
                viewX += 64 / zoom;
            }

            if (up)
            {
                viewY += 64 / zoom;
            }

            if (down)
            {
                viewY -= 64 / zoom;
            }

            if (viewX < minX)
            {
                viewX = minX;
            }
            else if (viewX > maxX)
            {
                viewX = maxX;
            }

            if (viewY < minY)
            {
                viewY = minY;
            }
            else if (viewY > maxY)
            {
                viewY = maxY;
            }

            if (follow)
            {
                var player = world.ConsolePlayer.Mobj;
                viewX = player.X;
                viewY = player.Y;
            }
        }
Esempio n. 21
0
 public void Thrust(Player player, Angle angle, Fixed move)
 {
     player.Mobj.MomX += move * Trig.Cos(angle);
     player.Mobj.MomY += move * Trig.Sin(angle);
 }
Esempio n. 22
0
        public void DamageMobj(Mobj target, Mobj inflictor, Mobj source, int damage)
        {
            if ((target.Flags & MobjFlags.Shootable) == 0)
            {
                // Shouldn't happen...
                return;
            }

            if (target.Health <= 0)
            {
                return;
            }

            if ((target.Flags & MobjFlags.SkullFly) != 0)
            {
                target.MomX = target.MomY = target.MomZ = Fixed.Zero;
            }

            var player = target.Player;

            if (player != null && world.Options.Skill == GameSkill.Baby)
            {
                // Take half damage in trainer mode.
                damage >>= 1;
            }

            // Some close combat weapons should not inflict thrust and
            // push the victim out of reach, thus kick away unless using the chainsaw.
            var notChainsawAttack =
                source == null ||
                source.Player == null ||
                source.Player.ReadyWeapon != WeaponType.Chainsaw;

            if (inflictor != null && (target.Flags & MobjFlags.NoClip) == 0 && notChainsawAttack)
            {
                var ang = Geometry.PointToAngle(
                    inflictor.X,
                    inflictor.Y,
                    target.X,
                    target.Y);

                var thrust = new Fixed(damage * (Fixed.FracUnit >> 3) * 100 / target.Info.Mass);

                // Make fall forwards sometimes.
                if (damage < 40 &&
                    damage > target.Health &&
                    target.Z - inflictor.Z > Fixed.FromInt(64) &&
                    (world.Random.Next() & 1) != 0)
                {
                    ang    += Angle.Ang180;
                    thrust *= 4;
                }

                target.MomX += thrust * Trig.Cos(ang);
                target.MomY += thrust * Trig.Sin(ang);
            }

            // Player specific.
            if (player != null)
            {
                // End of game hell hack.
                if (target.Subsector.Sector.Special == (SectorSpecial)11 && damage >= target.Health)
                {
                    damage = target.Health - 1;
                }

                // Below certain threshold, ignore damage in GOD mode, or with INVUL power.
                if (damage < 1000 && ((player.Cheats & CheatFlags.GodMode) != 0 ||
                                      player.Powers[(int)PowerType.Invulnerability] > 0))
                {
                    return;
                }

                int saved;

                if (player.ArmorType != 0)
                {
                    if (player.ArmorType == 1)
                    {
                        saved = damage / 3;
                    }
                    else
                    {
                        saved = damage / 2;
                    }

                    if (player.ArmorPoints <= saved)
                    {
                        // Armor is used up.
                        saved            = player.ArmorPoints;
                        player.ArmorType = 0;
                    }

                    player.ArmorPoints -= saved;
                    damage             -= saved;
                }

                // Mirror mobj health here for Dave.
                player.Health -= damage;
                if (player.Health < 0)
                {
                    player.Health = 0;
                }

                player.Attacker = source;

                // Add damage after armor / invuln.
                player.DamageCount += damage;

                if (player.DamageCount > 100)
                {
                    // Teleport stomp does 10k points...
                    player.DamageCount = 100;
                }
            }

            // Do the damage.
            target.Health -= damage;
            if (target.Health <= 0)
            {
                KillMobj(source, target);
                return;
            }

            if ((world.Random.Next() < target.Info.PainChance) &&
                (target.Flags & MobjFlags.SkullFly) == 0)
            {
                // Fight back!
                target.Flags |= MobjFlags.JustHit;

                target.SetState(target.Info.PainState);
            }

            // We're awake now...
            target.ReactionTime = 0;

            if ((target.Threshold == 0 || target.Type == MobjType.Vile) &&
                source != null &&
                source != target &&
                source.Type != MobjType.Vile)
            {
                // If not intent on another player, chase after this one.
                target.Target    = source;
                target.Threshold = baseThreshold;
                if (target.State == DoomInfo.States[(int)target.Info.SpawnState] &&
                    target.Info.SeeState != MobjState.Null)
                {
                    target.SetState(target.Info.SeeState);
                }
            }
        }
Esempio n. 23
0
        public override void Run()
        {
            SectorActionResult result;

            var sa = world.SectorAction;

            switch (direction)
            {
            case 0:
                // In statis.
                break;

            case 1:
                // Up.
                result = sa.MovePlane(
                    sector,
                    speed,
                    topHeight,
                    false,
                    1,
                    direction);

                if ((world.LevelTime & 7) == 0)
                {
                    switch (type)
                    {
                    case CeilingMoveType.SilentCrushAndRaise:
                        break;

                    default:
                        world.StartSound(sector.SoundOrigin, Sfx.STNMOV, SfxType.Misc);
                        break;
                    }
                }

                if (result == SectorActionResult.PastDestination)
                {
                    switch (type)
                    {
                    case CeilingMoveType.RaiseToHighest:
                        sa.RemoveActiveCeiling(this);
                        break;

                    case CeilingMoveType.SilentCrushAndRaise:
                    case CeilingMoveType.FastCrushAndRaise:
                    case CeilingMoveType.CrushAndRaise:
                        if (type == CeilingMoveType.SilentCrushAndRaise)
                        {
                            world.StartSound(sector.SoundOrigin, Sfx.PSTOP, SfxType.Misc);
                        }
                        direction = -1;
                        break;

                    default:
                        break;
                    }
                }
                break;

            case -1:
                // Down.
                result = sa.MovePlane(
                    sector,
                    speed,
                    bottomHeight,
                    crush,
                    1,
                    direction);

                if ((world.LevelTime & 7) == 0)
                {
                    switch (type)
                    {
                    case CeilingMoveType.SilentCrushAndRaise:
                        break;

                    default:
                        world.StartSound(sector.SoundOrigin, Sfx.STNMOV, SfxType.Misc);
                        break;
                    }
                }

                if (result == SectorActionResult.PastDestination)
                {
                    switch (type)
                    {
                    case CeilingMoveType.SilentCrushAndRaise:
                    case CeilingMoveType.CrushAndRaise:
                    case CeilingMoveType.FastCrushAndRaise:
                        if (type == CeilingMoveType.SilentCrushAndRaise)
                        {
                            world.StartSound(sector.SoundOrigin, Sfx.PSTOP, SfxType.Misc);
                            speed = SectorAction.CeilingSpeed;
                        }
                        if (type == CeilingMoveType.CrushAndRaise)
                        {
                            speed = SectorAction.CeilingSpeed;
                        }
                        direction = 1;
                        break;

                    case CeilingMoveType.LowerAndCrush:
                    case CeilingMoveType.LowerToFloor:
                        sa.RemoveActiveCeiling(this);
                        break;

                    default:
                        break;
                    }
                }
                else
                {
                    if (result == SectorActionResult.Crushed)
                    {
                        switch (type)
                        {
                        case CeilingMoveType.SilentCrushAndRaise:
                        case CeilingMoveType.CrushAndRaise:
                        case CeilingMoveType.LowerAndCrush:
                            speed = SectorAction.CeilingSpeed / 8;
                            break;

                        default:
                            break;
                        }
                    }
                }
                break;
            }
        }