[Features] Appearance Effects will now be sent to clients upon zone in. GM commands. (#1874)

* start

* working

* Update perl_mob.cpp

* updates

* Update perl_mob.cpp

* illusion behavior

* rework start

* fix later

* Update mob.cpp

* rework

* updates

* Update mob.cpp

* update

* gm command updates

* updates

* Update CMakeLists.txt

* [Features] Appearance Effects will now be sent to clients upon zone in. GM commands.

remove debugs

* [Features] Appearance Effects will now be sent to clients upon zone in. GM commands.

perl fix

* [Features] Appearance Effects will now be sent to clients upon zone in. GM commands.

space fix

* [Features] Appearance Effects will now be sent to clients upon zone in. GM commands.

minor fix

* Update CMakeLists.txt

* [Features] Appearance Effects will now be sent to clients upon zone in. GM commands.

cleaned up some inconsistency

* [Features] Appearance Effects will now be sent to clients upon zone in. GM commands.
This commit is contained in:
KayenEQ 2021-12-10 13:46:23 -05:00 committed by GitHub
parent 550485ba33
commit 8de410ebb7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 177 additions and 26 deletions

View File

@ -188,7 +188,7 @@
#define MAX_SYMPATHETIC_PROCS 10 // Number of sympathetic procs a client can have (This is arbitrary)
#define MAX_FOCUS_PROC_LIMIT_TIMERS 20 //Number of focus recast timers that can be going at same time (This is arbitrary)
#define MAX_PROC_LIMIT_TIMERS 8 //Number of proc delay timers that can be going at same time, different proc types get their own timer array. (This is arbitrary)
#define MAX_APPEARANCE_EFFECTS 20 //Up to 20 Appearance Effects can be saved to a mobs appearance effect array, these will be sent to other clients when they enter a zone (This is arbitrary)
const int Z_AGGRO=10;

View File

@ -294,6 +294,7 @@ SET(gm_commands
gm_commands/aggrozone.cpp
gm_commands/ai.cpp
gm_commands/appearance.cpp
gm_commands/appearanceeffects.cpp
gm_commands/attack.cpp
gm_commands/augmentitem.cpp
gm_commands/ban.cpp

View File

@ -745,6 +745,8 @@ void Client::CompleteConnect()
entity_list.SendUntargetable(this);
entity_list.SendAppearanceEffects(this);
int x;
for (x = EQ::textures::textureBegin; x <= EQ::textures::LastTexture; x++) {
SendWearChange(x);

View File

@ -120,6 +120,7 @@ int command_init(void)
command_add("aggrozone", "[aggro] - Aggro every mob in the zone with X aggro. Default is 0. Not recommend if you're not invulnerable.", AccountStatus::GMAdmin, command_aggrozone) ||
command_add("ai", "[factionid/spellslist/con/guard/roambox/stop/start] - Modify AI on NPC target", AccountStatus::GMAdmin, command_ai) ||
command_add("appearance", "[type] [value] - Send an appearance packet for you or your target", AccountStatus::GMLeadAdmin, command_appearance) ||
command_add("appearanceeffects", "- [view] [set] [remove] appearance effects.", AccountStatus::GMAdmin, command_appearanceeffects) ||
command_add("apply_shared_memory", "[shared_memory_name] - Tells every zone and world to apply a specific shared memory segment by name.", AccountStatus::GMImpossible, command_apply_shared_memory) ||
command_add("attack", "[targetname] - Make your NPC target attack targetname", AccountStatus::GMLeadAdmin, command_attack) ||
command_add("augmentitem", "Force augments an item. Must have the augment item window open.", AccountStatus::GMImpossible, command_augmentitem) ||

View File

@ -34,6 +34,7 @@ void command_aggro(Client *c, const Seperator *sep);
void command_aggrozone(Client *c, const Seperator *sep);
void command_ai(Client *c, const Seperator *sep);
void command_appearance(Client *c, const Seperator *sep);
void command_appearanceeffects(Client *c, const Seperator *sep);
void command_apply_shared_memory(Client *c, const Seperator *sep);
void command_attack(Client *c, const Seperator *sep);
void command_augmentitem(Client *c, const Seperator *sep);

View File

@ -4582,6 +4582,26 @@ void EntityList::SendUntargetable(Client *c)
}
}
void EntityList::SendAppearanceEffects(Client *c)
{
if (!c)
return;
auto it = mob_list.begin();
while (it != mob_list.end()) {
Mob *cur = it->second;
if (cur) {
if (cur == c) {
++it;
continue;
}
cur->SendSavedAppearenceEffects(c);
}
++it;
}
}
void EntityList::ZoneWho(Client *c, Who_All_Struct *Who)
{
// This is only called for SoF clients, as regular /who is now handled server-side for that client.

View File

@ -380,6 +380,7 @@ public:
void SendZoneAppearance(Client *c);
void SendNimbusEffects(Client *c);
void SendUntargetable(Client *c);
void SendAppearanceEffects(Client *c);
void DuelMessage(Mob* winner, Mob* loser, bool flee);
void QuestJournalledSayClose(Mob *sender, float dist, const char* mobname, const char* message, Journal::Options &opts);
void GroupMessage(uint32 gid, const char *from, const char *message);

View File

@ -0,0 +1,44 @@
#include "../client.h"
void command_appearanceeffects(Client *c, const Seperator *sep)
{
if (sep->arg[1][0] == '\0' || !strcasecmp(sep->arg[1], "help")) {
c->Message(Chat::White, "Syntax: #appearanceeffects [subcommand].");
c->Message(Chat::White, "[view] Display all appearance effects saved to your target. #appearanceffects view");
c->Message(Chat::White, "[set] Set an appearance effects saved to your target. #appearanceffects set [app_effectid] [slotid]");
c->Message(Chat::White, "[remove] Remove all appearance effects saved to your target. #appearanceffects remove");
}
if (!strcasecmp(sep->arg[1], "view")) {
Mob* m_target = c->GetTarget();
if (m_target) {
m_target->GetAppearenceEffects();
}
return;
}
if (!strcasecmp(sep->arg[1], "set")) {
int32 app_effectid = atof(sep->arg[2]);
int32 slot = atoi(sep->arg[3]);
Mob* m_target = c->GetTarget();
if (m_target) {
m_target->SendAppearanceEffect(app_effectid, 0, 0, 0, 0, nullptr, slot, 0, 0, 0, 0, 0, 0, 0, 0, 0);
c->Message(Chat::White, "Appearance Effect ID %i for slot %i has been set.", app_effectid, slot);
}
}
if (!strcasecmp(sep->arg[1], "remove")) {
Mob* m_target = c->GetTarget();
if (m_target) {
m_target->SendIllusionPacket(m_target->GetRace(), m_target->GetGender(), m_target->GetTexture(), m_target->GetHelmTexture(),
m_target->GetHairColor(), m_target->GetBeardColor(), m_target->GetEyeColor1(), m_target->GetEyeColor2(),
m_target->GetHairStyle(), m_target->GetLuclinFace(), m_target->GetBeard(), 0xFF,
m_target->GetDrakkinHeritage(), m_target->GetDrakkinTattoo(), m_target->GetDrakkinDetails(), m_target->GetSize(), false);
m_target->ClearAppearenceEffects();
c->Message(Chat::White, "All Appearance Effects have been removed.");
}
return;
}
}

View File

@ -480,6 +480,11 @@ Mob::Mob(
Vulnerability_Mod[i] = 0;
}
for (int i = 0; i < MAX_APPEARANCE_EFFECTS; i++) {
appearance_effects_id[i] = 0;
appearance_effects_slot[i] = 0;
}
emoteid = 0;
endur_upkeep = false;
degenerating_effects = false;
@ -2385,7 +2390,8 @@ void Mob::SendIllusionPacket(
uint32 in_drakkin_heritage,
uint32 in_drakkin_tattoo,
uint32 in_drakkin_details,
float in_size
float in_size,
bool send_appearance_effects
)
{
uint8 new_texture = in_texture;
@ -2494,6 +2500,10 @@ void Mob::SendIllusionPacket(
/* Refresh armor and tints after send illusion packet */
SendArmorAppearance();
if (send_appearance_effects) {
SendSavedAppearenceEffects(nullptr);
}
LogSpells(
"Illusion: Race [{}] Gender [{}] Texture [{}] HelmTexture [{}] HairColor [{}] BeardColor [{}] EyeColor1 [{}] EyeColor2 [{}] HairStyle [{}] Face [{}] DrakkinHeritage [{}] DrakkinTattoo [{}] DrakkinDetails [{}] Size [{}]",
race,
@ -2869,7 +2879,7 @@ void Mob::SendAppearanceEffect(uint32 parm1, uint32 parm2, uint32 parm3, uint32
6 = right foot
9 = Face
value#ground = 1, will place the effect on ground, of corresponding slot is set to 0 effect is permanenant, if > 0 will fade if mob death/despawn.
value#ground = 1, will place the effect on ground, this is permanenant
*/
//higher values can crash client
@ -2892,6 +2902,22 @@ void Mob::SendAppearanceEffect(uint32 parm1, uint32 parm2, uint32 parm3, uint32
value5slot = 1;
}
if (!value1ground && parm1) {
SetAppearenceEffects(value1slot, parm1);
}
if (!value2ground && parm2) {
SetAppearenceEffects(value2slot, parm2);
}
if (!value3ground && parm3) {
SetAppearenceEffects(value3slot, parm3);
}
if (!value4ground && parm4) {
SetAppearenceEffects(value4slot, parm4);
}
if (!value5ground && parm5) {
SetAppearenceEffects(value5slot, parm5);
}
LevelAppearance_Struct* la = (LevelAppearance_Struct*)outapp->pBuffer;
la->spawn_id = GetID();
la->parm1 = parm1;
@ -2920,6 +2946,62 @@ void Mob::SendAppearanceEffect(uint32 parm1, uint32 parm2, uint32 parm3, uint32
safe_delete(outapp);
}
void Mob::SetAppearenceEffects(int32 slot, int32 value)
{
for (int i = 0; i < MAX_APPEARANCE_EFFECTS; i++) {
if (!appearance_effects_id[i]) {
appearance_effects_id[i] = value;
appearance_effects_slot[i] = slot;
return;
}
}
}
void Mob::GetAppearenceEffects()
{
//used with GM command
if (!appearance_effects_id[0]) {
Message(Chat::Red, "No Appearance Effects exist on this mob");
return;
}
for (int i = 0; i < MAX_APPEARANCE_EFFECTS; i++) {
Message(Chat::Red, "ID: %i :: App Effect ID %i :: Slot %i", i, appearance_effects_id[i], appearance_effects_slot[i]);
}
}
void Mob::ClearAppearenceEffects()
{
for (int i = 0; i < MAX_APPEARANCE_EFFECTS; i++) {
appearance_effects_id[i] = 0;
appearance_effects_slot[i] = 0;
}
}
void Mob::SendSavedAppearenceEffects(Client *receiver = nullptr)
{
if (!appearance_effects_id[0]) {
return;
}
if (appearance_effects_id[0]) {
SendAppearanceEffect(appearance_effects_id[0], appearance_effects_id[1], appearance_effects_id[2], appearance_effects_id[3], appearance_effects_id[4], receiver,
appearance_effects_slot[0], 0, appearance_effects_slot[1], 0, appearance_effects_slot[2], 0, appearance_effects_slot[3], 0, appearance_effects_slot[4], 0);
}
if (appearance_effects_id[5]) {
SendAppearanceEffect(appearance_effects_id[5], appearance_effects_id[6], appearance_effects_id[7], appearance_effects_id[8], appearance_effects_id[9], receiver,
appearance_effects_slot[5], 0, appearance_effects_slot[6], 0, appearance_effects_slot[7], 0, appearance_effects_slot[8], 0, appearance_effects_slot[9], 0);
}
if (appearance_effects_id[10]) {
SendAppearanceEffect(appearance_effects_id[10], appearance_effects_id[11], appearance_effects_id[12], appearance_effects_id[13], appearance_effects_id[14], receiver,
appearance_effects_slot[10], 0, appearance_effects_slot[11], 0, appearance_effects_slot[12], 0, appearance_effects_slot[13], 0, appearance_effects_slot[14], 0);
}
if (appearance_effects_id[15]) {
SendAppearanceEffect(appearance_effects_id[15], appearance_effects_id[16], appearance_effects_id[17], appearance_effects_id[18], appearance_effects_id[19], receiver,
appearance_effects_slot[15], 0, appearance_effects_slot[16], 0, appearance_effects_slot[17], 0, appearance_effects_slot[18], 0, appearance_effects_slot[19], 0);
}
}
void Mob::SendTargetable(bool on, Client *specific_target) {
auto outapp = new EQApplicationPacket(OP_Untargetable, sizeof(Untargetable_Struct));
Untargetable_Struct *ut = (Untargetable_Struct*)outapp->pBuffer;

View File

@ -425,6 +425,10 @@ public:
inline bool HasEndurUpkeep() const { return endur_upkeep; }
inline void SetEndurUpkeep(bool val) { endur_upkeep = val; }
bool HasBuffWithSpellGroup(int spell_group);
void SetAppearenceEffects(int32 slot, int32 value);
void GetAppearenceEffects();
void ClearAppearenceEffects();
void SendSavedAppearenceEffects(Client *receiver);
//Basic Stats/Inventory
virtual void SetLevel(uint8 in_level, bool command = false) { level = in_level; }
@ -788,7 +792,7 @@ public:
uint8 in_haircolor = 0xFF, uint8 in_beardcolor = 0xFF, uint8 in_eyecolor1 = 0xFF, uint8 in_eyecolor2 = 0xFF,
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);
uint32 in_drakkin_details = 0xFFFFFFFF, float in_size = -1.0f, bool send_appearance_effects = true);
bool RandomizeFeatures(bool send_illusion = true, bool set_variables = true);
virtual void Stun(int duration);
virtual void UnStun();
@ -1508,6 +1512,9 @@ protected:
Timer def_proclimit_timer[MAX_PROC_LIMIT_TIMERS]; //SPA 512
int32 def_proclimit_spellid[MAX_PROC_LIMIT_TIMERS]; //SPA 512
int32 appearance_effects_id[MAX_APPEARANCE_EFFECTS];
int32 appearance_effects_slot[MAX_APPEARANCE_EFFECTS];
Timer shield_timer;
uint32 m_shield_target_id;
uint32 m_shielder_id;

View File

@ -4809,31 +4809,22 @@ XS(XS_Mob_SendAppearanceEffectActor) {
XS(XS_Mob_SendAppearanceEffectGround); /* prototype to pass -Wmissing-prototypes */
XS(XS_Mob_SendAppearanceEffectGround) {
dXSARGS;
if (items < 3 || items > 12)
Perl_croak(aTHX_ "Usage: Mob::SendAppearanceEffectGround(THIS, int32 effect1, uint32 slot1 = 1, [int32 effect2 = 0], [uint32 slot2 = 1], [int32 effect3 = 0], [uint32 slot3 = 1], [int32 effect4 = 0], [uint32 slot4 = 1], [int32 effect5 = 0], [uint32 slot5 = 1], [Client* single_client_to_send_to = null])"); // @categories Script Utility
if (items < 3 || items > 8)
Perl_croak(aTHX_ "Usage: Mob::SendAppearanceEffectGround(THIS, int32 effect1, [int32 effect2 = 0], [int32 effect3 = 0], [int32 effect4 = 0], [int32 effect5 = 0], [Client* single_client_to_send_to = null])"); // @categories Script Utility
{
Mob *THIS;
int32 parm1 = (int32)SvIV(ST(1));
uint32 value1slot = (uint32)SvIV(ST(2));
int32 parm2 = 0;
uint32 value2slot = 1;
int32 parm3 = 0;
uint32 value3slot = 1;
int32 parm4 = 0;
uint32 value4slot = 1;
int32 parm5 = 0;
uint32 value5slot = 1;
Client *client = nullptr;
VALIDATE_THIS_IS_MOB;
if (items > 3) { parm2 = (int32)SvIV(ST(3)); }
if (items > 4) { value2slot = (uint32)SvIV(ST(4)); }
if (items > 5) { parm3 = (int32)SvIV(ST(5)); }
if (items > 6) { value3slot = (uint32)SvIV(ST(6)); }
if (items > 7) { parm4 = (int32)SvIV(ST(7)); }
if (items > 8) { value4slot = (uint32)SvIV(ST(8)); }
if (items > 9) { parm5 = (int32)SvIV(ST(9)); }
if (items > 10) { value5slot = (uint32)SvIV(ST(10)); }
if (items > 11) {
if (items > 3) { parm2 = (int32)SvIV(ST(2)); }
if (items > 4) { parm3 = (int32)SvIV(ST(3)); }
if (items > 5) { parm4 = (int32)SvIV(ST(4)); }
if (items > 6) { parm5 = (int32)SvIV(ST(5)); }
if (items > 7) {
if (sv_derived_from(ST(6), "Client")) {
IV tmp = SvIV((SV *)SvRV(ST(11)));
client = INT2PTR(Client *, tmp);
@ -4844,8 +4835,8 @@ XS(XS_Mob_SendAppearanceEffectGround) {
Perl_croak(aTHX_ "client is nullptr, avoiding crash.");
}
THIS->SendAppearanceEffect(parm1, parm2, parm3, parm4, parm5, client, value1slot, 1, value2slot, 1, value3slot, 1,
value4slot, 1, value5slot, 1);
THIS->SendAppearanceEffect(parm1, parm2, parm3, parm4, parm5, client, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1);
}
XSRETURN_EMPTY;
}
@ -4858,10 +4849,11 @@ XS(XS_Mob_RemoveAllAppearanceEffects) {
{
Mob *THIS;
VALIDATE_THIS_IS_MOB;
THIS->SendIllusionPacket(THIS->GetRace(), THIS->GetGender(), THIS->GetTexture(), THIS->GetHelmTexture(),
THIS->GetHairColor(), THIS->GetBeardColor(), THIS->GetEyeColor1(), THIS->GetEyeColor2(),
THIS->GetHairStyle(), THIS->GetLuclinFace(), THIS->GetBeard(), 0xFF,
THIS->GetDrakkinHeritage(), THIS->GetDrakkinTattoo(), THIS->GetDrakkinDetails(), THIS->GetSize());
THIS->SendIllusionPacket(THIS->GetRace(), THIS->GetGender(), THIS->GetTexture(), THIS->GetHelmTexture(),
THIS->GetHairColor(), THIS->GetBeardColor(), THIS->GetEyeColor1(), THIS->GetEyeColor2(),
THIS->GetHairStyle(), THIS->GetLuclinFace(), THIS->GetBeard(), 0xFF,
THIS->GetDrakkinHeritage(), THIS->GetDrakkinTattoo(), THIS->GetDrakkinDetails(), THIS->GetSize(), false);
THIS->ClearAppearenceEffects();
}
XSRETURN_EMPTY;
}