PWADp/* Ceiling Run version 1.0.2 by Lach modified by Kaldrum A modification of Lach's ArcadePhysics ceiling running script from Chrispy's Arcade. Should allow for implementation of loops. Requires landing on a slope to start ceiling running, and depending on player orientation when entering a slope will flip movement when upside down. Wouldn't recommend using flipcam with this active. */ local CEILING_SPEED_THRESHOLD = 16*FRACUNIT local function FixedSquare(n) return FixedMul(n, n) end //Will swap the current gravity state, allowing for ceiling running in existing reverse gravity. local function FlipGravity(mo) mo.flags2 = $ ^^ MF2_OBJECTFLIP mo.eflags = $ ^^ MFE_VERTICALFLIP end //Cool slope math (that I don't understand) local function FV3_Rotate(rotVecX, rotVecY, rotVecZ, axisVecX, axisVecY, axisVecZ, angle) local ux, uy, uz = FixedMul(axisVecX, rotVecX), FixedMul(axisVecX, rotVecY), FixedMul(axisVecX, rotVecZ) local vx, vy, vz = FixedMul(axisVecY, rotVecX), FixedMul(axisVecY, rotVecY), FixedMul(axisVecY, rotVecZ) local wx, wy, wz = FixedMul(axisVecZ, rotVecX), FixedMul(axisVecZ, rotVecY), FixedMul(axisVecZ, rotVecZ) local sa, ca = sin(angle), cos(angle) local ua = ux + vy + wz local ax, ay, az = FixedMul(axisVecX, ua), FixedMul(axisVecY, ua), FixedMul(axisVecZ, ua) local xs, ys, zs = FixedSquare(axisVecX), FixedSquare(axisVecY), FixedSquare(axisVecZ) local bx, by, bz = FixedMul(rotVecX, ys + zs), FixedMul(rotVecY, xs + zs), FixedMul(rotVecZ, xs + ys) local cx, cy, cz = FixedMul(axisVecX, vy + wz), FixedMul(axisVecY, ux + wz), FixedMul(axisVecZ, ux + vy) local dx, dy, dz = FixedMul(bx - cx, ca), FixedMul(by - cy, ca), FixedMul(bz - cz, ca) local ex, ey, ez = FixedMul(vz - wy, sa), FixedMul(wx - uz, sa), FixedMul(uy - vx, sa) return ax + dx + ex, ay + dy + ey, az + dz + ez end local function GetSlopeLandingMomentum(mo, slope) if not slope or slope.flags & SL_NOPHYSICS or slope.zangle == 0 return mo.momx, mo.momy end return FV3_Rotate(mo.momx, mo.momy, 2 * mo.momz, -slope.d.y, slope.d.x, 0, InvAngle(slope.zangle)) end //Gets the slope of the floor above the player. local function GetFloorSlope(mo) if not (mo.eflags & MFE_VERTICALFLIP) == not true local fof = mo.floorrover if fof return fof.t_slope end return mo.subsector.sector.f_slope else local fof = mo.ceilingrover if fof return fof.b_slope end return mo.subsector.sector.c_slope end end //Determines if the object will touch the floor based on their height and momentum local function MobjWillTouchFloor(mo) if not (mo.eflags & MFE_VERTICALFLIP) == not true return mo.z + mo.momz < mo.floorz else return mo.z + mo.height + mo.momz > mo.ceilingz end end addHook("PreThinkFrame", function() for player in players.iterate do local mo = player.mo if not mo continue end if player.inputFlip == true player.cmd.forwardmove = -$ end //Cannot run on the ceiling if clipping through ceilings or floors, or carrying something. if (mo.flags & MF_NOCLIPHEIGHT)or (player.powers[pw_carry] ~= CR_NONE) if player.ceilingRun FlipGravity(mo) player.ceilingRun = false end continue end if P_IsObjectOnGround(mo) if not player.ceilingRun continue end if FixedHypot(mo.momx - player.cmomx , mo.momy - player.cmomy) < FixedMul(CEILING_SPEED_THRESHOLD, mo.scale) FlipGravity(mo) player.ceilingRun = false end continue end //Flips gravity if the player will touch a slope with enough momentum. Reverses forward and backward input if the player is flipped around by the slope. if MobjWillTouchFloor(mo) local speed = FixedHypot(GetSlopeLandingMomentum(mo, GetFloorSlope(mo))) local threshold = FixedMul(CEILING_SPEED_THRESHOLD, mo.scale) local slope = GetFloorSlope(mo) if not ((slope==nil) or (slope.flags & SL_NOPHYSICS) or (slope.zangle == 0)) if (abs(slope.xydirection - mo.player.drawangle) < ANG30) player.inputFlip = true end if speed >= threshold FlipGravity(mo) player.ceilingRun = true end if player.inputFlip and player.ceilingRun player.cmd.forwardmove = -$ end end elseif player.ceilingRun player.falltimer = $+1 if player.pflags & PF_JUMPED player.falltimer = 2 end if player.falltimer == 2 if player.powers[pw_justlaunched] == 2 P_Thrust(mo, player.drawangle, FRACUNIT) end FlipGravity(mo) player.ceilingRun = false end end if not player.ceilingRun player.inputFlip = false player.falltimer = 0 end end end) dLUA_CLRN