using ACE.Entity; using ACE.Entity.Enum; using ACE.Entity.Models; using ACE.Server.Entity; using ACE.Server.Entity.Actions; using ACE.Server.Entity.Chess; using ACE.Server.Network.GameMessages.Messages; namespace ACE.Server.WorldObjects { public class GamePiece : Creature { public ChessMatch ChessMatch; public GamePieceState GamePieceState; public Position Position; public GamePiece TargetPiece; /// /// A new biota be created taking all of its values from weenie. /// public GamePiece(Weenie weenie, ObjectGuid guid) : base(weenie, guid) { SetEphemeralValues(); } /// /// Restore a WorldObject from the database. /// public GamePiece(Biota biota) : base(biota) { SetEphemeralValues(); } private void SetEphemeralValues() { TimeToRot = -1; } public void Kill() { ActionChain killChain = new ActionChain(); killChain.AddAction(this, () => { EnqueueBroadcastMotion(new Motion(MotionStance.NonCombat, MotionCommand.Dead)); }); killChain.AddDelaySeconds(5); killChain.AddAction(this, () => { ApplyVisualEffects(PlayScript.Destroy); }); killChain.AddDelaySeconds(1); killChain.AddAction(this, () => Destroy()); killChain.EnqueueChain(); } public void MoveEnqueue(Position dest) { GamePieceState = GamePieceState.MoveToSquare; Position = dest; } public void AttackEnqueue(Position dest, ObjectGuid victim) { GamePieceState = GamePieceState.MoveToAttack; Position = dest; TargetPiece = CurrentLandblock.GetObject(victim) as GamePiece; } public void Tick(double currentUnixTime) { NextMonsterTickTime = currentUnixTime + monsterTickInterval; switch (GamePieceState) { case GamePieceState.MoveToSquare: GamePieceState = GamePieceState.WaitingForMoveToSquare; MoveWeenie(Position, 0.3f, true); break; // visual awareness range of piece is only 1, make sure we are close enough to attack case GamePieceState.MoveToAttack: GamePieceState = GamePieceState.WaitingForMoveToAttack; MoveWeenie(Position, PhysicsObj.GetRadius() + TargetPiece.PhysicsObj.GetRadius(), false); break; case GamePieceState.WaitingForMoveToSquare: case GamePieceState.WaitingForMoveToAttack: UpdatePosition(); break; case GamePieceState.WaitingForMoveToSquareAnimComplete: /*if (PhysicsObj.IsAnimating) { UpdatePosition(); break; }*/ ChessMatch.PieceReady(Guid); GamePieceState = GamePieceState.None; break; case GamePieceState.Combat: if (CombatTable == null) GetCombatTable(); MeleeAttack(); break; } } public override void OnMoveComplete(WeenieError status) { //Console.WriteLine($"{Name}.OnMoveComplete({status})"); base.OnMoveComplete(status); if (status != WeenieError.None) return; switch (GamePieceState) { // we are done, tell the match so the turn can finish case GamePieceState.WaitingForMoveToSquare: GamePieceState = GamePieceState.WaitingForMoveToSquareAnimComplete; break; // there is another piece on this square, attack it! case GamePieceState.WaitingForMoveToAttack: AttackTarget = TargetPiece; GamePieceState = GamePieceState.Combat; break; } } public void OnDealtDamage(/*DamageEvent damageData*/) { // weenie piece is dead, time to move into the square completely if (TargetPiece.IsDead) GamePieceState = GamePieceState.MoveToSquare; } public Motion LastMoveTo; public void MoveWeenie(Position to, float distanceToObject, bool finalHeading) { if (MoveSpeed == 0.0f) GetMovementSpeed(); var moveToPosition = new Motion(this, to); moveToPosition.MoveToParameters.DistanceToObject = distanceToObject; moveToPosition.MoveToParameters.MovementParameters &= ~MovementParams.UseSpheres; if (finalHeading) moveToPosition.MoveToParameters.MovementParameters |= MovementParams.UseFinalHeading; var physPos = new Physics.Common.Position(to); moveToPosition.MoveToParameters.DesiredHeading = physPos.Frame.get_heading(); SetWalkRunThreshold(moveToPosition, to); var mvp = GetMovementParameters(); mvp.CanWalk = true; mvp.StopCompletely = true; mvp.UseSpheres = false; mvp.DistanceToObject = distanceToObject; mvp.UseFinalHeading = finalHeading; mvp.DesiredHeading = physPos.Frame.get_heading(); PhysicsObj.MoveToPosition(physPos, mvp); IsMoving = true; MonsterState = State.Awake; IsAwake = true; LastMoveTo = moveToPosition; EnqueueBroadcastMotion(moveToPosition); } public override void BroadcastMoveTo(Player player) { player.Session.Network.EnqueueSend(new GameMessageUpdateMotion(this, LastMoveTo)); } } }