bool PassengerEjectEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/) { if (!m_vehicle.GetVehicleInfo()) return true; VehicleKit* pVehicle = m_vehicle.GetVehicleKit(); if (!pVehicle) return true; Unit* passenger = pVehicle->GetPassenger(m_seatId); if (passenger && passenger->IsInWorld() && passenger->hasUnitState(UNIT_STAT_ON_VEHICLE)) { uint32 controlSpell = 0; Unit::AuraList const& controlAuras = m_vehicle.GetAurasByType(SPELL_AURA_CONTROL_VEHICLE); for(Unit::AuraList::const_iterator i = controlAuras.begin(); i != controlAuras.end(); ++i) { if ((*i)->GetCasterGuid() == passenger->GetObjectGuid()) { controlSpell = (*i)->GetId(); break; } } if (controlSpell) { m_vehicle.RemoveAurasByCasterSpell(controlSpell, passenger->GetObjectGuid()); } else passenger->ExitVehicle(); } return true; }
void WorldSession::HandleSpellClick( WorldPacket & recv_data ) { ObjectGuid guid; recv_data >> guid; Creature* unit = _player->GetMap()->GetAnyTypeCreature(guid); if (!unit) return; if (_player->isInCombat() && !unit->IsVehicle()) // client prevent click and set different icon at combat state return; SpellClickInfoMapBounds clickPair = sObjectMgr.GetSpellClickInfoMapBounds(unit->GetEntry()); for(SpellClickInfoMap::const_iterator itr = clickPair.first; itr != clickPair.second; ++itr) { if (itr->second.IsFitToRequirements(_player, unit)) { if (sScriptMgr.OnNpcSpellClick(_player, unit, itr->second.spellId)) return; Unit* caster = (itr->second.castFlags & 0x1) ? (Unit*)_player : (Unit*)unit; Unit* target = (itr->second.castFlags & 0x2) ? (Unit*)_player : (Unit*)unit; if (itr->second.spellId) caster->CastSpell(target, itr->second.spellId, true, NULL, NULL,caster->GetObjectGuid()); else sLog.outError("WorldSession::HandleSpellClick: npc_spell_click with entry %u has 0 in spell_id. Not handled custom case?", unit->GetEntry()); } } }
void WorldSession::HandleRequestVehicleSwitchSeat(WorldPacket &recv_data) { DEBUG_LOG("WORLD: Recvd CMSG_REQUEST_VEHICLE_SWITCH_SEAT"); recv_data.hexlike(); ObjectGuid guid; recv_data >> guid.ReadAsPacked(); int8 seatId; recv_data >> seatId; Unit *pVehicleBase = GetPlayer()->GetVehicleBase(); if(!pVehicleBase) return; if (pVehicleBase->GetObjectGuid() == guid) GetPlayer()->ChangeSeat(seatId); else if (Unit *vehUnit = ObjectAccessor::GetUnit(*GetPlayer(), guid)) { if (VehicleKit *vehicle = vehUnit->GetVehicleKit()) { if (vehicle->HasEmptySeat(seatId)) GetPlayer()->EnterVehicle(vehicle, seatId); } } }
void WorldSession::HandleMoveKnockBackAck(WorldPacket& recv_data) { DEBUG_LOG("CMSG_MOVE_KNOCK_BACK_ACK"); Unit* mover = _player->GetMover(); Player* plMover = mover->GetTypeId() == TYPEID_PLAYER ? (Player*)mover : nullptr; // ignore, waiting processing in WorldSession::HandleMoveWorldportAckOpcode and WorldSession::HandleMoveTeleportAck if (plMover && plMover->IsBeingTeleported()) { recv_data.rpos(recv_data.wpos()); // prevent warnings spam return; } ObjectGuid guid; MovementInfo movementInfo; recv_data >> guid; recv_data >> Unused<uint32>(); // knockback packets counter recv_data >> movementInfo; if (!VerifyMovementInfo(movementInfo, guid)) return; HandleMoverRelocation(movementInfo); WorldPacket data(MSG_MOVE_KNOCK_BACK, recv_data.size() + 15); data << mover->GetObjectGuid(); data << movementInfo; data << movementInfo.GetJumpInfo().sinAngle; data << movementInfo.GetJumpInfo().cosAngle; data << movementInfo.GetJumpInfo().xyspeed; data << movementInfo.GetJumpInfo().velocity; mover->SendMessageToSetExcept(data, _player); }
bool PetAI::_needToStop() const { Unit* pVictim = m_creature->getVictim(); if (!pVictim) return true; // This is needed for charmed creatures, as once their target was reset other effects can trigger threat if (m_creature->isCharmed() && m_creature->GetCharmer() == pVictim) return true; Unit* owner = m_creature->GetCharmerOrOwner(); if (owner == pVictim) return true; if (!pVictim->isVisibleForOrDetect(m_creature, m_creature, false)) return true; if (owner && !pVictim->isVisibleForOrDetect(owner, owner, true)) return true; if (m_primaryTargetGuid && m_primaryTargetGuid != pVictim->GetObjectGuid()) return true; return !pVictim->isTargetableForAttack(); }
// Custom threat management bool SelectHostileTarget() { Unit* pTarget = nullptr; Unit* pOldTarget = m_creature->getVictim(); if (!m_creature->getThreatManager().isThreatListEmpty()) pTarget = m_creature->getThreatManager().getHostileTarget(); if (pTarget) { if (pOldTarget != pTarget) AttackStart(pTarget); // Set victim to old target if (pOldTarget && pOldTarget->isAlive()) { m_creature->SetTargetGuid(pOldTarget->GetObjectGuid()); m_creature->SetInFront(pOldTarget); } return true; } // Will call EnterEvadeMode if fit return m_creature->SelectHostileTarget(); }
void UpdateAI(const uint32 diff) { if (!init) { init = true; Unit* owner = m_creature->GetCreator(); if (!owner) return; summonedBySpell = m_creature->GetUInt32Value(UNIT_CREATED_BY_SPELL); m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); if (summonedBySpell == SPELL_GUARDIAN_PROT) { m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); m_creature->StopMoving(); m_creature->SetTargetGuid(owner->GetObjectGuid()); m_creature->CastSpell(owner, SPELL_ANCIENT_GUARDIAN, true); } else if (summonedBySpell == SPELL_GUARDIAN_RETRO) { owner->CastSpell(owner, SPELL_ANCIENT_CRUSADER_PLAYER, true); m_creature->CastSpell(m_creature, SPELL_ANCIENT_CRUSADER_PET, true); } else if (summonedBySpell == SPELL_GUARDIAN_HOLY) owner->CastSpell(owner, SPELL_ANCIENT_HEALER, true); } else { if (summonedBySpell == SPELL_GUARDIAN_RETRO) { Unit* owner = m_creature->GetOwner(); Unit* ownerVictim = owner ? owner->getVictim() : NULL; if (m_creature->getVictim()) { if (m_creature->getVictim()->hasUnitState(UNIT_STAT_NO_FREE_MOVE)) { m_creature->AttackStop(); return; } else if (ownerVictim && m_creature->getVictim() != ownerVictim && !ownerVictim->hasUnitState(UNIT_STAT_NO_FREE_MOVE)) AttackStart(ownerVictim); } else if (ownerVictim && !ownerVictim->hasUnitState(UNIT_STAT_NO_FREE_MOVE)) AttackStart(ownerVictim); } } if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; if (!m_creature->IsNonMeleeSpellCasted(false)) return; if (summonedBySpell == SPELL_GUARDIAN_RETRO) DoMeleeAttackIfReady(); }
// Custom threat management bool SelectHostileTarget() { Unit* pTarget = NULL; Unit* pOldTarget = m_creature->getVictim(); if (!m_creature->getThreatManager().isThreatListEmpty()) pTarget = m_creature->getThreatManager().getHostileTarget(); if (pTarget) { if (pOldTarget != pTarget && m_Phase == PHASE_EYE_NORMAL) AttackStart(pTarget); // Set victim to old target (if not while Dark Glare) if (pOldTarget && pOldTarget->isAlive() && m_Phase == PHASE_EYE_NORMAL) { m_creature->SetTargetGuid(pOldTarget->GetObjectGuid()); m_creature->SetInFront(pOldTarget); } return true; } // Will call EnterEvadeMode if fit return m_creature->SelectHostileTarget(); }
void VehicleKit::Dismount(Unit* passenger, VehicleSeatEntry const* seatInfo) { if (!passenger) return; float ox, oy, oz, oo; Unit* base = m_pBase->GetVehicle() ? m_pBase->GetVehicle()->GetBase() : m_pBase; base->GetPosition(ox, oy, oz); oo = base->GetOrientation(); passenger->SetPosition(ox,oy,oz,oo,false); if (b_dstSet) { // parabolic traectory (catapults, explode, other effects). mostly set destination in DummyEffect. // destination Z not checked in this case! only limited on 8.0 delta. requred full correct set in spelleffects. float speed = ((m_dst_speed > M_NULL_F) ? m_dst_speed : ((seatInfo && seatInfo->m_exitSpeed > M_NULL_F) ? seatInfo->m_exitSpeed : BASE_CHARGE_SPEED)); float verticalSpeed = speed * sin(m_dst_elevation); float horisontalSpeed = speed * cos(m_dst_elevation); float moveTimeHalf = verticalSpeed / ((seatInfo && seatInfo->m_exitGravity > 0.0f) ? seatInfo->m_exitGravity : Movement::gravity); float max_height = - Movement::computeFallElevation(moveTimeHalf,false,-verticalSpeed); passenger->GetMotionMaster()->MoveSkyDiving(m_dst_x,m_dst_y,m_dst_z,passenger->GetOrientation(), horisontalSpeed, max_height, true); } else if (seatInfo) { // half-parabolic traectory (unmount) float horisontalSpeed = seatInfo->m_exitSpeed; if (horisontalSpeed < M_NULL_F) horisontalSpeed = BASE_CHARGE_SPEED; // may be under water base->GetClosePoint(m_dst_x, m_dst_y, m_dst_z, base->GetObjectBoundingRadius(), frand(2.0f, 3.0f), frand(M_PI_F/2.0f,3.0f*M_PI_F/2.0f), passenger); if (m_dst_z < oz) m_dst_z = oz; passenger->GetMotionMaster()->MoveSkyDiving(m_dst_x, m_dst_y, m_dst_z + 0.1f, passenger->GetOrientation(), horisontalSpeed, 0.0f); } else { // jump from vehicle without seatInfo (? error case) base->GetClosePoint(m_dst_x, m_dst_y, m_dst_z, base->GetObjectBoundingRadius(), 2.0f, M_PI_F, passenger); passenger->UpdateAllowedPositionZ(m_dst_x, m_dst_y, m_dst_z); if (m_dst_z < oz) m_dst_z = oz; passenger->GetMotionMaster()->MoveSkyDiving(m_dst_x, m_dst_y, m_dst_z + 0.1f, passenger->GetOrientation(), BASE_CHARGE_SPEED, 0.0f); } DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS,"VehicleKit::Dismount %s from %s (%f %f %f), destination point is %f %f %f", passenger->GetObjectGuid().GetString().c_str(), base->GetObjectGuid().GetString().c_str(), ox,oy,oz, m_dst_x,m_dst_y,m_dst_z); SetDestination(); }
void AggressorAI::UpdateAI(const uint32 /*diff*/) { // update i_victimGuid if m_creature->getVictim() != 0 and changed Unit* pVictim = SelectVictim(); if (!pVictim) return; i_victimGuid = pVictim->GetObjectGuid(); DoMeleeAttackIfReady(); }
void PetAI::UpdateAllies() { Unit* owner = m_creature->GetCharmerOrOwner(); Group *group = NULL; m_updateAlliesTimer = 10 * IN_MILLISECONDS; //update friendly targets every 10 seconds, lesser checks increase performance if (!owner) return; else if (owner->GetTypeId() == TYPEID_PLAYER) group = ((Player*)owner)->GetGroup(); //only pet and owner/not in group->ok if (m_AllySet.size() == 2 && !group) return; //owner is in group; group members filled in already (no raid -> subgroupcount = whole count) if (group && !group->isRaidGroup() && m_AllySet.size() == (group->GetMembersCount() + 2)) return; m_AllySet.clear(); m_AllySet.insert(m_creature->GetObjectGuid()); if (group) //add group { for (GroupReference *itr = group->GetFirstMember(); itr != NULL; itr = itr->next()) { Player* target = itr->getSource(); if (!target || !group->SameSubGroup((Player*)owner, target)) continue; if (target->GetObjectGuid() == owner->GetObjectGuid()) continue; m_AllySet.insert(target->GetObjectGuid()); } } else //remove group m_AllySet.insert(owner->GetObjectGuid()); }
void PetAI::UpdateAllies() { Unit* owner = m_creature->GetCharmerOrOwner(); if (!owner) return; Group* pGroup = NULL; if (owner->GetTypeId() == TYPEID_PLAYER) pGroup = ((Player*)owner)->GetGroup(); // only pet and owner/not in group->ok if (m_AllySet.size() == 2 && !pGroup) return; // owner is in group; group members filled in already (no raid -> subgroupcount = whole count) if (pGroup && !pGroup->isRaidGroup() && m_AllySet.size() == (pGroup->GetMembersCount() + 2)) return; m_AllySet.clear(); m_AllySet.insert(m_creature->GetObjectGuid()); if (pGroup) // add group { for (GroupReference* itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next()) { Player* target = itr->getSource(); if (!target || !pGroup->SameSubGroup((Player*)owner, target)) continue; if (target->GetObjectGuid() == owner->GetObjectGuid()) continue; m_AllySet.insert(target->GetObjectGuid()); } } else // remove group m_AllySet.insert(owner->GetObjectGuid()); }
void TotemAI::UpdateAI(const uint32 /*diff*/) { if (getTotem().GetTotemType() != TOTEM_ACTIVE) return; if (!m_creature->isAlive() || m_creature->IsNonMeleeSpellCasted(false)) return; // Search spell SpellEntry const *spellInfo = sSpellStore.LookupEntry(getTotem().GetSpell()); if (!spellInfo) return; SpellMiscEntry const* spellMisc = sSpellMiscStore.LookupEntry(spellInfo->Id); // Get spell rangy SpellRangeEntry const* srange = sSpellRangeStore.LookupEntry(spellMisc->rangeIndex); float max_range = GetSpellMaxRange(srange); // SPELLMOD_RANGE not applied in this place just because nonexistent range mods for attacking totems // pointer to appropriate target if found any Unit* victim = m_creature->GetMap()->GetUnit(i_victimGuid); // Search victim if no, not attackable, or out of range, or friendly (possible in case duel end) if( !victim || !victim->isTargetableForAttack() || !m_creature->IsWithinDistInMap(victim, max_range) || m_creature->IsFriendlyTo(victim) || !victim->isVisibleForOrDetect(m_creature,m_creature,false) ) { victim = NULL; Strawberry::NearestAttackableUnitInObjectRangeCheck u_check(m_creature, m_creature, max_range); Strawberry::UnitLastSearcher<Strawberry::NearestAttackableUnitInObjectRangeCheck> checker(victim, u_check); Cell::VisitAllObjects(m_creature, checker, max_range); } // If have target if (victim) { // remember i_victimGuid = victim->GetObjectGuid(); // attack m_creature->SetInFront(victim); // client change orientation by self m_creature->CastSpell(victim, getTotem().GetSpell(), false); } else i_victimGuid.Clear(); }
// Vehicle events bool PassengerEjectEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/) { if (!m_vehicle.IsVehicle()) return true; VehicleKitPtr pVehicle = m_vehicle.GetVehicleKit(); Unit* passenger = pVehicle->GetPassenger(m_seatId); if (passenger && passenger->IsInWorld()) { if (!m_vehicle.RemoveSpellsCausingAuraByCaster(SPELL_AURA_CONTROL_VEHICLE, passenger->GetObjectGuid())) passenger->ExitVehicle(); } return true; }
void WorldSession::HandleMoverRelocation(MovementInfo& movementInfo) { //movementInfo.UpdateTime(WorldTimer::getMSTime()); Unit *mover = _player->GetMover(); if (Player *plMover = mover->ToPlayer()) { if (sWorld.getConfig(CONFIG_ENABLE_PASSIVE_ANTICHEAT) && !plMover->hasUnitState(UNIT_STAT_LOST_CONTROL | UNIT_STAT_NOT_MOVE) && !plMover->GetSession()->HasPermissions(PERM_GMT) && plMover->m_AC_timer == 0) sWorld.m_ac.execute(new ACRequest(plMover, plMover->m_movementInfo, movementInfo)); if (movementInfo.HasMovementFlag(MOVEFLAG_ONTRANSPORT)) { if (!plMover->GetTransport()) { // elevators also cause the client to send MOVEFLAG_ONTRANSPORT - just unmount if the guid can be found in the transport list for (MapManager::TransportSet::const_iterator iter = sMapMgr.m_Transports.begin(); iter != sMapMgr.m_Transports.end(); ++iter) { if ((*iter)->GetObjectGuid() == movementInfo.GetTransportGuid()) { plMover->m_transport = (*iter); (*iter)->AddPassenger(plMover); break; } } } } else if (plMover->GetTransport()) // if we were on a transport, leave { plMover->GetTransport()->RemovePassenger(plMover); plMover->SetTransport(NULL); movementInfo.ClearTransportData(); } if (movementInfo.HasMovementFlag(MOVEFLAG_SWIMMING) != plMover->IsInWater()) { // now client not include swimming flag in case jumping under water plMover->SetInWater(!plMover->IsInWater() || plMover->GetTerrain()->IsInWater(movementInfo.GetPos()->x, movementInfo.GetPos()->y, movementInfo.GetPos()->z)); } } mover->m_movementInfo = movementInfo; mover->SetPosition(movementInfo.GetPos()->x, movementInfo.GetPos()->y, movementInfo.GetPos()->z, movementInfo.GetPos()->o); if (mover->GetObjectGuid().IsPlayer()) mover->ToPlayer()->HandleFallUnderMap(movementInfo.GetPos()->z); }
void UpdateAI(const uint32 uiDiff) override { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) { return; } if (m_bCanTeleport) { if (m_uiExile_Timer < uiDiff) { if (Player* pTarget = m_creature->GetMap()->GetPlayer(m_playerGuid)) { pTarget->CastSpell(pTarget, SPELL_EXILE, true); pTarget->CastSpell(pTarget, SPELL_BANISH_TELEPORT, true); } m_playerGuid.Clear(); m_uiExile_Timer = 8500; m_bCanTeleport = false; } else { m_uiExile_Timer -= uiDiff; } } else if (m_uiBanish_Timer < uiDiff) { Unit* pVictim = m_creature->getVictim(); if (pVictim && pVictim->GetTypeId() == TYPEID_PLAYER) { DoCastSpellIfCan(pVictim, m_uiAuraBanished); m_uiBanish_Timer = 9000; m_playerGuid = pVictim->GetObjectGuid(); m_bCanTeleport = true; } } else { m_uiBanish_Timer -= uiDiff; } DoMeleeAttackIfReady(); }
void WorldSession::HandleChangeSeatsOnControlledVehicle(WorldPacket& recvPacket) { DEBUG_LOG("WORLD: Received CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE"); recvPacket.hexlike(); ObjectGuid srcVehicleGuid; MovementInfo movementInfo; ObjectGuid destVehicleGuid; uint8 seat; recvPacket >> srcVehicleGuid.ReadAsPacked(); recvPacket >> movementInfo; // Not used at the moment recvPacket >> destVehicleGuid.ReadAsPacked(); recvPacket >> seat; TransportInfo* transportInfo = _player->GetTransportInfo(); if (!transportInfo || !transportInfo->IsOnVehicle()) return; Unit* srcVehicle = (Unit*)transportInfo->GetTransport(); // Something went wrong if (srcVehicleGuid != srcVehicle->GetObjectGuid()) return; if (srcVehicleGuid != destVehicleGuid) { Unit* destVehicle = _player->GetMap()->GetUnit(destVehicleGuid); if (!destVehicle || !destVehicle->IsVehicle()) return; // Change vehicle is not possible if (destVehicle->GetVehicleInfo()->GetVehicleEntry()->m_flags & VEHICLE_FLAG_DISABLE_SWITCH) return; SpellClickInfoMapBounds clickPair = sObjectMgr.GetSpellClickInfoMapBounds(destVehicle->GetEntry()); for (SpellClickInfoMap::const_iterator itr = clickPair.first; itr != clickPair.second; ++itr) if (itr->second.IsFitToRequirements(_player)) _player->CastSpell(destVehicle, itr->second.spellId, true); } else srcVehicle->GetVehicleInfo()->SwitchSeat(_player, seat); }
void WorldSession::HandleRequestVehicleSwitchSeat(WorldPacket &recv_data) { DEBUG_LOG("WORLD: Recvd CMSG_REQUEST_VEHICLE_SWITCH_SEAT"); recv_data.hexlike(); ObjectGuid guid; recv_data >> guid.ReadAsPacked(); int8 seatId; recv_data >> seatId; Unit *pVehicleBase = GetPlayer()->GetVehicleBase(); if (!pVehicleBase) return; if (pVehicleBase->GetObjectGuid() == guid) GetPlayer()->ChangeSeat(seatId); }
void EnfeebleHealthEffect() { const SpellEntry *info = GetSpellStore()->LookupEntry(SPELL_ENFEEBLE_EFFECT); if (!info) return; ThreatList const& tList = m_creature->getThreatManager().getThreatList(); std::vector<Unit *> targets; if (tList.empty()) return; //begin + 1 , so we don't target the one with the highest threat ThreatList::const_iterator itr = tList.begin(); std::advance(itr, 1); for(; itr!= tList.end(); ++itr) //store the threat list in a different container { Unit *target = m_creature->GetMap()->GetUnit((*itr)->getUnitGuid()); //only on alive players if (target && target->isAlive() && target->GetTypeId() == TYPEID_PLAYER) targets.push_back(target); } //cut down to size if we have more than 5 targets while(targets.size() > 5) targets.erase(targets.begin()+rand()%targets.size()); int i = 0; for(std::vector<Unit *>::iterator iter = targets.begin(); iter!= targets.end(); ++iter, ++i) { Unit *target = *iter; if (target) { m_aEnfeebleTargetGuid[i] = target->GetObjectGuid(); m_auiEnfeebleHealth[i] = target->GetHealth(); target->CastSpell(target, SPELL_ENFEEBLE, true, 0, 0, m_creature->GetObjectGuid()); target->SetHealth(1); } } }
void WorldSession::HandleSpellClick( WorldPacket & recv_data ) { ObjectGuid guid; recv_data >> guid; Creature *unit = _player->GetMap()->GetAnyTypeCreature(guid); if (!unit) return; if (_player->isInCombat() && !guid.IsVehicle()) // client prevent click and set different icon at combat state return; if(guid.IsVehicle() && _player->GetVehicleKit()) _player->RemoveVehicleKit(); SpellClickInfoMapBounds clickPair = sObjectMgr.GetSpellClickInfoMapBounds(unit->GetEntry()); for(SpellClickInfoMap::const_iterator itr = clickPair.first; itr != clickPair.second; ++itr) { if (itr->second.IsFitToRequirements(_player)) { Unit *caster = (itr->second.castFlags & 0x1) ? (Unit*)_player : (Unit*)unit; Unit *target = (itr->second.castFlags & 0x2) ? (Unit*)_player : (Unit*)unit; if(itr->second.castFlags & 0x4) { unit->SetDeathState(JUST_DIED); unit->RemoveCorpse(); unit->SetHealth(0); } caster->CastSpell(target, itr->second.spellId, true, NULL, NULL,caster->GetObjectGuid()); } } if (unit->GetObjectGuid().IsVehicle()) { _player->EnterVehicle(unit->GetVehicleKit()); } }
void WorldSession::HandleEjectPassenger(WorldPacket &recv_data) { recv_data.hexlike(); ObjectGuid guid; recv_data >> guid; DEBUG_LOG("WORLD: Received CMSG_EJECT_PASSENGER %s",guid.GetString().c_str()); Unit* passenger = ObjectAccessor::GetUnit(*GetPlayer(), guid); if (!passenger) return; VehicleKit* pVehicle = passenger->GetVehicle(); if (!pVehicle || ((pVehicle != GetPlayer()->GetVehicleKit()) && !(pVehicle->GetBase()->GetVehicleInfo()->GetEntry()->m_flags & (VEHICLE_FLAG_ACCESSORY)))) { sLog.outError("WorldSession::HandleEjectPassenger %s try eject %s, but not may do this!",GetPlayer()->GetObjectGuid().GetString().c_str(),guid.GetString().c_str()); return; } passenger->ExitVehicle(); // eject and remove creatures of player mounts if (passenger->GetTypeId() == TYPEID_UNIT) { if (((Creature*)passenger)->IsTemporarySummon()) { // Fixme: delay must be calculated not from this, but from creature template parameters (off traders ...?). uint32 delay = passenger->GetObjectGuid().IsVehicle() ? 1000: 60000; ((TemporarySummon*)passenger)->UnSummon(delay); } else passenger->AddObjectToRemoveList(); } }
void instance_onyxias_lair::OnCreatureCreate(Creature* pCreature) { switch(pCreature->GetEntry()) { case NPC_ONYXIA: m_mNpcEntryGuidStore[pCreature->GetEntry()] = pCreature->GetObjectGuid(); break; case NPC_ONYXIA_WARDER: m_uiOnyxiaWarderGUID.push_back(pCreature->GetObjectGuid()); break; case NPC_ONYXIA_WHELP: case NPC_ONYXIA_WHELP_WEST: { TemporarySummon * summonedWhelp = dynamic_cast<TemporarySummon*>(pCreature); if (summonedWhelp != NULL) { m_onyxianWhelps.push_back(summonedWhelp); Unit* pOnyxia = GetSingleCreatureFromStorage(NPC_ONYXIA); if (pOnyxia && summonedWhelp->GetSummonerGuid() == pOnyxia->GetObjectGuid()) { //Hard-summoned whelps- start them pathing & set them up to aggro on LOS summonedWhelp->GetMotionMaster()->MoveWaypoint(); } else { //Egg-summoned whelps- aggro them now summonedWhelp->SetInCombatWithZone(); } } break; } case NPC_ONYXIA_TRIGGER: this->m_mNpcEntryGuidStore[NPC_ONYXIA_TRIGGER] = pCreature->GetObjectGuid(); break; } }
void WorldSession::HandleChangeSeatsOnControlledVehicle(WorldPacket &recv_data) { DEBUG_LOG("WORLD: Recvd CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE"); recv_data.hexlike(); ObjectGuid guid; recv_data >> guid.ReadAsPacked(); MovementInfo mi; recv_data >> mi; ObjectGuid accessory; recv_data >> accessory.ReadAsPacked(); int8 seatId; recv_data >> seatId; Unit *pVehicleBase = GetPlayer()->GetVehicleBase(); if(!pVehicleBase) return; GetPlayer()->m_movementInfo = mi; if(pVehicleBase->GetObjectGuid() != guid) return; if (accessory.IsEmpty()) GetPlayer()->ChangeSeat(-1, seatId > 0); // prev/next else if (Unit *vehUnit = ObjectAccessor::GetUnit(*_player, accessory)) { if (VehicleKit *vehicle = vehUnit->GetVehicleKit()) { if (vehicle->HasEmptySeat(seatId)) GetPlayer()->EnterVehicle(vehicle, seatId); } } }
void WorldSession::HandleRequestVehicleSwitchSeat(WorldPacket& recvPacket) { DEBUG_LOG("WORLD: Received CMSG_REQUEST_VEHICLE_SWITCH_SEAT"); recvPacket.hexlike(); ObjectGuid vehicleGuid; uint8 seat; recvPacket >> vehicleGuid.ReadAsPacked(); recvPacket >> seat; TransportInfo* transportInfo = _player->GetTransportInfo(); if (!transportInfo || !transportInfo->IsOnVehicle()) return; Unit* vehicle = (Unit*)transportInfo->GetTransport(); // Something went wrong if (vehicleGuid != vehicle->GetObjectGuid()) return; vehicle->GetVehicleInfo()->SwitchSeat(_player, seat); }
void WorldSession::HandleDismissControlledVehicle(WorldPacket& recvPacket) { DEBUG_LOG("WORLD: Received CMSG_DISMISS_CONTROLLED_VEHICLE"); recvPacket.hexlike(); ObjectGuid vehicleGuid; MovementInfo movementInfo; // Not used at the moment recvPacket >> vehicleGuid.ReadAsPacked(); recvPacket >> movementInfo; TransportInfo* transportInfo = _player->GetTransportInfo(); if (!transportInfo || !transportInfo->IsOnVehicle()) return; Unit* vehicle = (Unit*)transportInfo->GetTransport(); // Something went wrong if (vehicleGuid != vehicle->GetObjectGuid()) return; // Remove Vehicle Control Aura vehicle->RemoveSpellsCausingAura(SPELL_AURA_CONTROL_VEHICLE, _player->GetObjectGuid()); }
void UpdateAI(const uint32 uiDiff) override { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; if (m_uiSummonTimer < uiDiff) { if (DoCastSpellIfCan(m_creature, SPELL_SUMMON_FIENDISH_HOUND) == CAST_OK) m_uiSummonTimer = urand(24100, 26900); } else m_uiSummonTimer -= uiDiff; if (m_bCanPullBack) { if (m_uiShadowWhipTimer < uiDiff) { if (Player* pPlayer = m_creature->GetMap()->GetPlayer(m_playerGuid)) { // if unit dosen't have this flag, then no pulling back (script will attempt cast, even if orbital strike was resisted) if (pPlayer->HasMovementFlag(MOVEFLAG_FALLING)) DoCastSpellIfCan(pPlayer, SPELL_SHADOW_WHIP, CAST_INTERRUPT_PREVIOUS); } m_playerGuid.Clear(); m_uiShadowWhipTimer = 2000; m_bCanPullBack = false; } else m_uiShadowWhipTimer -= uiDiff; } else if (m_uiOrbitalStrikeTimer < uiDiff) { Unit* pTemp = NULL; if (m_creature->CanReachWithMeleeAttack(m_creature->getVictim())) pTemp = m_creature->getVictim(); else pTemp = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0); if (pTemp && pTemp->GetTypeId() == TYPEID_PLAYER) { if (DoCastSpellIfCan(pTemp, SPELL_ORBITAL_STRIKE) == CAST_OK) { m_uiOrbitalStrikeTimer = urand(14000, 16000); m_playerGuid = pTemp->GetObjectGuid(); m_bCanPullBack = true; } } } else m_uiOrbitalStrikeTimer -= uiDiff; if (m_creature->GetHealthPercent() < 20.0f) { if (m_uiDemonicShieldTimer < uiDiff) { if (DoCastSpellIfCan(m_creature, SPELL_DEMONIC_SHIELD) == CAST_OK) m_uiDemonicShieldTimer = 15000; } else m_uiDemonicShieldTimer -= uiDiff; } if (m_uiAuraTimer < uiDiff) { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) { if (DoCastSpellIfCan(pTarget, m_bIsRegularMode ? SPELL_TREACHEROUS_AURA : SPELL_BANE_OF_TREACHERY_H) == CAST_OK) { m_uiAuraTimer = urand(8000, 16000); DoScriptText(SAY_CURSE, m_creature); } } } else m_uiAuraTimer -= uiDiff; if (m_uiShadowboltTimer < uiDiff) { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1)) { if (DoCastSpellIfCan(pTarget, m_bIsRegularMode ? SPELL_SHADOW_BOLT : SPELL_SHADOW_BOLT_H) == CAST_OK) m_uiShadowboltTimer = urand(4200, 7300); } else m_uiShadowboltTimer = 2000; } else m_uiShadowboltTimer -= uiDiff; DoMeleeAttackIfReady(); }
void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) { Opcodes opcode = recv_data.GetOpcodeEnum(); DEBUG_LOG("WORLD: Recvd %s (%u, 0x%X) opcode", LookupOpcodeName(opcode), opcode, opcode); recv_data.hexlike(); Unit *mover = _player->m_mover; STRAWBERRY_ASSERT(mover != NULL); // there must always be a mover Player *plMover = mover->GetTypeId() == TYPEID_PLAYER ? (Player*)mover : NULL; // ignore, waiting processing in WorldSession::HandleMoveWorldportAckOpcode and WorldSession::HandleMoveTeleportAck if (plMover && plMover->IsBeingTeleported()) { recv_data.rfinish(); // prevent warnings spam return; } /* extract packet */ MovementInfo movementInfo; ReadMovementInfo(recv_data, &movementInfo); recv_data.rfinish(); // prevent warnings spam // prevent tampered movement data if (movementInfo.guid != mover->GetObjectGuid()) return; /* handle special cases */ if (movementInfo.moveFlags & MOVEFLAG_ONTRANSPORT) { // transports size limited // (also received at zeppelin leave by some reason with t_* as absolute in continent coordinates, can be safely skipped) if (movementInfo.t_pos.x > 50 || movementInfo.t_pos.y > 50 || movementInfo.t_pos.z > 50) { recv_data.rfinish(); // prevent warnings spam return; } if (!Strawberry::IsValidMapCoord(movementInfo.pos.x + movementInfo.t_pos.x, movementInfo.pos.y + movementInfo.t_pos.y), movementInfo.pos.z + movementInfo.t_pos.z, movementInfo.pos.o + movementInfo.t_pos.o) { recv_data.rfinish(); // prevent warnings spam return; } // if we boarded a transport, add us to it if (plMover && !plMover->GetTransport()) { // elevators also cause the client to send MOVEMENTFLAG_ONTRANSPORT - just unmount if the guid can be found in the transport list for (MapManager::TransportSet::const_iterator iter = sMapMgr.m_Transports.begin(); iter != sMapMgr.m_Transports.end(); ++iter) { if ((*iter)->GetObjectGuid() == movementInfo.t_guid) { plMover->m_transport = (*iter); (*iter)->AddPassenger(plMover); break; } } } if (!mover->GetTransport() && !mover->GetVehicle()) { GameObject *go = mover->GetMap()->GetGameObject(movementInfo.t_guid); if (!go || go->GetGoType() != GAMEOBJECT_TYPE_TRANSPORT) movementInfo.moveFlags &= ~MOVEFLAG_ONTRANSPORT; } } else if (plMover && plMover->GetTransport()) // if we were on a transport, leave { plMover->m_transport->RemovePassenger(plMover); plMover->m_transport = NULL; movementInfo.t_time = 0; movementInfo.t_seat = -1; } // fall damage generation (ignore in flight case that can be triggered also at lags in moment teleportation to another map). if (opcode == MSG_MOVE_FALL_LAND && plMover) plMover->HandleFall(movementInfo); if (plMover && ((movementInfo.moveFlags & MOVEFLAG_SWIMMING) != 0) != plMover->IsInWater()) { // now client not include swimming flag in case jumping under water plMover->SetInWater(!plMover->IsInWater());// || plMover->GetMap()->IsUnderWater(movementInfo.pos.x, movementInfo.pos.y, movementInfo.pos.y)); } /*----------------------*/ /* process position-change */ WorldPacket data(Opcodes(opcode), recv_data.size()); movementInfo.time = WorldTimer::getMSTime(); movementInfo.guid = mover->GetObjectGuid(); WriteMovementInfo(&data, &movementInfo); mover->SendMessageToSet(&data, _player); mover->m_movementInfo = movementInfo; // this is almost never true (not sure why it is sometimes, but it is), normally use mover->IsVehicle() if (mover->GetVehicle()) { mover->SetOrientation(movementInfo.pos.o); return; } mover->SetPosition(movementInfo.pos.x, movementInfo.pos.y, movementInfo.pos.z, movementInfo.pos.o, false); if (plMover) // nothing is charmed, or player charmed { plMover->UpdateFallInformationIfNeed(movementInfo, opcode); if (movementInfo.pos.z < -500.0f) { //if (!(plMover->InBattleground() // && plMover->GetBattleground() // && plMover->GetBattleground()->HandlePlayerUnderMap(_player))) { // 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 (plMover->isAlive()) { plMover->EnvironmentalDamage(DAMAGE_FALL_TO_VOID, GetPlayer()->GetMaxHealth()); // pl can be alive if GM/etc if (!plMover->isAlive()) { // change the death state to CORPSE to prevent the death timer from // starting in the next player update plMover->KillPlayer(); plMover->BuildPlayerRepop(); } } // cancel the death timer here if started //plMover->RepopAtGraveyard(); } } } }
/*this procedure handles clients CMSG_REQUEST_PARTY_MEMBER_STATS request*/ void WorldSession::HandleRequestPartyMemberStatsOpcode( WorldPacket &recv_data ) { DEBUG_LOG("WORLD: Received CMSG_REQUEST_PARTY_MEMBER_STATS"); uint64 Guid; recv_data >> Guid; Player *player = sObjectMgr.GetPlayer(Guid); if(!player) { WorldPacket data(SMSG_PARTY_MEMBER_STATS_FULL, 3+4+2); data << uint8(0); // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related data.appendPackGUID(Guid); data << uint32(GROUP_UPDATE_FLAG_STATUS); data << uint16(MEMBER_STATUS_OFFLINE); SendPacket(&data); return; } Unit *pet = player->GetCharmOrPet(); WorldPacket data(SMSG_PARTY_MEMBER_STATS_FULL, 4+2+2+2+1+2*6+8+1+8); data << uint8(0); // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related data << player->GetPackGUID(); uint32 mask1 = 0x00040BFF; // common mask, real flags used 0x000040BFF if(pet) mask1 = 0xFFFFFFFF; // for hunters and other classes with pets Powers powerType = player->getPowerType(); data << uint32(mask1); // group update mask data << uint16(MEMBER_STATUS_ONLINE); // member's online status data << uint32(player->GetHealth()); // GROUP_UPDATE_FLAG_CUR_HP data << uint32(player->GetMaxHealth()); // GROUP_UPDATE_FLAG_MAX_HP data << uint8(powerType); // GROUP_UPDATE_FLAG_POWER_TYPE data << uint16(player->GetPower(powerType)); // GROUP_UPDATE_FLAG_CUR_POWER data << uint16(player->GetMaxPower(powerType)); // GROUP_UPDATE_FLAG_MAX_POWER data << uint16(player->getLevel()); // GROUP_UPDATE_FLAG_LEVEL data << uint16(player->GetZoneId()); // GROUP_UPDATE_FLAG_ZONE data << uint16(player->GetPositionX()); // GROUP_UPDATE_FLAG_POSITION data << uint16(player->GetPositionY()); // GROUP_UPDATE_FLAG_POSITION uint64 auramask = 0; size_t maskPos = data.wpos(); data << uint64(auramask); // placeholder for(uint8 i = 0; i < MAX_AURAS; ++i) { if(uint32 aura = player->GetVisibleAura(i)) { auramask |= (uint64(1) << i); data << uint32(aura); data << uint8(1); } } data.put<uint64>(maskPos, auramask); // GROUP_UPDATE_FLAG_AURAS if(pet) { Powers petpowertype = pet->getPowerType(); data << pet->GetObjectGuid(); // GROUP_UPDATE_FLAG_PET_GUID data << pet->GetName(); // GROUP_UPDATE_FLAG_PET_NAME data << uint16(pet->GetDisplayId()); // GROUP_UPDATE_FLAG_PET_MODEL_ID data << uint32(pet->GetHealth()); // GROUP_UPDATE_FLAG_PET_CUR_HP data << uint32(pet->GetMaxHealth()); // GROUP_UPDATE_FLAG_PET_MAX_HP data << uint8(petpowertype); // GROUP_UPDATE_FLAG_PET_POWER_TYPE data << uint16(pet->GetPower(petpowertype)); // GROUP_UPDATE_FLAG_PET_CUR_POWER data << uint16(pet->GetMaxPower(petpowertype)); // GROUP_UPDATE_FLAG_PET_MAX_POWER uint64 petauramask = 0; size_t petMaskPos = data.wpos(); data << uint64(petauramask); // placeholder for(uint8 i = 0; i < MAX_AURAS; ++i) { if(uint32 petaura = pet->GetVisibleAura(i)) { petauramask |= (uint64(1) << i); data << uint32(petaura); data << uint8(1); } } data.put<uint64>(petMaskPos, petauramask); // GROUP_UPDATE_FLAG_PET_AURAS data << (uint32) player->m_movementInfo.GetTransportDBCSeat(); } else { data << uint8(0); // GROUP_UPDATE_FLAG_PET_NAME data << uint64(0); // GROUP_UPDATE_FLAG_PET_AURAS } SendPacket(&data); }
void WorldSession::BuildPartyMemberStatsChangedPacket(Player *player, WorldPacket *data) { uint32 mask = player->GetGroupUpdateFlag(); if (mask & GROUP_UPDATE_FLAG_POWER_TYPE) // if update power type, update current/max power also mask |= (GROUP_UPDATE_FLAG_CUR_POWER | GROUP_UPDATE_FLAG_MAX_POWER); if (mask & GROUP_UPDATE_FLAG_PET_POWER_TYPE) // same for pets mask |= (GROUP_UPDATE_FLAG_PET_CUR_POWER | GROUP_UPDATE_FLAG_PET_MAX_POWER); uint32 byteCount = 0; for (int i = 1; i < GROUP_UPDATE_FLAGS_COUNT; ++i) if (mask & (1 << i)) byteCount += GroupUpdateLength[i]; data->Initialize(SMSG_PARTY_MEMBER_STATS, 8 + 4 + byteCount); *data << player->GetPackGUID(); *data << uint32(mask); if (mask & GROUP_UPDATE_FLAG_STATUS) { if (player) { if (player->IsPvP()) *data << uint16(MEMBER_STATUS_ONLINE | MEMBER_STATUS_PVP); else *data << uint16(MEMBER_STATUS_ONLINE); } else *data << uint16(MEMBER_STATUS_OFFLINE); } if (mask & GROUP_UPDATE_FLAG_CUR_HP) *data << uint32(player->GetHealth()); if (mask & GROUP_UPDATE_FLAG_MAX_HP) *data << uint32(player->GetMaxHealth()); Powers powerType = player->getPowerType(); if (mask & GROUP_UPDATE_FLAG_POWER_TYPE) *data << uint8(powerType); if (mask & GROUP_UPDATE_FLAG_CUR_POWER) *data << uint16(player->GetPower(powerType)); if (mask & GROUP_UPDATE_FLAG_MAX_POWER) *data << uint16(player->GetMaxPower(powerType)); if (mask & GROUP_UPDATE_FLAG_LEVEL) *data << uint16(player->getLevel()); if (mask & GROUP_UPDATE_FLAG_ZONE) *data << uint16(player->GetZoneId()); if (mask & GROUP_UPDATE_FLAG_POSITION) *data << uint16(player->GetPositionX()) << uint16(player->GetPositionY()); if (mask & GROUP_UPDATE_FLAG_AURAS) { const uint64& auramask = player->GetAuraUpdateMask(); *data << uint64(auramask); for(uint32 i = 0; i < MAX_AURAS; ++i) { if(auramask & (uint64(1) << i)) { *data << uint32(player->GetVisibleAura(i)); *data << uint8(1); } } } Unit *pet = player->GetCharmOrPet(); if (mask & GROUP_UPDATE_FLAG_PET_GUID) *data << (pet ? pet->GetObjectGuid() : ObjectGuid()); if (mask & GROUP_UPDATE_FLAG_PET_NAME) { if(pet) *data << pet->GetName(); else *data << uint8(0); } if (mask & GROUP_UPDATE_FLAG_PET_MODEL_ID) { if(pet) *data << uint16(pet->GetDisplayId()); else *data << uint16(0); } if (mask & GROUP_UPDATE_FLAG_PET_CUR_HP) { if(pet) *data << uint32(pet->GetHealth()); else *data << uint32(0); } if (mask & GROUP_UPDATE_FLAG_PET_MAX_HP) { if(pet) *data << uint32(pet->GetMaxHealth()); else *data << uint32(0); } if (mask & GROUP_UPDATE_FLAG_PET_POWER_TYPE) { if(pet) *data << uint8(pet->getPowerType()); else *data << uint8(0); } if (mask & GROUP_UPDATE_FLAG_PET_CUR_POWER) { if(pet) *data << uint16(pet->GetPower(pet->getPowerType())); else *data << uint16(0); } if (mask & GROUP_UPDATE_FLAG_PET_MAX_POWER) { if(pet) *data << uint16(pet->GetMaxPower(pet->getPowerType())); else *data << uint16(0); } if (mask & GROUP_UPDATE_FLAG_PET_AURAS) { if(pet) { const uint64& auramask = pet->GetAuraUpdateMask(); *data << uint64(auramask); for(uint32 i = 0; i < MAX_AURAS; ++i) { if(auramask & (uint64(1) << i)) { *data << uint32(pet->GetVisibleAura(i)); *data << uint8(1); } } } else *data << uint64(0); } if (mask & GROUP_UPDATE_FLAG_VEHICLE_SEAT) { *data << (uint32) player->m_movementInfo.GetTransportDBCSeat(); } }
bool TargetedMovementGeneratorMedium<T, D>::update(T& owner, const uint32& time_diff) { if (!m_target.isValid() || !m_target->IsInWorld()) return false; if (!owner.isAlive()) return true; if (owner.hasUnitState(UNIT_STAT_NOT_MOVE) || (owner.IsInUnitState(UNIT_ACTION_CHASE) && owner.hasUnitState(UNIT_STAT_NO_COMBAT_MOVEMENT))) { D::_clearUnitStateMove(owner); return true; } // prevent movement while casting spells with cast time or channel time if (!IsAbleMoveWhenCast(owner.GetEntry()) && owner.IsNonMeleeSpellCasted(false, false, true)) { owner.StopMoving(); return true; } // prevent crash after creature killed pet if (static_cast<D*>(this)->_lostTarget(owner)) { D::_clearUnitStateMove(owner); if (m_waitTargetTimer >= TARGET_NOT_ACCESSIBLE_MAX_TIMER) return false; else { m_waitTargetTimer += 5 * time_diff; return true; } } if (!m_target->isInAccessablePlaceFor(&owner)) return true; bool moveToTarget = false; m_recheckDistanceTimer.Update(time_diff); if (m_recheckDistanceTimer.Passed()) { m_recheckDistanceTimer.Reset(this->GetMovementGeneratorType() == FOLLOW_MOTION_TYPE ? RECHECK_DISTANCE_TIMER_FOLLOW : RECHECK_DISTANCE_TIMER); G3D::Vector3 dest = owner.movespline->FinalDestination(); moveToTarget = dest == Vector3() ? true : RequiresNewPosition(owner, dest.x, dest.y, dest.z); if (owner.GetTypeId() == TYPEID_UNIT && !((Creature*)&owner)->IsPet()) { Unit* pVictim = owner.getVictim(); if (pVictim && pVictim->GetObjectGuid() == m_target->GetObjectGuid()) { if (!pVictim->isAlive() && owner.movespline->Finalized()) return false; if (!m_offset && owner.movespline->Finalized() && !owner.CanReachWithMeleeAttack(pVictim) && !m_target->m_movementInfo.HasMovementFlag(MOVEFLAG_PENDINGSTOP)) { if (m_waitTargetTimer < TARGET_NOT_ACCESSIBLE_MAX_TIMER) m_waitTargetTimer += m_recheckDistanceTimer.GetExpiry(); else return false; } else m_waitTargetTimer = 0; } } } if (m_speedChanged || moveToTarget) _setTargetLocation(owner, moveToTarget); if (owner.movespline->Finalized()) { if (fabs(m_angle) < M_NULL_F && !owner.HasInArc(0.01f, m_target.getTarget())) owner.SetInFront(m_target.getTarget()); if (!m_targetReached) { m_targetReached = true; static_cast<D*>(this)->_reachTarget(owner); } } return true; }