mirror of
https://github.com/araxiaonline/TrinityCore.git
synced 2026-06-13 03:32:28 -04:00
*Update to Mangos 6856. Source: Mangos.
--HG-- branch : trunk
This commit is contained in:
1
sql/updates/341_world.sql
Normal file
1
sql/updates/341_world.sql
Normal file
@@ -0,0 +1 @@
|
||||
TRUNCATE TABLE playercreateinfo_item;
|
||||
@@ -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);
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 )
|
||||
{
|
||||
StoreNewItem( sDest, titem_id, true, Item::GenerateItemRandomPropertyId(titem_id) );
|
||||
continue; // stored, to next
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
if(oEntry)
|
||||
{
|
||||
for(int j = 0; j < MAX_OUTFIT_ITEMS; ++j)
|
||||
{
|
||||
if(oEntry->ItemId[j] <= 0)
|
||||
continue;
|
||||
|
||||
uint32 item_id = oEntry->ItemId[j];
|
||||
|
||||
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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 )
|
||||
{
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user