diff --git a/CMakeLists.txt b/CMakeLists.txt index a7897be92..312095f08 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -112,6 +112,7 @@ OPTION(EQEMU_BUILD_SERVER "Build the game server." ON) OPTION(EQEMU_BUILD_LOGIN "Build the login server." OFF) OPTION(EQEMU_BUILD_AZONE "Build azone utility." OFF) OPTION(EQEMU_BUILD_TESTS "Build utility tests." OFF) +OPTION(EQEMU_BUILD_PERL "Build Perl parser." ON) #C++11 stuff IF(NOT MSVC) @@ -128,8 +129,10 @@ IF(EQEMU_ENABLE_RVALUE_MOVE) ENDIF(EQEMU_ENABLE_RVALUE_MOVE) #Various definitions -ADD_DEFINITIONS(-DEMBPERL) -ADD_DEFINITIONS(-DEMBPERL_PLUGIN) +IF(EQEMU_BUILD_PERL) + ADD_DEFINITIONS(-DEMBPERL) + ADD_DEFINITIONS(-DEMBPERL_PLUGIN) +ENDIF(EQEMU_BUILD_PERL) ADD_DEFINITIONS(-DEQDEBUG=${EQEMU_DEBUG_LEVEL}) ADD_DEFINITIONS(-DINVERSEXY) ADD_DEFINITIONS(-DFIELD_ITEMS) @@ -138,8 +141,11 @@ ADD_DEFINITIONS(-DMAP_DIR="./Maps") #Find everything we need FIND_PACKAGE(ZLIB REQUIRED) FIND_PACKAGE(MySQL REQUIRED) -FIND_PACKAGE(PerlLibs REQUIRED) -INCLUDE_DIRECTORIES("${ZLIB_INCLUDE_DIRS}" "${PERL_INCLUDE_PATH}" "${MySQL_INCLUDE_DIR}") +IF(EQEMU_BUILD_PERL) + FIND_PACKAGE(PerlLibs REQUIRED) + INCLUDE_DIRECTORIES("${PERL_INCLUDE_PATH}") +ENDIF(EQEMU_BUILD_PERL) +INCLUDE_DIRECTORIES("${ZLIB_INCLUDE_DIRS}" "${MySQL_INCLUDE_DIR}") IF(EQEMU_BUILD_SERVER OR EQEMU_BUILD_LOGIN OR EQEMU_BUILD_TESTS) ADD_SUBDIRECTORY(common) diff --git a/changelog.txt b/changelog.txt index d39146a1e..a77b903b0 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,11 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 04/28/2013 == +PiB: Implement CRC16 using CRC32. + +== 04/27/2013 == +PiB: Verify OP_Ack size & fix crash in BasePacket::build_raw_header_dump due to uninitialised timestamp. +Derision: Verify minimum size of OP_Packet, OP_Fragment and OP_OutOfOrderAck. == 04/24/2013 == Bad_Captain: Fixed a couple of merc stat issues. diff --git a/common/BasePacket.cpp b/common/BasePacket.cpp index 2717ee354..82fd13649 100644 --- a/common/BasePacket.cpp +++ b/common/BasePacket.cpp @@ -28,6 +28,7 @@ BasePacket::BasePacket(const unsigned char *buf, uint32 len) this->size=0; this->_wpos = 0; this->_rpos = 0; + this->timestamp.tv_sec = 0; if (len>0) { this->size=len; pBuffer= new unsigned char[len]; diff --git a/common/CRC16.cpp b/common/CRC16.cpp index 6a6f44078..d5a8942d5 100644 --- a/common/CRC16.cpp +++ b/common/CRC16.cpp @@ -1,346 +1,14 @@ -#include +#include "crc32.h" -unsigned long IntArray[]={ -0x00000000, -0x77073096, -0xEE0E612C, -0x990951BA, -0x076DC419, -0x706AF48F, -0xE963A535, -0x9E6495A3, -0x0EDB8832, -0x79DCB8A4, -0xE0D5E91E, -0x97D2D988, -0x09B64C2B, -0x7EB17CBD, -0xE7B82D07, -0x90BF1D91, -0x1DB71064, -0x6AB020F2, -0xF3B97148, -0x84BE41DE, -0x1ADAD47D, -0x6DDDE4EB, -0xF4D4B551, -0x83D385C7, -0x136C9856, -0x646BA8C0, -0xFD62F97A, -0x8A65C9EC, -0x14015C4F, -0x63066CD9, -0xFA0F3D63, -0x8D080DF5, -0x3B6E20C8, -0x4C69105E, -0xD56041E4, -0xA2677172, -0x3C03E4D1, -0x4B04D447, -0xD20D85FD, -0xA50AB56B, -0x35B5A8FA, -0x42B2986C, -0xDBBBC9D6, -0xACBCF940, -0x32D86CE3, -0x45DF5C75, -0xDCD60DCF, -0xABD13D59, -0x26D930AC, -0x51DE003A, -0xC8D75180, -0xBFD06116, -0x21B4F4B5, -0x56B3C423, -0xCFBA9599, -0xB8BDA50F, -0x2802B89E, -0x5F058808, -0xC60CD9B2, -0xB10BE924, -0x2F6F7C87, -0x58684C11, -0xC1611DAB, -0xB6662D3D, -0x76DC4190, -0x01DB7106, -0x98D220BC, -0xEFD5102A, -0x71B18589, -0x06B6B51F, -0x9FBFE4A5, -0xE8B8D433, -0x7807C9A2, -0x0F00F934, -0x9609A88E, -0xE10E9818, -0x7F6A0DBB, -0x086D3D2D, -0x91646C97, -0xE6635C01, -0x6B6B51F4, -0x1C6C6162, -0x856530D8, -0xF262004E, -0x6C0695ED, -0x1B01A57B, -0x8208F4C1, -0xF50FC457, -0x65B0D9C6, -0x12B7E950, -0x8BBEB8EA, -0xFCB9887C, -0x62DD1DDF, -0x15DA2D49, -0x8CD37CF3, -0xFBD44C65, -0x4DB26158, -0x3AB551CE, -0xA3BC0074, -0xD4BB30E2, -0x4ADFA541, -0x3DD895D7, -0xA4D1C46D, -0xD3D6F4FB, -0x4369E96A, -0x346ED9FC, -0xAD678846, -0xDA60B8D0, -0x44042D73, -0x33031DE5, -0xAA0A4C5F, -0xDD0D7CC9, -0x5005713C, -0x270241AA, -0xBE0B1010, -0xC90C2086, -0x5768B525, -0x206F85B3, -0xB966D409, -0xCE61E49F, -0x5EDEF90E, -0x29D9C998, -0xB0D09822, -0xC7D7A8B4, -0x59B33D17, -0x2EB40D81, -0xB7BD5C3B, -0xC0BA6CAD, -0xEDB88320, -0x9ABFB3B6, -0x03B6E20C, -0x74B1D29A, -0xEAD54739, -0x9DD277AF, -0x04DB2615, -0x73DC1683, -0xE3630B12, -0x94643B84, -0x0D6D6A3E, -0x7A6A5AA8, -0xE40ECF0B, -0x9309FF9D, -0x0A00AE27, -0x7D079EB1, -0xF00F9344, -0x8708A3D2, -0x1E01F268, -0x6906C2FE, -0xF762575D, -0x806567CB, -0x196C3671, -0x6E6B06E7, -0xFED41B76, -0x89D32BE0, -0x10DA7A5A, -0x67DD4ACC, -0xF9B9DF6F, -0x8EBEEFF9, -0x17B7BE43, -0x60B08ED5, -0xD6D6A3E8, -0xA1D1937E, -0x38D8C2C4, -0x4FDFF252, -0xD1BB67F1, -0xA6BC5767, -0x3FB506DD, -0x48B2364B, -0xD80D2BDA, -0xAF0A1B4C, -0x36034AF6, -0x41047A60, -0xDF60EFC3, -0xA867DF55, -0x316E8EEF, -0x4669BE79, -0xCB61B38C, -0xBC66831A, -0x256FD2A0, -0x5268E236, -0xCC0C7795, -0xBB0B4703, -0x220216B9, -0x5505262F, -0xC5BA3BBE, -0xB2BD0B28, -0x2BB45A92, -0x5CB36A04, -0xC2D7FFA7, -0xB5D0CF31, -0x2CD99E8B, -0x5BDEAE1D, -0x9B64C2B0, -0xEC63F226, -0x756AA39C, -0x026D930A, -0x9C0906A9, -0xEB0E363F, -0x72076785, -0x05005713, -0x95BF4A82, -0xE2B87A14, -0x7BB12BAE, -0x0CB61B38, -0x92D28E9B, -0xE5D5BE0D, -0x7CDCEFB7, -0x0BDBDF21, -0x86D3D2D4, -0xF1D4E242, -0x68DDB3F8, -0x1FDA836E, -0x81BE16CD, -0xF6B9265B, -0x6FB077E1, -0x18B74777, -0x88085AE6, -0xFF0F6A70, -0x66063BCA, -0x11010B5C, -0x8F659EFF, -0xF862AE69, -0x616BFFD3, -0x166CCF45, -0xA00AE278, -0xD70DD2EE, -0x4E048354, -0x3903B3C2, -0xA7672661, -0xD06016F7, -0x4969474D, -0x3E6E77DB, -0xAED16A4A, -0xD9D65ADC, -0x40DF0B66, -0x37D83BF0, -0xA9BCAE53, -0xDEBB9EC5, -0x47B2CF7F, -0x30B5FFE9, -0xBDBDF21C, -0xCABAC28A, -0x53B39330, -0x24B4A3A6, -0xBAD03605, -0xCDD70693, -0x54DE5729, -0x23D967BF, -0xB3667A2E, -0xC4614AB8, -0x5D681B02, -0x2A6F2B94, -0xB40BBE37, -0xC30C8EA1, -0x5A05DF1B, -0x2D02EF8D, -}; - -unsigned long CRC16(const unsigned char *buf, int size, int key) +uint16 CRC16(const unsigned char *buf, int size, int key) { - - //printf("CRC16() key=%d\n",key); -/* -sub_0_10020760 proc near ; CODE XREF: sub_0_10008620+AEp - ; sub_0_10022A90+14Fp ... - -arg_0 = dword ptr 4 -arg_4 = dword ptr 8 -arg_8 = dword ptr 0Ch -*/ - - //int *pecx = buf; - unsigned long ecx = key; //mov ecx, [esp+arg_8] - unsigned long eax = ecx; //mov eax, ecx - unsigned long edi; -/* int ecx = key; //mov ecx, [esp+arg_8] - int eax = ecx; //mov eax, ecx - int edi; -*/ - eax = ~ eax; //not eax - eax&=0xFF; //and eax, 0FFh - eax=IntArray[eax]; //mov eax, dword_0_10115D38[eax*4] IntArray - eax ^= 0x00FFFFFF; //xor eax, 0FFFFFFh - int edx = ecx; //mov edx, ecx - edx = edx >> 8; //sar edx, 8 - edx = edx ^ eax; //xor edx, eax - eax = eax >> 8; //sar eax, 8 - edx &= 0xFF; //and edx, 0FFh - eax &= 0x00FFFFFF; //and eax, 0FFFFFFh - //push esi - eax ^= IntArray[edx]; //xor eax, dword_0_10115D38[edx*4] - edx = ecx; //mov edx, ecx - edx = edx >> 0x10; //sar edx, 10h - edx ^= eax; //xor edx, eax - eax = eax >> 8; //sar eax, 8 - edx &= 0xFF; //and edx, 0FFh - int esi = IntArray[edx]; //mov esi, dword_0_10115D38[edx*4] - edx = size; //mov edx, [esp+4+arg_4] - eax &= 0x00FFFFFF; //and eax, 0FFFFFFh - eax ^= esi; //xor eax, esi - ecx = ecx >> 0x18; //sar ecx, 18h - ecx ^= eax; //xor ecx, eax - ecx &= 0xFF; //and ecx, 0FFh - esi = IntArray[ecx]; //mov esi, dword_0_10115D38[ecx*4] - /*ecx = (int) buf; not used */ //mov ecx, [esp+4+arg_0] - eax = eax >> 8; //sar eax, 8 - eax &= 0x00FFFFFF; //and eax, 0FFFFFFh - eax ^= esi; //xor eax, esi - /* int* esi = ecx+edx //??*///lea esi, [ecx+edx] - for(int x = 0; x < size; x++) - { //eax is the crc, ecx is the current part of the buffer - int edx = 0; //xor edx, edx - edx = buf[x] & 0x00FF; //mov dl, [ecx] - - /*if(pos > size) //cmp ecx, esi - return ~eax; //jnb short loc_0_10020803 - */ - //push edi - -//loc_0_100207E0: ; CODE XREF: sub_0_10020760+A0j -//LOOP - edx ^= eax; //xor edx, eax - eax = eax >> 8; //sar eax, 8 - edx &= 0xFF; //and edx, 0FFh - edi = IntArray[edx]; //mov edi, dword_0_10115D38[edx*4] - eax &= 0x00FFFFFF; //and eax, 0FFFFFFh - eax ^= edi; //xor eax, edi - //inc ecx - //cmp ecx, esi - // jb short loc_0_100207E0 - //pop edi - } - - return ~eax; -} - -/*loc_0_10020803: ; CODE XREF: sub_0_10020760+7Dj - not eax - pop esi - retn -sub_0_10020760 endp - -*/ + // This is computed as the lowest 16 bits of an Ethernet CRC32 checksum + // where the key is prepended to the data in little endian order. + uint8 keyBuf[] = {(uint8)((key >> 0) & 0xff), + (uint8)((key >> 8) & 0xff), + (uint8)((key >> 16) & 0xff), + (uint8)((key >> 24) & 0xff)}; + uint32 crc = CRC32::Update(keyBuf, sizeof(uint32)); + crc = CRC32::Update(buf, size, crc); + return CRC32::Finish(crc) & 0xffff; +} diff --git a/common/CRC16.h b/common/CRC16.h index df1768f00..04de64e1e 100644 --- a/common/CRC16.h +++ b/common/CRC16.h @@ -1,6 +1,7 @@ #ifndef _CRC16_H #define _CRC16_H +#include "types.h" -unsigned long CRC16(const unsigned char *buf, int size, int key); +uint16 CRC16(const unsigned char *buf, int size, int key); #endif diff --git a/common/EQStream.cpp b/common/EQStream.cpp index 561c8f4a6..ae5c6953c 100644 --- a/common/EQStream.cpp +++ b/common/EQStream.cpp @@ -173,6 +173,11 @@ uint32 processed=0,subpacket_length=0; break; case OP_Packet: { + if(!p->pBuffer || (p->Size() < 4)) + { + _log(NET__ERROR, _L "Received OP_Packet that was of malformed size" __L); + break; + } uint16 seq=ntohs(*(uint16 *)(p->pBuffer)); SeqOrder check=CompareSequence(NextInSeq,seq); if (check == SeqFuture) { @@ -218,6 +223,11 @@ uint32 processed=0,subpacket_length=0; break; case OP_Fragment: { + if(!p->pBuffer || (p->Size() < 4)) + { + _log(NET__ERROR, _L "Received OP_Fragment that was of malformed size" __L); + break; + } uint16 seq=ntohs(*(uint16 *)(p->pBuffer)); SeqOrder check=CompareSequence(NextInSeq,seq); if (check == SeqFuture) { @@ -284,6 +294,11 @@ uint32 processed=0,subpacket_length=0; } break; case OP_Ack: { + if(!p->pBuffer || (p->Size() < 4)) + { + _log(NET__ERROR, _L "Received OP_Ack that was of malformed size" __L); + break; + } #ifndef COLLECTOR uint16 seq=ntohs(*(uint16 *)(p->pBuffer)); AckPackets(seq); @@ -383,6 +398,11 @@ uint32 processed=0,subpacket_length=0; } break; case OP_OutOfOrderAck: { + if(!p->pBuffer || (p->Size() < 4)) + { + _log(NET__ERROR, _L "Received OP_OutOfOrderAck that was of malformed size" __L); + break; + } #ifndef COLLECTOR uint16 seq=ntohs(*(uint16 *)(p->pBuffer)); MOutboundQueue.lock(); diff --git a/utils/EQExtractor2/EQExtractor2/ChangeLog.txt b/utils/EQExtractor2/EQExtractor2/ChangeLog.txt index abdfab715..2181b9279 100644 --- a/utils/EQExtractor2/EQExtractor2/ChangeLog.txt +++ b/utils/EQExtractor2/EQExtractor2/ChangeLog.txt @@ -1,5 +1,8 @@ EQExtractor2 Changelog. All changes since the 1.0 release. +==04/25/2013== +Derision: Added SQL generation support to current Live client decoder. + ==04/24/2013== Derision: Added decoder to support packet dumps from current Live client. SQL generation NOT SUPPORTED YET (need tweaks to position struct). diff --git a/utils/EQExtractor2/EQExtractor2/EQExtractor2Form1.cs b/utils/EQExtractor2/EQExtractor2/EQExtractor2Form1.cs index 220c743d9..4fb5096bc 100644 --- a/utils/EQExtractor2/EQExtractor2/EQExtractor2Form1.cs +++ b/utils/EQExtractor2/EQExtractor2/EQExtractor2Form1.cs @@ -18,7 +18,7 @@ namespace EQExtractor2 { public partial class EQExtractor2Form1 : Form { - string Version = "EQExtractor2 Version 2.6.3 SVN"; + string Version = "EQExtractor2 Version 2.6.4 GIT"; static int PacketsSeen = 0; static long BytesRead = 0; diff --git a/utils/EQExtractor2/EQExtractor2/PatchApril15-2013.cs b/utils/EQExtractor2/EQExtractor2/PatchApril15-2013.cs index 7d8804577..9ae389832 100644 --- a/utils/EQExtractor2/EQExtractor2/PatchApril15-2013.cs +++ b/utils/EQExtractor2/EQExtractor2/PatchApril15-2013.cs @@ -17,7 +17,224 @@ namespace EQExtractor2.Patches PatchConfFileName = "patch_April15-2013.conf"; - SupportsSQLGeneration = false; - } + SupportsSQLGeneration = true; + } + + override public List GetSpawns() + { + List ZoneSpawns = new List(); + + List SpawnPackets = GetPacketsOfType("OP_ZoneEntry", PacketDirection.ServerToClient); + + foreach (byte[] SpawnPacket in SpawnPackets) + { + ZoneEntryStruct NewSpawn = new ZoneEntryStruct(); + + ByteStream Buffer = new ByteStream(SpawnPacket); + + NewSpawn.SpawnName = Buffer.ReadString(true); + + NewSpawn.SpawnName = Utils.MakeCleanName(NewSpawn.SpawnName); + + NewSpawn.SpawnID = Buffer.ReadUInt32(); + + NewSpawn.Level = Buffer.ReadByte(); + + float UnkSize = Buffer.ReadSingle(); + + NewSpawn.IsNPC = Buffer.ReadByte(); + + UInt32 Bitfield = Buffer.ReadUInt32(); + + NewSpawn.Gender = (Bitfield & 3); + + Byte OtherData = Buffer.ReadByte(); + + Buffer.SkipBytes(8); // Skip 8 unknown bytes + + NewSpawn.DestructableString1 = ""; + NewSpawn.DestructableString2 = ""; + NewSpawn.DestructableString3 = ""; + + if ((NewSpawn.IsNPC > 0) && ((OtherData & 1) > 0)) + { + // Destructable Objects + NewSpawn.DestructableString1 = Buffer.ReadString(false); + NewSpawn.DestructableString2 = Buffer.ReadString(false); + NewSpawn.DestructableString3 = Buffer.ReadString(false); + Buffer.SkipBytes(53); + } + + if ((OtherData & 4) > 0) + { + // Auras + Buffer.ReadString(false); + Buffer.ReadString(false); + Buffer.SkipBytes(54); + } + + NewSpawn.PropCount = Buffer.ReadByte(); + + if (NewSpawn.PropCount > 0) + NewSpawn.BodyType = Buffer.ReadUInt32(); + else + NewSpawn.BodyType = 0; + + + for (int j = 1; j < NewSpawn.PropCount; ++j) + Buffer.SkipBytes(4); + + Buffer.SkipBytes(1); // Skip HP % + NewSpawn.HairColor = Buffer.ReadByte(); + NewSpawn.BeardColor = Buffer.ReadByte(); + NewSpawn.EyeColor1 = Buffer.ReadByte(); + NewSpawn.EyeColor2 = Buffer.ReadByte(); + NewSpawn.HairStyle = Buffer.ReadByte(); + NewSpawn.Beard = Buffer.ReadByte(); + + NewSpawn.DrakkinHeritage = Buffer.ReadUInt32(); + NewSpawn.DrakkinTattoo = Buffer.ReadUInt32(); + NewSpawn.DrakkinDetails = Buffer.ReadUInt32(); + + NewSpawn.EquipChest2 = Buffer.ReadByte(); + + bool UseWorn = (NewSpawn.EquipChest2 == 255); + + Buffer.SkipBytes(2); // 2 Unknown bytes; + + NewSpawn.Helm = Buffer.ReadByte(); + + NewSpawn.Size = Buffer.ReadSingle(); + + NewSpawn.Face = Buffer.ReadByte(); + + NewSpawn.WalkSpeed = Buffer.ReadSingle(); + + NewSpawn.RunSpeed = Buffer.ReadSingle(); + + NewSpawn.Race = Buffer.ReadUInt32(); + + Buffer.SkipBytes(1); // Skip Holding + + NewSpawn.Deity = Buffer.ReadUInt32(); + + Buffer.SkipBytes(8); // Skip GuildID and GuildRank + + NewSpawn.Class = Buffer.ReadByte(); + + Buffer.SkipBytes(4); // Skip PVP, Standstate, Light, Flymode + + NewSpawn.LastName = Buffer.ReadString(true); + + Buffer.SkipBytes(6); + + NewSpawn.PetOwnerID = Buffer.ReadUInt32(); + + Buffer.SkipBytes(25); + + NewSpawn.MeleeTexture1 = 0; + NewSpawn.MeleeTexture2 = 0; + + if ((NewSpawn.IsNPC == 0) || NPCType.IsPlayableRace(NewSpawn.Race)) + { + for (int ColourSlot = 0; ColourSlot < 9; ++ColourSlot) + NewSpawn.SlotColour[ColourSlot] = Buffer.ReadUInt32(); + + for (int i = 0; i < 9; ++i) + { + NewSpawn.Equipment[i] = Buffer.ReadUInt32(); + + UInt32 Equip3 = Buffer.ReadUInt32(); + + UInt32 Equip2 = Buffer.ReadUInt32(); + + UInt32 Equip1 = Buffer.ReadUInt32(); + + UInt32 Equip0 = Buffer.ReadUInt32(); + } + + if (NewSpawn.Equipment[Constants.MATERIAL_CHEST] > 0) + { + NewSpawn.EquipChest2 = (byte)NewSpawn.Equipment[Constants.MATERIAL_CHEST]; + + } + + NewSpawn.ArmorTintRed = (byte)((NewSpawn.SlotColour[Constants.MATERIAL_CHEST] >> 16) & 0xff); + + NewSpawn.ArmorTintGreen = (byte)((NewSpawn.SlotColour[Constants.MATERIAL_CHEST] >> 8) & 0xff); + + NewSpawn.ArmorTintBlue = (byte)(NewSpawn.SlotColour[Constants.MATERIAL_CHEST] & 0xff); + + if (NewSpawn.Equipment[Constants.MATERIAL_PRIMARY] > 0) + NewSpawn.MeleeTexture1 = NewSpawn.Equipment[Constants.MATERIAL_PRIMARY]; + + if (NewSpawn.Equipment[Constants.MATERIAL_SECONDARY] > 0) + NewSpawn.MeleeTexture2 = NewSpawn.Equipment[Constants.MATERIAL_SECONDARY]; + + if (UseWorn) + NewSpawn.Helm = (byte)NewSpawn.Equipment[Constants.MATERIAL_HEAD]; + else + NewSpawn.Helm = 0; + + } + else + { + // Non playable race + + Buffer.SkipBytes(20); + + NewSpawn.MeleeTexture1 = Buffer.ReadUInt32(); + Buffer.SkipBytes(16); + NewSpawn.MeleeTexture2 = Buffer.ReadUInt32(); + Buffer.SkipBytes(16); + } + + if (NewSpawn.EquipChest2 == 255) + NewSpawn.EquipChest2 = 0; + + if (NewSpawn.Helm == 255) + NewSpawn.Helm = 0; + + UInt32 Position1 = Buffer.ReadUInt32(); + + UInt32 Position2 = Buffer.ReadUInt32(); + + UInt32 Position3 = Buffer.ReadUInt32(); + + UInt32 Position4 = Buffer.ReadUInt32(); + + UInt32 Position5 = Buffer.ReadUInt32(); + + NewSpawn.YPos = Utils.EQ19ToFloat((Int32)((Position1 >> 12) & 0x7FFFF)); + + NewSpawn.ZPos = Utils.EQ19ToFloat((Int32)(Position2) & 0x7FFFF); + + NewSpawn.XPos = Utils.EQ19ToFloat((Int32)(Position4 >> 13) & 0x7FFFF); + + NewSpawn.Heading = Utils.EQ19ToFloat((Int32)(Position3 >> 13) & 0xFFF); + + if ((OtherData & 16) > 0) + { + NewSpawn.Title = Buffer.ReadString(false); + } + + if ((OtherData & 32) > 0) + { + NewSpawn.Suffix = Buffer.ReadString(false); + } + + // unknowns + Buffer.SkipBytes(8); + + NewSpawn.IsMercenary = Buffer.ReadByte(); + + Buffer.SkipBytes(54); + + Debug.Assert(Buffer.GetPosition() == Buffer.Length(), "Length mismatch while parsing zone spawns"); + + ZoneSpawns.Add(NewSpawn); + } + return ZoneSpawns; + } } } \ No newline at end of file diff --git a/zone/merc.cpp b/zone/merc.cpp index ba9e5d66f..04df278a3 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -275,7 +275,8 @@ void Merc::CalcItemBonuses(StatBonuses* newbon) { if(equipment[i] == 0) continue; const Item_Struct * itm = database.GetItem(equipment[i]); - AddItemBonuses(itm, newbon); + if(itm) + AddItemBonuses(itm, newbon); } //Power Source Slot diff --git a/zone/net.cpp b/zone/net.cpp index ac3ab94f2..2ac9d1c61 100644 --- a/zone/net.cpp +++ b/zone/net.cpp @@ -284,9 +284,11 @@ int main(int argc, char** argv) { } parse = new QuestParserCollection(); - PerlXSParser *pxs = new PerlXSParser(); - Parser *ps = new Parser(); - parse->RegisterQuestInterface(pxs, "pl"); +#ifdef EMBPERL + PerlXSParser *pxs = new PerlXSParser(); + parse->RegisterQuestInterface(pxs, "pl"); +#endif + Parser *ps = new Parser(); //parse->RegisterQuestInterface(ps, "qst"); @@ -473,7 +475,9 @@ int main(int argc, char** argv) { entity_list.Clear(); safe_delete(parse); - safe_delete(pxs); +#ifdef EMBPERL + safe_delete(pxs); +#endif safe_delete(ps); safe_delete(mmf);