bool WaypointMovementGenerator<Creature>::Update(Creature &creature, const uint32 &diff)
{
    // Waypoint movement can be switched on/off
    // This is quite handy for escort quests and other stuff
    if (creature.HasUnitState(UNIT_STATE_NOT_MOVE))
    {
        creature.ClearUnitState(UNIT_STATE_ROAMING_MOVE);
        return true;
    }
    // prevent a crash at empty waypoint path.
    if (!i_path || i_path->empty())
        return false;

    if (Stopped())
    {
        if (CanMove(diff))
            return StartMove(creature);
    }
    else
    {
        if (creature.IsStopped())
            Stop(STOP_TIME_FOR_PLAYER);
        else if (creature.movespline->Finalized())
        {
            OnArrived(creature);
            return StartMove(creature);
        }
    }
     return true;
 }
void HomeMovementGenerator<Creature>::_setTargetLocation(Creature & owner)
{
    if (!&owner)
        return;

    if (owner.HasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DISTRACTED))
        return;

    float x, y, z;
    owner.GetHomePosition(x, y, z, ori);

    CreatureTraveller traveller(owner);

    uint32 travel_time = i_destinationHolder.SetDestination(traveller, x, y, z);
    modifyTravelTime(travel_time);
    owner.ClearUnitState(uint32(UNIT_STAT_ALL_STATE & ~UNIT_STAT_EVADE));
}
bool RandomMovementGenerator<Creature>::Update(Creature &creature, const uint32 diff)
{
    if (creature.HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED | UNIT_STATE_DISTRACTED))
    {
        i_nextMoveTime.Reset(0);  // Expire the timer
        creature.ClearUnitState(UNIT_STATE_ROAMING_MOVE);
        return true;
    }

    if (creature.movespline->Finalized())
    {
        i_nextMoveTime.Update(diff);
        if (i_nextMoveTime.Passed())
            _setRandomLocation(creature);
    }
    return true;
}
Example #4
0
void HomeMovementGenerator<Creature>::_setTargetLocation(Creature & owner)
{
    if (owner.HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED | UNIT_STATE_DISTRACTED))
        return;

    Movement::MoveSplineInit init(owner);
    float x, y, z, o;
    // at apply we can select more nice return points base at current movegen
    //if (owner.GetMotionMaster()->empty() || !owner.GetMotionMaster()->top()->GetResetPosition(owner, x, y, z))
    //{
    owner.GetHomePosition(x, y, z, o);
    init.SetFacing(o);
    //}
    init.MoveTo(x, y, z, true);
    init.SetWalk(false);
    init.Launch();

    arrived = false;
    owner.ClearUnitState(UNIT_STATE_ALL_STATE & ~UNIT_STATE_EVADE);
}
            void CheckChannelers()
            {
				if (addYell)
				{
					if (!SelectTargetFromPlayerList(100.0f))
						EnterEvadeMode();
					return;
				}

				SummonChannelers();
                for (uint8 i = 0; i < 5; ++i)
                {
                    Creature* channeler = ObjectAccessor::GetCreature(*me, channelers[i]);
                    if (channeler && !channeler->HasUnitState(UNIT_STATE_CASTING) && !channeler->IsInCombat())
					{
						Creature* target = ObjectAccessor::GetCreature(*me, channelers[(i+2)%5]);
						if (target)
							channeler->CastSpell(target, SPELL_CHANNELING, false);
					}
                }
            }
Example #6
0
bool
RandomMovementGenerator<Creature>::Update(Creature &creature, const uint32 diff)
{
    if (creature.HasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DISTRACTED))
    {
        i_nextMoveTime.Update(i_nextMoveTime.GetExpiry());    // Expire the timer
        creature.ClearUnitState(UNIT_STAT_ROAMING);
        return true;
    }

    i_nextMoveTime.Update(diff);

    if (i_destinationHolder.HasArrived() && !creature.IsStopped() && !creature.canFly())
        creature.ClearUnitState(UNIT_STAT_ROAMING | UNIT_STAT_MOVE);

    if (!i_destinationHolder.HasArrived() && creature.IsStopped())
        creature.AddUnitState(UNIT_STAT_ROAMING);

    CreatureTraveller traveller(creature);

    if (i_destinationHolder.UpdateTraveller(traveller, diff, true))
    {
        if (i_nextMoveTime.Passed())
        {
            if (irand(0, RUNNING_CHANCE_RANDOMMV) > 0)
                creature.AddUnitMovementFlag(MOVEMENTFLAG_WALKING);
            _setRandomLocation(creature);
        }
        else if (creature.isPet() && creature.GetOwner() && !creature.IsWithinDist(creature.GetOwner(), PET_FOLLOW_DIST+2.5f))
        {
           creature.RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
           _setRandomLocation(creature);
        }
    }
    return true;
}
Example #7
0
void WorldSession::SendListInventory(uint64 vendorGuid)
{
    sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_LIST_INVENTORY");

    Creature* vendor = GetPlayer()->GetNPCIfCanInteractWith(vendorGuid, UNIT_NPC_FLAG_VENDOR);
    if (!vendor)
    {
        sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: SendListInventory - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(vendorGuid)));
        _player->SendSellError(SELL_ERR_CANT_FIND_VENDOR, NULL, 0, 0);
        return;
    }

    // remove fake death
    if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
        GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH);

    // Stop the npc if moving
    if (vendor->HasUnitState(UNIT_STATE_MOVING))
        vendor->StopMoving();

    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_FLAGS_EXTRA_HORDE_ONLY && _player->GetTeam() == ALLIANCE) || (itemTemplate->Flags2 == ITEM_FLAGS_EXTRA_ALLIANCE_ONLY && _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;

                ++count;

                // 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 == 0)
    {
        data << uint8(0);
        SendPacket(&data);
        return;
    }

    data.put<uint8>(countPos, count);
    SendPacket(&data);
}
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 WorldSession::SendListInventory(uint64 vendorguid) {
	sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_LIST_INVENTORY");

	Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(vendorguid,
			UNIT_NPC_FLAG_VENDOR);
	if (!pCreature) {
		sLog->outDebug(
				LOG_FILTER_NETWORKIO,
				"WORLD: SendListInventory - Unit (GUID: %u) not found or you can not interact with him.",
				uint32(GUID_LOPART(vendorguid)));
		_player->SendSellError(SELL_ERR_CANT_FIND_VENDOR, NULL, 0, 0);
		return;
	}

	// remove fake death
	if (GetPlayer()->HasUnitState(UNIT_STAT_DIED))
		GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH);

	// Stop the npc if moving
	if (pCreature->HasUnitState(UNIT_STAT_MOVING))
		pCreature->StopMoving();

	VendorItemData const* vItems = pCreature->GetVendorItems();
	if (!vItems) {
		WorldPacket data(SMSG_LIST_INVENTORY, (8 + 1 + 1 + 2), true);
		data << uint64(vendorguid);
		data << uint8(0); // count==0, next will be error code
		data << uint8(0); // "Vendor has no inventory"
		SendPacket(&data);
		return;
	}

	uint32 numitems = vItems->GetItemCount();
	uint8 count = 0;

	WorldPacket data(SMSG_LIST_INVENTORY,
			(8 + 1 + numitems * 9 * 4 + 1 * numitems + 2), true);
	data << uint64(vendorguid);

	size_t count_pos = data.wpos();
	data << uint8(count);

	float discountMod = _player->GetReputationPriceDiscount(pCreature);

	for (uint32 vendorslot = 0; vendorslot < numitems; ++vendorslot) {
		if (VendorItem const* crItem = vItems->GetItem(vendorslot)) {
			if (ItemPrototype const *pProto = ObjectMgr::GetItemPrototype(crItem->item)) {
				if ((pProto->AllowableClass & _player->getClassMask()) == 0
						&& pProto->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()
						&& ((pProto->Flags2 & ITEM_FLAGS_EXTRA_HORDE_ONLY
								&& _player->GetTeam() == ALLIANCE)
								|| (pProto->Flags2
										== ITEM_FLAGS_EXTRA_ALLIANCE_ONLY
										&& _player->GetTeam() == HORDE)))
					continue;
				++count;
				if (count == 150)
					break; // client can only display 15 pages

				// reputation discount
				int32 price =
						crItem->IsGoldRequired(pProto) ?
								uint32(floor(pProto->BuyPrice * discountMod)) :
								0;

				data << uint32(vendorslot + 1); // client expects counting to start at 1
				data << uint32(1); // unknow value 4.0.1, always 1
				data << uint32(crItem->item);
				data << uint32(pProto->DisplayInfoID);
				data
						<< int32(
								crItem->maxcount <= 0 ?
										0xFFFFFFFF :
										pCreature->GetVendorItemCurrentCount(
												crItem));
				data << uint32(price);
				data << uint32(pProto->MaxDurability);
				data << uint32(pProto->BuyCount);
				data << uint32(crItem->ExtendedCost);
				data << uint8(0); // unk 4.0.1
			}
		}
	}

	//TODO: add error messages.
	/*switch ( v13 )
	 {
	 case 2:
	 ConsoleWrite(v7, a2, (int)"You are too far away", 0);
	 break;
	 case 1:
	 ConsoleWrite(v7, a2, (int)"I don't think he likes you very much", 0);
	 break;
	 case 0:
	 ConsoleWrite(v7, a2, (int)"Vendor has no inventory", 0);
	 break;
	 case 3:
	 ConsoleWrite(v7, a2, (int)"Vendor is dead", 0);
	 break;
	 case 4:
	 ConsoleWrite(v7, a2, (int)"You can't shop while dead.", 0);
	 break;
	 default:
	 break;
	 }*/

	if (count == 0) {
		data << uint8(0);
		SendPacket(&data);
		return;
	}

	data.put<uint8>(count_pos, count);
	SendPacket(&data);
}
Example #10
0
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, NULL, ObjectGuid::Empty);
        return;
    }

    // remove fake death
    if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
        GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH);

    // Stop the npc if moving
    if (vendor->HasUnitState(UNIT_STATE_MOVING))
        vendor->StopMoving();

    VendorItemData const* vendorItems = vendor->GetVendorItems();
    uint32 rawItemCount = vendorItems ? vendorItems->GetItemCount() : 0;

    WorldPackets::NPC::VendorInventory packet;
    packet.Vendor = vendor->GetGUID();

    packet.Items.resize(rawItemCount);

    const float discountMod = _player->GetReputationPriceDiscount(vendor);
    uint8 count = 0;
    for (uint32 slot = 0; slot < rawItemCount; ++slot)
    {
        VendorItem const* vendorItem = vendorItems->GetItem(slot);
        if (!vendorItem)
            continue;

        WorldPackets::NPC::VendorItem& item = packet.Items[count];

        if (vendorItem->Type == ITEM_VENDOR_TYPE_ITEM)
        {
            ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(vendorItem->item);
            if (!itemTemplate)
                continue;

            int32 leftInStock = !vendorItem->maxcount ? -1 : vendor->GetVendorItemCurrentCount(vendorItem);
            if (!_player->IsGameMaster()) // ignore conditions if GM on
            {
                // Respect allowed class
                if (!(itemTemplate->GetAllowableClass() & _player->getClassMask()) && itemTemplate->GetBonding() == BIND_ON_ACQUIRE)
                    continue;

                // Only display items in vendor lists for the team the player is on
                if ((itemTemplate->GetFlags2() & ITEM_FLAG2_FACTION_HORDE && _player->GetTeam() == ALLIANCE) ||
                    (itemTemplate->GetFlags2() & ITEM_FLAG2_FACTION_ALLIANCE && _player->GetTeam() == HORDE))
                    continue;

                // Items sold out are not displayed in list
                if (leftInStock == 0)
                    continue;
            }

            if (!sConditionMgr->IsObjectMeetingVendorItemConditions(vendor->GetEntry(), vendorItem->item, _player, vendor))
            {
                TC_LOG_DEBUG("condition", "SendListInventory: conditions not met for creature entry %u item %u", vendor->GetEntry(), vendorItem->item);
                continue;
            }

            int32 price = vendorItem->IsGoldRequired(itemTemplate) ? uint32(floor(itemTemplate->GetBuyPrice() * discountMod)) : 0;

            if (int32 priceMod = _player->GetTotalAuraModifier(SPELL_AURA_MOD_VENDOR_ITEMS_PRICES))
                price -= CalculatePct(price, priceMod);

            item.MuID = slot + 1; // client expects counting to start at 1
            item.Durability = itemTemplate->MaxDurability;
            item.ExtendedCostID = vendorItem->ExtendedCost;
            item.Type = vendorItem->Type;
            item.Quantity = leftInStock;
            item.StackCount = itemTemplate->GetBuyCount();
            item.Price = price;

            item.Item.ItemID = vendorItem->item;
        }
        else if (vendorItem->Type == ITEM_VENDOR_TYPE_CURRENCY)
        {
            CurrencyTypesEntry const* currencyTemplate = sCurrencyTypesStore.LookupEntry(vendorItem->item);
            if (!currencyTemplate)
                continue;

            if (!vendorItem->ExtendedCost)
                continue; // there's no price defined for currencies, only extendedcost is used

            item.MuID = slot + 1; // client expects counting to start at 1
            item.ExtendedCostID = vendorItem->ExtendedCost;
            item.Item.ItemID = vendorItem->item;
            item.Type = vendorItem->Type;
            item.StackCount = vendorItem->maxcount;
        }
        else
            continue;

        if (++count >= MAX_VENDOR_ITEMS)
            break;
    }

    // Resize vector to real size (some items can be skipped due to checks)
    packet.Items.resize(count);

    SendPacket(packet.Write());
}
Example #11
0
    bool OnGossipSelect(Player* player, Creature* creature, uint32 sender, uint32 action)
    {
        WorldSession* session = player->GetSession();
        player->PlayerTalkClass->ClearMenus();
        switch(sender)
        {
        case SENDER_SELECT_VENDOR: // action = slot
            {
                Item* item = player->GetItemByPos(INVENTORY_SLOT_BAG_0, action);
                if (!item)
                {
                    if (const char* slotname = getSlotName(action))
                        session->SendNotification("No item equipped in %s slot", slotname);
                    OnGossipHello(player, creature);
                    return true;
                }
                const ItemTemplate * itemTemplate = item->GetTemplate();
                optionData* oM = &optionMap[(itemTemplate->Class == ITEM_CLASS_WEAPON ? MAX_ITEM_SUBCLASS_WEAPON : 0)+itemTemplate->SubClass][getCorrectInvType(itemTemplate->InventoryType)];
                if (!oM->size())
                {
                    if (const char* slotname = getSlotName(action))
                        session->SendNotification("No transmogrifications available for %s", slotname);
                    OnGossipHello(player, creature);
                    return true;
                }
                player->ADD_GOSSIP_ITEM(GOSSIP_ICON_INTERACT_1, (std::string)"Update selected; "+getItemName(itemTemplate, session), sender, action);
                for(optionData::iterator it = oM->begin(); it != oM->end(); ++it)
                {
                    if (!TransmogDisplayVendorMgr::AllowedQuality(it->first)) // skip not allowed qualities
                        continue;
                    for(uint32 count = 0; count*MAX_VENDOR_ITEMS < it->second.size(); ++count)
                    {
                        std::ostringstream ss;
                        ss << getQualityName(it->first);
                        if (count)
                            ss << " [" << count << "]";
                        player->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, ss.str().c_str(), it->first, count*MAX_VENDOR_ITEMS);
                    }
                }
                if (player->PlayerTalkClass->GetGossipMenu().GetMenuItemCount() <= 1)
                {
                    if (const char* slotname = getSlotName(action))
                        session->SendNotification("No transmogrifications available for %s", slotname);
                    player->PlayerTalkClass->ClearMenus();
                    OnGossipHello(player, creature);
                    return true;
                }
                selDataStruct temp = {action, 0, 0}; // slot, offset, quality
                selData[player->GetGUIDLow()] = temp;
                player->ADD_GOSSIP_ITEM(GOSSIP_ICON_TALK, "Back..", SENDER_BACK, 0);
                player->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, creature->GetGUID());
            } break;
        case SENDER_BACK: // Back
            {
                OnGossipHello(player, creature);
            } break;
        case SENDER_REMOVE_ALL: // Remove TransmogDisplayVendorMgrs
            {
                bool removed = false;
                for (uint8 Slot = EQUIPMENT_SLOT_START; Slot < EQUIPMENT_SLOT_END; Slot++)
                {
                    if (Item* newItem = player->GetItemByPos(INVENTORY_SLOT_BAG_0, Slot))
                    {
                        if (TransmogDisplayVendorMgr::DeleteFakeEntry(newItem) && !removed)
                            removed = true;
                    }
                }
                if (removed)
                {
                    session->SendAreaTriggerMessage("Transmogrifications removed from equipped items");
                    player->PlayDirectSound(3337);
                }
                else
                    session->SendNotification("You have no transmogrified items equipped");
                OnGossipSelect(player, creature, SENDER_REMOVE_MENU, 0);
            } break;
        case SENDER_REMOVE_ONE: // Remove TransmogDisplayVendorMgr from single item
            {
                const char* slotname = getSlotName(action);
                if (Item* newItem = player->GetItemByPos(INVENTORY_SLOT_BAG_0, action))
                {
                    if (TransmogDisplayVendorMgr::DeleteFakeEntry(newItem))
                    {
                        if (slotname)
                            session->SendAreaTriggerMessage("%s transmogrification removed", slotname);
                        player->PlayDirectSound(3337);
                    }
                    else if (slotname)
                        session->SendNotification("No transmogrification on %s slot", slotname);
                }
                else if (slotname)
                    session->SendNotification("No item equipped in %s slot", slotname);
                OnGossipSelect(player, creature, SENDER_REMOVE_MENU, 0);
            } break;
        case SENDER_REMOVE_MENU:
            {
                for (uint8 slot = EQUIPMENT_SLOT_START; slot < EQUIPMENT_SLOT_END; slot++)
                {
                    const char* slotname = getSlotName(slot);
                    if (!slotname)
                        continue;
                    std::ostringstream ss;
                    ss << "Remove transmogrification from " << slotname << "?";
                    player->ADD_GOSSIP_ITEM_EXTENDED(GOSSIP_ICON_INTERACT_1, (std::string)"Remove from "+slotname, SENDER_REMOVE_ONE, slot, ss.str().c_str(), 0, false);
                }
                player->ADD_GOSSIP_ITEM_EXTENDED(GOSSIP_ICON_INTERACT_1, "Remove all transmogrifications", SENDER_REMOVE_ALL, 0, "Are you sure you want to remove all transmogrifications?", 0, false);
                player->ADD_GOSSIP_ITEM(GOSSIP_ICON_TALK, "Back..", SENDER_BACK, 0);
                player->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, creature->GetGUID());
            } break;
        default: // Show items you can use
            {
                if (sender >= MAX_ITEM_QUALITY) // sender = quality, action = iterator
                    return false; // cheat
                if (selData.find(player->GetGUIDLow()) == selData.end())
                    return false; // cheat
                if (selData[player->GetGUIDLow()].offset != 0 || selData[player->GetGUIDLow()].quality != 0)
                    return false; // cheat (something is off)
                selData[player->GetGUIDLow()].offset = action;
                selData[player->GetGUIDLow()].quality = sender;
                uint32 slot = selData[player->GetGUIDLow()].slot; // slot
                if (Item* item = player->GetItemByPos(INVENTORY_SLOT_BAG_0, slot))
                {
                    if (!TransmogDisplayVendorMgr::AllowedQuality(item->GetTemplate()->Quality))
                    {
                        session->SendNotification("Equipped item has wrong quality");
                        OnGossipSelect(player, creature, SENDER_SELECT_VENDOR, slot);
                        return true;
                    }
                    optionDataList oM = optionMap[(item->GetTemplate()->Class == ITEM_CLASS_WEAPON ? MAX_ITEM_SUBCLASS_WEAPON : 0)+item->GetTemplate()->SubClass][getCorrectInvType(item->GetTemplate()->InventoryType)][sender];
                    uint32 itemCount = (oM.size()-action);
                    if (itemCount > MAX_VENDOR_ITEMS)
                        itemCount = MAX_VENDOR_ITEMS;
                    if (!itemCount)
                    {
                        session->SendAreaTriggerMessage("No items found");
                        OnGossipSelect(player, creature, SENDER_SELECT_VENDOR, slot);
                        return true;
                    }
                    player->CLOSE_GOSSIP_MENU();

                    TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_LIST_INVENTORY");

                    Creature* vendor = player->GetNPCIfCanInteractWith(creature->GetGUID(), UNIT_NPC_FLAG_VENDOR);
                    if (!vendor)
                    {
                        TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: SendListInventory - Unit (GUID: %u) not found or you can not interact with him.", creature->GetGUIDLow());
                        player->SendSellError(SELL_ERR_CANT_FIND_VENDOR, NULL, 0, 0);
                        return true;
                    }

                    if (player->HasUnitState(UNIT_STATE_DIED))
                        player->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH);

                    if (vendor->HasUnitState(UNIT_STATE_MOVING))
                        vendor->StopMoving();
                    uint8 count = 0;

                    WorldPacket data(SMSG_LIST_INVENTORY, 8 + 1 + itemCount * 8 * 4);
                    data << uint64(creature->GetGUID());

                    size_t countPos = data.wpos();
                    data << uint8(count);

                    bool added = false;
                    optionDataList::iterator it = oM.begin();
                    std::advance(it, action);
                    for (; it != oM.end() && count < itemCount; ++it, ++count)
                    {
                        if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(*it))
                        {
                            data << uint32(count + 1);
                            data << uint32(itemTemplate->ItemId);
                            data << uint32(itemTemplate->DisplayInfoID);
                            data << int32(0xFFFFFFFF);
                            data << uint32(0);
                            data << uint32(itemTemplate->MaxDurability);
                            data << uint32(itemTemplate->BuyCount);
                            data << uint32(0);
                            added = true;
                        }
                    }

                    if (!added)
                    {
                        data << uint8(0);
                        session->SendPacket(&data);
                    }
                    else
                    {
                        data.put<uint8>(countPos, count);
                        session->SendPacket(&data);
                    }
                }
                else
                {
                    session->SendNotification("No item equipped");
                    OnGossipSelect(player, creature, SENDER_SELECT_VENDOR, slot);
                    return true;
                }
            } break;
        }
        return true;
    }
Example #12
0
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
RandomMovementGenerator<Creature>::_setRandomLocation(Creature& creature)
{
    if (creature.HasUnitState(UNIT_STATE_CASTING) && !creature.CanMoveDuringChannel())
    {
        creature.CastStop();
        return;
    }

    float X, Y, Z, nx, ny, nz, ori, dist;
    creature.GetHomePosition(X, Y, Z, ori);
    Map const* map = creature.GetBaseMap();

    // For 2D/3D system selection
    //bool is_land_ok  = creature.canWalk();
    //bool is_water_ok = creature.canSwim();
    bool is_air_ok   = creature.canFly();

    const float angle = rand_norm() * (M_PI * 2);
    const float range = rand_norm() * wander_distance;
    const float distanceX = range * cos(angle);
    const float distanceY = range * sin(angle);

    nx = X + distanceX;
    ny = Y + distanceY;

    // prevent invalid coordinates generation
    Oregon::NormalizeMapCoord(nx);
    Oregon::NormalizeMapCoord(ny);

    dist = (nx - X) * (nx - X) + (ny - Y) * (ny - Y);
    
    if (is_air_ok)                                          // 3D system above ground and above water (flying mode)
    {
        // Limit height change
        const float distanceZ = rand_norm() * sqrtf(dist) / 2.0f;
        nz = Z + distanceZ;
        float tz = map->GetHeight(nx, ny, nz - 2.0f, false); // Map check only, vmap needed here but need to alter vmaps checks for height.
        float wz = map->GetWaterLevel(nx, ny);

        // Problem here, we must fly above the ground and water, not under. Let's try on next tick
        if (tz >= nz || wz >= nz)
            return;
    }
    //else if (is_water_ok)                                 // 3D system under water and above ground (swimming mode)
    else                                                    // 2D only
    {
        dist = dist >= 100.0f ? 10.0f : sqrtf(dist);        // 10.0 is the max that vmap high can check (MAX_CAN_FALL_DISTANCE)

        // The fastest way to get an accurate result 90% of the time.
        // Better result can be obtained like 99% accuracy with a ray light, but the cost is too high and the code is too long.
        nz = map->GetHeight(nx, ny, Z + dist - 2.0f, false);

        if (fabs(nz - Z) > dist)                            // Map check
        {
            nz = map->GetHeight(nx, ny, Z - 2.0f, true);    // Vmap Horizontal or above

            if (fabs(nz - Z) > dist)
            {
                // Vmap Higher
                nz = map->GetHeight(nx, ny, Z + dist - 2.0f, true);

                // let's forget this bad coords where a z cannot be find and retry at next tick
                if (fabs(nz - Z) > dist)
                    return;
            }
        }
    }

    if (is_air_ok)
        i_nextMoveTime.Reset(0);
    else
    {
        if (roll_chance_i(MOVEMENT_RANDOM_MMGEN_CHANCE_NO_BREAK))
            i_nextMoveTime.Reset(urand(5000, 10000));
        else
            i_nextMoveTime.Reset(urand(50, 400));
    }

    creature.AddUnitState(UNIT_STATE_ROAMING);

    Movement::MoveSplineInit init(creature);
    init.MoveTo(nx, ny, nz, true);
    if (creature.IsPet() && creature.GetOwner() && !creature.IsWithinDist(creature.GetOwner(), PET_FOLLOW_DIST + 2.5f))
        init.SetWalk(false);
    else
        init.SetWalk(true);
    init.Launch();
        if (roll_chance_i(MOVEMENT_RANDOM_MMGEN_CHANCE_NO_BREAK))
            i_nextMoveTime.Reset(50);
        else
        i_nextMoveTime.Reset(urand(1500, 10000));       // Keep a short wait time
}
void RandomMovementGenerator<Creature>::Finalize(Creature& creature)
{
    creature.ClearUnitState(UNIT_STATE_ROAMING);
    creature.SetWalk(!creature.HasUnitState(UNIT_STATE_RUNNING_STATE));
}