diff options
Diffstat (limited to 'src')
21 files changed, 274 insertions, 147 deletions
diff --git a/src/server/collision/Management/VMapManager2.cpp b/src/server/collision/Management/VMapManager2.cpp index 62abc31831a..81b97f5f352 100644 --- a/src/server/collision/Management/VMapManager2.cpp +++ b/src/server/collision/Management/VMapManager2.cpp @@ -245,7 +245,7 @@ namespace VMAP return false; } - WorldModel* VMapManager2::acquireModelInstance(const std::string& basepath, const std::string& filename) + WorldModel* VMapManager2::acquireModelInstance(const std::string& basepath, const std::string& filename, uint32 flags/* Only used when creating the model */) { //! Critical section, thread safe access to iLoadedModelFiles TRINITY_GUARD(ACE_Thread_Mutex, LoadedModelFilesLock); @@ -261,6 +261,7 @@ namespace VMAP return NULL; } sLog->outDebug(LOG_FILTER_MAPS, "VMapManager2: loading file '%s%s'", basepath.c_str(), filename.c_str()); + worldmodel->Flags = flags; model = iLoadedModelFiles.insert(std::pair<std::string, ManagedModel>(filename, ManagedModel())).first; model->second.setModel(worldmodel); } diff --git a/src/server/collision/Management/VMapManager2.h b/src/server/collision/Management/VMapManager2.h index 1fba108388a..4b66a2e9fc7 100755 --- a/src/server/collision/Management/VMapManager2.h +++ b/src/server/collision/Management/VMapManager2.h @@ -103,7 +103,7 @@ namespace VMAP bool getAreaInfo(unsigned int pMapId, float x, float y, float& z, uint32& flags, int32& adtId, int32& rootId, int32& groupId) const; bool GetLiquidLevel(uint32 pMapId, float x, float y, float z, uint8 reqLiquidType, float& level, float& floor, uint32& type) const; - WorldModel* acquireModelInstance(const std::string& basepath, const std::string& filename); + WorldModel* acquireModelInstance(const std::string& basepath, const std::string& filename, uint32 flags = 0); void releaseModelInstance(const std::string& filename); // what's the use of this? o.O diff --git a/src/server/collision/Maps/MapTree.cpp b/src/server/collision/Maps/MapTree.cpp index fda0535e8a7..f94f9bbf52b 100644 --- a/src/server/collision/Maps/MapTree.cpp +++ b/src/server/collision/Maps/MapTree.cpp @@ -127,7 +127,7 @@ namespace VMAP StaticMapTree::StaticMapTree(uint32 mapID, const std::string &basePath): iMapID(mapID), iTreeValues(0), iBasePath(basePath) { - if (iBasePath.length() > 0 && (iBasePath[iBasePath.length()-1] != '/' || iBasePath[iBasePath.length()-1] != '\\')) + if (iBasePath.length() > 0 && iBasePath[iBasePath.length()-1] != '/' && iBasePath[iBasePath.length()-1] != '\\') { iBasePath.push_back('/'); } @@ -241,7 +241,7 @@ namespace VMAP bool StaticMapTree::CanLoadMap(const std::string &vmapPath, uint32 mapID, uint32 tileX, uint32 tileY) { std::string basePath = vmapPath; - if (basePath.length() > 0 && (basePath[basePath.length()-1] != '/' || basePath[basePath.length()-1] != '\\')) + if (basePath.length() > 0 && basePath[basePath.length()-1] != '/' && basePath[basePath.length()-1] != '\\') basePath.push_back('/'); std::string fullname = basePath + VMapManager2::getMapFileName(mapID); bool success = true; @@ -309,7 +309,7 @@ namespace VMAP #endif if (!iIsTiled && ModelSpawn::readFromFile(rf, spawn)) { - WorldModel* model = vm->acquireModelInstance(iBasePath, spawn.name); + WorldModel* model = vm->acquireModelInstance(iBasePath, spawn.name, spawn.flags); sLog->outDebug(LOG_FILTER_MAPS, "StaticMapTree::InitMap() : loading %s", spawn.name.c_str()); if (model) { @@ -380,7 +380,7 @@ namespace VMAP if (result) { // acquire model instance - WorldModel* model = vm->acquireModelInstance(iBasePath, spawn.name); + WorldModel* model = vm->acquireModelInstance(iBasePath, spawn.name, spawn.flags); if (!model) sLog->outError("StaticMapTree::LoadMapTile() : could not acquire WorldModel pointer [%u, %u]", tileX, tileY); diff --git a/src/server/collision/Models/WorldModel.cpp b/src/server/collision/Models/WorldModel.cpp index a7de37d41e6..b49538a485d 100644 --- a/src/server/collision/Models/WorldModel.cpp +++ b/src/server/collision/Models/WorldModel.cpp @@ -420,6 +420,9 @@ namespace VMAP bool WorldModel::IntersectRay(const G3D::Ray &ray, float &distance, bool stopAtFirstHit) const { + // M2 models are not taken into account for LoS calculation + if (Flags & MOD_M2) + return false; // small M2 workaround, maybe better make separate class with virtual intersection funcs // in any case, there's no need to use a bound tree if we only have one submodel if (groupModels.size() == 1) diff --git a/src/server/collision/Models/WorldModel.h b/src/server/collision/Models/WorldModel.h index ebf828e4935..dbaccb58573 100755 --- a/src/server/collision/Models/WorldModel.h +++ b/src/server/collision/Models/WorldModel.h @@ -113,6 +113,7 @@ namespace VMAP bool GetLocationInfo(const G3D::Vector3 &p, const G3D::Vector3 &down, float &dist, LocationInfo &info) const; bool writeFile(const std::string &filename); bool readFile(const std::string &filename); + uint32 Flags; protected: uint32 RootWMOID; std::vector<GroupModel> groupModels; diff --git a/src/server/game/AI/CoreAI/CombatAI.cpp b/src/server/game/AI/CoreAI/CombatAI.cpp index d8def36f999..86f2c6a28b7 100755 --- a/src/server/game/AI/CoreAI/CombatAI.cpp +++ b/src/server/game/AI/CoreAI/CombatAI.cpp @@ -326,7 +326,7 @@ void VehicleAI::CheckConditions(const uint32 diff) { if (Player* player = passenger->ToPlayer()) { - if (!sConditionMgr->IsObjectMeetToConditions(player, conditions)) + if (!sConditionMgr->IsObjectMeetToConditions(player, me, conditions)) { player->ExitVehicle(); return;//check other pessanger in next tick diff --git a/src/server/game/AuctionHouse/AuctionHouseMgr.h b/src/server/game/AuctionHouse/AuctionHouseMgr.h index f81393be761..190fbcc5107 100644 --- a/src/server/game/AuctionHouse/AuctionHouseMgr.h +++ b/src/server/game/AuctionHouse/AuctionHouseMgr.h @@ -30,6 +30,7 @@ class Player; class WorldPacket; #define MIN_AUCTION_TIME (12*HOUR) +#define MAX_AUCTION_ITEMS 160 enum AuctionError { diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp index bcdc6c26524..f52cb96501f 100755 --- a/src/server/game/Conditions/ConditionMgr.cpp +++ b/src/server/game/Conditions/ConditionMgr.cpp @@ -343,6 +343,10 @@ uint32 Condition::GetMaxAvailableConditionTargets() switch(SourceType) { case CONDITION_SOURCE_TYPE_SPELL: + case CONDITION_SOURCE_TYPE_CREATURE_TEMPLATE_VEHICLE: + case CONDITION_SOURCE_TYPE_VEHICLE_SPELL: + case CONDITION_SOURCE_TYPE_GOSSIP_MENU: + case CONDITION_SOURCE_TYPE_GOSSIP_MENU_OPTION: return 2; case CONDITION_SOURCE_TYPE_SMART_EVENT: return 2; @@ -418,6 +422,12 @@ bool ConditionMgr::IsObjectMeetToConditions(WorldObject* object, ConditionList c return IsObjectMeetToConditions(srcInfo, conditions); } +bool ConditionMgr::IsObjectMeetToConditions(WorldObject* object1, WorldObject* object2, ConditionList const& conditions) +{ + ConditionSourceInfo srcInfo = ConditionSourceInfo(object1, object2); + return IsObjectMeetToConditions(srcInfo, conditions); +} + bool ConditionMgr::IsObjectMeetToConditions(ConditionSourceInfo& sourceInfo, ConditionList const& conditions) { if (conditions.empty()) diff --git a/src/server/game/Conditions/ConditionMgr.h b/src/server/game/Conditions/ConditionMgr.h index dc204ccd0ec..c0bc5635838 100755 --- a/src/server/game/Conditions/ConditionMgr.h +++ b/src/server/game/Conditions/ConditionMgr.h @@ -199,6 +199,7 @@ class ConditionMgr ConditionList GetConditionReferences(uint32 refId); bool IsObjectMeetToConditions(WorldObject* object, ConditionList const& conditions); + bool IsObjectMeetToConditions(WorldObject* object1, WorldObject* object2, ConditionList const& conditions); bool IsObjectMeetToConditions(ConditionSourceInfo& sourceInfo, ConditionList const& conditions); ConditionList GetConditionsForNotGroupedEntry(ConditionSourceType sourceType, uint32 entry); ConditionList GetConditionsForSmartEvent(int32 entryOrGuid, uint32 eventId, uint32 sourceType); diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 64b0e542467..80511f49a64 100755 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -14089,7 +14089,7 @@ void Player::PrepareGossipMenu(WorldObject* source, uint32 menuId /*= 0*/, bool for (GossipMenuItemsContainer::const_iterator itr = menuItemBounds.first; itr != menuItemBounds.second; ++itr) { bool canTalk = true; - if (!sConditionMgr->IsObjectMeetToConditions(this, itr->second.Conditions)) + if (!sConditionMgr->IsObjectMeetToConditions(this, source, itr->second.Conditions)) continue; if (source->GetTypeId() == TYPEID_UNIT) @@ -14233,7 +14233,7 @@ void Player::SendPreparedGossip(WorldObject* source) uint32 textId = GetGossipTextId(source); if (uint32 menuId = PlayerTalkClass->GetGossipMenu().GetMenuId()) - textId = GetGossipTextId(menuId); + textId = GetGossipTextId(menuId, source); PlayerTalkClass->SendGossipMenu(textId, source->GetGUID()); } @@ -14378,10 +14378,10 @@ uint32 Player::GetGossipTextId(WorldObject* source) if (!source) return DEFAULT_GOSSIP_MESSAGE; - return GetGossipTextId(GetDefaultGossipMenuForSource(source)); + return GetGossipTextId(GetDefaultGossipMenuForSource(source), source); } -uint32 Player::GetGossipTextId(uint32 menuId) +uint32 Player::GetGossipTextId(uint32 menuId, WorldObject* source) { uint32 textId = DEFAULT_GOSSIP_MESSAGE; @@ -14391,8 +14391,10 @@ uint32 Player::GetGossipTextId(uint32 menuId) GossipMenusMapBounds menuBounds = sObjectMgr->GetGossipMenusMapBounds(menuId); for (GossipMenusContainer::const_iterator itr = menuBounds.first; itr != menuBounds.second; ++itr) - if (sConditionMgr->IsObjectMeetToConditions(this, itr->second.conditions)) + { + if (sConditionMgr->IsObjectMeetToConditions(this, source, itr->second.conditions)) textId = itr->second.text_id; + } return textId; } @@ -19862,7 +19864,7 @@ void Player::VehicleSpellInitialize() } ConditionList conditions = sConditionMgr->GetConditionsForVehicleSpell(veh->GetEntry(), spellId); - if (!sConditionMgr->IsObjectMeetToConditions(this, conditions)) + if (!sConditionMgr->IsObjectMeetToConditions(this, veh, conditions)) { sLog->outDebug(LOG_FILTER_CONDITIONSYS, "VehicleSpellInitialize: conditions not met for Vehicle entry %u spell %u", veh->ToCreature()->GetEntry(), spellId); data << uint16(0) << uint8(0) << uint8(i+8); diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 0fb2a6fb75d..7f08f03b5f8 100755 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -1383,7 +1383,7 @@ class Player : public Unit, public GridObject<Player> void SendPreparedGossip(WorldObject* source); void OnGossipSelect(WorldObject* source, uint32 gossipListId, uint32 menuId); - uint32 GetGossipTextId(uint32 menuId); + uint32 GetGossipTextId(uint32 menuId, WorldObject* source); uint32 GetGossipTextId(WorldObject* source); static uint32 GetDefaultGossipMenuForSource(WorldObject* source); diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.h b/src/server/game/Grids/Notifiers/GridNotifiers.h index e3029a1be65..4112711ad3c 100755 --- a/src/server/game/Grids/Notifiers/GridNotifiers.h +++ b/src/server/game/Grids/Notifiers/GridNotifiers.h @@ -530,20 +530,38 @@ namespace Trinity class RaiseDeadObjectCheck { public: - RaiseDeadObjectCheck(Unit* funit, float range) : i_funit(funit), i_range(range) {} + RaiseDeadObjectCheck(Unit* source, float range) : _source(source), i_range(range) {} bool operator()(Creature* u) { - if (i_funit->GetTypeId() != TYPEID_PLAYER || !((Player*)i_funit)->isHonorOrXPTarget(u) || - u->getDeathState() != CORPSE || u->isInFlight() || + if (_source->GetTypeId() != TYPEID_PLAYER || !((Player*)_source)->isHonorOrXPTarget(u) || + u->getDeathState() != CORPSE || (u->GetCreatureTypeMask() & (1 << (CREATURE_TYPE_HUMANOID-1))) == 0 || (u->GetDisplayId() != u->GetNativeDisplayId())) return false; - return i_funit->IsWithinDistInMap(u, i_range); + return _source->IsWithinDistInMap(u, i_range); + } + + bool operator()(Player* u) + { + if (_source == u || _source->GetTypeId() != TYPEID_PLAYER || !((Player*)_source)->isHonorOrXPTarget(u) || + u->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST) || u->isInFlight() || !u->isDead() || + (u->GetCreatureTypeMask() & (1 << (CREATURE_TYPE_HUMANOID-1))) == 0) + return false; + + return _source->IsWithinDistInMap(u, i_range); + } + + bool operator()(Corpse* u) + { + if (_source->GetTypeId() != TYPEID_PLAYER || u->GetType() == CORPSE_BONES) + return false; + + return _source->IsWithinDistInMap(u, i_range); } template<class NOT_INTERESTED> bool operator()(NOT_INTERESTED*) { return false; } private: - Unit* const i_funit; + Unit* const _source; float i_range; }; diff --git a/src/server/game/Handlers/AuctionHouseHandler.cpp b/src/server/game/Handlers/AuctionHouseHandler.cpp index 8a98b038efd..fc87d3ed8d6 100755 --- a/src/server/game/Handlers/AuctionHouseHandler.cpp +++ b/src/server/game/Handlers/AuctionHouseHandler.cpp @@ -115,42 +115,53 @@ void WorldSession::SendAuctionOwnerNotification(AuctionEntry* auction) //this void creates new auction and adds auction to some auctionhouse void WorldSession::HandleAuctionSellItem(WorldPacket & recv_data) { - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_AUCTION_SELL_ITEM"); - - uint64 auctioneer, item; - uint32 etime, bid, buyout, count; + uint64 auctioneer; + uint32 itemsCount, etime, bid, buyout; recv_data >> auctioneer; - recv_data.read_skip<uint32>(); // const 1? - recv_data >> item; - recv_data >> count; // 3.2.2, number of items being auctioned + recv_data >> itemsCount; + + uint64 itemGUIDs[MAX_AUCTION_ITEMS]; // 160 slot = 4x 36 slot bag + backpack 16 slot + uint32 count[MAX_AUCTION_ITEMS]; + + for (uint32 i = 0; i < itemsCount; ++i) + { + recv_data >> itemGUIDs[i]; + recv_data >> count[i]; + + if (!itemGUIDs[i] || !count[i] || count[i] > 1000 ) + return; + } + recv_data >> bid; recv_data >> buyout; recv_data >> etime; - Player* player = GetPlayer(); - - if (!item || !bid || !etime) - return; //check for cheaters + if (!bid || !etime) + return; Creature* creature = GetPlayer()->GetNPCIfCanInteractWith(auctioneer, UNIT_NPC_FLAG_AUCTIONEER); if (!creature) { - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleAuctionSellItem - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(auctioneer))); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleAuctionSellItem - Unit (GUID: %u) not found or you can't interact with him.", GUID_LOPART(auctioneer)); return; } AuctionHouseEntry const* auctionHouseEntry = AuctionHouseMgr::GetAuctionHouseEntry(creature->getFaction()); if (!auctionHouseEntry) { - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleAuctionSellItem - Unit (GUID: %u) has wrong faction.", uint32(GUID_LOPART(auctioneer))); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleAuctionSellItem - Unit (GUID: %u) has wrong faction.", GUID_LOPART(auctioneer)); + return; + } + + if (itemsCount > MAX_AUCTION_ITEMS) + { + SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR); return; } - // client send time in minutes, convert to common used sec time etime *= MINUTE; - // client understand only 3 auction time - switch (etime) + switch(etime) { case 1*MIN_AUCTION_TIME: case 2*MIN_AUCTION_TIME: @@ -160,96 +171,181 @@ void WorldSession::HandleAuctionSellItem(WorldPacket & recv_data) return; } - // remove fake death if (GetPlayer()->HasUnitState(UNIT_STATE_DIED)) GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - Item* it = player->GetItemByGuid(item); - //do not allow to sell already auctioned items - if (sAuctionMgr->GetAItem(GUID_LOPART(item))) - { - sLog->outError("AuctionError, player %s is sending item id: %u, but item is already in another auction", player->GetName(), GUID_LOPART(item)); - SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR); - return; - } - // prevent sending bag with items (cheat: can be placed in bag after adding equiped empty bag to auction) - if (!it) + Item* items[MAX_AUCTION_ITEMS]; + + uint32 finalCount = 0; + + for (uint32 i = 0; i < itemsCount; ++i) { - SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_ITEM_NOT_FOUND); - return; + Item* item = _player->GetItemByGuid(itemGUIDs[i]); + + if (!item) + { + SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_ITEM_NOT_FOUND); + return; + } + + if (sAuctionMgr->GetAItem(item->GetGUIDLow()) || !item->CanBeTraded() || item->IsNotEmptyBag() || + item->GetTemplate()->Flags & ITEM_PROTO_FLAG_CONJURED || item->GetUInt32Value(ITEM_FIELD_DURATION) || + item->GetCount() < count[i]) + { + SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR); + return; + } + + items[i] = item; + finalCount += count[i]; } - if (!it->CanBeTraded()) + if (!finalCount) { SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR); return; } - if (it->GetTemplate()->Flags & ITEM_PROTO_FLAG_CONJURED || it->GetUInt32Value(ITEM_FIELD_DURATION)) + for (uint32 i = 0; i < itemsCount; ++i) { - SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR); - return; + Item* item = items[i]; + + if (item->GetMaxStackCount() < finalCount) + { + SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR); + return; + } } - if (it->IsNotEmptyBag()) + for (uint32 i = 0; i < itemsCount; ++i) { - SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR); - return; - } + Item* item = items[i]; - AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->getFaction()); + uint32 auctionTime = uint32(etime * sWorld->getRate(RATE_AUCTION_TIME)); + AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->getFaction()); - //we have to take deposit : - uint32 deposit = sAuctionMgr->GetAuctionDeposit(auctionHouseEntry, etime, it, count); - if (!player->HasEnoughMoney(deposit)) - { - SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_NOT_ENOUGHT_MONEY); - return; - } + uint32 deposit = sAuctionMgr->GetAuctionDeposit(auctionHouseEntry, etime, item, finalCount); + if (!_player->HasEnoughMoney(deposit)) + { + SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_NOT_ENOUGHT_MONEY); + return; + } - if (AccountMgr::IsGMAccount(GetSecurity()) && sWorld->getBoolConfig(CONFIG_GM_LOG_TRADE)) - { - sLog->outCommand(GetAccountId(), "GM %s (Account: %u) create auction: %s (Entry: %u Count: %u)", - GetPlayerName(), GetAccountId(), it->GetTemplate()->Name1.c_str(), it->GetEntry(), count); - } + _player->ModifyMoney(-int32(deposit)); - player->ModifyMoney(-int32(deposit)); + AuctionEntry* AH = new AuctionEntry; + AH->Id = sObjectMgr->GenerateAuctionID(); - uint32 auction_time = uint32(etime * sWorld->getRate(RATE_AUCTION_TIME)); + if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION)) + AH->auctioneer = 23442; + else + AH->auctioneer = GUID_LOPART(auctioneer); - AuctionEntry* AH = new AuctionEntry; - AH->Id = sObjectMgr->GenerateAuctionID(); - if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION)) - AH->auctioneer = 23442; - else - AH->auctioneer = GUID_LOPART(auctioneer); - AH->item_guidlow = GUID_LOPART(item); - AH->item_template = it->GetEntry(); - AH->owner = player->GetGUIDLow(); - AH->startbid = bid; - AH->bidder = 0; - AH->bid = 0; - AH->buyout = buyout; - AH->expire_time = time(NULL) + auction_time; - AH->deposit = deposit; - AH->auctionHouseEntry = auctionHouseEntry; - - sLog->outDetail("selling item %u to auctioneer %u with initial bid %u with buyout %u and with time %u (in sec) in auctionhouse %u", GUID_LOPART(item), AH->auctioneer, bid, buyout, auction_time, AH->GetHouseId()); - sAuctionMgr->AddAItem(it); - auctionHouse->AddAuction(AH); - - player->MoveItemFromInventory(it->GetBagSlot(), it->GetSlot(), true); + if (itemsCount == 1 && item->GetCount() == count[i]) + { + if (GetSecurity() > SEC_PLAYER && sWorld->getBoolConfig(CONFIG_GM_LOG_TRADE)) + { + sLog->outCommand(GetAccountId(), "GM %s (Account: %u) create auction: %s (Entry: %u Count: %u)", + GetPlayerName(), GetAccountId(), item->GetTemplate()->Name1.c_str(), item->GetEntry(), item->GetCount()); + } - SQLTransaction trans = CharacterDatabase.BeginTransaction(); - it->DeleteFromInventoryDB(trans); - it->SaveToDB(trans); // recursive and not have transaction guard into self, not in inventiory and can be save standalone - AH->SaveToDB(trans); - player->SaveInventoryAndGoldToDB(trans); - CharacterDatabase.CommitTransaction(trans); + AH->item_guidlow = item->GetGUIDLow(); + AH->item_template = item->GetEntry(); + AH->owner = _player->GetGUIDLow(); + AH->startbid = bid; + AH->bidder = 0; + AH->bid = 0; + AH->buyout = buyout; + AH->expire_time = time(NULL) + auctionTime; + AH->deposit = deposit; + AH->auctionHouseEntry = auctionHouseEntry; + + sLog->outDetail("CMSG_AUCTION_SELL_ITEM: Player %s (guid %d) is selling item %s entry %u (guid %d) to auctioneer %u with count %u with initial bid %u with buyout %u and with time %u (in sec) in auctionhouse %u", _player->GetName(), _player->GetGUIDLow(), item->GetTemplate()->Name1.c_str(), item->GetEntry(), item->GetGUIDLow(), AH->auctioneer, item->GetCount(), bid, buyout, auctionTime, AH->GetHouseId()); + sAuctionMgr->AddAItem(item); + auctionHouse->AddAuction(AH); + + _player->MoveItemFromInventory(item->GetBagSlot(), item->GetSlot(), true); + + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + item->DeleteFromInventoryDB(trans); + item->SaveToDB(trans); + AH->SaveToDB(trans); + _player->SaveInventoryAndGoldToDB(trans); + CharacterDatabase.CommitTransaction(trans); + + SendAuctionCommandResult(AH->Id, AUCTION_SELL_ITEM, AUCTION_OK); + + GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION, 1); + return; + } + else + { + Item* newItem = item->CloneItem(finalCount, _player); + if (!newItem) + { + sLog->outError("CMSG_AUCTION_SELL_ITEM: Could not create clone of item %u", item->GetEntry()); + SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR); + return; + } - SendAuctionCommandResult(AH->Id, AUCTION_SELL_ITEM, AUCTION_OK); + if (GetSecurity() > SEC_PLAYER && sWorld->getBoolConfig(CONFIG_GM_LOG_TRADE)) + { + sLog->outCommand(GetAccountId(), "GM %s (Account: %u) create auction: %s (Entry: %u Count: %u)", + GetPlayerName(), GetAccountId(), newItem->GetTemplate()->Name1.c_str(), newItem->GetEntry(), newItem->GetCount()); + } + + AH->item_guidlow = newItem->GetGUIDLow(); + AH->item_template = newItem->GetEntry(); + AH->owner = _player->GetGUIDLow(); + AH->startbid = bid; + AH->bidder = 0; + AH->bid = 0; + AH->buyout = buyout; + AH->expire_time = time(NULL) + auctionTime; + AH->deposit = deposit; + AH->auctionHouseEntry = auctionHouseEntry; + + sLog->outDetail("CMSG_AUCTION_SELL_ITEM: Player %s (guid %d) is selling item %s entry %u (guid %d) to auctioneer %u with count %u with initial bid %u with buyout %u and with time %u (in sec) in auctionhouse %u", _player->GetName(), _player->GetGUIDLow(), newItem->GetTemplate()->Name1.c_str(), newItem->GetEntry(), newItem->GetGUIDLow(), AH->auctioneer, newItem->GetCount(), bid, buyout, auctionTime, AH->GetHouseId()); + sAuctionMgr->AddAItem(newItem); + auctionHouse->AddAuction(AH); + + for (uint32 i = 0; i < itemsCount; ++i) + { + Item* item = items[i]; + + if (item->GetCount() == count[i]) + { + _player->MoveItemFromInventory(item->GetBagSlot(), item->GetSlot(), true); + + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + item->DeleteFromInventoryDB(trans); + item->SaveToDB(trans); + CharacterDatabase.CommitTransaction(trans); + } + else + { + item->SetCount(item->GetCount() - count[i]); + item->SetState(ITEM_CHANGED, _player); + _player->ItemRemovedQuestCheck(item->GetEntry(), count[i]); + item->SendUpdateToPlayer(_player); + + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + item->SaveToDB(trans); + CharacterDatabase.CommitTransaction(trans); + } + } + + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + AH->SaveToDB(trans); + _player->SaveInventoryAndGoldToDB(trans); + CharacterDatabase.CommitTransaction(trans); - GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION, 1); + SendAuctionCommandResult(AH->Id, AUCTION_SELL_ITEM, AUCTION_OK); + + GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION, 1); + return; + } + } } //this function is called when client bids or buys out auction diff --git a/src/server/game/Handlers/PetitionsHandler.cpp b/src/server/game/Handlers/PetitionsHandler.cpp index b4c07811598..38d17d8c3b6 100755 --- a/src/server/game/Handlers/PetitionsHandler.cpp +++ b/src/server/game/Handlers/PetitionsHandler.cpp @@ -241,9 +241,8 @@ void WorldSession::HandlePetitionBuyOpcode(WorldPacket & recv_data) CharacterDatabase.CommitTransaction(trans); } -void WorldSession::HandlePetitionShowSignOpcode(WorldPacket & recv_data) +void WorldSession::HandlePetitionShowSignOpcode(WorldPacket& recv_data) { - // ok sLog->outDebug(LOG_FILTER_NETWORKIO, "Received opcode CMSG_PETITION_SHOW_SIGNATURES"); uint8 signs = 0; @@ -256,7 +255,7 @@ void WorldSession::HandlePetitionShowSignOpcode(WorldPacket & recv_data) QueryResult result = CharacterDatabase.PQuery("SELECT type FROM petition WHERE petitionguid = '%u'", petitionguid_low); if (!result) { - sLog->outError("Petition %u is not found for player %u %s", GUID_LOPART(petitionguid), GetPlayer()->GetGUIDLow(), GetPlayer()->GetName()); + sLog->outDebug(LOG_FILTER_PLAYER_ITEMS, "Petition %u is not found for player %u %s", GUID_LOPART(petitionguid), GetPlayer()->GetGUIDLow(), GetPlayer()->GetName()); return; } Field* fields = result->Fetch(); diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 670b743d725..6cacf5e7e5a 100755 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -598,24 +598,10 @@ WorldObject* Spell::FindCorpseUsing() // non-standard target selection float max_range = m_spellInfo->GetMaxRange(false); - CellCoord p(Trinity::ComputeCellCoord(m_caster->GetPositionX(), m_caster->GetPositionY())); - Cell cell(p); - cell.SetNoCreate(); - WorldObject* result = NULL; - T u_check(m_caster, max_range); Trinity::WorldObjectSearcher<T> searcher(m_caster, result, u_check); - - TypeContainerVisitor<Trinity::WorldObjectSearcher<T>, GridTypeMapContainer > grid_searcher(searcher); - cell.Visit(p, grid_searcher, *m_caster->GetMap(), *m_caster, max_range); - - if (!result) - { - TypeContainerVisitor<Trinity::WorldObjectSearcher<T>, WorldTypeMapContainer > world_searcher(searcher); - cell.Visit(p, world_searcher, *m_caster->GetMap(), *m_caster, max_range); - } - + m_caster->GetMap()->VisitFirstFound(m_caster->GetPositionX(), m_caster->GetPositionY(), max_range, searcher); return result; } @@ -2554,11 +2540,15 @@ uint32 Spell::SelectEffectTargets(uint32 i, SpellImplicitTargetInfo const& cur) { case 46584: // Raise Dead { - if (WorldObject* result = FindCorpseUsing<Trinity::RaiseDeadObjectCheck> ()) + if (WorldObject* result = FindCorpseUsing<Trinity::RaiseDeadObjectCheck>()) { switch (result->GetTypeId()) { case TYPEID_UNIT: + case TYPEID_PLAYER: + unitList.push_back(result->ToUnit()); + // no break; + case TYPEID_CORPSE: // wont work until corpses are allowed in target lists, but at least will send dest in packet m_targets.SetDst(*result); break; default: @@ -2582,7 +2572,7 @@ uint32 Spell::SelectEffectTargets(uint32 i, SpellImplicitTargetInfo const& cur) { CleanupTargetList(); - WorldObject* result = FindCorpseUsing <Trinity::ExplodeCorpseObjectCheck> (); + WorldObject* result = FindCorpseUsing<Trinity::ExplodeCorpseObjectCheck>(); if (result) { @@ -2824,12 +2814,12 @@ uint32 Spell::SelectEffectTargets(uint32 i, SpellImplicitTargetInfo const& cur) unitList.remove(m_targets.GetUnitTarget()); Trinity::RandomResizeList(unitList, maxTargets); } + } - CallScriptAfterUnitTargetSelectHandlers(unitList, SpellEffIndex(i)); + CallScriptAfterUnitTargetSelectHandlers(unitList, SpellEffIndex(i)); - for (std::list<Unit*>::iterator itr = unitList.begin(); itr != unitList.end(); ++itr) - AddUnitTarget(*itr, effectMask, false); - } + for (std::list<Unit*>::iterator itr = unitList.begin(); itr != unitList.end(); ++itr) + AddUnitTarget(*itr, effectMask, false); if (!gobjectList.empty()) { @@ -3725,6 +3715,27 @@ void Spell::SendCastResult(Player* caster, SpellInfo const* spellInfo, uint8 cas case SPELL_FAILED_CUSTOM_ERROR: data << uint32(customError); break; + case SPELL_FAILED_REAGENTS: + { + uint32 missingItem = 0; + for (uint32 i = 0; i < MAX_SPELL_REAGENTS; i++) + { + if (spellInfo->Reagent[i] <= 0) + continue; + + uint32 itemid = spellInfo->Reagent[i]; + uint32 itemcount = spellInfo->ReagentCount[i]; + + if (!caster->HasItemCount(itemid, itemcount)) + { + missingItem = itemid; + break; + } + } + + data << uint32(missingItem); // first missing item + break; + } default: break; } @@ -5926,7 +5937,7 @@ SpellCastResult Spell::CheckItems() } } if (!p_caster->HasItemCount(itemid, itemcount)) - return SPELL_FAILED_ITEM_NOT_READY; //0x54 + return SPELL_FAILED_REAGENTS; } } diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index ef5f32b5575..a8f6ece7102 100755 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -5665,7 +5665,7 @@ void Spell::EffectStuck(SpellEffIndex /*effIndex*/) if (target->isInFlight()) return; - target->TeleportTo(target->GetStartPosition(), m_caster == m_caster ? TELE_TO_SPELL : 0); + target->TeleportTo(target->GetStartPosition(), TELE_TO_SPELL); // homebind location is loaded always // target->TeleportTo(target->m_homebindMapId, target->m_homebindX, target->m_homebindY, target->m_homebindZ, target->GetOrientation(), (m_caster == m_caster ? TELE_TO_SPELL : 0)); diff --git a/src/server/scripts/Kalimdor/silithus.cpp b/src/server/scripts/Kalimdor/silithus.cpp index e6322591bf3..fac56021c3a 100644 --- a/src/server/scripts/Kalimdor/silithus.cpp +++ b/src/server/scripts/Kalimdor/silithus.cpp @@ -1425,7 +1425,7 @@ class go_wind_stone : public GameObjectScript break; } - player->SEND_GOSSIP_MENU(player->GetGossipTextId(gossipId), go->GetGUID()); + player->SEND_GOSSIP_MENU(player->GetGossipTextId(gossipId, go), go->GetGUID()); return true; } diff --git a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_jedoga_shadowseeker.cpp b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_jedoga_shadowseeker.cpp index 4e1b9da0adb..2789bc48a4c 100644 --- a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_jedoga_shadowseeker.cpp +++ b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_jedoga_shadowseeker.cpp @@ -402,7 +402,8 @@ public: if (!CAST_AI(boss_jedoga_shadowseeker::boss_jedoga_shadowseekerAI, boss->AI())->bOpFerok) CAST_AI(boss_jedoga_shadowseeker::boss_jedoga_shadowseekerAI, boss->AI())->bOpFerokFail = true; - boss->AI()->DoAction(ACTION_INITIAND_KILLED); + if (Killer->GetTypeId() == TYPEID_PLAYER) + boss->AI()->DoAction(ACTION_INITIAND_KILLED); } instance->SetData64(DATA_ADD_JEDOGA_OPFER, 0); diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp index fc01ad2efea..6cd049967c1 100755 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp @@ -68,7 +68,6 @@ enum BossSpells { SPELL_LEGION_FLAME = 66197, // player should run away from raid because he triggers Legion Flame SPELL_LEGION_FLAME_EFFECT = 66201, // used by trigger npc - SPELL_TOUCH_OF_JARAXXUS = 66209, // used only in 25H SPELL_NETHER_POWER = 66228, // +20% of spell damage per stack, stackable up to 5/10 times, must be dispelled/stealed SPELL_FEL_LIGHTING = 66528, // jumps to nearby targets SPELL_FEL_FIREBALL = 66532, // does heavy damage to the tank, interruptable @@ -120,7 +119,6 @@ public: uint32 m_uiIncinerateFleshTimer; uint32 m_uiNetherPowerTimer; uint32 m_uiLegionFlameTimer; - uint32 m_uiTouchOfJaraxxusTimer; uint32 m_uiSummonNetherPortalTimer; uint32 m_uiSummonInfernalEruptionTimer; @@ -134,7 +132,6 @@ public: m_uiIncinerateFleshTimer = urand(20*IN_MILLISECONDS, 25*IN_MILLISECONDS); m_uiNetherPowerTimer = 40*IN_MILLISECONDS; m_uiLegionFlameTimer = 30*IN_MILLISECONDS; - m_uiTouchOfJaraxxusTimer = urand(10*IN_MILLISECONDS, 15*IN_MILLISECONDS); m_uiSummonNetherPortalTimer = 1*MINUTE*IN_MILLISECONDS; m_uiSummonInfernalEruptionTimer = 2*MINUTE*IN_MILLISECONDS; Summons.DespawnAll(); @@ -240,13 +237,6 @@ public: m_uiLegionFlameTimer = 30*IN_MILLISECONDS; } else m_uiLegionFlameTimer -= uiDiff; - if (GetDifficulty() == RAID_DIFFICULTY_25MAN_HEROIC && m_uiTouchOfJaraxxusTimer <= uiDiff) - { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) - DoCast(target, SPELL_TOUCH_OF_JARAXXUS); - m_uiTouchOfJaraxxusTimer = urand(10*IN_MILLISECONDS, 15*IN_MILLISECONDS); - } else m_uiTouchOfJaraxxusTimer -= uiDiff; - DoMeleeAttackIfReady(); } }; diff --git a/src/server/shared/Database/MySQLConnection.h b/src/server/shared/Database/MySQLConnection.h index 46e14d81a5e..c05c4e62c96 100755 --- a/src/server/shared/Database/MySQLConnection.h +++ b/src/server/shared/Database/MySQLConnection.h @@ -62,13 +62,6 @@ struct MySQLConnectionInfo std::string port_or_socket; }; -struct PreparedStatementTable -{ - uint32 index; - const char* query; - ConnectionFlags type; -}; - typedef std::map<uint32 /*index*/, std::pair<const char* /*query*/, ConnectionFlags /*sync/async*/> > PreparedStatementMap; #define PREPARE_STATEMENT(a, b, c) m_queries[a] = std::make_pair(strdup(b), c); diff --git a/src/server/worldserver/TCSoap/TCSoap.cpp b/src/server/worldserver/TCSoap/TCSoap.cpp index 8b7d8c19071..26b28b25fbb 100755 --- a/src/server/worldserver/TCSoap/TCSoap.cpp +++ b/src/server/worldserver/TCSoap/TCSoap.cpp @@ -30,7 +30,7 @@ void TCSoapRunnable::run() soap.accept_timeout = 3; soap.recv_timeout = 5; soap.send_timeout = 5; - if (soap_bind(&soap, m_host.c_str(), m_port, 100) < 0) + if (!soap_valid_socket(soap_bind(&soap, m_host.c_str(), m_port, 100))) { sLog->outError("TCSoap: couldn't bind to %s:%d", m_host.c_str(), m_port); exit(-1); |