mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-27 23:56:25 +00:00
feat(Core/Loot): Implement player_loot_template (#9198)
* Also fix AV player loot
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
INSERT INTO `version_db_world` (`sql_rev`) VALUES ('1636980654557070200');
|
||||
|
||||
DROP TABLE IF EXISTS `player_loot_template`;
|
||||
CREATE TABLE IF NOT EXISTS `player_loot_template` (
|
||||
`Entry` MEDIUMINT UNSIGNED NOT NULL DEFAULT 0,
|
||||
`Item` MEDIUMINT UNSIGNED NOT NULL DEFAULT 0,
|
||||
`Reference` MEDIUMINT NOT NULL DEFAULT 0,
|
||||
`Chance` FLOAT NOT NULL DEFAULT 100,
|
||||
`QuestRequired` TINYINT NOT NULL DEFAULT 0,
|
||||
`LootMode` SMALLINT UNSIGNED NOT NULL DEFAULT 1,
|
||||
`GroupId` TINYINT UNSIGNED NOT NULL DEFAULT 0,
|
||||
`MinCount` TINYINT UNSIGNED NOT NULL DEFAULT 1,
|
||||
`MaxCount` TINYINT UNSIGNED NOT NULL DEFAULT 1,
|
||||
`Comment` TEXT DEFAULT NULL,
|
||||
PRIMARY KEY (`Entry`,`Item`)
|
||||
) ENGINE=MYISAM DEFAULT CHARSET=utf8mb4 COMMENT='Loot System';
|
||||
|
||||
DELETE FROM `player_loot_template` WHERE `Entry` IN (1, 0);
|
||||
INSERT INTO `player_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES
|
||||
(1, 17306, 0, 50, 0, 1, 0, 2, 5, 'Alterac Valley - Alliance - Stormpike Soldier\s Blood'),
|
||||
(1, 17326, 0, 30, 0, 1, 0, 1, 1, 'Alterac Valley - Alliance - Stormpike Soldier\s Flesh'),
|
||||
(1, 17327, 0, 20, 0, 1, 0, 1, 1, 'Alterac Valley - Alliance - Stormpike Lieutenant\s Flesh'),
|
||||
(1, 17328, 0, 10, 0, 1, 0, 1, 1, 'Alterac Valley - Alliance - Stormpike Commander\'s Flesh'),
|
||||
(1, 17422, 0, 85, 0, 1, 0, 15, 22, 'Alterac Valley - Alliance - Armor Scrapts'),
|
||||
(1, 18228, 0, 1, 0, 1, 0, 1, 1, 'Alterac Valley - Alliance - Autographed Picture of Foror & Tigule'),
|
||||
(0, 17423, 0, 50, 0, 1, 0, 2, 5, 'Alterac Valley - Horde - Storm Crystal'), -- Horde
|
||||
(0, 17502, 0, 30, 0, 1, 0, 1, 1, 'Alterac Valley - Horde - Frostwolf Soldier\s Medal'),
|
||||
(0, 17503, 0, 20, 0, 1, 0, 1, 1, 'Alterac Valley - Horde - Frostwolf Lieutenant\s Medal'),
|
||||
(0, 17504, 0, 10, 0, 1, 0, 1, 1, 'Alterac Valley - Horde - Frostwolf Commander\'s Medal'),
|
||||
(0, 17422, 0, 85, 0, 1, 0, 15, 22, 'Alterac Valley - Horde - Armor Scraps'),
|
||||
(0, 18228, 0, 1, 0, 1, 0, 1, 1, 'Alterac Valley - Horde - Autographed Picture of Foror & Tigule');
|
||||
|
||||
DELETE FROM `conditions` WHERE (`SourceTypeOrReferenceId` = 28) AND (`SourceGroup` IN (0, 1)) AND (`SourceEntry` IN (17306, 17326, 17327, 17328, 17422, 18228, 17423, 17502, 17503, 17504));
|
||||
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
|
||||
(28, 1, 17306, 0, 0, 22, 0, 30, 0, 0, 0, 0, 0, '', 'Stormpike Soldier Blood Hat only drops inside Alterac Valley Battleground'),
|
||||
(28, 1, 17326, 0, 0, 22, 0, 30, 0, 0, 0, 0, 0, '', 'Stormpike Soldier Flesh only drops inside Alterac Valley Battleground'),
|
||||
(28, 1, 17327, 0, 0, 22, 0, 30, 0, 0, 0, 0, 0, '', 'Stormpike Lieutenant Flesh only drops inside Alterac Valley Battleground'),
|
||||
(28, 1, 17328, 0, 0, 22, 0, 30, 0, 0, 0, 0, 0, '', 'Stormpike Commander Flesh only drops inside Alterac Valley Battleground'),
|
||||
(28, 1, 17422, 0, 0, 22, 0, 30, 0, 0, 0, 0, 0, '', 'Armor Scrap only drops inside Alterac Valley Battleground'),
|
||||
(28, 1, 18228, 0, 0, 22, 0, 30, 0, 0, 0, 0, 0, '', 'Autographed Picture of Foror & Tigule only drops inside Alterac Valley Battleground'),
|
||||
(28, 0, 17423, 0, 0, 22, 0, 30, 0, 0, 0, 0, 0, '', 'Storm Crystal only drops inside Alterac Valley Battleground'),
|
||||
(28, 0, 17502, 0, 0, 22, 0, 30, 0, 0, 0, 0, 0, '', 'Frostwolf Soldier\s Medal only drops inside Alterac Valley Battleground'),
|
||||
(28, 0, 17503, 0, 0, 22, 0, 30, 0, 0, 0, 0, 0, '', 'Frostwolf Lieutenant\s Medal only drops inside Alterac Valley Battleground'),
|
||||
(28, 0, 17504, 0, 0, 22, 0, 30, 0, 0, 0, 0, 0, '', 'Frostwolf Commander\'s Medal only drops inside Alterac Valley Battleground'),
|
||||
(28, 0, 17422, 0, 0, 22, 0, 30, 0, 0, 0, 0, 0, '', 'Armor Scrap only drops inside Alterac Valley Battleground'),
|
||||
(28, 0, 18228, 0, 0, 22, 0, 30, 0, 0, 0, 0, 0, '', 'Autographed Picture of Foror & Tigule only drops inside Alterac Valley Battleground');
|
||||
|
||||
DELETE FROM `command` WHERE `name` IN ('reload player_loot_template');
|
||||
INSERT INTO `command` (`name`, `security`, `help`) VALUES
|
||||
('reload player_loot_template', 3, 'Syntax: .reload player_loot_template\nReload player_loot_template table.');
|
||||
@@ -763,7 +763,7 @@ bool ConditionMgr::CanHaveSourceGroupSet(ConditionSourceType sourceType) const
|
||||
{
|
||||
return (sourceType == CONDITION_SOURCE_TYPE_CREATURE_LOOT_TEMPLATE || sourceType == CONDITION_SOURCE_TYPE_DISENCHANT_LOOT_TEMPLATE || sourceType == CONDITION_SOURCE_TYPE_FISHING_LOOT_TEMPLATE || sourceType == CONDITION_SOURCE_TYPE_GAMEOBJECT_LOOT_TEMPLATE || sourceType == CONDITION_SOURCE_TYPE_ITEM_LOOT_TEMPLATE || sourceType == CONDITION_SOURCE_TYPE_MAIL_LOOT_TEMPLATE || sourceType == CONDITION_SOURCE_TYPE_MILLING_LOOT_TEMPLATE ||
|
||||
sourceType == CONDITION_SOURCE_TYPE_PICKPOCKETING_LOOT_TEMPLATE || sourceType == CONDITION_SOURCE_TYPE_PROSPECTING_LOOT_TEMPLATE || sourceType == CONDITION_SOURCE_TYPE_REFERENCE_LOOT_TEMPLATE || sourceType == CONDITION_SOURCE_TYPE_SKINNING_LOOT_TEMPLATE || sourceType == CONDITION_SOURCE_TYPE_SPELL_LOOT_TEMPLATE || sourceType == CONDITION_SOURCE_TYPE_GOSSIP_MENU || sourceType == CONDITION_SOURCE_TYPE_GOSSIP_MENU_OPTION || sourceType == CONDITION_SOURCE_TYPE_VEHICLE_SPELL ||
|
||||
sourceType == CONDITION_SOURCE_TYPE_SPELL_IMPLICIT_TARGET || sourceType == CONDITION_SOURCE_TYPE_SPELL_CLICK_EVENT || sourceType == CONDITION_SOURCE_TYPE_SMART_EVENT || sourceType == CONDITION_SOURCE_TYPE_NPC_VENDOR);
|
||||
sourceType == CONDITION_SOURCE_TYPE_SPELL_IMPLICIT_TARGET || sourceType == CONDITION_SOURCE_TYPE_SPELL_CLICK_EVENT || sourceType == CONDITION_SOURCE_TYPE_SMART_EVENT || sourceType == CONDITION_SOURCE_TYPE_NPC_VENDOR || sourceType == CONDITION_SOURCE_TYPE_PLAYER_LOOT_TEMPLATE);
|
||||
}
|
||||
|
||||
bool ConditionMgr::CanHaveSourceIdSet(ConditionSourceType sourceType) const
|
||||
@@ -876,6 +876,7 @@ void ConditionMgr::LoadConditions(bool isReload)
|
||||
LootTemplates_Disenchant.ResetConditions();
|
||||
LootTemplates_Prospecting.ResetConditions();
|
||||
LootTemplates_Spell.ResetConditions();
|
||||
LootTemplates_Player.ResetConditions();
|
||||
|
||||
LOG_INFO("server.loading", "Re-Loading `gossip_menu` Table for Conditions!");
|
||||
sObjectMgr->LoadGossipMenu();
|
||||
@@ -1003,7 +1004,7 @@ void ConditionMgr::LoadConditions(bool isReload)
|
||||
cond->ErrorTextId = 0;
|
||||
}
|
||||
|
||||
if (cond->SourceGroup)
|
||||
if (cond->SourceGroup || cond->SourceType == CONDITION_SOURCE_TYPE_PLAYER_LOOT_TEMPLATE)
|
||||
{
|
||||
bool valid = false;
|
||||
// handle grouped conditions
|
||||
@@ -1084,6 +1085,11 @@ void ConditionMgr::LoadConditions(bool isReload)
|
||||
++count;
|
||||
continue;
|
||||
}
|
||||
case CONDITION_SOURCE_TYPE_PLAYER_LOOT_TEMPLATE:
|
||||
{
|
||||
valid = addToLootTemplate(cond, LootTemplates_Player.GetLootForConditionFill(cond->SourceGroup));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -1615,6 +1621,23 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond)
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CONDITION_SOURCE_TYPE_PLAYER_LOOT_TEMPLATE:
|
||||
{
|
||||
if (!LootTemplates_Player.HaveLootFor(cond->SourceGroup))
|
||||
{
|
||||
LOG_ERROR("sql.sql", "SourceGroup %u in `condition` table, does not exist in `player_loot_template`, ignoring.", cond->SourceGroup);
|
||||
return false;
|
||||
}
|
||||
|
||||
LootTemplate* loot = LootTemplates_Player.GetLootForConditionFill(cond->SourceGroup);
|
||||
ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry);
|
||||
if (!pItemProto && !loot->isReference(cond->SourceEntry))
|
||||
{
|
||||
LOG_ERROR("sql.sql", "SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->SourceType, cond->SourceEntry);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CONDITION_SOURCE_TYPE_GOSSIP_MENU:
|
||||
case CONDITION_SOURCE_TYPE_GOSSIP_MENU_OPTION:
|
||||
case CONDITION_SOURCE_TYPE_SMART_EVENT:
|
||||
|
||||
@@ -147,7 +147,8 @@ enum ConditionSourceType
|
||||
CONDITION_SOURCE_TYPE_TERRAIN_SWAP = 25, // don't use on 3.3.5a
|
||||
CONDITION_SOURCE_TYPE_PHASE = 26, // don't use on 3.3.5a
|
||||
CONDITION_SOURCE_TYPE_GRAVEYARD = 27, // don't use on 3.3.5a
|
||||
CONDITION_SOURCE_TYPE_MAX = 28 // placeholder
|
||||
CONDITION_SOURCE_TYPE_PLAYER_LOOT_TEMPLATE = 28,
|
||||
CONDITION_SOURCE_TYPE_MAX = 29 // placeholder
|
||||
};
|
||||
|
||||
enum RelationType
|
||||
|
||||
@@ -7706,15 +7706,7 @@ void Player::SendLoot(ObjectGuid guid, LootType loot_type)
|
||||
uint32 pLevel = bones->loot.gold;
|
||||
bones->loot.clear();
|
||||
|
||||
// Xinef: For AV Achievement
|
||||
if (Battleground* bg = GetBattleground())
|
||||
{
|
||||
if (bg->GetBgTypeID(true) == BATTLEGROUND_AV)
|
||||
loot->FillLoot(1, LootTemplates_Creature, this, true);
|
||||
}
|
||||
// Xinef: For wintergrasp Quests
|
||||
else if (GetZoneId() == AREA_WINTERGRASP)
|
||||
loot->FillLoot(1, LootTemplates_Creature, this, true);
|
||||
loot->FillLoot(GetTeamId(), LootTemplates_Player, this, true);
|
||||
|
||||
// It may need a better formula
|
||||
// Now it works like this: lvl10: ~6copper, lvl70: ~9silver
|
||||
|
||||
@@ -51,6 +51,7 @@ LootStore LootTemplates_Prospecting("prospecting_loot_template", "item entry
|
||||
LootStore LootTemplates_Reference("reference_loot_template", "reference id", false);
|
||||
LootStore LootTemplates_Skinning("skinning_loot_template", "creature skinning id", true);
|
||||
LootStore LootTemplates_Spell("spell_loot_template", "spell id (random item creating)", false);
|
||||
LootStore LootTemplates_Player("player_loot_template", "team id", true);
|
||||
|
||||
// Selects invalid loot items to be removed from group possible entries (before rolling)
|
||||
struct LootGroupInvalidSelector : public Acore::unary_function<LootStoreItem*, bool>
|
||||
@@ -2252,6 +2253,27 @@ void LoadLootTemplates_Spell()
|
||||
LOG_INFO("server.loading", " ");
|
||||
}
|
||||
|
||||
void LoadLootTemplates_Player()
|
||||
{
|
||||
LOG_INFO("server.loading", "Loading player loot templates...");
|
||||
|
||||
uint32 oldMSTime = getMSTime();
|
||||
|
||||
LootIdSet lootIdSet;
|
||||
uint32 count = LootTemplates_Player.LoadAndCollectLootIds(lootIdSet);
|
||||
|
||||
if (count)
|
||||
{
|
||||
LOG_INFO("server.loading", ">> Loaded %u player loot templates in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR("sql.sql", ">> Loaded 0 player loot templates. DB table `player_loot_template` is empty");
|
||||
}
|
||||
|
||||
LOG_INFO("server.loading", " ");
|
||||
}
|
||||
|
||||
void LoadLootTemplates_Reference()
|
||||
{
|
||||
LOG_INFO("server.loading", "Loading reference loot templates...");
|
||||
|
||||
@@ -421,6 +421,7 @@ extern LootStore LootTemplates_Skinning;
|
||||
extern LootStore LootTemplates_Disenchant;
|
||||
extern LootStore LootTemplates_Prospecting;
|
||||
extern LootStore LootTemplates_Spell;
|
||||
extern LootStore LootTemplates_Player;
|
||||
|
||||
void LoadLootTemplates_Creature();
|
||||
void LoadLootTemplates_Fishing();
|
||||
@@ -436,6 +437,8 @@ void LoadLootTemplates_Prospecting();
|
||||
void LoadLootTemplates_Spell();
|
||||
void LoadLootTemplates_Reference();
|
||||
|
||||
void LoadLootTemplates_Player();
|
||||
|
||||
inline void LoadLootTables()
|
||||
{
|
||||
LoadLootTemplates_Creature();
|
||||
@@ -451,6 +454,8 @@ inline void LoadLootTables()
|
||||
LoadLootTemplates_Spell();
|
||||
|
||||
LoadLootTemplates_Reference();
|
||||
|
||||
LoadLootTemplates_Player();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -156,6 +156,7 @@ public:
|
||||
{ "spell_target_position", HandleReloadSpellTargetPositionCommand, SEC_ADMINISTRATOR, Console::Yes },
|
||||
{ "spell_threats", HandleReloadSpellThreatsCommand, SEC_ADMINISTRATOR, Console::Yes },
|
||||
{ "spell_group_stack_rules", HandleReloadSpellGroupStackRulesCommand, SEC_ADMINISTRATOR, Console::Yes },
|
||||
{ "player_loot_template", HandleReloadLootTemplatesPlayerCommand, SEC_ADMINISTRATOR, Console::Yes },
|
||||
{ "acore_string", HandleReloadAcoreStringCommand, SEC_ADMINISTRATOR, Console::Yes },
|
||||
{ "warden_action", HandleReloadWardenactionCommand, SEC_ADMINISTRATOR, Console::Yes },
|
||||
{ "waypoint_scripts", HandleReloadWpScriptsCommand, SEC_ADMINISTRATOR, Console::Yes },
|
||||
@@ -658,6 +659,16 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool HandleReloadLootTemplatesPlayerCommand(ChatHandler* handler)
|
||||
{
|
||||
LOG_INFO("server.loading", "Re-Loading Loot Tables... (`player_loot_template`)");
|
||||
LoadLootTemplates_Player();
|
||||
LootTemplates_Player.CheckLootRefs();
|
||||
handler->SendGlobalGMSysMessage("DB table `player_loot_template` reloaded.");
|
||||
sConditionMgr->LoadConditions(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool HandleReloadAcoreStringCommand(ChatHandler* handler)
|
||||
{
|
||||
LOG_INFO("server.loading", "Re-Loading acore_string Table!");
|
||||
|
||||
Reference in New Issue
Block a user