feat(Core/Loot): Implement player_loot_template (#9198)

* Also fix AV player loot
This commit is contained in:
Skjalf
2021-11-17 08:07:21 -03:00
committed by GitHub
parent 0c5b307e7d
commit 39425e0c1f
7 changed files with 116 additions and 12 deletions

View File

@@ -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.');

View File

@@ -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:

View File

@@ -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

View File

@@ -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

View File

@@ -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...");

View File

@@ -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

View File

@@ -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!");