public bool FunctionExecute(Dynel self, Dynel caller, object target, object[] arguments) { Client cli = ((Character)self).Client; Quaternion q = new Quaternion(0, 1, 0, 0); AOCoord a = new AOCoord(); Int32 pf; if (target is Statels.Statel) { a.x = Int32.Parse((string)arguments[0]); a.y = Int32.Parse((string)arguments[1]); a.z = Int32.Parse((string)arguments[2]); pf = Int32.Parse((string)arguments[3]); } else { a.x = (Int32)arguments[0]; a.y = (Int32)arguments[1]; a.z = (Int32)arguments[2]; pf = (Int32)arguments[3]; } // Same playfield teleport sometimes has 0 for pf argument if (pf == 0) { pf = cli.Character.PlayField; } cli.Teleport(a, q, pf); return true; }
/// <summary> /// Calculate move vector /// </summary> /// <returns>Movevector</returns> private Vector3 calculateMoveVector() { double forwardSpeed; double strafeSpeed; Vector3 forwardMove; Vector3 strafeMove; if (!this.canMove()) { return(Vector3.Origin); } forwardSpeed = this.calculateForwardSpeed(); strafeSpeed = this.calculateStrafeSpeed(); if ((forwardSpeed == 0) && (strafeSpeed == 0)) { return(Vector3.Origin); } if (forwardSpeed != 0) { forwardMove = Quaternion.RotateVector3(this.RawHeading, Vector3.AxisZ); forwardMove.Magnitude = Math.Abs(forwardSpeed); if (forwardSpeed < 0) { forwardMove = -forwardMove; } } else { forwardMove = Vector3.Origin; } if (strafeSpeed != 0) { strafeMove = Quaternion.RotateVector3(this.RawHeading, Vector3.AxisX); strafeMove.Magnitude = Math.Abs(strafeSpeed); if (strafeSpeed < 0) { strafeMove = -strafeMove; } } else { strafeMove = Vector3.Origin; } return(forwardMove + strafeMove); }
public VendingMachine(int _id, int _playfield, int template) { ID = _id; PlayField = _playfield; // Vending machines = type 51035 Type = 51035; ourType = 3; rawCoord = new AOCoord(); rawHeading = new Quaternion(0, 0, 0, 0); TemplateID = template; dontdotimers = true; Stats = new Character_Stats(this); if (ID != 0) { LoadTemplate(TemplateID); // All shops will have level 1 } dontdotimers = false; }
public CoordHeading FindEntry(int Playfield, int DestinationNumber) { CoordHeading ret = new CoordHeading(); ret.Coordinates.x = -1; foreach (WallCollision.Line l in WallCollision.Destinations[Playfield].Playfield.Lines) { if (l.ID != DestinationNumber) { continue; } ret.Coordinates.x = (l.LineStartPoint.X + l.LineEndPoint.X) / 2; ret.Coordinates.y = (l.LineStartPoint.Y + l.LineEndPoint.Y) / 2; ret.Coordinates.z = (l.LineStartPoint.Z + l.LineEndPoint.Z) / 2; // TODO: Calculate the right Quaternion for the heading... // - Algorithman Quaternion q = new Quaternion( new Vector3( (l.LineEndPoint.X - l.LineStartPoint.X), 1, -(l.LineEndPoint.Z - l.LineStartPoint.Z))); ret.Heading.x = q.x; ret.Heading.y = q.y; ret.Heading.z = q.z; ret.Heading.w = q.w; } return ret; }
// public AOKnuBot KnuBot; // TODO: Create a proper class for KnuBot contents /// <summary> /// Create a Dynel /// </summary> /// <param name="id">Unique ID</param> /// <param name="playfield">on Playfield</param> public Dynel(int id, int playfield) { lock (this) { this.Id = id; this.Type = 0; // empty Dynel has no type, subclasses are setting it this.OurType = 0; // our type to identify the subclasses this.PlayField = playfield; this.RawCoord = new AOCoord(); this.RawHeading = new Quaternion(0, 0, 0, 0); this.events = new List<AOEvents>(); this.actions = new List<AOActions>(); this.Textures = new List<AOTextures>(); this.SocialTab = new Dictionary<int, int>(); } }
public void Execute(Client cli, Statel parent, int Eventnumber) { switch (FunctionNumber) { // Hit case 53002: { int statnum = Int32.Parse(Arguments.ElementAt(0)); int min = Int32.Parse(Arguments.ElementAt(1)); int max = Int32.Parse(Arguments.ElementAt(2)); if (min > max) { min = max; max = Int32.Parse(Arguments.ElementAt(1)); } Random rnd = new Random(); cli.Character.Stats.Set(statnum, (uint)(cli.Character.Stats.Get(statnum) + rnd.Next(min, max))); break; } // Lineteleport // case 53059: { #if DEBUG Console.WriteLine("Function 53059 (LineTeleport)"); Console.WriteLine("Object: " + parent.Type + ":" + parent.Instance); #endif uint arg2 = UInt32.Parse(Arguments.ElementAt(1)); // Linesegment and playfield (lower word) arg2 = arg2 >> 16; int to_pf = Int32.Parse(Arguments.ElementAt(2)); coordheading a = FindEntry(to_pf, (Int32)arg2); if (a.Coordinates.x != -1) { cli.Teleport(a.Coordinates, a.Heading, to_pf); break; } break; } case 53082: // Teleport Proxy { Identity pfinstance = new Identity(); pfinstance.Type = Int32.Parse(Arguments.ElementAt(0)); pfinstance.Instance = Int32.Parse(Arguments.ElementAt(1)); Identity id2 = new Identity(); id2.Type = Int32.Parse(Arguments.ElementAt(2)); id2.Instance = Int32.Parse(Arguments.ElementAt(3)); Identity id3 = new Identity(); id3.Type = Int32.Parse(Arguments.ElementAt(4)); id3.Instance = Int32.Parse(Arguments.ElementAt(5)); SqlWrapper ms = new SqlWrapper(); DataTable dt = ms.ReadDT("SELECT * from proxydestinations WHERE playfield=" + pfinstance.Instance); if (dt.Rows.Count == 0) { #if DEBUG cli.SendChatText("No Destination found for playfield " + pfinstance.Instance); cli.SendChatText("Statel " + parent.Type.ToString() + ":" + parent.Instance.ToString() + " handling " + Eventnumber.ToString() + " Function " + FunctionNumber.ToString() + " " + cli.Character.Coordinates.ToString()); foreach (string arg in Arguments) { cli.SendChatText("Argument: " + arg); } #endif } else { AOCoord a = new AOCoord(); a.x= (Single)dt.Rows[0][1]; a.y= (Single)dt.Rows[0][2]; a.z = (Single)dt.Rows[0][3]; Quaternion q = new Quaternion(0, 0, 0, 0); q.x = (Single)dt.Rows[0][4]; q.y = (Single)dt.Rows[0][5]; q.z = (Single)dt.Rows[0][6]; q.w = (Single)dt.Rows[0][7]; cli.TeleportProxy(a, q, pfinstance.Instance, pfinstance, 1, (Int32)parent.Instance, id2, id3); } break; } case 53092: // Bank { Packets.BankOpen.Send(cli); break; } case 53083: // Teleport Proxy 2 { Identity pfinstance = new Identity(); pfinstance.Type = Int32.Parse(Arguments.ElementAt(0)); pfinstance.Instance = Int32.Parse(Arguments.ElementAt(1)); int gs = 1; int sg = 0; Identity R = new Identity(); R.Type = Int32.Parse(Arguments.ElementAt(2)); R.Instance = Int32.Parse(Arguments.ElementAt(3)); Identity dest = new Identity(); dest.Type = Int32.Parse(Arguments.ElementAt(4)); dest.Instance = Int32.Parse(Arguments.ElementAt(5)); int to_pf = (Int32)((UInt32)(dest.Instance & 0xffff)); int arg2 = (Int32)((UInt32)(dest.Instance >> 16)); coordheading a = FindEntry(to_pf, arg2); if (a.Coordinates.x != -1) { cli.TeleportProxy(a.Coordinates, a.Heading, to_pf, pfinstance, gs, sg, R, dest); break; } break; } // Teleport case 53016: { Quaternion q = new Quaternion(0, 1, 0, 0); AOCoord a = new AOCoord(); a.x = Int32.Parse(Arguments.ElementAt(0)); a.y = Int32.Parse(Arguments.ElementAt(1)); a.z = Int32.Parse(Arguments.ElementAt(2)); cli.Teleport(a, q, Int32.Parse(Arguments.ElementAt(3))); break; } case 53044: { string text = Arguments.ElementAt(0); Packets.SystemText.Send(cli, text, 0); break; } default: { #if DEBUG cli.SendChatText("Statel " + parent.Type.ToString() + ":" + parent.Instance.ToString() + " handling " + Eventnumber.ToString() + " Function " + FunctionNumber.ToString() + " " + cli.Character.Coordinates.ToString()); foreach (string arg in Arguments) { cli.SendChatText("Argument: " + arg); } #endif break; } } }
/// <summary> /// /// </summary> /// <param name="destination"></param> /// <param name="heading"></param> /// <param name="playfield"></param> /// <returns></returns> public bool Teleport(AOCoord destination, Quaternion heading, int playfield) { PacketWriter writer = new PacketWriter(); // header starts writer.PushByte(0xDF); writer.PushByte(0xDF); writer.PushShort(10); writer.PushShort(1); writer.PushShort(0); writer.PushInt(3086); writer.PushInt(Character.ID); writer.PushInt(0x43197D22); writer.PushIdentity(50000, Character.ID); writer.PushByte(0); // Header ends writer.PushCoord(destination); writer.PushQuat(heading); writer.PushByte(97); writer.PushIdentity(51100, playfield); writer.PushInt(0); writer.PushInt(0); writer.PushIdentity(40016, playfield); writer.PushInt(0); writer.PushInt(0); writer.PushIdentity(100001, playfield); writer.PushInt(0); writer.PushInt(0); writer.PushInt(0); byte[] tpreply = writer.Finish(); Misc.Announce.Playfield(this.Character.PlayField, ref tpreply); Character.stopMovement(); Character.rawCoord = destination; Character.rawHeading = heading; Character.PlayField = playfield; Character.Purge(); // Purge character information to DB before client reconnect IPAddress tempIP; if (IPAddress.TryParse(ConfigReadWrite.Instance.CurrentConfig.ZoneIP, out tempIP) == false) { IPHostEntry zoneHost = Dns.GetHostEntry(ConfigReadWrite.Instance.CurrentConfig.ZoneIP); foreach (IPAddress ip in zoneHost.AddressList) { if (ip.AddressFamily == AddressFamily.InterNetwork) { tempIP = ip; break; } } } int zoneIP = IPAddress.HostToNetworkOrder(BitConverter.ToInt32(tempIP.GetAddressBytes(), 0)); short zonePort = Convert.ToInt16(ConfigReadWrite.Instance.CurrentConfig.ZonePort); Thread.Sleep(1000); PacketWriter writer2 = new PacketWriter(); writer2.PushByte(0xDF); writer2.PushByte(0xDF); writer2.PushShort(1); writer2.PushShort(1); writer2.PushShort(0); writer2.PushInt(3086); writer2.PushInt(Character.ID); writer2.PushInt(60); writer2.PushInt(zoneIP); writer2.PushShort(zonePort); byte[] connect = writer2.Finish(); SendCompressed(connect); return true; }
public static void UpdateDoorHeading(Client cli) { SqlWrapper ms = new SqlWrapper(); Doors door = DoorinRange(cli.Character.PlayField, cli.Character.Coordinates, 4.0f); if (door == null) { cli.SendChatText("No door in range to align"); return; } cli.SendChatText( string.Format("Door {0} Heading before: {1} {2} {3} {4}", door.ID, door.hX, door.hY, door.hZ, door.hW)); AOCoord a = new AOCoord { x = cli.Character.Coordinates.x - door.Coordinates.x, y = cli.Character.Coordinates.y - door.Coordinates.y, z = cli.Character.Coordinates.z - door.Coordinates.z }; Quaternion q = new Quaternion(a.x, a.y, a.z, 0); cli.SendChatText(string.Format("Door {0} Heading now: {1} {2} {3} {4}", door.ID, q.x, q.y, q.z, q.w)); ms.SqlUpdate( "UPDATE doors SET HX=" + String.Format(CultureInfo.InvariantCulture, "'{0}'", q.x) + ", HY=" + String.Format(CultureInfo.InvariantCulture, "'{0}'", q.y) + ", HZ=" + String.Format(CultureInfo.InvariantCulture, "'{0}'", q.z) + ", HW=" + String.Format(CultureInfo.InvariantCulture, "'{0}'", q.w) + " WHERE ID=" + door.ID + ";"); door.hX = (float)q.x; door.hY = (float)q.y; door.hZ = (float)q.z; door.hW = (float)q.w; }
// Create Quat from Vec3 /// <summary> /// Fill this info in /// </summary> /// <param name="vDirection"> /// </param> /// <returns> /// Fill this info in /// </returns> public Quaternion GenerateRotationFromDirectionVector(Vector3 vDirection) { // Step 1. Setup basis vectors describing the rotation given the input vector and assuming an initial up direction of (0, 1, 0) Vector3 vUp = new Vector3(0, 1.0f, 0.0f); // Y Up vector Vector3 vRight = Vector3.Cross(vUp, vDirection); // The perpendicular vector to Up and Direction vUp = Vector3.Cross(vDirection, vRight); // The actual up vector given the direction and the right vector // Step 2. Put the three vectors into the matrix to bulid a basis rotation matrix // This step isnt necessary, but im adding it because often you would want to convert from matricies to quaternions instead of vectors to quaternions // If you want to skip this step, you can use the vector values directly in the quaternion setup below Matrix mBasis = new DenseMatrix(4, 4); mBasis.SetRow(0, new[] { (float)vRight.x, (float)vRight.y, (float)vRight.z, 0.0f }); mBasis.SetRow(1, new[] { (float)vUp.x, (float)vUp.y, (float)vUp.z, 0.0f }); mBasis.SetRow(2, new[] { (float)vDirection.x, (float)vDirection.y, (float)vDirection.z, 0.0f }); mBasis.SetRow(3, new[] { 0.0f, 0.0f, 0.0f, 1.0f }); // Step 3. Build a quaternion from the matrix double dfWScale = Math.Sqrt(1.0f + mBasis.At(0, 0) + mBasis.At(1, 1) + mBasis.At(2, 2)) / 2.0f * 4.0; if (dfWScale == 0.0) { Quaternion q = new Quaternion(0, 1, 0, 0); return q; } Quaternion qrot = new Quaternion( (float)((mBasis.At(3, 2) - mBasis.At(2, 3)) / dfWScale), (float)((mBasis.At(0, 2) - mBasis.At(2, 0)) / dfWScale), (float)((mBasis.At(1, 0) - mBasis.At(0, 1)) / dfWScale), (float)Math.Sqrt(1.0f + mBasis.At(0, 0) + mBasis.At(1, 1) + mBasis.At(2, 2)) / 2.0f); return qrot; }
/// <summary> /// Return a Vector representation of a Quaternion (w is dropped) /// </summary> /// <param name="q1"> /// Quaternion /// </param> /// <returns> /// </returns> public static Vector3 VectorRepresentation(Quaternion q1) { return new Vector3(q1.x, q1.y, q1.z); }
/// <summary> /// Return a Vector rotated around the Quaternion /// </summary> /// <param name="q1"> /// Quaternion /// </param> /// <param name="v2"> /// Vector /// </param> /// <returns> /// </returns> public static Vector3 RotateVector3(Quaternion q1, Vector3 v2) { Quaternion QuatVect = new Quaternion(v2.x, v2.y, v2.z, 0); Quaternion QuatNorm = q1.Normalize(); Quaternion Result = Hamilton(Hamilton(QuatNorm, QuatVect), QuatNorm.Conjugate()); return new Vector3(Result.x, Result.y, Result.z); }
/// <summary> /// Return a Normalized Quaternion /// </summary> /// <param name="q1"> /// Quaternion /// </param> /// <returns> /// </returns> public static Quaternion Normalize(Quaternion q1) { double mag = q1.magnitude; return new Quaternion(q1.x / mag, q1.y / mag, q1.z / mag, q1.w / mag); }
/// <summary> /// Returns the Hamilton Product of two Quaternions /// </summary> /// <param name="vLeft"> /// Quaternion 1 /// </param> /// <param name="vRight"> /// Quaternion 2 /// </param> /// <returns> /// </returns> public static Quaternion Hamilton(Quaternion vLeft, Quaternion vRight) { double w = (vLeft.w * vRight.w) - (vLeft.x * vRight.x) - (vLeft.y * vRight.y) - (vLeft.z * vRight.z); double x = (vLeft.w * vRight.x) + (vLeft.x * vRight.w) + (vLeft.y * vRight.z) - (vLeft.z * vRight.y); double y = (vLeft.w * vRight.y) - (vLeft.x * vRight.z) + (vLeft.y * vRight.w) + (vLeft.z * vRight.x); double z = (vLeft.w * vRight.z) + (vLeft.x * vRight.y) - (vLeft.y * vRight.x) + (vLeft.z * vRight.w); return new Quaternion(x, y, z, w); }
/// <summary> /// Return the Conjugate of the Quaternion /// </summary> /// <param name="q1"> /// Quaternion /// </param> /// <returns> /// </returns> public static Quaternion Conjugate(Quaternion q1) { return new Quaternion(-q1.x, -q1.y, -q1.z, q1.w); }
/// <summary> /// /// </summary> /// <param name="destination"></param> /// <param name="heading"></param> /// <param name="playfield"></param> /// <returns></returns> public bool TeleportProxy( AOCoord destination, Quaternion heading, int playfield, Identity pfinstance, int GS, int SG, Identity R, Identity dest) { PacketWriter writer = new PacketWriter(); // header starts writer.PushByte(0xDF); writer.PushByte(0xDF); writer.PushShort(10); writer.PushShort(1); writer.PushShort(0); writer.PushInt(3086); writer.PushInt(this.Character.Id); writer.PushInt(0x43197D22); writer.PushIdentity(50000, this.Character.Id); writer.PushByte(0); // Header ends writer.PushCoord(this.Character.RawCoord); writer.PushQuat(this.Character.RawHeading); writer.PushByte(97); writer.PushIdentity(pfinstance.Type, pfinstance.Instance); writer.PushInt(GS); writer.PushInt(SG); writer.PushIdentity(40016, playfield); // Dont know for sure if its correct to only transfer the playfield here writer.PushInt(0); writer.PushInt(0); writer.PushIdentity(dest.Type, dest.Instance); writer.PushInt(0); byte[] tpreply = writer.Finish(); this.Character.DoNotDoTimers = true; Despawn.DespawnPacket(this.Character.Id); this.SendCompressed(tpreply); this.Character.DoNotDoTimers = true; this.Character.Stats.LastConcretePlayfieldInstance.Value = this.Character.PlayField; this.Character.Stats.ExtenalDoorInstance.Value = SG; this.Character.StopMovement(); this.Character.RawCoord = destination; this.Character.RawHeading = heading; this.Character.PlayField = playfield; this.Character.Resource = 0x3c000; this.Character.Purge(); // Purge character information to DB before client reconnect IPAddress tempIP; if (IPAddress.TryParse(Config.Instance.CurrentConfig.ZoneIP, out tempIP) == false) { IPHostEntry zoneHost = Dns.GetHostEntry(Config.Instance.CurrentConfig.ZoneIP); foreach (IPAddress ip in zoneHost.AddressList) { if (ip.AddressFamily == AddressFamily.InterNetwork) { tempIP = ip; break; } } } int zoneIP = IPAddress.HostToNetworkOrder(BitConverter.ToInt32(tempIP.GetAddressBytes(), 0)); short zonePort = Convert.ToInt16(Config.Instance.CurrentConfig.ZonePort); Thread.Sleep(1000); PacketWriter writer2 = new PacketWriter(); writer2.PushByte(0xDF); writer2.PushByte(0xDF); writer2.PushShort(1); writer2.PushShort(1); writer2.PushShort(0); writer2.PushInt(3086); writer2.PushInt(this.Character.Id); writer2.PushInt(60); writer2.PushInt(zoneIP); writer2.PushShort(zonePort); byte[] connect = writer2.Finish(); this.SendCompressed(connect); return true; }
/// <summary> /// Returns the Hamilton Product of two Quaternions /// </summary> /// <param name="vRight"> /// Other Quaternion /// </param> /// <returns> /// </returns> public Quaternion Hamilton(Quaternion vRight) { return Hamilton(this, vRight); }
public bool PushQuat(Quaternion _quat) { PushFloat(_quat.xf); PushFloat(_quat.yf); PushFloat(_quat.zf); PushFloat(_quat.wf); return true; }
/// <summary> /// </summary> /// <param name="message"> /// </param> /// <param name="client"> /// </param> public static void Read(CharDCMoveMessage message, Client client) { byte moveType = message.MoveType; var heading = new Quaternion(message.Heading.X, message.Heading.Y, message.Heading.Z, message.Heading.W); var coordinates = new AOCoord(message.Coordinates); // TODO: Find out what these (tmpInt) are and name them int tmpInt1 = message.Unknown1; int tmpInt2 = message.Unknown2; int tmpInt3 = message.Unknown3; /* if (!client.Character.DoNotDoTimers) { var teleportPlayfield = WallCollision.WallCollisionCheck( coordinates.x, coordinates.z, client.Character.PlayField); if (teleportPlayfield.ZoneToPlayfield >= 1) { var coordHeading = WallCollision.GetCoord( teleportPlayfield, coordinates.x, coordinates.z, coordinates); if (teleportPlayfield.Flags != 1337 && client.Character.PlayField != 152 || Math.Abs(client.Character.Coordinates.y - teleportPlayfield.Y) <= 2 || teleportPlayfield.Flags == 1337 && Math.Abs(client.Character.Coordinates.y - teleportPlayfield.Y) <= 6) { client.Teleport( coordHeading.Coordinates, coordHeading.Heading, teleportPlayfield.ZoneToPlayfield); Program.zoneServer.Clients.Remove(client); } return; } if (client.Character.Stats.LastConcretePlayfieldInstance.Value != 0) { var correspondingDoor = DoorHandler.DoorinRange( client.Character.PlayField, client.Character.Coordinates, 1.0f); if (correspondingDoor != null) { correspondingDoor = DoorHandler.FindCorrespondingDoor(correspondingDoor, client.Character); client.Character.Stats.LastConcretePlayfieldInstance.Value = 0; var aoc = correspondingDoor.Coordinates; aoc.x += correspondingDoor.hX * 3; aoc.y += correspondingDoor.hY * 3; aoc.z += correspondingDoor.hZ * 3; client.Teleport(aoc, client.Character.Heading, correspondingDoor.playfield); Program.zoneServer.Clients.Remove(client); return; } } } */ client.Character.RawCoordinates = coordinates.coordinate; client.Character.RawHeading = heading; client.Character.UpdateMoveType(moveType); /* Start NV Heading Testing Code * Yaw: 0 to 360 Degrees (North turning clockwise to a complete revolution) * Roll: Not sure, but is always 0 cause we can't roll in AO * Pitch: 90 to -90 Degrees (90 is nose in the air, 0 is level, -90 is nose to the ground) */ /* Comment this line with a '//' to enable heading testing client.SendChatText("Raw Headings: X: " + client.Character.heading.x + " Y: " + client.Character.heading.y + " Z:" + client.Character.heading.z); client.SendChatText("Yaw: " + Math.Round(180 * client.Character.heading.yaw / Math.PI) + " Degrees"); client.SendChatText("Roll: " + Math.Round(180 * client.Character.heading.roll / Math.PI) + " Degrees"); client.SendChatText("Pitch: " + Math.Round(180 * client.Character.heading.pitch / Math.PI) + " Degrees"); /* End NV Heading testing code */ /* start of packet */ var reply = new CharDCMoveMessage { Identity = client.Character.Identity, Unknown = 0x00, MoveType = moveType, Heading = new SmokeLounge.AOtomation.Messaging.GameData.Quaternion { X = heading .xf, Y = heading .yf, Z = heading .zf, W = heading .wf }, Coordinates = new Vector3 { X = coordinates.x, Y = coordinates.y, Z = coordinates.z }, Unknown1 = tmpInt1, Unknown2 = tmpInt2, Unknown3 = tmpInt3 }; client.Playfield.Publish(new IMSendAOtMessageToPlayfield { Body = reply }); // TODO: rewrite statelscheck /* if (Statels.StatelppfonEnter.ContainsKey(client.Character.PlayField)) { foreach (var s in Statels.StatelppfonEnter[client.Character.PlayField]) { if (s.onEnter(client)) { return; } if (s.onTargetinVicinity(client)) { return; } } } */ }