public void LoadFromCustomModel(CustomModel model) { // convert to pixel units this.nameY = model.nameY * 16.0f; this.eyeY = model.eyeY * 16.0f; this.collisionBounds = new Vec3F32 { X = model.collisionBounds.X * 16.0f, Y = model.collisionBounds.Y * 16.0f, Z = model.collisionBounds.Z * 16.0f, }; this.pickingBoundsMin = new Vec3F32 { X = model.pickingBoundsMin.X * 16.0f, Y = model.pickingBoundsMin.Y * 16.0f, Z = model.pickingBoundsMin.Z * 16.0f, }; this.pickingBoundsMax = new Vec3F32 { X = model.pickingBoundsMax.X * 16.0f, Y = model.pickingBoundsMax.Y * 16.0f, Z = model.pickingBoundsMax.Z * 16.0f, }; this.bobbing = model.bobbing; this.pushes = model.pushes; this.usesHumanSkin = model.usesHumanSkin; this.calcHumanAnims = model.calcHumanAnims; }
public static AABB CalcAABB(Entity entity) { string model = GetRawModel(entity.Model); AABB bb; BlockID raw; if (BlockID.TryParse(model, out raw) && raw <= Block.MaxRaw) { BlockID block = Block.FromRaw(raw); bb = Block.BlockAABB(block, entity.Level); bb = bb.Offset(-16, 0, -16); // centre around [-16, 16] instead of [0, 32] } else { bb = AABB.Make(new Vec3S32(0, 0, 0), Get(model).BaseSize); } bb = bb.Expand(-1); // adjust the model AABB inwards slightly Vec3F32 scale = CalcScale(entity); // always limit max scale for collisions performance float max = DefaultMaxScale(model); scale.X = Math.Min(scale.X, max); scale.Y = Math.Min(scale.Y, max); scale.Z = Math.Min(scale.Z, max); bb.Min.X = (int)(bb.Min.X * scale.X); bb.Max.X = (int)(bb.Max.X * scale.X); bb.Min.Y = (int)(bb.Min.Y * scale.Y); bb.Max.Y = (int)(bb.Max.Y * scale.Y); bb.Min.Z = (int)(bb.Min.Z * scale.Z); bb.Max.Z = (int)(bb.Max.Z * scale.Z); return(bb); }
static bool MoveTowards(PlayerBot bot, Player p, Metadata meta) { if (p == null) { return(false); } int dist = (int)(0.875 * 32); int dx = p.Pos.X - bot.Pos.X, dy = p.Pos.Y - bot.Pos.Y, dz = p.Pos.Z - bot.Pos.Z; bot.TargetPos = p.Pos; bot.movement = true; Vec3F32 dir = new Vec3F32(dx, dy, dz); dir = Vec3F32.Normalise(dir); Orientation rot = bot.Rot; DirUtils.GetYawPitch(dir, out rot.RotY, out rot.HeadX); MobAI.SetDirectionalSpeeds(bot); dx = Math.Abs(dx); dy = Math.Abs(dy); dz = Math.Abs(dz); if (InRange(p, bot, dist)) { p.Message("%cInfect"); } bot.Rot = rot; return(dx <= 8 && dy <= 16 && dz <= 8); }
static bool MoveTowards(PlayerBot bot, Player p, Metadata meta) { if (p == null) { return(false); } int dx = p.Pos.X - bot.Pos.X, dy = p.Pos.Y - bot.Pos.Y, dz = p.Pos.Z - bot.Pos.Z; bot.TargetPos = p.Pos; bot.movement = true; Vec3F32 dir = new Vec3F32(dx, dy, dz); dir = Vec3F32.Normalise(dir); Orientation rot = bot.Rot; DirUtils.GetYawPitch(dir, out rot.RotY, out rot.HeadX); MobAI.SetDirectionalSpeeds(bot); p.Message("I am facing: %b" + MobAI.CalculateCardinal(bot)); p.Message("sp " + bot.movementSpeed); //p.Message("The block in front of me is: %b"); dx = Math.Abs(dx); dy = Math.Abs(dy); dz = Math.Abs(dz); bot.Rot = rot; return(dx <= 8 && dy <= 16 && dz <= 8); }
void Step(PlayerBot bot) { bot.TargetPos = bot.Pos; bot.movement = true; Vec3F32 dir = DirUtils.GetDirVector(bot.Rot.RotY, 0); bot.TargetPos.X = bot.Pos.X + (int)(dir.X * bot.movementSpeed); bot.TargetPos.Z = bot.Pos.Z + (int)(dir.Z * bot.movementSpeed); }
static bool MoveTowards(PlayerBot bot, Player p, Metadata meta) { if (p == null) { return(false); } int dx = p.Pos.X - bot.Pos.X, dy = p.Pos.Y - bot.Pos.Y, dz = p.Pos.Z - bot.Pos.Z; bot.TargetPos = p.Pos; bot.movement = true; Vec3F32 dir = new Vec3F32(dx, dy, dz); dir = Vec3F32.Normalise(dir); Orientation rot = bot.Rot; DirUtils.GetYawPitch(dir, out rot.RotY, out rot.HeadX); MobAI.SetDirectionalSpeeds(bot); dx = Math.Abs(dx); dy = Math.Abs(dy); dz = Math.Abs(dz); if (bot.Model == "creeper") { if (dx < (3 * 32) && dz < (3 * 32)) { if (meta.explodeTime == 0) { meta.explodeTime = 10; } } else { meta.explodeTime = 0; } } else { if ((dx <= 8 && dy <= 16 && dz <= 8)) { HitPlayer(bot, p, rot); } } bot.Rot = rot; return(dx <= 8 && dy <= 16 && dz <= 8); }
/// <summary> /// Face bot towards target position. /// </summary> /// <param name="bot"></param> public static void FaceTowards(PlayerBot bot) { int dstHeight = ModelInfo.CalcEyeHeight(bot); int dx = (bot.TargetPos.X) - bot.Pos.X, dy = bot.Rot.RotY, dz = (bot.TargetPos.Z) - bot.Pos.Z; Vec3F32 dir = new Vec3F32(dx, dy, dz); dir = Vec3F32.Normalise(dir); Orientation rot = bot.Rot; DirUtils.GetYawPitch(dir, out rot.RotY, out rot.HeadX); bot.Rot = rot; }
/// <summary> Gives distance (in half-pixel world units) from feet to camera height </summary> public static int CalcEyeHeight(Entity entity) { Vec3F32 scale = CalcScale(entity); string model = GetRawModel(entity.Model); BlockID raw; if (BlockID.TryParse(model, out raw) && raw <= Block.MaxRaw) { return(16); //lazily return middle of full block if it thinks it's a block ID. } float eyeHeight = Get(model).EyeHeight; eyeHeight *= scale.Y; eyeHeight *= 2f; //multiply by two because world positions are measured in half-pixels return((int)eyeHeight); }
static bool MoveTowards(PlayerBot bot, Player p, Metadata meta) { if (p == null) { return(false); } int dist = (int)(0.875 * 32); int dx = p.Pos.X - bot.Pos.X, dy = p.Pos.Y - bot.Pos.Y, dz = p.Pos.Z - bot.Pos.Z; bot.TargetPos = p.Pos; bot.movement = true; Vec3F32 dir = new Vec3F32(dx, dy, dz); dir = Vec3F32.Normalise(dir); Orientation rot = bot.Rot; DirUtils.GetYawPitch(dir, out rot.RotY, out rot.HeadX); MobAI.SetDirectionalSpeeds(bot); dx = Math.Abs(dx); dy = Math.Abs(dy); dz = Math.Abs(dz); //if (InRange(p, bot, dist)) p.Message("%cInfect"); bot.Rot = rot; if (dx < (5 * 32) && dz < (5 * 32)) // 5 block reach { Random rnd = new Random(); // This code serves as a sort of 'CPS mechanism' to ensure that the bot does not perfectly delete every single block int chance = rnd.Next(0, 4); // 33% chance of deleting the block if (chance < 3) { bot.level.UpdateBlock(Player.Console, (ushort)(p.Pos.X / 32), (ushort)((p.Pos.Y / 32) - 2), (ushort)(p.Pos.Z / 32), Block.Air); if ((p.Pos.Y / 32) > lastY) { bot.level.UpdateBlock(Player.Console, (ushort)(p.Pos.X / 32), (ushort)((p.Pos.Y / 32) - 3), (ushort)(p.Pos.Z / 32), Block.Air); } } lastY = (p.Pos.Y / 32); } return(dx <= 8 && dy <= 16 && dz <= 8); }
public void LoadFromFile() { string path = GetCCPath(); string contentsCC = File.ReadAllText(path); StoredCustomModel o = JsonConvert.DeserializeObject <StoredCustomModel>(contentsCC, jsonSettings); this.nameY = o.nameY; this.autoNameY = o.autoNameY; this.eyeY = o.eyeY; this.collisionBounds = o.collisionBounds; this.pickingBoundsMin = o.pickingBoundsMin; this.pickingBoundsMax = o.pickingBoundsMax; this.bobbing = o.bobbing; this.pushes = o.pushes; this.usesHumanSkin = o.usesHumanSkin; this.calcHumanAnims = o.calcHumanAnims; this.defaultSkin = o.defaultSkin; }
public static void GetYawPitch(Vec3F32 dir, out byte yaw, out byte pitch) { // y = -sin(pitch) -> pitch = arcsin(-y) // x = sin(yaw) -> yaw = arcsin(x) // z = -cos(yaw) -> yaw = arccos(-z) // We ignore the cos(pitch) multiplication by the x/z components, since // this does not affect the resulting yaw const double rad2Packed = 256.0 / (2 * Math.PI); // NOTE: This conversion method **does** lose information // a) If x and z are 0, yaw cannot be properly recalculated // b) Pitch will always be from 0-64 or 192-256, therefore flipped heads lost // However since we have X/Z, this problem does not occur for yaw, // as we can use both values to determine which side of unit circle yaw is in // c) Resulting yaw/pitch may be 1 or 2 values off due to rounding yaw = (byte)(Math.Atan2(dir.X, -dir.Z) * rad2Packed); pitch = (byte)(Math.Asin(-dir.Y) * rad2Packed); }
// graceLength is how far (in pixels) you can extend past max width/height on all sides private static bool SizeAllowed(Vec3F32 boxCorner, float graceLength) { //convert to block-unit to match boxCorner const float maxWidthB = maxWidth / 16f; const float maxHeightB = maxHeight / 16f; float graceLengthB = graceLength / 16f; if ( boxCorner.Y < -graceLengthB || boxCorner.Y > maxHeightB + graceLengthB || boxCorner.X < -((maxWidthB / 2) + graceLengthB) || boxCorner.X > (maxWidthB / 2) + graceLengthB || boxCorner.Z < -((maxWidthB / 2) + graceLengthB) || boxCorner.Z > (maxWidthB / 2) + graceLengthB ) { return(false); } return(true); }
public static void HitPlayer(PlayerBot bot, Player p, Orientation rot) { // Send player backwards if hit // Code "borrowed" from PvP plugin int srcHeight = ModelInfo.CalcEyeHeight(bot); int dstHeight = ModelInfo.CalcEyeHeight(p); int dx2 = bot.Pos.X - p.Pos.X, dy2 = (bot.Pos.Y + srcHeight) - (p.Pos.Y + dstHeight), dz2 = bot.Pos.Z - p.Pos.Z; Vec3F32 dir2 = new Vec3F32(dx2, dy2, dz2); if (dir2.Length > 0) { dir2 = Vec3F32.Normalise(dir2); } float mult = 1 / ModelInfo.GetRawScale(p.Model); float plScale = ModelInfo.GetRawScale(p.Model); float VelocityY = 1.0117f * mult; if (dir2.Length <= 0) { VelocityY = 0; } if (p.Supports(CpeExt.VelocityControl)) { // Intensity of force is in part determined by model scale p.Send(Packet.VelocityControl((-dir2.X * mult) * 0.57f, VelocityY, (-dir2.Z * mult) * 0.57f, 0, 1, 0)); } // If we are very close to a player, switch from trying to look // at them to just facing the opposite direction to them rot.RotY = (byte)(p.Rot.RotY + 128); bot.Rot = rot; }
static bool MoveTowards(PlayerBot bot, Player p) { int dx = p.Pos.X - bot.Pos.X, dy = p.Pos.Y - bot.Pos.Y, dz = p.Pos.Z - bot.Pos.Z; bot.TargetPos = p.Pos; bot.movement = true; Vec3F32 dir = new Vec3F32(dx, dy, dz); dir = Vec3F32.Normalise(dir); Orientation rot = bot.Rot; DirUtils.GetYawPitch(dir, out rot.RotY, out rot.HeadX); // If we are very close to a player, switch from trying to look // at them to just facing the opposite direction to them if (Math.Abs(dx) < 4 && Math.Abs(dz) < 4) { rot.RotY = (byte)(p.Rot.RotY + 128); } bot.Rot = rot; return(dx <= 8 && dy <= 16 && dz <= 8); }
void OnPlayerMove(Player p, Position next, byte yaw, byte pitch) { string data = playerEffects.FindData(p.name); if (data == null) { return; } if (rnd.NextDouble() > 0.125f && !data.StartsWith("puff")) { return; } float x = p.Pos.X * 0.03125f; float y = (p.Pos.Y + ModelInfo.CalcEyeHeight(p) - Entities.CharacterHeight) * 0.03125f; float z = p.Pos.Z * 0.03125f; float originX = x; float originY = y; float originZ = z; Player notShownTo = null; //ugly hack if (data.StartsWith("leaf")) { if (rnd.NextDouble() > 0.5f) { return; } originX += 32; originZ += 8; } else if (data.StartsWith("puff")) { Random playerRandom = new Random(p.name.GetHashCode()); const int cycle = 4000; const int breatheOut = 1000; int offset = playerRandom.Next(0, cycle + 1); TimeSpan delta = DateTime.UtcNow - (startTime.AddMilliseconds(offset)); int ms = (int)delta.TotalMilliseconds; bool phase1 = (ms % cycle) < breatheOut; if (!phase1) { return; } Vec3F32 dir = DirUtils.GetDirVector(yaw, pitch); dir.X *= 0.3f; dir.Y *= 0.3f; dir.Z *= 0.3f; originY = y; x += dir.X; y += dir.Y; z += dir.Z; y -= 0.15f; originY -= 0.15f; notShownTo = p; } SpawnEffectAt(p.level, data, x, y, z, originX, originY, originZ); }
private Part ToPart(Element e) { if (!e.visibility) { return(null); } Vec3F32 rotation = new Vec3F32 { X = 0, Y = 0, Z = 0 }; if (e.rotation != null) { rotation.X = e.rotation[0]; rotation.Y = e.rotation[1]; rotation.Z = e.rotation[2]; } Vec3F32 min = new Vec3F32 { X = (e.from[0] - e.inflate) / 16.0f, Y = (e.from[1] - e.inflate) / 16.0f, Z = (e.from[2] - e.inflate) / 16.0f, }; Vec3F32 max = new Vec3F32 { X = (e.to[0] + e.inflate) / 16.0f, Y = (e.to[1] + e.inflate) / 16.0f, Z = (e.to[2] + e.inflate) / 16.0f, }; var rotationOrigin = new Vec3F32 { X = e.origin[0] / 16.0f, Y = e.origin[1] / 16.0f, Z = e.origin[2] / 16.0f, }; // faces in order [u1, v1, u2, v2] /* uv coords in order: top, bottom, front, back, left, right */ // swap up's uv's UInt16[] u1 = new[] { (UInt16)e.faces.up.uv[2], (UInt16)e.faces.down.uv[0], (UInt16)e.faces.north.uv[0], (UInt16)e.faces.south.uv[0], (UInt16)e.faces.east.uv[0], (UInt16)e.faces.west.uv[0], }; UInt16[] v1 = new[] { (UInt16)e.faces.up.uv[3], (UInt16)e.faces.down.uv[1], (UInt16)e.faces.north.uv[1], (UInt16)e.faces.south.uv[1], (UInt16)e.faces.east.uv[1], (UInt16)e.faces.west.uv[1], }; UInt16[] u2 = new[] { (UInt16)e.faces.up.uv[0], (UInt16)e.faces.down.uv[2], (UInt16)e.faces.north.uv[2], (UInt16)e.faces.south.uv[2], (UInt16)e.faces.east.uv[2], (UInt16)e.faces.west.uv[2], }; UInt16[] v2 = new[] { (UInt16)e.faces.up.uv[1], (UInt16)e.faces.down.uv[3], (UInt16)e.faces.north.uv[3], (UInt16)e.faces.south.uv[3], (UInt16)e.faces.east.uv[3], (UInt16)e.faces.west.uv[3], }; var part = new Part { min = min, max = max, u1 = u2, v1 = v1, u2 = u1, v2 = v2, rotationOrigin = rotationOrigin, rotation = rotation, }; var anims = new List <CustomModelAnim>(); var partName = e.name.Replace(" ", ""); foreach (var attr in partName.SplitComma()) { float?a = null; float?b = null; float?c = null; float?d = null; var colonSplit = attr.Split(':'); var attrName = colonSplit[0]; if (colonSplit.Length >= 2) { var modifiers = colonSplit[1].Replace(" ", "").Split('|'); if (modifiers.Length > 0) { a = float.Parse(modifiers[0]); if (modifiers.Length > 1) { b = float.Parse(modifiers[1]); if (modifiers.Length > 2) { c = float.Parse(modifiers[2]); if (modifiers.Length > 3) { d = float.Parse(modifiers[3]); } } } } } if (PartNamesToAnim.TryGetValue(attrName, out PartNameToAnim toAnim)) { anims.AddRange(toAnim.ToAnim(attrName, a, b, c, d)); } else if (attrName.CaselessEq("leftidle")) { anims.Add(new CustomModelAnim { type = CustomModelAnimType.SinRotate, axis = CustomModelAnimAxis.X, a = ANIM_IDLE_XPERIOD, b = ANIM_IDLE_MAX, c = 0, d = 0, }); anims.Add(new CustomModelAnim { type = CustomModelAnimType.SinRotate, axis = CustomModelAnimAxis.Z, a = ANIM_IDLE_ZPERIOD, b = -ANIM_IDLE_MAX, c = 0.25f, d = 1, }); } else if (attrName.CaselessEq("rightidle")) { anims.Add(new CustomModelAnim { type = CustomModelAnimType.SinRotate, axis = CustomModelAnimAxis.X, a = ANIM_IDLE_XPERIOD, b = -ANIM_IDLE_MAX, c = 0, d = 0, }); anims.Add(new CustomModelAnim { type = CustomModelAnimType.SinRotate, axis = CustomModelAnimAxis.Z, a = ANIM_IDLE_ZPERIOD, b = ANIM_IDLE_MAX, c = 0.25f, d = 1, }); } else if (attrName.CaselessEq("fullbright")) { part.fullbright = true; } else if (attrName.CaselessEq("hand")) { part.firstPersonArm = true; } else if (attrName.CaselessEq("layer")) { part.layer = true; } else if (attrName.CaselessEq("humanleftarm")) { part.skinLeftArm = true; } else if (attrName.CaselessEq("humanrightarm")) { part.skinRightArm = true; } else if (attrName.CaselessEq("humanleftleg")) { part.skinLeftLeg = true; } else if (attrName.CaselessEq("humanrightleg")) { part.skinRightLeg = true; } } part.anims = anims.ToArray(); return(part); }