Esempio n. 1
0
		protected override void HandleMessage(EntityActorMessageContext messageContext, DefaultEntityActorStateContainer state, InteractWithEntityActorMessage message)
		{
			if(Logger.IsDebugEnabled)
				Logger.Debug($"Entity: {message.EntityInteracting} Interacted with Creature: {state.EntityGuid}");

			messageContext.Sender.Tell(new AddPlayerExperienceActorMessage(50));

			//Let's create the path data.
			IMovementGenerator<GameObject> movementGenerator = MovementGeneratorMappable.RetrieveEntity(state.EntityGuid);
			var playerMovementGenerator = MovementGeneratorMappable.RetrieveEntity(message.EntityInteracting);

			//WARNING: NEVER DO THIS, NOT SAFE TO ACCESS PLAYER DATA.
			Vector3 creatureCurrentPosition = movementGenerator.CurrentPosition;
			Vector3 playerCurrentPosition = playerMovementGenerator.CurrentPosition;

			UnityAsyncHelper.UnityMainThreadContext.Post(o =>
			{
				var path = new NavMeshPath();
				NavMesh.CalculatePath(creatureCurrentPosition, playerCurrentPosition, NavMesh.AllAreas, path);

				if(path.status != NavMeshPathStatus.PathComplete)
					if(Logger.IsWarnEnabled)
						Logger.Warn($"Produced invalid PathResult: {path.status} for Entity: {state.EntityGuid} Start: {creatureCurrentPosition} End: {playerCurrentPosition}");

				//Don't broadcast if not invalid
				if(path.status == NavMeshPathStatus.PathComplete)
					messageContext.Entity.Tell(new CreatureSetPathMovementMessage(creatureCurrentPosition, path.corners));
			}, null);
		}
Esempio n. 2
0
        /// <inheritdoc />
        protected override Task HandleMessage(IPeerSessionMessageContext <GameServerPacketPayload> context, ClientMovementDataUpdateRequest payload, NetworkEntityGuid guid)
        {
            try
            {
                IMovementGenerator <GameObject> generator = MovementGenerator.RetrieveEntity(guid);
                IMovementData movementData = MovementDataMap.RetrieveEntity(guid);
                PositionChangeMovementData changeMovementData = BuildPositionChangeMovementData(payload, generator, movementData);
                MovementDataMap.ReplaceObject(guid, changeMovementData);

                IActorRef playerActorRef = ActorReferenceMappable.RetrieveEntity(guid);

                playerActorRef.TellSelf(new PlayerMovementStateChangedMessage(changeMovementData.Direction));

                //If the generator is running, we should use its initial position instead of the last movement data's position.
                MovementGenerator.ReplaceObject(guid, BuildCharacterControllerMovementGenerator(guid, changeMovementData, generator, movementData));
            }
            catch (Exception e)
            {
                if (Logger.IsErrorEnabled)
                {
                    Logger.Error($"Failed to update MovementData for GUID: {guid} Reason: {e.Message}");
                }

                throw;
            }

            return(Task.CompletedTask);
        }
Esempio n. 3
0
        /// <inheritdoc />
        protected override Task HandleMessage(IPeerSessionMessageContext <GameServerPacketPayload> context, ClientRotationDataUpdateRequest payload, NetworkEntityGuid guid)
        {
            try
            {
                IMovementGenerator <GameObject> generator = MovementGenerator.RetrieveEntity(guid);
                IMovementData movementData = MovementDataMap.RetrieveEntity(guid);

                //TODO: This is a temporary hack, we nee d abetter solluition
                if (movementData is PositionChangeMovementData posChangeMoveDat)
                {
                    Vector2 direction = posChangeMoveDat.Direction;

                    //TODO: Sanity check position sent.
                    //TODO: Sanity check timestamp
                    MovementDataMap.ReplaceObject(guid, new PositionChangeMovementData(payload.TimeStamp, payload.ClientCurrentPosition, direction, payload.Rotation));
                }
                else
                {
                    throw new NotImplementedException($"TODO: Implement rotation when dealing with: {movementData.GetType().Name} type movement.");
                }

                OnPlayerRotationChanged?.Invoke(this, new PlayerRotiationChangeEventArgs(guid, payload.Rotation));
            }
            catch (Exception e)
            {
                if (Logger.IsErrorEnabled)
                {
                    Logger.Error($"Failed to update MovementData for GUID: {guid} Reason: {e.Message}");
                }

                throw;
            }

            return(Task.CompletedTask);
        }
Esempio n. 4
0
        protected override void HandleMessage(EntityActorMessageContext messageContext, DefaultEntityActorStateContainer state, CreatureSetPathMovementMessage message)
        {
            PathBasedMovementData           data      = new PathBasedMovementData(message.PathPoints, TimeService.CurrentLocalTime);
            IMovementGenerator <GameObject> generator = MovementGeneratorFactory.Create(new EntityAssociatedData <IMovementData>(state.EntityGuid, data));

            MovementDataMappable.ReplaceObject(state.EntityGuid, data);
            MovementGeneratorMappable.ReplaceObject(state.EntityGuid, generator);
        }
Esempio n. 5
0
        protected override void OnEventFired(object source, EntityCreationFinishedEventArgs args)
        {
            IMovementData movementData = MovementDataMappable.RetrieveEntity(args.EntityGuid);

            IMovementGenerator <IWorldObject> generator = MovementGeneratorFactory.Create(new EntityAssociatedData <IMovementData>(args.EntityGuid, movementData));

            MovementGeneratorMappable.AddObject(args.EntityGuid, generator);
        }
        protected override void OnEventFired(object source, EntityWorldObjectCreatedEventArgs args)
        {
            IMovementData movementData = MovementDataMappable.RetrieveEntity(args.EntityGuid);

            IMovementGenerator <IWorldObject> generator = MovementGeneratorFactory.Create(new EntityAssociatedData <IMovementData>(args.EntityGuid, movementData));

            MovementGeneratorMappable.AddObject(args.EntityGuid, generator);

            InitializePosition(args.EntityGuid, movementData, generator, args.WorldReprensetation);
        }
Esempio n. 7
0
        private ZoneServerCharacterLocationSaveRequest CreatedLocationSaveData([NotNull] NetworkEntityGuid guid)
        {
            if (guid == null)
            {
                throw new ArgumentNullException(nameof(guid));
            }

            //TODO: Check that the entity actually exists
            IMovementGenerator <GameObject> movementData = MovementDataMap.RetrieveEntity(guid);

            return(new ZoneServerCharacterLocationSaveRequest(movementData.CurrentPosition));
        }
        /// <inheritdoc />
        public override Task HandleMessage(IPeerMessageContext <GameClientPacketPayload> context, MovementDataUpdateEventPayload payload)
        {
            if (!payload.HasMovementData)
            {
                if (Logger.IsWarnEnabled)
                {
                    Logger.Warn($"Empty movement update packet received.");
                }

                return(Task.CompletedTask);
            }

            foreach (var movementUpdate in payload.MovementDatas)
            {
                if (!KnownEntities.isEntityKnown(movementUpdate.EntityGuid))
                {
                    if (Logger.IsInfoEnabled)
                    {
                        Logger.Info($"TODO: Received movement update too soon. Must enable deferred movement update queueing for entities that are about to spawn.");
                    }

                    continue;
                }

                try
                {
                    IMovementGenerator <IWorldObject> generator = MovementGeneratorFactory.Create(movementUpdate);

                    //We just initialize this casually, the next update tick in Unity3D will start the movement generator, the old generator actually might be running right now
                    //at the time this is set.
                    MovementGeneratorMappable.ReplaceObject(movementUpdate.EntityGuid, generator);
                    MovementDataMappable.ReplaceObject(movementUpdate.EntityGuid, movementUpdate.Data);
                }
                catch (Exception e)
                {
                    string error = $"Failed to handle Movement Data for Entity: {movementUpdate.EntityGuid} Type: {movementUpdate.Data.GetType().Name} Error: {e.Message}";

                    if (Logger.IsErrorEnabled)
                    {
                        Logger.Error(error);
                    }

                    throw new InvalidOperationException(error, e);
                }
            }

            return(Task.CompletedTask);
        }
Esempio n. 9
0
        public void HandleMovementUpdate(EntityAssociatedData <IMovementData> movementUpdate, bool forceHandleLocal = false)
        {
            if (!KnownEntities.isEntityKnown(movementUpdate.EntityGuid))
            {
                if (Logger.IsInfoEnabled)
                {
                    Logger.Info($"TODO: Received movement update too soon. Must enable deferred movement update queueing for entities that are about to spawn.");
                }

                return;
            }

            try
            {
                if (!forceHandleLocal)
                {
                    //Cheap check, and we're on another thread so performance doesn't really matter
                    if (movementUpdate.EntityGuid == PlayerDetails.LocalPlayerGuid)
                    {
                        if (movementUpdate.Data.isUserCreated)
                        {
                            return;                             //don't handle user created movement data about ourselves. It'll just make movement abit janky locally.
                        }
                    }
                }

                IMovementGenerator <GameObject> generator = MovementGeneratorFactory.Create(movementUpdate);

                //We just initialize this casually, the next update tick in Unity3D will start the movement generator, the old generator actually might be running right now
                //at the time this is set.
                MovementGeneratorMappable.ReplaceObject(movementUpdate.EntityGuid, generator);
                MovementDataMappable.ReplaceObject(movementUpdate.EntityGuid, movementUpdate.Data);
            }
            catch (Exception e)
            {
                string error = $"Failed to handle Movement Data for Entity: {movementUpdate.EntityGuid} Type: {movementUpdate.Data.GetType().Name} Error: {e.Message}";

                if (Logger.IsErrorEnabled)
                {
                    Logger.Error(error);
                }

                throw new InvalidOperationException(error, e);
            }
        }
Esempio n. 10
0
        public void SetEscortPaused(bool on)
        {
            if (!HasEscortState(EscortState.Escorting))
            {
                return;
            }

            if (on)
            {
                AddEscortState(EscortState.Paused);
                IMovementGenerator movementGenerator = me.GetMotionMaster().GetMotionSlot(MovementSlot.Idle);
                if (movementGenerator != null)
                {
                    movementGenerator.Pause(0);
                }
            }
            else
            {
                RemoveEscortState(EscortState.Paused);
                _resume = true;
            }
        }
Esempio n. 11
0
        /// <inheritdoc />
        protected override Task HandleMessage(IPeerSessionMessageContext <GameServerPacketPayload> context, ClientSetClickToMovePathRequestPayload payload, NetworkEntityGuid guid)
        {
            try
            {
                IMovementGenerator <GameObject> generator = MovementGenerator.RetrieveEntity(guid);

                IMovementData         movementData       = MovementDataMap.RetrieveEntity(guid);
                PathBasedMovementData changeMovementData = BuildPathData(payload, generator, movementData, guid);

                //If it doesn't have more one point reject it
                if (changeMovementData.MovementPath.Count < 2)
                {
                    return(Task.CompletedTask);
                }

                MovementDataMap.ReplaceObject(guid, changeMovementData);

                IActorRef playerActorRef = ActorReferenceMappable.RetrieveEntity(guid);

                Vector3 direction3D = (changeMovementData.MovementPath[1] - changeMovementData.MovementPath[0]);
                Vector2 direction2D = new Vector2(direction3D.x, direction3D.z).normalized;
                playerActorRef.TellSelf(new PlayerMovementStateChangedMessage(direction2D));

                //If the generator is running, we should use its initial position instead of the last movement data's position.
                MovementGenerator.ReplaceObject(guid, new PathMovementGenerator(changeMovementData));
            }
            catch (Exception e)
            {
                if (Logger.IsErrorEnabled)
                {
                    Logger.Error($"Failed to update MovementData for GUID: {guid} Reason: {e.Message}");
                }

                throw;
            }

            return(Task.CompletedTask);
        }
        private void InitializePosition([JetBrains.Annotations.NotNull] NetworkEntityGuid guid,
                                        [JetBrains.Annotations.NotNull] IMovementData movementData,
                                        [JetBrains.Annotations.NotNull] IMovementGenerator <IWorldObject> movementGenerator,
                                        [JetBrains.Annotations.NotNull] IWorldObject entityWorldObject)
        {
            if (guid == null)
            {
                throw new ArgumentNullException(nameof(guid));
            }
            if (movementData == null)
            {
                throw new ArgumentNullException(nameof(movementData));
            }
            if (movementGenerator == null)
            {
                throw new ArgumentNullException(nameof(movementGenerator));
            }
            if (entityWorldObject == null)
            {
                throw new ArgumentNullException(nameof(entityWorldObject));
            }

            //We need to fast forward the fake/stub WorldObject so that we can get an accurate initial position.
            if (movementData is PathBasedMovementData)
            {
                IWorldObject worldObjectStub = new WorldObjectStub((int)movementData.InitialPosition.x - Client.baseX, (int)movementData.InitialPosition.z - Client.baseY);

                //At this point, the worldObjectStub actually will have the correct initial position
                movementGenerator.Update(worldObjectStub, TimeService.CurrentRemoteTime);
                entityWorldObject.DirectSetPosition(worldObjectStub.CurrentX, worldObjectStub.CurrentY);
            }
            else
            {
                entityWorldObject.setPos((int)movementData.InitialPosition.x - Client.baseX, (int)movementData.InitialPosition.z - Client.baseY);
            }
        }
        void HandleMoveWorldportAck()
        {
            // ignore unexpected far teleports
            if (!GetPlayer().IsBeingTeleportedFar())
            {
                return;
            }

            bool seamlessTeleport = GetPlayer().IsBeingTeleportedSeamlessly();

            GetPlayer().SetSemaphoreTeleportFar(false);

            // get the teleport destination
            WorldLocation loc = GetPlayer().GetTeleportDest();

            // possible errors in the coordinate validity check
            if (!GridDefines.IsValidMapCoord(loc))
            {
                LogoutPlayer(false);
                return;
            }

            // get the destination map entry, not the current one, this will fix homebind and reset greeting
            MapRecord        mapEntry  = CliDB.MapStorage.LookupByKey(loc.GetMapId());
            InstanceTemplate mInstance = Global.ObjectMgr.GetInstanceTemplate(loc.GetMapId());

            // reset instance validity, except if going to an instance inside an instance
            if (!GetPlayer().m_InstanceValid&& mInstance == null)
            {
                GetPlayer().m_InstanceValid = true;
            }

            Map oldMap = GetPlayer().GetMap();
            Map newMap = Global.MapMgr.CreateMap(loc.GetMapId(), GetPlayer());

            if (GetPlayer().IsInWorld)
            {
                Log.outError(LogFilter.Network, "Player (Name {0}) is still in world when teleported from map {1} to new map {2}", GetPlayer().GetName(), oldMap.GetId(), loc.GetMapId());
                oldMap.RemovePlayerFromMap(GetPlayer(), false);
            }

            // relocate the player to the teleport destination
            // the CannotEnter checks are done in TeleporTo but conditions may change
            // while the player is in transit, for example the map may get full
            if (newMap == null || newMap.CannotEnter(GetPlayer()) != 0)
            {
                Log.outError(LogFilter.Network, "Map {0} could not be created for {1} ({2}), porting player to homebind", loc.GetMapId(), newMap ? newMap.GetMapName() : "Unknown", GetPlayer().GetGUID().ToString());
                GetPlayer().TeleportTo(GetPlayer().GetHomebind());
                return;
            }

            float z = loc.GetPositionZ();

            if (GetPlayer().HasUnitMovementFlag(MovementFlag.Hover))
            {
                z += GetPlayer().m_unitData.HoverHeight;
            }

            GetPlayer().Relocate(loc.GetPositionX(), loc.GetPositionY(), z, loc.GetOrientation());
            GetPlayer().SetFallInformation(0, GetPlayer().GetPositionZ());

            GetPlayer().ResetMap();
            GetPlayer().SetMap(newMap);

            ResumeToken resumeToken = new ResumeToken();

            resumeToken.SequenceIndex = _player.m_movementCounter;
            resumeToken.Reason        = seamlessTeleport ? 2 : 1u;
            SendPacket(resumeToken);

            if (!seamlessTeleport)
            {
                GetPlayer().SendInitialPacketsBeforeAddToMap();
            }

            if (!GetPlayer().GetMap().AddPlayerToMap(GetPlayer(), !seamlessTeleport))
            {
                Log.outError(LogFilter.Network, "WORLD: failed to teleport player {0} ({1}) to map {2} ({3}) because of unknown reason!",
                             GetPlayer().GetName(), GetPlayer().GetGUID().ToString(), loc.GetMapId(), newMap ? newMap.GetMapName() : "Unknown");
                GetPlayer().ResetMap();
                GetPlayer().SetMap(oldMap);
                GetPlayer().TeleportTo(GetPlayer().GetHomebind());
                return;
            }

            // Battleground state prepare (in case join to BG), at relogin/tele player not invited
            // only add to bg group and object, if the player was invited (else he entered through command)
            if (GetPlayer().InBattleground())
            {
                // cleanup setting if outdated
                if (!mapEntry.IsBattlegroundOrArena())
                {
                    // We're not in BG
                    GetPlayer().SetBattlegroundId(0, BattlegroundTypeId.None);
                    // reset destination bg team
                    GetPlayer().SetBGTeam(0);
                }
                // join to bg case
                else
                {
                    Battleground bg = GetPlayer().GetBattleground();
                    if (bg)
                    {
                        if (GetPlayer().IsInvitedForBattlegroundInstance(GetPlayer().GetBattlegroundId()))
                        {
                            bg.AddPlayer(GetPlayer());
                        }
                    }
                }
            }

            if (!seamlessTeleport)
            {
                GetPlayer().SendInitialPacketsAfterAddToMap();
            }
            else
            {
                GetPlayer().UpdateVisibilityForPlayer();
                Garrison garrison = GetPlayer().GetGarrison();
                if (garrison != null)
                {
                    garrison.SendRemoteInfo();
                }
            }

            // flight fast teleport case
            if (GetPlayer().GetMotionMaster().GetCurrentMovementGeneratorType() == MovementGeneratorType.Flight)
            {
                if (!GetPlayer().InBattleground())
                {
                    if (!seamlessTeleport)
                    {
                        // short preparations to continue flight
                        IMovementGenerator movementGenerator = GetPlayer().GetMotionMaster().Top();
                        movementGenerator.Initialize(GetPlayer());
                    }
                    return;
                }

                // Battlegroundstate prepare, stop flight
                GetPlayer().GetMotionMaster().MovementExpired();
                GetPlayer().CleanupAfterTaxiFlight();
            }

            // resurrect character at enter into instance where his corpse exist after add to map
            if (mapEntry.IsDungeon() && !GetPlayer().IsAlive())
            {
                if (GetPlayer().GetCorpseLocation().GetMapId() == mapEntry.Id)
                {
                    GetPlayer().ResurrectPlayer(0.5f, false);
                    GetPlayer().SpawnCorpseBones();
                }
            }

            bool allowMount = !mapEntry.IsDungeon() || mapEntry.IsBattlegroundOrArena();

            if (mInstance != null)
            {
                // check if this instance has a reset time and send it to player if so
                Difficulty          diff    = newMap.GetDifficultyID();
                MapDifficultyRecord mapDiff = Global.DB2Mgr.GetMapDifficultyData(mapEntry.Id, diff);
                if (mapDiff != null)
                {
                    if (mapDiff.GetRaidDuration() != 0)
                    {
                        long timeReset = Global.InstanceSaveMgr.GetResetTimeFor(mapEntry.Id, diff);
                        if (timeReset != 0)
                        {
                            uint timeleft = (uint)(timeReset - Time.UnixTime);
                            GetPlayer().SendInstanceResetWarning(mapEntry.Id, diff, timeleft, true);
                        }
                    }
                }

                // check if instance is valid
                if (!GetPlayer().CheckInstanceValidity(false))
                {
                    GetPlayer().m_InstanceValid = false;
                }

                // instance mounting is handled in InstanceTemplate
                allowMount = mInstance.AllowMount;
            }

            // mount allow check
            if (!allowMount)
            {
                GetPlayer().RemoveAurasByType(AuraType.Mounted);
            }

            // update zone immediately, otherwise leave channel will cause crash in mtmap
            uint newzone, newarea;

            GetPlayer().GetZoneAndAreaId(out newzone, out newarea);
            GetPlayer().UpdateZone(newzone, newarea);

            // honorless target
            if (GetPlayer().pvpInfo.IsHostile)
            {
                GetPlayer().CastSpell(GetPlayer(), 2479, true);
            }

            // in friendly area
            else if (GetPlayer().IsPvP() && !GetPlayer().HasPlayerFlag(PlayerFlags.InPVP))
            {
                GetPlayer().UpdatePvP(false, false);
            }

            // resummon pet
            GetPlayer().ResummonPetTemporaryUnSummonedIfAny();

            //lets process all delayed operations on successful teleport
            GetPlayer().ProcessDelayedOperations();
        }
Esempio n. 14
0
 private CharacterControllerInputMovementGenerator BuildCharacterControllerMovementGenerator(NetworkEntityGuid guid, PositionChangeMovementData data, IMovementGenerator <GameObject> generator, IMovementData movementData)
 {
     //TODO: Sanity check timestamp and position.
     //We used to use the last generators current position
     //However we now use the hint position from the client.
     //This NEEDS to be sanity checked before used.
     //This semi-authorative approach is less secure but more responsive for the user.
     return(new CharacterControllerInputMovementGenerator(data, new Lazy <CharacterController>(() => this.CharacterControllerMappable.RetrieveEntity(guid)), data.InitialPosition));
 }
Esempio n. 15
0
        public override void UpdateAI(uint diff)
        {
            //Waypoint Updating
            if (HasEscortState(EscortState.Escorting) && !me.IsEngaged() && !HasEscortState(EscortState.Returning))
            {
                if (_pauseTimer <= diff)
                {
                    if (!HasEscortState(EscortState.Paused))
                    {
                        _pauseTimer = 0;

                        if (_ended)
                        {
                            _ended = false;
                            me.GetMotionMaster().MoveIdle();

                            if (_despawnAtEnd)
                            {
                                Log.outDebug(LogFilter.Scripts, "EscortAI.UpdateAI: reached end of waypoints, despawning at end");
                                if (_returnToStart)
                                {
                                    Position respawnPosition = new Position();
                                    float    orientation;
                                    me.GetRespawnPosition(out respawnPosition.posX, out respawnPosition.posY, out respawnPosition.posZ, out orientation);
                                    respawnPosition.SetOrientation(orientation);
                                    me.GetMotionMaster().MovePoint(EscortPointIds.Home, respawnPosition);
                                    Log.outDebug(LogFilter.Scripts, $"EscortAI.UpdateAI: returning to spawn location: {respawnPosition}");
                                }
                                else if (_instantRespawn)
                                {
                                    me.Respawn();
                                }
                                else
                                {
                                    me.DespawnOrUnsummon();
                                }
                            }

                            Log.outDebug(LogFilter.Scripts, "EscortAI.UpdateAI: reached end of waypoints");
                            RemoveEscortState(EscortState.Escorting);
                            return;
                        }

                        if (!_started)
                        {
                            _started = true;
                            me.GetMotionMaster().MovePath(_path, false);
                        }
                        else if (_resume)
                        {
                            _resume = false;
                            IMovementGenerator movementGenerator = me.GetMotionMaster().GetMotionSlot(MovementSlot.Idle);
                            if (movementGenerator != null)
                            {
                                movementGenerator.Resume(0);
                            }
                        }
                    }
                }
                else
                {
                    _pauseTimer -= diff;
                }
            }


            //Check if player or any member of his group is within range
            if (_despawnAtFar && HasEscortState(EscortState.Escorting) && !_playerGUID.IsEmpty() && !me.GetVictim() && !HasEscortState(EscortState.Returning))
            {
                if (_playerCheckTimer <= diff)
                {
                    if (!IsPlayerOrGroupInRange())
                    {
                        Log.outDebug(LogFilter.Scripts, "EscortAI failed because player/group was to far away or not found");

                        bool         isEscort     = false;
                        CreatureData creatureData = me.GetCreatureData();
                        if (creatureData != null)
                        {
                            isEscort = (WorldConfig.GetBoolValue(WorldCfg.RespawnDynamicEscortNpc) && creatureData.spawnGroupData.flags.HasAnyFlag(SpawnGroupFlags.EscortQuestNpc));
                        }

                        if (_instantRespawn && !isEscort)
                        {
                            me.DespawnOrUnsummon(0, TimeSpan.FromSeconds(1));
                        }
                        else if (_instantRespawn && isEscort)
                        {
                            me.GetMap().RemoveRespawnTime(SpawnObjectType.Creature, me.GetSpawnId(), true);
                        }
                        else
                        {
                            me.DespawnOrUnsummon();
                        }

                        return;
                    }

                    _playerCheckTimer = 1000;
                }
                else
                {
                    _playerCheckTimer -= diff;
                }
            }

            UpdateEscortAI(diff);
        }
Esempio n. 16
0
 private PositionChangeMovementData BuildPositionChangeMovementData(ClientMovementDataUpdateRequest payload, IMovementGenerator <GameObject> generator, IMovementData originalMovementData)
 {
     //TODO: Sanity check timestamp and position.
     //So, originally we used authorative time and position but now we semi-trust the client.
     //We need to verify the send timestamp is not too far off and also sanity check the position too.
     return(new PositionChangeMovementData(payload.Timestamp, payload.CurrentClientPosition, payload.MovementInput, originalMovementData.Rotation));
 }
Esempio n. 17
0
        public bool SetCharmedBy(Unit charmer, CharmType type, AuraApplication aurApp = null)
        {
            if (!charmer)
            {
                return(false);
            }

            // dismount players when charmed
            if (IsTypeId(TypeId.Player))
            {
                RemoveAurasByType(AuraType.Mounted);
            }

            if (charmer.IsTypeId(TypeId.Player))
            {
                charmer.RemoveAurasByType(AuraType.Mounted);
            }

            Cypher.Assert(type != CharmType.Possess || charmer.IsTypeId(TypeId.Player));
            Cypher.Assert((type == CharmType.Vehicle) == IsVehicle());

            Log.outDebug(LogFilter.Unit, "SetCharmedBy: charmer {0} (GUID {1}), charmed {2} (GUID {3}), type {4}.", charmer.GetEntry(), charmer.GetGUID().ToString(), GetEntry(), GetGUID().ToString(), type);

            if (this == charmer)
            {
                Log.outFatal(LogFilter.Unit, "Unit:SetCharmedBy: Unit {0} (GUID {1}) is trying to charm itself!", GetEntry(), GetGUID().ToString());
                return(false);
            }

            if (IsTypeId(TypeId.Player) && ToPlayer().GetTransport())
            {
                Log.outFatal(LogFilter.Unit, "Unit:SetCharmedBy: Player on transport is trying to charm {0} (GUID {1})", GetEntry(), GetGUID().ToString());
                return(false);
            }

            // Already charmed
            if (!GetCharmerGUID().IsEmpty())
            {
                Log.outFatal(LogFilter.Unit, "Unit:SetCharmedBy: {0} (GUID {1}) has already been charmed but {2} (GUID {3}) is trying to charm it!", GetEntry(), GetGUID().ToString(), charmer.GetEntry(), charmer.GetGUID().ToString());
                return(false);
            }

            CastStop();
            CombatStop(); // @todo CombatStop(true) may cause crash (interrupt spells)

            Player playerCharmer = charmer.ToPlayer();

            // Charmer stop charming
            if (playerCharmer)
            {
                playerCharmer.StopCastingCharm();
                playerCharmer.StopCastingBindSight();
            }

            // Charmed stop charming
            if (IsTypeId(TypeId.Player))
            {
                ToPlayer().StopCastingCharm();
                ToPlayer().StopCastingBindSight();
            }

            // StopCastingCharm may remove a possessed pet?
            if (!IsInWorld)
            {
                Log.outFatal(LogFilter.Unit, "Unit:SetCharmedBy: {0} (GUID {1}) is not in world but {2} (GUID {3}) is trying to charm it!", GetEntry(), GetGUID().ToString(), charmer.GetEntry(), charmer.GetGUID().ToString());
                return(false);
            }

            // charm is set by aura, and aura effect remove handler was called during apply handler execution
            // prevent undefined behaviour
            if (aurApp != null && aurApp.GetRemoveMode() != 0)
            {
                return(false);
            }

            _oldFactionId = GetFaction();
            SetFaction(charmer.GetFaction());

            // Set charmed
            charmer.SetCharm(this, true);

            if (IsTypeId(TypeId.Unit))
            {
                IMovementGenerator movementGenerator = GetMotionMaster().GetMotionSlot(MovementSlot.Idle);
                if (movementGenerator != null)
                {
                    movementGenerator.Pause(0);
                }

                GetMotionMaster().Clear(MovementSlot.Active);

                StopMoving();

                ToCreature().GetAI().OnCharmed(true);
            }
            else
            {
                Player player = ToPlayer();
                if (player)
                {
                    if (player.IsAFK())
                    {
                        player.ToggleAFK();
                    }

                    if (charmer.IsTypeId(TypeId.Unit)) // we are charmed by a creature
                    {
                        // change AI to charmed AI on next Update tick
                        NeedChangeAI = true;
                        if (IsAIEnabled)
                        {
                            IsAIEnabled = false;
                            player.GetAI().OnCharmed(true);
                        }
                    }

                    player.SetClientControl(this, false);
                }
            }

            // charm is set by aura, and aura effect remove handler was called during apply handler execution
            // prevent undefined behaviour
            if (aurApp != null && aurApp.GetRemoveMode() != 0)
            {
                return(false);
            }

            // Pets already have a properly initialized CharmInfo, don't overwrite it.
            if (type != CharmType.Vehicle && GetCharmInfo() == null)
            {
                InitCharmInfo();
                if (type == CharmType.Possess)
                {
                    GetCharmInfo().InitPossessCreateSpells();
                }
                else
                {
                    GetCharmInfo().InitCharmCreateSpells();
                }
            }

            if (playerCharmer)
            {
                switch (type)
                {
                case CharmType.Vehicle:
                    AddUnitFlag(UnitFlags.PlayerControlled);
                    playerCharmer.SetClientControl(this, true);
                    playerCharmer.VehicleSpellInitialize();
                    break;

                case CharmType.Possess:
                    AddUnitState(UnitState.Possessed);
                    AddUnitFlag(UnitFlags.PlayerControlled);
                    charmer.AddUnitFlag(UnitFlags.RemoveClientControl);
                    playerCharmer.SetClientControl(this, true);
                    playerCharmer.PossessSpellInitialize();
                    break;

                case CharmType.Charm:
                    if (IsTypeId(TypeId.Unit) && charmer.GetClass() == Class.Warlock)
                    {
                        CreatureTemplate cinfo = ToCreature().GetCreatureTemplate();
                        if (cinfo != null && cinfo.CreatureType == CreatureType.Demon)
                        {
                            // to prevent client crash
                            SetClass(Class.Mage);

                            // just to enable stat window
                            if (GetCharmInfo() != null)
                            {
                                GetCharmInfo().SetPetNumber(Global.ObjectMgr.GeneratePetNumber(), true);
                            }

                            // if charmed two demons the same session, the 2nd gets the 1st one's name
                            SetPetNameTimestamp((uint)GameTime.GetGameTime());     // cast can't be helped
                        }
                    }
                    playerCharmer.CharmSpellInitialize();
                    break;

                default:
                case CharmType.Convert:
                    break;
                }
            }
            return(true);
        }
Esempio n. 18
0
        private PathBasedMovementData BuildPathData(ClientSetClickToMovePathRequestPayload payload, IMovementGenerator <GameObject> generator, IMovementData originalMovementData, NetworkEntityGuid guid)
        {
            //TODO: Sanity check timestamp and position.
            //So, originally we used authorative time and position but now we semi-trust the client.
            //We need to verify the send timestamp is not too far off and also sanity check the position too.
            Vector3[] path = payload.PathData.MovementPath.ToArrayTryAvoidCopy();

            Vector3[] fullPath = new Vector3[path.Length + 1];

            //If we haven't even started the last movement generator from the last click.
            if (generator.isStarted)
            {
                //Force the current position as the start point of the path.
                fullPath[0] = generator.CurrentPosition;
            }
            else
            {
                //We need to use the last WorldTransform because
                //the last movement generator has not started.
                WorldTransform transform = TransformMap.RetrieveEntity(guid);
                fullPath[0] = new Vector3(transform.PositionX, transform.PositionY, transform.PositionZ);
            }

            Array.Copy(path, 0, fullPath, 1, path.Length);

            return(new PathBasedMovementData(fullPath, TimeService.CurrentLocalTime));
        }