예제 #1
0
        /// <summary>
        /// Returns false if the player cannot be respawned at the given
        /// mapthing spot because something is occupying it.
        /// </summary>
        public bool CheckSpot(int playernum, MapThing mthing)
        {
            var players = world.Options.Players;

            if (players[playernum].Mobj == null)
            {
                // First spawn of level, before corpses.
                for (var i = 0; i < playernum; i++)
                {
                    if (players[i].Mobj.X == mthing.X && players[i].Mobj.Y == mthing.Y)
                    {
                        return(false);
                    }
                }
                return(true);
            }

            var x = mthing.X;
            var y = mthing.Y;

            if (!world.ThingMovement.CheckPosition(players[playernum].Mobj, x, y))
            {
                return(false);
            }

            // Flush an old corpse if needed.
            if (bodyQueSlot >= bodyQueSize)
            {
                RemoveMobj(bodyQue[bodyQueSlot % bodyQueSize]);
            }
            bodyQue[bodyQueSlot % bodyQueSize] = players[playernum].Mobj;
            bodyQueSlot++;

            // Spawn a teleport fog.
            var subsector = Geometry.PointInSubsector(x, y, world.Map);

            var angle = (Angle.Ang45.Data >> Trig.AngleToFineShift) *
                        ((int)Math.Round(mthing.Angle.ToDegree()) / 45);

            //
            // The code below to reproduce respawn fog bug in deathmath
            // is based on Chocolate Doom's implementation.
            //

            Fixed xa;
            Fixed ya;

            switch (angle)
            {
            case 4096:               // -4096:
                xa = Trig.Tan(2048); // finecosine[-4096]
                ya = Trig.Tan(0);    // finesine[-4096]
                break;

            case 5120:               // -3072:
                xa = Trig.Tan(3072); // finecosine[-3072]
                ya = Trig.Tan(1024); // finesine[-3072]
                break;

            case 6144:               // -2048:
                xa = Trig.Sin(0);    // finecosine[-2048]
                ya = Trig.Tan(2048); // finesine[-2048]
                break;

            case 7168:               // -1024:
                xa = Trig.Sin(1024); // finecosine[-1024]
                ya = Trig.Tan(3072); // finesine[-1024]
                break;

            case 0:
            case 1024:
            case 2048:
            case 3072:
                xa = Trig.Cos((int)angle);
                ya = Trig.Sin((int)angle);
                break;

            default:
                throw new Exception("Unexpected angle: " + angle);
            }

            var mo = SpawnMobj(
                x + 20 * xa, y + 20 * ya,
                subsector.Sector.FloorHeight,
                MobjType.Tfog);

            if (!world.FirstTicIsNotYetDone)
            {
                // Don't start sound on first frame.
                world.StartSound(mo, Sfx.TELEPT, SfxType.Misc);
            }

            return(true);
        }
예제 #2
0
        //
        // G_CheckSpot
        // Returns false if the player cannot be respawned
        // at the given mapthing_t spot
        // because something is occupying it
        //
        public bool G_CheckSpot(int playernum, MapThing mthing)
        {
            if (Players[playernum].Mobj == null)
            {
                // first spawn of level, before corpses
                for (var i = 0; i < playernum; i++)
                {
                    if (Players[i].Mobj.X == mthing.X && Players[i].Mobj.Y == mthing.Y)
                    {
                        return(false);
                    }
                }
                return(true);
            }

            var x = mthing.X;
            var y = mthing.Y;

            if (!thingMovement.CheckPosition(Players[playernum].Mobj, x, y))
            {
                return(false);
            }

            // flush an old corpse if needed
            if (bodyqueslot >= BODYQUESIZE)
            {
                thingAllocation.RemoveMobj(bodyque[bodyqueslot % BODYQUESIZE]);
            }
            bodyque[bodyqueslot % BODYQUESIZE] = Players[playernum].Mobj;
            bodyqueslot++;

            // spawn a teleport fog
            var ss = Geometry.PointInSubsector(x, y, map);

            var an = (Angle.Ang45.Data >> Trig.AngleToFineShift) * ((int)Math.Round(mthing.Angle.ToDegree()) / 45);

            Fixed xa;
            Fixed ya;

            switch (an)
            {
            case 4096:               // -4096:
                xa = Trig.Tan(2048); // finecosine[-4096]
                ya = Trig.Tan(0);    // finesine[-4096]
                break;

            case 5120:               // -3072:
                xa = Trig.Tan(3072); // finecosine[-3072]
                ya = Trig.Tan(1024); // finesine[-3072]
                break;

            case 6144:               // -2048:
                xa = Trig.Sin(0);    // finecosine[-2048]
                ya = Trig.Tan(2048); // finesine[-2048]
                break;

            case 7168:               // -1024:
                xa = Trig.Sin(1024); // finecosine[-1024]
                ya = Trig.Tan(3072); // finesine[-1024]
                break;

            case 0:
            case 1024:
            case 2048:
            case 3072:
                xa = Trig.Cos((int)an);
                ya = Trig.Sin((int)an);
                break;

            default:
                throw new Exception("G_CheckSpot: unexpected angle " + an);
            }

            var mo = thingAllocation.SpawnMobj(
                x + 20 * xa, y + 20 * ya,
                ss.Sector.FloorHeight,
                MobjType.Tfog);

            if (Players[Options.ConsolePlayer].ViewZ != new Fixed(1))
            {
                // don't start sound on first frame
                StartSound(mo, Sfx.TELEPT);
            }

            return(true);
        }