void Vehicle::AddPassenger(Unit *unit, int8 seatId, bool force) { SeatMap::iterator seat; seat = m_Seats.find(seatId); // this should never happen if(seat == m_Seats.end()) return; unit->SetVehicleGUID(GetGUID()); seat->second.passenger = unit; if(unit->GetTypeId() == TYPEID_UNIT && ((Creature*)unit)->isVehicle()) { if(((Vehicle*)unit)->GetEmptySeatsCount(true) == 0) seat->second.flags = SEAT_VEHICLE_FULL; else seat->second.flags = SEAT_VEHICLE_FREE; } else { seat->second.flags = SEAT_FULL; } if(unit->GetTypeId() == TYPEID_PLAYER) { WorldPacket data0(SMSG_FORCE_MOVE_ROOT, 10); data0 << unit->GetPackGUID(); data0 << (uint32)((seat->second.vs_flags & SF_CAN_CAST) ? 2 : 0); unit->SendMessageToSet(&data0,true); } if(seat->second.vs_flags & SF_MAIN_RIDER) { if(!(GetVehicleFlags() & VF_MOVEMENT)) { GetMotionMaster()->Clear(false); GetMotionMaster()->MoveIdle(); SetCharmerGUID(unit->GetGUID()); unit->SetUInt64Value(UNIT_FIELD_CHARM, GetGUID()); if(unit->GetTypeId() == TYPEID_PLAYER) { ((Player*)unit)->SetMover(this); ((Player*)unit)->SetMoverInQueve(this); ((Player*)unit)->SetClientControl(this, 1); } if(canFly() || HasAuraType(SPELL_AURA_FLY) || HasAuraType(SPELL_AURA_MOD_FLIGHT_SPEED_MOUNTED)) { WorldPacket data3(SMSG_MOVE_SET_CAN_FLY, 12); data3<< GetPackGUID(); data3 << (uint32)(0); SendMessageToSet(&data3,false); } } SpellClickInfoMapBounds clickPair = sObjectMgr.GetSpellClickInfoMapBounds(GetEntry()); for(SpellClickInfoMap::const_iterator itr = clickPair.first; itr != clickPair.second; ++itr) { if (unit->GetTypeId() == TYPEID_UNIT || itr->second.IsFitToRequirements((Player*)unit)) { Unit *caster = (itr->second.castFlags & 0x1) ? unit : this; Unit *target = (itr->second.castFlags & 0x2) ? unit : this; caster->CastSpell(target, itr->second.spellId, true); } } if(unit->GetTypeId() == TYPEID_PLAYER) { // it should be added only on rider enter? if(((Player*)unit)->GetGroup()) ((Player*)unit)->SetGroupUpdateFlag(GROUP_UPDATE_VEHICLE); ((Player*)unit)->GetCamera().SetView(this); BuildVehicleActionBar((Player*)unit); } if(!(GetVehicleFlags() & VF_FACTION)) setFaction(unit->getFaction()); if(GetVehicleFlags() & VF_CANT_MOVE) { WorldPacket data2(SMSG_FORCE_MOVE_ROOT, 10); data2<< GetPackGUID(); data2 << (uint32)(2); SendMessageToSet(&data2,false); } if(GetVehicleFlags() & VF_NON_SELECTABLE) SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); } if(seat->second.vs_flags & SF_UNATTACKABLE) unit->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); EmptySeatsCountChanged(); }
void Vehicle::_AddToSlot(Unit* pPassenger, uint8 slot) { assert( slot < m_seatSlotMax ); if(pPassenger->IsPlayer() && TO_PLAYER(pPassenger)->m_CurrentCharm) return; if(pPassenger->IsPlayer() && TO_PLAYER(pPassenger)->m_isGmInvisible) { sChatHandler.GreenSystemMessage(TO_PLAYER(pPassenger)->GetSession(), "Please turn off invis before entering vehicle."); return; } CreatureProtoVehicle* vehicleproto = CreatureProtoVehicleStorage.LookupEntry(GetEntry()); m_passengers[slot] = pPassenger; LocationVector v; v.x = m_vehicleSeats[slot]->m_attachmentOffsetX; /* pPassenger->m_TransporterX = */ v.y = m_vehicleSeats[slot]->m_attachmentOffsetY; /* pPassenger->m_TransporterY = */ v.z = m_vehicleSeats[slot]->m_attachmentOffsetZ; /* pPassenger->m_TransporterZ = */ v.o = 0; /* pPassenger->m_TransporterO = */ //pPassenger->m_transportPosition =& v; // This is handled elsewhere, do not initialize here. pPassenger->movement_info.flags |= MOVEFLAG_TAXI; pPassenger->movement_info.transX = v.x; pPassenger->movement_info.transY = v.y; pPassenger->movement_info.transZ = v.z; pPassenger->movement_info.transO = GetOrientation(); pPassenger->movement_info.transSeat = slot; pPassenger->movement_info.transGuid = WoWGuid(GetGUID()); pPassenger->SetSeatID(slot); pPassenger->m_TransporterGUID = GetGUID(); if( m_CastSpellOnMount ) pPassenger->CastSpell( pPassenger, m_CastSpellOnMount, true ); RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SELF_RES); // This is where the real magic happens if( pPassenger->IsPlayer() ) { Player* pPlayer = TO_PLAYER(pPassenger); //pPlayer->Root(); //Dismount if(pPlayer->m_MountSpellId && pPlayer->m_MountSpellId != m_mountSpell) pPlayer->RemoveAura(pPlayer->m_MountSpellId); //Remove morph spells if(pPlayer->GetUInt32Value(UNIT_FIELD_DISPLAYID) != pPlayer->GetUInt32Value(UNIT_FIELD_NATIVEDISPLAYID)) { pPlayer->RemoveAllAurasOfType(SPELL_AURA_TRANSFORM); pPlayer->RemoveAllAurasOfType(SPELL_AURA_MOD_SHAPESHIFT); } //Dismiss any pets if(pPlayer->GetSummon()) { if(pPlayer->GetSummon()->GetUInt32Value(UNIT_CREATED_BY_SPELL) > 0) pPlayer->GetSummon()->Dismiss(false); // warlock summon -> dismiss else pPlayer->GetSummon()->Remove(false, true, true); // hunter pet -> just remove for later re-call } pPlayer->SetVehicle(this); pPlayer->SetUInt64Value(PLAYER_FARSIGHT, GetGUID()); pPlayer->SetPlayerStatus(TRANSFER_PENDING); sEventMgr.AddEvent(pPlayer, &Player::CheckPlayerStatus, (uint8)TRANSFER_PENDING, EVENT_PLAYER_CHECK_STATUS_Transfer, 5000, 0, 0); pPlayer->m_sentTeleportPosition.ChangeCoords(GetPositionX(), GetPositionY(), GetPositionZ()); WorldPacket data(SMSG_MONSTER_MOVE_TRANSPORT, 100); data << pPlayer->GetNewGUID(); // Passengerguid data << GetNewGUID(); // Transporterguid (vehicleguid) data << uint8(slot); // Vehicle Seat ID data << uint8(0); // Unknown data << GetPositionX() - pPlayer->GetPositionX(); // OffsetTransporterX data << GetPositionY() - pPlayer->GetPositionY(); // OffsetTransporterY data << GetPositionZ() - pPlayer->GetPositionZ(); // OffsetTransporterZ data << getMSTime(); // Timestamp data << uint8(0x04); // Flags data << float(0); // Orientation Offset data << uint32(MOVEFLAG_TB_MOVED); // MovementFlags data << uint32(0); // MoveTime data << uint32(1); // Points data << v.x; // GetTransOffsetX(); data << v.y; // GetTransOffsetY(); data << v.z; // GetTransOffsetZ(); SendMessageToSet(&data, true); if(vehicleproto) { // We have proto, no accessory in slot, and slot sets unselectable, unlike some seats if(!vehicleproto->seats[slot].accessoryentry && vehicleproto->seats[slot].unselectableaccessory) pPlayer->SetFlag(UNIT_FIELD_FLAGS, (UNIT_FLAG_UNKNOWN_5 | UNIT_FLAG_PREPARATION | UNIT_FLAG_NOT_SELECTABLE)); } else pPlayer->SetFlag(UNIT_FIELD_FLAGS, (UNIT_FLAG_UNKNOWN_5 | UNIT_FLAG_PREPARATION | UNIT_FLAG_NOT_SELECTABLE)); if(slot == 0) { if(m_vehicleSeats[slot]->IsControllable()) { m_redirectSpellPackets = pPlayer; SetSpeed(RUN, m_runSpeed); SetSpeed(FLY, m_flySpeed); // send "switch mover" packet data.Initialize(SMSG_CLIENT_CONTROL_UPDATE); data << GetNewGUID() << uint8(1); pPlayer->GetSession()->SendPacket(&data); pPlayer->m_CurrentCharm = TO_UNIT(this); pPlayer->SetUInt64Value(UNIT_FIELD_CHARM, GetGUID()); SetUInt64Value(UNIT_FIELD_CHARMEDBY, pPlayer->GetGUID()); SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED_CREATURE); if(!m_faction || m_faction->ID == 35 || m_faction->ID == 2105) { SetCharmTempVal(pPlayer->GetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE)); SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, pPlayer->GetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE)); } if(vehicleproto && vehicleproto->healthfromdriver) { uint32 health = GetUInt32Value(UNIT_FIELD_HEALTH); uint32 maxhealth = GetUInt32Value(UNIT_FIELD_MAXHEALTH); uint32 healthdiff = maxhealth - health; SetUInt32Value(UNIT_FIELD_MAXHEALTH, (maxhealth+((pPlayer->GetTotalItemLevel())*(vehicleproto->healthunitfromitemlev)))); SetUInt32Value(UNIT_FIELD_HEALTH, (health+((pPlayer->GetTotalItemLevel())*(vehicleproto->healthunitfromitemlev))) - healthdiff); } SendSpells(GetEntry(), pPlayer); if(pPlayer->HasAura(62064)) { uint32 stack = pPlayer->FindActiveAura(62064)->stackSize; AddAura(new Aura(dbcSpell.LookupEntry(62064),-1,this,this)); FindActiveAura(62064)->ModStackSize(stack); } } } else { data.Initialize(SMSG_CLIENT_CONTROL_UPDATE); data << GetNewGUID() << uint8(0); pPlayer->GetSession()->SendPacket(&data); } data.Initialize(SMSG_PET_DISMISS_SOUND); data << uint32(m_vehicleSeats[slot]->m_enterUISoundID); data << pPlayer->GetPosition(); pPlayer->GetSession()->SendPacket(&data); ++m_ppassengerCount; } else { pPassenger->SetVehicle(this); if(vehicleproto != NULL) if(vehicleproto->seats[slot].accessoryentry == pPassenger->GetEntry()) if(vehicleproto->seats[slot].unselectableaccessory == true) pPassenger->SetFlag(UNIT_FIELD_FLAGS, (UNIT_FLAG_UNKNOWN_5 | UNIT_FLAG_PREPARATION | UNIT_FLAG_NOT_SELECTABLE)); else pPassenger->SetFlag(UNIT_FIELD_FLAGS, (UNIT_FLAG_UNKNOWN_5 | UNIT_FLAG_PREPARATION)); else pPassenger->SetFlag(UNIT_FIELD_FLAGS, (UNIT_FLAG_UNKNOWN_5 | UNIT_FLAG_PREPARATION | UNIT_FLAG_NOT_SELECTABLE)); pPassenger->SetPosition(GetPositionX()+v.x, GetPositionY()+v.y, GetPositionZ()+v.z, GetOrientation()); } SendHeartBeatMsg(false); if(IsFull()) RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); if(canFly()) EnableFlight(); _setFaction(); }
bool Class::isMobile(const MWWorld::Ptr& ptr) const { return canSwim(ptr) || canWalk(ptr) || canFly(ptr); }
void Vehicle::RemovePassenger(Unit* pPassenger) { if(pPassenger == NULL) // We have enough problems that we need to do this :( return; uint8 slot = pPassenger->GetSeatID(); pPassenger->SetVehicle(NULL); pPassenger->SetSeatID(NULL); pPassenger->RemoveFlag(UNIT_FIELD_FLAGS, (UNIT_FLAG_UNKNOWN_5 | UNIT_FLAG_PREPARATION | UNIT_FLAG_NOT_SELECTABLE)); if( pPassenger->IsPlayer() && TO_PLAYER(pPassenger)->m_MountSpellId != m_mountSpell ) pPassenger->RemoveAura(TO_PLAYER(pPassenger)->m_MountSpellId); if( m_mountSpell ) pPassenger->RemoveAura( m_mountSpell ); if( m_CastSpellOnMount ) pPassenger->RemoveAura( m_CastSpellOnMount ); WorldPacket data(SMSG_MONSTER_MOVE, 85); data << pPassenger->GetNewGUID(); // PlayerGUID data << uint8(0x40); // Unk - blizz uses 0x40 data << pPassenger->GetPosition(); // Player Position xyz data << getMSTime(); // Timestamp data << uint8(0x4); // Flags data << pPassenger->GetOrientation(); // Orientation data << uint32(MOVEFLAG_AIR_SUSPENSION); // MovementFlags data << uint32(0); // MovementTime data << uint32(1); // Pointcount data << GetPosition(); // Vehicle Position xyz SendMessageToSet(&data, false); pPassenger->movement_info.flags &= ~MOVEFLAG_TAXI; pPassenger->movement_info.transX = 0; pPassenger->movement_info.transY = 0; pPassenger->movement_info.transZ = 0; pPassenger->movement_info.transO = 0; pPassenger->movement_info.transTime = 0; pPassenger->movement_info.transSeat = 0; pPassenger->movement_info.transGuid = WoWGuid(uint64(NULL)); if(pPassenger->IsPlayer()) { Player* plr = TO_PLAYER(pPassenger); if(plr == GetControllingUnit()) { plr->m_CurrentCharm = NULL; data.Initialize(SMSG_CLIENT_CONTROL_UPDATE); data << GetNewGUID() << (uint8)0; plr->GetSession()->SendPacket(&data); } RemoveFlag(UNIT_FIELD_FLAGS, (UNIT_FLAG_PLAYER_CONTROLLED_CREATURE | UNIT_FLAG_PLAYER_CONTROLLED)); plr->SetPlayerStatus(TRANSFER_PENDING); // We get an ack later, if we don't set this now, we get disconnected. sEventMgr.AddEvent(plr, &Player::CheckPlayerStatus, (uint8)TRANSFER_PENDING, EVENT_PLAYER_CHECK_STATUS_Transfer, 5000, 0, 0); plr->m_sentTeleportPosition.ChangeCoords(GetPositionX(), GetPositionY(), GetPositionZ()); plr->SetPosition(GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation()); data.Initialize(MSG_MOVE_TELEPORT_ACK); data << plr->GetNewGUID(); data << plr->m_teleportAckCounter; plr->m_teleportAckCounter++; data << uint32(MOVEFLAG_FLYING); data << uint16(0x40); data << getMSTime(); data << GetPositionX(); data << GetPositionY(); data << GetPositionZ(); data << GetOrientation(); data << uint32(0); plr->GetSession()->SendPacket(&data); plr->SetUInt64Value( PLAYER_FARSIGHT, 0 ); data.Initialize(SMSG_PET_DISMISS_SOUND); data << uint32(m_vehicleSeats[slot]->m_exitUISoundID); data << plr->GetPosition(); plr->GetSession()->SendPacket(&data); data.Initialize(SMSG_PET_SPELLS); data << uint64(0); data << uint32(0); plr->GetSession()->SendPacket(&data); CreatureProtoVehicle* vehicleproto = CreatureProtoVehicleStorage.LookupEntry(GetEntry()); if(vehicleproto && vehicleproto->healthfromdriver) { if(slot == 0) { uint32 health = GetUInt32Value(UNIT_FIELD_HEALTH); uint32 maxhealth = GetUInt32Value(UNIT_FIELD_MAXHEALTH); uint32 protomaxhealth = GetProto()->MaxHealth; uint32 healthdiff = maxhealth - health; uint32 plritemlevel = plr->GetTotalItemLevel(); uint32 convrate = vehicleproto->healthunitfromitemlev; if(plritemlevel != 0 && convrate != 0) { uint32 healthloss = healthdiff+plritemlevel*convrate; SetUInt32Value(UNIT_FIELD_HEALTH, GetProto()->MaxHealth - healthloss); } else if(protomaxhealth > healthdiff) SetUInt32Value(UNIT_FIELD_HEALTH, protomaxhealth-healthdiff); else SetUInt32Value(UNIT_FIELD_HEALTH, 1); SetUInt32Value(UNIT_FIELD_MAXHEALTH, protomaxhealth); } } } if(slot == 0) { m_redirectSpellPackets = NULLPLR; CombatStatus.Vanished(); pPassenger->SetUInt64Value( UNIT_FIELD_CHARM, 0 ); SetUInt64Value(UNIT_FIELD_CHARMEDBY, 0); if(!m_faction || m_faction->ID == 35 || m_faction->ID == 2105) SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, GetCharmTempVal()); RemoveAura(62064); } SendHeartBeatMsg(false); m_passengers[slot] = NULL; pPassenger->m_TransporterGUID = NULL; // We need to null this out if(pPassenger->IsPlayer()) --m_ppassengerCount; //note: this is not blizz like we should despawn //and respawn at spawn point. //Well actually this is how blizz wanted it //but they couldnt get it to work xD bool haspassengers = false; for(uint8 i = 0; i < m_seatSlotMax; i++) { if(m_passengers[i] != NULL && m_passengers[i]->IsPlayer()) { haspassengers = true; break; } } if(!haspassengers && !GetVehicle()) // Passenger and accessory checks. { if( m_spawn == NULL ) SafeDelete(); } if(!IsFull()) SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); if(canFly()) DisableFlight(); _setFaction(); }
bool Vehicle::LoadFromDB(uint32 guid, Map *map) { CreatureData const* data = objmgr.GetCreatureData(guid); if(!data) { sLog.outErrorDb("Creature (GUID: %u) not found in table `creature`, can't load. ",guid); return false; } uint32 id = 0; if(const CreatureInfo *cInfo = objmgr.GetCreatureTemplate(data->id)) id = cInfo->VehicleId; if(!id || !sVehicleStore.LookupEntry(id)) return false; m_DBTableGuid = guid; if (map->GetInstanceId() != 0) guid = objmgr.GenerateLowGuid(HIGHGUID_VEHICLE); uint16 team = 0; if(!Create(guid,map,data->phaseMask,data->id,id,team,data->posX,data->posY,data->posZ,data->orientation,data)) return false; //We should set first home position, because then AI calls home movement SetHomePosition(data->posX,data->posY,data->posZ,data->orientation); m_respawnradius = data->spawndist; m_respawnDelay = data->spawntimesecs; m_isDeadByDefault = data->is_dead; m_deathState = m_isDeadByDefault ? DEAD : ALIVE; m_respawnTime = objmgr.GetCreatureRespawnTime(m_DBTableGuid,GetInstanceId()); if(m_respawnTime > time(NULL)) // not ready to respawn { m_deathState = DEAD; if(canFly()) { float tz = GetMap()->GetHeight(data->posX,data->posY,data->posZ,false); if(data->posZ - tz > 0.1) Relocate(data->posX,data->posY,tz); } } else if(m_respawnTime) // respawn time set but expired { m_respawnTime = 0; objmgr.SaveCreatureRespawnTime(m_DBTableGuid,GetInstanceId(),0); } uint32 curhealth = data->curhealth; if(curhealth) { curhealth = uint32(curhealth*_GetHealthMod(GetCreatureInfo()->rank)); if(curhealth < 1) curhealth = 1; } SetHealth(m_deathState == ALIVE ? curhealth : 0); SetPower(POWER_MANA,data->curmana); // checked at creature_template loading m_defaultMovementType = MovementGeneratorType(data->movementType); m_creatureData = data; return true; }