Fix issues with claims and implement for RoF/RoF2

This commit is contained in:
Michael Cook (mackal) 2015-02-20 16:29:56 -05:00
parent 921a292f5b
commit c5a217842f
12 changed files with 243 additions and 129 deletions

View File

@ -1,5 +1,9 @@
EQEMu Changelog (Started on Sept 24, 2003 15:50) EQEMu Changelog (Started on Sept 24, 2003 15:50)
------------------------------------------------------- -------------------------------------------------------
== 02/20/2015 ==
demonstar55: Implement claims for RoF/RoF2 (should no longer crash the client!)
- fixed bugs related to claims for the rest of the clients (woo infinite loops)
== 02/18/2015 == == 02/18/2015 ==
Trevius: Fix for potential recursive loops if using RemoveFromHateList() within EVENT_HATE_LIST. Trevius: Fix for potential recursive loops if using RemoveFromHateList() within EVENT_HATE_LIST.

View File

@ -63,6 +63,7 @@ public:
void WriteFloat(float value) { *(float *)(pBuffer + _wpos) = value; _wpos += sizeof(float); } void WriteFloat(float value) { *(float *)(pBuffer + _wpos) = value; _wpos += sizeof(float); }
void WriteDouble(double value) { *(double *)(pBuffer + _wpos) = value; _wpos += sizeof(double); } void WriteDouble(double value) { *(double *)(pBuffer + _wpos) = value; _wpos += sizeof(double); }
void WriteString(const char * str) { uint32 len = static_cast<uint32>(strlen(str)) + 1; memcpy(pBuffer + _wpos, str, len); _wpos += len; } void WriteString(const char * str) { uint32 len = static_cast<uint32>(strlen(str)) + 1; memcpy(pBuffer + _wpos, str, len); _wpos += len; }
void WriteData(const void *ptr, size_t n) { memcpy(pBuffer + _wpos, ptr, n); _wpos += n; }
uint8 ReadUInt8() { uint8 value = *(uint8 *)(pBuffer + _rpos); _rpos += sizeof(uint8); return value; } uint8 ReadUInt8() { uint8 value = *(uint8 *)(pBuffer + _rpos); _rpos += sizeof(uint8); return value; }
uint8 ReadUInt8(uint32 Offset) const { uint8 value = *(uint8 *)(pBuffer + Offset); return value; } uint8 ReadUInt8(uint32 Offset) const { uint8 value = *(uint8 *)(pBuffer + Offset); return value; }

View File

@ -4553,19 +4553,12 @@ struct InternalVeteranReward
/*012*/ InternalVeteranRewardItem items[8]; /*012*/ InternalVeteranRewardItem items[8];
}; };
struct VeteranClaimReply struct VeteranClaim
{ {
/*000*/ char name[64]; /*000*/ char name[64]; //name + other data
/*064*/ uint32 claim_id;
/*068*/ uint32 reject_field;
/*072*/ uint32 unknown072;
};
struct VeteranClaimRequest
{
/*000*/ char name_data[64]; //name + other data
/*064*/ uint32 claim_id; /*064*/ uint32 claim_id;
/*068*/ uint32 unknown068; /*068*/ uint32 unknown068;
/*072*/ uint32 action;
}; };
struct GMSearchCorpse_Struct struct GMSearchCorpse_Struct

View File

@ -15,6 +15,8 @@
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
#include <numeric>
#include <cassert>
namespace RoF namespace RoF
{ {
@ -3608,37 +3610,71 @@ namespace RoF
FINISH_ENCODE(); FINISH_ENCODE();
} }
ENCODE(OP_VetClaimReply)
{
ENCODE_LENGTH_EXACT(VeteranClaim);
SETUP_DIRECT_ENCODE(VeteranClaim, structs::VeteranClaim);
memcpy(eq->name, emu->name, sizeof(emu->name));
OUT(claim_id);
OUT(action);
FINISH_ENCODE();
}
ENCODE(OP_VetRewardsAvaliable) ENCODE(OP_VetRewardsAvaliable)
{ {
EQApplicationPacket *inapp = *p; EQApplicationPacket *inapp = *p;
unsigned char * __emu_buffer = inapp->pBuffer; auto __emu_buffer = inapp->pBuffer;
uint32 count = ((*p)->Size() / sizeof(InternalVeteranReward)); uint32 count = ((*p)->Size() / sizeof(InternalVeteranReward));
*p = nullptr;
EQApplicationPacket *outapp_create = new EQApplicationPacket(OP_VetRewardsAvaliable, (sizeof(structs::VeteranReward)*count)); // calculate size of names, note the packet DOES NOT have null termed c-strings
uchar *old_data = __emu_buffer; std::vector<uint32> name_lengths;
uchar *data = outapp_create->pBuffer; for (int i = 0; i < count; ++i) {
for (unsigned int i = 0; i < count; ++i) InternalVeteranReward *ivr = (InternalVeteranReward *)__emu_buffer;
{
structs::VeteranReward *vr = (structs::VeteranReward*)data;
InternalVeteranReward *ivr = (InternalVeteranReward*)old_data;
vr->claim_count = ivr->claim_count; for (int i = 0; i < ivr->claim_count; i++) {
vr->claim_id = ivr->claim_id; uint32 length = strnlen(ivr->items[i].item_name, 63);
vr->number_available = ivr->number_available; if (length)
for (int x = 0; x < 8; ++x) name_lengths.push_back(length);
{
vr->items[x].item_id = ivr->items[x].item_id;
strncpy(vr->items[x].item_name, ivr->items[x].item_name, sizeof(vr->items[x].item_name));
vr->items[x].charges = ivr->items[x].charges;
} }
old_data += sizeof(InternalVeteranReward); __emu_buffer += sizeof(InternalVeteranReward);
data += sizeof(structs::VeteranReward);
} }
dest->FastQueuePacket(&outapp_create); uint32 packet_size = std::accumulate(name_lengths.begin(), name_lengths.end(), 0) +
sizeof(structs::VeteranReward) + (sizeof(structs::VeteranRewardEntry) * count) +
// size of name_lengths is the same as item count
(sizeof(structs::VeteranRewardItem) * name_lengths.size());
// build packet now!
auto outapp = new EQApplicationPacket(OP_VetRewardsAvaliable, packet_size);
__emu_buffer = inapp->pBuffer;
outapp->WriteUInt32(count);
auto name_itr = name_lengths.begin();
for (int i = 0; i < count; i++) {
InternalVeteranReward *ivr = (InternalVeteranReward *)__emu_buffer;
outapp->WriteUInt32(ivr->claim_id);
outapp->WriteUInt32(ivr->number_available);
outapp->WriteUInt32(ivr->claim_count);
outapp->WriteUInt8(1); // enabled
for (int j = 0; j < ivr->claim_count; j++) {
assert(name_itr != name_lengths.end()); // the way it's written, it should never happen, so just assert
outapp->WriteUInt32(*name_itr);
outapp->WriteData(ivr->items[j].item_name, *name_itr);
outapp->WriteUInt32(ivr->items[j].item_id);
outapp->WriteUInt32(ivr->items[j].charges);
++name_itr;
}
__emu_buffer += sizeof(InternalVeteranReward);
}
dest->FastQueuePacket(&outapp);
delete inapp; delete inapp;
} }
@ -4924,6 +4960,16 @@ namespace RoF
FINISH_DIRECT_DECODE(); FINISH_DIRECT_DECODE();
} }
DECODE(OP_VetClaimRequest)
{
DECODE_LENGTH_EXACT(structs::VeteranClaim);
SETUP_DIRECT_DECODE(VeteranClaim, structs::VeteranClaim);
IN(claim_id);
FINISH_DIRECT_DECODE();
}
DECODE(OP_ZoneChange) DECODE(OP_ZoneChange)
{ {
DECODE_LENGTH_EXACT(structs::ZoneChange_Struct); DECODE_LENGTH_EXACT(structs::ZoneChange_Struct);

View File

@ -15,6 +15,8 @@
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
#include <numeric>
#include <cassert>
namespace RoF2 namespace RoF2
{ {
@ -3749,37 +3751,71 @@ namespace RoF2
FINISH_ENCODE(); FINISH_ENCODE();
} }
ENCODE(OP_VetClaimReply)
{
ENCODE_LENGTH_EXACT(VeteranClaim);
SETUP_DIRECT_ENCODE(VeteranClaim, structs::VeteranClaim);
memcpy(eq->name, emu->name, sizeof(emu->name));
OUT(claim_id);
OUT(action);
FINISH_ENCODE();
}
ENCODE(OP_VetRewardsAvaliable) ENCODE(OP_VetRewardsAvaliable)
{ {
EQApplicationPacket *inapp = *p; EQApplicationPacket *inapp = *p;
unsigned char * __emu_buffer = inapp->pBuffer; auto __emu_buffer = inapp->pBuffer;
uint32 count = ((*p)->Size() / sizeof(InternalVeteranReward)); uint32 count = ((*p)->Size() / sizeof(InternalVeteranReward));
*p = nullptr;
EQApplicationPacket *outapp_create = new EQApplicationPacket(OP_VetRewardsAvaliable, (sizeof(structs::VeteranReward)*count)); // calculate size of names, note the packet DOES NOT have null termed c-strings
uchar *old_data = __emu_buffer; std::vector<uint32> name_lengths;
uchar *data = outapp_create->pBuffer; for (int i = 0; i < count; ++i) {
for (unsigned int i = 0; i < count; ++i) InternalVeteranReward *ivr = (InternalVeteranReward *)__emu_buffer;
{
structs::VeteranReward *vr = (structs::VeteranReward*)data;
InternalVeteranReward *ivr = (InternalVeteranReward*)old_data;
vr->claim_count = ivr->claim_count; for (int i = 0; i < ivr->claim_count; i++) {
vr->claim_id = ivr->claim_id; uint32 length = strnlen(ivr->items[i].item_name, 63);
vr->number_available = ivr->number_available; if (length)
for (int x = 0; x < 8; ++x) name_lengths.push_back(length);
{
vr->items[x].item_id = ivr->items[x].item_id;
strncpy(vr->items[x].item_name, ivr->items[x].item_name, sizeof(vr->items[x].item_name));
vr->items[x].charges = ivr->items[x].charges;
} }
old_data += sizeof(InternalVeteranReward); __emu_buffer += sizeof(InternalVeteranReward);
data += sizeof(structs::VeteranReward);
} }
dest->FastQueuePacket(&outapp_create); uint32 packet_size = std::accumulate(name_lengths.begin(), name_lengths.end(), 0) +
sizeof(structs::VeteranReward) + (sizeof(structs::VeteranRewardEntry) * count) +
// size of name_lengths is the same as item count
(sizeof(structs::VeteranRewardItem) * name_lengths.size());
// build packet now!
auto outapp = new EQApplicationPacket(OP_VetRewardsAvaliable, packet_size);
__emu_buffer = inapp->pBuffer;
outapp->WriteUInt32(count);
auto name_itr = name_lengths.begin();
for (int i = 0; i < count; i++) {
InternalVeteranReward *ivr = (InternalVeteranReward *)__emu_buffer;
outapp->WriteUInt32(ivr->claim_id);
outapp->WriteUInt32(ivr->number_available);
outapp->WriteUInt32(ivr->claim_count);
outapp->WriteUInt8(1); // enabled
for (int j = 0; j < ivr->claim_count; j++) {
assert(name_itr != name_lengths.end()); // the way it's written, it should never happen, so just assert
outapp->WriteUInt32(*name_itr);
outapp->WriteData(ivr->items[j].item_name, *name_itr);
outapp->WriteUInt32(ivr->items[j].item_id);
outapp->WriteUInt32(ivr->items[j].charges);
++name_itr;
}
__emu_buffer += sizeof(InternalVeteranReward);
}
dest->FastQueuePacket(&outapp);
delete inapp; delete inapp;
} }
@ -5122,6 +5158,16 @@ namespace RoF2
FINISH_DIRECT_DECODE(); FINISH_DIRECT_DECODE();
} }
DECODE(OP_VetClaimRequest)
{
DECODE_LENGTH_EXACT(structs::VeteranClaim);
SETUP_DIRECT_DECODE(VeteranClaim, structs::VeteranClaim);
IN(claim_id);
FINISH_DIRECT_DECODE();
}
DECODE(OP_ZoneChange) DECODE(OP_ZoneChange)
{ {
DECODE_LENGTH_EXACT(structs::ZoneChange_Struct); DECODE_LENGTH_EXACT(structs::ZoneChange_Struct);

View File

@ -111,6 +111,7 @@ E(OP_Trader)
E(OP_TraderBuy) E(OP_TraderBuy)
E(OP_TributeInfo) E(OP_TributeInfo)
E(OP_TributeItem) E(OP_TributeItem)
E(OP_VetClaimReply)
E(OP_VetRewardsAvaliable) E(OP_VetRewardsAvaliable)
E(OP_WearChange) E(OP_WearChange)
E(OP_WhoAllResponse) E(OP_WhoAllResponse)
@ -174,6 +175,7 @@ D(OP_Trader)
D(OP_TraderBuy) D(OP_TraderBuy)
D(OP_TradeSkillCombine) D(OP_TradeSkillCombine)
D(OP_TributeItem) D(OP_TributeItem)
D(OP_VetClaimRequest)
D(OP_WhoAllRequest) D(OP_WhoAllRequest)
D(OP_ZoneChange) D(OP_ZoneChange)
D(OP_ZoneEntry) D(OP_ZoneEntry)

View File

@ -4727,17 +4727,33 @@ struct AugmentInfo_Struct
struct VeteranRewardItem struct VeteranRewardItem
{ {
/*000*/ uint32 item_id; /*000*/ uint32 name_length;
/*004*/ uint32 charges; /*004*/ char item_name[0]; // THIS IS NOT NULL TERMED
/*008*/ char item_name[64]; /*???*/ uint32 item_id;
/*???*/ uint32 charges;
};
struct VeteranRewardEntry
{
/*000*/ uint32 claim_id; // guessed
/*004*/ uint32 avaliable_count;
/*008*/ uint32 claim_count;
/*012*/ char enabled;
/*013*/ VeteranRewardItem items[0];
}; };
struct VeteranReward struct VeteranReward
{ {
/*000*/ uint32 claim_id; /*000*/ uint32 claim_count;
/*004*/ uint32 number_available; /*004*/ VeteranRewardEntry entries[0];
/*008*/ uint32 claim_count; };
/*012*/ VeteranRewardItem items[8];
struct VeteranClaim
{
/*000*/ char name[68]; //name + other data
/*068*/ uint32 claim_id;
/*072*/ uint32 unknown072;
/*076*/ uint32 action;
}; };
struct ExpeditionEntryHeader_Struct struct ExpeditionEntryHeader_Struct

View File

@ -96,6 +96,7 @@ E(OP_Trader)
E(OP_TraderBuy) E(OP_TraderBuy)
E(OP_TributeInfo) E(OP_TributeInfo)
E(OP_TributeItem) E(OP_TributeItem)
E(OP_VetClaimReply)
E(OP_VetRewardsAvaliable) E(OP_VetRewardsAvaliable)
E(OP_WearChange) E(OP_WearChange)
E(OP_WhoAllResponse) E(OP_WhoAllResponse)
@ -159,6 +160,7 @@ D(OP_Trader)
D(OP_TraderBuy) D(OP_TraderBuy)
D(OP_TradeSkillCombine) D(OP_TradeSkillCombine)
D(OP_TributeItem) D(OP_TributeItem)
D(OP_VetClaimRequest)
D(OP_WhoAllRequest) D(OP_WhoAllRequest)
D(OP_ZoneChange) D(OP_ZoneChange)
D(OP_ZoneEntry) D(OP_ZoneEntry)

View File

@ -4718,17 +4718,33 @@ struct AugmentInfo_Struct
struct VeteranRewardItem struct VeteranRewardItem
{ {
/*000*/ uint32 item_id; /*000*/ uint32 name_length;
/*004*/ uint32 charges; /*004*/ char item_name[0]; // THIS IS NOT NULL TERMED
/*008*/ char item_name[64]; /*???*/ uint32 item_id;
/*???*/ uint32 charges;
};
struct VeteranRewardEntry
{
/*000*/ uint32 claim_id; // guessed
/*004*/ uint32 avaliable_count;
/*008*/ uint32 claim_count;
/*012*/ char enabled;
/*013*/ VeteranRewardItem items[0];
}; };
struct VeteranReward struct VeteranReward
{ {
/*000*/ uint32 claim_id; /*000*/ uint32 claim_count;
/*004*/ uint32 number_available; /*004*/ VeteranRewardEntry entries[0];
/*008*/ uint32 claim_count; };
/*012*/ VeteranRewardItem items[8];
struct VeteranClaim
{
/*000*/ char name[68]; //name + other data
/*068*/ uint32 claim_id;
/*072*/ uint32 unknown072;
/*076*/ uint32 action;
}; };
struct ExpeditionEntryHeader_Struct struct ExpeditionEntryHeader_Struct

View File

@ -525,7 +525,7 @@ OP_KnowledgeBase=0x0000
OP_SlashAdventure=0x571a # /adventure OP_SlashAdventure=0x571a # /adventure
OP_VetRewardsAvaliable=0x0557 OP_VetRewardsAvaliable=0x0557
OP_VetClaimRequest=0x6ba0 OP_VetClaimRequest=0x6ba0
OP_VetClaimReply=0x0000 OP_VetClaimReply=0x407e
OP_BecomePVPPrompt=0x36B2 #guessed from ASM OP_BecomePVPPrompt=0x36B2 #guessed from ASM
OP_PVPStats=0x5cc0 OP_PVPStats=0x5cc0
OP_PVPLeaderBoardRequest=0x61d2 OP_PVPLeaderBoardRequest=0x61d2

View File

@ -5362,25 +5362,26 @@ void Client::SendRewards()
FastQueuePacket(&vetapp); FastQueuePacket(&vetapp);
} }
bool Client::TryReward(uint32 claim_id) { bool Client::TryReward(uint32 claim_id)
//Make sure we have an open spot {
//Make sure we have it in our acct and count > 0 // Make sure we have an open spot
//Make sure the entry was found // Make sure we have it in our acct and count > 0
//If we meet all the criteria: // Make sure the entry was found
//Decrement our count by 1 if it > 1 delete if it == 1 // If we meet all the criteria:
//Create our item in bag if necessary at the free inv slot // Decrement our count by 1 if it > 1 delete if it == 1
//save // Create our item in bag if necessary at the free inv slot
// save
uint32 free_slot = 0xFFFFFFFF; uint32 free_slot = 0xFFFFFFFF;
for(int i = EmuConstants::GENERAL_BEGIN; i <= EmuConstants::GENERAL_END; ++i) { for (int i = EmuConstants::GENERAL_BEGIN; i <= EmuConstants::GENERAL_END; ++i) {
ItemInst *item = GetInv().GetItem(i); ItemInst *item = GetInv().GetItem(i);
if(!item) { if (!item) {
free_slot = i; free_slot = i;
break; break;
} }
} }
if(free_slot == 0xFFFFFFFF) if (free_slot == 0xFFFFFFFF)
return false; return false;
char errbuf[MYSQL_ERRMSG_SIZE]; char errbuf[MYSQL_ERRMSG_SIZE];
@ -5388,9 +5389,8 @@ bool Client::TryReward(uint32 claim_id) {
"WHERE account_id = %i AND reward_id = %i", "WHERE account_id = %i AND reward_id = %i",
AccountID(), claim_id); AccountID(), claim_id);
auto results = database.QueryDatabase(query); auto results = database.QueryDatabase(query);
if (!results.Success()) { if (!results.Success())
return false; return false;
}
if (results.RowCount() == 0) if (results.RowCount() == 0)
return false; return false;
@ -5398,52 +5398,49 @@ bool Client::TryReward(uint32 claim_id) {
auto row = results.begin(); auto row = results.begin();
uint32 amt = atoi(row[0]); uint32 amt = atoi(row[0]);
if(amt == 0) if (amt == 0)
return false; return false;
std::list<InternalVeteranReward>::iterator iter = zone->VeteranRewards.begin(); auto iter = std::find_if(zone->VeteranRewards.begin(), zone->VeteranRewards.end(),
for (; iter != zone->VeteranRewards.end(); ++row) [claim_id](const InternalVeteranReward &a) { return a.claim_id == claim_id; });
if((*iter).claim_id == claim_id)
break;
if(iter == zone->VeteranRewards.end()) if (iter == zone->VeteranRewards.end())
return false; return false;
if(amt == 1) { if (amt == 1) {
query = StringFormat("DELETE FROM account_rewards " query = StringFormat("DELETE FROM account_rewards "
"WHERE account_id = %i AND reward_id = %i", "WHERE account_id = %i AND reward_id = %i",
AccountID(), claim_id); AccountID(), claim_id);
auto results = database.QueryDatabase(query); auto results = database.QueryDatabase(query);
} } else {
else {
query = StringFormat("UPDATE account_rewards SET amount = (amount-1) " query = StringFormat("UPDATE account_rewards SET amount = (amount-1) "
"WHERE account_id = %i AND reward_id = %i", "WHERE account_id = %i AND reward_id = %i",
AccountID(), claim_id); AccountID(), claim_id);
auto results = database.QueryDatabase(query); auto results = database.QueryDatabase(query);
} }
InternalVeteranReward ivr = (*iter); auto &ivr = (*iter);
ItemInst *claim = database.CreateItem(ivr.items[0].item_id, ivr.items[0].charges); ItemInst *claim = database.CreateItem(ivr.items[0].item_id, ivr.items[0].charges);
if(!claim) { if (!claim) {
Save(); Save();
return true; return true;
} }
bool lore_conflict = CheckLoreConflict(claim->GetItem()); bool lore_conflict = CheckLoreConflict(claim->GetItem());
for(int y = 1; y < 8; y++) for (int y = 1; y < 8; y++)
if(ivr.items[y].item_id && claim->GetItem()->ItemClass == 1) { if (ivr.items[y].item_id && claim->GetItem()->ItemClass == 1) {
ItemInst *item_temp = database.CreateItem(ivr.items[y].item_id, ivr.items[y].charges); ItemInst *item_temp = database.CreateItem(ivr.items[y].item_id, ivr.items[y].charges);
if(item_temp) { if (item_temp) {
if(CheckLoreConflict(item_temp->GetItem())) { if (CheckLoreConflict(item_temp->GetItem())) {
lore_conflict = true; lore_conflict = true;
DuplicateLoreMessage(ivr.items[y].item_id); DuplicateLoreMessage(ivr.items[y].item_id);
} }
claim->PutItem(y-1, *item_temp); claim->PutItem(y - 1, *item_temp);
} }
} }
if(lore_conflict) { if (lore_conflict) {
safe_delete(claim); safe_delete(claim);
return true; return true;
} }

View File

@ -13793,41 +13793,32 @@ void Client::Handle_OP_TributeUpdate(const EQApplicationPacket *app)
void Client::Handle_OP_VetClaimRequest(const EQApplicationPacket *app) void Client::Handle_OP_VetClaimRequest(const EQApplicationPacket *app)
{ {
if (app->size < sizeof(VeteranClaimRequest)) if (app->size < sizeof(VeteranClaim)) {
{ Log.Out(Logs::General, Logs::None,
Log.Out(Logs::General, Logs::None, "OP_VetClaimRequest size lower than expected: got %u expected at least %u", app->size, sizeof(VeteranClaimRequest)); "OP_VetClaimRequest size lower than expected: got %u expected at least %u", app->size,
sizeof(VeteranClaim));
DumpPacket(app); DumpPacket(app);
return; return;
} }
VeteranClaimRequest *vcr = (VeteranClaimRequest*)app->pBuffer; VeteranClaim *vcr = (VeteranClaim *)app->pBuffer;
if (vcr->claim_id == 0xFFFFFFFF) //request update packet if (vcr->claim_id == 0xFFFFFFFF) { // request update packet
{
SendRewards(); SendRewards();
return;
} }
else //try to claim something! // try to claim something!
{ EQApplicationPacket *vetapp = new EQApplicationPacket(OP_VetClaimReply, sizeof(VeteranClaim));
VeteranClaim *cr = (VeteranClaim *)vetapp->pBuffer;
strcpy(cr->name, GetName());
cr->claim_id = vcr->claim_id;
if (!TryReward(vcr->claim_id)) if (!TryReward(vcr->claim_id))
{ cr->action = 1;
Message(13, "Your claim has been rejected.");
EQApplicationPacket *vetapp = new EQApplicationPacket(OP_VetClaimReply, sizeof(VeteranClaimReply));
VeteranClaimReply * cr = (VeteranClaimReply*)vetapp->pBuffer;
strcpy(cr->name, GetName());
cr->claim_id = vcr->claim_id;
cr->reject_field = -1;
FastQueuePacket(&vetapp);
}
else else
{ cr->action = 0;
EQApplicationPacket *vetapp = new EQApplicationPacket(OP_VetClaimReply, sizeof(VeteranClaimReply));
VeteranClaimReply * cr = (VeteranClaimReply*)vetapp->pBuffer;
strcpy(cr->name, GetName());
cr->claim_id = vcr->claim_id;
cr->reject_field = 0;
FastQueuePacket(&vetapp); FastQueuePacket(&vetapp);
}
}
} }
void Client::Handle_OP_VoiceMacroIn(const EQApplicationPacket *app) void Client::Handle_OP_VoiceMacroIn(const EQApplicationPacket *app)