/* * ================== * = * = 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 }
/* * =============== * = * = 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); }
/* * ================== * = * = 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 }
/* * ================== * = * = 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]); } }
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)); }
//---------------------------------------------------------------------------- // // 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); }
/* * ================== * = * = 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()); }
/* * ================== * = * = 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; } }