mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-12 01:11:29 +00:00
[Opcode] Implement SetFace opcode (#2167)
* Implement SetFace opcode This implements the opcode that's used to update zone clients when a client updates their face * Use SetFace in #feature command Add check for valid number This adds the #feature eyes command which isn't in the illusion struct
This commit is contained in:
parent
29cdd91ca0
commit
d8aa8f7e7a
@ -455,6 +455,7 @@ N(OP_ServerListResponse),
|
||||
N(OP_SessionReady),
|
||||
N(OP_SetChatServer),
|
||||
N(OP_SetChatServer2),
|
||||
N(OP_SetFace),
|
||||
N(OP_SetGroupTarget),
|
||||
N(OP_SetGuildMOTD),
|
||||
N(OP_SetGuildRank),
|
||||
|
||||
@ -2316,9 +2316,12 @@ struct FaceChange_Struct {
|
||||
/*004*/ uint8 hairstyle;
|
||||
/*005*/ uint8 beard;
|
||||
/*006*/ uint8 face;
|
||||
/*007*/ uint32 drakkin_heritage;
|
||||
/*011*/ uint32 drakkin_tattoo;
|
||||
/*015*/ uint32 drakkin_details;
|
||||
/*007*/ uint8 unused_padding;
|
||||
/*008*/ uint32 drakkin_heritage;
|
||||
/*012*/ uint32 drakkin_tattoo;
|
||||
/*016*/ uint32 drakkin_details;
|
||||
/*020*/ uint32 entity_id;
|
||||
/*024*/
|
||||
//there are only 10 faces for barbs changing woad just
|
||||
//increase the face value by ten so if there were 8 woad
|
||||
//designs then there would be 80 barb faces
|
||||
|
||||
@ -2649,11 +2649,11 @@ struct FaceChange_Struct {
|
||||
/*004*/ uint8 hairstyle;
|
||||
/*005*/ uint8 beard;
|
||||
/*006*/ uint8 face;
|
||||
/*007*/ uint8 unknown007;
|
||||
/*007*/ uint8 unused_padding;
|
||||
/*008*/ uint32 drakkin_heritage;
|
||||
/*012*/ uint32 drakkin_tattoo;
|
||||
/*016*/ uint32 drakkin_details;
|
||||
/*020*/ uint32 unknown020;
|
||||
/*020*/ uint32 entity_id;
|
||||
/*024*/
|
||||
};
|
||||
//there are only 10 faces for barbs changing woad just
|
||||
|
||||
@ -2622,11 +2622,11 @@ struct FaceChange_Struct {
|
||||
/*004*/ uint8 hairstyle;
|
||||
/*005*/ uint8 beard;
|
||||
/*006*/ uint8 face;
|
||||
/*007*/ uint8 unknown007;
|
||||
/*007*/ uint8 unused_padding;
|
||||
/*008*/ uint32 drakkin_heritage;
|
||||
/*012*/ uint32 drakkin_tattoo;
|
||||
/*016*/ uint32 drakkin_details;
|
||||
/*020*/ uint32 unknown020;
|
||||
/*020*/ uint32 entity_id;
|
||||
/*024*/
|
||||
};
|
||||
//there are only 10 faces for barbs changing woad just
|
||||
|
||||
@ -2136,11 +2136,11 @@ struct FaceChange_Struct {
|
||||
/*004*/ uint8 hairstyle;
|
||||
/*005*/ uint8 beard;
|
||||
/*006*/ uint8 face;
|
||||
/*007*/ uint8 unknown007;
|
||||
/*007*/ uint8 unused_padding;
|
||||
/*008*/ uint32 drakkin_heritage;
|
||||
/*012*/ uint32 drakkin_tattoo;
|
||||
/*016*/ uint32 drakkin_details;
|
||||
/*020*/ uint32 unknown020;
|
||||
/*020*/ uint32 entity_id;
|
||||
/*024*/
|
||||
};
|
||||
//there are only 10 faces for barbs changing woad just
|
||||
|
||||
@ -2106,11 +2106,11 @@ struct FaceChange_Struct {
|
||||
/*004*/ uint8 hairstyle;
|
||||
/*005*/ uint8 beard;
|
||||
/*006*/ uint8 face;
|
||||
/*007*/ uint8 unknown007;
|
||||
/*007*/ uint8 unused_padding;
|
||||
/*008*/ uint32 drakkin_heritage;
|
||||
/*012*/ uint32 drakkin_tattoo;
|
||||
/*016*/ uint32 drakkin_details;
|
||||
/*020*/ uint32 unknown020;
|
||||
/*020*/ uint32 entity_id;
|
||||
/*024*/
|
||||
};
|
||||
//there are only 10 faces for barbs changing woad just
|
||||
|
||||
@ -1464,6 +1464,30 @@ namespace Titanium
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_SetFace)
|
||||
{
|
||||
auto emu = reinterpret_cast<FaceChange_Struct*>((*p)->pBuffer);
|
||||
|
||||
EQApplicationPacket outapp(OP_Illusion, sizeof(structs::Illusion_Struct));
|
||||
auto buf = reinterpret_cast<structs::Illusion_Struct*>(outapp.pBuffer);
|
||||
|
||||
buf->spawnid = emu->entity_id;
|
||||
buf->race = -1; // unchanged
|
||||
buf->gender = -1; // unchanged
|
||||
buf->texture = -1; // unchanged
|
||||
buf->helmtexture = -1; // unchanged
|
||||
buf->face = emu->face;
|
||||
buf->hairstyle = emu->hairstyle;
|
||||
buf->haircolor = emu->haircolor;
|
||||
buf->beard = emu->beard;
|
||||
buf->beardcolor = emu->beardcolor;
|
||||
buf->size = 0.0f; // unchanged
|
||||
|
||||
safe_delete(*p); // not using the original packet
|
||||
|
||||
dest->QueuePacket(&outapp, ack_req);
|
||||
}
|
||||
|
||||
ENCODE(OP_ShopPlayerSell)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(Merchant_Purchase_Struct);
|
||||
|
||||
@ -66,6 +66,7 @@ E(OP_ReadBook)
|
||||
E(OP_RespondAA)
|
||||
E(OP_SendCharInfo)
|
||||
E(OP_SendAATable)
|
||||
E(OP_SetFace)
|
||||
E(OP_ShopPlayerSell)
|
||||
E(OP_SpecialMesg)
|
||||
E(OP_TaskDescription)
|
||||
|
||||
@ -1761,8 +1761,7 @@ struct AdventureRequestResponse_Struct{
|
||||
struct Illusion_Struct {
|
||||
/*000*/ uint32 spawnid;
|
||||
/*004*/ char charname[64];
|
||||
/*068*/ uint16 race;
|
||||
/*070*/ char unknown070[2];
|
||||
/*068*/ int race;
|
||||
/*072*/ uint8 gender;
|
||||
/*073*/ uint8 texture;
|
||||
/*074*/ uint8 helmtexture;
|
||||
|
||||
@ -2185,11 +2185,11 @@ struct FaceChange_Struct {
|
||||
/*004*/ uint8 hairstyle;
|
||||
/*005*/ uint8 beard;
|
||||
/*006*/ uint8 face;
|
||||
/*007*/ uint8 unknown007;
|
||||
/*007*/ uint8 unused_padding;
|
||||
/*008*/ uint32 drakkin_heritage;
|
||||
/*012*/ uint32 drakkin_tattoo;
|
||||
/*016*/ uint32 drakkin_details;
|
||||
/*020*/ uint32 unknown020;
|
||||
/*020*/ uint32 entity_id;
|
||||
/*024*/
|
||||
};
|
||||
//there are only 10 faces for barbs changing woad just
|
||||
|
||||
@ -203,6 +203,7 @@ OP_DeleteSpell=0x3358
|
||||
OP_Surname=0x0423
|
||||
OP_ClearSurname=0x3fb0
|
||||
OP_FaceChange=0x5578
|
||||
OP_SetFace=0x1af3
|
||||
OP_SenseHeading=0x260a
|
||||
OP_Action=0x744c
|
||||
OP_ConsiderCorpse=0x5204
|
||||
|
||||
@ -201,6 +201,7 @@ OP_DeleteSpell=0x0736 # C
|
||||
OP_Surname=0x7547 # C
|
||||
OP_ClearSurname=0x2edd # C
|
||||
OP_FaceChange=0x5658 # C
|
||||
OP_SetFace=0x210a
|
||||
OP_SenseHeading=0x3887 # C
|
||||
OP_Action=0x2c27 # C
|
||||
OP_ConsiderCorpse=0x37a7 # C
|
||||
|
||||
@ -198,6 +198,7 @@ OP_DeleteSpell=0x6D7E #Xinu 02/20/09
|
||||
OP_Surname=0x683E #Xinu 02/21/09
|
||||
OP_ClearSurname=0x2613
|
||||
OP_FaceChange=0x482D #Trevius 01/16/09
|
||||
OP_SetFace=0x49dc
|
||||
OP_SenseHeading=0x1237 #Trevius 01/16/09
|
||||
OP_Action=0x5285 #Trevius 01/16/09
|
||||
OP_ConsiderCorpse=0x4CBB #Xinu 02/20/09
|
||||
|
||||
@ -205,6 +205,7 @@ OP_DeleteSpell=0x0698 # C
|
||||
OP_Surname=0x44ae # C
|
||||
OP_ClearSurname=0x6705 # C
|
||||
OP_FaceChange=0x37a7 # C
|
||||
OP_SetFace=0x6cfa
|
||||
OP_SenseHeading=0x1b8a # C
|
||||
OP_Action=0x0f14 # C
|
||||
OP_ConsiderCorpse=0x0a18 # C
|
||||
|
||||
@ -5856,10 +5856,11 @@ void Client::Handle_OP_FaceChange(const EQApplicationPacket *app)
|
||||
return;
|
||||
}
|
||||
|
||||
// Notify other clients in zone
|
||||
entity_list.QueueClients(this, app, false);
|
||||
auto fc = reinterpret_cast<FaceChange_Struct*>(app->pBuffer);
|
||||
|
||||
// Notify other clients in zone
|
||||
SetFaceAppearance(*fc, true);
|
||||
|
||||
FaceChange_Struct* fc = (FaceChange_Struct*)app->pBuffer;
|
||||
m_pp.haircolor = fc->haircolor;
|
||||
m_pp.beardcolor = fc->beardcolor;
|
||||
m_pp.eyecolor1 = fc->eyecolor1;
|
||||
@ -5872,7 +5873,6 @@ void Client::Handle_OP_FaceChange(const EQApplicationPacket *app)
|
||||
m_pp.drakkin_details = fc->drakkin_details;
|
||||
Save();
|
||||
MessageString(Chat::Red, FACE_ACCEPTED);
|
||||
//Message(Chat::Red, "Facial features updated.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
void command_feature(Client *c, const Seperator *sep)
|
||||
{
|
||||
int arguments = sep->argnum;
|
||||
if (arguments < 2) {
|
||||
if (arguments < 2 || !sep->IsNumber(2)) {
|
||||
auto feature_save_link = EQ::SayLinkEngine::GenerateQuestSaylink(
|
||||
"#npcedit featuresave",
|
||||
false,
|
||||
@ -13,6 +13,7 @@ void command_feature(Client *c, const Seperator *sep)
|
||||
c->Message(Chat::White, "Usage: #feature beard [Beard] - Change your or your target's Beard");
|
||||
c->Message(Chat::White, "Usage: #feature beardcolor [Beard Color] - Change your or your target's Beard Color");
|
||||
c->Message(Chat::White, "Usage: #feature details [Details] - Change your or your target's Drakkin Details");
|
||||
c->Message(Chat::White, "Usage: #feature eyes [Eye Color] - Change your or your target's Eyes");
|
||||
c->Message(Chat::White, "Usage: #feature face [Face] - Change your or your target's Face");
|
||||
c->Message(Chat::White, "Usage: #feature gender [Gender] - Change your or your target's Gender");
|
||||
c->Message(Chat::White, "Usage: #feature hair [Hair] - Change your or your target's Hair");
|
||||
@ -38,6 +39,7 @@ void command_feature(Client *c, const Seperator *sep)
|
||||
bool is_beard = !strcasecmp(sep->arg[1], "beard");
|
||||
bool is_beard_color = !strcasecmp(sep->arg[1], "beardcolor");
|
||||
bool is_details = !strcasecmp(sep->arg[1], "details");
|
||||
bool is_eyes = !strcasecmp(sep->arg[1], "eyes");
|
||||
bool is_face = !strcasecmp(sep->arg[1], "face");
|
||||
bool is_gender = !strcasecmp(sep->arg[1], "gender");
|
||||
bool is_hair = !strcasecmp(sep->arg[1], "hair");
|
||||
@ -53,6 +55,7 @@ void command_feature(Client *c, const Seperator *sep)
|
||||
!is_beard &&
|
||||
!is_beard_color &&
|
||||
!is_details &&
|
||||
!is_eyes &&
|
||||
!is_face &&
|
||||
!is_gender &&
|
||||
!is_hair &&
|
||||
@ -73,6 +76,7 @@ void command_feature(Client *c, const Seperator *sep)
|
||||
c->Message(Chat::White, "Usage: #feature beard [Beard] - Change your or your target's Beard");
|
||||
c->Message(Chat::White, "Usage: #feature beardcolor [Beard Color] - Change your or your target's Beard Color");
|
||||
c->Message(Chat::White, "Usage: #feature details [Details] - Change your or your target's Drakkin Details");
|
||||
c->Message(Chat::White, "Usage: #feature eyes [Eye Color] - Change your or your target's Eyes");
|
||||
c->Message(Chat::White, "Usage: #feature face [Face] - Change your or your target's Face");
|
||||
c->Message(Chat::White, "Usage: #feature gender [Gender] - Change your or your target's Gender");
|
||||
c->Message(Chat::White, "Usage: #feature hair [Hair] - Change your or your target's Hair");
|
||||
@ -93,57 +97,64 @@ void command_feature(Client *c, const Seperator *sep)
|
||||
return;
|
||||
}
|
||||
|
||||
auto beard = target->GetBeard();
|
||||
auto beard_color = target->GetBeardColor();
|
||||
auto details = target->GetDrakkinDetails();
|
||||
auto face = target->GetLuclinFace();
|
||||
FaceChange_Struct face{};
|
||||
face.haircolor = target->GetHairColor();
|
||||
face.beardcolor = target->GetBeardColor();
|
||||
face.eyecolor1 = target->GetEyeColor1();
|
||||
face.eyecolor2 = target->GetEyeColor2();
|
||||
face.hairstyle = target->GetHairStyle();
|
||||
face.face = target->GetLuclinFace();
|
||||
face.beard = target->GetBeard();
|
||||
face.drakkin_heritage = target->GetDrakkinHeritage();
|
||||
face.drakkin_tattoo = target->GetDrakkinTattoo();
|
||||
face.drakkin_details = target->GetDrakkinDetails();
|
||||
|
||||
auto gender = target->GetGender();
|
||||
auto hair = target->GetHairStyle();
|
||||
auto hair_color = target->GetHairColor();
|
||||
auto helm_texture = target->GetHelmTexture();
|
||||
auto heritage = target->GetDrakkinHeritage();
|
||||
auto race = target->GetModel();
|
||||
auto size = target->GetSize();
|
||||
auto tattoo = target->GetDrakkinTattoo();
|
||||
auto texture = target->GetTexture();
|
||||
|
||||
|
||||
std::string feature_changed;
|
||||
float value_changed;
|
||||
float value_changed = 0.0f;
|
||||
|
||||
if (is_beard) {
|
||||
beard = static_cast<uint8>(std::stoul(sep->arg[2]));
|
||||
face.beard = static_cast<uint8>(std::stoul(sep->arg[2]));
|
||||
feature_changed = "Beard";
|
||||
value_changed = beard;
|
||||
value_changed = face.beard;
|
||||
} else if (is_beard_color) {
|
||||
beard_color = static_cast<uint8>(std::stoul(sep->arg[2]));
|
||||
face.beardcolor = static_cast<uint8>(std::stoul(sep->arg[2]));
|
||||
feature_changed = "Beard Color";
|
||||
value_changed = beard_color;
|
||||
value_changed = face.beardcolor;
|
||||
} else if (is_details) {
|
||||
if (target->GetRace() != DRAKKIN) {
|
||||
c->Message(Chat::White, "You must target a Drakkin to use this command.");
|
||||
return;
|
||||
}
|
||||
|
||||
details = static_cast<uint8>(std::stoul(sep->arg[2]));
|
||||
face.drakkin_details = static_cast<uint8>(std::stoul(sep->arg[2]));
|
||||
feature_changed = "Drakkin Details";
|
||||
value_changed = details;
|
||||
value_changed = static_cast<float>(face.drakkin_details);
|
||||
} else if (is_eyes) {
|
||||
face.eyecolor1 = static_cast<uint8>(std::stoul(sep->arg[2]));
|
||||
feature_changed = "Eyes";
|
||||
value_changed = face.eyecolor1; // eyecolor2 isn't used
|
||||
} else if (is_face) {
|
||||
face = static_cast<uint8>(std::stoul(sep->arg[2]));
|
||||
face.face = static_cast<uint8>(std::stoul(sep->arg[2]));
|
||||
feature_changed = "Face";
|
||||
value_changed = face;
|
||||
value_changed = face.face;
|
||||
} else if (is_gender) {
|
||||
gender = static_cast<uint8>(std::stoul(sep->arg[2]));
|
||||
feature_changed = "Gender";
|
||||
value_changed = gender;
|
||||
} else if (is_hair) {
|
||||
hair = static_cast<uint8>(std::stoul(sep->arg[2]));
|
||||
face.hairstyle = static_cast<uint8>(std::stoul(sep->arg[2]));
|
||||
feature_changed = "Hair";
|
||||
value_changed = hair;
|
||||
value_changed = face.hairstyle;
|
||||
} else if (is_hair_color) {
|
||||
hair_color = static_cast<uint8>(std::stoul(sep->arg[2]));
|
||||
face.haircolor = static_cast<uint8>(std::stoul(sep->arg[2]));
|
||||
feature_changed = "Hair Color";
|
||||
value_changed = hair_color;
|
||||
value_changed = face.haircolor;
|
||||
} else if (is_helm) {
|
||||
helm_texture = static_cast<uint8>(std::stoul(sep->arg[2]));
|
||||
feature_changed = "Helmet Texture";
|
||||
@ -154,16 +165,16 @@ void command_feature(Client *c, const Seperator *sep)
|
||||
return;
|
||||
}
|
||||
|
||||
heritage = static_cast<uint8>(std::stoul(sep->arg[2]));
|
||||
face.drakkin_heritage = static_cast<uint8>(std::stoul(sep->arg[2]));
|
||||
feature_changed = "Drakkin Heritage";
|
||||
value_changed = heritage;
|
||||
value_changed = static_cast<float>(face.drakkin_heritage);
|
||||
} else if (is_race) {
|
||||
race = static_cast<uint16>(std::stoul(sep->arg[2]));
|
||||
feature_changed = "Race";
|
||||
value_changed = race;
|
||||
} else if (is_size) {
|
||||
size = std::stof(sep->arg[2]);
|
||||
|
||||
|
||||
if (size < 0 || size > 255) {
|
||||
c->Message(Chat::White, "Usage: #feature size [Size] - Change your or your target's Size temporarily (Valid values are 0 to 255, decimal increments are allowed.)");
|
||||
return;
|
||||
@ -177,33 +188,43 @@ void command_feature(Client *c, const Seperator *sep)
|
||||
return;
|
||||
}
|
||||
|
||||
tattoo = static_cast<uint8>(std::stoul(sep->arg[2]));
|
||||
face.drakkin_tattoo = static_cast<uint8>(std::stoul(sep->arg[2]));
|
||||
feature_changed = "Drakkin Tattoos";
|
||||
value_changed = tattoo;
|
||||
value_changed = static_cast<float>(face.drakkin_tattoo);
|
||||
} else if (is_texture) {
|
||||
texture = static_cast<uint8>(std::stoul(sep->arg[2]));
|
||||
feature_changed = "Texture";
|
||||
value_changed = texture;
|
||||
}
|
||||
|
||||
target->SendIllusionPacket(
|
||||
race,
|
||||
gender,
|
||||
texture,
|
||||
helm_texture,
|
||||
hair_color,
|
||||
beard_color,
|
||||
target->GetEyeColor1(),
|
||||
target->GetEyeColor2(),
|
||||
hair,
|
||||
face,
|
||||
beard,
|
||||
0xFF,
|
||||
heritage,
|
||||
tattoo,
|
||||
details,
|
||||
size
|
||||
);
|
||||
// For now face number is not set through SetFace. This is because the
|
||||
// client may not update face features after being set to an invalid face
|
||||
// until a specific valid face number is re-sent (needs more research)
|
||||
if (!is_gender && !is_helm && !is_race && !is_size && !is_texture && !is_face)
|
||||
{
|
||||
target->SetFaceAppearance(face);
|
||||
}
|
||||
else
|
||||
{
|
||||
target->SendIllusionPacket(
|
||||
race,
|
||||
gender,
|
||||
texture,
|
||||
helm_texture,
|
||||
face.haircolor,
|
||||
face.beardcolor,
|
||||
target->GetEyeColor1(),
|
||||
target->GetEyeColor2(),
|
||||
face.hairstyle,
|
||||
face.face,
|
||||
face.beard,
|
||||
0xFF,
|
||||
face.drakkin_heritage,
|
||||
face.drakkin_tattoo,
|
||||
face.drakkin_details,
|
||||
size
|
||||
);
|
||||
}
|
||||
|
||||
c->Message(
|
||||
Chat::White,
|
||||
|
||||
21
zone/mob.cpp
21
zone/mob.cpp
@ -2606,6 +2606,27 @@ void Mob::SendIllusionPacket(
|
||||
);
|
||||
}
|
||||
|
||||
void Mob::SetFaceAppearance(const FaceChange_Struct& face, bool skip_sender)
|
||||
{
|
||||
haircolor = face.haircolor;
|
||||
beardcolor = face.beardcolor;
|
||||
eyecolor1 = face.eyecolor1;
|
||||
eyecolor2 = face.eyecolor2;
|
||||
hairstyle = face.hairstyle;
|
||||
luclinface = face.face;
|
||||
beard = face.beard;
|
||||
drakkin_heritage = face.drakkin_heritage;
|
||||
drakkin_tattoo = face.drakkin_tattoo;
|
||||
drakkin_details = face.drakkin_details;
|
||||
|
||||
EQApplicationPacket outapp(OP_SetFace, sizeof(FaceChange_Struct));
|
||||
memcpy(outapp.pBuffer, &face, sizeof(FaceChange_Struct));
|
||||
auto buf = reinterpret_cast<FaceChange_Struct*>(outapp.pBuffer);
|
||||
buf->entity_id = GetID();
|
||||
|
||||
entity_list.QueueClients(this, &outapp, skip_sender);
|
||||
}
|
||||
|
||||
bool Mob::RandomizeFeatures(bool send_illusion, bool set_variables)
|
||||
{
|
||||
if (IsPlayerRace(GetRace())) {
|
||||
|
||||
@ -834,6 +834,7 @@ public:
|
||||
uint8 in_hairstyle = 0xFF, uint8 in_luclinface = 0xFF, uint8 in_beard = 0xFF, uint8 in_aa_title = 0xFF,
|
||||
uint32 in_drakkin_heritage = 0xFFFFFFFF, uint32 in_drakkin_tattoo = 0xFFFFFFFF,
|
||||
uint32 in_drakkin_details = 0xFFFFFFFF, float in_size = -1.0f, bool send_appearance_effects = true);
|
||||
void SetFaceAppearance(const FaceChange_Struct& face, bool skip_sender = false);
|
||||
bool RandomizeFeatures(bool send_illusion = true, bool set_variables = true);
|
||||
virtual void Stun(int duration);
|
||||
virtual void UnStun();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user