public static Character SpawnMobFromTemplate( string hash, Identity playfieldIdentity, Coordinate coord, Quaternion heading, IController controller, int desiredLevel = -1) { Character mobCharacter = null; DBMobTemplate mob = MobTemplateDao.Instance.GetMobTemplateByHash(hash); if (mob != null) { int level = desiredLevel; if (level == -1) { // Get random inside level range Random rnd = new Random(); level = mob.MinLvl + rnd.Next(mob.MaxLvl - mob.MinLvl); } else { // Put it inside level range level = (level < mob.MinLvl ? mob.MinLvl : level); level = level > mob.MaxLvl ? mob.MaxLvl : level; } mobCharacter = CreateMob(mob, playfieldIdentity, coord, heading, controller, level); } return(mobCharacter); }
/// <summary> /// </summary> /// <param name="moveType"> /// </param> /// <param name="newCoordinates"> /// </param> /// <param name="heading"> /// </param> /// <returns> /// </returns> /// <exception cref="NotImplementedException"> /// </exception> public bool Move(int moveType, Coordinate newCoordinates, Quaternion heading) { // Procedure: // 1. Check if new coordinates are plausible (in range of runspeed since last update) // 2. Set coordinates & heading // Is this correct? Shouldnt the client input be compared to the prediction and then be overridden to prevent teleportation exploits? // - Algorithman // give it a bit uncertainty (2.0f) LogUtil.Debug( DebugInfoDetail.Movement, newCoordinates.ToString() + "<->" + this.Character.Coordinates().ToString()); // if (newCoordinates.Distance2D(this.Character.Coordinates) < 2.0f) { this.Character.SetCoordinates(newCoordinates, heading); this.Character.UpdateMoveType((byte)moveType); } /* * else * { * this.Character.StopMovement(); * } */ return(true); }
public void StartPatrolling() { Waypoint next = this.FindNextWaypoint(); // If a suitable waypoint is found if (next != null) { if (next.Running) { this.Run(); } else { this.Walk(); } this.followCoordinates = next.Position; Vector3 temp = this.Character.Coordinates().coordinate - next.Position; temp.y = 0; this.Character.Heading = (Quaternion)Quaternion.GenerateRotationFromDirectionVector(temp).Normalize(); LogUtil.Debug(DebugInfoDetail.Movement, "Direction: " + this.Character.Heading.ToString()); FollowTargetMessageHandler.Default.Send( this.Character, this.Character.Coordinates().coordinate, next.Position); this.StartMovement(); LogUtil.Debug(DebugInfoDetail.Movement, "Walking to: " + this.followCoordinates); } }
public void MoveTo(SmokeLounge.AOtomation.Messaging.GameData.Vector3 destination) { FollowTargetMessageHandler.Default.Send(this.Character, this.Character.RawCoordinates, destination); Vector3 dest = destination; Vector3 start = this.Character.RawCoordinates; dest = start - dest; dest = dest.Normalize(); this.Character.Heading = (Quaternion)Quaternion.GenerateRotationFromDirectionVector(dest); this.Run(); Coordinate c = new Coordinate(destination); this.followCoordinates = c.coordinate; /*bool arrived = false; * double lastDistance = double.MaxValue; * while (!arrived) * { * Coordinate temp = this.Character.Coordinates; * double distance = this.Character.Coordinates.Distance2D(c); * arrived = (distance < 0.2f) || (lastDistance < distance); * lastDistance = distance; * // LogUtil.Debug(DebugInfoDetail.Movement,"Moving..."); * Thread.Sleep(100); * } * LogUtil.Debug(DebugInfoDetail.Movement, "Arrived at "+this.Character.Coordinates.ToString()); * this.StopMovement();*/ }
public void DoFollow() { Coordinate sourceCoord = this.Character.Coordinates(); Vector3 targetPosition = this.followCoordinates; if (!this.followIdentity.Equals(Identity.None)) { ICharacter targetChar = Pool.Instance.GetObject <ICharacter>( this.Character.Playfield.Identity, this.followIdentity); if (targetChar == null) { // If target does not longer exist (death or zone or logoff) then stop following this.followIdentity = Identity.None; this.followCoordinates = new Vector3(); return; } targetPosition = targetChar.Coordinates().coordinate; } // Do we have coordinates to follow? if (targetPosition.Distance2D(new Vector3()) < 0.01f) { return; } // /!\ If target flies away, there has to be some kind of adjustment Vector3 start = sourceCoord.coordinate; Vector3 dest = targetPosition; // Check if we have arrived if (start.Distance2D(dest) < 0.3f) { this.StopMovement(); this.Character.RawCoordinates = dest; FollowTargetMessageHandler.Default.Send(this.Character, dest); this.followCoordinates = new Vector3(); return; } LogUtil.Debug(DebugInfoDetail.Movement, "Distance to target: " + start.Distance2D(dest).ToString()); // If target moved or first call, then issue a new follow if (targetPosition.Distance2D(this.followCoordinates) > 2.0f) { this.StopMovement(); this.Character.Coordinates(start); FollowTargetMessageHandler.Default.Send(this.Character, start); Vector3 temp = start - dest; temp.y = 0; this.Character.Heading = (Quaternion)Quaternion.GenerateRotationFromDirectionVector(temp); this.followCoordinates = dest; FollowTargetMessageHandler.Default.Send(this.Character, start, dest); this.StartMovement(); } }
public override bool Execute( INamedEntity self, IEntity caller, IInstancedEntity target, MessagePackObject[] arguments) { ICharacter character = (ICharacter)self; int statelId = (int)((uint)0xC0000000 | arguments[1].AsInt32() | (arguments[2].AsInt32() << 16)); character.Stats[StatIds.externaldoorinstance].BaseValue = 0; character.Stats[StatIds.externalplayfieldinstance].BaseValue = 0; if (arguments[1].AsInt32() > 0) { StatelData sd = PlayfieldLoader.PFData[arguments[1].AsInt32()].GetDoor(statelId); if (sd == null) { throw new Exception( "Statel " + arguments[3].AsInt32().ToString("X") + " not found? Check the rdb dammit"); } Vector3 v = new Vector3(sd.X, sd.Y, sd.Z); Quaternion q = new Quaternion(sd.HeadingX, sd.HeadingY, sd.HeadingZ, sd.HeadingW); Quaternion.Normalize(q); Vector3 n = (Vector3)q.RotateVector3(Vector3.AxisZ); v.x += n.x * 2.5; v.z += n.z * 2.5; character.Playfield.Teleport( (Dynel)character, new Coordinate(v), q, new Identity() { Type = (IdentityType)arguments[0].AsInt32(), Instance = arguments[1].AsInt32() }); } return(true); self.Stats[StatIds.externalplayfieldinstance].Value = 0; self.Stats[StatIds.externaldoorinstance].Value = 0; self.Playfield.Teleport( (Dynel)self, new Coordinate(100, 10, 100), ((ICharacter)self).Heading, new Identity() { Type = (IdentityType)arguments[0].AsInt32(), Instance = arguments[1].AsInt32() }); return(true); }
/// <summary> /// Calculate move vector /// </summary> /// <returns>Movevector</returns> private Vector.Vector3 calculateMoveVector() { double forwardSpeed; double strafeSpeed; Vector.Vector3 forwardMove; Vector.Vector3 strafeMove; if (!this.CanMove()) { return(Vector.Vector3.Origin); } forwardSpeed = this.calculateForwardSpeed(); strafeSpeed = this.calculateStrafeSpeed(); if ((forwardSpeed == 0) && (strafeSpeed == 0)) { return(Vector.Vector3.Origin); } if (forwardSpeed != 0) { forwardMove = (Vector.Vector3)Quaternion.RotateVector3(this.RawHeading, Vector.Vector3.AxisZ); forwardMove.Magnitude = Math.Abs(forwardSpeed); if (forwardSpeed < 0) { forwardMove = -forwardMove; } } else { forwardMove = Vector.Vector3.Origin; } if (strafeSpeed != 0) { strafeMove = (Vector.Vector3)Quaternion.RotateVector3(this.RawHeading, Vector.Vector3.AxisX); strafeMove.Magnitude = Math.Abs(strafeSpeed); if (strafeSpeed < 0) { strafeMove = -strafeMove; } } else { strafeMove = Vector.Vector3.Origin; } return(forwardMove + strafeMove); }
/// <summary> /// </summary> /// <param name="Self"> /// </param> /// <param name="Caller"> /// </param> /// <param name="Target"> /// </param> /// <param name="Arguments"> /// </param> /// <returns> /// </returns> public bool FunctionExecute( INamedEntity Self, INamedEntity Caller, IInstancedEntity Target, MessagePackObject[] Arguments) { // TODO: Use the arguments!!!!! Coordinate destination = new Coordinate(); IQuaternion heading = new Quaternion(0.0, 0.0, 0.0, 0.0); Identity playfield = new Identity(); ((Character)Self).Teleport(destination, heading, playfield); return(true); }
public bool Follow(Identity target) { this.followIdentity = target; ICharacter npc = Pool.Instance.GetObject <ICharacter>(this.Character.Playfield.Identity, target); if (npc != null) { Vector3 temp = npc.Coordinates().coordinate - this.Character.Coordinates().coordinate; temp.y = 0; this.Character.Heading = (Quaternion)Quaternion.GenerateRotationFromDirectionVector(temp).Normalize(); FollowTargetMessageHandler.Default.Send( this.Character, this.Character.Coordinates().coordinate, npc.Coordinates().coordinate); this.Run(); this.StartMovement(); } return(true); }
/// <summary> /// </summary> /// <param name="Self"> /// </param> /// <param name="Caller"> /// </param> /// <param name="Target"> /// </param> /// <param name="Arguments"> /// </param> /// <returns> /// </returns> public bool FunctionExecute( INamedEntity Self, IEntity Caller, IInstancedEntity Target, MessagePackObject[] Arguments) { // TODO: Use the arguments!!!!! Coordinate destination = new Coordinate(Arguments[0].AsInt32(), Arguments[1].AsInt32(), Arguments[2].AsInt32()); IQuaternion heading = new Quaternion(0.0, 0.0, 0.0, 0.0); Identity playfield = new Identity() { Type = IdentityType.Playfield, Instance = Arguments[3].AsInt32() }; if (playfield.Instance == 0) { playfield = Self.Playfield.Identity; } ((Character)Self).Teleport(destination, heading, playfield); return(true); }
public override bool Execute( INamedEntity self, IEntity caller, IInstancedEntity target, MessagePackObject[] arguments) { uint externalDoorInstance = self.Stats[StatIds.externaldoorinstance].BaseValue; int externalPlayfieldId = self.Stats[StatIds.externalplayfieldinstance].Value; StatelData door = PlayfieldLoader.PFData[externalPlayfieldId].Statels.FirstOrDefault( x => (uint)x.Identity.Instance == externalDoorInstance && (x.Identity.Type == IdentityType.Door /*|| x.Identity.Type==IdentityType.MissionEntrance*/)); if (door != null) { Vector3 v = new Vector3(door.X, door.Y, door.Z); Quaternion q = new Quaternion(door.HeadingX, door.HeadingY, door.HeadingZ, door.HeadingW); Quaternion.Normalize(q); Vector3 n = (Vector3)q.RotateVector3(Vector3.AxisZ); v.x += n.x * 2.5; v.z += n.z * 2.5; self.Playfield.Teleport( (Dynel)self, new Coordinate(v), q, new Identity() { Type = IdentityType.Playfield, Instance = externalPlayfieldId }); } return(door != null); }
internal Coordinate CalculatePredictedPosition() { if ((this.moveDirection == MoveDirections.None) && (this.strafeDirection == SpinOrStrafeDirections.None)) { return(new Coordinate(this.RawCoordinates)); } else if (this.spinDirection == SpinOrStrafeDirections.None) { Vector3 moveVector = this.CalculateMoveVector(); moveVector = moveVector * this.PredictionDuration.TotalSeconds; /*this.RawCoordinates = new Vector3() * { * x = this.RawCoordinates.X + moveVector.x, * y = this.RawCoordinates.Y + moveVector.y, * z = this.RawCoordinates.Z + moveVector.z * }; * * this.PredictionTime = DateTime.UtcNow;*/ Coordinate result = new Coordinate( new Vector3( this.RawCoordinates.X + moveVector.x, this.RawCoordinates.Y + moveVector.y, this.RawCoordinates.Z + moveVector.z)); LogUtil.Debug( DebugInfoDetail.Movement, moveVector.ToString().PadRight(40) + "/" + result.ToString() + "/"); return(result); } else { Vector3 moveVector; Vector3 positionFromCentreOfTurningCircle; double turnArcAngle; double y; double duration; duration = this.PredictionDuration.TotalSeconds; moveVector = this.CalculateMoveVector(); turnArcAngle = this.calculateTurnArcAngle(); // This is calculated seperately as height is unaffected by turning y = this.RawCoordinates.Y + (moveVector.y * duration); if (this.spinDirection == SpinOrStrafeDirections.Left) { positionFromCentreOfTurningCircle = new Vector3(moveVector.z, y, -moveVector.x); } else { positionFromCentreOfTurningCircle = new Vector3(-moveVector.z, y, moveVector.x); } return (new Coordinate( new Vector3(this.RawCoordinates.X, this.RawCoordinates.Y, this.RawCoordinates.Z) + (Vector3) Quaternion.RotateVector3( new Quaternion(Vector3.AxisY, turnArcAngle), positionFromCentreOfTurningCircle) - positionFromCentreOfTurningCircle)); } }
public bool Move(int moveType, Coordinate newCoordinates, Quaternion heading) { throw new NotImplementedException(); }
private static Character CreateMob( DBMobTemplate mob, Identity playfieldIdentity, Coordinate coord, Quaternion heading, IController controller, int level) { IPlayfield playfield = Pool.Instance.GetObject <IPlayfield>(Identity.None, playfieldIdentity); if (playfield != null) { int newInstanceId = Pool.Instance.GetFreeInstance <Character>(1000000, IdentityType.CanbeAffected); Identity newIdentity = new Identity() { Type = IdentityType.CanbeAffected, Instance = newInstanceId }; Character mobCharacter = new Character(playfield.Identity, newIdentity, controller); mobCharacter.Read(); mobCharacter.Coordinates(coord); mobCharacter.Playfield = Pool.Instance.GetObject <IPlayfield>(Identity.None, playfieldIdentity); mobCharacter.RawHeading = new Quaternion(heading.xf, heading.yf, heading.zf, heading.wf); mobCharacter.Stats.SetBaseValueWithoutTriggering((int)StatIds.life, (uint)mob.Health); mobCharacter.Stats.SetBaseValueWithoutTriggering((int)StatIds.level, (uint)level); mobCharacter.Stats.SetBaseValueWithoutTriggering((int)StatIds.npcfamily, (uint)mob.NPCFamily); mobCharacter.Stats.SetBaseValueWithoutTriggering((int)StatIds.side, (uint)mob.Side); mobCharacter.Stats.SetBaseValueWithoutTriggering((int)StatIds.fatness, (uint)mob.Fatness); mobCharacter.Stats.SetBaseValueWithoutTriggering((int)StatIds.breed, (uint)mob.Breed); mobCharacter.Stats.SetBaseValueWithoutTriggering((int)StatIds.sex, (uint)mob.Sex); mobCharacter.Stats.SetBaseValueWithoutTriggering((int)StatIds.race, (uint)mob.Race); mobCharacter.Stats.SetBaseValueWithoutTriggering((int)StatIds.flags, (uint)mob.Flags); mobCharacter.Stats.SetBaseValueWithoutTriggering((int)StatIds.monsterdata, (uint)mob.MonsterData); mobCharacter.Stats.SetBaseValueWithoutTriggering((int)StatIds.monsterscale, (uint)mob.MonsterScale); mobCharacter.Stats.SetBaseValueWithoutTriggering((int)StatIds.profession, 15); mobCharacter.Stats.SetBaseValueWithoutTriggering((int)StatIds.accountflags, 0); mobCharacter.Stats.SetBaseValueWithoutTriggering((int)StatIds.expansion, 0); mobCharacter.Stats.SetBaseValueWithoutTriggering((int)StatIds.runspeed, 513); mobCharacter.Stats[StatIds.headmesh].BaseValue = (uint)mob.HeadMesh; mobCharacter.Stats.SetBaseValueWithoutTriggering((int)StatIds.losheight, 15); mobCharacter.Stats.SetBaseValueWithoutTriggering((int)StatIds.visualprofession, 15); /* * // For testing only, blue trousers and a helmet * IItem trousers = new Item(1, ItemLoader.ItemList[27350].GetLowId(1),ItemLoader.ItemList[27350].GetLowId(1)); * IItem helmet = new Item(1, ItemLoader.ItemList[85534].GetLowId(1), ItemLoader.ItemList[85534].GetHighId(1)); * mobCharacter.BaseInventory.Pages[(int)IdentityType.ArmorPage].Add((int)ArmorSlots.Legs + mobCharacter.BaseInventory.Pages[(int)IdentityType.ArmorPage].FirstSlotNumber, trousers); * mobCharacter.BaseInventory.Pages[(int)IdentityType.ArmorPage].Add((int)ArmorSlots.Head + mobCharacter.BaseInventory.Pages[(int)IdentityType.ArmorPage].FirstSlotNumber, helmet); */ // Set the MeshLayers correctly ( Head mesh!! ) /!\ // TODO: This needs to be in StatHeadmesh.cs (somehow) mobCharacter.MeshLayer.AddMesh(0, mob.HeadMesh, 0, 4); mobCharacter.SocialMeshLayer.AddMesh(0, mob.HeadMesh, 0, 4); mobCharacter.Name = mob.Name; mobCharacter.FirstName = ""; mobCharacter.LastName = ""; controller.Character = mobCharacter; return(mobCharacter); } return(null); }
/// <summary> /// </summary> /// <param name="Self"> /// </param> /// <param name="Caller"> /// </param> /// <param name="Target"> /// </param> /// <param name="Arguments"> /// </param> /// <returns> /// </returns> public bool FunctionExecute( INamedEntity Self, INamedEntity Caller, IInstancedEntity Target, MessagePackObject[] Arguments) { // TODO: Use the arguments!!!!! Coordinate destination = new Coordinate(); IQuaternion heading = new Quaternion(0.0, 0.0, 0.0, 0.0); Identity playfield = new Identity(); ((Character)Self).Teleport(destination, heading, playfield); return true; }
/// <summary> /// </summary> /// <param name="message"> /// </param> /// <param name="client"> /// </param> public static void Read(CharDCMoveMessage message, ZoneClient client) { byte moveType = message.MoveType; var heading = new Quaternion(message.Heading.X, message.Heading.Y, message.Heading.Z, message.Heading.W); Coordinate coordinates = new Coordinate(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; } } } */ // Is this correct? Shouldnt the client input be compared to the prediction and then be overridden to prevent teleportation exploits? // - Algorithman 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 IMSendAOtomationMessageToPlayfield { 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; } } } */ }
/// <summary> /// </summary> /// <param name="newCoordinates"> /// </param> /// <param name="heading"> /// </param> public void SetCoordinates(Coordinate newCoordinates, Quaternion heading) { this.Coordinates(newCoordinates); this.Heading = heading; this.PredictionTime = DateTime.UtcNow; }
/// <summary> /// </summary> /// <param name="moveType"> /// </param> /// <param name="newCoordinates"> /// </param> /// <param name="heading"> /// </param> /// <returns> /// </returns> /// <exception cref="NotImplementedException"> /// </exception> public bool Move(int moveType, Coordinate newCoordinates, Quaternion heading) { // Procedure: // 1. Check if new coordinates are plausible (in range of runspeed since last update) // 2. Set coordinates & heading // Is this correct? Shouldnt the client input be compared to the prediction and then be overridden to prevent teleportation exploits? // - Algorithman // give it a bit uncertainty (2.0f) LogUtil.Debug( DebugInfoDetail.Movement, newCoordinates.ToString() + "<->" + this.Character.Coordinates().ToString()); // if (newCoordinates.Distance2D(this.Character.Coordinates) < 2.0f) { this.Character.SetCoordinates(newCoordinates, heading); this.Character.UpdateMoveType((byte)moveType); } /* else { this.Character.StopMovement(); } */ return true; }
private static Character CreateMob( DBMobTemplate mob, Identity playfieldIdentity, Coordinate coord, Quaternion heading, IController controller, int level) { IPlayfield playfield = Pool.Instance.GetObject<IPlayfield>(Identity.None, playfieldIdentity); if (playfield != null) { int newInstanceId = Pool.Instance.GetFreeInstance<Character>(1000000, IdentityType.CanbeAffected); Identity newIdentity = new Identity() { Type = IdentityType.CanbeAffected, Instance = newInstanceId }; Character mobCharacter = new Character(playfield.Identity, newIdentity, controller); mobCharacter.Read(); mobCharacter.Coordinates(coord); mobCharacter.Playfield = Pool.Instance.GetObject<IPlayfield>(Identity.None, playfieldIdentity); mobCharacter.RawHeading = new Quaternion(heading.xf, heading.yf, heading.zf, heading.wf); mobCharacter.Stats.SetBaseValueWithoutTriggering((int)StatIds.life, (uint)mob.Health); mobCharacter.Stats.SetBaseValueWithoutTriggering((int)StatIds.level, (uint)level); mobCharacter.Stats.SetBaseValueWithoutTriggering((int)StatIds.npcfamily, (uint)mob.NPCFamily); mobCharacter.Stats.SetBaseValueWithoutTriggering((int)StatIds.side, (uint)mob.Side); mobCharacter.Stats.SetBaseValueWithoutTriggering((int)StatIds.fatness, (uint)mob.Fatness); mobCharacter.Stats.SetBaseValueWithoutTriggering((int)StatIds.breed, (uint)mob.Breed); mobCharacter.Stats.SetBaseValueWithoutTriggering((int)StatIds.sex, (uint)mob.Sex); mobCharacter.Stats.SetBaseValueWithoutTriggering((int)StatIds.race, (uint)mob.Race); mobCharacter.Stats.SetBaseValueWithoutTriggering((int)StatIds.flags, (uint)mob.Flags); mobCharacter.Stats.SetBaseValueWithoutTriggering((int)StatIds.monsterdata, (uint)mob.MonsterData); mobCharacter.Stats.SetBaseValueWithoutTriggering((int)StatIds.monsterscale, (uint)mob.MonsterScale); mobCharacter.Stats.SetBaseValueWithoutTriggering((int)StatIds.profession, 15); mobCharacter.Stats.SetBaseValueWithoutTriggering((int)StatIds.accountflags, 0); mobCharacter.Stats.SetBaseValueWithoutTriggering((int)StatIds.expansion, 0); mobCharacter.Stats.SetBaseValueWithoutTriggering((int)StatIds.runspeed, 513); mobCharacter.Stats[StatIds.headmesh].BaseValue = (uint)mob.HeadMesh; mobCharacter.Stats.SetBaseValueWithoutTriggering((int)StatIds.losheight, 15); mobCharacter.Stats.SetBaseValueWithoutTriggering((int)StatIds.visualprofession, 15); /* // For testing only, blue trousers and a helmet IItem trousers = new Item(1, ItemLoader.ItemList[27350].GetLowId(1),ItemLoader.ItemList[27350].GetLowId(1)); IItem helmet = new Item(1, ItemLoader.ItemList[85534].GetLowId(1), ItemLoader.ItemList[85534].GetHighId(1)); mobCharacter.BaseInventory.Pages[(int)IdentityType.ArmorPage].Add((int)ArmorSlots.Legs + mobCharacter.BaseInventory.Pages[(int)IdentityType.ArmorPage].FirstSlotNumber, trousers); mobCharacter.BaseInventory.Pages[(int)IdentityType.ArmorPage].Add((int)ArmorSlots.Head + mobCharacter.BaseInventory.Pages[(int)IdentityType.ArmorPage].FirstSlotNumber, helmet); */ // Set the MeshLayers correctly ( Head mesh!! ) /!\ // TODO: This needs to be in StatHeadmesh.cs (somehow) mobCharacter.MeshLayer.AddMesh(0, mob.HeadMesh, 0, 4); mobCharacter.SocialMeshLayer.AddMesh(0, mob.HeadMesh, 0, 4); mobCharacter.Name = mob.Name; mobCharacter.FirstName = ""; mobCharacter.LastName = ""; controller.Character = mobCharacter; return mobCharacter; } return null; }
/// <summary> /// Return a Vector representation of a Quaternion (w is dropped) /// </summary> /// <param name="q1"> /// Quaternion /// </param> /// <returns> /// </returns> public static IVector3 VectorRepresentation(Quaternion q1) { return new Vector3(q1.x, q1.y, q1.z); }
public static Character SpawnMobFromTemplate( string hash, Identity playfieldIdentity, Coordinate coord, Quaternion heading, IController controller, int desiredLevel = -1) { Character mobCharacter = null; DBMobTemplate mob = MobTemplateDao.Instance.GetMobTemplateByHash(hash); if (mob != null) { int level = desiredLevel; if (level == -1) { // Get random inside level range Random rnd = new Random(); level = mob.MinLvl + rnd.Next(mob.MaxLvl - mob.MinLvl); } else { // Put it inside level range level = (level < mob.MinLvl ? mob.MinLvl : level); level = level > mob.MaxLvl ? mob.MaxLvl : level; } mobCharacter = CreateMob(mob, playfieldIdentity, coord, heading, controller, level); } return mobCharacter; }
/// <summary> /// Fill this info in /// </summary> /// <param name="vDirection"> /// </param> /// <returns> /// Fill this info in /// </returns> public static IQuaternion GenerateRotationFromDirectionVector(IVector3 vDirection) { // Step 1. Setup basis vectors describing the rotation given the input vector and assuming an initial up direction of (0, 1, 0) Vector3 vDirNormalized = Vector3.Normalize((Vector3)vDirection); Vector3 vUp = new Vector3(0, 1.0f, 0.0f); // Y Up vector Vector3 vRight = Vector3.Cross(vUp, vDirNormalized); // The perpendicular vector to Up and Direction vUp = Vector3.Cross(vDirNormalized, 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)vDirNormalized.x, (float)vDirNormalized.y, (float)vDirNormalized.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); var temp = qrot.w; qrot.w = qrot.y; qrot.y = temp; return qrot.Normalize(); }
/// <summary> /// Return a Vector rotated around the Quaternion /// </summary> /// <param name="q1"> /// Quaternion /// </param> /// <param name="v2"> /// Vector /// </param> /// <returns> /// </returns> public static IVector3 RotateVector3(IQuaternion q1, IVector3 v2) { Quaternion QuatVect = new Quaternion(v2.x, v2.y, v2.z, 0); Quaternion QuatNorm = (Quaternion)q1.Normalize(); Quaternion Result = Hamilton(Hamilton(QuatNorm, QuatVect), QuatNorm.Conjugate()); return new Vector3(Result.x, Result.y, Result.z); }
/// <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); }
public override bool Execute( INamedEntity self, IEntity caller, IInstancedEntity target, MessagePackObject[] arguments) { ICharacter character = (ICharacter)self; int statelId = (int)((uint)0xC0000000 | arguments[1].AsInt32() | (arguments[2].AsInt32() << 16)); character.Stats[StatIds.externaldoorinstance].BaseValue = 0; character.Stats[StatIds.externalplayfieldinstance].BaseValue = 0; if (arguments[1].AsInt32() > 0) { StatelData sd = PlayfieldLoader.PFData[arguments[1].AsInt32()].GetDoor(statelId); if (sd == null) { throw new Exception( "Statel " + arguments[3].AsInt32().ToString("X") + " not found? Check the rdb dammit"); } Vector3 v = new Vector3(sd.X, sd.Y, sd.Z); Quaternion q = new Quaternion(sd.HeadingX, sd.HeadingY, sd.HeadingZ, sd.HeadingW); Quaternion.Normalize(q); Vector3 n = (Vector3)q.RotateVector3(Vector3.AxisZ); v.x += n.x * 2.5; v.z += n.z * 2.5; character.Playfield.Teleport( (Dynel)character, new Coordinate(v), q, new Identity() { Type = (IdentityType)arguments[0].AsInt32(), Instance = arguments[1].AsInt32() }); } return true; self.Stats[StatIds.externalplayfieldinstance].Value = 0; self.Stats[StatIds.externaldoorinstance].Value = 0; self.Playfield.Teleport( (Dynel)self, new Coordinate(100, 10, 100), ((ICharacter)self).Heading, new Identity() { Type = (IdentityType)arguments[0].AsInt32(), Instance = arguments[1].AsInt32() }); return true; }
/// <summary> /// </summary> /// <param name="Self"> /// </param> /// <param name="Caller"> /// </param> /// <param name="Target"> /// </param> /// <param name="Arguments"> /// </param> /// <returns> /// </returns> public bool FunctionExecute( INamedEntity Self, IEntity Caller, IInstancedEntity Target, MessagePackObject[] Arguments) { // TODO: Use the arguments!!!!! Coordinate destination = new Coordinate(Arguments[0].AsInt32(), Arguments[1].AsInt32(), Arguments[2].AsInt32()); IQuaternion heading = new Quaternion(0.0, 0.0, 0.0, 0.0); Identity playfield = new Identity() { Type = IdentityType.Playfield, Instance = Arguments[3].AsInt32() }; if (playfield.Instance==0) { playfield = Self.Playfield.Identity; } ((Character)Self).Teleport(destination, heading, playfield); return true; }
public override bool Execute( INamedEntity self, IEntity caller, IInstancedEntity target, MessagePackObject[] arguments) { uint externalDoorInstance = self.Stats[StatIds.externaldoorinstance].BaseValue; int externalPlayfieldId = self.Stats[StatIds.externalplayfieldinstance].Value; StatelData door = PlayfieldLoader.PFData[externalPlayfieldId].Statels.FirstOrDefault( x => (uint)x.Identity.Instance == externalDoorInstance && (x.Identity.Type == IdentityType.Door /*|| x.Identity.Type==IdentityType.MissionEntrance*/)); if (door != null) { Vector3 v = new Vector3(door.X, door.Y, door.Z); Quaternion q = new Quaternion(door.HeadingX, door.HeadingY, door.HeadingZ, door.HeadingW); Quaternion.Normalize(q); Vector3 n = (Vector3)q.RotateVector3(Vector3.AxisZ); v.x += n.x * 2.5; v.z += n.z * 2.5; self.Playfield.Teleport( (Dynel)self, new Coordinate(v), q, new Identity() { Type = IdentityType.Playfield, Instance = externalPlayfieldId }); } return door != null; }