bool WaypointMovementGenerator<Creature>::StartMove(Creature &creature) { if (!i_path || i_path->empty()) return false; if (Stopped()) return true; if (m_isArrivalDone) { if ((i_currentNode == i_path->size() - 1) && !repeating) // If that's our last waypoint { creature.SetHomePosition(i_path->at(i_currentNode)->x, i_path->at(i_currentNode)->y, i_path->at(i_currentNode)->z, creature.GetOrientation()); creature.GetMotionMaster()->Initialize(); return false; } i_currentNode = (i_currentNode+1) % i_path->size(); } WaypointData const* node = i_path->at(i_currentNode); m_isArrivalDone = false; creature.AddUnitState(UNIT_STATE_ROAMING_MOVE); Movement::MoveSplineInit init(creature); init.MoveTo(node->x, node->y, node->z, true); //! Accepts angles such as 0.00001 and -0.00001, 0 must be ignored, default value in waypoint table if (node->orientation && node->delay) init.SetFacing(node->orientation); init.SetWalk(!node->run); init.Launch(); //Call for creature group update if (creature.GetFormation() && creature.GetFormation()->getLeader() == &creature) creature.GetFormation()->LeaderMoveTo(node->x, node->y, node->z); return true; }
Creature* Transport::AddNPCPassengerInInstance(uint32 entry, float x, float y, float z, float o, uint32 anim) { Map* map = GetMap(); Creature* creature = new Creature; if (!creature->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, GetPhaseMask(), entry, 0, GetGOInfo()->faction, 0, 0, 0, 0)) { delete creature; return NULL; } creature->SetTransport(this); creature->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT); creature->m_movementInfo.guid = GetGUID(); creature->m_movementInfo.t_pos.Relocate(x, y, z, o); o += GetOrientation(); MapManager::NormalizeOrientation(o); creature->Relocate( GetPositionX() + (x * cos(GetOrientation()) + y * sin(GetOrientation() + float(M_PI))), GetPositionY() + (y * cos(GetOrientation()) + x * sin(GetOrientation())), z + GetPositionZ() , o); creature->SetHomePosition(creature->GetPositionX(), creature->GetPositionY(), creature->GetPositionZ(), creature->GetOrientation()); if (!creature->IsPositionValid()) { sLog->outError("Creature (guidlow %d, entry %d) not created. Suggested coordinates isn't valid (X: %f Y: %f)", creature->GetGUIDLow(), creature->GetEntry(), creature->GetPositionX(), creature->GetPositionY()); delete creature; return NULL; } map->AddToMap(creature); m_NPCPassengerSet.insert(creature); creature->setActive(true); sScriptMgr->OnAddCreaturePassenger(this, creature); return creature; }
void Transport::UpdateNPCPositions() { for (CreatureSet::iterator itr = m_NPCPassengerSet.begin(); itr != m_NPCPassengerSet.end(); ++itr) { Creature* npc = *itr; float x, y, z, o; o = GetOrientation() + npc->m_movementInfo.t_pos.m_orientation; MapManager::NormalizeOrientation(o); x = GetPositionX() + (npc->m_movementInfo.t_pos.m_positionX * cos(GetOrientation()) + npc->m_movementInfo.t_pos.m_positionY * sin(GetOrientation() + M_PI)); y = GetPositionY() + (npc->m_movementInfo.t_pos.m_positionY * cos(GetOrientation()) + npc->m_movementInfo.t_pos.m_positionX * sin(GetOrientation())); z = GetPositionZ() + npc->m_movementInfo.t_pos.m_positionZ; npc->SetHomePosition(x, y, z, o); GetMap()->CreatureRelocation(npc, x, y, z, o, false); } for (PlayerSet::iterator itr = m_passengers.begin(); itr != m_passengers.end(); ++itr) { Player* plr = *itr; float x, y, z, o; o = GetOrientation() + plr->m_movementInfo.t_pos.m_orientation; MapManager::NormalizeOrientation(o); x = GetPositionX() + (plr->m_movementInfo.t_pos.m_positionX * cos(GetOrientation()) + plr->m_movementInfo.t_pos.m_positionY * sin(GetOrientation() + M_PI)); y = GetPositionY() + (plr->m_movementInfo.t_pos.m_positionY * cos(GetOrientation()) + plr->m_movementInfo.t_pos.m_positionX * sin(GetOrientation())); z = GetPositionZ() + plr->m_movementInfo.t_pos.m_positionZ; plr->Relocate(x, y, z, o); UpdateData transData; WorldPacket packet; transData.BuildPacket(&packet); plr->SendDirectMessage(&packet); } }
Creature* Transport::CreateNPCPassenger(uint32 entry, float x, float y, float z, float o, CreatureData const* data /*= NULL*/) { Map* map = GetMap(); Creature* creature = new Creature(); if (!creature->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, GetPhaseMask(), entry, 0, GetGOInfo()->faction, 0.0f, 0.0f, 0.0f, 0.0f, data)) { delete creature; return NULL; } creature->SetTransport(this); creature->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT); creature->m_movementInfo.guid = GetGUID(); creature->m_movementInfo.t_pos.Relocate(x, y, z, o); o += GetOrientation(); MapManager::NormalizeOrientation(o); creature->Relocate(GetPositionX() + (x * cos(GetOrientation()) + y * sin(GetOrientation() + float(M_PI))), GetPositionY() + (y * cos(GetOrientation()) + x * sin(GetOrientation())), z + GetPositionZ(), o); creature->SetHomePosition(creature->GetPositionX(), creature->GetPositionY(), creature->GetPositionZ(), creature->GetOrientation()); if (!creature->IsPositionValid()) { sLog->outError("Creature (guidlow %d, entry %d) not created. Suggested coordinates isn't valid (X: %f Y: %f)",creature->GetGUIDLow(),creature->GetEntry(),creature->GetPositionX(),creature->GetPositionY()); delete creature; return NULL; } map->AddToMap(creature); AddPassenger(creature); creature->SetWorldObject(true); //so it will not be unloaded with grid sScriptMgr->OnAddCreaturePassenger(this, creature); return creature; }
// gunship data Creature* Transport::AddNPCPassengerInInstance(uint32 entry, float x, float y, float z, float o, uint32 anim) { Map* map = GetMap(); Creature* creature = new Creature; if (!creature->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, GetPhaseMask(), entry, 0, GetGOInfo()->faction, 0, 0, 0, 0)) { delete creature; return 0; } creature->SetTransport(this); creature->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT); creature->m_movementInfo.guid = GetGUID(); creature->m_movementInfo.transport.pos.Relocate(x, y, z, o); creature->Relocate( GetPositionX() + (x * cos(GetOrientation()) + y * sin(GetOrientation() + float(M_PI))), GetPositionY() + (y * cos(GetOrientation()) + x * sin(GetOrientation())), z + GetPositionZ(), o + GetOrientation()); creature->SetHomePosition(creature->GetPositionX(), creature->GetPositionY(), creature->GetPositionZ(), creature->GetOrientation()); if (!creature->IsPositionValid()) { delete creature; return 0; } map->AddToMap(creature); m_NPCPassengerSet.insert(creature); creature->setActive(true); sScriptMgr->OnAddCreaturePassenger(this, creature); return creature; }
Creature *Battlefield::SpawnCreature(uint32 entry, float x, float y, float z, float o, TeamId team) { //Get map object Map* map = const_cast<Map*>(sMapMgr->CreateBaseMap(_MapId)); if (!map) { sLog->outError("Can't create creature entry: %u map not found", entry); return 0; } //Create creature Creature* creature = new Creature; if (!creature->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, PHASEMASK_NORMAL, entry, 0, team, x, y, z, o)) { sLog->outError("Can't create creature entry: %u", entry); delete creature; return NULL; } creature->SetHomePosition(x, y, z, o); CreatureTemplate const* cinfo = sObjectMgr->GetCreatureTemplate(entry); if (!cinfo) { sLog->outErrorDb("Battleground::AddCreature: entry %u does not exist.", entry); return NULL; } // force using DB speeds -- do we really need this? creature->SetSpeed(MOVE_WALK, cinfo->speed_walk); creature->SetSpeed(MOVE_RUN, cinfo->speed_run); // Set creature in world map->AddToMap(creature); creature->setActive(true); return creature; }
void CreatureGroup::LeaderMoveTo(float x, float y, float z) { //! To do: This should probably get its own movement generator or use WaypointMovementGenerator. //! If the leader's path is known, member's path can be plotted as well using formation offsets. if (!m_leader) return; float pathangle = atan2(m_leader->GetPositionY() - y, m_leader->GetPositionX() - x); for (CreatureGroupMemberType::iterator itr = m_members.begin(); itr != m_members.end(); ++itr) { Creature* member = itr->first; if (member == m_leader || !member->isAlive() || member->getVictim()) continue; float angle = itr->second->follow_angle; float dist = itr->second->follow_dist; float dx = x + std::cos(angle + pathangle) * dist; float dy = y + std::sin(angle + pathangle) * dist; float dz = z; Trinity::NormalizeMapCoord(dx); Trinity::NormalizeMapCoord(dy); member->UpdateGroundPositionZ(dx, dy, dz); if (member->IsWithinDist(m_leader, dist + MAX_DESYNC)) member->SetUnitMovementFlags(m_leader->GetUnitMovementFlags()); else member->SetWalk(false); member->GetMotionMaster()->MovePoint(0, dx, dy, dz); member->SetHomePosition(dx, dy, dz, pathangle); } }
Creature* Battlefield::SpawnCreature(uint32 entry, Position const& pos) { //Get map object Map* map = sMapMgr->CreateBaseMap(m_MapId); if (!map) { TC_LOG_ERROR("bg.battlefield", "Battlefield::SpawnCreature: Can't create creature entry: %u, map not found.", entry); return nullptr; } CreatureTemplate const* cinfo = sObjectMgr->GetCreatureTemplate(entry); if (!cinfo) { TC_LOG_ERROR("bg.battlefield", "Battlefield::SpawnCreature: entry %u does not exist.", entry); return nullptr; } float x, y, z, o; pos.GetPosition(x, y, z, o); Creature* creature = new Creature(); if (!creature->Create(map->GenerateLowGuid<HighGuid::Creature>(), map, PHASEMASK_NORMAL, entry, x, y, z, o)) { TC_LOG_ERROR("bg.battlefield", "Battlefield::SpawnCreature: Can't create creature entry: %u", entry); delete creature; return nullptr; } creature->SetHomePosition(x, y, z, o); // Set creature in world map->AddToMap(creature); creature->setActive(true); return creature; }
bool WaypointMovementGenerator<Creature>::Update(Creature &unit, const uint32 &diff) { if (!&unit) return true; if (!path_id) return false; // Waypoint movement can be switched on/off // This is quite handy for escort quests and other stuff if (unit.HasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DISTRACTED)) return true; // Clear the generator if the path doesn't exist if (!waypoints || !waypoints->size()) return false; Traveller<Creature> traveller(unit); i_nextMoveTime.Update(diff); i_destinationHolder.UpdateTraveller(traveller, diff, true); if (i_nextMoveTime.GetExpiry() < TIMEDIFF_NEXT_WP) { if (unit.IsStopped()) { if (StopedByPlayer) { ASSERT(node); InitTraveller(unit, *node); i_destinationHolder.SetDestination(traveller, node->x, node->y, node->z); i_nextMoveTime.Reset(i_destinationHolder.GetTotalTravelTime()); StopedByPlayer = false; return true; } if (i_currentNode == waypoints->size() - 1) // If that's our last waypoint { if (repeating) // If the movement is repeating i_currentNode = 0; // Start moving all over again else { unit.SetHomePosition(node->x, node->y, node->z, unit.GetOrientation()); unit.GetMotionMaster()->Initialize(); return false; // Clear the waypoint movement } } else ++i_currentNode; node = waypoints->at(i_currentNode); InitTraveller(unit, *node); i_destinationHolder.SetDestination(traveller, node->x, node->y, node->z); i_nextMoveTime.Reset(i_destinationHolder.GetTotalTravelTime()); //Call for creature group update if (unit.GetFormation() && unit.GetFormation()->getLeader() == &unit) unit.GetFormation()->LeaderMoveTo(node->x, node->y, node->z); } else { //Determine waittime if (node->delay) i_nextMoveTime.Reset(node->delay); //note: disable "start" for mtmap if (node->event_id && urand(0,99) < node->event_chance) unit.GetMap()->ScriptsStart(sWaypointScripts, node->event_id, &unit, NULL/*, false*/); i_destinationHolder.ResetTravelTime(); MovementInform(unit); unit.UpdateWaypointID(i_currentNode); unit.ClearUnitState(UNIT_STAT_ROAMING); unit.Relocate(node->x, node->y, node->z); } } else { if (unit.IsStopped() && !i_destinationHolder.HasArrived()) { if (!StopedByPlayer) { i_destinationHolder.IncreaseTravelTime(STOP_TIME_FOR_PLAYER); i_nextMoveTime.Reset(STOP_TIME_FOR_PLAYER); StopedByPlayer = true; } } } return true; }
void hyjalAI::DoOverrun(uint32 faction, const uint32 diff) { npc_escortAI::UpdateAI(diff); if (WaitForTeleport) { if (TeleportTimer <= diff) { CellCoord pair(Trinity::ComputeCellCoord(me->GetPositionX(), me->GetPositionY())); Cell cell(pair); cell.SetNoCreate(); std::list<Creature*> creatures; Trinity::AllFriendlyCreaturesInGrid creature_check(me); Trinity::CreatureListSearcher<Trinity::AllFriendlyCreaturesInGrid> creature_searcher(me, creatures, creature_check); TypeContainerVisitor <Trinity::CreatureListSearcher<Trinity::AllFriendlyCreaturesInGrid>, GridTypeMapContainer> creature_visitor(creature_searcher); cell.Visit(pair, creature_visitor, *(me->GetMap()), *me, me->GetGridActivationRange()); if (!creatures.empty()) { for (std::list<Creature*>::const_iterator itr = creatures.begin(); itr != creatures.end(); ++itr) { if ((*itr) && (*itr)->isAlive()) { (*itr)->CastSpell(*itr, SPELL_TELEPORT_VISUAL, true); (*itr)->setFaction(35);//make them friendly so mobs won't attack them (*itr)->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); } } DoCast(me, SPELL_TELEPORT_VISUAL); bRetreat = true; RetreatTimer = 1000; } WaitForTeleport = false; Teleported = true; }TeleportTimer -= diff; } if (!Teleported) return; Overrun = false;//execute once switch (faction) { case 0://alliance for (uint8 i = 0; i < 92; ++i)//summon fires me->SummonGameObject(FLAMEOBJECT, AllianceFirePos[i][0], AllianceFirePos[i][1], AllianceFirePos[i][2], AllianceFirePos[i][3], AllianceFirePos[i][4], AllianceFirePos[i][5], AllianceFirePos[i][6], AllianceFirePos[i][7], 0); for (uint8 i = 0; i < 25; ++i)//summon 25 ghouls { uint8 r = rand()%4; Creature* unit = me->SummonCreature(GHOUL, AllianceBase[r][0]+irand(-15, 15), AllianceBase[r][1]+irand(-15, 15), AllianceBase[r][2], 0, TEMPSUMMON_MANUAL_DESPAWN, 2*60*1000); if (unit) { CAST_AI(hyjal_trashAI, unit->AI())->faction = Faction; CAST_AI(hyjal_trashAI, unit->AI())->IsOverrun = true; CAST_AI(hyjal_trashAI, unit->AI())->OverrunType = i; unit->setActive(true); } } for (uint8 i = 0; i < 3; ++i)//summon 3 abominations { uint8 r = rand()%4; Creature* unit = me->SummonCreature(ABOMINATION, AllianceBase[r][0]+irand(-15, 15), AllianceBase[r][1]+irand(-15, 15), AllianceBase[r][2], 0, TEMPSUMMON_MANUAL_DESPAWN, 2*60*1000); if (unit) { CAST_AI(hyjal_trashAI, unit->AI())->faction = Faction; CAST_AI(hyjal_trashAI, unit->AI())->IsOverrun = true; CAST_AI(hyjal_trashAI, unit->AI())->OverrunType = i; unit->setActive(true); } } for (uint8 i = 0; i < 5; ++i)//summon 5 gargoyles { Creature* unit = me->SummonCreature(GARGOYLE, AllianceOverrunGargPos[i][0], AllianceOverrunGargPos[i][1], AllianceOverrunGargPos[i][2], AllianceOverrunGargPos[i][3], TEMPSUMMON_MANUAL_DESPAWN, 2*60*1000); if (unit) { unit->SetHomePosition(AllianceOverrunGargPos[i][0], AllianceOverrunGargPos[i][1], AllianceOverrunGargPos[i][2], AllianceOverrunGargPos[i][3]); CAST_AI(hyjal_trashAI, unit->AI())->faction = Faction; CAST_AI(hyjal_trashAI, unit->AI())->IsOverrun = true; CAST_AI(hyjal_trashAI, unit->AI())->OverrunType = i; unit->setActive(true); } } break; case 1://horde for (uint8 i = 0; i < 65; ++i)//summon fires me->SummonGameObject(FLAMEOBJECT, HordeFirePos[i][0], HordeFirePos[i][1], HordeFirePos[i][2], HordeFirePos[i][3], HordeFirePos[i][4], HordeFirePos[i][5], HordeFirePos[i][6], HordeFirePos[i][7], 0); for (uint8 i = 0; i < 26; ++i)//summon infernals { Creature* unit = me->SummonCreature(GIANT_INFERNAL, InfernalSPWP[i][0], InfernalSPWP[i][1], InfernalSPWP[i][2], InfernalSPWP[i][3], TEMPSUMMON_MANUAL_DESPAWN, 2*60*1000); if (unit) { unit->SetHomePosition(InfernalSPWP[i][0], InfernalSPWP[i][1], InfernalSPWP[i][2], InfernalSPWP[i][3]); CAST_AI(hyjal_trashAI, unit->AI())->faction = Faction; CAST_AI(hyjal_trashAI, unit->AI())->IsOverrun = true; CAST_AI(hyjal_trashAI, unit->AI())->OverrunType = i; unit->setActive(true); } } for (uint8 i = 0; i < 25; ++i)//summon 25 ghouls { uint8 r = rand()%4; Creature* unit = me->SummonCreature(GHOUL, HordeBase[r][0]+irand(-15, 15), HordeBase[r][1]+irand(-15, 15), HordeBase[r][2], 0, TEMPSUMMON_MANUAL_DESPAWN, 2*60*1000); if (unit) { CAST_AI(hyjal_trashAI, unit->AI())->faction = Faction; CAST_AI(hyjal_trashAI, unit->AI())->IsOverrun = true; CAST_AI(hyjal_trashAI, unit->AI())->OverrunType = i; unit->setActive(true); } } for (uint8 i = 0; i < 5; ++i)//summon 5 abominations { uint8 r = rand()%4; Creature* unit = me->SummonCreature(ABOMINATION, HordeBase[r][0]+irand(-15, 15), HordeBase[r][1]+irand(-15, 15), HordeBase[r][2], 0, TEMPSUMMON_MANUAL_DESPAWN, 2*60*1000); if (unit) { CAST_AI(hyjal_trashAI, unit->AI())->faction = Faction; CAST_AI(hyjal_trashAI, unit->AI())->IsOverrun = true; CAST_AI(hyjal_trashAI, unit->AI())->OverrunType = i; unit->setActive(true); } } break; } }
void CreatureGroup::LeaderMoveTo(float x, float y, float z, bool run) { //! To do: This should probably get its own movement generator or use WaypointMovementGenerator. //! If the leader's path is known, member's path can be plotted as well using formation offsets. if (!m_leader) return; uint8 groupAI = sFormationMgr->CreatureGroupMap[m_leader->GetDBTableGUIDLow()]->groupAI; if (groupAI == 5) return; float pathDist = m_leader->GetExactDist(x, y, z); float pathAngle = m_leader->GetAngle(x, y); for (CreatureGroupMemberType::iterator itr = m_members.begin(); itr != m_members.end(); ++itr) { Creature* member = itr->first; if (member == m_leader || !member->IsAlive() || member->GetVictim()) continue; // Xinef: If member is stunned / rooted etc don't allow to move him if (member->HasUnitState(UNIT_STATE_NOT_MOVE)) continue; // Xinef: this should be automatized, if turn angle is greater than PI/2 (90°) we should swap formation angle if (M_PI - fabs(fabs(m_leader->GetOrientation() - pathAngle) - M_PI) > M_PI*0.50f) { // pussywizard: in both cases should be 2*M_PI - follow_angle // pussywizard: also, GetCurrentWaypointID() returns 0..n-1, while point_1 must be > 0, so +1 // pussywizard: db table waypoint_data shouldn't have point id 0 and shouldn't have any gaps for this to work! // if (m_leader->GetCurrentWaypointID()+1 == itr->second->point_1 || m_leader->GetCurrentWaypointID()+1 == itr->second->point_2) itr->second->follow_angle = Position::NormalizeOrientation(itr->second->follow_angle + M_PI); //(2 * M_PI) - itr->second->follow_angle; } float followAngle = itr->second->follow_angle; float followDist = itr->second->follow_dist; float dx = x + cos(followAngle + pathAngle) * followDist; float dy = y + sin(followAngle + pathAngle) * followDist; float dz = z; Trinity::NormalizeMapCoord(dx); Trinity::NormalizeMapCoord(dy); member->UpdateGroundPositionZ(dx, dy, dz); member->SetUnitMovementFlags(m_leader->GetUnitMovementFlags()); // pussywizard: setting the same movementflags is not enough, spline decides whether leader walks/runs, so spline param is now passed as "run" parameter to this function if (run && member->IsWalking()) member->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING); else if (!run && !member->IsWalking()) member->AddUnitMovementFlag(MOVEMENTFLAG_WALKING); // xinef: if we move members to position without taking care of sizes, we should compare distance without sizes // xinef: change members speed basing on distance - if too far speed up, if too close slow down UnitMoveType mtype = Movement::SelectSpeedType(member->GetUnitMovementFlags()); member->SetSpeedRate(mtype, m_leader->GetSpeedRate(mtype) * member->GetExactDist(dx, dy, dz) / pathDist); member->GetMotionMaster()->MovePoint(0, dx, dy, dz); member->SetHomePosition(dx, dy, dz, pathAngle); } }
void WorldSession::SendListInventory(ObjectGuid vendorGuid) { Creature* vendor = GetPlayer()->GetNPCIfCanInteractWith(vendorGuid, UNIT_NPC_FLAG_VENDOR); if (!vendor) { TC_LOG_DEBUG("network", "WORLD: SendListInventory - %s not found or you can not interact with him.", vendorGuid.ToString().c_str()); _player->SendSellError(SELL_ERR_CANT_FIND_VENDOR, nullptr, ObjectGuid::Empty, 0); return; } // remove fake death if (GetPlayer()->HasUnitState(UNIT_STATE_DIED)) GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); // Stop the npc if moving vendor->PauseMovement(sWorld->getIntConfig(CONFIG_CREATURE_STOP_FOR_PLAYER)); vendor->SetHomePosition(vendor->GetPosition()); VendorItemData const* items = vendor->GetVendorItems(); if (!items) { WorldPacket data(SMSG_LIST_INVENTORY, 8 + 1 + 1); data << uint64(vendorGuid); data << uint8(0); // count == 0, next will be error code data << uint8(0); // "Vendor has no inventory" SendPacket(&data); return; } uint8 itemCount = items->GetItemCount(); uint8 count = 0; WorldPacket data(SMSG_LIST_INVENTORY, 8 + 1 + itemCount * 8 * 4); data << uint64(vendorGuid); size_t countPos = data.wpos(); data << uint8(count); float discountMod = _player->GetReputationPriceDiscount(vendor); for (uint8 slot = 0; slot < itemCount; ++slot) { if (VendorItem const* item = items->GetItem(slot)) { if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(item->item)) { if (!(itemTemplate->AllowableClass & _player->getClassMask()) && itemTemplate->Bonding == BIND_WHEN_PICKED_UP && !_player->IsGameMaster()) continue; // Only display items in vendor lists for the team the // player is on. If GM on, display all items. if (!_player->IsGameMaster() && ((itemTemplate->Flags2 & ITEM_FLAG2_FACTION_HORDE && _player->GetTeam() == ALLIANCE) || (itemTemplate->Flags2 == ITEM_FLAG2_FACTION_ALLIANCE && _player->GetTeam() == HORDE))) continue; // Items sold out are not displayed in list uint32 leftInStock = !item->maxcount ? 0xFFFFFFFF : vendor->GetVendorItemCurrentCount(item); if (!_player->IsGameMaster() && !leftInStock) continue; if (!sConditionMgr->IsObjectMeetingVendorItemConditions(vendor->GetEntry(), item->item, _player, vendor)) { TC_LOG_DEBUG("condition", "SendListInventory: conditions not met for creature entry %u item %u", vendor->GetEntry(), item->item); continue; } // reputation discount int32 price = item->IsGoldRequired(itemTemplate) ? uint32(floor(itemTemplate->BuyPrice * discountMod)) : 0; data << uint32(slot + 1); // client expects counting to start at 1 data << uint32(item->item); data << uint32(itemTemplate->DisplayInfoID); data << int32(leftInStock); data << uint32(price); data << uint32(itemTemplate->MaxDurability); data << uint32(itemTemplate->BuyCount); data << uint32(item->ExtendedCost); if (++count >= MAX_VENDOR_ITEMS) break; } } } if (count == 0) { data << uint8(0); SendPacket(&data); return; } data.put<uint8>(countPos, count); SendPacket(&data); }