Ejemplo n.º 1
0
        public void UpdateCharmAI()
        {
            if (IsCharmed())
            {
                UnitAI newAI = null;
                if (IsPlayer())
                {
                    Unit charmer = GetCharmer();
                    if (charmer != null)
                    {
                        // first, we check if the creature's own AI specifies an override playerai for its owned players
                        Creature creatureCharmer = charmer.ToCreature();
                        if (creatureCharmer != null)
                        {
                            CreatureAI charmerAI = creatureCharmer.GetAI();
                            if (charmerAI != null)
                            {
                                newAI = charmerAI.GetAIForCharmedPlayer(ToPlayer());
                            }
                        }
                        else
                        {
                            Log.outError(LogFilter.Misc, $"Attempt to assign charm AI to player {GetGUID()} who is charmed by non-creature {GetCharmerGUID()}.");
                        }
                    }
                    if (newAI == null) // otherwise, we default to the generic one
                    {
                        newAI = new SimpleCharmedPlayerAI(ToPlayer());
                    }
                }
                else
                {
                    Cypher.Assert(IsCreature());
                    if (IsPossessed() || IsVehicle())
                    {
                        newAI = new PossessedAI(ToCreature());
                    }
                    else
                    {
                        newAI = new PetAI(ToCreature());
                    }
                }

                Cypher.Assert(newAI != null);
                SetAI(newAI);
                newAI.OnCharmed(true);
            }
            else
            {
                RestoreDisabledAI();
                // Hack: this is required because we want to call OnCharmed(true) on the restored AI
                RefreshAI();
                UnitAI ai = GetAI();
                if (ai != null)
                {
                    ai.OnCharmed(true);
                }
            }
        }
Ejemplo n.º 2
0
        public void RemoveCharmedBy(Unit charmer)
        {
            if (!IsCharmed())
            {
                return;
            }

            if (charmer)
            {
                Cypher.Assert(charmer == GetCharmer());
            }
            else
            {
                charmer = GetCharmer();
            }

            Cypher.Assert(charmer);

            CharmType type;

            if (HasUnitState(UnitState.Possessed))
            {
                type = CharmType.Possess;
            }
            else if (charmer && charmer.IsOnVehicle(this))
            {
                type = CharmType.Vehicle;
            }
            else
            {
                type = CharmType.Charm;
            }

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

            if (_oldFactionId != 0)
            {
                SetFaction(_oldFactionId);
                _oldFactionId = 0;
            }
            else
            {
                RestoreFaction();
            }

            ///@todo Handle SLOT_IDLE motion resume
            GetMotionMaster().InitializeDefault();

            // Vehicle should not attack its passenger after he exists the seat
            if (type != CharmType.Vehicle)
            {
                LastCharmerGUID = charmer.GetGUID();
            }

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

            charmer.SetCharm(this, false);

            Player playerCharmer = charmer.ToPlayer();

            if (playerCharmer)
            {
                switch (type)
                {
                case CharmType.Vehicle:
                    playerCharmer.SetClientControl(this, false);
                    playerCharmer.SetClientControl(charmer, true);
                    RemoveUnitFlag(UnitFlags.Possessed);
                    break;

                case CharmType.Possess:
                    ClearUnitState(UnitState.Possessed);
                    playerCharmer.SetClientControl(this, false);
                    playerCharmer.SetClientControl(charmer, true);
                    charmer.RemoveUnitFlag(UnitFlags.RemoveClientControl);
                    RemoveUnitFlag(UnitFlags.Possessed);
                    break;

                case CharmType.Charm:
                    if (IsTypeId(TypeId.Unit) && charmer.GetClass() == Class.Warlock)
                    {
                        CreatureTemplate cinfo = ToCreature().GetCreatureTemplate();
                        if (cinfo != null && cinfo.CreatureType == CreatureType.Demon)
                        {
                            SetClass((Class)cinfo.UnitClass);
                            if (GetCharmInfo() != null)
                            {
                                GetCharmInfo().SetPetNumber(0, true);
                            }
                            else
                            {
                                Log.outError(LogFilter.Unit, "Aura:HandleModCharm: target={0} with typeid={1} has a charm aura but no charm info!", GetGUID(), GetTypeId());
                            }
                        }
                    }
                    break;

                case CharmType.Convert:
                    break;
                }
            }

            Player player = ToPlayer();

            if (player != null)
            {
                player.SetClientControl(this, true);
            }

            if (playerCharmer && this != charmer.GetFirstControlled())
            {
                playerCharmer.SendRemoveControlBar();
            }

            // a guardian should always have charminfo
            if (!IsGuardian())
            {
                DeleteCharmInfo();
            }

            // reset confused movement for example
            ApplyControlStatesIfNeeded();

            if (!IsPlayer() || charmer.IsCreature())
            {
                UnitAI charmedAI = GetAI();
                if (charmedAI != null)
                {
                    charmedAI.OnCharmed(false); // AI will potentially schedule a charm ai update
                }
                else
                {
                    ScheduleAIChange();
                }
            }
        }
Ejemplo n.º 3
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) == (GetVehicleKit() && GetVehicleKit().IsControllableVehicle()));

            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());

            // Pause any Idle movement
            PauseMovement(0, 0, false);

            // Remove any active voluntary movement
            GetMotionMaster().Clear(MovementGeneratorPriority.Normal);

            // Stop any remaining spline, if no involuntary movement is found
            Func <MovementGenerator, bool> criteria = movement => movement.Priority == MovementGeneratorPriority.Highest;

            if (!GetMotionMaster().HasMovementGenerator(criteria))
            {
                StopMoving();
            }

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

            Player player = ToPlayer();

            if (player)
            {
                if (player.IsAFK())
                {
                    player.ToggleAFK();
                }

                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.Possessed);
                    playerCharmer.SetClientControl(this, true);
                    playerCharmer.VehicleSpellInitialize();
                    break;

                case CharmType.Possess:
                    AddUnitFlag(UnitFlags.Possessed);
                    charmer.AddUnitFlag(UnitFlags.RemoveClientControl);
                    playerCharmer.SetClientControl(this, true);
                    playerCharmer.PossessSpellInitialize();
                    AddUnitState(UnitState.Possessed);
                    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;
                }
            }

            AddUnitState(UnitState.Charmed);

            if (!IsPlayer() || !charmer.IsPlayer())
            {
                // AI will schedule its own change if appropriate
                UnitAI ai = GetAI();
                if (ai != null)
                {
                    ai.OnCharmed(false);
                }
                else
                {
                    ScheduleAIChange();
                }
            }
            return(true);
        }