*Implement new LootMode system, and add some basic support in boss_sartharion.cpp. Requires database support.

--HG--
branch : trunk
This commit is contained in:
maximius
2009-10-28 16:31:19 -07:00
parent d5b8ad0080
commit f4d76b8216
10 changed files with 90 additions and 29 deletions
+15
View File
@@ -0,0 +1,15 @@
-- Currently utilized in the following tables (1 = default, 0 = disabled)
ALTER TABLE `creature_loot_template` ADD COLUMN `lootmode` SMALLINT UNSIGNED NOT NULL DEFAULT 1 BEFORE `groupid`;
ALTER TABLE `gameobject_loot_template` ADD COLUMN `lootmode` SMALLINT UNSIGNED NOT NULL DEFAULT 1 BEFORE `groupid`;
ALTER TABLE `reference_loot_template` ADD COLUMN `lootmode` SMALLINT UNSIGNED NOT NULL DEFAULT 1 BEFORE `groupid`;
-- Currently not utilized in the following tables (1 = enabled, any other value = disabled)
ALTER TABLE `fishing_loot_template` ADD COLUMN `lootmode` SMALLINT UNSIGNED NOT NULL DEFAULT 1 BEFORE `groupid`;
ALTER TABLE `disenchant_loot_template` ADD COLUMN `lootmode` SMALLINT UNSIGNED NOT NULL DEFAULT 1 BEFORE `groupid`;
ALTER TABLE `item_loot_template` ADD COLUMN `lootmode` SMALLINT UNSIGNED NOT NULL DEFAULT 1 BEFORE `groupid`;
ALTER TABLE `milling_loot_template` ADD COLUMN `lootmode` SMALLINT UNSIGNED NOT NULL DEFAULT 1 BEFORE `groupid`;
ALTER TABLE `pickpocketing_loot_template` ADD COLUMN `lootmode` SMALLINT UNSIGNED NOT NULL DEFAULT 1 BEFORE `groupid`;
ALTER TABLE `prospecting_loot_template` ADD COLUMN `lootmode` SMALLINT UNSIGNED NOT NULL DEFAULT 1 BEFORE `groupid`;
ALTER TABLE `skinning_loot_template` ADD COLUMN `lootmode` SMALLINT UNSIGNED NOT NULL DEFAULT 1 BEFORE `groupid`;
ALTER TABLE `quest_mail_loot_template` ADD COLUMN `lootmode` SMALLINT UNSIGNED NOT NULL DEFAULT 1 BEFORE `groupid`;
@@ -214,6 +214,8 @@ struct TRINITY_DLL_DECL boss_sartharionAI : public ScriptedAI
if (m_creature->HasAura(SPELL_TWILIGHT_REVENGE))
m_creature->RemoveAurasDueToSpell(SPELL_TWILIGHT_REVENGE);
m_creature->ResetLootMode();
}
void JustReachedHome()
@@ -247,6 +249,18 @@ struct TRINITY_DLL_DECL boss_sartharionAI : public ScriptedAI
DoScriptText(RAND(SAY_SARTHARION_SLAY_1,SAY_SARTHARION_SLAY_2,SAY_SARTHARION_SLAY_3), m_creature);
}
// m_creature->ResetLootMode() is called from Reset()
// AddDrakeLootMode() should only ever be called from FetchDragons(), which is called from Aggro()
void AddDrakeLootMode()
{
if (m_creature->HasLootMode(4)) // Has two Drake loot modes
m_creature->AddLootMode(8); // Add 3rd Drake loot mode
else if (m_creature->HasLootMode(2)) // Has one Drake loot mode
m_creature->AddLootMode(4); // Add 2nd Drake loot mode
else // Has no Drake loot modes
m_creature->AddLootMode(2); // Add 1st Drake loot mode
}
void FetchDragons()
{
Unit* pTene = Unit::GetUnit(*m_creature, pInstance->GetData64(DATA_TENEBRON));
@@ -258,6 +272,7 @@ struct TRINITY_DLL_DECL boss_sartharionAI : public ScriptedAI
if (pTene && pTene->isAlive() && !pTene->getVictim())
{
AddDrakeLootMode();
bCanUseWill = true;
pTene->GetMotionMaster()->MovePoint(POINT_ID_INIT, m_aTene[0].m_fX, m_aTene[0].m_fY, m_aTene[0].m_fZ);
@@ -267,6 +282,7 @@ struct TRINITY_DLL_DECL boss_sartharionAI : public ScriptedAI
if (pShad && pShad->isAlive() && !pShad->getVictim())
{
AddDrakeLootMode();
bCanUseWill = true;
pShad->GetMotionMaster()->MovePoint(POINT_ID_INIT, m_aShad[0].m_fX, m_aShad[0].m_fY, m_aShad[0].m_fZ);
@@ -276,6 +292,7 @@ struct TRINITY_DLL_DECL boss_sartharionAI : public ScriptedAI
if (pVesp && pVesp->isAlive() && !pVesp->getVictim())
{
AddDrakeLootMode();
bCanUseWill = true;
pVesp->GetMotionMaster()->MovePoint(POINT_ID_INIT, m_aVesp[0].m_fX, m_aVesp[0].m_fY, m_aVesp[0].m_fZ);
+2
View File
@@ -157,6 +157,8 @@ m_creatureInfo(NULL), m_reactState(REACT_AGGRESSIVE), m_formation(NULL)
m_SightDistance = sWorld.getConfig(CONFIG_SIGHT_MONSTER);
m_CombatDistance = 0;//MELEE_RANGE;
ResetLootMode(); // restore default loot mode
}
Creature::~Creature()
+8
View File
@@ -621,6 +621,13 @@ class TRINITY_DLL_SPEC Creature : public Unit
void SetLootRecipient (Unit* unit);
void AllLootRemovedFromCorpse();
uint16 GetLootMode() { return m_LootMode; }
bool HasLootMode(uint16 lootMode) { return m_LootMode & lootMode; }
void SetLootMode(uint16 lootMode) { m_LootMode = lootMode; }
void AddLootMode(uint16 lootMode) { m_LootMode |= lootMode; }
void RemoveLootMode(uint16 lootMode) { m_LootMode &= ~lootMode; }
void ResetLootMode() { m_LootMode = DEFAULT_LOOT_MODE; }
SpellEntry const *reachWithSpellAttack(Unit *pVictim);
SpellEntry const *reachWithSpellCure(Unit *pVictim);
@@ -778,6 +785,7 @@ class TRINITY_DLL_SPEC Creature : public Unit
CreatureInfo const* m_creatureInfo; // in heroic mode can different from ObjMgr::GetCreatureTemplate(GetEntry())
CreatureData const* m_creatureData;
uint16 m_LootMode; // bitmask, default DEFAULT_LOOT_MODE, determines what loot will be lootable
private:
//WaypointMovementGenerator vars
uint32 m_waypointID;
+2
View File
@@ -60,6 +60,8 @@ GameObject::GameObject() : WorldObject(), m_goValue(new GameObjectValue)
m_DBTableGuid = 0;
m_rotation = 0;
ResetLootMode(); // restore default loot mode
}
GameObject::~GameObject()
+9
View File
@@ -672,6 +672,13 @@ class TRINITY_DLL_SPEC GameObject : public WorldObject
LootState getLootState() const { return m_lootState; }
void SetLootState(LootState s) { m_lootState = s; }
uint16 GetLootMode() { return m_LootMode; }
bool HasLootMode(uint16 lootMode) { return m_LootMode & lootMode; }
void SetLootMode(uint16 lootMode) { m_LootMode = lootMode; }
void AddLootMode(uint16 lootMode) { m_LootMode |= lootMode; }
void RemoveLootMode(uint16 lootMode) { m_LootMode &= ~lootMode; }
void ResetLootMode() { m_LootMode = DEFAULT_LOOT_MODE; }
void AddToSkillupList(uint32 PlayerGuidLow) { m_SkillupList.push_back(PlayerGuidLow); }
bool IsInSkillupList(uint32 PlayerGuidLow) const
{
@@ -738,6 +745,8 @@ class TRINITY_DLL_SPEC GameObject : public WorldObject
GameObjectValue * const m_goValue;
uint64 m_rotation;
uint16 m_LootMode; // bitmask, default DEFAULT_LOOT_MODE, determines what loot will be lootable
private:
void SwitchDoorOrButton(bool activate, bool alternative = false);
+26 -22
View File
@@ -57,11 +57,11 @@ class LootTemplate::LootGroup // A set of loot def
bool HasQuestDrop() const; // True if group includes at least 1 quest drop entry
bool HasQuestDropForPlayer(Player const * player) const;
// The same for active quests of the player
void Process(Loot& loot) const; // Rolls an item from the group (if any) and adds the item to the loot
void Process(Loot& loot, uint16 lootMode) const; // Rolls an item from the group (if any) and adds the item to the loot
float RawTotalChance() const; // Overall chance for the group (without equal chanced items)
float TotalChance() const; // Overall chance for the group
void Verify(LootStore const& lootstore, uint32 id, uint32 group_id) const;
void Verify(LootStore const& lootstore, uint32 id, uint8 group_id) const;
void CollectLootIds(LootIdSet& set) const;
void CheckLootRefs(LootTemplateMap const& store, LootIdSet* ref_set) const;
private:
@@ -99,8 +99,8 @@ void LootStore::LoadLootTable()
sLog.outString( "%s :", GetName());
// 0 1 2 3 4 5 6 7 8
QueryResult *result = WorldDatabase.PQuery("SELECT entry, item, ChanceOrQuestChance, groupid, mincountOrRef, maxcount, lootcondition, condition_value1, condition_value2 FROM %s",GetName());
// 0 1 2 3 4 5 6 7 8 9
QueryResult *result = WorldDatabase.PQuery("SELECT entry, item, ChanceOrQuestChance, lootmode, groupid, mincountOrRef, maxcount, lootcondition, condition_value1, condition_value2 FROM %s",GetName());
if (result)
{
@@ -114,12 +114,13 @@ void LootStore::LoadLootTable()
uint32 entry = fields[0].GetUInt32();
uint32 item = fields[1].GetUInt32();
float chanceOrQuestChance = fields[2].GetFloat();
uint8 group = fields[3].GetUInt8();
int32 mincountOrRef = fields[4].GetInt32();
uint32 maxcount = fields[5].GetUInt32();
ConditionType condition = (ConditionType)fields[6].GetUInt8();
uint32 cond_value1 = fields[7].GetUInt32();
uint32 cond_value2 = fields[8].GetUInt32();
uint16 lootmode = fields[3].GetUInt16();
uint8 group = fields[4].GetUInt8();
int32 mincountOrRef = fields[5].GetInt32();
uint32 maxcount = fields[6].GetUInt32();
ConditionType condition = (ConditionType)fields[7].GetUInt8();
uint32 cond_value1 = fields[8].GetUInt32();
uint32 cond_value2 = fields[9].GetUInt32();
if(maxcount > std::numeric_limits<uint8>::max())
{
@@ -136,7 +137,7 @@ void LootStore::LoadLootTable()
// (condition + cond_value1/2) are converted into single conditionId
uint16 conditionId = objmgr.GetConditionId(condition, cond_value1, cond_value2);
LootStoreItem storeitem = LootStoreItem(item, chanceOrQuestChance, group, conditionId, mincountOrRef, maxcount);
LootStoreItem storeitem = LootStoreItem(item, chanceOrQuestChance, lootmode, group, conditionId, mincountOrRef, maxcount);
if (!storeitem.IsValid(*this,entry)) // Validity checks
continue;
@@ -387,7 +388,7 @@ void Loot::AddItem(LootStoreItem const & item)
}
// Calls processor of corresponding LootTemplate (which handles everything including references)
void Loot::FillLoot(uint32 loot_id, LootStore const& store, Player* loot_owner, bool personal)
void Loot::FillLoot(uint32 loot_id, LootStore const& store, Player* loot_owner, bool personal, uint16 lootMode /*= DEFAULT_LOOT_MODE*/)
{
// Must be provided
if(!loot_owner)
@@ -404,7 +405,7 @@ void Loot::FillLoot(uint32 loot_id, LootStore const& store, Player* loot_owner,
items.reserve(MAX_NR_LOOT_ITEMS);
quest_items.reserve(MAX_NR_QUEST_ITEMS);
tab->Process(*this, store,store.IsRatesAllowed ()); // Processing is done there, callback via Loot::AddItem()
tab->Process(*this, store, store.IsRatesAllowed(), lootMode); // Processing is done there, callback via Loot::AddItem()
// Setting access rights for group loot case
Group * pGroup=loot_owner->GetGroup();
@@ -857,10 +858,10 @@ bool LootTemplate::LootGroup::HasQuestDropForPlayer(Player const * player) const
}
// Rolls an item from the group (if any takes its chance) and adds the item to the loot
void LootTemplate::LootGroup::Process(Loot& loot) const
void LootTemplate::LootGroup::Process(Loot& loot, uint16 lootMode) const
{
LootStoreItem const * item = Roll();
if (item != NULL)
if (item != NULL && item->lootmode & lootMode) // only add this item if roll succeeds and the mode matches
loot.AddItem(*item);
}
@@ -887,7 +888,7 @@ float LootTemplate::LootGroup::TotalChance() const
return result;
}
void LootTemplate::LootGroup::Verify(LootStore const& lootstore, uint32 id, uint32 group_id) const
void LootTemplate::LootGroup::Verify(LootStore const& lootstore, uint32 id, uint8 group_id) const
{
float chance = RawTotalChance();
if (chance > 101.0f) // TODO: replace with 100% when DBs will be ready
@@ -944,20 +945,23 @@ void LootTemplate::AddEntry(LootStoreItem& item)
}
// Rolls for every item in the template and adds the rolled items the the loot
void LootTemplate::Process(Loot& loot, LootStore const& store, bool rate, uint8 groupId) const
void LootTemplate::Process(Loot& loot, LootStore const& store, bool rate, uint16 lootMode, uint8 groupId) const
{
if (groupId) // Group reference uses own processing of the group
{
if (groupId > Groups.size())
return; // Error message already printed at loading stage
Groups[groupId-1].Process(loot);
Groups[groupId-1].Process(loot, lootMode);
return;
}
// Rolling non-grouped items
for (LootStoreItemList::const_iterator i = Entries.begin() ; i != Entries.end() ; ++i )
{
if (i->lootmode &~ lootMode) // Do not add if mode mismatch
continue;
if (!i->Roll(rate))
continue; // Bad luck for the entry
@@ -968,16 +972,16 @@ void LootTemplate::Process(Loot& loot, LootStore const& store, bool rate, uint8
if(!Referenced)
continue; // Error message already printed at loading stage
for (uint32 loop=0; loop < i->maxcount; ++loop )// Ref multiplicator
Referenced->Process(loot, store, rate, i->group);
for (uint32 loop=0; loop < i->maxcount; ++loop) // Ref multiplicator
Referenced->Process(loot, store, rate, lootMode, i->group);
}
else // Plain entries (not a reference, not grouped)
loot.AddItem(*i); // Chance is already checked, just add
}
// Now processing groups
for (LootGroups::const_iterator i = Groups.begin( ) ; i != Groups.end( ) ; ++i )
i->Process(loot);
for (LootGroups::const_iterator i = Groups.begin(); i != Groups.end(); ++i)
i->Process(loot, lootMode);
}
// True if template includes at least 1 quest drop entry
+6 -5
View File
@@ -81,14 +81,15 @@ struct LootStoreItem
float chance; // always positive, chance to drop for both quest and non-quest items, chance to be used for refs
int32 mincountOrRef; // mincount for drop items (positive) or minus referenced TemplateleId (negative)
uint8 group :7;
uint16 lootmode;
bool needs_quest :1; // quest drop (negative ChanceOrQuestChance in DB)
uint8 maxcount :8; // max drop count for the item (mincountOrRef positive) or Ref multiplicator (mincountOrRef negative)
uint16 conditionId :16; // additional loot condition Id
// Constructor, converting ChanceOrQuestChance -> (chance, needs_quest)
// displayid is filled in IsValid() which must be called after
LootStoreItem(uint32 _itemid, float _chanceOrQuestChance, int8 _group, uint8 _conditionId, int32 _mincountOrRef, uint8 _maxcount)
: itemid(_itemid), chance(fabs(_chanceOrQuestChance)), mincountOrRef(_mincountOrRef),
LootStoreItem(uint32 _itemid, float _chanceOrQuestChance, uint8 _group, uint16 _lootmode, uint8 _conditionId, int32 _mincountOrRef, uint8 _maxcount)
: itemid(_itemid), chance(fabs(_chanceOrQuestChance)), mincountOrRef(_mincountOrRef), lootmode(_lootmode),
group(_group), needs_quest(_chanceOrQuestChance < 0), maxcount(_maxcount), conditionId(_conditionId)
{}
@@ -183,12 +184,12 @@ class LootTemplate
// Adds an entry to the group (at loading stage)
void AddEntry(LootStoreItem& item);
// Rolls for every item in the template and adds the rolled items the the loot
void Process(Loot& loot, LootStore const& store, bool rate, uint8 GroupId = 0) const;
void Process(Loot& loot, LootStore const& store, bool rate, uint16 lootMode, uint8 groupId = 0) const;
// True if template includes at least 1 quest drop entry
bool HasQuestDrop(LootTemplateMap const& store, uint8 GroupId = 0) const;
// True if template includes at least 1 quest drop for an active quest of the player
bool HasQuestDropForPlayer(LootTemplateMap const& store, Player const * player, uint8 GroupId = 0) const;
bool HasQuestDropForPlayer(LootTemplateMap const& store, Player const * player, uint8 groupId = 0) const;
// Checks integrity of the template
void Verify(LootStore const& store, uint32 Id) const;
@@ -285,7 +286,7 @@ struct Loot
void RemoveLooter(uint64 GUID) { PlayersLooting.erase(GUID); }
void generateMoneyLoot(uint32 minAmount, uint32 maxAmount);
void FillLoot(uint32 loot_id, LootStore const& store, Player* loot_owner, bool personal);
void FillLoot(uint32 loot_id, LootStore const& store, Player* loot_owner, bool personal, uint16 lootMode = DEFAULT_LOOT_MODE);
// Inserts the item into the loot (called by LootTemplate processors)
void AddItem(LootStoreItem const & item);
+2 -2
View File
@@ -7856,7 +7856,7 @@ void Player::SendLoot(uint64 guid, LootType loot_type)
{
sLog.outDebug(" if(lootid)");
loot->clear();
loot->FillLoot(lootid, LootTemplates_Gameobject, this, false);
loot->FillLoot(lootid, LootTemplates_Gameobject, this, false, go->GetLootMode());
}
if (loot_type == LOOT_FISHING)
@@ -7985,7 +7985,7 @@ void Player::SendLoot(uint64 guid, LootType loot_type)
loot->clear();
if (uint32 lootid = creature->GetCreatureInfo()->lootid)
loot->FillLoot(lootid, LootTemplates_Creature, recipient, false);
loot->FillLoot(lootid, LootTemplates_Creature, recipient, false, creature->GetLootMode());
loot->generateMoneyLoot(creature->GetCreatureInfo()->mingold,creature->GetCreatureInfo()->maxgold);
+3
View File
@@ -24,6 +24,9 @@
#include "Platform/Define.h"
#include <cassert>
// default loot mode for creatures and gameobjects
#define DEFAULT_LOOT_MODE 1
enum Gender
{
GENDER_MALE = 0,