bool TransportKit::AddPassenger(WorldObject* passenger, Position const& transportPos) { // possible requires check for board possibility here and return false // Calculate passengers local position, if not provided BoardPassenger(passenger, transportPos.IsEmpty() ? CalculateBoardingPositionOf(passenger->GetPosition()) : transportPos, -1); DETAIL_FILTER_LOG(LOG_FILTER_TRANSPORT_MOVES,"TransportKit::AddPassenger %s boarded on %s offset %f %f %f", passenger->GetObjectGuid().GetString().c_str(), GetBase()->GetObjectGuid().GetString().c_str(), transportPos.getX(), transportPos.getY(), transportPos.getZ()); return true; }
/** * This function will board a passenger onto a vehicle * * @param passenger MUST be provided. This Unit will be boarded onto the vehicles (if it checks out) * @param seat Seat to which the passenger will be boarded (if can, elsewise an alternative will be selected if possible) */ void VehicleInfo::Board(Unit* passenger, uint8 seat) { MANGOS_ASSERT(passenger); DEBUG_LOG("VehicleInfo::Board: Try to board passenger %s to seat %u", passenger->GetGuidStr().c_str(), seat); // This check is also called in Spell::CheckCast() if (!CanBoard(passenger)) return; // Use the planned seat only if the seat is valid, possible to choose and empty if (!IsSeatAvailableFor(passenger, seat)) if (!GetUsableSeatFor(passenger, seat)) return; VehicleSeatEntry const* seatEntry = GetSeatEntry(seat); MANGOS_ASSERT(seatEntry); // ToDo: Unboard passenger from a MOTransport when they are properly implemented /*if (TransportInfo* transportInfo = passenger->GetTransportInfo()) { WorldObject* transporter = transportInfo->GetTransport(); // Must be a MO transporter MANGOS_ASSERT(transporter->GetObjectGuid().IsMOTransport()); ((Transport*)transporter)->UnBoardPassenger(passenger); }*/ DEBUG_LOG("VehicleInfo::Board: Board passenger: %s to seat %u", passenger->GetGuidStr().c_str(), seat); // Calculate passengers local position float lx, ly, lz, lo; CalculateBoardingPositionOf(passenger->GetPositionX(), passenger->GetPositionY(), passenger->GetPositionZ(), passenger->GetOrientation(), lx, ly, lz, lo); BoardPassenger(passenger, lx, ly, lz, lo, seat); // Use TransportBase to store the passenger // Set data for createobject packets passenger->m_movementInfo.SetTransportData(m_owner->GetObjectGuid(), lx, ly, lz, lo, 0, seat); if (passenger->GetTypeId() == TYPEID_PLAYER) { Player* pPlayer = (Player*)passenger; pPlayer->RemovePet(PET_SAVE_AS_CURRENT); WorldPacket data(SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA); pPlayer->GetSession()->SendPacket(&data); // SMSG_BREAK_TARGET (?) } if (!passenger->IsRooted()) passenger->SetRoot(true); Movement::MoveSplineInit init(*passenger); init.MoveTo(0.0f, 0.0f, 0.0f); // ToDo: Set correct local coords init.SetFacing(0.0f); // local orientation ? ToDo: Set proper orientation! init.SetBoardVehicle(); init.Launch(); // Apply passenger modifications ApplySeatMods(passenger, seatEntry->m_flags); }
bool VehicleKit::AddPassenger(Unit* passenger, int8 seatId) { SeatMap::iterator seat; if (seatId < 0) // no specific seat requirement { for (seat = m_Seats.begin(); seat != m_Seats.end(); ++seat) { if (!seat->second.passenger && (seat->second.seatInfo->IsUsable() || (seat->second.seatInfo->m_flags & SEAT_FLAG_UNCONTROLLED))) break; } if (seat == m_Seats.end()) // no available seat return false; } else { seat = m_Seats.find(seatId); if (seat == m_Seats.end()) return false; if (seat->second.passenger) return false; } VehicleSeatEntry const* seatInfo = seat->second.seatInfo; seat->second.passenger = passenger->GetObjectGuid(); seat->second.b_dismount = true; if (!(seatInfo->m_flags & SEAT_FLAG_FREE_ACTION)) passenger->addUnitState(UNIT_STAT_ON_VEHICLE); GetBase()->SetPhaseMask(passenger->GetPhaseMask(), true); // Calculate passengers local position float lx, ly, lz, lo; CalculateBoardingPositionOf(passenger->GetPositionX(), passenger->GetPositionY(), passenger->GetPositionZ(), passenger->GetOrientation(), lx, ly, lz, lo); BoardPassenger(passenger, lx, ly, lz, lo, seat->first); // Use TransportBase to store the passenger passenger->m_movementInfo.ClearTransportData(); passenger->m_movementInfo.AddMovementFlag(MOVEFLAG_ONTRANSPORT); passenger->m_movementInfo.SetTransportData(GetBase()->GetObjectGuid(), lx, ly, lz, lo, WorldTimer::getMSTime(), seat->first, seatInfo); if (passenger->GetTypeId() == TYPEID_PLAYER) { ((Player*)passenger)->SetViewPoint(GetBase()); passenger->SetRoot(true); } if (seat->second.IsProtectPassenger()) { switch (GetBase()->GetEntry()) { case 33651: // VX 001 case 33432: // Leviathan MX case 33118: // Ignis (Ulduar) case 30234: // Nexus Lord's Hover Disk (Eye of Eternity, Malygos Encounter) case 30248: // Scion's of Eternity Hover Disk (Eye of Eternity, Malygos Encounter) break; case 28817: default: passenger->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); break; } passenger->RemoveSpellsCausingAura(SPELL_AURA_MOD_SHAPESHIFT); } if (seatInfo->m_flags & SEAT_FLAG_CAN_CONTROL) { if (!(GetEntry()->m_flags & (VEHICLE_FLAG_ACCESSORY))) { GetBase()->StopMoving(); GetBase()->GetMotionMaster()->Clear(); GetBase()->CombatStop(true); } GetBase()->DeleteThreatList(); GetBase()->getHostileRefManager().deleteReferences(); GetBase()->SetCharmerGuid(passenger->GetObjectGuid()); GetBase()->addUnitState(UNIT_STAT_CONTROLLED); passenger->SetCharm(GetBase()); if (GetBase()->HasAuraType(SPELL_AURA_FLY) || GetBase()->HasAuraType(SPELL_AURA_MOD_FLIGHT_SPEED)) { WorldPacket data; data.Initialize(SMSG_MOVE_SET_CAN_FLY, 12); data << GetBase()->GetPackGUID(); data << (uint32)(0); GetBase()->SendMessageToSet(&data,false); } if (passenger->GetTypeId() == TYPEID_PLAYER) { GetBase()->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED); if (CharmInfo* charmInfo = GetBase()->InitCharmInfo(GetBase())) { charmInfo->SetState(CHARM_STATE_ACTION,ACTIONS_DISABLE); charmInfo->InitVehicleCreateSpells(seat->first); } Player* player = (Player*)passenger; player->SetMover(GetBase()); player->SetClientControl(GetBase(), 1); player->VehicleSpellInitialize(); } if(!(((Creature*)GetBase())->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_KEEP_AI)) ((Creature*)GetBase())->AIM_Initialize(); if (GetBase()->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE)) { GetBase()->SetRoot(true); } else if (passenger->IsWalking() && !GetBase()->IsWalking()) ((Creature*)GetBase())->SetWalk(true, true); else if (!passenger->IsWalking() && GetBase()->IsWalking()) ((Creature*)GetBase())->SetWalk(false, true); } else if ((seatInfo->m_flags & SEAT_FLAG_FREE_ACTION) || (seatInfo->m_flags & SEAT_FLAG_CAN_ATTACK)) { if (passenger->GetTypeId() == TYPEID_PLAYER) { Player* player = (Player*)passenger; player->SetClientControl(GetBase(), 0); } } // need correct, position not normalized currently passenger->GetMotionMaster()->MoveBoardVehicle(seatInfo->m_attachmentOffsetX, seatInfo->m_attachmentOffsetY, seatInfo->m_attachmentOffsetZ, seatInfo->m_passengerYaw, seatInfo->m_enterSpeed < M_NULL_F ? BASE_CHARGE_SPEED : seatInfo->m_enterSpeed, 0.0f); UpdateFreeSeatCount(); if (GetBase()->GetTypeId() == TYPEID_UNIT) { if (((Creature*)GetBase())->AI()) ((Creature*)GetBase())->AI()->PassengerBoarded(passenger, seat->first, true); } if (passenger->GetTypeId() == TYPEID_UNIT) { if (((Creature*)passenger)->AI()) ((Creature*)passenger)->AI()->EnteredVehicle(GetBase(), seat->first, true); } if (b_dstSet && (seatInfo->m_flagsB & VEHICLE_SEAT_FLAG_B_EJECTABLE_FORCED)) { uint32 delay = seatInfo->m_exitMaxDuration * IN_MILLISECONDS; GetBase()->AddEvent(new PassengerEjectEvent(seatId,*GetBase()), delay); DEBUG_LOG("Vehicle::AddPassenger eject event for %s added, delay %u",passenger->GetObjectGuid().GetString().c_str(), delay); } DEBUG_LOG("VehicleKit::AddPassenger passenger %s boarded on %s, transport offset %f %f %f %f (parent - %s)", passenger->GetObjectGuid().GetString().c_str(), passenger->m_movementInfo.GetTransportGuid().GetString().c_str(), passenger->m_movementInfo.GetTransportPos()->x, passenger->m_movementInfo.GetTransportPos()->y, passenger->m_movementInfo.GetTransportPos()->z, passenger->m_movementInfo.GetTransportPos()->o, GetBase()->m_movementInfo.GetTransportGuid().IsEmpty() ? "<none>" : GetBase()->m_movementInfo.GetTransportGuid().GetString().c_str()); return true; }
bool VehicleKit::AddPassenger(Unit* passenger, SeatId seatId) { SeatMap::iterator seat; if (seatId < 0) // no specific seat requirement { for (seat = m_Seats.begin(); seat != m_Seats.end(); ++seat) { if (!seat->second.passengerGuid && (seat->second.seatInfo->IsUsable() || (seat->second.seatInfo->m_flags & SEAT_FLAG_UNCONTROLLED))) break; } if (seat == m_Seats.end()) // no available seat return false; } else { seat = m_Seats.find(seatId); if (seat == m_Seats.end()) return false; if (seat->second.passengerGuid) return false; } VehicleSeatEntry const* seatInfo = seat->second.seatInfo; seat->second.passengerGuid = passenger->GetObjectGuid(); seat->second.b_dismount = true; if (!(seatInfo->m_flags & SEAT_FLAG_FREE_ACTION)) passenger->addUnitState(UNIT_STAT_ON_VEHICLE); GetBase()->SetPhaseMask(passenger->GetPhaseMask(), true); // Calculate passengers local position Position localPos = CalculateBoardingPositionOf(passenger->GetPosition()); BoardPassenger(passenger, localPos, seat->first); // Use TransportBase to store the passenger if (passenger->GetTypeId() == TYPEID_PLAYER) { ((Player*)passenger)->SetViewPoint(GetBase()); ((Player*)passenger)->SetGravity(false); passenger->SetRoot(true, (seatInfo->m_flags & (SEAT_FLAG_CAN_CAST | SEAT_FLAG_CAN_ATTACK) ? 2 : 0)); } if (seat->second.IsProtectPassenger()) { // make passenger attackable in some vehicles and allow him to cast when sitting on vehicle switch (GetBase()->GetEntry()) { case 29625: // Hyldsmeet Proto-Drake case 30234: // Nexus Lord's Hover Disk (Eye of Eternity, Malygos Encounter) case 30248: // Scion's of Eternity Hover Disk (Eye of Eternity, Malygos Encounter) case 33118: // Ignis (Ulduar) case 33432: // Leviathan MX case 33651: // VX 001 break; // case 28817: // Mine Car (quest Massacre At Light's Point) // case 28864: // Scourge Gryphon (quest Massacre At Light's Point) default: passenger->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); break; } passenger->RemoveSpellsCausingAura(SPELL_AURA_MOD_SHAPESHIFT); } if (passenger->GetTypeId() == TYPEID_UNIT) { if (seatInfo->m_flags & SEAT_FLAG_NOT_SELECTABLE) passenger->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); } if ((seatInfo->m_flags & SEAT_FLAG_CAN_CONTROL) && GetBase()->GetTypeId() == TYPEID_UNIT) { if (!(GetEntry()->m_flags & VEHICLE_FLAG_ACCESSORY)) { GetBase()->StopMoving(); GetBase()->GetMotionMaster()->Clear(); GetBase()->CombatStop(true); } GetBase()->DeleteThreatList(); GetBase()->getHostileRefManager().deleteReferences(); GetBase()->SetCharmerGuid(passenger->GetObjectGuid()); GetBase()->addUnitState(UNIT_STAT_CONTROLLED); passenger->SetCharm(GetBase()); if (GetBase()->HasAuraType(SPELL_AURA_FLY) || GetBase()->HasAuraType(SPELL_AURA_MOD_FLIGHT_SPEED) || (GetBase()->GetTypeId() == TYPEID_UNIT && ((Creature*)GetBase())->CanFly())) { WorldPacket data; GetBase()->BuildMoveSetCanFlyPacket(&data, true, 0); GetBase()->SendMessageToSet(&data, false); } if (passenger->GetTypeId() == TYPEID_PLAYER) { GetBase()->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED); if (CharmInfo* charmInfo = GetBase()->InitCharmInfo(GetBase())) { charmInfo->SetState(CHARM_STATE_ACTION, ACTIONS_DISABLE); charmInfo->InitVehicleCreateSpells(seat->first); } Player* player = (Player*)passenger; player->SetMover(GetBase()); player->SetClientControl(GetBase(), 1); player->VehicleSpellInitialize(); } // Allow to keep AI of controlled vehicle with CREATURE_FLAG_EXTRA_KEEP_AI extra-flag if (!(((Creature*)GetBase())->GetCreatureInfo()->ExtraFlags & CREATURE_FLAG_EXTRA_KEEP_AI)) ((Creature*)GetBase())->AIM_Initialize(); if (GetBase()->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE)) { GetBase()->SetRoot(true); // save player's walk mode for further use in dismount ((Creature*)GetBase())->SetWalk(passenger->IsWalking(), true); } // Set owner's speedrate to vehicle at board. else if (passenger->IsWalking() && !GetBase()->IsWalking()) ((Creature*)GetBase())->SetWalk(true, true); else if (!passenger->IsWalking() && GetBase()->IsWalking()) ((Creature*)GetBase())->SetWalk(false, true); } else if ((seatInfo->m_flags & SEAT_FLAG_FREE_ACTION) || (seatInfo->m_flags & SEAT_FLAG_CAN_ATTACK)) { if (passenger->GetTypeId() == TYPEID_PLAYER) ((Player*)passenger)->SetClientControl(GetBase(), 0); } // Calculate passenger seat position (FIXME - requires correct calculation!) Position seatpos = CalculateSeatPositionOf(seatInfo); passenger->GetMotionMaster()->MoveBoardVehicle(seatpos.x, seatpos.y, seatpos.z, seatpos.o, seatInfo->m_enterSpeed < M_NULL_F ? BASE_CHARGE_SPEED : seatInfo->m_enterSpeed, 0.0f); UpdateFreeSeatCount(); if (passenger->GetTypeId() == TYPEID_PLAYER) { // group update if (((Player*)passenger)->GetGroup()) ((Player*)passenger)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_VEHICLE_SEAT); } if (GetBase()->GetTypeId() == TYPEID_UNIT) { if (((Creature*)GetBase())->AI()) ((Creature*)GetBase())->AI()->PassengerBoarded(passenger, seat->first, true); } if (passenger->GetTypeId() == TYPEID_UNIT) { if (((Creature*)passenger)->AI()) { ((Creature*)passenger)->AI()->SetCombatMovement(false); ((Creature*)passenger)->AI()->EnteredVehicle(GetBase(), seat->first, true); } // Not entirely sure how this must be handled in relation to CONTROL // But in any way this at least would require some changes in the movement system most likely passenger->GetMotionMaster()->Clear(false, true); } if (m_dstSet && (seatInfo->m_flagsB & VEHICLE_SEAT_FLAG_B_EJECTABLE_FORCED)) { uint32 delay = seatInfo->m_exitMaxDuration * IN_MILLISECONDS; GetBase()->AddEvent(new PassengerEjectEvent(seatId, *GetBase()), delay); DEBUG_LOG("Vehicle::AddPassenger eject event for %s added, delay %u", passenger->GetGuidStr().c_str(), delay); } DEBUG_LOG("VehicleKit::AddPassenger passenger %s boarded on %s, transport offset %f %f %f %f (parent - %s)", passenger->GetGuidStr().c_str(), passenger->m_movementInfo.GetTransportGuid().GetString().c_str(), passenger->m_movementInfo.GetTransportPos()->x, passenger->m_movementInfo.GetTransportPos()->y, passenger->m_movementInfo.GetTransportPos()->z, passenger->m_movementInfo.GetTransportPos()->o, GetBase()->m_movementInfo.GetTransportGuid().IsEmpty() ? "<none>" : GetBase()->m_movementInfo.GetTransportGuid().GetString().c_str()); return true; }