mirror of
https://github.com/EQEmu/Server.git
synced 2026-04-25 02:02:25 +00:00
commit
70b6b5490c
@ -1,5 +1,18 @@
|
|||||||
EQEMu Changelog (Started on Sept 24, 2003 15:50)
|
EQEMu Changelog (Started on Sept 24, 2003 15:50)
|
||||||
-------------------------------------------------------
|
-------------------------------------------------------
|
||||||
|
|
||||||
|
== 04/27/2013 ==
|
||||||
|
Pixel Bounds: 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.
|
||||||
|
Bad_Captain: Removed unneeded bot pet AI.
|
||||||
|
Bad_Captain: Fixed a few bot aggro issues. (Uleat)
|
||||||
|
|
||||||
|
== 04/20/2013 ==
|
||||||
|
JJ: Fixed rare case where heals from buffs could go negative.
|
||||||
|
|
||||||
== 04/12/2013 ==
|
== 04/12/2013 ==
|
||||||
Derision: Moved entity_list.Clear() prior to destruction of Perl objects in zone shutdown as I was seeing a segfault due to attempts to call EVENT_HATE_LIST as mobs were being destroyed.
|
Derision: Moved entity_list.Clear() prior to destruction of Perl objects in zone shutdown as I was seeing a segfault due to attempts to call EVENT_HATE_LIST as mobs were being destroyed.
|
||||||
|
|
||||||
|
|||||||
@ -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];
|
||||||
|
|||||||
@ -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();
|
||||||
|
|||||||
@ -1,5 +1,11 @@
|
|||||||
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==
|
||||||
|
Derision: Added decoder to support packet dumps from current Live client. SQL generation NOT SUPPORTED YET (need tweaks to position struct).
|
||||||
|
|
||||||
==03/17/2013==
|
==03/17/2013==
|
||||||
Derision: Added SQL generation support to current Live client decoder.
|
Derision: Added SQL generation support to current Live client decoder.
|
||||||
|
|
||||||
|
|||||||
@ -105,6 +105,8 @@ namespace EQApplicationLayer
|
|||||||
|
|
||||||
PatchList.Add(new PatchMarch132013Decoder());
|
PatchList.Add(new PatchMarch132013Decoder());
|
||||||
|
|
||||||
|
PatchList.Add(new PatchApril152013Decoder());
|
||||||
|
|
||||||
PatchList.Add(new PatchSoD());
|
PatchList.Add(new PatchSoD());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -72,6 +72,7 @@
|
|||||||
<DependentUpon>LogForm.cs</DependentUpon>
|
<DependentUpon>LogForm.cs</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="OpcodeManager.cs" />
|
<Compile Include="OpcodeManager.cs" />
|
||||||
|
<Compile Include="PatchApril15-2013.cs" />
|
||||||
<Compile Include="PatchAug04-2011.cs" />
|
<Compile Include="PatchAug04-2011.cs" />
|
||||||
<Compile Include="PatchAugust15-2012.cs" />
|
<Compile Include="PatchAugust15-2012.cs" />
|
||||||
<Compile Include="PatchDec7-2010.cs" />
|
<Compile Include="PatchDec7-2010.cs" />
|
||||||
@ -137,6 +138,9 @@
|
|||||||
<DependentUpon>UserOptions.cs</DependentUpon>
|
<DependentUpon>UserOptions.cs</DependentUpon>
|
||||||
</EmbeddedResource>
|
</EmbeddedResource>
|
||||||
<None Include="app.config" />
|
<None Include="app.config" />
|
||||||
|
<None Include="patch_April15-2013.conf">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
<None Include="patch_Aug04-2011.conf">
|
<None Include="patch_Aug04-2011.conf">
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
|
|||||||
@ -18,7 +18,7 @@ namespace EQExtractor2
|
|||||||
{
|
{
|
||||||
public partial class EQExtractor2Form1 : Form
|
public partial class EQExtractor2Form1 : Form
|
||||||
{
|
{
|
||||||
string Version = "EQExtractor2 Version 2.6.2 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;
|
||||||
|
|||||||
240
utils/EQExtractor2/EQExtractor2/PatchApril15-2013.cs
Normal file
240
utils/EQExtractor2/EQExtractor2/PatchApril15-2013.cs
Normal file
@ -0,0 +1,240 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using EQExtractor2.InternalTypes;
|
||||||
|
using EQExtractor2.OpCodes;
|
||||||
|
using EQPacket;
|
||||||
|
using MyUtils;
|
||||||
|
|
||||||
|
namespace EQExtractor2.Patches
|
||||||
|
{
|
||||||
|
class PatchApril152013Decoder : PatchMarch132013Decoder
|
||||||
|
{
|
||||||
|
public PatchApril152013Decoder()
|
||||||
|
{
|
||||||
|
Version = "EQ Client Build Date April 15 2013.";
|
||||||
|
|
||||||
|
PatchConfFileName = "patch_April15-2013.conf";
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
653
utils/EQExtractor2/EQExtractor2/patch_April15-2013.conf
Normal file
653
utils/EQExtractor2/EQExtractor2/patch_April15-2013.conf
Normal file
@ -0,0 +1,653 @@
|
|||||||
|
# ShowEQ Import Notes:
|
||||||
|
# ZERO THE FILE first
|
||||||
|
# perl -pi -e 's/0x[0-9a-fA-F]{4}/0x0000/g' opcodes.conf
|
||||||
|
# Unknown Mapping:
|
||||||
|
# OP_Action2 -> OP_Damage
|
||||||
|
# OP_EnvDamage -> OP_Damage ---> might have been a one time mistake
|
||||||
|
# Name Differences:
|
||||||
|
# OP_CancelInvite -> OP_GroupCancelInvite
|
||||||
|
# OP_GMFind -> OP_FindPersonRequest
|
||||||
|
# OP_CommonMessage -> OP_ChannelMessage
|
||||||
|
|
||||||
|
OP_Unknown=0x0000
|
||||||
|
OP_ExploreUnknown=0x0000 used for unknown explorer
|
||||||
|
|
||||||
|
# world packets
|
||||||
|
# Required to reach Char Select:
|
||||||
|
OP_SendLoginInfo=0x5f21
|
||||||
|
OP_ApproveWorld=0x6604
|
||||||
|
OP_LogServer=0x27a4
|
||||||
|
OP_SendCharInfo=0x6b98
|
||||||
|
OP_ExpansionInfo=0x0322
|
||||||
|
OP_GuildsList=0x3d34
|
||||||
|
OP_EnterWorld=0x70c9
|
||||||
|
OP_PostEnterWorld=0x29f7
|
||||||
|
OP_World_Client_CRC1=0x0786
|
||||||
|
OP_World_Client_CRC2=0x77cd
|
||||||
|
OP_SendSpellChecksum=0x0000
|
||||||
|
OP_SendSkillCapsChecksum=0x0000
|
||||||
|
|
||||||
|
# Character Select Related:
|
||||||
|
OP_SendMaxCharacters=0x5a84
|
||||||
|
OP_SendMembership=0x3603
|
||||||
|
OP_SendMembershipDetails=0x3222
|
||||||
|
OP_CharacterCreateRequest=0x329a
|
||||||
|
OP_CharacterCreate=0x7f24
|
||||||
|
OP_DeleteCharacter=0x3078
|
||||||
|
OP_RandomNameGenerator=0x2617
|
||||||
|
OP_ApproveName=0x657d
|
||||||
|
OP_MOTD=0x0db2
|
||||||
|
OP_SetChatServer=0x6a13
|
||||||
|
OP_SetChatServer2=0x48a1
|
||||||
|
OP_ZoneServerInfo=0x4cae
|
||||||
|
OP_WorldComplete=0x1db8
|
||||||
|
OP_WorldUnknown001=0x5810
|
||||||
|
OP_FloatListThing=0x1ada
|
||||||
|
|
||||||
|
# Reasons for Disconnect:
|
||||||
|
OP_ZoneUnavail=0x2a10
|
||||||
|
OP_WorldClientReady=0x0b64
|
||||||
|
OP_CharacterStillInZone=0x0000
|
||||||
|
OP_WorldChecksumFailure=0x0000
|
||||||
|
OP_WorldLoginFailed=0x0000
|
||||||
|
OP_WorldLogout=0x0000
|
||||||
|
OP_WorldLevelTooHigh=0x0000
|
||||||
|
OP_CharInacessable=0x0000
|
||||||
|
OP_UserCompInfo=0x0000
|
||||||
|
OP_SendExeChecksum=0x0000
|
||||||
|
OP_SendBaseDataChecksum=0x0000
|
||||||
|
|
||||||
|
# Zone in opcodes
|
||||||
|
OP_AckPacket=0x58f7
|
||||||
|
OP_ZoneEntry=0x31d8
|
||||||
|
OP_ReqNewZone=0x3cb7
|
||||||
|
OP_NewZone=0x0bf6
|
||||||
|
OP_ZoneSpawns=0x36f6
|
||||||
|
OP_PlayerProfile=0x6b5b
|
||||||
|
OP_TimeOfDay=0x3377
|
||||||
|
OP_LevelUpdate=0x3e3c
|
||||||
|
OP_Stamina=0x5813
|
||||||
|
OP_RequestClientZoneChange=0x1b24
|
||||||
|
OP_ZoneChange=0x5538
|
||||||
|
OP_LockoutTimerInfo=0x0000
|
||||||
|
OP_ZoneServerReady=0x0000
|
||||||
|
OP_ZoneInUnknown=0x0000
|
||||||
|
OP_LogoutReply=0x0000
|
||||||
|
OP_PreLogoutReply=0x0000
|
||||||
|
|
||||||
|
# Required to fully log in
|
||||||
|
OP_SpawnAppearance=0x130f
|
||||||
|
OP_ChangeSize=0x3619
|
||||||
|
OP_TributeUpdate=0x365d
|
||||||
|
OP_TributeTimer=0x7ea7
|
||||||
|
OP_SendTributes=0x57f5
|
||||||
|
OP_SendGuildTributes=0x430c
|
||||||
|
OP_TributeInfo=0x3c65
|
||||||
|
OP_Weather=0x4ec0
|
||||||
|
OP_ReqClientSpawn=0x16ca
|
||||||
|
OP_SpawnDoor=0x375d
|
||||||
|
OP_GroundSpawn=0x3a2b
|
||||||
|
OP_SendZonepoints=0x41b8
|
||||||
|
OP_BlockedBuffs=0x52b5
|
||||||
|
OP_RemoveBlockedBuffs=0x5884
|
||||||
|
OP_ClearBlockedBuffs=0x565c
|
||||||
|
OP_WorldObjectsSent=0x37d3
|
||||||
|
OP_SendExpZonein=0x7d57
|
||||||
|
OP_SendAATable=0x65c4
|
||||||
|
OP_RespondAA=0x0b69
|
||||||
|
OP_UpdateAA=0x67e0
|
||||||
|
OP_SendAAStats=0x702d
|
||||||
|
OP_AAExpUpdate=0x4616
|
||||||
|
OP_ExpUpdate=0x39a0
|
||||||
|
OP_HPUpdate=0x648b
|
||||||
|
OP_ManaChange=0x2ed8
|
||||||
|
OP_TGB=0x6516
|
||||||
|
OP_SpecialMesg=0x0000
|
||||||
|
OP_GuildMemberList=0x2bad
|
||||||
|
OP_GuildMOTD=0x4e44
|
||||||
|
OP_CharInventory=0x3deb
|
||||||
|
OP_WearChange=0x1ff6
|
||||||
|
OP_ClientUpdate=0x6962
|
||||||
|
OP_ClientReady=0x0c66 # 0x422d
|
||||||
|
OP_SetServerFilter=0x3b5b
|
||||||
|
|
||||||
|
# Guild Opcodes - Disabled until crashes are resolved in RoF
|
||||||
|
OP_GetGuildMOTD=0x6ce8 # Was 0x35dc
|
||||||
|
OP_GetGuildMOTDReply=0x150b # Was 0x4586
|
||||||
|
OP_GuildMemberUpdate=0x665a # Was 0x5643
|
||||||
|
OP_GuildInvite=0x3834
|
||||||
|
OP_GuildRemove=0x1eb3
|
||||||
|
OP_GuildPeace=0x5b6e
|
||||||
|
OP_SetGuildMOTD=0x183e
|
||||||
|
OP_GuildList=0x0000
|
||||||
|
OP_GuildWar=0x7e3d
|
||||||
|
OP_GuildLeader=0x0c63
|
||||||
|
OP_GuildDelete=0x1e22
|
||||||
|
OP_GuildInviteAccept=0x3462
|
||||||
|
OP_GuildDemote=0x47ed
|
||||||
|
OP_GuildPublicNote=0x6208
|
||||||
|
OP_GuildManageBanker=0x2010 # Was 0x0737
|
||||||
|
OP_GuildBank=0x3d39 # Was 0x10c3
|
||||||
|
OP_SetGuildRank=0x671c
|
||||||
|
OP_GuildUpdateURLAndChannel=0x31fc
|
||||||
|
OP_GuildStatus=0x7b81
|
||||||
|
OP_GuildCreate=0x52c7 # or maybe 0x086e
|
||||||
|
OP_GuildMemberLevelUpdate=0x0000 # Unused?
|
||||||
|
OP_ZoneGuildList=0x0000 # Unused?
|
||||||
|
OP_GetGuildsList=0x0000 # Unused?
|
||||||
|
OP_LFGuild=0x0000
|
||||||
|
OP_GuildManageRemove=0x0000
|
||||||
|
OP_GuildManageAdd=0x0000
|
||||||
|
OP_GuildManageStatus=0x0000
|
||||||
|
|
||||||
|
# GM/Guide Opcodes
|
||||||
|
OP_GMServers=0x4946
|
||||||
|
OP_GMBecomeNPC=0x2b92
|
||||||
|
OP_GMZoneRequest=0x7a65
|
||||||
|
OP_GMZoneRequest2=0x5585
|
||||||
|
OP_GMGoto=0x15b4
|
||||||
|
OP_GMSearchCorpse=0x594b
|
||||||
|
OP_GMHideMe=0x0005
|
||||||
|
OP_GMDelCorpse=0x0633
|
||||||
|
OP_GMApproval=0x4bbf
|
||||||
|
OP_GMToggle=0x5e6f
|
||||||
|
OP_GMSummon=0x7b50 # Was 0x684f
|
||||||
|
OP_GMEmoteZone=0x735a # Was 0x0655
|
||||||
|
OP_GMEmoteWorld=0x2114 # Was 0x1935
|
||||||
|
OP_GMFind=0x4e59
|
||||||
|
OP_GMKick=0x5c02
|
||||||
|
OP_GMKill=0x2728
|
||||||
|
OP_GMNameChange=0x7b23 # Was 0x4434
|
||||||
|
OP_GMLastName=0x1063 # Was 0x3077
|
||||||
|
|
||||||
|
# Misc Opcodes
|
||||||
|
OP_InspectRequest=0x5d21
|
||||||
|
OP_InspectAnswer=0x5569
|
||||||
|
OP_InspectMessageUpdate=0x09cd
|
||||||
|
OP_BeginCast=0x557a
|
||||||
|
OP_BuffFadeMsg=0x6226
|
||||||
|
OP_ConsentResponse=0x0333
|
||||||
|
OP_MemorizeSpell=0x7bc9
|
||||||
|
OP_SwapSpell=0x3217
|
||||||
|
OP_CastSpell=0x3f6d
|
||||||
|
OP_Consider=0x3815
|
||||||
|
OP_FormattedMessage=0x52c0
|
||||||
|
OP_SimpleMessage=0x0e29
|
||||||
|
OP_Buff=0x0dd5
|
||||||
|
OP_Illusion=0x1182
|
||||||
|
OP_MoneyOnCorpse=0x05e8
|
||||||
|
OP_RandomReply=0x4b1a
|
||||||
|
OP_DenyResponse=0x3918
|
||||||
|
OP_SkillUpdate=0x4b94
|
||||||
|
OP_GMTrainSkillConfirm=0x0498 # 0x3960
|
||||||
|
OP_RandomReq=0x4629
|
||||||
|
OP_Death=0x1aa0
|
||||||
|
OP_GMTraining=0x698c
|
||||||
|
OP_GMEndTraining=0x36dc
|
||||||
|
OP_GMTrainSkill=0x580c
|
||||||
|
OP_Animation=0x172f
|
||||||
|
OP_Begging=0x39a6
|
||||||
|
OP_Consent=0x2c4e
|
||||||
|
OP_ConsentDeny=0x69bb
|
||||||
|
OP_AutoFire=0x086e
|
||||||
|
OP_PetCommands=0x17bc
|
||||||
|
OP_DeleteSpell=0x709b
|
||||||
|
OP_Surname=0x0329
|
||||||
|
OP_ClearSurname=0x6182
|
||||||
|
OP_FaceChange=0x6b0e
|
||||||
|
OP_SenseHeading=0x12cf
|
||||||
|
OP_Action=0x7329
|
||||||
|
OP_ConsiderCorpse=0x28ed
|
||||||
|
OP_HideCorpse=0x0179
|
||||||
|
OP_CorpseDrag=0x47d9
|
||||||
|
OP_CorpseDrop=0x0df7
|
||||||
|
OP_Bug=0x51a4
|
||||||
|
OP_Feedback=0x2061
|
||||||
|
OP_Report=0x4c00
|
||||||
|
OP_Damage=0x4725
|
||||||
|
OP_ChannelMessage=0x0dc9
|
||||||
|
OP_Assist=0x68d3
|
||||||
|
OP_AssistGroup=0x6c10
|
||||||
|
OP_MoveCoin=0x37b3
|
||||||
|
OP_ZonePlayerToBind=0x36ad
|
||||||
|
OP_KeyRing=0x7ac2
|
||||||
|
OP_WhoAllRequest=0x7cf3
|
||||||
|
OP_WhoAllResponse=0x14cc
|
||||||
|
OP_FriendsWho=0x7ee9
|
||||||
|
OP_ConfirmDelete=0x13c1
|
||||||
|
OP_Logout=0x226f
|
||||||
|
OP_Rewind=0x7562
|
||||||
|
OP_TargetCommand=0x3bd6
|
||||||
|
OP_Hide=0x4517
|
||||||
|
OP_Jump=0x1dbf
|
||||||
|
OP_Camp=0x6aa7
|
||||||
|
OP_Emote=0x6195
|
||||||
|
OP_SetRunMode=0x068d
|
||||||
|
OP_BankerChange=0x4d5b
|
||||||
|
OP_TargetMouse=0x3f43
|
||||||
|
OP_MobHealth=0x52dc
|
||||||
|
OP_InitialMobHealth=0x0000 # Unused?
|
||||||
|
OP_TargetHoTT=0x2baa
|
||||||
|
OP_XTargetResponse=0x0be2
|
||||||
|
OP_XTargetRequest=0x024c
|
||||||
|
OP_XTargetAutoAddHaters=0x3729
|
||||||
|
OP_TargetBuffs=0x241c
|
||||||
|
OP_BuffCreate=0x6878
|
||||||
|
OP_BuffRemoveRequest=0x78ab
|
||||||
|
OP_DeleteSpawn=0x5279
|
||||||
|
OP_AutoAttack=0x1bf5
|
||||||
|
OP_AutoAttack2=0x0ce9
|
||||||
|
OP_Consume=0x7711
|
||||||
|
OP_MoveItem=0x2bb9
|
||||||
|
OP_DeleteItem=0x5c68
|
||||||
|
OP_DeleteCharge=0x7660
|
||||||
|
OP_ItemPacket=0x154e
|
||||||
|
OP_ItemLinkResponse=0x62f9
|
||||||
|
OP_ItemLinkClick=0x53c8
|
||||||
|
OP_ItemPreview=0x0ee7
|
||||||
|
OP_NewSpawn=0x61e9
|
||||||
|
OP_Track=0x7f7a
|
||||||
|
OP_TrackTarget=0x4190
|
||||||
|
OP_TrackUnknown=0x3a5e
|
||||||
|
OP_ClickDoor=0x349b
|
||||||
|
OP_MoveDoor=0x4920
|
||||||
|
OP_RemoveAllDoors=0x6542
|
||||||
|
OP_EnvDamage=0x7912
|
||||||
|
OP_BoardBoat=0x6a35
|
||||||
|
OP_Forage=0x7621
|
||||||
|
OP_LeaveBoat=0x7251
|
||||||
|
OP_ControlBoat=0x5635
|
||||||
|
OP_SafeFallSuccess=0x3358
|
||||||
|
OP_RezzComplete=0x570d
|
||||||
|
OP_RezzRequest=0x3e8b
|
||||||
|
OP_RezzAnswer=0x77c7
|
||||||
|
OP_Shielding=0x3f0b
|
||||||
|
OP_RequestDuel=0x0a38
|
||||||
|
OP_MobRename=0x2638
|
||||||
|
OP_AugmentItem=0x4695 # Was 0x37cb
|
||||||
|
OP_WeaponEquip1=0x1d1d
|
||||||
|
OP_WeaponEquip2=0x6147 # Was 0x6022
|
||||||
|
OP_WeaponUnequip2=0x4b3e # Was 0x0110
|
||||||
|
OP_ApplyPoison=0x1b5b
|
||||||
|
OP_Save=0x6444
|
||||||
|
OP_TestBuff=0x2c3c # Was 0x3772
|
||||||
|
OP_CustomTitles=0x61ab
|
||||||
|
OP_Split=0x3dff
|
||||||
|
OP_YellForHelp=0x694a
|
||||||
|
OP_LoadSpellSet=0x5d60
|
||||||
|
OP_Bandolier=0x1d9d
|
||||||
|
OP_PotionBelt=0x5499 # Was 0x4d3b
|
||||||
|
OP_DuelResponse=0x3a06
|
||||||
|
OP_DuelResponse2=0x7929
|
||||||
|
OP_SaveOnZoneReq=0x0b2e
|
||||||
|
OP_ReadBook=0x1b02
|
||||||
|
OP_Dye=0x0999
|
||||||
|
OP_InterruptCast=0x57e1
|
||||||
|
OP_AAAction=0x3994
|
||||||
|
OP_LeadershipExpToggle=0x2746
|
||||||
|
OP_LeadershipExpUpdate=0x0fdc
|
||||||
|
OP_PurchaseLeadershipAA=0x0f78
|
||||||
|
OP_UpdateLeadershipAA=0x4ef0
|
||||||
|
OP_MarkNPC=0x70e1
|
||||||
|
OP_ClearNPCMarks=0x643a
|
||||||
|
OP_DelegateAbility=0x2aa5
|
||||||
|
OP_SetGroupTarget=0x19d0
|
||||||
|
OP_Charm=0x5221
|
||||||
|
OP_Stun=0x5826
|
||||||
|
OP_SendFindableNPCs=0x743b
|
||||||
|
OP_FindPersonRequest=0x3560
|
||||||
|
OP_FindPersonReply=0x0844
|
||||||
|
OP_Sound=0x1b73
|
||||||
|
OP_PetBuffWindow=0x56c0
|
||||||
|
OP_LevelAppearance=0x6698
|
||||||
|
OP_Translocate=0x091a
|
||||||
|
OP_Sacrifice=0x5b22
|
||||||
|
OP_PopupResponse=0x1475
|
||||||
|
OP_OnLevelMessage=0x1cbd
|
||||||
|
OP_AugmentInfo=0x6524
|
||||||
|
OP_Petition=0x3b76
|
||||||
|
OP_SomeItemPacketMaybe=0x0668
|
||||||
|
OP_PVPStats=0x3388 # Unsure
|
||||||
|
OP_PVPLeaderBoardRequest=0x2852
|
||||||
|
OP_PVPLeaderBoardReply=0x65cf
|
||||||
|
OP_PVPLeaderBoardDetailsRequest=0x1d11
|
||||||
|
OP_PVPLeaderBoardDetailsReply=0x1a8e
|
||||||
|
OP_RestState=0x3018
|
||||||
|
OP_RespawnWindow=0x7b02
|
||||||
|
OP_LDoNButton=0x4438
|
||||||
|
OP_SetStartCity=0x2121 # Was 0x2d1b
|
||||||
|
OP_VoiceMacroIn=0x6f3d
|
||||||
|
OP_VoiceMacroOut=0x0577
|
||||||
|
OP_ItemViewUnknown=0x31a8
|
||||||
|
OP_VetRewardsAvaliable=0x0687
|
||||||
|
OP_VetClaimRequest=0x0407
|
||||||
|
OP_VetClaimReply=0x1ef4
|
||||||
|
OP_DisciplineUpdate=0x06da # Was 0x2f05
|
||||||
|
OP_DisciplineTimer=0x2a91 # Was 0x5e3f
|
||||||
|
OP_BecomeCorpse=0x0000 # Unused?
|
||||||
|
OP_Action2=0x0000 # Unused?
|
||||||
|
OP_MobUpdate=0x6d4b
|
||||||
|
OP_NPCMoveUpdate=0x5a39
|
||||||
|
OP_CameraEffect=0x5099
|
||||||
|
OP_SpellEffect=0x1e99
|
||||||
|
OP_RemoveNimbusEffect=0x29af
|
||||||
|
OP_AltCurrency=0x797d
|
||||||
|
OP_AltCurrencyMerchantRequest=0x5132
|
||||||
|
OP_AltCurrencyMerchantReply=0x7ec5
|
||||||
|
OP_AltCurrencyPurchase=0x6731
|
||||||
|
OP_AltCurrencySell=0x5420
|
||||||
|
OP_AltCurrencySellSelection=0x6fed
|
||||||
|
OP_AltCurrencyReclaim=0x5eda
|
||||||
|
OP_CrystalCountUpdate=0x3b26 # Was 0x3f60
|
||||||
|
OP_CrystalCreate=0x39ed # Was 0x5a82
|
||||||
|
OP_CrystalReclaim=0x369e # Was 0x7616
|
||||||
|
OP_Untargetable=0x6c0b
|
||||||
|
OP_IncreaseStats=0x757b
|
||||||
|
OP_Weblink=0x4173
|
||||||
|
#OP_OpenInventory=0x0000 # Likely does not exist in RoF -U
|
||||||
|
OP_OpenContainer=0x0000
|
||||||
|
|
||||||
|
OP_DzQuit=0x7579
|
||||||
|
OP_DzListTimers=0x00e5
|
||||||
|
OP_DzAddPlayer=0x070f
|
||||||
|
OP_DzRemovePlayer=0x11eb
|
||||||
|
OP_DzSwapPlayer=0x72fe
|
||||||
|
OP_DzMakeLeader=0x3904
|
||||||
|
OP_DzPlayerList=0x20a4
|
||||||
|
OP_DzJoinExpeditionConfirm=0x1c57
|
||||||
|
OP_DzJoinExpeditionReply=0x3274
|
||||||
|
OP_DzExpeditionInfo=0xe86b
|
||||||
|
OP_DzExpeditionList=0x1349
|
||||||
|
OP_DzMemberStatus=0x638e
|
||||||
|
OP_DzLeaderStatus=0x39cf
|
||||||
|
OP_DzExpeditionEndsWarning=0x44eb
|
||||||
|
OP_DzMemberList=0x0000
|
||||||
|
OP_DzCompass=0x5baa # Was 0x4f09
|
||||||
|
OP_DzChooseZone=0x0000 # Maybe 0x29d6
|
||||||
|
|
||||||
|
# New Opcodes
|
||||||
|
OP_SpawnPositionUpdate=0x0000 # Actually OP_MobUpdate ?
|
||||||
|
OP_ManaUpdate=0x4c12
|
||||||
|
OP_EnduranceUpdate=0x250e
|
||||||
|
OP_MobManaUpdate=0x230a
|
||||||
|
OP_MobEnduranceUpdate=0x7012
|
||||||
|
|
||||||
|
# Mercenary Opcodes
|
||||||
|
OP_MercenaryDataUpdateRequest=0x1d60
|
||||||
|
OP_MercenaryDataUpdate=0x0c2d
|
||||||
|
OP_MercenaryDataRequest=0x8fa2
|
||||||
|
OP_MercenaryDataResponse=0x6a0c
|
||||||
|
OP_MercenaryHire=0x05bd
|
||||||
|
OP_MercenaryDismiss=0x376f
|
||||||
|
OP_MercenaryTimerRequest=0x293d
|
||||||
|
OP_MercenaryTimer=0x3f92
|
||||||
|
OP_MercenaryUnknown1=0x1c14
|
||||||
|
OP_MercenaryCommand=0x26b9
|
||||||
|
OP_MercenarySuspendRequest=0x4b19
|
||||||
|
OP_MercenarySuspendResponse=0x0830
|
||||||
|
OP_MercenaryUnsuspendResponse=0x4405
|
||||||
|
|
||||||
|
# Looting
|
||||||
|
OP_LootRequest=0x52ba
|
||||||
|
OP_EndLootRequest=0x0573
|
||||||
|
OP_LootItem=0x2344
|
||||||
|
OP_LootComplete=0x71c6
|
||||||
|
|
||||||
|
# bazaar trader stuff:
|
||||||
|
OP_BazaarSearch=0x6c36
|
||||||
|
OP_TraderDelItem=0x0000
|
||||||
|
OP_BecomeTrader=0x081e
|
||||||
|
OP_TraderShop=0x327c
|
||||||
|
OP_Trader=0x2284 # Was 0x6790
|
||||||
|
OP_TraderBuy=0x0000
|
||||||
|
OP_Barter=0x241f
|
||||||
|
OP_ShopItem=0x0000
|
||||||
|
OP_BazaarInspect=0x0000
|
||||||
|
OP_Bazaar=0x0000
|
||||||
|
OP_TraderItemUpdate=0x0000
|
||||||
|
|
||||||
|
# pc/npc trading
|
||||||
|
OP_TradeRequest=0x164e
|
||||||
|
OP_TradeAcceptClick=0x61eb
|
||||||
|
OP_TradeRequestAck=0x76c1
|
||||||
|
OP_TradeCoins=0x582b
|
||||||
|
OP_FinishTrade=0x6bba
|
||||||
|
OP_CancelTrade=0x5a9f
|
||||||
|
OP_TradeMoneyUpdate=0x2432
|
||||||
|
OP_MoneyUpdate=0x52e5
|
||||||
|
OP_TradeBusy=0x6482
|
||||||
|
|
||||||
|
# Sent after canceling trade or after closing tradeskill object
|
||||||
|
OP_FinishWindow=0x5ea3
|
||||||
|
OP_FinishWindow2=0x6177
|
||||||
|
|
||||||
|
# Sent on Live for what seems to be item existance verification
|
||||||
|
# Ex. Before Right Click Effect happens from items
|
||||||
|
OP_ItemVerifyRequest=0x49fc
|
||||||
|
OP_ItemVerifyReply=0x0061
|
||||||
|
|
||||||
|
# merchant stuff
|
||||||
|
OP_ShopPlayerSell=0x1961
|
||||||
|
OP_ShopRequest=0x393f
|
||||||
|
OP_ShopEnd=0x7385
|
||||||
|
OP_ShopEndConfirm=0x2ed5
|
||||||
|
OP_ShopPlayerBuy=0x0f9d
|
||||||
|
OP_ShopDelItem=0x78d2
|
||||||
|
|
||||||
|
# tradeskill stuff:
|
||||||
|
OP_ClickObject=0x6cb6
|
||||||
|
OP_ClickObjectAction=0x5d27
|
||||||
|
OP_ClearObject=0x3a64
|
||||||
|
OP_RecipeDetails=0x2d9b
|
||||||
|
OP_RecipesFavorite=0x2875
|
||||||
|
OP_RecipesSearch=0x5013
|
||||||
|
OP_RecipeReply=0x4161
|
||||||
|
OP_RecipeAutoCombine=0x74ac
|
||||||
|
OP_TradeSkillCombine=0x48fd
|
||||||
|
|
||||||
|
# Tribute Packets:
|
||||||
|
OP_OpenGuildTributeMaster=0x5ba2
|
||||||
|
OP_OpenTributeMaster=0x6c0f # Was 0x40f5
|
||||||
|
OP_SelectTribute=0x003e
|
||||||
|
OP_TributeItem=0x07cd
|
||||||
|
OP_TributeMoney=0x2f60 # Was 0x6fed
|
||||||
|
OP_TributeToggle=0x420c
|
||||||
|
OP_TributePointUpdate=0x5552
|
||||||
|
OP_TributeNPC=0x0000
|
||||||
|
OP_GuildTributeInfo=0x0000
|
||||||
|
OP_OpenTributeReply=0x0000
|
||||||
|
OP_GuildTributeStatus=0x0000
|
||||||
|
|
||||||
|
# Adventure packets:
|
||||||
|
OP_LeaveAdventure=0x234c
|
||||||
|
OP_AdventureFinish=0x33a0
|
||||||
|
OP_AdventureInfoRequest=0x00af
|
||||||
|
OP_AdventureInfo=0x6a8c
|
||||||
|
OP_AdventureRequest=0x1c3b
|
||||||
|
OP_AdventureDetails=0x4b02
|
||||||
|
OP_AdventureData=0x0e46
|
||||||
|
OP_AdventureUpdate=0x724c
|
||||||
|
OP_AdventureMerchantRequest=0x6d4f # Was 654d
|
||||||
|
OP_AdventureMerchantResponse=0x7d2d # Was 7949
|
||||||
|
OP_AdventureMerchantPurchase=0x3afc # Was 155a
|
||||||
|
OP_AdventureMerchantSell=0x19eb # Was 389c
|
||||||
|
OP_AdventurePointsUpdate=0x7df1 # Was 7589
|
||||||
|
OP_AdventureStatsRequest=0x0dc1
|
||||||
|
OP_AdventureStatsReply=0x7ca8
|
||||||
|
OP_AdventureLeaderboardRequest=0x4769
|
||||||
|
OP_AdventureLeaderboardReply=0x08fc
|
||||||
|
|
||||||
|
# Group Opcodes
|
||||||
|
OP_GroupDisband=0x4e45
|
||||||
|
OP_GroupInvite=0x1694
|
||||||
|
OP_GroupFollow=0x6246
|
||||||
|
OP_GroupUpdate=0x31c8
|
||||||
|
OP_GroupUpdateB=0x13cd
|
||||||
|
OP_GroupCancelInvite=0x0000
|
||||||
|
OP_GroupAcknowledge=0x4dbe
|
||||||
|
OP_GroupDelete=0x6d6b
|
||||||
|
OP_CancelInvite=0x6417
|
||||||
|
OP_GroupFollow2=0x26fc
|
||||||
|
OP_GroupInvite2=0x6232
|
||||||
|
OP_GroupDisbandYou=0x14ca
|
||||||
|
OP_GroupDisbandOther=0x0f0b
|
||||||
|
OP_GroupLeaderChange=0x1cdb
|
||||||
|
OP_GroupRoles=0x75de
|
||||||
|
OP_GroupMakeLeader=0x24b9
|
||||||
|
OP_DoGroupLeadershipAbility=0x46df
|
||||||
|
OP_GroupLeadershipAAUpdate=0x3b89
|
||||||
|
|
||||||
|
# LFG/LFP Opcodes
|
||||||
|
OP_LFGCommand=0x4719
|
||||||
|
OP_LFGGetMatchesRequest=0x78db
|
||||||
|
OP_LFGGetMatchesResponse=0x36b4
|
||||||
|
OP_LFPGetMatchesRequest=0x5ef8
|
||||||
|
OP_LFPGetMatchesResponse=0x1c19
|
||||||
|
OP_LFPCommand=0x00f4
|
||||||
|
OP_LFGAppearance=0x0000
|
||||||
|
OP_LFGResponse=0x0000
|
||||||
|
|
||||||
|
# Raid Opcodes
|
||||||
|
OP_RaidInvite=0x1419
|
||||||
|
OP_RaidUpdate=0x5191
|
||||||
|
OP_RaidJoin=0x0000
|
||||||
|
|
||||||
|
# Button-push commands
|
||||||
|
OP_Taunt=0x1fbe
|
||||||
|
OP_CombatAbility=0x11c2
|
||||||
|
OP_SenseTraps=0x713b # Was 0x2ee0
|
||||||
|
OP_PickPocket=0x5229
|
||||||
|
OP_DisarmTraps=0x0000
|
||||||
|
OP_Disarm=0x5482
|
||||||
|
OP_Sneak=0x209e
|
||||||
|
OP_Fishing=0x3520
|
||||||
|
OP_InstillDoubt=0x5e78
|
||||||
|
OP_FeignDeath=0x0258
|
||||||
|
OP_Mend=0x742c
|
||||||
|
OP_Bind_Wound=0x5f4d
|
||||||
|
OP_LDoNOpen=0x0621
|
||||||
|
|
||||||
|
# Task packets
|
||||||
|
OP_TaskDescription=0x3c8f
|
||||||
|
OP_TaskActivity=0x6140
|
||||||
|
OP_CompletedTasks=0x7b7c
|
||||||
|
OP_TaskActivityComplete=0x6bb5
|
||||||
|
OP_AcceptNewTask=0x5d0e
|
||||||
|
OP_CancelTask=0x2f6c
|
||||||
|
OP_TaskMemberList=0x16f5 # Was 0x1656
|
||||||
|
OP_OpenNewTasksWindow=0x065c # Was 0x11de
|
||||||
|
OP_AvaliableTask=0x5ed2 # Was 0x2377
|
||||||
|
OP_TaskHistoryRequest=0x2da2
|
||||||
|
OP_TaskHistoryReply=0x2cc2
|
||||||
|
OP_DeclineAllTasks=0x0000
|
||||||
|
|
||||||
|
# Title opcodes
|
||||||
|
OP_NewTitlesAvailable=0x7705
|
||||||
|
OP_RequestTitles=0x6cde
|
||||||
|
OP_SendTitleList=0x12cc
|
||||||
|
OP_SetTitle=0x0bda
|
||||||
|
OP_SetTitleReply=0x05b3
|
||||||
|
|
||||||
|
# mail opcodes
|
||||||
|
OP_Command=0x0000
|
||||||
|
OP_MailboxHeader=0x0000
|
||||||
|
OP_MailHeader=0x0000
|
||||||
|
OP_MailBody=0x0000
|
||||||
|
OP_NewMail=0x0000
|
||||||
|
OP_SentConfirm=0x0000
|
||||||
|
|
||||||
|
########### Below this point should not be needed ###########
|
||||||
|
|
||||||
|
# This section are all unknown in Titanium
|
||||||
|
OP_ForceFindPerson=0x0000
|
||||||
|
OP_LocInfo=0x0000
|
||||||
|
OP_ReloadUI=0x0000
|
||||||
|
OP_ItemName=0x0000
|
||||||
|
OP_ItemLinkText=0x0000
|
||||||
|
OP_MultiLineMsg=0x0000
|
||||||
|
OP_MendHPUpdate=0x0000
|
||||||
|
OP_TargetReject=0x0000
|
||||||
|
OP_SafePoint=0x0000
|
||||||
|
OP_ApproveZone=0x0000
|
||||||
|
OP_ZoneComplete=0x0000
|
||||||
|
OP_ClientError=0x0000
|
||||||
|
OP_DumpName=0x0000
|
||||||
|
OP_Heartbeat=0x0000
|
||||||
|
OP_CrashDump=0x0000
|
||||||
|
OP_LoginComplete=0x0000
|
||||||
|
|
||||||
|
# discovered opcodes not yet used:
|
||||||
|
OP_PickLockSuccess=0x0000
|
||||||
|
OP_PlayMP3=0x0000
|
||||||
|
OP_ReclaimCrystals=0x0000
|
||||||
|
OP_DynamicWall=0x0000
|
||||||
|
OP_OpenDiscordMerchant=0x0000
|
||||||
|
OP_DiscordMerchantInventory=0x0000
|
||||||
|
OP_GiveMoney=0x0000
|
||||||
|
OP_RequestKnowledgeBase=0x0000
|
||||||
|
OP_KnowledgeBase=0x0000
|
||||||
|
OP_SlashAdventure=0x0000 # /adventure
|
||||||
|
OP_BecomePVPPrompt=0x0000
|
||||||
|
OP_MoveLogRequest=0x0000 # gone I think
|
||||||
|
OP_MoveLogDisregard=0x0000 # gone I think
|
||||||
|
|
||||||
|
# named unknowns, to make looking for real unknown easier
|
||||||
|
OP_AnnoyingZoneUnknown=0x0000
|
||||||
|
OP_Some6ByteHPUpdate=0x0000 seems to happen when you target group members
|
||||||
|
OP_QueryResponseThing=0x0000
|
||||||
|
|
||||||
|
|
||||||
|
# realityincarnate: these are just here to stop annoying several thousand byte packet dumps
|
||||||
|
#OP_LoginUnknown1=0x46d3 # OP_SendSpellChecksum
|
||||||
|
#OP_LoginUnknown2=0x040b # OP_SendSkillCapsChecksum
|
||||||
|
|
||||||
|
# Petition Opcodes
|
||||||
|
OP_PetitionSearch=0x0000 search term for petition
|
||||||
|
OP_PetitionSearchResults=0x0000 (list of?) matches from search
|
||||||
|
OP_PetitionSearchText=0x0000 text results of search
|
||||||
|
|
||||||
|
OP_PetitionUpdate=0x0000
|
||||||
|
OP_PetitionCheckout=0x0000
|
||||||
|
OP_PetitionCheckIn=0x0000
|
||||||
|
OP_PetitionQue=0x0000
|
||||||
|
OP_PetitionUnCheckout=0x0000
|
||||||
|
OP_PetitionDelete=0x0000
|
||||||
|
OP_DeletePetition=0x0000
|
||||||
|
OP_PetitionResolve=0x0000
|
||||||
|
OP_PDeletePetition=0x0000
|
||||||
|
OP_PetitionBug=0x0000
|
||||||
|
OP_PetitionRefresh=0x0000
|
||||||
|
OP_PetitionCheckout2=0x0000
|
||||||
|
OP_PetitionViewPetition=0x0000
|
||||||
|
|
||||||
|
# Login opcodes
|
||||||
|
OP_SessionReady=0x0000
|
||||||
|
OP_Login=0x0000
|
||||||
|
OP_ServerListRequest=0x0000
|
||||||
|
OP_PlayEverquestRequest=0x0000
|
||||||
|
OP_PlayEverquestResponse=0x0000
|
||||||
|
OP_ChatMessage=0x0000
|
||||||
|
OP_LoginAccepted=0x0000
|
||||||
|
OP_ServerListResponse=0x0000
|
||||||
|
OP_Poll=0x0000
|
||||||
|
OP_EnterChat=0x0000
|
||||||
|
OP_PollResponse=0x0000
|
||||||
|
|
||||||
|
# raw opcodes
|
||||||
|
OP_RAWSessionRequest=0x0000
|
||||||
|
OP_RAWSessionResponse=0x0000
|
||||||
|
OP_RAWCombined=0x0000
|
||||||
|
OP_RAWSessionDisconnect=0x0000
|
||||||
|
OP_RAWKeepAlive=0x0000
|
||||||
|
OP_RAWSessionStatRequest=0x0000
|
||||||
|
OP_RAWSessionStatResponse=0x0000
|
||||||
|
OP_RAWPacket=0x0000
|
||||||
|
OP_RAWFragment=0x0000
|
||||||
|
OP_RAWOutOfOrderAck=0x0000
|
||||||
|
OP_RAWAck=0x0000
|
||||||
|
OP_RAWAppCombined=0x0000
|
||||||
|
OP_RAWOutOfSession=0x0000
|
||||||
|
|
||||||
|
# we need to document the differences between these packets to make identifying them easier
|
||||||
|
OP_Some3ByteHPUpdate=0x0000 # initial HP update for mobs
|
||||||
|
OP_InitialHPUpdate=0x0000
|
||||||
272
world/client.cpp
272
world/client.cpp
@ -368,46 +368,9 @@ void Client::SendPostEnterWorld() {
|
|||||||
safe_delete(outapp);
|
safe_delete(outapp);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Client::HandlePacket(const EQApplicationPacket *app) {
|
bool Client::HandleSendLoginInfoPacket(const EQApplicationPacket *app) {
|
||||||
const WorldConfig *Config=WorldConfig::get();
|
|
||||||
EmuOpcode opcode = app->GetOpcode();
|
|
||||||
|
|
||||||
clog(WORLD__CLIENT_TRACE,"Recevied EQApplicationPacket");
|
|
||||||
_pkt(WORLD__CLIENT_TRACE,app);
|
|
||||||
|
|
||||||
bool ret = true;
|
|
||||||
|
|
||||||
if (!eqs->CheckState(ESTABLISHED)) {
|
|
||||||
clog(WORLD__CLIENT,"Client disconnected (net inactive on send)");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Voidd: Anti-GM Account hack, Checks source ip against valid GM Account IP Addresses
|
|
||||||
if (RuleB(World, GMAccountIPList) && this->GetAdmin() >= (RuleI(World, MinGMAntiHackStatus))) {
|
|
||||||
if(!database.CheckGMIPs(long2ip(this->GetIP()).c_str(), this->GetAccountID())) {
|
|
||||||
clog(WORLD__CLIENT,"GM Account not permited from source address %s and accountid %i", long2ip(this->GetIP()).c_str(), this->GetAccountID());
|
|
||||||
eqs->Close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (GetAccountID() == 0 && opcode != OP_SendLoginInfo) {
|
|
||||||
// Got a packet other than OP_SendLoginInfo when not logged in
|
|
||||||
clog(WORLD__CLIENT_ERR,"Expecting OP_SendLoginInfo, got %s", OpcodeNames[opcode]);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else if (opcode == OP_AckPacket) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(opcode)
|
|
||||||
{
|
|
||||||
case OP_CrashDump:
|
|
||||||
break;
|
|
||||||
case OP_SendLoginInfo:
|
|
||||||
{
|
|
||||||
if (app->size != sizeof(LoginInfo_Struct)) {
|
if (app->size != sizeof(LoginInfo_Struct)) {
|
||||||
ret = false;
|
return false;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LoginInfo_Struct *li=(LoginInfo_Struct *)app->pBuffer;
|
LoginInfo_Struct *li=(LoginInfo_Struct *)app->pBuffer;
|
||||||
@ -421,8 +384,7 @@ bool Client::HandlePacket(const EQApplicationPacket *app) {
|
|||||||
if (strlen(password) <= 1) {
|
if (strlen(password) <= 1) {
|
||||||
// TODO: Find out how to tell the client wrong username/password
|
// TODO: Find out how to tell the client wrong username/password
|
||||||
clog(WORLD__CLIENT_ERR,"Login without a password");
|
clog(WORLD__CLIENT_ERR,"Login without a password");
|
||||||
ret = false;
|
return false;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pZoning=(li->zoning==1);
|
pZoning=(li->zoning==1);
|
||||||
@ -447,8 +409,7 @@ bool Client::HandlePacket(const EQApplicationPacket *app) {
|
|||||||
#else
|
#else
|
||||||
if (loginserverlist.Connected() == false && !pZoning) {
|
if (loginserverlist.Connected() == false && !pZoning) {
|
||||||
clog(WORLD__CLIENT_ERR,"Error: Login server login while not connected to login server.");
|
clog(WORLD__CLIENT_ERR,"Error: Login server login while not connected to login server.");
|
||||||
ret = false;
|
return false;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
if ((minilogin && (cle = client_list.CheckAuth(id,password,ip))) || (cle = client_list.CheckAuth(id, password)))
|
if ((minilogin && (cle = client_list.CheckAuth(id,password,ip))) || (cle = client_list.CheckAuth(id, password)))
|
||||||
#endif
|
#endif
|
||||||
@ -459,8 +420,7 @@ bool Client::HandlePacket(const EQApplicationPacket *app) {
|
|||||||
clog(WORLD__CLIENT_ERR,"If so you forget the minilogin variable...");
|
clog(WORLD__CLIENT_ERR,"If so you forget the minilogin variable...");
|
||||||
else
|
else
|
||||||
clog(WORLD__CLIENT_ERR,"Could not find a minilogin account, verify ip address logging into minilogin is the same that is in your account table.");
|
clog(WORLD__CLIENT_ERR,"Could not find a minilogin account, verify ip address logging into minilogin is the same that is in your account table.");
|
||||||
ret = false;
|
return false;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cle->SetOnline();
|
cle->SetOnline();
|
||||||
@ -474,6 +434,9 @@ bool Client::HandlePacket(const EQApplicationPacket *app) {
|
|||||||
else {
|
else {
|
||||||
clog(WORLD__CLIENT,"LS Account #%d",cle->LSID());
|
clog(WORLD__CLIENT,"LS Account #%d",cle->LSID());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const WorldConfig *Config=WorldConfig::get();
|
||||||
|
|
||||||
if(Config->UpdateStats){
|
if(Config->UpdateStats){
|
||||||
ServerPacket* pack = new ServerPacket;
|
ServerPacket* pack = new ServerPacket;
|
||||||
pack->opcode = ServerOP_LSPlayerJoinWorld;
|
pack->opcode = ServerOP_LSPlayerJoinWorld;
|
||||||
@ -503,22 +466,23 @@ bool Client::HandlePacket(const EQApplicationPacket *app) {
|
|||||||
else {
|
else {
|
||||||
// TODO: Find out how to tell the client wrong username/password
|
// TODO: Find out how to tell the client wrong username/password
|
||||||
clog(WORLD__CLIENT_ERR,"Bad/Expired session key '%s'",name);
|
clog(WORLD__CLIENT_ERR,"Bad/Expired session key '%s'",name);
|
||||||
ret = false;
|
return false;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cle)
|
if (!cle)
|
||||||
break;
|
return true;
|
||||||
|
|
||||||
cle->SetIP(GetIP());
|
cle->SetIP(GetIP());
|
||||||
break;
|
return true;
|
||||||
}
|
}
|
||||||
case OP_ApproveName: //Name approval
|
|
||||||
{
|
bool Client::HandleNameApprovalPacket(const EQApplicationPacket *app) {
|
||||||
|
|
||||||
if (GetAccountID() == 0) {
|
if (GetAccountID() == 0) {
|
||||||
clog(WORLD__CLIENT_ERR,"Name approval request with no logged in account");
|
clog(WORLD__CLIENT_ERR,"Name approval request with no logged in account");
|
||||||
ret = false;
|
return false;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(char_name, 64, "%s", (char*)app->pBuffer);
|
snprintf(char_name, 64, "%s", (char*)app->pBuffer);
|
||||||
uchar race = app->pBuffer[64];
|
uchar race = app->pBuffer[64];
|
||||||
uchar clas = app->pBuffer[68];
|
uchar clas = app->pBuffer[68];
|
||||||
@ -530,6 +494,7 @@ bool Client::HandlePacket(const EQApplicationPacket *app) {
|
|||||||
outapp->SetOpcode(OP_ApproveName);
|
outapp->SetOpcode(OP_ApproveName);
|
||||||
outapp->pBuffer = new uchar[1];
|
outapp->pBuffer = new uchar[1];
|
||||||
outapp->size = 1;
|
outapp->size = 1;
|
||||||
|
|
||||||
bool valid;
|
bool valid;
|
||||||
if(!database.CheckNameFilter(char_name)) {
|
if(!database.CheckNameFilter(char_name)) {
|
||||||
valid = false;
|
valid = false;
|
||||||
@ -552,10 +517,10 @@ bool Client::HandlePacket(const EQApplicationPacket *app) {
|
|||||||
memset(char_name, 0, sizeof(char_name));
|
memset(char_name, 0, sizeof(char_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
return true;
|
||||||
}
|
}
|
||||||
case OP_RandomNameGenerator:
|
|
||||||
{
|
bool Client::HandleGenerateRandomNamePacket(const EQApplicationPacket *app) {
|
||||||
// creates up to a 10 char name
|
// creates up to a 10 char name
|
||||||
char vowels[18]="aeiouyaeiouaeioe";
|
char vowels[18]="aeiouyaeiouaeioe";
|
||||||
char cons[48]="bcdfghjklmnpqrstvwxzybcdgklmnprstvwbcdgkpstrkd";
|
char cons[48]="bcdfghjklmnpqrstvwxzybcdgklmnprstvwbcdgkpstrkd";
|
||||||
@ -630,16 +595,11 @@ bool Client::HandlePacket(const EQApplicationPacket *app) {
|
|||||||
memset(ngs->name,0,64);
|
memset(ngs->name,0,64);
|
||||||
strcpy(ngs->name,rndname);
|
strcpy(ngs->name,rndname);
|
||||||
|
|
||||||
// char names[8][64] = { "How", "About", "You", "Think", "Of", "Your", "Own", "Name" };
|
|
||||||
// //Could have parts of the random name in this struct and they compile together
|
|
||||||
// NameGeneration_Struct* ngs = (NameGeneration_Struct*)app->pBuffer;
|
|
||||||
// strncpy(ngs->name,"Notcreated",64);
|
|
||||||
|
|
||||||
QueuePacket(app);
|
QueuePacket(app);
|
||||||
break;
|
return true;
|
||||||
|
|
||||||
}
|
}
|
||||||
case OP_CharacterCreateRequest: {
|
|
||||||
|
bool Client::HandleCharacterCreateRequestPacket(const EQApplicationPacket *app) {
|
||||||
// New OpCode in SoF
|
// New OpCode in SoF
|
||||||
uint32 allocs = character_create_allocations.size();
|
uint32 allocs = character_create_allocations.size();
|
||||||
uint32 combos = character_create_race_class_combos.size();
|
uint32 combos = character_create_race_class_combos.size();
|
||||||
@ -683,22 +643,22 @@ bool Client::HandlePacket(const EQApplicationPacket *app) {
|
|||||||
|
|
||||||
QueuePacket(outapp);
|
QueuePacket(outapp);
|
||||||
safe_delete(outapp);
|
safe_delete(outapp);
|
||||||
break;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
case OP_CharacterCreate: //Char create
|
bool Client::HandleCharacterCreatePacket(const EQApplicationPacket *app) {
|
||||||
{
|
|
||||||
if (GetAccountID() == 0)
|
if (GetAccountID() == 0)
|
||||||
{
|
{
|
||||||
clog(WORLD__CLIENT_ERR,"Account ID not set; unable to create character.");
|
clog(WORLD__CLIENT_ERR,"Account ID not set; unable to create character.");
|
||||||
ret = false;
|
return false;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
else if (app->size != sizeof(CharCreate_Struct))
|
else if (app->size != sizeof(CharCreate_Struct))
|
||||||
{
|
{
|
||||||
clog(WORLD__CLIENT_ERR,"Wrong size on OP_CharacterCreate. Got: %d, Expected: %d",app->size,sizeof(CharCreate_Struct));
|
clog(WORLD__CLIENT_ERR,"Wrong size on OP_CharacterCreate. Got: %d, Expected: %d",app->size,sizeof(CharCreate_Struct));
|
||||||
DumpPacket(app);
|
DumpPacket(app);
|
||||||
break;
|
// the previous behavior was essentially returning true here
|
||||||
|
// but that seems a bit odd to me.
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
CharCreate_Struct *cc = (CharCreate_Struct*)app->pBuffer;
|
CharCreate_Struct *cc = (CharCreate_Struct*)app->pBuffer;
|
||||||
@ -712,20 +672,23 @@ bool Client::HandlePacket(const EQApplicationPacket *app) {
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
SendCharInfo();
|
SendCharInfo();
|
||||||
break;
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
case OP_EnterWorld: // Enter world
|
|
||||||
{
|
bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) {
|
||||||
|
|
||||||
if (GetAccountID() == 0) {
|
if (GetAccountID() == 0) {
|
||||||
clog(WORLD__CLIENT_ERR,"Enter world with no logged in account");
|
clog(WORLD__CLIENT_ERR,"Enter world with no logged in account");
|
||||||
eqs->Close();
|
eqs->Close();
|
||||||
break;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(GetAdmin() < 0)
|
if(GetAdmin() < 0)
|
||||||
{
|
{
|
||||||
clog(WORLD__CLIENT,"Account banned or suspended.");
|
clog(WORLD__CLIENT,"Account banned or suspended.");
|
||||||
eqs->Close();
|
eqs->Close();
|
||||||
break;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (RuleI(World, MaxClientsPerIP) >= 0) {
|
if (RuleI(World, MaxClientsPerIP) >= 0) {
|
||||||
@ -741,14 +704,14 @@ bool Client::HandlePacket(const EQApplicationPacket *app) {
|
|||||||
if (charid == 0 || tmpaccid != GetAccountID()) {
|
if (charid == 0 || tmpaccid != GetAccountID()) {
|
||||||
clog(WORLD__CLIENT_ERR,"Could not get CharInfo for '%s'",char_name);
|
clog(WORLD__CLIENT_ERR,"Could not get CharInfo for '%s'",char_name);
|
||||||
eqs->Close();
|
eqs->Close();
|
||||||
break;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure this account owns this character
|
// Make sure this account owns this character
|
||||||
if (tmpaccid != GetAccountID()) {
|
if (tmpaccid != GetAccountID()) {
|
||||||
clog(WORLD__CLIENT_ERR,"This account does not own the character named '%s'",char_name);
|
clog(WORLD__CLIENT_ERR,"This account does not own the character named '%s'",char_name);
|
||||||
eqs->Close();
|
eqs->Close();
|
||||||
break;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!pZoning && ew->return_home)
|
if(!pZoning && ew->return_home)
|
||||||
@ -765,7 +728,7 @@ bool Client::HandlePacket(const EQApplicationPacket *app) {
|
|||||||
if(cs->gohome[x] == 1)
|
if(cs->gohome[x] == 1)
|
||||||
{
|
{
|
||||||
home_enabled = true;
|
home_enabled = true;
|
||||||
break;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -780,7 +743,7 @@ bool Client::HandlePacket(const EQApplicationPacket *app) {
|
|||||||
clog(WORLD__CLIENT_ERR,"'%s' is trying to go home before they're able...",char_name);
|
clog(WORLD__CLIENT_ERR,"'%s' is trying to go home before they're able...",char_name);
|
||||||
database.SetHackerFlag(GetAccountName(), char_name, "MQGoHome: player tried to go home before they were able.");
|
database.SetHackerFlag(GetAccountName(), char_name, "MQGoHome: player tried to go home before they were able.");
|
||||||
eqs->Close();
|
eqs->Close();
|
||||||
break;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -797,7 +760,7 @@ bool Client::HandlePacket(const EQApplicationPacket *app) {
|
|||||||
if(cs->tutorial[x] == 1)
|
if(cs->tutorial[x] == 1)
|
||||||
{
|
{
|
||||||
tutorial_enabled = true;
|
tutorial_enabled = true;
|
||||||
break;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -813,7 +776,7 @@ bool Client::HandlePacket(const EQApplicationPacket *app) {
|
|||||||
clog(WORLD__CLIENT_ERR,"'%s' is trying to go to tutorial but are not allowed...",char_name);
|
clog(WORLD__CLIENT_ERR,"'%s' is trying to go to tutorial but are not allowed...",char_name);
|
||||||
database.SetHackerFlag(GetAccountName(), char_name, "MQTutorial: player tried to enter the tutorial without having tutorial enabled for this character.");
|
database.SetHackerFlag(GetAccountName(), char_name, "MQTutorial: player tried to enter the tutorial without having tutorial enabled for this character.");
|
||||||
eqs->Close();
|
eqs->Close();
|
||||||
break;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -893,6 +856,9 @@ bool Client::HandlePacket(const EQApplicationPacket *app) {
|
|||||||
|
|
||||||
EQApplicationPacket *outapp2 = new EQApplicationPacket(OP_SetChatServer);
|
EQApplicationPacket *outapp2 = new EQApplicationPacket(OP_SetChatServer);
|
||||||
char buffer[112];
|
char buffer[112];
|
||||||
|
|
||||||
|
const WorldConfig *Config = WorldConfig::get();
|
||||||
|
|
||||||
sprintf(buffer,"%s,%i,%s.%s,%c%08X",
|
sprintf(buffer,"%s,%i,%s.%s,%c%08X",
|
||||||
Config->ChatHost.c_str(),
|
Config->ChatHost.c_str(),
|
||||||
Config->ChatPort,
|
Config->ChatPort,
|
||||||
@ -923,12 +889,12 @@ bool Client::HandlePacket(const EQApplicationPacket *app) {
|
|||||||
safe_delete(outapp2);
|
safe_delete(outapp2);
|
||||||
|
|
||||||
EnterWorld();
|
EnterWorld();
|
||||||
break;
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
case OP_LoginComplete:{
|
|
||||||
break;
|
bool Client::HandleDeleteCharacterPacket(const EQApplicationPacket *app) {
|
||||||
}
|
|
||||||
case OP_DeleteCharacter: {
|
|
||||||
uint32 char_acct_id = database.GetAccountIDByChar((char*)app->pBuffer);
|
uint32 char_acct_id = database.GetAccountIDByChar((char*)app->pBuffer);
|
||||||
if(char_acct_id == GetAccountID())
|
if(char_acct_id == GetAccountID())
|
||||||
{
|
{
|
||||||
@ -936,51 +902,119 @@ bool Client::HandlePacket(const EQApplicationPacket *app) {
|
|||||||
database.DeleteCharacter((char *)app->pBuffer);
|
database.DeleteCharacter((char *)app->pBuffer);
|
||||||
SendCharInfo();
|
SendCharInfo();
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
case OP_ApproveWorld:
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case OP_WorldClientReady:{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case OP_World_Client_CRC1:
|
|
||||||
case OP_World_Client_CRC2: {
|
|
||||||
// There is no obvious entry in the CC struct to indicate that the 'Start Tutorial button
|
|
||||||
// is selected when a character is created. I have observed that in this case, OP_EnterWorld is sent
|
|
||||||
// before OP_World_Client_CRC1. Therefore, if we receive OP_World_Client_CRC1 before OP_EnterWorld,
|
|
||||||
// then 'Start Tutorial' was not chosen.
|
|
||||||
StartInTutorial = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case OP_WearChange: { // User has selected a different character
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case OP_WorldComplete: {
|
|
||||||
eqs->Close();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case OP_LoginUnknown1:
|
|
||||||
case OP_LoginUnknown2:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case OP_ZoneChange:
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Client::HandleZoneChangePacket(const EQApplicationPacket *app) {
|
||||||
// HoT sends this to world while zoning and wants it echoed back.
|
// HoT sends this to world while zoning and wants it echoed back.
|
||||||
if(ClientVersionBit & BIT_RoFAndLater)
|
if(ClientVersionBit & BIT_RoFAndLater)
|
||||||
{
|
{
|
||||||
QueuePacket(app);
|
QueuePacket(app);
|
||||||
}
|
}
|
||||||
break;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Client::HandlePacket(const EQApplicationPacket *app) {
|
||||||
|
|
||||||
default: {
|
EmuOpcode opcode = app->GetOpcode();
|
||||||
|
|
||||||
|
clog(WORLD__CLIENT_TRACE,"Recevied EQApplicationPacket");
|
||||||
|
_pkt(WORLD__CLIENT_TRACE,app);
|
||||||
|
|
||||||
|
if (!eqs->CheckState(ESTABLISHED)) {
|
||||||
|
clog(WORLD__CLIENT,"Client disconnected (net inactive on send)");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Voidd: Anti-GM Account hack, Checks source ip against valid GM Account IP Addresses
|
||||||
|
if (RuleB(World, GMAccountIPList) && this->GetAdmin() >= (RuleI(World, MinGMAntiHackStatus))) {
|
||||||
|
if(!database.CheckGMIPs(long2ip(this->GetIP()).c_str(), this->GetAccountID())) {
|
||||||
|
clog(WORLD__CLIENT,"GM Account not permited from source address %s and accountid %i", long2ip(this->GetIP()).c_str(), this->GetAccountID());
|
||||||
|
eqs->Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GetAccountID() == 0 && opcode != OP_SendLoginInfo) {
|
||||||
|
// Got a packet other than OP_SendLoginInfo when not logged in
|
||||||
|
clog(WORLD__CLIENT_ERR,"Expecting OP_SendLoginInfo, got %s", OpcodeNames[opcode]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (opcode == OP_AckPacket) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(opcode)
|
||||||
|
{
|
||||||
|
case OP_World_Client_CRC1:
|
||||||
|
case OP_World_Client_CRC2:
|
||||||
|
{
|
||||||
|
// There is no obvious entry in the CC struct to indicate that the 'Start Tutorial button
|
||||||
|
// is selected when a character is created. I have observed that in this case, OP_EnterWorld is sent
|
||||||
|
// before OP_World_Client_CRC1. Therefore, if we receive OP_World_Client_CRC1 before OP_EnterWorld,
|
||||||
|
// then 'Start Tutorial' was not chosen.
|
||||||
|
StartInTutorial = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case OP_SendLoginInfo:
|
||||||
|
{
|
||||||
|
return HandleSendLoginInfoPacket(app);
|
||||||
|
}
|
||||||
|
case OP_ApproveName: //Name approval
|
||||||
|
{
|
||||||
|
return HandleNameApprovalPacket(app);
|
||||||
|
}
|
||||||
|
case OP_RandomNameGenerator:
|
||||||
|
{
|
||||||
|
return HandleGenerateRandomNamePacket(app);
|
||||||
|
}
|
||||||
|
case OP_CharacterCreateRequest:
|
||||||
|
{
|
||||||
|
// New OpCode in SoF
|
||||||
|
return HandleCharacterCreateRequestPacket(app);
|
||||||
|
}
|
||||||
|
case OP_CharacterCreate: //Char create
|
||||||
|
{
|
||||||
|
return HandleCharacterCreatePacket(app);
|
||||||
|
}
|
||||||
|
case OP_EnterWorld: // Enter world
|
||||||
|
{
|
||||||
|
return HandleEnterWorldPacket(app);
|
||||||
|
}
|
||||||
|
case OP_DeleteCharacter:
|
||||||
|
{
|
||||||
|
return HandleDeleteCharacterPacket(app);
|
||||||
|
}
|
||||||
|
case OP_WorldComplete:
|
||||||
|
{
|
||||||
|
eqs->Close();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case OP_ZoneChange:
|
||||||
|
{
|
||||||
|
// HoT sends this to world while zoning and wants it echoed back.
|
||||||
|
return HandleZoneChangePacket(app);
|
||||||
|
}
|
||||||
|
case OP_LoginUnknown1:
|
||||||
|
case OP_LoginUnknown2:
|
||||||
|
case OP_CrashDump:
|
||||||
|
case OP_WearChange:
|
||||||
|
case OP_LoginComplete:
|
||||||
|
case OP_ApproveWorld:
|
||||||
|
case OP_WorldClientReady:
|
||||||
|
{
|
||||||
|
// Essentially we are just 'eating' these packets, indicating
|
||||||
|
// they are handled.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
clog(WORLD__CLIENT_ERR,"Received unknown EQApplicationPacket");
|
clog(WORLD__CLIENT_ERR,"Received unknown EQApplicationPacket");
|
||||||
_pkt(WORLD__CLIENT_ERR,app);
|
_pkt(WORLD__CLIENT_ERR,app);
|
||||||
break;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Client::Process() {
|
bool Client::Process() {
|
||||||
|
|||||||
@ -97,7 +97,17 @@ private:
|
|||||||
bool firstlogin;
|
bool firstlogin;
|
||||||
bool seencharsel;
|
bool seencharsel;
|
||||||
bool realfirstlogin;
|
bool realfirstlogin;
|
||||||
|
|
||||||
bool HandlePacket(const EQApplicationPacket *app);
|
bool HandlePacket(const EQApplicationPacket *app);
|
||||||
|
bool HandleNameApprovalPacket(const EQApplicationPacket *app);
|
||||||
|
bool HandleSendLoginInfoPacket(const EQApplicationPacket *app);
|
||||||
|
bool HandleGenerateRandomNamePacket(const EQApplicationPacket *app);
|
||||||
|
bool HandleCharacterCreateRequestPacket(const EQApplicationPacket *app);
|
||||||
|
bool HandleCharacterCreatePacket(const EQApplicationPacket *app);
|
||||||
|
bool HandleEnterWorldPacket(const EQApplicationPacket *app);
|
||||||
|
bool HandleDeleteCharacterPacket(const EQApplicationPacket *app);
|
||||||
|
bool HandleZoneChangePacket(const EQApplicationPacket *app);
|
||||||
|
|
||||||
EQStreamInterface* const eqs;
|
EQStreamInterface* const eqs;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1084,6 +1084,15 @@ void Mob::AI_Process() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef BOTS
|
||||||
|
if (IsPet() && GetOwner()->IsBot() && target == GetOwner())
|
||||||
|
{
|
||||||
|
// this blocks all pet attacks against owner..bot pet test (copied above check)
|
||||||
|
RemoveFromHateList(this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif //BOTS
|
||||||
|
|
||||||
if(DivineAura())
|
if(DivineAura())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|||||||
28
zone/bot.cpp
28
zone/bot.cpp
@ -3122,10 +3122,6 @@ bool Bot::Process()
|
|||||||
// Bot AI
|
// Bot AI
|
||||||
AI_Process();
|
AI_Process();
|
||||||
|
|
||||||
// Bot Pet AI
|
|
||||||
if(HasPet())
|
|
||||||
PetAIProcess();
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3581,8 +3577,8 @@ void Bot::AI_Process() {
|
|||||||
|
|
||||||
if(!IsEngaged()) {
|
if(!IsEngaged()) {
|
||||||
if(GetFollowID()) {
|
if(GetFollowID()) {
|
||||||
if(BotOwner && BotOwner->CastToClient()->AutoAttackEnabled() && BotOwner->GetTarget() &&
|
if(BotOwner && BotOwner->GetTarget() && BotOwner->GetTarget()->IsNPC() && (BotOwner->GetTarget()->GetHateAmount(BotOwner)
|
||||||
BotOwner->GetTarget()->IsNPC() && BotOwner->GetTarget()->GetHateAmount(BotOwner)) {
|
|| BotOwner->CastToClient()->AutoAttackEnabled()) && IsAttackAllowed(BotOwner->GetTarget())) {
|
||||||
AddToHateList(BotOwner->GetTarget(), 1);
|
AddToHateList(BotOwner->GetTarget(), 1);
|
||||||
|
|
||||||
if(HasPet())
|
if(HasPet())
|
||||||
@ -3594,11 +3590,12 @@ void Bot::AI_Process() {
|
|||||||
if(g) {
|
if(g) {
|
||||||
for(int counter = 0; counter < g->GroupCount(); counter++) {
|
for(int counter = 0; counter < g->GroupCount(); counter++) {
|
||||||
if(g->members[counter]) {
|
if(g->members[counter]) {
|
||||||
if(g->members[counter]->IsEngaged() && g->members[counter]->GetTarget()) {
|
Mob* tar = g->members[counter]->GetTarget();
|
||||||
AddToHateList(g->members[counter]->GetTarget(), 1);
|
if(tar && tar->IsNPC() && tar->GetHateAmount(g->members[counter]) && IsAttackAllowed(g->members[counter]->GetTarget())) {
|
||||||
|
AddToHateList(tar, 1);
|
||||||
|
|
||||||
if(HasPet())
|
if(HasPet())
|
||||||
GetPet()->AddToHateList(g->members[counter]->GetTarget(), 1);
|
GetPet()->AddToHateList(tar, 1);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -6370,6 +6367,10 @@ void Bot::Damage(Mob *from, int32 damage, uint16 spell_id, SkillType attack_skil
|
|||||||
|
|
||||||
SendHPUpdate();
|
SendHPUpdate();
|
||||||
|
|
||||||
|
if(this == from) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Aggro the bot's group members
|
// Aggro the bot's group members
|
||||||
if(IsGrouped())
|
if(IsGrouped())
|
||||||
{
|
{
|
||||||
@ -6378,7 +6379,7 @@ void Bot::Damage(Mob *from, int32 damage, uint16 spell_id, SkillType attack_skil
|
|||||||
{
|
{
|
||||||
for(int i=0; i<MAX_GROUP_MEMBERS; i++)
|
for(int i=0; i<MAX_GROUP_MEMBERS; i++)
|
||||||
{
|
{
|
||||||
if(g->members[i] && g->members[i]->IsBot() && from && !g->members[i]->CheckAggro(from))
|
if(g->members[i] && g->members[i]->IsBot() && from && !g->members[i]->CheckAggro(from) && g->members[i]->IsAttackAllowed(from))
|
||||||
{
|
{
|
||||||
g->members[i]->AddToHateList(from, 1);
|
g->members[i]->AddToHateList(from, 1);
|
||||||
}
|
}
|
||||||
@ -9045,7 +9046,12 @@ bool Bot::IsBotAttackAllowed(Mob* attacker, Mob* target, bool& hasRuleDefined)
|
|||||||
|
|
||||||
if(attacker && target)
|
if(attacker && target)
|
||||||
{
|
{
|
||||||
if(attacker->IsClient() && target->IsBot() && attacker->CastToClient()->GetPVP() && target->CastToBot()->GetBotOwner()->CastToClient()->GetPVP())
|
if(attacker == target)
|
||||||
|
{
|
||||||
|
hasRuleDefined = true;
|
||||||
|
Result = false;
|
||||||
|
}
|
||||||
|
else if(attacker->IsClient() && target->IsBot() && attacker->CastToClient()->GetPVP() && target->CastToBot()->GetBotOwner()->CastToClient()->GetPVP())
|
||||||
{
|
{
|
||||||
hasRuleDefined = true;
|
hasRuleDefined = true;
|
||||||
Result = true;
|
Result = true;
|
||||||
|
|||||||
@ -308,7 +308,7 @@ bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) {
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
// no buffs with illusions.. use #bot command to cast illusions
|
// no buffs with illusions.. use #bot command to cast illusions
|
||||||
if(IsEffectInSpell(selectedBotSpell.SpellId, SE_Illusion))
|
if(IsEffectInSpell(selectedBotSpell.SpellId, SE_Illusion) && tar != this)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
//no teleport spells use #bot command to cast teleports
|
//no teleport spells use #bot command to cast teleports
|
||||||
|
|||||||
@ -61,6 +61,7 @@ Merc::Merc(const NPCType* d, float x, float y, float z, float heading)
|
|||||||
skills[r] = database.GetSkillCap(GetClass(),(SkillType)r,GetLevel());
|
skills[r] = database.GetSkillCap(GetClass(),(SkillType)r,GetLevel());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GetMercSize();
|
||||||
CalcBonuses();
|
CalcBonuses();
|
||||||
|
|
||||||
SetHP(GetMaxHP());
|
SetHP(GetMaxHP());
|
||||||
@ -80,7 +81,6 @@ Merc::~Merc() {
|
|||||||
void Merc::CalcBonuses()
|
void Merc::CalcBonuses()
|
||||||
{
|
{
|
||||||
//_ZP(Merc_CalcBonuses);
|
//_ZP(Merc_CalcBonuses);
|
||||||
GenerateBaseStats();
|
|
||||||
memset(&itembonuses, 0, sizeof(StatBonuses));
|
memset(&itembonuses, 0, sizeof(StatBonuses));
|
||||||
memset(&aabonuses, 0, sizeof(StatBonuses));
|
memset(&aabonuses, 0, sizeof(StatBonuses));
|
||||||
CalcItemBonuses(&itembonuses);
|
CalcItemBonuses(&itembonuses);
|
||||||
@ -117,59 +117,7 @@ void Merc::CalcBonuses()
|
|||||||
rooted = FindType(SE_Root);
|
rooted = FindType(SE_Root);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Merc::GenerateBaseStats() {
|
void Merc::GetMercSize() {
|
||||||
|
|
||||||
// base stats
|
|
||||||
uint16 Strength = _baseSTR;
|
|
||||||
uint16 Stamina = _baseSTA;
|
|
||||||
uint16 Dexterity = _baseDEX;
|
|
||||||
uint16 Agility = _baseAGI;
|
|
||||||
uint16 Wisdom = _baseWIS;
|
|
||||||
uint16 Intelligence = _baseINT;
|
|
||||||
uint16 Charisma = _baseCHA;
|
|
||||||
uint16 Attack = _baseATK;
|
|
||||||
uint16 MagicResist = _baseMR;
|
|
||||||
uint16 FireResist = _baseFR;
|
|
||||||
uint16 DiseaseResist = _baseDR;
|
|
||||||
uint16 PoisonResist = _basePR;
|
|
||||||
uint16 ColdResist = _baseCR;
|
|
||||||
uint16 CorruptionResist = _baseCorrup;
|
|
||||||
|
|
||||||
switch(this->GetClass()) {
|
|
||||||
case 1: // Warrior
|
|
||||||
Strength += 10;
|
|
||||||
Stamina += 20;
|
|
||||||
Agility += 10;
|
|
||||||
Dexterity += 10;
|
|
||||||
Attack += 12;
|
|
||||||
break;
|
|
||||||
case 2: // Cleric
|
|
||||||
Strength += 5;
|
|
||||||
Stamina += 5;
|
|
||||||
Agility += 10;
|
|
||||||
Wisdom += 30;
|
|
||||||
Attack += 8;
|
|
||||||
break;
|
|
||||||
case 4: // Ranger
|
|
||||||
Strength += 15;
|
|
||||||
Stamina += 10;
|
|
||||||
Agility += 10;
|
|
||||||
Wisdom += 15;
|
|
||||||
Attack += 17;
|
|
||||||
break;
|
|
||||||
case 9: // Rogue
|
|
||||||
Strength += 10;
|
|
||||||
Stamina += 20;
|
|
||||||
Agility += 10;
|
|
||||||
Dexterity += 10;
|
|
||||||
Attack += 12;
|
|
||||||
break;
|
|
||||||
case 12: // Wizard
|
|
||||||
Stamina += 20;
|
|
||||||
Intelligence += 30;
|
|
||||||
Attack += 5;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
float MercSize = GetSize();
|
float MercSize = GetSize();
|
||||||
|
|
||||||
@ -220,20 +168,6 @@ void Merc::GenerateBaseStats() {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->_baseSTR = Strength;
|
|
||||||
this->_baseSTA = Stamina;
|
|
||||||
this->_baseDEX = Dexterity;
|
|
||||||
this->_baseAGI = Agility;
|
|
||||||
this->_baseWIS = Wisdom;
|
|
||||||
this->_baseINT = Intelligence;
|
|
||||||
this->_baseCHA = Charisma;
|
|
||||||
this->_baseATK = Attack;
|
|
||||||
this->_baseMR = MagicResist;
|
|
||||||
this->_baseFR = FireResist;
|
|
||||||
this->_baseDR = DiseaseResist;
|
|
||||||
this->_basePR = PoisonResist;
|
|
||||||
this->_baseCR = ColdResist;
|
|
||||||
this->_baseCorrup = CorruptionResist;
|
|
||||||
this->size = MercSize;
|
this->size = MercSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -940,7 +874,7 @@ int16 Merc::CalcCorrup()
|
|||||||
}
|
}
|
||||||
|
|
||||||
int16 Merc::CalcATK() {
|
int16 Merc::CalcATK() {
|
||||||
ATK = _baseATK + itembonuses.ATK + spellbonuses.ATK + aabonuses.ATK + GroupLeadershipAAOffenseEnhancement() + ((GetSTR() + GetSkill(OFFENSE)) * 9 / 10);
|
ATK = _baseATK + itembonuses.ATK + spellbonuses.ATK + aabonuses.ATK + GroupLeadershipAAOffenseEnhancement();
|
||||||
return(ATK);
|
return(ATK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -328,7 +328,7 @@ private:
|
|||||||
int GroupLeadershipAAHealthRegeneration();
|
int GroupLeadershipAAHealthRegeneration();
|
||||||
int GroupLeadershipAAOffenseEnhancement();
|
int GroupLeadershipAAOffenseEnhancement();
|
||||||
|
|
||||||
void GenerateBaseStats();
|
void GetMercSize();
|
||||||
void GenerateAppearance();
|
void GenerateAppearance();
|
||||||
|
|
||||||
bool LoadMercSpells();
|
bool LoadMercSpells();
|
||||||
|
|||||||
@ -1178,7 +1178,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
|
|||||||
{
|
{
|
||||||
Gate();
|
Gate();
|
||||||
}
|
}
|
||||||
// solar: shadow step is handled by client already, nothing required
|
// shadow step is handled by client already, nothing required
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1189,7 +1189,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
|
|||||||
#endif
|
#endif
|
||||||
if (spells[spell_id].base[i] == 1)
|
if (spells[spell_id].base[i] == 1)
|
||||||
BuffFadeByEffect(SE_Blind);
|
BuffFadeByEffect(SE_Blind);
|
||||||
// solar: handled by client
|
// handled by client
|
||||||
// TODO: blind flag?
|
// TODO: blind flag?
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1369,7 +1369,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
|
|||||||
#ifdef SPELL_EFFECT_SPAM
|
#ifdef SPELL_EFFECT_SPAM
|
||||||
snprintf(effect_desc, _EDLEN, "Spin: %d", effect_value);
|
snprintf(effect_desc, _EDLEN, "Spin: %d", effect_value);
|
||||||
#endif
|
#endif
|
||||||
// solar: the spinning is handled by the client
|
// the spinning is handled by the client
|
||||||
int max_level = spells[spell_id].max[i];
|
int max_level = spells[spell_id].max[i];
|
||||||
if(max_level == 0)
|
if(max_level == 0)
|
||||||
max_level = RuleI(Spells, BaseImmunityLevel); // Default max is 55 level limit
|
max_level = RuleI(Spells, BaseImmunityLevel); // Default max is 55 level limit
|
||||||
@ -1383,7 +1383,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// solar: the spinning is handled by the client
|
// the spinning is handled by the client
|
||||||
// Stun duration is based on the effect_value, not the buff duration(alot don't have buffs)
|
// Stun duration is based on the effect_value, not the buff duration(alot don't have buffs)
|
||||||
Stun(effect_value);
|
Stun(effect_value);
|
||||||
if(!IsClient()) {
|
if(!IsClient()) {
|
||||||
@ -2004,7 +2004,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
|
|||||||
#ifdef SPELL_EFFECT_SPAM
|
#ifdef SPELL_EFFECT_SPAM
|
||||||
snprintf(effect_desc, _EDLEN, "Call Pet");
|
snprintf(effect_desc, _EDLEN, "Call Pet");
|
||||||
#endif
|
#endif
|
||||||
// solar: this is cast on self, not on the pet
|
// this is cast on self, not on the pet
|
||||||
if(GetPet() && GetPet()->IsNPC())
|
if(GetPet() && GetPet()->IsNPC())
|
||||||
{
|
{
|
||||||
GetPet()->CastToNPC()->GMMove(GetX(), GetY(), GetZ(), GetHeading());
|
GetPet()->CastToNPC()->GMMove(GetX(), GetY(), GetZ(), GetHeading());
|
||||||
@ -2015,7 +2015,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
|
|||||||
case SE_StackingCommand_Block:
|
case SE_StackingCommand_Block:
|
||||||
case SE_StackingCommand_Overwrite:
|
case SE_StackingCommand_Overwrite:
|
||||||
{
|
{
|
||||||
// solar: these are special effects used by the buff stuff
|
// these are special effects used by the buff stuff
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2100,7 +2100,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
|
|||||||
#ifdef SPELL_EFFECT_SPAM
|
#ifdef SPELL_EFFECT_SPAM
|
||||||
snprintf(effect_desc, _EDLEN, "Skill Attack");
|
snprintf(effect_desc, _EDLEN, "Skill Attack");
|
||||||
#endif
|
#endif
|
||||||
/*Kayen:
|
/*
|
||||||
Weapon Damage = spells[spell_id].base[i]
|
Weapon Damage = spells[spell_id].base[i]
|
||||||
Chance to Hit Bonus = spells[spell_id].base2[i]
|
Chance to Hit Bonus = spells[spell_id].base2[i]
|
||||||
???? = spells[spell_id].max[i] - MOST of the effects have this value.
|
???? = spells[spell_id].max[i] - MOST of the effects have this value.
|
||||||
@ -2812,11 +2812,10 @@ int Mob::CalcSpellEffectValue(uint16 spell_id, int effect_id, int caster_level,
|
|||||||
return(effect_value);
|
return(effect_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// solar: generic formula calculations
|
// generic formula calculations
|
||||||
int Mob::CalcSpellEffectValue_formula(int formula, int base, int max, int caster_level, uint16 spell_id, int ticsremaining)
|
int Mob::CalcSpellEffectValue_formula(int formula, int base, int max, int caster_level, uint16 spell_id, int ticsremaining)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
neotokyo: i need those formulas checked!!!!
|
|
||||||
|
|
||||||
0 = base
|
0 = base
|
||||||
1 - 99 = base + level * formulaID
|
1 - 99 = base + level * formulaID
|
||||||
@ -2845,8 +2844,11 @@ neotokyo: i need those formulas checked!!!!
|
|||||||
int result = 0, updownsign = 1, ubase = base;
|
int result = 0, updownsign = 1, ubase = base;
|
||||||
if(ubase < 0)
|
if(ubase < 0)
|
||||||
ubase = 0 - ubase;
|
ubase = 0 - ubase;
|
||||||
|
int level_diff = caster_level - GetMinLevel(spell_id);
|
||||||
|
if (level_diff < 0)
|
||||||
|
level_diff = 0;
|
||||||
|
|
||||||
// solar: this updown thing might look messed up but if you look at the
|
// this updown thing might look messed up but if you look at the
|
||||||
// spells it actually looks like some have a positive base and max where
|
// spells it actually looks like some have a positive base and max where
|
||||||
// the max is actually less than the base, hence they grow downward
|
// the max is actually less than the base, hence they grow downward
|
||||||
/*
|
/*
|
||||||
@ -2875,17 +2877,17 @@ snare has both of them negative, yet their range should work the same:
|
|||||||
case 70:
|
case 70:
|
||||||
result = ubase/100; break;
|
result = ubase/100; break;
|
||||||
case 0:
|
case 0:
|
||||||
case 100: // solar: confirmed 2/6/04
|
case 100: // confirmed 2/6/04
|
||||||
result = ubase; break;
|
result = ubase; break;
|
||||||
case 101: // solar: confirmed 2/6/04
|
case 101: // confirmed 2/6/04
|
||||||
result = updownsign * (ubase + (caster_level / 2)); break;
|
result = updownsign * (ubase + (caster_level / 2)); break;
|
||||||
case 102: // solar: confirmed 2/6/04
|
case 102: // confirmed 2/6/04
|
||||||
result = updownsign * (ubase + caster_level); break;
|
result = updownsign * (ubase + caster_level); break;
|
||||||
case 103: // solar: confirmed 2/6/04
|
case 103: // confirmed 2/6/04
|
||||||
result = updownsign * (ubase + (caster_level * 2)); break;
|
result = updownsign * (ubase + (caster_level * 2)); break;
|
||||||
case 104: // solar: confirmed 2/6/04
|
case 104: // confirmed 2/6/04
|
||||||
result = updownsign * (ubase + (caster_level * 3)); break;
|
result = updownsign * (ubase + (caster_level * 3)); break;
|
||||||
case 105: // solar: confirmed 2/6/04
|
case 105: // confirmed 2/6/04
|
||||||
result = updownsign * (ubase + (caster_level * 4)); break;
|
result = updownsign * (ubase + (caster_level * 4)); break;
|
||||||
|
|
||||||
case 107:
|
case 107:
|
||||||
@ -2893,35 +2895,35 @@ snare has both of them negative, yet their range should work the same:
|
|||||||
result = updownsign * (ubase + (caster_level / 2)); break;
|
result = updownsign * (ubase + (caster_level / 2)); break;
|
||||||
case 108:
|
case 108:
|
||||||
result = updownsign * (ubase + (caster_level / 3)); break;
|
result = updownsign * (ubase + (caster_level / 3)); break;
|
||||||
case 109: // solar: confirmed 2/6/04
|
case 109: // confirmed 2/6/04
|
||||||
result = updownsign * (ubase + (caster_level / 4)); break;
|
result = updownsign * (ubase + (caster_level / 4)); break;
|
||||||
|
|
||||||
case 110: // solar: confirmed 2/6/04
|
case 110: // confirmed 2/6/04
|
||||||
//is there a reason we dont use updownsign here???
|
//is there a reason we dont use updownsign here???
|
||||||
result = ubase + (caster_level / 5); break;
|
result = ubase + (caster_level / 5); break;
|
||||||
|
|
||||||
case 111:
|
case 111:
|
||||||
result = updownsign * (ubase + 6 * (caster_level - GetMinLevel(spell_id))); break;
|
result = updownsign * (ubase + 6 * level_diff); break;
|
||||||
case 112:
|
case 112:
|
||||||
result = updownsign * (ubase + 8 * (caster_level - GetMinLevel(spell_id))); break;
|
result = updownsign * (ubase + 8 * level_diff); break;
|
||||||
case 113:
|
case 113:
|
||||||
result = updownsign * (ubase + 10 * (caster_level - GetMinLevel(spell_id))); break;
|
result = updownsign * (ubase + 10 * level_diff); break;
|
||||||
case 114:
|
case 114:
|
||||||
result = updownsign * (ubase + 15 * (caster_level - GetMinLevel(spell_id))); break;
|
result = updownsign * (ubase + 15 * level_diff); break;
|
||||||
|
|
||||||
//these formula were updated according to lucy 10/16/04
|
//these formula were updated according to lucy 10/16/04
|
||||||
case 115: // solar: this is only in symbol of transal
|
case 115: // this is only in symbol of transal
|
||||||
result = ubase + 6 * (caster_level - GetMinLevel(spell_id)); break;
|
result = ubase + 6 * level_diff; break;
|
||||||
case 116: // solar: this is only in symbol of ryltan
|
case 116: // this is only in symbol of ryltan
|
||||||
result = ubase + 8 * (caster_level - GetMinLevel(spell_id)); break;
|
result = ubase + 8 * level_diff; break;
|
||||||
case 117: // solar: this is only in symbol of pinzarn
|
case 117: // this is only in symbol of pinzarn
|
||||||
result = ubase + 12 * (caster_level - GetMinLevel(spell_id)); break;
|
result = ubase + 12 * level_diff; break;
|
||||||
case 118: // solar: used in naltron and a few others
|
case 118: // used in naltron and a few others
|
||||||
result = ubase + 20 * (caster_level - GetMinLevel(spell_id)); break;
|
result = ubase + 20 * level_diff; break;
|
||||||
|
|
||||||
case 119: // solar: confirmed 2/6/04
|
case 119: // confirmed 2/6/04
|
||||||
result = ubase + (caster_level / 8); break;
|
result = ubase + (caster_level / 8); break;
|
||||||
case 121: // solar: corrected 2/6/04
|
case 121: // corrected 2/6/04
|
||||||
result = ubase + (caster_level / 3); break;
|
result = ubase + (caster_level / 3); break;
|
||||||
case 122:
|
case 122:
|
||||||
{
|
{
|
||||||
@ -2933,7 +2935,7 @@ snare has both of them negative, yet their range should work the same:
|
|||||||
result = updownsign * (ubase - (12 * ticdif));
|
result = updownsign * (ubase - (12 * ticdif));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 123: // solar: added 2/6/04
|
case 123: // added 2/6/04
|
||||||
result = MakeRandomInt(ubase, abs(max));
|
result = MakeRandomInt(ubase, abs(max));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -3304,7 +3306,7 @@ void Mob::DoBuffTic(uint16 spell_id, uint32 ticsremaining, uint8 caster_level, M
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// solar: removes the buff in the buff slot 'slot'
|
// removes the buff in the buff slot 'slot'
|
||||||
void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses)
|
void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses)
|
||||||
{
|
{
|
||||||
if(slot < 0 || slot > GetMaxTotalSlots())
|
if(slot < 0 || slot > GetMaxTotalSlots())
|
||||||
@ -5317,7 +5319,7 @@ int32 Mob::GetAdditionalDamage(Mob *caster, uint32 spell_id, bool use_skill, uin
|
|||||||
|
|
||||||
int32 Mob::ApplySpellEffectiveness(Mob* caster, int16 spell_id, int32 value, bool IsBard) {
|
int32 Mob::ApplySpellEffectiveness(Mob* caster, int16 spell_id, int32 value, bool IsBard) {
|
||||||
|
|
||||||
//Kayen 9-17-12: This is likely causing crashes, disabled till can resolve.
|
//9-17-12: This is likely causing crashes, disabled till can resolve.
|
||||||
if (IsBard)
|
if (IsBard)
|
||||||
return value;
|
return value;
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user