2 * Copyright (C) 2005,2006 MaNGOS <http://www.mangosproject.org/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #include "Database/DatabaseEnv.h"
23 #include "ObjectMgr.h"
25 #include "WorldPacket.h"
26 #include "WorldSession.h"
27 #include "UpdateMask.h"
30 #include "GossipDef.h"
32 #include "UpdateData.h"
35 #include "MapManager.h"
36 #include "ObjectMgr.h"
37 #include "ObjectAccessor.h"
38 #include "CreatureAI.h"
43 #include "SpellAuras.h"
48 Player::Player (WorldSession
*session
): Unit()
50 m_objectType
|= TYPE_PLAYER
;
51 m_objectTypeId
= TYPEID_PLAYER
;
53 m_valuesCount
= PLAYER_END
;
61 if(GetSession()->GetSecurity() >=2)
62 SetAcceptTicket(true);
63 if(GetSession()->GetSecurity() >=1 && sWorld
.getConfig(CONFIG_GM_WISPERING_TO
))
64 SetAcceptWhispers(true);
76 m_nextSave
= sWorld
.getConfig(CONFIG_INTERVAL_SAVE
);
79 m_resurrectX
= m_resurrectY
= m_resurrectZ
= 0;
80 m_resurrectHealth
= m_resurrectMana
= 0;
82 memset(m_items
, 0, sizeof(Item
*)*BUYBACK_SLOT_END
);
83 memset(m_buybackitems
, 0, sizeof(Item
*)*(BUYBACK_SLOT_END
- BUYBACK_SLOT_START
));
97 m_total_honor_points
= 0;
105 PlayerTalkClass
= new PlayerMenu( GetSession() );
106 m_currentBuybackSlot
= BUYBACK_SLOT_START
;
108 for ( int aX
= 0 ; aX
< 8 ; aX
++ )
109 m_Tutorials
[ aX
] = 0x00;
123 m_pvp_counting
= false;
125 m_bgInBattleGround
= false;
126 m_bgBattleGroundID
= 0;
128 m_movement_flags
= 0;
132 m_logintime
= time(NULL
);
133 m_Last_tick
= m_logintime
;
135 m_soulStoneSpell
= 0;
136 m_WeaponProficiency
= 0;
137 m_ArmorProficiency
= 0;
139 m_canDualWield
= false;
141 ////////////////////Rest System/////////////////////
148 ////////////////////Rest System/////////////////////
150 m_mailsLoaded
= false;
151 m_mailsUpdated
= false;
153 m_resetTalentsCost
= 0;
154 m_resetTalentsTime
= 0;
168 for(int j
= BUYBACK_SLOT_START
; j
< BUYBACK_SLOT_END
; j
++)
170 eslot
= j
- BUYBACK_SLOT_START
;
171 if(m_buybackitems
[eslot
])
173 m_buybackitems
[eslot
]->DeleteFromDB();
174 m_buybackitems
[eslot
]->RemoveFromWorld();
175 delete m_buybackitems
[eslot
];
178 for(int i
= 0; i
< BANK_SLOT_BAG_END
; i
++)
185 //all mailed items should be deleted, also all mail should be dealocated
186 for (std::list
<Mail
*>::iterator itr
= m_mail
.begin(); itr
!= m_mail
.end();++itr
)
189 for (ItemMap::iterator iter
= mMitems
.begin(); iter
!= mMitems
.end(); ++iter
)
190 delete iter
->second
; //if item is duplicated... then server may crash ... but that item should be dealocated
193 delete PlayerTalkClass
;
196 bool Player::Create( uint32 guidlow
, WorldPacket
& data
)
199 uint8 race
,class_
,gender
,skin
,face
,hairStyle
,hairColor
,facialHair
,outfitId
;
201 Object::_Create(guidlow
, HIGHGUID_PLAYER
);
205 normalizePlayerName(m_name
);
207 data
>> race
>> class_
>> gender
>> skin
>> face
;
208 data
>> hairStyle
>> hairColor
>> facialHair
>> outfitId
;
210 info
= objmgr
.GetPlayerCreateInfo((uint32
)race
, (uint32
)class_
);
213 sLog
.outError("Player have incorrect race/class pair. Can't be loaded.");
217 m_createStats
[STAT_AGILITY
] = (float)info
->agility
;
218 m_createStats
[STAT_INTELLECT
] = (float)info
->intellect
;
219 m_createStats
[STAT_SPIRIT
] = (float)info
->spirit
;
220 m_createStats
[STAT_STAMINA
] = (float)info
->stamina
;
221 m_createStats
[STAT_STRENGTH
] = (float)info
->strength
;
223 for (i
= 0; i
< BANK_SLOT_BAG_END
; i
++)
227 for(int j
= BUYBACK_SLOT_START
; j
< BUYBACK_SLOT_END
; j
++)
229 eslot
= j
- BUYBACK_SLOT_START
;
230 m_buybackitems
[eslot
] = NULL
;
231 // SetUInt64Value(PLAYER_FIELD_VENDORBUYBACK_SLOT_1+j*2,0);
232 // SetUInt32Value(PLAYER_FIELD_BUYBACK_PRICE_1+j,0);
233 // SetUInt32Value(PLAYER_FIELD_BUYBACK_TIMESTAMP_1+j,0);
239 m_mapId
= info
->mapId
;
240 m_positionX
= info
->positionX
;
241 m_positionY
= info
->positionY
;
242 m_positionZ
= info
->positionZ
;
245 memset(m_taximask
, 0, sizeof(m_taximask
));
247 // Automatically add the race's taxi hub to the character's taximask at creation time ( 1 << (taxi_node_id-1) )
250 case TAUREN
: m_taximask
[0]= 1 << (22-1); break;
251 case HUMAN
: m_taximask
[0]= 1 << ( 2-1); break;
252 case DWARF
: m_taximask
[0]= 1 << ( 6-1); break;
253 case NIGHTELF
: m_taximask
[0]= (1 << (26-1)) | (1 << (27-1)); break;
254 case GNOME
: m_taximask
[0]= 1 << ( 6-1); break;
255 case ORC
: m_taximask
[0]= 1 << (23-1); break;
256 case UNDEAD_PLAYER
: m_taximask
[0]= 1 << (11-1); break;
257 case TROLL
: m_taximask
[0]= 1 << (23-1); break;
261 uint32 unitfield
= 0;
264 case WARRIOR
: powertype
= 1; unitfield
= 0x1100EE00; break;
265 case PALADIN
: powertype
= 0; unitfield
= 0x0000EE00; break;
266 case HUNTER
: powertype
= 0; unitfield
= 0x0000EE00; break;
267 case ROGUE
: powertype
= 3; unitfield
= 0x00000000; break;
268 case PRIEST
: powertype
= 0; unitfield
= 0x0000EE00; break;
269 case SHAMAN
: powertype
= 0; unitfield
= 0x0000EE00; break;
270 case MAGE
: powertype
= 0; unitfield
= 0x0000EE00; break;
271 case WARLOCK
: powertype
= 0; unitfield
= 0x0000EE00; break;
272 case DRUID
: powertype
= 0; unitfield
= 0x0000EE00; break;
275 if ( race
== TAUREN
)
277 SetFloatValue(OBJECT_FIELD_SCALE_X
, 1.35f
);
279 else SetFloatValue(OBJECT_FIELD_SCALE_X
, 1.0f
);
280 SetStat(STAT_STRENGTH
,info
->strength
);
281 SetStat(STAT_AGILITY
,info
->agility
);
282 SetStat(STAT_STAMINA
,info
->stamina
);
283 SetStat(STAT_INTELLECT
,info
->intellect
);
284 SetStat(STAT_SPIRIT
,info
->spirit
);
285 SetArmor(info
->basearmor
);
286 SetUInt32Value(UNIT_FIELD_ATTACK_POWER
, 0 );
288 SetHealth(info
->health
);
289 SetMaxHealth(info
->health
);
291 SetPower( POWER_MANA
, info
->mana
);
292 SetMaxPower(POWER_MANA
, info
->mana
);
293 SetPower( POWER_RAGE
, 0 );
294 SetMaxPower(POWER_RAGE
, info
->rage
);
295 SetPower( POWER_FOCUS
, info
->focus
);
296 SetMaxPower(POWER_FOCUS
, info
->focus
);
297 SetPower( POWER_ENERGY
, info
->energy
);
298 SetMaxPower(POWER_ENERGY
, info
->energy
);
300 SetFloatValue(UNIT_FIELD_MINDAMAGE
, 0 );
301 SetFloatValue(UNIT_FIELD_MAXDAMAGE
, 0 );
302 SetFloatValue(UNIT_FIELD_MINRANGEDDAMAGE
, 0 );
303 SetFloatValue(UNIT_FIELD_MAXRANGEDDAMAGE
, 0 );
305 SetAttackTime(BASE_ATTACK
, 2000 ); // melee attack time
306 SetAttackTime(RANGED_ATTACK
, 2000 ); // ranged attack time
308 SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS
, 0.388999998569489f
);
309 SetFloatValue(UNIT_FIELD_COMBATREACH
, 1.5f
);
311 SetUInt32Value(UNIT_FIELD_DISPLAYID
, info
->displayId
+ gender
);
312 SetUInt32Value(UNIT_FIELD_NATIVEDISPLAYID
, info
->displayId
+ gender
);
316 setFactionForRace(m_race
);
318 SetUInt32Value(UNIT_FIELD_BYTES_0
, ( ( race
) | ( class_
<< 8 ) | ( gender
<< 16 ) | ( powertype
<< 24 ) ) );
319 SetUInt32Value(UNIT_FIELD_BYTES_1
, unitfield
);
320 SetUInt32Value(UNIT_FIELD_BYTES_2
, 0xEEEEEE00 );
321 SetUInt32Value(UNIT_FIELD_FLAGS
, UNIT_FLAG_NONE
| UNIT_FLAG_NOT_IN_PVP
);
323 SetUInt32Value(UNIT_DYNAMIC_FLAGS
, 0x10);
324 //-1 is default value
325 SetUInt32Value(PLAYER_FIELD_WATCHED_FACTION_INDEX
, uint32(-1));
327 SetUInt32Value(PLAYER_BYTES
, ((skin
) | (face
<< 8) | (hairStyle
<< 16) | (hairColor
<< 24)));
328 SetUInt32Value(PLAYER_BYTES_2
, (facialHair
| (0xEE << 8) | (0x00 << 16) | (0x02 << 24)));
329 SetUInt32Value(PLAYER_BYTES_3
, gender
);
330 SetUInt32Value(PLAYER_NEXT_LEVEL_XP
, 400);
331 SetUInt32Value(PLAYER_FIELD_BYTES
, 0xEEE00000 );
333 SetFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT
, 1.00);
334 SetFloatValue(PLAYER_CRIT_PERCENTAGE
, 5);
335 SetFloatValue(PLAYER_PARRY_PERCENTAGE
, 5);
338 SetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG, 0);
339 SetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS, 0);
341 SetUInt32Value(PLAYER_GUILDID, 0);
342 SetUInt32Value(PLAYER_GUILDRANK, 0);
343 SetUInt32Value(PLAYER_GUILD_TIMESTAMP, 0);
345 SetUInt32Value(PLAYER_FIELD_HONOR_RANK, 0);
346 SetUInt32Value(PLAYER_FIELD_HONOR_HIGHEST_RANK, 0); SetUInt32Value(PLAYER_FIELD_TODAY_KILLS, 0); SetUInt32Value(PLAYER_FIELD_YESTERDAY_HONORABLE_KILLS, 0); SetUInt32Value(PLAYER_FIELD_LAST_WEEK_HONORABLE_KILLS, 0); SetUInt32Value(PLAYER_FIELD_THIS_WEEK_HONORABLE_KILLS, 0); SetUInt32Value(PLAYER_FIELD_THIS_WEEK_HONOR, 0); SetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS, 0); SetUInt32Value(PLAYER_FIELD_LIFETIME_DISHONORABLE_KILLS, 0); SetUInt32Value(PLAYER_FIELD_YESTERDAY_HONOR, 0); SetUInt32Value(PLAYER_FIELD_LAST_WEEK_HONOR, 0); SetUInt32Value(PLAYER_FIELD_LAST_WEEK_STANDING, 0); SetUInt32Value(PLAYER_FIELD_LIFETIME_HONOR, 0); SetUInt32Value(PLAYER_FIELD_SESSION_KILLS, 0);
350 m_Last_tick
= time(NULL
);
351 m_Played_time
[0] = 0;
352 m_Played_time
[1] = 0;
356 uint8 titem_bagIndex
;
358 uint16 tspell
, tskill
[3], taction
[4];
359 std::list
<uint32
>::iterator item_id_itr
;
360 std::list
<uint8
>::iterator item_bagIndex_itr
;
361 std::list
<uint8
>::iterator item_slot_itr
;
362 std::list
<uint32
>::iterator item_amount_itr
;
363 std::list
<uint16
>::iterator skill_itr
[3], action_itr
[4];
364 std::list
<CreateSpellPair
>::iterator spell_itr
;
366 item_id_itr
= info
->item_id
.begin();
367 item_bagIndex_itr
= info
->item_bagIndex
.begin();
368 item_slot_itr
= info
->item_slot
.begin();
369 item_amount_itr
= info
->item_amount
.begin();
370 spell_itr
= info
->spell
.begin();
372 for (; spell_itr
!=info
->spell
.end(); spell_itr
++)
374 tspell
= spell_itr
->first
;
377 sLog
.outDebug("PLAYER: Adding initial spell, id = %u",tspell
);
378 addSpell(tspell
,spell_itr
->second
);
383 skill_itr
[i
] = info
->skill
[i
].begin();
385 for (; skill_itr
[0]!=info
->skill
[0].end() && skill_itr
[1]!=info
->skill
[1].end() && skill_itr
[2]!=info
->skill
[2].end(); )
388 tskill
[i
] = (*skill_itr
[i
]);
392 sLog
.outDebug("PLAYER: Adding initial skill line, skillId = %u, value = %u, max = %u", tskill
[0], tskill
[1], tskill
[2]);
393 SetSkill(tskill
[0], tskill
[1], tskill
[2]);
401 action_itr
[i
] = info
->action
[i
].begin();
403 for (; action_itr
[0]!=info
->action
[0].end() && action_itr
[1]!=info
->action
[1].end();)
406 taction
[i
] = (*action_itr
[i
]);
408 addAction((uint8
)taction
[0], taction
[1], (uint8
)taction
[2], (uint8
)taction
[3]);
422 // initilize potential block chance (used if item with Block value equiped)
423 SetFloatValue(PLAYER_BLOCK_PERCENTAGE
, 5 );
424 UpdateBlockPercentage(GetDefenceSkillValue(),getLevel());
426 // apply original stats mods before item equipment that call before equip _RemoveStatsMods()
432 for (; item_id_itr
!=info
->item_id
.end(); item_id_itr
++, item_bagIndex_itr
++, item_slot_itr
++, item_amount_itr
++)
434 titem_id
= (*item_id_itr
);
435 titem_bagIndex
= (*item_bagIndex_itr
);
436 titem_slot
= (*item_slot_itr
);
437 titem_amount
= (*item_amount_itr
);
441 sLog
.outDebug("STORAGE: Creating initial item, itemId = %u, bagIndex = %u, slot = %u, count = %u",titem_id
, titem_bagIndex
, titem_slot
, titem_amount
);
443 pItem
= CreateItem( titem_id
, titem_amount
);
446 dest
= ((titem_bagIndex
<< 8) | titem_slot
);
447 if( IsInventoryPos( dest
) )
449 msg
= CanStoreItem( titem_bagIndex
, titem_slot
, dest
, pItem
, false );
450 if( msg
== EQUIP_ERR_OK
)
451 StoreItem( dest
, pItem
, true);
454 sLog
.outDebug("STORAGE: Can't store item, error msg = %u",msg
);
458 else if( IsEquipmentPos( dest
) )
460 msg
= CanEquipItem( titem_slot
, dest
, pItem
, false );
461 if( msg
== EQUIP_ERR_OK
)
462 EquipItem( dest
, pItem
, true);
465 sLog
.outDebug("STORAGE: Can't equip item, error msg = %u",msg
);
469 else if( IsBankPos( dest
) )
471 msg
= CanBankItem( titem_bagIndex
, titem_slot
, dest
, pItem
, false );
472 if( msg
== EQUIP_ERR_OK
)
473 BankItem( dest
, pItem
, true);
476 sLog
.outDebug("STORAGE: Can't bank item, error msg = %u",msg
);
486 // remove applied original stats mods before item equipment
491 void Player::StartMirrorTimer(MirrorTimerType Type
, uint32 MaxValue
)
494 uint32 BreathRegen
= (uint32
)-1;
495 data
.Initialize(SMSG_START_MIRROR_TIMER
);
496 data
<< (uint32
)Type
;
502 GetSession()->SendPacket(&data
);
505 void Player::ModifyMirrorTimer(MirrorTimerType Type
, uint32 MaxValue
, uint32 CurrentValue
, uint32 Regen
)
507 if(Type
==BREATH_TIMER
)
508 m_breathTimer
= ((MaxValue
+ 1000) - CurrentValue
) / Regen
;
511 data
.Initialize(SMSG_START_MIRROR_TIMER
);
512 data
<< (uint32
)Type
;
513 data
<< CurrentValue
;
518 GetSession()->SendPacket( &data
);
521 void Player::StopMirrorTimer(MirrorTimerType Type
)
523 if(Type
==BREATH_TIMER
)
527 data
.Initialize(SMSG_STOP_MIRROR_TIMER
);
528 data
<< (uint32
)Type
;
529 GetSession()->SendPacket( &data
);
532 void Player::EnvironmentalDamage(uint64 Guid
, uint8 Type
, uint32 Amount
)
535 data
.Initialize(SMSG_ENVIRONMENTALDAMAGELOG
);
541 //m_session->SendPacket(&data);
542 //Let other players see that you get damage
543 SendMessageToSet(&data
, true);
544 DealDamage((Unit
*)this, Amount
, 0, true);
547 void Player::HandleDrowing(uint32 UnderWaterTime
)
549 AuraList
& mModWaterBreathing
= GetAurasByType(SPELL_AURA_MOD_WATER_BREATHING
);
550 for(AuraList::iterator i
= mModWaterBreathing
.begin(); i
!= mModWaterBreathing
.end(); ++i
)
551 UnderWaterTime
= uint32(UnderWaterTime
* (100.0f
+ (*i
)->GetModifier()->m_amount
) / 100.0f
);
553 //if have water breath , then remove bar
554 if(waterbreath
|| !isAlive())
556 StopMirrorTimer(BREATH_TIMER
);
561 if ((m_isunderwater
& 0x01) && !(m_isunderwater
& 0x80) && isAlive())
563 //single trigger timer
564 if (!(m_isunderwater
& 0x02))
566 m_isunderwater
|= 0x02;
567 m_breathTimer
= UnderWaterTime
+ 1000;
569 //single trigger "Breathbar"
570 if ( m_breathTimer
<= UnderWaterTime
&& !(m_isunderwater
& 0x04))
572 m_isunderwater
|= 0x04;
573 StartMirrorTimer(BREATH_TIMER
, UnderWaterTime
);
575 //continius trigger drowning "Damage"
576 if ((m_breathTimer
== 0) && (m_isunderwater
& 0x01))
578 //TODO: Check this formula
579 uint64 guid
= GetGUID();
580 uint32 damage
= (GetMaxHealth() / 5) + rand()%getLevel();
582 EnvironmentalDamage(guid
, DAMAGE_DROWNING
,damage
);
583 m_breathTimer
= 2000;
586 //single trigger retract bar
587 else if (!(m_isunderwater
& 0x01) && !(m_isunderwater
& 0x08) && (m_isunderwater
& 0x02) && (m_breathTimer
> 0) && isAlive())
589 m_isunderwater
= 0x08;
591 uint32 BreathRegen
= 10;
592 ModifyMirrorTimer(BREATH_TIMER
, UnderWaterTime
, m_breathTimer
,BreathRegen
);
593 m_isunderwater
= 0x10;
596 else if ((m_breathTimer
< 50) && !(m_isunderwater
& 0x01) && (m_isunderwater
== 0x10))
598 StopMirrorTimer(BREATH_TIMER
);
603 void Player::HandleLava()
605 if ((m_isunderwater
& 0x80) && isAlive())
607 //Single trigger Set BreathTimer
608 if (!(m_isunderwater
& 0x04))
610 m_isunderwater
|= 0x04;
611 m_breathTimer
= 1000;
613 //Reset BreathTimer and still in the lava
617 //uint32 damage = 10;
618 uint32 damage
= (GetMaxHealth() / 3) + rand()%getLevel();
621 EnvironmentalDamage(guid
, DAMAGE_LAVA
, damage
);
622 m_breathTimer
= 1000;
626 //Death timer disabled and WaterFlags reset
627 else if (m_deathState
== DEAD
)
634 void Player::HandleSobering()
637 if (m_drunk
<= (0xFFFF / 30))
643 m_drunk
-= (0xFFFF / 30);
645 SetUInt32Value(PLAYER_BYTES_3
, (GetUInt32Value(PLAYER_BYTES_3
) & 0xFFFF0001) | m_drunk
);
648 void Player::SetDrunkValue(uint16 newDrunkValue
)
650 m_drunk
= newDrunkValue
;
651 SetUInt32Value(PLAYER_BYTES_3
,
652 (GetUInt32Value(PLAYER_BYTES_3
) & 0xFFFF0001) | m_drunk
);
655 void Player::Update( uint32 p_time
)
662 Unit::Update( p_time
);
664 // update player only attacks
665 if(uint32 ranged_att
= getAttackTimer(RANGED_ATTACK
))
667 setAttackTimer(RANGED_ATTACK
, (p_time
>= ranged_att
? 0 : ranged_att
- p_time
) );
670 if(uint32 off_att
= getAttackTimer(OFF_ATTACK
))
672 setAttackTimer(OFF_ATTACK
, (p_time
>= off_att
? 0 : off_att
- p_time
) );
675 time_t now
= time (NULL
);
677 UpdatePVPFlag(time(NULL
));
681 CheckExploreSystem();
683 if (m_timedquests
.size() > 0)
685 list
<uint32
>::iterator iter
= m_timedquests
.begin();
686 while (iter
!= m_timedquests
.end())
688 //if( mQuestStatus[*iter].m_timer > 0 )
690 if( mQuestStatus
[*iter
].m_timer
<= p_time
)
692 FailTimedQuest( *iter
);
693 iter
= m_timedquests
.begin();
697 mQuestStatus
[*iter
].m_timer
-= p_time
;
706 Unit
*pVictim
= getVictim();
707 if( m_currentSpell
== 0 && pVictim
)
710 // default combat reach 10
711 // TODO add weapon,skill check
713 float pldistance
= 5.0f
;
715 /*if(getClass() == WARRIOR)
718 if(GetItemByPos( INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND ) != 0)
721 if(GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_HANDS) != 0)
724 if (isAttackReady(BASE_ATTACK
))
726 if(!IsWithinDist(pVictim
, pldistance
))
728 setAttackTimer(BASE_ATTACK
,1000);
729 SendAttackSwingNotInRange();
731 //120 degreas of radiant range
732 else if( !HasInArc( 2*M_PI
/3, pVictim
))
734 setAttackTimer(BASE_ATTACK
,1000);
735 SendAttackSwingBadFacingAttack();
739 // prevent base and off attack in same time, delay attack at 0.2 sec
740 if(haveOffhandWeapon())
742 uint32 off_att
= getAttackTimer(OFF_ATTACK
);
743 if(off_att
< ATTACK_DISPLAY_DELAY
)
744 setAttackTimer(OFF_ATTACK
,ATTACK_DISPLAY_DELAY
);
746 AttackerStateUpdate(pVictim
, BASE_ATTACK
);
747 resetAttackTimer(BASE_ATTACK
);
751 if ( haveOffhandWeapon() && isAttackReady(OFF_ATTACK
))
753 if(! IsWithinDist(pVictim
, pldistance
))
755 setAttackTimer(OFF_ATTACK
,1000);
757 else if( !HasInArc( 2*M_PI
/3, pVictim
))
759 setAttackTimer(OFF_ATTACK
,1000);
763 // prevent base and off attack in same time, delay attack at 0.2 sec
764 uint32 base_att
= getAttackTimer(BASE_ATTACK
);
765 if(base_att
< ATTACK_DISPLAY_DELAY
)
766 setAttackTimer(BASE_ATTACK
,ATTACK_DISPLAY_DELAY
);
768 AttackerStateUpdate(pVictim
, OFF_ATTACK
);
769 resetAttackTimer(OFF_ATTACK
);
775 else if (isAttacked())
777 // Leave here so we don't forget this case
778 // Attacked, but not necessarily attacking
782 // Leave here so we don't forget this case
783 // Not attacking or attacked
786 if(HasFlag(PLAYER_FLAGS
, PLAYER_FLAGS_RESTING
))
789 if(GetRestType()==1) //rest in tavern
791 if(sqrt((GetPositionX()-GetInnPosX())*(GetPositionX()-GetInnPosX())+(GetPositionY()-GetInnPosY())*(GetPositionY()-GetInnPosY())+(GetPositionZ()-GetInnPosZ())*(GetPositionZ()-GetInnPosZ()))>40)
793 //speed collect rest bonus (section/in hour)
794 float bubble
=1; //0% Blizzlike
795 if(GetTimeInnEter()>0)SetRestBonus( GetRestBonus()+ (time(NULL
)-GetTimeInnEter())*0.0142108*bubble
);
796 RemoveFlag(PLAYER_FLAGS
, PLAYER_FLAGS_RESTING
);
803 if(p_time
>= m_regenTimer
)
806 m_regenTimer
-= p_time
;
814 if (m_deathState
== JUST_DIED
)
824 if( GetSoulStoneSpell() && GetSoulStone())
826 SpellEntry
*spellInfo
= sSpellStore
.LookupEntry(GetSoulStoneSpell());
829 Spell
spell(this, spellInfo
, true, 0);
831 SpellCastTargets targets
;
832 targets
.setUnitTarget( this );
833 spell
.m_CastItem
= GetSoulStone();
834 spell
.prepare(&targets
);
837 SetSoulStoneSpell(0);
843 if(p_time
>= m_nextSave
)
845 m_nextSave
= sWorld
.getConfig(CONFIG_INTERVAL_SAVE
);
847 sLog
.outBasic("Player '%u' '%s' Saved", GetGUIDLow(), GetName());
851 m_nextSave
-= p_time
;
856 if(m_breathTimer
> 0)
858 if(p_time
>= m_breathTimer
)
861 m_breathTimer
-= p_time
;
865 //Handle Water/drowning
866 HandleDrowing(60000);
872 if (now
> m_Last_tick
)
874 uint32 elapsed
= uint32(now
- m_Last_tick
);
875 m_Played_time
[0] += elapsed
; // Total played time
876 m_Played_time
[1] += elapsed
; // Level played time
882 m_drunkTimer
+= p_time
;
884 if (m_drunkTimer
> 30000)
890 if(p_time
>= m_deathTimer
)
897 m_deathTimer
-= p_time
;
899 UpdateEnchantTime(p_time
);
902 void Player::BuildEnumData( WorldPacket
* p_data
)
904 *p_data
<< GetGUID();
907 *p_data
<< getRace();
908 *p_data
<< getClass();
909 *p_data
<< getGender();
911 uint32 bytes
= GetUInt32Value(PLAYER_BYTES
);
912 *p_data
<< uint8(bytes
);
913 *p_data
<< uint8(bytes
>> 8);
914 *p_data
<< uint8(bytes
>> 16);
915 *p_data
<< uint8(bytes
>> 24);
917 bytes
= GetUInt32Value(PLAYER_BYTES_2
);
918 *p_data
<< uint8(bytes
);
920 *p_data
<< uint8(getLevel()); //1
921 uint32 zoneId
= MapManager::Instance ().GetMap(m_mapId
)->GetZoneId(m_positionX
,m_positionY
);
924 *p_data
<< GetMapId();
926 *p_data
<< m_positionX
;
927 *p_data
<< m_positionY
;
928 *p_data
<< m_positionZ
;
930 *p_data
<< GetUInt32Value(PLAYER_GUILDID
); //probebly wrong
932 //*p_data << GetUInt32Value(PLAYER_GUILDRANK); //this was
933 *p_data
<< uint8(0x0);
934 *p_data
<< uint8(GetUInt32Value(PLAYER_FLAGS
) << 1);
935 *p_data
<< uint8(0x0); //Bit 4 is something dono
936 *p_data
<< uint8(0x0); //is this player_GUILDRANK????
939 *p_data
<< (uint32
)m_petInfoId
;
940 *p_data
<< (uint32
)m_petLevel
;
941 *p_data
<< (uint32
)m_petFamilyId
;
943 ItemPrototype
const *items
[EQUIPMENT_SLOT_END
];
944 for (int i
= 0; i
< EQUIPMENT_SLOT_END
; i
++)
947 QueryResult
*result
= sDatabase
.PQuery("SELECT `slot`,`item_template` FROM `character_inventory` WHERE `guid` = '%u' AND `bag` = '%u'",GetGUIDLow(),INVENTORY_SLOT_BAG_0
);
952 Field
*fields
= result
->Fetch();
953 uint8 slot
= fields
[0].GetUInt8() & 255;
954 uint32 item_id
= fields
[1].GetUInt32();
955 if( slot
>= EQUIPMENT_SLOT_END
)
958 items
[slot
] = objmgr
.GetItemPrototype(item_id
);
961 sLog
.outError( "Player::BuildEnumData: Player %s have unknown item (id: #%u) in inventory, skipped.", GetName(),item_id
);
964 } while (result
->NextRow());
968 for (int i
= 0; i
< EQUIPMENT_SLOT_END
; i
++)
970 if (items
[i
] != NULL
)
972 *p_data
<< (uint32
)items
[i
]->DisplayInfoID
;
973 *p_data
<< (uint8
)items
[i
]->InventoryType
;
977 *p_data
<< (uint32
)0;
981 // EQUIPMENT_SLOT_END always 0,0
982 *p_data
<< (uint32
)0;
986 bool Player::ToggleAFK()
988 if(HasFlag(PLAYER_FLAGS
,PLAYER_FLAGS_AFK
))
989 RemoveFlag(PLAYER_FLAGS
,PLAYER_FLAGS_AFK
);
992 // to prevent show <AFK> in invisiable mode
994 SetFlag(PLAYER_FLAGS
,PLAYER_FLAGS_AFK
);
996 GetSession()->SendNotification("You invisible currently!");
999 return HasFlag(PLAYER_FLAGS
,PLAYER_FLAGS_AFK
);
1002 bool Player::ToggleDND()
1004 if(HasFlag(PLAYER_FLAGS
,PLAYER_FLAGS_DND
))
1005 RemoveFlag(PLAYER_FLAGS
,PLAYER_FLAGS_DND
);
1008 // to prevent show <DND> in invisiable mode
1010 SetFlag(PLAYER_FLAGS
,PLAYER_FLAGS_DND
);
1012 GetSession()->SendNotification("You invisible currently!");
1015 return HasFlag(PLAYER_FLAGS
,PLAYER_FLAGS_DND
);
1018 uint8
Player::chatTag()
1030 void Player::SendFriendlist()
1036 FriendStr friendstr
[255];
1038 QueryResult
*result
= sDatabase
.PQuery("SELECT `friend` FROM `character_social` WHERE `flags` = 'FRIEND' AND `guid` = '%u'",GetGUIDLow());
1041 fields
= result
->Fetch();
1045 friendstr
[i
].PlayerGUID
= fields
[0].GetUInt64();
1046 pObj
= ObjectAccessor::Instance().FindPlayer(friendstr
[i
].PlayerGUID
);
1047 if( pObj
&& pObj
->isGMVisibleFor(this))
1050 friendstr
[i
].Status
= 2;
1051 else if(pObj
->isDND())
1052 friendstr
[i
].Status
= 4;
1054 friendstr
[i
].Status
= 1;
1055 friendstr
[i
].Area
= pObj
->GetZoneId();
1056 friendstr
[i
].Level
= pObj
->getLevel();
1057 friendstr
[i
].Class
= pObj
->getClass();
1061 friendstr
[i
].Status
= 0;
1062 friendstr
[i
].Area
= 0;
1063 friendstr
[i
].Level
= 0;
1064 friendstr
[i
].Class
= 0;
1071 } while( result
->NextRow() );
1076 data
.Initialize( SMSG_FRIEND_LIST
);
1079 for (int j
=0; j
< i
; j
++)
1082 sLog
.outDetail( "WORLD: Adding Friend Guid: %u, Status:%u, Area:%u, Level:%u Class:%u",GUID_LOPART(friendstr
[j
].PlayerGUID
), friendstr
[j
].Status
, friendstr
[j
].Area
,friendstr
[j
].Level
,friendstr
[j
].Class
);
1084 data
<< friendstr
[j
].PlayerGUID
<< friendstr
[j
].Status
;
1085 if (friendstr
[j
].Status
!= 0)
1086 data
<< friendstr
[j
].Area
<< friendstr
[j
].Level
<< friendstr
[j
].Class
;
1089 this->GetSession()->SendPacket( &data
);
1090 sLog
.outDebug( "WORLD: Sent (SMSG_FRIEND_LIST)" );
1093 void Player::SendIgnorelist()
1097 unsigned char nrignore
=0;
1101 QueryResult
*result
= sDatabase
.PQuery("SELECT COUNT(`friend`) FROM `character_social` WHERE `flags` = 'IGNORE' AND `guid` = '%u'", GetGUIDLow());
1105 fields
= result
->Fetch();
1106 nrignore
=fields
[0].GetUInt32();
1109 dataI
.Initialize( SMSG_IGNORE_LIST
);
1112 result
= sDatabase
.PQuery("SELECT `friend` FROM `character_social` WHERE `flags` = 'IGNORE' AND `guid` = '%u'", GetGUIDLow());
1119 fields
= result
->Fetch();
1120 dataI
<< fields
[0].GetUInt64();
1122 }while( result
->NextRow() );
1125 this->GetSession()->SendPacket( &dataI
);
1126 sLog
.outDebug( "WORLD: Sent (SMSG_IGNORE_LIST)" );
1129 void Player::TeleportTo(uint32 mapid
, float x
, float y
, float z
, float orientation
, bool outofrange
)
1131 if(this->GetMapId() == mapid
)
1135 BuildTeleportAckMsg(&data
, x
, y
, z
, orientation
);
1136 GetSession()->SendPacket(&data
);
1137 SetPosition( x
, y
, z
, orientation
);
1138 BuildHeartBeatMsg(&data
);
1139 SendMessageToSet(&data
, true);
1143 MapManager::Instance().GetMap(GetMapId())->Remove(this, false);
1145 data
.Initialize(SMSG_TRANSFER_PENDING
);
1146 data
<< uint32(mapid
);
1147 GetSession()->SendPacket(&data
);
1149 data
.Initialize(SMSG_NEW_WORLD
);
1150 data
<< (uint32
)mapid
<< (float)x
<< (float)y
<< (float)z
<< (float)orientation
;
1151 GetSession()->SendPacket( &data
);
1154 Relocate(x
,y
,z
,orientation
);
1155 SetPosition(x
,y
,z
,orientation
);
1159 MapManager::Instance().GetMap(GetMapId())->Add(this);
1161 // Resend spell list to client after far teleport.
1162 SendInitialSpells();
1172 Unit
* unit
= ObjectAccessor::Instance().GetUnit(*this, GetSelection());
1174 SendOutOfRange(unit
);
1177 // unsommon pet if lost
1178 Creature
* pet
= GetPet();
1180 if(!IsWithinDistInMap(pet
, OWNER_MAX_DISTANCE
))
1185 void Player::AddToWorld()
1187 Object::AddToWorld();
1189 for(int i
= 0; i
< BANK_SLOT_BAG_END
; i
++)
1192 m_items
[i
]->AddToWorld();
1196 if(Corpse
* corpse
= GetCorpse())
1197 corpse
->UpdateForPlayer(this,true);
1200 void Player::RemoveFromWorld()
1203 for(int i
= 0; i
< BANK_SLOT_BAG_END
; i
++)
1206 m_items
[i
]->RemoveFromWorld();
1209 Object::RemoveFromWorld();
1212 void Player::CalcRage( uint32 damage
,bool attacker
)
1217 addRage
= (uint32
)(10*damage
/(getLevel()*0.5f
));
1219 addRage
= (uint32
)(10*damage
/(getLevel()*1.5f
));
1221 ModifyPower(POWER_RAGE
, addRage
);
1224 void Player::RegenerateAll()
1227 if (m_regenTimer
!= 0)
1229 uint32 regenDelay
= 2000;
1231 // Not in combat or they have regeneration
1232 if (!isInCombat() || HasAuraType(SPELL_AURA_MOD_REGEN_DURING_COMBAT
))
1236 Regenerate(POWER_RAGE
);
1239 Regenerate( POWER_ENERGY
);
1240 Regenerate( POWER_MANA
);
1242 m_regenTimer
= regenDelay
;
1246 void Player::Regenerate(Powers power
)
1248 uint32 curValue
= GetPower(power
);
1249 uint32 maxValue
= GetMaxPower(power
);
1251 if(power
!= POWER_RAGE
)
1253 if (curValue
>= maxValue
) return;
1255 else if (curValue
== 0)
1258 float ManaIncreaseRate
= sWorld
.getRate(RATE_POWER_MANA
);
1259 float RageIncreaseRate
= sWorld
.getRate(RATE_POWER_RAGE
);
1261 float Spirit
= GetStat(STAT_SPIRIT
);
1262 uint8 Class
= getClass();
1264 if( ManaIncreaseRate
<= 0 ) ManaIncreaseRate
= 1;
1265 if( RageIncreaseRate
<= 0 ) RageIncreaseRate
= 1;
1267 float addvalue
= 0.0;
1272 // If < 5s after previous cast which used mana, no regeneration unless
1273 // we happen to have a modifer that adds it back
1274 // If > 5s, get portion between the 5s and now, up to a maximum of 2s worth
1275 uint32 msecSinceLastCast
;
1276 msecSinceLastCast
= ((uint32
)getMSTime() - m_lastManaUse
);
1277 if (msecSinceLastCast
>= 7000)
1279 ManaIncreaseRate
*= 1;
1283 long regenInterrupt
= GetTotalAuraModifier(SPELL_AURA_MOD_MANA_REGEN_INTERRUPT
);
1284 if (msecSinceLastCast
< 5000)
1286 ManaIncreaseRate
*= (float)regenInterrupt
/ 100;
1290 ManaIncreaseRate
= (((1 - (float)(msecSinceLastCast
- 5000)/2000)) * regenInterrupt
)
1291 + (((float)(msecSinceLastCast
- 5000)/2000) * ManaIncreaseRate
* 100);
1292 ManaIncreaseRate
/= 100;
1295 ManaIncreaseRate
= (ManaIncreaseRate
* 100 + GetTotalAuraModifier(SPELL_AURA_MOD_POWER_REGEN_PERCENT
)) / 100;
1299 case DRUID
: addvalue
= (Spirit
/5 + 15) * ManaIncreaseRate
; break;
1300 case HUNTER
: addvalue
= (Spirit
/5 + 15) * ManaIncreaseRate
; break;
1301 case MAGE
: addvalue
= (Spirit
/4 + 12.5) * ManaIncreaseRate
; break;
1302 case PALADIN
: addvalue
= (Spirit
/5 + 15) * ManaIncreaseRate
; break;
1303 case PRIEST
: addvalue
= (Spirit
/4 + 12.5) * ManaIncreaseRate
; break;
1304 case SHAMAN
: addvalue
= (Spirit
/5 + 17) * ManaIncreaseRate
; break;
1305 case WARLOCK
: addvalue
= (Spirit
/5 + 15) * ManaIncreaseRate
; break;
1308 case POWER_RAGE
: // Regenerate rage
1309 addvalue
= 30 * RageIncreaseRate
; // 3 rage by tick
1311 case POWER_ENERGY
: // Regenerate energy (rogue)
1315 case POWER_HAPPINESS
:
1319 if (power
!= POWER_RAGE
)
1321 curValue
+= uint32(addvalue
);
1322 if (curValue
> maxValue
) curValue
= maxValue
;
1326 if(curValue
<= uint32(addvalue
))
1329 curValue
-= uint32(addvalue
);
1331 SetPower(power
, curValue
);
1334 void Player::RegenerateHealth()
1336 uint32 curValue
= GetHealth();
1337 uint32 maxValue
= GetMaxHealth();
1339 if (curValue
>= maxValue
) return;
1341 float HealthIncreaseRate
= sWorld
.getRate(RATE_HEALTH
);
1343 float Spirit
= GetStat(STAT_SPIRIT
);
1344 uint8 Class
= getClass();
1346 if( HealthIncreaseRate
<= 0 ) HealthIncreaseRate
= 1;
1348 float addvalue
= 0.0;
1352 case DRUID
: addvalue
= (Spirit
*0.11 + 1) * HealthIncreaseRate
; break;
1353 case HUNTER
: addvalue
= (Spirit
*0.43 - 5.5) * HealthIncreaseRate
; break;
1354 case MAGE
: addvalue
= (Spirit
*0.11 + 1) * HealthIncreaseRate
; break;
1355 case PALADIN
: addvalue
= (Spirit
*0.25) * HealthIncreaseRate
; break;
1356 case PRIEST
: addvalue
= (Spirit
*0.15 + 1.4) * HealthIncreaseRate
; break;
1357 case ROGUE
: addvalue
= (Spirit
*0.84 - 13) * HealthIncreaseRate
; break;
1358 case SHAMAN
: addvalue
= (Spirit
*0.28 - 3.6) * HealthIncreaseRate
; break;
1359 case WARLOCK
: addvalue
= (Spirit
*0.12 + 1.5) * HealthIncreaseRate
; break;
1360 case WARRIOR
: addvalue
= (Spirit
*1.26 - 22.6) * HealthIncreaseRate
; break;
1365 AuraList
& mModHealthRegenPct
= GetAurasByType(SPELL_AURA_MOD_HEALTH_REGEN_PERCENT
);
1366 for(AuraList::iterator i
= mModHealthRegenPct
.begin(); i
!= mModHealthRegenPct
.end(); ++i
)
1367 addvalue
*= (100.0f
+ (*i
)->GetModifier()->m_amount
) / 100.0f
;
1370 addvalue
*= m_AuraModifiers
[SPELL_AURA_MOD_REGEN_DURING_COMBAT
] / 100.0f
;
1372 switch (getStandState())
1374 case PLAYER_STATE_SIT_CHAIR
:
1375 case PLAYER_STATE_SIT_LOW_CHAIR
:
1376 case PLAYER_STATE_SIT_MEDIUM_CHAIR
:
1377 case PLAYER_STATE_SIT_HIGH_CHAIR
:
1378 case PLAYER_STATE_SIT
:
1379 case PLAYER_STATE_SLEEP
:
1380 case PLAYER_STATE_KNEEL
:
1381 addvalue
*= 1.5; break;
1383 ModifyHealth(int32(addvalue
));
1386 bool Player::isAcceptTickets() const
1388 return GetSession()->GetSecurity() >=2 && (m_GMFlags
& GM_ACCEPT_TICKETS
);
1391 void Player::SetGameMaster(bool on
)
1397 SetFlag(PLAYER_BYTES_2
, 0x8);
1399 // to prevent show <GM> in invisible mode
1401 SetFlag(PLAYER_FLAGS
, PLAYER_FLAGS_GM
);
1405 m_GMFlags
&= ~GM_ON
;
1406 setFactionForRace(getRace());
1407 RemoveFlag(PLAYER_BYTES_2
, 0x8);
1408 RemoveFlag(PLAYER_FLAGS
, PLAYER_FLAGS_GM
);
1412 void Player::SetGMVisible(bool on
)
1416 m_GMFlags
&= ~GM_INVISIBLE
; //remove flag
1418 // if in GM mode show <GM> befire removing invisibility
1420 SetFlag(PLAYER_FLAGS
, PLAYER_FLAGS_GM
);
1423 RemoveAura(10032,1); //crash?
1428 m_GMFlags
|= GM_INVISIBLE
; //add flag
1430 // remove <AFK> before go to invisible mode
1434 // remove <DND> before go to invisible mode
1438 SetAcceptWhispers(false);
1439 SetGameMaster(true); // <GM> wiil be not added
1441 SetUInt32Value(UNIT_FIELD_DISPLAYID
, 6908); //Set invisible model
1444 SpellEntry
*spellInfo
= sSpellStore
.LookupEntry( 10032 );
1445 Aura
*Aur
= new Aura(spellInfo
, 1, this);
1449 // hide or show name
1450 GetSession()->SendNameQueryOpcode(this,true);
1453 void Player::SendLogXPGain(uint32 GivenXP
, Unit
* victim
, uint32 RestXP
)
1456 data
.Initialize( SMSG_LOG_XPGAIN
);
1457 data
<< ( victim
? victim
->GetGUID() : uint64(0) );
1458 data
<< uint32(GivenXP
+RestXP
); // given experience
1459 data
<< ( victim
? (uint8
)0 : (uint8
)1 ); // 00-kill_xp type, 01-non_kill_xp type
1460 data
<< uint32(RestXP
); // rested given experience
1461 data
<< float(1); // 1 - none 0 - 100% group bonus output
1462 GetSession()->SendPacket(&data
);
1465 void Player::GiveXP(uint32 xp
, Unit
* victim
)
1470 uint32 level
= getLevel();
1472 // XP to money conversion processed in Player::RewardQuest
1473 if(level
>= sWorld
.getConfig(CONFIG_MAX_PLAYER_LEVEL
))
1476 // XP resting bonus for kill
1477 uint32 rested_bonus_xp
= victim
? GetXPRestBonus(xp
) : 0;
1479 SendLogXPGain(xp
,victim
,rested_bonus_xp
);
1481 uint32 curXP
= GetUInt32Value(PLAYER_XP
);
1482 uint32 nextLvlXP
= GetUInt32Value(PLAYER_NEXT_LEVEL_XP
);
1483 uint32 newXP
= curXP
+ xp
+ rested_bonus_xp
;
1485 while( newXP
>= nextLvlXP
&& level
< sWorld
.getConfig(CONFIG_MAX_PLAYER_LEVEL
) )
1492 nextLvlXP
= GetUInt32Value(PLAYER_NEXT_LEVEL_XP
);
1495 SetUInt32Value(PLAYER_XP
, newXP
);
1498 // Update player to next level
1499 // Current player expirience not update (must be update by caller)
1500 void Player::GiveLevel()
1502 uint32 MPGain
,HPGain
;
1505 uint32 level
= getLevel();
1507 if ( level
>= sWorld
.getConfig(CONFIG_MAX_PLAYER_LEVEL
) )
1512 // Remove item, aura, stats bonuses
1513 _RemoveAllItemMods();
1514 _RemoveAllAuraMods();
1518 float newMP
= (getClass() == WARRIOR
|| getClass() == ROGUE
) ? 0 : GetMaxPower(POWER_MANA
);
1520 float newHP
= GetMaxHealth();
1522 float newStats
[MAX_STATS
];
1524 for(int i
= STAT_STRENGTH
; i
< MAX_STATS
; ++i
)
1525 newStats
[i
] = GetStat(Stats(i
));
1527 uint32 gainStats
[MAX_STATS
];
1529 for(int i
= STAT_STRENGTH
; i
< MAX_STATS
; ++i
)
1533 BuildLvlUpStats(&gainStats
);
1536 for(int i
= STAT_STRENGTH
; i
< MAX_STATS
; ++i
)
1537 newStats
[i
] += gainStats
[i
];
1539 MPGain
= (getClass() == WARRIOR
|| getClass() == ROGUE
) ? 0 : uint32(newStats
[STAT_SPIRIT
] / 2);
1540 HPGain
= uint32(newStats
[STAT_STAMINA
] / 2);
1545 // update level, talants, max level of skills
1547 SetUInt32Value(PLAYER_NEXT_LEVEL_XP
, MaNGOS::XP::xp_to_level(level
));
1550 SetUInt32Value(PLAYER_CHARACTER_POINTS1
,GetUInt32Value(PLAYER_CHARACTER_POINTS1
)+1);
1555 if(getClass() != WARRIOR
&& getClass() != ROGUE
)
1557 SetPower( POWER_MANA
, uint32(newMP
)); // only integer part
1558 SetMaxPower(POWER_MANA
, uint32(newMP
)); // only integer part
1561 SetHealth( uint32(newHP
)); // only integer part
1562 SetMaxHealth(uint32(newHP
)); // only integer part
1564 for(int i
= STAT_STRENGTH
; i
< MAX_STATS
; ++i
)
1565 SetStat(Stats(i
), uint32(newStats
[i
])); // only integer part
1567 // update dependent from level part BlockChanceWithoutMods = 5 + (GetDefenceSkillValue() - getLevel()*5)*0.04);
1568 UpdateBlockPercentage(0,1);
1570 // apply stats, aura, items mods
1572 _ApplyAllAuraMods();
1573 _ApplyAllItemMods();
1575 // send levelup info to client
1577 data
.Initialize(SMSG_LEVELUP_INFO
);
1578 data
<< uint32(level
);
1579 data
<< uint32(HPGain
);
1580 data
<< uint32(MPGain
);
1586 for(int i
= STAT_STRENGTH
; i
< MAX_STATS
; ++i
)
1587 data
<< uint32(gainStats
[i
]);
1589 WPAssert(data
.size() == 48);
1590 GetSession()->SendPacket(&data
);
1592 // Level Played Time reset
1593 m_Played_time
[1] = 0;
1596 void Player::BuildLvlUpStats(uint32 (*gainStats
)[MAX_STATS
])
1598 uint8 _class
= getClass();
1599 uint8 lvl
= getLevel();
1600 uint8 race
= getRace();
1602 if (lvl
< sWorld
.getConfig(CONFIG_MAX_PLAYER_LEVEL
))
1604 for(int i
= STAT_STRENGTH
; i
< MAX_STATS
; ++i
)
1605 (*gainStats
)[i
] += objmgr
.GetLevelUpStatGain(_class
,race
,lvl
,Stats(i
));
1612 (*gainStats
)[STAT_STRENGTH
] += (lvl
> 23 ? 2: (lvl
> 1 ? 1: 0));
1613 (*gainStats
)[STAT_STAMINA
] += (lvl
> 23 ? 2: (lvl
> 1 ? 1: 0));
1614 (*gainStats
)[STAT_AGILITY
] += (lvl
> 36 ? 1: (lvl
> 6 && (lvl
%2) ? 1: 0));
1615 (*gainStats
)[STAT_INTELLECT
] += (lvl
> 9 && !(lvl
%2) ? 1: 0);
1616 (*gainStats
)[STAT_SPIRIT
] += (lvl
> 9 && !(lvl
%2) ? 1: 0);
1619 (*gainStats
)[STAT_STRENGTH
] += (lvl
> 3 ? 1: 0);
1620 (*gainStats
)[STAT_STAMINA
] += (lvl
> 33 ? 2: (lvl
> 1 ? 1: 0));
1621 (*gainStats
)[STAT_AGILITY
] += (lvl
> 38 ? 1: (lvl
> 7 && !(lvl
%2) ? 1: 0));
1622 (*gainStats
)[STAT_INTELLECT
] += (lvl
> 6 && (lvl
%2) ? 1: 0);
1623 (*gainStats
)[STAT_SPIRIT
] += (lvl
> 7 ? 1: 0);
1626 (*gainStats
)[STAT_STRENGTH
] += (lvl
> 4 ? 1: 0);
1627 (*gainStats
)[STAT_STAMINA
] += (lvl
> 4 ? 1: 0);
1628 (*gainStats
)[STAT_AGILITY
] += (lvl
> 33 ? 2: (lvl
> 1 ? 1: 0));
1629 (*gainStats
)[STAT_INTELLECT
] += (lvl
> 8 && (lvl
%2) ? 1: 0);
1630 (*gainStats
)[STAT_SPIRIT
] += (lvl
> 38 ? 1: (lvl
> 9 && !(lvl
%2) ? 1: 0));
1633 (*gainStats
)[STAT_STRENGTH
] += (lvl
> 5 ? 1: 0);
1634 (*gainStats
)[STAT_STAMINA
] += (lvl
> 4 ? 1: 0);
1635 (*gainStats
)[STAT_AGILITY
] += (lvl
> 16 ? 2: (lvl
> 1 ? 1: 0));
1636 (*gainStats
)[STAT_INTELLECT
] += (lvl
> 8 && !(lvl
%2) ? 1: 0);
1637 (*gainStats
)[STAT_SPIRIT
] += (lvl
> 38 ? 1: (lvl
> 9 && !(lvl
%2) ? 1: 0));
1640 (*gainStats
)[STAT_STRENGTH
] += (lvl
> 9 && !(lvl
%2) ? 1: 0);
1641 (*gainStats
)[STAT_STAMINA
] += (lvl
> 5 ? 1: 0);
1642 (*gainStats
)[STAT_AGILITY
] += (lvl
> 38 ? 1: (lvl
> 8 && (lvl
%2) ? 1: 0));
1643 (*gainStats
)[STAT_INTELLECT
] += (lvl
> 22 ? 2: (lvl
> 1 ? 1: 0));
1644 (*gainStats
)[STAT_SPIRIT
] += (lvl
> 3 ? 1: 0);
1647 (*gainStats
)[STAT_STRENGTH
] += (lvl
> 34 ? 1: (lvl
> 6 && (lvl
%2) ? 1: 0));
1648 (*gainStats
)[STAT_STAMINA
] += (lvl
> 4 ? 1: 0);
1649 (*gainStats
)[STAT_AGILITY
] += (lvl
> 7 && !(lvl
%2) ? 1: 0);
1650 (*gainStats
)[STAT_INTELLECT
] += (lvl
> 5 ? 1: 0);
1651 (*gainStats
)[STAT_SPIRIT
] += (lvl
> 4 ? 1: 0);
1654 (*gainStats
)[STAT_STRENGTH
] += (lvl
> 9 && !(lvl
%2) ? 1: 0);
1655 (*gainStats
)[STAT_STAMINA
] += (lvl
> 5 ? 1: 0);
1656 (*gainStats
)[STAT_AGILITY
] += (lvl
> 9 && !(lvl
%2) ? 1: 0);
1657 (*gainStats
)[STAT_INTELLECT
] += (lvl
> 24 ? 2: (lvl
> 1 ? 1: 0));
1658 (*gainStats
)[STAT_SPIRIT
] += (lvl
> 33 ? 2: (lvl
> 2 ? 1: 0));
1661 (*gainStats
)[STAT_STRENGTH
] += (lvl
> 9 && !(lvl
%2) ? 1: 0);
1662 (*gainStats
)[STAT_STAMINA
] += (lvl
> 38 ? 2: (lvl
> 3 ? 1: 0));
1663 (*gainStats
)[STAT_AGILITY
] += (lvl
> 9 && !(lvl
%2) ? 1: 0);
1664 (*gainStats
)[STAT_INTELLECT
] += (lvl
> 33 ? 2: (lvl
> 2 ? 1: 0));
1665 (*gainStats
)[STAT_SPIRIT
] += (lvl
> 38 ? 2: (lvl
> 3 ? 1: 0));
1668 (*gainStats
)[STAT_STRENGTH
] += (lvl
> 38 ? 2: (lvl
> 6 && (lvl
%2) ? 1: 0));
1669 (*gainStats
)[STAT_STAMINA
] += (lvl
> 32 ? 2: (lvl
> 4 ? 1: 0));
1670 (*gainStats
)[STAT_AGILITY
] += (lvl
> 38 ? 2: (lvl
> 8 && (lvl
%2) ? 1: 0));
1671 (*gainStats
)[STAT_INTELLECT
] += (lvl
> 38 ? 3: (lvl
> 4 ? 1: 0));
1672 (*gainStats
)[STAT_SPIRIT
] += (lvl
> 38 ? 3: (lvl
> 5 ? 1: 0));
1677 void Player::SendInitialSpells()
1680 uint16 spellCount
= 0;
1682 PlayerSpellMap::const_iterator itr
;
1684 for (itr
= m_spells
.begin(); itr
!= m_spells
.end(); ++itr
)
1686 if(itr
->second
->state
== PLAYERSPELL_REMOVED
)
1689 if(itr
->second
->active
)
1693 data
.Initialize( SMSG_INITIAL_SPELLS
);
1695 data
<< uint16(spellCount
);
1697 for (itr
= m_spells
.begin(); itr
!= m_spells
.end(); ++itr
)
1699 if(itr
->second
->state
== PLAYERSPELL_REMOVED
)
1702 if(!itr
->second
->active
)
1705 data
<< uint16(itr
->first
);
1706 data
<< uint16(itr
->second
->slotId
);
1710 WPAssert(data
.size() == 5+(4*size_t(spellCount
)));
1712 GetSession()->SendPacket(&data
);
1714 sLog
.outDetail( "CHARACTER: Sent Initial Spells" );
1717 void Player::RemoveMail(uint32 id
)
1719 std::list
<Mail
*>::iterator itr
;
1720 for (itr
= m_mail
.begin(); itr
!= m_mail
.end();)
1722 if ((*itr
)->messageID
== id
)
1724 //do not delete item. beacuse Player::removeMail() is called when returning mail to sender.
1725 m_mail
.erase(itr
++);
1734 //called when mail's state changed, removes mail and adds it to the end - mails are sorted
1735 void Player::SetMail(Mail
*m
)
1740 std::list
<Mail
*>::iterator itr
;
1741 for (itr
= m_mail
.begin(); itr
!= m_mail
.end();)
1743 if ((*itr
)->messageID
== m
->messageID
)
1744 m_mail
.erase(itr
++);
1748 m_mail
.push_back(m
); //insert to the end
1751 //call this function only when sending new mail
1752 void Player::AddMail(Mail
*m
)
1756 data
.Initialize(SMSG_RECEIVED_MAIL
);
1758 GetSession()->SendPacket(&data
);
1764 std::list
<Mail
*>::iterator itr
;
1765 for (itr
= m_mail
.begin(); itr
!= m_mail
.end();)
1767 if ((*itr
)->messageID
== m
->messageID
)
1769 m_mail
.erase(itr
++);
1776 m_mail
.push_front(m
); //to insert new mail to beginning of maillist
1779 bool Player::addSpell(uint16 spell_id
, uint8 active
, PlayerSpellState state
, uint16 slot_id
)
1781 SpellEntry
*spellInfo
= sSpellStore
.LookupEntry(spell_id
);
1784 sLog
.outError("Player::addSpell: Non-existed in SpellStore spell #%u request.",spell_id
);
1788 PlayerSpellMap::iterator itr
= m_spells
.find(spell_id
);
1789 if (itr
!= m_spells
.end())
1791 if (itr
->second
->state
== PLAYERSPELL_REMOVED
)
1794 m_spells
.erase(itr
);
1795 state
= PLAYERSPELL_CHANGED
;
1801 PlayerSpell
*newspell
;
1803 newspell
= new PlayerSpell
;
1804 newspell
->active
= active
;
1805 newspell
->state
= state
;
1808 if(newspell
->active
&& !canStackSpellRank(spellInfo
))
1810 PlayerSpellMap::iterator itr
;
1811 for (itr
= m_spells
.begin(); itr
!= m_spells
.end(); itr
++)
1813 if(itr
->second
->state
== PLAYERSPELL_REMOVED
) continue;
1814 SpellEntry
*i_spellInfo
= sSpellStore
.LookupEntry(itr
->first
);
1815 if(!i_spellInfo
) continue;
1817 if(IsRankSpellDueToSpell(spellInfo
,itr
->first
))
1819 if(itr
->second
->active
)
1821 data
.Initialize(SMSG_SUPERCEDED_SPELL
);
1823 if(FindSpellRank(spell_id
) >= FindSpellRank(itr
->first
))
1825 data
<< uint32(itr
->first
);
1826 data
<< uint32(spell_id
);
1827 itr
->second
->active
= 0;
1831 data
<< uint32(spell_id
);
1832 data
<< uint32(itr
->first
);
1833 newspell
->active
= 0;
1836 GetSession()->SendPacket( &data
);
1842 uint16 tmpslot
=slot_id
;
1844 if (tmpslot
== 0xffff)
1847 PlayerSpellMap::iterator itr
;
1848 for (itr
= m_spells
.begin(); itr
!= m_spells
.end(); ++itr
)
1850 if(itr
->second
->state
== PLAYERSPELL_REMOVED
) continue;
1851 if (itr
->second
->slotId
> maxid
) maxid
= itr
->second
->slotId
;
1853 tmpslot
= maxid
+ 1;
1856 newspell
->slotId
= tmpslot
;
1857 m_spells
[spell_id
] = newspell
;
1859 if (IsPassiveSpell(spell_id
))
1861 // if spell doesnt require a stance or the player is in the required stance
1862 if ((!spellInfo
->Stances
&& spell_id
!= 5419) || (spellInfo
->Stances
& (1<<(m_form
-1)) || (spell_id
== 5419 && m_form
== FORM_TRAVEL
)))
1863 CastSpell(this, spell_id
, true);
1869 void Player::learnSpell(uint16 spell_id
)
1871 SpellEntry
*spellInfo
= sSpellStore
.LookupEntry(spell_id
);
1874 sLog
.outError("Player::addSpell: Non-existed in SpellStore spell #%u request.",spell_id
);
1879 data
.Initialize(SMSG_LEARNED_SPELL
);
1880 data
<<uint32(spell_id
);
1881 GetSession()->SendPacket(&data
);
1883 if (!addSpell(spell_id
,1))
1886 uint16 maxskill
= getLevel()*5 > 300 ? 300 :getLevel()*5;
1893 case 9077: //Leather
1899 case 750: //Plate Mail
1907 SetSkill(44,1,maxskill
);
1909 case 197: //Two-Handed Axes
1910 SetSkill(172,1,maxskill
);
1913 SetSkill(136,1,maxskill
);
1916 SetSkill(54,1,maxskill
);
1918 case 199: //Two-Handed Maces
1919 SetSkill(160,1,maxskill
);
1922 SetSkill(43,1,maxskill
);
1924 case 202: //Two-Handed Swords
1925 SetSkill(55,1,maxskill
);
1927 case 1180: //Daggers
1928 SetSkill(173,1,maxskill
);
1930 case 15590: //Fist Weapons
1931 SetSkill(473,1,maxskill
);
1933 case 200: //Polearms
1934 SetSkill(229,1,maxskill
);
1936 case 3386: //Polearms
1937 SetSkill(227,1,maxskill
);
1941 SetSkill(45,1,maxskill
);
1943 case 5011: //Crossbows
1944 SetSkill(226,1,maxskill
);
1947 SetSkill(46,1,maxskill
);
1950 SetSkill(176,1,maxskill
);
1953 SetSkill(228,1,maxskill
);
1956 case 2842: //poisons
1957 SetSkill(40,1,maxskill
);
1964 SetSkill(109,1,300);
1967 SetSkill(115,1,300);
1970 SetSkill(113,1,300);
1973 SetSkill(111,1,300);
1976 SetSkill(137,1,300);
1979 SetSkill(138,1,300);
1982 SetSkill(139,1,300);
1985 SetSkill(140,1,300);
1988 SetSkill(141,1,300);
1991 SetSkill(313,1,300);
1994 SetSkill(315,1,300);
1997 SetSkill(673,1,300);
2003 bool Player::removeSpell(uint16 spell_id
)
2005 PlayerSpellMap::iterator itr
= m_spells
.find(spell_id
);
2006 if (itr
!= m_spells
.end())
2008 if(itr
->second
->state
== PLAYERSPELL_REMOVED
) return false;
2011 data
.Initialize(SMSG_REMOVED_SPELL
);
2013 GetSession()->SendPacket(&data
);
2015 if(itr
->second
->state
== PLAYERSPELL_NEW
)
2018 m_spells
.erase(itr
);
2021 itr
->second
->state
= PLAYERSPELL_REMOVED
;
2023 RemoveAurasDueToSpell(spell_id
);
2029 uint32
Player::resetTalentsCost() const
2031 // The first time reset costs 1 gold
2032 if(m_resetTalentsCost
< 1*GOLD
)
2035 else if(m_resetTalentsCost
< 5*GOLD
)
2037 // After that it increases in increments of 5 gold
2038 else if(m_resetTalentsCost
< 10*GOLD
)
2042 uint32 months
= (sWorld
.GetLastTickTime() - m_resetTalentsTime
)/MONTH
;
2045 // This cost will be reduced by a rate of 5 gold per month
2046 int32 new_cost
= int32(m_resetTalentsCost
) - 5*GOLD
*months
;
2047 // to a minimum of 10 gold.
2048 return (new_cost
< 10*GOLD
? 10*GOLD
: new_cost
);
2052 // After that it increases in increments of 5 gold
2053 int32 new_cost
= m_resetTalentsCost
+ 5*GOLD
;
2054 // until it hits a cap of 50 gold.
2055 if(new_cost
> 50*GOLD
)
2062 bool Player::resetTalents()
2064 uint32 level
= getLevel();
2065 if (level
< 10 || (GetUInt32Value(PLAYER_CHARACTER_POINTS1
) >= level
- 9))
2068 uint32 cost
= resetTalentsCost();
2070 if (GetMoney() < cost
)
2072 SendBuyError( BUY_ERR_NOT_ENOUGHT_MONEY
, 0, 0, 0);
2076 for (int i
= 0; i
< sTalentStore
.GetNumRows(); i
++)
2078 TalentEntry
*talentInfo
= sTalentStore
.LookupEntry(i
);
2079 if (!talentInfo
) continue;
2080 for (int j
= 0; j
< 5; j
++)
2082 SpellEntry
*spellInfo
= sSpellStore
.LookupEntry(talentInfo
->RankID
[j
]);
2083 if (!spellInfo
) continue;
2084 const PlayerSpellMap
& s_list
= GetSpellMap();
2085 for(PlayerSpellMap::const_iterator itr
= s_list
.begin(); itr
!= s_list
.end(); ++itr
)
2087 if(itr
->second
->state
== PLAYERSPELL_REMOVED
) continue;
2088 if (itr
->first
== spellInfo
->Id
)
2090 RemoveAurasDueToSpell(itr
->first
);
2091 removeSpell(itr
->first
);
2098 SetUInt32Value(PLAYER_CHARACTER_POINTS1
, level
- 9);
2099 ModifyMoney(-(int32
)cost
);
2101 m_resetTalentsCost
= cost
;
2102 m_resetTalentsTime
= time(NULL
);
2106 bool Player::_removeSpell(uint16 spell_id
)
2108 PlayerSpellMap::iterator itr
= m_spells
.find(spell_id
);
2109 if (itr
!= m_spells
.end())
2112 m_spells
.erase(itr
);
2118 Mail
* Player::GetMail(uint32 id
)
2120 std::list
<Mail
*>::iterator itr
;
2121 for (itr
= m_mail
.begin(); itr
!= m_mail
.end(); itr
++)
2123 if ((*itr
)->messageID
== id
)
2131 void Player::_SetCreateBits(UpdateMask
*updateMask
, Player
*target
) const
2135 Object::_SetCreateBits(updateMask
, target
);
2140 mask
.SetCount(m_valuesCount
);
2141 _SetVisibleBits(&mask
, target
);
2143 for(uint16 index
= 0; index
< m_valuesCount
; index
++)
2145 if(GetUInt32Value(index
) != 0 && mask
.GetBit(index
))
2146 updateMask
->SetBit(index
);
2151 void Player::_SetUpdateBits(UpdateMask
*updateMask
, Player
*target
) const
2155 Object::_SetUpdateBits(updateMask
, target
);
2160 mask
.SetCount(m_valuesCount
);
2161 _SetVisibleBits(&mask
, target
);
2163 Object::_SetUpdateBits(updateMask
, target
);
2164 *updateMask
&= mask
;
2168 void Player::_SetVisibleBits(UpdateMask
*updateMask
, Player
*target
) const
2170 updateMask
->SetBit(OBJECT_FIELD_GUID
);
2171 updateMask
->SetBit(OBJECT_FIELD_TYPE
);
2172 updateMask
->SetBit(OBJECT_FIELD_SCALE_X
);
2174 updateMask
->SetBit(UNIT_FIELD_SUMMON
);
2175 updateMask
->SetBit(UNIT_FIELD_SUMMON
+1);
2177 updateMask
->SetBit(UNIT_FIELD_TARGET
);
2178 updateMask
->SetBit(UNIT_FIELD_TARGET
+1);
2180 updateMask
->SetBit(UNIT_FIELD_HEALTH
);
2181 updateMask
->SetBit(UNIT_FIELD_POWER1
);
2182 updateMask
->SetBit(UNIT_FIELD_POWER2
);
2183 updateMask
->SetBit(UNIT_FIELD_POWER3
);
2184 updateMask
->SetBit(UNIT_FIELD_POWER4
);
2185 updateMask
->SetBit(UNIT_FIELD_POWER5
);
2187 updateMask
->SetBit(UNIT_FIELD_MAXHEALTH
);
2188 updateMask
->SetBit(UNIT_FIELD_MAXPOWER1
);
2189 updateMask
->SetBit(UNIT_FIELD_MAXPOWER2
);
2190 updateMask
->SetBit(UNIT_FIELD_MAXPOWER3
);
2191 updateMask
->SetBit(UNIT_FIELD_MAXPOWER4
);
2192 updateMask
->SetBit(UNIT_FIELD_MAXPOWER5
);
2194 updateMask
->SetBit(UNIT_FIELD_LEVEL
);
2195 updateMask
->SetBit(UNIT_FIELD_FACTIONTEMPLATE
);
2196 updateMask
->SetBit(UNIT_FIELD_BYTES_0
);
2197 updateMask
->SetBit(UNIT_FIELD_FLAGS
);
2198 for(uint16 i
= UNIT_FIELD_AURA
; i
< UNIT_FIELD_AURASTATE
; i
++)
2199 updateMask
->SetBit(i
);
2200 updateMask
->SetBit(UNIT_FIELD_BASEATTACKTIME
);
2201 updateMask
->SetBit(UNIT_FIELD_OFFHANDATTACKTIME
);
2202 updateMask
->SetBit(UNIT_FIELD_RANGEDATTACKTIME
);
2203 updateMask
->SetBit(UNIT_FIELD_BOUNDINGRADIUS
);
2204 updateMask
->SetBit(UNIT_FIELD_COMBATREACH
);
2205 updateMask
->SetBit(UNIT_FIELD_DISPLAYID
);
2206 updateMask
->SetBit(UNIT_FIELD_NATIVEDISPLAYID
);
2207 updateMask
->SetBit(UNIT_FIELD_MOUNTDISPLAYID
);
2208 updateMask
->SetBit(UNIT_FIELD_BYTES_1
);
2209 updateMask
->SetBit(UNIT_FIELD_MOUNTDISPLAYID
);
2210 updateMask
->SetBit(UNIT_FIELD_PETNUMBER
);
2211 updateMask
->SetBit(UNIT_FIELD_PET_NAME_TIMESTAMP
);
2212 updateMask
->SetBit(UNIT_DYNAMIC_FLAGS
);
2214 updateMask
->SetBit(PLAYER_FLAGS
);
2215 updateMask
->SetBit(PLAYER_BYTES
);
2216 updateMask
->SetBit(PLAYER_BYTES_2
);
2217 updateMask
->SetBit(PLAYER_BYTES_3
);
2218 updateMask
->SetBit(PLAYER_GUILDID
);
2219 updateMask
->SetBit(PLAYER_GUILDRANK
);
2220 updateMask
->SetBit(PLAYER_GUILD_TIMESTAMP
);
2222 for(uint16 i
= 0; i
< INVENTORY_SLOT_BAG_END
; i
++)
2225 updateMask
->SetBit((uint16
)(PLAYER_FIELD_INV_SLOT_HEAD
+ i
*2));
2227 updateMask
->SetBit((uint16
)(PLAYER_FIELD_INV_SLOT_HEAD
+ (i
*2) + 1));
2230 //Players visible items are not inventory stuff
2231 //431) = 884 (0x374) = main weapon
2232 for(uint16 i
= 0; i
< EQUIPMENT_SLOT_END
; i
++)
2234 updateMask
->SetBit((uint16
)(PLAYER_VISIBLE_ITEM_1_0
+ (i
*12)));
2235 //updateMask->SetBit((uint16)(PLAYER_VISIBLE_ITEM_1_0 + 1 + (i*12)));
2238 updateMask
->SetBit(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY
);
2239 updateMask
->SetBit(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY_01
);
2240 updateMask
->SetBit(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY_02
);
2241 updateMask
->SetBit(UNIT_VIRTUAL_ITEM_INFO
);
2242 updateMask
->SetBit(UNIT_VIRTUAL_ITEM_INFO_01
);
2243 updateMask
->SetBit(UNIT_VIRTUAL_ITEM_INFO_02
);
2244 updateMask
->SetBit(UNIT_VIRTUAL_ITEM_INFO_03
);
2245 updateMask
->SetBit(UNIT_VIRTUAL_ITEM_INFO_04
);
2246 updateMask
->SetBit(UNIT_VIRTUAL_ITEM_INFO_05
);
2250 void Player::BuildCreateUpdateBlockForPlayer( UpdateData
*data
, Player
*target
) const
2253 for(int i
= 0; i
< EQUIPMENT_SLOT_END
; i
++)
2255 if(m_items
[i
] == NULL
)
2258 m_items
[i
]->BuildCreateUpdateBlockForPlayer( data
, target
);
2264 for(int i
= EQUIPMENT_SLOT_END
; i
< BANK_SLOT_BAG_END
; i
++)
2266 if(m_items
[i
] == NULL
)
2269 m_items
[i
]->BuildCreateUpdateBlockForPlayer( data
, target
);
2273 Unit::BuildCreateUpdateBlockForPlayer( data
, target
);
2276 void Player::DestroyForPlayer( Player
*target
) const
2278 Unit::DestroyForPlayer( target
);
2280 for(int i
= 0; i
< INVENTORY_SLOT_BAG_END
; i
++)
2282 if(m_items
[i
] == NULL
)
2285 m_items
[i
]->DestroyForPlayer( target
);
2291 for(int i
= EQUIPMENT_SLOT_END
; i
< BANK_SLOT_BAG_END
; i
++)
2293 if(m_items
[i
] == NULL
)
2296 m_items
[i
]->DestroyForPlayer( target
);
2301 bool Player::HasSpell(uint32 spell
) const
2303 PlayerSpellMap::const_iterator itr
= m_spells
.find((uint16
)spell
);
2304 return (itr
!= m_spells
.end() && itr
->second
->state
!= PLAYERSPELL_REMOVED
);
2306 // Look in the effects of spell , if is a Learn Spell Effect, see if is equal to triggerspell
2307 // If inst, look if have this spell.
2308 /*for (PlayerSpellMap::const_iterator itr = m_spells.begin(); itr != m_spells.end(); ++itr)
2310 for(uint8 i=0;i<3;i++)
2312 if(spellInfo->Effect[i]==36) // Learn Spell effect
2314 if ( itr->first == spellInfo->EffectTriggerSpell[i] )
2317 else if(itr->first == spellInfo->Id)
2325 bool Player::CanLearnProSpell(uint32 spell
)
2327 SpellEntry
*spellInfo
= sSpellStore
.LookupEntry(spell
);
2331 if(spellInfo
->Effect
[0] != 36)
2334 uint32 skill
= spellInfo
->EffectMiscValue
[1];
2337 if( skill
!= SKILL_HERBALISM
&& skill
!= SKILL_MINING
&& skill
!= SKILL_LEATHERWORKING
2338 && skill
!= SKILL_BLACKSMITHING
&& skill
!= SKILL_ALCHEMY
&& skill
!= SKILL_ENCHANTING
2339 && skill
!= SKILL_TAILORING
&& skill
!= SKILL_ENGINERING
&& skill
!= SKILL_SKINNING
)
2342 for (PlayerSpellMap::const_iterator itr
= m_spells
.begin(); itr
!= m_spells
.end(); ++itr
)
2344 if (itr
->second
->state
== PLAYERSPELL_REMOVED
) continue;
2345 SpellEntry
*pSpellInfo
= sSpellStore
.LookupEntry(itr
->first
);
2346 if(!pSpellInfo
) continue;
2348 if(pSpellInfo
->Effect
[1] == 118)
2350 uint32 pskill
= pSpellInfo
->EffectMiscValue
[1];
2351 if( pskill
!= SKILL_HERBALISM
&& pskill
!= SKILL_MINING
&& pskill
!= SKILL_LEATHERWORKING
2352 && pskill
!= SKILL_BLACKSMITHING
&& pskill
!= SKILL_ALCHEMY
&& pskill
!= SKILL_ENCHANTING
2353 && pskill
!= SKILL_TAILORING
&& pskill
!= SKILL_ENGINERING
&& pskill
!= SKILL_SKINNING
)
2356 // not check prof count for not first prof. spells (when skill already known)
2360 // count only first rank prof. spells
2361 if(FindSpellRank(pSpellInfo
->Id
)==1)
2365 if(value
>= sWorld
.getConfig(CONFIG_MAX_PRIMARY_TRADE_SKILL
))
2370 void Player::DeleteFromDB()
2372 uint32 guid
= GetGUIDLow();
2374 // convert corpse to bones if exist (to prevent exiting Corpse in World without DB entry)
2375 // bones will be deleted by corpse/bones deleting thread shortly
2378 // remove from guild
2379 if(GetGuildId() != 0)
2380 objmgr
.GetGuildById(GetGuildId())->DelMember(guid
);
2382 // remove signs from petitions (also remove petitions if owner);
2383 RemovePetitionsAndSigns(GetGUID());
2385 sDatabase
.PExecute("DELETE FROM `character` WHERE `guid` = '%u'",guid
);
2386 sDatabase
.PExecute("DELETE FROM `character_aura` WHERE `guid` = '%u'",guid
);
2387 sDatabase
.PExecute("DELETE FROM `character_spell` WHERE `guid` = '%u'",guid
);
2388 sDatabase
.PExecute("DELETE FROM `character_tutorial` WHERE `guid` = '%u'",guid
);
2389 sDatabase
.PExecute("DELETE FROM `character_inventory` WHERE `guid` = '%u'",guid
);
2390 sDatabase
.PExecute("DELETE FROM `character_social` WHERE `guid` = '%u' OR `friend`='%u'",guid
,guid
);
2391 sDatabase
.PExecute("DELETE FROM `mail` WHERE `receiver` = '%u'",guid
);
2392 sDatabase
.PExecute("DELETE FROM `character_pet` WHERE `owner` = '%u'",guid
);
2394 //loginDatabase.PExecute("UPDATE `realmcharacters` SET `numchars` = `numchars` - 1 WHERE `acctid` = %d AND `realmid` = %d", GetSession()->GetAccountId(), realmID);
2395 QueryResult
*resultCount
= sDatabase
.PQuery("SELECT COUNT(guid) FROM `character` WHERE `account` = '%d'", GetSession()->GetAccountId());
2396 uint32 charCount
= 0;
2399 Field
*fields
= resultCount
->Fetch();
2400 charCount
= fields
[0].GetUInt32();
2402 loginDatabase
.PExecute("INSERT INTO `realmcharacters` (`numchars`, `acctid`, `realmid`) VALUES (%d, %d, %d) ON DUPLICATE KEY UPDATE `numchars` = '%d'", charCount
, GetSession()->GetAccountId(), realmID
, charCount
);
2405 for(int i
= 0; i
< BANK_SLOT_ITEM_END
; i
++)
2407 if(m_items
[i
] == NULL
)
2409 m_items
[i
]->DeleteFromDB(); // Bag items delete also by virtual call Bag::DeleteFromDB
2412 sDatabase
.PExecute("DELETE FROM `character_queststatus` WHERE `guid` = '%u'",guid
);
2413 sDatabase
.PExecute("DELETE FROM `character_action` WHERE `guid` = '%u'",guid
);
2414 sDatabase
.PExecute("DELETE FROM `character_reputation` WHERE `guid` = '%u'",guid
);
2415 sDatabase
.PExecute("DELETE FROM `character_homebind` WHERE `guid` = '%u'",guid
);
2416 sDatabase
.PExecute("DELETE FROM `character_kill` WHERE `guid` = '%u'",guid
);
2417 sDatabase
.PExecute("DELETE FROM `character_stable` WHERE `owner` = '%u'",guid
);
2420 void Player::SetMovement(uint8 pType
)
2428 data
.Initialize(SMSG_FORCE_MOVE_ROOT
);
2429 data
<< uint8(0xFF) << GetGUID();
2430 GetSession()->SendPacket( &data
);
2434 data
.Initialize(SMSG_FORCE_MOVE_UNROOT
);
2435 data
<< uint8(0xFF) << GetGUID();
2436 GetSession()->SendPacket( &data
);
2438 case MOVE_WATER_WALK
:
2440 data
.Initialize(SMSG_MOVE_WATER_WALK
);
2441 data
<< uint8(0xFF) << GetGUID();
2442 GetSession()->SendPacket( &data
);
2444 case MOVE_LAND_WALK
:
2446 data
.Initialize(SMSG_MOVE_LAND_WALK
);
2447 data
<< uint8(0xFF) << GetGUID();
2448 GetSession()->SendPacket( &data
);
2454 void Player::SetPlayerSpeed(uint8 SpeedType
, float value
, bool forced
)
2462 SetSpeed( value
/ SPEED_RUN
);
2463 if(forced
) { data
.Initialize(SMSG_FORCE_RUN_SPEED_CHANGE
); }
2464 else { data
.Initialize(MSG_MOVE_SET_RUN_SPEED
); }
2465 data
<< uint8(0xFF);
2468 data
<< float(value
);
2469 GetSession()->SendPacket( &data
);
2473 SetSpeed( value
/ SPEED_WALKBACK
);
2474 if(forced
) { data
.Initialize(SMSG_FORCE_RUN_BACK_SPEED_CHANGE
); }
2475 else { data
.Initialize(MSG_MOVE_SET_RUN_BACK_SPEED
); }
2476 data
<< uint8(0xFF);
2479 data
<< float(value
);
2480 GetSession()->SendPacket( &data
);
2484 SetSpeed( value
/ SPEED_SWIM
);
2485 if(forced
) { data
.Initialize(SMSG_FORCE_SWIM_SPEED_CHANGE
); }
2486 else { data
.Initialize(MSG_MOVE_SET_SWIM_SPEED
); }
2487 data
<< uint8(0xFF);
2490 data
<< float(value
);
2491 GetSession()->SendPacket( &data
);
2495 SetSpeed( value
/ SPEED_SWIMBACK
);
2496 data
.Initialize(MSG_MOVE_SET_SWIM_BACK_SPEED
);
2497 data
<< uint8(0xFF);
2500 data
<< float(value
);
2501 GetSession()->SendPacket( &data
);
2507 void Player::BuildPlayerRepop()
2509 // place corpse instead player body
2510 Corpse
* corpse
= GetCorpse();
2512 corpse
= CreateCorpse();
2514 // now show corpse for all
2515 MapManager::Instance().GetMap(corpse
->GetMapId())->Add(corpse
);
2517 // convert player body to ghost
2522 SetMovement(MOVE_WATER_WALK
);
2523 SetMovement(MOVE_UNROOT
);
2525 // setting new speed
2526 if (getRace() == RACE_NIGHT_ELF
)
2528 SetPlayerSpeed(MOVE_RUN
, (float)12.75, true);
2529 SetPlayerSpeed(MOVE_SWIM
, (float)8.85, true);
2533 SetPlayerSpeed(MOVE_RUN
, (float)10.625, true);
2534 SetPlayerSpeed(MOVE_SWIM
, (float)7.375, true);
2537 //! corpse reclaim delay 30 * 1000ms
2538 data
.Initialize(SMSG_CORPSE_RECLAIM_DELAY
);
2539 data
<< (uint32
)(CORPSE_RECLAIM_DELAY
*1000);
2540 GetSession()->SendPacket( &data
);
2542 // to prevent cheating
2543 corpse
->ResetGhostTime();
2545 //TODO: Check/research this
2546 data
.Initialize(SMSG_SPELL_START
);
2547 data
<< uint8(0xFF) << GetGUID() //9
2548 << uint8(0xFF) << GetGUID() //9
2549 //<< uint16(8326); //2
2550 << uint32(20305) //2
2553 << uint32(0x00)<< uint16(0x00); //6
2554 GetSession()->SendPacket( &data
);
2556 data
.Initialize(SMSG_SPELL_GO
);
2557 data
<< uint8(0xFF) << GetGUID() << uint8(0xFF) << GetGUID() << uint16(8326);
2558 /// uint8(0x0D) = probably race + 2
2559 data
<< uint16(0x00) << uint8(0x0D) << uint8(0x01)<< uint8(0x01) << GetGUID();
2560 data
<< uint32(0x00) << uint16(0x0200) << uint16(0x00);
2561 GetSession()->SendPacket( &data
);
2563 data
.Initialize(SMSG_UPDATE_AURA_DURATION
);
2564 data
<< uint32(0x20) << uint8(0);
2565 GetSession()->SendPacket( &data
);
2567 StopMirrorTimer(FATIGUE_TIMER
); //disable timers(bars)
2568 StopMirrorTimer(BREATH_TIMER
);
2569 StopMirrorTimer(FIRE_TIMER
);
2571 SetUInt32Value(UNIT_FIELD_FLAGS
, UNIT_FLAG_NONE
| UNIT_FLAG_NOT_IN_PVP
);
2572 SetUInt32Value(UNIT_FIELD_AURA
+ 32, 8326); // set ghost form
2573 SetUInt32Value(UNIT_FIELD_AURA
+ 33, 0x5068 ); //!dono
2575 SetUInt32Value(UNIT_FIELD_AURAFLAGS
+ 4, 0xEE);
2577 SetUInt32Value(UNIT_FIELD_AURASTATE
, 0x02);
2579 SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS
,(float)1.0); //see radius of death player?
2581 SetUInt32Value(UNIT_FIELD_BYTES_1
, 0x1000000); //Set standing so always be standing
2583 if (getRace() == RACE_NIGHT_ELF
)
2584 SetUInt32Value(UNIT_FIELD_DISPLAYID
, 10045); //10045 correct wisp model
2586 SetUInt32Value(PLAYER_FLAGS
, PLAYER_FLAGS_GHOST
);
2589 void Player::SendDelayResponse(const uint32 ml_seconds
)
2592 data
.Initialize( SMSG_QUERY_TIME_RESPONSE
);
2593 data
<< (uint32
)getMSTime();
2594 GetSession()->SendPacket( &data
);
2597 void Player::ResurrectPlayer()
2599 // remove death flag + set aura
2600 RemoveFlag(PLAYER_FLAGS
, PLAYER_FLAGS_GHOST
);
2602 // return the PvP enable flag to normal
2605 setDeathState(ALIVE
);
2607 SetMovement(MOVE_LAND_WALK
);
2608 SetMovement(MOVE_UNROOT
);
2610 SetPlayerSpeed(MOVE_RUN
, (float)7.5, true);
2611 SetPlayerSpeed(MOVE_SWIM
, (float)4.9, true);
2613 SetUInt32Value(CONTAINER_FIELD_SLOT_1
+29, 0);
2615 SetUInt32Value(UNIT_FIELD_AURA
+32, 0);
2616 SetUInt32Value(UNIT_FIELD_AURALEVELS
+8, 0xeeeeeeee);
2617 SetUInt32Value(UNIT_FIELD_AURAAPPLICATIONS
+8, 0xeeeeeeee);
2618 SetUInt32Value(UNIT_FIELD_AURAFLAGS
+4, 0);
2619 SetUInt32Value(UNIT_FIELD_AURASTATE
, 0);
2621 if(getRace() == NIGHTELF
)
2629 void Player::KillPlayer()
2631 SetMovement(MOVE_ROOT
);
2633 StopMirrorTimer(FATIGUE_TIMER
); //disable timers(bars)
2634 StopMirrorTimer(BREATH_TIMER
);
2635 StopMirrorTimer(FIRE_TIMER
);
2637 setDeathState(CORPSE
);
2638 SetFlag( UNIT_FIELD_FLAGS
, UNIT_FLAG_NOT_IN_PVP
);
2640 SetFlag( UNIT_DYNAMIC_FLAGS
, 0x00 );
2642 // 6 minutes until repop at graveyard
2643 m_deathTimer
= 360000;
2645 // dead player body showed at this moment, corpse wiil be show at Player ghost repop
2649 Corpse
* Player::CreateCorpse()
2651 // prevent existance 2 corpse for player
2654 uint32 _uf
, _pb
, _pb2
, _cfb1
, _cfb2
;
2656 Corpse
* corpse
= new Corpse(CORPSE_RESURRECTABLE
);
2657 if(!corpse
->Create(objmgr
.GenerateLowGuid(HIGHGUID_CORPSE
), this, GetMapId(), GetPositionX(),
2658 GetPositionY(), GetPositionZ(), GetOrientation()))
2664 _uf
= GetUInt32Value(UNIT_FIELD_BYTES_0
);
2665 _pb
= GetUInt32Value(PLAYER_BYTES
);
2666 _pb2
= GetUInt32Value(PLAYER_BYTES_2
);
2668 uint8 race
= (uint8
)(_uf
);
2669 uint8 skin
= (uint8
)(_pb
);
2670 uint8 face
= (uint8
)(_pb
>> 8);
2671 uint8 hairstyle
= (uint8
)(_pb
>> 16);
2672 uint8 haircolor
= (uint8
)(_pb
>> 24);
2673 uint8 facialhair
= (uint8
)(_pb2
);
2675 _cfb1
= ((0x00) | (race
<< 8) | (0x00 << 16) | (skin
<< 24));
2676 _cfb2
= ((face
) | (hairstyle
<< 8) | (haircolor
<< 16) | (facialhair
<< 24));
2678 corpse
->SetUInt32Value( CORPSE_FIELD_BYTES_1
, _cfb1
);
2679 corpse
->SetUInt32Value( CORPSE_FIELD_BYTES_2
, _cfb2
);
2680 corpse
->SetUInt32Value( CORPSE_FIELD_FLAGS
, 4 );
2681 corpse
->SetUInt32Value( CORPSE_FIELD_DISPLAY_ID
, GetUInt32Value(UNIT_FIELD_DISPLAYID
) );
2684 uint16 iIventoryType
;
2686 for (int i
= 0; i
< EQUIPMENT_SLOT_END
; i
++)
2690 iDisplayID
= m_items
[i
]->GetProto()->DisplayInfoID
;
2691 iIventoryType
= (uint16
)m_items
[i
]->GetProto()->InventoryType
;
2693 _cfi
= (uint16(iDisplayID
)) | (iIventoryType
)<< 24;
2694 corpse
->SetUInt32Value(CORPSE_FIELD_ITEM
+ i
,_cfi
);
2700 // register for player, but not show
2701 corpse
->AddToWorld();
2705 void Player::SpawnCorpseBones()
2707 Corpse
* corpse
= GetCorpse();
2710 corpse
->ConvertCorpseToBones();
2711 SaveToDB(); // prevent loading as ghost without corpse
2714 Corpse
* Player::GetCorpse() const
2716 return ObjectAccessor::Instance().GetCorpseForPlayer(*this);
2719 void Player::DurabilityLossAll(double percent
)
2721 for (uint16 i
= EQUIPMENT_SLOT_START
; i
< EQUIPMENT_SLOT_END
; i
++)
2722 DurabilityLoss(i
,percent
);
2725 void Player::DurabilityLoss(uint8 equip_pos
, double percent
)
2727 if(!m_items
[equip_pos
])
2730 uint32 pDurability
= m_items
[equip_pos
]->GetUInt32Value(ITEM_FIELD_DURABILITY
);
2735 uint32 pDurabilityLoss
= (uint32
)(pDurability
*percent
);
2737 if(pDurabilityLoss
< 1 )
2738 pDurabilityLoss
= 1;
2740 uint32 pNewDurability
= pDurability
- pDurabilityLoss
;
2742 // we have durability 25% or 0 we should modify item stats
2743 // modify item stats _before_ Durability set to 0 to pass _ApplyItemMods internal check
2744 // if ( pNewDurability == 0 || pNewDurability * 100 / pDurability < 25)
2745 if ( pNewDurability
== 0 )
2746 _ApplyItemMods(m_items
[equip_pos
],equip_pos
, false);
2748 m_items
[equip_pos
]->SetUInt32Value(ITEM_FIELD_DURABILITY
, pNewDurability
);
2751 void Player::DurabilityRepairAll(bool cost
)
2753 for (uint16 i
= EQUIPMENT_SLOT_START
; i
< EQUIPMENT_SLOT_END
; i
++)
2754 DurabilityRepair(( (INVENTORY_SLOT_BAG_0
<< 8) | i
),cost
);
2757 void Player::DurabilityRepair(uint16 pos
, bool cost
)
2759 Item
* item
= GetItemByPos(pos
);
2764 uint32 maxDurability
= item
->GetUInt32Value(ITEM_FIELD_MAXDURABILITY
);
2768 uint32 curDurability
= item
->GetUInt32Value(ITEM_FIELD_DURABILITY
);
2770 // some simple repair formula depending on durability lost
2773 uint32 costs
= maxDurability
- curDurability
;
2775 if (GetMoney() < costs
)
2777 DEBUG_LOG("You do not have enough money");
2781 ModifyMoney( -int32(costs
) );
2784 item
->SetUInt32Value(ITEM_FIELD_DURABILITY
, maxDurability
);
2786 // reapply mods for total broken and repaired item if equiped
2787 if(IsEquipmentPos(pos
) && !curDurability
)
2788 _ApplyItemMods(item
,pos
& 255, true);
2791 void Player::RepopAtGraveyard()
2793 WorldSafeLocsEntry
*ClosestGrave
= objmgr
.GetClosestGraveYard( m_positionX
, m_positionY
, m_positionZ
, GetMapId(), GetTeam() );
2797 // stop countdown until repop
2800 TeleportTo(ClosestGrave
->map_id
, ClosestGrave
->x
, ClosestGrave
->y
, ClosestGrave
->z
, GetOrientation());
2802 if(Corpse
* corpse
= GetCorpse())
2803 corpse
->UpdateForPlayer(this,true);
2807 void Player::JoinedChannel(Channel
*c
)
2809 m_channels
.push_back(c
);
2812 void Player::LeftChannel(Channel
*c
)
2814 m_channels
.remove(c
);
2817 void Player::CleanupChannels()
2819 list
<Channel
*>::iterator i
;
2820 for(i
= m_channels
.begin(); i
!= m_channels
.end(); i
++)
2821 (*i
)->Leave(this,false);
2824 void Player::BroadcastPacketToFriendListers(WorldPacket
*packet
)
2829 QueryResult
*result
= sDatabase
.PQuery("SELECT `guid` FROM `character_social` WHERE `flags` = 'FRIEND' AND `friend` = '%u'", GetGUIDLow());
2836 fields
= result
->Fetch();
2838 pfriend
= ObjectAccessor::Instance().FindPlayer(fields
[0].GetUInt64());
2840 if (pfriend
&& pfriend
->IsInWorld())
2841 pfriend
->GetSession()->SendPacket(packet
);
2843 }while( result
->NextRow() );
2847 void Player::UpdateDefense()
2849 if(UpdateSkill(SKILL_DEFENSE
))
2851 // update dependent from defense skill part BlockChanceWithoutMods = 5 + (GetDefenceSkillValue() - getLevel()*5)*0.04);
2852 UpdateBlockPercentage(1,0);
2856 //skill+1, checking for max value
2857 bool Player::UpdateSkill(uint32 skill_id
)
2859 if(!skill_id
) return false;
2861 for (; i
< PLAYER_MAX_SKILLS
; i
++)
2862 if ((GetUInt32Value(PLAYER_SKILL(i
)) & 0x0000FFFF) == skill_id
) break;
2863 if(i
>=PLAYER_MAX_SKILLS
) return false;
2865 uint32 data
= GetUInt32Value(PLAYER_SKILL(i
)+1);
2866 uint32 value
= SKILL_VALUE(data
);
2867 uint32 max
= SKILL_MAX(data
);
2869 if ((!max
) || (!value
) || (value
>= max
)) return false;
2871 if (value
*512 < max
*urand(0,512))
2873 SetUInt32Value(PLAYER_SKILL(i
)+1,data
+1);
2880 void Player::UpdateSkillPro(uint32 spellid
)
2882 SkillLineAbilityEntry
*pAbility
= sSkillLineAbilityStore
.LookupEntry(spellid
);
2885 uint32 minValue
= pAbility
->min_value
;
2886 uint32 maxValue
= pAbility
->max_value
;
2887 uint32 skill_id
= pAbility
->skillId
;
2889 if(!skill_id
)return;
2891 for (; i
< PLAYER_MAX_SKILLS
; i
++)
2892 if ((GetUInt32Value(PLAYER_SKILL(i
)) & 0x0000FFFF) == skill_id
) break;
2893 if(i
>=PLAYER_MAX_SKILLS
) return;
2895 uint32 data
= GetUInt32Value(PLAYER_SKILL(i
)+1);
2896 uint32 value
= SKILL_VALUE(data
);
2897 uint32 max
= SKILL_MAX(data
);
2899 if ((!max
) || (!value
) || (value
>= max
)) return;
2900 //generates chance for unsuccess gain
2901 if (value
*512 > max
*urand(0,512)) return;
2902 if(skill_id
== SKILL_POISONS
&& value
< 125)
2904 SetUInt32Value(PLAYER_SKILL(i
)+1,data
+1);
2907 if(skill_id
== SKILL_MINING
&& value
>75)
2909 if(value
>= maxValue
+25 )
2911 else if(value
>= maxValue
)
2913 if(urand(0,100) <30)
2914 SetUInt32Value(PLAYER_SKILL(i
)+1,data
+1);
2917 else if(value
>= minValue
)
2919 if(urand(0,100) <70)
2920 SetUInt32Value(PLAYER_SKILL(i
)+1,data
+1);
2925 SetUInt32Value(PLAYER_SKILL(i
)+1,data
+1);
2932 void Player::UpdateWeaponSkill (WeaponAttackType attType
)
2934 // no skill gain in pvp
2935 Unit
*pVictim
= getVictim();
2936 if(pVictim
&& pVictim
->GetTypeId() == TYPEID_PLAYER
)
2943 Item
*tmpitem
= GetItemByPos(INVENTORY_SLOT_BAG_0
, EQUIPMENT_SLOT_MAINHAND
);
2945 if (!tmpitem
|| tmpitem
->IsBroken())
2946 UpdateSkill(SKILL_UNARMED
);
2947 else if(tmpitem
->GetProto()->SubClass
!= ITEM_SUBCLASS_WEAPON_FISHING_POLE
)
2948 UpdateSkill(tmpitem
->GetSkill());
2953 Item
*tmpitem
= GetItemByPos(INVENTORY_SLOT_BAG_0
, EQUIPMENT_SLOT_OFFHAND
);
2955 if (tmpitem
&& !tmpitem
->IsBroken())
2956 UpdateSkill(tmpitem
->GetSkill());
2960 Item
* tmpitem
= GetItemByPos(INVENTORY_SLOT_BAG_0
, EQUIPMENT_SLOT_RANGED
);
2962 if (tmpitem
&& !tmpitem
->IsBroken())
2963 UpdateSkill(tmpitem
->GetSkill());
2968 void Player::UpdateCombatSkills(Unit
*pVictim
, WeaponAttackType attType
, MeleeHitOutcome outcome
, bool defence
)
2972 case MELEE_HIT_CRIT
:
2974 case MELEE_HIT_DODGE
:
2976 case MELEE_HIT_PARRY
:
2978 case MELEE_HIT_BLOCK
:
2985 uint32 plevel
= getLevel(); // if defence than pVictim == attacker
2986 uint32 greylevel
= MaNGOS::XP::GetGrayLevel(plevel
);
2987 uint32 moblevel
= pVictim
->getLevel();
2988 if(moblevel
< greylevel
)
2991 if (moblevel
> plevel
+ 5)
2992 moblevel
= plevel
+ 5;
2994 uint32 lvldif
= moblevel
- greylevel
;
2998 uint32 skilldif
= 5 * plevel
- (defence
? GetPureDefenceSkillValue() : GetPureWeaponSkillValue(attType
));
3002 float chance
= 3 * lvldif
* skilldif
/ plevel
;
3005 if(getClass() == WARRIOR
|| getClass() == ROGUE
)
3006 chance
*= 0.1 * GetStat(STAT_INTELLECT
);
3009 chance
= chance
< 1 ? 1 : chance
; //minimum chance to increase skill is 1%
3011 if(chance
> urand(0,100))
3016 UpdateWeaponSkill(attType
);
3022 void Player::ModifySkillBonus(uint32 skillid
,int32 val
)
3024 for (uint16 i
=0; i
< PLAYER_MAX_SKILLS
; i
++)
3025 if ((GetUInt32Value(PLAYER_SKILL(i
)) & 0x0000FFFF) == skillid
)
3028 SetUInt32Value(PLAYER_SKILL(i
)+2,((int32
)(GetUInt32Value(PLAYER_SKILL(i
)+2)))+val
);
3033 void Player::UpdateMaxSkills()
3035 for (uint16 i
=0; i
< PLAYER_MAX_SKILLS
; i
++)
3036 if (GetUInt32Value(PLAYER_SKILL(i
)))
3038 uint32 pskill
= GetUInt32Value(PLAYER_SKILL(i
)) & 0x0000FFFF;
3039 if(pskill
== SKILL_HERBALISM
|| pskill
== SKILL_MINING
|| pskill
==SKILL_FISHING
3040 || pskill
== SKILL_FIRST_AID
|| pskill
== SKILL_COOKING
|| pskill
== SKILL_LEATHERWORKING
3041 || pskill
== SKILL_BLACKSMITHING
|| pskill
== SKILL_ALCHEMY
|| pskill
== SKILL_ENCHANTING
3042 || pskill
== SKILL_TAILORING
|| pskill
== SKILL_ENGINERING
|| pskill
== SKILL_SKINNING
)
3044 uint32 data
= GetUInt32Value(PLAYER_SKILL(i
)+1);
3045 uint32 max
= data
>>16;
3046 uint32 max_Skill
= data
%0x10000+getLevel()*5*0x10000;
3047 if((max_Skill
>>16) > 300)
3048 max_Skill
= data
%0x10000+300*0x10000;
3050 if(max
!=1 && max
!= 300)
3051 SetUInt32Value(PLAYER_SKILL(i
)+1,max_Skill
);
3055 void Player::UpdateSkillsToMaxSkillsForLevel()
3057 for (uint16 i
=0; i
< PLAYER_MAX_SKILLS
; i
++)
3058 if (GetUInt32Value(PLAYER_SKILL(i
)))
3060 uint32 pskill
= GetUInt32Value(PLAYER_SKILL(i
)) & 0x0000FFFF;
3061 if(pskill
== SKILL_HERBALISM
|| pskill
== SKILL_MINING
|| pskill
==SKILL_FISHING
3062 || pskill
== SKILL_FIRST_AID
|| pskill
== SKILL_COOKING
|| pskill
== SKILL_LEATHERWORKING
3063 || pskill
== SKILL_BLACKSMITHING
|| pskill
== SKILL_ALCHEMY
|| pskill
== SKILL_ENCHANTING
3064 || pskill
== SKILL_TAILORING
|| pskill
== SKILL_ENGINERING
|| pskill
== SKILL_SKINNING
)
3066 uint32 data
= GetUInt32Value(PLAYER_SKILL(i
)+1);
3068 uint32 max
= data
>>16;
3072 uint32 new_data
= max
* 0x10000 + max
;
3073 SetUInt32Value(PLAYER_SKILL(i
)+1,new_data
);
3078 // This functions sets a skill line value (and adds if doesn't exist yet)
3079 // To "remove" a skill line, set it's values to zero
3080 void Player::SetSkill(uint32 id
, uint16 currVal
, uint16 maxVal
)
3084 for (; i
< PLAYER_MAX_SKILLS
; i
++)
3085 if ((GetUInt32Value(PLAYER_SKILL(i
)) & 0x0000FFFF) == id
) break;
3087 if(i
<PLAYER_MAX_SKILLS
) //has skill
3090 SetUInt32Value(PLAYER_SKILL(i
)+1,currVal
+maxVal
*0x10000);
3093 SetUInt64Value(PLAYER_SKILL(i
),0);
3094 SetUInt32Value(PLAYER_SKILL(i
)+2,0);
3095 // remove spells that depend on this skill when removing the skill
3096 for (PlayerSpellMap::const_iterator itr
= m_spells
.begin(), next
= m_spells
.begin(); itr
!= m_spells
.end(); itr
= next
)
3099 if(itr
->second
->state
== PLAYERSPELL_REMOVED
) continue;
3100 SkillLineAbilityEntry
*ability
= sSkillLineAbilityStore
.LookupEntry(itr
->first
);
3101 if (ability
&& ability
->skillId
== id
)
3102 removeSpell(itr
->first
);
3105 }else if(currVal
) //add
3108 for (i
=0; i
< PLAYER_MAX_SKILLS
; i
++)
3109 if (!GetUInt32Value(PLAYER_SKILL(i
)))
3111 SkillLineEntry
*pSkill
= sSkillLineStore
.LookupEntry(id
);
3114 sLog
.outError("Skill not found in SkillLineStore: skill #%u", id
);
3117 // enable unlearn button for professions only
3118 if (pSkill
->categoryId
== 11)
3119 SetUInt32Value(PLAYER_SKILL(i
), id
| (1 << 16));
3121 SetUInt32Value(PLAYER_SKILL(i
),id
);
3122 SetUInt32Value(PLAYER_SKILL(i
)+1,maxVal
*0x10000+currVal
);
3123 // apply skill bonuses
3124 SetUInt32Value(PLAYER_SKILL(i
)+2,0);
3125 AuraList
& mModSkill
= GetAurasByType(SPELL_AURA_MOD_SKILL
);
3126 for(AuraList::iterator i
= mModSkill
.begin(); i
!= mModSkill
.end(); ++i
)
3127 if ((*i
)->GetModifier()->m_miscvalue
== id
)
3128 (*i
)->ApplyModifier(true);
3129 AuraList
& mModSkillTalent
= GetAurasByType(SPELL_AURA_MOD_SKILL_TALENT
);
3130 for(AuraList::iterator i
= mModSkillTalent
.begin(); i
!= mModSkillTalent
.end(); ++i
)
3131 if ((*i
)->GetModifier()->m_miscvalue
== id
)
3132 (*i
)->ApplyModifier(true);
3140 bool Player::HasSkill(uint32 skill
) const
3142 if(!skill
)return false;
3143 for (uint16 i
=0; i
< PLAYER_MAX_SKILLS
; i
++)
3145 if ((GetUInt32Value(PLAYER_SKILL(i
)) & 0x0000FFFF) == skill
)
3153 uint16
Player::GetSkillValue(uint32 skill
) const
3156 for (uint16 i
=0; i
< PLAYER_MAX_SKILLS
; i
++)
3158 if ((GetUInt32Value(PLAYER_SKILL(i
)) & 0x0000FFFF) == skill
)
3160 return SKILL_VALUE(GetUInt32Value(PLAYER_SKILL(i
)+1))+GetUInt32Value(PLAYER_SKILL(i
)+2);
3166 uint16
Player::GetPureSkillValue(uint32 skill
) const
3169 for (uint16 i
=0; i
< PLAYER_MAX_SKILLS
; i
++)
3171 if ((GetUInt32Value(PLAYER_SKILL(i
)) & 0x0000FFFF) == skill
)
3173 return SKILL_VALUE(GetUInt32Value(PLAYER_SKILL(i
)+1));
3179 void Player::SendInitialActions()
3181 sLog
.outDetail( "Initializing Action Buttons for '%u'", GetGUIDLow() );
3185 std::list
<struct actions
>::iterator itr
;
3186 data
.Initialize(SMSG_ACTION_BUTTONS
);
3187 for (itr
= m_actions
.begin(); itr
!= m_actions
.end();)
3189 if (itr
->button
== button
)
3191 data
<< uint16(itr
->action
);
3192 data
<< uint8(itr
->misc
);
3193 data
<< uint8(itr
->type
);
3205 for (int temp_counter
=(120-button
); temp_counter
>0; temp_counter
--)
3210 GetSession()->SendPacket( &data
);
3211 sLog
.outDetail( "Action Buttons for '%u' Initialized", GetGUIDLow() );
3214 void Player::addAction(const uint8 button
, const uint16 action
, const uint8 type
, const uint8 misc
)
3216 // check cheating with adding non-known spells to action bar
3217 if(type
==ACTION_BUTTON_SPELL
)
3219 if(!sSpellStore
.LookupEntry(action
))
3221 sLog
.outError( "Action %u not added into button %u for player %s: spell not exist", action
, button
, GetName() );
3225 if(!HasSpell(action
))
3227 sLog
.outError( "Action %u not added into button %u for player %s: player don't known this spell", action
, button
, GetName() );
3232 bool ButtonExists
= false;
3233 std::list
<struct actions
>::iterator itr
;
3234 for (itr
= m_actions
.begin(); itr
!= m_actions
.end(); ++itr
)
3236 if (itr
->button
== button
)
3242 ButtonExists
= true;
3248 struct actions newaction
;
3249 newaction
.button
=button
;
3250 newaction
.action
=action
;
3251 newaction
.type
=type
;
3252 newaction
.misc
=misc
;
3253 m_actions
.push_back(newaction
);
3255 sLog
.outDetail( "Player '%u' Added Action '%u' to Button '%u'", GetGUIDLow(), action
, button
);
3258 void Player::removeAction(uint8 button
)
3260 std::list
<struct actions
>::iterator itr
;
3261 for (itr
= m_actions
.begin(); itr
!= m_actions
.end(); ++itr
)
3263 if (itr
->button
== button
)
3265 m_actions
.erase(itr
);
3269 sLog
.outDetail( "Action Button '%u' Removed from Player '%u'", button
, GetGUIDLow() );
3272 void Player::SetDontMove(bool dontMove
)
3274 m_dontMove
= dontMove
;
3277 bool Player::IsGroupMember(Player
*plyr
)
3279 if(!plyr
->IsInGroup())
3281 Group
*grp
= objmgr
.GetGroupByLeader(plyr
->GetGroupLeader());
3282 if(grp
->GroupCheck(plyr
->GetGUID()))
3289 bool Player::SetPosition(float x
, float y
, float z
, float orientation
)
3291 Map
*m
= MapManager::Instance().GetMap(m_mapId
);
3293 const float old_x
= m_positionX
;
3294 const float old_y
= m_positionY
;
3295 const float old_r
= m_orientation
;
3297 if( old_x
!= x
|| old_y
!= y
|| old_r
!= orientation
)
3299 m
->PlayerRelocation(this, x
, y
, z
, orientation
);
3301 // remove at movement non-move stealth aura
3302 if(HasFlag(UNIT_FIELD_BYTES_1
,0x2000000))
3303 RemoveAurasDueToSpell(20580);
3306 // reread after Ma::Relocation
3307 m
= MapManager::Instance().GetMap(GetMapId());
3312 float water_z
= m
->GetWaterLevel(x
,y
);
3313 uint8 flag1
= m
->GetTerrainType(x
,y
);
3316 if ((z
< (water_z
- 2)) && (flag1
& 0x01))
3317 m_isunderwater
|= 0x01;
3318 else if (z
> (water_z
- 2))
3319 m_isunderwater
&= 0x7A;
3322 if ((z
< (water_z
- 0)) && (flag1
& 0x02))
3323 m_isunderwater
|= 0x80;
3326 if ( IsUnderWater() )
3328 // remove travel forms
3329 if(m_form
== FORM_TRAVEL
|| m_form
== FORM_GHOSTWOLF
)
3330 RemoveAurasDueToSpell(m_ShapeShiftForm
);
3332 // IsInWater check ignore bridge and underwater ways case, check additional z
3333 else if( !IsInWater() && z
< water_z
+ 1 )
3335 if(m_form
== FORM_AQUA
)
3336 RemoveAurasDueToSpell(m_ShapeShiftForm
);
3339 CheckExploreSystem();
3344 void Player::SendMessageToSet(WorldPacket
*data
, bool self
)
3346 MapManager::Instance().GetMap(m_mapId
)->MessageBoardcast(this, data
, self
);
3349 void Player::SendMessageToOwnTeamSet(WorldPacket
*data
, bool self
)
3351 MapManager::Instance().GetMap(m_mapId
)->MessageBoardcast(this, data
, self
,true);
3354 void Player::SendDirectMessage(WorldPacket
*data
)
3356 GetSession()->SendPacket(data
);
3359 void Player::CheckExploreSystem()
3369 uint16 areaFlag
=MapManager::Instance().GetMap(GetMapId())->GetAreaFlag(m_positionX
,m_positionY
);
3370 if(areaFlag
==0xffff)return;
3371 int offset
= areaFlag
/ 32;
3375 sLog
.outError("ERROR: Wrong area flag %u in map data for (X: %f Y: %f) point to field PLAYER_EXPLORED_ZONES_1 + %u ( %u must be < 64 ).",areaFlag
,m_positionX
,m_positionY
,offset
,offset
);
3379 uint32 val
= (uint32
)(1 << (areaFlag
% 32));
3380 uint32 currFields
= GetUInt32Value(PLAYER_EXPLORED_ZONES_1
+ offset
);
3382 if( !(currFields
& val
) )
3384 SetUInt32Value(PLAYER_EXPLORED_ZONES_1
+ offset
, (uint32
)(currFields
| val
));
3386 AreaTableEntry
*p
= GetAreaEntryByAreaFlag(areaFlag
);
3389 sLog
.outError("PLAYER: Player %u discovered unknown area (x: %f y: %f map: %u", GetGUIDLow(), m_positionX
,m_positionY
,GetMapId());
3391 else if(p
->area_level
> 0)
3393 uint32 area
= p
->ID
;
3394 if (getLevel() >= sWorld
.getConfig(CONFIG_MAX_PLAYER_LEVEL
))
3396 SendExplorationExperience(area
,0);
3400 uint32 XP
= uint32(p
->area_level
*10*sWorld
.getRate(RATE_XP_EXPLORE
));
3402 SendExplorationExperience(area
,XP
);
3404 sLog
.outDetail("PLAYER: Player %u discovered a new area: %u", GetGUIDLow(), area
);
3410 uint32
Player::TeamForRace(uint8 race
)
3428 void Player::setFactionForRace(uint8 race
)
3430 m_team
= TeamForRace(race
);
3460 setFaction( faction
);
3463 void Player::UpdateReputation() const
3465 std::list
<struct Factions
>::const_iterator itr
;
3467 sLog
.outDebug( "WORLD: Player::UpdateReputation" );
3469 for(itr
= factions
.begin(); itr
!= factions
.end(); ++itr
)
3471 SendSetFactionStanding(&*itr
);
3475 void Player::SendSetFactionStanding(const Factions
* faction
) const
3479 if(faction
->Flags
& 0x00000001 ) //If faction is visible then update it
3481 data
.Initialize(SMSG_SET_FACTION_STANDING
);
3482 data
<< (uint32
) faction
->Flags
;
3483 data
<< (uint32
) faction
->ReputationListID
;
3484 data
<< (uint32
) faction
->Standing
;
3485 GetSession()->SendPacket(&data
);
3489 bool Player::FactionIsInTheList(uint32 faction
)
3491 std::list
<struct Factions
>::iterator itr
;
3493 for(itr
= factions
.begin(); itr
!= factions
.end(); ++itr
)
3495 if(itr
->ReputationListID
== faction
) return true;
3500 void Player::SetInitialFactions()
3502 Factions newFaction
;
3503 FactionEntry
*factionEntry
= NULL
;
3505 for(unsigned int i
= 1; i
<= sFactionStore
.GetNumRows(); i
++)
3507 factionEntry
= sFactionStore
.LookupEntry(i
);
3509 if( factionEntry
&& (factionEntry
->reputationListID
>= 0))
3511 newFaction
.ID
= factionEntry
->ID
;
3512 newFaction
.ReputationListID
= factionEntry
->reputationListID
;
3513 newFaction
.Standing
= 0;
3514 //Set visible to factions of own team
3515 if( GetTeam() == factionEntry
->team
) newFaction
.Flags
= 1;
3516 else newFaction
.Flags
= 0;
3518 //If the faction's team is enemy of my one we are at war!
3519 if(GetTeam() == ALLIANCE
)
3521 if( factionEntry
->team
== HORDE
|| factionEntry
->team
== HORDE_FORCES
)
3522 newFaction
.Flags
= (newFaction
.Flags
| 2);
3525 if(GetTeam() == HORDE
)
3527 if( factionEntry
->team
== ALLIANCE
|| factionEntry
->team
== ALLIANCE_FORCES
)
3528 newFaction
.Flags
= (newFaction
.Flags
| 2);
3531 factions
.push_back(newFaction
);
3536 uint32
Player::GetReputation(uint32 faction_id
) const
3538 FactionEntry
*factionEntry
= sFactionStore
.LookupEntry(faction_id
);
3540 std::list
<struct Factions
>::const_iterator itr
;
3541 for(itr
= factions
.begin(); itr
!= factions
.end(); ++itr
)
3543 if(int32(itr
->ReputationListID
) == factionEntry
->reputationListID
)
3545 return itr
->Standing
;
3551 bool Player::SetStanding(uint32 faction
, int standing
)
3553 FactionTemplateEntry
*factionTemplateEntry
= sFactionTemplateStore
.LookupEntry(faction
);
3555 if(!factionTemplateEntry
)
3557 sLog
.outError("Player::SetStanding: Can't update reputation of %s for unknown faction (faction template id) #%u.",GetName(),faction
);
3561 FactionEntry
*factionEntry
= sFactionStore
.LookupEntry(factionTemplateEntry
->faction
);
3563 // Faction without recorded reputation. Just ignore.
3567 return ModifyFactionReputation(factionEntry
,standing
);
3570 bool Player::ModifyFactionReputation(FactionEntry
* factionEntry
, int32 standing
)
3572 std::list
<struct Factions
>::iterator itr
;
3573 for(itr
= factions
.begin(); itr
!= factions
.end(); ++itr
)
3575 if(int32(itr
->ReputationListID
) == factionEntry
->reputationListID
)
3577 itr
->Standing
= (((int32
)itr
->Standing
+ standing
) > 0 ? itr
->Standing
+ standing
: 0);
3578 itr
->Flags
= (itr
->Flags
| 0x00000001);
3579 SendSetFactionStanding(&*itr
);
3586 //Calculates how many reputation points player gains in wich victim's enemy factions
3587 void Player::CalculateReputation(Unit
*pVictim
)
3589 if( !pVictim
) return;
3591 if( pVictim
->GetTypeId() != TYPEID_PLAYER
)
3593 SetStanding( pVictim
->getFaction(), (-100) );
3597 //Calculate how many reputation points player gain with the quest
3598 void Player::CalculateReputation(Quest
*pQuest
, uint64 guid
)
3600 Creature
*pCreature
= ObjectAccessor::Instance().GetCreature(*this, guid
);
3603 int dif
= getLevel() - pQuest
->GetQuestInfo()->MinLevel
;
3604 if(dif
< 0) dif
= 0;
3605 else if(dif
> 5) dif
= 5;
3607 int RepPoints
= (uint32
)(((5-dif
)*0.20)*(100.0f
+ m_AuraModifiers
[SPELL_AURA_MOD_REPUTATION_GAIN
]));
3608 // correct would be multiplicative but currently only one such aura in game
3610 SetStanding(pCreature
->getFaction(), (RepPoints
> 0 ? RepPoints
: 1) );
3613 // special quest repuration reward/losts
3614 if(pQuest
->GetQuestInfo()->RewRepFaction1
&& pQuest
->GetQuestInfo()->RewRepValue1
)
3615 SetStanding(pQuest
->GetQuestInfo()->RewRepFaction1
, pQuest
->GetQuestInfo()->RewRepValue1
);
3617 if(pQuest
->GetQuestInfo()->RewRepFaction2
&& pQuest
->GetQuestInfo()->RewRepValue2
)
3618 SetStanding(pQuest
->GetQuestInfo()->RewRepFaction2
, pQuest
->GetQuestInfo()->RewRepValue2
);
3621 //Update honor fields
3622 void Player::UpdateHonor(void)
3631 uint32 Yestarday
= 0;
3632 uint32 ThisWeekBegin
= 0;
3633 uint32 ThisWeekEnd
= 0;
3634 uint32 LastWeekBegin
= 0;
3635 uint32 LastWeekEnd
= 0;
3637 uint32 lifetime_honorableKills
= 0;
3638 uint32 lifetime_dishonorableKills
= 0;
3639 uint32 today_honorableKills
= 0;
3640 uint32 today_dishonorableKills
= 0;
3642 uint32 yestardayKills
= 0;
3643 uint32 thisWeekKills
= 0;
3644 uint32 lastWeekKills
= 0;
3646 float total_honor
= 0;
3647 float yestardayHonor
= 0;
3648 float thisWeekHonor
= 0;
3649 float lastWeekHonor
= 0;
3652 now
= localtime( &rawtime
);
3654 today
= ((uint32
)(now
->tm_year
<< 16)|(uint32
)(now
->tm_yday
));
3656 Yestarday
= today
- 1;
3657 ThisWeekBegin
= today
- now
->tm_wday
;
3658 ThisWeekEnd
= ThisWeekBegin
+ 7;
3659 LastWeekBegin
= ThisWeekBegin
- 7;
3660 LastWeekEnd
= LastWeekBegin
+ 7;
3662 sLog
.outDetail("PLAYER: UpdateHonor");
3664 QueryResult
*result
= sDatabase
.PQuery("SELECT `type`,`honor`,`date` FROM `character_kill` WHERE `guid` = '%u'", GetGUIDLow());
3670 Field
*fields
= result
->Fetch();
3671 date
= fields
[2].GetUInt32();
3673 if(fields
[0].GetUInt32() == HONORABLE_KILL
)
3675 lifetime_honorableKills
++;
3676 //total_honor += fields[1].GetFloat();
3680 today_honorableKills
++;
3682 if( date
== Yestarday
)
3685 yestardayHonor
+= fields
[1].GetFloat();
3687 if( (date
>= ThisWeekBegin
) && (date
< ThisWeekEnd
) )
3690 thisWeekHonor
+= fields
[1].GetFloat();
3692 if( (date
>= LastWeekBegin
) && (date
< LastWeekEnd
) )
3695 lastWeekHonor
+= fields
[1].GetFloat();
3698 //All honor points until last week
3699 if( date
< LastWeekEnd
)
3701 total_honor
+= fields
[1].GetFloat();
3705 else if(fields
[0].GetUInt32() == DISHONORABLE_KILL
)
3707 lifetime_dishonorableKills
++;
3708 //total_honor -= fields[1].GetFloat();
3712 today_dishonorableKills
++;
3715 //All honor points until last week
3716 if( date
< LastWeekEnd
)
3718 total_honor
-= fields
[1].GetFloat();
3722 while( result
->NextRow() );
3727 //Store Total Honor points...
3728 SetTotalHonor(total_honor
);
3731 //If the new rank is highest then the old one, then m_highest_rank is updated
3732 if( CalculateHonorRank(total_honor
) > GetHonorHighestRank() )
3734 SetHonorHighestRank( CalculateHonorRank(total_honor
) );
3738 SetHonorRating( MaNGOS::Honor::CalculeRating(this) );
3741 SetHonorLastWeekStanding( MaNGOS::Honor::CalculeStanding(this) );
3743 //TODO Fix next rank bar... it is not working fine! For while it be set with the total honor points...
3745 SetUInt32Value(PLAYER_FIELD_HONOR_BAR
, (uint32
)( (total_honor
< 0) ? 0: total_honor
) );
3748 if( CalculateHonorRank(total_honor
) )
3749 SetUInt32Value(PLAYER_BYTES_3
, (( CalculateHonorRank(total_honor
) << 24) + 0x04000000) + (m_drunk
& 0xFFFE) + getGender());
3751 SetUInt32Value(PLAYER_BYTES_3
, (m_drunk
& 0xFFFE) + getGender());
3754 SetUInt32Value(PLAYER_FIELD_SESSION_KILLS
, (today_dishonorableKills
<< 16) + today_honorableKills
);
3756 SetUInt32Value(PLAYER_FIELD_YESTERDAY_KILLS
, yestardayKills
);
3757 SetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION
, (uint32
)yestardayHonor
);
3759 SetUInt32Value(PLAYER_FIELD_THIS_WEEK_KILLS
, thisWeekKills
);
3760 SetUInt32Value(PLAYER_FIELD_THIS_WEEK_CONTRIBUTION
, (uint32
)thisWeekHonor
);
3762 SetUInt32Value(PLAYER_FIELD_LAST_WEEK_KILLS
, lastWeekKills
);
3763 SetUInt32Value(PLAYER_FIELD_LAST_WEEK_CONTRIBUTION
, (uint32
)lastWeekHonor
);
3764 SetUInt32Value(PLAYER_FIELD_LAST_WEEK_RANK
, GetHonorLastWeekStanding());
3767 SetUInt32Value(PLAYER_FIELD_SESSION_KILLS
, (lifetime_dishonorableKills
<< 16) + lifetime_honorableKills
);
3768 SetUInt32Value(PLAYER_FIELD_LIFETIME_DISHONORABLE_KILLS
, lifetime_dishonorableKills
);
3769 SetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS
, lifetime_honorableKills
);
3770 //TODO: Into what field we need to set it? Fix it!
3771 SetUInt32Value(PLAYER_FIELD_PVP_MEDALS
/*???*/, (GetHonorHighestRank() != 0 ? ((GetHonorHighestRank() << 24) + 0x040F0001) : 0) );
3774 uint32
Player::GetHonorRank() const
3776 return CalculateHonorRank(m_total_honor_points
);
3779 //What is Player's rank... private, scout...
3780 uint32
Player::CalculateHonorRank(float honor_points
) const
3784 if(honor_points
<= 0.00) rank
= 0; else
3785 if(honor_points
< 2000.00) rank
= 1;
3787 rank
= ( (int)(honor_points
/ 5000) + 1);
3792 //How many times Player kill pVictim...
3793 int Player::CalculateTotalKills(Player
*pVictim
) const
3795 int total_kills
= 0;
3797 QueryResult
*result
= sDatabase
.PQuery("SELECT `honor` FROM `character_kill` WHERE `guid` = '%u' AND `creature_template` = '%u'", GetGUIDLow(), pVictim
->GetEntry());
3801 total_kills
= result
->GetRowCount();
3807 //How much honor Player gains/loses killing uVictim
3808 void Player::CalculateHonor(Unit
*uVictim
)
3810 float parcial_honor_points
= 0;
3812 bool savekill
= false;
3814 sLog
.outDetail("PLAYER: CalculateHonor");
3816 if( !uVictim
) return;
3818 if( uVictim
->GetTypeId() == TYPEID_UNIT
)
3820 Creature
*cVictim
= (Creature
*)uVictim
;
3821 if( cVictim
->isCivilian() )
3823 parcial_honor_points
= MaNGOS::Honor::DishonorableKillPoints( getLevel() );
3824 kill_type
= DISHONORABLE_KILL
;
3829 if( uVictim
->GetTypeId() == TYPEID_PLAYER
)
3831 Player
*pVictim
= (Player
*)uVictim
;
3833 if( GetTeam() == pVictim
->GetTeam() ) return;
3835 if( getLevel() < (pVictim
->getLevel()+5) )
3837 parcial_honor_points
= MaNGOS::Honor::HonorableKillPoints( this, pVictim
);
3838 kill_type
= HONORABLE_KILL
;
3849 now
= localtime( &rawtime
);
3850 today
= ((uint32
)(now
->tm_year
<< 16)|(uint32
)(now
->tm_yday
));
3852 sDatabase
.PExecute("INSERT INTO `character_kill` (`guid`,`creature_template`,`honor`,`date`,`type`) VALUES (%u, %u, %f, %u, %u)", (uint32
)GetGUIDLow(), (uint32
)uVictim
->GetEntry(), (float)parcial_honor_points
, (uint32
)today
, (uint8
)kill_type
);
3858 uint32
Player::GetGuildIdFromDB(uint64 guid
)
3860 std::ostringstream ss
;
3861 ss
<<"SELECT `guildid` FROM `guild_member` WHERE `guid`='"<<guid
<<"'";
3862 QueryResult
*result
= sDatabase
.Query( ss
.str().c_str() );
3864 return (*result
)[0].GetUInt32();
3869 uint32
Player::GetRankFromDB(uint64 guid
)
3871 std::ostringstream ss
;
3872 ss
<<"SELECT `rank` FROM `guild_member` WHERE `guid`='"<<guid
<<"'";
3873 QueryResult
*result
= sDatabase
.Query( ss
.str().c_str() );
3875 return (*result
)[0].GetUInt32();
3880 uint32
Player::GetZoneIdFromDB(uint64 guid
)
3882 std::ostringstream ss
;
3883 ss
<<"SELECT `map`,`position_x`,`position_y` FROM `character` WHERE `guid`='"<<guid
<<"'";
3884 QueryResult
*result
= sDatabase
.Query( ss
.str().c_str() );
3888 return MapManager::Instance().GetMap((*result
)[0].GetUInt32())->GetZoneId((*result
)[0].GetFloat(),(*result
)[0].GetFloat());
3891 //If players are too far way of duel flag... then player loose the duel
3892 void Player::CheckDuelDistance()
3894 if( !isInDuel() ) return;
3896 uint64 duelFlagGUID
= GetUInt64Value(PLAYER_DUEL_ARBITER
);
3898 GameObject
* obj
= ObjectAccessor::Instance().GetGameObject(*this, duelFlagGUID
);
3900 //If the distance of duel flag is > 50
3901 if( !obj
|| !IsWithinDist(obj
, 50))
3908 void Player::DuelComplete()
3910 // duel not requested
3915 uint64 duelFlagGUID
= GetUInt64Value(PLAYER_DUEL_ARBITER
);
3917 // if dual really started
3921 m_pDuel
->CombatStop();
3923 data
.Initialize(SMSG_DUEL_WINNER
);
3925 data
<< m_pDuel
->GetName();
3927 SendMessageToSet(&data
,true);
3929 data
.Initialize(SMSG_DUEL_COMPLETE
);
3931 GetSession()->SendPacket(&data
);
3932 m_pDuel
->GetSession()->SendPacket(&data
);
3935 m_pDuel
->SetInDuel(false);
3938 //Restore the state of pvpOn
3940 m_pDuel
->RestorePvpState();
3941 //Restore to correct factiontemplate
3942 setFactionForRace(getRace());
3943 m_pDuel
->setFactionForRace(m_pDuel
->getRace());
3944 //Restore pet factiontemplate
3945 if(Creature
* pet
= GetPet())
3948 pet
->setFaction(getFaction());
3950 if(Creature
* pet
= m_pDuel
->GetPet())
3953 pet
->setFaction(m_pDuel
->getFaction());
3957 //ResurrectPlayer();
3959 setDeathState(ALIVE
);
3961 else // duel not started
3963 data
.Initialize(SMSG_DUEL_COMPLETE
);
3965 GetSession()->SendPacket(&data
);
3966 m_pDuel
->GetSession()->SendPacket(&data
);
3969 //Remove Duel Flag object
3970 GameObject
* obj
= ObjectAccessor::Instance().GetGameObject(*this, duelFlagGUID
);
3972 m_pDuelSender
->RemoveGameObject(obj
,true);
3974 //Player kneel when finish the duel
3976 HandleEmoteCommand(ANIM_EMOTE_BEG
);
3978 SetUInt64Value(PLAYER_DUEL_ARBITER
, 0);
3979 SetUInt32Value(PLAYER_DUEL_TEAM
, 0);
3980 m_pDuel
->SetUInt64Value(PLAYER_DUEL_ARBITER
, 0);
3981 m_pDuel
->SetUInt32Value(PLAYER_DUEL_TEAM
, 0);
3984 m_pDuel
->m_pDuelSender
= NULL
;
3985 m_pDuel
->m_pDuel
= NULL
;
3986 m_pDuelSender
= NULL
;
3990 static unsigned long holdrand
= 0x89abcdef;
3992 void Rand_Init(int seed
)
3997 int irand(int min
, int max
)
3999 assert((max
- min
) < 32768);
4002 holdrand
= (holdrand
* 214013L) + 2531011L;
4004 return (((holdrand
>> 17) * (max
- min
)) >> 15) + min
;
4007 //---------------------------------------------------------//
4009 void Player::FlightComplete()
4011 clearUnitState(UNIT_STAT_IN_FLIGHT
);
4012 SetMoney( m_dismountCost
);
4016 void Player::_ApplyItemMods(Item
*item
, uint8 slot
,bool apply
)
4018 if(slot
>= INVENTORY_SLOT_BAG_END
|| !item
) return;
4020 // not apply/premove mods for broken item
4021 if(item
->IsBroken()) return;
4023 ItemPrototype
const *proto
= item
->GetProto();
4027 sLog
.outDetail("applying mods for item %u ",item
->GetGUIDLow());
4031 AddItemsSetItem(this,item
);
4033 RemoveItemsSetItem(this,proto
);
4037 AuraList
& mModBaseResistancePct
= GetAurasByType(SPELL_AURA_MOD_BASE_RESISTANCE_PCT
);
4038 for(AuraList::iterator i
= mModBaseResistancePct
.begin(); i
!= mModBaseResistancePct
.end(); ++i
)
4039 (*i
)->ApplyModifier(false);
4041 _ApplyItemBonuses(proto
,slot
,apply
);
4043 for(AuraList::iterator i
= mModBaseResistancePct
.begin(); i
!= mModBaseResistancePct
.end(); ++i
)
4044 (*i
)->ApplyModifier(true);
4048 CastItemEquipSpell(item
);
4050 for (int i
= 0; i
< 5; i
++)
4051 if(proto
->Spells
[i
].SpellId
)
4052 RemoveAurasDueToSpell(proto
->Spells
[i
].SpellId
);
4054 for(int enchant_slot
= 0 ; enchant_slot
< 7; enchant_slot
++)
4056 uint32 Enchant_id
= item
->GetUInt32Value(ITEM_FIELD_ENCHANTMENT
+enchant_slot
*3);
4058 AddItemEnchant(item
,Enchant_id
, apply
);
4061 sLog
.outDebug("_ApplyItemMods complete.");
4064 void Player::_ApplyItemBonuses(ItemPrototype
const *proto
,uint8 slot
,bool apply
)
4066 if(slot
>= INVENTORY_SLOT_BAG_END
|| !proto
) return;
4069 std::string typestr
;
4070 std::string applystr
= apply
? "Add" : "Remove";
4071 for (int i
= 0; i
< 10; i
++)
4073 val
= proto
->ItemStat
[i
].ItemStatValue
;
4075 switch (proto
->ItemStat
[i
].ItemStatType
)
4077 case POWER
: // modify MP
4078 ApplyMaxPowerMod(POWER_MANA
, val
, apply
);
4081 case HEALTH
: // modify HP
4082 ApplyMaxHealthMod(val
, apply
);
4085 case AGILITY
: // modify agility
4086 ApplyStatMod(STAT_AGILITY
, val
, apply
);
4087 ApplyPosStatMod(STAT_AGILITY
, val
, apply
);
4088 typestr
= "AGILITY";
4090 case STRENGHT
: //modify strength
4091 ApplyStatMod(STAT_STRENGTH
, val
, apply
);
4092 ApplyPosStatMod(STAT_STRENGTH
, val
, apply
);
4093 typestr
= "STRENGHT";
4095 case INTELLECT
: //modify intellect
4096 ApplyStatMod(STAT_INTELLECT
, val
, apply
);
4097 ApplyPosStatMod(STAT_INTELLECT
, val
, apply
);
4098 //ApplyMaxPowerMod(POWER_MANA, val*15, apply);
4099 typestr
= "INTELLECT";
4101 case SPIRIT
: //modify spirit
4102 ApplyStatMod(STAT_SPIRIT
, val
, apply
);
4103 ApplyPosStatMod(STAT_SPIRIT
, val
, apply
);
4106 case STAMINA
: //modify stamina
4107 ApplyStatMod(STAT_STAMINA
,val
, apply
);
4108 ApplyPosStatMod(STAT_STAMINA
,val
, apply
);
4109 //ApplyMaxHealthMod( val*10,apply);
4110 typestr
= "STAMINA";
4114 sLog
.outDebug("%s %s: \t\t%u", applystr
.c_str(), typestr
.c_str(), val
);
4120 ApplyArmorMod( proto
->Armor
, apply
);
4121 sLog
.outDebug("%s Armor: \t\t%u", applystr
.c_str(), proto
->Armor
);
4126 ApplyBlockValueMod(proto
->Block
, apply
);
4127 sLog
.outDebug("%s Block: \t\t%u", applystr
.c_str(), proto
->Block
);
4132 ApplyResistanceMod(SPELL_SCHOOL_HOLY
, proto
->HolyRes
, apply
);
4133 sLog
.outDebug("%s HolyRes: \t\t%u", applystr
.c_str(), proto
->HolyRes
);
4138 ApplyResistanceMod(SPELL_SCHOOL_FIRE
, proto
->FireRes
, apply
);
4139 sLog
.outDebug("%s FireRes: \t\t%u", applystr
.c_str(), proto
->FireRes
);
4142 if (proto
->NatureRes
)
4144 ApplyResistanceMod(SPELL_SCHOOL_NATURE
, proto
->NatureRes
, apply
);
4145 sLog
.outDebug("%s NatureRes: \t\t%u", applystr
.c_str(), proto
->NatureRes
);
4148 if (proto
->FrostRes
)
4150 ApplyResistanceMod(SPELL_SCHOOL_FROST
, proto
->FrostRes
, apply
);
4151 sLog
.outDebug("%s FrostRes: \t\t%u", applystr
.c_str(), proto
->FrostRes
);
4154 if (proto
->ShadowRes
)
4156 ApplyResistanceMod(SPELL_SCHOOL_SHADOW
, proto
->ShadowRes
, apply
);
4157 sLog
.outDebug("%s ShadowRes: \t\t%u", applystr
.c_str(), proto
->ShadowRes
);
4160 if (proto
->ArcaneRes
)
4162 ApplyResistanceMod(SPELL_SCHOOL_ARCANE
, proto
->ArcaneRes
, apply
);
4163 sLog
.outDebug("%s ArcaneRes: \t\t%u", applystr
.c_str(), proto
->ArcaneRes
);
4166 uint8 MINDAMAGEFIELD
= 0;
4167 uint8 MAXDAMAGEFIELD
= 0;
4169 if( slot
== EQUIPMENT_SLOT_RANGED
&& ( proto
->InventoryType
== INVTYPE_RANGED
||
4170 proto
->InventoryType
== INVTYPE_THROWN
|| proto
->InventoryType
== INVTYPE_RANGEDRIGHT
))
4172 MINDAMAGEFIELD
= UNIT_FIELD_MINRANGEDDAMAGE
;
4173 MAXDAMAGEFIELD
= UNIT_FIELD_MAXRANGEDDAMAGE
;
4176 else if(slot
==EQUIPMENT_SLOT_MAINHAND
)
4178 MINDAMAGEFIELD
= UNIT_FIELD_MINDAMAGE
;
4179 MAXDAMAGEFIELD
= UNIT_FIELD_MAXDAMAGE
;
4180 typestr
= "Mainhand";
4182 else if(slot
==EQUIPMENT_SLOT_OFFHAND
)
4184 MINDAMAGEFIELD
= UNIT_FIELD_MINOFFHANDDAMAGE
;
4185 MAXDAMAGEFIELD
= UNIT_FIELD_MAXOFFHANDDAMAGE
;
4186 typestr
= "Offhand";
4189 if (proto
->Damage
[0].DamageMin
> 0 && MINDAMAGEFIELD
)
4191 ApplyModFloatValue(MINDAMAGEFIELD
, proto
->Damage
[0].DamageMin
, apply
);
4192 sLog
.outDetail("%s %s mindam: %f, now is: %f", applystr
.c_str(), typestr
.c_str(), proto
->Damage
[0].DamageMin
, GetFloatValue(MINDAMAGEFIELD
));
4195 if (proto
->Damage
[0].DamageMax
> 0 && MAXDAMAGEFIELD
)
4197 ApplyModFloatValue(MAXDAMAGEFIELD
, proto
->Damage
[0].DamageMax
, apply
);
4198 sLog
.outDetail("%s %s mindam: %f, now is: %f", applystr
.c_str(), typestr
.c_str(), proto
->Damage
[0].DamageMax
, GetFloatValue(MAXDAMAGEFIELD
));
4203 if(slot
== EQUIPMENT_SLOT_RANGED
)
4205 SetAttackTime(RANGED_ATTACK
, apply
? proto
->Delay
: 2000);
4207 sLog
.outDebug("%s %s Delay: \t\t%u", applystr
.c_str(), typestr
.c_str(), proto
->Delay
);
4209 else if(slot
==EQUIPMENT_SLOT_MAINHAND
)
4211 SetAttackTime(BASE_ATTACK
, apply
? proto
->Delay
: 2000);
4212 typestr
= "Mainhand";
4213 sLog
.outDebug("%s %s Delay: \t\t%u", applystr
.c_str(), typestr
.c_str(), proto
->Delay
);
4215 else if(slot
==EQUIPMENT_SLOT_OFFHAND
)
4217 SetAttackTime(OFF_ATTACK
, apply
? proto
->Delay
: 2000);
4218 typestr
= "Offhand";
4219 sLog
.outDebug("%s %s Delay: \t\t%u", applystr
.c_str(), typestr
.c_str(), proto
->Delay
);
4224 void Player::CastItemEquipSpell(Item
*item
)
4228 ItemPrototype
const *proto
= item
->GetProto();
4232 SpellEntry
*spellInfo
;
4234 for (int i
= 0; i
< 5; i
++)
4236 if(!proto
->Spells
[i
].SpellId
) continue;
4237 if(proto
->Spells
[i
].SpellTrigger
!= ON_EQUIP
) continue;
4239 spellInfo
= sSpellStore
.LookupEntry(proto
->Spells
[i
].SpellId
);
4242 sLog
.outError("WORLD: unknown Item spellid %i", proto
->Spells
[i
].SpellId
);
4246 DEBUG_LOG("WORLD: cast Item spellId - %i", proto
->Spells
[i
].SpellId
);
4248 Spell
spell(this, spellInfo
, true, 0);
4250 SpellCastTargets targets
;
4251 targets
.setUnitTarget( this );
4252 spell
.m_CastItem
= item
;
4253 spell
.prepare(&targets
);
4257 void Player::CastItemCombatSpell(Item
*item
,Unit
* Target
)
4259 if(!item
|| item
->IsBroken())
4262 ItemPrototype
const *proto
= item
->GetProto();
4266 if (!Target
|| Target
== this )
4269 SpellEntry
*spellInfo
;
4271 for (int i
= 0; i
< 5; i
++)
4273 if(!proto
->Spells
[i
].SpellId
) continue;
4275 spellInfo
= sSpellStore
.LookupEntry(proto
->Spells
[i
].SpellId
);
4278 sLog
.outError("WORLD: unknown Item spellid %i", proto
->Spells
[i
].SpellId
);
4282 if(proto
->Spells
[i
].SpellTrigger
!= CHANCE_ON_HIT
) continue;
4284 uint32 chance
= spellInfo
->procChance
<= 100 ? spellInfo
->procChance
: GetWeaponProcChance();
4285 if (chance
> rand_chance())
4286 this->CastSpell(Target
, spellInfo
->Id
, true, item
);
4289 // item combat enchantments
4290 for(int e_slot
= 0; e_slot
< 7; e_slot
++)
4292 uint32 enchant_id
= item
->GetUInt32Value(ITEM_FIELD_ENCHANTMENT
+e_slot
*3);
4293 SpellItemEnchantmentEntry
*pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
4294 if(!pEnchant
) continue;
4295 uint32 enchant_display
= pEnchant
->display_type
;
4296 uint32 chance
= pEnchant
->value1
!= 0 ? pEnchant
->value1
: GetWeaponProcChance();
4297 uint32 enchant_spell_id
= pEnchant
->spellid
;
4298 SpellEntry
*enchantSpell_info
= sSpellStore
.LookupEntry(enchant_spell_id
);
4299 if(!enchantSpell_info
) continue;
4300 if(enchant_display
!=4 && enchant_display
!=2 && this->IsItemSpellToCombat(enchantSpell_info
))
4301 if (chance
> rand_chance())
4302 this->CastSpell(Target
, enchantSpell_info
->Id
, true);
4306 // only some item spell/auras effects can be executed when item is equiped.
4307 // If not you can have unexpected beaviur. like item giving damage to player when equip.
4308 bool Player::IsItemSpellToEquip(SpellEntry
*spellInfo
)
4310 return (GetDuration(spellInfo
) == -1); // infinite duration -> passive aura
4312 for(int j = 0; j< 3; j++)
4314 if(spellInfo->Effect[j] == 6)
4316 switch(spellInfo->EffectApplyAuraName[j])
4334 // only some item spell/auras effects can be executed when in combat.
4335 // If not you can have unexpected beaviur. like having stats always growing each attack.
4336 bool Player::IsItemSpellToCombat(SpellEntry
*spellInfo
)
4338 return (GetDuration(spellInfo
) != -1); // infinite duration -> passive aura
4341 for(int j = 0; j< 3; j++)
4343 if(spellInfo->Effect[j] == 6)
4345 switch(spellInfo->EffectApplyAuraName[j])
4363 void Player::_RemoveAllItemMods()
4365 sLog
.outDebug("_RemoveAllItemMods start.");
4367 for (int i
= 0; i
< INVENTORY_SLOT_BAG_END
; i
++)
4371 if(m_items
[i
]->IsBroken()) break;
4372 ItemPrototype
const *proto
= m_items
[i
]->GetProto();
4375 RemoveItemsSetItem(this,proto
);
4377 for (int m
= 0; m
< 5; m
++)
4379 if(proto
->Spells
[m
].SpellId
)
4380 RemoveAurasDueToSpell(proto
->Spells
[m
].SpellId
);
4383 for(int enchant_slot
= 0 ; enchant_slot
< 7; enchant_slot
++)
4385 uint32 Enchant_id
= m_items
[i
]->GetUInt32Value(ITEM_FIELD_ENCHANTMENT
+enchant_slot
*3);
4387 AddItemEnchant(m_items
[i
],Enchant_id
, false);
4394 AuraList
& mModBaseResistancePct
= GetAurasByType(SPELL_AURA_MOD_BASE_RESISTANCE_PCT
);
4395 for(AuraList::iterator i
= mModBaseResistancePct
.begin(); i
!= mModBaseResistancePct
.end(); ++i
)
4396 (*i
)->ApplyModifier(false);
4398 for (int i
= 0; i
< INVENTORY_SLOT_BAG_END
; i
++)
4402 if(m_items
[i
]->IsBroken()) break;
4403 ItemPrototype
const *proto
= m_items
[i
]->GetProto();
4405 _ApplyItemBonuses(proto
,i
, false);
4409 for(AuraList::iterator i
= mModBaseResistancePct
.begin(); i
!= mModBaseResistancePct
.end(); ++i
)
4410 (*i
)->ApplyModifier(true);
4414 sLog
.outDebug("_RemoveAllItemMods complete.");
4417 void Player::_ApplyAllItemMods()
4419 sLog
.outDebug("_ApplyAllItemMods start.");
4421 for (int i
= 0; i
< INVENTORY_SLOT_BAG_END
; i
++)
4425 if(m_items
[i
]->IsBroken()) break;
4426 ItemPrototype
const *proto
= m_items
[i
]->GetProto();
4429 AddItemsSetItem(this,m_items
[i
]);
4431 CastItemEquipSpell(m_items
[i
]);
4433 for(int enchant_slot
= 0 ; enchant_slot
< 7; enchant_slot
++)
4435 uint32 Enchant_id
= m_items
[i
]->GetUInt32Value(ITEM_FIELD_ENCHANTMENT
+enchant_slot
*3);
4437 AddItemEnchant(m_items
[i
],Enchant_id
, true);
4444 AuraList
& mModBaseResistancePct
= GetAurasByType(SPELL_AURA_MOD_BASE_RESISTANCE_PCT
);
4445 for(AuraList::iterator i
= mModBaseResistancePct
.begin(); i
!= mModBaseResistancePct
.end(); ++i
)
4446 (*i
)->ApplyModifier(false);
4448 for (int i
= 0; i
< INVENTORY_SLOT_BAG_END
; i
++)
4452 if(m_items
[i
]->IsBroken()) break;
4453 ItemPrototype
const *proto
= m_items
[i
]->GetProto();
4455 _ApplyItemBonuses(proto
,i
, true);
4459 for(AuraList::iterator i
= mModBaseResistancePct
.begin(); i
!= mModBaseResistancePct
.end(); ++i
)
4460 (*i
)->ApplyModifier(true);
4464 sLog
.outDebug("_ApplyAllItemMods complete.");
4473 void Player::SendLoot(uint64 guid
, LootType loot_type
)
4476 PermissionTypes permission
= ALL_PERMISSION
;
4478 if (IS_GAMEOBJECT_GUID(guid
))
4481 ObjectAccessor::Instance().GetGameObject(*this, guid
);
4483 if (!go
|| !go
->IsWithinDistInMap(this,OBJECT_ITERACTION_DISTANCE
))
4488 if(go
->getLootState() == GO_CLOSED
)
4490 uint32 lootid
= go
->lootid
;
4493 FillLoot(this,loot
,lootid
,LootTemplates_Gameobject
);
4495 if(loot_type
== LOOT_FISHING
)
4496 go
->getFishLoot(loot
);
4498 go
->SetLootState(GO_OPEN
);
4501 else if (IS_ITEM_GUID(guid
))
4503 Item
*item
= this->GetItemByPos( this->GetPosByGuid( guid
));
4509 FillLoot(this,loot
,item
->GetEntry(),LootTemplates_Item
);
4513 Creature
*creature
=
4514 ObjectAccessor::Instance().GetCreature(*this, guid
);
4516 if (!creature
|| creature
->isAlive() || !creature
->IsWithinDistInMap(this,OBJECT_ITERACTION_DISTANCE
))
4519 loot
= &creature
->loot
;
4521 uint32 lootid
= creature
->GetCreatureInfo()->lootid
;
4523 if(loot_type
== LOOT_PICKPOKETING
)
4525 if ( !creature
->lootForPickPocketed
)
4527 creature
->lootForPickPocketed
= true;
4530 if (!creature
->HasFlag(UNIT_NPC_FLAGS
,UNIT_NPC_FLAG_VENDOR
) && lootid
)
4531 FillLoot(this,loot
,lootid
,LootTemplates_Pickpocketing
);
4532 // Generate extra money for pick pocket loot
4533 loot
->gold
= uint32((10* (rand() % ( (creature
->getLevel() / 2) + 1) + rand() % ( (getLevel() / 2) + 1 )))*sWorld
.getRate(RATE_DROP_MONEY
));
4538 // the player whose group may loot the corpse
4539 Player
*recipient
= creature
->GetLootRecipient();
4542 creature
->SetLootRecipient(this);
4546 if (creature
->lootForPickPocketed
)
4548 creature
->lootForPickPocketed
= false;
4552 if(!creature
->lootForBody
)
4554 creature
->lootForBody
= true;
4555 if (!creature
->HasFlag(UNIT_NPC_FLAGS
,UNIT_NPC_FLAG_VENDOR
) && lootid
)
4556 FillLoot(this,loot
,lootid
,LootTemplates_Creature
);
4558 creature
->generateMoneyLoot();
4560 if (recipient
->IsInGroup())
4562 // round robin style looting applies for all low
4563 // quality items in each loot metho except free for all
4564 Group
*group
= objmgr
.GetGroupByLeader(recipient
->GetGroupLeader());
4565 uint32 siz
= group
->GetMembersCount();
4567 for (pos
= 0; pos
<siz
; pos
++)
4568 if (group
->GetMemberGUID(pos
) == group
->GetLooterGuid())
4570 group
->SetLooterGuid(group
->GetMemberGUID((pos
+1)%siz
));
4572 switch (group
->GetLootMethod())
4575 // GroupLoot delete items over threshold (threshold even not implemented), and roll them. Items with quality<threshold, round robin
4576 group
->GroupLoot(recipient
->GetGUID(), loot
, creature
);
4578 case NEED_BEFORE_GREED
:
4579 group
->NeedBeforeGreed(recipient
->GetGUID(), loot
, creature
);
4585 if (loot_type
== LOOT_SKINNING
)
4588 FillLoot(this,loot
,creature
->GetCreatureInfo()->SkinLootId
,LootTemplates_Skinning
);
4589 for(std::vector
<LootItem
>::iterator i
= loot
->items
.begin(); i
!= loot
->items
.end(); ++i
)
4591 LootSkinnigAlternative::iterator i2iter
= sLootSkinnigAlternative
.find(i
->itemid
);
4592 if(i2iter
!= sLootSkinnigAlternative
.end())
4594 if(rand_chance() > 80)
4596 i
->itemid
= i2iter
->second
.itemid
;
4597 i
->displayid
= i2iter
->second
.displayid
;
4603 if (!IsInGroup() && recipient
== this)
4604 permission
= ALL_PERMISSION
;
4609 Group
*group
= objmgr
.GetGroupByLeader(recipient
->GetGroupLeader());
4610 if ((GetGroupLeader() == recipient
->GetGroupLeader()) && (group
->GetLooterGuid() == GetGUID() || loot
->released
|| group
->GetLootMethod() == FREE_FOR_ALL
))
4611 permission
= ALL_PERMISSION
;
4613 if (GetGroupLeader() == recipient
->GetGroupLeader())
4614 permission
= GROUP_PERMISSION
;
4616 permission
= NONE_PERMISSION
;
4619 permission
= NONE_PERMISSION
;
4626 QuestItemList
*q_list
= NULL
;
4627 if (permission
!= NONE_PERMISSION
)
4629 QuestItemMap::iterator itr
= loot
->PlayerQuestItems
.find(this);
4630 if (itr
== loot
->PlayerQuestItems
.end())
4631 q_list
= FillQuestLoot(this, loot
);
4633 q_list
= itr
->second
;
4636 // LOOT_PICKPOKETING unsupported by client, sending LOOT_SKINNING instead
4637 if(loot_type
== LOOT_PICKPOKETING
)
4638 loot_type
= LOOT_SKINNING
;
4641 data
.Initialize (SMSG_LOOT_RESPONSE
);
4644 data
<< uint8(loot_type
);
4645 data
<< LootView(*loot
, q_list
, permission
);
4647 SendDirectMessage(&data
);
4649 // add 'this' player as one of the players that are looting 'loot'
4650 if (permission
!= NONE_PERMISSION
)
4651 loot
->AddLooter(this);
4654 void Player::SendNotifyLootMoneyRemoved()
4657 data
.Initialize( SMSG_LOOT_CLEAR_MONEY
);
4658 GetSession()->SendPacket( &data
);
4661 void Player::SendNotifyLootItemRemoved(uint8 lootSlot
)
4664 data
.Initialize( SMSG_LOOT_REMOVED
);
4665 data
<< uint8(lootSlot
);
4666 GetSession()->SendPacket( &data
);
4669 void Player::SendUpdateWordState(uint16 Field
, uint16 Value
)
4672 data
.Initialize(SMSG_UPDATE_WORLD_STATE
); //0x2D4
4673 data
<< uint32(Field
);
4674 data
<< uint32(Value
);
4675 GetSession()->SendPacket(&data
);
4678 void Player::SendInitWorldStates(uint32 MapID
)
4680 // TODO Figure out the unknown data.
4682 if ((MapID
== 0) || (MapID
== 1))
4684 sLog
.outDebug("Sending SMSG_INIT_WORLD_STATES to Map:%u",MapID
);
4686 uint16 NumberOfFields
= 108;
4688 data
.Initialize (SMSG_INIT_WORLD_STATES
); //0x2C5
4691 (uint16
)NumberOfFields
<<
4692 //field (uint16) value (uint16)
4693 (uint16
)0x07AE<< (uint16
)0x01<<
4694 (uint16
)0x0532<< (uint16
)0x01<<
4695 (uint16
)0x0531<< (uint16
)0x00<<
4696 (uint16
)0x052E<< (uint16
)0x00<<
4697 (uint16
)0x06F9<< (uint16
)0x00<<
4698 (uint16
)0x06F3<< (uint16
)0x00<<
4699 (uint16
)0x06F1<< (uint16
)0x00<<
4700 (uint16
)0x06EE<< (uint16
)0x00<<
4701 (uint16
)0x06ED<< (uint16
)0x00<<
4702 (uint16
)0x0571<< (uint16
)0x00<<
4703 (uint16
)0x0570<< (uint16
)0x00<<
4704 (uint16
)0x0567<< (uint16
)0x01<<
4705 (uint16
)0x0566<< (uint16
)0x01<<
4706 (uint16
)0x0550<< (uint16
)0x01<<
4707 (uint16
)0x0544<< (uint16
)0x00<<
4708 (uint16
)0x0536<< (uint16
)0x00<<
4709 (uint16
)0x0535<< (uint16
)0x01<<
4710 (uint16
)0x03C6<< (uint16
)0x00<<
4711 (uint16
)0x03C4<< (uint16
)0x00<<
4712 (uint16
)0x03C2<< (uint16
)0x00<<
4713 (uint16
)0x07A8<< (uint16
)0x00<<
4714 (uint16
)0x07A3<< (uint16
)0x270F<<
4715 (uint16
)0x0574<< (uint16
)0x00<<
4716 (uint16
)0x0573<< (uint16
)0x00<<
4717 (uint16
)0x0572<< (uint16
)0x00<<
4718 (uint16
)0x056F<< (uint16
)0x00<<
4719 (uint16
)0x056E<< (uint16
)0x00<<
4720 (uint16
)0x056D<< (uint16
)0x00<<
4721 (uint16
)0x056C<< (uint16
)0x00<<
4722 (uint16
)0x056B<< (uint16
)0x00<<
4723 (uint16
)0x056A<< (uint16
)0x01<<
4724 (uint16
)0x0569<< (uint16
)0x01<<
4725 (uint16
)0x0568<< (uint16
)0x01<<
4726 (uint16
)0x0565<< (uint16
)0x00<<
4727 (uint16
)0x0564<< (uint16
)0x00<<
4728 (uint16
)0x0563<< (uint16
)0x00<<
4729 (uint16
)0x0562<< (uint16
)0x00<<
4730 (uint16
)0x0561<< (uint16
)0x00<<
4731 (uint16
)0x0560<< (uint16
)0x00<<
4732 (uint16
)0x055F<< (uint16
)0x00<<
4733 (uint16
)0x055E<< (uint16
)0x00<<
4734 (uint16
)0x055D<< (uint16
)0x00<<
4735 (uint16
)0x055C<< (uint16
)0x00<<
4736 (uint16
)0x055B<< (uint16
)0x00<<
4737 (uint16
)0x055A<< (uint16
)0x00<<
4738 (uint16
)0x0559<< (uint16
)0x00<<
4739 (uint16
)0x0558<< (uint16
)0x00<<
4740 (uint16
)0x0557<< (uint16
)0x00<<
4741 (uint16
)0x0556<< (uint16
)0x00<<
4742 (uint16
)0x0555<< (uint16
)0x00<<
4743 (uint16
)0x0554<< (uint16
)0x01<<
4744 (uint16
)0x0553<< (uint16
)0x01<<
4745 (uint16
)0x0552<< (uint16
)0x01<<
4746 (uint16
)0x0551<< (uint16
)0x01<<
4747 (uint16
)0x054F<< (uint16
)0x00<<
4748 (uint16
)0x054E<< (uint16
)0x00<<
4749 (uint16
)0x054D<< (uint16
)0x01<<
4750 (uint16
)0x054C<< (uint16
)0x00<<
4751 (uint16
)0x054B<< (uint16
)0x00<<
4752 (uint16
)0x0545<< (uint16
)0x00<<
4753 (uint16
)0x0543<< (uint16
)0x01<<
4754 (uint16
)0x0542<< (uint16
)0x00<<
4755 (uint16
)0x0540<< (uint16
)0x00<<
4756 (uint16
)0x053F<< (uint16
)0x00<<
4757 (uint16
)0x053E<< (uint16
)0x00<<
4758 (uint16
)0x053D<< (uint16
)0x00<<
4759 (uint16
)0x053C<< (uint16
)0x00<<
4760 (uint16
)0x053B<< (uint16
)0x00<<
4761 (uint16
)0x053A<< (uint16
)0x01<<
4762 (uint16
)0x0539<< (uint16
)0x00<<
4763 (uint16
)0x0538<< (uint16
)0x00<<
4764 (uint16
)0x0537<< (uint16
)0x00<<
4765 (uint16
)0x0534<< (uint16
)0x00<<
4766 (uint16
)0x0533<< (uint16
)0x00<<
4767 (uint16
)0x0530<< (uint16
)0x00<<
4768 (uint16
)0x052F<< (uint16
)0x00<<
4769 (uint16
)0x052D<< (uint16
)0x01<<
4770 (uint16
)0x0516<< (uint16
)0x01<<
4771 (uint16
)0x0515<< (uint16
)0x00<<
4772 (uint16
)0x03B6<< (uint16
)0x00<<
4773 (uint16
)0x0745<< (uint16
)0x02<<
4774 (uint16
)0x0736<< (uint16
)0x01<<
4775 (uint16
)0x0735<< (uint16
)0x01<<
4776 (uint16
)0x0734<< (uint16
)0x01<<
4777 (uint16
)0x0733<< (uint16
)0x01<<
4778 (uint16
)0x0732<< (uint16
)0x01<<
4779 (uint16
)0x0702<< (uint16
)0x00<<
4780 (uint16
)0x0701<< (uint16
)0x00<<
4781 (uint16
)0x0700<< (uint16
)0x00<<
4782 (uint16
)0x06FE<< (uint16
)0x00<<
4783 (uint16
)0x06FD<< (uint16
)0x00<<
4784 (uint16
)0x06FC<< (uint16
)0x00<<
4785 (uint16
)0x06FB<< (uint16
)0x00<<
4786 (uint16
)0x06F8<< (uint16
)0x00<<
4787 (uint16
)0x06F7<< (uint16
)0x00<<
4788 (uint16
)0x06F6<< (uint16
)0x00<<
4789 (uint16
)0x06F4<< (uint16
)0x7D0<<
4790 (uint16
)0x06F2<< (uint16
)0x00<<
4791 (uint16
)0x06F0<< (uint16
)0x00<<
4792 (uint16
)0x06EF<< (uint16
)0x00<<
4793 (uint16
)0x06EC<< (uint16
)0x00<<
4794 (uint16
)0x06EA<< (uint16
)0x00<<
4795 (uint16
)0x06E9<< (uint16
)0x00<<
4796 (uint16
)0x06E8<< (uint16
)0x00<<
4797 (uint16
)0x06E7<< (uint16
)0x00<<
4798 (uint16
)0x0518<< (uint16
)0x00<<
4799 (uint16
)0x0517<< (uint16
)0x00<<
4800 (uint16
)0x0703<< (uint16
)0x00;
4801 GetSession()->SendPacket(&data
);
4804 //BattleGround currently only map 489
4805 else if (MapID
== 489) // && and guid is in a current Battlefield)
4807 sLog
.outDebug("Sending SMSG_INIT_WORLD_STATES to Map:%u",MapID
);
4809 uint16 NumberOfFields
= 114;
4811 data
.Initialize (SMSG_INIT_WORLD_STATES
);
4815 (uint16
)NumberOfFields
<<
4816 //field (uint16) value (uint16)
4817 (uint16
)0x07AE<< (uint16
)0x01<<
4818 (uint16
)0x0532<< (uint16
)0x01<<
4819 (uint16
)0x0531<< (uint16
)0x00<<
4820 (uint16
)0x052E<< (uint16
)0x00<<
4821 (uint16
)0x06F9<< (uint16
)0x00<<
4822 (uint16
)0x06F3<< (uint16
)0x00<<
4823 (uint16
)0x06F1<< (uint16
)0x00<<
4824 (uint16
)0x06EE<< (uint16
)0x00<<
4825 (uint16
)0x06ED<< (uint16
)0x00<<
4826 (uint16
)0x0571<< (uint16
)0x00<<
4827 (uint16
)0x0570<< (uint16
)0x00<<
4828 (uint16
)0x0567<< (uint16
)0x01<<
4829 (uint16
)0x0566<< (uint16
)0x01<<
4830 (uint16
)0x0550<< (uint16
)0x01<<
4831 (uint16
)0x0544<< (uint16
)0x00<<
4832 (uint16
)0x0536<< (uint16
)0x00<<
4833 (uint16
)0x0535<< (uint16
)0x01<<
4834 (uint16
)0x03C6<< (uint16
)0x00<<
4835 (uint16
)0x03C4<< (uint16
)0x00<<
4836 (uint16
)0x03C2<< (uint16
)0x00<<
4837 (uint16
)0x07A8<< (uint16
)0x00<<
4838 (uint16
)0x07A3<< (uint16
)0x270F <<
4839 (uint16
)0x060B<< (uint16
)0x02<<
4840 (uint16
)0x0574<< (uint16
)0x00<<
4841 (uint16
)0x0573<< (uint16
)0x00<<
4842 (uint16
)0x0572<< (uint16
)0x00<<
4843 (uint16
)0x056F<< (uint16
)0x00<<
4844 (uint16
)0x056E<< (uint16
)0x00<<
4845 (uint16
)0x056D<< (uint16
)0x00<<
4846 (uint16
)0x056C<< (uint16
)0x00<<
4847 (uint16
)0x056B<< (uint16
)0x00<<
4848 (uint16
)0x056A<< (uint16
)0x01<<
4849 (uint16
)0x0569<< (uint16
)0x01<<
4850 (uint16
)0x0568<< (uint16
)0x01<<
4851 (uint16
)0x0565<< (uint16
)0x00<<
4852 (uint16
)0x0564<< (uint16
)0x00<<
4853 (uint16
)0x0563<< (uint16
)0x00<<
4854 (uint16
)0x0562<< (uint16
)0x00<<
4855 (uint16
)0x0561<< (uint16
)0x00<<
4856 (uint16
)0x0560<< (uint16
)0x00<<
4857 (uint16
)0x055F<< (uint16
)0x00<<
4858 (uint16
)0x055E<< (uint16
)0x00<<
4859 (uint16
)0x055D<< (uint16
)0x00<<
4860 (uint16
)0x055C<< (uint16
)0x00<<
4861 (uint16
)0x055B<< (uint16
)0x00<<
4862 (uint16
)0x055A<< (uint16
)0x00<<
4863 (uint16
)0x0559<< (uint16
)0x00<<
4864 (uint16
)0x0558<< (uint16
)0x00<<
4865 (uint16
)0x0557<< (uint16
)0x00<<
4866 (uint16
)0x0556<< (uint16
)0x00<<
4867 (uint16
)0x0555<< (uint16
)0x00<<
4868 (uint16
)0x0554<< (uint16
)0x01<<
4869 (uint16
)0x0553<< (uint16
)0x01<<
4870 (uint16
)0x0552<< (uint16
)0x01<<
4871 (uint16
)0x0551<< (uint16
)0x01<<
4872 (uint16
)0x054F<< (uint16
)0x00<<
4873 (uint16
)0x054E<< (uint16
)0x00<<
4874 (uint16
)0x054D<< (uint16
)0x01<<
4875 (uint16
)0x054C<< (uint16
)0x00<<
4876 (uint16
)0x054B<< (uint16
)0x00<<
4877 (uint16
)0x0545<< (uint16
)0x00<<
4878 (uint16
)0x0543<< (uint16
)0x01<<
4879 (uint16
)0x0542<< (uint16
)0x00<<
4880 (uint16
)0x0540<< (uint16
)0x00<<
4881 (uint16
)0x053F<< (uint16
)0x00<<
4882 (uint16
)0x053E<< (uint16
)0x00<<
4883 (uint16
)0x053D<< (uint16
)0x00<<
4884 (uint16
)0x053C<< (uint16
)0x00<<
4885 (uint16
)0x053B<< (uint16
)0x00<<
4886 (uint16
)0x053A<< (uint16
)0x01<<
4887 (uint16
)0x0539<< (uint16
)0x00<<
4888 (uint16
)0x0538<< (uint16
)0x00<<
4889 (uint16
)0x0537<< (uint16
)0x00<<
4890 (uint16
)0x0534<< (uint16
)0x00<<
4891 (uint16
)0x0533<< (uint16
)0x00<<
4892 (uint16
)0x0530<< (uint16
)0x00<<
4893 (uint16
)0x052F<< (uint16
)0x00<<
4894 (uint16
)0x052D<< (uint16
)0x01<<
4895 (uint16
)0x0516<< (uint16
)0x01<<
4896 (uint16
)0x0515<< (uint16
)0x00<<
4897 (uint16
)0x03B6<< (uint16
)0x00<<
4898 (uint16
)0x0745<< (uint16
)0x02<<
4899 (uint16
)0x0736<< (uint16
)0x01<<
4900 (uint16
)0x0735<< (uint16
)0x01<<
4901 (uint16
)0x0734<< (uint16
)0x01<<
4902 (uint16
)0x0733<< (uint16
)0x01<<
4903 (uint16
)0x0732<< (uint16
)0x01<<
4904 (uint16
)0x0702<< (uint16
)0x00<<
4905 (uint16
)0x0701<< (uint16
)0x00<<
4906 (uint16
)0x0700<< (uint16
)0x00<<
4907 (uint16
)0x06FE<< (uint16
)0x00<<
4908 (uint16
)0x06FD<< (uint16
)0x00<<
4909 (uint16
)0x06FC<< (uint16
)0x00<<
4910 (uint16
)0x06FB<< (uint16
)0x00<<
4911 (uint16
)0x06F8<< (uint16
)0x00<<
4912 (uint16
)0x06F7<< (uint16
)0x00<<
4913 (uint16
)0x06F6<< (uint16
)0x00<<
4914 (uint16
)0x06F4<< (uint16
)0x07D0 <<
4915 (uint16
)0x06F2<< (uint16
)0x00<<
4916 (uint16
)0x06F0<< (uint16
)0x00<<
4917 (uint16
)0x06EF<< (uint16
)0x00<<
4918 (uint16
)0x06EC<< (uint16
)0x00<<
4919 (uint16
)0x06EA<< (uint16
)0x00<<
4920 (uint16
)0x06E9<< (uint16
)0x00<<
4921 (uint16
)0x06E8<< (uint16
)0x00<<
4922 (uint16
)0x06E7<< (uint16
)0x00<<
4923 (uint16
)0x0641<< (uint16
)0x03<<
4924 (uint16
)0x062E<< (uint16
)0x00<<
4925 (uint16
)0x062D<< (uint16
)0x00<<
4926 (uint16
)0x060A<< (uint16
)0x00<<
4927 (uint16
)0x0609<< (uint16
)0x00<<
4928 (uint16
)0x0518<< (uint16
)0x00<<
4929 (uint16
)0x0517<< (uint16
)0x00<<
4930 (uint16
)0x0703<< (uint16
)0x00;
4931 GetSession()->SendPacket(&data
);
4935 void Player::AddWeather()
4937 uint32 zoneid
= GetZoneId();
4938 if(!sWorld
.FindWeather(zoneid
))
4940 Weather
*wth
= new Weather(this);
4941 sWorld
.AddWeather(wth
);
4945 uint32
Player::GetXPRestBonus(uint32 xp
)
4948 float xp_bl
= (float)GetUInt32Value(PLAYER_NEXT_LEVEL_XP
) / 20;
4949 float blpoint_bl
=0; //rested bonuse for 1 section
4952 case 1: {blpoint_bl
=50.9;break;}
4953 case 2: {blpoint_bl
=51.05;break;}
4954 case 3: {blpoint_bl
=51.1;break;}
4955 case 4: {blpoint_bl
=51.1;break;}
4956 default: {blpoint_bl
=51.15;break;}
4958 float rested_xp
= (xp_bl
/blpoint_bl
) * GetRestBonus(); //xp for each rested bonus
4960 float rest_xp_percent
= rested_xp
/ ((float)xp
/ 100); //% rest bonuse from total rest bonus
4961 if(rest_xp_percent
>100)rest_xp_percent
=100;
4963 sLog
.outDetail("XP_GAIN: %f, value1=%f, rest_xp_percent=%f",(float)xp
,(xp_bl
/blpoint_bl
),rest_xp_percent
);
4965 rested_xp
= ((float)xp
/ 100 * rest_xp_percent
);
4967 SetRestBonus( GetRestBonus() - ((xp_bl
/ blpoint_bl
) * (xp
+ rested_xp
) ));
4969 sLog
.outDetail("Player gain %u xp (+ %u Rested Bonus). Rested bonus=%f",xp
+(uint32
)rested_xp
,(uint32
)((float)xp
/ 100 * rest_xp_percent
),GetRestBonus());
4970 return (uint32
)rested_xp
;
4973 uint8
Player::CheckFishingAble() const
4975 uint32 zone
= GetZoneId();
4976 uint32 fish_value
= GetSkillValue(SKILL_FISHING
);
4977 uint32 ZoneMaxSkill
;
5971 if((ZoneMaxSkill
-50) > fish_value
)
5973 else if(ZoneMaxSkill
-50 <= fish_value
&& fish_value
< ZoneMaxSkill
-25)
5975 else if(ZoneMaxSkill
-25 <= fish_value
&& fish_value
< ZoneMaxSkill
)
5977 else if(ZoneMaxSkill
<= fish_value
&& fish_value
< ZoneMaxSkill
+ 25)
5982 void Player::SetBindPoint(uint64 guid
)
5985 data
.Initialize( SMSG_BINDER_CONFIRM
);
5987 GetSession()->SendPacket( &data
);
5990 void Player::SendTalentWipeConfirm(uint64 guid
)
5993 data
.Initialize( MSG_TALENT_WIPE_CONFIRM
);
5995 data
<< (uint32
)resetTalentsCost();
5996 GetSession()->SendPacket( &data
);
5999 /*********************************************************/
6000 /*** STORAGE SYSTEM ***/
6001 /*********************************************************/
6003 void Player::SetVirtualItemSlot( uint8 i
, Item
* item
)
6006 SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO
+ 2*i
, item
? item
->GetGUIDLow() : 0);
6007 SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO
+ 2*i
+1, item
? item
->GetProto()->Sheath
: 0);
6008 SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY
+i
,item
? item
->GetProto()->DisplayInfoID
: 0);
6011 if(!item
->GetUInt32Value(ITEM_FIELD_ENCHANTMENT
+3))
6013 uint32 charges
= item
->GetUInt32Value(ITEM_FIELD_ENCHANTMENT
+3+2);
6017 item
->SetUInt32Value(ITEM_FIELD_ENCHANTMENT
+3+2,charges
-1);
6018 else if(charges
<= 1)
6020 AddItemEnchant(item
,item
->GetUInt32Value(ITEM_FIELD_ENCHANTMENT
+3),false);
6021 for(int y
=0;y
<3;y
++)
6022 item
->SetUInt32Value(ITEM_FIELD_ENCHANTMENT
+3+y
,0);
6027 void Player::SetSheath( uint32 sheathed
)
6032 case 0: // no prepeared weapon
6033 SetVirtualItemSlot(0,NULL
);
6034 SetVirtualItemSlot(1,NULL
);
6035 SetVirtualItemSlot(2,NULL
);
6037 case 1: // prepeared melee weapon
6039 item
= GetItemByPos(INVENTORY_SLOT_BAG_0
, EQUIPMENT_SLOT_MAINHAND
);
6040 SetVirtualItemSlot(0,item
&& !item
->IsBroken() ? item
: NULL
);
6041 item
= GetItemByPos(INVENTORY_SLOT_BAG_0
, EQUIPMENT_SLOT_OFFHAND
);
6042 SetVirtualItemSlot(1,item
&& !item
->IsBroken() ? item
: NULL
);
6043 SetVirtualItemSlot(2,NULL
);
6045 case 2: // prepeared ranged weapon
6046 SetVirtualItemSlot(0,NULL
);
6047 SetVirtualItemSlot(1,NULL
);
6048 item
= GetItemByPos(INVENTORY_SLOT_BAG_0
, EQUIPMENT_SLOT_RANGED
);
6049 SetVirtualItemSlot(2,item
&& !item
->IsBroken() ? item
: NULL
);
6052 SetVirtualItemSlot(0,NULL
);
6053 SetVirtualItemSlot(1,NULL
);
6054 SetVirtualItemSlot(2,NULL
);
6059 uint8
Player::FindEquipSlot( uint32 type
, uint32 slot
, bool swap
) const
6062 slots
[0] = NULL_SLOT
;
6063 slots
[1] = NULL_SLOT
;
6064 slots
[2] = NULL_SLOT
;
6065 slots
[3] = NULL_SLOT
;
6069 slots
[0] = EQUIPMENT_SLOT_HEAD
;
6072 slots
[0] = EQUIPMENT_SLOT_NECK
;
6074 case INVTYPE_SHOULDERS
:
6075 slots
[0] = EQUIPMENT_SLOT_SHOULDERS
;
6078 slots
[0] = EQUIPMENT_SLOT_BODY
;
6081 slots
[0] = EQUIPMENT_SLOT_CHEST
;
6084 slots
[0] = EQUIPMENT_SLOT_CHEST
;
6087 slots
[0] = EQUIPMENT_SLOT_WAIST
;
6090 slots
[0] = EQUIPMENT_SLOT_LEGS
;
6093 slots
[0] = EQUIPMENT_SLOT_FEET
;
6095 case INVTYPE_WRISTS
:
6096 slots
[0] = EQUIPMENT_SLOT_WRISTS
;
6099 slots
[0] = EQUIPMENT_SLOT_HANDS
;
6101 case INVTYPE_FINGER
:
6102 slots
[0] = EQUIPMENT_SLOT_FINGER1
;
6103 slots
[1] = EQUIPMENT_SLOT_FINGER2
;
6105 case INVTYPE_TRINKET
:
6106 slots
[0] = EQUIPMENT_SLOT_TRINKET1
;
6107 slots
[1] = EQUIPMENT_SLOT_TRINKET2
;
6110 slots
[0] = EQUIPMENT_SLOT_BACK
;
6112 case INVTYPE_WEAPON
:
6114 slots
[0] = EQUIPMENT_SLOT_MAINHAND
;
6116 // suggest offhand slot only if know dual wielding
6117 // (this will be replace mainhand weapon at auto equip instead unwonted "you don't known dual weilding" ...
6119 slots
[1] = EQUIPMENT_SLOT_OFFHAND
;
6121 case INVTYPE_SHIELD
:
6122 slots
[0] = EQUIPMENT_SLOT_OFFHAND
;
6124 case INVTYPE_RANGED
:
6125 slots
[0] = EQUIPMENT_SLOT_RANGED
;
6127 case INVTYPE_2HWEAPON
:
6128 slots
[0] = EQUIPMENT_SLOT_MAINHAND
;
6130 case INVTYPE_TABARD
:
6131 slots
[0] = EQUIPMENT_SLOT_TABARD
;
6133 case INVTYPE_WEAPONMAINHAND
:
6134 slots
[0] = EQUIPMENT_SLOT_MAINHAND
;
6136 case INVTYPE_WEAPONOFFHAND
:
6137 slots
[0] = EQUIPMENT_SLOT_OFFHAND
;
6139 case INVTYPE_HOLDABLE
:
6140 slots
[0] = EQUIPMENT_SLOT_OFFHAND
;
6142 case INVTYPE_THROWN
:
6143 slots
[0] = EQUIPMENT_SLOT_RANGED
;
6145 case INVTYPE_RANGEDRIGHT
:
6146 slots
[0] = EQUIPMENT_SLOT_RANGED
;
6149 slots
[0] = INVENTORY_SLOT_BAG_1
;
6150 slots
[1] = INVENTORY_SLOT_BAG_2
;
6151 slots
[2] = INVENTORY_SLOT_BAG_3
;
6152 slots
[3] = INVENTORY_SLOT_BAG_4
;
6155 slots
[0] = EQUIPMENT_SLOT_RANGED
;
6161 if( slot
!= NULL_SLOT
)
6163 if( swap
|| !GetItemByPos( INVENTORY_SLOT_BAG_0
, slot
) )
6165 for (int i
= 0; i
< 4; i
++)
6167 if ( slots
[i
] == slot
)
6174 // search empty slot at first
6175 for (int i
= 0; i
< 4; i
++)
6177 if ( slots
[i
] != NULL_SLOT
&& !GetItemByPos( INVENTORY_SLOT_BAG_0
, slots
[i
] ) )
6181 // if not found empty and can swap return first appropriate
6182 for (int i
= 0; i
< 4; i
++)
6184 if ( slots
[i
] != NULL_SLOT
&& swap
)
6193 Item
* Player::CreateItem( uint32 item
, uint32 count
) const
6195 ItemPrototype
const *pProto
= objmgr
.GetItemPrototype( item
);
6198 Item
*pItem
= NewItemOrBag( pProto
);
6199 if ( count
> pProto
->Stackable
)
6200 count
= pProto
->Stackable
;
6203 if( pItem
->Create(objmgr
.GenerateLowGuid(HIGHGUID_ITEM
), item
, const_cast<Player
*>(this)) )
6205 pItem
->SetCount( count
);
6214 uint32
Player::GetItemCount( uint32 item
) const
6218 for(int i
= EQUIPMENT_SLOT_START
; i
< INVENTORY_SLOT_ITEM_END
; i
++)
6220 pItem
= GetItemByPos( INVENTORY_SLOT_BAG_0
, i
);
6221 if( pItem
&& pItem
->GetEntry() == item
)
6222 count
+= pItem
->GetCount();
6225 for(int i
= INVENTORY_SLOT_BAG_START
; i
< INVENTORY_SLOT_BAG_END
; i
++)
6227 pBag
= (Bag
*)GetItemByPos( INVENTORY_SLOT_BAG_0
, i
);
6229 count
+= pBag
->GetItemCount(item
);
6234 uint32
Player::GetBankItemCount( uint32 item
) const
6238 for(int i
= BANK_SLOT_ITEM_START
; i
< BANK_SLOT_ITEM_END
; i
++)
6240 pItem
= GetItemByPos( INVENTORY_SLOT_BAG_0
, i
);
6241 if( pItem
&& pItem
->GetEntry() == item
)
6242 count
+= pItem
->GetCount();
6245 for(int i
= BANK_SLOT_BAG_START
; i
< BANK_SLOT_BAG_END
; i
++)
6247 pBag
= (Bag
*)GetItemByPos( INVENTORY_SLOT_BAG_0
, i
);
6249 count
+= pBag
->GetItemCount(item
);
6254 uint16
Player::GetPosByGuid( uint64 guid
) const
6258 for(int i
= EQUIPMENT_SLOT_START
; i
< INVENTORY_SLOT_ITEM_END
; i
++)
6260 pos
= ((INVENTORY_SLOT_BAG_0
<< 8) | i
);
6261 pItem
= GetItemByPos( pos
);
6262 if( pItem
&& pItem
->GetGUID() == guid
)
6266 ItemPrototype
const *pBagProto
;
6267 for(int i
= INVENTORY_SLOT_BAG_START
; i
< INVENTORY_SLOT_BAG_END
; i
++)
6269 pos
= ((INVENTORY_SLOT_BAG_0
<< 8) | i
);
6270 pBag
= (Bag
*)GetItemByPos( pos
);
6273 pBagProto
= pBag
->GetProto();
6276 for(uint32 j
= 0; j
< pBagProto
->ContainerSlots
; j
++)
6278 pos
= ((i
<< 8) | j
);
6279 pItem
= GetItemByPos( pos
);
6280 if( pItem
&& pItem
->GetGUID() == guid
)
6286 for(int i
= BANK_SLOT_BAG_START
; i
< BANK_SLOT_BAG_END
; i
++)
6288 pos
= ((INVENTORY_SLOT_BAG_0
<< 8) | i
);
6289 pBag
= (Bag
*)GetItemByPos( pos
);
6292 pBagProto
= pBag
->GetProto();
6295 for(uint32 j
= 0; j
< pBagProto
->ContainerSlots
; j
++)
6297 pos
= ((i
<< 8) | j
);
6298 pItem
= GetItemByPos( pos
);
6299 if( pItem
&& pItem
->GetGUID() == guid
)
6308 Item
* Player::GetItemByPos( uint16 pos
) const
6310 uint8 bag
= pos
>> 8;
6311 uint8 slot
= pos
& 255;
6312 return GetItemByPos( bag
, slot
);
6315 Item
* Player::GetItemByPos( uint8 bag
, uint8 slot
) const
6317 if( bag
== INVENTORY_SLOT_BAG_0
&& ( slot
< BANK_SLOT_BAG_END
) )
6318 return m_items
[slot
];
6319 else if(bag
>= INVENTORY_SLOT_BAG_START
&& bag
< INVENTORY_SLOT_BAG_END
6320 || bag
>= BANK_SLOT_BAG_START
&& bag
< BANK_SLOT_BAG_END
)
6322 Bag
*pBag
= (Bag
*)GetItemByPos( INVENTORY_SLOT_BAG_0
, bag
);
6324 return pBag
->GetItemByPos(slot
);
6329 bool Player::HasBankBagSlot( uint8 slot
) const
6331 uint32 maxslot
= ((GetUInt32Value(PLAYER_BYTES_2
) & 0x70000) >> 16) + BANK_SLOT_BAG_START
;
6332 if( slot
< maxslot
)
6337 bool Player::IsInventoryPos( uint16 pos
) const
6339 uint8 bag
= pos
>> 8;
6340 uint8 slot
= pos
& 255;
6341 if( bag
== INVENTORY_SLOT_BAG_0
&& slot
== NULL_SLOT
)
6343 if( bag
== INVENTORY_SLOT_BAG_0
&& ( slot
>= INVENTORY_SLOT_ITEM_START
&& slot
< INVENTORY_SLOT_ITEM_END
) )
6345 if( bag
>= INVENTORY_SLOT_BAG_START
&& bag
< INVENTORY_SLOT_BAG_END
)
6350 bool Player::IsEquipmentPos( uint16 pos
) const
6352 uint8 bag
= pos
>> 8;
6353 uint8 slot
= pos
& 255;
6354 if( bag
== INVENTORY_SLOT_BAG_0
&& ( slot
< EQUIPMENT_SLOT_END
) )
6356 if( bag
== INVENTORY_SLOT_BAG_0
&& ( slot
>= INVENTORY_SLOT_BAG_START
&& slot
< INVENTORY_SLOT_BAG_END
) )
6361 bool Player::IsBankPos( uint16 pos
) const
6363 uint8 bag
= pos
>> 8;
6364 uint8 slot
= pos
& 255;
6365 if( bag
== INVENTORY_SLOT_BAG_0
&& ( slot
>= BANK_SLOT_ITEM_START
&& slot
< BANK_SLOT_ITEM_END
) )
6367 if( bag
== INVENTORY_SLOT_BAG_0
&& ( slot
>= BANK_SLOT_BAG_START
&& slot
< BANK_SLOT_BAG_END
) )
6369 if( bag
>= BANK_SLOT_BAG_START
&& bag
< BANK_SLOT_BAG_END
)
6374 bool Player::HasItemCount( uint32 item
, uint32 count
) const
6377 uint32 tempcount
= 0;
6378 for(int i
= EQUIPMENT_SLOT_START
; i
< INVENTORY_SLOT_ITEM_END
; i
++)
6380 pItem
= GetItemByPos( INVENTORY_SLOT_BAG_0
, i
);
6381 if( pItem
&& pItem
->GetEntry() == item
)
6383 tempcount
+= pItem
->GetCount();
6384 if( tempcount
>= count
)
6389 ItemPrototype
const *pBagProto
;
6390 for(int i
= INVENTORY_SLOT_BAG_START
; i
< INVENTORY_SLOT_BAG_END
; i
++)
6392 pBag
= (Bag
*)GetItemByPos( INVENTORY_SLOT_BAG_0
, i
);
6395 pBagProto
= pBag
->GetProto();
6398 for(uint32 j
= 0; j
< pBagProto
->ContainerSlots
; j
++)
6400 pItem
= GetItemByPos( i
, j
);
6401 if( pItem
&& pItem
->GetEntry() == item
)
6403 tempcount
+= pItem
->GetCount();
6404 if( tempcount
>= count
)
6414 uint8
Player::CanStoreNewItem( uint8 bag
, uint8 slot
, uint16
&dest
, uint32 item
, uint32 count
, bool swap
) const
6417 Item
*pItem
= CreateItem( item
, count
);
6420 uint8 result
= CanStoreItem( bag
, slot
, dest
, pItem
, swap
);
6425 return EQUIP_ERR_ITEM_NOT_FOUND
;
6427 return EQUIP_ERR_ITEMS_CANT_BE_SWAPPED
;
6430 uint8
Player::CanStoreItem( uint8 bag
, uint8 slot
, uint16
&dest
, Item
*pItem
, bool swap
) const
6435 sLog
.outDebug( "STORAGE: CanStoreItem bag = %u, slot = %u, item = %u, count = %u", bag
, slot
, pItem
->GetEntry(), pItem
->GetCount());
6436 ItemPrototype
const *pProto
= pItem
->GetProto();
6441 ItemPrototype
const *pBagProto
;
6443 if(pItem
->IsBindedNotWith(GetGUID()))
6444 return EQUIP_ERR_DONT_OWN_THAT_ITEM
;
6447 // check count of items
6448 if( !swap
&& pProto
->MaxCount
> 0 )
6450 uint32 curcount
= 0;
6451 for(int i
= EQUIPMENT_SLOT_START
; i
< INVENTORY_SLOT_ITEM_END
; i
++)
6453 pos
= ((INVENTORY_SLOT_BAG_0
<< 8) | i
);
6454 pItem2
= GetItemByPos( pos
);
6455 if( pItem2
&& pItem2
->GetEntry() == pItem
->GetEntry() )
6457 curcount
+= pItem2
->GetCount();
6458 if( curcount
+ pItem
->GetCount() > pProto
->MaxCount
)
6459 return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS
;
6462 for(int i
= INVENTORY_SLOT_BAG_START
; i
< INVENTORY_SLOT_BAG_END
; i
++)
6464 pos
= ((INVENTORY_SLOT_BAG_0
<< 8) | i
);
6465 pBag
= (Bag
*)GetItemByPos( pos
);
6468 pBagProto
= pBag
->GetProto();
6471 for(uint32 j
= 0; j
< pBagProto
->ContainerSlots
; j
++)
6473 pos
= ((i
<< 8) | j
);
6474 pItem2
= GetItemByPos( pos
);
6475 if( pItem2
&& pItem2
->GetEntry() == pItem
->GetEntry() )
6477 curcount
+= pItem2
->GetCount();
6478 if( curcount
+ pItem
->GetCount() > pProto
->MaxCount
)
6479 return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS
;
6485 for(int i
= BANK_SLOT_BAG_START
; i
< BANK_SLOT_BAG_END
; i
++)
6487 pos
= ((INVENTORY_SLOT_BAG_0
<< 8) | i
);
6488 pBag
= (Bag
*)GetItemByPos( pos
);
6491 pBagProto
= pBag
->GetProto();
6494 for(uint32 j
= 0; j
< pBagProto
->ContainerSlots
; j
++)
6496 pos
= ((i
<< 8) | j
);
6497 pItem2
= GetItemByPos( pos
);
6498 if( pItem2
&& pItem2
->GetEntry() == pItem
->GetEntry() )
6500 curcount
+= pItem2
->GetCount();
6501 if( curcount
+ pItem
->GetCount() > pProto
->MaxCount
)
6502 return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS
;
6510 // search stack for merge to
6511 if( pProto
->Stackable
> 1 )
6513 for(int i
= INVENTORY_SLOT_ITEM_START
; i
< INVENTORY_SLOT_ITEM_END
; i
++)
6515 pos
= ( (INVENTORY_SLOT_BAG_0
<< 8) | i
);
6516 pItem2
= GetItemByPos( pos
);
6517 if( pItem2
&& pItem2
->GetEntry() == pItem
->GetEntry() && pItem2
->GetCount() + pItem
->GetCount() <= pProto
->Stackable
)
6520 return EQUIP_ERR_OK
;
6523 for(int i
= INVENTORY_SLOT_BAG_START
; i
< INVENTORY_SLOT_BAG_END
; i
++)
6525 pos
= ( (INVENTORY_SLOT_BAG_0
<< 8) | i
);
6526 pBag
= (Bag
*)GetItemByPos( pos
);
6529 pBagProto
= pBag
->GetProto();
6532 for(uint32 j
= 0; j
< pBagProto
->ContainerSlots
; j
++)
6534 pos
= ( (i
<< 8) | j
);
6535 pItem2
= GetItemByPos( pos
);
6536 if( pItem2
&& pItem2
->GetEntry() == pItem
->GetEntry() && pItem2
->GetCount() + pItem
->GetCount() <= pProto
->Stackable
)
6539 return EQUIP_ERR_OK
;
6547 // search free slot - ammo special case
6548 if( pProto
->Class
== ITEM_CLASS_PROJECTILE
)
6550 for(int i
= INVENTORY_SLOT_BAG_START
; i
< INVENTORY_SLOT_BAG_END
; i
++)
6552 pos
= ( (INVENTORY_SLOT_BAG_0
<< 8) | i
);
6553 pBag
= (Bag
*)GetItemByPos( INVENTORY_SLOT_BAG_0
, i
);
6556 pBagProto
= pBag
->GetProto();
6557 if( pBagProto
&& pBagProto
->SubClass
== pProto
->SubClass
)
6559 for(uint32 j
= 0; j
< pBagProto
->ContainerSlots
; j
++)
6561 pos
= ( (INVENTORY_SLOT_BAG_0
<< 8) | i
);
6562 pItem2
= GetItemByPos( i
, j
);
6565 dest
= ( (i
<< 8) | j
);
6566 return EQUIP_ERR_OK
;
6575 for(int i
= INVENTORY_SLOT_ITEM_START
; i
< INVENTORY_SLOT_ITEM_END
; i
++)
6577 pItem2
= GetItemByPos( INVENTORY_SLOT_BAG_0
, i
);
6580 dest
= ( (INVENTORY_SLOT_BAG_0
<< 8) | i
);
6581 return EQUIP_ERR_OK
;
6585 for(int i
= INVENTORY_SLOT_BAG_START
; i
< INVENTORY_SLOT_BAG_END
; i
++)
6587 pBag
= (Bag
*)GetItemByPos( INVENTORY_SLOT_BAG_0
, i
);
6590 pBagProto
= pBag
->GetProto();
6591 if( pBagProto
&& pBagProto
->Class
!= ITEM_CLASS_QUIVER
)
6593 for(uint32 j
= 0; j
< pBagProto
->ContainerSlots
; j
++)
6595 pItem2
= GetItemByPos( i
, j
);
6598 dest
= ( (i
<< 8) | j
);
6599 return EQUIP_ERR_OK
;
6605 return EQUIP_ERR_INVENTORY_FULL
;
6607 else // in specific bag
6609 if( slot
== NULL_SLOT
)
6611 if( pProto
->InventoryType
== INVTYPE_BAG
)
6613 Bag
*pBag
= (Bag
*)pItem
;
6614 if( pBag
&& !pBag
->IsEmpty() )
6615 return EQUIP_ERR_NONEMPTY_BAG_OVER_OTHER_BAG
;
6618 // search stack in bag for merge to
6619 if( pProto
->Stackable
> 1 )
6621 if( bag
== INVENTORY_SLOT_BAG_0
)
6623 for(int i
= INVENTORY_SLOT_ITEM_START
; i
< INVENTORY_SLOT_ITEM_END
; i
++)
6625 pItem2
= GetItemByPos( INVENTORY_SLOT_BAG_0
, i
);
6626 if( pItem2
&& pItem2
->GetEntry() == pItem
->GetEntry() && pItem2
->GetCount() + pItem
->GetCount() <= pProto
->Stackable
)
6628 dest
= ( (INVENTORY_SLOT_BAG_0
<< 8) | i
);
6629 return EQUIP_ERR_OK
;
6635 pBag
= (Bag
*)GetItemByPos( INVENTORY_SLOT_BAG_0
, bag
);
6638 pBagProto
= pBag
->GetProto();
6641 for(uint32 j
= 0; j
< pBagProto
->ContainerSlots
; j
++)
6643 pItem2
= GetItemByPos( bag
, j
);
6644 if( pItem2
&& pItem2
->GetEntry() == pItem
->GetEntry() && pItem2
->GetCount() + pItem
->GetCount() <= pProto
->Stackable
)
6646 dest
= ( (bag
<< 8) | j
);
6647 return EQUIP_ERR_OK
;
6654 if( bag
== INVENTORY_SLOT_BAG_0
)
6656 for(int i
= INVENTORY_SLOT_ITEM_START
; i
< INVENTORY_SLOT_ITEM_END
; i
++)
6658 pItem2
= GetItemByPos( INVENTORY_SLOT_BAG_0
, i
);
6661 dest
= ( (INVENTORY_SLOT_BAG_0
<< 8) | i
);
6662 return EQUIP_ERR_OK
;
6668 pBag
= (Bag
*)GetItemByPos( INVENTORY_SLOT_BAG_0
, bag
);
6671 pBagProto
= pBag
->GetProto();
6674 if( pBagProto
->Class
== ITEM_CLASS_QUIVER
&& pBagProto
->SubClass
!= pProto
->SubClass
)
6675 return EQUIP_ERR_ONLY_AMMO_CAN_GO_HERE
;
6676 if( pBagProto
->Class
== ITEM_CLASS_CONTAINER
&& pBagProto
->SubClass
> ITEM_SUBCLASS_CONTAINER
&& pBagProto
->SubClass
!= pProto
->SubClass
)
6677 return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG
;
6678 for(uint32 j
= 0; j
< pBagProto
->ContainerSlots
; j
++)
6680 pItem2
= GetItemByPos( bag
, j
);
6683 dest
= ( (bag
<< 8) | j
);
6684 return EQUIP_ERR_OK
;
6690 return EQUIP_ERR_BAG_FULL
;
6692 else // specific bag and slot
6694 if( pProto
->InventoryType
== INVTYPE_BAG
)
6696 Bag
*pBag
= (Bag
*)pItem
;
6697 if( pBag
&& !pBag
->IsEmpty() )
6698 return EQUIP_ERR_NONEMPTY_BAG_OVER_OTHER_BAG
;
6700 pItem2
= GetItemByPos( bag
, slot
);
6701 if( pItem2
&& !swap
)
6703 if( pProto
->Stackable
> 1 && pItem2
->GetEntry() == pItem
->GetEntry() && pItem2
->GetCount() < pProto
->Stackable
)
6705 dest
= ( (bag
<< 8) | slot
);
6706 return EQUIP_ERR_OK
;
6709 return EQUIP_ERR_COULDNT_SPLIT_ITEMS
;
6713 if( bag
== INVENTORY_SLOT_BAG_0
)
6715 dest
= ( (bag
<< 8) | slot
);
6716 return EQUIP_ERR_OK
;
6720 pBag
= (Bag
*)GetItemByPos( INVENTORY_SLOT_BAG_0
, bag
);
6723 pBagProto
= pBag
->GetProto();
6726 if( pBagProto
->Class
== ITEM_CLASS_QUIVER
&& pBagProto
->SubClass
!= pProto
->SubClass
)
6727 return EQUIP_ERR_ONLY_AMMO_CAN_GO_HERE
;
6728 if( pBagProto
->Class
== ITEM_CLASS_CONTAINER
&& pBagProto
->SubClass
> ITEM_SUBCLASS_CONTAINER
&& pBagProto
->SubClass
!= pProto
->SubClass
)
6729 return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG
;
6730 dest
= ( (bag
<< 8) | slot
);
6731 return EQUIP_ERR_OK
;
6741 return EQUIP_ERR_ITEM_NOT_FOUND
;
6743 return EQUIP_ERR_ITEMS_CANT_BE_SWAPPED
;
6747 uint8
Player::CanEquipItem( uint8 slot
, uint16
&dest
, Item
*pItem
, bool swap
, bool check_alive
) const
6752 sLog
.outDebug( "STORAGE: CanEquipItem slot = %u, item = %u, count = %u", slot
, pItem
->GetEntry(), pItem
->GetCount());
6753 ItemPrototype
const *pProto
= pItem
->GetProto();
6756 if(isInCombat()&& pProto
->Class
!= ITEM_CLASS_WEAPON
&& pProto
->Class
!= ITEM_CLASS_PROJECTILE
)
6757 return EQUIP_ERR_CANT_DO_IN_COMBAT
;
6759 uint32 type
= pProto
->InventoryType
;
6760 uint8 eslot
= FindEquipSlot( type
, slot
, swap
);
6761 if( eslot
== NULL_SLOT
)
6762 return EQUIP_ERR_ITEM_CANT_BE_EQUIPPED
;
6764 uint8 msg
= CanUseItem( pItem
, check_alive
);
6765 if( msg
!= EQUIP_ERR_OK
)
6767 if( !swap
&& GetItemByPos( INVENTORY_SLOT_BAG_0
, eslot
) )
6768 return EQUIP_ERR_NO_EQUIPMENT_SLOT_AVAILABLE
;
6770 if(eslot
== EQUIPMENT_SLOT_OFFHAND
)
6772 if( type
== INVTYPE_WEAPON
|| type
== INVTYPE_WEAPONOFFHAND
)
6775 return EQUIP_ERR_CANT_DUAL_WIELD
;
6778 Item
*mainItem
= GetItemByPos( INVENTORY_SLOT_BAG_0
, EQUIPMENT_SLOT_MAINHAND
);
6781 if(mainItem
->GetProto()->InventoryType
== INVTYPE_2HWEAPON
)
6782 return EQUIP_ERR_CANT_EQUIP_WITH_TWOHANDED
;
6784 // not let equip offhand item if mainhand not equiped
6785 return EQUIP_ERR_ITEM_CANT_BE_EQUIPPED
;
6789 if( type
== INVTYPE_2HWEAPON
)
6791 uint8 twinslot
= ( eslot
== EQUIPMENT_SLOT_MAINHAND
? EQUIPMENT_SLOT_OFFHAND
: EQUIPMENT_SLOT_MAINHAND
);
6792 Item
*twinItem
= GetItemByPos( INVENTORY_SLOT_BAG_0
, twinslot
);
6794 return EQUIP_ERR_ITEM_CANT_BE_EQUIPPED
;
6796 dest
= ((INVENTORY_SLOT_BAG_0
<< 8) | eslot
);
6797 return EQUIP_ERR_OK
;
6801 return EQUIP_ERR_ITEM_NOT_FOUND
;
6803 return EQUIP_ERR_ITEMS_CANT_BE_SWAPPED
;
6806 uint8
Player::CanUnequipItem( uint16 pos
, bool swap
) const
6808 // Applied only to equiped items
6809 if(!IsEquipmentPos(pos
) )
6810 return EQUIP_ERR_OK
;
6812 Item
* pItem
= GetItemByPos(pos
);
6814 // Applied only to existed equiped item
6816 return EQUIP_ERR_OK
;
6818 sLog
.outDebug( "STORAGE: CanUnequipItem slot = %u, item = %u, count = %u", pos
, pItem
->GetEntry(), pItem
->GetCount());
6820 ItemPrototype
const *pProto
= pItem
->GetProto();
6822 return EQUIP_ERR_ITEM_NOT_FOUND
;
6824 if(isInCombat()&& pProto
->Class
!= ITEM_CLASS_WEAPON
&& pProto
->Class
!= ITEM_CLASS_PROJECTILE
)
6825 return EQUIP_ERR_CANT_DO_IN_COMBAT
;
6827 // All equiped items can swaped (not in combat case)
6829 return EQUIP_ERR_OK
;
6831 uint32 type
= pProto
->InventoryType
;
6832 uint8 slot
= pos
& 255;
6834 // can't unequip mainhand item if offhand item equiped
6835 if(slot
== EQUIPMENT_SLOT_MAINHAND
&& GetItemByPos( INVENTORY_SLOT_BAG_0
, EQUIPMENT_SLOT_OFFHAND
))
6836 return EQUIP_ERR_CANT_DO_RIGHT_NOW
;
6838 return EQUIP_ERR_OK
;
6841 uint8
Player::CanBankItem( uint8 bag
, uint8 slot
, uint16
&dest
, Item
*pItem
, bool swap
) const
6846 sLog
.outDebug( "STORAGE: CanBankItem bag = %u, slot = %u, item = %u, count = %u", bag
, slot
, pItem
->GetEntry(), pItem
->GetCount());
6847 ItemPrototype
const *pProto
= pItem
->GetProto();
6852 ItemPrototype
const *pBagProto
;
6854 if( pItem
->IsBindedNotWith(GetGUID()) )
6855 return EQUIP_ERR_DONT_OWN_THAT_ITEM
;
6858 if( !swap
&& pProto
->MaxCount
> 0 )
6860 uint32 curcount
= 0;
6861 for(int i
= EQUIPMENT_SLOT_START
; i
< INVENTORY_SLOT_ITEM_END
; i
++)
6863 pos
= ((INVENTORY_SLOT_BAG_0
<< 8) | i
);
6864 pItem2
= GetItemByPos( pos
);
6865 if( pItem2
&& pItem2
->GetEntry() == pItem
->GetEntry() )
6867 curcount
+= pItem2
->GetCount();
6868 if( curcount
+ pItem
->GetCount() > pProto
->MaxCount
)
6869 return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS
;
6872 for(int i
= INVENTORY_SLOT_BAG_START
; i
< INVENTORY_SLOT_BAG_END
; i
++)
6874 pos
= ((INVENTORY_SLOT_BAG_0
<< 8) | i
);
6875 pBag
= (Bag
*)GetItemByPos( pos
);
6878 pBagProto
= pBag
->GetProto();
6881 for(uint32 j
= 0; j
< pBagProto
->ContainerSlots
; j
++)
6883 pos
= ((i
<< 8) | j
);
6884 pItem2
= GetItemByPos( pos
);
6885 if( pItem2
&& pItem2
->GetEntry() == pItem
->GetEntry() )
6887 curcount
+= pItem2
->GetCount();
6888 if( curcount
+ pItem
->GetCount() > pProto
->MaxCount
)
6889 return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS
;
6895 for(int i
= BANK_SLOT_BAG_START
; i
< BANK_SLOT_BAG_END
; i
++)
6897 pos
= ((INVENTORY_SLOT_BAG_0
<< 8) | i
);
6898 pBag
= (Bag
*)GetItemByPos( pos
);
6901 pBagProto
= pBag
->GetProto();
6904 for(uint32 j
= 0; j
< pBagProto
->ContainerSlots
; j
++)
6906 pos
= ((i
<< 8) | j
);
6907 pItem2
= GetItemByPos( pos
);
6908 if( pItem2
&& pItem2
->GetEntry() == pItem
->GetEntry() )
6910 curcount
+= pItem2
->GetCount();
6911 if( curcount
+ pItem
->GetCount() > pProto
->MaxCount
)
6912 return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS
;
6919 if( pProto
->Stackable
> 1 )
6921 for(int i
= BANK_SLOT_ITEM_START
; i
< BANK_SLOT_ITEM_END
; i
++)
6923 pos
= ( (INVENTORY_SLOT_BAG_0
<< 8) | i
);
6924 pItem2
= GetItemByPos( pos
);
6925 if( pItem2
&& pItem2
->GetEntry() == pItem
->GetEntry() && pItem2
->GetCount() + pItem
->GetCount() <= pProto
->Stackable
)
6928 return EQUIP_ERR_OK
;
6931 for(int i
= BANK_SLOT_BAG_START
; i
< BANK_SLOT_BAG_END
; i
++)
6933 pos
= ( (INVENTORY_SLOT_BAG_0
<< 8) | i
);
6934 pBag
= (Bag
*)GetItemByPos( pos
);
6937 pBagProto
= pBag
->GetProto();
6940 for(uint32 j
= 0; j
< pBagProto
->ContainerSlots
; j
++)
6942 pos
= ( (i
<< 8) | j
);
6943 pItem2
= GetItemByPos( pos
);
6944 if( pItem2
&& pItem2
->GetEntry() == pItem
->GetEntry() && pItem2
->GetCount() + pItem
->GetCount() <= pProto
->Stackable
)
6947 return EQUIP_ERR_OK
;
6954 if( pProto
->Class
== ITEM_CLASS_PROJECTILE
)
6956 for(int i
= BANK_SLOT_BAG_START
; i
< BANK_SLOT_BAG_END
; i
++)
6958 pos
= ( (INVENTORY_SLOT_BAG_0
<< 8) | i
);
6959 pBag
= (Bag
*)GetItemByPos( INVENTORY_SLOT_BAG_0
, i
);
6962 pBagProto
= pBag
->GetProto();
6963 if( pBagProto
&& pBagProto
->SubClass
== pProto
->SubClass
)
6965 for(int j
= 0; j
< pBagProto
->ContainerSlots
; j
++)
6967 pos
= ( (INVENTORY_SLOT_BAG_0
<< 8) | i
);
6968 pItem2
= GetItemByPos( i
, j
);
6971 dest
= ( (i
<< 8) | j
);
6972 return EQUIP_ERR_OK
;
6979 for(int i
= BANK_SLOT_ITEM_START
; i
< BANK_SLOT_ITEM_END
; i
++)
6981 pItem2
= GetItemByPos( INVENTORY_SLOT_BAG_0
, i
);
6984 dest
= ( (INVENTORY_SLOT_BAG_0
<< 8) | i
);
6985 return EQUIP_ERR_OK
;
6988 for(int i
= BANK_SLOT_BAG_START
; i
< BANK_SLOT_BAG_END
; i
++)
6990 pBag
= (Bag
*)GetItemByPos( INVENTORY_SLOT_BAG_0
, i
);
6993 pBagProto
= pBag
->GetProto();
6994 if( pBagProto
&& pBagProto
->Class
!= ITEM_CLASS_QUIVER
)
6996 for(uint32 j
= 0; j
< pBagProto
->ContainerSlots
; j
++)
6998 pItem2
= GetItemByPos( i
, j
);
7001 dest
= ( (i
<< 8) | j
);
7002 return EQUIP_ERR_OK
;
7008 return EQUIP_ERR_BANK_FULL
;
7012 if( slot
== NULL_SLOT
)
7014 if( pProto
->InventoryType
== INVTYPE_BAG
)
7016 Bag
*pBag
= (Bag
*)pItem
;
7017 if( pBag
&& !pBag
->IsEmpty() )
7018 return EQUIP_ERR_NONEMPTY_BAG_OVER_OTHER_BAG
;
7020 if( pProto
->Stackable
> 1 )
7022 if( bag
== INVENTORY_SLOT_BAG_0
)
7024 for(int i
= BANK_SLOT_ITEM_START
; i
< BANK_SLOT_ITEM_END
; i
++)
7026 pItem2
= GetItemByPos( INVENTORY_SLOT_BAG_0
, i
);
7027 if( pItem2
&& pItem2
->GetEntry() == pItem
->GetEntry() && pItem2
->GetCount() + pItem
->GetCount() <= pProto
->Stackable
)
7029 dest
= ( (INVENTORY_SLOT_BAG_0
<< 8) | i
);
7030 return EQUIP_ERR_OK
;
7036 pBag
= (Bag
*)GetItemByPos( INVENTORY_SLOT_BAG_0
, bag
);
7039 pBagProto
= pBag
->GetProto();
7042 for(uint32 j
= 0; j
< pBagProto
->ContainerSlots
; j
++)
7044 pItem2
= GetItemByPos( bag
, j
);
7045 if( pItem2
&& pItem2
->GetEntry() == pItem
->GetEntry() && pItem2
->GetCount() + pItem
->GetCount() <= pProto
->Stackable
)
7047 dest
= ( (bag
<< 8) | j
);
7048 return EQUIP_ERR_OK
;
7055 if( bag
== INVENTORY_SLOT_BAG_0
)
7057 for(int i
= BANK_SLOT_ITEM_START
; i
< BANK_SLOT_ITEM_END
; i
++)
7059 pItem2
= GetItemByPos( INVENTORY_SLOT_BAG_0
, i
);
7062 dest
= ( (INVENTORY_SLOT_BAG_0
<< 8) | i
);
7063 return EQUIP_ERR_OK
;
7069 pBag
= (Bag
*)GetItemByPos( INVENTORY_SLOT_BAG_0
, bag
);
7072 pBagProto
= pBag
->GetProto();
7075 if( pBagProto
->Class
== ITEM_CLASS_QUIVER
&& pBagProto
->SubClass
!= pProto
->SubClass
)
7076 return EQUIP_ERR_ONLY_AMMO_CAN_GO_HERE
;
7077 if( pBagProto
->Class
== ITEM_CLASS_CONTAINER
&& pBagProto
->SubClass
> ITEM_SUBCLASS_CONTAINER
&& pBagProto
->SubClass
!= pProto
->SubClass
)
7078 return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG
;
7079 for(uint32 j
= 0; j
< pBagProto
->ContainerSlots
; j
++)
7081 pItem2
= GetItemByPos( bag
, j
);
7084 dest
= ( (bag
<< 8) | j
);
7085 return EQUIP_ERR_OK
;
7091 return EQUIP_ERR_BAG_FULL
;
7095 if( pProto
->InventoryType
== INVTYPE_BAG
)
7097 Bag
*pBag
= (Bag
*)pItem
;
7100 if( slot
>= BANK_SLOT_BAG_START
&& slot
< BANK_SLOT_BAG_END
)
7102 if( !HasBankBagSlot( slot
) )
7103 return EQUIP_ERR_MUST_PURCHASE_THAT_BAG_SLOT
;
7104 if( uint8 cantuse
= CanUseItem( pItem
) != EQUIP_ERR_OK
)
7109 if( !pBag
->IsEmpty() )
7110 return EQUIP_ERR_NONEMPTY_BAG_OVER_OTHER_BAG
;
7116 if( slot
>= BANK_SLOT_BAG_START
&& slot
< BANK_SLOT_BAG_END
)
7117 return EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT
;
7119 pItem2
= GetItemByPos( bag
, slot
);
7120 if( pItem2
&& !swap
)
7122 if( pProto
->Stackable
> 1 && pItem2
->GetEntry() == pItem
->GetEntry() && pItem2
->GetCount() + pItem
->GetCount() <= pProto
->Stackable
)
7124 dest
= ( (bag
<< 8) | slot
);
7125 return EQUIP_ERR_OK
;
7128 return EQUIP_ERR_COULDNT_SPLIT_ITEMS
;
7132 if( bag
== INVENTORY_SLOT_BAG_0
)
7134 dest
= ( (bag
<< 8) | slot
);
7135 return EQUIP_ERR_OK
;
7139 pBag
= (Bag
*)GetItemByPos( INVENTORY_SLOT_BAG_0
, bag
);
7142 pBagProto
= pBag
->GetProto();
7145 if( pBagProto
->Class
== ITEM_CLASS_QUIVER
&& pBagProto
->SubClass
!= pProto
->SubClass
)
7146 return EQUIP_ERR_ONLY_AMMO_CAN_GO_HERE
;
7147 if( pBagProto
->Class
== ITEM_CLASS_CONTAINER
&& pBagProto
->SubClass
> ITEM_SUBCLASS_CONTAINER
&& pBagProto
->SubClass
!= pProto
->SubClass
)
7148 return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG
;
7149 dest
= ( (bag
<< 8) | slot
);
7150 return EQUIP_ERR_OK
;
7160 return EQUIP_ERR_ITEM_NOT_FOUND
;
7162 return EQUIP_ERR_ITEMS_CANT_BE_SWAPPED
;
7166 uint8
Player::CanUseItem( Item
*pItem
, bool check_alive
) const
7170 sLog
.outDebug( "STORAGE: CanUseItem item = %u", pItem
->GetEntry());
7171 if( !isAlive() && check_alive
)
7172 return EQUIP_ERR_YOU_ARE_DEAD
;
7174 // return EQUIP_ERR_YOU_ARE_STUNNED;
7175 ItemPrototype
const *pProto
= pItem
->GetProto();
7178 if( pItem
->IsBindedNotWith(GetGUID()) )
7179 return EQUIP_ERR_DONT_OWN_THAT_ITEM
;
7180 if( (pProto
->AllowableClass
& getClassMask()) == 0 || (pProto
->AllowableRace
& getRaceMask()) == 0 )
7181 return EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM
;
7182 if( pItem
->GetSkill() != 0 )
7184 if( GetSkillValue( pItem
->GetSkill() ) == 0 )
7185 return EQUIP_ERR_NO_REQUIRED_PROFICIENCY
;
7187 if( pProto
->RequiredSkill
!= 0 )
7189 if( GetSkillValue( pProto
->RequiredSkill
) == 0 )
7190 return EQUIP_ERR_NO_REQUIRED_PROFICIENCY
;
7191 else if( GetSkillValue( pProto
->RequiredSkill
) < pProto
->RequiredSkillRank
)
7192 return EQUIP_ERR_SKILL_ISNT_HIGH_ENOUGH
;
7194 if( pProto
->RequiredSpell
!= 0 && !HasSpell( pProto
->RequiredSpell
) )
7195 return EQUIP_ERR_NO_REQUIRED_PROFICIENCY
;
7196 if( GetHonorRank() < pProto
->RequiredHonorRank
)
7197 return EQUIP_ITEM_RANK_NOT_ENOUGH
;
7198 /*if( GetREputation() < pProto->RequiredReputation )
7199 return EQUIP_ITEM_REPUTATION_NOT_ENOUGH;
7201 if( getLevel() < pProto
->RequiredLevel
)
7202 return EQUIP_ERR_YOU_MUST_REACH_LEVEL_N
;
7203 return EQUIP_ERR_OK
;
7206 return EQUIP_ERR_ITEM_NOT_FOUND
;
7209 bool Player::CanUseItem( ItemPrototype
const *pProto
)
7211 // Used by group, function NeedBeforeGreed, to know if a prototype can be used by a player
7215 if( (pProto
->AllowableClass
& getClassMask()) == 0 || (pProto
->AllowableRace
& getRaceMask()) == 0 )
7217 if( pProto
->RequiredSkill
!= 0 )
7219 if( GetSkillValue( pProto
->RequiredSkill
) == 0 )
7221 else if( GetSkillValue( pProto
->RequiredSkill
) < pProto
->RequiredSkillRank
)
7224 if( pProto
->RequiredSpell
!= 0 && !HasSpell( pProto
->RequiredSpell
) )
7226 if( GetHonorRank() < pProto
->RequiredHonorRank
)
7228 if( getLevel() < pProto
->RequiredLevel
)
7235 uint8
Player::CanUseAmmo( uint32 item
) const
7237 sLog
.outDebug( "STORAGE: CanUseAmmo item = %u", item
);
7239 return EQUIP_ERR_YOU_ARE_DEAD
;
7241 // return EQUIP_ERR_YOU_ARE_STUNNED;
7242 ItemPrototype
const *pProto
= objmgr
.GetItemPrototype( item
);
7245 if( (pProto
->AllowableClass
& getClassMask()) == 0 || (pProto
->AllowableRace
& getRaceMask()) == 0 )
7246 return EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM
;
7247 if( pProto
->RequiredSkill
!= 0 )
7249 if( GetSkillValue( pProto
->RequiredSkill
) == 0 )
7250 return EQUIP_ERR_NO_REQUIRED_PROFICIENCY
;
7251 else if( GetSkillValue( pProto
->RequiredSkill
) < pProto
->RequiredSkillRank
)
7252 return EQUIP_ERR_SKILL_ISNT_HIGH_ENOUGH
;
7254 if( pProto
->RequiredSpell
!= 0 && !HasSpell( pProto
->RequiredSpell
) )
7255 return EQUIP_ERR_NO_REQUIRED_PROFICIENCY
;
7256 if( GetHonorRank() < pProto
->RequiredHonorRank
)
7257 return EQUIP_ITEM_RANK_NOT_ENOUGH
;
7258 /*if( GetREputation() < pProto->RequiredReputation )
7259 return EQUIP_ITEM_REPUTATION_NOT_ENOUGH;
7261 if( getLevel() < pProto
->RequiredLevel
)
7262 return EQUIP_ERR_YOU_MUST_REACH_LEVEL_N
;
7263 return EQUIP_ERR_OK
;
7265 return EQUIP_ERR_ITEM_NOT_FOUND
;
7268 // Return stored item (if stored to stack, it can diff. from pItem). And pItem ca be deleted in this case.
7269 Item
* Player::StoreNewItem( uint16 pos
, uint32 item
, uint32 count
, bool update
,bool fromLoot
)
7271 Item
*pItem
= CreateItem( item
, count
);
7274 ItemPrototype
const *pProto
= pItem
->GetProto();
7275 ItemAdded( item
, count
);
7277 pItem
->SetItemRandomProperties();
7278 return StoreItem( pos
, pItem
, update
);
7283 // Return stored item (if stored to stack, it can diff. from pItem). And pItem ca be deleted in this case.
7284 Item
* Player::StoreItem( uint16 pos
, Item
*pItem
, bool update
)
7288 if( pItem
->GetProto()->Bonding
== BIND_WHEN_PICKED_UP
|| pItem
->GetProto()->Class
== ITEM_CLASS_QUEST
)
7289 pItem
->SetBinding( true );
7291 uint8 bag
= pos
>> 8;
7292 uint8 slot
= pos
& 255;
7294 sLog
.outDebug( "STORAGE: StoreItem bag = %u, slot = %u, item = %u, count = %u", bag
, slot
, pItem
->GetEntry(), pItem
->GetCount());
7296 Item
*pItem2
= GetItemByPos( bag
, slot
);
7300 if( bag
== INVENTORY_SLOT_BAG_0
)
7302 m_items
[slot
] = pItem
;
7303 SetUInt64Value( (uint16
)(PLAYER_FIELD_INV_SLOT_HEAD
+ (slot
* 2) ), pItem
->GetGUID() );
7304 pItem
->SetUInt64Value( ITEM_FIELD_CONTAINED
, GetGUID() );
7305 pItem
->SetUInt64Value( ITEM_FIELD_OWNER
, GetGUID() );
7307 pItem
->SetSlot( slot
);
7309 if( IsInWorld() && update
)
7311 pItem
->AddToWorld();
7312 pItem
->SendUpdateToPlayer( this );
7317 Bag
*pBag
= (Bag
*)GetItemByPos( INVENTORY_SLOT_BAG_0
, bag
);
7320 pBag
->StoreItem( slot
, pItem
, update
);
7321 if( IsInWorld() && update
)
7323 pItem
->AddToWorld();
7324 pItem
->SendUpdateToPlayer( this );
7331 pItem2
->SetCount( pItem2
->GetCount() + pItem
->GetCount() );
7332 if( IsInWorld() && update
)
7333 pItem2
->SendUpdateToPlayer( this );
7335 // delete item (it not in any slot currently)
7336 pItem
->DeleteFromDB();
7337 if( IsInWorld() && update
)
7339 pItem
->RemoveFromWorld();
7340 pItem
->DestroyForPlayer( this );
7350 void Player::EquipItem( uint16 pos
, Item
*pItem
, bool update
)
7354 VisualizeItem( pos
, pItem
);
7355 uint8 slot
= pos
& 255;
7358 _ApplyItemMods(pItem
, slot
, true);
7360 if( IsInWorld() && update
)
7362 pItem
->AddToWorld();
7363 pItem
->SendUpdateToPlayer( this );
7368 void Player::QuickEquipItem( uint16 pos
, Item
*pItem
)
7372 VisualizeItem( pos
, pItem
);
7376 pItem
->AddToWorld();
7377 pItem
->SendUpdateToPlayer( this );
7382 void Player::VisualizeItem( uint16 pos
, Item
*pItem
)
7387 // check also BIND_WHEN_PICKED_UP for .additem or .additemset case by GM (not binded at adding to inventory)
7388 if( pItem
->GetProto()->Bonding
== BIND_WHEN_EQUIPED
|| pItem
->GetProto()->Bonding
== BIND_WHEN_PICKED_UP
)
7389 pItem
->SetBinding( true );
7391 uint8 bag
= pos
>> 8;
7392 uint8 slot
= pos
& 255;
7394 sLog
.outDebug( "STORAGE: EquipItem bag = %u, slot = %u, item = %u", bag
, slot
, pItem
->GetEntry());
7396 m_items
[slot
] = pItem
;
7397 SetUInt64Value( (uint16
)(PLAYER_FIELD_INV_SLOT_HEAD
+ (slot
* 2) ), pItem
->GetGUID() );
7398 pItem
->SetUInt64Value( ITEM_FIELD_CONTAINED
, GetGUID() );
7399 pItem
->SetUInt64Value( ITEM_FIELD_OWNER
, GetGUID() );
7400 pItem
->SetSlot( slot
);
7402 if( slot
< EQUIPMENT_SLOT_END
)
7404 int VisibleBase
= PLAYER_VISIBLE_ITEM_1_0
+ (slot
* 12);
7405 SetUInt32Value(VisibleBase
, pItem
->GetEntry());
7406 SetUInt32Value(VisibleBase
+ 1, pItem
->GetUInt32Value(ITEM_FIELD_ENCHANTMENT
));
7407 SetUInt32Value(VisibleBase
+ 2, pItem
->GetUInt32Value(ITEM_FIELD_ENCHANTMENT
+ 1*3));
7408 SetUInt32Value(VisibleBase
+ 3, pItem
->GetUInt32Value(ITEM_FIELD_ENCHANTMENT
+ 2*3));
7409 SetUInt32Value(VisibleBase
+ 4, pItem
->GetUInt32Value(ITEM_FIELD_ENCHANTMENT
+ 3*3));
7410 SetUInt32Value(VisibleBase
+ 5, pItem
->GetUInt32Value(ITEM_FIELD_ENCHANTMENT
+ 4*3));
7411 SetUInt32Value(VisibleBase
+ 6, pItem
->GetUInt32Value(ITEM_FIELD_ENCHANTMENT
+ 5*3));
7412 SetUInt32Value(VisibleBase
+ 7, pItem
->GetUInt32Value(ITEM_FIELD_ENCHANTMENT
+ 6*3));
7413 SetUInt32Value(VisibleBase
+ 8, pItem
->GetUInt32Value(ITEM_FIELD_RANDOM_PROPERTIES_ID
));
7418 // Return stored item (if stored to stack, it can diff. from pItem). And pItem ca be deleted in this case.
7419 Item
* Player::BankItem( uint16 pos
, Item
*pItem
, bool update
)
7421 return StoreItem( pos
, pItem
, update
);
7424 void Player::RemoveItem( uint8 bag
, uint8 slot
, bool update
)
7426 Item
*pItem
= GetItemByPos( bag
, slot
);
7429 sLog
.outDebug( "STORAGE: RemoveItem bag = %u, slot = %u, item = %u", bag
, slot
, pItem
->GetEntry());
7431 if( bag
== INVENTORY_SLOT_BAG_0
)
7433 m_items
[slot
] = NULL
;
7434 SetUInt64Value((uint16
)(PLAYER_FIELD_INV_SLOT_HEAD
+ (slot
*2)), 0);
7436 if ( slot
< INVENTORY_SLOT_BAG_END
)
7438 _ApplyItemMods(pItem
, slot
, false);
7439 if ( slot
< EQUIPMENT_SLOT_END
)
7441 int VisibleBase
= PLAYER_VISIBLE_ITEM_1_0
+ (slot
* 12);
7442 for (int i
= VisibleBase
; i
< VisibleBase
+ 12; ++i
)
7443 SetUInt32Value(i
, 0);
7449 Bag
*pBag
= (Bag
*)GetItemByPos( INVENTORY_SLOT_BAG_0
, bag
);
7451 pBag
->RemoveItem(slot
, update
);
7453 pItem
->SetUInt64Value( ITEM_FIELD_CONTAINED
, 0 );
7454 // pItem->SetUInt64Value( ITEM_FIELD_OWNER, 0 ); not clear owner at remove (it will be set at store). This used in mail and auction code
7455 pItem
->SetSlot( NULL_SLOT
);
7456 if( IsInWorld() && update
)
7457 pItem
->SendUpdateToPlayer( this );
7461 void Player::RemoveItemCount( uint32 item
, uint32 count
, bool update
)
7463 sLog
.outDebug( "STORAGE: RemoveItemCount item = %u, count = %u", item
, count
);
7465 uint32 remcount
= 0;
7466 for(int i
= EQUIPMENT_SLOT_START
; i
< INVENTORY_SLOT_ITEM_END
; i
++)
7468 pItem
= GetItemByPos( INVENTORY_SLOT_BAG_0
, i
);
7469 if( pItem
&& pItem
->GetEntry() == item
)
7471 if( pItem
->GetCount() + remcount
<= count
)
7473 remcount
+= pItem
->GetCount();
7474 RemoveItem( INVENTORY_SLOT_BAG_0
, i
, update
);
7476 if(remcount
>=count
)
7481 pItem
->SetCount( pItem
->GetCount() - count
+ remcount
);
7482 if( IsInWorld() && update
)
7483 pItem
->SendUpdateToPlayer( this );
7489 ItemPrototype
const *pBagProto
;
7490 for(int i
= INVENTORY_SLOT_BAG_START
; i
< INVENTORY_SLOT_BAG_END
; i
++)
7492 pBag
= (Bag
*)GetItemByPos( INVENTORY_SLOT_BAG_0
, i
);
7495 pBagProto
= pBag
->GetProto();
7498 for(uint32 j
= 0; j
< pBagProto
->ContainerSlots
; j
++)
7500 pItem
= GetItemByPos( i
, j
);
7501 if( pItem
&& pItem
->GetEntry() == item
)
7503 if( pItem
->GetCount() + remcount
<= count
)
7505 remcount
+= pItem
->GetCount();
7506 RemoveItem( i
, j
, update
);
7508 if(remcount
>=count
)
7513 pItem
->SetCount( pItem
->GetCount() - count
+ remcount
);
7514 if( IsInWorld() && update
)
7515 pItem
->SendUpdateToPlayer( this );
7525 void Player::DestroyItem( uint8 bag
, uint8 slot
, bool update
)
7527 Item
*pItem
= GetItemByPos( bag
, slot
);
7530 sLog
.outDebug( "STORAGE: DestroyItem bag = %u, slot = %u, item = %u", bag
, slot
, pItem
->GetEntry());
7531 pItem
->SetOwnerGUID(0);
7532 pItem
->SetSlot( NULL_SLOT
);
7533 pItem
->SetUInt64Value( ITEM_FIELD_CONTAINED
, 0 );
7534 pItem
->DeleteFromDB();
7535 ItemPrototype
const *pProto
= pItem
->GetProto();
7537 if( bag
== INVENTORY_SLOT_BAG_0
)
7539 ItemRemoved( pItem
->GetEntry(), pItem
->GetCount() );
7541 SetUInt64Value((uint16
)(PLAYER_FIELD_INV_SLOT_HEAD
+ (slot
*2)), 0);
7543 if ( slot
< EQUIPMENT_SLOT_END
)
7545 _ApplyItemMods(pItem
, slot
, false);
7546 int VisibleBase
= PLAYER_VISIBLE_ITEM_1_0
+ (slot
* 12);
7547 for (int i
= VisibleBase
; i
< VisibleBase
+ 12; ++i
)
7548 SetUInt32Value(i
, 0);
7549 for(int enchant_slot
= 0 ; enchant_slot
< 7; enchant_slot
++)
7551 uint32 Enchant_id
= pItem
->GetUInt32Value(ITEM_FIELD_ENCHANTMENT
+enchant_slot
*3);
7554 SpellItemEnchantmentEntry
*pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(Enchant_id
);
7557 uint32 enchant_display
= pEnchant
->display_type
;
7558 uint32 enchant_value1
= pEnchant
->value1
;
7559 //uint32 enchant_value2 = pEnchant->value2;
7560 uint32 enchant_spell_id
= pEnchant
->spellid
;
7561 //uint32 enchant_aura_id = pEnchant->aura_id;
7562 //uint32 enchant_description = pEnchant->description;
7563 //SpellEntry *enchantSpell_info = sSpellStore.LookupEntry(enchant_spell_id);
7564 if(enchant_display
==4)
7565 SetArmor(GetArmor()-enchant_value1
);
7566 else if(enchant_display
==2)
7568 SetUInt32Value(UNIT_FIELD_MINDAMAGE
,GetUInt32Value(UNIT_FIELD_MINDAMAGE
)-enchant_value1
);
7569 SetUInt32Value(UNIT_FIELD_MAXDAMAGE
,GetUInt32Value(UNIT_FIELD_MAXDAMAGE
)-enchant_value1
);
7573 RemoveAurasDueToSpell(enchant_spell_id
);
7579 m_items
[slot
] = NULL
;
7580 if( IsInWorld() && update
)
7582 pItem
->RemoveFromWorld();
7583 pItem
->DestroyForPlayer( this );
7588 Bag
*pBag
= (Bag
*)GetItemByPos( INVENTORY_SLOT_BAG_0
, bag
);
7591 if( pProto
&& pProto
->Class
== ITEM_CLASS_QUEST
)
7592 ItemRemoved( pItem
->GetEntry(), pItem
->GetCount() );
7593 pBag
->RemoveItem(slot
, update
);
7595 if( IsInWorld() && update
)
7597 pItem
->RemoveFromWorld();
7598 pItem
->DestroyForPlayer(this);
7606 void Player::DestroyItemCount( uint32 item
, uint32 count
, bool update
)
7608 sLog
.outDebug( "STORAGE: DestroyItemCount item = %u, count = %u", item
, count
);
7610 ItemPrototype
const *pProto
;
7611 uint32 remcount
= 0;
7612 for(int i
= EQUIPMENT_SLOT_START
; i
< INVENTORY_SLOT_ITEM_END
; i
++)
7614 pItem
= GetItemByPos( INVENTORY_SLOT_BAG_0
, i
);
7615 if( pItem
&& pItem
->GetEntry() == item
)
7617 if( pItem
->GetCount() + remcount
<= count
)
7619 remcount
+= pItem
->GetCount();
7620 DestroyItem( INVENTORY_SLOT_BAG_0
, i
, update
);
7622 if(remcount
>=count
)
7627 pProto
= pItem
->GetProto();
7628 ItemRemoved( pItem
->GetEntry(), count
- remcount
);
7629 pItem
->SetCount( pItem
->GetCount() - count
+ remcount
);
7630 if( IsInWorld() & update
)
7631 pItem
->SendUpdateToPlayer( this );
7637 ItemPrototype
const *pBagProto
;
7638 for(int i
= INVENTORY_SLOT_BAG_START
; i
< INVENTORY_SLOT_BAG_END
; i
++)
7640 pBag
= (Bag
*)GetItemByPos( INVENTORY_SLOT_BAG_0
, i
);
7643 pBagProto
= pBag
->GetProto();
7646 for(uint32 j
= 0; j
< pBagProto
->ContainerSlots
; j
++)
7648 pItem
= pBag
->GetItemByPos(j
);
7649 if( pItem
&& pItem
->GetEntry() == item
)
7651 if( pItem
->GetCount() + remcount
<= count
)
7653 remcount
+= pItem
->GetCount();
7654 DestroyItem( i
, j
, update
);
7656 if(remcount
>=count
)
7661 pProto
= pItem
->GetProto();
7662 ItemRemoved( pItem
->GetEntry(), count
- remcount
);
7663 pItem
->SetCount( pItem
->GetCount() - count
+ remcount
);
7664 if( IsInWorld() && update
)
7665 pItem
->SendUpdateToPlayer( this );
7675 void Player::SplitItem( uint16 src
, uint16 dst
, uint32 count
)
7677 uint8 srcbag
= src
>> 8;
7678 uint8 srcslot
= src
& 255;
7680 uint8 dstbag
= dst
>> 8;
7681 uint8 dstslot
= dst
& 255;
7683 Item
*pSrcItem
= GetItemByPos( srcbag
, srcslot
);
7686 sLog
.outDebug( "STORAGE: SplitItem bag = %u, slot = %u, item = %u, count = %u", dstbag
, dstslot
, pSrcItem
->GetEntry(), count
);
7687 Item
*pNewItem
= CreateItem( pSrcItem
->GetEntry(), count
);
7692 if( IsInventoryPos( dst
) )
7694 msg
= CanStoreItem( dstbag
, dstslot
, dest
, pNewItem
, false );
7695 if( msg
== EQUIP_ERR_OK
)
7697 pSrcItem
->SetCount( pSrcItem
->GetCount() - count
);
7699 pSrcItem
->SendUpdateToPlayer( this );
7700 StoreItem( dest
, pNewItem
, true);
7705 SendEquipError( msg
, pSrcItem
, NULL
);
7708 else if( IsBankPos ( dst
) )
7710 msg
= CanBankItem( dstbag
, dstslot
, dest
, pNewItem
, false );
7711 if( msg
== EQUIP_ERR_OK
)
7713 pSrcItem
->SetCount( pSrcItem
->GetCount() - count
);
7715 pSrcItem
->SendUpdateToPlayer( this );
7716 BankItem( dest
, pNewItem
, true);
7721 SendEquipError( msg
, pSrcItem
, NULL
);
7724 else if( IsEquipmentPos ( dst
) )
7726 msg
= CanEquipItem( dstslot
, dest
, pNewItem
, false );
7727 if( msg
== EQUIP_ERR_OK
)
7729 pSrcItem
->SetCount( pSrcItem
->GetCount() - count
);
7731 pSrcItem
->SendUpdateToPlayer( this );
7732 EquipItem( dest
, pNewItem
, true);
7737 SendEquipError( msg
, pSrcItem
, NULL
);
7743 SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND
, pSrcItem
, NULL
);
7746 void Player::SwapItem( uint16 src
, uint16 dst
)
7748 uint8 srcbag
= src
>> 8;
7749 uint8 srcslot
= src
& 255;
7751 uint8 dstbag
= dst
>> 8;
7752 uint8 dstslot
= dst
& 255;
7754 Item
*pSrcItem
= GetItemByPos( srcbag
, srcslot
);
7755 Item
*pDstItem
= GetItemByPos( dstbag
, dstslot
);
7759 sLog
.outDebug( "STORAGE: SwapItem bag = %u, slot = %u, item = %u", dstbag
, dstslot
, pSrcItem
->GetEntry());
7763 SendEquipError( EQUIP_ERR_YOU_ARE_DEAD
, pSrcItem
, pDstItem
);
7767 if(IsEquipmentPos ( src
))
7769 uint8 msg
= CanUnequipItem( src
, pDstItem
!= NULL
);
7770 if(msg
!= EQUIP_ERR_OK
)
7772 SendEquipError( msg
, pSrcItem
, pDstItem
);
7777 if( srcslot
== dstbag
)
7779 SendEquipError( EQUIP_ERR_NONEMPTY_BAG_OVER_OTHER_BAG
, pSrcItem
, pDstItem
);
7787 if( IsInventoryPos( dst
) )
7789 msg
= CanStoreItem( dstbag
, dstslot
, dest
, pSrcItem
, false );
7790 if( msg
== EQUIP_ERR_OK
)
7792 RemoveItem(srcbag
, srcslot
, true);
7793 StoreItem( dest
, pSrcItem
, true);
7797 SendEquipError( msg
, pSrcItem
, NULL
);
7799 else if( IsBankPos ( dst
) )
7801 msg
= CanBankItem( dstbag
, dstslot
, dest
, pSrcItem
, false);
7802 if( msg
== EQUIP_ERR_OK
)
7804 RemoveItem(srcbag
, srcslot
, true);
7805 BankItem( dest
, pSrcItem
, true);
7809 SendEquipError( msg
, pSrcItem
, NULL
);
7811 else if( IsEquipmentPos ( dst
) )
7813 msg
= CanEquipItem( dstslot
, dest
, pSrcItem
, false );
7814 if( msg
== EQUIP_ERR_OK
)
7816 RemoveItem(srcbag
, srcslot
, true);
7817 EquipItem( dest
, pSrcItem
, true);
7821 SendEquipError( msg
, pSrcItem
, NULL
);
7826 if( IsInventoryPos( dst
) )
7828 if( CanStoreItem( dstbag
, dstslot
, dest
, pSrcItem
, false ) == EQUIP_ERR_OK
)
7830 if( pSrcItem
->GetCount() + pDstItem
->GetCount() <= pSrcItem
->GetProto()->Stackable
)
7832 RemoveItem(srcbag
, srcslot
, true);
7833 StoreItem( dest
, pSrcItem
, true);
7837 pSrcItem
->SetCount( pSrcItem
->GetCount() + pDstItem
->GetCount() - pSrcItem
->GetProto()->Stackable
);
7838 pDstItem
->SetCount( pSrcItem
->GetProto()->Stackable
);
7841 pSrcItem
->SendUpdateToPlayer( this );
7842 pDstItem
->SendUpdateToPlayer( this );
7848 else if( IsBankPos ( dst
) )
7850 if( CanBankItem( dstbag
, dstslot
, dest
, pSrcItem
, false ) == EQUIP_ERR_OK
)
7852 if( pSrcItem
->GetCount() + pDstItem
->GetCount() <= pSrcItem
->GetProto()->Stackable
)
7854 RemoveItem(srcbag
, srcslot
, true);
7855 BankItem( dest
, pSrcItem
, true);
7859 pSrcItem
->SetCount( pSrcItem
->GetCount() + pDstItem
->GetCount() - pSrcItem
->GetProto()->Stackable
);
7860 pDstItem
->SetCount( pSrcItem
->GetProto()->Stackable
);
7863 pSrcItem
->SendUpdateToPlayer( this );
7864 pDstItem
->SendUpdateToPlayer( this );
7870 else if( IsEquipmentPos ( dst
) )
7872 if( CanEquipItem( dstslot
, dest
, pSrcItem
, false ) == EQUIP_ERR_OK
)
7874 if( pSrcItem
->GetCount() + pDstItem
->GetCount() <= pSrcItem
->GetProto()->Stackable
)
7876 RemoveItem(srcbag
, srcslot
, true);
7877 EquipItem( dest
, pSrcItem
, true);
7881 pSrcItem
->SetCount( pSrcItem
->GetCount() + pDstItem
->GetCount() - pSrcItem
->GetProto()->Stackable
);
7882 pDstItem
->SetCount( pSrcItem
->GetProto()->Stackable
);
7885 pSrcItem
->SendUpdateToPlayer( this );
7886 pDstItem
->SendUpdateToPlayer( this );
7892 if( IsInventoryPos( dst
) )
7893 msg
= CanStoreItem( dstbag
, dstslot
, dest
, pSrcItem
, true );
7894 else if( IsBankPos( dst
) )
7895 msg
= CanBankItem( dstbag
, dstslot
, dest
, pSrcItem
, true );
7896 else if( IsEquipmentPos( dst
) )
7898 msg
= CanEquipItem( dstslot
, dest
, pSrcItem
, true );
7899 if( msg
== EQUIP_ERR_OK
)
7900 msg
= CanUnequipItem( dest
, true );
7903 if( msg
== EQUIP_ERR_OK
)
7906 if( IsInventoryPos( src
) )
7908 msg
= CanStoreItem( srcbag
, srcslot
, dest2
, pDstItem
, true );
7909 if( msg
!= EQUIP_ERR_OK
)
7911 SendEquipError( EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG
, pSrcItem
, pDstItem
);
7915 else if( IsBankPos( src
) )
7917 msg
= CanBankItem( srcbag
, srcslot
, dest2
, pDstItem
, true );
7918 if( msg
!= EQUIP_ERR_OK
)
7920 SendEquipError( EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG
, pSrcItem
, pDstItem
);
7924 else if( IsEquipmentPos( src
) )
7926 msg
= CanEquipItem( srcslot
, dest2
, pDstItem
, true);
7927 if( msg
== EQUIP_ERR_OK
)
7928 msg
= CanUnequipItem( dest2
, true);
7930 if( msg
!= EQUIP_ERR_OK
)
7932 SendEquipError( EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT
, pSrcItem
, pDstItem
);
7936 RemoveItem(dstbag
, dstslot
, false);
7937 RemoveItem(srcbag
, srcslot
, false);
7938 if( IsInventoryPos( dst
) )
7939 StoreItem(dest
, pSrcItem
, true);
7940 else if( IsBankPos( dst
) )
7941 BankItem(dest
, pSrcItem
, true);
7942 else if( IsEquipmentPos( dst
) )
7943 EquipItem(dest
, pSrcItem
, true);
7944 if( IsInventoryPos( src
) )
7945 StoreItem(dest2
, pDstItem
, true);
7946 else if( IsBankPos( src
) )
7947 BankItem(dest2
, pDstItem
, true);
7948 else if( IsEquipmentPos( src
) )
7949 EquipItem(dest2
, pDstItem
, true);
7953 SendEquipError( msg
, pSrcItem
, pDstItem
);
7959 void Player::AddItemToBuyBackSlot( uint32 slot
, Item
*pItem
)
7963 if( slot
>= BUYBACK_SLOT_START
&& slot
< BUYBACK_SLOT_END
)
7965 RemoveItemFromBuyBackSlot( slot
);
7966 sLog
.outDebug( "STORAGE: AddItemToBuyBackSlot item = %u, slot = %u", pItem
->GetEntry(), slot
);
7967 uint32 eslot
= slot
- BUYBACK_SLOT_START
;
7969 m_buybackitems
[eslot
] = pItem
;
7970 time_t base
= time(NULL
);
7971 time_t etime
= base
+ (30 * 3600);
7973 SetUInt64Value( PLAYER_FIELD_VENDORBUYBACK_SLOT_1
+ eslot
* 2, pItem
->GetGUID() );
7974 ItemPrototype
const *pProto
= pItem
->GetProto();
7976 SetUInt32Value( PLAYER_FIELD_BUYBACK_PRICE_1
+ eslot
, pProto
->SellPrice
* pItem
->GetCount() );
7978 SetUInt32Value( PLAYER_FIELD_BUYBACK_PRICE_1
+ eslot
, 0 );
7979 SetUInt32Value( PLAYER_FIELD_BUYBACK_TIMESTAMP_1
+ eslot
, (uint32
)etime
);
7984 Item
* Player::GetItemFromBuyBackSlot( uint32 slot
)
7986 sLog
.outDebug( "STORAGE: GetItemFromBuyBackSlot slot = %u", slot
);
7987 if( slot
>= BUYBACK_SLOT_START
&& slot
< BUYBACK_SLOT_END
)
7988 return m_buybackitems
[slot
- BUYBACK_SLOT_START
];
7992 void Player::RemoveItemFromBuyBackSlot( uint32 slot
)
7994 sLog
.outDebug( "STORAGE: RemoveItemFromBuyBackSlot slot = %u", slot
);
7995 if( slot
>= BUYBACK_SLOT_START
&& slot
< BUYBACK_SLOT_END
)
7997 uint32 eslot
= slot
- BUYBACK_SLOT_START
;
7998 Item
*pItem
= m_buybackitems
[eslot
];
8000 pItem
->RemoveFromWorld();
8002 m_buybackitems
[eslot
] = NULL
;
8003 SetUInt64Value( PLAYER_FIELD_VENDORBUYBACK_SLOT_1
+ eslot
* 2, 0 );
8004 SetUInt32Value( PLAYER_FIELD_BUYBACK_PRICE_1
+ eslot
, 0 );
8005 SetUInt32Value( PLAYER_FIELD_BUYBACK_TIMESTAMP_1
+ eslot
, 0 );
8009 void Player::SendEquipError( uint8 msg
, Item
* pItem
, Item
*pItem2
)
8011 sLog
.outDetail( "WORLD: Sent SMSG_INVENTORY_CHANGE_FAILURE" );
8013 data
.Initialize( SMSG_INVENTORY_CHANGE_FAILURE
);
8015 if( msg
== EQUIP_ERR_YOU_MUST_REACH_LEVEL_N
)
8016 data
<< (pItem
&& pItem
->GetProto() ? pItem
->GetProto()->RequiredLevel
: uint32(0));
8017 data
<< (pItem
? pItem
->GetGUID() : uint64(0));
8018 data
<< (pItem2
? pItem2
->GetGUID() : uint64(0));
8020 GetSession()->SendPacket(&data
);
8023 void Player::SendBuyError( uint8 msg
, Creature
* pCreature
, uint32 item
, uint32 param
)
8025 sLog
.outDetail( "WORLD: Sent SMSG_BUY_FAILED" );
8027 data
.Initialize( SMSG_BUY_FAILED
);
8028 data
<< (pCreature
? pCreature
->GetGUID() : uint64(0));
8033 GetSession()->SendPacket(&data
);
8036 void Player::SendSellError( uint8 msg
, Creature
* pCreature
, uint64 guid
, uint32 param
)
8038 sLog
.outDetail( "WORLD: Sent SMSG_SELL_ITEM" );
8040 data
.Initialize( SMSG_SELL_ITEM
);
8041 data
<< (pCreature
? pCreature
->GetGUID() : uint64(0));
8046 GetSession()->SendPacket(&data
);
8049 void Player::ClearTrade()
8052 acceptTrade
= false;
8053 for(int i
=0; i
<7; i
++)
8054 tradeItems
[i
] = NULL_SLOT
;
8057 void Player::TradeCancel(bool sendback
)
8061 // prevent loop cancel message (already processed)
8063 pTrader
->pTrader
= NULL
;
8065 WorldSession
* ws
= pTrader
->GetSession();
8067 ws
->SendCancelTrade();
8072 void Player::UpdateEnchantTime(uint32 time
)
8074 for(std::list
<struct EnchantDuration
*>::iterator itr
= m_enchantDuration
.begin(),next
;itr
!= m_enchantDuration
.end();itr
=next
)
8082 if(!(*itr
)->item
->GetUInt32Value(ITEM_FIELD_ENCHANTMENT
+(*itr
)->slot
*3))
8085 m_enchantDuration
.erase(itr
);
8088 if((*itr
)->leftduration
<= time
)
8090 AddItemEnchant((*itr
)->item
,(*itr
)->item
->GetUInt32Value(ITEM_FIELD_ENCHANTMENT
+(*itr
)->slot
*3),false);
8091 for(int y
=0;y
<3;y
++)
8092 (*itr
)->item
->SetUInt32Value(ITEM_FIELD_ENCHANTMENT
+(*itr
)->slot
*3+y
,0);
8094 m_enchantDuration
.erase(itr
);
8097 else if((*itr
)->leftduration
> time
)
8099 (*itr
)->leftduration
-= time
;
8106 // duration == 0 will remove item enchant
8107 void Player::AddEnchantDuration(Item
*item
,uint32 slot
,uint32 duration
)
8111 for(std::list
<struct EnchantDuration
*>::iterator itr
= m_enchantDuration
.begin(),next
;itr
!= m_enchantDuration
.end();itr
=next
)
8119 if((*itr
)->item
== item
&& (*itr
)->slot
== slot
)
8122 m_enchantDuration
.erase(itr
);
8128 if(item
&& duration
> 0 )
8130 GetSession()->SendItemEnchantTimeUpdate(item
->GetGUID(),slot
,uint32(duration
/1000));
8131 EnchantDuration
*ed
= new EnchantDuration();
8133 ed
->leftduration
= duration
;
8135 m_enchantDuration
.push_back(ed
);
8139 void Player::ReducePoisonCharges(uint32 enchantId
)
8143 uint32 pEnchantId
= 0;
8148 for(int i
= EQUIPMENT_SLOT_MAINHAND
; i
< EQUIPMENT_SLOT_RANGED
; i
++)
8150 pos
= ((INVENTORY_SLOT_BAG_0
<< 8) | i
);
8152 pItem
= GetItemByPos( pos
);
8155 for(int x
=0;x
<7;x
++)
8157 charges
= pItem
->GetUInt32Value(ITEM_FIELD_ENCHANTMENT
+x
*3+2);
8162 AddItemEnchant(pItem
,enchantId
,false);
8163 for(int y
=0;y
<3;y
++)
8164 pItem
->SetUInt32Value(ITEM_FIELD_ENCHANTMENT
+x
*3+y
,0);
8169 pItem
->SetUInt32Value(ITEM_FIELD_ENCHANTMENT
+x
*3+2,charges
-1);
8176 void Player::SaveEnchant()
8178 uint32 duration
= 0;
8180 for(std::list
<struct EnchantDuration
*>::iterator itr
= m_enchantDuration
.begin();itr
!= m_enchantDuration
.end();itr
++)
8186 if((*itr
)->leftduration
> 0)
8188 (*itr
)->item
->SetUInt32Value(ITEM_FIELD_ENCHANTMENT
+(*itr
)->slot
*3+1,(*itr
)->leftduration
);
8195 void Player::LoadEnchant()
8197 uint32 duration
= 0;
8201 for(int i
= EQUIPMENT_SLOT_START
; i
< INVENTORY_SLOT_ITEM_END
; i
++)
8203 pos
= ((INVENTORY_SLOT_BAG_0
<< 8) | i
);
8205 pItem
= GetItemByPos( pos
);
8208 if(pItem
->GetProto()->Class
!= ITEM_CLASS_WEAPON
&& pItem
->GetProto()->Class
!= ITEM_CLASS_ARMOR
)
8210 for(int x
=0;x
<7;x
++)
8212 duration
= pItem
->GetUInt32Value(ITEM_FIELD_ENCHANTMENT
+x
*3+1);
8215 else if( duration
> 0 )
8216 AddEnchantDuration(pItem
,x
,duration
);
8220 ItemPrototype
const *pBagProto
;
8221 for(int i
= INVENTORY_SLOT_BAG_START
; i
< INVENTORY_SLOT_BAG_END
; i
++)
8223 pos
= ((INVENTORY_SLOT_BAG_0
<< 8) | i
);
8224 pBag
= (Bag
*)GetItemByPos( pos
);
8227 pBagProto
= pBag
->GetProto();
8230 for(uint32 j
= 0; j
< pBagProto
->ContainerSlots
; j
++)
8232 pos
= ((i
<< 8) | j
);
8233 pItem
= GetItemByPos( pos
);
8236 if(pItem
->GetProto()->Class
!= ITEM_CLASS_WEAPON
&& pItem
->GetProto()->Class
!= ITEM_CLASS_ARMOR
)
8238 for(int x
=0;x
<7;x
++)
8240 duration
= pItem
->GetUInt32Value(ITEM_FIELD_ENCHANTMENT
+x
*3+1);
8243 else if( duration
> 0 )
8244 AddEnchantDuration(pItem
,x
,duration
);
8250 for(int i
= BANK_SLOT_BAG_START
; i
< BANK_SLOT_BAG_END
; i
++)
8252 pos
= ((INVENTORY_SLOT_BAG_0
<< 8) | i
);
8253 pBag
= (Bag
*)GetItemByPos( pos
);
8256 pBagProto
= pBag
->GetProto();
8259 for(uint32 j
= 0; j
< pBagProto
->ContainerSlots
; j
++)
8261 pos
= ((i
<< 8) | j
);
8262 pItem
= GetItemByPos( pos
);
8265 if(pItem
->GetProto()->Class
!= ITEM_CLASS_WEAPON
&& pItem
->GetProto()->Class
!= ITEM_CLASS_ARMOR
)
8267 for(int x
=0;x
<7;x
++)
8269 duration
= pItem
->GetUInt32Value(ITEM_FIELD_ENCHANTMENT
+x
*3+1);
8272 else if( duration
> 0 )
8273 AddEnchantDuration(pItem
,x
,duration
);
8282 /*********************************************************/
8283 /*** QUEST SYSTEM ***/
8284 /*********************************************************/
8286 void Player::PrepareQuestMenu( uint64 guid
)
8289 Creature
*pCreature
= ObjectAccessor::Instance().GetCreature(*this, guid
);
8291 pObject
= (Object
*)pCreature
;
8294 GameObject
*pGameObject
= ObjectAccessor::Instance().GetGameObject(*this, guid
);
8296 pObject
= (Object
*)pGameObject
;
8301 QuestMenu
*qm
= PlayerTalkClass
->GetQuestMenu();
8304 for( std::list
<Quest
*>::iterator i
= pObject
->mInvolvedQuests
.begin( ); i
!= pObject
->mInvolvedQuests
.end( ); i
++ )
8310 uint32 quest_id
= pQuest
->GetQuestId();
8311 uint32 status
= GetQuestStatus( quest_id
);
8313 if ( status
== QUEST_STATUS_COMPLETE
&& !GetQuestRewardStatus( quest_id
) )
8314 qm
->AddMenuItem( quest_id
, DIALOG_STATUS_REWARD
, false );
8315 else if ( status
== QUEST_STATUS_INCOMPLETE
)
8316 qm
->AddMenuItem( quest_id
, DIALOG_STATUS_INCOMPLETE
, false );
8319 for( std::list
<Quest
*>::iterator i
= pObject
->mQuests
.begin( ); i
!= pObject
->mQuests
.end( ); i
++ )
8325 uint32 quest_id
= pQuest
->GetQuestId();
8326 uint32 status
= GetQuestStatus( quest_id
);
8328 if ( status
== QUEST_STATUS_NONE
&& CanTakeQuest( pQuest
, false ) )
8329 qm
->AddMenuItem( quest_id
, DIALOG_STATUS_AVAILABLE
, true );
8333 void Player::SendPreparedQuest( uint64 guid
)
8335 QuestMenu
* pQuestMenu
= PlayerTalkClass
->GetQuestMenu();
8336 if( !pQuestMenu
|| pQuestMenu
->MenuItemCount() < 1 )
8339 uint32 status
= pQuestMenu
->GetItem(0).m_qIcon
;
8340 if ( pQuestMenu
->MenuItemCount() == 1 )
8342 uint32 quest_id
= pQuestMenu
->GetItem(0).m_qId
;
8343 Quest
*pQuest
= objmgr
.NewQuest( quest_id
);
8346 if( status
== DIALOG_STATUS_REWARD
&& !GetQuestRewardStatus( quest_id
) )
8347 PlayerTalkClass
->SendRequestedItems( pQuest
, guid
, CanRewardQuest(pQuest
,false), true );
8348 else if( status
== DIALOG_STATUS_INCOMPLETE
)
8349 PlayerTalkClass
->SendRequestedItems( pQuest
, guid
, false, true );
8351 PlayerTalkClass
->SendQuestDetails( pQuest
, guid
, true );
8360 std::string title
= "";
8361 Creature
*pCreature
= ObjectAccessor::Instance().GetCreature(*this, guid
);
8364 uint32 textid
= pCreature
->GetNpcTextId();
8365 GossipText
* gossiptext
= objmgr
.GetGossipText(textid
);
8368 qe
._Delay
= TEXTEMOTE_MESSAGE
; //zyg: player emote
8369 qe
._Emote
= TEXTEMOTE_HELLO
; //zyg: NPC emote
8370 title
= "Do Quest ?";
8374 qe
= gossiptext
->Options
[0].Emotes
[0];
8375 title
= gossiptext
->Options
[0].Text_0
;
8376 if( &title
== NULL
)
8380 PlayerTalkClass
->SendQuestMenu( qe
, title
, guid
);
8384 Quest
*Player::GetActiveQuest( uint32 quest_id
) const
8386 StatusMap::const_iterator itr
= mQuestStatus
.find(quest_id
);
8388 return itr
!= mQuestStatus
.end() && itr
->second
.m_status
!= QUEST_STATUS_NONE
? itr
->second
.m_quest
: NULL
;
8391 Quest
* Player::GetNextQuest( uint64 guid
, Quest
*pQuest
)
8396 Creature
*pCreature
= ObjectAccessor::Instance().GetCreature(*this, guid
);
8398 pObject
= (Object
*)pCreature
;
8401 GameObject
*pGameObject
= ObjectAccessor::Instance().GetGameObject(*this, guid
);
8403 pObject
= (Object
*)pGameObject
;
8408 uint32 quest
= pQuest
->GetQuestInfo()->NextQuestId
;
8409 for( std::list
<Quest
*>::iterator i
= pObject
->mQuests
.begin( ); i
!= pObject
->mQuests
.end( ); i
++ )
8411 Quest
*pQuest2
= *i
;
8412 if( pQuest2
->GetQuestId() == quest
)
8414 if ( CanTakeQuest( pQuest2
, false ) )
8424 bool Player::CanSeeStartQuest( uint32 quest_id
)
8428 if( SatisfyQuestRace( quest_id
, false ) && SatisfyQuestClass( quest_id
, false ) && SatisfyQuestExclusiveGroup( quest_id
, false )
8429 && SatisfyQuestSkill( quest_id
, false ) && SatisfyQuestReputation( quest_id
, false )
8430 && SatisfyQuestPreviousQuest( quest_id
, false ) )
8431 return ( getLevel() + 7 >= objmgr
.GetQuestInfo(quest_id
)->MinLevel
);
8436 bool Player::CanTakeQuest( Quest
*pQuest
, bool msg
)
8440 uint32 quest_id
= pQuest
->GetQuestId();
8441 return ( SatisfyQuestStatus( quest_id
, msg
) && SatisfyQuestExclusiveGroup( quest_id
, msg
)
8442 && SatisfyQuestRace( quest_id
, msg
) && SatisfyQuestLevel( quest_id
, msg
) && SatisfyQuestClass( quest_id
, msg
)
8443 && SatisfyQuestSkill( quest_id
, msg
) && SatisfyQuestReputation( quest_id
, msg
)
8444 && SatisfyQuestPreviousQuest( quest_id
, msg
) && SatisfyQuestTimed( quest_id
, msg
) );
8449 bool Player::CanAddQuest( Quest
*pQuest
, bool msg
)
8453 if(!GetQuestSlot( 0 ))
8456 if( !SatisfyQuestLog( msg
) )
8459 uint32 srcitem
= pQuest
->GetQuestInfo()->SrcItemId
;
8462 uint32 count
= pQuest
->GetQuestInfo()->SrcItemCount
;
8466 uint8 msg
= CanStoreNewItem( 0, NULL_SLOT
, dest
, srcitem
, count
, false );
8467 if( msg
!= EQUIP_ERR_OK
)
8469 SendEquipError( msg
, NULL
, NULL
);
8478 bool Player::CanCompleteQuest( uint32 quest_id
)
8482 if( mQuestStatus
[quest_id
].m_status
== QUEST_STATUS_COMPLETE
)
8485 if ( mQuestStatus
[quest_id
].m_status
== QUEST_STATUS_INCOMPLETE
)
8487 QuestInfo
const* qInfo
= objmgr
.GetQuestInfo(quest_id
);
8489 if ( qInfo
->HasSpecialFlag( QUEST_SPECIAL_FLAGS_DELIVER
) )
8491 for(int i
= 0; i
< QUEST_OBJECTIVES_COUNT
; i
++)
8493 if( qInfo
->ReqItemCount
[i
]!= 0 && mQuestStatus
[quest_id
].m_itemcount
[i
] < qInfo
->ReqItemCount
[i
] )
8498 if ( qInfo
->HasSpecialFlag( QUEST_SPECIAL_FLAGS_KILL_OR_CAST
) )
8500 for(int i
= 0; i
< QUEST_OBJECTIVES_COUNT
; i
++)
8502 // skip GO activate objectives
8503 if( qInfo
->ReqCreatureOrGOId
[i
] <= 0 )
8506 if( qInfo
->ReqCreatureOrGOCount
[i
] != 0 && mQuestStatus
[quest_id
].m_creatureOrGOcount
[i
] < qInfo
->ReqCreatureOrGOCount
[i
] )
8511 if ( qInfo
->HasSpecialFlag( QUEST_SPECIAL_FLAGS_EXPLORATION
) && !mQuestStatus
[quest_id
].m_explored
)
8514 if ( qInfo
->HasSpecialFlag( QUEST_SPECIAL_FLAGS_TIMED
) && mQuestStatus
[quest_id
].m_timer
== 0 )
8517 if ( qInfo
->RewOrReqMoney
< 0 )
8519 if ( int32(GetMoney()) < -qInfo
->RewOrReqMoney
)
8528 bool Player::CanRewardQuest( Quest
*pQuest
, bool msg
)
8532 // not completed quest (only cheating case, then ignore without message)
8533 if(GetQuestStatus(pQuest
->GetQuestId()) != QUEST_STATUS_COMPLETE
)
8536 // rewarded and not repeatable quest (only cheating case, then ignore without message)
8537 if(GetQuestRewardStatus(pQuest
->GetQuestId()) && !pQuest
->GetQuestInfo()->HasSpecialFlag(QUEST_SPECIAL_FLAGS_REPEATABLE
))
8540 // prevent recive reward with quest items in bank
8541 if ( pQuest
->GetQuestInfo()->HasSpecialFlag( QUEST_SPECIAL_FLAGS_DELIVER
) )
8543 for(int i
= 0; i
< QUEST_OBJECTIVES_COUNT
; i
++)
8545 if( pQuest
->GetQuestInfo()->ReqItemCount
[i
]!= 0 &&
8546 GetItemCount(pQuest
->GetQuestInfo()->ReqItemId
[i
]) < pQuest
->GetQuestInfo()->ReqItemCount
[i
] )
8549 SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND
, NULL
, NULL
);
8560 bool Player::CanRewardQuest( Quest
*pQuest
, uint32 reward
, bool msg
)
8564 // prevent recive reward with quest items in bank or for not completed quest
8565 if(!CanRewardQuest(pQuest
,msg
))
8571 if ( pQuest
->m_rewchoiceitemscount
> 0 )
8573 if( pQuest
->GetQuestInfo()->RewChoiceItemId
[reward
] )
8575 msg
= CanStoreNewItem( 0, NULL_SLOT
, dest
, pQuest
->GetQuestInfo()->RewChoiceItemId
[reward
], pQuest
->GetQuestInfo()->RewChoiceItemCount
[reward
], false );
8576 if( msg
!= EQUIP_ERR_OK
)
8578 SendEquipError( msg
, NULL
, NULL
);
8584 if ( pQuest
->m_rewitemscount
> 0 )
8586 for (int i
= 0; i
< QUEST_REWARDS_COUNT
; i
++)
8588 if( pQuest
->GetQuestInfo()->RewItemId
[i
] )
8590 msg
= CanStoreNewItem( 0, NULL_SLOT
, dest
, pQuest
->GetQuestInfo()->RewItemId
[i
], pQuest
->GetQuestInfo()->RewItemCount
[i
], false );
8591 if( msg
!= EQUIP_ERR_OK
)
8593 SendEquipError( msg
, NULL
, NULL
);
8604 void Player::AddQuest( Quest
*pQuest
)
8608 uint16 log_slot
= GetQuestSlot( 0 );
8611 uint32 quest_id
= pQuest
->GetQuestId();
8612 QuestInfo
const* qInfo
= pQuest
->GetQuestInfo();
8614 mQuestStatus
[quest_id
].m_quest
= pQuest
;
8615 mQuestStatus
[quest_id
].m_status
= QUEST_STATUS_INCOMPLETE
;
8616 mQuestStatus
[quest_id
].m_rewarded
= false;
8617 mQuestStatus
[quest_id
].m_explored
= false;
8619 if ( qInfo
->HasSpecialFlag( QUEST_SPECIAL_FLAGS_DELIVER
) )
8621 for(int i
= 0; i
< QUEST_OBJECTIVES_COUNT
; i
++)
8622 mQuestStatus
[quest_id
].m_itemcount
[i
] = 0;
8624 if ( qInfo
->HasSpecialFlag( QUEST_SPECIAL_FLAGS_KILL_OR_CAST
) )
8626 for(int i
= 0; i
< QUEST_OBJECTIVES_COUNT
; i
++)
8627 mQuestStatus
[quest_id
].m_creatureOrGOcount
[i
] = 0;
8630 GiveQuestSourceItem( quest_id
);
8631 AdjustQuestReqItemCount( quest_id
);
8633 SetUInt32Value(log_slot
+ 0, quest_id
);
8634 SetUInt32Value(log_slot
+ 1, 0);
8636 if( qInfo
->HasSpecialFlag( QUEST_SPECIAL_FLAGS_TIMED
) )
8638 uint32 limittime
= qInfo
->LimitTime
;
8639 AddTimedQuest( quest_id
);
8640 mQuestStatus
[quest_id
].m_timer
= limittime
* 1000;
8641 uint32 qtime
= static_cast<uint32
>(time(NULL
)) + limittime
;
8642 SetUInt32Value( log_slot
+ 2, qtime
);
8646 mQuestStatus
[quest_id
].m_timer
= 0;
8647 SetUInt32Value( log_slot
+ 2, 0 );
8652 void Player::CompleteQuest( uint32 quest_id
)
8656 SetQuestStatus( quest_id
, QUEST_STATUS_COMPLETE
);
8658 uint16 log_slot
= GetQuestSlot( quest_id
);
8661 uint32 state
= GetUInt32Value( log_slot
+ 1 );
8663 SetUInt32Value( log_slot
+ 1, state
);
8666 SendQuestComplete( quest_id
);
8670 void Player::IncompleteQuest( uint32 quest_id
)
8674 SetQuestStatus( quest_id
, QUEST_STATUS_INCOMPLETE
);
8676 uint16 log_slot
= GetQuestSlot( quest_id
);
8679 uint32 state
= GetUInt32Value( log_slot
+ 1 );
8680 state
&= ~(1 << 24);
8681 SetUInt32Value( log_slot
+ 1, state
);
8686 void Player::RewardQuest( Quest
*pQuest
, uint32 reward
)
8690 uint32 quest_id
= pQuest
->GetQuestId();
8691 QuestInfo
const* qInfo
= pQuest
->GetQuestInfo();
8694 for (int i
= 0; i
< QUEST_OBJECTIVES_COUNT
; i
++ )
8696 if ( qInfo
->ReqItemId
[i
] )
8697 RemoveItemCount( qInfo
->ReqItemId
[i
], qInfo
->ReqItemCount
[i
], true);
8700 //if( qInfo->HasSpecialFlag( QUEST_SPECIAL_FLAGS_TIMED ) )
8701 // SetTimedQuest( 0 );
8702 if (find(m_timedquests
.begin(), m_timedquests
.end(), qInfo
->QuestId
) != m_timedquests
.end())
8703 m_timedquests
.remove(qInfo
->QuestId
);
8705 if ( pQuest
->m_rewchoiceitemscount
> 0 )
8707 if( qInfo
->RewChoiceItemId
[reward
] )
8709 if( CanStoreNewItem( 0, NULL_SLOT
, dest
, qInfo
->RewChoiceItemId
[reward
], qInfo
->RewChoiceItemCount
[reward
], false ) == EQUIP_ERR_OK
)
8710 StoreNewItem( dest
, qInfo
->RewChoiceItemId
[reward
], qInfo
->RewChoiceItemCount
[reward
], true);
8714 if ( pQuest
->m_rewitemscount
> 0 )
8716 for (int i
=0; i
< QUEST_REWARDS_COUNT
; i
++)
8718 if( qInfo
->RewItemId
[i
] )
8720 if( CanStoreNewItem( 0, NULL_SLOT
, dest
, qInfo
->RewItemId
[i
], qInfo
->RewItemCount
[i
], false ) == EQUIP_ERR_OK
)
8721 StoreNewItem( dest
, qInfo
->RewItemId
[i
], qInfo
->RewItemCount
[i
], true);
8726 if( qInfo
->RewSpell
> 0 )
8727 CastSpell( this, qInfo
->RewSpell
, true);
8729 uint16 log_slot
= GetQuestSlot( quest_id
);
8732 SetUInt32Value(log_slot
+ 0, 0);
8733 SetUInt32Value(log_slot
+ 1, 0);
8734 SetUInt32Value(log_slot
+ 2, 0);
8737 // Not give XP in case already completed once repeatable quest
8738 uint32 XP
= mQuestStatus
[quest_id
].m_completed_once
&& qInfo
->HasSpecialFlag( QUEST_SPECIAL_FLAGS_REPEATABLE
)
8739 ? 0 : uint32(pQuest
->XPValue( this )*sWorld
.getRate(RATE_XP_QUEST
));
8741 if ( getLevel() < sWorld
.getConfig(CONFIG_MAX_PLAYER_LEVEL
) )
8742 GiveXP( XP
, NULL
);
8744 ModifyMoney( MaNGOS::XP::xp_to_money(XP
) );
8746 ModifyMoney( qInfo
->RewOrReqMoney
);
8748 if ( !qInfo
->HasSpecialFlag( QUEST_SPECIAL_FLAGS_REPEATABLE
) )
8749 mQuestStatus
[quest_id
].m_rewarded
= true;
8752 SetQuestStatus(quest_id
, QUEST_STATUS_NONE
);
8755 SendQuestReward( pQuest
, XP
);
8757 mQuestStatus
[quest_id
].m_completed_once
= true; // in repeated quest case prevent recive XP at second complete
8761 void Player::FailQuest( uint32 quest_id
)
8765 IncompleteQuest( quest_id
);
8767 uint16 log_slot
= GetQuestSlot( quest_id
);
8770 SetUInt32Value( log_slot
+ 2, 1 );
8772 uint32 state
= GetUInt32Value( log_slot
+ 1 );
8774 SetUInt32Value( log_slot
+ 1, state
);
8776 SendQuestFailed( quest_id
);
8780 void Player::FailTimedQuest( uint32 quest_id
)
8784 mQuestStatus
[quest_id
].m_timer
= 0;
8786 IncompleteQuest( quest_id
);
8788 uint16 log_slot
= GetQuestSlot( quest_id
);
8791 SetUInt32Value( log_slot
+ 2, 1 );
8793 uint32 state
= GetUInt32Value( log_slot
+ 1 );
8795 SetUInt32Value( log_slot
+ 1, state
);
8797 SendQuestTimerFailed( quest_id
);
8801 bool Player::SatisfyQuestClass( uint32 quest_id
, bool msg
)
8803 QuestInfo
const* qInfo
= objmgr
.GetQuestInfo(quest_id
);
8806 uint32 reqclasses
= qInfo
->RequiredClass
;
8807 if ( reqclasses
== QUEST_CLASS_NONE
)
8809 if( (reqclasses
& getClassMask()) == 0 )
8812 SendCanTakeQuestResponse( INVALIDREASON_DONT_HAVE_REQ
);
8821 bool Player::SatisfyQuestLevel( uint32 quest_id
, bool msg
)
8823 QuestInfo
const* qInfo
= objmgr
.GetQuestInfo(quest_id
);
8826 if( getLevel() < qInfo
->MinLevel
)
8829 SendCanTakeQuestResponse( INVALIDREASON_DONT_HAVE_REQ
);
8837 bool Player::SatisfyQuestLog( bool msg
)
8839 uint16 log_slot
= GetQuestSlot( 0 );
8847 data
.Initialize( SMSG_QUESTLOG_FULL
);
8848 GetSession()->SendPacket( &data
);
8849 sLog
.outDebug( "WORLD: Sent QUEST_LOG_FULL_MESSAGE" );
8855 bool Player::SatisfyQuestPreviousQuest( uint32 quest_id
, bool msg
)
8859 QuestRelations::iterator iter
= sPrevQuests
.lower_bound(quest_id
);
8860 QuestRelations::iterator end
= sPrevQuests
.upper_bound(quest_id
);
8862 // First quest in series
8866 // Have one form prev, quests in rewarded state
8867 for(; iter
!= end
; ++iter
)
8869 uint32 prevId
= iter
->second
;
8871 StatusMap::iterator i_prevstatus
= mQuestStatus
.find( prevId
);
8873 if( i_prevstatus
!= mQuestStatus
.end() && i_prevstatus
->second
.m_rewarded
)
8877 // Have only prev. quests in non-rewarded state
8879 SendCanTakeQuestResponse( INVALIDREASON_DONT_HAVE_REQ
);
8884 bool Player::SatisfyQuestRace( uint32 quest_id
, bool msg
)
8886 QuestInfo
const* qInfo
= objmgr
.GetQuestInfo(quest_id
);
8889 uint32 reqraces
= qInfo
->RequiredRaces
;
8890 if ( reqraces
== QUEST_RACE_NONE
)
8892 if( (reqraces
& getRaceMask()) == 0 )
8895 SendCanTakeQuestResponse( INVALIDREASON_DONT_HAVE_RACE
);
8903 bool Player::SatisfyQuestReputation( uint32 quest_id
, bool msg
)
8905 QuestInfo
const* qInfo
= objmgr
.GetQuestInfo(quest_id
);
8908 uint32 faction_id
= qInfo
->RequiredRepFaction
;
8912 return GetReputation(faction_id
) >= qInfo
->RequiredRepValue
;
8917 bool Player::SatisfyQuestSkill( uint32 quest_id
, bool msg
)
8919 QuestInfo
const* qInfo
= objmgr
.GetQuestInfo(quest_id
);
8922 uint32 reqskill
= qInfo
->RequiredSkill
;
8923 if( reqskill
== QUEST_TRSKILL_NONE
)
8925 if( GetSkillValue( reqskill
) < qInfo
->RequiredSkillValue
)
8928 SendCanTakeQuestResponse( INVALIDREASON_DONT_HAVE_REQ
);
8936 bool Player::SatisfyQuestStatus( uint32 quest_id
, bool msg
)
8940 StatusMap::iterator itr
= mQuestStatus
.find( quest_id
);
8941 if ( itr
!= mQuestStatus
.end() && itr
->second
.m_status
!= QUEST_STATUS_NONE
)
8944 SendCanTakeQuestResponse( INVALIDREASON_HAVE_QUEST
);
8952 bool Player::SatisfyQuestTimed( uint32 quest_id
, bool msg
)
8954 QuestInfo
const* qInfo
= objmgr
.GetQuestInfo(quest_id
);
8957 if ( (find(m_timedquests
.begin(), m_timedquests
.end(), quest_id
) != m_timedquests
.end()) && qInfo
->HasSpecialFlag(QUEST_SPECIAL_FLAGS_TIMED
) )
8960 SendCanTakeQuestResponse( INVALIDREASON_HAVE_TIMED_QUEST
);
8968 bool Player::SatisfyQuestExclusiveGroup( uint32 quest_id
, bool msg
)
8970 QuestInfo
const* qInfo
= objmgr
.GetQuestInfo(quest_id
);
8973 if(!qInfo
->ExclusiveGroup
)
8976 QuestRelations::iterator iter
= sExclusiveQuestGroups
.lower_bound(qInfo
->ExclusiveGroup
);
8977 QuestRelations::iterator end
= sExclusiveQuestGroups
.upper_bound(qInfo
->ExclusiveGroup
);
8979 assert(iter
!=end
); // always must be found if qInfo->ExclusiveGroup != 0
8981 for(; iter
!= end
; ++iter
)
8983 uint32 exclude_Id
= iter
->second
;
8985 // skip checked quest id, intrested only state of another quests in group
8986 if(exclude_Id
== quest_id
)
8989 StatusMap::iterator i_exstatus
= mQuestStatus
.find( exclude_Id
);
8991 // altearnative quest already start or complete
8992 if( i_exstatus
!= mQuestStatus
.end()
8993 && (i_exstatus
->second
.m_status
== QUEST_STATUS_COMPLETE
|| i_exstatus
->second
.m_status
== QUEST_STATUS_INCOMPLETE
) )
9001 bool Player::GiveQuestSourceItem( uint32 quest_id
)
9003 QuestInfo
const* qInfo
= objmgr
.GetQuestInfo(quest_id
);
9007 uint32 srcitem
= qInfo
->SrcItemId
;
9011 uint32 count
= qInfo
->SrcItemCount
;
9014 uint8 msg
= CanStoreNewItem( 0, NULL_SLOT
, dest
, srcitem
, count
, false );
9015 if( msg
== EQUIP_ERR_OK
)
9017 StoreNewItem(dest
, srcitem
, count
, true);
9021 SendEquipError( msg
, NULL
, NULL
);
9028 void Player::TakeQuestSourceItem( uint32 quest_id
)
9030 QuestInfo
const* qInfo
= objmgr
.GetQuestInfo(quest_id
);
9033 uint32 srcitem
= qInfo
->SrcItemId
;
9036 uint32 count
= qInfo
->SrcItemCount
;
9039 DestroyItemCount(srcitem
, count
, true);
9044 bool Player::GetQuestRewardStatus( uint32 quest_id
)
9048 StatusMap::iterator itr
= mQuestStatus
.find( quest_id
);
9049 if ( itr
!= mQuestStatus
.end() && itr
->second
.m_status
!= QUEST_STATUS_NONE
)
9050 return mQuestStatus
[quest_id
].m_rewarded
;
9057 uint32
Player::GetQuestStatus( uint32 quest_id
)
9061 if ( mQuestStatus
.find( quest_id
) != mQuestStatus
.end() )
9062 return mQuestStatus
[quest_id
].m_status
;
9064 return QUEST_STATUS_NONE
;
9067 void Player::SetQuestStatus( uint32 quest_id
, QuestStatus status
)
9069 QuestInfo
const* qInfo
= objmgr
.GetQuestInfo(quest_id
);
9072 if ((status
== QUEST_STATUS_NONE
) || (status
== QUEST_STATUS_INCOMPLETE
))
9074 if( qInfo
->HasSpecialFlag( QUEST_SPECIAL_FLAGS_TIMED
) )
9075 if (find(m_timedquests
.begin(), m_timedquests
.end(), quest_id
) != m_timedquests
.end())
9076 m_timedquests
.remove(qInfo
->QuestId
);
9079 mQuestStatus
[quest_id
].m_status
= status
;
9083 void Player::AdjustQuestReqItemCount( uint32 quest_id
)
9085 QuestInfo
const* qInfo
= objmgr
.GetQuestInfo(quest_id
);
9088 if ( qInfo
->HasSpecialFlag( QUEST_SPECIAL_FLAGS_DELIVER
) )
9090 for(int i
= 0; i
< QUEST_OBJECTIVES_COUNT
; i
++)
9092 uint32 reqitemcount
= qInfo
->ReqItemCount
[i
];
9093 if( reqitemcount
!= 0 )
9095 uint32 curitemcount
= GetItemCount(qInfo
->ReqItemId
[i
]) + GetBankItemCount(qInfo
->ReqItemId
[i
]);
9096 mQuestStatus
[quest_id
].m_itemcount
[i
] = min(curitemcount
, reqitemcount
);
9103 uint16
Player::GetQuestSlot( uint32 quest_id
)
9105 for ( uint16 i
= 0; i
< MAX_QUEST_LOG_SIZE
; i
++ )
9107 if ( GetUInt32Value(PLAYER_QUEST_LOG_1_1
+ 3*i
) == quest_id
)
9108 return PLAYER_QUEST_LOG_1_1
+ 3*i
;
9113 void Player::AreaExplored( uint32 questId
)
9117 uint16 log_slot
= GetQuestSlot( questId
);
9120 mQuestStatus
[questId
].m_explored
= true;
9122 if( CanCompleteQuest( questId
) )
9123 CompleteQuest( questId
);
9127 void Player::ItemAdded( uint32 entry
, uint32 count
)
9131 uint32 reqitemcount
;
9132 uint32 curitemcount
;
9133 uint32 additemcount
;
9134 for( int i
= 0; i
< MAX_QUEST_LOG_SIZE
; i
++ )
9136 quest
= GetUInt32Value(PLAYER_QUEST_LOG_1_1
+ 3*i
);
9137 if ( quest
!= 0 && mQuestStatus
[quest
].m_status
== QUEST_STATUS_INCOMPLETE
)
9139 QuestInfo
const *qInfo
= objmgr
.GetQuestInfo(quest
);
9140 if( qInfo
&& qInfo
->HasSpecialFlag( QUEST_SPECIAL_FLAGS_DELIVER
) )
9142 for (int j
= 0; j
< QUEST_OBJECTIVES_COUNT
; j
++)
9144 reqitem
= qInfo
->ReqItemId
[j
];
9145 if ( reqitem
== entry
)
9147 reqitemcount
= qInfo
->ReqItemCount
[j
];
9148 curitemcount
= mQuestStatus
[quest
].m_itemcount
[j
];
9149 if ( curitemcount
< reqitemcount
)
9151 additemcount
= ( curitemcount
+ count
<= reqitemcount
? count
: reqitemcount
- curitemcount
);
9152 mQuestStatus
[quest
].m_itemcount
[j
] += additemcount
;
9153 SendQuestUpdateAddItem( quest
, j
, additemcount
);
9155 if ( CanCompleteQuest( quest
) )
9156 CompleteQuest( quest
);
9165 void Player::ItemRemoved( uint32 entry
, uint32 count
)
9169 uint32 reqitemcount
;
9170 uint32 curitemcount
;
9171 uint32 remitemcount
;
9172 for( int i
= 0; i
< MAX_QUEST_LOG_SIZE
; i
++ )
9174 quest
= GetUInt32Value(PLAYER_QUEST_LOG_1_1
+ 3*i
);
9175 QuestInfo
const* qInfo
= objmgr
.GetQuestInfo(quest
);
9178 if( qInfo
->HasSpecialFlag( QUEST_SPECIAL_FLAGS_DELIVER
) )
9180 for (int j
= 0; j
< QUEST_OBJECTIVES_COUNT
; j
++)
9182 reqitem
= qInfo
->ReqItemId
[j
];
9183 if ( reqitem
== entry
)
9185 reqitemcount
= qInfo
->ReqItemCount
[j
];
9186 if( mQuestStatus
[quest
].m_status
!= QUEST_STATUS_COMPLETE
)
9187 curitemcount
= mQuestStatus
[quest
].m_itemcount
[j
];
9189 curitemcount
= GetItemCount(entry
) + GetBankItemCount(entry
);
9190 if ( curitemcount
- count
< reqitemcount
)
9192 remitemcount
= ( curitemcount
<= reqitemcount
? count
: count
+ reqitemcount
- curitemcount
);
9193 mQuestStatus
[quest
].m_itemcount
[j
] = curitemcount
- remitemcount
;
9194 IncompleteQuest( quest
);
9204 void Player::KilledMonster( uint32 entry
, uint64 guid
)
9208 uint32 reqkillcount
;
9209 uint32 curkillcount
;
9210 uint32 addkillcount
= 1;
9211 for( int i
= 0; i
< MAX_QUEST_LOG_SIZE
; i
++ )
9213 quest
= GetUInt32Value(PLAYER_QUEST_LOG_1_1
+ 3*i
);
9218 QuestInfo
const* qInfo
= objmgr
.GetQuestInfo(quest
);
9219 if ( qInfo
&& mQuestStatus
[quest
].m_status
== QUEST_STATUS_INCOMPLETE
)
9221 if( qInfo
->HasSpecialFlag( QUEST_SPECIAL_FLAGS_KILL_OR_CAST
) )
9223 for (int j
= 0; j
< QUEST_OBJECTIVES_COUNT
; j
++)
9225 // skip GO activate objective or none
9226 if(qInfo
->ReqCreatureOrGOId
[j
] <=0)
9229 // skip Cast at creature objective
9230 if(qInfo
->ReqSpell
[j
] !=0 )
9233 reqkill
= qInfo
->ReqCreatureOrGOId
[j
];
9235 if ( reqkill
== entry
)
9237 reqkillcount
= qInfo
->ReqCreatureOrGOCount
[j
];
9238 curkillcount
= mQuestStatus
[quest
].m_creatureOrGOcount
[j
];
9239 if ( curkillcount
< reqkillcount
)
9241 mQuestStatus
[quest
].m_creatureOrGOcount
[j
] = curkillcount
+ addkillcount
;
9242 SendQuestUpdateAddCreature( quest
, guid
, j
, curkillcount
, addkillcount
);
9244 if ( CanCompleteQuest( quest
) )
9245 CompleteQuest( quest
);
9254 void Player::CastedCreatureOrGO( uint32 entry
, uint64 guid
, uint32 spell_id
)
9257 uint32 reqCastCount
;
9258 uint32 curCastCount
;
9259 uint32 addCastCount
= 1;
9260 for( int i
= 0; i
< MAX_QUEST_LOG_SIZE
; i
++ )
9262 quest
= GetUInt32Value(PLAYER_QUEST_LOG_1_1
+ 3*i
);
9267 QuestInfo
const* qInfo
= objmgr
.GetQuestInfo(quest
);
9268 if ( qInfo
&& mQuestStatus
[quest
].m_status
== QUEST_STATUS_INCOMPLETE
)
9270 if( qInfo
->HasSpecialFlag( QUEST_SPECIAL_FLAGS_KILL_OR_CAST
) )
9272 for (int j
= 0; j
< QUEST_OBJECTIVES_COUNT
; j
++)
9274 // skip kill creature objective (0) or wrong spell casts
9275 if(qInfo
->ReqSpell
[j
] != spell_id
)
9278 uint32 reqTarget
= 0;
9279 // GO activate objective
9280 if(qInfo
->ReqCreatureOrGOId
[j
] < 0)
9282 reqTarget
= - qInfo
->ReqCreatureOrGOId
[j
];
9283 assert(sGOStorage
.LookupEntry
<GameObject
>(reqTarget
));
9285 // creature acivate objectives
9286 else if(qInfo
->ReqCreatureOrGOId
[j
] > 0)
9288 reqTarget
= qInfo
->ReqCreatureOrGOId
[j
];
9289 assert(sCreatureStorage
.LookupEntry
<Creature
>(reqTarget
));
9291 // other not creature/GO related obejctives
9295 if ( reqTarget
== entry
)
9297 reqCastCount
= qInfo
->ReqCreatureOrGOCount
[j
];
9298 curCastCount
= mQuestStatus
[quest
].m_creatureOrGOcount
[j
];
9299 if ( curCastCount
< reqCastCount
)
9301 mQuestStatus
[quest
].m_creatureOrGOcount
[j
] = curCastCount
+ addCastCount
;
9302 SendQuestUpdateAddCreature( quest
, guid
, j
, curCastCount
, addCastCount
);
9304 if ( CanCompleteQuest( quest
) )
9305 CompleteQuest( quest
);
9314 void Player::MoneyChanged( uint32 count
)
9317 for( int i
= 0; i
< MAX_QUEST_LOG_SIZE
; i
++ )
9319 quest
= GetUInt32Value(PLAYER_QUEST_LOG_1_1
+ 3*i
);
9322 QuestInfo
const *qInfo
= objmgr
.GetQuestInfo(quest
);
9323 if( qInfo
&& qInfo
->RewOrReqMoney
< 0 )
9325 if( mQuestStatus
[quest
].m_status
== QUEST_STATUS_INCOMPLETE
)
9327 if(int32(count
) >= -qInfo
->RewOrReqMoney
)
9329 if ( CanCompleteQuest( quest
) )
9330 CompleteQuest( quest
);
9333 else if( mQuestStatus
[quest
].m_status
== QUEST_STATUS_COMPLETE
)
9335 if(int32(count
) < -qInfo
->RewOrReqMoney
)
9336 IncompleteQuest( quest
);
9343 bool Player::HaveQuestForItem( uint32 itemid
)
9345 for( StatusMap::iterator i
= mQuestStatus
.begin( ); i
!= mQuestStatus
.end( ); ++ i
)
9347 quest_status qs
=i
->second
;
9349 if (qs
.m_status
== QUEST_STATUS_INCOMPLETE
)
9351 if (!qs
.m_quest
) continue;
9352 QuestInfo
const* qinfo
= qs
.m_quest
->GetQuestInfo();
9354 // There should be no mixed ReqItem/ReqSource drop
9355 // This part for ReqItem drop
9356 for (int j
= 0; j
< QUEST_OBJECTIVES_COUNT
; j
++)
9358 if(itemid
== qinfo
->ReqItemId
[j
] && qs
.m_itemcount
[j
] < qinfo
->ReqItemCount
[j
] )
9361 // This part - for ReqSource
9362 for (int j
= 0; j
< QUEST_SOURCE_ITEM_IDS_COUNT
; j
++)
9364 // examined item is a source item
9365 if (qinfo
->ReqSourceId
[j
] == itemid
&& qinfo
->ReqSourceRef
[j
] > 0 && qinfo
->ReqSourceRef
[j
] <= QUEST_OBJECTIVES_COUNT
)
9367 uint32 idx
= qinfo
->ReqSourceRef
[j
]-1;
9368 // total count of created ReqItems and SourceItems is less than ReqItemCount
9369 if(qinfo
->ReqItemId
[idx
] != 0 &&
9370 qs
.m_itemcount
[idx
] + GetItemCount(itemid
)+ GetBankItemCount(itemid
) < qinfo
->ReqItemCount
[idx
])
9373 // total count of casted ReqCreatureOrGOs and SourceItems is less than ReqCreatureOrGOCount
9374 if (qinfo
->ReqCreatureOrGOId
[idx
] != 0 &&
9375 qs
.m_creatureOrGOcount
[idx
] + GetItemCount(itemid
)+ GetBankItemCount(itemid
) < qinfo
->ReqCreatureOrGOCount
[idx
])
9384 void Player::SendQuestComplete( uint32 quest_id
)
9389 data
.Initialize( SMSG_QUESTUPDATE_COMPLETE
);
9391 GetSession()->SendPacket( &data
);
9392 sLog
.outDebug( "WORLD: Sent SMSG_QUESTUPDATE_COMPLETE quest = %u", quest_id
);
9396 void Player::SendQuestReward( Quest
*pQuest
, uint32 XP
)
9400 uint32 quest
= pQuest
->GetQuestInfo()->QuestId
;
9401 sLog
.outDebug( "WORLD: Sent SMSG_QUESTGIVER_QUEST_COMPLETE quest = %u", quest
);
9403 data
.Initialize( SMSG_QUESTGIVER_QUEST_COMPLETE
);
9405 data
<< uint32(0x03);
9407 if ( getLevel() < sWorld
.getConfig(CONFIG_MAX_PLAYER_LEVEL
) )
9410 data
<< uint32(pQuest
->GetQuestInfo()->RewOrReqMoney
);
9415 data
<< uint32(pQuest
->GetQuestInfo()->RewOrReqMoney
+ XP
);
9417 data
<< uint32( pQuest
->m_rewitemscount
);
9419 for (int i
= 0; i
< QUEST_REWARDS_COUNT
; i
++)
9421 if ( pQuest
->GetQuestInfo()->RewItemId
[i
] > 0 )
9422 data
<< pQuest
->GetQuestInfo()->RewItemId
[i
] << pQuest
->GetQuestInfo()->RewItemCount
[i
];
9425 GetSession()->SendPacket( &data
);
9429 void Player::SendQuestFailed( uint32 quest_id
)
9434 data
.Initialize( SMSG_QUESTGIVER_QUEST_FAILED
);
9436 GetSession()->SendPacket( &data
);
9437 sLog
.outDebug("WORLD: Sent SMSG_QUESTGIVER_QUEST_FAILED");
9441 void Player::SendQuestTimerFailed( uint32 quest_id
)
9446 data
.Initialize( SMSG_QUESTUPDATE_FAILEDTIMER
);
9448 GetSession()->SendPacket( &data
);
9449 sLog
.outDebug("WORLD: Sent SMSG_QUESTUPDATE_FAILEDTIMER");
9453 void Player::SendCanTakeQuestResponse( uint32 msg
)
9456 data
.Initialize( SMSG_QUESTGIVER_QUEST_INVALID
);
9458 GetSession()->SendPacket( &data
);
9459 sLog
.outDebug("WORLD: Sent SMSG_QUESTGIVER_QUEST_INVALID");
9462 void Player::SendPushToPartyResponse( Player
*pPlayer
, uint32 msg
)
9467 data
.Initialize( MSG_QUEST_PUSH_RESULT
);
9468 data
<< pPlayer
->GetGUID();
9471 GetSession()->SendPacket( &data
);
9472 sLog
.outDebug("WORLD: Sent MSG_QUEST_PUSH_RESULT");
9476 void Player::SendQuestUpdateAddItem( uint32 quest_id
, uint32 item_idx
, uint32 count
)
9481 data
.Initialize( SMSG_QUESTUPDATE_ADD_ITEM
);
9482 sLog
.outDebug( "WORLD: Sent SMSG_QUESTUPDATE_ADD_ITEM" );
9483 data
<< objmgr
.GetQuestInfo(quest_id
)->ReqItemId
[item_idx
];
9485 GetSession()->SendPacket( &data
);
9489 void Player::SendQuestUpdateAddCreature( uint32 quest_id
, uint64 guid
, uint32 creature_idx
, uint32 old_count
, uint32 add_count
)
9491 assert(old_count
+ add_count
< 64 && "mob/GO count store in 6 bits 2^6 = 64 (0..63)");
9493 QuestInfo
const* qInfo
= objmgr
.GetQuestInfo(quest_id
);
9497 data
.Initialize( SMSG_QUESTUPDATE_ADD_KILL
);
9498 sLog
.outDebug( "WORLD: Sent SMSG_QUESTUPDATE_ADD_KILL" );
9499 data
<< qInfo
->QuestId
;
9500 data
<< uint32(qInfo
->ReqCreatureOrGOId
[ creature_idx
]);
9501 data
<< old_count
+ add_count
;
9502 data
<< qInfo
->ReqCreatureOrGOCount
[ creature_idx
];
9504 GetSession()->SendPacket(&data
);
9506 uint16 log_slot
= GetQuestSlot( quest_id
);
9507 uint32 kills
= GetUInt32Value( log_slot
+ 1 );
9508 kills
= kills
+ (add_count
<< ( 6 * creature_idx
));
9509 SetUInt32Value( log_slot
+ 1, kills
);
9513 /*********************************************************/
9514 /*** LOAD SYSTEM ***/
9515 /*********************************************************/
9517 bool Player::MinimalLoadFromDB( uint32 guid
)
9519 QueryResult
*result
= sDatabase
.PQuery("SELECT `data`,`name`,`position_x`,`position_y`,`position_z`,`map` FROM `character` WHERE `guid` = '%u'",guid
);
9523 Field
*fields
= result
->Fetch();
9525 if(!LoadValues( fields
[0].GetString()))
9527 sLog
.outError("ERROR: Player #%d have broken data in `data` field. Can't be loaded.",GUID_LOPART(guid
));
9532 m_name
= fields
[1].GetCppString();
9533 m_positionX
= fields
[2].GetFloat();
9534 m_positionY
= fields
[3].GetFloat();
9535 m_positionZ
= fields
[4].GetFloat();
9536 m_mapId
= fields
[5].GetUInt32();
9538 for (int i
= 0; i
< MAX_QUEST_LOG_SIZE
; i
++)
9545 bool Player::LoadPositionFromDB(uint32
& mapid
, float& x
,float& y
,float& z
,float& o
, uint64 guid
)
9547 QueryResult
*result
= sDatabase
.PQuery("SELECT `position_x`,`position_y`,`position_z`,`orientation`,`map` FROM `character` WHERE `guid` = '%u'",guid
);
9551 Field
*fields
= result
->Fetch();
9553 x
= fields
[0].GetFloat();
9554 y
= fields
[1].GetFloat();
9555 z
= fields
[2].GetFloat();
9556 o
= fields
[3].GetFloat();
9557 mapid
= fields
[4].GetUInt32();
9563 bool Player::LoadValuesArrayFromDB(vector
<string
> & data
, uint64 guid
)
9565 std::ostringstream ss
;
9566 ss
<<"SELECT `data` FROM `character` WHERE `guid`='"<<guid
<<"'";
9567 QueryResult
*result
= sDatabase
.Query( ss
.str().c_str() );
9571 Field
*fields
= result
->Fetch();
9573 data
= StrSplit(fields
[0].GetString(), " ");
9580 uint32
Player::GetUInt32ValueFromArray(vector
<string
> const& data
, uint16 index
)
9582 return (uint32
)atoi(data
[index
].c_str());
9585 float Player::GetFloatValueFromArray(vector
<string
> const& data
, uint16 index
)
9588 uint32 temp
= Player::GetUInt32ValueFromArray(data
,index
);
9589 memcpy(&result
, &temp
, sizeof(result
));
9594 uint32
Player::GetUInt32ValueFromDB(uint16 index
, uint64 guid
)
9596 vector
<string
> data
;
9597 if(!LoadValuesArrayFromDB(data
,guid
))
9600 return GetUInt32ValueFromArray(data
,index
);
9603 float Player::GetFloatValueFromDB(uint16 index
, uint64 guid
)
9606 uint32 temp
= Player::GetUInt32ValueFromDB(index
, guid
);
9607 memcpy(&result
, &temp
, sizeof(result
));
9612 bool Player::LoadFromDB( uint32 guid
)
9614 // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
9615 QueryResult
*result
= sDatabase
.PQuery("SELECT `guid`,`realm`,`account`,`data`,`name`,`race`,`class`,`position_x`,`position_y`,`position_z`,`map`,`orientation`,`taximask`,`online`,`highest_rank`,`standing`,`rating`,`cinematic`,`totaltime`,`leveltime`,`rest_bonus`,`logout_time`,`is_logout_resting`,`resettalents_cost`,`resettalents_time` FROM `character` WHERE `guid` = '%u'",guid
);
9619 sLog
.outError("ERROR: Player (GUID: %u) not found in table `character`, can't load. ",guid
);
9623 Field
*fields
= result
->Fetch();
9625 Object::_Create( guid
, HIGHGUID_PLAYER
);
9627 if(!LoadValues( fields
[3].GetString()))
9629 sLog
.outError("ERROR: Player #%d have broken data in `data` field. Can't be loaded.",GUID_LOPART(guid
));
9634 // cleanup inventory related item value fields (its will be filled correctly in _LoadInventory)
9635 for(uint8 slot
= EQUIPMENT_SLOT_START
; slot
< EQUIPMENT_SLOT_END
; ++slot
)
9637 SetUInt64Value( (uint16
)(PLAYER_FIELD_INV_SLOT_HEAD
+ (slot
* 2) ), 0 );
9639 int VisibleBase
= PLAYER_VISIBLE_ITEM_1_0
+ (slot
* 12);
9640 for(int i
= 0; i
< 9; ++i
)
9641 SetUInt32Value(VisibleBase
+ i
, 0);
9645 delete m_items
[slot
];
9646 m_items
[slot
] = NULL
;
9650 m_drunk
= GetUInt32Value(PLAYER_BYTES_3
) & 0xFFFE;
9652 m_name
= fields
[4].GetCppString();
9654 sLog
.outDebug("Load Basic value of player %s is: ", m_name
.c_str());
9657 m_race
= fields
[5].GetUInt8();
9658 //Need to call it to initialize m_team (m_team can be calculated from m_race)
9659 //Other way is to saves m_team into characters table.
9660 setFactionForRace(m_race
);
9663 m_class
= fields
[6].GetUInt8();
9665 info
= objmgr
.GetPlayerCreateInfo(m_race
, m_class
);
9668 sLog
.outError("Player have incorrect race/class pair. Can't be loaded.");
9673 m_createStats
[STAT_AGILITY
] = (float)info
->agility
;
9674 m_createStats
[STAT_INTELLECT
] = (float)info
->intellect
;
9675 m_createStats
[STAT_SPIRIT
] = (float)info
->spirit
;
9676 m_createStats
[STAT_STAMINA
] = (float)info
->stamina
;
9677 m_createStats
[STAT_STRENGTH
] = (float)info
->strength
;
9679 m_positionX
= fields
[7].GetFloat();
9680 m_positionY
= fields
[8].GetFloat();
9681 m_positionZ
= fields
[9].GetFloat();
9682 m_mapId
= fields
[10].GetUInt32();
9683 m_orientation
= fields
[11].GetFloat();
9685 // since last logout (in ms)
9686 uint32 time_diff
= (time(NULL
) - fields
[21].GetUInt32()) * 1000;
9688 rest_bonus
= fields
[20].GetFloat();
9689 //speed collect rest bonus in offline, in logaut, far from tavern, city (section/in hour)
9690 float bubble
=0.0416; //100% Blizzlike
9691 //speed collect rest bonus in offline, in logaut, far from tavern, city (section/in hour)
9692 float bubble1
=0.083; //100% Blizzlike
9693 if((int)fields
[22].GetUInt32()==1&&(int)fields
[21].GetUInt32()>0)
9694 SetRestBonus( GetRestBonus() + (time(NULL
)-(int)fields
[21].GetUInt32())*0.0142108*bubble1
);
9695 if((int)fields
[22].GetUInt32()==0&&(int)fields
[21].GetUInt32()>0)
9696 SetRestBonus( GetRestBonus() + (time(NULL
)-(int)fields
[21].GetUInt32())*0.0142108*bubble
);
9698 if(!IsPositionValid())
9700 sLog
.outError("ERROR: Player (guidlow %d) have invalid coordinates (X: %d Y: ^%d). Teleport to default race/class locations.",guid
,m_positionX
,m_positionY
);
9702 m_mapId
= info
->mapId
;
9703 m_positionX
= info
->positionX
;
9704 m_positionY
= info
->positionY
;
9705 m_positionZ
= info
->positionZ
;
9708 m_highest_rank
= fields
[14].GetUInt32();
9709 m_standing
= fields
[15].GetUInt32();
9710 m_rating
= fields
[16].GetFloat();
9711 m_cinematic
= fields
[17].GetUInt32();
9712 m_Played_time
[0]= fields
[18].GetUInt32();
9713 m_Played_time
[1]= fields
[19].GetUInt32();
9715 m_resetTalentsCost
= fields
[23].GetUInt32();
9716 m_resetTalentsTime
= fields
[24].GetUInt64();
9718 if( HasFlag(PLAYER_FLAGS
, 8) )
9719 SetUInt32Value(PLAYER_FLAGS
, 0);
9721 if( HasFlag(PLAYER_FLAGS
, 0x11) )
9722 m_deathState
= DEAD
;
9724 _LoadTaxiMask( fields
[12].GetString() );
9728 // make sure the unit is considered out of combat for proper loading
9729 RemoveFlag(UNIT_FIELD_FLAGS
, UNIT_FLAG_IN_COMBAT
);
9731 //mails are loaded only when needed ;-) - when player in game click on mailbox.
9734 _LoadAuras(time_diff
);
9736 _LoadSpells(time_diff
);
9742 _LoadInventory(time_diff
);
9748 // Skip _ApplyAllAuraMods(); -- applied in _LoadAuras by AddAura calls at aura load
9749 // Skip _ApplyAllItemMods(); -- already applied in _LoadInventory()
9751 sLog
.outDebug("The value of player %s after load item and aura is: ", m_name
.c_str());
9757 void Player::_LoadActions()
9762 QueryResult
*result
= sDatabase
.PQuery("SELECT `button`,`action`,`type`,`misc` FROM `character_action` WHERE `guid` = '%u' ORDER BY `button`",GetGUIDLow());
9768 Field
*fields
= result
->Fetch();
9770 addAction(fields
[0].GetUInt8(), fields
[1].GetUInt16(), fields
[2].GetUInt8(), fields
[3].GetUInt8());
9772 while( result
->NextRow() );
9778 void Player::_LoadAuras(uint32 timediff
)
9781 for (int i
= 0; i
< TOTAL_AURAS
; i
++)
9782 m_modAuras
[i
].clear();
9784 for(uint8 i
= 0; i
< 48; i
++)
9785 SetUInt32Value((uint16
)(UNIT_FIELD_AURA
+ i
), 0);
9786 for(uint8 j
= 0; j
< 6; j
++)
9787 SetUInt32Value((uint16
)(UNIT_FIELD_AURAFLAGS
+ j
), 0);
9789 QueryResult
*result
= sDatabase
.PQuery("SELECT `spell`,`effect_index`,`remaintime` FROM `character_aura` WHERE `guid` = '%u'",GetGUIDLow());
9795 Field
*fields
= result
->Fetch();
9796 uint32 spellid
= fields
[0].GetUInt32();
9797 uint32 effindex
= fields
[1].GetUInt32();
9798 int32 remaintime
= (int32
)fields
[2].GetUInt32();
9800 SpellEntry
* spellproto
= sSpellStore
.LookupEntry(spellid
);
9803 sLog
.outError("Unknown aura (spellid %u, effindex %u), ignore.",spellid
,effindex
);
9807 // negative effects should continue counting down after logout
9808 if (remaintime
!= -1 && !IsPositiveEffect(spellid
, effindex
))
9810 remaintime
-= timediff
;
9811 if(remaintime
<= 0) continue;
9814 // FIXME: real caster not stored in DB currently
9816 Aura
* aura
= new Aura(spellproto
, effindex
, this, this/*caster*/);
9817 aura
->SetAuraDuration(remaintime
);
9820 while( result
->NextRow() );
9825 if(m_class
== WARRIOR
)
9826 CastSpell(this,SPELL_PASSIVE_BATTLE_STANCE
,true);
9829 void Player::LoadCorpse()
9831 if(Corpse
* corpse
= GetCorpse())
9834 corpse
->ConvertCorpseToBones();
9836 corpse
->UpdateForPlayer(this,true);
9840 //Prevent Dead Player login without corpse
9846 void Player::_LoadInventory(uint32 timediff
)
9848 QueryResult
*result
= sDatabase
.PQuery("SELECT `slot`,`item`,`item_template` FROM `character_inventory` WHERE `guid` = '%u' AND `bag` = '%u' ORDER BY `slot`",GetGUIDLow(),INVENTORY_SLOT_BAG_0
);
9855 Field
*fields
= result
->Fetch();
9856 uint8 slot
= fields
[0].GetUInt8();
9857 uint32 item_guid
= fields
[1].GetUInt32();
9858 uint32 item_id
= fields
[2].GetUInt32();
9860 ItemPrototype
const * proto
= objmgr
.GetItemPrototype(item_id
);
9864 sLog
.outError( "Player::_LoadInventory: Player %s have unknown item (id: #%u) in inventory, skipped.", GetName(),item_id
);
9868 Item
*item
= NewItemOrBag(proto
);
9869 item
->SetSlot(slot
);
9871 if(!item
->LoadFromDB(item_guid
, GetGUID()))
9877 dest
= ((INVENTORY_SLOT_BAG_0
<< 8) | slot
);
9878 if( IsInventoryPos( dest
) )
9880 if( CanStoreItem( INVENTORY_SLOT_BAG_0
, slot
, dest
, item
, false ) == EQUIP_ERR_OK
)
9881 StoreItem(dest
, item
, true);
9885 else if( IsEquipmentPos( dest
) )
9887 if( CanEquipItem( slot
, dest
, item
, false, false ) == EQUIP_ERR_OK
)
9888 QuickEquipItem(dest
, item
);
9892 else if( IsBankPos( dest
) )
9894 if( CanBankItem( INVENTORY_SLOT_BAG_0
, slot
, dest
, item
, false ) == EQUIP_ERR_OK
)
9895 BankItem(dest
, item
, true);
9899 } while (result
->NextRow());
9904 _ApplyAllItemMods();
9907 // load mailed items which should receive current player
9908 void Player::_LoadMailedItems()
9910 QueryResult
*result
= sDatabase
.PQuery( "SELECT `item` FROM `mail` WHERE `receiver` = '%u' AND `item` > 0", GetGUIDLow());
9918 fields
= result
->Fetch();
9919 Item
* item
= new Item
;
9920 if(!item
->LoadFromDB(fields
[0].GetUInt32(), 0))
9927 while( result
->NextRow() );
9932 void Player::_LoadMail()
9934 //delete old mails, and if old mail has item so delete it too
9935 time_t base
= time(NULL
);
9937 //FIXME: mails with COD will not be returned, but deleted.
9940 sDatabase
.PExecute("DELETE a FROM item_instance AS a INNER JOIN mail AS ab ON a.guid=ab.item WHERE ab.time < '" I64FMTD
"' AND `receiver` = '%u'", (uint64
)base
, GetGUIDLow());
9941 sDatabase
.PExecute("DELETE FROM `mail` WHERE `time` < '" I64FMTD
"' AND `receiver` = '%u'", (uint64
)base
, GetGUIDLow());
9947 QueryResult
*result
= sDatabase
.PQuery("SELECT `id`,`sender`,`receiver`,`subject`,`body`,`item`,`time`,`money`,`cod`,`checked` FROM `mail` WHERE `receiver` = '%u'",GetGUIDLow());
9953 Field
*fields
= result
->Fetch();
9954 Mail
*be
= new Mail
;
9955 be
->messageID
= fields
[0].GetUInt32();
9956 be
->sender
= fields
[1].GetUInt32();
9957 be
->receiver
= fields
[2].GetUInt32();
9958 be
->subject
= fields
[3].GetCppString();
9959 be
->body
= fields
[4].GetCppString();
9960 be
->item
= fields
[5].GetUInt32();
9961 be
->time
= fields
[6].GetUInt32();
9962 be
->money
= fields
[7].GetUInt32();
9963 be
->COD
= fields
[8].GetUInt32();
9964 be
->checked
= fields
[9].GetUInt32();
9965 m_mail
.push_back(be
);
9967 while( result
->NextRow() );
9972 m_mailsLoaded
= true;
9975 void Player::LoadPet()
9977 uint64 pet_guid
= GetPetGUID();
9980 Creature
* in_pet
= ObjectAccessor::Instance().GetCreature(*this, pet_guid
);
9983 Pet
*pet
= new Pet();
9984 pet
->LoadPetFromDB(this);
9988 void Player::_LoadQuestStatus()
9990 mQuestStatus
.clear();
9992 QueryResult
*result
= sDatabase
.PQuery("SELECT `quest`,`status`,`rewarded`,`explored`,`completed_once`,`timer`,`mobcount1`,`mobcount2`,`mobcount3`,`mobcount4`,`itemcount1`,`itemcount2`,`itemcount3`,`itemcount4` FROM `character_queststatus` WHERE `guid` = '%u'", GetGUIDLow());
9998 Field
*fields
= result
->Fetch();
10000 uint32 quest_id
= fields
[0].GetUInt32();
10001 Quest
* pQuest
= objmgr
.NewQuest(quest_id
);
10004 mQuestStatus
[quest_id
].m_quest
= pQuest
;
10006 uint32 qstatus
= fields
[1].GetUInt32();
10007 if(qstatus
< MAX_QUEST_STATUS
)
10008 mQuestStatus
[quest_id
].m_status
= QuestStatus(qstatus
);
10011 mQuestStatus
[quest_id
].m_status
= QUEST_STATUS_NONE
;
10012 sLog
.outError("Player %s have invalid quest %d status (%d), replaced by QUEST_STATUS_NONE(0).",GetName(),quest_id
,qstatus
);
10015 mQuestStatus
[quest_id
].m_rewarded
= ( fields
[2].GetUInt8() > 0 );
10016 mQuestStatus
[quest_id
].m_explored
= ( fields
[3].GetUInt8() > 0 );
10017 mQuestStatus
[quest_id
].m_completed_once
= ( fields
[4].GetUInt8() > 0 );
10019 if( objmgr
.GetQuestInfo(quest_id
)->HasSpecialFlag( QUEST_SPECIAL_FLAGS_TIMED
) && !mQuestStatus
[quest_id
].m_rewarded
)
10020 AddTimedQuest( quest_id
);
10022 if (fields
[5].GetUInt32() <= sWorld
.GetGameTime())
10024 mQuestStatus
[quest_id
].m_timer
= 1;
10026 mQuestStatus
[quest_id
].m_timer
= (fields
[5].GetUInt32() - sWorld
.GetGameTime()) * 1000;
10028 mQuestStatus
[quest_id
].m_creatureOrGOcount
[0] = fields
[6].GetUInt32();
10029 mQuestStatus
[quest_id
].m_creatureOrGOcount
[1] = fields
[7].GetUInt32();
10030 mQuestStatus
[quest_id
].m_creatureOrGOcount
[2] = fields
[8].GetUInt32();
10031 mQuestStatus
[quest_id
].m_creatureOrGOcount
[3] = fields
[9].GetUInt32();
10032 mQuestStatus
[quest_id
].m_itemcount
[0] = fields
[10].GetUInt32();
10033 mQuestStatus
[quest_id
].m_itemcount
[1] = fields
[11].GetUInt32();
10034 mQuestStatus
[quest_id
].m_itemcount
[2] = fields
[12].GetUInt32();
10035 mQuestStatus
[quest_id
].m_itemcount
[3] = fields
[13].GetUInt32();
10037 sLog
.outDebug("Quest status is {%u} for quest {%u}", mQuestStatus
[quest_id
].m_status
, quest_id
);
10040 while( result
->NextRow() );
10046 void Player::_LoadReputation()
10048 Factions newFaction
;
10052 QueryResult
*result
= sDatabase
.PQuery("SELECT `faction`,`reputation`,`standing`,`flags` FROM `character_reputation` WHERE `guid` = '%u'",GetGUIDLow());
10058 Field
*fields
= result
->Fetch();
10060 newFaction
.ID
= fields
[0].GetUInt32();
10061 newFaction
.ReputationListID
= fields
[1].GetUInt32();
10062 newFaction
.Standing
= fields
[2].GetUInt32();
10063 newFaction
.Flags
= fields
[3].GetUInt32();
10065 factions
.push_back(newFaction
);
10067 while( result
->NextRow() );
10073 //LoadReputationFromDBC();
10074 //Set initial reputations
10075 SetInitialFactions();
10079 void Player::_LoadSpells(uint32 timediff
)
10081 for (PlayerSpellMap::iterator itr
= m_spells
.begin(); itr
!= m_spells
.end(); ++itr
)
10082 delete itr
->second
;
10085 QueryResult
*result
= sDatabase
.PQuery("SELECT `spell`,`slot`,`active` FROM `character_spell` WHERE `guid` = '%u'",GetGUIDLow());
10091 Field
*fields
= result
->Fetch();
10093 addSpell(fields
[0].GetUInt16(), fields
[2].GetUInt8(), PLAYERSPELL_UNCHANGED
, fields
[1].GetUInt16());
10095 while( result
->NextRow() );
10101 void Player::_LoadTaxiMask(const char* data
)
10103 vector
<string
> tokens
= StrSplit(data
, " ");
10106 vector
<string
>::iterator iter
;
10108 for (iter
= tokens
.begin(), index
= 0;
10109 (index
< 8) && (iter
!= tokens
.end()); ++iter
, ++index
)
10111 m_taximask
[index
] = atol((*iter
).c_str());
10115 void Player::_LoadTutorials()
10117 QueryResult
*result
= sDatabase
.PQuery("SELECT `tut0`,`tut1`,`tut2`,`tut3`,`tut4`,`tut5`,`tut6`,`tut7` FROM `character_tutorial` WHERE `guid` = '%u'",GetGUIDLow());
10123 Field
*fields
= result
->Fetch();
10125 for (int iI
=0; iI
<8; iI
++)
10126 m_Tutorials
[iI
] = fields
[iI
].GetUInt32();
10129 while( result
->NextRow() );
10135 /*********************************************************/
10136 /*** SAVE SYSTEM ***/
10137 /*********************************************************/
10139 void Player::SaveToDB()
10141 // saved before flight
10146 uint32 tmp_bytes
= GetUInt32Value(UNIT_FIELD_BYTES_1
);
10147 uint32 tmp_flags
= GetUInt32Value(UNIT_FIELD_FLAGS
);
10148 uint32 tmp_pflags
= GetUInt32Value(PLAYER_FLAGS
);
10150 int is_logout_resting
=0; //logaut far from tavern\city
10151 //logaut, but in tavern\city
10152 if(!IsInWorld()&&HasFlag(PLAYER_FLAGS
, PLAYER_FLAGS_RESTING
))is_logout_resting
=1;
10154 // Set player sit state to standing on save
10155 RemoveFlag(UNIT_FIELD_BYTES_1
,PLAYER_STATE_SIT
);
10156 RemoveFlag(UNIT_FIELD_FLAGS
, UNIT_FLAG_DISABLE_ROTATE
);
10158 //remove restflag when save
10159 //this is becouse of the rename char stuff
10160 RemoveFlag(PLAYER_FLAGS
, PLAYER_FLAGS_RESTING
);
10162 sLog
.outDebug("The value of player %s before unload item and aura is: ", m_name
.c_str());
10167 _RemoveAllItemMods();
10168 _RemoveAllAuraMods();
10171 bool inworld
= IsInWorld();
10175 sDatabase
.PExecute("DELETE FROM `character` WHERE `guid` = '%u'",GetGUIDLow());
10177 std::ostringstream ss
;
10178 ss
<< "INSERT INTO `character` (`guid`,`realm`,`account`,`name`,`race`,`class`,"
10179 "`map`,`position_x`,`position_y`,`position_z`,`orientation`,`data`,"
10180 "`taximask`,`online`,`highest_rank`,`standing`,`rating`,`cinematic`,"
10181 "`totaltime`,`leveltime`,`rest_bonus`,`logout_time`,`is_logout_resting`,`resettalents_cost`,`resettalents_time`) VALUES ("
10182 << GetGUIDLow() << ", "
10184 << GetSession()->GetAccountId() << ", '"
10189 << m_positionX
<< ", "
10190 << m_positionY
<< ", "
10191 << m_positionZ
<< ", "
10192 << m_orientation
<< ", '";
10195 for( i
= 0; i
< m_valuesCount
; i
++ )
10197 ss
<< GetUInt32Value(i
) << " ";
10202 for( i
= 0; i
< 8; i
++ )
10203 ss
<< m_taximask
[i
] << " ";
10206 inworld
? ss
<< 1: ss
<< 0;
10209 ss
<< m_highest_rank
;
10221 ss
<< m_Played_time
[0];
10223 ss
<< m_Played_time
[1];
10228 ss
<< (uint64
)time(NULL
);
10230 ss
<< is_logout_resting
;
10232 ss
<< m_resetTalentsCost
;
10234 ss
<< (uint64
)m_resetTalentsTime
;
10238 sDatabase
.Execute( ss
.str().c_str() );
10242 if(m_mailsUpdated
) //save mails only when needed
10246 _SaveQuestStatus();
10254 sLog
.outDebug("Save Basic value of player %s is: ", m_name
.c_str());
10259 _ApplyAllAuraMods();
10260 _ApplyAllItemMods();
10264 SetUInt32Value(UNIT_FIELD_BYTES_1
, tmp_bytes
);
10265 SetUInt32Value(UNIT_FIELD_FLAGS
, tmp_flags
);
10266 SetUInt32Value(PLAYER_FLAGS
, tmp_pflags
);
10272 void Player::_SaveActions()
10274 sDatabase
.PExecute("DELETE FROM `character_action` WHERE `guid` = '%u'",GetGUIDLow());
10276 std::list
<struct actions
>::iterator itr
;
10277 for (itr
= m_actions
.begin(); itr
!= m_actions
.end(); ++itr
)
10279 sDatabase
.PExecute("INSERT INTO `character_action` (`guid`,`button`,`action`,`type`,`misc`) VALUES ('%u', '%u', '%u', '%u', '%u')", GetGUIDLow(), (uint32
)itr
->button
, (uint32
)itr
->action
, (uint32
)itr
->type
, (uint32
)itr
->misc
);
10283 void Player::_SaveAuras()
10285 sDatabase
.PExecute("DELETE FROM `character_aura` WHERE `guid` = '%u'",GetGUIDLow());
10287 AuraMap
const& auras
= GetAuras();
10288 for(AuraMap::const_iterator itr
= auras
.begin(); itr
!= auras
.end(); ++itr
)
10290 SpellEntry
*spellInfo
= itr
->second
->GetSpellProto();
10292 for (i
= 0; i
< 3; i
++)
10293 if (spellInfo
->EffectApplyAuraName
[i
] == SPELL_AURA_MOD_SHAPESHIFT
||
10294 spellInfo
->EffectApplyAuraName
[i
] == SPELL_AURA_MOD_STEALTH
)
10296 if (i
== 3 && !itr
->second
->IsPassive())
10297 sDatabase
.PExecute("INSERT INTO `character_aura` (`guid`,`spell`,`effect_index`,`remaintime`) VALUES ('%u', '%u', '%u', '%d')", GetGUIDLow(), (uint32
)(*itr
).second
->GetId(), (uint32
)(*itr
).second
->GetEffIndex(), int((*itr
).second
->GetAuraDuration()));
10301 void Player::_SaveInventory()
10303 sDatabase
.PExecute("DELETE FROM `character_inventory` WHERE `guid` = '%u' AND `bag` = '%u'",GetGUIDLow(), INVENTORY_SLOT_BAG_0
);
10305 for(int i
= EQUIPMENT_SLOT_START
; i
< BANK_SLOT_BAG_END
; i
++)
10307 if ( m_items
[i
] != 0 )
10309 sDatabase
.PExecute("INSERT INTO `character_inventory` (`guid`,`bag`,`slot`,`item`,`item_template`) VALUES ('%u', '%u', '%u', '%u', '%u')", GetGUIDLow(), INVENTORY_SLOT_BAG_0
, i
, m_items
[i
]->GetGUIDLow(), m_items
[i
]->GetEntry());
10310 m_items
[i
]->SaveToDB();
10315 void Player::_SaveMail()
10317 if (!m_mailsLoaded
)
10320 sDatabase
.PExecute("DELETE FROM `mail` WHERE `receiver` = '%u'",GetGUIDLow());
10322 std::list
<Mail
*>::iterator itr
;
10323 for (itr
= m_mail
.begin(); itr
!= m_mail
.end(); itr
++)
10327 //escape apostrophes
10328 std::string subject
= m
->subject
;
10329 std::string body
= m
->body
;
10330 sDatabase
.escape_string(body
);
10331 sDatabase
.escape_string(subject
);
10333 sDatabase
.PExecute("INSERT INTO `mail` (`id`,`sender`,`receiver`,`subject`,`body`,`item`,`time`,`money`,`cod`,`checked`) "
10334 "VALUES ('%u', '%u', '%u', '%s', '%s', '%u', '" I64FMTD
"', '%u', '%u', '%u')",
10335 m
->messageID
, m
->sender
, m
->receiver
, subject
.c_str(), body
.c_str(), m
->item
, (uint64
)m
->time
, m
->money
, m
->COD
, m
->checked
);
10337 m_mailsUpdated
= false;
10340 void Player::_SaveQuestStatus()
10342 sDatabase
.PExecute("DELETE FROM `character_queststatus` WHERE `guid` = '%u'",GetGUIDLow());
10344 for( StatusMap::iterator i
= mQuestStatus
.begin( ); i
!= mQuestStatus
.end( ); ++ i
)
10346 sDatabase
.PExecute("INSERT INTO `character_queststatus` (`guid`,`quest`,`status`,`rewarded`,`explored`,`completed_once`,`timer`,`mobcount1`,`mobcount2`,`mobcount3`,`mobcount4`,`itemcount1`,`itemcount2`,`itemcount3`,`itemcount4`) VALUES ('%u', '%u', '%u', '%u', '%u', '%u', '" I64FMTD
"', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u')",
10347 GetGUIDLow(), i
->first
, i
->second
.m_status
, i
->second
.m_rewarded
, i
->second
.m_explored
, i
->second
.m_completed_once
, uint64(i
->second
.m_timer
/ 1000 + sWorld
.GetGameTime()), i
->second
.m_creatureOrGOcount
[0], i
->second
.m_creatureOrGOcount
[1], i
->second
.m_creatureOrGOcount
[2], i
->second
.m_creatureOrGOcount
[3], i
->second
.m_itemcount
[0], i
->second
.m_itemcount
[1], i
->second
.m_itemcount
[2], i
->second
.m_itemcount
[3]);
10351 void Player::_SaveReputation()
10353 std::list
<Factions
>::iterator itr
;
10355 sDatabase
.PExecute("DELETE FROM `character_reputation` WHERE `guid` = '%u'",GetGUIDLow());
10357 for(itr
= factions
.begin(); itr
!= factions
.end(); ++itr
)
10359 sDatabase
.PExecute("INSERT INTO `character_reputation` (`guid`,`faction`,`reputation`,`standing`,`flags`) VALUES ('%u', '%u', '%u', '%u', '%u')", GetGUIDLow(), itr
->ID
, itr
->ReputationListID
, itr
->Standing
, itr
->Flags
);
10363 void Player::_SaveSpells()
10365 for (PlayerSpellMap::const_iterator itr
= m_spells
.begin(), next
= m_spells
.begin(); itr
!= m_spells
.end(); itr
= next
)
10368 if (itr
->second
->state
== PLAYERSPELL_REMOVED
|| itr
->second
->state
== PLAYERSPELL_CHANGED
)
10369 sDatabase
.PExecute("DELETE FROM `character_spell` WHERE `guid` = '%u' and `spell` = '%u'", GetGUIDLow(), itr
->first
);
10370 if (itr
->second
->state
== PLAYERSPELL_NEW
|| itr
->second
->state
== PLAYERSPELL_CHANGED
)
10371 sDatabase
.PExecute("INSERT INTO `character_spell` (`guid`,`spell`,`slot`,`active`) VALUES ('%u', '%u', '%u','%u')", GetGUIDLow(), itr
->first
, itr
->second
->slotId
,itr
->second
->active
);
10372 if (itr
->second
->state
== PLAYERSPELL_REMOVED
)
10373 _removeSpell(itr
->first
);
10375 itr
->second
->state
= PLAYERSPELL_UNCHANGED
;
10379 void Player::_SaveTutorials()
10381 sDatabase
.PExecute("DELETE FROM `character_tutorial` WHERE `guid` = '%u'",GetGUIDLow());
10382 sDatabase
.PExecute("INSERT INTO `character_tutorial` (`guid`,`tut0`,`tut1`,`tut2`,`tut3`,`tut4`,`tut5`,`tut6`,`tut7`) VALUES ('%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u')", GetGUIDLow(), m_Tutorials
[0], m_Tutorials
[1], m_Tutorials
[2], m_Tutorials
[3], m_Tutorials
[4], m_Tutorials
[5], m_Tutorials
[6], m_Tutorials
[7]);
10385 void Player::SavePet()
10387 Creature
* pet
= GetPet();
10388 if(pet
&& (pet
->isPet() || pet
->isTamed()))
10392 void Player::outDebugValues() const
10394 sLog
.outDebug("HP is: \t\t\t%u\t\tMP is: \t\t\t%u",GetMaxHealth(), GetMaxPower(POWER_MANA
));
10395 sLog
.outDebug("AGILITY is: \t\t%f\t\tSTRENGTH is: \t\t%f",GetStat(STAT_AGILITY
), GetStat(STAT_STRENGTH
));
10396 sLog
.outDebug("INTELLECT is: \t\t%f\t\tSPIRIT is: \t\t%f",GetStat(STAT_INTELLECT
), GetStat(STAT_SPIRIT
));
10397 sLog
.outDebug("STAMINA is: \t\t%f\t\tSPIRIT is: \t\t%f",GetStat(STAT_STAMINA
), GetStat(STAT_SPIRIT
));
10398 sLog
.outDebug("Armor is: \t\t%f\t\tBlock is: \t\t%f",GetArmor(), GetFloatValue(PLAYER_BLOCK_PERCENTAGE
));
10399 sLog
.outDebug("HolyRes is: \t\t%f\t\tFireRes is: \t\t%f",GetResistance(SPELL_SCHOOL_HOLY
), GetResistance(SPELL_SCHOOL_FIRE
));
10400 sLog
.outDebug("NatureRes is: \t\t%f\t\tFrostRes is: \t\t%f",GetResistance(SPELL_SCHOOL_NATURE
), GetResistance(SPELL_SCHOOL_FROST
));
10401 sLog
.outDebug("ShadowRes is: \t\t%f\t\tArcaneRes is: \t\t%f",GetResistance(SPELL_SCHOOL_SHADOW
), GetResistance(SPELL_SCHOOL_ARCANE
));
10402 sLog
.outDebug("MIN_DAMAGE is: \t\t%f\tMAX_DAMAGE is: \t\t%f",GetFloatValue(UNIT_FIELD_MINDAMAGE
), GetFloatValue(UNIT_FIELD_MAXDAMAGE
));
10403 sLog
.outDebug("MIN_OFFHAND_DAMAGE is: \t%f\tMAX_OFFHAND_DAMAGE is: \t%f",GetFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE
), GetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE
));
10404 sLog
.outDebug("MIN_RANGED_DAMAGE is: \t%f\tMAX_RANGED_DAMAGE is: \t%f",GetFloatValue(UNIT_FIELD_MINRANGEDDAMAGE
), GetFloatValue(UNIT_FIELD_MAXRANGEDDAMAGE
));
10405 sLog
.outDebug("ATTACK_TIME is: \t%u\t\tRANGE_ATTACK_TIME is: \t%u",GetAttackTime(BASE_ATTACK
), GetAttackTime(RANGED_ATTACK
));
10408 /*********************************************************/
10409 /*** LOW LEVEL FUNCTIONS:Notifiers ***/
10410 /*********************************************************/
10412 void Player::SendOutOfRange(Object
* obj
)
10414 UpdateData his_data
;
10415 WorldPacket his_pk
;
10416 obj
->BuildOutOfRangeUpdateBlock(&his_data
);
10417 his_data
.BuildPacket(&his_pk
);
10418 GetSession()->SendPacket(&his_pk
);
10421 inline void Player::SendAttackSwingNotInRange()
10424 data
.Initialize(SMSG_ATTACKSWING_NOTINRANGE
);
10425 GetSession()->SendPacket( &data
);
10428 void Player::SavePositionInDB(uint32 mapid
, float x
,float y
,float z
,float o
,uint64 guid
)
10430 std::ostringstream ss2
;
10431 ss2
<< "UPDATE `character` SET `position_x`='"<<x
<<"',`position_y`='"<<y
10432 << "',`position_z`='"<<z
<<"',`orientation`='"<<o
<<"',`map`='"<<mapid
10433 << "' WHERE `guid`='"<<guid
<<"'";
10434 sDatabase
.Execute(ss2
.str().c_str());
10437 bool Player::SaveValuesArrayInDB(vector
<string
> const& tokens
, uint64 guid
)
10439 std::ostringstream ss2
;
10440 ss2
<<"UPDATE `character` SET `data`='";
10441 vector
<string
>::const_iterator iter
;
10443 for (iter
= tokens
.begin(); iter
!= tokens
.end(); ++iter
, ++i
)
10445 ss2
<<tokens
[i
]<<" ";
10447 ss2
<<"' WHERE `guid`='"<<guid
<<"'";
10449 return sDatabase
.Execute(ss2
.str().c_str());
10452 void Player::SetUInt32ValueInArray(vector
<string
>& tokens
,uint16 index
, uint32 value
)
10455 snprintf(buf
,11,"%u",value
);
10456 tokens
[index
] = buf
;
10459 void Player::SetUInt32ValueInDB(uint16 index
, uint32 value
, uint64 guid
)
10461 vector
<string
> tokens
;
10462 if(!LoadValuesArrayFromDB(tokens
,guid
))
10466 snprintf(buf
,11,"%u",value
);
10467 tokens
[index
] = buf
;
10469 SaveValuesArrayInDB(tokens
,guid
);
10472 void Player::SetFloatValueInDB(uint16 index
, float value
, uint64 guid
)
10475 memcpy(&temp
, &value
, sizeof(value
));
10476 Player::SetUInt32ValueInDB(index
, temp
, guid
);
10479 inline void Player::SendAttackSwingNotStanding()
10482 data
.Initialize(SMSG_ATTACKSWING_NOTSTANDING
);
10483 GetSession()->SendPacket( &data
);
10486 inline void Player::SendAttackSwingDeadTarget()
10489 data
.Initialize(SMSG_ATTACKSWING_DEADTARGET
);
10490 GetSession()->SendPacket( &data
);
10493 inline void Player::SendAttackSwingCantAttack()
10496 data
.Initialize(SMSG_ATTACKSWING_CANT_ATTACK
);
10497 GetSession()->SendPacket( &data
);
10500 inline void Player::SendAttackSwingCancelAttack()
10503 data
.Initialize(SMSG_CANCEL_COMBAT
);
10504 GetSession()->SendPacket( &data
);
10507 inline void Player::SendAttackSwingBadFacingAttack()
10510 data
.Initialize(SMSG_ATTACKSWING_BADFACING
);
10511 GetSession()->SendPacket( &data
);
10514 void Player::PlaySound(uint32 Sound
, bool OnlySelf
)
10517 data
.Initialize(SMSG_PLAY_SOUND
);
10520 GetSession()->SendPacket( &data
);
10522 SendMessageToSet( &data
, true );
10525 void Player::SendExplorationExperience(uint32 Area
, uint32 Experience
)
10528 data
.Initialize( SMSG_EXPLORATION_EXPERIENCE
);
10530 data
<< Experience
;
10531 GetSession()->SendPacket(&data
);
10534 /*********************************************************/
10535 /*** Update timers ***/
10536 /*********************************************************/
10538 void Player::UpdatePVPFlag(time_t currTime
)
10540 if( !GetPvP() ) return;
10542 //Player is counting to set/unset pvp flag
10543 if( !m_pvp_counting
) return;
10545 //Is player is in a PvP action stop counting
10546 if( isInCombatWithPlayer() || isInDuel() )
10548 m_pvp_counting
= false;
10549 m_pvp_count
= time(NULL
);
10553 //Wait 5 min until remove pvp mode
10554 if( currTime
< m_pvp_count
+ 300 ) return;
10557 sChatHandler
.SendSysMessage(GetSession(), "PvP toggled off.");
10561 void Player::UnsummonPet(Creature
* pet
)
10566 if(!pet
||pet
->GetGUID()!=GetPetGUID()) return;
10576 data
.Initialize(SMSG_DESTROY_OBJECT
);
10577 data
<< pet
->GetGUID();
10578 SendMessageToSet (&data
, true);
10580 data
.Initialize(SMSG_PET_SPELLS
);
10582 GetSession()->SendPacket(&data
);
10584 ObjectAccessor::Instance().AddObjectToRemoveList(pet
);
10587 void Player::UnTamePet(Creature
* pet
)
10592 if(!pet
||!pet
->isTamed()||pet
->GetGUID()!=GetPetGUID()) return;
10594 pet
->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE
,pet
->GetCreatureInfo()->faction
);
10595 pet
->SetMaxPower(POWER_HAPPINESS
,0);
10596 pet
->SetPower(POWER_HAPPINESS
,0);
10597 pet
->SetMaxPower(POWER_FOCUS
,0);
10598 pet
->SetPower(POWER_FOCUS
,0);
10599 pet
->SetUInt64Value(UNIT_FIELD_CREATEDBY
, 0);
10600 pet
->SetUInt32Value(UNIT_FIELD_PETNUMBER
,0);
10601 pet
->SetTamed(false);
10604 pet
->AIM_Initialize();
10608 data
.Initialize(SMSG_PET_SPELLS
);
10610 GetSession()->SendPacket(&data
);
10613 void Player::Uncharm()
10615 Creature
* charm
= GetCharm();
10620 CreatureInfo
const *cinfo
= charm
->GetCreatureInfo();
10621 charm
->SetUInt64Value(UNIT_FIELD_CHARMEDBY
,0);
10622 charm
->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE
,cinfo
->faction
);
10624 charm
->AIM_Initialize();
10626 data
.Initialize(SMSG_PET_SPELLS
);
10628 GetSession()->SendPacket(&data
);
10631 void Player::PetSpellInitialize()
10633 Creature
* pet
= GetPet();
10640 uint16 Command
= 7;
10644 sLog
.outDebug("Pet Spells Groups");
10647 data
.Initialize(SMSG_PET_SPELLS
);
10649 data
<< (uint64
)pet
->GetGUID() << uint32(0x00000000) << uint32(0x1010000);
10651 data
<< uint16 (2) << uint16(Command
<< 8) << uint16 (1) << uint16(Command
<< 8) << uint16 (0) << uint16(Command
<< 8);
10653 for(uint32 i
=0; i
< CREATURE_MAX_SPELLS
; i
++)
10654 //C100 = maybe group
10655 data
<< uint16 (pet
->m_spells
[i
]) << uint16 (0xC100);
10657 data
<< uint16 (2) << uint16(State
<< 8) << uint16 (1) << uint16(State
<< 8) << uint16 (0) << uint16(State
<< 8);
10659 if(pet
->GetUInt32Value(UNIT_FIELD_PETNUMBER
))
10661 for(PlayerSpellMap::iterator itr
= m_spells
.begin();itr
!= m_spells
.end();itr
++)
10663 if(itr
->second
->active
== 4)
10668 data
<< uint8(addlist
);
10670 if(pet
->GetUInt32Value(UNIT_FIELD_PETNUMBER
))
10672 for(PlayerSpellMap::iterator itr
= m_spells
.begin();itr
!= m_spells
.end();itr
++)
10674 if(itr
->second
->active
== 4)
10676 bool hasthisspell
= false;
10678 SpellEntry
*spellInfo
= sSpellStore
.LookupEntry(itr
->first
);
10679 data
<< uint16(spellInfo
->EffectTriggerSpell
[0]);
10680 for(uint32 i
=0; i
< CREATURE_MAX_SPELLS
; i
++)
10682 if(pet
->m_spells
[i
] == spellInfo
->EffectTriggerSpell
[0])
10684 data
<< uint16(0xC1);
10685 hasthisspell
= true;
10690 data
<< uint16(0x01);
10695 data
<< uint8(0x01) << uint32(0x6010) << uint32(0x00) << uint32(0x00) << uint16(0x00);
10697 GetSession()->SendPacket(&data
);
10701 int32
Player::GetTotalFlatMods(uint32 spellId
, uint8 op
)
10703 SpellEntry
*spellInfo
= sSpellStore
.LookupEntry(spellId
);
10704 if (!spellInfo
) return 0;
10706 for (SpellModList::iterator itr
= m_spellMods
[op
].begin(); itr
!= m_spellMods
[op
].end(); ++itr
)
10708 SpellModifier
*mod
= *itr
;
10709 if (!mod
) continue;
10710 if ((mod
->mask
& spellInfo
->SpellFamilyFlags
) == 0) continue;
10711 if (mod
->type
== SPELLMOD_FLAT
)
10712 total
+= mod
->value
;
10717 int32
Player::GetTotalPctMods(uint32 spellId
, uint8 op
)
10719 SpellEntry
*spellInfo
= sSpellStore
.LookupEntry(spellId
);
10720 if (!spellInfo
) return 0;
10722 for (SpellModList::iterator itr
= m_spellMods
[op
].begin(); itr
!= m_spellMods
[op
].end(); ++itr
)
10724 SpellModifier
*mod
= *itr
;
10725 if (!mod
) continue;
10726 if ((mod
->mask
& spellInfo
->SpellFamilyFlags
) == 0) continue;
10727 if (mod
->type
== SPELLMOD_PCT
)
10728 total
+= mod
->value
;
10733 void Player::ApplyBlockValueMod(int32 val
,bool apply
)
10735 ApplyModUInt32Var(m_BlockValue
,val
,apply
);
10738 void Player::RemoveAreaAurasFromGroup()
10740 Group
* pGroup
= objmgr
.GetGroupByLeader(this->GetGroupLeader());
10744 for(uint32 p
=0;p
<pGroup
->GetMembersCount();p
++)
10746 Unit
* Member
= ObjectAccessor::Instance().FindPlayer(pGroup
->GetMemberGUID(p
));
10749 Member
->RemoveAreaAurasByOthers(GetGUID());
10750 for (uint8 i
= 0; i
< 4; i
++)
10751 if (m_TotemSlot
[i
])
10752 Member
->RemoveAreaAurasByOthers(m_TotemSlot
[i
]);
10756 // send Proficiency
10757 void Player::SendProficiency(uint8 pr1
, uint32 pr2
)
10760 data
.Initialize (SMSG_SET_PROFICIENCY
);
10761 data
<< pr1
<< pr2
;
10762 GetSession()->SendPacket (&data
);
10765 void Player::RemovePetitionsAndSigns(uint64 guid
)
10767 QueryResult
*result
= sDatabase
.PQuery("SELECT `ownerguid`,`charterguid` FROM `guild_charter_sign` WHERE `playerguid` = '%u'", guid
);
10772 Field
*fields
= result
->Fetch();
10773 uint64 ownerguid
= MAKE_GUID(fields
[0].GetUInt32(),HIGHGUID_PLAYER
);
10774 uint64 charterguid
= MAKE_GUID(fields
[1].GetUInt32(),HIGHGUID_ITEM
);
10776 // send update if charter owner in game
10777 Player
* owner
= objmgr
.GetPlayer(ownerguid
);
10779 owner
->GetSession()->SendPetitionQueryOpcode(charterguid
);
10781 } while ( result
->NextRow() );
10785 sDatabase
.PExecute("DELETE FROM `guild_charter_sign` WHERE `playerguid` = '%u'",guid
);
10788 sDatabase
.PExecute("DELETE FROM `guild_charter` WHERE `ownerguid` = '%u'",guid
);
10789 sDatabase
.PExecute("DELETE FROM `guild_charter_sign` WHERE `ownerguid` = '%u'",guid
);