Example #1
0
        public void HandleActionJump(JumpPack jump)
        {
            StartJump = new ACE.Entity.Position(Location);
            //Console.WriteLine($"JumpPack: Velocity: {jump.Velocity}, Extent: {jump.Extent}");

            var strength = Strength.Current;
            var capacity = EncumbranceSystem.EncumbranceCapacity((int)strength, AugmentationIncreasedCarryingCapacity);
            var burden   = EncumbranceSystem.GetBurden(capacity, EncumbranceVal ?? 0);

            // calculate stamina cost for this jump
            var extent      = Math.Clamp(jump.Extent, 0.0f, 1.0f);
            var staminaCost = MovementSystem.JumpStaminaCost(extent, burden, PKTimerActive);

            //Console.WriteLine($"Strength: {strength}, Capacity: {capacity}, Encumbrance: {EncumbranceVal ?? 0}, Burden: {burden}, StaminaCost: {staminaCost}");

            // ensure player has enough stamina to jump

            /*if (staminaCost > Stamina.Current)
             * {
             *  // get adjusted power
             *  extent = MovementSystem.GetJumpPower(Stamina.Current, burden, false);
             *
             *  staminaCost = (int)Stamina.Current;
             *
             *  // adjust jump velocity
             *  var velocityZ = MovementSystem.GetJumpHeight(burden, GetCreatureSkill(Skill.Jump).Current, extent, 1.0f);
             *
             *  jump.Velocity.Z = velocityZ;
             * }*/

            LastJumpTime = DateTime.UtcNow;

            UpdateVitalDelta(Stamina, -staminaCost);

            //Console.WriteLine($"Jump velocity: {jump.Velocity}");

            // TODO: have server verify / scale magnitude
            if (FastTick)
            {
                if (!PhysicsObj.IsMovingOrAnimating)
                {
                    //PhysicsObj.UpdateTime = PhysicsTimer.CurrentTime - Physics.PhysicsGlobals.MinQuantum;
                    PhysicsObj.UpdateTime = PhysicsTimer.CurrentTime;
                }

                // perform jump in physics engine
                PhysicsObj.TransientState &= ~(Physics.TransientStateFlags.Contact | Physics.TransientStateFlags.WaterContact);
                PhysicsObj.calc_acceleration();
                PhysicsObj.set_on_walkable(false);
                PhysicsObj.set_local_velocity(jump.Velocity, false);

                if (CombatMode == CombatMode.Magic && MagicState.IsCasting)
                {
                    FailCast();
                }
            }
            else
            {
                PhysicsObj.UpdateTime = PhysicsTimer.CurrentTime;

                // set jump velocity
                //var glob_velocity = Vector3.Transform(jump.Velocity, Location.Rotation);
                //PhysicsObj.set_velocity(glob_velocity, true);

                // perform jump in physics engine
                PhysicsObj.TransientState &= ~(Physics.TransientStateFlags.Contact | Physics.TransientStateFlags.WaterContact);
                PhysicsObj.calc_acceleration();
                PhysicsObj.set_on_walkable(false);
                PhysicsObj.set_local_velocity(jump.Velocity, false);
            }

            // this shouldn't be needed, but without sending this update motion / simulated movement event beforehand,
            // running forward and then performing a charged jump does an uncharged shallow arc jump instead
            // this hack fixes that...
            var movementData = new MovementData(this);

            movementData.IsAutonomous = true;
            movementData.MovementType = MovementType.Invalid;
            movementData.Invalid      = new MovementInvalid(movementData);
            EnqueueBroadcast(new GameMessageUpdateMotion(this, movementData));

            // broadcast jump
            EnqueueBroadcast(new GameMessageVectorUpdate(this));

            if (MagicState.IsCasting && RecordCast.Enabled)
            {
                RecordCast.OnJump(jump);
            }
        }
Example #2
0
        private void SetEphemeralValues()
        {
            ObjectDescriptionFlags |= ObjectDescriptionFlag.Player;

            // This is the default send upon log in and the most common. Anything with a velocity will need to add that flag.
            // This should be handled automatically...
            //PositionFlags |= PositionFlags.OrientationHasNoX | PositionFlags.OrientationHasNoY | PositionFlags.IsGrounded | PositionFlags.HasPlacementID;

            FirstEnterWorldDone = false;

            SetStance(MotionStance.NonCombat, false);

            // radius for object updates
            ListeningRadius = 5f;

            if (Session != null && Common.ConfigManager.Config.Server.Accounts.OverrideCharacterPermissions)
            {
                if (Session.AccessLevel == AccessLevel.Admin)
                {
                    IsAdmin = true;
                }
                if (Session.AccessLevel == AccessLevel.Developer)
                {
                    IsArch = true;
                }
                if (Session.AccessLevel == AccessLevel.Envoy || Session.AccessLevel == AccessLevel.Sentinel)
                {
                    IsSentinel = true;
                }
                if (Session.AccessLevel == AccessLevel.Advocate)
                {
                    IsAdvocate = true;
                }
            }

            ContainerCapacity = (byte)(7 + AugmentationExtraPackSlot);

            if (Session != null && AdvocateQuest && IsAdvocate) // Advocate permissions are per character regardless of override
            {
                if (Session.AccessLevel == AccessLevel.Player)
                {
                    Session.SetAccessLevel(AccessLevel.Advocate); // Elevate to Advocate permissions
                }
                if (AdvocateLevel > 4)
                {
                    IsPsr = true; // Enable AdvocateTeleport via MapClick
                }
            }

            CombatTable = DatManager.PortalDat.ReadFromDat <CombatManeuverTable>(CombatTableDID.Value);

            _questManager = new QuestManager(this);

            ContractManager = new ContractManager(this);

            ConfirmationManager = new ConfirmationManager(this);

            LootPermission = new Dictionary <ObjectGuid, DateTime>();

            SquelchManager = new SquelchManager(this);

            MagicState = new MagicState(this);

            RecordCast = new RecordCast(this);

            AttackQueue = new AttackQueue(this);

            return; // todo

            // =======================================
            // This code was taken from the old Load()
            // =======================================

            /*AceCharacter character;
             *
             * if (Common.ConfigManager.Config.Server.Accounts.OverrideCharacterPermissions)
             * {
             *  if (Session.AccessLevel == AccessLevel.Admin)
             *      character.IsAdmin = true;
             *  if (Session.AccessLevel == AccessLevel.Developer)
             *      character.IsArch = true;
             *  if (Session.AccessLevel == AccessLevel.Envoy)
             *      character.IsEnvoy = true;
             *  // TODO: Need to setup and account properly for IsSentinel and IsAdvocate.
             *  // if (Session.AccessLevel == AccessLevel.Sentinel)
             *  //    character.IsSentinel = true;
             *  // if (Session.AccessLevel == AccessLevel.Advocate)
             *  //    character.IsAdvocate= true;
             * }*/

            // FirstEnterWorldDone = false;

            // IsAlive = true;
        }
Example #3
0
        /// <summary>
        /// Used by physics engine to actually update a player position
        /// Automatically notifies clients of updated position
        /// </summary>
        /// <param name="newPosition">The new position being requested, before verification through physics engine</param>
        /// <returns>TRUE if object moves to a different landblock</returns>
        public bool UpdatePlayerPosition(ACE.Entity.Position newPosition, bool forceUpdate = false)
        {
            //Console.WriteLine($"{Name}.UpdatePlayerPhysics({newPosition}, {forceUpdate}, {Teleporting})");
            bool verifyContact = false;

            // possible bug: while teleporting, client can still send AutoPos packets from old landblock
            if (Teleporting && !forceUpdate)
            {
                return(false);
            }

            // pre-validate movement
            if (!ValidateMovement(newPosition))
            {
                log.Error($"{Name}.UpdatePlayerPhysics() - movement pre-validation failed from {Location} to {newPosition}");
                return(false);
            }

            try
            {
                if (!forceUpdate) // This is needed beacuse this function might be called recursively
                {
                    stopwatch.Restart();
                }

                var success = true;

                if (PhysicsObj != null)
                {
                    var distSq = Location.SquaredDistanceTo(newPosition);

                    if (distSq > PhysicsGlobals.EpsilonSq)
                    {
                        /*var p = new Physics.Common.Position(newPosition);
                         * var dist = PhysicsObj.Position.Distance(p);
                         * Console.WriteLine($"Dist: {dist}");*/

                        if (newPosition.Landblock == 0x18A && Location.Landblock != 0x18A)
                        {
                            log.Info($"{Name} is getting swanky");
                        }

                        if (!Teleporting)
                        {
                            var blockDist = PhysicsObj.GetBlockDist(Location.Cell, newPosition.Cell);

                            // verify movement
                            if (distSq > MaxSpeedSq && blockDist > 1)
                            {
                                //Session.Network.EnqueueSend(new GameMessageSystemChat("Movement error", ChatMessageType.Broadcast));
                                log.Warn($"MOVEMENT SPEED: {Name} trying to move from {Location} to {newPosition}, speed: {Math.Sqrt(distSq)}");
                                return(false);
                            }

                            // verify z-pos
                            if (blockDist == 0 && LastGroundPos != null && newPosition.PositionZ - LastGroundPos.PositionZ > 10 && DateTime.UtcNow - LastJumpTime > TimeSpan.FromSeconds(1) && GetCreatureSkill(Skill.Jump).Current < 1000)
                            {
                                verifyContact = true;
                            }
                        }

                        var curCell = LScape.get_landcell(newPosition.Cell);
                        if (curCell != null)
                        {
                            //if (PhysicsObj.CurCell == null || curCell.ID != PhysicsObj.CurCell.ID)
                            //PhysicsObj.change_cell_server(curCell);

                            PhysicsObj.set_request_pos(newPosition.Pos, newPosition.Rotation, curCell, Location.LandblockId.Raw);
                            if (FastTick)
                            {
                                success = PhysicsObj.update_object_server_new();
                            }
                            else
                            {
                                success = PhysicsObj.update_object_server();
                            }

                            if (PhysicsObj.CurCell == null && curCell.ID >> 16 != 0x18A)
                            {
                                PhysicsObj.CurCell = curCell;
                            }

                            if (verifyContact && !PhysicsObj.TransientState.HasFlag(TransientStateFlags.OnWalkable))
                            {
                                log.Warn($"z-pos hacking detected for {Name}, lastGroundPos: {LastGroundPos.ToLOCString()} - requestPos: {newPosition.ToLOCString()}");
                                Location = new ACE.Entity.Position(LastGroundPos);
                                Sequences.GetNextSequence(SequenceType.ObjectForcePosition);
                                SendUpdatePosition();
                                return(false);
                            }

                            CheckMonsters();
                        }
                    }
                }

                // double update path: landblock physics update -> updateplayerphysics() -> update_object_server() -> Teleport() -> updateplayerphysics() -> return to end of original branch
                if (Teleporting && !forceUpdate)
                {
                    return(true);
                }

                if (!success)
                {
                    return(false);
                }

                var landblockUpdate = Location.Cell >> 16 != newPosition.Cell >> 16;

                Location = newPosition;

                if (RecordCast.Enabled)
                {
                    RecordCast.Log($"CurPos: {Location.ToLOCString()}");
                }

                if (RequestedLocationBroadcast || DateTime.UtcNow - LastUpdatePosition >= MoveToState_UpdatePosition_Threshold)
                {
                    SendUpdatePosition();
                }
                else
                {
                    Session.Network.EnqueueSend(new GameMessageUpdatePosition(this));
                }

                if (!InUpdate)
                {
                    LandblockManager.RelocateObjectForPhysics(this, true);
                }

                return(landblockUpdate);
            }
            finally
            {
                if (!forceUpdate) // This is needed beacuse this function might be called recursively
                {
                    var elapsedSeconds = stopwatch.Elapsed.TotalSeconds;
                    ServerPerformanceMonitor.AddToCumulativeEvent(ServerPerformanceMonitor.CumulativeEventHistoryType.Player_Tick_UpdateObjectPhysics, elapsedSeconds);
                    if (elapsedSeconds >= 1) // Yea, that ain't good....
                    {
                        log.Warn($"[PERFORMANCE][PHYSICS] {Guid}:{Name} took {(elapsedSeconds * 1000):N1} ms to process UpdatePlayerPhysics() at loc: {Location}");
                    }
                    else if (elapsedSeconds >= 0.010)
                    {
                        log.Debug($"[PERFORMANCE][PHYSICS] {Guid}:{Name} took {(elapsedSeconds * 1000):N1} ms to process UpdatePlayerPhysics() at loc: {Location}");
                    }
                }
            }
        }