public static void Do(Level lvl, ref PhysInfo C) { if (C.Data.Type1 != PhysicsArgs.Custom) { return; } if (C.Data.Data == 0) { BlockID block = (BlockID)(C.Data.Value2 | (C.Data.ExtBlock << Block.ExtendedShift)); bool tdoor = lvl.Props[block].IsTDoor; if (tdoor) { tDoor(lvl, ref C); } else { Door(lvl, ref C); } } if (C.Data.Data <= C.Data.Value1) // value1 for wait time { C.Data.Data++; } else { PhysicsArgs dArgs = default(PhysicsArgs); dArgs.ExtBlock = C.Data.ExtBlock; lvl.AddUpdate(C.Index, C.Data.Value2, dArgs); C.Data.Data = PhysicsArgs.RemoveFromChecks; } }
static bool MoveSnake(Level lvl, ref PhysInfo C, ushort x, ushort y, ushort z) { int index; // Move snake up or down blocks if (lvl.IsAirAt(x, (ushort)(y - 1), z, out index) && lvl.IsAirAt(x, y, z)) { } else if (lvl.IsAirAt(x, y, z, out index) && lvl.IsAirAt(x, (ushort)(y + 1), z)) { } else if (lvl.IsAirAt(x, (ushort)(y + 1), z, out index) && lvl.IsAirAt(x, (ushort)(y + 2), z)) { } else { return(false); } if (lvl.AddUpdate(index, C.Block)) { PhysicsArgs args = default(PhysicsArgs); args.Type1 = PhysicsArgs.Wait; args.Value1 = 5; args.Type2 = PhysicsArgs.Revert; args.Value2 = Block.Air; lvl.AddUpdate(C.Index, Block.SnakeTail, args, true); return(true); } return(false); }
public static void DoLeaf(Level lvl, ref PhysInfo C) { // Decaying disabled? Then just remove from the physics list if (!lvl.Config.LeafDecay) { C.Data.Data = PhysicsArgs.RemoveFromChecks; return; } // Delay checking for leaf decay for a random amount of time if (C.Data.Data < 5) { Random rand = lvl.physRandom; if (rand.Next(10) == 0) { C.Data.Data++; } return; } // Perform actual leaf decay, then remove from physics list if (DoLeafDecay(lvl, ref C)) { lvl.AddUpdate(C.Index, Block.Air, default(PhysicsArgs)); if (lvl.physics > 1) { ActivateablePhysics.CheckNeighbours(lvl, C.X, C.Y, C.Z); } } C.Data.Data = PhysicsArgs.RemoveFromChecks; }
public static void DoFlood(Level lvl, ref PhysInfo C, AirFlood mode, BlockID block) { if (C.Data.Data >= 1) { lvl.AddUpdate(C.Index, Block.Air, default(PhysicsArgs)); C.Data.Data = PhysicsArgs.RemoveFromChecks; return; } ushort x = C.X, y = C.Y, z = C.Z; FloodAir(lvl, (ushort)(x + 1), y, z, block); FloodAir(lvl, (ushort)(x - 1), y, z, block); FloodAir(lvl, x, y, (ushort)(z + 1), block); FloodAir(lvl, x, y, (ushort)(z - 1), block); switch (mode) { case AirFlood.Full: FloodAir(lvl, x, (ushort)(y - 1), z, block); FloodAir(lvl, x, (ushort)(y + 1), z, block); break; case AirFlood.Layer: break; case AirFlood.Down: FloodAir(lvl, x, (ushort)(y - 1), z, block); break; case AirFlood.Up: FloodAir(lvl, x, (ushort)(y + 1), z, block); break; } C.Data.Data++; }
public static void DoAir(Level lvl, ref PhysInfo C) { if (C.Data.Type1 == PhysicsArgs.Custom) { DoorPhysics.Do(lvl, ref C); return; } ushort x = C.X, y = C.Y, z = C.Z; ActivateablePhysics.CheckNeighbours(lvl, x, y, z); ActivateablePhysics.CheckAt(lvl, x, (ushort)(y - 1), z); //Edge of map water if (lvl.Config.EdgeWater && (y < lvl.Config.EdgeLevel && y >= (lvl.Config.EdgeLevel + lvl.Config.SidesOffset))) { if (x == 0 || x == lvl.Width - 1 || z == 0 || z == lvl.Length - 1) { BlockID horizon = lvl.Config.HorizonBlock; lvl.AddUpdate(C.Index, horizon == Block.Invalid ? Block.Water : horizon); } } if (!C.Data.HasWait) { C.Data.Data = PhysicsArgs.RemoveFromChecks; } }
public static void DoWater(Level lvl, ref PhysInfo C) { if (lvl.Config.FiniteLiquids) { if (lvl.Config.FiniteHighWater) { ushort y = C.Y; if (y >= lvl.Config.EdgeLevel) { FinitePhysics.DoWaterOrLava(lvl, ref C); return; } } else { FinitePhysics.DoWaterOrLava(lvl, ref C); return; } } if (lvl.Config.RandomFlow) { DoWaterRandowFlow(lvl, ref C); } else { DoWaterUniformFlow(lvl, ref C); } }
public static void DoFaucet(Level lvl, ref PhysInfo C, BlockID target) { C.Data.Data++; if (C.Data.Data < 2) { return; } C.Data.Data = 0; Random rand = lvl.physRandom; int index; BlockID below = lvl.GetBlock(C.X, (ushort)(C.Y - 1), C.Z, out index); if (below == Block.Air || below == target) { if (rand.Next(1, 10) > 7) { lvl.AddUpdate(index, Block.Air_FloodDown, default(PhysicsArgs)); } } else if (below == Block.Air_FloodDown) { if (rand.Next(1, 10) > 4) { lvl.AddUpdate(index, target); } } }
public static void DoLeaf(Level lvl, ref PhysInfo C) { if (lvl.physics > 1) //Adv physics kills flowers and mushroos in water/lava { ActivateablePhysics.CheckNeighbours(lvl, C.X, C.Y, C.Z); } // Just immediately remove from physics list if (!lvl.Config.LeafDecay) { lvl.leaves.Clear(); C.Data.Data = PhysicsArgs.RemoveFromChecks; return; } // Delay checking for decay for a random amount of time if (C.Data.Data < 5) { Random rand = lvl.physRandom; if (rand.Next(10) == 0) { C.Data.Data++; } return; } // Perform actual leaf decay, then remove from physics list if (DoLeafDecay(lvl, ref C)) { lvl.AddUpdate(C.Index, Block.Air, default(PhysicsArgs)); } C.Data.Data = PhysicsArgs.RemoveFromChecks; }
public static void DoLargeTnt(Level lvl, ref PhysInfo C, int power) { ushort x = C.X, y = C.Y, z = C.Z; if (lvl.physics < 3) { lvl.Blockchange(x, y, z, Block.Air); } else { if (C.Data.Data < 5 && lvl.physics == 3) { C.Data.Data++; ToggleFuse(lvl, x, (ushort)(y + 1), z); ToggleFuse(lvl, x, (ushort)(y - 1), z); ToggleFuse(lvl, (ushort)(x + 1), y, z); ToggleFuse(lvl, (ushort)(x - 1), y, z); ToggleFuse(lvl, x, y, (ushort)(z + 1)); ToggleFuse(lvl, x, y, (ushort)(z - 1)); return; } MakeExplosion(lvl, x, y, z, power); } }
public static bool DoNormal(Level lvl, ref PhysInfo C) { if (!C.Data.HasWait && C.Block == Block.Air) { C.Data.ResetTypes(); } ExtraInfoArgs args = default(ExtraInfoArgs); ParseType(C.Data.Type1, ref args, C.Data.Value1); ParseType(C.Data.Type2, ref args, C.Data.Value2); args.ExtBlock = C.Data.ExtBlock; if (args.Wait) { if (C.Data.Data <= args.WaitTime) { C.Data.Data++; return(true); } if (C.Data.Type1 == PhysicsArgs.Wait) { C.Data.Type1 = 0; } if (C.Data.Type2 == PhysicsArgs.Wait) { C.Data.Type2 = 0; } } DoOther(lvl, ref C, ref args); return(false); }
static void DoWaterUniformFlow(Level lvl, ref PhysInfo C) { ushort x = C.X, y = C.Y, z = C.Z; if (!lvl.CheckSpongeWater(x, y, z)) { BlockID block = C.Block; if (y < lvl.Height - 1) { CheckFallingBlocks(lvl, C.Index + lvl.Width * lvl.Length); } LiquidPhysics.PhysWater(lvl, (ushort)(x + 1), y, z, block); LiquidPhysics.PhysWater(lvl, (ushort)(x - 1), y, z, block); LiquidPhysics.PhysWater(lvl, x, y, (ushort)(z + 1), block); LiquidPhysics.PhysWater(lvl, x, y, (ushort)(z - 1), block); LiquidPhysics.PhysWater(lvl, x, (ushort)(y - 1), z, block); } else //was placed near sponge { lvl.AddUpdate(C.Index, Block.Air, default(PhysicsArgs)); } if (!C.Data.HasWait) { C.Data.Data = PhysicsArgs.RemoveFromChecks; } }
public static void DoLavafall(Level lvl, ref PhysInfo C) { ushort x = C.X, y = C.Y, z = C.Z; int index; BlockID below = lvl.GetBlock(x, (ushort)(y - 1), z, out index); switch (below) { case Block.Air: lvl.AddUpdate(index, Block.LavaDown, default(PhysicsArgs)); if (!C.Data.HasWait) { C.Data.Data = PhysicsArgs.RemoveFromChecks; } break; case Block.Air_FloodDown: case Block.StillLava: case Block.StillWater: case Block.LavaDown: break; default: BlockID block = C.Block; LiquidPhysics.PhysLava(lvl, (ushort)(x + 1), y, z, block); LiquidPhysics.PhysLava(lvl, (ushort)(x - 1), y, z, block); LiquidPhysics.PhysLava(lvl, x, y, (ushort)(z + 1), block); LiquidPhysics.PhysLava(lvl, x, y, (ushort)(z - 1), block); if (!C.Data.HasWait) { C.Data.Data = PhysicsArgs.RemoveFromChecks; } break; } }
static void Firework(ref PhysInfo C, int size, Level lvl, Random rand) { int rand1 = rand.Next(Block.Red, Block.White); int rand2 = rand.Next(Block.Red, Block.White); int min = Math.Min(rand1, rand2), max = Math.Max(rand1, rand2); // Not using override, since override = true makes it more likely that a colored block will be // generated with no extraInfo, because it sets a Check for that position with no extraInfo. lvl.AddUpdate(C.Index, Block.Air, default(PhysicsArgs)); int index; ushort x = C.X, y = C.Y, z = C.Z; for (int yy = y - (size + 1); yy <= y + (size + 1); ++yy) { for (int zz = z - (size + 1); zz <= z + (size + 1); ++zz) { for (int xx = x - (size + 1); xx <= x + (size + 1); ++xx) { if (lvl.IsAirAt((ushort)xx, (ushort)yy, (ushort)zz, out index) && rand.Next(1, 40) < 2) { PhysicsArgs args = default(PhysicsArgs); args.Type1 = PhysicsArgs.Drop; args.Value1 = 100; args.Type2 = PhysicsArgs.Dissipate; args.Value2 = 25; lvl.AddUpdate(index, (byte)rand.Next(min, max), args); } } } } }
static void FlyTo(Level lvl, ref PhysInfo C, ushort x, ushort y, ushort z, BlockID block) { int index; BlockID neighbour = lvl.GetBlock(x, y, z, out index); if (neighbour == Block.Invalid) { return; } switch (neighbour) { case Block.Air: lvl.AddUpdate(index, block); break; case Block.Op_Air: break; default: // bird died by hitting a block PhysicsArgs args = default(PhysicsArgs); args.Type1 = PhysicsArgs.Dissipate; args.Value1 = 25; lvl.AddUpdate(C.Index, Block.Red, args); break; } }
static bool MoveZombie(Level lvl, ref PhysInfo C, ushort x, ushort y, ushort z) { int index; // Move zombie up or down blocks if (lvl.IsAirAt(x, (ushort)(y - 1), z, out index) && lvl.IsAirAt(x, y, z)) { } else if (lvl.IsAirAt(x, y, z, out index) && lvl.IsAirAt(x, (ushort)(y + 1), z)) { } else if (lvl.IsAirAt(x, (ushort)(y + 1), z, out index) && lvl.IsAirAt(x, (ushort)(y + 2), z)) { } else { return(false); } if (lvl.AddUpdate(index, C.Block)) { lvl.AddUpdate(lvl.IntOffset(index, 0, 1, 0), Block.ZombieHead, default(PhysicsArgs)); lvl.AddUpdate(C.Index, Block.Air, default(PhysicsArgs)); lvl.AddUpdate(lvl.IntOffset(C.Index, 0, 1, 0), Block.Air, default(PhysicsArgs)); return(true); } return(false); }
static void DoOther(Level lvl, ref PhysInfo C, ref ExtraInfoArgs args) { Random rand = lvl.physRandom; if (args.Rainbow) { if (C.Data.Data < 4) { C.Data.Data++; } else { DoRainbow(lvl, ref C, rand, args.RainbowNum); } return; } if (args.Revert) { PhysicsArgs revertArgs = default(PhysicsArgs); revertArgs.ExtBlock = args.ExtBlock; lvl.AddUpdate(C.Index, args.RevertType, revertArgs); C.Data.ResetTypes(); C.Data.Data = PhysicsArgs.RemoveFromChecks; } ushort x = C.X, y = C.Y, z = C.Z; // Not setting drop = false can cause occasional leftover blocks, since C.extraInfo is emptied, so // drop can generate another block with no dissipate/explode information. if (args.Dissipate && rand.Next(1, 100) <= args.DissipateNum) { if (!lvl.listUpdateExists.Get(x, y, z)) { lvl.AddUpdate(C.Index, Block.Air, default(PhysicsArgs)); C.Data.ResetTypes(); args.Drop = false; } else { lvl.AddUpdate(C.Index, C.Block, C.Data); } } if (args.Explode && rand.Next(1, 100) <= args.ExplodeNum) { lvl.MakeExplosion(x, y, z, 0); C.Data.ResetTypes(); args.Drop = false; } if (args.Drop && rand.Next(1, 100) <= args.DropNum) { DoDrop(lvl, ref C, rand, args.DropNum, x, y, z); } }
public static void DoTntExplosion(Level lvl, ref PhysInfo C) { Random rand = lvl.physRandom; if (rand.Next(1, 11) <= 7) { lvl.AddUpdate(C.Index, Block.Air, default(PhysicsArgs)); } }
public static void DoHead(Level lvl, ref PhysInfo C) { BlockID below = lvl.GetBlock(C.X, (ushort)(C.Y - 1), C.Z); if (below != Block.ZombieBody && below != Block.Creeper) { C.Data.Type1 = PhysicsArgs.Revert; C.Data.Value1 = Block.Air; } }
public static void Do(Level lvl, ref PhysInfo C) { Random rand = lvl.physRandom; ushort x = C.X, y = C.Y, z = C.Z; BlockID block = lvl.GetBlock(x, y, z); int index; switch (rand.Next(1, 15)) { case 1: if (lvl.IsAirAt(x, (ushort)(y - 1), z, out index)) { lvl.AddUpdate(index, block); } else { goto case 3; } break; case 2: if (lvl.IsAirAt(x, (ushort)(y + 1), z, out index)) { lvl.AddUpdate(index, block); } else { goto case 6; } break; case 3: case 4: case 5: FlyTo(lvl, ref C, (ushort)(x - 1), y, z, block); break; case 6: case 7: case 8: FlyTo(lvl, ref C, (ushort)(x + 1), y, z, block); break; case 9: case 10: case 11: FlyTo(lvl, ref C, x, y, (ushort)(z - 1), block); break; default: FlyTo(lvl, ref C, x, y, (ushort)(z + 1), block); break; } lvl.AddUpdate(C.Index, Block.Air, default(PhysicsArgs)); C.Data.Data = PhysicsArgs.RemoveFromChecks; }
public static void DoOther(Level lvl, ref PhysInfo C) { if (lvl.physics <= 1) { C.Data.Data = PhysicsArgs.RemoveFromChecks; return; } //Adv physics kills flowers and mushroos in water/lava ActivateablePhysics.CheckNeighbours(lvl, C.X, C.Y, C.Z); C.Data.Data = PhysicsArgs.RemoveFromChecks; }
static void tDoor(Level lvl, ref PhysInfo C) { ushort x = C.X, y = C.Y, z = C.Z; ActivateTDoor(lvl, (ushort)(x - 1), y, z); ActivateTDoor(lvl, (ushort)(x + 1), y, z); ActivateTDoor(lvl, x, (ushort)(y - 1), z); ActivateTDoor(lvl, x, (ushort)(y + 1), z); ActivateTDoor(lvl, x, y, (ushort)(z - 1)); ActivateTDoor(lvl, x, y, (ushort)(z + 1)); }
void HandleTNTPhysics(Level lvl, ref PhysInfo C) { ushort x = C.X, y = C.Y, z = C.Z; Player p = GetPlayer(ref C.Data); if (p == null) { C.Data.Data = PhysicsArgs.RemoveFromChecks; return; } int power = 2, threshold = 3; switch (Config.Difficulty) { case TWDifficulty.Easy: threshold = 7; break; case TWDifficulty.Normal: threshold = 5; break; case TWDifficulty.Extreme: power = 3; break; } if ((C.Data.Data >> 4) < threshold) { C.Data.Data += (1 << 4); TntPhysics.ToggleFuse(lvl, x, (ushort)(y + 1), z); return; } TWData data = Get(p); if (data.KillStreak >= cfg.StreakTwoAmount && cfg.Streaks) { power++; } TntPhysics.MakeExplosion(Map, x, y, z, power - 2, true, this); List <Player> inRange = new List <Player>(); Player[] all = allPlayers.Items; foreach (Player pl in all) { if (pl == p) { continue; } if (Math.Abs(pl.Pos.BlockX - x) + Math.Abs(pl.Pos.BlockY - y) + Math.Abs(pl.Pos.BlockZ - z) < ((power * 3) + 1)) { inRange.Add(pl); } } KillPlayers(p, data, inRange); }
static bool MoveTo(Level lvl, ref PhysInfo C, BlockID target, ushort x, ushort y, ushort z) { int index; BlockID block = lvl.GetBlock(x, y, z, out index); if (block == target && lvl.AddUpdate(index, C.Block)) { lvl.AddUpdate(C.Index, target); return(true); } return(false); }
public static void oDoor(Level lvl, ref PhysInfo C) { ushort x = C.X, y = C.Y, z = C.Z; BlockID block = C.Block; ActivateODoor(lvl, block, (ushort)(x - 1), y, z); ActivateODoor(lvl, block, (ushort)(x + 1), y, z); ActivateODoor(lvl, block, x, (ushort)(y - 1), z); ActivateODoor(lvl, block, x, (ushort)(y + 1), z); ActivateODoor(lvl, block, x, y, (ushort)(z - 1)); ActivateODoor(lvl, block, x, y, (ushort)(z + 1)); C.Data.Data = PhysicsArgs.RemoveFromChecks; }
public static void DoTail(Level lvl, ref PhysInfo C) { ushort x = C.X, y = C.Y, z = C.Z; bool revert = lvl.GetBlock((ushort)(x - 1), y, z) != Block.Snake || lvl.GetBlock((ushort)(x + 1), y, z) != Block.Snake || lvl.GetBlock(x, y, (ushort)(z - 1)) != Block.Snake || lvl.GetBlock(x, y, (ushort)(z + 1)) != Block.Snake; if (revert) { C.Data.Type1 = PhysicsArgs.Revert; C.Data.Value1 = Block.Air; } }
public static void DoFastLava(Level lvl, ref PhysInfo C) { if (lvl.Config.RandomFlow) { DoLavaRandowFlow(lvl, ref C, false); if (C.Data.Data != PhysicsArgs.RemoveFromChecks) { C.Data.Data = 0; // no lava delay } } else { DoLavaUniformFlow(lvl, ref C, false); } }
public static void DoWater(Level lvl, ref PhysInfo C) { if (lvl.Config.FiniteLiquids) { FinitePhysics.DoWaterOrLava(lvl, ref C); } else if (lvl.Config.RandomFlow) { DoWaterRandowFlow(lvl, ref C); } else { DoWaterUniformFlow(lvl, ref C); } }
static void DoDrop(Level lvl, ref PhysInfo C, Random rand, int dropnum, ushort x, ushort y, ushort z) { int index; BlockID below = lvl.GetBlock(x, (ushort)(y - 1), z, out index); if (!(below == Block.Air || below == Block.Lava || below == Block.Water)) { return; } if (rand.Next(1, 100) < dropnum && lvl.AddUpdate(index, C.Block, C.Data)) { lvl.AddUpdate(C.Index, Block.Air, default(PhysicsArgs)); C.Data.ResetTypes(); } }
public static void Do(Level lvl, ref PhysInfo C) { Random rand = lvl.physRandom; int dirX = rand.Next(1, 10) <= 5 ? 1 : -1; int dirY = rand.Next(1, 10) <= 5 ? 1 : -1; int dirZ = rand.Next(1, 10) <= 5 ? 1 : -1; ushort x = C.X, y = C.Y, z = C.Z; for (int cx = -dirX; cx != 2 * dirX; cx += dirX) { for (int cy = -dirY; cy != 2 * dirY; cy += dirY) { for (int cz = -dirZ; cz != 2 * dirZ; cz += dirZ) { BlockID rocketTail = lvl.GetBlock((ushort)(x + cx), (ushort)(y + cy), (ushort)(z + cz)); if (rocketTail != Block.LavaFire) { continue; } int headIndex; BlockID rocketHead = lvl.GetBlock((ushort)(x - cx), (ushort)(y - cy), (ushort)(z - cz), out headIndex); bool unblocked = !lvl.listUpdateExists.Get(x, y, z) && (headIndex < 0 || !lvl.listUpdateExists.Get(x - cx, y - cy, z - cz)); if (unblocked && (rocketHead == Block.Air || rocketHead == Block.RocketStart)) { lvl.AddUpdate(headIndex, Block.RocketHead, default(PhysicsArgs)); lvl.AddUpdate(C.Index, Block.LavaFire, default(PhysicsArgs)); } else if (rocketHead == Block.LavaFire) { } else { if (lvl.physics > 2) { lvl.MakeExplosion(x, y, z, 2); } else { lvl.AddUpdate(C.Index, Block.LavaFire, default(PhysicsArgs)); } } } } } }
// Change anys door blocks nearby into air forms static void Door(Level lvl, ref PhysInfo C) { ushort x = C.X, y = C.Y, z = C.Z; BlockID block = (BlockID)(C.Data.Value2 | (C.Data.ExtBlock << Block.ExtendedShift)); bool instant = block == Block.Door_Air || block == Block.Door_AirActivatable; ActivateablePhysics.DoDoors(lvl, (ushort)(x + 1), y, z, instant); ActivateablePhysics.DoDoors(lvl, (ushort)(x - 1), y, z, instant); ActivateablePhysics.DoDoors(lvl, x, y, (ushort)(z + 1), instant); ActivateablePhysics.DoDoors(lvl, x, y, (ushort)(z - 1), instant); ActivateablePhysics.DoDoors(lvl, x, (ushort)(y - 1), z, instant); ActivateablePhysics.DoDoors(lvl, x, (ushort)(y + 1), z, instant); if (block == Block.Door_Green && lvl.physics != 5) { ActivateablePhysics.DoNeighbours(lvl, x, y, z); } }