예제 #1
0
        /*
         * ==================
         * =
         * = P_PointOnLineSide
         * =
         * = Returns 0 or 1
         * ==================
         */

        public static int P_PointOnLineSide(int x, int y, r_local.line_t line)
        {
            int dx, dy;
            int left, right;

            if (line.dx == 0)
            {
                if (x <= line.v1.x)
                {
                    return(line.dy > 0 ? 1 : 0);
                }
                return(line.dy < 0 ? 1 : 0);
            }
            if (line.dy == 0)
            {
                if (y <= line.v1.y)
                {
                    return(line.dx < 0 ? 1 : 0);
                }
                return(line.dx > 0 ? 1 : 0);
            }

            dx = (x - line.v1.x);
            dy = (y - line.v1.y);

            left  = DoomDef.FixedMul(line.dy >> DoomDef.FRACBITS, dx);
            right = DoomDef.FixedMul(dy, line.dx >> DoomDef.FRACBITS);

            if (right < left)
            {
                return(0);                              // front side
            }
            return(1);                                  // back side
        }
예제 #2
0
        /*
         * ===============
         * =
         * = P_InterceptVector
         * =
         * = Returns the fractional intercept point along the first divline
         * =
         * = This is only called by the addthings and addlines traversers
         * ===============
         */

        public static int P_InterceptVector(p_local.divline_t v2, p_local.divline_t v1)
        {
            int frac, num, den;

            den = DoomDef.FixedMul(v1.dy >> 8, v2.dx) - DoomDef.FixedMul(v1.dx >> 8, v2.dy);
            if (den == 0)
            {
                return(0);
            }
            num = DoomDef.FixedMul((v1.x - v2.x) >> 8, v1.dy) +
                  DoomDef.FixedMul((v2.y - v1.y) >> 8, v1.dx);
            frac = d_main.FixedDiv(num, den);

            return(frac);
        }
예제 #3
0
        /*
         * ==================
         * =
         * = P_PointOnDivlineSide
         * =
         * = Returns 0 or 1
         * ==================
         */

        public static int P_PointOnDivlineSide(int x, int y, p_local.divline_t line)
        {
            int dx, dy;
            int left, right;

            if (line.dx == 0)
            {
                if (x <= line.x)
                {
                    return((line.dy > 0) ? 1 : 0);
                }
                return((line.dy < 0) ? 1 : 0);
            }
            if (line.dy == 0)
            {
                if (y <= line.y)
                {
                    return((line.dx < 0) ? 1 : 0);
                }
                return((line.dx > 0) ? 1 : 0);
            }

            dx = (x - line.x);
            dy = (y - line.y);

            // try to quickly decide by looking at sign bits
            if (((line.dy ^ line.dx ^ dx ^ dy) & 0x80000000) != 0)
            {
                if (((line.dy ^ dx) & 0x80000000) != 0)
                {
                    return(1);                          // (left is negative)
                }
                return(0);
            }

            left  = DoomDef.FixedMul(line.dy >> 8, dx >> 8);
            right = DoomDef.FixedMul(dy >> 8, line.dx >> 8);

            if (right < left)
            {
                return(0);                              // front side
            }
            return(1);                                  // back side
        }
예제 #4
0
        /*
         * ==================
         * =
         * = P_Thrust
         * =
         * = moves the given origin along a given angle
         * =
         * ==================
         */

        public static void P_Thrust(DoomDef.player_t player, uint angle, int move)
        {
            angle = (uint)(angle >> (int)DoomDef.ANGLETOFINESHIFT);
            if (player.powers[(int)DoomDef.powertype_t.pw_flight] != 0 && !(player.mo.z <= player.mo.floorz))
            {
                player.mo.momx += DoomDef.FixedMul(move, r_main.finecosine(angle));
                player.mo.momy += DoomDef.FixedMul(move, tables.finesine[angle]);
            }
            else if (player.mo.subsector.sector.special == 15)             // Friction_Low
            {
                player.mo.momx += DoomDef.FixedMul(move >> 2, r_main.finecosine(angle));
                player.mo.momy += DoomDef.FixedMul(move >> 2, tables.finesine[angle]);
            }
            else
            {
                player.mo.momx += DoomDef.FixedMul(move, r_main.finecosine(angle));
                player.mo.momy += DoomDef.FixedMul(move, tables.finesine[angle]);
            }
        }
예제 #5
0
        public static bool P_PathTraverse(int x1, int y1, int x2, int y2,
                                          int flags, P_PathTraverse_delegate trav)
        {
            int xt1, yt1, xt2, yt2;
            int xstep, ystep;
            int partial;
            int xintercept, yintercept;
            int mapx, mapy, mapxstep, mapystep;
            int count;

            earlyout = (flags & p_local.PT_EARLYOUT) != 0;

            r_main.validcount++;
            intercept_p = 0;

            if (((x1 - p_setup.bmaporgx) & (p_local.MAPBLOCKSIZE - 1)) == 0)
            {
                x1 += DoomDef.FRACUNIT;                                         // don't side exactly on a line
            }
            if (((y1 - p_setup.bmaporgy) & (p_local.MAPBLOCKSIZE - 1)) == 0)
            {
                y1 += DoomDef.FRACUNIT;                                         // don't side exactly on a line
            }
            trace.x  = x1;
            trace.y  = y1;
            trace.dx = x2 - x1;
            trace.dy = y2 - y1;

            x1 -= p_setup.bmaporgx;
            y1 -= p_setup.bmaporgy;
            xt1 = x1 >> p_local.MAPBLOCKSHIFT;
            yt1 = y1 >> p_local.MAPBLOCKSHIFT;

            x2 -= p_setup.bmaporgx;
            y2 -= p_setup.bmaporgy;
            xt2 = x2 >> p_local.MAPBLOCKSHIFT;
            yt2 = y2 >> p_local.MAPBLOCKSHIFT;

            if (xt2 > xt1)
            {
                mapxstep = 1;
                partial  = DoomDef.FRACUNIT - ((x1 >> p_local.MAPBTOFRAC) & (DoomDef.FRACUNIT - 1));
                ystep    = d_main.FixedDiv(y2 - y1, Math.Abs(x2 - x1));
            }
            else if (xt2 < xt1)
            {
                mapxstep = -1;
                partial  = (x1 >> p_local.MAPBTOFRAC) & (DoomDef.FRACUNIT - 1);
                ystep    = d_main.FixedDiv(y2 - y1, Math.Abs(x2 - x1));
            }
            else
            {
                mapxstep = 0;
                partial  = DoomDef.FRACUNIT;
                ystep    = 256 * DoomDef.FRACUNIT;
            }
            yintercept = (y1 >> p_local.MAPBTOFRAC) + DoomDef.FixedMul(partial, ystep);


            if (yt2 > yt1)
            {
                mapystep = 1;
                partial  = DoomDef.FRACUNIT - ((y1 >> p_local.MAPBTOFRAC) & (DoomDef.FRACUNIT - 1));
                xstep    = d_main.FixedDiv(x2 - x1, Math.Abs(y2 - y1));
            }
            else if (yt2 < yt1)
            {
                mapystep = -1;
                partial  = (y1 >> p_local.MAPBTOFRAC) & (DoomDef.FRACUNIT - 1);
                xstep    = d_main.FixedDiv(x2 - x1, Math.Abs(y2 - y1));
            }
            else
            {
                mapystep = 0;
                partial  = DoomDef.FRACUNIT;
                xstep    = 256 * DoomDef.FRACUNIT;
            }
            xintercept = (x1 >> p_local.MAPBTOFRAC) + DoomDef.FixedMul(partial, xstep);


            //
            // step through map blocks
            // Count is present to prevent a round off error from skipping the break
            mapx = xt1;
            mapy = yt1;

            for (count = 0; count < 64; count++)
            {
                if ((flags & p_local.PT_ADDLINES) != 0)
                {
                    if (!P_BlockLinesIterator(mapx, mapy, PIT_AddLineIntercepts))
                    {
                        return(false);                          // early out
                    }
                }
                if ((flags & p_local.PT_ADDTHINGS) != 0)
                {
                    if (!P_BlockThingsIterator(mapx, mapy, PIT_AddThingIntercepts))
                    {
                        return(false);                          // early out
                    }
                }

                if (mapx == xt2 && mapy == yt2)
                {
                    break;
                }

                if ((yintercept >> DoomDef.FRACBITS) == mapy)
                {
                    yintercept += ystep;
                    mapx       += mapxstep;
                }
                else if ((xintercept >> DoomDef.FRACBITS) == mapx)
                {
                    xintercept += xstep;
                    mapy       += mapystep;
                }
            }


            //
            // go through the sorted list
            //
            return(p_maputl.P_TraverseIntercepts(trav, DoomDef.FRACUNIT));
        }
예제 #6
0
        //----------------------------------------------------------------------------
        //
        // FUNC P_Teleport
        //
        //----------------------------------------------------------------------------

        public static bool P_Teleport(DoomDef.mobj_t thing, int x, int y, uint angle)
        {
            int oldx;
            int oldy;
            int oldz;
            int aboveFloor;
            int fogDelta;

            DoomDef.player_t player;
            uint             an;

            DoomDef.mobj_t fog;

            oldx       = thing.x;
            oldy       = thing.y;
            oldz       = thing.z;
            aboveFloor = thing.z - thing.floorz;
            if (!p_map.P_TeleportMove(thing, x, y))
            {
                return(false);
            }
            if (thing.player != null)
            {
                player = thing.player;
                if (player.powers[(int)DoomDef.powertype_t.pw_flight] != 0 && aboveFloor != 0)
                {
                    thing.z = thing.floorz + aboveFloor;
                    if (thing.z + thing.height > thing.ceilingz)
                    {
                        thing.z = thing.ceilingz - thing.height;
                    }
                    player.viewz = thing.z + player.viewheight;
                }
                else
                {
                    thing.z        = thing.floorz;
                    player.viewz   = thing.z + player.viewheight;
                    player.lookdir = 0;
                }
            }
            else if ((thing.flags & DoomDef.MF_MISSILE) != 0)
            {
                thing.z = thing.floorz + aboveFloor;
                if (thing.z + thing.height > thing.ceilingz)
                {
                    thing.z = thing.ceilingz - thing.height;
                }
            }
            else
            {
                thing.z = thing.floorz;
            }
            // Spawn teleport fog at source and destination
            fogDelta = (thing.flags & DoomDef.MF_MISSILE) != 0 ? 0 : DoomDef.TELEFOGHEIGHT;
            fog      = p_mobj.P_SpawnMobj(oldx, oldy, oldz + fogDelta, info.mobjtype_t.MT_TFOG);
            i_ibm.S_StartSound(fog, (int)sounds.sfxenum_t.sfx_telept);
            an  = angle >> (int)DoomDef.ANGLETOFINESHIFT;
            fog = p_mobj.P_SpawnMobj(x + 20 * r_main.finecosine(an),
                                     y + 20 * tables.finesine[an], thing.z + fogDelta, info.mobjtype_t.MT_TFOG);
            i_ibm.S_StartSound(fog, (int)sounds.sfxenum_t.sfx_telept);
            if (thing.player != null && thing.player.powers[(int)DoomDef.powertype_t.pw_weaponlevel2] == 0)
            {             // Freeze player for about .5 sec
                thing.reactiontime = 18;
            }
            thing.angle = angle;
            if ((thing.flags2 & DoomDef.MF2_FOOTCLIP) != 0 && p_mobj.P_GetThingFloorType(thing) != p_local.FLOOR_SOLID)
            {
                thing.flags2 |= DoomDef.MF2_FEETARECLIPPED;
            }
            else if ((thing.flags2 & DoomDef.MF2_FEETARECLIPPED) != 0)
            {
                thing.flags2 &= ~DoomDef.MF2_FEETARECLIPPED;
            }
            if ((thing.flags & DoomDef.MF_MISSILE) != 0)
            {
                angle    >>= (int)DoomDef.ANGLETOFINESHIFT;
                thing.momx = DoomDef.FixedMul(thing.infol.speed, r_main.finecosine(angle));
                thing.momy = DoomDef.FixedMul(thing.infol.speed, tables.finesine[angle]);
            }
            else
            {
                thing.momx = thing.momy = thing.momz = 0;
            }
            return(true);
        }
예제 #7
0
        /*
         * ==================
         * =
         * = P_SightPathTraverse
         * =
         * = 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
         * ==================
         */

        public static bool P_SightPathTraverse(int x1, int y1, int x2, int y2)
        {
            int xt1, yt1, xt2, yt2;
            int xstep, ystep;
            int partial;
            int xintercept, yintercept;
            int mapx, mapy, mapxstep, mapystep;
            int count;

            r_main.validcount++;
            p_maputl.intercept_p = 0;

            if (((x1 - p_setup.bmaporgx) & (p_local.MAPBLOCKSIZE - 1)) == 0)
            {
                x1 += DoomDef.FRACUNIT;                                         // don't side exactly on a line
            }
            if (((y1 - p_setup.bmaporgy) & (p_local.MAPBLOCKSIZE - 1)) == 0)
            {
                y1 += DoomDef.FRACUNIT;                                         // don't side exactly on a line
            }
            p_maputl.trace.x  = x1;
            p_maputl.trace.y  = y1;
            p_maputl.trace.dx = x2 - x1;
            p_maputl.trace.dy = y2 - y1;

            x1 -= p_setup.bmaporgx;
            y1 -= p_setup.bmaporgy;
            xt1 = x1 >> p_local.MAPBLOCKSHIFT;
            yt1 = y1 >> p_local.MAPBLOCKSHIFT;

            x2 -= p_setup.bmaporgx;
            y2 -= p_setup.bmaporgy;
            xt2 = x2 >> p_local.MAPBLOCKSHIFT;
            yt2 = y2 >> p_local.MAPBLOCKSHIFT;

            // points should never be out of bounds, but check once instead of
            // each block
            if (xt1 < 0 || yt1 < 0 || xt1 >= p_setup.bmapwidth || yt1 >= p_setup.bmapheight ||
                xt2 < 0 || yt2 < 0 || xt2 >= p_setup.bmapwidth || yt2 >= p_setup.bmapheight)
            {
                return(false);
            }

            if (xt2 > xt1)
            {
                mapxstep = 1;
                partial  = DoomDef.FRACUNIT - ((x1 >> p_local.MAPBTOFRAC) & (DoomDef.FRACUNIT - 1));
                ystep    = d_main.FixedDiv(y2 - y1, Math.Abs(x2 - x1));
            }
            else if (xt2 < xt1)
            {
                mapxstep = -1;
                partial  = (x1 >> p_local.MAPBTOFRAC) & (DoomDef.FRACUNIT - 1);
                ystep    = d_main.FixedDiv(y2 - y1, Math.Abs(x2 - x1));
            }
            else
            {
                mapxstep = 0;
                partial  = DoomDef.FRACUNIT;
                ystep    = 256 * DoomDef.FRACUNIT;
            }
            yintercept = (y1 >> p_local.MAPBTOFRAC) + DoomDef.FixedMul(partial, ystep);


            if (yt2 > yt1)
            {
                mapystep = 1;
                partial  = DoomDef.FRACUNIT - ((y1 >> p_local.MAPBTOFRAC) & (DoomDef.FRACUNIT - 1));
                xstep    = d_main.FixedDiv(x2 - x1, Math.Abs(y2 - y1));
            }
            else if (yt2 < yt1)
            {
                mapystep = -1;
                partial  = (y1 >> p_local.MAPBTOFRAC) & (DoomDef.FRACUNIT - 1);
                xstep    = d_main.FixedDiv(x2 - x1, Math.Abs(y2 - y1));
            }
            else
            {
                mapystep = 0;
                partial  = DoomDef.FRACUNIT;
                xstep    = 256 * DoomDef.FRACUNIT;
            }
            xintercept = (x1 >> p_local.MAPBTOFRAC) + DoomDef.FixedMul(partial, xstep);


            //
            // step through map blocks
            // Count is present to prevent a round off error from skipping the break
            mapx = xt1;
            mapy = yt1;


            for (count = 0; count < 64; count++)
            {
                if (!P_SightBlockLinesIterator(mapx, mapy))
                {
                    sightcounts[1]++;
                    return(false);                      // early out
                }

                if (mapx == xt2 && mapy == yt2)
                {
                    break;
                }

                if ((yintercept >> DoomDef.FRACBITS) == mapy)
                {
                    yintercept += ystep;
                    mapx       += mapxstep;
                }
                else if ((xintercept >> DoomDef.FRACBITS) == mapx)
                {
                    xintercept += xstep;
                    mapy       += mapystep;
                }
            }


            //
            // couldn't early out, so go through the sorted list
            //
            sightcounts[2]++;

            return(P_SightTraverseIntercepts());
        }
예제 #8
0
        /*
         * ==================
         * =
         * = P_CalcHeight
         * =
         * =Calculate the walking / running height adjustment
         * =
         * ==================
         */

        public static void P_CalcHeight(DoomDef.player_t player)
        {
            int angle;
            int bob;

            //
            // regular movement bobbing (needs to be calculated for gun swing even
            // if not on ground)
            // OPTIMIZE: tablify angle

            player.bob =
                DoomDef.FixedMul(player.mo.momx, player.mo.momx) +
                DoomDef.FixedMul(player.mo.momy, player.mo.momy);
            player.bob >>= 2;
            if (player.bob > MAXBOB)
            {
                player.bob = MAXBOB;
            }
            if ((player.mo.flags2 & DoomDef.MF2_FLY) != 0 && !onground)
            {
                player.bob = DoomDef.FRACUNIT / 2;
            }

            if ((player.cheats & DoomDef.CF_NOMOMENTUM) != 0)
            {
                player.viewz = player.mo.z + p_local.VIEWHEIGHT;
                if (player.viewz > player.mo.ceilingz - 4 * DoomDef.FRACUNIT)
                {
                    player.viewz = player.mo.ceilingz - 4 * DoomDef.FRACUNIT;
                }
                player.viewz = player.mo.z + player.viewheight;
                return;
            }

            angle = (int)((DoomDef.FINEANGLES / 20 * p_tick.leveltime) & DoomDef.FINEMASK);
            bob   = DoomDef.FixedMul(player.bob / 2, tables.finesine[angle]);

            //
            // move viewheight
            //
            if (player.playerstate == DoomDef.playerstate_t.PST_LIVE)
            {
                player.viewheight += player.deltaviewheight;
                if (player.viewheight > p_local.VIEWHEIGHT)
                {
                    player.viewheight      = p_local.VIEWHEIGHT;
                    player.deltaviewheight = 0;
                }
                if (player.viewheight < p_local.VIEWHEIGHT / 2)
                {
                    player.viewheight = p_local.VIEWHEIGHT / 2;
                    if (player.deltaviewheight <= 0)
                    {
                        player.deltaviewheight = 1;
                    }
                }

                if (player.deltaviewheight != 0)
                {
                    player.deltaviewheight += DoomDef.FRACUNIT / 4;
                    if (player.deltaviewheight == 0)
                    {
                        player.deltaviewheight = 1;
                    }
                }
            }

            if (player.chickenTics != 0)
            {
                player.viewz = player.mo.z + player.viewheight - (20 * DoomDef.FRACUNIT);
            }
            else
            {
                player.viewz = player.mo.z + player.viewheight + bob;
            }
            if ((player.mo.flags2 & DoomDef.MF2_FEETARECLIPPED) != 0 &&
                player.playerstate != DoomDef.playerstate_t.PST_DEAD &&
                player.mo.z <= player.mo.floorz)
            {
                player.viewz -= p_local.FOOTCLIPSIZE;
            }
            if (player.viewz > player.mo.ceilingz - 4 * DoomDef.FRACUNIT)
            {
                player.viewz = player.mo.ceilingz - 4 * DoomDef.FRACUNIT;
            }
            if (player.viewz < player.mo.floorz + 4 * DoomDef.FRACUNIT)
            {
                player.viewz = player.mo.floorz + 4 * DoomDef.FRACUNIT;
            }
        }