diff --git a/src/Client/DefScriptInterface.cpp b/src/Client/DefScriptInterface.cpp index d6f6091..7be5cd9 100644 --- a/src/Client/DefScriptInterface.cpp +++ b/src/Client/DefScriptInterface.cpp @@ -598,10 +598,7 @@ DefReturnResult DefScriptPackage::SCGetItemProtoValue(CmdSet& Set) uint32 tmp=0; if(t=="class") r.ret=toString(proto->Class); else if(t=="subclass") r.ret=toString(proto->SubClass); - else if(t=="name1" || t=="name") r.ret=proto->Name[0]; - else if(t=="name2") r.ret=proto->Name[1]; - else if(t=="name3") r.ret=proto->Name[2]; - else if(t=="name4") r.ret=proto->Name[3]; + else if(t=="name") r.ret=proto->Name; else if(t=="model" || t=="displayid") r.ret=toString(proto->DisplayInfoID); else if(t=="quality") r.ret=toString(proto->Quality); else if(t=="flags") r.ret=toString(proto->Flags); diff --git a/src/Client/World/CMSGConstructor.cpp b/src/Client/World/CMSGConstructor.cpp index 3107a18..1edc8c3 100644 --- a/src/Client/World/CMSGConstructor.cpp +++ b/src/Client/World/CMSGConstructor.cpp @@ -112,15 +112,15 @@ void WorldSession::SendCastSpell(uint32 spellid, bool nocheck) Object *target = objmgr.GetObj(my->GetTarget()); - if(!target) // this is wrong, some spells dont require a target (areaspells, self-only spells) - return; // but for now, this should be ok, until a db is used that provides spell info + //if(!target) // this is wrong, some spells dont require a target (areaspells, self-only spells) + // return; // but for now, this should be ok, until a db is used that provides spell info WorldPacket packet; ByteBuffer temp; uint16 flags=TARGET_FLAG_SELF; // target mask. spellcast implementeation needs to be changed if TARGET_MASK_SELF is != 0 packet << spellid; packet << (uint8)0; // unk - if(my->GetTarget() != GetGuid()) // self cast? + if(target && my->GetTarget() != GetGuid()) // self cast? { if(target->GetTypeId() == TYPEID_PLAYER || target->GetTypeId() == TYPEID_UNIT) { @@ -145,7 +145,7 @@ void WorldSession::SendCastSpell(uint32 spellid, bool nocheck) SendWorldPacket(packet); logdetail("Casting spell %u on target "I64FMT,spellid,my->GetTarget()); if(!known) - logerror(" - WARNING: spell is NOT known!"); + logcustom(1,RED," - WARNING: spell is NOT known!"); } void WorldSession::SendWhoListRequest(uint32 minlvl, uint32 maxlvl, uint32 racemask, uint32 classmask, std::string name, std::string guildname, std::vector *zonelist, std::vector *strlist) diff --git a/src/Client/World/Object.h b/src/Client/World/Object.h index 195855c..50988e5 100644 --- a/src/Client/World/Object.h +++ b/src/Client/World/Object.h @@ -4,6 +4,7 @@ #include "UpdateFields.h" #include "ObjectDefines.h" #include "common.h" +#include "HelperDefs.h" enum TYPE { @@ -145,6 +146,28 @@ inline uint32 GetValuesCountByTypeId(uint8 tid) return 0; } +inline uint8 GetTypeIdByGuid(uint64 guid) +{ + switch(GUID_HIPART(guid)) + { + case HIGHGUID_PLAYER: + return TYPEID_PLAYER; + case HIGHGUID_CORPSE: + case HIGHGUID_PLAYER_CORPSE: // not sure + return TYPEID_CORPSE; + case HIGHGUID_ITEM: // == HIGHGUID_CONTAINER + return TYPEID_ITEM; + case HIGHGUID_DYNAMICOBJECT: + return TYPEID_DYNAMICOBJECT; + case HIGHGUID_GAMEOBJECT: + case HIGHGUID_TRANSPORT: // not sure + return TYPEID_GAMEOBJECT; + case HIGHGUID_UNIT: + return TYPEID_UNIT; + } + return TYPEID_OBJECT; +} + #endif diff --git a/src/Client/World/ObjectDefines.h b/src/Client/World/ObjectDefines.h index 296a228..3ff46b2 100644 --- a/src/Client/World/ObjectDefines.h +++ b/src/Client/World/ObjectDefines.h @@ -19,17 +19,18 @@ #ifndef MANGOS_OBJECTDEFINES_H #define MANGOS_OBJECTDEFINES_H -enum HIGHGUID -{ - HIGHGUID_ITEM = 0x40000070, - HIGHGUID_CONTAINER = 0x40000070, - HIGHGUID_UNIT = 0xF0001000, - HIGHGUID_PLAYER = 0x00000000, - HIGHGUID_GAMEOBJECT = 0xF0004000, - HIGHGUID_DYNAMICOBJECT = 0xF000A000, - HIGHGUID_CORPSE = 0xF0007000, - HIGHGUID_PLAYER_CORPSE = 0x80000001, // ?? - HIGHGUID_TRANSPORT = 0x80000000 +enum HighGuid +{ + HIGHGUID_ITEM = 0x40000000, // blizz 40000000 + HIGHGUID_CONTAINER = 0x40000000, // blizz 40000000 + HIGHGUID_UNIT = 0xF0070000, // blizz F009????, where "????" is unit entry + HIGHGUID_PLAYER = 0x00000000, // blizz 00000000 + HIGHGUID_GAMEOBJECT = 0xF0060000, // blizz F0090000 + HIGHGUID_DYNAMICOBJECT = 0xF00A0000, // blizz F0090000, F0320000 + HIGHGUID_CORPSE = 0xF0090000, // blizz F0090000, F0320000 + HIGHGUID_PLAYER_CORPSE = 0xF0080000, // blizz F0090000, F0320000 + HIGHGUID_MO_TRANSPORT = 0x1FC00000, // blizz 1FC00000 (type 15) + HIGHGUID_TRANSPORT = 0x1FA70000 // blizz 1FA70000 (type 11) }; #define IS_CREATURE_GUID(Guid) ( GUID_HIPART(Guid) == HIGHGUID_UNIT ) diff --git a/src/Client/World/UpdateData.cpp b/src/Client/World/UpdateData.cpp index f91df91..8198dcc 100644 --- a/src/Client/World/UpdateData.cpp +++ b/src/Client/World/UpdateData.cpp @@ -56,11 +56,18 @@ void WorldSession::_HandleUpdateObjectOpcode(WorldPacket& recvPacket) case UPDATETYPE_MOVEMENT: { recvPacket >> uguid; // the guid is NOT packed here! + uint8 tyid; Object *obj = objmgr.GetObj(uguid); if(obj) - this->_MovementUpdate(obj->GetTypeId(),uguid,recvPacket); - else - logerror("Got UpdateObject_Movement for unknown object "I64FMT,uguid); + tyid = obj->GetTypeId(); + else // sometimes objects get deleted BEFORE a last update packet arrives, this must be handled also + { + tyid = GetTypeIdByGuid(uguid); + logerror("Got UpdateObject_Movement for unknown object "I64FMT". Using typeid %u",uguid,(uint32)tyid); + } + + if(obj) + this->_MovementUpdate(tyid,uguid,recvPacket); } break; @@ -315,30 +322,46 @@ void WorldSession::_MovementUpdate(uint8 objtypeid, uint64 uguid, WorldPacket& r void WorldSession::_ValuesUpdate(uint64 uguid, WorldPacket& recvPacket) { Object *obj = objmgr.GetObj(uguid); - uint8 blockcount; + uint8 blockcount,tyid; uint32 value, masksize, valuesCount; float fvalue; - if (obj) + if(obj) { valuesCount = obj->GetValuesCount(); - recvPacket >> blockcount; - masksize = blockcount << 2; // each sizeof(uint32) == <4> * sizeof(uint8) // 1<<2 == <4> - UpdateMask umask; - uint32 *updateMask = new uint32[blockcount]; - umask.SetCount(masksize); - recvPacket.read((uint8*)updateMask, masksize); - umask.SetMask(updateMask); - //delete [] updateMask; // will be deleted at ~UpdateMask() !!!! - logdev("ValuesUpdate TypeId=%u GUID="I64FMT" pObj=%X Blocks=%u Masksize=%u",obj->GetTypeId(),uguid,obj,blockcount,masksize); + tyid = obj->GetTypeId(); + } + else + { + logcustom(1,RED,"Got UpdateObject_Values for unknown object "I64FMT,uguid); + tyid = GetTypeIdByGuid(uguid); // can cause problems with TYPEID_CONTAINER!! + valuesCount = GetValuesCountByTypeId(tyid); + } - for (uint32 i = 0; i < valuesCount; i++) + + recvPacket >> blockcount; + masksize = blockcount << 2; // each sizeof(uint32) == <4> * sizeof(uint8) // 1<<2 == <4> + UpdateMask umask; + uint32 *updateMask = new uint32[blockcount]; + umask.SetCount(masksize); + recvPacket.read((uint8*)updateMask, masksize); + umask.SetMask(updateMask); + //delete [] updateMask; // will be deleted at ~UpdateMask() !!!! + logdev("ValuesUpdate TypeId=%u GUID="I64FMT" pObj=%X Blocks=%u Masksize=%u",tyid,uguid,obj,blockcount,masksize); + + // just in case the object does not exist, and we have really a container instead of an item, and a value in + // the container fields is set, THEN we have a problem. this should never be the case; it can be fixed in a + // more correct way if there is the need. + // (-> valuesCount smaller then it should be might skip a few bytes and corrupt the packet) + for (uint32 i = 0; i < valuesCount; i++) + { + if (umask.GetBit(i)) { - if (umask.GetBit(i)) + if(obj) { if(IsFloatField(obj->GetTypeMask(),i)) { - recvPacket >> fvalue; + recvPacket >> fvalue; obj->SetFloatValue(i, fvalue); logdev("-> Field[%u] = %f",i,fvalue); } @@ -348,15 +371,13 @@ void WorldSession::_ValuesUpdate(uint64 uguid, WorldPacket& recvPacket) obj->SetUInt32Value(i, value); logdev("-> Field[%u] = %u",i,value); } - } + else + { + recvPacket >> value; // drop the value, since object doesnt exist (always 4 bytes) + } } } - else - { - logerror("Got UpdateObject_Values for unknown object "I64FMT,uguid); - } - } void WorldSession::_QueryObjectInfo(uint64 guid) diff --git a/src/Client/World/WorldSession.cpp b/src/Client/World/WorldSession.cpp index ef983b6..3b5935d 100644 --- a/src/Client/World/WorldSession.cpp +++ b/src/Client/World/WorldSession.cpp @@ -1028,7 +1028,7 @@ void WorldSession::_HandleEmoteOpcode(WorldPacket& recvPacket) } if(name.empty()) { - if(o->IsPlayer()) + if(IS_PLAYER_GUID(guid)) { name = GetOrRequestPlayerName(guid); if(name.empty())