From 6a28828e08eaa4a418c809537300163f8840cd42 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Sat, 27 Nov 2021 12:10:08 -0500 Subject: [PATCH] [API] mob->AppearanceEffects improved functionality. (#1821) * appearanceffectscript * update * debugged * [API] SendAppearanceEffect update * [API] SendAppearanceEffect update * [API] SendAppearanceEffect Upates perl method RemoveAppearanceEffect to remove the apperanceeffect * [API} AppearanceEffects update * [API] SendAppearanceEffects update --- zone/mob.cpp | 58 ++++++++++++++---- zone/mob.h | 3 +- zone/perl_mob.cpp | 147 ++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 190 insertions(+), 18 deletions(-) diff --git a/zone/mob.cpp b/zone/mob.cpp index e7fea3ca2..30cc77e45 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -2838,8 +2838,44 @@ void Mob::SendStunAppearance() safe_delete(outapp); } -void Mob::SendAppearanceEffect(uint32 parm1, uint32 parm2, uint32 parm3, uint32 parm4, uint32 parm5, Client *specific_target){ +void Mob::SendAppearanceEffect(uint32 parm1, uint32 parm2, uint32 parm3, uint32 parm4, uint32 parm5, Client *specific_target, + uint32 value1slot, uint32 value1ground, uint32 value2slot, uint32 value2ground, uint32 value3slot, uint32 value3ground, + uint32 value4slot, uint32 value4ground, uint32 value5slot, uint32 value5ground){ auto outapp = new EQApplicationPacket(OP_LevelAppearance, sizeof(LevelAppearance_Struct)); + + /* Location of the effect from value#slot, this is removed upon mob death/despawn. + 0 = pelvis1 + 1 = pelvis2 + 2 = helm + 3 = Offhand + 4 = Mainhand + 5 = left foot + 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. + */ + + //higher values can crash client + if (value1slot > 9) { + value1slot = 1; + } + if (value2slot > 9) { + value2slot = 1; + } + if (value2slot > 9) { + value2slot = 1; + } + if (value3slot > 9) { + value3slot = 1; + } + if (value4slot > 9) { + value4slot = 1; + } + if (value5slot > 9) { + value5slot = 1; + } + LevelAppearance_Struct* la = (LevelAppearance_Struct*)outapp->pBuffer; la->spawn_id = GetID(); la->parm1 = parm1; @@ -2849,16 +2885,16 @@ void Mob::SendAppearanceEffect(uint32 parm1, uint32 parm2, uint32 parm3, uint32 la->parm5 = parm5; // Note that setting the b values to 0 will disable the related effect from the corresponding parameter. // Setting the a value appears to have no affect at all.s - la->value1a = 1; - la->value1b = 1; - la->value2a = 1; - la->value2b = 1; - la->value3a = 1; - la->value3b = 1; - la->value4a = 1; - la->value4b = 1; - la->value5a = 1; - la->value5b = 1; + la->value1a = value1slot; + la->value1b = value1ground; + la->value2a = value2slot; + la->value2b = value2ground; + la->value3a = value3slot; + la->value3b = value3ground; + la->value4a = value4slot; + la->value4b = value4ground; + la->value5a = value5slot; + la->value5b = value5ground; if(specific_target == nullptr) { entity_list.QueueClients(this,outapp); } diff --git a/zone/mob.h b/zone/mob.h index 13c812cca..e3ae9c7f6 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -277,7 +277,8 @@ public: void ChangeSize(float in_size, bool bNoRestriction = false); void DoAnim(const int animnum, int type=0, bool ackreq = true, eqFilterType filter = FilterNone); void ProjectileAnimation(Mob* to, int item_id, bool IsArrow = false, float speed = 0, float angle = 0, float tilt = 0, float arc = 0, const char *IDFile = nullptr, EQ::skills::SkillType skillInUse = EQ::skills::SkillArchery); - void SendAppearanceEffect(uint32 parm1, uint32 parm2, uint32 parm3, uint32 parm4, uint32 parm5, Client *specific_target=nullptr); + void SendAppearanceEffect(uint32 parm1, uint32 parm2, uint32 parm3, uint32 parm4, uint32 parm5, Client *specific_target=nullptr, uint32 value1slot = 1, uint32 value1ground = 1, uint32 value2slot = 1, uint32 value2ground = 1, + uint32 value3slot = 1, uint32 value3ground = 1, uint32 value4slot = 1, uint32 value4ground = 1, uint32 value5slot = 1, uint32 value5ground = 1); void SendLevelAppearance(); void SendStunAppearance(); void SendTargetable(bool on, Client *specific_target = nullptr); diff --git a/zone/perl_mob.cpp b/zone/perl_mob.cpp index d87714367..006492918 100644 --- a/zone/perl_mob.cpp +++ b/zone/perl_mob.cpp @@ -4701,8 +4701,8 @@ XS(XS_Mob_HasNPCSpecialAtk) { XS(XS_Mob_SendAppearanceEffect); /* prototype to pass -Wmissing-prototypes */ XS(XS_Mob_SendAppearanceEffect) { dXSARGS; - if (items < 2 || items > 7) - Perl_croak(aTHX_ "Usage: Mob::SendAppearanceEffect(THIS, int32 param_1, [int32 param_2 = 0], [int32 param_3 = 0], [int32 param_4 = 0], [int32 param_5 = 0], [Client* single_client_to_send_to = null])"); // @categories Script Utility + if (items < 2 || items > 17) + Perl_croak(aTHX_ "Usage: Mob::SendAppearanceEffect(THIS, int32 effect1, [int32 effect2 = 0], [int32 effect3 = 0], [int32 effect4 = 0], [int32 effect5 = 0], [Client* single_client_to_send_to = null]), [uint32 slot1 = 1], [uint32 ground1 = 1], [uint32 slot2 = 1], [uint32 ground2 = 1], [uint32 slot3 = 1], [uint32 ground2 = 1], [uint32 slot4 = 1], [uint32 ground4 = 1], [uint32 slot5 = 1], [uint32 ground5 = 1]"); // @categories Script Utility { Mob *THIS; int32 parm1 = (int32) SvIV(ST(1)); @@ -4710,7 +4710,18 @@ XS(XS_Mob_SendAppearanceEffect) { int32 parm3 = 0; int32 parm4 = 0; int32 parm5 = 0; + uint32 value1slot = 1; + uint32 value1ground = 1; + uint32 value2slot = 1; + uint32 value2ground = 1; + uint32 value3slot = 1; + uint32 value3ground = 1; + uint32 value4slot = 1; + uint32 value4ground = 1; + uint32 value5slot = 1; + uint32 value5ground = 1; Client *client = nullptr; + bool nullclient = false; VALIDATE_THIS_IS_MOB; if (items > 2) { parm2 = (int32) SvIV(ST(2)); } if (items > 3) { parm3 = (int32) SvIV(ST(3)); } @@ -4718,15 +4729,136 @@ XS(XS_Mob_SendAppearanceEffect) { if (items > 5) { parm5 = (int32) SvIV(ST(5)); } if (items > 6) { if (sv_derived_from(ST(6), "Client")) { - IV tmp = SvIV((SV *) SvRV(ST(6))); + IV tmp = SvIV((SV *)SvRV(ST(6))); client = INT2PTR(Client *, tmp); - } else + } + else { + nullclient = true; + } + if (client == nullptr) { + nullclient = true; + } + } + if (items > 7) { value1slot = (uint32)SvIV(ST(7)); } + if (items > 8) { value1ground = (uint32)SvIV(ST(8)); } + if (items > 9) { value2slot = (uint32)SvIV(ST(9)); } + if (items > 10) { value2ground = (uint32)SvIV(ST(10)); } + if (items > 11) { value3slot = (uint32)SvIV(ST(11)); } + if (items > 12) { value3ground = (uint32)SvIV(ST(12)); } + if (items > 13) { value4slot = (uint32)SvIV(ST(13)); } + if (items > 14) { value4ground = (uint32)SvIV(ST(14)); } + if (items > 15) { value5slot = (uint32)SvIV(ST(15)); } + if (items > 16) { value5ground = (uint32)SvIV(ST(16)); } + + if (nullclient) { + THIS->SendAppearanceEffect(parm1, parm2, parm3, parm4, parm5, 0, value1slot, value1ground, value2slot, value2ground, value3slot, value3ground, + value4slot, value4ground, value5slot, value5ground); + } + else { + THIS->SendAppearanceEffect(parm1, parm2, parm3, parm4, parm5, client, value1slot, value1ground, value2slot, value2ground, value3slot, value3ground, + value4slot, value4ground, value5slot, value5ground); + } + } + XSRETURN_EMPTY; +} + +XS(XS_Mob_SendAppearanceEffectActor); /* prototype to pass -Wmissing-prototypes */ +XS(XS_Mob_SendAppearanceEffectActor) { + dXSARGS; + if (items < 3 || items > 12) + Perl_croak(aTHX_ "Usage: Mob::SendAppearanceEffectActor(THIS, int32 effect1, uint32 slot1 = 0, [int32 effect2 = 0], [uint32 slot2 = 0], [int32 effect3 = 0], [uint32 slot3 = 0], [int32 effect4 = 0], [uint32 slot4 = 0], [int32 effect5 = 0], [uint32 slot5 = 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 = 0; + int32 parm3 = 0; + uint32 value3slot = 0; + int32 parm4 = 0; + uint32 value4slot = 0; + int32 parm5 = 0; + uint32 value5slot = 0; + 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 (sv_derived_from(ST(11), "Client")) { + IV tmp = SvIV((SV *)SvRV(ST(11))); + client = INT2PTR(Client *, tmp); + } + else Perl_croak(aTHX_ "client is not of type Client"); if (client == nullptr) Perl_croak(aTHX_ "client is nullptr, avoiding crash."); } - THIS->SendAppearanceEffect(parm1, parm2, parm3, parm4, parm5, client); + THIS->SendAppearanceEffect(parm1, parm2, parm3, parm4, parm5, client, value1slot, 0, value2slot, 0, value3slot, 0, + value4slot, 0, value5slot, 0); + } + XSRETURN_EMPTY; +} + +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 + { + 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 (sv_derived_from(ST(6), "Client")) { + IV tmp = SvIV((SV *)SvRV(ST(11))); + client = INT2PTR(Client *, tmp); + } + else + Perl_croak(aTHX_ "client is not of type Client"); + if (client == nullptr) + 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); + } + XSRETURN_EMPTY; +} + +XS(XS_Mob_RemoveAllAppearanceEffects); /* prototype to pass -Wmissing-prototypes */ +XS(XS_Mob_RemoveAllAppearanceEffects) { + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: Mob::RemoveAllAppearanceEffects(THIS)"); // @categories Script Utility + { + Mob *THIS; + VALIDATE_THIS_IS_MOB; + THIS->SendIllusionPacket(THIS->GetRace()); } XSRETURN_EMPTY; } @@ -6698,6 +6830,7 @@ XS(boot_Mob) { newXSproto(strcpy(buf, "ProjectileAnim"), XS_Mob_ProjectileAnim, file, "$$$;$$$$$$"); newXSproto(strcpy(buf, "RandomizeFeatures"), XS_Mob_RandomizeFeatures, file, "$$;$"); newXSproto(strcpy(buf, "RangedAttack"), XS_Mob_RangedAttack, file, "$$"); + newXSproto(strcpy(buf, "RemoveAllAppearanceEffects"), XS_Mob_RemoveAllAppearanceEffects, file, "$"); newXSproto(strcpy(buf, "RemoveAllNimbusEffects"), XS_Mob_RemoveAllNimbusEffects, file, "$"); newXSproto(strcpy(buf, "RemoveFromFeignMemory"), XS_Mob_RemoveFromFeignMemory, file, "$$"); newXSproto(strcpy(buf, "RemoveNimbusEffect"), XS_Mob_RemoveNimbusEffect, file, "$$"); @@ -6710,7 +6843,9 @@ XS(boot_Mob) { newXSproto(strcpy(buf, "SeeImprovedHide"), XS_Mob_SeeImprovedHide, file, "$"); newXSproto(strcpy(buf, "SeeInvisible"), XS_Mob_SeeInvisible, file, "$"); newXSproto(strcpy(buf, "SeeInvisibleUndead"), XS_Mob_SeeInvisibleUndead, file, "$"); - newXSproto(strcpy(buf, "SendAppearanceEffect"), XS_Mob_SendAppearanceEffect, file, "$$;$$$$"); + newXSproto(strcpy(buf, "SendAppearanceEffect"), XS_Mob_SendAppearanceEffect, file, "$$;$$$$$$$$$$$$$$"); + newXSproto(strcpy(buf, "SendAppearanceEffectActor"), XS_Mob_SendAppearanceEffectActor, file, "$$$;$$$$$$$$$"); + newXSproto(strcpy(buf, "SendAppearanceEffectGround"), XS_Mob_SendAppearanceEffectGround, file, "$$$;$$$$$$$$$"); newXSproto(strcpy(buf, "SendIllusion"), XS_Mob_SendIllusion, file, "$$;$$$$$$$$$$$$"); newXSproto(strcpy(buf, "SendTo"), XS_Mob_SendTo, file, "$$$$"); newXSproto(strcpy(buf, "SendToFixZ"), XS_Mob_SendToFixZ, file, "$$$$");