Merge pull request #2 from EQEmu/master

sync
This commit is contained in:
josheb 2013-05-04 07:30:46 -07:00
commit 824b101831
11 changed files with 284 additions and 357 deletions

View File

@ -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_LOGIN "Build the login server." OFF)
OPTION(EQEMU_BUILD_AZONE "Build azone utility." OFF) OPTION(EQEMU_BUILD_AZONE "Build azone utility." OFF)
OPTION(EQEMU_BUILD_TESTS "Build utility tests." OFF) OPTION(EQEMU_BUILD_TESTS "Build utility tests." OFF)
OPTION(EQEMU_BUILD_PERL "Build Perl parser." ON)
#C++11 stuff #C++11 stuff
IF(NOT MSVC) IF(NOT MSVC)
@ -128,8 +129,10 @@ IF(EQEMU_ENABLE_RVALUE_MOVE)
ENDIF(EQEMU_ENABLE_RVALUE_MOVE) ENDIF(EQEMU_ENABLE_RVALUE_MOVE)
#Various definitions #Various definitions
ADD_DEFINITIONS(-DEMBPERL) IF(EQEMU_BUILD_PERL)
ADD_DEFINITIONS(-DEMBPERL_PLUGIN) ADD_DEFINITIONS(-DEMBPERL)
ADD_DEFINITIONS(-DEMBPERL_PLUGIN)
ENDIF(EQEMU_BUILD_PERL)
ADD_DEFINITIONS(-DEQDEBUG=${EQEMU_DEBUG_LEVEL}) ADD_DEFINITIONS(-DEQDEBUG=${EQEMU_DEBUG_LEVEL})
ADD_DEFINITIONS(-DINVERSEXY) ADD_DEFINITIONS(-DINVERSEXY)
ADD_DEFINITIONS(-DFIELD_ITEMS) ADD_DEFINITIONS(-DFIELD_ITEMS)
@ -138,8 +141,11 @@ ADD_DEFINITIONS(-DMAP_DIR="./Maps")
#Find everything we need #Find everything we need
FIND_PACKAGE(ZLIB REQUIRED) FIND_PACKAGE(ZLIB REQUIRED)
FIND_PACKAGE(MySQL REQUIRED) FIND_PACKAGE(MySQL REQUIRED)
FIND_PACKAGE(PerlLibs REQUIRED) IF(EQEMU_BUILD_PERL)
INCLUDE_DIRECTORIES("${ZLIB_INCLUDE_DIRS}" "${PERL_INCLUDE_PATH}" "${MySQL_INCLUDE_DIR}") 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) IF(EQEMU_BUILD_SERVER OR EQEMU_BUILD_LOGIN OR EQEMU_BUILD_TESTS)
ADD_SUBDIRECTORY(common) ADD_SUBDIRECTORY(common)

View File

@ -1,5 +1,11 @@
EQEMu Changelog (Started on Sept 24, 2003 15:50) 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 == == 04/24/2013 ==
Bad_Captain: Fixed a couple of merc stat issues. Bad_Captain: Fixed a couple of merc stat issues.

View File

@ -28,6 +28,7 @@ BasePacket::BasePacket(const unsigned char *buf, uint32 len)
this->size=0; this->size=0;
this->_wpos = 0; this->_wpos = 0;
this->_rpos = 0; this->_rpos = 0;
this->timestamp.tv_sec = 0;
if (len>0) { if (len>0) {
this->size=len; this->size=len;
pBuffer= new unsigned char[len]; pBuffer= new unsigned char[len];

View File

@ -1,346 +1,14 @@
#include <stdio.h> #include "crc32.h"
unsigned long IntArray[]={ uint16 CRC16(const unsigned char *buf, int size, int key)
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)
{ {
// This is computed as the lowest 16 bits of an Ethernet CRC32 checksum
//printf("CRC16() key=%d\n",key); // where the key is prepended to the data in little endian order.
/* uint8 keyBuf[] = {(uint8)((key >> 0) & 0xff),
sub_0_10020760 proc near ; CODE XREF: sub_0_10008620+AEp (uint8)((key >> 8) & 0xff),
; sub_0_10022A90+14Fp ... (uint8)((key >> 16) & 0xff),
(uint8)((key >> 24) & 0xff)};
arg_0 = dword ptr 4 uint32 crc = CRC32::Update(keyBuf, sizeof(uint32));
arg_4 = dword ptr 8 crc = CRC32::Update(buf, size, crc);
arg_8 = dword ptr 0Ch return CRC32::Finish(crc) & 0xffff;
*/ }
//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
*/

View File

@ -1,6 +1,7 @@
#ifndef _CRC16_H #ifndef _CRC16_H
#define _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 #endif

View File

@ -173,6 +173,11 @@ uint32 processed=0,subpacket_length=0;
break; break;
case OP_Packet: { 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)); uint16 seq=ntohs(*(uint16 *)(p->pBuffer));
SeqOrder check=CompareSequence(NextInSeq,seq); SeqOrder check=CompareSequence(NextInSeq,seq);
if (check == SeqFuture) { if (check == SeqFuture) {
@ -218,6 +223,11 @@ uint32 processed=0,subpacket_length=0;
break; break;
case OP_Fragment: { 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)); uint16 seq=ntohs(*(uint16 *)(p->pBuffer));
SeqOrder check=CompareSequence(NextInSeq,seq); SeqOrder check=CompareSequence(NextInSeq,seq);
if (check == SeqFuture) { if (check == SeqFuture) {
@ -284,6 +294,11 @@ uint32 processed=0,subpacket_length=0;
} }
break; break;
case OP_Ack: { 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 #ifndef COLLECTOR
uint16 seq=ntohs(*(uint16 *)(p->pBuffer)); uint16 seq=ntohs(*(uint16 *)(p->pBuffer));
AckPackets(seq); AckPackets(seq);
@ -383,6 +398,11 @@ uint32 processed=0,subpacket_length=0;
} }
break; break;
case OP_OutOfOrderAck: { 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 #ifndef COLLECTOR
uint16 seq=ntohs(*(uint16 *)(p->pBuffer)); uint16 seq=ntohs(*(uint16 *)(p->pBuffer));
MOutboundQueue.lock(); MOutboundQueue.lock();

View File

@ -1,5 +1,8 @@
EQExtractor2 Changelog. All changes since the 1.0 release. 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== ==04/24/2013==
Derision: Added decoder to support packet dumps from current Live client. SQL generation NOT SUPPORTED YET (need tweaks to position struct). Derision: Added decoder to support packet dumps from current Live client. SQL generation NOT SUPPORTED YET (need tweaks to position struct).

View File

@ -18,7 +18,7 @@ namespace EQExtractor2
{ {
public partial class EQExtractor2Form1 : Form 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 int PacketsSeen = 0;
static long BytesRead = 0; static long BytesRead = 0;

View File

@ -17,7 +17,224 @@ namespace EQExtractor2.Patches
PatchConfFileName = "patch_April15-2013.conf"; PatchConfFileName = "patch_April15-2013.conf";
SupportsSQLGeneration = false; SupportsSQLGeneration = true;
} }
override public List<ZoneEntryStruct> GetSpawns()
{
List<ZoneEntryStruct> ZoneSpawns = new List<ZoneEntryStruct>();
List<byte[]> 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;
}
} }
} }

View File

@ -275,7 +275,8 @@ void Merc::CalcItemBonuses(StatBonuses* newbon) {
if(equipment[i] == 0) if(equipment[i] == 0)
continue; continue;
const Item_Struct * itm = database.GetItem(equipment[i]); const Item_Struct * itm = database.GetItem(equipment[i]);
AddItemBonuses(itm, newbon); if(itm)
AddItemBonuses(itm, newbon);
} }
//Power Source Slot //Power Source Slot

View File

@ -284,9 +284,11 @@ int main(int argc, char** argv) {
} }
parse = new QuestParserCollection(); parse = new QuestParserCollection();
PerlXSParser *pxs = new PerlXSParser(); #ifdef EMBPERL
Parser *ps = new Parser(); PerlXSParser *pxs = new PerlXSParser();
parse->RegisterQuestInterface(pxs, "pl"); parse->RegisterQuestInterface(pxs, "pl");
#endif
Parser *ps = new Parser();
//parse->RegisterQuestInterface(ps, "qst"); //parse->RegisterQuestInterface(ps, "qst");
@ -473,7 +475,9 @@ int main(int argc, char** argv) {
entity_list.Clear(); entity_list.Clear();
safe_delete(parse); safe_delete(parse);
safe_delete(pxs); #ifdef EMBPERL
safe_delete(pxs);
#endif
safe_delete(ps); safe_delete(ps);
safe_delete(mmf); safe_delete(mmf);