/// <summary> /// Compute the current position based on the time and updates. /// </summary> /// <param name="timestamp">local time in ticks (milliseconds)</param> /// <returns></returns> public virtual Vector3 ComputePosition(long timestamp) { long timeDifference = (timestamp - lastLocTimestamp); if (pathInterpolator != null) { PathLocAndDir locAndDir = pathInterpolator.Interpolate(timestamp); log.DebugFormat("MobNode.ComputePosition: oid {0}, followTerrain {1}, pathInterpolator {2}", oid, followTerrain, locAndDir == null ? "null" : locAndDir.ToString()); if (locAndDir != null) { if (locAndDir.LengthLeft != 0f) { SetOrientation(Vector3.UnitZ.GetRotationTo(LastDirection.ToNormalized())); } LastDirection = locAndDir.Direction; lastDirTimestamp = timestamp; lastLocTimestamp = timestamp; Vector3 loc = locAndDir.Location; // If we don't have full pathing support, use // MoveMobNode so the mob is supported by // collision volumes. if (useMoveMobNodeForPathInterpolator && collider != null && collider.PartCount > 0) { Vector3 diff = loc - Position; diff.y = 0; Vector3 newpos = worldManager.MoveMobNode(this, diff, timeDifference); lastPosition = newpos; return(newpos); } else { loc = worldManager.ResolveLocation(this, loc); if (collider != null) { Vector3 diff = loc - lastPosition; collider.AddDisplacement(diff); } lastPosition = loc; return(loc); } } else { // This interpolator has expired, so get rid of it pathInterpolator = null; LastDirection = Vector3.Zero; } } else { lastLocTimestamp = timestamp; } Vector3 pos = lastPosition + ((timeDifference / 1000.0f) * LastDirection); Vector3 displacement = pos - Position; // Move the mob node - - given pathing, this should // _only_ happen for mobnodes that are other clients' // players. pos = worldManager.MoveMobNode(this, displacement, timeDifference); lastPosition = pos; return(pos); }