aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authormegamage <none@none>2008-11-28 11:38:28 -0600
committermegamage <none@none>2008-11-28 11:38:28 -0600
commite26beb36c2073bb35151aa0cfee7e95f1b5a3901 (patch)
tree0adc111c86d8a75c406889c231a3b6922ff9933c /src
parent1d6e33add4f41ba07d5bd9115b1fe8c52ebb6d21 (diff)
*Update to Mangos 6856. Source: Mangos.
--HG-- branch : trunk
Diffstat (limited to 'src')
-rw-r--r--src/framework/Utilities/LinkedList.h30
-rw-r--r--src/framework/Utilities/LinkedReference/Reference.h12
-rw-r--r--src/game/Map.cpp37
-rw-r--r--src/game/Map.h1
-rw-r--r--src/game/MapReference.h102
-rw-r--r--src/game/MovementHandler.cpp15
-rw-r--r--src/game/ObjectMgr.cpp5
-rw-r--r--src/game/Pet.cpp2
-rw-r--r--src/game/PetHandler.cpp5
-rw-r--r--src/game/Player.cpp103
-rw-r--r--src/game/Player.h1
-rw-r--r--src/game/SpellEffects.cpp96
-rw-r--r--src/shared/Database/DBCStores.cpp3
-rw-r--r--src/shared/Database/DBCStores.h1
-rw-r--r--src/shared/Database/DBCStructure.h15
-rw-r--r--src/shared/Database/DBCfmt.cpp3
16 files changed, 270 insertions, 161 deletions
diff --git a/src/framework/Utilities/LinkedList.h b/src/framework/Utilities/LinkedList.h
index fe4d1b7dd8d..3f9c99b31ff 100644
--- a/src/framework/Utilities/LinkedList.h
+++ b/src/framework/Utilities/LinkedList.h
@@ -46,6 +46,11 @@ class LinkedListElement
LinkedListElement * prev() { return hasPrev() ? iPrev : NULL; }
LinkedListElement const* prev() const { return hasPrev() ? iPrev : NULL; }
+ LinkedListElement * nocheck_next() { return iNext; }
+ LinkedListElement const* nocheck_next() const { return iNext; }
+ LinkedListElement * nocheck_prev() { return iPrev; }
+ LinkedListElement const* nocheck_prev() const { return iPrev; }
+
void delink()
{
if(isInList())
@@ -136,7 +141,10 @@ class LinkedListHead
typedef ptrdiff_t difference_type;
typedef ptrdiff_t distance_type;
typedef _Ty* pointer;
+ typedef _Ty const* const_pointer;
typedef _Ty& reference;
+ typedef _Ty const & const_reference;
+
Iterator() : _Ptr(0)
{ // construct with null node pointer
@@ -146,6 +154,17 @@ class LinkedListHead
{ // construct with node pointer _Pnode
}
+ Iterator& operator=(Iterator const &_Right)
+ {
+ return (*this) = _Right._Ptr;
+ }
+
+ Iterator& operator=(const_pointer const &_Right)
+ {
+ _Ptr = (pointer)_Right;
+ return (*this);
+ }
+
reference operator*()
{ // return designated value
return *_Ptr;
@@ -202,6 +221,17 @@ class LinkedListHead
return (!(*this == _Right));
}
+ bool operator==(const_reference _Right) const
+ { // test for reference equality
+ return (_Ptr == &_Right);
+ }
+
+ bool operator!=(const_reference _Right) const
+ { // test for reference equality
+ return (_Ptr != &_Right);
+ }
+
+
pointer _Mynode()
{ // return node pointer
return (_Ptr);
diff --git a/src/framework/Utilities/LinkedReference/Reference.h b/src/framework/Utilities/LinkedReference/Reference.h
index ca837c81f91..bce0e0f387c 100644
--- a/src/framework/Utilities/LinkedReference/Reference.h
+++ b/src/framework/Utilities/LinkedReference/Reference.h
@@ -73,9 +73,15 @@ template <class TO, class FROM> class Reference : public LinkedListElement
return iRefTo != NULL;
}
- Reference<TO,FROM>* next() { return((Reference<TO,FROM>*)LinkedListElement::next()); }
- Reference<TO,FROM>const* next() const { return((Reference<TO,FROM> const*)LinkedListElement::next()); }
- Reference<TO,FROM>* prev() { return((Reference<TO,FROM>*)LinkedListElement::prev()); }
+ Reference<TO,FROM> * next() { return((Reference<TO,FROM> *) LinkedListElement::next()); }
+ Reference<TO,FROM> const * next() const { return((Reference<TO,FROM> const *) LinkedListElement::next()); }
+ Reference<TO,FROM> * prev() { return((Reference<TO,FROM> *) LinkedListElement::prev()); }
+ Reference<TO,FROM> const * prev() const { return((Reference<TO,FROM> const *) LinkedListElement::prev()); }
+
+ Reference<TO,FROM> * nocheck_next() { return((Reference<TO,FROM> *) LinkedListElement::nocheck_next()); }
+ Reference<TO,FROM> const * nocheck_next() const { return((Reference<TO,FROM> const *) LinkedListElement::nocheck_next()); }
+ Reference<TO,FROM> * nocheck_prev() { return((Reference<TO,FROM> *) LinkedListElement::nocheck_prev()); }
+ Reference<TO,FROM> const * nocheck_prev() const { return((Reference<TO,FROM> const *) LinkedListElement::nocheck_prev()); }
inline TO* operator ->() const { return iRefTo; }
inline TO* getTarget() const { return iRefTo; }
diff --git a/src/game/Map.cpp b/src/game/Map.cpp
index 246af3792fb..b1f22a63e78 100644
--- a/src/game/Map.cpp
+++ b/src/game/Map.cpp
@@ -641,22 +641,18 @@ void Map::Update(const uint32 &t_diff)
{
resetMarkedCells();
- // update cells around players
- /*for(MapRefManager::iterator iter = m_mapRefManager.begin(); iter != m_mapRefManager.end(); ++iter)
- {
- Player* plr = iter->getSource();
- if(plr->IsInWorld())
- UpdateActiveCells(plr->GetPositionX(), plr->GetPositionY(), t_diff);
- }*/
-
- // update cells around active objects
- // clone the active object list, because update might remove from it
- std::set<WorldObject *> activeObjects(i_activeObjects);
+ //TODO: is there a better way to update activeobjects?
+ std::vector<WorldObject*> activeObjects;
for(MapRefManager::iterator iter = m_mapRefManager.begin(); iter != m_mapRefManager.end(); ++iter)
{
Player* plr = iter->getSource();
if(plr->IsInWorld())
- activeObjects.insert(plr);
+ activeObjects.push_back(plr);
+ }
+ for(std::set<WorldObject *>::iterator iter = i_activeObjects.begin(); iter != i_activeObjects.end(); ++iter)
+ {
+ if((*iter)->IsInWorld())
+ activeObjects.push_back(*iter);
}
Trinity::ObjectUpdater updater(t_diff);
@@ -665,11 +661,8 @@ void Map::Update(const uint32 &t_diff)
// for pets
TypeContainerVisitor<Trinity::ObjectUpdater, WorldTypeMapContainer > world_object_update(updater);
- for(std::set<WorldObject *>::iterator iter = activeObjects.begin(); iter != activeObjects.end(); ++iter)
+ for(std::vector<WorldObject*>::iterator iter = activeObjects.begin(); iter != activeObjects.end(); ++iter)
{
- if(!(*iter)->IsInWorld())
- continue;
-
CellPair standing_cell(Trinity::ComputeCellPair((*iter)->GetPositionX(), (*iter)->GetPositionY()));
// Check for correctness of standing_cell, it also avoids problems with update_cell
@@ -723,6 +716,13 @@ void Map::Update(const uint32 &t_diff)
void Map::Remove(Player *player, bool remove)
{
+ // this may be called during Map::Update
+ // after decrement+unlink, ++m_mapRefIter will continue correctly
+ // when the first element of the list is being removed
+ // nocheck_prev will return the padding element of the RefManager
+ // instead of NULL in the case of prev
+ if(m_mapRefIter == player->GetMapRef())
+ m_mapRefIter = m_mapRefIter->nocheck_prev();
player->GetMapRef().unlink();
CellPair p = Trinity::ComputeCellPair(player->GetPositionX(), player->GetPositionY());
if(p.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || p.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP)
@@ -1754,6 +1754,8 @@ bool InstanceMap::Add(Player *player)
}
if(i_data) i_data->OnPlayerEnter(player);
+ // for normal instances cancel the reset schedule when the
+ // first player enters (no players yet)
SetResetSchedule(false);
player->SendInitWorldStates();
@@ -1780,11 +1782,12 @@ void InstanceMap::Update(const uint32& t_diff)
void InstanceMap::Remove(Player *player, bool remove)
{
sLog.outDetail("MAP: Removing player '%s' from instance '%u' of map '%s' before relocating to other map", player->GetName(), GetInstanceId(), GetMapName());
- SetResetSchedule(true);
//if last player set unload timer
if(!m_unloadTimer && m_mapRefManager.getSize() == 1)
m_unloadTimer = m_unloadWhenEmpty ? MIN_UNLOAD_DELAY : std::max(sWorld.getConfig(CONFIG_INSTANCE_UNLOAD_DELAY), (uint32)MIN_UNLOAD_DELAY);
Map::Remove(player, remove);
+ // for normal instances schedule the reset after all players have left
+ SetResetSchedule(true);
}
Creature * Map::GetCreatureInMap(uint64 guid)
diff --git a/src/game/Map.h b/src/game/Map.h
index cd476f5e3c6..5f2212e53a7 100644
--- a/src/game/Map.h
+++ b/src/game/Map.h
@@ -302,6 +302,7 @@ class TRINITY_DLL_SPEC Map : public GridRefManager<NGridType>, public Trinity::O
uint32 m_unloadTimer;
MapRefManager m_mapRefManager;
+ MapRefManager::iterator m_mapRefIter;
private:
typedef GridReadGuard ReadGuard;
typedef GridWriteGuard WriteGuard;
diff --git a/src/game/MapReference.h b/src/game/MapReference.h
index b41796ea91b..5300d1aa4a7 100644
--- a/src/game/MapReference.h
+++ b/src/game/MapReference.h
@@ -1,50 +1,52 @@
-/*
- * Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef _MAPREFERENCE_H
-#define _MAPREFERENCE_H
-
-#include "Utilities/LinkedReference/Reference.h"
-#include "Map.h"
-
-class TRINITY_DLL_SPEC MapReference : public Reference<Map, Player>
-{
- protected:
- void targetObjectBuildLink()
- {
- // called from link()
- getTarget()->m_mapRefManager.insertFirst(this);
- getTarget()->m_mapRefManager.incSize();
- }
- void targetObjectDestroyLink()
- {
- // called from unlink()
- if(isValid()) getTarget()->m_mapRefManager.decSize();
- }
- void sourceObjectDestroyLink()
- {
- // called from invalidate()
- getTarget()->m_mapRefManager.decSize();
- }
- public:
- MapReference() : Reference<Map, Player>() {}
- ~MapReference() { unlink(); }
- MapReference *next() { return (MapReference*)Reference<Map, Player>::next(); }
- MapReference const *next() const { return (MapReference const*)Reference<Map, Player>::next(); }
-};
-#endif
+/*
+ * Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _MAPREFERENCE_H
+#define _MAPREFERENCE_H
+
+#include "Utilities/LinkedReference/Reference.h"
+#include "Map.h"
+
+class TRINITY_DLL_SPEC MapReference : public Reference<Map, Player>
+{
+ protected:
+ void targetObjectBuildLink()
+ {
+ // called from link()
+ getTarget()->m_mapRefManager.insertFirst(this);
+ getTarget()->m_mapRefManager.incSize();
+ }
+ void targetObjectDestroyLink()
+ {
+ // called from unlink()
+ if(isValid()) getTarget()->m_mapRefManager.decSize();
+ }
+ void sourceObjectDestroyLink()
+ {
+ // called from invalidate()
+ getTarget()->m_mapRefManager.decSize();
+ }
+ public:
+ MapReference() : Reference<Map, Player>() {}
+ ~MapReference() { unlink(); }
+ MapReference *next() { return (MapReference*)Reference<Map, Player>::next(); }
+ MapReference const *next() const { return (MapReference const*)Reference<Map, Player>::next(); }
+ MapReference *nockeck_prev() { return (MapReference*)Reference<Map, Player>::nocheck_prev(); }
+ MapReference const *nocheck_prev() const { return (MapReference const*)Reference<Map, Player>::nocheck_prev(); }
+};
+#endif
diff --git a/src/game/MovementHandler.cpp b/src/game/MovementHandler.cpp
index 78cabe07bab..cdc922aa84c 100644
--- a/src/game/MovementHandler.cpp
+++ b/src/game/MovementHandler.cpp
@@ -10,12 +10,12 @@
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "Common.h"
@@ -50,15 +50,6 @@ void WorldSession::HandleMoveWorldportAckOpcode()
return;
}
- if(!sWorld.IsAllowedMap(loc.mapid) && (GetSecurity() < SEC_GAMEMASTER))
- {
- if(sWorld.IsAllowedMap(GetPlayer()->m_homebindMapId))
- GetPlayer()->TeleportTo(GetPlayer()->m_homebindMapId, GetPlayer()->m_homebindX, GetPlayer()->m_homebindY, GetPlayer()->m_homebindZ, GetPlayer()->GetOrientation());
- else
- LogoutPlayer(false);
- return;
- }
-
// get the destination map entry, not the current one, this will fix homebind and reset greeting
MapEntry const* mEntry = sMapStore.LookupEntry(loc.mapid);
InstanceTemplate const* mInstance = objmgr.GetInstanceTemplate(loc.mapid);
@@ -83,7 +74,7 @@ void WorldSession::HandleMoveWorldportAckOpcode()
GetPlayer()->SendInitialPacketsBeforeAddToMap();
// the CanEnter checks are done in TeleporTo but conditions may change
// while the player is in transit, for example the map may get full
- if(!MapManager::Instance().GetMap(GetPlayer()->GetMapId(), GetPlayer())->Add(GetPlayer()))
+ if(!GetPlayer()->GetMap()->Add(GetPlayer()))
{
sLog.outDebug("WORLD: teleport of player %s (%d) to location %d,%f,%f,%f,%f failed", GetPlayer()->GetName(), GetPlayer()->GetGUIDLow(), loc.mapid, loc.x, loc.y, loc.z, loc.o);
// teleport the player home
diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp
index 16ef4a26a34..bdf9e0328f2 100644
--- a/src/game/ObjectMgr.cpp
+++ b/src/game/ObjectMgr.cpp
@@ -2183,8 +2183,7 @@ void ObjectMgr::LoadPlayerInfo()
barGoLink bar( 1 );
sLog.outString();
- sLog.outString( ">> Loaded %u player create items", count );
- sLog.outErrorDb( "Error loading `playercreateinfo_item` table or empty table.");
+ sLog.outString( ">> Loaded %u custom player create items", count );
}
else
{
@@ -2236,7 +2235,7 @@ void ObjectMgr::LoadPlayerInfo()
delete result;
sLog.outString();
- sLog.outString( ">> Loaded %u player create items", count );
+ sLog.outString( ">> Loaded %u custom player create items", count );
}
}
diff --git a/src/game/Pet.cpp b/src/game/Pet.cpp
index 65d5fd73199..3ab892fd2fb 100644
--- a/src/game/Pet.cpp
+++ b/src/game/Pet.cpp
@@ -1015,7 +1015,7 @@ bool Pet::InitStatsForLevel(uint32 petlevel)
SetFloatValue(UNIT_MOD_CAST_SPEED, 1.0);
CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(cinfo->family);
- if(cFamily && cFamily->minScale > 0.0f)
+ if(cFamily && cFamily->minScale > 0.0f && getPetType()==HUNTER_PET)
{
float scale;
if (getLevel() >= cFamily->maxScaleLevel)
diff --git a/src/game/PetHandler.cpp b/src/game/PetHandler.cpp
index d912f42c22b..7950db27464 100644
--- a/src/game/PetHandler.cpp
+++ b/src/game/PetHandler.cpp
@@ -112,7 +112,10 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data )
return;
// not let attack friendly units.
- if( GetPlayer()->IsFriendlyTo(TargetUnit))
+ if(GetPlayer()->IsFriendlyTo(TargetUnit))
+ return;
+ // Not let attack through obstructions
+ if(!pet->IsWithinLOSInMap(TargetUnit))
return;
if(pet->GetTypeId() != TYPEID_PLAYER)
diff --git a/src/game/Player.cpp b/src/game/Player.cpp
index 1a5775845b1..8b7bcdf8c06 100644
--- a/src/game/Player.cpp
+++ b/src/game/Player.cpp
@@ -566,7 +566,9 @@ bool Player::Create( uint32 guidlow, std::string name, uint8 race, uint8 class_,
setFactionForRace(m_race);
- SetUInt32Value(UNIT_FIELD_BYTES_0, ( ( race ) | ( class_ << 8 ) | ( gender << 16 ) | ( powertype << 24 ) ) );
+ uint32 RaceClassGender = ( race ) | ( class_ << 8 ) | ( gender << 16 );
+
+ SetUInt32Value(UNIT_FIELD_BYTES_0, ( RaceClassGender | ( powertype << 24 ) ) );
SetUInt32Value(UNIT_FIELD_BYTES_1, unitfield);
SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_UNK3 | UNIT_BYTE2_FLAG_UNK5 );
SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE );
@@ -674,8 +676,10 @@ bool Player::Create( uint32 guidlow, std::string name, uint8 race, uint8 class_,
SetPower(POWER_MANA,GetMaxPower(POWER_MANA));
}
+ // original spells
learnDefaultSpells(true);
+ // original action bar
std::list<uint16>::const_iterator action_itr[4];
for(int i=0; i<4; i++)
action_itr[i] = info->action[i].begin();
@@ -692,37 +696,59 @@ bool Player::Create( uint32 guidlow, std::string name, uint8 race, uint8 class_,
++action_itr[i];
}
- for (PlayerCreateInfoItems::const_iterator item_id_itr = info->item.begin(); item_id_itr!=info->item.end(); ++item_id_itr++)
+ // original items
+ CharStartOutfitEntry const* oEntry = NULL;
+ for (uint32 i = 1; i < sCharStartOutfitStore.GetNumRows(); ++i)
{
- uint32 titem_id = item_id_itr->item_id;
- uint32 titem_amount = item_id_itr->item_amount;
-
- sLog.outDebug("STORAGE: Creating initial item, itemId = %u, count = %u",titem_id, titem_amount);
-
- // attempt equip
- uint16 eDest;
- uint8 msg = CanEquipNewItem( NULL_SLOT, eDest, titem_id, titem_amount, false );
- if( msg == EQUIP_ERR_OK )
+ if(CharStartOutfitEntry const* entry = sCharStartOutfitStore.LookupEntry(i))
{
- EquipNewItem( eDest, titem_id, titem_amount, true);
- AutoUnequipOffhandIfNeed();
- continue; // equipped, to next
+ if(entry->RaceClassGender == RaceClassGender)
+ {
+ oEntry = entry;
+ break;
+ }
}
+ }
- // attempt store
- ItemPosCountVec sDest;
- // store in main bag to simplify second pass (special bags can be not equipped yet at this moment)
- msg = CanStoreNewItem( INVENTORY_SLOT_BAG_0, NULL_SLOT, sDest, titem_id, titem_amount );
- if( msg == EQUIP_ERR_OK )
+ if(oEntry)
+ {
+ for(int j = 0; j < MAX_OUTFIT_ITEMS; ++j)
{
- StoreNewItem( sDest, titem_id, true, Item::GenerateItemRandomPropertyId(titem_id) );
- continue; // stored, to next
- }
+ if(oEntry->ItemId[j] <= 0)
+ continue;
+
+ uint32 item_id = oEntry->ItemId[j];
- // item can't be added
- sLog.outError("STORAGE: Can't equip or store initial item %u for race %u class %u , error msg = %u",titem_id,race,class_,msg);
+ ItemPrototype const* iProto = objmgr.GetItemPrototype(item_id);
+ if(!iProto)
+ {
+ sLog.outErrorDb("Initial item id %u (race %u class %u) from CharStartOutfit.dbc not listed in `item_template`, ignoring.",item_id,getRace(),getClass());
+ continue;
+ }
+
+ uint32 count = iProto->Stackable; // max stack by default (mostly 1)
+ if(iProto->Class==ITEM_CLASS_CONSUMABLE && iProto->SubClass==ITEM_SUBCLASS_FOOD)
+ {
+ switch(iProto->Spells[0].SpellCategory)
+ {
+ case 11: // food
+ if(iProto->Stackable > 4)
+ count = 4;
+ break;
+ case 59: // drink
+ if(iProto->Stackable > 2)
+ count = 2;
+ break;
+ }
+ }
+
+ StoreNewItemInBestSlot(item_id, count);
+ }
}
+ for (PlayerCreateInfoItems::const_iterator item_id_itr = info->item.begin(); item_id_itr!=info->item.end(); ++item_id_itr++)
+ StoreNewItemInBestSlot(item_id_itr->item_id, item_id_itr->item_amount);
+
// bags and main-hand weapon must equipped at this moment
// now second pass for not equipped (offhand weapon/shield if it attempt equipped before main-hand weapon)
// or ammo not equipped in special bag
@@ -761,6 +787,35 @@ bool Player::Create( uint32 guidlow, std::string name, uint8 race, uint8 class_,
return true;
}
+bool Player::StoreNewItemInBestSlot(uint32 titem_id, uint32 titem_amount)
+{
+ sLog.outDebug("STORAGE: Creating initial item, itemId = %u, count = %u",titem_id, titem_amount);
+
+ // attempt equip
+ uint16 eDest;
+ uint8 msg = CanEquipNewItem( NULL_SLOT, eDest, titem_id, titem_amount, false );
+ if( msg == EQUIP_ERR_OK )
+ {
+ EquipNewItem( eDest, titem_id, titem_amount, true);
+ AutoUnequipOffhandIfNeed();
+ return true; // equipped
+ }
+
+ // attempt store
+ ItemPosCountVec sDest;
+ // store in main bag to simplify second pass (special bags can be not equipped yet at this moment)
+ msg = CanStoreNewItem( INVENTORY_SLOT_BAG_0, NULL_SLOT, sDest, titem_id, titem_amount );
+ if( msg == EQUIP_ERR_OK )
+ {
+ StoreNewItem( sDest, titem_id, true, Item::GenerateItemRandomPropertyId(titem_id) );
+ return true; // stored
+ }
+
+ // item can't be added
+ sLog.outError("STORAGE: Can't equip or store initial item %u for race %u class %u , error msg = %u",titem_id,getRace(),getClass(),msg);
+ return false;
+}
+
void Player::StartMirrorTimer(MirrorTimerType Type, uint32 MaxValue)
{
uint32 BreathRegen = (uint32)-1;
diff --git a/src/game/Player.h b/src/game/Player.h
index 2f98793f3d1..0f2b9fc0dd5 100644
--- a/src/game/Player.h
+++ b/src/game/Player.h
@@ -1081,6 +1081,7 @@ class TRINITY_DLL_SPEC Player : public Unit
Item* EquipNewItem( uint16 pos, uint32 item, uint32 count, bool update );
Item* EquipItem( uint16 pos, Item *pItem, bool update );
void AutoUnequipOffhandIfNeed();
+ bool StoreNewItemInBestSlot(uint32 item_id, uint32 item_count);
uint8 _CanTakeMoreSimilarItems(uint32 entry, uint32 count, Item* pItem, uint32* no_space_count = NULL) const;
uint8 _CanStoreItem( uint8 bag, uint8 slot, ItemPosCountVec& dest, uint32 entry, uint32 count, Item *pItem = NULL, bool swap = false, uint32* no_space_count = NULL ) const;
diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp
index e7e1302ab58..073e8b36a8b 100644
--- a/src/game/SpellEffects.cpp
+++ b/src/game/SpellEffects.cpp
@@ -572,58 +572,9 @@ void Spell::EffectDummy(uint32 i)
switch(m_spellInfo->SpellFamilyName)
{
case SPELLFAMILY_GENERIC:
- // Gnomish Poultryizer trinket
+ {
switch(m_spellInfo->Id )
{
- // Mingo's Fortune Giblets
- case 40802:
- {
- if (m_caster->GetTypeId() != TYPEID_PLAYER) return;
-
- Player *player = (Player*)m_caster;
- uint32 newitemid;
-
- switch(urand(1,20))
- {
- case 1: newitemid = 32688; break;
- case 2: newitemid = 32689; break;
- case 3: newitemid = 32690; break;
- case 4: newitemid = 32691; break;
- case 5: newitemid = 32692; break;
- case 6: newitemid = 32693; break;
- case 7: newitemid = 32700; break;
- case 8: newitemid = 32701; break;
- case 9: newitemid = 32702; break;
- case 10: newitemid = 32703; break;
- case 11: newitemid = 32704; break;
- case 12: newitemid = 32705; break;
- case 13: newitemid = 32706; break;
- case 14: newitemid = 32707; break;
- case 15: newitemid = 32708; break;
- case 16: newitemid = 32709; break;
- case 17: newitemid = 32710; break;
- case 18: newitemid = 32711; break;
- case 19: newitemid = 32712; break;
- case 20: newitemid = 32713; break;
- }
- ItemPosCountVec dest;
- uint8 msg = player->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, newitemid, 1, false);
- if (msg != EQUIP_ERR_OK)
- {
- player->SendEquipError(msg, NULL, NULL);
- return;
- }
- Item *pItem = player->StoreNewItem(dest, newitemid, true, Item::GenerateItemRandomPropertyId(newitemid));
-
- if (!pItem)
- {
- player->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL);
- return;
- }
- player->SendNewItem(pItem, 1, true, true);
-
- return;
- }
// Encapsulate Voidwalker
case 29364:
{
@@ -1035,6 +986,50 @@ void Spell::EffectDummy(uint32 i)
if(unitTarget)
m_caster->CastSpell(unitTarget,37675,true);
return;
+ case 40802: // Mingo's Fortune Generator (Mingo's Fortune Giblets)
+ {
+ // selecting one from Bloodstained Fortune item
+ uint32 newitemid;
+ switch(urand(1,20))
+ {
+ case 1: newitemid = 32688; break;
+ case 2: newitemid = 32689; break;
+ case 3: newitemid = 32690; break;
+ case 4: newitemid = 32691; break;
+ case 5: newitemid = 32692; break;
+ case 6: newitemid = 32693; break;
+ case 7: newitemid = 32700; break;
+ case 8: newitemid = 32701; break;
+ case 9: newitemid = 32702; break;
+ case 10: newitemid = 32703; break;
+ case 11: newitemid = 32704; break;
+ case 12: newitemid = 32705; break;
+ case 13: newitemid = 32706; break;
+ case 14: newitemid = 32707; break;
+ case 15: newitemid = 32708; break;
+ case 16: newitemid = 32709; break;
+ case 17: newitemid = 32710; break;
+ case 18: newitemid = 32711; break;
+ case 19: newitemid = 32712; break;
+ case 20: newitemid = 32713; break;
+ default:
+ return;
+ }
+
+ DoCreateItem(i,newitemid);
+ return;
+ }
+ // Demon Broiled Surprise
+ /* FIX ME: Required for correct work implementing implicit target 7 (in pair (22,7))
+ case 43723:
+ {
+ if (m_caster->GetTypeId() != TYPEID_PLAYER)
+ return;
+
+ ((Player*)m_caster)->CastSpell(unitTarget, 43753, true);
+ return;
+ }
+ */
case 44875: // Complete Raptor Capture
{
if(!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
@@ -1182,6 +1177,7 @@ void Spell::EffectDummy(uint32 i)
}
}
break;
+ }
case SPELLFAMILY_MAGE:
switch(m_spellInfo->Id )
{
diff --git a/src/shared/Database/DBCStores.cpp b/src/shared/Database/DBCStores.cpp
index 71e3483a1ab..b337acb1bd7 100644
--- a/src/shared/Database/DBCStores.cpp
+++ b/src/shared/Database/DBCStores.cpp
@@ -38,6 +38,7 @@ static AreaFlagByMapID sAreaFlagByMapID; // for instances wit
DBCStorage <AreaTriggerEntry> sAreaTriggerStore(AreaTriggerEntryfmt);
DBCStorage <BankBagSlotPricesEntry> sBankBagSlotPricesStore(BankBagSlotPricesEntryfmt);
DBCStorage <BattlemasterListEntry> sBattlemasterListStore(BattlemasterListEntryfmt);
+DBCStorage <CharStartOutfitEntry> sCharStartOutfitStore(CharStartOutfitEntryfmt);
DBCStorage <CharTitlesEntry> sCharTitlesStore(CharTitlesEntryfmt);
DBCStorage <ChatChannelsEntry> sChatChannelsStore(ChatChannelsEntryfmt);
DBCStorage <ChrClassesEntry> sChrClassesStore(ChrClassesEntryfmt);
@@ -203,6 +204,8 @@ void LoadDBCStores(std::string dataPath)
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sAreaTriggerStore, dbcPath,"AreaTrigger.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sBankBagSlotPricesStore, dbcPath,"BankBagSlotPrices.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sBattlemasterListStore, dbcPath,"BattlemasterList.dbc");
+ LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCharStartOutfitStore, dbcPath,"CharStartOutfit.dbc");
+
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCharTitlesStore, dbcPath,"CharTitles.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sChatChannelsStore, dbcPath,"ChatChannels.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sChrClassesStore, dbcPath,"ChrClasses.dbc");
diff --git a/src/shared/Database/DBCStores.h b/src/shared/Database/DBCStores.h
index 0375f20c7eb..eb824e331cc 100644
--- a/src/shared/Database/DBCStores.h
+++ b/src/shared/Database/DBCStores.h
@@ -136,6 +136,7 @@ extern DBCStorage <AreaTriggerEntry> sAreaTriggerStore;
extern DBCStorage <BankBagSlotPricesEntry> sBankBagSlotPricesStore;
extern DBCStorage <BattlemasterListEntry> sBattlemasterListStore;
//extern DBCStorage <ChatChannelsEntry> sChatChannelsStore; -- accessed using function, no usable index
+extern DBCStorage <CharStartOutfitEntry> sCharStartOutfitStore;
extern DBCStorage <CharTitlesEntry> sCharTitlesStore;
extern DBCStorage <ChrClassesEntry> sChrClassesStore;
extern DBCStorage <ChrRacesEntry> sChrRacesStore;
diff --git a/src/shared/Database/DBCStructure.h b/src/shared/Database/DBCStructure.h
index ce72661066b..dde32406b94 100644
--- a/src/shared/Database/DBCStructure.h
+++ b/src/shared/Database/DBCStructure.h
@@ -86,6 +86,21 @@ struct BattlemasterListEntry
// 32 unused
};
+#define MAX_OUTFIT_ITEMS 12
+// #define MAX_OUTFIT_ITEMS 24 // 12->24 in 3.0.x
+
+struct CharStartOutfitEntry
+{
+ //uint32 Id; // 0
+ uint32 RaceClassGender; // 1 (UNIT_FIELD_BYTES_0 & 0x00FFFFFF) comparable (0 byte = race, 1 byte = class, 2 byte = gender)
+ int32 ItemId[MAX_OUTFIT_ITEMS]; // 2-13
+ //int32 ItemDisplayId[MAX_OUTFIT_ITEMS]; // 14-25 not required at server side
+ //int32 ItemInventorySlot[MAX_OUTFIT_ITEMS]; // 26-37 not required at server side
+ //uint32 Unknown1; // 38, unique values (index-like with gaps ordered in other way as ids)
+ //uint32 Unknown2; // 39
+ //uint32 Unknown3; // 40
+};
+
struct CharTitlesEntry
{
uint32 ID; // 0, title ids, for example in Quest::GetCharTitleId()
diff --git a/src/shared/Database/DBCfmt.cpp b/src/shared/Database/DBCfmt.cpp
index 64163664b49..fe8d3cdb400 100644
--- a/src/shared/Database/DBCfmt.cpp
+++ b/src/shared/Database/DBCfmt.cpp
@@ -22,6 +22,9 @@ const char AreaTableEntryfmt[]="iiinixxxxxissssssssssssssssxixxxxxx";
const char AreaTriggerEntryfmt[]="niffffffff";
const char BankBagSlotPricesEntryfmt[]="ni";
const char BattlemasterListEntryfmt[]="niiixxxxxiiiixxssssssssssssssssxx";
+const char CharStartOutfitEntryfmt[]="diiiiiiiiiiiiixxxxxxxxxxxxxxxxxxxxxxxxxxx";
+// 3*12 new item fields in 3.0.x
+//const char CharStartOutfitEntryfmt[]="diiiiiiiiiiiiiiiiiiiiiiiiixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
const char CharTitlesEntryfmt[]="nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxi";
const char ChatChannelsEntryfmt[]="iixssssssssssssssssxxxxxxxxxxxxxxxxxx";
// ChatChannelsEntryfmt, index not used (more compact store)