public bool IsVisibleIndoors(ObjCell cell) { var blockDist = PhysicsObj.GetBlockDist(ID, cell.ID); // if landblocks equal if (blockDist == 0) { // check env VisibleCells var cellID = cell.ID & 0xFFFF; if (VisibleCells.ContainsKey(cellID)) { return(true); } } return(SeenOutside && blockDist <= 1); }
/// <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}.UpdatePlayerPosition() - 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.ObjCellID, newPosition.ObjCellID); // 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.Pos.Z - LastGroundPos.Pos.Z > 10 && DateTime.UtcNow - LastJumpTime > TimeSpan.FromSeconds(1) && GetCreatureSkill(Skill.Jump).Current < 1000) { verifyContact = true; } } var curCell = LScape.get_landcell(newPosition.LongObjCellID); 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, newPosition.Instance, curCell, Location.ObjCellID); if (FastTick) { success = PhysicsObj.update_object_server_new(true, newPosition.Instance); } else { success = PhysicsObj.update_object_server(true, newPosition.Instance); } if (PhysicsObj.CurCell == null && curCell.ID >> 16 != 0x18A) { PhysicsObj.CurCell = curCell; } if (verifyContact && IsJumping) { 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(); } } else { PhysicsObj.Position.Frame.Orientation = newPosition.Rotation; } } // 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.Landblock != newPosition.Landblock; 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) { // todo: improve this logic /*if (CurrentLandblock.Instance > 0) * { * ClearInstance(CurrentLandblock.LongId); * }*/ 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 >= 0.100) // Yea, that ain't good.... { log.Warn($"[PERFORMANCE][PHYSICS] {Guid}:{Name} took {(elapsedSeconds * 1000):N1} ms to process UpdatePlayerPosition() at loc: {Location}"); } else if (elapsedSeconds >= 0.010) { log.Debug($"[PERFORMANCE][PHYSICS] {Guid}:{Name} took {(elapsedSeconds * 1000):N1} ms to process UpdatePlayerPosition() at loc: {Location}"); } } } }
public bool IsVisibleOutdoors(ObjCell cell) { var blockDist = PhysicsObj.GetBlockDist(ID, cell.ID); return(blockDist <= 1); }