/// <summary> /// Returns true if a straight line between the looker and target is unobstructed. /// </summary> public bool CheckSight(Mobj looker, Mobj target) { var map = this.world.Map; // First check for trivial rejection. // Check in REJECT table. if (map.Reject.Check(looker.Subsector.Sector, target.Subsector.Sector)) { // Can't possibly be connected. return(false); } // An unobstructed LOS is possible. // Now look from eyes of t1 to any part of t2. this.sightZStart = looker.Z + looker.Height - (looker.Height >> 2); this.topSlope = (target.Z + target.Height) - this.sightZStart; this.bottomSlope = (target.Z) - this.sightZStart; this.trace.X = looker.X; this.trace.Y = looker.Y; this.trace.Dx = target.X - looker.X; this.trace.Dy = target.Y - looker.Y; this.targetX = target.X; this.targetY = target.Y; // The head node is the last node output. return(this.CrossBspNode(map.Nodes.Length - 1, this.world.GetNewValidCount())); }
private bool StompThing(Mobj thing) { if ((thing.Flags & MobjFlags.Shootable) == 0) { return(true); } var blockDist = thing.Radius + this.currentThing.Radius; var dx = Fixed.Abs(thing.X - this.currentX); var dy = Fixed.Abs(thing.Y - this.currentY); if (dx >= blockDist || dy >= blockDist) { // Didn't hit it. return(true); } // Don't clip against self. if (thing == this.currentThing) { return(true); } // Monsters don't stomp things except on boss level. if (this.currentThing.Player == null && this.world.Options.Map != 30) { return(false); } this.world.ThingInteraction.DamageMobj(thing, this.currentThing, this.currentThing, 10000); return(true); }
public void BFGSpray(Mobj bfgBall) { var hs = this.world.Hitscan; var random = this.world.Random; // Offset angles from its attack angle. for (var i = 0; i < 40; i++) { var an = bfgBall.Angle - Angle.Ang90 / 2 + Angle.Ang90 / 40 * (uint)i; // bfgBall.Target is the originator (player) of the missile. hs.AimLineAttack(bfgBall.Target, an, Fixed.FromInt(16 * 64)); if (hs.LineTarget == null) { continue; } this.world.ThingAllocation.SpawnMobj(hs.LineTarget.X, hs.LineTarget.Y, hs.LineTarget.Z + (hs.LineTarget.Height >> 2), MobjType.Extrabfg); var damage = 0; for (var j = 0; j < 15; j++) { damage += (random.Next() & 7) + 1; } this.world.ThingInteraction.DamageMobj(hs.LineTarget, bfgBall.Target, bfgBall.Target, damage); } }
private void StairStep(Mobj thing) { if (!this.TryMove(thing, thing.X, thing.Y + thing.MomY)) { this.TryMove(thing, thing.X + thing.MomX, thing.Y); } }
/// <summary> /// Find a target on the aiming line. /// Sets LineTaget when a target is aimed at. /// </summary> public Fixed AimLineAttack(Mobj shooter, Angle angle, Fixed range) { this.currentShooter = shooter; this.currentShooterZ = shooter.Z + (shooter.Height >> 1) + Fixed.FromInt(8); this.currentRange = range; var targetX = shooter.X + range.ToIntFloor() * Trig.Cos(angle); var targetY = shooter.Y + range.ToIntFloor() * Trig.Sin(angle); // Can't shoot outside view angles. this.topSlope = Fixed.FromInt(100) / 160; this.bottomSlope = Fixed.FromInt(-100) / 160; this.lineTarget = null; this.world.PathTraversal.PathTraverse( shooter.X, shooter.Y, targetX, targetY, PathTraverseFlags.AddLines | PathTraverseFlags.AddThings, this.aimTraverseFunc ); if (this.lineTarget != null) { return(this.currentAimSlope); } return(Fixed.Zero); }
/// <summary> /// Remove the mobj from the level. /// </summary> public void RemoveMobj(Mobj mobj) { var tm = this.world.ThingMovement; if ((mobj.Flags & MobjFlags.Special) != 0 && (mobj.Flags & MobjFlags.Dropped) == 0 && (mobj.Type != MobjType.Inv) && (mobj.Type != MobjType.Ins)) { this.itemRespawnQue[this.itemQueHead] = mobj.SpawnPoint; this.itemRespawnTime[this.itemQueHead] = this.world.LevelTime; this.itemQueHead = (this.itemQueHead + 1) & (ThingAllocation.itemQueSize - 1); // Lose one off the end? if (this.itemQueHead == this.itemQueTail) { this.itemQueTail = (this.itemQueTail + 1) & (ThingAllocation.itemQueSize - 1); } } // Unlink from sector and block lists. tm.UnsetThingPosition(mobj); // Stop any playing sound. this.world.StopSound(mobj); // Free block. this.world.Thinkers.Remove(mobj); }
public void Clear() { this.line = null; this.position = 0; this.texture = 0; this.timer = 0; this.soundOrigin = null; }
public bool TeleportMove(Mobj thing, Fixed x, Fixed y) { // Kill anything occupying the position. this.currentThing = thing; this.currentFlags = thing.Flags; this.currentX = x; this.currentY = y; this.currentBox[Box.Top] = y + this.currentThing.Radius; this.currentBox[Box.Bottom] = y - this.currentThing.Radius; this.currentBox[Box.Right] = x + this.currentThing.Radius; this.currentBox[Box.Left] = x - this.currentThing.Radius; var ss = Geometry.PointInSubsector(x, y, this.world.Map); this.currentCeilingLine = null; // The base floor / ceiling is from the subsector that contains the point. // Any contacted lines the step closer together will adjust them. this.currentFloorZ = this.currentDropoffZ = ss.Sector.FloorHeight; this.currentCeilingZ = ss.Sector.CeilingHeight; var validcount = this.world.GetNewValidCount(); this.crossedSpecialCount = 0; // Stomp on any things contacted. var bm = this.world.Map.BlockMap; var blockX1 = bm.GetBlockX(this.currentBox[Box.Left] - GameConst.MaxThingRadius); var blockX2 = bm.GetBlockX(this.currentBox[Box.Right] + GameConst.MaxThingRadius); var blockY1 = bm.GetBlockY(this.currentBox[Box.Bottom] - GameConst.MaxThingRadius); var blockY2 = bm.GetBlockY(this.currentBox[Box.Top] + GameConst.MaxThingRadius); for (var bx = blockX1; bx <= blockX2; bx++) { for (var by = blockY1; by <= blockY2; by++) { if (!bm.IterateThings(bx, by, this.stompThingFunc)) { return(false); } } } // the move is ok, so link the thing into its new position this.UnsetThingPosition(thing); thing.FloorZ = this.currentFloorZ; thing.CeilingZ = this.currentCeilingZ; thing.X = x; thing.Y = y; this.SetThingPosition(thing); return(true); }
private void RecursiveSound(Sector sec, int soundblocks, Mobj soundtarget, int validCount) { // Wake up all monsters in this sector. if (sec.ValidCount == validCount && sec.SoundTraversed <= soundblocks + 1) { // Already flooded. return; } sec.ValidCount = validCount; sec.SoundTraversed = soundblocks + 1; sec.SoundTarget = soundtarget; var mc = this.world.MapCollision; for (var i = 0; i < sec.Lines.Length; i++) { var check = sec.Lines[i]; if ((check.Flags & LineFlags.TwoSided) == 0) { continue; } mc.LineOpening(check); if (mc.OpenRange <= Fixed.Zero) { // Closed door. continue; } Sector other; if (check.FrontSide.Sector == sec) { other = check.BackSide.Sector; } else { other = check.FrontSide.Sector; } if ((check.Flags & LineFlags.SoundBlock) != 0) { if (soundblocks == 0) { this.RecursiveSound(other, 1, soundtarget, validCount); } } else { this.RecursiveSound(other, soundblocks, soundtarget, validCount); } } }
/// <summary> /// Looks for things that intercept the given trace. /// </summary> private bool AddThingIntercepts(Mobj thing) { var tracePositive = (this.trace.Dx.Data ^ this.trace.Dy.Data) > 0; Fixed x1; Fixed y1; Fixed x2; Fixed y2; // Check a corner to corner crossection for hit. if (tracePositive) { x1 = thing.X - thing.Radius; y1 = thing.Y + thing.Radius; x2 = thing.X + thing.Radius; y2 = thing.Y - thing.Radius; } else { x1 = thing.X - thing.Radius; y1 = thing.Y - thing.Radius; x2 = thing.X + thing.Radius; y2 = thing.Y + thing.Radius; } var s1 = Geometry.PointOnDivLineSide(x1, y1, this.trace); var s2 = Geometry.PointOnDivLineSide(x2, y2, this.trace); if (s1 == s2) { // Line isn't crossed. return(true); } this.target.X = x1; this.target.Y = y1; this.target.Dx = x2 - x1; this.target.Dy = y2 - y1; var frac = this.InterceptVector(this.trace, this.target); if (frac < Fixed.Zero) { // Behind source. return(true); } this.intercepts[this.interceptCount].Make(frac, thing); this.interceptCount++; // Keep going. return(true); }
//////////////////////////////////////////////////////////// // Thing spawn functions for the middle of a game //////////////////////////////////////////////////////////// /// <summary> /// Spawn a mobj at the given position as the given type. /// </summary> public Mobj SpawnMobj(Fixed x, Fixed y, Fixed z, MobjType type) { var mobj = new Mobj(this.world); var info = DoomInfo.MobjInfos[(int)type]; mobj.Type = type; mobj.Info = info; mobj.X = x; mobj.Y = y; mobj.Radius = info.Radius; mobj.Height = info.Height; mobj.Flags = info.Flags; mobj.Health = info.SpawnHealth; if (this.world.Options.Skill != GameSkill.Nightmare) { mobj.ReactionTime = info.ReactionTime; } mobj.LastLook = this.world.Random.Next() % Player.MaxPlayerCount; // Do not set the state with P_SetMobjState, // because action routines can not be called yet. var st = DoomInfo.States[(int)info.SpawnState]; mobj.State = st; mobj.Tics = st.Tics; mobj.Sprite = st.Sprite; mobj.Frame = st.Frame; // Set subsector and/or block links. this.world.ThingMovement.SetThingPosition(mobj); mobj.FloorZ = mobj.Subsector.Sector.FloorHeight; mobj.CeilingZ = mobj.Subsector.Sector.CeilingHeight; if (z == Mobj.OnFloorZ) { mobj.Z = mobj.FloorZ; } else if (z == Mobj.OnCeilingZ) { mobj.Z = mobj.CeilingZ - mobj.Info.Height; } else { mobj.Z = z; } this.world.Thinkers.Add(mobj); return(mobj); }
//////////////////////////////////////////////////////////// // Line shoot //////////////////////////////////////////////////////////// /// <summary> /// Called when a thing shoots a special line. /// </summary> public void ShootSpecialLine(Mobj thing, LineDef line) { bool ok; // Impacts that other things can activate. if (thing.Player == null) { ok = false; switch ((int)line.Special) { case 46: // Open door impact. ok = true; break; } if (!ok) { return; } } var sa = this.world.SectorAction; var specials = this.world.Specials; switch ((int)line.Special) { case 24: // Raise floor. sa.DoFloor(line, FloorMoveType.RaiseFloor); specials.ChangeSwitchTexture(line, false); break; case 46: // Open door. sa.DoDoor(line, VerticalDoorType.Open); specials.ChangeSwitchTexture(line, true); break; case 47: // Raise floor near and change. sa.DoPlatform(line, PlatformType.RaiseToNearestAndChange, 0); specials.ChangeSwitchTexture(line, false); break; } }
/// <summary> /// Links a thing into both a block and a subsector based on /// its x and y. Sets thing.Subsector properly. /// </summary> public void SetThingPosition(Mobj thing) { var map = this.world.Map; var subsector = Geometry.PointInSubsector(thing.X, thing.Y, map); thing.Subsector = subsector; // Invisible things don't go into the sector links. if ((thing.Flags & MobjFlags.NoSector) == 0) { var sector = subsector.Sector; thing.SectorPrev = null; thing.SectorNext = sector.ThingList; if (sector.ThingList != null) { sector.ThingList.SectorPrev = thing; } sector.ThingList = thing; } // Inert things don't need to be in blockmap. if ((thing.Flags & MobjFlags.NoBlockMap) == 0) { var index = map.BlockMap.GetIndex(thing.X, thing.Y); if (index != -1) { var link = map.BlockMap.ThingLists[index]; thing.BlockPrev = null; thing.BlockNext = link; if (link != null) { link.BlockPrev = thing; } map.BlockMap.ThingLists[index] = thing; } else { // Thing is off the map. thing.BlockNext = null; thing.BlockPrev = null; } } }
/// <summary> /// Looks for special lines in front of the player to activate. /// </summary> public void UseLines(Player player) { var pt = this.world.PathTraversal; this.useThing = player.Mobj; var angle = player.Mobj.Angle; var x1 = player.Mobj.X; var y1 = player.Mobj.Y; var x2 = x1 + MapInteraction.useRange.ToIntFloor() * Trig.Cos(angle); var y2 = y1 + MapInteraction.useRange.ToIntFloor() * Trig.Sin(angle); pt.PathTraverse(x1, y1, x2, y2, PathTraverseFlags.AddLines, this.useTraverseFunc); }
/// <summary> /// Unlinks a thing from block map and sectors. /// On each position change, BLOCKMAP and other lookups /// maintaining lists ot things inside these structures /// need to be updated. /// </summary> public void UnsetThingPosition(Mobj thing) { var map = this.world.Map; // Invisible things don't go into the sector links. if ((thing.Flags & MobjFlags.NoSector) == 0) { // Unlink from subsector. if (thing.SectorNext != null) { thing.SectorNext.SectorPrev = thing.SectorPrev; } if (thing.SectorPrev != null) { thing.SectorPrev.SectorNext = thing.SectorNext; } else { thing.Subsector.Sector.ThingList = thing.SectorNext; } } // Inert things don't need to be in blockmap. if ((thing.Flags & MobjFlags.NoBlockMap) == 0) { // Unlink from block map. if (thing.BlockNext != null) { thing.BlockNext.BlockPrev = thing.BlockPrev; } if (thing.BlockPrev != null) { thing.BlockPrev.BlockNext = thing.BlockNext; } else { var index = map.BlockMap.GetIndex(thing.X, thing.Y); if (index != -1) { map.BlockMap.ThingLists[index] = thing.BlockNext; } } } }
//////////////////////////////////////////////////////////// // Miscellaneous //////////////////////////////////////////////////////////// /// <summary> /// Play the player's death sound. /// </summary> public void PlayerScream(Mobj player) { // Default death sound. var sound = Sfx.PLDETH; if ((DoomApplication.Instance.IWad == "doom2" || DoomApplication.Instance.IWad == "freedoom2" || DoomApplication.Instance.IWad == "plutonia" || DoomApplication.Instance.IWad == "tnt") && (player.Health < -50)) { // If the player dies less than -50% without gibbing. sound = Sfx.PDIEHI; } this.world.StartSound(player, sound, SfxType.Voice); }
/// <summary> /// Shoot a missile from the source. /// For players. /// </summary> public void SpawnPlayerMissile(Mobj source, MobjType type) { var hs = this.world.Hitscan; // See which target is to be aimed at. var angle = source.Angle; var slope = hs.AimLineAttack(source, angle, Fixed.FromInt(16 * 64)); if (hs.LineTarget == null) { angle += new Angle(1 << 26); slope = hs.AimLineAttack(source, angle, Fixed.FromInt(16 * 64)); if (hs.LineTarget == null) { angle -= new Angle(2 << 26); slope = hs.AimLineAttack(source, angle, Fixed.FromInt(16 * 64)); } if (hs.LineTarget == null) { angle = source.Angle; slope = Fixed.Zero; } } var x = source.X; var y = source.Y; var z = source.Z + Fixed.FromInt(32); var missile = this.SpawnMobj(x, y, z, type); if (missile.Info.SeeSound != 0) { this.world.StartSound(missile, missile.Info.SeeSound, SfxType.Misc); } missile.Target = source; missile.Angle = angle; missile.MomX = new Fixed(missile.Info.Speed) * Trig.Cos(angle); missile.MomY = new Fixed(missile.Info.Speed) * Trig.Sin(angle); missile.MomZ = new Fixed(missile.Info.Speed) * slope; this.CheckMissileSpawn(missile); }
/// <summary> /// Shoot a missile from the source to the destination. /// For monsters. /// </summary> public Mobj SpawnMissile(Mobj source, Mobj dest, MobjType type) { var missile = this.SpawnMobj(source.X, source.Y, source.Z + Fixed.FromInt(32), type); if (missile.Info.SeeSound != 0) { this.world.StartSound(missile, missile.Info.SeeSound, SfxType.Misc); } // Where it came from? missile.Target = source; var angle = Geometry.PointToAngle(source.X, source.Y, dest.X, dest.Y); // Fuzzy player. if ((dest.Flags & MobjFlags.Shadow) != 0) { var random = this.world.Random; angle += new Angle((random.Next() - random.Next()) << 20); } var speed = this.GetMissileSpeed(missile.Type); missile.Angle = angle; missile.MomX = new Fixed(speed) * Trig.Cos(angle); missile.MomY = new Fixed(speed) * Trig.Sin(angle); var dist = Geometry.AproxDistance(dest.X - source.X, dest.Y - source.Y); var num = (dest.Z - source.Z).Data; var den = (dist / speed).Data; if (den < 1) { den = 1; } missile.MomZ = new Fixed(num / den); this.CheckMissileSpawn(missile); return(missile); }
/// <summary> /// Moves the missile forward a bit and possibly explodes it right there. /// </summary> private void CheckMissileSpawn(Mobj missile) { missile.Tics -= this.world.Random.Next() & 3; if (missile.Tics < 1) { missile.Tics = 1; } // Move a little forward so an angle can be computed if it immediately explodes. missile.X += (missile.MomX >> 1); missile.Y += (missile.MomY >> 1); missile.Z += (missile.MomZ >> 1); if (!this.world.ThingMovement.TryMove(missile, missile.X, missile.Y)) { this.world.ThingInteraction.ExplodeMissile(missile); } }
/// <summary> /// Called when the missile hits something (wall or thing). /// </summary> public void ExplodeMissile(Mobj thing) { thing.MomX = thing.MomY = thing.MomZ = Fixed.Zero; thing.SetState(DoomInfo.MobjInfos[(int)thing.Type].DeathState); thing.Tics -= this.world.Random.Next() & 3; if (thing.Tics < 1) { thing.Tics = 1; } thing.Flags &= ~MobjFlags.Missile; if (thing.Info.DeathSound != 0) { this.world.StartSound(thing, thing.Info.DeathSound, SfxType.Misc); } }
/// <summary> /// Fire a hitscan bullet. /// If damage == 0, it is just a test trace that will leave linetarget set. /// </summary> public void LineAttack(Mobj shooter, Angle angle, Fixed range, Fixed slope, int damage) { this.currentShooter = shooter; this.currentShooterZ = shooter.Z + (shooter.Height >> 1) + Fixed.FromInt(8); this.currentRange = range; this.currentAimSlope = slope; this.currentDamage = damage; var targetX = shooter.X + range.ToIntFloor() * Trig.Cos(angle); var targetY = shooter.Y + range.ToIntFloor() * Trig.Sin(angle); this.world.PathTraversal.PathTraverse( shooter.X, shooter.Y, targetX, targetY, PathTraverseFlags.AddLines | PathTraverseFlags.AddThings, this.shootTraverseFunc ); }
/// <summary> /// "bombSource" is the creature that caused the explosion at "bombSpot". /// </summary> private bool DoRadiusAttack(Mobj thing) { if ((thing.Flags & MobjFlags.Shootable) == 0) { return(true); } // Boss spider and cyborg take no damage from concussion. if (thing.Type == MobjType.Cyborg || thing.Type == MobjType.Spider) { return(true); } var dx = Fixed.Abs(thing.X - this.bombSpot.X); var dy = Fixed.Abs(thing.Y - this.bombSpot.Y); var dist = dx > dy ? dx : dy; dist = new Fixed((dist - thing.Radius).Data >> Fixed.FracBits); if (dist < Fixed.Zero) { dist = Fixed.Zero; } if (dist.Data >= this.bombDamage) { // Out of range. return(true); } if (this.world.VisibilityCheck.CheckSight(thing, this.bombSpot)) { // Must be in direct path. this.DamageMobj(thing, this.bombSpot, this.bombSource, this.bombDamage - dist.Data); } return(true); }
/// <summary> /// Source is the creature that caused the explosion at spot. /// </summary> public void RadiusAttack(Mobj spot, Mobj source, int damage) { var bm = this.world.Map.BlockMap; var dist = Fixed.FromInt(damage + GameConst.MaxThingRadius.Data); var blockY1 = bm.GetBlockY(spot.Y - dist); var blockY2 = bm.GetBlockY(spot.Y + dist); var blockX1 = bm.GetBlockX(spot.X - dist); var blockX2 = bm.GetBlockX(spot.X + dist); this.bombSpot = spot; this.bombSource = source; this.bombDamage = damage; for (var by = blockY1; by <= blockY2; by++) { for (var bx = blockX1; bx <= blockX2; bx++) { bm.IterateThings(bx, by, this.radiusAttackFunc); } } }
/// <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 = this.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 = this.currentRange * intercept.Frac; if (line.FrontSector.FloorHeight != line.BackSector.FloorHeight) { var slope = (mc.OpenBottom - this.currentShooterZ) / dist; if (slope > this.bottomSlope) { this.bottomSlope = slope; } } if (line.FrontSector.CeilingHeight != line.BackSector.CeilingHeight) { var slope = (mc.OpenTop - this.currentShooterZ) / dist; if (slope < this.topSlope) { this.topSlope = slope; } } if (this.topSlope <= this.bottomSlope) { // Stop. return(false); } // Shot continues. return(true); } // Shoot a thing. var thing = intercept.Thing; if (thing == this.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 = this.currentRange * intercept.Frac; var thingTopSlope = (thing.Z + thing.Height - this.currentShooterZ) / dist; if (thingTopSlope < this.bottomSlope) { // Shot over the thing. return(true); } var thingBottomSlope = (thing.Z - this.currentShooterZ) / dist; if (thingBottomSlope > this.topSlope) { // Shot under the thing. return(true); } // This thing can be hit! if (thingTopSlope > this.topSlope) { thingTopSlope = this.topSlope; } if (thingBottomSlope < this.bottomSlope) { thingBottomSlope = this.bottomSlope; } this.currentAimSlope = (thingTopSlope + thingBottomSlope) / 2; this.lineTarget = thing; // Don't go any farther. return(false); } }
public void StopSound(Mobj mobj) { this.options.Sound.StopSound(mobj); }
private void NoiseAlert(Mobj target, Mobj emmiter) { this.RecursiveSound(emmiter.Subsector.Sector, 0, target, this.world.GetNewValidCount()); }
/// <summary> /// Called when a thing uses a special line. /// Only the front sides of lines are usable. /// </summary> public bool UseSpecialLine(Mobj thing, LineDef line, int side) { var specials = this.world.Specials; var sa = this.world.SectorAction; // Err... // Use the back sides of VERY SPECIAL lines... if (side != 0) { switch ((int)line.Special) { case 124: // Sliding door open and close (unused). break; default: return(false); } } // Switches that other things can activate. if (thing.Player == null) { // Never open secret doors. if ((line.Flags & LineFlags.Secret) != 0) { return(false); } switch ((int)line.Special) { case 1: // Manual door raise. case 32: // Manual blue. case 33: // Manual red. case 34: // Manual yellow. break; default: return(false); } } // Do something. switch ((int)line.Special) { // MANUALS case 1: // Vertical door. case 26: // Blue door (locked). case 27: // Yellow door (locked). case 28: // Red door (locked). case 31: // Manual door open. case 32: // Blue locked door open. case 33: // Red locked door open. case 34: // Yellow locked door open. case 117: // Blazing door raise. case 118: // Blazing door open. sa.DoLocalDoor(line, thing); break; // SWITCHES case 7: // Build stairs. if (sa.BuildStairs(line, StairType.Build8)) { specials.ChangeSwitchTexture(line, false); } break; case 9: // Change donut. if (sa.DoDonut(line)) { specials.ChangeSwitchTexture(line, false); } break; case 11: // Exit level. specials.ChangeSwitchTexture(line, false); this.world.ExitLevel(); break; case 14: // Raise floor 32 and change texture. if (sa.DoPlatform(line, PlatformType.RaiseAndChange, 32)) { specials.ChangeSwitchTexture(line, false); } break; case 15: // Raise floor 24 and change texture. if (sa.DoPlatform(line, PlatformType.RaiseAndChange, 24)) { specials.ChangeSwitchTexture(line, false); } break; case 18: // Raise floor to next highest floor. if (sa.DoFloor(line, FloorMoveType.RaiseFloorToNearest)) { specials.ChangeSwitchTexture(line, false); } break; case 20: // Raise platform next highest floor and change texture. if (sa.DoPlatform(line, PlatformType.RaiseToNearestAndChange, 0)) { specials.ChangeSwitchTexture(line, false); } break; case 21: // Platform down, wait, up and stay. if (sa.DoPlatform(line, PlatformType.DownWaitUpStay, 0)) { specials.ChangeSwitchTexture(line, false); } break; case 23: // Lower floor to Lowest. if (sa.DoFloor(line, FloorMoveType.LowerFloorToLowest)) { specials.ChangeSwitchTexture(line, false); } break; case 29: // Raise door. if (sa.DoDoor(line, VerticalDoorType.Normal)) { specials.ChangeSwitchTexture(line, false); } break; case 41: // Lower ceiling to floor. if (sa.DoCeiling(line, CeilingMoveType.LowerToFloor)) { specials.ChangeSwitchTexture(line, false); } break; case 71: // Turbo lower floor. if (sa.DoFloor(line, FloorMoveType.TurboLower)) { specials.ChangeSwitchTexture(line, false); } break; case 49: // Ceiling crush and raise. if (sa.DoCeiling(line, CeilingMoveType.CrushAndRaise)) { specials.ChangeSwitchTexture(line, false); } break; case 50: // Close door. if (sa.DoDoor(line, VerticalDoorType.Close)) { specials.ChangeSwitchTexture(line, false); } break; case 51: // Secret exit. specials.ChangeSwitchTexture(line, false); this.world.SecretExitLevel(); break; case 55: // Raise floor crush. if (sa.DoFloor(line, FloorMoveType.RaiseFloorCrush)) { specials.ChangeSwitchTexture(line, false); } break; case 101: // Raise floor. if (sa.DoFloor(line, FloorMoveType.RaiseFloor)) { specials.ChangeSwitchTexture(line, false); } break; case 102: // Lower floor to surrounding floor height. if (sa.DoFloor(line, FloorMoveType.LowerFloor)) { specials.ChangeSwitchTexture(line, false); } break; case 103: // Open door. if (sa.DoDoor(line, VerticalDoorType.Open)) { specials.ChangeSwitchTexture(line, false); } break; case 111: // Blazing door raise (faster than turbo). if (sa.DoDoor(line, VerticalDoorType.BlazeRaise)) { specials.ChangeSwitchTexture(line, false); } break; case 112: // Blazing door open (faster than turbo). if (sa.DoDoor(line, VerticalDoorType.BlazeOpen)) { specials.ChangeSwitchTexture(line, false); } break; case 113: // Blazing door close (faster than turbo). if (sa.DoDoor(line, VerticalDoorType.BlazeClose)) { specials.ChangeSwitchTexture(line, false); } break; case 122: // Blazing platform down, wait, up and stay. if (sa.DoPlatform(line, PlatformType.BlazeDwus, 0)) { specials.ChangeSwitchTexture(line, false); } break; case 127: // Build stairs turbo 16. if (sa.BuildStairs(line, StairType.Turbo16)) { specials.ChangeSwitchTexture(line, false); } break; case 131: // Raise floor turbo. if (sa.DoFloor(line, FloorMoveType.RaiseFloorTurbo)) { specials.ChangeSwitchTexture(line, false); } break; case 133: // Blazing open door (blue). case 135: // Blazing open door (red). case 137: // Blazing open door (yellow). if (sa.DoLockedDoor(line, VerticalDoorType.BlazeOpen, thing)) { specials.ChangeSwitchTexture(line, false); } break; case 140: // Raise floor 512. if (sa.DoFloor(line, FloorMoveType.RaiseFloor512)) { specials.ChangeSwitchTexture(line, false); } break; // BUTTONS case 42: // Close door. if (sa.DoDoor(line, VerticalDoorType.Close)) { specials.ChangeSwitchTexture(line, true); } break; case 43: // Lower ceiling to floor. if (sa.DoCeiling(line, CeilingMoveType.LowerToFloor)) { specials.ChangeSwitchTexture(line, true); } break; case 45: // lower floor to surrounding floor height. if (sa.DoFloor(line, FloorMoveType.LowerFloor)) { specials.ChangeSwitchTexture(line, true); } break; case 60: // Lower floor to Lowest. if (sa.DoFloor(line, FloorMoveType.LowerFloorToLowest)) { specials.ChangeSwitchTexture(line, true); } break; case 61: // Open door. if (sa.DoDoor(line, VerticalDoorType.Open)) { specials.ChangeSwitchTexture(line, true); } break; case 62: // Platform down, wait, up and stay. if (sa.DoPlatform(line, PlatformType.DownWaitUpStay, 1)) { specials.ChangeSwitchTexture(line, true); } break; case 63: // Raise door. if (sa.DoDoor(line, VerticalDoorType.Normal)) { specials.ChangeSwitchTexture(line, true); } break; case 64: // Raise floor to ceiling. if (sa.DoFloor(line, FloorMoveType.RaiseFloor)) { specials.ChangeSwitchTexture(line, true); } break; case 66: // Raise floor 24 and change texture. if (sa.DoPlatform(line, PlatformType.RaiseAndChange, 24)) { specials.ChangeSwitchTexture(line, true); } break; case 67: // Raise floor 32 and change texture. if (sa.DoPlatform(line, PlatformType.RaiseAndChange, 32)) { specials.ChangeSwitchTexture(line, true); } break; case 65: // Raise floor crush. if (sa.DoFloor(line, FloorMoveType.RaiseFloorCrush)) { specials.ChangeSwitchTexture(line, true); } break; case 68: // Raise platform to next highest floor and change texture. if (sa.DoPlatform(line, PlatformType.RaiseToNearestAndChange, 0)) { specials.ChangeSwitchTexture(line, true); } break; case 69: // Raise floor to next highest floor. if (sa.DoFloor(line, FloorMoveType.RaiseFloorToNearest)) { specials.ChangeSwitchTexture(line, true); } break; case 70: // Turbo lower floor. if (sa.DoFloor(line, FloorMoveType.TurboLower)) { specials.ChangeSwitchTexture(line, true); } break; case 114: // Blazing door raise (faster than turbo). if (sa.DoDoor(line, VerticalDoorType.BlazeRaise)) { specials.ChangeSwitchTexture(line, true); } break; case 115: // Blazing door open (faster than turbo). if (sa.DoDoor(line, VerticalDoorType.BlazeOpen)) { specials.ChangeSwitchTexture(line, true); } break; case 116: // Blazing door close (faster than turbo). if (sa.DoDoor(line, VerticalDoorType.BlazeClose)) { specials.ChangeSwitchTexture(line, true); } break; case 123: // Blazing platform down, wait, up and stay. if (sa.DoPlatform(line, PlatformType.BlazeDwus, 0)) { specials.ChangeSwitchTexture(line, true); } break; case 132: // Raise floor turbo. if (sa.DoFloor(line, FloorMoveType.RaiseFloorTurbo)) { specials.ChangeSwitchTexture(line, true); } break; case 99: // Blazing open door (blue). case 134: // Blazing open door (red). case 136: // Blazing open door (yellow). if (sa.DoLockedDoor(line, VerticalDoorType.BlazeOpen, thing)) { specials.ChangeSwitchTexture(line, true); } break; case 138: // Light turn on. sa.LightTurnOn(line, 255); specials.ChangeSwitchTexture(line, true); break; case 139: // Light turn Off. sa.LightTurnOn(line, 35); specials.ChangeSwitchTexture(line, true); break; } return(true); }
//////////////////////////////////////////////////////////// // Line crossing //////////////////////////////////////////////////////////// /// <summary> /// Called every time a thing origin is about to cross a line /// with a non zero special. /// </summary> public void CrossSpecialLine(LineDef line, int side, Mobj thing) { // Triggers that other things can activate. if (thing.Player == null) { // Things that should NOT trigger specials... switch (thing.Type) { case MobjType.Rocket: case MobjType.Plasma: case MobjType.Bfg: case MobjType.Troopshot: case MobjType.Headshot: case MobjType.Bruisershot: return; default: break; } var ok = false; switch ((int)line.Special) { case 39: // TELEPORT TRIGGER case 97: // TELEPORT RETRIGGER case 125: // TELEPORT MONSTERONLY TRIGGER case 126: // TELEPORT MONSTERONLY RETRIGGER case 4: // RAISE DOOR case 10: // PLAT DOWN-WAIT-UP-STAY TRIGGER case 88: // PLAT DOWN-WAIT-UP-STAY RETRIGGER ok = true; break; } if (!ok) { return; } } var sa = this.world.SectorAction; // Note: could use some const's here. switch ((int)line.Special) { // TRIGGERS. // All from here to RETRIGGERS. case 2: // Open door. sa.DoDoor(line, VerticalDoorType.Open); line.Special = 0; break; case 3: // Close door. sa.DoDoor(line, VerticalDoorType.Close); line.Special = 0; break; case 4: // Raise door. sa.DoDoor(line, VerticalDoorType.Normal); line.Special = 0; break; case 5: // Raise floor. sa.DoFloor(line, FloorMoveType.RaiseFloor); line.Special = 0; break; case 6: // Fast ceiling crush and raise. sa.DoCeiling(line, CeilingMoveType.FastCrushAndRaise); line.Special = 0; break; case 8: // Build stairs. sa.BuildStairs(line, StairType.Build8); line.Special = 0; break; case 10: // Platform down, wait, up and stay. sa.DoPlatform(line, PlatformType.DownWaitUpStay, 0); line.Special = 0; break; case 12: // Light turn on - brightest near. sa.LightTurnOn(line, 0); line.Special = 0; break; case 13: // Light turn on 255. sa.LightTurnOn(line, 255); line.Special = 0; break; case 16: // Close door 30. sa.DoDoor(line, VerticalDoorType.Close30ThenOpen); line.Special = 0; break; case 17: // Start light strobing. sa.StartLightStrobing(line); line.Special = 0; break; case 19: // Lower floor. sa.DoFloor(line, FloorMoveType.LowerFloor); line.Special = 0; break; case 22: // Raise floor to nearest height and change texture. sa.DoPlatform(line, PlatformType.RaiseToNearestAndChange, 0); line.Special = 0; break; case 25: // Ceiling crush and raise. sa.DoCeiling(line, CeilingMoveType.CrushAndRaise); line.Special = 0; break; case 30: // Raise floor to shortest texture height on either side of lines. sa.DoFloor(line, FloorMoveType.RaiseToTexture); line.Special = 0; break; case 35: // Lights very dark. sa.LightTurnOn(line, 35); line.Special = 0; break; case 36: // Lower floor (turbo). sa.DoFloor(line, FloorMoveType.TurboLower); line.Special = 0; break; case 37: // Lower and change. sa.DoFloor(line, FloorMoveType.LowerAndChange); line.Special = 0; break; case 38: // Lower floor to lowest. sa.DoFloor(line, FloorMoveType.LowerFloorToLowest); line.Special = 0; break; case 39: // Do teleport. sa.Teleport(line, side, thing); line.Special = 0; break; case 40: // Raise ceiling and lower floor. sa.DoCeiling(line, CeilingMoveType.RaiseToHighest); sa.DoFloor(line, FloorMoveType.LowerFloorToLowest); line.Special = 0; break; case 44: // Ceiling crush. sa.DoCeiling(line, CeilingMoveType.LowerAndCrush); line.Special = 0; break; case 52: // Do exit. this.world.ExitLevel(); break; case 53: // Perpetual platform raise. sa.DoPlatform(line, PlatformType.PerpetualRaise, 0); line.Special = 0; break; case 54: // Platform stop. sa.StopPlatform(line); line.Special = 0; break; case 56: // Raise floor crush. sa.DoFloor(line, FloorMoveType.RaiseFloorCrush); line.Special = 0; break; case 57: // Ceiling crush stop. sa.CeilingCrushStop(line); line.Special = 0; break; case 58: // Raise floor 24. sa.DoFloor(line, FloorMoveType.RaiseFloor24); line.Special = 0; break; case 59: // Raise floor 24 and change. sa.DoFloor(line, FloorMoveType.RaiseFloor24AndChange); line.Special = 0; break; case 104: // Turn lights off in sector (tag). sa.TurnTagLightsOff(line); line.Special = 0; break; case 108: // Blazing door raise (faster than turbo). sa.DoDoor(line, VerticalDoorType.BlazeRaise); line.Special = 0; break; case 109: // Blazing door open (faster than turbo). sa.DoDoor(line, VerticalDoorType.BlazeOpen); line.Special = 0; break; case 100: // Build stairs turbo 16. sa.BuildStairs(line, StairType.Turbo16); line.Special = 0; break; case 110: // Blazing door close (faster than turbo). sa.DoDoor(line, VerticalDoorType.BlazeClose); line.Special = 0; break; case 119: // Raise floor to nearest surrounding floor. sa.DoFloor(line, FloorMoveType.RaiseFloorToNearest); line.Special = 0; break; case 121: // Blazing platform down, wait, up and stay. sa.DoPlatform(line, PlatformType.BlazeDwus, 0); line.Special = 0; break; case 124: // Secret exit. this.world.SecretExitLevel(); break; case 125: // Teleport monster only. if (thing.Player == null) { sa.Teleport(line, side, thing); line.Special = 0; } break; case 130: // Raise floor turbo. sa.DoFloor(line, FloorMoveType.RaiseFloorTurbo); line.Special = 0; break; case 141: // Silent ceiling crush and raise. sa.DoCeiling(line, CeilingMoveType.SilentCrushAndRaise); line.Special = 0; break; // RETRIGGERS. All from here till end. case 72: // Ceiling crush. sa.DoCeiling(line, CeilingMoveType.LowerAndCrush); break; case 73: // Ceiling crush and raise. sa.DoCeiling(line, CeilingMoveType.CrushAndRaise); break; case 74: // Ceiling crush stop. sa.CeilingCrushStop(line); break; case 75: // Close door. sa.DoDoor(line, VerticalDoorType.Close); break; case 76: // Close door 30. sa.DoDoor(line, VerticalDoorType.Close30ThenOpen); break; case 77: // Fast ceiling crush and raise. sa.DoCeiling(line, CeilingMoveType.FastCrushAndRaise); break; case 79: // Lights very dark. sa.LightTurnOn(line, 35); break; case 80: // Light turn on - brightest near. sa.LightTurnOn(line, 0); break; case 81: // Light turn on 255. sa.LightTurnOn(line, 255); break; case 82: // Lower floor to lowest. sa.DoFloor(line, FloorMoveType.LowerFloorToLowest); break; case 83: // Lower floor. sa.DoFloor(line, FloorMoveType.LowerFloor); break; case 84: // Lower and change. sa.DoFloor(line, FloorMoveType.LowerAndChange); break; case 86: // Open door. sa.DoDoor(line, VerticalDoorType.Open); break; case 87: // Perpetual platform raise. sa.DoPlatform(line, PlatformType.PerpetualRaise, 0); break; case 88: // Platform down, wait, up and stay. sa.DoPlatform(line, PlatformType.DownWaitUpStay, 0); break; case 89: // Platform stop. sa.StopPlatform(line); break; case 90: // Raise door. sa.DoDoor(line, VerticalDoorType.Normal); break; case 91: // Raise floor. sa.DoFloor(line, FloorMoveType.RaiseFloor); break; case 92: // Raise floor 24. sa.DoFloor(line, FloorMoveType.RaiseFloor24); break; case 93: // Raise floor 24 and change. sa.DoFloor(line, FloorMoveType.RaiseFloor24AndChange); break; case 94: // Raise Floor Crush sa.DoFloor(line, FloorMoveType.RaiseFloorCrush); break; case 95: // Raise floor to nearest height and change texture. sa.DoPlatform(line, PlatformType.RaiseToNearestAndChange, 0); break; case 96: // Raise floor to shortest texture height on either side of lines. sa.DoFloor(line, FloorMoveType.RaiseToTexture); break; case 97: // Do Teleport. sa.Teleport(line, side, thing); break; case 98: // Lower floor (turbo). sa.DoFloor(line, FloorMoveType.TurboLower); break; case 105: // Blazing door raise (faster than turbo). sa.DoDoor(line, VerticalDoorType.BlazeRaise); break; case 106: // Blazing door open (faster than turbo). sa.DoDoor(line, VerticalDoorType.BlazeOpen); break; case 107: // Blazing door close (faster than turbo). sa.DoDoor(line, VerticalDoorType.BlazeClose); break; case 120: // Blazing platform down, wait, up and stay. sa.DoPlatform(line, PlatformType.BlazeDwus, 0); break; case 126: // Teleport monster only. if (thing.Player == null) { sa.Teleport(line, side, thing); } break; case 128: // Raise to nearest floor. sa.DoFloor(line, FloorMoveType.RaiseFloorToNearest); break; case 129: // Raise floor turbo. sa.DoFloor(line, FloorMoveType.RaiseFloorTurbo); break; } }
public void Make(Fixed frac, LineDef line) { this.frac = frac; this.thing = null; this.line = line; }
public void Make(Fixed frac, Mobj thing) { this.frac = frac; this.thing = thing; this.line = null; }