Merge commit 'origin/master' into 320

This commit is contained in:
tomrus88 2009-08-23 18:57:07 +04:00
commit 935c0a44c2
31 changed files with 1284 additions and 942 deletions

View file

@ -21,7 +21,7 @@
DROP TABLE IF EXISTS `character_db_version`; DROP TABLE IF EXISTS `character_db_version`;
CREATE TABLE `character_db_version` ( CREATE TABLE `character_db_version` (
`required_8339_02_characters_character_battleground_data` bit(1) default NULL `required_8402_02_characters_guild_bank_eventlog` bit(1) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Last applied sql update to DB'; ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Last applied sql update to DB';
-- --
@ -935,16 +935,16 @@ UNLOCK TABLES;
DROP TABLE IF EXISTS `guild_bank_eventlog`; DROP TABLE IF EXISTS `guild_bank_eventlog`;
CREATE TABLE `guild_bank_eventlog` ( CREATE TABLE `guild_bank_eventlog` (
`guildid` int(11) unsigned NOT NULL default '0', `guildid` int(11) unsigned NOT NULL default '0' COMMENT 'Guild Identificator',
`LogGuid` int(11) unsigned NOT NULL default '0', `LogGuid` int(11) unsigned NOT NULL default '0' COMMENT 'Log record identificator - auxiliary column',
`LogEntry` tinyint(1) unsigned NOT NULL default '0', `TabId` tinyint(3) unsigned NOT NULL default '0' COMMENT 'Guild bank TabId',
`TabId` tinyint(1) unsigned NOT NULL default '0', `EventType` tinyint(3) unsigned NOT NULL default '0' COMMENT 'Event type',
`PlayerGuid` int(11) unsigned NOT NULL default '0', `PlayerGuid` int(11) unsigned NOT NULL default '0',
`ItemOrMoney` int(11) unsigned NOT NULL default '0', `ItemOrMoney` int(11) unsigned NOT NULL default '0',
`ItemStackCount` tinyint(3) unsigned NOT NULL default '0', `ItemStackCount` tinyint(3) unsigned NOT NULL default '0',
`DestTabId` tinyint(1) unsigned NOT NULL default '0', `DestTabId` tinyint(1) unsigned NOT NULL default '0' COMMENT 'Destination Tab Id',
`TimeStamp` bigint(20) unsigned NOT NULL default '0', `TimeStamp` bigint(20) unsigned NOT NULL default '0' COMMENT 'Event UNIX time',
PRIMARY KEY (`guildid`,`LogGuid`), PRIMARY KEY (`guildid`,`LogGuid`,`TabId`),
KEY `guildid_key` (`guildid`) KEY `guildid_key` (`guildid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8; ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
@ -1036,12 +1036,13 @@ UNLOCK TABLES;
DROP TABLE IF EXISTS `guild_eventlog`; DROP TABLE IF EXISTS `guild_eventlog`;
CREATE TABLE `guild_eventlog` ( CREATE TABLE `guild_eventlog` (
`guildid` int(11) NOT NULL COMMENT 'Guild Identificator', `guildid` int(11) NOT NULL COMMENT 'Guild Identificator',
`LogGuid` int(11) NOT NULL COMMENT 'Log entry identificator', `LogGuid` int(11) NOT NULL COMMENT 'Log record identificator - auxiliary column',
`EventType` tinyint(1) NOT NULL COMMENT 'Event type', `EventType` tinyint(1) NOT NULL COMMENT 'Event type',
`PlayerGuid1` int(11) NOT NULL COMMENT 'Player 1', `PlayerGuid1` int(11) NOT NULL COMMENT 'Player 1',
`PlayerGuid2` int(11) NOT NULL COMMENT 'Player 2', `PlayerGuid2` int(11) NOT NULL COMMENT 'Player 2',
`NewRank` tinyint(2) NOT NULL COMMENT 'New rank(in case promotion/demotion)', `NewRank` tinyint(2) NOT NULL COMMENT 'New rank(in case promotion/demotion)',
`TimeStamp` bigint(20) NOT NULL COMMENT 'Event UNIX time' `TimeStamp` bigint(20) NOT NULL COMMENT 'Event UNIX time',
PRIMARY KEY (`guildid`, `LogGuid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT 'Guild Eventlog'; ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT 'Guild Eventlog';
-- --

View file

@ -24,7 +24,7 @@ CREATE TABLE `db_version` (
`version` varchar(120) default NULL, `version` varchar(120) default NULL,
`creature_ai_version` varchar(120) default NULL, `creature_ai_version` varchar(120) default NULL,
`cache_id` int(10) default '0', `cache_id` int(10) default '0',
`required_8394_01_mangos_spell_proc_event` bit(1) default NULL `required_8399_01_mangos_spell_elixir` bit(1) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes'; ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes';
-- --
@ -15382,14 +15382,6 @@ INSERT INTO spell_chain VALUES
(30356,25258,23922,6,0), (30356,25258,23922,6,0),
(47487,30356,23922,7,0), (47487,30356,23922,7,0),
(47488,47487,23922,8,0), (47488,47487,23922,8,0),
/*SunderArmor*/
(7386,0,7386,1,0),
(7405,7386,7386,2,0),
(8380,7405,7386,3,0),
(11596,8380,7386,4,0),
(11597,11596,7386,5,0),
(25225,11597,7386,6,0),
(47467,25225,7386,7,0),
/*------------------ /*------------------
-- (267) Protection (Paladin) -- (267) Protection (Paladin)
------------------*/ ------------------*/
@ -16974,12 +16966,19 @@ INSERT INTO `spell_elixir` VALUES
(17627,0x3), (17627,0x3),
(17629,0x3), (17629,0x3),
(17628,0x3), (17628,0x3),
(18191,0x10),
(18192,0x10),
(18193,0x10),
(18194,0x10),
(18222,0x10),
(21920,0x1), (21920,0x1),
(22730,0x10),
(24361,0x2), (24361,0x2),
(24363,0x2), (24363,0x2),
(24382,0x2), (24382,0x2),
(24383,0x2), (24383,0x2),
(24417,0x2), (24417,0x2),
(25661,0x10),
(26276,0x1), (26276,0x1),
(27652,0x2), (27652,0x2),
(27653,0x2), (27653,0x2),
@ -17022,6 +17021,8 @@ INSERT INTO `spell_elixir` VALUES
(45373,0x1), (45373,0x1),
(46837,0xB), (46837,0xB),
(46839,0xB); (46839,0xB);
/*!40000 ALTER TABLE `spell_elixir` ENABLE KEYS */; /*!40000 ALTER TABLE `spell_elixir` ENABLE KEYS */;
UNLOCK TABLES; UNLOCK TABLES;
@ -18104,11 +18105,9 @@ INSERT INTO `spell_threat` VALUES
(7373,141), (7373,141),
(7379,235), (7379,235),
(7386,100), (7386,100),
(7405,140),
(8198,40), (8198,40),
(8204,64), (8204,64),
(8205,96), (8205,96),
(8380,180),
(8972,118), (8972,118),
(9745,148), (9745,148),
(9880,178), (9880,178),
@ -18120,8 +18119,6 @@ INSERT INTO `spell_threat` VALUES
(11567,145), (11567,145),
(11580,143), (11580,143),
(11581,180), (11581,180),
(11596,220),
(11597,261),
(11600,275), (11600,275),
(11601,315), (11601,315),
(11775,395), (11775,395),
@ -18142,7 +18139,6 @@ INSERT INTO `spell_threat` VALUES
(23925,250), (23925,250),
(24394,580), (24394,580),
(24583,5), (24583,5),
(25225,300),
(25231,130), (25231,130),
(25258,286), (25258,286),
(25264,215), (25264,215),

View file

@ -0,0 +1,3 @@
ALTER TABLE db_version CHANGE COLUMN required_8394_01_mangos_spell_proc_event required_8397_01_mangos_spell_chain bit;
DELETE FROM spell_chain WHERE first_spell=7386;

View file

@ -0,0 +1,3 @@
ALTER TABLE db_version CHANGE COLUMN required_8397_01_mangos_spell_chain required_8397_02_mangos_spell_threat bit;
DELETE FROM spell_threat WHERE entry IN (7405,8380,11596,11597,25225);

View file

@ -0,0 +1,5 @@
ALTER TABLE character_db_version CHANGE COLUMN required_8339_02_characters_character_battleground_data required_8397_03_characters_character_spell bit;
UPDATE IGNORE character_spell SET spell=7386 WHERE spell IN (7405,8380,11596,11597,25225,47467);
UPDATE character_spell SET active=1 WHERE spell=7386;
DELETE FROM character_spell WHERE spell IN (7405,8380,11596,11597,25225,47467);

View file

@ -0,0 +1,12 @@
ALTER TABLE db_version CHANGE COLUMN required_8397_02_mangos_spell_threat required_8399_01_mangos_spell_elixir bit;
-- Well Fed (SPELLFAMILY_POTION)
DELETE FROM spell_elixir WHERE entry IN (18191, 18192, 18193, 18194, 18222, 22730, 25661);
INSERT INTO spell_elixir (entry, mask) VALUES
(18191,0x10),
(18192,0x10),
(18193,0x10),
(18194,0x10),
(18222,0x10),
(22730,0x10),
(25661,0x10);

View file

@ -0,0 +1,20 @@
ALTER TABLE character_db_version CHANGE COLUMN required_8397_03_characters_character_spell required_8402_01_characters_guild_eventlog bit;
-- THIS SCRIPT DELETES table `guild_eventlog` - MAKE BACKUP, if you need it.
DROP TABLE IF EXISTS `guild_eventlog`;
CREATE TABLE `guild_eventlog` (
`guildid` int(11) NOT NULL COMMENT 'Guild Identificator',
`LogGuid` int(11) NOT NULL COMMENT 'Log record identificator - auxiliary column',
`EventType` tinyint(1) NOT NULL COMMENT 'Event type',
`PlayerGuid1` int(11) NOT NULL COMMENT 'Player 1',
`PlayerGuid2` int(11) NOT NULL COMMENT 'Player 2',
`NewRank` tinyint(2) NOT NULL COMMENT 'New rank(in case promotion/demotion)',
`TimeStamp` bigint(20) NOT NULL COMMENT 'Event UNIX time',
PRIMARY KEY (`guildid`, `LogGuid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT 'Guild Eventlog';
-- The reason i decided for such dramatic change is that old guild_eventlog table didn't have Primary key and
-- used LogGuids from 0 to infinity
-- New system uses LogGuids from 0 to number defined in config.

View file

@ -0,0 +1,23 @@
ALTER TABLE character_db_version CHANGE COLUMN required_8402_01_characters_guild_eventlog required_8402_02_characters_guild_bank_eventlog bit;
-- THIS SCRIPT DELETES table `guild_bank_eventlog` - MAKE BACKUP, if you need it.
DROP TABLE IF EXISTS `guild_bank_eventlog`;
CREATE TABLE `guild_bank_eventlog` (
`guildid` int(11) unsigned NOT NULL default '0' COMMENT 'Guild Identificator',
`LogGuid` int(11) unsigned NOT NULL default '0' COMMENT 'Log record identificator - auxiliary column',
`TabId` tinyint(3) unsigned NOT NULL default '0' COMMENT 'Guild bank TabId',
`EventType` tinyint(3) unsigned NOT NULL default '0' COMMENT 'Event type',
`PlayerGuid` int(11) unsigned NOT NULL default '0',
`ItemOrMoney` int(11) unsigned NOT NULL default '0',
`ItemStackCount` tinyint(3) unsigned NOT NULL default '0',
`DestTabId` tinyint(1) unsigned NOT NULL default '0' COMMENT 'Destination Tab Id',
`TimeStamp` bigint(20) unsigned NOT NULL default '0' COMMENT 'Event UNIX time',
PRIMARY KEY (`guildid`,`LogGuid`,`TabId`),
KEY `guildid_key` (`guildid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- The reason i decided for such dramatic change is that old guild_bank_eventlog table used `TabId` = 0 for Money events and
-- used `LogGuid` from 0 to infinity
-- New system uses `LogGuid` from 0 to number defined in config.

View file

@ -86,6 +86,12 @@ pkgdata_DATA = \
8392_01_mangos_spell_proc_event.sql \ 8392_01_mangos_spell_proc_event.sql \
8392_02_mangos_spell_chain.sql \ 8392_02_mangos_spell_chain.sql \
8394_01_mangos_spell_proc_event.sql \ 8394_01_mangos_spell_proc_event.sql \
8397_01_mangos_spell_chain.sql \
8397_02_mangos_spell_threat.sql \
8397_03_characters_character_spell.sql \
8399_01_mangos_spell_elixir.sql \
8402_01_characters_guild_eventlog.sql \
8402_02_characters_guild_bank_eventlog.sql \
README README
## Additional files to include when running 'make dist' ## Additional files to include when running 'make dist'
@ -152,4 +158,10 @@ EXTRA_DIST = \
8392_01_mangos_spell_proc_event.sql \ 8392_01_mangos_spell_proc_event.sql \
8392_02_mangos_spell_chain.sql \ 8392_02_mangos_spell_chain.sql \
8394_01_mangos_spell_proc_event.sql \ 8394_01_mangos_spell_proc_event.sql \
8397_01_mangos_spell_chain.sql \
8397_02_mangos_spell_threat.sql \
8397_03_characters_character_spell.sql \
8399_01_mangos_spell_elixir.sql \
8402_01_characters_guild_eventlog.sql \
8402_02_characters_guild_bank_eventlog.sql \
README README

View file

@ -1079,7 +1079,7 @@ bool BGQueueRemoveEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
sBattleGroundMgr.m_BattleGroundQueues[m_BgQueueTypeId].RemovePlayer(m_PlayerGuid, true); sBattleGroundMgr.m_BattleGroundQueues[m_BgQueueTypeId].RemovePlayer(m_PlayerGuid, true);
//update queues if battleground isn't ended //update queues if battleground isn't ended
if (bg) if (bg)
sBattleGroundMgr.m_BattleGroundQueues[m_BgQueueTypeId].Update(m_BgTypeId, bg->GetQueueId()); sBattleGroundMgr.ScheduleQueueUpdate(m_BgQueueTypeId, m_BgTypeId, bg->GetQueueId());
WorldPacket data; WorldPacket data;
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_NONE, 0, 0, 0); sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_NONE, 0, 0, 0);
@ -1163,6 +1163,22 @@ void BattleGroundMgr::Update(uint32 diff)
} }
} }
} }
// update scheduled queues
if (!m_QueueUpdateScheduler.empty())
{
//copy vector and clear the other
std::vector<uint32> scheduled(m_QueueUpdateScheduler);
m_QueueUpdateScheduler.clear();
for (uint8 i = 0; i < scheduled.size(); i++)
{
BattleGroundQueueTypeId bgQueueTypeId = BattleGroundQueueTypeId(scheduled[i] / 65536);
BattleGroundTypeId bgTypeId = BattleGroundTypeId((scheduled[i] % 65536) / 256);
BGQueueIdBasedOnLevel queue_id = BGQueueIdBasedOnLevel(scheduled[i] % 256);
m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, queue_id);
}
}
// if rating difference counts, maybe force-update queues // if rating difference counts, maybe force-update queues
if (sWorld.getConfig(CONFIG_ARENA_MAX_RATING_DIFFERENCE) && sWorld.getConfig(CONFIG_ARENA_RATING_DISCARD_TIMER)) if (sWorld.getConfig(CONFIG_ARENA_MAX_RATING_DIFFERENCE) && sWorld.getConfig(CONFIG_ARENA_RATING_DISCARD_TIMER))
{ {
@ -2005,6 +2021,24 @@ void BattleGroundMgr::ToggleArenaTesting()
sWorld.SendWorldText(LANG_DEBUG_ARENA_OFF); sWorld.SendWorldText(LANG_DEBUG_ARENA_OFF);
} }
void BattleGroundMgr::ScheduleQueueUpdate(BattleGroundQueueTypeId bgQueueTypeId, BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLevel queue_id)
{
//This method must be atomic!
//we will use only 1 number created of bgTypeId and queue_id
uint32 schedule_id = (bgQueueTypeId * 65536) + (bgTypeId * 256) + queue_id;
bool found = false;
for (uint8 i = 0; i < m_QueueUpdateScheduler.size(); i++)
{
if (m_QueueUpdateScheduler[i] == schedule_id)
{
found = true;
break;
}
}
if (!found)
m_QueueUpdateScheduler.push_back(schedule_id);
}
uint32 BattleGroundMgr::GetMaxRatingDifference() const uint32 BattleGroundMgr::GetMaxRatingDifference() const
{ {
// this is for stupid people who can't use brain and set max rating difference to 0 // this is for stupid people who can't use brain and set max rating difference to 0

View file

@ -217,6 +217,7 @@ class BattleGroundMgr
BGFreeSlotQueueType BGFreeSlotQueue[MAX_BATTLEGROUND_TYPE_ID]; BGFreeSlotQueueType BGFreeSlotQueue[MAX_BATTLEGROUND_TYPE_ID];
void ScheduleQueueUpdate(BattleGroundQueueTypeId bgQueueTypeId, BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLevel queue_id);
uint32 GetMaxRatingDifference() const; uint32 GetMaxRatingDifference() const;
uint32 GetRatingDiscardTimer() const; uint32 GetRatingDiscardTimer() const;
uint32 GetPrematureFinishTime() const; uint32 GetPrematureFinishTime() const;
@ -248,6 +249,7 @@ class BattleGroundMgr
/* Battlegrounds */ /* Battlegrounds */
BattleGroundSet m_BattleGrounds[MAX_BATTLEGROUND_TYPE_ID]; BattleGroundSet m_BattleGrounds[MAX_BATTLEGROUND_TYPE_ID];
std::vector<uint32>m_QueueUpdateScheduler;
std::set<uint32> m_ClientBattleGroundIds[MAX_BATTLEGROUND_TYPE_ID][MAX_BATTLEGROUND_QUEUES]; //the instanceids just visible for the client std::set<uint32> m_ClientBattleGroundIds[MAX_BATTLEGROUND_TYPE_ID][MAX_BATTLEGROUND_QUEUES]; //the instanceids just visible for the client
uint32 m_NextRatingDiscardUpdate; uint32 m_NextRatingDiscardUpdate;
time_t m_NextAutoDistributionTime; time_t m_NextAutoDistributionTime;

File diff suppressed because it is too large Load diff

View file

@ -26,13 +26,19 @@
class Item; class Item;
#define GUILD_RANKS_MIN_COUNT 5
#define GUILD_RANKS_MAX_COUNT 10
enum GuildDefaultRanks enum GuildDefaultRanks
{ {
//these ranks can be modified, but they cannot be deleted
GR_GUILDMASTER = 0, GR_GUILDMASTER = 0,
GR_OFFICER = 1, GR_OFFICER = 1,
//GR_VETERAN = 2, -- not used anywhere and possible incorrect in modified rank list GR_VETERAN = 2,
//GR_MEMBER = 3, GR_MEMBER = 3,
//GR_INITIATE = 4, -- use Guild::GetLowestRank() instead for lowest rank GR_INITIATE = 4,
//When promoting member server does: rank--;!
//When demoting member server does: rank++;!
}; };
enum GuildRankRights enum GuildRankRights
@ -146,7 +152,7 @@ enum GuildBankRights
GUILD_BANK_RIGHT_FULL = 0xFF, GUILD_BANK_RIGHT_FULL = 0xFF,
}; };
enum GuildBankLogEntries enum GuildBankEventLogTypes
{ {
GUILD_BANK_LOG_DEPOSIT_ITEM = 1, GUILD_BANK_LOG_DEPOSIT_ITEM = 1,
GUILD_BANK_LOG_WITHDRAW_ITEM = 2, GUILD_BANK_LOG_WITHDRAW_ITEM = 2,
@ -159,7 +165,7 @@ enum GuildBankLogEntries
GUILD_BANK_LOG_UNK2 = 9, GUILD_BANK_LOG_UNK2 = 9,
}; };
enum GuildEventLogEntryTypes enum GuildEventLogTypes
{ {
GUILD_EVENT_LOG_INVITE_PLAYER = 1, GUILD_EVENT_LOG_INVITE_PLAYER = 1,
GUILD_EVENT_LOG_JOIN_GUILD = 2, GUILD_EVENT_LOG_JOIN_GUILD = 2,
@ -169,16 +175,6 @@ enum GuildEventLogEntryTypes
GUILD_EVENT_LOG_LEAVE_GUILD = 6, GUILD_EVENT_LOG_LEAVE_GUILD = 6,
}; };
struct GuildEventlogEntry
{
uint32 LogGuid;
uint8 EventType;
uint32 PlayerGuid1;
uint32 PlayerGuid2;
uint8 NewRank;
uint64 TimeStamp;
};
enum GuildEmblem enum GuildEmblem
{ {
ERR_GUILDEMBLEM_SUCCESS = 0, ERR_GUILDEMBLEM_SUCCESS = 0,
@ -205,11 +201,18 @@ inline uint32 GetGuildBankTabPrice(uint8 Index)
return 0; return 0;
} }
struct GuildBankEvent struct GuildEventLogEntry
{ {
uint32 LogGuid; uint8 EventType;
uint8 LogEntry; uint32 PlayerGuid1;
uint8 TabId; uint32 PlayerGuid2;
uint8 NewRank;
uint64 TimeStamp;
};
struct GuildBankEventLogEntry
{
uint8 EventType;
uint32 PlayerGuid; uint32 PlayerGuid;
uint32 ItemOrMoney; uint32 ItemOrMoney;
uint8 ItemStackCount; uint8 ItemStackCount;
@ -218,9 +221,9 @@ struct GuildBankEvent
bool isMoneyEvent() const bool isMoneyEvent() const
{ {
return LogEntry == GUILD_BANK_LOG_DEPOSIT_MONEY || return EventType == GUILD_BANK_LOG_DEPOSIT_MONEY ||
LogEntry == GUILD_BANK_LOG_WITHDRAW_MONEY || EventType == GUILD_BANK_LOG_WITHDRAW_MONEY ||
LogEntry == GUILD_BANK_LOG_REPAIR_MONEY; EventType == GUILD_BANK_LOG_REPAIR_MONEY;
} }
}; };
@ -283,38 +286,40 @@ class Guild
Guild(); Guild();
~Guild(); ~Guild();
bool create(Player* leader, std::string gname); bool Create(Player* leader, std::string gname);
void CreateDefaultGuildRanks(int locale_idx);
void Disband(); void Disband();
typedef std::map<uint32, MemberSlot> MemberList; typedef std::map<uint32, MemberSlot> MemberList;
typedef std::vector<RankInfo> RankList; typedef std::vector<RankInfo> RankList;
uint32 GetId(){ return Id; } uint32 GetId(){ return m_Id; }
const uint64& GetLeader(){ return leaderGuid; } const uint64& GetLeader(){ return m_LeaderGuid; }
std::string GetName(){ return name; } std::string GetName(){ return m_Name; }
std::string GetMOTD(){ return MOTD; } std::string GetMOTD(){ return MOTD; }
std::string GetGINFO(){ return GINFO; } std::string GetGINFO(){ return GINFO; }
uint32 GetCreatedYear(){ return CreatedYear; } uint32 GetCreatedYear(){ return m_CreatedYear; }
uint32 GetCreatedMonth(){ return CreatedMonth; } uint32 GetCreatedMonth(){ return m_CreatedMonth; }
uint32 GetCreatedDay(){ return CreatedDay; } uint32 GetCreatedDay(){ return m_CreatedDay; }
uint32 GetEmblemStyle(){ return EmblemStyle; } uint32 GetEmblemStyle(){ return m_EmblemStyle; }
uint32 GetEmblemColor(){ return EmblemColor; } uint32 GetEmblemColor(){ return m_EmblemColor; }
uint32 GetBorderStyle(){ return BorderStyle; } uint32 GetBorderStyle(){ return m_BorderStyle; }
uint32 GetBorderColor(){ return BorderColor; } uint32 GetBorderColor(){ return m_BorderColor; }
uint32 GetBackgroundColor(){ return BackgroundColor; } uint32 GetBackgroundColor(){ return m_BackgroundColor; }
void SetLeader(uint64 guid); void SetLeader(uint64 guid);
bool AddMember(uint64 plGuid, uint32 plRank); bool AddMember(uint64 plGuid, uint32 plRank);
void ChangeRank(uint64 guid, uint32 newRank); void ChangeRank(uint64 guid, uint32 newRank);
void DelMember(uint64 guid, bool isDisbanding=false); void DelMember(uint64 guid, bool isDisbanding = false);
uint32 GetLowestRank() const { return GetNrRanks()-1; } //lowest rank is the count of ranks - 1 (the highest rank_id in table)
uint32 GetLowestRank() const { return m_Ranks.size() - 1; }
void SetMOTD(std::string motd); void SetMOTD(std::string motd);
void SetGINFO(std::string ginfo); void SetGINFO(std::string ginfo);
void SetPNOTE(uint64 guid,std::string pnote); void SetPNOTE(uint64 guid, std::string pnote);
void SetOFFNOTE(uint64 guid,std::string offnote); void SetOFFNOTE(uint64 guid, std::string offnote);
void SetEmblem(uint32 emblemStyle, uint32 emblemColor, uint32 borderStyle, uint32 borderColor, uint32 backgroundColor); void SetEmblem(uint32 emblemStyle, uint32 emblemColor, uint32 borderStyle, uint32 borderColor, uint32 backgroundColor);
uint32 GetMemberSize() const { return members.size(); } uint32 GetMemberSize() const { return members.size(); }
@ -323,8 +328,7 @@ class Guild
bool LoadRanksFromDB(uint32 GuildId); bool LoadRanksFromDB(uint32 GuildId);
bool LoadMembersFromDB(uint32 GuildId); bool LoadMembersFromDB(uint32 GuildId);
bool FillPlayerData(uint64 guid, MemberSlot* memslot); void SetMemberStats(uint64 guid);
void LoadPlayerStatsByGuid(uint64 guid);
void BroadcastToGuild(WorldSession *session, const std::string& msg, uint32 language = LANG_UNIVERSAL); void BroadcastToGuild(WorldSession *session, const std::string& msg, uint32 language = LANG_UNIVERSAL);
void BroadcastToOfficers(WorldSession *session, const std::string& msg, uint32 language = LANG_UNIVERSAL); void BroadcastToOfficers(WorldSession *session, const std::string& msg, uint32 language = LANG_UNIVERSAL);
@ -344,7 +348,7 @@ class Guild
void DelRank(); void DelRank();
std::string GetRankName(uint32 rankId); std::string GetRankName(uint32 rankId);
uint32 GetRankRights(uint32 rankId); uint32 GetRankRights(uint32 rankId);
uint32 GetNrRanks() const { return m_ranks.size(); } uint32 GetRanksSize() const { return m_Ranks.size(); }
void SetRankName(uint32 rankId, std::string name); void SetRankName(uint32 rankId, std::string name);
void SetRankRights(uint32 rankId, uint32 rights); void SetRankRights(uint32 rankId, uint32 rights);
@ -373,25 +377,21 @@ class Guild
void Roster(WorldSession *session); void Roster(WorldSession *session);
void Query(WorldSession *session); void Query(WorldSession *session);
void UpdateLogoutTime(uint64 guid); void UpdateLogoutTime(uint64 guid);
// Guild eventlog // Guild EventLog
void LoadGuildEventLogFromDB(); void LoadGuildEventLogFromDB();
void UnloadGuildEventlog(); void UnloadGuildEventLog();
void DisplayGuildEventlog(WorldSession *session); void DisplayGuildEventLog(WorldSession *session);
void LogGuildEvent(uint8 EventType, uint32 PlayerGuid1, uint32 PlayerGuid2, uint8 NewRank); void LogGuildEvent(uint8 EventType, uint32 PlayerGuid1, uint32 PlayerGuid2, uint8 NewRank);
void RenumGuildEventlog();
// ** Guild bank ** // ** Guild bank **
// Content & item deposit/withdraw // Content & item deposit/withdraw
void DisplayGuildBankContent(WorldSession *session, uint8 TabId); void DisplayGuildBankContent(WorldSession *session, uint8 TabId);
void DisplayGuildBankContentUpdate(uint8 TabId, int32 slot1, int32 slot2 = -1);
void DisplayGuildBankContentUpdate(uint8 TabId, GuildItemPosCountVec const& slots);
void DisplayGuildBankMoneyUpdate(); void DisplayGuildBankMoneyUpdate();
Item* GetItem(uint8 TabId, uint8 SlotId); void SwapItems( Player * pl, uint8 BankTab, uint8 BankTabSlot, uint8 BankTabDst, uint8 BankTabSlotDst, uint32 SplitedAmount);
uint8 CanStoreItem( uint8 tab, uint8 slot, GuildItemPosCountVec& dest, uint32 count, Item *pItem, bool swap = false) const; void MoveFromBankToChar( Player * pl, uint8 BankTab, uint8 BankTabSlot, uint8 PlayerBag, uint8 PlayerSlot, uint32 SplitedAmount);
Item* StoreItem( uint8 tab, GuildItemPosCountVec const& pos, Item *pItem ); void MoveFromCharToBank( Player * pl, uint8 PlayerBag, uint8 PlayerSlot, uint8 BankTab, uint8 BankTabSlot, uint32 SplitedAmount);
void RemoveItem(uint8 tab, uint8 slot );
// Tabs // Tabs
void DisplayGuildBankTabsInfo(WorldSession *session); void DisplayGuildBankTabsInfo(WorldSession *session);
@ -399,20 +399,19 @@ class Guild
void SetGuildBankTabText(uint8 TabId, std::string text); void SetGuildBankTabText(uint8 TabId, std::string text);
void SendGuildBankTabText(WorldSession *session, uint8 TabId); void SendGuildBankTabText(WorldSession *session, uint8 TabId);
void SetGuildBankTabInfo(uint8 TabId, std::string name, std::string icon); void SetGuildBankTabInfo(uint8 TabId, std::string name, std::string icon);
void CreateBankRightForTab(uint32 rankid, uint8 TabId);
const GuildBankTab *GetBankTab(uint8 index) { if(index >= m_TabListMap.size()) return NULL; return m_TabListMap[index]; } const GuildBankTab *GetBankTab(uint8 index) { if(index >= m_TabListMap.size()) return NULL; return m_TabListMap[index]; }
uint8 GetPurchasedTabs() const { return purchased_tabs; } uint8 GetPurchasedTabs() const { return m_PurchasedTabs; }
uint32 GetBankRights(uint32 rankId, uint8 TabId) const; uint32 GetBankRights(uint32 rankId, uint8 TabId) const;
bool IsMemberHaveRights(uint32 LowGuid, uint8 TabId,uint32 rights) const; bool IsMemberHaveRights(uint32 LowGuid, uint8 TabId,uint32 rights) const;
bool CanMemberViewTab(uint32 LowGuid, uint8 TabId) const; bool CanMemberViewTab(uint32 LowGuid, uint8 TabId) const;
// Load/unload // Load/unload
void LoadGuildBankFromDB(); void LoadGuildBankFromDB();
void UnloadGuildBank(); void UnloadGuildBank();
void IncOnlineMemberCount() { ++m_onlinemembers; } void IncOnlineMemberCount() { ++m_OnlineMembers; }
// Money deposit/withdraw // Money deposit/withdraw
void SendMoneyInfo(WorldSession *session, uint32 LowGuid); void SendMoneyInfo(WorldSession *session, uint32 LowGuid);
bool MemberMoneyWithdraw(uint32 amount, uint32 LowGuid); bool MemberMoneyWithdraw(uint32 amount, uint32 LowGuid);
uint64 GetGuildBankMoney() { return guildbank_money; } uint64 GetGuildBankMoney() { return m_GuildBankMoney; }
void SetBankMoney(int64 money); void SetBankMoney(int64 money);
// per days // per days
bool MemberItemWithdraw(uint8 TabId, uint32 LowGuid); bool MemberItemWithdraw(uint8 TabId, uint32 LowGuid);
@ -424,33 +423,32 @@ class Guild
uint32 GetBankSlotPerDay(uint32 rankId, uint8 TabId); uint32 GetBankSlotPerDay(uint32 rankId, uint8 TabId);
// rights per day // rights per day
void LoadBankRightsFromDB(uint32 GuildId); void LoadBankRightsFromDB(uint32 GuildId);
// logs // Guild Bank Event Logs
void LoadGuildBankEventLogFromDB(); void LoadGuildBankEventLogFromDB();
void UnloadGuildBankEventLog(); void UnloadGuildBankEventLog();
void DisplayGuildBankLogs(WorldSession *session, uint8 TabId); void DisplayGuildBankLogs(WorldSession *session, uint8 TabId);
void LogBankEvent(uint8 LogEntry, uint8 TabId, uint32 PlayerGuidLow, uint32 ItemOrMoney, uint8 ItemStackCount=0, uint8 DestTabId=0); void LogBankEvent(uint8 EventType, uint8 TabId, uint32 PlayerGuidLow, uint32 ItemOrMoney, uint8 ItemStackCount=0, uint8 DestTabId=0);
void RenumBankLogs();
bool AddGBankItemToDB(uint32 GuildId, uint32 BankTab , uint32 BankTabSlot , uint32 GUIDLow, uint32 Entry ); bool AddGBankItemToDB(uint32 GuildId, uint32 BankTab , uint32 BankTabSlot , uint32 GUIDLow, uint32 Entry );
protected: protected:
void AddRank(const std::string& name,uint32 rights,uint32 money); void AddRank(const std::string& name,uint32 rights,uint32 money);
uint32 Id; uint32 m_Id;
std::string name; std::string m_Name;
uint64 leaderGuid; uint64 m_LeaderGuid;
std::string MOTD; std::string MOTD;
std::string GINFO; std::string GINFO;
uint32 CreatedYear; uint32 m_CreatedYear;
uint32 CreatedMonth; uint32 m_CreatedMonth;
uint32 CreatedDay; uint32 m_CreatedDay;
uint32 EmblemStyle; uint32 m_EmblemStyle;
uint32 EmblemColor; uint32 m_EmblemColor;
uint32 BorderStyle; uint32 m_BorderStyle;
uint32 BorderColor; uint32 m_BorderColor;
uint32 BackgroundColor; uint32 m_BackgroundColor;
RankList m_ranks; RankList m_Ranks;
MemberList members; MemberList members;
@ -458,21 +456,31 @@ class Guild
TabListMap m_TabListMap; TabListMap m_TabListMap;
/** These are actually ordered lists. The first element is the oldest entry.*/ /** These are actually ordered lists. The first element is the oldest entry.*/
typedef std::list<GuildEventlogEntry> GuildEventlog; typedef std::list<GuildEventLogEntry> GuildEventLog;
typedef std::list<GuildBankEvent> GuildBankEventLog; typedef std::list<GuildBankEventLogEntry> GuildBankEventLog;
GuildEventlog m_GuildEventlog; GuildEventLog m_GuildEventLog;
GuildBankEventLog m_GuildBankEventLog_Money; GuildBankEventLog m_GuildBankEventLog_Money;
GuildBankEventLog m_GuildBankEventLog_Item[GUILD_BANK_MAX_TABS]; GuildBankEventLog m_GuildBankEventLog_Item[GUILD_BANK_MAX_TABS];
bool m_bankloaded; uint32 m_GuildEventLogNextGuid;
bool m_eventlogloaded; uint32 m_GuildBankEventLogNextGuid_Money;
uint32 m_onlinemembers; uint32 m_GuildBankEventLogNextGuid_Item[GUILD_BANK_MAX_TABS];
uint64 guildbank_money;
uint8 purchased_tabs; bool m_GuildBankLoaded;
bool m_EventLogLoaded;
uint32 m_OnlineMembers;
uint64 m_GuildBankMoney;
uint8 m_PurchasedTabs;
uint32 LogMaxGuid;
uint32 GuildEventlogMaxGuid;
private: private:
// used only from high level Swap/Move functions
Item* GetItem(uint8 TabId, uint8 SlotId);
uint8 CanStoreItem( uint8 tab, uint8 slot, GuildItemPosCountVec& dest, uint32 count, Item *pItem, bool swap = false) const;
Item* StoreItem( uint8 tab, GuildItemPosCountVec const& pos, Item *pItem );
void RemoveItem(uint8 tab, uint8 slot );
void DisplayGuildBankContentUpdate(uint8 TabId, int32 slot1, int32 slot2 = -1);
void DisplayGuildBankContentUpdate(uint8 TabId, GuildItemPosCountVec const& slots);
// internal common parts for CanStore/StoreItem functions // internal common parts for CanStore/StoreItem functions
void AppendDisplayGuildBankSlot( WorldPacket& data, GuildBankTab const *tab, int32 slot ); void AppendDisplayGuildBankSlot( WorldPacket& data, GuildBankTab const *tab, int32 slot );
uint8 _CanStoreItem_InSpecificSlot( uint8 tab, uint8 slot, GuildItemPosCountVec& dest, uint32& count, bool swap, Item *pSrcItem ) const; uint8 _CanStoreItem_InSpecificSlot( uint8 tab, uint8 slot, GuildItemPosCountVec& dest, uint32& count, bool swap, Item *pSrcItem ) const;

View file

@ -58,7 +58,7 @@ void WorldSession::HandleGuildCreateOpcode(WorldPacket& recvPacket)
return; return;
Guild *guild = new Guild; Guild *guild = new Guild;
if(!guild->create(GetPlayer(),gname)) if(!guild->Create(GetPlayer(),gname))
{ {
delete guild; delete guild;
return; return;
@ -176,6 +176,13 @@ void WorldSession::HandleGuildRemoveOpcode(WorldPacket& recvPacket)
return; return;
} }
//do not allow to kick player with same or higher rights
if(GetPlayer()->GetRank() >= slot->RankId)
{
SendGuildCommandResult(GUILD_QUIT_S, plName, GUILD_RANK_TOO_HIGH_S);
return;
}
guild->DelMember(plGuid); guild->DelMember(plGuid);
// Put record into guildlog // Put record into guildlog
guild->LogGuildEvent(GUILD_EVENT_LOG_UNINVITE_PLAYER, GetPlayer()->GetGUIDLow(), GUID_LOPART(plGuid), 0); guild->LogGuildEvent(GUILD_EVENT_LOG_UNINVITE_PLAYER, GetPlayer()->GetGUIDLow(), GUID_LOPART(plGuid), 0);
@ -210,7 +217,7 @@ void WorldSession::HandleGuildAcceptOpcode(WorldPacket& /*recvPacket*/)
WorldPacket data(SMSG_GUILD_EVENT, (2+10)); // guess size WorldPacket data(SMSG_GUILD_EVENT, (2+10)); // guess size
data << (uint8)GE_JOINED; data << (uint8)GE_JOINED;
data << (uint8)1; data << (uint8)1; // strings count
data << player->GetName(); data << player->GetName();
guild->BroadcastPacket(&data); guild->BroadcastPacket(&data);
@ -297,10 +304,16 @@ void WorldSession::HandleGuildPromoteOpcode(WorldPacket& recvPacket)
return; return;
} }
if(slot->RankId < 2 || (slot->RankId-1) < GetPlayer()->GetRank()) //allow to promote only to lower rank than member's rank
//guildmaster's rank = 0
//GetPlayer()->GetRank() + 1 is highest rank that current player can promote to
if(GetPlayer()->GetRank() + 1 >= slot->RankId)
{
SendGuildCommandResult(GUILD_INVITE_S, plName, GUILD_RANK_TOO_HIGH_S);
return; return;
}
uint32 newRankId = slot->RankId < guild->GetNrRanks() ? slot->RankId-1 : guild->GetNrRanks()-1; uint32 newRankId = slot->RankId - 1; //when promoting player, rank is decreased
guild->ChangeRank(plGuid, newRankId); guild->ChangeRank(plGuid, newRankId);
// Put record into guildlog // Put record into guildlog
@ -308,7 +321,7 @@ void WorldSession::HandleGuildPromoteOpcode(WorldPacket& recvPacket)
WorldPacket data(SMSG_GUILD_EVENT, (2+30)); // guess size WorldPacket data(SMSG_GUILD_EVENT, (2+30)); // guess size
data << (uint8)GE_PROMOTION; data << (uint8)GE_PROMOTION;
data << (uint8)3; data << (uint8)3; // strings count
data << GetPlayer()->GetName(); data << GetPlayer()->GetName();
data << plName; data << plName;
data << guild->GetRankName(newRankId); data << guild->GetRankName(newRankId);
@ -355,16 +368,29 @@ void WorldSession::HandleGuildDemoteOpcode(WorldPacket& recvPacket)
return; return;
} }
if((slot->RankId+1) >= guild->GetNrRanks() || slot->RankId <= GetPlayer()->GetRank()) //do not allow to demote same or higher rank
if(GetPlayer()->GetRank() >= slot->RankId)
{
SendGuildCommandResult(GUILD_INVITE_S, plName, GUILD_RANK_TOO_HIGH_S);
return; return;
}
guild->ChangeRank(plGuid, (slot->RankId+1)); //do not allow to demote lowest rank
if(slot->RankId >= guild->GetLowestRank())
{
SendGuildCommandResult(GUILD_INVITE_S, plName, GUILD_ALREADY_LOWEST_RANK_S);
return;
}
uint32 newRankId = slot->RankId + 1; //when demoting player, rank is increased
guild->ChangeRank(plGuid, newRankId);
// Put record into guildlog // Put record into guildlog
guild->LogGuildEvent(GUILD_EVENT_LOG_DEMOTE_PLAYER, GetPlayer()->GetGUIDLow(), GUID_LOPART(plGuid), slot->RankId); guild->LogGuildEvent(GUILD_EVENT_LOG_DEMOTE_PLAYER, GetPlayer()->GetGUIDLow(), GUID_LOPART(plGuid), newRankId);
WorldPacket data(SMSG_GUILD_EVENT, (2+30)); // guess size WorldPacket data(SMSG_GUILD_EVENT, (2+30)); // guess size
data << (uint8)GE_DEMOTION; data << (uint8)GE_DEMOTION;
data << (uint8)3; data << (uint8)3; // strings count
data << GetPlayer()->GetName(); data << GetPlayer()->GetName();
data << plName; data << plName;
data << guild->GetRankName(slot->RankId); data << guild->GetRankName(slot->RankId);
@ -404,7 +430,7 @@ void WorldSession::HandleGuildLeaveOpcode(WorldPacket& /*recvPacket*/)
WorldPacket data(SMSG_GUILD_EVENT, (2+10)); // guess size WorldPacket data(SMSG_GUILD_EVENT, (2+10)); // guess size
data << (uint8)GE_LEFT; data << (uint8)GE_LEFT;
data << (uint8)1; data << (uint8)1; // strings count
data << plName; data << plName;
guild->BroadcastPacket(&data); guild->BroadcastPacket(&data);
@ -478,7 +504,7 @@ void WorldSession::HandleGuildLeaderOpcode(WorldPacket& recvPacket)
WorldPacket data(SMSG_GUILD_EVENT, (2+20)); // guess size WorldPacket data(SMSG_GUILD_EVENT, (2+20)); // guess size
data << (uint8)GE_LEADER_CHANGED; data << (uint8)GE_LEADER_CHANGED;
data << (uint8)2; data << (uint8)2; // strings count
data << oldLeader->GetName(); data << oldLeader->GetName();
data << name.c_str(); data << name.c_str();
guild->BroadcastPacket(&data); guild->BroadcastPacket(&data);
@ -514,7 +540,7 @@ void WorldSession::HandleGuildMOTDOpcode(WorldPacket& recvPacket)
WorldPacket data(SMSG_GUILD_EVENT, (2+MOTD.size()+1)); WorldPacket data(SMSG_GUILD_EVENT, (2+MOTD.size()+1));
data << (uint8)GE_MOTD; data << (uint8)GE_MOTD;
data << (uint8)1; data << (uint8)1; // strings count
data << MOTD; data << MOTD;
guild->BroadcastPacket(&data); guild->BroadcastPacket(&data);
@ -646,7 +672,7 @@ void WorldSession::HandleGuildRankOpcode(WorldPacket& recvPacket)
guild->SetBankMoneyPerDay(rankId, MoneyPerDay); guild->SetBankMoneyPerDay(rankId, MoneyPerDay);
guild->SetRankName(rankId, rankname); guild->SetRankName(rankId, rankname);
if(rankId==GR_GUILDMASTER) // prevent loss leader rights if (rankId == GR_GUILDMASTER) // prevent loss leader rights
rights = GR_RIGHT_ALL; rights = GR_RIGHT_ALL;
guild->SetRankRights(rankId, rights); guild->SetRankRights(rankId, rights);
@ -675,7 +701,7 @@ void WorldSession::HandleGuildAddRankOpcode(WorldPacket& recvPacket)
return; return;
} }
if(guild->GetNrRanks() >= GUILD_MAX_RANKS) // client not let create more 10 than ranks if(guild->GetRanksSize() >= GUILD_RANKS_MAX_COUNT) // client not let create more 10 than ranks
return; return;
recvPacket >> rankname; recvPacket >> rankname;
@ -825,7 +851,7 @@ void WorldSession::HandleGuildEventLogQueryOpcode(WorldPacket& /* recvPacket */)
if(!pGuild) if(!pGuild)
return; return;
pGuild->DisplayGuildEventlog(this); pGuild->DisplayGuildEventLog(this);
} }
/****** GUILD BANK *******/ /****** GUILD BANK *******/
@ -866,6 +892,7 @@ void WorldSession::HandleGuildPermissions( WorldPacket& /* recv_data */ )
// money per day left // money per day left
data << uint32(pGuild->GetMemberMoneyWithdrawRem(GetPlayer()->GetGUIDLow())); data << uint32(pGuild->GetMemberMoneyWithdrawRem(GetPlayer()->GetGUIDLow()));
data << uint8(pGuild->GetPurchasedTabs()); // tabs count data << uint8(pGuild->GetPurchasedTabs()); // tabs count
// why sending all info when not all tabs are purchased???
for(int i = 0; i < GUILD_BANK_MAX_TABS; ++i) for(int i = 0; i < GUILD_BANK_MAX_TABS; ++i)
{ {
data << uint32(pGuild->GetBankRights(rankId, uint8(i))); data << uint32(pGuild->GetBankRights(rankId, uint8(i)));
@ -1098,117 +1125,7 @@ void WorldSession::HandleGuildBankSwapItems( WorldPacket & recv_data )
// Bank <-> Bank // Bank <-> Bank
if (BankToBank) if (BankToBank)
{ {
// empty operation pGuild->SwapItems(pl, BankTab, BankTabSlot, BankTabDst, BankTabSlotDst, SplitedAmount);
if(BankTab==BankTabDst && BankTabSlot==BankTabSlotDst)
return;
Item *pItemSrc = pGuild->GetItem(BankTab, BankTabSlot);
if (!pItemSrc) // may prevent crash
return;
if(SplitedAmount > pItemSrc->GetCount())
return; // cheating?
else if(SplitedAmount == pItemSrc->GetCount())
SplitedAmount = 0; // no split
Item *pItemDst = pGuild->GetItem(BankTabDst, BankTabSlotDst);
if(BankTab!=BankTabDst)
{
// check dest pos rights (if different tabs)
if(!pGuild->IsMemberHaveRights(pl->GetGUIDLow(), BankTabDst, GUILD_BANK_RIGHT_DEPOSIT_ITEM))
return;
// check source pos rights (if different tabs)
uint32 remRight = pGuild->GetMemberSlotWithdrawRem(pl->GetGUIDLow(), BankTab);
if(remRight <= 0)
return;
}
if (SplitedAmount)
{ // Bank -> Bank item split (in empty or non empty slot
GuildItemPosCountVec dest;
uint8 msg = pGuild->CanStoreItem(BankTabDst,BankTabSlotDst,dest,SplitedAmount,pItemSrc,false);
if( msg != EQUIP_ERR_OK )
{
pl->SendEquipError( msg, pItemSrc, NULL );
return;
}
Item *pNewItem = pItemSrc->CloneItem( SplitedAmount );
if( !pNewItem )
{
pl->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, pItemSrc, NULL );
return;
}
CharacterDatabase.BeginTransaction();
pGuild->LogBankEvent(GUILD_BANK_LOG_MOVE_ITEM, BankTab, pl->GetGUIDLow(), pItemSrc->GetEntry(), SplitedAmount, BankTabDst);
pl->ItemRemovedQuestCheck( pItemSrc->GetEntry(), SplitedAmount );
pItemSrc->SetCount( pItemSrc->GetCount() - SplitedAmount );
pItemSrc->FSetState(ITEM_CHANGED);
pItemSrc->SaveToDB(); // not in inventory and can be save standalone
pGuild->StoreItem(BankTabDst,dest,pNewItem);
CharacterDatabase.CommitTransaction();
}
else // non split
{
GuildItemPosCountVec gDest;
uint8 msg = pGuild->CanStoreItem(BankTabDst,BankTabSlotDst,gDest,pItemSrc->GetCount(),pItemSrc,false);
if( msg == EQUIP_ERR_OK ) // merge to
{
CharacterDatabase.BeginTransaction();
pGuild->LogBankEvent(GUILD_BANK_LOG_MOVE_ITEM, BankTab, pl->GetGUIDLow(), pItemSrc->GetEntry(), pItemSrc->GetCount(), BankTabDst);
pGuild->RemoveItem(BankTab, BankTabSlot);
pGuild->StoreItem(BankTabDst, gDest, pItemSrc);
CharacterDatabase.CommitTransaction();
}
else // swap
{
gDest.clear();
msg = pGuild->CanStoreItem(BankTabDst,BankTabSlotDst,gDest,pItemSrc->GetCount(),pItemSrc,true);
if( msg != EQUIP_ERR_OK )
{
pl->SendEquipError( msg, pItemSrc, NULL );
return;
}
GuildItemPosCountVec gSrc;
msg = pGuild->CanStoreItem(BankTab,BankTabSlot,gSrc,pItemDst->GetCount(),pItemDst,true);
if( msg != EQUIP_ERR_OK )
{
pl->SendEquipError( msg, pItemDst, NULL );
return;
}
if(BankTab!=BankTabDst)
{
// check source pos rights (item swapped to src)
if(!pGuild->IsMemberHaveRights(pl->GetGUIDLow(), BankTab, GUILD_BANK_RIGHT_DEPOSIT_ITEM))
return;
// check dest pos rights (item swapped to src)
uint32 remRightDst = pGuild->GetMemberSlotWithdrawRem(pl->GetGUIDLow(), BankTabDst);
if(remRightDst <= 0)
return;
}
CharacterDatabase.BeginTransaction();
pGuild->LogBankEvent(GUILD_BANK_LOG_MOVE_ITEM, BankTab, pl->GetGUIDLow(), pItemSrc->GetEntry(), pItemSrc->GetCount(), BankTabDst);
pGuild->LogBankEvent(GUILD_BANK_LOG_MOVE_ITEM, BankTabDst, pl->GetGUIDLow(), pItemDst->GetEntry(), pItemDst->GetCount(), BankTab);
pGuild->RemoveItem(BankTab, BankTabSlot);
pGuild->RemoveItem(BankTabDst, BankTabSlotDst);
pGuild->StoreItem(BankTab, gSrc, pItemDst);
pGuild->StoreItem(BankTabDst, gDest, pItemSrc);
CharacterDatabase.CommitTransaction();
}
}
pGuild->DisplayGuildBankContentUpdate(BankTab,BankTabSlot,BankTab==BankTabDst ? BankTabSlotDst : -1);
if(BankTab!=BankTabDst)
pGuild->DisplayGuildBankContentUpdate(BankTabDst,BankTabSlotDst);
return; return;
} }
@ -1221,301 +1138,11 @@ void WorldSession::HandleGuildBankSwapItems( WorldPacket & recv_data )
return; return;
} }
Item *pItemBank = pGuild->GetItem(BankTab, BankTabSlot);
Item *pItemChar = GetPlayer()->GetItemByPos(PlayerBag, PlayerSlot);
if (!pItemChar && !pItemBank) // Nothing to do
return;
if (!pItemChar && !ToChar) // Problem to get item from player
return;
if (!pItemBank && ToChar) // Problem to get bank item
return;
// BankToChar swap or char to bank remaining // BankToChar swap or char to bank remaining
if (ToChar) // Bank -> Char cases if (ToChar) // Bank -> Char cases
{ pGuild->MoveFromBankToChar(pl, BankTab, BankTabSlot, PlayerBag, PlayerSlot, SplitedAmount);
if(SplitedAmount > pItemBank->GetCount()) else // Char -> Bank cases
return; // cheating? pGuild->MoveFromCharToBank(pl, PlayerBag, PlayerSlot, BankTab, BankTabSlot, SplitedAmount);
else if(SplitedAmount == pItemBank->GetCount())
SplitedAmount = 0; // no split
if (SplitedAmount)
{ // Bank -> Char split to slot (patly move)
Item *pNewItem = pItemBank->CloneItem( SplitedAmount );
if( !pNewItem )
{
pl->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, pItemBank, NULL );
return;
}
ItemPosCountVec dest;
uint8 msg = pl->CanStoreItem(PlayerBag, PlayerSlot, dest, pNewItem, false);
if( msg != EQUIP_ERR_OK )
{
pl->SendEquipError( msg, pNewItem, NULL );
delete pNewItem;
return;
}
// check source pos rights (item moved to inventory)
uint32 remRight = pGuild->GetMemberSlotWithdrawRem(pl->GetGUIDLow(), BankTab);
if(remRight <= 0)
{
delete pNewItem;
return;
}
CharacterDatabase.BeginTransaction();
pGuild->LogBankEvent(GUILD_BANK_LOG_WITHDRAW_ITEM, BankTab, pl->GetGUIDLow(), pItemBank->GetEntry(), SplitedAmount);
pItemBank->SetCount(pItemBank->GetCount()-SplitedAmount);
pItemBank->FSetState(ITEM_CHANGED);
pItemBank->SaveToDB(); // not in inventory and can be save standalone
pl->MoveItemToInventory(dest,pNewItem,true);
pl->SaveInventoryAndGoldToDB();
pGuild->MemberItemWithdraw(BankTab, pl->GetGUIDLow());
CharacterDatabase.CommitTransaction();
}
else // Bank -> Char swap with slot (move)
{
ItemPosCountVec dest;
uint8 msg = pl->CanStoreItem(PlayerBag, PlayerSlot, dest, pItemBank, false);
if( msg == EQUIP_ERR_OK ) // merge case
{
// check source pos rights (item moved to inventory)
uint32 remRight = pGuild->GetMemberSlotWithdrawRem(pl->GetGUIDLow(), BankTab);
if(remRight <= 0)
return;
CharacterDatabase.BeginTransaction();
pGuild->LogBankEvent(GUILD_BANK_LOG_WITHDRAW_ITEM, BankTab, pl->GetGUIDLow(), pItemBank->GetEntry(), pItemBank->GetCount());
pGuild->RemoveItem(BankTab, BankTabSlot);
pl->MoveItemToInventory(dest,pItemBank,true);
pl->SaveInventoryAndGoldToDB();
pGuild->MemberItemWithdraw(BankTab, pl->GetGUIDLow());
CharacterDatabase.CommitTransaction();
}
else // Bank <-> Char swap items
{
// check source pos rights (item swapped to bank)
if(!pGuild->IsMemberHaveRights(pl->GetGUIDLow(), BankTab, GUILD_BANK_RIGHT_DEPOSIT_ITEM))
return;
if(pItemChar)
{
if(!pItemChar->CanBeTraded())
{
_player->SendEquipError( EQUIP_ERR_ITEMS_CANT_BE_SWAPPED, pItemChar, NULL );
return;
}
}
ItemPosCountVec iDest;
msg = pl->CanStoreItem(PlayerBag, PlayerSlot, iDest, pItemBank, true);
if( msg != EQUIP_ERR_OK )
{
pl->SendEquipError( msg, pItemBank, NULL );
return;
}
GuildItemPosCountVec gDest;
if(pItemChar)
{
msg = pGuild->CanStoreItem(BankTab,BankTabSlot,gDest,pItemChar->GetCount(),pItemChar,true);
if( msg != EQUIP_ERR_OK )
{
pl->SendEquipError( msg, pItemChar, NULL );
return;
}
}
// check source pos rights (item moved to inventory)
uint32 remRight = pGuild->GetMemberSlotWithdrawRem(pl->GetGUIDLow(), BankTab);
if(remRight <= 0)
return;
if(pItemChar)
{
// logging item move to bank
if(_player->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE))
{
sLog.outCommand(_player->GetSession()->GetAccountId(),"GM %s (Account: %u) deposit item: %s (Entry: %d Count: %u) to guild bank (Guild ID: %u )",
_player->GetName(),_player->GetSession()->GetAccountId(),
pItemChar->GetProto()->Name1,pItemChar->GetEntry(),pItemChar->GetCount(),
GuildId);
}
}
CharacterDatabase.BeginTransaction();
pGuild->LogBankEvent(GUILD_BANK_LOG_WITHDRAW_ITEM, BankTab, pl->GetGUIDLow(), pItemBank->GetEntry(), pItemBank->GetCount());
if(pItemChar)
pGuild->LogBankEvent(GUILD_BANK_LOG_DEPOSIT_ITEM, BankTab, pl->GetGUIDLow(), pItemChar->GetEntry(), pItemChar->GetCount());
pGuild->RemoveItem(BankTab, BankTabSlot);
if(pItemChar)
{
pl->MoveItemFromInventory(PlayerBag, PlayerSlot, true);
pItemChar->DeleteFromInventoryDB();
}
if(pItemChar)
pGuild->StoreItem(BankTab, gDest, pItemChar);
pl->MoveItemToInventory(iDest,pItemBank,true);
pl->SaveInventoryAndGoldToDB();
pGuild->MemberItemWithdraw(BankTab, pl->GetGUIDLow());
CharacterDatabase.CommitTransaction();
}
}
pGuild->DisplayGuildBankContentUpdate(BankTab,BankTabSlot);
return;
} // End "To char" part
// Char -> Bank cases
if(!pItemChar->CanBeTraded())
{
_player->SendEquipError( EQUIP_ERR_ITEMS_CANT_BE_SWAPPED, pItemChar, NULL );
return;
}
// check source pos rights (item moved to bank)
if(!pGuild->IsMemberHaveRights(pl->GetGUIDLow(), BankTab, GUILD_BANK_RIGHT_DEPOSIT_ITEM))
return;
if(SplitedAmount > pItemChar->GetCount())
return; // cheating?
else if(SplitedAmount == pItemChar->GetCount())
SplitedAmount = 0; // no split
if (SplitedAmount)
{ // Char -> Bank split to empty or non-empty slot (partly move)
GuildItemPosCountVec dest;
uint8 msg = pGuild->CanStoreItem(BankTab,BankTabSlot,dest,SplitedAmount,pItemChar,false);
if( msg != EQUIP_ERR_OK )
{
pl->SendEquipError( msg, pItemChar, NULL );
return;
}
Item *pNewItem = pItemChar->CloneItem( SplitedAmount );
if( !pNewItem )
{
pl->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, pItemChar, NULL );
return;
}
// logging item move to bank (before items merge
if(_player->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE))
{
sLog.outCommand(_player->GetSession()->GetAccountId(),"GM %s (Account: %u) deposit item: %s (Entry: %d Count: %u) to guild bank (Guild ID: %u )",
_player->GetName(),_player->GetSession()->GetAccountId(),
pItemChar->GetProto()->Name1,pItemChar->GetEntry(),SplitedAmount,GuildId);
}
CharacterDatabase.BeginTransaction();
pGuild->LogBankEvent(GUILD_BANK_LOG_DEPOSIT_ITEM, BankTab, pl->GetGUIDLow(), pItemChar->GetEntry(), SplitedAmount);
pl->ItemRemovedQuestCheck( pItemChar->GetEntry(), SplitedAmount );
pItemChar->SetCount(pItemChar->GetCount()-SplitedAmount);
pItemChar->SetState(ITEM_CHANGED);
pl->SaveInventoryAndGoldToDB();
pGuild->StoreItem(BankTab, dest, pNewItem);
CharacterDatabase.CommitTransaction();
pGuild->DisplayGuildBankContentUpdate(BankTab,dest);
}
else // Char -> Bank swap with empty or non-empty (move)
{
GuildItemPosCountVec dest;
uint8 msg = pGuild->CanStoreItem(BankTab,BankTabSlot,dest,pItemChar->GetCount(),pItemChar,false);
if( msg == EQUIP_ERR_OK ) // merge
{
// logging item move to bank
if(_player->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE))
{
sLog.outCommand(_player->GetSession()->GetAccountId(),"GM %s (Account: %u) deposit item: %s (Entry: %d Count: %u) to guild bank (Guild ID: %u )",
_player->GetName(),_player->GetSession()->GetAccountId(),
pItemChar->GetProto()->Name1,pItemChar->GetEntry(),pItemChar->GetCount(),
GuildId);
}
CharacterDatabase.BeginTransaction();
pGuild->LogBankEvent(GUILD_BANK_LOG_DEPOSIT_ITEM, BankTab, pl->GetGUIDLow(), pItemChar->GetEntry(), pItemChar->GetCount());
pl->MoveItemFromInventory(PlayerBag, PlayerSlot, true);
pItemChar->DeleteFromInventoryDB();
pGuild->StoreItem(BankTab,dest,pItemChar);
pl->SaveInventoryAndGoldToDB();
CharacterDatabase.CommitTransaction();
pGuild->DisplayGuildBankContentUpdate(BankTab,dest);
}
else // Char <-> Bank swap items (posible NULL bank item)
{
ItemPosCountVec iDest;
if(pItemBank)
{
msg = pl->CanStoreItem(PlayerBag, PlayerSlot, iDest, pItemBank, true);
if( msg != EQUIP_ERR_OK )
{
pl->SendEquipError( msg, pItemBank, NULL );
return;
}
}
GuildItemPosCountVec gDest;
msg = pGuild->CanStoreItem(BankTab,BankTabSlot,gDest,pItemChar->GetCount(),pItemChar,true);
if( msg != EQUIP_ERR_OK )
{
pl->SendEquipError( msg, pItemChar, NULL );
return;
}
if(pItemBank)
{
// check bank pos rights (item swapped with inventory)
uint32 remRight = pGuild->GetMemberSlotWithdrawRem(pl->GetGUIDLow(), BankTab);
if(remRight <= 0)
return;
}
// logging item move to bank
if(_player->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE))
{
sLog.outCommand(_player->GetSession()->GetAccountId(),"GM %s (Account: %u) deposit item: %s (Entry: %d Count: %u) to guild bank (Guild ID: %u )",
_player->GetName(),_player->GetSession()->GetAccountId(),
pItemChar->GetProto()->Name1,pItemChar->GetEntry(),pItemChar->GetCount(),
GuildId);
}
CharacterDatabase.BeginTransaction();
if(pItemBank)
pGuild->LogBankEvent(GUILD_BANK_LOG_WITHDRAW_ITEM, BankTab, pl->GetGUIDLow(), pItemBank->GetEntry(), pItemBank->GetCount());
pGuild->LogBankEvent(GUILD_BANK_LOG_DEPOSIT_ITEM, BankTab, pl->GetGUIDLow(), pItemChar->GetEntry(), pItemChar->GetCount());
pl->MoveItemFromInventory(PlayerBag, PlayerSlot, true);
pItemChar->DeleteFromInventoryDB();
if(pItemBank)
pGuild->RemoveItem(BankTab, BankTabSlot);
pGuild->StoreItem(BankTab,gDest,pItemChar);
if(pItemBank)
pl->MoveItemToInventory(iDest,pItemBank,true);
pl->SaveInventoryAndGoldToDB();
if(pItemBank)
pGuild->MemberItemWithdraw(BankTab, pl->GetGUIDLow());
CharacterDatabase.CommitTransaction();
pGuild->DisplayGuildBankContentUpdate(BankTab,gDest);
}
}
} }
void WorldSession::HandleGuildBankBuyTab( WorldPacket & recv_data ) void WorldSession::HandleGuildBankBuyTab( WorldPacket & recv_data )
@ -1546,7 +1173,7 @@ void WorldSession::HandleGuildBankBuyTab( WorldPacket & recv_data )
if (pGuild->GetPurchasedTabs() >= GUILD_BANK_MAX_TABS) if (pGuild->GetPurchasedTabs() >= GUILD_BANK_MAX_TABS)
return; return;
if (TabId != pGuild->GetPurchasedTabs()) // purchased_tabs = 0 when buying Tab 0, that is why this check can be made if (TabId != pGuild->GetPurchasedTabs()) // m_PurchasedTabs = 0 when buying Tab 0, that is why this check can be made
{ {
sLog.outError("Error: trying to buy a tab non contigous to owned ones"); sLog.outError("Error: trying to buy a tab non contigous to owned ones");
return; return;

View file

@ -3210,7 +3210,7 @@ bool ChatHandler::HandleGuildCreateCommand(const char* args)
} }
Guild *guild = new Guild; Guild *guild = new Guild;
if (!guild->create (target,guildname)) if (!guild->Create (target,guildname))
{ {
delete guild; delete guild;
SendSysMessage (LANG_GUILD_NOT_CREATED); SendSysMessage (LANG_GUILD_NOT_CREATED);

View file

@ -236,7 +236,10 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
recv_data.rpos(recv_data.wpos()); // prevent warnings spam recv_data.rpos(recv_data.wpos()); // prevent warnings spam
if (!MaNGOS::IsValidMapCoord(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o)) if (!MaNGOS::IsValidMapCoord(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o))
{
recv_data.rpos(recv_data.wpos()); // prevent warnings spam
return; return;
}
/* handle special cases */ /* handle special cases */
if (movementInfo.HasMovementFlag(MOVEMENTFLAG_ONTRANSPORT)) if (movementInfo.HasMovementFlag(MOVEMENTFLAG_ONTRANSPORT))
@ -244,11 +247,17 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
// transports size limited // transports size limited
// (also received at zeppelin leave by some reason with t_* as absolute in continent coordinates, can be safely skipped) // (also received at zeppelin leave by some reason with t_* as absolute in continent coordinates, can be safely skipped)
if( movementInfo.t_x > 50 || movementInfo.t_y > 50 || movementInfo.t_z > 50 ) if( movementInfo.t_x > 50 || movementInfo.t_y > 50 || movementInfo.t_z > 50 )
{
recv_data.rpos(recv_data.wpos()); // prevent warnings spam
return; return;
}
if( !MaNGOS::IsValidMapCoord(movementInfo.x+movementInfo.t_x, movementInfo.y + movementInfo.t_y, if( !MaNGOS::IsValidMapCoord(movementInfo.x+movementInfo.t_x, movementInfo.y + movementInfo.t_y,
movementInfo.z + movementInfo.t_z, movementInfo.o + movementInfo.t_o) ) movementInfo.z + movementInfo.t_z, movementInfo.o + movementInfo.t_o) )
{
recv_data.rpos(recv_data.wpos()); // prevent warnings spam
return; return;
}
// if we boarded a transport, add us to it // if we boarded a transport, add us to it
if (plMover && !plMover->m_transport) if (plMover && !plMover->m_transport)

View file

@ -2886,6 +2886,11 @@ void ObjectMgr::LoadGuilds()
delete result; delete result;
//delete unused LogGuid records in guild_eventlog and guild_bank_eventlog table
//you can comment these lines if you don't plan to change CONFIG_GUILD_EVENT_LOG_COUNT and CONFIG_GUILD_BANK_EVENT_LOG_COUNT
CharacterDatabase.PQuery("DELETE FROM guild_eventlog WHERE LogGuid > '%u'", sWorld.getConfig(CONFIG_GUILD_EVENT_LOG_COUNT));
CharacterDatabase.PQuery("DELETE FROM guild_bank_eventlog WHERE LogGuid > '%u'", sWorld.getConfig(CONFIG_GUILD_BANK_EVENT_LOG_COUNT));
sLog.outString(); sLog.outString();
sLog.outString( ">> Loaded %u guild definitions", count ); sLog.outString( ">> Loaded %u guild definitions", count );
} }

View file

@ -805,7 +805,7 @@ void WorldSession::HandleTurnInPetitionOpcode(WorldPacket & recv_data)
if(type == 9) // create guild if(type == 9) // create guild
{ {
Guild* guild = new Guild; Guild* guild = new Guild;
if(!guild->create(_player, name)) if(!guild->Create(_player, name))
{ {
delete guild; delete guild;
delete result; delete result;

View file

@ -4018,6 +4018,9 @@ void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmC
CharacterDatabase.PExecute("DELETE FROM character_achievement WHERE guid = '%u'",guid); CharacterDatabase.PExecute("DELETE FROM character_achievement WHERE guid = '%u'",guid);
CharacterDatabase.PExecute("DELETE FROM character_achievement_progress WHERE guid = '%u'",guid); CharacterDatabase.PExecute("DELETE FROM character_achievement_progress WHERE guid = '%u'",guid);
CharacterDatabase.PExecute("DELETE FROM character_equipmentsets WHERE guid = '%u'",guid); CharacterDatabase.PExecute("DELETE FROM character_equipmentsets WHERE guid = '%u'",guid);
CharacterDatabase.PExecute("DELETE FROM guild_eventlog WHERE PlayerGuid1 = '%u'",guid);
CharacterDatabase.PExecute("DELETE FROM guild_eventlog WHERE PlayerGuid2 = '%u'",guid);
CharacterDatabase.PExecute("DELETE FROM guild_bank_eventlog WHERE PlayerGuid = '%u'",guid);
CharacterDatabase.CommitTransaction(); CharacterDatabase.CommitTransaction();
//loginDatabase.PExecute("UPDATE realmcharacters SET numchars = numchars - 1 WHERE acctid = %d AND realmid = %d", accountId, realmID); //loginDatabase.PExecute("UPDATE realmcharacters SET numchars = numchars - 1 WHERE acctid = %d AND realmid = %d", accountId, realmID);

View file

@ -308,7 +308,7 @@ enum ItemQualities
#define SPELL_ATTR_EX2_UNK28 0x10000000 // 28 no breaks stealth if it fails?? #define SPELL_ATTR_EX2_UNK28 0x10000000 // 28 no breaks stealth if it fails??
#define SPELL_ATTR_EX2_CANT_CRIT 0x20000000 // 29 Spell can't crit #define SPELL_ATTR_EX2_CANT_CRIT 0x20000000 // 29 Spell can't crit
#define SPELL_ATTR_EX2_UNK30 0x40000000 // 30 #define SPELL_ATTR_EX2_UNK30 0x40000000 // 30
#define SPELL_ATTR_EX2_UNK31 0x80000000 // 31 #define SPELL_ATTR_EX2_FOOD_BUFF 0x80000000 // 31 Food or Drink Buff (like Well Fed)
#define SPELL_ATTR_EX3_UNK0 0x00000001 // 0 #define SPELL_ATTR_EX3_UNK0 0x00000001 // 0
#define SPELL_ATTR_EX3_UNK1 0x00000002 // 1 #define SPELL_ATTR_EX3_UNK1 0x00000002 // 1
@ -2329,9 +2329,11 @@ enum PetDiet
// Max values for Guild & Guild Bank // Max values for Guild & Guild Bank
#define GUILD_BANK_MAX_TABS 6 #define GUILD_BANK_MAX_TABS 6
#define GUILD_BANK_MAX_SLOTS 98 #define GUILD_BANK_MAX_SLOTS 98
#define GUILD_BANK_MAX_LOGS 24 #define GUILD_BANK_MAX_LOGS 25
#define GUILD_EVENTLOG_MAX_ENTRIES 100 #define GUILD_BANK_MONEY_LOGS_TAB 100
#define GUILD_MAX_RANKS 10 #define GUILD_EVENTLOG_MAX_RECORDS 100
#define GUILD_RANKS_MIN_COUNT 5
#define GUILD_RANKS_MAX_COUNT 10
enum AiReaction enum AiReaction
{ {

View file

@ -289,7 +289,10 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket)
// ignore for remote control state (for player case) // ignore for remote control state (for player case)
Unit* mover = _player->m_mover; Unit* mover = _player->m_mover;
if(mover != _player && mover->GetTypeId()==TYPEID_PLAYER) if(mover != _player && mover->GetTypeId()==TYPEID_PLAYER)
{
recvPacket.rpos(recvPacket.wpos()); // prevent spam at ignore packet
return; return;
}
sLog.outDebug("WORLD: got cast spell packet, spellId - %u, cast_count: %u, unk_flags %u, data length = %i", sLog.outDebug("WORLD: got cast spell packet, spellId - %u, cast_count: %u, unk_flags %u, data length = %i",
spellId, cast_count, unk_flags, (uint32)recvPacket.size()); spellId, cast_count, unk_flags, (uint32)recvPacket.size());
@ -299,6 +302,7 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket)
if(!spellInfo) if(!spellInfo)
{ {
sLog.outError("WORLD: unknown spell id %u", spellId); sLog.outError("WORLD: unknown spell id %u", spellId);
recvPacket.rpos(recvPacket.wpos()); // prevent spam at ignore packet
return; return;
} }
@ -308,6 +312,7 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket)
if (!((Player*)mover)->HasActiveSpell (spellId) || IsPassiveSpell(spellId) ) if (!((Player*)mover)->HasActiveSpell (spellId) || IsPassiveSpell(spellId) )
{ {
//cheater? kick? ban? //cheater? kick? ban?
recvPacket.rpos(recvPacket.wpos()); // prevent spam at ignore packet
return; return;
} }
} }
@ -317,6 +322,7 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket)
if (!((Creature*)mover)->HasSpell(spellId) || IsPassiveSpell(spellId) ) if (!((Creature*)mover)->HasSpell(spellId) || IsPassiveSpell(spellId) )
{ {
//cheater? kick? ban? //cheater? kick? ban?
recvPacket.rpos(recvPacket.wpos()); // prevent spam at ignore packet
return; return;
} }
} }
@ -324,7 +330,21 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket)
// client provided targets // client provided targets
SpellCastTargets targets; SpellCastTargets targets;
if(!targets.read(&recvPacket,mover)) if(!targets.read(&recvPacket,mover))
{
recvPacket.rpos(recvPacket.wpos()); // prevent spam at ignore packet
return; return;
}
// some spell cast packet including more data (for projectiles?)
if (unk_flags & 0x02)
{
recvPacket.read_skip<float>(); // unk1, coords?
recvPacket.read_skip<float>(); // unk1, coords?
recvPacket.read_skip<uint8>(); // >> 1
recvPacket.read_skip<uint32>(); // >> MSG_MOVE_STOP
MovementInfo movementInfo;
ReadMovementInfo(recvPacket, &movementInfo);
}
// auto-selection buff level base at target level (in spellInfo) // auto-selection buff level base at target level (in spellInfo)
if(targets.getUnitTarget()) if(targets.getUnitTarget())

View file

@ -135,6 +135,47 @@ SpellSpecific GetSpellSpecific(uint32 spellId)
switch(spellInfo->SpellFamilyName) switch(spellInfo->SpellFamilyName)
{ {
case SPELLFAMILY_GENERIC:
{
// Food / Drinks (mostly)
if(spellInfo->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED)
{
bool food = false;
bool drink = false;
for(int i = 0; i < 3; ++i)
{
switch(spellInfo->EffectApplyAuraName[i])
{
// Food
case SPELL_AURA_MOD_REGEN:
case SPELL_AURA_OBS_MOD_HEALTH:
food = true;
break;
// Drink
case SPELL_AURA_MOD_POWER_REGEN:
case SPELL_AURA_OBS_MOD_MANA:
drink = true;
break;
default:
break;
}
}
if(food && drink)
return SPELL_FOOD_AND_DRINK;
else if(food)
return SPELL_FOOD;
else if(drink)
return SPELL_DRINK;
}
else
{
// Well Fed buffs (must be exclusive with Food / Drink replenishment effects, or else Well Fed will cause them to be removed)
// SpellIcon 2560 is Spell 46687, does not have this flag
if ((spellInfo->AttributesEx2 & SPELL_ATTR_EX2_FOOD_BUFF) || spellInfo->SpellIconID == 2560)
return SPELL_WELL_FED;
}
}
case SPELLFAMILY_MAGE: case SPELLFAMILY_MAGE:
{ {
// family flags 18(Molten), 25(Frost/Ice), 28(Mage) // family flags 18(Molten), 25(Frost/Ice), 28(Mage)
@ -165,6 +206,15 @@ SpellSpecific GetSpellSpecific(uint32 spellId)
break; break;
} }
case SPELLFAMILY_PRIEST:
{
// "Well Fed" buff from Blessed Sunfruit, Blessed Sunfruit Juice, Alterac Spring Water
if ((spellInfo->Attributes & SPELL_ATTR_CASTABLE_WHILE_SITTING) &&
(spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_AUTOATTACK) &&
(spellInfo->SpellIconID == 52 || spellInfo->SpellIconID == 79))
return SPELL_WELL_FED;
break;
}
case SPELLFAMILY_HUNTER: case SPELLFAMILY_HUNTER:
{ {
// only hunter stings have this // only hunter stings have this
@ -224,6 +274,8 @@ SpellSpecific GetSpellSpecific(uint32 spellId)
return SPELL_NORMAL; return SPELL_NORMAL;
} }
// target not allow have more one spell specific from same caster
bool IsSingleFromSpellSpecificPerCaster(SpellSpecific spellSpec1,SpellSpecific spellSpec2) bool IsSingleFromSpellSpecificPerCaster(SpellSpecific spellSpec1,SpellSpecific spellSpec2)
{ {
switch(spellSpec1) switch(spellSpec1)
@ -242,7 +294,17 @@ bool IsSingleFromSpellSpecificPerCaster(SpellSpecific spellSpec1,SpellSpecific s
case SPELL_JUDGEMENT: case SPELL_JUDGEMENT:
case SPELL_PRESENCE: case SPELL_PRESENCE:
case SPELL_HAND: case SPELL_HAND:
return spellSpec1==spellSpec2; case SPELL_WELL_FED:
case SPELL_FOOD:
return spellSpec2==SPELL_FOOD
|| spellSpec2==SPELL_FOOD_AND_DRINK;
case SPELL_DRINK:
return spellSpec2==SPELL_DRINK
|| spellSpec2==SPELL_FOOD_AND_DRINK;
case SPELL_FOOD_AND_DRINK:
return spellSpec2==SPELL_FOOD
|| spellSpec2==SPELL_DRINK
|| spellSpec2==SPELL_FOOD_AND_DRINK;
case SPELL_BATTLE_ELIXIR: case SPELL_BATTLE_ELIXIR:
return spellSpec2==SPELL_BATTLE_ELIXIR return spellSpec2==SPELL_BATTLE_ELIXIR
|| spellSpec2==SPELL_FLASK_ELIXIR; || spellSpec2==SPELL_FLASK_ELIXIR;
@ -258,6 +320,7 @@ bool IsSingleFromSpellSpecificPerCaster(SpellSpecific spellSpec1,SpellSpecific s
} }
} }
// target not allow have more one ranks from spell from spell specific per target
bool IsSingleFromSpellSpecificRanksPerTarget(SpellSpecific spellId_spec, SpellSpecific i_spellId_spec) bool IsSingleFromSpellSpecificRanksPerTarget(SpellSpecific spellId_spec, SpellSpecific i_spellId_spec)
{ {
switch(spellId_spec) switch(spellId_spec)
@ -266,6 +329,7 @@ bool IsSingleFromSpellSpecificRanksPerTarget(SpellSpecific spellId_spec, SpellSp
case SPELL_AURA: case SPELL_AURA:
case SPELL_CURSE: case SPELL_CURSE:
case SPELL_HAND: case SPELL_HAND:
case SPELL_ELEMENTAL_SHIELD:
return spellId_spec==i_spellId_spec; return spellId_spec==i_spellId_spec;
default: default:
return false; return false;
@ -1505,10 +1569,6 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons
case SPELLFAMILY_SHAMAN: case SPELLFAMILY_SHAMAN:
if( spellInfo_2->SpellFamilyName == SPELLFAMILY_SHAMAN ) if( spellInfo_2->SpellFamilyName == SPELLFAMILY_SHAMAN )
{ {
// shaman shields
if( IsElementalShield(spellInfo_1) && IsElementalShield(spellInfo_2) )
return true;
// Windfury weapon // Windfury weapon
if( spellInfo_1->SpellIconID==220 && spellInfo_2->SpellIconID==220 && if( spellInfo_1->SpellIconID==220 && spellInfo_2->SpellIconID==220 &&
spellInfo_1->SpellFamilyFlags != spellInfo_2->SpellFamilyFlags ) spellInfo_1->SpellFamilyFlags != spellInfo_2->SpellFamilyFlags )

View file

@ -99,6 +99,10 @@ enum SpellSpecific
SPELL_FLASK_ELIXIR = 16, SPELL_FLASK_ELIXIR = 16,
SPELL_PRESENCE = 17, SPELL_PRESENCE = 17,
SPELL_HAND = 18, SPELL_HAND = 18,
SPELL_WELL_FED = 19,
SPELL_FOOD = 20,
SPELL_DRINK = 21,
SPELL_FOOD_AND_DRINK = 22,
}; };
SpellSpecific GetSpellSpecific(uint32 spellId); SpellSpecific GetSpellSpecific(uint32 spellId);
@ -508,11 +512,12 @@ struct SpellBonusEntry
typedef UNORDERED_MAP<uint32, SpellProcEventEntry> SpellProcEventMap; typedef UNORDERED_MAP<uint32, SpellProcEventEntry> SpellProcEventMap;
typedef UNORDERED_MAP<uint32, SpellBonusEntry> SpellBonusMap; typedef UNORDERED_MAP<uint32, SpellBonusEntry> SpellBonusMap;
#define ELIXIR_BATTLE_MASK 0x1 #define ELIXIR_BATTLE_MASK 0x01
#define ELIXIR_GUARDIAN_MASK 0x2 #define ELIXIR_GUARDIAN_MASK 0x02
#define ELIXIR_FLASK_MASK (ELIXIR_BATTLE_MASK|ELIXIR_GUARDIAN_MASK) #define ELIXIR_FLASK_MASK (ELIXIR_BATTLE_MASK|ELIXIR_GUARDIAN_MASK)
#define ELIXIR_UNSTABLE_MASK 0x4 #define ELIXIR_UNSTABLE_MASK 0x04
#define ELIXIR_SHATTRATH_MASK 0x8 #define ELIXIR_SHATTRATH_MASK 0x08
#define ELIXIR_WELL_FED 0x10 // Some foods have SPELLFAMILY_POTION
typedef std::map<uint32, uint8> SpellElixirMap; typedef std::map<uint32, uint8> SpellElixirMap;
typedef std::map<uint32, float> SpellProcItemEnchantMap; typedef std::map<uint32, float> SpellProcItemEnchantMap;
@ -730,6 +735,8 @@ class SpellMgr
return SPELL_BATTLE_ELIXIR; return SPELL_BATTLE_ELIXIR;
else if(mask & ELIXIR_GUARDIAN_MASK) else if(mask & ELIXIR_GUARDIAN_MASK)
return SPELL_GUARDIAN_ELIXIR; return SPELL_GUARDIAN_ELIXIR;
else if(mask & ELIXIR_WELL_FED)
return SPELL_WELL_FED;
else else
return SPELL_NORMAL; return SPELL_NORMAL;
} }

View file

@ -3631,9 +3631,8 @@ bool Unit::RemoveNoStackAurasDueToAura(Aura *Aur)
SpellSpecific i_spellId_spec = GetSpellSpecific(i_spellId); SpellSpecific i_spellId_spec = GetSpellSpecific(i_spellId);
// single allowed spell specific from same caster
bool is_sspc = IsSingleFromSpellSpecificPerCaster(spellId_spec,i_spellId_spec); bool is_sspc = IsSingleFromSpellSpecificPerCaster(spellId_spec,i_spellId_spec);
bool is_sspt = IsSingleFromSpellSpecificRanksPerTarget(spellId_spec,i_spellId_spec);
if( is_sspc && Aur->GetCasterGUID() == (*i).second->GetCasterGUID() ) if( is_sspc && Aur->GetCasterGUID() == (*i).second->GetCasterGUID() )
{ {
// cannot remove higher rank // cannot remove higher rank
@ -3653,8 +3652,15 @@ bool Unit::RemoveNoStackAurasDueToAura(Aura *Aur)
break; break;
else else
next = m_Auras.begin(); next = m_Auras.begin();
continue;
} }
else if( is_sspt && Aur->GetCasterGUID() != (*i).second->GetCasterGUID() && spellmgr.IsRankSpellDueToSpell(spellProto, i_spellId) )
// spell with spell specific that allow single ranks for spell from diff caster
// same caster case processed or early or later
bool is_sspt = IsSingleFromSpellSpecificRanksPerTarget(spellId_spec,i_spellId_spec);
if ( is_sspt && Aur->GetCasterGUID() != (*i).second->GetCasterGUID() &&
(spellProto->Id == i_spellId || spellmgr.IsRankSpellDueToSpell(spellProto, i_spellId)))
{ {
// cannot remove higher rank // cannot remove higher rank
if(CompareAuraRanks(spellId, effIndex, i_spellId, i_effIndex) < 0) if(CompareAuraRanks(spellId, effIndex, i_spellId, i_effIndex) < 0)
@ -3672,8 +3678,12 @@ bool Unit::RemoveNoStackAurasDueToAura(Aura *Aur)
break; break;
else else
next = m_Auras.begin(); next = m_Auras.begin();
continue;
} }
else if( !is_sspc && spellmgr.IsNoStackSpellDueToSpell(spellId, i_spellId) )
// non single per caster spell specific (possible single per target spells at caster)
if( !is_sspc && spellmgr.IsNoStackSpellDueToSpell(spellId, i_spellId) )
{ {
// Its a parent aura (create this aura in ApplyModifier) // Its a parent aura (create this aura in ApplyModifier)
if ((*i).second->IsInUse()) if ((*i).second->IsInUse())
@ -3687,9 +3697,12 @@ bool Unit::RemoveNoStackAurasDueToAura(Aura *Aur)
break; break;
else else
next = m_Auras.begin(); next = m_Auras.begin();
continue;
} }
// Potions stack aura by aura (elixirs/flask already checked) // Potions stack aura by aura (elixirs/flask already checked)
else if( spellProto->SpellFamilyName == SPELLFAMILY_POTION && i_spellProto->SpellFamilyName == SPELLFAMILY_POTION ) if( spellProto->SpellFamilyName == SPELLFAMILY_POTION && i_spellProto->SpellFamilyName == SPELLFAMILY_POTION )
{ {
if (IsNoStackAuraDueToAura(spellId, effIndex, i_spellId, i_effIndex)) if (IsNoStackAuraDueToAura(spellId, effIndex, i_spellId, i_effIndex))
{ {
@ -11043,6 +11056,10 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag
// Fill procTriggered list // Fill procTriggered list
for(AuraMap::const_iterator itr = GetAuras().begin(); itr!= GetAuras().end(); ++itr) for(AuraMap::const_iterator itr = GetAuras().begin(); itr!= GetAuras().end(); ++itr)
{ {
// skip deleted auras (possible at recursive triggered call
if(itr->second->IsDeleted())
continue;
SpellProcEventEntry const* spellProcEvent = NULL; SpellProcEventEntry const* spellProcEvent = NULL;
if(!IsTriggeredAtSpellProcEvent(pTarget, itr->second, procSpell, procFlag, procExtra, attType, isVictim, (damage > 0), spellProcEvent)) if(!IsTriggeredAtSpellProcEvent(pTarget, itr->second, procSpell, procFlag, procExtra, attType, isVictim, (damage > 0), spellProcEvent))
continue; continue;

View file

@ -73,7 +73,7 @@ enum SpellAuraInterruptFlags
AURA_INTERRUPT_FLAG_UNK15 = 0x00008000, // 15 removed by casting a spell? AURA_INTERRUPT_FLAG_UNK15 = 0x00008000, // 15 removed by casting a spell?
AURA_INTERRUPT_FLAG_UNK16 = 0x00010000, // 16 AURA_INTERRUPT_FLAG_UNK16 = 0x00010000, // 16
AURA_INTERRUPT_FLAG_MOUNTING = 0x00020000, // 17 removed by mounting AURA_INTERRUPT_FLAG_MOUNTING = 0x00020000, // 17 removed by mounting
AURA_INTERRUPT_FLAG_NOT_SEATED = 0x00040000, // 18 removed by standing up AURA_INTERRUPT_FLAG_NOT_SEATED = 0x00040000, // 18 removed by standing up (used by food and drink mostly and sleep/Fake Death like)
AURA_INTERRUPT_FLAG_CHANGE_MAP = 0x00080000, // 19 leaving map/getting teleported AURA_INTERRUPT_FLAG_CHANGE_MAP = 0x00080000, // 19 leaving map/getting teleported
AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION = 0x00100000, // 20 removed by auras that make you invulnerable, or make other to loose selection on you AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION = 0x00100000, // 20 removed by auras that make you invulnerable, or make other to loose selection on you
AURA_INTERRUPT_FLAG_UNK21 = 0x00200000, // 21 AURA_INTERRUPT_FLAG_UNK21 = 0x00200000, // 21

View file

@ -975,6 +975,13 @@ void World::LoadConfigSettings(bool reload)
m_configs[CONFIG_INSTANT_LOGOUT] = sConfig.GetIntDefault("InstantLogout", SEC_MODERATOR); m_configs[CONFIG_INSTANT_LOGOUT] = sConfig.GetIntDefault("InstantLogout", SEC_MODERATOR);
m_configs[CONFIG_GUILD_EVENT_LOG_COUNT] = sConfig.GetIntDefault("Guild.EventLogRecordsCount", GUILD_EVENTLOG_MAX_RECORDS);
if (m_configs[CONFIG_GUILD_EVENT_LOG_COUNT] < GUILD_EVENTLOG_MAX_RECORDS)
m_configs[CONFIG_GUILD_EVENT_LOG_COUNT] = GUILD_EVENTLOG_MAX_RECORDS;
m_configs[CONFIG_GUILD_BANK_EVENT_LOG_COUNT] = sConfig.GetIntDefault("Guild.BankEventLogRecordsCount", GUILD_BANK_MAX_LOGS);
if (m_configs[CONFIG_GUILD_BANK_EVENT_LOG_COUNT] < GUILD_BANK_MAX_LOGS)
m_configs[CONFIG_GUILD_BANK_EVENT_LOG_COUNT] = GUILD_BANK_MAX_LOGS;
m_VisibleUnitGreyDistance = sConfig.GetFloatDefault("Visibility.Distance.Grey.Unit", 1); m_VisibleUnitGreyDistance = sConfig.GetFloatDefault("Visibility.Distance.Grey.Unit", 1);
if(m_VisibleUnitGreyDistance > MAX_VISIBILITY_DISTANCE) if(m_VisibleUnitGreyDistance > MAX_VISIBILITY_DISTANCE)
{ {

View file

@ -213,6 +213,8 @@ enum WorldConfigs
CONFIG_ARENA_SEASON_IN_PROGRESS, CONFIG_ARENA_SEASON_IN_PROGRESS,
CONFIG_OFFHAND_CHECK_AT_TALENTS_RESET, CONFIG_OFFHAND_CHECK_AT_TALENTS_RESET,
CONFIG_CLIENTCACHE_VERSION, CONFIG_CLIENTCACHE_VERSION,
CONFIG_GUILD_EVENT_LOG_COUNT,
CONFIG_GUILD_BANK_EVENT_LOG_COUNT,
CONFIG_VALUE_COUNT CONFIG_VALUE_COUNT
}; };

View file

@ -368,7 +368,7 @@ void WorldSession::LogoutPlayer(bool Save)
Guild *guild = objmgr.GetGuildById(_player->GetGuildId()); Guild *guild = objmgr.GetGuildById(_player->GetGuildId());
if(guild) if(guild)
{ {
guild->LoadPlayerStatsByGuid(_player->GetGUID()); guild->SetMemberStats(_player->GetGUID());
guild->UpdateLogoutTime(_player->GetGUID()); guild->UpdateLogoutTime(_player->GetGUID());
WorldPacket data(SMSG_GUILD_EVENT, (1+1+12+8)); // name limited to 12 in character table. WorldPacket data(SMSG_GUILD_EVENT, (1+1+12+8)); // name limited to 12 in character table.

View file

@ -697,6 +697,7 @@ class MANGOS_DLL_SPEC WorldSession
void HandleGuildBankDepositMoney(WorldPacket& recv_data); void HandleGuildBankDepositMoney(WorldPacket& recv_data);
void HandleGuildBankWithdrawMoney(WorldPacket& recv_data); void HandleGuildBankWithdrawMoney(WorldPacket& recv_data);
void HandleGuildBankSwapItems(WorldPacket& recv_data); void HandleGuildBankSwapItems(WorldPacket& recv_data);
void HandleGuildBankUpdateTab(WorldPacket& recv_data); void HandleGuildBankUpdateTab(WorldPacket& recv_data);
void HandleGuildBankBuyTab(WorldPacket& recv_data); void HandleGuildBankBuyTab(WorldPacket& recv_data);
void HandleQueryGuildBankTabText(WorldPacket& recv_data); void HandleQueryGuildBankTabText(WorldPacket& recv_data);

View file

@ -537,6 +537,18 @@ LogColors = ""
# Default: 7 # Default: 7
# -1 (show all available quests marks) # -1 (show all available quests marks)
# #
# Guild.EventLogRecordsCount
# Count of guild event log records stored in guild_eventlog table
# Increase to store more guild events in table, minimum is 100
# You can set it to very high value to prevent oldest guild events to be rewritten by latest guild events - but it can slow down performance
# Default: 100
#
# Guild.BankEventLogRecordsCount
# Count of guild_bank event log records stored in guild_bank_eventlog table
# Increase to store more guild_bank events in table - minimum is 25 (GUILD_BANK_MAX_LOGS) for each guild_bank tab
# Useful when you don't want old log events to be overwritten by new, but increasing can slow down performance
# Default: 25
#
# MaxPrimaryTradeSkill # MaxPrimaryTradeSkill
# Max count that player can learn the primary trade skill. # Max count that player can learn the primary trade skill.
# Default: 2 # Default: 2
@ -624,6 +636,8 @@ Instance.ResetTimeHour = 4
Instance.UnloadDelay = 1800000 Instance.UnloadDelay = 1800000
Quests.LowLevelHideDiff = 4 Quests.LowLevelHideDiff = 4
Quests.HighLevelHideDiff = 7 Quests.HighLevelHideDiff = 7
Guild.EventLogRecordsCount = 100
Guild.BankEventLogRecordsCount = 25
MaxPrimaryTradeSkill = 2 MaxPrimaryTradeSkill = 2
MinPetitionSigns = 9 MinPetitionSigns = 9
MaxGroupXPDistance = 74 MaxGroupXPDistance = 74

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__ #ifndef __REVISION_NR_H__
#define __REVISION_NR_H__ #define __REVISION_NR_H__
#define REVISION_NR "8396" #define REVISION_NR "8408"
#endif // __REVISION_NR_H__ #endif // __REVISION_NR_H__