public void UpdateCharmAI() { switch (GetTypeId()) { case TypeId.Unit: if (i_disabledAI != null) // disabled AI must be primary AI { if (!IsCharmed()) { i_AI = i_disabledAI; i_disabledAI = null; if (IsTypeId(TypeId.Unit)) { ToCreature().GetAI().OnCharmed(false); } } } else { if (IsCharmed()) { i_disabledAI = i_AI; if (IsPossessed() || IsVehicle()) { i_AI = new PossessedAI(ToCreature()); } else { i_AI = new PetAI(ToCreature()); } } } break; case TypeId.Player: { if (IsCharmed()) // if we are currently being charmed, then we should apply charm AI { i_disabledAI = i_AI; UnitAI newAI = null; // first, we check if the creature's own AI specifies an override playerai for its owned players Unit charmer = GetCharmer(); if (charmer) { Creature creatureCharmer = charmer.ToCreature(); if (creatureCharmer) { PlayerAI charmAI = creatureCharmer.IsAIEnabled ? creatureCharmer.GetAI().GetAIForCharmedPlayer(ToPlayer()) : null; if (charmAI != null) { newAI = charmAI; } } else { Log.outError(LogFilter.Misc, "Attempt to assign charm AI to player {0} who is charmed by non-creature {1}.", GetGUID().ToString(), GetCharmerGUID().ToString()); } } if (newAI == null) // otherwise, we default to the generic one { newAI = new SimpleCharmedPlayerAI(ToPlayer()); } i_AI = newAI; newAI.OnCharmed(true); } else { if (i_AI != null) { // we allow the charmed PlayerAI to clean up i_AI.OnCharmed(false); } else { Log.outError(LogFilter.Misc, "Attempt to remove charm AI from player {0} who doesn't currently have charm AI.", GetGUID().ToString()); } // and restore our previous PlayerAI (if we had one) i_AI = i_disabledAI; i_disabledAI = null; // IsAIEnabled gets handled in the caller } break; } default: Log.outError(LogFilter.Misc, "Attempt to update charm AI for unit {0}, which is neither player nor creature.", GetGUID().ToString()); break; } }
public override bool Execute(ulong e_time, uint p_time) { Contract.Assert(Passenger.IsInWorld); Contract.Assert(Target != null && Target.GetBase().IsInWorld); Contract.Assert(Target.GetBase().HasAuraTypeWithCaster(AuraType.ControlVehicle, Passenger.GetGUID())); Target.RemovePendingEventsForSeat(Seat.Key); Target.RemovePendingEventsForPassenger(Passenger); Passenger.SetVehicle(Target); Seat.Value.Passenger.Guid = Passenger.GetGUID(); Seat.Value.Passenger.IsUnselectable = Passenger.HasFlag(UnitFields.Flags, UnitFlags.NotSelectable); if (Seat.Value.SeatInfo.CanEnterOrExit()) { Contract.Assert(Target.UsableSeatNum != 0); --Target.UsableSeatNum; if (Target.UsableSeatNum == 0) { if (Target.GetBase().IsTypeId(TypeId.Player)) { Target.GetBase().RemoveFlag64(UnitFields.NpcFlags, NPCFlags.PlayerVehicle); } else { Target.GetBase().RemoveFlag64(UnitFields.NpcFlags, NPCFlags.SpellClick); } } } Passenger.InterruptNonMeleeSpells(false); Passenger.RemoveAurasByType(AuraType.Mounted); VehicleSeatRecord veSeat = Seat.Value.SeatInfo; Player player = Passenger.ToPlayer(); if (player != null) { // drop flag Battleground bg = player.GetBattleground(); if (bg) { bg.EventPlayerDroppedFlag(player); } player.StopCastingCharm(); player.StopCastingBindSight(); player.SendOnCancelExpectedVehicleRideAura(); if (!veSeat.Flags[1].HasAnyFlag((uint)VehicleSeatFlagsB.KeepPet)) { player.UnsummonPetTemporaryIfAny(); } } if (Seat.Value.SeatInfo.Flags[0].HasAnyFlag((uint)VehicleSeatFlags.PassengerNotSelectable)) { Passenger.SetFlag(UnitFields.Flags, UnitFlags.NotSelectable); } Passenger.m_movementInfo.transport.pos.Relocate(veSeat.AttachmentOffset.X, veSeat.AttachmentOffset.Y, veSeat.AttachmentOffset.Z); Passenger.m_movementInfo.transport.time = 0; Passenger.m_movementInfo.transport.seat = Seat.Key; Passenger.m_movementInfo.transport.guid = Target.GetBase().GetGUID(); if (Target.GetBase().IsTypeId(TypeId.Unit) && Passenger.IsTypeId(TypeId.Player) && Seat.Value.SeatInfo.Flags[0].HasAnyFlag((uint)VehicleSeatFlags.CanControl)) { Contract.Assert(Target.GetBase().SetCharmedBy(Passenger, CharmType.Vehicle)); // SMSG_CLIENT_CONTROL } Passenger.SendClearTarget(); // SMSG_BREAK_TARGET Passenger.SetControlled(true, UnitState.Root); // SMSG_FORCE_ROOT - In some cases we send SMSG_SPLINE_MOVE_ROOT here (for creatures) // also adds MOVEMENTFLAG_ROOT MoveSplineInit init = new MoveSplineInit(Passenger); init.DisableTransportPathTransformations(); init.MoveTo(veSeat.AttachmentOffset.X, veSeat.AttachmentOffset.Y, veSeat.AttachmentOffset.Z, false, true); init.SetFacing(0.0f); init.SetTransportEnter(); init.Launch(); Creature creature = Target.GetBase().ToCreature(); if (creature != null) { if (creature.IsAIEnabled) { creature.GetAI().PassengerBoarded(Passenger, Seat.Key, true); } Global.ScriptMgr.OnAddPassenger(Target, Passenger, Seat.Key); // Actually quite a redundant hook. Could just use OnAddPassenger and check for unit typemask inside script. if (Passenger.HasUnitTypeMask(UnitTypeMask.Accessory)) { Global.ScriptMgr.OnInstallAccessory(Target, Passenger.ToCreature()); } } return(true); }
public void RemoveCharmedBy(Unit charmer) { if (!IsCharmed()) { return; } if (!charmer) { charmer = GetCharmer(); } if (charmer != GetCharmer()) // one aura overrides another? { return; } 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) GetHostileRefManager().DeleteReferences(); GetThreatManager().ClearAllThreat(); if (_oldFactionId != 0) { SetFaction(_oldFactionId); _oldFactionId = 0; } else { RestoreFaction(); } ///@todo Handle SLOT_IDLE motion resume GetMotionMaster().InitDefault(); Creature creature = ToCreature(); if (creature) { // Creature will restore its old AI on next update if (creature.GetAI() != null) { creature.GetAI().OnCharmed(false); } // Vehicle should not attack its passenger after he exists the seat if (type != CharmType.Vehicle) { LastCharmerGUID = charmer ? charmer.GetGUID() : ObjectGuid.Empty; } } // If charmer still exists if (!charmer) { return; } 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.PlayerControlled); break; case CharmType.Possess: playerCharmer.SetClientControl(this, false); playerCharmer.SetClientControl(charmer, true); charmer.RemoveUnitFlag(UnitFlags.RemoveClientControl); RemoveUnitFlag(UnitFlags.PlayerControlled); ClearUnitState(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) { 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) { if (charmer.IsTypeId(TypeId.Unit)) // charmed by a creature, this means we had PlayerAI { NeedChangeAI = true; IsAIEnabled = false; } player.SetClientControl(this, true); } // a guardian should always have charminfo if (playerCharmer && this != charmer.GetFirstControlled()) { playerCharmer.SendRemoveControlBar(); } else if (IsTypeId(TypeId.Player) || (IsTypeId(TypeId.Unit) && !IsGuardian())) { DeleteCharmInfo(); } }