root/trunk/src/arcemu-world/Object.cpp @ 2860

Revision 2860, 105.8 kB (checked in by Vlack, 12 months ago)

Notice: Trunk is now 3.2.0

FIXED: Mail sending (by providing a missing item for the world database, this item is necessary for the client - for the item, thanks goes to Darkgrööm)
FIXED: Battleground selection crash (now the server will queue you on Isle of Conquest - note: this does not mean you can play on it, but it solves the instant crash when players selected it)
FIXED: Glyphs (till we properly implement dual spec)
FIXED: A9 target GUID sending (on flags & UPDATEFLAG_HAS_TARGET - thanks Alleycat)
FIXED: Re-enabled ground targeted spells (on m_targetMask & TARGET_FLAG_DEST_LOCATION - if a spell where you can select the area of its effect crashes the client in the future, we'll revise this part)
FIXED: A9 (actually just moved the already existing code pieces up/down to better suit the required format, but to know the format right, I had looked into Mangos code too, as I haven't got months to figure out the right structure)
FIXED: TaxiMgr::GetGlobalTaxiNodeMask? (index check, as with the new DBCs we have a "to" with value "-1", and when that's used as an uint, it'll result in an index of 255, while the structure is from 0 to 11).
ADDED: Override support (this extends the core with special features for special gameobjects, like what's required for trams and transports, which include features as: "override update fields", "never despawn on same map", "announce on greater range" and "push to player on map entry").
FIXED: static map object pushing (repaired the buffer handling error which duplicated buffer content in a pretty unique way).
ADDED: SQL fixes for Deeprun and Ulduar Trams (retail data, but it works right only with the override system).
UPDATED: UpdateFields?.h
UPDATED: DBCs (thanks Xuni)
UPDATED: Error codes (thanks Hopla)
FIXED: various packets, especially the following ones: character enumeration, mail list, group details (raid difficulty), movement-related packets
FIXED: The display of quest rewards the player can choose from on the quest page before accepting it.
FIXED: A nasty bug when un-equipping an item to a bag and not to the backpack. The problem was that I have missed 2 for loops where the visible items get nulled out on unequip, it erased 17 fields instead of just 2, so it made the character pretty much naked.

  • Property svn:eol-style set to native
  • Property ff set to
    *.cpp = svn:eol-style=native
    Makefile = svn:eol-style=native
    README = svn:eol-style=native
    CHANGELOG = svn:eol-style=native
    LICENSE = svn:eol-style=native
Line 
1/*
2 * ArcEmu MMORPG Server
3 * Copyright (C) 2005-2007 Ascent Team <http://www.ascentemu.com/>
4 * Copyright (C) 2008-2009 <http://www.ArcEmu.org/>
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU Affero General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU Affero General Public License for more details.
15 *
16 * You should have received a copy of the GNU Affero General Public License
17 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 *
19 */
20
21#include "StdAfx.h"
22#include "Unit.h"
23using namespace std;
24
25//#define DEG2RAD (M_PI/180.0)
26#define M_PI            3.14159265358979323846
27#define M_H_PI          1.57079632679489661923
28#define M_Q_PI          0.785398163397448309615
29
30static float DamageToRageConversionTable[PLAYER_LEVEL_CAP+1]=
31{
32        0.0f,
33        3.33333332596f,
34        2.32494760373f,
35        1.78264780661f,
36        1.44396357117f,
37        1.2123533165f,
38        1.04397785496f,
39        0.916056052096f,
40        0.815576431602f,
41        0.734567160417f,
42        0.66787149277f,
43        0.612005960162f,
44        0.564532608393f,
45        0.523694129722f,
46        0.488191825581f,
47        0.457045164141f,
48        0.429499969492f,
49        0.404966667879f,
50        0.382977704896f,
51        0.363157531812f,
52        0.345201035638f,
53        0.328857765668f,
54        0.313920217094f,
55        0.300215004319f,
56        0.287596125288f,
57        0.27593976089f,
58        0.265140216201f,
59        0.255106721412f,
60        0.24576088725f,
61        0.23703466382f,
62        0.228868690383f,
63        0.221210951417f,
64        0.214015674635f,
65        0.20724242161f,
66        0.200855332852f,
67        0.194822497576f,
68        0.189115424762f,
69        0.183708597032f,
70        0.178579092584f,
71        0.17370626337f,
72        0.169071460011f,
73        0.164657795691f,
74        0.160449942759f,
75        0.156433956854f,
76        0.152597124314f,
77        0.148927829351f,
78        0.145415438059f,
79        0.142050196824f,
80        0.138823143098f,
81        0.1357260268f,
82        0.132751240913f,
83        0.129891760035f,
84        0.127141085846f,
85        0.124493198595f,
86        0.121942513852f,
87        0.119483843862f,
88        0.117112362949f,
89        0.114823576474f,
90        0.112613292937f,
91        0.110477598847f,
92        0.108412836061f,
93        0.106415581293f,
94        0.104482627572f,
95        0.102610967429f,
96        0.100797777624f,
97        0.0990404052564f,
98        0.0973363551185f,
99        0.0956832781503f,
100        0.094078960901f,
101        0.0925213158854f,
102        0.0910083727537f,
103#if PLAYER_LEVEL_CAP==80
104        0.0910083727537f,
105        0.0910083727537f,
106        0.0910083727537f,
107        0.0910083727537f,
108        0.0910083727537f,
109        0.0910083727537f,
110        0.0910083727537f,
111        0.0910083727537f,
112        0.0910083727537f,
113#endif
114};
115
116void Object::SetRotation( uint64 guid )
117{
118        WorldPacket data(SMSG_AI_REACTION, 12);
119        data << guid;
120        data << uint32(2);
121        SendMessageToSet(&data, false);
122}
123
124Object::Object() : m_position(0,0,0,0), m_spawnLocation(0,0,0,0)
125{
126        m_mapId = 0;
127        m_zoneId = 0;
128
129        m_uint32Values = 0;
130        m_objectUpdated = false;
131
132
133        m_valuesCount = 0;
134
135        //official Values
136        m_walkSpeed = 2.5f;
137        m_runSpeed = 7.0f;
138        m_base_runSpeed = m_runSpeed;
139        m_base_walkSpeed = m_walkSpeed;
140
141        m_flySpeed = 7.0f;
142        m_backFlySpeed = 4.5f;
143
144        m_backWalkSpeed = 4.5f; // this should really be named m_backRunSpeed
145        m_swimSpeed = 4.722222f;
146        m_backSwimSpeed = 2.5f;
147        m_turnRate = 3.141593f;
148
149        m_phase = 1; //Set the default phase: 00000000 00000000 00000000 00000001
150
151        m_mapMgr = 0;
152        m_mapCell = 0;
153
154        mSemaphoreTeleport = false;
155
156
157        m_faction = NULL;
158        m_factionDBC = NULL;
159
160        m_instanceId = 0;
161        Active = false;
162        m_inQueue = false;
163        m_extensions = NULL;
164        m_loadedFromDB = false;
165
166        m_faction = dbcFactionTemplate.LookupRow( 0 );
167        m_factionDBC = dbcFaction.LookupRow( 0 );
168
169        m_objectsInRange.clear();
170        m_inRangePlayers.clear();
171        m_oppFactsInRange.clear();
172        m_sameFactsInRange.clear();
173
174        Active = false;
175}
176
177Object::~Object( )
178{
179        if(m_objectTypeId != TYPEID_ITEM)
180                ASSERT(!m_inQueue);
181
182        if (this->IsInWorld() && m_objectTypeId != TYPEID_ITEM && m_objectTypeId != TYPEID_CONTAINER)
183        {
184                this->RemoveFromWorld(false);
185                this->ClearInRangeSet();
186        }
187
188        // for linux
189        m_instanceId = -1;
190        m_objectTypeId=TYPEID_UNUSED;
191
192        if( m_extensions != NULL )
193                delete m_extensions;
194
195        //avoid leaving traces in eventmanager. Have to work on the speed. Not all objects ever had events so list iteration can be skipped
196        sEventMgr.RemoveEvents( this );
197}
198
199
200void Object::_Create( uint32 mapid, float x, float y, float z, float ang )
201{
202        m_mapId = mapid;
203        m_position.ChangeCoords(x, y, z, ang);
204        m_spawnLocation.ChangeCoords(x, y, z, ang);
205        m_lastMapUpdatePosition.ChangeCoords(x,y,z,ang);
206}
207
208uint32 Object::BuildCreateUpdateBlockForPlayer(ByteBuffer *data, Player *target)
209{
210        uint16 flags = 0;
211        uint32 flags2 = 0;
212
213        uint8 updatetype = UPDATETYPE_CREATE_OBJECT;
214        if(m_objectTypeId == TYPEID_CORPSE)
215        {
216                if(m_uint32Values[CORPSE_FIELD_DISPLAY_ID] == 0)
217                        return 0;
218                updatetype = UPDATETYPE_CREATE_YOURSELF;
219        }
220
221        // any other case
222        switch(m_objectTypeId)
223        {
224                // items + containers: 0x8
225        case TYPEID_ITEM:
226        case TYPEID_CONTAINER:
227                flags = 0x10;
228                break;
229
230                // player/unit: 0x68 (except self)
231        case TYPEID_UNIT:
232                flags = 0x70;
233                break;
234
235        case TYPEID_PLAYER:
236                flags = 0x70;
237                break;
238
239                // gameobject/dynamicobject
240        case TYPEID_GAMEOBJECT:
241                flags = 0x0350;
242                if( m_uint32Values[GAMEOBJECT_DISPLAYID]==3831 ) flags=0x0252; //Deeprun Tram proper flags as of 3.2.0.
243                break;
244
245        case TYPEID_DYNAMICOBJECT:
246                flags = 0x0150;
247                break;
248
249        case TYPEID_CORPSE:
250                flags = 0x0150;
251                break;
252                // anyone else can get fucked and die!
253        }
254
255        if(target == this)
256        {
257                // player creating self
258                flags |= 0x01;
259                updatetype = UPDATETYPE_CREATE_YOURSELF;
260        }
261
262        // gameobject stuff
263        if(m_objectTypeId == TYPEID_GAMEOBJECT)
264        {
265//              switch( GetByte(GAMEOBJECT_BYTES_1,GAMEOBJECT_BYTES_TYPEID) )
266                switch(m_uint32Values[GAMEOBJECT_BYTES_1])
267                {
268                        case GAMEOBJECT_TYPE_MO_TRANSPORT: 
269                                {
270                                        if(GetTypeFromGUID() != HIGHGUID_TYPE_TRANSPORTER)
271                                                return 0;   // bad transporter
272                                        else
273                                                flags = 0x0352;
274                                }break;
275
276                        case GAMEOBJECT_TYPE_TRANSPORT:
277                                {
278                                        /* deeprun tram, etc */
279                                        flags = 0x252;
280                                }break;
281
282                        case GAMEOBJECT_TYPE_DUEL_ARBITER:
283                                {
284                                        // duel flags have to stay as updatetype 3, otherwise
285                                        // it won't animate
286                                        updatetype = UPDATETYPE_CREATE_YOURSELF;
287                                }break;
288                }
289                //The above 3 checks FAIL to identify transports, thus their flags remain 0x58, and this is BAAAAAAD! Later they don't get position x,y,z,o updates, so they appear randomly by a client-calculated path, they always face north, etc... By: VLack
290                if( flags != 0x0352 && GetTypeId() == TYPEID_GAMEOBJECT && static_cast<GameObject*>(this)->GetInfo()->Type == GAMEOBJECT_TYPE_TRANSPORT && !(static_cast<GameObject*>(this)->GetOverrides() & GAMEOBJECT_OVERRIDE_PARENTROT) )
291                        flags = 0x0352;
292        }
293
294        // build our actual update
295        *data << updatetype;
296
297        // we shouldn't be here, under any circumstances, unless we have a wowguid..
298        ASSERT(m_wowGuid.GetNewGuidLen());
299        *data << m_wowGuid;
300       
301        *data << m_objectTypeId;
302
303        _BuildMovementUpdate(data, flags, flags2, target);
304
305        // we have dirty data, or are creating for ourself.
306        UpdateMask updateMask;
307        updateMask.SetCount( m_valuesCount );
308        _SetCreateBits( &updateMask, target );
309
310        if(GetTypeId() == TYPEID_GAMEOBJECT && (static_cast<GameObject*>(this)->GetOverrides() & GAMEOBJECT_OVERRIDE_PARENTROT) )
311        {
312                updateMask.SetBit(GAMEOBJECT_PARENTROTATION_02);
313                updateMask.SetBit(GAMEOBJECT_PARENTROTATION_03);
314        }
315
316        // this will cache automatically if needed
317        _BuildValuesUpdate( data, &updateMask, target );
318
319        // update count: 1 ;)
320        return 1;
321}
322
323
324//That is dirty fix it actually creates update of 1 field with
325//the given value ignoring existing changes in fields and so on
326//useful if we want update this field for certain players
327//NOTE: it does not change fields. This is also very fast method
328WorldPacket *Object::BuildFieldUpdatePacket( uint32 index,uint32 value)
329{
330   // uint64 guidfields = GetGUID();
331   // uint8 guidmask = 0;
332        WorldPacket * packet=new WorldPacket(1500);
333        packet->SetOpcode( SMSG_UPDATE_OBJECT );
334
335        *packet << (uint32)1;//number of update/create blocks
336//      *packet << (uint8)0;//unknown //VLack: removed for 3.1
337
338        *packet << (uint8) UPDATETYPE_VALUES;           // update type == update
339        *packet << GetNewGUID();
340
341        uint32 mBlocks = index/32+1;
342        *packet << (uint8)mBlocks;
343
344        for(uint32 dword_n=mBlocks-1;dword_n;dword_n--)
345        *packet <<(uint32)0;
346
347        *packet <<(((uint32)(1))<<(index%32));
348        *packet << value;
349
350        return packet;
351}
352
353void Object::BuildFieldUpdatePacket(Player* Target, uint32 Index, uint32 Value)
354{
355        ByteBuffer buf(500);
356        buf << uint8(UPDATETYPE_VALUES);
357        buf << GetNewGUID();
358
359        uint32 mBlocks = Index/32+1;
360        buf << (uint8)mBlocks;
361
362        for(uint32 dword_n=mBlocks-1;dword_n;dword_n--)
363                buf <<(uint32)0;
364
365        buf <<(((uint32)(1))<<(Index%32));
366        buf << Value;
367
368        Target->PushUpdateData(&buf, 1);
369}
370
371void Object::BuildFieldUpdatePacket(ByteBuffer * buf, uint32 Index, uint32 Value)
372{
373        *buf << uint8(UPDATETYPE_VALUES);
374        *buf << GetNewGUID();
375
376        uint32 mBlocks = Index/32+1;
377        *buf << (uint8)mBlocks;
378
379        for(uint32 dword_n=mBlocks-1;dword_n;dword_n--)
380                *buf <<(uint32)0;
381
382        *buf <<(((uint32)(1))<<(Index%32));
383        *buf << Value;
384}
385
386uint32 Object::BuildValuesUpdateBlockForPlayer(ByteBuffer *data, Player *target)
387{
388        UpdateMask updateMask;
389        updateMask.SetCount( m_valuesCount );
390        _SetUpdateBits( &updateMask, target );
391        for(uint32 x = 0; x < m_valuesCount; ++x)
392        {
393                if(updateMask.GetBit(x))
394                {
395                        *data << (uint8) UPDATETYPE_VALUES;             // update type == update
396                        ASSERT(m_wowGuid.GetNewGuidLen());
397                        *data << m_wowGuid;
398
399                        _BuildValuesUpdate( data, &updateMask, target );
400                        return 1;
401                }
402        }
403
404        return 0;
405}
406
407uint32 Object::BuildValuesUpdateBlockForPlayer(ByteBuffer * buf, UpdateMask * mask )
408{
409        // returns: update count
410        // update type == update
411        *buf << (uint8) UPDATETYPE_VALUES;             
412
413        ASSERT(m_wowGuid.GetNewGuidLen());
414        *buf << m_wowGuid;
415
416        _BuildValuesUpdate( buf, mask, 0 );
417
418        // 1 update.
419        return 1;
420}
421
422void Object::DestroyForPlayer(Player * target) const
423{
424        // If the target doesn't exist, return. If the target exists, but it session is null return
425         if( target == NULL || target->GetSession() == NULL )
426                return;
427
428        ASSERT(target);
429
430        WorldPacket data( SMSG_DESTROY_OBJECT, 9 );
431        data << GetGUID();
432        data << uint8( 0 ); //TODO: unk bool
433
434        target->GetSession()->SendPacket( &data );
435}
436
437
438///////////////////////////////////////////////////////////////
439/// Build the Movement Data portion of the update packet
440/// Fills the data with this object's movement/speed info
441/// TODO: rewrite this stuff, document unknown fields and flags
442uint32 TimeStamp();
443
444void Object::_BuildMovementUpdate(ByteBuffer * data, uint16 flags, uint32 flags2, Player* target )
445{
446        /* ByteBuffer *splinebuf = (m_objectTypeId == TYPEID_UNIT) ? target->GetAndRemoveSplinePacket(GetGUID()) : 0; */
447        uint16 flag16 = 0;      // some other flag
448        /* VLack: idea from Mangos, for future vehicle implementation
449        if(GetTypeId() == TYPEID_UNIT)
450                if(((Creature*)this)->isVehicle())
451                        flag16 |= 0x20;*/
452
453        *data << (uint16)flags;
454
455        Player * pThis = NULL;
456        MovementInfo* moveinfo = NULL;
457        if(GetTypeId() == TYPEID_PLAYER)
458        {
459                pThis = static_cast< Player* >( this );
460                if(pThis->GetSession())
461                        moveinfo = pThis->GetSession()->GetMovementInfo();
462                if(target == this)
463                {
464                        // Updating our last speeds.
465                        pThis->UpdateLastSpeeds();
466                }
467        }
468        Creature * uThis = NULL;
469        if (GetTypeId() == TYPEID_UNIT)
470                uThis = static_cast<Creature*>(this);
471
472        if (flags & UPDATEFLAG_LIVING) //0x20
473        {
474                if(pThis && pThis->m_TransporterGUID != 0)
475                        flags2 |= MOVEFLAG_TAXI; //0x200
476                else if(uThis != NULL && uThis->m_transportGuid != 0 && uThis->m_transportPosition != NULL)
477                        flags2 |= MOVEFLAG_TAXI; //0x200
478
479                /*if(splinebuf)
480                {
481                        flags2 |= MOVEFLAG_IMMOBILIZED;    //1=move forward
482                        flags2 |= MOVEFLAG_MOVE_FORWARD;
483                        if(uThis != NULL)
484                        {
485                                if(uThis->GetAIInterface()->m_moveRun == false)
486                                        flags2 |= MOVEFLAG_WALK;        //100=walk
487                        }
488                }*/
489
490                if(uThis != NULL)
491                {
492                        //               Don't know what this is, but I've only seen it applied to spirit healers.
493                        //               maybe some sort of invisibility flag? :/
494                        switch(GetEntry())
495                        {
496                        case 6491:  // Spirit Healer
497                        case 13116: // Alliance Spirit Guide
498                        case 13117: // Horde Spirit Guide
499                                {
500                                        flags2 |= MOVEFLAG_WATER_WALK; //0x10000000
501                                }break;
502                        }
503
504                        if(uThis->GetAIInterface()->IsFlying())
505                                //flags2 |= 0x800; //in 2.3 this is some state that i was not able to decode yet
506                                flags2 |= MOVEFLAG_NO_COLLISION; //0x400 Zack : Teribus the Cursed had flag 400 instead of 800 and he is flying all the time
507                        if(uThis->GetProto() && uThis->GetProto()->extra_a9_flags)
508                        {
509//do not send shit we can't honor
510#define UNKNOWN_FLAGS2 ( 0x00002000 | 0x04000000 | 0x08000000 )
511                                uint32 inherit = uThis->GetProto()->extra_a9_flags & UNKNOWN_FLAGS2;
512                                flags2 |= inherit;
513                        }
514                        /*if(GetGUIDHigh() == HIGHGUID_WAYPOINT)
515                        {
516                                if(GetUInt32Value(UNIT_FIELD_STAT0) == 768)             // flying waypoint
517                                        flags2 |= 0x800;
518                        }*/
519                }
520
521                *data << (uint32)flags2;
522
523                *data << (uint16)flag16;
524
525                *data << getMSTime(); // this appears to be time in ms but can be any thing. Maybe packet serializer ?
526
527                // this stuff:
528                //   0x01 -> Enable Swimming?
529                //   0x04 -> ??
530                //   0x10 -> disables movement compensation and causes players to jump around all the place
531                //   0x40 -> disables movement compensation and causes players to jump around all the place
532
533                //Send position data, every living thing has these
534                *data << (float)m_position.x;
535                *data << (float)m_position.y;
536                *data << (float)m_position.z;
537                *data << (float)m_position.o;
538
539                if(flags2 & MOVEFLAG_TAXI) //0x0200
540                {
541                        if(pThis)
542                        {
543                                WoWGuid wowguid(pThis->m_TransporterGUID);
544                                *data << wowguid;
545                                *data << pThis->m_TransporterX << pThis->m_TransporterY << pThis->m_TransporterZ << pThis->m_TransporterO;
546                                //*data << pThis->m_TransporterTime;
547                                *data << pThis->m_TransporterUnk;
548                                *data << (uint8)0;
549                        }
550                        else if(uThis != NULL && uThis->m_transportPosition != NULL)
551                        {
552                                uint64 tguid = ((uint64)HIGHGUID_TYPE_TRANSPORTER << 32) | uThis->m_transportGuid;
553                                WoWGuid wowguid( tguid );
554                                *data << wowguid;
555                                *data << uThis->m_transportPosition->x << uThis->m_transportPosition->y <<
556                                        uThis->m_transportPosition->z << uThis->m_transportPosition->o;
557                                *data << uint32(0);
558                                *data << uint8(0);
559                        }
560                }
561
562                if( (flags2 & (MOVEFLAG_SWIMMING | MOVEFLAG_AIR_SWIMMING)) || (flag16 & 0x20) ) // 0x2000000+0x0200000 flying/swimming, && unk sth to do with vehicles?
563                {
564                        if(pThis && moveinfo)
565                                *data << moveinfo->pitch;
566                        else 
567                                *data << (float)0; //pitch
568                }
569
570                if(pThis && moveinfo)
571                        *data << moveinfo->unklast;
572                else
573                        *data << (uint32)0; //last fall time
574
575                if( flags2 & MOVEFLAG_JUMPING ) // 0x00001000
576                {
577                        /*if(pThis && moveinfo)
578                        {
579                                *data << moveinfo->FallTime;
580                                *data << moveinfo->jump_sinAngle;
581                                *data << moveinfo->jump_cosAngle;
582                                *data << moveinfo->jump_xySpeed;
583                        }
584                        else
585                        {*/
586                                *data << (float)0;
587                                *data << (float)1.0;
588                                *data << (float)0;
589                                *data << (float)0;
590                        //}
591                }
592
593                if( flags2 & MOVEFLAG_SPLINE_MOVER ) // 0x4000000
594                {
595                        int err1, err2; err2=0; err1=10/err2; //FAIL please with divide by zero :)
596                }
597
598                if( m_walkSpeed == 0 )
599                        *data << 8.0f;
600                else
601                        *data << m_walkSpeed;   // walk speed
602                if( m_runSpeed == 0 )
603                        *data << 8.0f;
604                else
605                        *data << m_runSpeed;    // run speed
606                *data << m_backWalkSpeed;       // backwards walk speed
607                *data << m_swimSpeed;           // swim speed
608                *data << m_backSwimSpeed;       // backwards swim speed
609                if( m_flySpeed == 0 )
610                        *data << 8.0f;
611                else
612                        *data << m_flySpeed;    // fly speed
613                *data << m_backFlySpeed;        // back fly speed
614                *data << m_turnRate;            // turn rate
615                *data << float(7);              // pitch rate, now a constant...
616
617                if( flags2 & 0x08000000 ) //VLack: On Mangos this is a nice spline movement code, but we never had such... Also, at this point we haven't got this flag, that's for sure, but fail just in case...
618                {
619                        int err1, err2; err2=0; err1=10/err2; //FAIL please with divide by zero :)
620                }
621        }
622        else //----------------------------------- No UPDATEFLAG_LIVING -----------------------------------
623        {
624                if( flags & UPDATEFLAG_POSITION ) //0x0100
625                {
626                        *data << uint8( 0 ); //some say it is like parent guid ?
627                        *data << (float)m_position.x;
628                        *data << (float)m_position.y;
629                        *data << (float)m_position.z;
630                        *data << (float)m_position.x;
631                        *data << (float)m_position.y;
632                        *data << (float)m_position.z;
633                        *data << (float)m_position.o;
634
635                        if (m_objectTypeId == TYPEID_CORPSE)
636                                *data << (float)m_position.o; //VLack: repeat the orientation!
637                        else
638                                *data << (float)0;
639                }
640                else if (flags & UPDATEFLAG_HAS_POSITION) //0x40
641                {
642                        if(flags & UPDATEFLAG_TRANSPORT && m_uint32Values[GAMEOBJECT_BYTES_1]==GAMEOBJECT_TYPE_MO_TRANSPORT)
643                        {
644                                *data << (float)0;
645                                *data << (float)0;
646                                *data << (float)0;
647                        }
648                        else
649                        {
650                                *data << (float)m_position.x;
651                                *data << (float)m_position.y;
652                                *data << (float)m_position.z;
653                        }
654                        *data << (float)m_position.o;
655                }
656        }
657
658
659        if( flags & UPDATEFLAG_LOWGUID ) //0x08
660                *data << GetUInt32Value(OBJECT_FIELD_GUID);
661
662        if( flags & UPDATEFLAG_HIGHGUID ) //0x10
663                *data << GetUInt32Value(OBJECT_FIELD_GUID+1);
664
665        if( flags & UPDATEFLAG_HAS_TARGET ) //0x04
666                FastGUIDPack(*data, GetUInt64Value(UNIT_FIELD_TARGET)); //some compressed GUID
667
668
669        if( flags & UPDATEFLAG_TRANSPORT ) //0x2
670        {
671                if(target)
672                {
673                        /*int32 m_time = TimeStamp() - target->GetSession()->m_clientTimeDelay;
674                        *data << m_time;*/
675                        *data << getMSTime();
676                }
677                else
678                        *data << getMSTime();
679        }
680        if( flags & UPDATEFLAG_VEHICLE ) //0x80
681        {
682                *data << (uint32)0; //Vehicle ID
683                *data << (uint32)0; //Facing
684        }
685
686        if( flags & UPDATEFLAG_ROTATION ) //0x0200
687        {
688                if( IsGameObject() )
689                        *data << static_cast< GameObject* >( this )->m_rotation;
690                else
691                        *data << (uint64)0; //?
692        }
693}
694
695
696//=======================================================================================
697//  Creates an update block with the values of this object as
698//  determined by the updateMask.
699//=======================================================================================
700void Object::_BuildValuesUpdate(ByteBuffer * data, UpdateMask *updateMask, Player* target)
701{
702        bool activate_quest_object = false;
703        bool reset = false;
704        uint32 oldflags = 0;
705
706        if(updateMask->GetBit(OBJECT_FIELD_GUID) && target)        // We're creating.
707        {
708                Creature * pThis = static_cast<Creature*>(this);
709                if(GetTypeId() == TYPEID_UNIT && pThis->Tagged && (pThis->loot.gold || pThis->loot.items.size()))
710                {
711                        // Let's see if we're the tagger or not.
712                        oldflags = m_uint32Values[UNIT_DYNAMIC_FLAGS];
713                        uint32 Flags = m_uint32Values[UNIT_DYNAMIC_FLAGS];
714                        uint32 oldFlags = 0;
715
716                        if(pThis->TaggerGuid == target->GetGUID())
717                        {
718                                // Our target is our tagger.
719                                oldFlags = U_DYN_FLAG_TAGGED_BY_OTHER;
720
721                                if(Flags & U_DYN_FLAG_TAGGED_BY_OTHER)
722                                        Flags &= ~oldFlags;
723
724                                if( !(Flags & U_DYN_FLAG_LOOTABLE) && pThis->HasLootForPlayer( target ) )
725                                        Flags |= U_DYN_FLAG_LOOTABLE;
726                        }
727                        else
728                        {
729                                // Target is not the tagger.
730                                oldFlags = U_DYN_FLAG_LOOTABLE;
731
732                                if(!(Flags & U_DYN_FLAG_TAGGED_BY_OTHER))
733                                        Flags |= U_DYN_FLAG_TAGGED_BY_OTHER;
734
735                                if(Flags & U_DYN_FLAG_LOOTABLE)
736                                        Flags &= ~oldFlags;
737                        }
738
739                        m_uint32Values[UNIT_DYNAMIC_FLAGS] = Flags;
740
741                        updateMask->SetBit(UNIT_DYNAMIC_FLAGS);
742
743                        reset = true;
744                }
745
746                if(target && GetTypeId() == TYPEID_GAMEOBJECT)
747                {
748                        GameObject *go = ((GameObject*)this);
749                        QuestLogEntry *qle;
750                        GameObjectInfo *info;
751
752                        if ( go )
753                        {
754                                if( go->HasQuests() )
755                                {
756                                        std::list<QuestRelation *>::iterator itr;
757                                        for( itr = go->QuestsBegin(); itr != go->QuestsEnd(); ++itr ) {
758                                                QuestRelation * qr = (*itr);
759                                                if( qr != NULL )
760                                                {
761                                                        Quest * qst = qr->qst;
762                                                        if( qst != NULL )
763                                                        {
764                                                                if(             ( qr->type & QUESTGIVER_QUEST_START && !target->HasQuest(qst->id) ) 
765                                                                        ||      ( qr->type & QUESTGIVER_QUEST_END && target->HasQuest(qst->id) )
766                                                                        )
767                                                                {
768                                                                        activate_quest_object = true;
769                                                                        break;
770                                                                }
771                                                        }
772                                                }
773                                        }
774                                }
775                                else
776                                {
777                                        info = go->GetInfo();
778                                        if( info && ( info->goMap.size() || info->itemMap.size() ) )
779                                        {
780                                                for( GameObjectGOMap::iterator itr = go->GetInfo()->goMap.begin(); itr != go->GetInfo()->goMap.end(); ++itr )
781                                                {
782                                                        qle = target->GetQuestLogForEntry( itr->first->id );
783                                                        if( qle != NULL )
784                                                        {
785                                                                if( qle->GetQuest()->count_required_mob == 0 )
786                                                                        continue;
787                                                                for( uint32 i = 0; i < 4; ++i )
788                                                                {
789                                                                        if( qle->GetQuest()->required_mob[i] == static_cast<int32>( go->GetEntry() ) && qle->GetMobCount(i) < qle->GetQuest()->required_mobcount[i])
790                                                                        {
791                                                                                activate_quest_object = true;
792                                                                                break;
793                                                                        }
794                                                                }
795                                                                if(activate_quest_object)
796                                                                        break;
797                                                        }
798                                                }
799
800                                                if(!activate_quest_object)
801                                                {
802                                                        for(GameObjectItemMap::iterator itr = go->GetInfo()->itemMap.begin();
803                                                                itr != go->GetInfo()->itemMap.end();
804                                                                ++itr)
805                                                        {
806                                                                for(std::map<uint32, uint32>::iterator it2 = itr->second.begin();
807                                                                        it2 != itr->second.end();
808                                                                        ++it2)
809                                                                {
810                                                                        if((qle = target->GetQuestLogForEntry(itr->first->id)) != 0)
811                                                                        {
812                                                                                if(target->GetItemInterface()->GetItemCount(it2->first) < it2->second)
813                                                                                {
814                                                                                        activate_quest_object = true;
815                                                                                        break;
816                                                                                }
817                                                                        }
818                                                                }
819                                                                if(activate_quest_object)
820                                                                        break;
821                                                        }
822                                                }
823                                        }
824                                }
825                        }
826                }
827        }
828
829
830        if(activate_quest_object)
831        {
832                oldflags = m_uint32Values[GAMEOBJECT_DYNAMIC];
833                if(!updateMask->GetBit(GAMEOBJECT_DYNAMIC))
834                        updateMask->SetBit(GAMEOBJECT_DYNAMIC);
835                m_uint32Values[GAMEOBJECT_DYNAMIC] = 1 | 8; // 8 to show sparkles
836                reset = true;
837        }
838
839        ASSERT( updateMask && updateMask->GetCount() == m_valuesCount );
840        uint32 bc;
841        uint32 values_count;
842        if( m_valuesCount > ( 2 * 0x20 ) )//if number of blocks > 2->  unit and player+item container
843        {
844                bc = updateMask->GetUpdateBlockCount();
845                values_count = min<uint32>( bc * 32, m_valuesCount );
846
847        }
848        else
849        {
850                bc=updateMask->GetBlockCount();
851                values_count=m_valuesCount;
852        }
853
854        *data << (uint8)bc;
855        data->append( updateMask->GetMask(), bc*4 );
856
857        for( uint32 index = 0; index < values_count; index ++ )
858        {
859                if( updateMask->GetBit( index ) )
860                {
861                        *data << m_uint32Values[ index ];
862                }
863        }
864
865        if(reset)
866        {
867                switch(GetTypeId())
868                {
869                case TYPEID_UNIT:
870                        m_uint32Values[UNIT_DYNAMIC_FLAGS] = oldflags;
871                        break;
872                case TYPEID_GAMEOBJECT:
873                        m_uint32Values[GAMEOBJECT_DYNAMIC] = oldflags;
874                        break;
875                }
876        }
877}
878
879void Object::BuildHeartBeatMsg(WorldPacket *data) const
880{
881        data->Initialize(MSG_MOVE_HEARTBEAT);
882
883        *data << GetGUID();
884
885        *data << uint32(0); // flags
886//      *data << uint32(0); // mysterious value #1
887        *data << getMSTime();
888        *data << m_position;
889        *data << m_position.o;
890}
891
892WorldPacket * Object::BuildTeleportAckMsg(const LocationVector & v)
893{
894        ///////////////////////////////////////
895        //Update player on the client with TELEPORT_ACK
896        static_cast< Player* >( this )->SetPlayerStatus( TRANSFER_PENDING );
897
898        WorldPacket * data = new WorldPacket(MSG_MOVE_TELEPORT_ACK, 80);
899        *data << GetNewGUID();
900
901        //First 4 bytes = no idea what it is
902        *data << uint32(2); // flags
903//      *data << uint32(0); // mysterious value #1
904        *data << getMSTime();
905        *data << uint16(0);
906
907        *data << float(0);
908        *data << v;
909        *data << v.o;
910        *data << uint16(2);
911        *data << uint8(0);
912        return data;
913}
914
915bool Object::SetPosition(const LocationVector & v, bool allowPorting /* = false */)
916{
917        bool updateMap = false, result = true;
918
919        if (m_position.x != v.x || m_position.y != v.y)
920                updateMap = true;
921
922        m_position = const_cast<LocationVector&>(v);
923
924        if (!allowPorting && v.z < -500)
925        {
926                m_position.z = 500;
927                sLog.outError( "setPosition: fell through map; height ported" );
928
929                result = false;
930        }
931
932        if (IsInWorld() && updateMap)
933        {
934                m_mapMgr->ChangeObjectLocation(this);
935        }
936
937        return result;
938}
939
940bool Object::SetPosition( float newX, float newY, float newZ, float newOrientation, bool allowPorting )
941{
942        bool updateMap = false, result = true;
943
944        //It's a good idea to push through EVERY transport position change, no matter how small they are. By: VLack aka. VLsoft
945        if( GetTypeId() == TYPEID_GAMEOBJECT && static_cast<GameObject*>(this)->GetInfo()->Type == GAMEOBJECT_TYPE_TRANSPORT )
946                updateMap = true;
947
948        //if (m_position.x != newX || m_position.y != newY)
949                //updateMap = true;
950        if(m_lastMapUpdatePosition.Distance2DSq(newX, newY) > 4.0f)             /* 2.0f */
951                updateMap = true;
952
953        m_position.ChangeCoords(newX, newY, newZ, newOrientation);
954
955        if (!allowPorting && newZ < -500)
956        {
957                m_position.z = 500;
958                sLog.outError( "setPosition: fell through map; height ported" );
959
960                result = false;
961        }
962
963        if (IsInWorld() && updateMap)
964        {
965                m_lastMapUpdatePosition.ChangeCoords(newX,newY,newZ,newOrientation);
966                m_mapMgr->ChangeObjectLocation(this);
967
968                if( m_objectTypeId == TYPEID_PLAYER && static_cast< Player* >( this )->GetGroup() && static_cast< Player* >( this )->m_last_group_position.Distance2DSq(m_position) > 25.0f ) // distance of 5.0
969                {
970            static_cast< Player* >( this )->GetGroup()->HandlePartialChange( PARTY_UPDATE_FLAG_POSITION, static_cast< Player* >( this ) );
971                }
972        }
973
974        return result;
975}
976
977
978void Object::OutPacketToSet(uint16 Opcode, uint16 Len, const void * Data, bool self)
979{
980        if( self && m_objectTypeId == TYPEID_PLAYER )
981                static_cast< Player* >( this )->GetSession()->OutPacket( Opcode, Len, Data );
982
983        if( !IsInWorld() )
984                return;
985
986        std::set<Player*>::iterator itr = m_inRangePlayers.begin();
987        std::set<Player*>::iterator it_end = m_inRangePlayers.end();
988        int gm = ( m_objectTypeId == TYPEID_PLAYER ? static_cast< Player* >( this )->m_isGmInvisible : 0 );
989        for(; itr != it_end; ++itr)
990        {
991                ASSERT((*itr)->GetSession());
992                if( gm )
993                {
994                        if( (*itr)->GetSession()->GetPermissionCount() > 0 )
995                                (*itr)->GetSession()->OutPacket(Opcode, Len, Data);
996                }
997                else
998                {
999                        (*itr)->GetSession()->OutPacket(Opcode, Len, Data);
1000                }
1001        }
1002}
1003
1004void Object::SendMessageToSet(WorldPacket *data, bool bToSelf,bool myteam_only)
1005{
1006        if(bToSelf && m_objectTypeId == TYPEID_PLAYER && static_cast< Player* >( this )->GetSession())
1007        {
1008                static_cast< Player* >( this )->GetSession()->SendPacket(data);
1009        }
1010
1011        if(!IsInWorld())
1012                return;
1013
1014        std::set<Player*>::iterator itr = m_inRangePlayers.begin();
1015        std::set<Player*>::iterator it_end = m_inRangePlayers.end();
1016        bool gminvis = (m_objectTypeId == TYPEID_PLAYER ? static_cast< Player* >( this )->m_isGmInvisible : false);
1017        //Zehamster: Splitting into if/else allows us to avoid testing "gminvis==true" at each loop...
1018        //                 saving cpu cycles. Chat messages will be sent to everybody even if player is invisible.
1019        if(myteam_only)
1020        {
1021                uint32 myteam=static_cast< Player* >( this )->GetTeam();
1022                if(gminvis && data->GetOpcode()!=SMSG_MESSAGECHAT)
1023                {
1024                        for(; itr != it_end; ++itr)
1025                        {
1026                                if((*itr) && (*itr)->GetSession() && (*itr)->GetSession()->GetPermissionCount() > 0 && (*itr)->GetTeam()==myteam)
1027                                        (*itr)->GetSession()->SendPacket(data);
1028                        }
1029                }
1030                else
1031                {
1032                        for(; itr != it_end; ++itr)
1033                        {
1034                                if((*itr) && (*itr)->GetSession() && (*itr)->GetTeam()==myteam && !(*itr)->Social_IsIgnoring( GetLowGUID() ))
1035                                        (*itr)->GetSession()->SendPacket(data);
1036                        }
1037                }
1038        }
1039        else
1040        {
1041                if(gminvis && data->GetOpcode()!=SMSG_MESSAGECHAT)
1042                {
1043                        for(; itr != it_end; ++itr)
1044                        {
1045                                if((*itr) && (*itr)->GetSession() && (*itr)->GetSession()->GetPermissionCount() > 0)
1046                                        (*itr)->GetSession()->SendPacket(data);
1047                        }
1048                }
1049                else
1050                {
1051                        for(; itr != it_end; ++itr)
1052                        {
1053                                if((*itr) && (*itr)->GetSession() &&  !(m_objectTypeId == TYPEID_PLAYER && (*itr)->Social_IsIgnoring( GetLowGUID() )) )
1054                                        (*itr)->GetSession()->SendPacket(data);
1055                        }
1056                }
1057        }
1058}
1059
1060////////////////////////////////////////////////////////////////////////////
1061/// Fill the object's Update Values from a space delimitated list of values.
1062void Object::LoadValues(const char* data)
1063{
1064        // thread-safe ;) strtok is not.
1065        std::string ndata = data;
1066        std::string::size_type last_pos = 0, pos = 0;
1067        uint32 index = 0;
1068        uint32 val;
1069        do
1070        {
1071                // prevent overflow
1072                if(index >= m_valuesCount)
1073                {
1074                        break;
1075                }
1076                pos = ndata.find(" ", last_pos);
1077                val = atol(ndata.substr(last_pos, (pos-last_pos)).c_str());
1078                if(m_uint32Values[index] == 0)
1079                        m_uint32Values[index] = val;
1080                last_pos = pos+1;
1081                ++index;
1082        } while(pos != std::string::npos);
1083}
1084
1085void Object::_SetUpdateBits(UpdateMask *updateMask, Player *target) const
1086{
1087        *updateMask = m_updateMask;
1088}
1089
1090
1091void Object::_SetCreateBits(UpdateMask *updateMask, Player *target) const
1092{
1093        /*for( uint16 index = 0; index < m_valuesCount; index++ )
1094        {
1095                if(GetUInt32Value(index) != 0)
1096                        updateMask->SetBit(index);
1097        }*/
1098        for(uint32 i = 0; i < m_valuesCount; ++i)
1099                if(m_uint32Values[i] != 0)
1100                        updateMask->SetBit(i);
1101}
1102
1103void Object::AddToWorld()
1104{
1105        MapMgr *mapMgr = sInstanceMgr.GetInstance(this);
1106        if(!mapMgr)
1107                return;
1108
1109        if(this->IsPlayer())
1110        {
1111                Player *plr = static_cast< Player* >( this );
1112                if(mapMgr->pInstance != NULL && !plr->bGMTagOn)
1113                {
1114                        // Player limit?
1115                        if(mapMgr->GetMapInfo()->playerlimit && mapMgr->GetPlayerCount() >= mapMgr->GetMapInfo()->playerlimit)
1116                                return;
1117                        Group* group = plr->GetGroup();
1118                        // Player in group?
1119                        if(group == NULL && mapMgr->pInstance->m_creatorGuid == 0)
1120                                return;
1121                        // If set: Owns player the instance?
1122                        if(mapMgr->pInstance->m_creatorGuid != 0 && mapMgr->pInstance->m_creatorGuid != plr->GetLowGUID())
1123                                return;
1124
1125                        if (group != NULL) {
1126                                // Is instance empty or owns our group the instance?
1127                                if(mapMgr->pInstance->m_creatorGroup != 0 && mapMgr->pInstance->m_creatorGroup != group->GetID())
1128                                {
1129                                        // Player not in group or another group is already playing this instance.
1130                                        sChatHandler.SystemMessageToPlr(plr, "Another group is already inside this instance of the dungeon.");
1131                                        if(plr->GetSession()->GetPermissionCount() > 0)
1132                                                sChatHandler.BlueSystemMessageToPlr(plr, "Enable your GameMaster flag to ignore this rule.");
1133                                        return;
1134                                }
1135                                else if(mapMgr->pInstance->m_creatorGroup == 0)
1136                                        // Players group now "owns" the instance.
1137                                        mapMgr->pInstance->m_creatorGroup = group->GetID();
1138                        }
1139                }
1140        }
1141
1142        m_mapMgr = mapMgr;
1143        m_inQueue = true;
1144
1145        // correct incorrect instance id's
1146        m_instanceId = m_mapMgr->GetInstanceID();
1147
1148        mapMgr->AddObject(this);
1149
1150        mSemaphoreTeleport = false;
1151}
1152
1153void Object::AddToWorld(MapMgr * pMapMgr)
1154{
1155        if( !pMapMgr|| (pMapMgr->GetMapInfo()->playerlimit && this->IsPlayer() && pMapMgr->GetPlayerCount() >= pMapMgr->GetMapInfo()->playerlimit) )
1156                return; //instance add failed
1157
1158        m_mapMgr = pMapMgr;
1159        m_inQueue = true;
1160
1161        pMapMgr->AddObject(this);
1162
1163        // correct incorrect instance id's
1164        m_instanceId = pMapMgr->GetInstanceID();
1165
1166        mSemaphoreTeleport = false;
1167}
1168
1169//Unlike addtoworld it pushes it directly ignoring add pool
1170//this can only be called from the thread of mapmgr!!!
1171void Object::PushToWorld(MapMgr*mgr)
1172{
1173        if(!mgr/* || (m_mapMgr != NULL && m_mapCell != NULL) */)
1174        {
1175                Log.Debug("Object", "Invalid push to world");
1176                return; //instance add failed
1177        }
1178
1179        m_mapId=mgr->GetMapId();
1180        m_instanceId = mgr->GetInstanceID();
1181
1182        m_mapMgr = mgr;
1183        OnPrePushToWorld();
1184
1185        mgr->PushObject(this);
1186
1187        // correct incorrect instance id's
1188        mSemaphoreTeleport = false;
1189        m_inQueue = false;
1190
1191        event_Relocate();
1192
1193        // call virtual function to handle stuff.. :P
1194        OnPushToWorld();
1195}
1196
1197//! Remove object from world
1198void Object::RemoveFromWorld(bool free_guid)
1199{
1200        ASSERT(m_mapMgr);
1201        MapMgr * m = m_mapMgr;
1202        m_mapMgr = NULL;
1203
1204        mSemaphoreTeleport = true;
1205
1206        m->RemoveObject(this, free_guid);
1207
1208        // update our event holder
1209        event_Relocate();
1210}
1211
1212
1213
1214//! Set uint32 property
1215void Object::SetUInt32Value( const uint32 index, const uint32 value )
1216{
1217        ASSERT( index < m_valuesCount );
1218        //! Save updating when val isn't changing.
1219        if(m_uint32Values[index] == value)
1220                return;
1221
1222        m_uint32Values[ index ] = value;
1223
1224        if(IsInWorld())
1225        {
1226                m_updateMask.SetBit( index );
1227
1228                if(!m_objectUpdated)
1229                {
1230                        m_mapMgr->ObjectUpdated(this);
1231                        m_objectUpdated = true;
1232                }
1233        }
1234
1235        //! Group update handling
1236        if(m_objectTypeId == TYPEID_PLAYER)
1237        {
1238                if(IsInWorld())
1239                {
1240                        Group* pGroup = static_cast< Player* >( this )->GetGroup();
1241                        if( pGroup != NULL )
1242                                pGroup->HandleUpdateFieldChange( index, static_cast< Player* >( this ) );
1243                }
1244
1245#ifdef OPTIMIZED_PLAYER_SAVING
1246                switch(index)
1247                {
1248                case UNIT_FIELD_LEVEL:
1249                case PLAYER_XP:
1250                        static_cast< Player* >( this )->save_LevelXP();
1251                        break;
1252
1253                case PLAYER_FIELD_COINAGE:
1254                        static_cast< Player* >( this )->save_Gold();
1255                        break;
1256                }
1257#endif
1258
1259                switch (index)
1260                {
1261                        case UNIT_FIELD_POWER1:
1262                        case UNIT_FIELD_POWER2:
1263                        case UNIT_FIELD_POWER4:
1264                        case UNIT_FIELD_POWER7:
1265                                static_cast< Unit* >( this )->SendPowerUpdate(true);
1266                                break;
1267                        default:
1268                                break;
1269                }
1270        }
1271        else if(m_objectTypeId == TYPEID_UNIT)
1272        {
1273                switch(index)
1274                {
1275                        case UNIT_FIELD_POWER1:
1276                        case UNIT_FIELD_POWER2:
1277                        case UNIT_FIELD_POWER3:
1278                        case UNIT_FIELD_POWER4:
1279                        case UNIT_FIELD_POWER7:
1280                                static_cast< Unit* >( this )->SendPowerUpdate(false);
1281                                break;
1282                        default:
1283                                break;
1284                }
1285        }
1286}
1287/*
1288//must be in %
1289void Object::ModPUInt32Value(const uint32 index, const int32 value, bool apply )
1290{
1291        ASSERT( index < m_valuesCount );
1292        int32 basevalue = (int32)m_uint32Values[ index ];
1293        if(apply)
1294                m_uint32Values[ index ] += ((basevalue*value)/100);
1295        else
1296                m_uint32Values[ index ] = (basevalue*100)/(100+value);
1297
1298        if(IsInWorld())
1299        {
1300                m_updateMask.SetBit( index );
1301
1302                if(!m_objectUpdated )
1303                {
1304                        m_mapMgr->ObjectUpdated(this);
1305                        m_objectUpdated = true;
1306                }
1307        }
1308}
1309*/
1310uint32 Object::GetModPUInt32Value(const uint32 index, const int32 value)
1311{
1312        ASSERT( index < m_valuesCount );
1313        int32 basevalue = (int32)m_uint32Values[ index ];
1314        return ((basevalue*value)/100);
1315}
1316
1317void Object::ModUnsigned32Value(uint32 index, int32 mod)
1318{
1319        ASSERT( index < m_valuesCount );
1320        if(mod == 0)
1321                return;
1322
1323        m_uint32Values[ index ] += mod;
1324        if( (int32)m_uint32Values[index] < 0 )
1325                m_uint32Values[index] = 0;
1326
1327        if(IsInWorld())
1328        {
1329                m_updateMask.SetBit( index );
1330
1331                if(!m_objectUpdated)
1332                {
1333                        m_mapMgr->ObjectUpdated(this);
1334                        m_objectUpdated = true;
1335                }
1336        }
1337
1338        if(m_objectTypeId == TYPEID_PLAYER)
1339        {
1340#ifdef OPTIMIZED_PLAYER_SAVING
1341                switch(index)
1342                {
1343                case UNIT_FIELD_LEVEL:
1344                case PLAYER_XP:
1345                        static_cast< Player* >( this )->save_LevelXP();
1346                        break;
1347
1348                case PLAYER_FIELD_COINAGE:
1349                        static_cast< Player* >( this )->save_Gold();
1350                        break;
1351                }
1352#endif
1353
1354                switch (index)
1355                {
1356                        case UNIT_FIELD_POWER1:
1357                        case UNIT_FIELD_POWER2:
1358                        case UNIT_FIELD_POWER4:
1359                        case UNIT_FIELD_POWER7:
1360                                static_cast< Unit* >( this )->SendPowerUpdate(true);
1361                                break;
1362                        default:
1363                                break;
1364                }
1365        }
1366        else if(m_objectTypeId == TYPEID_UNIT)
1367        {
1368                switch(index)
1369                {
1370                        case UNIT_FIELD_POWER1:
1371                        case UNIT_FIELD_POWER2:
1372                        case UNIT_FIELD_POWER3:
1373                        case UNIT_FIELD_POWER4:
1374                        case UNIT_FIELD_POWER7:
1375                                static_cast< Unit* >( this )->SendPowerUpdate(false);
1376                                break;
1377                        default:
1378                                break;
1379                }
1380        }
1381}
1382
1383void Object::ModSignedInt32Value(uint32 index, int32 value )
1384{
1385        ASSERT( index < m_valuesCount );
1386        if(value == 0)
1387                return;
1388
1389        m_uint32Values[ index ] += value;
1390        if(IsInWorld())
1391        {
1392                m_updateMask.SetBit( index );
1393
1394                if(!m_objectUpdated)
1395                {
1396                        m_mapMgr->ObjectUpdated(this);
1397                        m_objectUpdated = true;
1398                }
1399        }
1400
1401        if(m_objectTypeId == TYPEID_PLAYER)
1402        {
1403#ifdef OPTIMIZED_PLAYER_SAVING
1404                switch(index)
1405                {
1406                case UNIT_FIELD_LEVEL:
1407                case PLAYER_XP:
1408                        static_cast< Player* >( this )->save_LevelXP();
1409                        break;
1410
1411                case PLAYER_FIELD_COINAGE:
1412                        static_cast< Player* >( this )->save_Gold();
1413                        break;
1414                }
1415#endif
1416        }
1417}
1418
1419void Object::ModFloatValue(const uint32 index, const float value )
1420{
1421        ASSERT( index < m_valuesCount );
1422        m_floatValues[ index ] += value;
1423
1424        if(IsInWorld())
1425        {
1426                m_updateMask.SetBit( index );
1427
1428                if(!m_objectUpdated)
1429                {
1430                        m_mapMgr->ObjectUpdated(this);
1431                        m_objectUpdated = true;
1432                }
1433        }
1434}
1435void Object::ModFloatValueByPCT( const uint32 index, int32 byPct )
1436{
1437        ASSERT( index < m_valuesCount );
1438        if( byPct > 0 )
1439                m_floatValues[ index ] *= 1.0f + float( byPct ) / 100.0f;
1440        else
1441                m_floatValues[ index ] /= 1.0f + float( -byPct ) / 100.0f;
1442
1443
1444        if( IsInWorld() )
1445        {
1446                m_updateMask.SetBit( index );
1447
1448                if( !m_objectUpdated )
1449                {
1450                        m_mapMgr->ObjectUpdated( this );
1451                        m_objectUpdated = true;
1452                }
1453        }
1454}
1455
1456//! Set uint64 property
1457void Object::SetUInt64Value( const uint32 index, const uint64 value )
1458{
1459        assert( index + 1 < m_valuesCount );
1460#ifndef USING_BIG_ENDIAN
1461        if(m_uint32Values[index] == GUID_LOPART(value) && m_uint32Values[index+1] == GUID_HIPART(value))
1462                return;
1463
1464        m_uint32Values[ index ] = *((uint32*)&value);
1465        m_uint32Values[ index + 1 ] = *(((uint32*)&value) + 1);
1466#else
1467        m_uint32Values[index] = value & 0xffffffff;
1468        m_uint32Values[index+1] = (value >> 32) & 0xffffffff;
1469#endif
1470
1471        if(IsInWorld())
1472        {
1473                m_updateMask.SetBit( index );
1474                m_updateMask.SetBit( index + 1 );
1475
1476                if(!m_objectUpdated)
1477                {
1478                        m_mapMgr->ObjectUpdated(this);
1479                        m_objectUpdated = true;
1480                }
1481        }
1482}
1483
1484//! Set float property
1485void Object::SetFloatValue( const uint32 index, const float value )
1486{
1487        ASSERT( index < m_valuesCount );
1488        if(m_floatValues[index] == value)
1489                return;
1490
1491        m_floatValues[ index ] = value;
1492
1493        if(IsInWorld())
1494        {
1495                m_updateMask.SetBit( index );
1496
1497                if(!m_objectUpdated)
1498                {
1499                        m_mapMgr->ObjectUpdated(this);
1500                        m_objectUpdated = true;
1501                }
1502        }
1503}
1504
1505
1506void Object::SetFlag( const uint32 index, uint32 newFlag )
1507{
1508        ASSERT( index < m_valuesCount );
1509
1510        //no change -> no update
1511        if((m_uint32Values[ index ] & newFlag)==newFlag)
1512                return;
1513
1514        m_uint32Values[ index ] |= newFlag;
1515
1516        if(IsInWorld())
1517        {
1518                m_updateMask.SetBit( index );
1519
1520                if(!m_objectUpdated)
1521                {
1522                        m_mapMgr->ObjectUpdated(this);
1523                        m_objectUpdated = true;
1524                }
1525        }
1526}
1527
1528
1529void Object::RemoveFlag( const uint32 index, uint32 oldFlag )
1530{
1531        ASSERT( index < m_valuesCount );
1532
1533        //no change -> no update
1534        if((m_uint32Values[ index ] & oldFlag)==0)
1535                return;
1536
1537        m_uint32Values[ index ] &= ~oldFlag;
1538
1539        if(IsInWorld())
1540        {
1541                m_updateMask.SetBit( index );
1542
1543                if(!m_objectUpdated)
1544                {
1545                        m_mapMgr->ObjectUpdated(this);
1546                        m_objectUpdated = true;
1547                }
1548        }
1549}
1550
1551////////////////////////////////////////////////////////////
1552
1553float Object::CalcDistance(Object *Ob)
1554{
1555        ASSERT(Ob != NULL);
1556        return CalcDistance(this->GetPositionX(), this->GetPositionY(), this->GetPositionZ(), Ob->GetPositionX(), Ob->GetPositionY(), Ob->GetPositionZ());
1557}
1558float Object::CalcDistance(float ObX, float ObY, float ObZ)
1559{
1560        return CalcDistance(this->GetPositionX(), this->GetPositionY(), this->GetPositionZ(), ObX, ObY, ObZ);
1561}
1562float Object::CalcDistance(Object *Oa, Object *Ob)
1563{
1564        ASSERT(Oa != NULL);
1565        ASSERT(Ob != NULL);
1566        return CalcDistance(Oa->GetPositionX(), Oa->GetPositionY(), Oa->GetPositionZ(), Ob->GetPositionX(), Ob->GetPositionY(), Ob->GetPositionZ());
1567}
1568float Object::CalcDistance(Object *Oa, float ObX, float ObY, float ObZ)
1569{
1570        ASSERT(Oa != NULL);
1571        return CalcDistance(Oa->GetPositionX(), Oa->GetPositionY(), Oa->GetPositionZ(), ObX, ObY, ObZ);
1572}
1573
1574float Object::CalcDistance(float OaX, float OaY, float OaZ, float ObX, float ObY, float ObZ)
1575{
1576        float xdest = OaX - ObX;
1577        float ydest = OaY - ObY;
1578        float zdest = OaZ - ObZ;
1579        return sqrtf(zdest*zdest + ydest*ydest + xdest*xdest);
1580}
1581
1582bool Object::IsWithinDistInMap(Object* obj, const float dist2compare) const
1583{
1584        ASSERT(obj != NULL);
1585        float xdest = this->GetPositionX() - obj->GetPositionX();
1586        float ydest = this->GetPositionY() - obj->GetPositionY();
1587        float zdest = this->GetPositionZ() - obj->GetPositionZ();
1588        return sqrtf(zdest*zdest + ydest*ydest + xdest*xdest) <= dist2compare;
1589}
1590
1591bool Object::IsWithinLOSInMap(Object* obj)
1592{
1593        ASSERT(obj != NULL);
1594    if (!IsInMap(obj)) return false;
1595        LocationVector location;
1596    location = obj->GetPosition();
1597    return IsWithinLOS(location );
1598}
1599
1600bool Object::IsWithinLOS( LocationVector location )
1601{
1602    LocationVector location2;
1603    location2 = GetPosition();
1604
1605        if (sWorld.Collision) {
1606                return CollideInterface.CheckLOS(GetMapId(), location2.x, location2.y, location2.z+2.0f, location.x, location.y, location.z+2.0f);
1607        } else {
1608                return true;
1609        }
1610}
1611
1612
1613float Object::calcAngle( float Position1X, float Position1Y, float Position2X, float Position2Y )
1614{
1615        float dx = Position2X-Position1X;
1616        float dy = Position2Y-Position1Y;
1617        double angle=0.0f;
1618
1619        // Calculate angle
1620        if (dx == 0.0)
1621        {
1622                if (dy == 0.0)
1623                        angle = 0.0;
1624                else if (dy > 0.0)
1625                        angle = M_PI * 0.5 /* / 2 */;
1626                else
1627                        angle = M_PI * 3.0 * 0.5/* / 2 */;
1628        }
1629        else if (dy == 0.0)
1630        {
1631                if (dx > 0.0)
1632                        angle = 0.0;
1633                else
1634                        angle = M_PI;
1635        }
1636        else
1637        {
1638                if (dx < 0.0)
1639                        angle = atanf(dy/dx) + M_PI;
1640                else if (dy < 0.0)
1641                        angle = atanf(dy/dx) + (2*M_PI);
1642                else
1643                        angle = atanf(dy/dx);
1644        }
1645
1646        // Convert to degrees
1647        angle = angle * float(180 / M_PI);
1648
1649        // Return
1650        return float(angle);
1651}
1652
1653float Object::calcRadAngle( float Position1X, float Position1Y, float Position2X, float Position2Y )
1654{
1655        double dx = double(Position2X-Position1X);
1656        double dy = double(Position2Y-Position1Y);
1657        double angle=0.0;
1658
1659        // Calculate angle
1660        if (dx == 0.0)
1661        {
1662                if (dy == 0.0)
1663                        angle = 0.0;
1664                else if (dy > 0.0)
1665                        angle = M_PI * 0.5/*/ 2.0*/;
1666                else
1667                        angle = M_PI * 3.0 * 0.5/*/ 2.0*/;
1668        }
1669        else if (dy == 0.0)
1670        {
1671                if (dx > 0.0)
1672                        angle = 0.0;
1673                else
1674                        angle = M_PI;
1675        }
1676        else
1677        {
1678                if (dx < 0.0)
1679                        angle = atan(dy/dx) + M_PI;
1680                else if (dy < 0.0)
1681                        angle = atan(dy/dx) + (2*M_PI);
1682                else
1683                        angle = atan(dy/dx);
1684        }
1685
1686        // Return
1687        return float(angle);
1688}
1689
1690float Object::getEasyAngle( float angle )
1691{
1692        while ( angle < 0 ) {
1693                angle = angle + 360;
1694        }
1695        while ( angle >= 360 ) {
1696                angle = angle - 360;
1697        }
1698        return angle;
1699}
1700
1701bool Object::inArc(float Position1X, float Position1Y, float FOV, float Orientation, float Position2X, float Position2Y )
1702{
1703        float angle = calcAngle( Position1X, Position1Y, Position2X, Position2Y );
1704        float lborder = getEasyAngle( ( Orientation - (FOV*0.5f/*/2*/) ) );
1705        float rborder = getEasyAngle( ( Orientation + (FOV*0.5f/*/2*/) ) );
1706        //sLog.outDebug("Orientation: %f Angle: %f LeftBorder: %f RightBorder %f",Orientation,angle,lborder,rborder);
1707        if(((angle >= lborder) && (angle <= rborder)) || ((lborder > rborder) && ((angle < rborder) || (angle > lborder))))
1708        {
1709                return true;
1710        }
1711        else
1712        {
1713                return false;
1714        }
1715}
1716
1717bool Object::isInFront(Object* target)
1718{
1719        // check if we facing something ( is the object within a 180 degree slice of our positive y axis )
1720
1721    double x = target->GetPositionX() - m_position.x;
1722    double y = target->GetPositionY() - m_position.y;
1723
1724    double angle = atan2( y, x );
1725    angle = ( angle >= 0.0 ) ? angle : 2.0 * M_PI + angle;
1726        angle -= m_position.o;
1727
1728    while( angle > M_PI)
1729        angle -= 2.0 * M_PI;
1730
1731    while(angle < -M_PI)
1732        angle += 2.0 * M_PI;
1733
1734        // replace M_PI in the two lines below to reduce or increase angle
1735
1736    double left = -1.0 * ( M_PI / 2.0 );
1737    double right = ( M_PI / 2.0 );
1738
1739    return( ( angle >= left ) && ( angle <= right ) );
1740}
1741
1742bool Object::isInBack(Object* target)
1743{
1744        // check if we are behind something ( is the object within a 180 degree slice of our negative y axis )
1745
1746    double x = m_position.x - target->GetPositionX();
1747    double y = m_position.y - target->GetPositionY();
1748
1749    double angle = atan2( y, x );
1750    angle = ( angle >= 0.0 ) ? angle : 2.0 * M_PI + angle;
1751
1752        // if we are a unit and have a UNIT_FIELD_TARGET then we are always facing them
1753        if( m_objectTypeId == TYPEID_UNIT && m_uint32Values[UNIT_FIELD_TARGET] != 0 && static_cast< Unit* >( this )->GetAIInterface()->GetNextTarget() )
1754        {
1755                Unit* pTarget = static_cast< Unit* >( this )->GetAIInterface()->GetNextTarget();
1756                angle -= double( Object::calcRadAngle( target->m_position.x, target->m_position.y, pTarget->m_position.x, pTarget->m_position.y ) );
1757        }
1758        else
1759                angle -= target->GetOrientation();
1760
1761    while( angle > M_PI)
1762        angle -= 2.0 * M_PI;
1763
1764    while(angle < -M_PI)
1765        angle += 2.0 * M_PI;
1766
1767        // replace M_H_PI in the two lines below to reduce or increase angle
1768
1769    double left = -1.0 * ( M_H_PI / 2.0 );
1770    double right = ( M_H_PI / 2.0 );
1771
1772    return( ( angle <= left ) && ( angle >= right ) );
1773}
1774bool Object::isInArc(Object* target , float angle) // angle in degrees
1775{
1776    return inArc( GetPositionX() , GetPositionY() , angle , GetOrientation() , target->GetPositionX() , target->GetPositionY() );
1777}
1778
1779bool Object::HasInArc( float degrees, Object* target )
1780{
1781        return isInArc(target, degrees);
1782}
1783
1784bool Object::isInRange(Object* target, float range)
1785{
1786  if ( !this->IsInWorld() || !target ) return false;
1787        float dist = CalcDistance( target );
1788        return( dist <= range );
1789}
1790
1791bool Object::IsPet()
1792{
1793    if (this->GetTypeId() != TYPEID_UNIT || !m_uint32Values || !this->IsCreature())
1794                return false;
1795
1796    if (m_uint32Values[UNIT_FIELD_CREATEDBY] == 0 || m_uint32Values[UNIT_FIELD_SUMMONEDBY] == 0)
1797        return false;
1798    if (static_cast< Creature * >(this)->IsPet())
1799        return true;
1800
1801        return false;
1802}
1803
1804void Object::_setFaction()
1805{
1806        FactionTemplateDBC* factT = NULL;
1807
1808        if(GetTypeId() == TYPEID_UNIT || GetTypeId() == TYPEID_PLAYER)
1809        {
1810                factT = dbcFactionTemplate.LookupEntry(GetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE));
1811                if( !factT )
1812                        sLog.outDetail("Unit does not have a valid faction. It will make him act stupid in world. Don't blame us, blame yourself for not checking :P, faction %u set to entry %u",GetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE),GetUInt32Value(OBJECT_FIELD_ENTRY) );
1813        }
1814        else
1815        if(GetTypeId() == TYPEID_GAMEOBJECT)
1816        {
1817                factT = dbcFactionTemplate.LookupEntry(GetUInt32Value(GAMEOBJECT_FACTION));
1818                if( !factT )
1819                        sLog.outDetail("Game Object does not have a valid faction. It will make him act stupid in world. Don't blame us, blame yourself for not checking :P, faction %u set to entry %u",GetUInt32Value(GAMEOBJECT_FACTION),GetUInt32Value(OBJECT_FIELD_ENTRY) );
1820        }
1821
1822        if(!factT)
1823        {
1824                factT = dbcFactionTemplate.LookupRow( 0 );
1825                //this is causing a lot of crashes cause people have shitty dbs
1826//              return;
1827        }
1828        m_faction = factT;
1829        m_factionDBC = dbcFaction.LookupEntry(factT->Faction);
1830        if( !m_factionDBC )
1831                m_factionDBC = dbcFaction.LookupRow( 0 );
1832}
1833
1834void Object::UpdateOppFactionSet()
1835{
1836        m_oppFactsInRange.clear();
1837        this->AquireInrangeLock(); //make sure to release lock before exit function !
1838        for(Object::InRangeSet::iterator i = GetInRangeSetBegin(); i != GetInRangeSetEnd(); ++i)
1839        {
1840                if (((*i)->GetTypeId() == TYPEID_UNIT) || ((*i)->GetTypeId() == TYPEID_PLAYER) || ((*i)->GetTypeId() == TYPEID_GAMEOBJECT))
1841                {
1842                        if (isHostile(this, (*i)))
1843                        {
1844                                if(!(*i)->IsInRangeOppFactSet(this))
1845                                        (*i)->m_oppFactsInRange.insert(this);
1846                                if (!IsInRangeOppFactSet((*i)))
1847                                        m_oppFactsInRange.insert((*i));
1848
1849                        }
1850                        else
1851                        {
1852                                if((*i)->IsInRangeOppFactSet(this))
1853                                        (*i)->m_oppFactsInRange.erase(this);
1854                                if (IsInRangeOppFactSet((*i)))
1855                                        m_oppFactsInRange.erase((*i));
1856                        }
1857                }
1858        }
1859        this->ReleaseInrangeLock();
1860}
1861
1862void Object::UpdateSameFactionSet()
1863{
1864        m_sameFactsInRange.clear();
1865        this->AquireInrangeLock(); //make sure to release lock before exit function !
1866        for(Object::InRangeSet::iterator i = GetInRangeSetBegin(); i != GetInRangeSetEnd(); ++i)
1867        {
1868                if (((*i)->GetTypeId() == TYPEID_UNIT) || ((*i)->GetTypeId() == TYPEID_PLAYER) || ((*i)->GetTypeId() == TYPEID_GAMEOBJECT))
1869                {
1870                        if (isFriendly(this, (*i)))
1871                        {
1872                                if(!(*i)->IsInRangeSameFactSet(this))
1873                                        (*i)->m_sameFactsInRange.insert(this);
1874                                if (!IsInRangeOppFactSet((*i)))
1875                                        m_sameFactsInRange.insert((*i));
1876
1877                        }
1878                        else
1879                        {
1880                                if((*i)->IsInRangeSameFactSet(this))
1881                                        (*i)->m_sameFactsInRange.erase(this);
1882                                if (IsInRangeSameFactSet((*i)))
1883                                        m_sameFactsInRange.erase((*i));
1884                        }
1885                }
1886        }
1887        this->ReleaseInrangeLock();
1888}
1889
1890void Object::EventSetUInt32Value(uint32 index, uint32 value)
1891{
1892        SetUInt32Value(index,value);
1893}
1894
1895void Object::DealDamage(Unit *pVictim, uint32 damage, uint32 targetEvent, uint32 unitEvent, uint32 spellId, bool no_remove_auras)
1896{
1897        Player* plr = 0;
1898
1899        if( !pVictim || !pVictim->isAlive() || !pVictim->IsInWorld() || !IsInWorld() )
1900                return;
1901        if( pVictim->GetTypeId() == TYPEID_PLAYER && static_cast< Player* >( pVictim )->GodModeCheat == true )
1902                return;
1903        if( pVictim->IsSpiritHealer() )
1904                return;
1905        if (this->IsPlayer())
1906                plr = static_cast<Player* >(this);
1907
1908        if( damage > 14000 && this != pVictim && this->IsPlayer() && !static_cast< Player* >(this)->GetSession()->HasPermissions() && sWorld.m_limits.enable )
1909        {
1910                if(spellId && sWorld.m_limits.spellDamageCap > 0)
1911                {
1912                        if((damage > sWorld.m_limits.spellDamageCap) && this!=pVictim && this->IsPlayer() && !((Player*)this)->GetSession()->HasPermissions())
1913                        {
1914                                SpellEntry* spellInfo = dbcSpell.LookupEntryForced(spellId);
1915                                char dmglog[256];
1916                                snprintf(dmglog, 256, "Dealt %u damage with spell %u ( %s )", damage, spellId, (spellInfo != NULL) ? spellInfo->Name : "ERROR (NULL SPELL)");
1917                                sCheatLog.writefromsession(((Player*)this)->GetSession(),dmglog);
1918                                if(sWorld.m_limits.broadcast) // send info to online GM
1919                                {
1920                                        string gm_ann = MSG_COLOR_GREEN;
1921                                        gm_ann += "|Hplayer:";
1922                                        gm_ann += ((Player*)this)->GetName();
1923                                        gm_ann += "|h[";
1924                                        gm_ann += ((Player*)this)->GetName();
1925                                        gm_ann += "]|h: ";
1926                                        gm_ann += MSG_COLOR_YELLOW;
1927                                        gm_ann += dmglog;
1928                                        sWorld.SendGMWorldText(gm_ann.c_str());
1929                                }
1930                                if(sWorld.m_limits.disconnect)
1931                                {
1932                                        ((Player*)this)->GetSession()->Disconnect();
1933                                }
1934                                else // no disconnect, we'll just set it to the cap. it's been logged and gms have been notified (if configured)
1935                                {
1936                                        damage = sWorld.m_limits.spellDamageCap;
1937                                }
1938                        }
1939                }
1940                else // !spellId
1941                {
1942                        if((sWorld.m_limits.autoattackDamageCap > 0) && (damage > sWorld.m_limits.autoattackDamageCap) && (this!=pVictim) && (this->IsPlayer()) && !((Player*)this)->GetSession()->HasPermissions())
1943                        {
1944                                char dmglog[64];
1945                                snprintf(dmglog, 64, "Dealt %u damage with Auto Attack", damage);
1946                                sCheatLog.writefromsession(((Player*)this)->GetSession(),dmglog);
1947                                if(sWorld.m_limits.broadcast) // send info to GM
1948                                {
1949                                        string gm_ann = MSG_COLOR_GREEN;
1950                                        gm_ann += "|Hplayer:";
1951                                        gm_ann += ((Player*)this)->GetName();
1952                                        gm_ann += "|h[";
1953                                        gm_ann += ((Player*)this)->GetName();
1954                                        gm_ann += "]|h: ";
1955                                        gm_ann += MSG_COLOR_YELLOW;
1956                                        gm_ann += dmglog;
1957                                        sWorld.SendGMWorldText(gm_ann.c_str());
1958                                }
1959                                if(sWorld.m_limits.disconnect)
1960                                {
1961                                        ((Player*)this)->GetSession()->Disconnect();
1962                                }
1963                                else // no disconnect, we'll just set it to the cap. it's been logged and gms have been notified (if configured)
1964                                {
1965                                        damage = sWorld.m_limits.autoattackDamageCap;
1966                                }
1967                        }
1968                }
1969        }
1970        if( this->IsUnit() && pVictim->IsUnit() && pVictim != this )
1971        {
1972                // Set our attack target to the victim.
1973                static_cast< Unit* >( this )->CombatStatus.OnDamageDealt( pVictim );
1974        }
1975
1976        if( pVictim->GetStandState() )//not standing-> standup
1977        {
1978                pVictim->SetStandState( STANDSTATE_STAND );//probably mobs also must standup
1979        }
1980
1981/////////////////////////////////////////////////////// PvP flagging on attack ///////////////////////////////////////////////
1982{
1983    // Player we are attacking, or the owner of totem/pet/etc
1984    Player *pOwner = GetPlayerOwner( static_cast< Object* >( pVictim ) );
1985
1986    // This is the player or the player controlling the totem/pet/summon
1987    Player *pAttacker = GetPlayerOwner( this );
1988
1989    // We identified both the attacker and the victim as possible PvP combatants, if we are not dueling we will flag the attacker
1990    if( pOwner != NULL && pAttacker != NULL && pOwner != pAttacker && pOwner != pAttacker->DuelingWith ){
1991        if( !pAttacker->IsPvPFlagged() ){
1992            pAttacker->PvPToggle();
1993        }
1994        pAttacker->AggroPvPGuards();
1995    }
1996
1997    // PvP NPCs will flag the player when attacking them
1998    if( pVictim->IsCreature() && pVictim->IsPvPFlagged() && pAttacker != NULL ){
1999        if( !pAttacker->IsPvPFlagged() ){
2000            pAttacker->PvPToggle();
2001        }
2002        pAttacker->AggroPvPGuards();
2003    }
2004
2005}
2006///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2007        if(!no_remove_auras)
2008        {
2009                //zack 2007 04 24 : root should not remove self (and also other unknown spells)
2010                if(spellId)
2011                {
2012                        pVictim->RemoveAurasByInterruptFlagButSkip(AURA_INTERRUPT_ON_ANY_DAMAGE_TAKEN,spellId);
2013                        if(Rand(35.0f))
2014                                pVictim->RemoveAurasByInterruptFlagButSkip(AURA_INTERRUPT_ON_UNUSED2,spellId);
2015                }
2016                else
2017                {
2018                        pVictim->RemoveAurasByInterruptFlag(AURA_INTERRUPT_ON_ANY_DAMAGE_TAKEN);
2019                        if(Rand(35.0f))
2020                                pVictim->RemoveAurasByInterruptFlag(AURA_INTERRUPT_ON_UNUSED2);
2021                }
2022        }
2023
2024        if(this->IsUnit())
2025        {
2026                if( pVictim->CombatStatus.IsInCombat() && pVictim->IsPlayer() )
2027                        sHookInterface.OnEnterCombat( static_cast< Player* >( pVictim ), static_cast< Unit* >( this ) );
2028
2029                if( IsPlayer() && static_cast< Player* >( this )->CombatStatus.IsInCombat() == true )
2030                        sHookInterface.OnEnterCombat( static_cast< Player* >( this ), static_cast< Player* >( this ) );
2031
2032                //the black sheep , no actually it is paladin : Ardent Defender
2033                if( static_cast< Unit* >( this )->DamageTakenPctModOnHP35 && HasFlag( UNIT_FIELD_AURASTATE , AURASTATE_FLAG_HEALTH35 ) )
2034                        damage = damage - float2int32( damage * static_cast< Unit* >( this )->DamageTakenPctModOnHP35 ) / 100 ;
2035
2036                //Mage: Fiery Payback
2037                if(pVictim->IsPlayer() && static_cast< Player* >(pVictim)->FieryPaybackModHP35 == 1)
2038                        if(pVictim->GetHealthPct() <= 35)
2039                        {
2040                                if(!pVictim->HasAura(44441))
2041                                pVictim->CastSpell(pVictim->GetGUID(), 44441, true);
2042                        }
2043                else if(pVictim->HasAura(44441))
2044                        pVictim->RemoveAllAuraById(44441);
2045               
2046                plr = 0;
2047                if(IsPet())
2048                        plr = static_cast<Pet*>(this)->GetPetOwner();
2049                else if(IsPlayer())
2050                        plr = static_cast< Player* >( this );
2051
2052                if(pVictim->GetTypeId()==TYPEID_UNIT && plr && plr->GetTypeId() == TYPEID_PLAYER) // Units can't tag..
2053                {
2054                        // Tagging
2055                        Creature *victim = static_cast<Creature*>(pVictim);
2056                        bool taggable;
2057                        if(victim->GetCreatureInfo() && victim->GetCreatureInfo()->Type == UNIT_TYPE_CRITTER || victim->IsPet())
2058                                taggable = false;
2059                        else taggable = true;
2060
2061                        if(!victim->Tagged && taggable)
2062                        {
2063                                victim->Tagged = true;
2064                                victim->TaggerGuid = plr->GetGUID();
2065
2066                                /* set loot method */
2067                                if( plr->GetGroup() != NULL )
2068                                        victim->m_lootMethod = plr->GetGroup()->GetMethod();
2069
2070                                // For new players who get a create object
2071                                uint32 Flags = pVictim->m_uint32Values[UNIT_DYNAMIC_FLAGS];
2072                                Flags |= U_DYN_FLAG_TAPPED_BY_PLAYER;
2073
2074                                pVictim->m_uint32Values[UNIT_DYNAMIC_FLAGS] |= U_DYN_FLAG_TAGGED_BY_OTHER;
2075
2076                                // Update existing players.
2077                                ByteBuffer buf(500);
2078                                ByteBuffer buf1(500);
2079
2080                                pVictim->BuildFieldUpdatePacket(&buf1, UNIT_DYNAMIC_FLAGS, Flags);
2081                                pVictim->BuildFieldUpdatePacket(&buf, UNIT_DYNAMIC_FLAGS, pVictim->m_uint32Values[UNIT_DYNAMIC_FLAGS]);
2082
2083                                // Loop inrange set, append to their update data.
2084                                for(std::set<Player*>::iterator itr = m_inRangePlayers.begin(); itr != m_inRangePlayers.end(); ++itr)
2085                                {
2086                                        if (static_cast< Player* >(plr)->InGroup())
2087                                        {
2088                                                if (static_cast< Player* >(*itr)->GetGroup() && static_cast< Player* >(plr)->GetGroup()->GetID() == static_cast< Player* >(*itr)->GetGroup()->GetID())
2089                                                {
2090                                                        (*itr)->PushUpdateData(&buf1, 1);
2091                                                }
2092                                                else
2093                                                {
2094                                                        (*itr)->PushUpdateData(&buf, 1);
2095                                                }
2096
2097                                        }
2098                                        else
2099                                        {
2100                                                (*itr)->PushUpdateData(&buf, 1);
2101                                        }
2102                                }
2103
2104                                // Update ourselves
2105                                plr->PushUpdateData(&buf1, 1);
2106
2107                        }
2108                }
2109        }
2110
2111        ///Rage
2112
2113                if( pVictim->GetPowerType() == POWER_TYPE_RAGE
2114                        && pVictim != this
2115                        && pVictim->IsPlayer())
2116                {
2117                        float val;
2118                        float level = (float)pVictim->getLevel();
2119                        float c = 0.0091107836f * level * level + 3.225598133f * level + 4.2652911f;
2120                        val = 2.5f * damage / c;
2121                        uint32 rage = pVictim->GetUInt32Value( UNIT_FIELD_POWER2 );
2122                        if( rage + float2int32( val ) > 1000 )
2123                                  val = 1000.0f - (float)pVictim->GetUInt32Value( UNIT_FIELD_POWER2 );
2124                        val *= 10.0;
2125                        pVictim->ModUnsigned32Value(UNIT_FIELD_POWER2, (int32)val);
2126                /*if( pVictim->GetPowerType() == POWER_TYPE_RAGE && pVictim != this )
2127                {
2128                float val;
2129                uint32 level = pVictim->getLevel();
2130                float conv;
2131                if( level <= PLAYER_LEVEL_CAP )
2132                        conv = DamageToRageConversionTable[ level ];
2133                else
2134                        conv = ( 2.5f * 10 ) / (0.0091107836f * level * level + 3.225598133f * level + 4.2652911f);
2135                float ragerate = sWorld.getRate(RATE_POWER2);
2136                val = damage * conv * ragerate;
2137                if( pVictim->IsPlayer() )
2138                        val *= ( 1 + ( static_cast< Player * >( pVictim )->rageFromDamageTaken / 100.0f ) );
2139                uint32 rage = pVictim->GetUInt32Value( UNIT_FIELD_POWER2 );
2140                if( rage + float2int32( val ) > 1000 )
2141                        val = 1000.0f - (float)pVictim->GetUInt32Value( UNIT_FIELD_POWER2 );
2142
2143                val *= 10.0;
2144                pVictim->ModUnsigned32Value( UNIT_FIELD_POWER2, (int32)val) ;*/
2145        }
2146
2147        if( pVictim->IsPlayer() )
2148        {
2149                Player *pThis = static_cast< Player* >(pVictim);
2150                if(pThis->cannibalize)
2151                {
2152                        sEventMgr.RemoveEvents(pVictim, EVENT_CANNIBALIZE);
2153                        pThis->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
2154                        pThis->cannibalize = false;
2155                }
2156        }
2157
2158        //* BATTLEGROUND DAMAGE COUNTER *//
2159        if( pVictim != this )
2160        {
2161                if( IsPlayer() )
2162                {
2163                        plr = static_cast< Player* >( this );
2164                }
2165                else if( IsPet() )
2166                {
2167                        plr = static_cast< Pet* >( this )->GetPetOwner();
2168                        if (plr)
2169                                if( plr != NULL && plr->GetMapMgr() == GetMapMgr() )
2170                                        plr = NULL;
2171                }
2172
2173                if( plr != NULL && plr->m_bg != NULL && plr->GetMapMgr() == GetMapMgr() )
2174                {
2175                        plr->m_bgScore.DamageDone += damage;
2176                        plr->m_bg->UpdatePvPData();
2177                }
2178        }
2179
2180        uint32 health = pVictim->GetUInt32Value(UNIT_FIELD_HEALTH );
2181
2182        /*------------------------------------ DUEL HANDLERS --------------------------*/
2183        if((pVictim->IsPlayer()) && (this->IsPlayer()) && static_cast< Player* >(pVictim)->DuelingWith == static_cast< Player* >( this ) ) //Both Players
2184        {
2185                if((health <= damage) && static_cast< Player* >( this )->DuelingWith != NULL)
2186                {
2187                        //Player in Duel and Player Victim has lost
2188                        uint32 NewHP = pVictim->GetUInt32Value(UNIT_FIELD_MAXHEALTH)/100;
2189
2190                        if(NewHP < 5)
2191                                NewHP = 5;
2192
2193                        //Set their health to 1% or 5 if 1% is lower then 5
2194                        pVictim->SetUInt32Value(UNIT_FIELD_HEALTH, NewHP);
2195                        //End Duel
2196                        static_cast< Player* >( this )->EndDuel(DUEL_WINNER_KNOCKOUT);
2197
2198                        // surrender emote
2199                        pVictim->Emote(EMOTE_ONESHOT_BEG);                      // Animation
2200
2201                        return;
2202                }
2203        }
2204
2205        if((pVictim->IsPlayer()) && (IsPet()))
2206        {
2207                if((health <= damage) && static_cast< Player* >(pVictim)->DuelingWith == static_cast<Pet*>(this)->GetPetOwner())
2208                {
2209                        Player *petOwner = static_cast<Pet*>(this)->GetPetOwner();
2210                        if(petOwner)
2211                        {
2212                                //Player in Duel and Player Victim has lost
2213                                uint32 NewHP = pVictim->GetUInt32Value(UNIT_FIELD_MAXHEALTH)/100;
2214                                if(NewHP < 5) NewHP = 5;
2215
2216                                //Set their health to 1% or 5 if 1% is lower then 5
2217                                pVictim->SetUInt32Value(UNIT_FIELD_HEALTH, NewHP);
2218                                //End Duel
2219                                petOwner->EndDuel(DUEL_WINNER_KNOCKOUT);
2220                                return;
2221                        }
2222                }
2223        }
2224        /*------------------------------------ DUEL HANDLERS END--------------------------*/
2225
2226        bool isCritter = false;
2227        uint32 highGUID = 0;
2228        uint32 lowGUID = 0;
2229        if(pVictim->GetTypeId() == TYPEID_UNIT && ((Creature*)pVictim)->GetCreatureInfo())
2230        {
2231                if(((Creature*)pVictim)->GetCreatureInfo()->Type == UNIT_TYPE_CRITTER)
2232                {
2233                        isCritter = true;
2234                }
2235        }
2236        /* -------------------------- HIT THAT CAUSES VICTIM TO DIE ---------------------------*/
2237        if ((isCritter || health <= damage) )
2238        {
2239                // If it's a training dummy then we simply set the HP to 1 instead of killing the unit
2240                if(pVictim->IsCreature() &&  (static_cast<Creature*>(pVictim))->GetProto() != NULL && (static_cast<Creature*>(pVictim))->GetProto()->isTrainingDummy ){
2241                        pVictim->SetUInt32Value( UNIT_FIELD_HEALTH, 1 );
2242                        return;
2243                }
2244
2245        // We've just killed a totem
2246        if( pVictim->IsCreature() && static_cast<Creature*>(pVictim)->IsTotem() ){
2247            Creature *pTotem = static_cast<Creature*>(pVictim);
2248           
2249            // If we have a summon then let's remove that first
2250            if(pTotem->summonPet != NULL){
2251                if( pTotem->summonPet->IsInWorld() )
2252                    pTotem->summonPet->RemoveFromWorld( false, true );
2253                else
2254                    pTotem->summonPet->SafeDelete();
2255                pTotem->summonPet = NULL;
2256            }
2257
2258            if(pTotem->IsInWorld())
2259                pTotem->RemoveFromWorld( false, true );
2260            else
2261                pTotem->SafeDelete();
2262            return;
2263        }
2264
2265        // We've killed some kind of summon
2266        if( pVictim->GetUInt64Value( UNIT_FIELD_CREATEDBY ) != 0 ){
2267            Unit *pSummoner = pVictim->GetMapMgr()->GetUnit( pVictim->GetUInt64Value( UNIT_FIELD_CREATEDBY ) );
2268
2269            if( pSummoner && pSummoner->IsInWorld() && pSummoner->IsCreature() ){
2270                Creature *pSummonerC = static_cast<Creature*>( pSummoner );
2271           
2272                // We've killed a summon summoned by a totem
2273                if( pSummonerC->IsTotem() ){
2274                    pSummoner->summonPet = NULL;
2275
2276                    // Removing the totem
2277                    if(pSummonerC->IsInWorld())
2278                      pSummonerC->RemoveFromWorld( false, true );
2279                    else
2280                      pSummonerC->SafeDelete();
2281                }
2282            }
2283
2284           
2285        }
2286
2287
2288               
2289#ifdef ENABLE_ACHIEVEMENTS
2290                // A Player has died
2291                if( pVictim->IsPlayer() )
2292                {
2293                        ((Player*)pVictim)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DEATH, 1, 0, 0);
2294                        ((Player*)pVictim)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP, pVictim->GetMapId(), 1, 0);
2295                        // A Player killed a Player
2296                        if( this->IsPlayer() )
2297                        {
2298                                ((Player*)pVictim)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER, 1, 0, 0);
2299                        }
2300                        // A Creature killed a Player
2301                        else if( this->IsCreature() )
2302                        {
2303                                ((Player*)pVictim)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE, 1, 0, 0);
2304                        }
2305                }
2306                // Player delivered a killing blow
2307                if( pVictim->IsUnit() && this->IsPlayer() )
2308                {
2309                        ((Player*)this)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILLING_BLOW, GetMapId(), 0, 0);
2310                }
2311#endif
2312                //general hook for die
2313                sHookInterface.OnPreUnitDie( static_cast< Unit* >( this ), pVictim);
2314                //warlock - seed of corruption
2315                if( IsUnit() )
2316                {
2317                        SpellEntry *killerspell;
2318                        if( spellId )
2319                                killerspell = dbcSpell.LookupEntry( spellId );
2320                        else killerspell = NULL;
2321                        pVictim->HandleProc( PROC_ON_DIE, static_cast< Unit* >( this ), killerspell );
2322                        pVictim->m_procCounter = 0;
2323                        static_cast< Unit* >( this )->HandleProc( PROC_ON_TARGET_DIE, pVictim, killerspell );
2324                        static_cast< Unit* >( this )->m_procCounter = 0;
2325                }
2326                // check if pets owner is combat participant
2327                bool owner_participe = false;
2328                if( IsPet() )
2329                {
2330                        Player* owner = static_cast<Pet*>( this )->GetPetOwner();
2331                        if( owner != NULL && pVictim->GetAIInterface()->getThreatByPtr( owner ) > 0 )
2332                                owner_participe = true;
2333                }
2334
2335                /* -------------------------------- HONOR + BATTLEGROUND CHECKS ------------------------ */
2336                //Zack : this event should occur before setting death state !
2337                plr = NULL;
2338                if( IsPlayer() )
2339                        plr = static_cast< Player* >( this );
2340                else if(IsPet())
2341                        plr = static_cast< Pet* >( this )->GetPetOwner();
2342
2343                if( plr != NULL)
2344                {
2345                        if( plr->m_bg != NULL )
2346                                plr->m_bg->HookOnUnitKill( plr, pVictim );
2347
2348                        if( pVictim->IsPlayer() )
2349                        {
2350                                if( plr->m_bg != NULL )
2351                                        plr->m_bg->HookOnPlayerKill( plr, static_cast< Player* >( pVictim ) );
2352
2353                                sHookInterface.OnKillPlayer( plr, static_cast< Player* >( pVictim ) );
2354                                bool setAurastateFlag = false;
2355                                if( plr->getLevel() >= (pVictim->getLevel() - 8) && (plr->GetGUID() != pVictim->GetGUID()) )
2356                                {
2357#ifdef ENABLE_ACHIEVEMENTS
2358                                        plr->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL_AT_AREA, plr->GetAreaID(), 1, 0);
2359                                        plr->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EARN_HONORABLE_KILL, 1, 0, 0);
2360#endif                         
2361                                        HonorHandler::OnPlayerKilledUnit(plr, pVictim);
2362                                        setAurastateFlag = true;
2363                                }
2364
2365                                if (setAurastateFlag)
2366                                {
2367                                        this->SetFlag(UNIT_FIELD_AURASTATE,AURASTATE_FLAG_LASTKILLWITHHONOR);
2368                                        if(!sEventMgr.HasEvent(this,EVENT_LASTKILLWITHHONOR_FLAG_EXPIRE))
2369                                                sEventMgr.AddEvent((Unit*)this,&Unit::EventAurastateExpire,(uint32)AURASTATE_FLAG_LASTKILLWITHHONOR,EVENT_LASTKILLWITHHONOR_FLAG_EXPIRE,20000,1,0);
2370                                        else sEventMgr.ModifyEventTimeLeft(this,EVENT_LASTKILLWITHHONOR_FLAG_EXPIRE,20000);
2371                                }
2372                        }
2373                        else
2374                        {
2375                                if (!isCritter) // REPUTATION
2376                                {
2377                                        plr->Reputation_OnKilledUnit( pVictim, false );
2378                                }
2379                        }
2380                }
2381                /* -------------------------------- HONOR + BATTLEGROUND CHECKS END------------------------ */
2382
2383                /* victim died! */
2384                if( pVictim->IsPlayer() )
2385                        static_cast< Player* >( pVictim )->KillPlayer();
2386                else
2387                {
2388                        pVictim->setDeathState( JUST_DIED );
2389                        pVictim->GetAIInterface()->HandleEvent( EVENT_LEAVECOMBAT, pVictim, 0);
2390                }
2391
2392                if( pVictim->IsPlayer() && !IsPlayer())
2393                {
2394                        static_cast< Player* >( pVictim )->DeathDurabilityLoss(0.10);
2395                }
2396
2397                /* Zone Under Attack */
2398        MapInfo * pMapInfo = WorldMapInfoStorage.LookupEntry(GetMapId());
2399        if( pMapInfo && pMapInfo->type == INSTANCE_NULL && !pVictim->IsPlayer() && !pVictim->IsPet() && ( IsPlayer() || IsPet() ) )
2400                {
2401                        // Only NPCs that bear the PvP flag can be truly representing their faction.
2402                        if( ((Creature*)pVictim)->HasFlag( UNIT_FIELD_FLAGS, UNIT_FLAG_PVP ) )
2403                        {
2404                                Player * pAttacker = NULL;
2405                                if( IsPet() )
2406                                        pAttacker = static_cast< Pet* >( this )->GetPetOwner();
2407                                else if(IsPlayer())
2408                                        pAttacker = static_cast< Player* >( this );
2409
2410                                if( pAttacker != NULL)
2411                {
2412                                    uint8 teamId = (uint8)pAttacker->GetTeam();
2413                                    if(teamId == 0) // Swap it.
2414                                            teamId = 1;
2415                                    else
2416                                            teamId = 0;
2417                                    uint32 AreaID = pVictim->GetMapMgr()->GetAreaID(pVictim->GetPositionX(), pVictim->GetPositionY());
2418                                    if(!AreaID)
2419                                            AreaID = pAttacker->GetZoneId(); // Failsafe for a shitty TerrainMgr
2420
2421                                    if(AreaID)
2422                                    {
2423                                            WorldPacket data(SMSG_ZONE_UNDER_ATTACK, 4);
2424                                            data << AreaID;
2425                                            sWorld.SendFactionMessage(&data, teamId);
2426                                    }
2427                }
2428                        }
2429                }
2430
2431                if(pVictim->GetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT) > 0)
2432                {
2433                        Spell *spl = pVictim->GetCurrentSpell();
2434                        if(spl != NULL)
2435                        {
2436                                for(int i = 0; i < 3; i++)
2437                                {
2438                                        if(spl->GetProto()->Effect[i] == SPELL_EFFECT_PERSISTENT_AREA_AURA)
2439                                        {
2440                                                DynamicObject *dObj = GetMapMgr()->GetDynamicObject(pVictim->GetUInt32Value(UNIT_FIELD_CHANNEL_OBJECT));
2441                                                if(!dObj)
2442                                                        return;
2443                                                WorldPacket data(SMSG_GAMEOBJECT_DESPAWN_ANIM, 8);
2444                                                data << dObj->GetGUID();
2445                                                dObj->SendMessageToSet(&data, false);
2446                                                dObj->Remove();
2447                                        }
2448                                }
2449                                if(spl->GetProto()->ChannelInterruptFlags == 48140) spl->cancel();
2450                        }
2451                }
2452
2453
2454                /* Stop players from casting */
2455                std::set<Player*>::iterator itr;
2456                for( itr = pVictim->GetInRangePlayerSetBegin() ; itr != pVictim->GetInRangePlayerSetEnd() ; itr ++ )
2457                {
2458                        if( (*itr)->GetCurrentSpell() != NULL)
2459                        {
2460                                if ((*itr)->GetCurrentSpell()->m_targets.m_unitTarget == pVictim->GetGUID())
2461                                        (*itr)->GetCurrentSpell()->cancel();
2462                        }
2463                }
2464                /* Stop victim from attacking */
2465                if( this->IsUnit() )
2466                        pVictim->smsg_AttackStop( static_cast< Unit* >( this ) );
2467
2468                if( pVictim->GetTypeId() == TYPEID_PLAYER )
2469                        static_cast< Player* >( pVictim )->EventAttackStop();
2470
2471                /* Set victim health to 0 */
2472                pVictim->SetUInt32Value(UNIT_FIELD_HEALTH, 0);
2473                CALL_INSTANCE_SCRIPT_EVENT( m_mapMgr, OnPlayerDeath )( TO_PLAYER( pVictim ), TO_UNIT(this) );
2474
2475                if(pVictim->IsPlayer())
2476                {
2477                        uint32 self_res_spell = 0;
2478                        if (static_cast< Player* >( pVictim )->m_bg == NULL || (static_cast< Player* >( pVictim )->m_bg != NULL && static_cast< Player* >( pVictim )->m_bg->GetType() != BATTLEGROUND_ARENA_5V5 && static_cast< Player* >( pVictim )->m_bg->GetType() != BATTLEGROUND_ARENA_3V3 && static_cast< Player* >( pVictim )->m_bg->GetType() != BATTLEGROUND_ARENA_2V2))
2479                        {
2480                                self_res_spell = static_cast< Player* >( pVictim )->SoulStone;
2481                                static_cast< Player* >( pVictim )->SoulStone = static_cast< Player* >( pVictim )->SoulStoneReceiver = 0;
2482
2483                                if( !self_res_spell && static_cast< Player* >( pVictim )->bReincarnation )
2484                                {
2485                                        SpellEntry* m_reincarnSpellInfo = dbcSpell.LookupEntry( 20608 );
2486                                        if( static_cast< Player* >( pVictim )->Cooldown_CanCast( m_reincarnSpellInfo ) )
2487                                        {
2488                                                uint32 ankh_count = static_cast< Player* >( pVictim )->GetItemInterface()->GetItemCount( 17030 );
2489                                                if( ankh_count )
2490                                                        self_res_spell = 21169;
2491                                        }
2492                                }
2493                        }
2494                        pVictim->SetUInt32Value( PLAYER_SELF_RES_SPELL, self_res_spell );
2495                        pVictim->SetUInt32Value( UNIT_FIELD_MOUNTDISPLAYID , 0 );
2496                        //pVictim->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_MOUNTED_TAXI);
2497                }
2498
2499                // Wipe our attacker set on death
2500                pVictim->CombatStatus.Vanished();
2501
2502                //               sent to set. don't send it to the party, because if they're out of
2503                //               range they won't know this guid exists -> possible 132.
2504
2505                /*if (this->IsPlayer())
2506                        if( static_cast< Player* >( this )->InGroup() )
2507                                static_cast< Player* >( this )->GetGroup()->SendPartyKillLog( this, pVictim );*/
2508
2509                /* Stop Unit from attacking */
2510                if( this->IsPlayer() && (((Player*)this)->GetSelection() == pVictim->GetGUID()) )
2511                        static_cast< Player* >( this )->EventAttackStop();
2512
2513                if( this->IsUnit() )
2514                {
2515            pVictim->RemoveAllNonPersistantAuras();
2516
2517            CALL_SCRIPT_EVENT( this, OnTargetDied )( pVictim );
2518                        static_cast< Unit* >( this )->smsg_AttackStop( pVictim );
2519
2520                        /* Tell Unit that it's target has Died */
2521                        static_cast< Unit* >( this )->addStateFlag( UF_TARGET_DIED );
2522
2523                        // We will no longer be attacking this target, as it's dead.
2524                        //static_cast<Unit*>(this)->setAttackTarget(NULL);
2525                }
2526                //so now we are completely dead
2527                //lets see if we have spirit of redemption
2528                if( pVictim->IsPlayer() )
2529                {
2530                        if( static_cast< Player* >( pVictim)->HasSpell( 20711 ) ) //check for spirit of Redemption
2531                        {
2532                                SpellEntry* sorInfo = dbcSpell.LookupEntry(27827);
2533                                if( sorInfo != NULL )
2534                                {
2535                                        Spell *sor = SpellPool.PooledNew();
2536                                        if (!sor)
2537                                                return;
2538                                        sor->Init(pVictim, sorInfo, true, NULL);
2539                                        SpellCastTargets targets;
2540                                        targets.m_unitTarget = pVictim->GetGUID();
2541                                        sor->prepare(&targets);
2542                                }
2543                        }
2544                }
2545                uint64 victimGuid = pVictim->GetGUID();
2546                lowGUID = victimGuid & 0x00000000ffffffff;
2547                highGUID = victimGuid >> 32;
2548
2549                if(pVictim->GetTypeId() == TYPEID_UNIT)
2550                {
2551                        pVictim->GetAIInterface()->OnDeath(this);
2552
2553                        /* Tell Unit that it's target has Died */
2554                        static_cast< Unit* >( pVictim )->SetFlag( UNIT_FIELD_FLAGS, UNIT_FLAG_DEAD );
2555
2556                        if(GetTypeId() == TYPEID_PLAYER)
2557                        {
2558                                WorldPacket data(SMSG_PARTYKILLLOG, 16);
2559                                data << GetGUID() << pVictim->GetGUID();
2560                                SendMessageToSet(&data, true);
2561                        }
2562
2563                        // it Seems that pets some how don't get a name and cause a crash here
2564                        //bool isCritter = (pVictim->GetCreatureInfo() != NULL)? pVictim->GetCreatureInfo()->Type : 0;
2565
2566                        //-----------------------------------LOOOT--------------------------------------------
2567            if ((!pVictim->IsPet())&& ( !isCritter ) && pVictim->GetUInt64Value( UNIT_FIELD_CREATEDBY ) == 0)
2568                        {
2569                                Creature * victim = static_cast<Creature*>(pVictim);
2570
2571                Player *owner = 0;
2572                                if(victim->TaggerGuid)
2573                                        owner = GetMapMgr()->GetPlayer( (uint32)victim->TaggerGuid );
2574
2575                if(owner == 0 || victim->IsTotem() )  // no owner, or a totem
2576                                {
2577                    // dunno why this would happen, but anyway.. anyone can loot ;p
2578                                        // no owner no loot
2579                                        //victim->SetFlag(UNIT_DYNAMIC_FLAGS, U_DYN_FLAG_LOOTABLE);
2580                                }
2581                                else
2582                                {
2583                    // fill loot vector.
2584                                    victim->generateLoot();
2585
2586                                        // Build the actual update.
2587                                        ByteBuffer buf( 500 );
2588
2589                                        uint32 Flags = victim->m_uint32Values[ UNIT_DYNAMIC_FLAGS ];
2590                                        Flags |= U_DYN_FLAG_LOOTABLE;
2591                                        Flags |= U_DYN_FLAG_TAPPED_BY_PLAYER;
2592
2593                                        victim->BuildFieldUpdatePacket( &buf, UNIT_DYNAMIC_FLAGS, Flags );
2594
2595                                        // Check for owner's group.
2596                                        Group * pGroup = owner->GetGroup();
2597                                        if( pGroup != NULL )
2598                                        {
2599                                                // Owner was in a party.
2600                                                // Check loot method.
2601                                                victim->m_lootMethod = pGroup->GetMethod();
2602                                                switch( victim->m_lootMethod )
2603                                                {
2604                                                case PARTY_LOOT_RR:
2605/*                                              //this commented code is not used because it was never tested and finished !
2606                                                {
2607                                                                //get new tagger for creature
2608                                                                Player *tp = pGroup->GetnextRRlooter();
2609                                                                if(tp)
2610                                                                {
2611                                                                        //we force on creature a new tagger
2612                                                                        victim->TaggerGuid = tp->GetGUID();
2613                                                                        victim->Tagged = true;
2614                                                                        if(tp->IsVisible(victim))  // Save updates for non-existent creatures
2615                                                                                tp->PushUpdateData(&buf, 1);
2616                                                                }
2617                                                        }break;*/
2618                                                case PARTY_LOOT_FFA:
2619                                                case PARTY_LOOT_GROUP:
2620                                                case PARTY_LOOT_NBG:
2621                                                        {
2622                                                                // Loop party players and push update data.
2623                                                                GroupMembersSet::iterator itr;
2624                                                                SubGroup * sGrp;
2625                                                                pGroup->Lock();
2626                                                                for( uint32 Index = 0; Index < pGroup->GetSubGroupCount(); ++Index )
2627                                                                {
2628                                                                        sGrp = pGroup->GetSubGroup( Index );
2629                                                                        itr = sGrp->GetGroupMembersBegin();
2630                                                                        for( ; itr != sGrp->GetGroupMembersEnd(); ++itr )
2631                                                                        {
2632                                                                                if( (*itr)->m_loggedInPlayer && (*itr)->m_loggedInPlayer->IsVisible( victim ) )    // Save updates for non-existent creatures
2633                                                                                        (*itr)->m_loggedInPlayer->PushUpdateData( &buf, 1 );
2634                                                                        }
2635                                                                }
2636                                                                pGroup->Unlock();
2637                                                        }break;
2638                                                case PARTY_LOOT_MASTER:
2639                                                        {
2640                                                                GroupMembersSet::iterator itr;
2641                                                                SubGroup * sGrp;
2642                                                                pGroup->Lock();
2643                                                                for( uint32 Index = 0; Index < pGroup->GetSubGroupCount(); ++Index )
2644                                                                {
2645                                                                        sGrp = pGroup->GetSubGroup( Index );
2646                                                                        itr = sGrp->GetGroupMembersBegin();
2647                                                                        for( ; itr != sGrp->GetGroupMembersEnd(); ++itr )
2648                                                                        {
2649                                                                                if( (*itr)->m_loggedInPlayer && (*itr)->m_loggedInPlayer->IsVisible( victim ) )    // Save updates for non-existent creatures
2650                                                                                        (*itr)->m_loggedInPlayer->PushUpdateData( &buf, 1 );
2651                                                                        }
2652                                                                }
2653                                                                pGroup->Unlock();
2654
2655                                                                Player * pLooter = pGroup->GetLooter() ? pGroup->GetLooter()->m_loggedInPlayer : NULL;
2656                                                                if( pLooter == NULL )
2657                                                                        pLooter = pGroup->GetLeader()->m_loggedInPlayer;
2658
2659                                                                if( pLooter->IsVisible( victim ) )  // Save updates for non-existent creatures
2660                                                                        pLooter->PushUpdateData( &buf, 1 );
2661                                                        }break;
2662                                                }
2663                                        }
2664                                        else
2665                                        {
2666                                                // Owner killed the mob solo.
2667                                                if( owner->IsVisible( victim ) )
2668                                                        owner->PushUpdateData( &buf, 1 );
2669                                        }
2670                                }
2671                        }
2672                        //---------------------------------looot-----------------------------------------
2673
2674           
2675
2676
2677                        // ----------------------------- XP --------------
2678                        if ( pVictim->GetUInt64Value( UNIT_FIELD_CREATEDBY ) == 0 &&
2679                                pVictim->GetUInt64Value( OBJECT_FIELD_CREATED_BY ) == 0 &&
2680                                !pVictim->IsPet() && static_cast<Creature*>(pVictim)->Tagged)
2681                        {
2682                                Unit *uTagger = pVictim->GetMapMgr()->GetUnit(static_cast<Creature*>(pVictim)->TaggerGuid);
2683                                if (uTagger != NULL)
2684                                {
2685                                        if (uTagger->IsPlayer())
2686                                        {
2687                                                Player *pTagger = static_cast<Player*>(uTagger);
2688                                                if (pTagger)
2689                                                {
2690                                                        if (pTagger->InGroup())
2691                                                        {
2692                                                                pTagger->GiveGroupXP( pVictim, pTagger);
2693                                                        }
2694                                                        else if( IsUnit() )
2695                                                        {
2696                                                                uint32 xp = CalculateXpToGive( pVictim, uTagger );
2697                                                                if( xp > 0 )
2698                                                                {
2699                                                                        pTagger->GiveXP( xp, victimGuid, true );
2700
2701                                                                        this->SetFlag(UNIT_FIELD_AURASTATE,AURASTATE_FLAG_LASTKILLWITHHONOR);
2702                                                                        if(!sEventMgr.HasEvent(this,EVENT_LASTKILLWITHHONOR_FLAG_EXPIRE))
2703                                                                        {
2704                                                                                sEventMgr.AddEvent((Unit*)this,&Unit::EventAurastateExpire,(uint32)AURASTATE_FLAG_LASTKILLWITHHONOR,EVENT_LASTKILLWITHHONOR_FLAG_EXPIRE,20000,1,0);
2705                                                                        }
2706                                                                        else
2707                                                                        {
2708                                                                                sEventMgr.ModifyEventTimeLeft(this,EVENT_LASTKILLWITHHONOR_FLAG_EXPIRE,20000);
2709                                                                        }
2710
2711                                                                        if( pTagger->GetSummon() && pTagger->GetSummon()->CanGainXP() )
2712                                                                        {
2713                                                                                xp = CalculateXpToGive( pVictim, pTagger->GetSummon() );
2714                                                                                if( xp > 0 )
2715                                                                                        pTagger->GetSummon()->GiveXP( xp );
2716                                                                        }
2717                                                                }
2718                                                        }
2719                                                        if( !pVictim->IsPlayer() )
2720                                                        {
2721                                                                sQuestMgr.OnPlayerKill( pTagger, static_cast< Creature* >( pVictim ) );
2722                                                                if(pVictim->IsCreature())
2723                                                                {
2724                                                                        // code stolen from Unit::GiveGroupXP()
2725                                                                        if(pTagger->InGroup())
2726                                                                        {
2727                                                                                Group *pGroup = pTagger->GetGroup();
2728                                                                                //since group is small we can afford to do this rather then recheck again the whole active player set
2729                                                                                Player *active_player_list[MAX_GROUP_SIZE_RAID];
2730                                                                                Player *pGroupGuy = NULL;
2731                                                                                int active_player_count=0;
2732                                                                                GroupMembersSet::iterator itr;
2733                                                                                pGroup->Lock();
2734                                                                                for(uint32 i = 0; i < pGroup->GetSubGroupCount(); ++i) {
2735                                                                                        for(itr = pGroup->GetSubGroup(i)->GetGroupMembersBegin(); itr != pGroup->GetSubGroup(i)->GetGroupMembersEnd(); ++itr)
2736                                                                                        {
2737                                                                                                pGroupGuy = (*itr)->m_loggedInPlayer;
2738                                                                                                if( pGroupGuy &&
2739                                                                                                        pGroupGuy->isAlive() &&
2740                                                                                                        pVictim->GetMapMgr() == pGroupGuy->GetMapMgr() &&
2741                                                                                                        pGroupGuy->GetDistanceSq(pVictim)<100*100
2742                                                                                                )
2743                                                                                                {
2744                                                                                                        active_player_list[active_player_count] = pGroupGuy;
2745                                                                                                        active_player_count++;
2746                                                                                                }
2747                                                                                        }
2748                                                                                }
2749                                                                                pGroup->Unlock();
2750                                                                                if(active_player_count<1) //killer is always close to the victim. This should never execute
2751                                                                                {
2752                                                                                        active_player_list[0] = pTagger;
2753                                                                                        active_player_count=1;
2754                                                                                }
2755                                                                                for(int i = 0; i < active_player_count; ++i)
2756                                                                                {
2757                                                                                        Player * plr = active_player_list[i];
2758#ifdef ENABLE_ACHIEVEMENTS
2759                                                                                        plr->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE, pVictim->GetEntry(), 1, 0);
2760                                                                                        plr->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE, highGUID, lowGUID, 0);
2761#endif
2762                                                                                }
2763                                                                        }
2764                                                                        else // not in group, just update for pTagger
2765                                                                        {
2766#ifdef ENABLE_ACHIEVEMENTS
2767                                                                                pTagger->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE, pVictim->GetEntry(), 1, 0);
2768                                                                                pTagger->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE, highGUID, lowGUID, 0);
2769#endif
2770                                                                        }
2771                                                                }
2772                                                        }
2773                                                }
2774                                        }
2775                                        else if (uTagger->IsPet())
2776                                        {
2777                                                Pet* petTagger = static_cast<Pet*>(uTagger);
2778                                                if (petTagger != NULL)
2779                                                {
2780                                                        Player* petOwner = petTagger->GetPetOwner();
2781                                                        if( petOwner != NULL)
2782                                                        {
2783                                                                if( petOwner->InGroup() )
2784                                                                {
2785                                                                        //Calc Group XP
2786                                                                        petOwner->GiveGroupXP( pVictim, petOwner );
2787                                                                }
2788                                                                else if( IsUnit() )
2789                                                                {
2790                                                                        uint32 xp = CalculateXpToGive( pVictim, petOwner );
2791                                                                        if( xp > 0 )
2792                                                                        {
2793                                                                                petOwner->GiveXP( xp, victimGuid, true );
2794
2795                                                                                this->SetFlag(UNIT_FIELD_AURASTATE,AURASTATE_FLAG_LASTKILLWITHHONOR);
2796                                                                                if(!sEventMgr.HasEvent(this,EVENT_LASTKILLWITHHONOR_FLAG_EXPIRE))
2797                                                                                {
2798                                                                                        sEventMgr.AddEvent((Unit*)this,&Unit::EventAurastateExpire,(uint32)AURASTATE_FLAG_LASTKILLWITHHONOR,EVENT_LASTKILLWITHHONOR_FLAG_EXPIRE,20000,1,0);
2799                                                                                }
2800                                                                                else
2801                                                                                {
2802                                                                                        sEventMgr.ModifyEventTimeLeft(this,EVENT_LASTKILLWITHHONOR_FLAG_EXPIRE,20000);
2803                                                                                }
2804
2805                                                                                if( petTagger->CanGainXP() )
2806                                                                                {
2807                                                                                        xp = CalculateXpToGive( pVictim, petTagger );
2808                                                                                        if( xp > 0 )
2809                                                                                                petTagger->GiveXP( xp );
2810                                                                                }
2811                                                                        }
2812                                                                }
2813                                                                if(pVictim->GetTypeId() != TYPEID_PLAYER)
2814                                                                {
2815                                                                        sQuestMgr.OnPlayerKill( petOwner, static_cast< Creature* >( pVictim ) );
2816                                                                        if(pVictim->IsCreature())
2817                                                                        {
2818                                                                                if(petOwner->InGroup())
2819                                                                                {
2820                                                                                        Group *pGroup = petOwner->GetGroup();
2821                                                                                        // since group is small we can afford to do this rather then recheck again the whole active player set
2822                                                                                        // This needs to be looked at..
2823                                                                                        Player *active_player_list[MAX_GROUP_SIZE_RAID];
2824                                                                                        Player *pGroupGuy = NULL;
2825                                                                                        int active_player_count = 0;
2826                                                                                        GroupMembersSet::iterator itr;
2827                                                                                        pGroup->Lock();
2828                                                                                        for(uint32 i = 0; i < pGroup->GetSubGroupCount(); ++i) {
2829                                                                                                for(itr = pGroup->GetSubGroup(i)->GetGroupMembersBegin(); itr != pGroup->GetSubGroup(i)->GetGroupMembersEnd(); ++itr)
2830                                                                                                {
2831                                                                                                        pGroupGuy = (*itr)->m_loggedInPlayer;
2832                                                                                                        if( pGroupGuy &&
2833                                                                                                                pGroupGuy->isAlive() &&
2834                                                                                                                //
2835                                                                                                                pVictim->GetMapMgr() == pGroupGuy->GetMapMgr() &&
2836                                                                                                                pGroupGuy->GetDistanceSq(pVictim)<100*100
2837                                                                                                        )
2838                                                                                                        {
2839                                                                                                                active_player_list[active_player_count] = pGroupGuy;
2840                                                                                                                active_player_count++;
2841                                                                                                        }
2842                                                                                                }
2843                                                                                        }
2844                                                                                        pGroup->Unlock();
2845                                                                                        //killer is always close to the victim. This should never execute
2846                                                                                        if(active_player_count < 1) 
2847                                                                                        {
2848                                                                                                active_player_list[0] = petOwner;
2849                                                                                                active_player_count=1;
2850                                                                                        }
2851                                                                                        for(int i = 0; i < active_player_count; ++i)
2852                                                                                        {
2853                                                                                                Player * plr = active_player_list[i];
2854#ifdef ENABLE_ACHIEVEMENTS
2855                                                                                                plr->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE, pVictim->GetEntry(), 1, 0);
2856                                                                                                plr->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE, highGUID, lowGUID, 0);
2857#endif
2858                                                                                        }
2859                                                                                }
2860                                                                                else // not in group, just update for petOwner
2861                                                                                {
2862#ifdef ENABLE_ACHIEVEMENTS
2863                                                                                        petOwner->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE, pVictim->GetEntry(), 1, 0);
2864                                                                                        petOwner->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE, highGUID, lowGUID, 0);
2865#endif                                                                 
2866                                                                                }
2867                                                                        }
2868                                                                }
2869                                                        }
2870                                                }
2871                                        }
2872                                }
2873                                // ----------------------------- XP --------------
2874
2875               
2876
2877                        /* ----------------------------- PET XP HANDLING END-------------- */
2878
2879                        /* ----------------------------- PET DEATH HANDLING -------------- */
2880                                if( pVictim->IsPet() )
2881                                {
2882                                        Pet* pPet = static_cast< Pet* >( pVictim );
2883
2884                                        // dying pet looses 1 happiness level (not in BG)
2885                                        if( !pPet->IsSummon() && !pPet->IsInBg() )
2886                                        {
2887                                                uint32 hap = pPet->GetUInt32Value( UNIT_FIELD_POWER5 );
2888                                                hap = hap - PET_HAPPINESS_UPDATE_VALUE > 0 ? hap - PET_HAPPINESS_UPDATE_VALUE : 0;
2889                                                pPet->SetUInt32Value( UNIT_FIELD_POWER5, hap );
2890                                        }
2891
2892                                        pPet->DelayedRemove( false, true );
2893                                }
2894                                /* ----------------------------- PET DEATH HANDLING END -------------- */
2895                                else if( pVictim->GetUInt64Value( UNIT_FIELD_CHARMEDBY ) )
2896                                {
2897                                        //remove owner warlock soul link from caster
2898                                        Unit *owner=pVictim->GetMapMgr()->GetUnit( pVictim->GetUInt64Value( UNIT_FIELD_CHARMEDBY ) );
2899                                        if( owner != NULL && owner->IsPlayer())
2900                                                static_cast< Player* >( owner )->EventDismissPet();
2901                                }
2902                        }
2903            // We don't want to reference a possibly logged out player or removed creature, better be safe than sorry!
2904            if(pVictim->GetUInt64Value(UNIT_FIELD_CREATEDBY) != 0)
2905                pVictim->SetUInt64Value(UNIT_FIELD_CREATEDBY, 0);
2906            // Same as the above
2907            if( pVictim->IsCreature() ){
2908                Creature *pCreature = static_cast<Creature*>( pVictim );
2909                if(pCreature->GetOwner() != NULL)
2910                    pCreature->SetOwner( NULL );
2911            }
2912
2913#ifdef ENABLE_ACHIEVEMENTS
2914                        if(isCritter)
2915                        {
2916                                if(IsPlayer()) // Player killed a critter
2917                                {
2918                                        ((Player*)this)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE, pVictim->GetEntry(), 1, 0);
2919                                        ((Player*)this)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE, highGUID, lowGUID, 0);
2920                                }
2921                                else if(IsPet()) // Player's pet killed a critter
2922                                {
2923                                        ((Pet*)this)->GetPetOwner()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE, pVictim->GetEntry(), 1, 0);
2924                                        ((Pet*)this)->GetPetOwner()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE, highGUID, lowGUID, 0);
2925                                }
2926                        }
2927#endif
2928                }
2929                else if( pVictim->GetTypeId() == TYPEID_PLAYER )
2930                {
2931
2932                        /* -------------------- RESET BREATH STATE ON DEATH -------------- */
2933                        static_cast< Player* >( pVictim )->m_UnderwaterTime = 0;
2934                        static_cast< Player* >( pVictim )->m_UnderwaterState = 0;
2935                        static_cast< Player* >( pVictim )->m_BreathDamageTimer = 0;
2936                        static_cast< Player* >( pVictim )->m_SwimmingTime = 0;
2937
2938                        /* -------------------- KILL PET WHEN PLAYER DIES ---------------*/
2939                        static_cast< Player* >( pVictim )->DismissActivePet();
2940                }
2941                else sLog.outError("DealDamage for Unknown Object.");
2942        }
2943        else /* ---------- NOT DEAD YET --------- */
2944        {
2945                if(pVictim != this /* && updateskill */)
2946                {
2947                        // Send AI Reaction UNIT vs UNIT
2948                        /* Weird: why should WE react on OUR damage?
2949                        If meaning of this is to get reaction of victim, then its already handled few rows below...
2950                        if( GetTypeId() ==TYPEID_UNIT )
2951                        {
2952                                static_cast< Unit* >( this )->GetAIInterface()->AttackReaction( pVictim, damage, spellId );
2953                        }*/
2954
2955                        // Send AI Victim Reaction
2956                        if( this->IsPlayer() || this->IsCreature() )
2957                        {
2958                                if( !pVictim->IsPlayer() )
2959                                {
2960                                        static_cast< Creature* >( pVictim )->GetAIInterface()->AttackReaction( static_cast< Unit* >( this ), damage, spellId );
2961                                }
2962                                else
2963                                {
2964                                        // Defensive pet
2965                                        Pet* pPet = static_cast< Player* >( pVictim )->GetSummon();
2966                                        if( pPet != NULL && pPet->GetPetState() != PET_STATE_PASSIVE )
2967                                        {
2968                                                pPet->GetAIInterface()->AttackReaction( static_cast< Unit* >( this ), 1, 0 );
2969                                                pPet->HandleAutoCastEvent( AUTOCAST_EVENT_OWNER_ATTACKED );
2970                                        }
2971                                }
2972                        }
2973                }
2974
2975                // TODO: Mark victim as a HK
2976                /*if( static_cast< Player* >( pVictim )->GetCurrentBattleground() != NULL && static_cast< Player* >( this )->GetCurrentBattleground() != NULL)
2977                {
2978
2979                }*/
2980
2981                pVictim->SetUInt32Value( UNIT_FIELD_HEALTH, health - damage );
2982        }
2983   
2984}
2985
2986void Object::SpellNonMeleeDamageLog(Unit *pVictim, uint32 spellID, uint32 damage, bool allowProc, bool static_damage, bool no_remove_auras)
2987{
2988//==========================================================================================
2989//==============================Unacceptable Cases Processing===============================
2990//==========================================================================================
2991        if(!pVictim || !pVictim->isAlive())
2992                return;
2993
2994        SpellEntry *spellInfo = dbcSpell.LookupEntry( spellID );
2995        if(!spellInfo)
2996        return;
2997
2998        if (this->IsPlayer() && !static_cast< Player* >( this )->canCast(spellInfo))
2999                return;
3000//==========================================================================================
3001//==============================Variables Initialization====================================
3002//==========================================================================================
3003        uint32 school = spellInfo->School;
3004        float res = float(damage);
3005        uint32 aproc = PROC_ON_ANY_HOSTILE_ACTION; /*| PROC_ON_SPELL_HIT;*/
3006        uint32 vproc = PROC_ON_ANY_HOSTILE_ACTION | PROC_ON_ANY_DAMAGE_VICTIM; /*| PROC_ON_SPELL_HIT_VICTIM;*/
3007
3008        //A school damage is not necessarily magic
3009        switch( spellInfo->Spell_Dmg_Type )
3010        {
3011        case SPELL_DMG_TYPE_RANGED:     {
3012                        aproc |= PROC_ON_RANGED_ATTACK;
3013                        vproc |= PROC_ON_RANGED_ATTACK_VICTIM;
3014                }break;
3015
3016        case SPELL_DMG_TYPE_MELEE:{
3017                        aproc |= PROC_ON_MELEE_ATTACK;
3018                        vproc |= PROC_ON_MELEE_ATTACK_VICTIM;
3019                }break;
3020
3021        case SPELL_DMG_TYPE_MAGIC:{
3022                        aproc |= PROC_ON_SPELL_HIT;
3023                        vproc |= PROC_ON_SPELL_HIT_VICTIM;
3024                }break;
3025        }
3026
3027        bool critical = false;
3028//==========================================================================================
3029//==============================+Spell Damage Bonus Calculations============================
3030//==========================================================================================
3031//------------------------------by stats----------------------------------------------------
3032        if( this->IsUnit() && !static_damage )
3033        {
3034                Unit* caster = static_cast< Unit* >( this );
3035                caster->RemoveAurasByInterruptFlag( AURA_INTERRUPT_ON_START_ATTACK );
3036                res += caster->GetSpellDmgBonus( pVictim, spellInfo, ( int )res, false );
3037
3038//==========================================================================================
3039//==============================Post +SpellDamage Bonus Modifications=======================
3040//==========================================================================================
3041                if( res < 0 )
3042                        res = 0;
3043                else if( spellInfo->spell_can_crit == true )
3044                {
3045//------------------------------critical strike chance--------------------------------------
3046                        // lol ranged spells were using spell crit chance
3047                        float CritChance=0.0f;
3048                        if( spellInfo->is_ranged_spell )
3049                        {
3050
3051                                if( IsPlayer() )
3052                                {
3053                                        CritChance = GetFloatValue( PLAYER_RANGED_CRIT_PERCENTAGE );
3054                                        if( pVictim->IsPlayer() )
3055                                                CritChance += static_cast< Player* >(pVictim)->res_R_crit_get();
3056
3057                                        CritChance += (float)(pVictim->AttackerCritChanceMod[spellInfo->School]);
3058                                }
3059                                else
3060                                {
3061                                        CritChance = 5.0f; // static value for mobs.. not blizzlike, but an unfinished formula is not fatal :)
3062                                }
3063                                if( pVictim->IsPlayer() )
3064                                        CritChance -= static_cast< Player* >(pVictim)->CalcRating( PLAYER_RATING_MODIFIER_RANGED_CRIT_RESILIENCE );
3065                        }
3066                        else if( spellInfo->is_melee_spell )
3067                        {
3068                                // Same shit with the melee spells, such as Judgement/Seal of Command
3069                                if( IsPlayer() )
3070                                {
3071                                        CritChance = GetFloatValue(PLAYER_CRIT_PERCENTAGE);
3072                                }
3073                                if( pVictim->IsPlayer() )
3074                                {
3075                                        CritChance += static_cast< Player* >(pVictim)->res_R_crit_get(); //this could be ability but in that case we overwrite the value
3076                                }
3077                                // Resilience
3078                                CritChance -= pVictim->IsPlayer() ? static_cast< Player* >(pVictim)->CalcRating( PLAYER_RATING_MODIFIER_MELEE_CRIT_RESILIENCE ) : 0.0f;
3079                                // Victim's (!) crit chance mod for physical attacks?
3080                                CritChance += (float)(pVictim->AttackerCritChanceMod[0]);
3081
3082                        }
3083                        else
3084                        {
3085                                CritChance = caster->spellcritperc + caster->SpellCritChanceSchool[school] + pVictim->AttackerCritChanceMod[school];
3086                                if( caster->IsPlayer() && ( pVictim->m_rooted - pVictim->m_stunned ) )
3087                                        CritChance += static_cast< Player* >( caster )->m_RootedCritChanceBonus;
3088
3089                                if( spellInfo->SpellGroupType )
3090                                {
3091                                        SM_FFValue(caster->SM_CriticalChance, &CritChance, spellInfo->SpellGroupType);
3092                                }
3093
3094                                if( pVictim->IsPlayer() )
3095                                CritChance -= static_cast< Player* >(pVictim)->CalcRating( PLAYER_RATING_MODIFIER_SPELL_CRIT_RESILIENCE );
3096                        }
3097                        if( CritChance < 0 ) CritChance = 0;
3098                        if( CritChance > 95 ) CritChance = 95;
3099                        critical = Rand(CritChance);
3100                        //sLog.outString( "SpellNonMeleeDamageLog: Crit Chance %f%%, WasCrit = %s" , CritChance , critical ? "Yes" : "No" );
3101
3102                        Aura *fs = NULL;
3103                        if(spellInfo->NameHash == SPELL_HASH_LAVA_BURST && (fs = pVictim->FindAuraByNameHash(SPELL_HASH_FLAME_SHOCK)) != NULL)
3104                        {
3105                                critical = true;
3106                                if(caster && !caster->HasAura(55447))   // Glyph of Flame Shock
3107                                                fs->Remove();
3108                        }
3109
3110//==========================================================================================
3111//==============================Spell Critical Hit==========================================
3112//==========================================================================================
3113                        if (critical)
3114                        {
3115                                int32 critical_bonus = 100;
3116                                if( spellInfo->SpellGroupType )
3117                                        SM_FIValue( caster->SM_PCriticalDamage, &critical_bonus, spellInfo->SpellGroupType );
3118
3119                                if( critical_bonus > 0 )
3120                                {
3121                                        // the bonuses are halved by 50% (funky blizzard math :S)
3122                                        float b;
3123                                        if( spellInfo->School == 0 || spellInfo->is_melee_spell || spellInfo->is_ranged_spell )         // physical || hackfix SoCommand/JoCommand
3124                                                b = ( ( float(critical_bonus) ) / 100.0f ) + 1.0f;
3125                                        else
3126                                                b = ( ( float(critical_bonus) / 2.0f ) / 100.0f ) + 1.0f;
3127
3128                                        res *= b;
3129                                }
3130
3131                                if( pVictim->IsPlayer() )
3132                                {
3133                                        //res = res*(1.0f-2.0f*static_cast< Player* >(pVictim)->CalcRating(PLAYER_RATING_MODIFIER_MELEE_CRIT_RESISTANCE));
3134                                        //Resilience is a special new rating which was created to reduce the effects of critical hits against your character.
3135                                        //It has two components; it reduces the chance you will be critically hit by x%,
3136                                        //and it reduces the damage dealt to you by critical hits by 2x%. x is the percentage resilience granted by a given resilience rating.
3137                                        //It is believed that resilience also functions against spell crits,
3138                                        //though it's worth noting that NPC mobs cannot get critical hits with spells.
3139                                        float dmg_reduction_pct = 2 * static_cast< Player* >(pVictim)->CalcRating( PLAYER_RATING_MODIFIER_MELEE_CRIT_RESILIENCE ) / 100.0f;
3140                                        if( dmg_reduction_pct > 1.0f )
3141                                                dmg_reduction_pct = 1.0f; //we cannot resist more then he is criticalling us, there is no point of the critical then :P
3142                                        res = res - res * dmg_reduction_pct;
3143                                }
3144
3145                                if (pVictim->GetTypeId() == TYPEID_UNIT && static_cast<Creature*>(pVictim)->GetCreatureInfo() && static_cast<Creature*>(pVictim)->GetCreatureInfo()->Rank != ELITE_WORLDBOSS)
3146                                        pVictim->Emote( EMOTE_ONESHOT_WOUNDCRITICAL );
3147                                /*aproc |= PROC_ON_SPELL_CRIT_HIT;
3148                                vproc |= PROC_ON_SPELL_CRIT_HIT_VICTIM;*/
3149
3150                                switch( spellInfo->Spell_Dmg_Type )
3151                                {
3152                                case SPELL_DMG_TYPE_RANGED:     {
3153                                                aproc |= PROC_ON_RANGED_CRIT_ATTACK;
3154                                                vproc |= PROC_ON_RANGED_CRIT_ATTACK_VICTIM;
3155                                        }break;
3156
3157                                case SPELL_DMG_TYPE_MELEE:{
3158                                                aproc |= PROC_ON_CRIT_ATTACK;
3159                                                vproc |= PROC_ON_CRIT_HIT_VICTIM;
3160                                        }break;
3161
3162                                case SPELL_DMG_TYPE_MAGIC:{
3163                                                aproc |= PROC_ON_SPELL_CRIT_HIT;
3164                                                vproc |= PROC_ON_SPELL_CRIT_HIT_VICTIM;
3165                                        }break;
3166                                }
3167                        }
3168                }
3169        }
3170//==========================================================================================
3171//==============================Post Roll Calculations======================================
3172//==========================================================================================
3173
3174//------------------------------absorption--------------------------------------------------
3175        uint32 ress=(uint32)res;
3176        uint32 abs_dmg = pVictim->AbsorbDamage(school, &ress);
3177        uint32 ms_abs_dmg= pVictim->ManaShieldAbsorb(ress);
3178        if (ms_abs_dmg)
3179        {
3180                if(ms_abs_dmg > ress)
3181                        ress = 0;
3182                else
3183                        ress-=ms_abs_dmg;
3184
3185                abs_dmg += ms_abs_dmg;
3186        }
3187
3188        if(abs_dmg)
3189                vproc |= PROC_ON_ABSORB;
3190
3191        // Incanter's Absorption
3192        if( pVictim->IsPlayer() && pVictim->HasAurasWithNameHash( SPELL_HASH_INCANTER_S_ABSORPTION ) )
3193        {
3194                float pctmod = 0.0f;
3195                Player* pl = static_cast< Player* >( pVictim );
3196                if( pl->HasAura( 44394 ) )
3197                        pctmod = 0.05f;
3198                else if( pl->HasAura( 44395 ) )
3199                        pctmod = 0.10f;
3200                else if( pl->HasAura( 44396 ) )
3201                        pctmod = 0.15f;
3202
3203                uint32 hp = static_cast<uint32>( 0.05f * pl->GetUInt32Value( UNIT_FIELD_MAXHEALTH ) );
3204                uint32 spellpower = static_cast<uint32>( pctmod * pl->GetUInt32Value( PLAYER_FIELD_MOD_DAMAGE_DONE_POS ) );
3205
3206                if( spellpower > hp )
3207                        spellpower = hp;
3208
3209                SpellEntry * entry = dbcSpell.LookupEntry( 44413 );
3210                if( !entry ) 
3211                        return;
3212
3213                Spell * sp = SpellPool.PooledNew();
3214                if ( !sp )
3215                        return;
3216                sp->Init( pl, entry, true, NULL );
3217                sp->GetProto()->EffectBasePoints[0] = spellpower;
3218                SpellCastTargets targets;
3219                targets.m_unitTarget = pl->GetGUID();
3220                sp->prepare(&targets);
3221        }
3222
3223        if(ress < 0) ress = 0;
3224
3225        res=(float)ress;
3226        dealdamage dmg;
3227        dmg.school_type = school;
3228        dmg.full_damage = ress;
3229        dmg.resisted_damage = 0;
3230
3231        if(res <= 0)
3232                dmg.resisted_damage = dmg.full_damage;
3233
3234        //------------------------------resistance reducing-----------------------------------------
3235        if(res > 0 && this->IsUnit())
3236        {
3237                static_cast<Unit*>(this)->CalculateResistanceReduction( pVictim, &dmg, spellInfo, 0 );
3238                if( (int32)dmg.resisted_damage > dmg.full_damage )
3239                        res = 0;
3240                else
3241                        res = float( dmg.full_damage - dmg.resisted_damage );
3242        }
3243        //------------------------------special states----------------------------------------------
3244        if(pVictim->GetTypeId() == TYPEID_PLAYER && static_cast< Player* >(pVictim)->GodModeCheat == true)
3245        {
3246                res = float(dmg.full_damage);
3247                dmg.resisted_damage = dmg.full_damage;
3248        }
3249
3250        // Paladin: Blessing of Sacrifice, and Warlock: Soul Link
3251        if( pVictim->m_damageSplitTarget)
3252        {
3253                res = (float)pVictim->DoDamageSplitTarget((uint32)res, school, false);
3254        }
3255
3256//==========================================================================================
3257//==============================Data Sending ProcHandling===================================
3258//==========================================================================================
3259        SendSpellNonMeleeDamageLog(this, pVictim, spellID, float2int32(res), static_cast<uint8>( school ), abs_dmg, dmg.resisted_damage, false, 0, critical, IsPlayer());
3260        DealDamage( pVictim, float2int32( res ), 2, 0, spellID );
3261
3262        if( this->IsUnit() && allowProc && spellInfo->Id != 25501 && spellInfo->noproc == false )
3263        {
3264                int32 dmg = float2int32(res);
3265
3266                pVictim->HandleProc( vproc, static_cast< Unit* >( this ), spellInfo, dmg, abs_dmg);
3267                pVictim->m_procCounter = 0;
3268                static_cast< Unit* >( this )->HandleProc( aproc, pVictim, spellInfo, dmg, abs_dmg);
3269                static_cast< Unit* >( this )->m_procCounter = 0;
3270        }
3271        if( this->IsPlayer() )
3272        {
3273                        static_cast< Player* >( this )->m_casted_amount[school] = ( uint32 )res;
3274        }
3275
3276        if( !(dmg.full_damage == 0 && abs_dmg) )
3277        {
3278                //Only pushback the victim current spell if it's not fully absorbed
3279                if( pVictim->GetCurrentSpell() )
3280                        pVictim->GetCurrentSpell()->AddTime( school );
3281        }
3282
3283//==========================================================================================
3284//==============================Post Damage Processing======================================
3285//==========================================================================================
3286        if( (int32)dmg.resisted_damage == dmg.full_damage && !abs_dmg )
3287        {
3288                //Magic Absorption
3289                if( pVictim->IsPlayer() )
3290                {
3291                        if( static_cast< Player* >( pVictim )->m_RegenManaOnSpellResist )
3292                        {
3293                                Player* pl = static_cast< Player* >( pVictim );
3294                                uint32 maxmana = pl->GetUInt32Value( UNIT_FIELD_MAXPOWER1 );
3295
3296                                //TODO: wtf is this ugly mess of casting bullshit
3297                                uint32 amount = uint32(float( float(maxmana)*pl->m_RegenManaOnSpellResist));
3298
3299                                pVictim->Energize( pVictim, 29442, amount, POWER_TYPE_MANA );
3300                        }
3301                        // we still stay in combat dude
3302                        static_cast< Player* >(pVictim)->CombatStatusHandler_ResetPvPTimeout();
3303                }
3304                if( IsPlayer() )
3305                        static_cast< Player* >(this)->CombatStatusHandler_ResetPvPTimeout();
3306        }
3307        if( school == SHADOW_DAMAGE )
3308        {
3309                if( IsPlayer() && ((Unit*)this)->isAlive() && ((Player*)this)->getClass() == PRIEST )
3310                        ((Player*)this)->VampiricSpell(float2int32(res), pVictim);
3311
3312                if( pVictim->isAlive() && this->IsUnit() )
3313                {
3314                        //Shadow Word:Death
3315                        if( spellID == 32379 || spellID == 32996 || spellID == 48157 || spellID == 48158 ) 
3316                        {
3317                                uint32 damage = (uint32)( res + abs_dmg );
3318                                uint32 absorbed = static_cast< Unit* >( this )->AbsorbDamage( school, &damage );
3319                                DealDamage( static_cast< Unit* >( this ), damage, 2, 0, spellID );
3320                                SendSpellNonMeleeDamageLog( this, this, spellID, damage, static_cast<uint8>( school ), absorbed, 0, false, 0, false, this->IsPlayer() );
3321                        }
3322                }
3323        }
3324}
3325
3326//*****************************************************************************************
3327//* SpellLog packets just to keep the code cleaner and better to read
3328//*****************************************************************************************
3329
3330void Object::SendSpellLog(Object *Caster, Object *Target,uint32 Ability, uint8 SpellLogType)
3331{
3332        if ( ( !Caster || !Target ) && Ability )
3333                return;
3334
3335
3336        WorldPacket data( SMSG_SPELLLOGMISS, 26 );
3337        data << Ability;                                                                                // spellid
3338        data << Caster->GetGUID();                                                        // caster / player
3339        data << (uint8)1;                                                                          // unknown but I think they are const
3340        data << (uint32)1;                                                                        // unknown but I think they are const
3341        data << Target->GetGUID();                                                        // target
3342        data << SpellLogType;                                                              // spelllogtype
3343        Caster->SendMessageToSet( &data, true );
3344}
3345
3346
3347void Object::SendSpellNonMeleeDamageLog( Object* Caster, Object* Target, uint32 SpellID, uint32 Damage, uint8 School, uint32 AbsorbedDamage, uint32 ResistedDamage, bool PhysicalDamage, uint32 BlockedDamage, bool CriticalHit, bool bToset )
3348{
3349        if( !Caster || !Target || !SpellID )
3350                return;
3351
3352        WorldPacket data( SMSG_SPELLNONMELEEDAMAGELOG, 48 );
3353        data << Target->GetNewGUID();
3354        data << Caster->GetNewGUID();
3355        data << SpellID;                    // SpellID / AbilityID
3356        data << Damage;                     // All Damage
3357        data << uint32(0);                                      // Why is this added?
3358        data << uint8(g_spellSchoolConversionTable[School]);                     // School
3359        data << AbsorbedDamage;             // Absorbed Damage
3360        data << ResistedDamage;             // Resisted Damage
3361        data << uint8(PhysicalDamage);      // Physical Damage (true/false)
3362        data << uint8(0);                   // unknown or it binds with Physical Damage
3363        data << BlockedDamage;               // Physical Damage (true/false)
3364        data << uint8(CriticalHit ? 7 : 5);                   // unknown const
3365        data << uint32(0);
3366
3367        Caster->SendMessageToSet( &data, bToset );
3368}
3369
3370void Object::SendAttackerStateUpdate( Object* Caster, Object* Target, dealdamage *Dmg, uint32 Damage, uint32 Abs, uint32 BlockedDamage, uint32 HitStatus, uint32 VState )
3371{
3372        if (!Caster || !Target || !Dmg)
3373                return;
3374
3375        WorldPacket data(SMSG_ATTACKERSTATEUPDATE, 70);
3376        //0x4--dualwield,0x10 miss,0x20 absorbed,0x80 crit,0x4000 -glancing,0x8000-crushing
3377        //only for melee!
3378
3379        if (!(HitStatus & (HITSTATUS_MISS))) {
3380//              HitStatus|= 0x00800000;
3381        }
3382
3383        data << (uint32)HitStatus;
3384        data << Caster->GetNewGUID();
3385        data << Target->GetNewGUID();
3386
3387        data << (uint32)Damage;                         // Realdamage
3388        data << (uint32)0;                                      // Overkill
3389        data << (uint8)1;                                       // Damage type counter / swing type
3390
3391        data << (uint32)g_spellSchoolConversionTable[Dmg->school_type];                           // Damage school
3392        data << (float)Dmg->full_damage;        // Damage float
3393        data << (uint32)Dmg->full_damage;       // Damage amount
3394        if (HitStatus & HITSTATUS_ABSORBED) {
3395                data << (uint32)Abs;                            // Damage absorbed
3396        }
3397        if (HitStatus & HITSTATUS_RESIST) {
3398                data << (uint32)Dmg->resisted_damage;   // Damage resisted
3399        }
3400//      data << (uint8)1;                                       // unknown - VLack: Victim state or target state on other emulators; maybe this is in the VState variable...
3401        data << (uint8)VState;
3402//      if(HitStatus & HITSTATUS_BLOCK)
3403                data << (uint32)0;                              // can be 0,1000 or -1
3404//      else
3405//              data << (uint32)0x03e8;                         // can be 0,1000 or -1
3406        data << (uint32)0;
3407        if (HitStatus & HITSTATUS_BLOCK) {
3408                data << (uint32)BlockedDamage;          // Damage amount blocked
3409        }
3410        if (HitStatus & 0x00800000) {
3411                data << (uint32)0;                              // unknown
3412        }
3413        if(HitStatus & HITSTATUS_unk)
3414        {
3415                data << uint32(0);
3416                data << float(0);
3417                data << float(0);
3418                data << float(0);
3419                data << float(0);
3420                data << float(0);
3421                data << float(0);
3422                data << float(0);
3423                data << float(0);
3424                for(uint8 i = 0; i < 5; ++i)
3425                {
3426                        data << float(0);
3427                        data << float(0);
3428                }
3429                data << uint32(0);
3430        }
3431//      data << (uint32)0;                                      // HitNumber?
3432//      data << (uint32)VState;                         // new victim state
3433
3434        SendMessageToSet(&data, Caster->IsPlayer());
3435}
3436
3437int32 Object::event_GetInstanceID()
3438{
3439        // return -1 for non-inworld.. so we get our shit moved to the right thread
3440        if(!IsInWorld())
3441                return -1;
3442        else
3443                return m_instanceId;
3444}
3445
3446void Object::EventSpellDamage(uint64 Victim, uint32 SpellID, uint32 Damage)
3447{
3448        if(!IsInWorld())
3449                return;
3450
3451        Unit * pUnit = GetMapMgr()->GetUnit(Victim);
3452        if(pUnit == 0) return;
3453
3454        SpellNonMeleeDamageLog(pUnit, SpellID, Damage, true);
3455}
3456
3457//! Object has an active state
3458bool Object::CanActivate()
3459{
3460        switch(m_objectTypeId)
3461        {
3462        case TYPEID_UNIT:
3463                {
3464                        if ( !IsPet() )
3465                                return true;
3466                }break;
3467
3468        case TYPEID_GAMEOBJECT:
3469                {
3470                        if(static_cast<GameObject*>(this)->HasAI() && GetByte(GAMEOBJECT_BYTES_1, 1) != GAMEOBJECT_TYPE_TRAP)
3471                                return true;
3472                }break;
3473        }
3474
3475        return false;
3476}
3477
3478void Object::Activate(MapMgr * mgr)
3479{
3480        switch ( m_objectTypeId )
3481        {
3482        case TYPEID_UNIT:
3483                mgr->activeCreatures.insert( ( Creature* )this );
3484                break;
3485
3486        case TYPEID_GAMEOBJECT:
3487                mgr->activeGameObjects.insert( ( GameObject* )this );
3488                break;
3489        }
3490        // Objects are active so set to true.
3491        Active = true;
3492}
3493
3494void Object::Deactivate(MapMgr * mgr)
3495{
3496        if ( mgr == NULL )
3497                return;
3498
3499        switch(m_objectTypeId)
3500        {
3501        case TYPEID_UNIT:
3502                mgr->activeCreatures.erase((Creature*)this);
3503                break;
3504
3505        case TYPEID_GAMEOBJECT:
3506                mgr->activeGameObjects.erase((GameObject*)this);
3507                break;
3508        }
3509        Active = false;
3510}
3511
3512void Object::SetByte(uint32 index, uint32 index1,uint8 value)
3513{
3514        ASSERT( index < m_valuesCount );
3515        // save updating when val isn't changing.
3516        #ifndef USING_BIG_ENDIAN
3517        uint8 * v =&((uint8*)m_uint32Values)[index*4+index1];
3518        #else
3519        uint8 * v = &((uint8*)m_uint32Values)[index*4+(3-index1)];
3520        #endif
3521        if(*v == value)
3522                return;
3523
3524        *v = value;
3525
3526        if(IsInWorld())
3527        {
3528                m_updateMask.SetBit( index );
3529
3530                if(!m_objectUpdated)
3531                {
3532                        m_mapMgr->ObjectUpdated(this);
3533                        m_objectUpdated = true;
3534                }
3535        }
3536
3537}
3538
3539void Object::SetByteFlag( uint16 index, uint8 offset, uint8 newFlag )
3540{
3541    ASSERT( index < m_valuesCount );
3542        ASSERT( offset < 4 );
3543       
3544        offset <<= 3;
3545
3546    if( !( uint8( m_uint32Values[ index ] >> offset ) & newFlag ) )
3547    {
3548        m_uint32Values[ index ] |= uint32( uint32( newFlag ) << offset );
3549
3550        if(IsInWorld())
3551        {
3552                        m_updateMask.SetBit( index );
3553
3554            if(!m_objectUpdated)
3555            {
3556                m_mapMgr->ObjectUpdated(this);
3557                m_objectUpdated = true;
3558            }
3559        }
3560    }
3561}
3562
3563void Object::RemoveByteFlag( uint16 index, uint8 offset, uint8 oldFlag )
3564{
3565        ASSERT( index < m_valuesCount );
3566        ASSERT( offset < 4 );
3567       
3568        offset <<= 3;
3569
3570    if( uint8( m_uint32Values[ index ] >> offset ) & oldFlag )
3571    {
3572        m_uint32Values[ index ] &= ~uint32( uint32( oldFlag ) << offset );
3573
3574        if(IsInWorld())
3575        {
3576                        m_updateMask.SetBit( index );
3577
3578            if(!m_objectUpdated)
3579            {
3580                m_mapMgr->ObjectUpdated(this);
3581                m_objectUpdated = true;
3582            }
3583        }
3584    }
3585}
3586
3587void Object::SetZoneId(uint32 newZone)
3588{
3589        m_zoneId = newZone;
3590        if( m_objectTypeId == TYPEID_PLAYER && static_cast< Player* >( this )->GetGroup() )
3591                static_cast< Player* >( this )->GetGroup()->HandlePartialChange( PARTY_UPDATE_FLAG_ZONEID, static_cast< Player* >( this ) );
3592}
3593
3594void Object::PlaySoundToSet(uint32 sound_entry)
3595{
3596        WorldPacket data(SMSG_PLAY_SOUND, 4);
3597        data << sound_entry;
3598        SendMessageToSet(&data, true);
3599}
3600
3601void Object::_SetExtension(const string& name, void* ptr)
3602{
3603        if( m_extensions == NULL )
3604                m_extensions = new ExtensionSet;
3605
3606        m_extensions->insert( make_pair( name, ptr ) );
3607}
3608
3609bool Object::IsInBg()
3610{
3611        MapInfo *pMapinfo = WorldMapInfoStorage.LookupEntry(this->GetMapId());
3612        if(pMapinfo)
3613        {
3614                return (pMapinfo->type == INSTANCE_BATTLEGROUND);
3615        }
3616
3617        return false;
3618}
3619
3620uint32 Object::GetTeam()
3621{
3622        if (IsPlayer())
3623        {
3624                return static_cast< Player* >( this )->GetTeam();
3625        }
3626        if (IsPet())
3627        {
3628                if (static_cast< Pet* >( this )->GetPetOwner() != NULL)
3629                {
3630                        return static_cast< Pet* >( this )->GetPetOwner()->GetTeam();
3631                }
3632        }
3633        if (IsUnit() && !IsPlayer() && static_cast< Creature* >( this )->IsTotem() )
3634        {
3635                if (static_cast< Creature* >( this )->GetTotemOwner() != NULL)
3636                {
3637                        return static_cast< Creature* >( this )->GetTotemOwner()->GetTeam();
3638                }
3639        }
3640
3641        return static_cast<uint32>(-1);
3642}
3643
3644//Manipulates the phase value, see "enum PHASECOMMANDS" in Object.h for a longer explanation!
3645void Object::Phase(uint8 command, uint32 newphase)
3646{
3647        switch( command )
3648        {
3649        case PHASE_SET:
3650                m_phase = newphase;
3651                break;
3652        case PHASE_ADD:
3653                m_phase |= newphase;
3654                break;
3655        case PHASE_DEL:
3656                m_phase &= ~newphase;
3657                break;
3658        case PHASE_RESET:
3659                m_phase = 1;
3660                break;
3661        default:
3662                return;
3663        }
3664
3665        if ( IsPlayer() ) {
3666                Player * p_player=static_cast< Player* >( this );
3667                if ( p_player->GetSummon() )
3668                        p_player->GetSummon()->Phase(command, newphase);
3669                //We should phase other, non-combat "pets" too...
3670        }
3671
3672        for( std::set<Object*>::iterator itr=m_objectsInRange.begin(); itr!=m_objectsInRange.end(); ++itr )
3673        {
3674                if ( (*itr)->IsUnit() )
3675                        static_cast< Unit* >( *itr )->UpdateVisibility();
3676        }
3677
3678        if ( IsUnit() )
3679                static_cast< Unit* >( this )->UpdateVisibility();
3680
3681        return;
3682}
Note: See TracBrowser for help on using the browser.