Skip to content

Commit

Permalink
[11701] Command .auction item and support auction without owner.
Browse files Browse the repository at this point in the history
* New command allow place auction from chat/console and create auction without owner.
* Same code can be used in other place when server code want create generated auction
  without need have associated player. Auction code update for support this case.
* MailDraft::SendMailTo now allow "send" mails to non-players. It correcly drop items in like case.
  • Loading branch information
VladimirMangos committed Jun 29, 2011
1 parent b58b29c commit 67588d4
Show file tree
Hide file tree
Showing 12 changed files with 210 additions and 86 deletions.
3 changes: 2 additions & 1 deletion sql/mangos.sql
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ CREATE TABLE `db_version` (
`version` varchar(120) default NULL,
`creature_ai_version` varchar(120) default NULL,
`cache_id` int(10) default '0',
`required_11690_01_mangos_spell_proc_event` bit(1) default NULL
`required_11701_01_mangos_command` bit(1) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes';

--
Expand Down Expand Up @@ -509,6 +509,7 @@ INSERT INTO `command` VALUES
('auction alliance',3,'Syntax: .auction alliance\r\n\r\nShow alliance auction store independent from your team.'),
('auction goblin',3,'Syntax: .auction goblin\r\n\r\nShow goblin auction store common for all teams.'),
('auction horde',3,'Syntax: .auction horde\r\n\r\nShow horde auction store independent from your team.'),
('auction item',3,'Syntax: .auction item (alliance|horde|goblin) #itemid[:#itemcount] [[[#minbid] #buyout] [short|long|verylong]\r\n\r\nAdd new item (in many stackes if amount grater stack size) to specific auction house at short|long|verylogn perios similar same settings in auction in game dialog. Created auction not have owner.'),
('aura',3,'Syntax: .aura #spellid\r\n\r\nAdd the aura from spell #spellid to the selected Unit.'),
('ban account',3,'Syntax: .ban account $Name $bantime $reason\r\nBan account kick player.\r\n$bantime: negative value leads to permban, otherwise use a timestring like \"4d20h3s\".'),
('ban character',3,'Syntax: .ban character $Name $bantime $reason\r\nBan account and kick player.\r\n$bantime: negative value leads to permban, otherwise use a timestring like \"4d20h3s\".'),
Expand Down
6 changes: 6 additions & 0 deletions sql/updates/11701_01_mangos_command.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
ALTER TABLE db_version CHANGE COLUMN required_11690_01_mangos_spell_proc_event required_11701_01_mangos_command bit;

DELETE FROM command WHERE name = 'auction item';

INSERT INTO command (name, security, help) VALUES
('auction item',3,'Syntax: .auction item (alliance|horde|goblin) #itemid[:#itemcount] [[[#minbid] #buyout] [short|long|verylong]\r\n\r\nAdd new item (in many stackes if amount grater stack size) to specific auction house at short|long|verylogn perios similar same settings in auction in game dialog. Created auction not have owner.');
91 changes: 30 additions & 61 deletions src/game/AuctionHouseHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -371,36 +371,10 @@ void WorldSession::HandleAuctionSellItem(WorldPacket & recv_data)

pl->ModifyMoney(-int32(deposit));

uint32 auction_time = uint32(etime * sWorld.getConfig(CONFIG_FLOAT_RATE_AUCTION_TIME));

AuctionEntry *AH = new AuctionEntry;
AH->Id = sObjectMgr.GenerateAuctionID();
AH->itemGuidLow = newItem->GetObjectGuid().GetCounter();
AH->itemTemplate = newItem->GetEntry();
AH->owner = pl->GetGUIDLow();

Utf8toWStr(pl->GetName(), AH->ownerName);

AH->startbid = bid;
AH->bidder = 0;
AH->bid = 0;
AH->buyout = buyout;
AH->expireTime = time(NULL) + auction_time;
AH->moneyDeliveryTime = 0;
AH->deposit = deposit;
AH->auctionHouseEntry = auctionHouseEntry;
AuctionEntry* AH = auctionHouse->AddAuction(auctionHouseEntry, newItem, etime, bid, buyout, deposit, pl);

DETAIL_LOG("selling %s to auctioneer %s with initial bid %u with buyout %u and with time %u (in sec) in auctionhouse %u",
itemGuid.GetString().c_str(), auctioneerGuid.GetString().c_str(), bid, buyout, auction_time, AH->GetHouseId());
auctionHouse->AddAuction(AH);

sAuctionMgr.AddAItem(newItem);

CharacterDatabase.BeginTransaction();
newItem->SaveToDB();
AH->SaveToDB();
pl->SaveInventoryAndGoldToDB();
CharacterDatabase.CommitTransaction();
itemGuid.GetString().c_str(), auctioneerGuid.GetString().c_str(), bid, buyout, etime, auctionHouseEntry->houseId);

SendAuctionCommandResult(AH, AUCTION_STARTED, AUCTION_OK);

Expand Down Expand Up @@ -447,7 +421,7 @@ void WorldSession::HandleAuctionPlaceBid(WorldPacket & recv_data)

// impossible have online own another character (use this for speedup check in case online owner)
Player* auction_owner = sObjectMgr.GetPlayer(ownerGuid);
if (!auction_owner && sObjectMgr.GetPlayerAccountIdByGUID(ownerGuid) == pl->GetSession()->GetAccountId())
if (!auction_owner && ownerGuid && sObjectMgr.GetPlayerAccountIdByGUID(ownerGuid) == pl->GetSession()->GetAccountId())
{
// you cannot bid your another character auction:
SendAuctionCommandResult(NULL, AUCTION_BID_PLACED, AUCTION_ERR_BID_OWN);
Expand Down Expand Up @@ -564,44 +538,39 @@ void WorldSession::HandleAuctionRemoveItem(WorldPacket & recv_data)
AuctionEntry *auction = auctionHouse->GetAuction(auctionId);
Player *pl = GetPlayer();

if (auction && auction->owner == pl->GetGUIDLow())
{
Item *pItem = sAuctionMgr.GetAItem(auction->itemGuidLow);
if (pItem)
{
if (auction->bidder > 0) // If we have a bidder, we have to send him the money he paid
{
uint32 auctionCut = auction->GetAuctionCut();
if (pl->GetMoney() < auctionCut) // player doesn't have enough money, maybe message needed
return;

SendAuctionCancelledToBidderMail(auction);
pl->ModifyMoney(-int32(auctionCut));
}
// Return the item by mail
std::ostringstream msgAuctionCanceledOwner;
msgAuctionCanceledOwner << auction->itemTemplate << ":0:" << AUCTION_CANCELED << ":0:0";

// item will deleted or added to received mail list
MailDraft(msgAuctionCanceledOwner.str(), "") // TODO: fix body
.AddItem(pItem)
.SendMailTo(pl, auction, MAIL_CHECK_MASK_COPIED);
}
else
{
sLog.outError("Auction id: %u has nonexistent item (item guid : %u)!!!", auction->Id, auction->itemGuidLow);
SendAuctionCommandResult(NULL, AUCTION_REMOVED, AUCTION_ERR_INVENTORY, EQUIP_ERR_ITEM_NOT_FOUND);
return;
}
}
else
if (!auction || auction->owner != pl->GetGUIDLow())
{
SendAuctionCommandResult(NULL, AUCTION_REMOVED, AUCTION_ERR_DATABASE);
// this code isn't possible ... maybe there should be ASSERT
sLog.outError("CHEATER : %u, he tried to cancel auction (id: %u) of another player, or auction is NULL", pl->GetGUIDLow(), auctionId);
return;
}

Item *pItem = sAuctionMgr.GetAItem(auction->itemGuidLow);
if (!pItem)
{
sLog.outError("Auction id: %u has nonexistent item (item guid : %u)!!!", auction->Id, auction->itemGuidLow);
SendAuctionCommandResult(NULL, AUCTION_REMOVED, AUCTION_ERR_INVENTORY, EQUIP_ERR_ITEM_NOT_FOUND);
return;
}

if (auction->bidder > 0) // If we have a bidder, we have to send him the money he paid
{
uint32 auctionCut = auction->GetAuctionCut();
if (pl->GetMoney() < auctionCut) // player doesn't have enough money, maybe message needed
return;

SendAuctionCancelledToBidderMail(auction);
pl->ModifyMoney(-int32(auctionCut));
}
// Return the item by mail
std::ostringstream msgAuctionCanceledOwner;
msgAuctionCanceledOwner << auction->itemTemplate << ":0:" << AUCTION_CANCELED << ":0:0";

// item will deleted or added to received mail list
MailDraft(msgAuctionCanceledOwner.str(), "") // TODO: fix body
.AddItem(pItem)
.SendMailTo(pl, auction, MAIL_CHECK_MASK_COPIED);

// inform player, that auction is removed
SendAuctionCommandResult(auction, AUCTION_REMOVED, AUCTION_OK);
// Now remove the auction
Expand Down
75 changes: 59 additions & 16 deletions src/game/AuctionHouseMgr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ void AuctionHouseMgr::SendAuctionWonMail(AuctionEntry *auction)

uint32 bidder_accId = 0;

ObjectGuid ownerGuid = ObjectGuid(HIGHGUID_PLAYER, auction->owner);
Player* auction_owner = sObjectMgr.GetPlayer(ownerGuid);

// data for gm.log
if (sWorld.getConfig(CONFIG_BOOL_GM_LOG_TRADE))
{
Expand All @@ -113,22 +116,21 @@ void AuctionHouseMgr::SendAuctionWonMail(AuctionEntry *auction)

if (bidder_security > SEC_PLAYER)
{
ObjectGuid owner_guid = ObjectGuid(HIGHGUID_PLAYER, auction->owner);
std::string owner_name;
if (!sObjectMgr.GetPlayerNameByGUID(owner_guid, owner_name))
if (auction_owner)
owner_name = auction_owner->GetName();
else if (ownerGuid && !sObjectMgr.GetPlayerNameByGUID(ownerGuid, owner_name))
owner_name = sObjectMgr.GetMangosStringForDBCLocale(LANG_UNKNOWN);

uint32 owner_accid = sObjectMgr.GetPlayerAccountIdByGUID(owner_guid);
uint32 owner_accid = ownerGuid ? sObjectMgr.GetPlayerAccountIdByGUID(ownerGuid) : 0;

sLog.outCommand(bidder_accId,"GM %s (Account: %u) won item in auction: %s (Entry: %u Count: %u) and pay money: %u. Original owner %s (Account: %u)",
bidder_name.c_str(),bidder_accId,pItem->GetProto()->Name1,pItem->GetEntry(),pItem->GetCount(),auction->bid,owner_name.c_str(),owner_accid);
bidder_name.c_str(), bidder_accId, pItem->GetProto()->Name1, pItem->GetEntry(), pItem->GetCount(), auction->bid, owner_name.c_str(), owner_accid);
}
}
else if (!bidder)
bidder_accId = sObjectMgr.GetPlayerAccountIdByGUID(bidder_guid);

ObjectGuid ownerGuid = ObjectGuid(HIGHGUID_PLAYER, auction->owner);
Player* auction_owner = sObjectMgr.GetPlayer(ownerGuid);
if (auction_owner)
auction_owner->GetSession()->SendAuctionOwnerNotification(auction);

Expand Down Expand Up @@ -178,7 +180,7 @@ void AuctionHouseMgr::SendAuctionSalePendingMail(AuctionEntry * auction)
Player *owner = sObjectMgr.GetPlayer(owner_guid);

// owner exist (online or offline)
if (owner || sObjectMgr.GetPlayerAccountIdByGUID(owner_guid))
if (owner || owner_guid && sObjectMgr.GetPlayerAccountIdByGUID(owner_guid))
{
std::ostringstream msgAuctionSalePendingSubject;
msgAuctionSalePendingSubject << auction->itemTemplate << ":0:" << AUCTION_SALE_PENDING;
Expand Down Expand Up @@ -208,7 +210,7 @@ void AuctionHouseMgr::SendAuctionSuccessfulMail(AuctionEntry * auction)
Player *owner = sObjectMgr.GetPlayer(owner_guid);

uint32 owner_accId = 0;
if (!owner)
if (!owner && owner_guid)
owner_accId = sObjectMgr.GetPlayerAccountIdByGUID(owner_guid);

// owner exist
Expand Down Expand Up @@ -389,17 +391,21 @@ void AuctionHouseMgr::LoadAuctions()
auction->itemGuidLow = fields[2].GetUInt32();
auction->itemTemplate = fields[3].GetUInt32();
auction->owner = fields[4].GetUInt32();
std::wstring& plWName = playerNames[auction->owner];
if (plWName.empty())

if (auction->owner)
{
std::string plName;
if (!sObjectMgr.GetPlayerNameByGUID(ObjectGuid(HIGHGUID_PLAYER, auction->owner), plName))
plName = sObjectMgr.GetMangosStringForDBCLocale(LANG_UNKNOWN);
std::wstring& plWName = playerNames[auction->owner];
if (plWName.empty())
{
std::string plName;
if (!sObjectMgr.GetPlayerNameByGUID(ObjectGuid(HIGHGUID_PLAYER, auction->owner), plName))
plName = sObjectMgr.GetMangosStringForDBCLocale(LANG_UNKNOWN);

Utf8toWStr(plName, plWName);
}
Utf8toWStr(plName, plWName);
}

auction->ownerName = plWName;
auction->ownerName = plWName;
}

auction->buyout = fields[5].GetUInt32();
auction->expireTime = fields[6].GetUInt32();
Expand Down Expand Up @@ -909,6 +915,43 @@ void AuctionHouseObject::BuildListPendingSales(WorldPacket& data, Player* player
}
}

AuctionEntry* AuctionHouseObject::AddAuction(AuctionHouseEntry const* auctionHouseEntry, Item* newItem, uint32 etime, uint32 bid, uint32 buyout, uint32 deposit, Player * pl /*= NULL*/)
{
uint32 auction_time = uint32(etime * sWorld.getConfig(CONFIG_FLOAT_RATE_AUCTION_TIME));

AuctionEntry *AH = new AuctionEntry;
AH->Id = sObjectMgr.GenerateAuctionID();
AH->itemGuidLow = newItem->GetObjectGuid().GetCounter();
AH->itemTemplate = newItem->GetEntry();
AH->owner = pl ? pl->GetGUIDLow() : 0;

if (pl)
Utf8toWStr(pl->GetName(), AH->ownerName);

AH->startbid = bid;
AH->bidder = 0;
AH->bid = 0;
AH->buyout = buyout;
AH->expireTime = time(NULL) + auction_time;
AH->moneyDeliveryTime = 0;
AH->deposit = deposit;
AH->auctionHouseEntry = auctionHouseEntry;

AddAuction(AH);

sAuctionMgr.AddAItem(newItem);

CharacterDatabase.BeginTransaction();
newItem->SaveToDB();
AH->SaveToDB();

if (pl)
pl->SaveInventoryAndGoldToDB();
CharacterDatabase.CommitTransaction();

return AH;
}

// this function inserts to WorldPacket auction's data
bool AuctionEntry::BuildAuctionInfo(WorldPacket & data) const
{
Expand Down
3 changes: 2 additions & 1 deletion src/game/AuctionHouseMgr.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ struct AuctionEntry
uint32 Id;
uint32 itemGuidLow;
uint32 itemTemplate;
uint32 owner;
uint32 owner; // player low guid, can be 0 for server generated auction
std::wstring ownerName; // cache name for sorting
uint32 startbid; // maybe useless
uint32 bid;
Expand Down Expand Up @@ -122,6 +122,7 @@ class AuctionHouseObject
void BuildListOwnerItems(WorldPacket& data, Player* player, uint32& count, uint32& totalcount);
void BuildListPendingSales(WorldPacket& data, Player* player, uint32& count);

AuctionEntry* AddAuction(AuctionHouseEntry const* auctionHouseEntry, Item* newItem, uint32 etime, uint32 bid, uint32 buyout = 0, uint32 deposit = 0, Player * pl = NULL);
private:
AuctionEntryMap AuctionsMap;
};
Expand Down
1 change: 1 addition & 0 deletions src/game/Chat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ ChatCommand * ChatHandler::getCommandTable()
{ "alliance", SEC_ADMINISTRATOR, false, &ChatHandler::HandleAuctionAllianceCommand, "", NULL },
{ "goblin", SEC_ADMINISTRATOR, false, &ChatHandler::HandleAuctionGoblinCommand, "", NULL },
{ "horde", SEC_ADMINISTRATOR, false, &ChatHandler::HandleAuctionHordeCommand, "", NULL },
{ "item", SEC_ADMINISTRATOR, true, &ChatHandler::HandleAuctionItemCommand, "", NULL },
{ "", SEC_ADMINISTRATOR, false, &ChatHandler::HandleAuctionCommand, "", NULL },
{ NULL, 0, false, NULL, "", NULL }
};
Expand Down
1 change: 1 addition & 0 deletions src/game/Chat.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ class MANGOS_DLL_SPEC ChatHandler
bool HandleAuctionAllianceCommand(char* args);
bool HandleAuctionGoblinCommand(char* args);
bool HandleAuctionHordeCommand(char* args);
bool HandleAuctionItemCommand(char* args);
bool HandleAuctionCommand(char* args);

bool HandleAchievementCommand(char* args);
Expand Down

6 comments on commit 67588d4

@SkirnirMaNGOS
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I whisper this one: looks like a huge step to ahbot implementation. Yay ;-)

@VladimirMangos
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will do tomorrow same for bidder case (need more testing) and after will possible avoid fake player use, main stopper for me review auction bot.

@SkirnirMaNGOS
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One more point for you on the unlimited "why we love you"-scale. Have a nice day.

@VladimirMangos
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm, just for note: i get crash with auction use with generated by command item so better not use added command until fix problem. :/

@VladimirMangos
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

base at testing problem with command use must be fixed in [11704]

@SkirnirMaNGOS
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thank you :)

Please sign in to comment.