예제 #1
0
        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);
                    }
                }
            }
        }
예제 #2
0
        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);
                        }
                    }
                }
            }
        }
예제 #3
0
        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());
            }
        }
예제 #4
0
        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);
        }
예제 #5
0
        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);
                    }
                }
            }
        }
예제 #6
0
        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();
        }
예제 #7
0
        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);
        }
예제 #8
0
        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);
                }
            }
        }
예제 #9
0
 public VehicleSeat(VehicleSeatRecord seatInfo)
 {
     SeatInfo = seatInfo;
     Passenger.Reset();
 }
예제 #10
0
        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);
        }