From 9277665f5f304f3b37ca843240ffc4ff4054d805 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 17 May 2017 15:03:14 -0400 Subject: [PATCH 01/12] Fix consumption Ahh not too sure why this is needed. We used the other field before and the client is still displaying correct item clicky cast times as well as food duration string ... Oh well --- zone/client.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zone/client.cpp b/zone/client.cpp index 4ec1ba898..d35308d73 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -8501,7 +8501,7 @@ void Client::Consume(const EQEmu::ItemData *item, uint8 type, int16 slot, bool a if (type == EQEmu::item::ItemTypeFood) { - int hchange = item->CastTime * cons_mod; + int hchange = item->CastTime_ * cons_mod; hchange = mod_food_value(item, hchange); if(hchange < 0) { return; } @@ -8518,7 +8518,7 @@ void Client::Consume(const EQEmu::ItemData *item, uint8 type, int16 slot, bool a } else { - int tchange = item->CastTime * cons_mod; + int tchange = item->CastTime_ * cons_mod; tchange = mod_drink_value(item, tchange); if(tchange < 0) { return; } From 5865948a8b9a2044def17a02e51ebb5c46615ff0 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 17 May 2017 15:20:27 -0400 Subject: [PATCH 02/12] Fix ST_Pet item/AA casts Modern clients don't require the pet to be targeted --- zone/aa.cpp | 5 +++++ zone/client_packet.cpp | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/zone/aa.cpp b/zone/aa.cpp index e002dd4f2..2451416aa 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -1202,6 +1202,11 @@ void Client::ActivateAlternateAdvancementAbility(int rank_id, int target_id) { Message_StringID(MT_SpellFailure, SNEAK_RESTRICT); return; } + // + // Modern clients don't require pet targeted for AA casts that are ST_Pet + if (spells[rank->spell].targettype == ST_Pet) + target_id = GetPetID(); + // Bards can cast instant cast AAs while they are casting another song if(spells[rank->spell].cast_time == 0 && GetClass() == BARD && IsBardSong(casting_spell_id)) { if(!SpellFinished(rank->spell, entity_list.GetMob(target_id), EQEmu::CastingSlot::AltAbility, spells[rank->spell].mana, -1, spells[rank->spell].ResistDiff, false)) { diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index bbd76183d..12250bdbd 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -8606,6 +8606,10 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app) return; } + // Modern clients don't require pet targeted for item clicks that are ST_Pet + if (spells[spell_id].targettype == ST_Pet) + target_id = GetPetID(); + Log(Logs::General, Logs::None, "OP ItemVerifyRequest: spell=%i, target=%i, inv=%i", spell_id, target_id, slot_id); if (m_inv.SupportsClickCasting(slot_id) || ((item->ItemType == EQEmu::item::ItemTypePotion || item->PotionBelt) && m_inv.SupportsPotionBeltCasting(slot_id))) // sanity check From 5eba112b7aa76622421f21b86f153ff2f47ba92d Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 18 May 2017 12:57:04 -0400 Subject: [PATCH 03/12] Fix Crash introduced in last patch --- zone/client_packet.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 12250bdbd..e9fad51c7 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -8599,15 +8599,15 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app) (IsAmnesiad() && IsDiscipline(spell_id)) || (IsDetrimentalSpell(spell_id) && !zone->CanDoCombat()) || (inst->IsScaling() && inst->GetExp() <= 0) // charms don't have spells when less than 0 - ) ) + ) { SendSpellBarEnable(spell_id); return; } // Modern clients don't require pet targeted for item clicks that are ST_Pet - if (spells[spell_id].targettype == ST_Pet) + if (spell_id > 0 && spells[spell_id].targettype == ST_Pet) target_id = GetPetID(); Log(Logs::General, Logs::None, "OP ItemVerifyRequest: spell=%i, target=%i, inv=%i", spell_id, target_id, slot_id); From 6bdcfaaa71522e51d339d185bcbad631ce93485b Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 18 May 2017 12:59:23 -0400 Subject: [PATCH 04/12] Forgot ST_SummonedPet --- zone/aa.cpp | 2 +- zone/client_packet.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/zone/aa.cpp b/zone/aa.cpp index 2451416aa..51cb376da 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -1204,7 +1204,7 @@ void Client::ActivateAlternateAdvancementAbility(int rank_id, int target_id) { } // // Modern clients don't require pet targeted for AA casts that are ST_Pet - if (spells[rank->spell].targettype == ST_Pet) + if (spells[rank->spell].targettype == ST_Pet || spells[rank->spell].targettype == ST_SummonedPet) target_id = GetPetID(); // Bards can cast instant cast AAs while they are casting another song diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index e9fad51c7..361c67d40 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -8607,7 +8607,7 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app) } // Modern clients don't require pet targeted for item clicks that are ST_Pet - if (spell_id > 0 && spells[spell_id].targettype == ST_Pet) + if (spell_id > 0 && (spells[spell_id].targettype == ST_Pet || spells[spell_id].targettype == ST_SummonedPet)) target_id = GetPetID(); Log(Logs::General, Logs::None, "OP ItemVerifyRequest: spell=%i, target=%i, inv=%i", spell_id, target_id, slot_id); From 962fcc2e8aa687a6383d96ca559d6e38b3e51661 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 24 May 2017 20:34:15 -0400 Subject: [PATCH 05/12] Modernize Specialization mana savings No idea how it worked in the past, this matches live and our AAs assume we're on new system so fuck the old code. --- zone/effects.cpp | 56 ++++-------------------------------------------- 1 file changed, 4 insertions(+), 52 deletions(-) diff --git a/zone/effects.cpp b/zone/effects.cpp index 2537751aa..2a1e189ce 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -356,58 +356,10 @@ int32 Client::GetActSpellCost(uint16 spell_id, int32 cost) cost -= mana_back; } - // This formula was derived from the following resource: - // http://www.eqsummoners.com/eq1/specialization-library.html - // WildcardX - float PercentManaReduction = 0; - float SpecializeSkill = GetSpecializeSkillValue(spell_id); - int SuccessChance = zone->random.Int(0, 100); - - float bonus = 1.0; - switch(GetAA(aaSpellCastingMastery)) - { - case 1: - bonus += 0.05; - break; - case 2: - bonus += 0.15; - break; - case 3: - bonus += 0.30; - break; - } - - bonus += 0.05f * GetAA(aaAdvancedSpellCastingMastery); - - if(SuccessChance <= (SpecializeSkill * 0.3 * bonus)) - { - PercentManaReduction = 1 + 0.05f * SpecializeSkill; - switch(GetAA(aaSpellCastingMastery)) - { - case 1: - PercentManaReduction += 2.5; - break; - case 2: - PercentManaReduction += 5.0; - break; - case 3: - PercentManaReduction += 10.0; - break; - } - - switch(GetAA(aaAdvancedSpellCastingMastery)) - { - case 1: - PercentManaReduction += 2.5; - break; - case 2: - PercentManaReduction += 5.0; - break; - case 3: - PercentManaReduction += 10.0; - break; - } - } + int spec = GetSpecializeSkillValue(spell_id); + int PercentManaReduction = 0; + if (spec) + PercentManaReduction = 1 + spec / 20; // there seems to be some non-obvious rounding here, let's truncate for now. int16 focus_redux = GetFocusEffect(focusManaCost, spell_id); From 7781dc6ffee4dc89eee684209b7caf134f3b51a7 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 24 May 2017 22:04:43 -0400 Subject: [PATCH 06/12] Remove double RNG for mana pres This still may not be 100% correct, but it may give us the correct average savings, but for more work than we need to do, but I don't need to rewrite code! Yet. --- zone/effects.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/zone/effects.cpp b/zone/effects.cpp index 2a1e189ce..3b19047d8 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -363,11 +363,6 @@ int32 Client::GetActSpellCost(uint16 spell_id, int32 cost) int16 focus_redux = GetFocusEffect(focusManaCost, spell_id); - if(focus_redux > 0) - { - PercentManaReduction += zone->random.Real(1, (double)focus_redux); - } - cost -= (cost * (PercentManaReduction / 100)); // Gift of Mana - reduces spell cost to 1 mana From b793f3d9cacdd1bb8ed203dc82918d9e5d27187b Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 24 May 2017 22:12:23 -0400 Subject: [PATCH 07/12] Whoops, lets make use of the calced focus effect --- zone/effects.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/effects.cpp b/zone/effects.cpp index 3b19047d8..a389a1336 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -361,7 +361,7 @@ int32 Client::GetActSpellCost(uint16 spell_id, int32 cost) if (spec) PercentManaReduction = 1 + spec / 20; // there seems to be some non-obvious rounding here, let's truncate for now. - int16 focus_redux = GetFocusEffect(focusManaCost, spell_id); + PercentManaReduction += GetFocusEffect(focusManaCost, spell_id); cost -= (cost * (PercentManaReduction / 100)); From c69df293450b66edccf10aa47414f9fd6760db20 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 24 May 2017 22:15:54 -0400 Subject: [PATCH 08/12] Fixed some idiot's mistake --- zone/effects.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/zone/effects.cpp b/zone/effects.cpp index a389a1336..135eb3f95 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -361,7 +361,8 @@ int32 Client::GetActSpellCost(uint16 spell_id, int32 cost) if (spec) PercentManaReduction = 1 + spec / 20; // there seems to be some non-obvious rounding here, let's truncate for now. - PercentManaReduction += GetFocusEffect(focusManaCost, spell_id); + int16 focus_redux = GetFocusEffect(focusManaCost, spell_id); + PercentManaReduction += focus_redux; cost -= (cost * (PercentManaReduction / 100)); From fd6387c830804ebcf53cb68de99a0298e8512cba Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 25 May 2017 12:45:17 -0400 Subject: [PATCH 09/12] Fix mana pres math --- zone/effects.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/effects.cpp b/zone/effects.cpp index 135eb3f95..8d8265e32 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -364,7 +364,7 @@ int32 Client::GetActSpellCost(uint16 spell_id, int32 cost) int16 focus_redux = GetFocusEffect(focusManaCost, spell_id); PercentManaReduction += focus_redux; - cost -= (cost * (PercentManaReduction / 100)); + cost -= cost * PercentManaReduction / 100; // Gift of Mana - reduces spell cost to 1 mana if(focus_redux >= 100) { From daced251018691ab66b20fa40826d840c2e71636 Mon Sep 17 00:00:00 2001 From: Natedog2012 Date: Sat, 3 Jun 2017 16:16:05 -0700 Subject: [PATCH 10/12] Add Popup2 .. allows for more customization of the popup window. Using PlayMp3 with the SoundControl option for Popup2 enabled will allow you to adjust sound volume as well. --- common/eq_packet_structs.h | 1 + common/patches/rof.cpp | 1 + common/patches/rof2.cpp | 1 + common/patches/rof2_structs.h | 2 +- common/patches/rof_structs.h | 2 +- common/patches/sod.cpp | 1 + common/patches/sod_structs.h | 2 +- common/patches/uf.cpp | 1 + common/patches/uf_structs.h | 2 +- zone/client.cpp | 40 +++++++++++++++++++++++++++++++++ zone/client.h | 1 + zone/perl_client.cpp | 42 +++++++++++++++++++++++++++++++++++ 12 files changed, 92 insertions(+), 4 deletions(-) diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index c84c4073a..c234e303a 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -1695,6 +1695,7 @@ struct OnLevelMessage_Struct uint32 Duration; uint32 PopupID; uint32 NegativeID; + uint32 SoundControls; char ButtonName0[25]; char ButtonName1[25]; }; diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index e342c5410..23e521a57 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -1849,6 +1849,7 @@ namespace RoF eq->Text_Count = 4096; memcpy(eq->Text, emu->Text, sizeof(eq->Text)); OUT(Buttons); + OUT(SoundControls); OUT(Duration); OUT(PopupID); OUT(NegativeID); diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index e38fde6f1..5befaf08c 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -1927,6 +1927,7 @@ namespace RoF2 eq->Text_Count = 4096; memcpy(eq->Text, emu->Text, sizeof(eq->Text)); OUT(Buttons); + OUT(SoundControls); OUT(Duration); OUT(PopupID); OUT(NegativeID); diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index 13befdad9..379941d51 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -2092,7 +2092,7 @@ struct OnLevelMessage_Struct { /*0000*/ uint32 ButtonName1_Count; /*0000*/ char ButtonName1[25]; /*0000*/ uint8 Buttons; -/*0000*/ uint8 Unknown4275; // Something to do with audio controls +/*0000*/ uint8 SoundControls; // Something to do with audio controls /*0000*/ uint32 Duration; /*0000*/ uint32 PopupID; // If none zero, a response packet with 00 00 00 00 is returned on clicking the left button /*0000*/ uint32 NegativeID; // If none zero, a response packet with 01 00 00 00 is returned on clicking the right button diff --git a/common/patches/rof_structs.h b/common/patches/rof_structs.h index 32c7c0d28..4c73c28d4 100644 --- a/common/patches/rof_structs.h +++ b/common/patches/rof_structs.h @@ -2122,7 +2122,7 @@ struct OnLevelMessage_Struct { /*0000*/ uint32 ButtonName1_Count; /*0000*/ char ButtonName1[25]; /*0000*/ uint8 Buttons; -/*0000*/ uint8 Unknown4275; // Something to do with audio controls +/*0000*/ uint8 SoundControls; // Something to do with audio controls /*0000*/ uint32 Duration; /*0000*/ uint32 PopupID; // If none zero, a response packet with 00 00 00 00 is returned on clicking the left button /*0000*/ uint32 NegativeID; // If none zero, a response packet with 01 00 00 00 is returned on clicking the right button diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index c68bfacef..f6d85f2bb 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -1373,6 +1373,7 @@ namespace SoD memcpy(eq->Title, emu->Title, sizeof(eq->Title)); memcpy(eq->Text, emu->Text, sizeof(eq->Text)); OUT(Buttons); + OUT(SoundControls); OUT(Duration); OUT(PopupID); OUT(NegativeID); diff --git a/common/patches/sod_structs.h b/common/patches/sod_structs.h index fdcb03658..ed71d837b 100644 --- a/common/patches/sod_structs.h +++ b/common/patches/sod_structs.h @@ -1760,7 +1760,7 @@ struct OnLevelMessage_Struct { /*4224*/ char ButtonName0[25]; // If Buttons = 1, these two are the text for the left and right buttons respectively /*4249*/ char ButtonName1[25]; /*4274*/ uint8 Buttons; -/*4275*/ uint8 Unknown4275; // Something to do with audio controls +/*4275*/ uint8 SoundControls; // Something to do with audio controls /*4276*/ uint32 Duration; /*4280*/ uint32 PopupID; // If none zero, a response packet with 00 00 00 00 is returned on clicking the left button /*4284*/ uint32 NegativeID; // If none zero, a response packet with 01 00 00 00 is returned on clicking the right button diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index e2093aef0..b6d251953 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -1607,6 +1607,7 @@ namespace UF memcpy(eq->Title, emu->Title, sizeof(eq->Title)); memcpy(eq->Text, emu->Text, sizeof(eq->Text)); OUT(Buttons); + OUT(SoundControls); OUT(Duration); OUT(PopupID); OUT(NegativeID); diff --git a/common/patches/uf_structs.h b/common/patches/uf_structs.h index 560a9378d..5a9562117 100644 --- a/common/patches/uf_structs.h +++ b/common/patches/uf_structs.h @@ -1801,7 +1801,7 @@ struct OnLevelMessage_Struct { /*4224*/ char ButtonName0[25]; // If Buttons = 1, these two are the text for the left and right buttons respectively /*4249*/ char ButtonName1[25]; /*4274*/ uint8 Buttons; -/*4275*/ uint8 Unknown4275; // Something to do with audio controls +/*4275*/ uint8 SoundControls; // Something to do with audio controls /*4276*/ uint32 Duration; /*4280*/ uint32 PopupID; // If none zero, a response packet with 00 00 00 00 is returned on clicking the left button /*4284*/ uint32 NegativeID; // If none zero, a response packet with 01 00 00 00 is returned on clicking the right button diff --git a/zone/client.cpp b/zone/client.cpp index d35308d73..ad8482b46 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -3929,6 +3929,46 @@ void Client::SendPopupToClient(const char *Title, const char *Text, uint32 Popup safe_delete(outapp); } +void Client::SendFullPopup(const char *Title, const char *Text, uint32 PopupID, uint32 NegativeID, uint32 Duration, uint32 Buttons, const char *ButtonName0, const char *ButtonName1, uint32 SoundControls) { + auto outapp = new EQApplicationPacket(OP_OnLevelMessage, sizeof(OnLevelMessage_Struct)); + OnLevelMessage_Struct *olms = (OnLevelMessage_Struct *)outapp->pBuffer; + + if((strlen(Text) > (sizeof(olms->Text)-1)) || (strlen(Title) > (sizeof(olms->Title) - 1)) ) { + safe_delete(outapp); + return; + } + + if (ButtonName0 && ButtonName1 && ( (strlen(ButtonName0) > (sizeof(olms->ButtonName0) - 1)) || (strlen(ButtonName1) > (sizeof(olms->ButtonName1) - 1)) ) ) { + safe_delete(outapp); + return; + } + + strcpy(olms->Title, Title); + strcpy(olms->Text, Text); + + olms->Buttons = Buttons; + + if (ButtonName0 == NULL || ButtonName1 == NULL) { + sprintf(olms->ButtonName0, "%s", "Yes"); + sprintf(olms->ButtonName1, "%s", "No"); + } else { + strcpy(olms->ButtonName0, ButtonName0); + strcpy(olms->ButtonName1, ButtonName1); + } + + if(Duration > 0) + olms->Duration = Duration * 1000; + else + olms->Duration = 0xffffffff; + + olms->PopupID = PopupID; + olms->NegativeID = NegativeID; + olms->SoundControls = SoundControls; + + QueuePacket(outapp); + safe_delete(outapp); +} + void Client::SendWindow(uint32 PopupID, uint32 NegativeID, uint32 Buttons, const char *ButtonName0, const char *ButtonName1, uint32 Duration, int title_type, Client* target, const char *Title, const char *Text, ...) { va_list argptr; char buffer[4096]; diff --git a/zone/client.h b/zone/client.h index 19dc4c05b..9ff541edc 100644 --- a/zone/client.h +++ b/zone/client.h @@ -945,6 +945,7 @@ public: inline bool HasSpellScribed(int spellid) { return (FindSpellBookSlotBySpellID(spellid) != -1 ? true : false); } uint16 GetMaxSkillAfterSpecializationRules(EQEmu::skills::SkillType skillid, uint16 maxSkill); void SendPopupToClient(const char *Title, const char *Text, uint32 PopupID = 0, uint32 Buttons = 0, uint32 Duration = 0); + void SendFullPopup(const char *Title, const char *Text, uint32 PopupID = 0, uint32 NegativeID = 0, uint32 Buttons = 0, uint32 Duration = 0, const char *ButtonName0 = 0, const char *ButtonName1 = 0, uint32 SoundControls = 0); void SendWindow(uint32 PopupID, uint32 NegativeID, uint32 Buttons, const char *ButtonName0, const char *ButtonName1, uint32 Duration, int title_type, Client* target, const char *Title, const char *Text, ...); bool PendingTranslocate; time_t TranslocateTime; diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index 46746970c..77fb0877b 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -6444,6 +6444,47 @@ XS(XS_Client_GetAccountAge) { XSRETURN(1); } +XS(XS_Client_Popup2); /* prototype to pass -Wmissing-prototypes */ +XS(XS_Client_Popup2) +{ + dXSARGS; + if (items < 3 || items > 10) + Perl_croak(aTHX_ "Usage: Client::SendFullPopup(THIS, Title, Text, PopupID, NegativeID, Duration, Buttons, ButtonName0, ButtonName1, SoundControls)"); + { + Client * THIS; + char* Title = (char *)SvPV_nolen(ST(1)); + char* Text = (char *)SvPV_nolen(ST(2)); + uint32 PopupID = 0; + uint32 NegativeID = 0; + uint32 Duration = 0; + uint32 Buttons = 0; + char* ButtonName0 = 0; + char* ButtonName1 = 0; + uint32 SoundControls = 0; + + if (sv_derived_from(ST(0), "Client")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(Client *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type Client"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + if (items > 3) { PopupID = (uint32)SvUV(ST(3)); } + if (items > 4) { NegativeID = (uint32)SvUV(ST(4)); } + if (items > 5) { Duration = (uint32)SvUV(ST(5)); } + if (items > 6) { Buttons = (uint32)SvUV(ST(6)); } + if (items > 7) { ButtonName0 = (char *)SvPV_nolen(ST(7)); } + if (items > 8) { ButtonName1 = (char *)SvPV_nolen(ST(8)); } + if (items > 9) { SoundControls = (uint32)SvUV(ST(9)); } + + + THIS->SendFullPopup(Title, Text, PopupID, NegativeID, Duration, Buttons, ButtonName0, ButtonName1, SoundControls); + } + XSRETURN_EMPTY; +} + #ifdef __cplusplus extern "C" @@ -6698,6 +6739,7 @@ XS(boot_Client) newXSproto(strcpy(buf, "CalcEXP"), XS_Client_CalcEXP, file, "$"); newXSproto(strcpy(buf, "GetMoney"), XS_Client_GetMoney, file, "$$$"); newXSproto(strcpy(buf, "GetAccountAge"), XS_Client_GetAccountAge, file, "$"); + newXSproto(strcpy(buf, "Popup2"), XS_Client_Popup2, file, "$$$;$$$$$$$"); XSRETURN_YES; } From decaa1f7b66967bb293cd6ec2f733f29a11d5ba0 Mon Sep 17 00:00:00 2001 From: Natedog2012 Date: Sat, 3 Jun 2017 16:35:30 -0700 Subject: [PATCH 11/12] Fix mismatch on Popup2 for Buttons / Duration (oops) $client->Popup2("Title", "Text", YesID, NoID, Buttons, Duration, Button0, Button1); YesID / NoID are the "popupid" for EVENT_POPUPRESPONSE depending on the players choice --- zone/client.cpp | 2 +- zone/perl_client.cpp | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/zone/client.cpp b/zone/client.cpp index ad8482b46..5f35c6916 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -3929,7 +3929,7 @@ void Client::SendPopupToClient(const char *Title, const char *Text, uint32 Popup safe_delete(outapp); } -void Client::SendFullPopup(const char *Title, const char *Text, uint32 PopupID, uint32 NegativeID, uint32 Duration, uint32 Buttons, const char *ButtonName0, const char *ButtonName1, uint32 SoundControls) { +void Client::SendFullPopup(const char *Title, const char *Text, uint32 PopupID, uint32 NegativeID, uint32 Buttons, uint32 Duration, const char *ButtonName0, const char *ButtonName1, uint32 SoundControls) { auto outapp = new EQApplicationPacket(OP_OnLevelMessage, sizeof(OnLevelMessage_Struct)); OnLevelMessage_Struct *olms = (OnLevelMessage_Struct *)outapp->pBuffer; diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index 77fb0877b..622551ce0 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -6449,15 +6449,15 @@ XS(XS_Client_Popup2) { dXSARGS; if (items < 3 || items > 10) - Perl_croak(aTHX_ "Usage: Client::SendFullPopup(THIS, Title, Text, PopupID, NegativeID, Duration, Buttons, ButtonName0, ButtonName1, SoundControls)"); + Perl_croak(aTHX_ "Usage: Client::SendFullPopup(THIS, Title, Text, PopupID, NegativeID, Buttons, Duration, ButtonName0, ButtonName1, SoundControls)"); { Client * THIS; char* Title = (char *)SvPV_nolen(ST(1)); char* Text = (char *)SvPV_nolen(ST(2)); uint32 PopupID = 0; uint32 NegativeID = 0; - uint32 Duration = 0; uint32 Buttons = 0; + uint32 Duration = 0; char* ButtonName0 = 0; char* ButtonName1 = 0; uint32 SoundControls = 0; @@ -6473,14 +6473,14 @@ XS(XS_Client_Popup2) if (items > 3) { PopupID = (uint32)SvUV(ST(3)); } if (items > 4) { NegativeID = (uint32)SvUV(ST(4)); } - if (items > 5) { Duration = (uint32)SvUV(ST(5)); } - if (items > 6) { Buttons = (uint32)SvUV(ST(6)); } + if (items > 5) { Buttons = (uint32)SvUV(ST(5)); } + if (items > 6) { Duration = (uint32)SvUV(ST(6)); } if (items > 7) { ButtonName0 = (char *)SvPV_nolen(ST(7)); } if (items > 8) { ButtonName1 = (char *)SvPV_nolen(ST(8)); } if (items > 9) { SoundControls = (uint32)SvUV(ST(9)); } - THIS->SendFullPopup(Title, Text, PopupID, NegativeID, Duration, Buttons, ButtonName0, ButtonName1, SoundControls); + THIS->SendFullPopup(Title, Text, PopupID, NegativeID, Buttons, Duration, ButtonName0, ButtonName1, SoundControls); } XSRETURN_EMPTY; } From c25a5fa0ba22b5904fbb34c105913e5191f6b6d4 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 8 Jun 2017 00:54:22 -0400 Subject: [PATCH 12/12] AC/ACv2 negative affects don't affect stacking fixes #622 Unsure if these are the only SPAs that should act this way, but this resolves the issues we were seeing --- zone/spells.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/zone/spells.cpp b/zone/spells.cpp index 2be0a0bce..ef0553526 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -3059,6 +3059,12 @@ int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, if (IsEffectIgnoredInStacking(effect1)) continue; + // negative AC affects are skipped. Ex. Sun's Corona and Glacier Breath should stack + // There may be more SPAs we need to add here .... + // The client does just check base rather than calculating the affect change value. + if ((effect1 == SE_ArmorClass || effect1 == SE_ACv2) && sp2.base[i] < 0) + continue; + /* If target is a npc and caster1 and caster2 exist If Caster1 isn't the same as Caster2 and the effect is a DoT then ignore it.