void HandleRequestVehicleSwitchSeat(RequestVehicleSwitchSeat packet) { Unit vehicle_base = GetPlayer().GetVehicleBase(); if (!vehicle_base) { return; } VehicleSeatRecord seat = GetPlayer().GetVehicle().GetSeatForPassenger(GetPlayer()); if (!seat.CanSwitchFromSeat()) { Log.outError(LogFilter.Network, "HandleRequestVehicleSwitchSeat: {0} tried to switch seats but current seatflags {1} don't permit that.", GetPlayer().GetGUID().ToString(), seat.Flags[0]); return; } Unit vehUnit; if (vehicle_base.GetGUID() == packet.Vehicle) { GetPlayer().ChangeSeat((sbyte)packet.SeatIndex); } else if (vehUnit = Global.ObjAccessor.GetUnit(GetPlayer(), packet.Vehicle)) { Vehicle vehicle = vehUnit.GetVehicleKit(); if (vehicle) { if (vehicle.HasEmptySeat((sbyte)packet.SeatIndex)) { vehUnit.HandleSpellClick(GetPlayer(), (sbyte)packet.SeatIndex); } } } }
void HandleMoveChangeVehicleSeats(MoveChangeVehicleSeats packet) { Unit vehicle_base = GetPlayer().GetVehicleBase(); if (!vehicle_base) { return; } VehicleSeatRecord seat = GetPlayer().GetVehicle().GetSeatForPassenger(GetPlayer()); if (!seat.CanSwitchFromSeat()) { Log.outError(LogFilter.Network, "HandleMoveChangeVehicleSeats, {0} tried to switch seats but current seatflags {1} don't permit that.", GetPlayer().GetGUID().ToString(), seat.Flags); return; } GetPlayer().ValidateMovementInfo(packet.Status); if (vehicle_base.GetGUID() != packet.Status.Guid) { return; } vehicle_base.m_movementInfo = packet.Status; if (packet.DstVehicle.IsEmpty()) { GetPlayer().ChangeSeat(-1, packet.DstSeatIndex != 255); } else { Unit vehUnit = Global.ObjAccessor.GetUnit(GetPlayer(), packet.DstVehicle); if (vehUnit) { Vehicle vehicle = vehUnit.GetVehicleKit(); if (vehicle) { if (vehicle.HasEmptySeat((sbyte)packet.DstSeatIndex)) { vehUnit.HandleSpellClick(GetPlayer(), (sbyte)packet.DstSeatIndex); } } } } }
void HandleEjectPassenger(EjectPassenger packet) { Vehicle vehicle = GetPlayer().GetVehicleKit(); if (!vehicle) { Log.outError(LogFilter.Network, "HandleEjectPassenger: {0} is not in a vehicle!", GetPlayer().GetGUID().ToString()); return; } if (packet.Passenger.IsUnit()) { Unit unit = Global.ObjAccessor.GetUnit(GetPlayer(), packet.Passenger); if (!unit) { Log.outError(LogFilter.Network, "{0} tried to eject {1} from vehicle, but the latter was not found in world!", GetPlayer().GetGUID().ToString(), packet.Passenger.ToString()); return; } if (!unit.IsOnVehicle(vehicle.GetBase())) { Log.outError(LogFilter.Network, "{0} tried to eject {1}, but they are not in the same vehicle", GetPlayer().GetGUID().ToString(), packet.Passenger.ToString()); return; } VehicleSeatRecord seat = vehicle.GetSeatForPassenger(unit); Cypher.Assert(seat != null); if (seat.IsEjectable()) { unit.ExitVehicle(); } else { Log.outError(LogFilter.Network, "{0} attempted to eject {1} from non-ejectable seat.", GetPlayer().GetGUID().ToString(), packet.Passenger.ToString()); } } else { Log.outError(LogFilter.Network, "HandleEjectPassenger: {0} tried to eject invalid {1}", GetPlayer().GetGUID().ToString(), packet.Passenger.ToString()); } }
void HandleRequestVehicleNextSeat(RequestVehicleNextSeat packet) { Unit vehicle_base = GetPlayer().GetVehicleBase(); if (!vehicle_base) { return; } VehicleSeatRecord seat = GetPlayer().GetVehicle().GetSeatForPassenger(GetPlayer()); if (!seat.CanSwitchFromSeat()) { Log.outError(LogFilter.Network, "HandleRequestVehicleNextSeat: {0} tried to switch seats but current seatflags {1} don't permit that.", GetPlayer().GetGUID().ToString(), seat.Flags); return; } GetPlayer().ChangeSeat(-1, true); }
void HandleRequestVehicleExit(RequestVehicleExit packet) { Vehicle vehicle = GetPlayer().GetVehicle(); if (vehicle) { VehicleSeatRecord seat = vehicle.GetSeatForPassenger(GetPlayer()); if (seat != null) { if (seat.CanEnterOrExit()) { GetPlayer().ExitVehicle(); } else { Log.outError(LogFilter.Network, "{0} tried to exit vehicle, but seatflags {1} (ID: {2}) don't permit that.", GetPlayer().GetGUID().ToString(), seat.Id, seat.Flags); } } } }
public Vehicle(Unit unit, VehicleRecord vehInfo, uint creatureEntry) { _me = unit; _vehicleInfo = vehInfo; _creatureEntry = creatureEntry; _status = Status.None; _lastShootPos = new Position(); for (uint i = 0; i < SharedConst.MaxVehicleSeats; ++i) { uint seatId = _vehicleInfo.SeatID[i]; if (seatId != 0) { VehicleSeatRecord veSeat = CliDB.VehicleSeatStorage.LookupByKey(seatId); if (veSeat != null) { VehicleSeatAddon addon = Global.ObjectMgr.GetVehicleSeatAddon(seatId); Seats.Add((sbyte)i, new VehicleSeat(veSeat, addon)); if (veSeat.CanEnterOrExit()) { ++UsableSeatNum; } } } } // Set or remove correct flags based on available seats. Will overwrite db data (if wrong). if (UsableSeatNum != 0) { _me.AddNpcFlag(_me.IsTypeId(TypeId.Player) ? NPCFlags.PlayerVehicle : NPCFlags.SpellClick); } else { _me.RemoveNpcFlag(_me.IsTypeId(TypeId.Player) ? NPCFlags.PlayerVehicle : NPCFlags.SpellClick); } InitMovementInfoForBase(); }
void HandleAttackSwing(AttackSwing packet) { Unit enemy = Global.ObjAccessor.GetUnit(GetPlayer(), packet.Victim); if (!enemy) { // stop attack state at client SendAttackStop(null); return; } if (!GetPlayer().IsValidAttackTarget(enemy)) { // stop attack state at client SendAttackStop(enemy); return; } //! Client explicitly checks the following before sending CMSG_ATTACKSWING packet, //! so we'll place the same check here. Note that it might be possible to reuse this snippet //! in other places as well. Vehicle vehicle = GetPlayer().GetVehicle(); if (vehicle) { VehicleSeatRecord seat = vehicle.GetSeatForPassenger(GetPlayer()); Cypher.Assert(seat != null); if (!seat.HasFlag(VehicleSeatFlags.CanAttack)) { SendAttackStop(enemy); return; } } GetPlayer().Attack(enemy, true); }
void HandleMovementOpcode(ClientOpcodes opcode, MovementInfo movementInfo) { Unit mover = GetPlayer().m_unitMovedByMe; Player plrMover = mover.ToPlayer(); if (plrMover && plrMover.IsBeingTeleported()) { return; } GetPlayer().ValidateMovementInfo(movementInfo); if (movementInfo.Guid != mover.GetGUID()) { Log.outError(LogFilter.Network, "HandleMovementOpcodes: guid error"); return; } if (!movementInfo.Pos.IsPositionValid()) { Log.outError(LogFilter.Network, "HandleMovementOpcodes: Invalid Position"); return; } // stop some emotes at player move if (plrMover && (plrMover.GetEmoteState() != 0)) { plrMover.SetEmoteState(Emote.OneshotNone); } //handle special cases if (!movementInfo.transport.guid.IsEmpty()) { // We were teleported, skip packets that were broadcast before teleport if (movementInfo.Pos.GetExactDist2d(mover) > MapConst.SizeofGrids) { return; } if (Math.Abs(movementInfo.transport.pos.GetPositionX()) > 75f || Math.Abs(movementInfo.transport.pos.GetPositionY()) > 75f || Math.Abs(movementInfo.transport.pos.GetPositionZ()) > 75f) { return; } if (!GridDefines.IsValidMapCoord(movementInfo.Pos.posX + movementInfo.transport.pos.posX, movementInfo.Pos.posY + movementInfo.transport.pos.posY, movementInfo.Pos.posZ + movementInfo.transport.pos.posZ, movementInfo.Pos.Orientation + movementInfo.transport.pos.Orientation)) { return; } if (plrMover) { if (!plrMover.GetTransport()) { Transport transport = plrMover.GetMap().GetTransport(movementInfo.transport.guid); if (transport) { transport.AddPassenger(plrMover); } } else if (plrMover.GetTransport().GetGUID() != movementInfo.transport.guid) { plrMover.GetTransport().RemovePassenger(plrMover); Transport transport = plrMover.GetMap().GetTransport(movementInfo.transport.guid); if (transport) { transport.AddPassenger(plrMover); } else { movementInfo.ResetTransport(); } } } if (!mover.GetTransport() && !mover.GetVehicle()) { GameObject go = mover.GetMap().GetGameObject(movementInfo.transport.guid); if (!go || go.GetGoType() != GameObjectTypes.Transport) { movementInfo.transport.Reset(); } } } else if (plrMover && plrMover.GetTransport()) // if we were on a transport, leave { plrMover.GetTransport().RemovePassenger(plrMover); } // fall damage generation (ignore in flight case that can be triggered also at lags in moment teleportation to another map). if (opcode == ClientOpcodes.MoveFallLand && plrMover && !plrMover.IsInFlight()) { plrMover.HandleFall(movementInfo); } // interrupt parachutes upon falling or landing in water if (opcode == ClientOpcodes.MoveFallLand || opcode == ClientOpcodes.MoveStartSwim) { mover.RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.Landing); // Parachutes } if (plrMover && movementInfo.HasMovementFlag(MovementFlag.Swimming) != plrMover.IsInWater()) { // now client not include swimming flag in case jumping under water plrMover.SetInWater(!plrMover.IsInWater() || plrMover.GetMap().IsUnderWater(plrMover.GetPhaseShift(), movementInfo.Pos.posX, movementInfo.Pos.posY, movementInfo.Pos.posZ)); } uint mstime = GameTime.GetGameTimeMS(); if (m_clientTimeDelay == 0) { m_clientTimeDelay = mstime - movementInfo.Time; } movementInfo.Time = movementInfo.Time + m_clientTimeDelay; movementInfo.Guid = mover.GetGUID(); mover.m_movementInfo = movementInfo; // Some vehicles allow the passenger to turn by himself Vehicle vehicle = mover.GetVehicle(); if (vehicle) { VehicleSeatRecord seat = vehicle.GetSeatForPassenger(mover); if (seat != null) { if (seat.HasSeatFlag(VehicleSeatFlags.AllowTurning)) { if (movementInfo.Pos.GetOrientation() != mover.GetOrientation()) { mover.SetOrientation(movementInfo.Pos.GetOrientation()); mover.RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.Turning); } } } return; } mover.UpdatePosition(movementInfo.Pos); MoveUpdate moveUpdate = new MoveUpdate(); moveUpdate.Status = mover.m_movementInfo; mover.SendMessageToSet(moveUpdate, GetPlayer()); if (plrMover) // nothing is charmed, or player charmed { if (plrMover.IsSitState() && movementInfo.HasMovementFlag(MovementFlag.MaskMoving | MovementFlag.MaskTurning)) { plrMover.SetStandState(UnitStandStateType.Stand); } plrMover.UpdateFallInformationIfNeed(movementInfo, opcode); if (movementInfo.Pos.posZ < plrMover.GetMap().GetMinHeight(plrMover.GetPhaseShift(), movementInfo.Pos.GetPositionX(), movementInfo.Pos.GetPositionY())) { if (!(plrMover.GetBattleground() && plrMover.GetBattleground().HandlePlayerUnderMap(GetPlayer()))) { // NOTE: this is actually called many times while falling // even after the player has been teleported away // @todo discard movement packets after the player is rooted if (plrMover.IsAlive()) { plrMover.AddPlayerFlag(PlayerFlags.IsOutOfBounds); plrMover.EnvironmentalDamage(EnviromentalDamage.FallToVoid, (uint)GetPlayer().GetMaxHealth()); // player can be alive if GM/etc // change the death state to CORPSE to prevent the death timer from // starting in the next player update if (plrMover.IsAlive()) { plrMover.KillPlayer(); } } } } else { plrMover.RemovePlayerFlag(PlayerFlags.IsOutOfBounds); } if (opcode == ClientOpcodes.MoveJump) { plrMover.RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.Jump, 605); // Mind Control plrMover.ProcSkillsAndAuras(null, ProcFlags.Jump, ProcFlags.None, ProcFlagsSpellType.MaskAll, ProcFlagsSpellPhase.None, ProcFlagsHit.None, null, null, null); } } }
public VehicleSeat(VehicleSeatRecord seatInfo) { SeatInfo = seatInfo; Passenger.Reset(); }
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); }