mirror of
https://github.com/EQEmu/Server.git
synced 2026-04-10 16:12:25 +00:00
Merge branch 'master' into luamod
This commit is contained in:
commit
4d8f5df261
@ -1695,6 +1695,7 @@ struct OnLevelMessage_Struct
|
|||||||
uint32 Duration;
|
uint32 Duration;
|
||||||
uint32 PopupID;
|
uint32 PopupID;
|
||||||
uint32 NegativeID;
|
uint32 NegativeID;
|
||||||
|
uint32 SoundControls;
|
||||||
char ButtonName0[25];
|
char ButtonName0[25];
|
||||||
char ButtonName1[25];
|
char ButtonName1[25];
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1849,6 +1849,7 @@ namespace RoF
|
|||||||
eq->Text_Count = 4096;
|
eq->Text_Count = 4096;
|
||||||
memcpy(eq->Text, emu->Text, sizeof(eq->Text));
|
memcpy(eq->Text, emu->Text, sizeof(eq->Text));
|
||||||
OUT(Buttons);
|
OUT(Buttons);
|
||||||
|
OUT(SoundControls);
|
||||||
OUT(Duration);
|
OUT(Duration);
|
||||||
OUT(PopupID);
|
OUT(PopupID);
|
||||||
OUT(NegativeID);
|
OUT(NegativeID);
|
||||||
|
|||||||
@ -1927,6 +1927,7 @@ namespace RoF2
|
|||||||
eq->Text_Count = 4096;
|
eq->Text_Count = 4096;
|
||||||
memcpy(eq->Text, emu->Text, sizeof(eq->Text));
|
memcpy(eq->Text, emu->Text, sizeof(eq->Text));
|
||||||
OUT(Buttons);
|
OUT(Buttons);
|
||||||
|
OUT(SoundControls);
|
||||||
OUT(Duration);
|
OUT(Duration);
|
||||||
OUT(PopupID);
|
OUT(PopupID);
|
||||||
OUT(NegativeID);
|
OUT(NegativeID);
|
||||||
|
|||||||
@ -2092,7 +2092,7 @@ struct OnLevelMessage_Struct {
|
|||||||
/*0000*/ uint32 ButtonName1_Count;
|
/*0000*/ uint32 ButtonName1_Count;
|
||||||
/*0000*/ char ButtonName1[25];
|
/*0000*/ char ButtonName1[25];
|
||||||
/*0000*/ uint8 Buttons;
|
/*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 Duration;
|
||||||
/*0000*/ uint32 PopupID; // If none zero, a response packet with 00 00 00 00 <PopupID> is returned on clicking the left button
|
/*0000*/ uint32 PopupID; // If none zero, a response packet with 00 00 00 00 <PopupID> is returned on clicking the left button
|
||||||
/*0000*/ uint32 NegativeID; // If none zero, a response packet with 01 00 00 00 <NegativeID> is returned on clicking the right button
|
/*0000*/ uint32 NegativeID; // If none zero, a response packet with 01 00 00 00 <NegativeID> is returned on clicking the right button
|
||||||
|
|||||||
@ -2122,7 +2122,7 @@ struct OnLevelMessage_Struct {
|
|||||||
/*0000*/ uint32 ButtonName1_Count;
|
/*0000*/ uint32 ButtonName1_Count;
|
||||||
/*0000*/ char ButtonName1[25];
|
/*0000*/ char ButtonName1[25];
|
||||||
/*0000*/ uint8 Buttons;
|
/*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 Duration;
|
||||||
/*0000*/ uint32 PopupID; // If none zero, a response packet with 00 00 00 00 <PopupID> is returned on clicking the left button
|
/*0000*/ uint32 PopupID; // If none zero, a response packet with 00 00 00 00 <PopupID> is returned on clicking the left button
|
||||||
/*0000*/ uint32 NegativeID; // If none zero, a response packet with 01 00 00 00 <NegativeID> is returned on clicking the right button
|
/*0000*/ uint32 NegativeID; // If none zero, a response packet with 01 00 00 00 <NegativeID> is returned on clicking the right button
|
||||||
|
|||||||
@ -1373,6 +1373,7 @@ namespace SoD
|
|||||||
memcpy(eq->Title, emu->Title, sizeof(eq->Title));
|
memcpy(eq->Title, emu->Title, sizeof(eq->Title));
|
||||||
memcpy(eq->Text, emu->Text, sizeof(eq->Text));
|
memcpy(eq->Text, emu->Text, sizeof(eq->Text));
|
||||||
OUT(Buttons);
|
OUT(Buttons);
|
||||||
|
OUT(SoundControls);
|
||||||
OUT(Duration);
|
OUT(Duration);
|
||||||
OUT(PopupID);
|
OUT(PopupID);
|
||||||
OUT(NegativeID);
|
OUT(NegativeID);
|
||||||
|
|||||||
@ -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
|
/*4224*/ char ButtonName0[25]; // If Buttons = 1, these two are the text for the left and right buttons respectively
|
||||||
/*4249*/ char ButtonName1[25];
|
/*4249*/ char ButtonName1[25];
|
||||||
/*4274*/ uint8 Buttons;
|
/*4274*/ uint8 Buttons;
|
||||||
/*4275*/ uint8 Unknown4275; // Something to do with audio controls
|
/*4275*/ uint8 SoundControls; // Something to do with audio controls
|
||||||
/*4276*/ uint32 Duration;
|
/*4276*/ uint32 Duration;
|
||||||
/*4280*/ uint32 PopupID; // If none zero, a response packet with 00 00 00 00 <PopupID> is returned on clicking the left button
|
/*4280*/ uint32 PopupID; // If none zero, a response packet with 00 00 00 00 <PopupID> is returned on clicking the left button
|
||||||
/*4284*/ uint32 NegativeID; // If none zero, a response packet with 01 00 00 00 <NegativeID> is returned on clicking the right button
|
/*4284*/ uint32 NegativeID; // If none zero, a response packet with 01 00 00 00 <NegativeID> is returned on clicking the right button
|
||||||
|
|||||||
@ -1607,6 +1607,7 @@ namespace UF
|
|||||||
memcpy(eq->Title, emu->Title, sizeof(eq->Title));
|
memcpy(eq->Title, emu->Title, sizeof(eq->Title));
|
||||||
memcpy(eq->Text, emu->Text, sizeof(eq->Text));
|
memcpy(eq->Text, emu->Text, sizeof(eq->Text));
|
||||||
OUT(Buttons);
|
OUT(Buttons);
|
||||||
|
OUT(SoundControls);
|
||||||
OUT(Duration);
|
OUT(Duration);
|
||||||
OUT(PopupID);
|
OUT(PopupID);
|
||||||
OUT(NegativeID);
|
OUT(NegativeID);
|
||||||
|
|||||||
@ -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
|
/*4224*/ char ButtonName0[25]; // If Buttons = 1, these two are the text for the left and right buttons respectively
|
||||||
/*4249*/ char ButtonName1[25];
|
/*4249*/ char ButtonName1[25];
|
||||||
/*4274*/ uint8 Buttons;
|
/*4274*/ uint8 Buttons;
|
||||||
/*4275*/ uint8 Unknown4275; // Something to do with audio controls
|
/*4275*/ uint8 SoundControls; // Something to do with audio controls
|
||||||
/*4276*/ uint32 Duration;
|
/*4276*/ uint32 Duration;
|
||||||
/*4280*/ uint32 PopupID; // If none zero, a response packet with 00 00 00 00 <PopupID> is returned on clicking the left button
|
/*4280*/ uint32 PopupID; // If none zero, a response packet with 00 00 00 00 <PopupID> is returned on clicking the left button
|
||||||
/*4284*/ uint32 NegativeID; // If none zero, a response packet with 01 00 00 00 <NegativeID> is returned on clicking the right button
|
/*4284*/ uint32 NegativeID; // If none zero, a response packet with 01 00 00 00 <NegativeID> is returned on clicking the right button
|
||||||
|
|||||||
@ -1202,6 +1202,11 @@ void Client::ActivateAlternateAdvancementAbility(int rank_id, int target_id) {
|
|||||||
Message_StringID(MT_SpellFailure, SNEAK_RESTRICT);
|
Message_StringID(MT_SpellFailure, SNEAK_RESTRICT);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
//
|
||||||
|
// Modern clients don't require pet targeted for AA casts that are 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
|
// 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(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)) {
|
if(!SpellFinished(rank->spell, entity_list.GetMob(target_id), EQEmu::CastingSlot::AltAbility, spells[rank->spell].mana, -1, spells[rank->spell].ResistDiff, false)) {
|
||||||
|
|||||||
@ -3960,6 +3960,46 @@ void Client::SendPopupToClient(const char *Title, const char *Text, uint32 Popup
|
|||||||
safe_delete(outapp);
|
safe_delete(outapp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
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, ...) {
|
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;
|
va_list argptr;
|
||||||
char buffer[4096];
|
char buffer[4096];
|
||||||
@ -8532,7 +8572,7 @@ void Client::Consume(const EQEmu::ItemData *item, uint8 type, int16 slot, bool a
|
|||||||
|
|
||||||
if (type == EQEmu::item::ItemTypeFood)
|
if (type == EQEmu::item::ItemTypeFood)
|
||||||
{
|
{
|
||||||
int hchange = item->CastTime * cons_mod;
|
int hchange = item->CastTime_ * cons_mod;
|
||||||
hchange = mod_food_value(item, hchange);
|
hchange = mod_food_value(item, hchange);
|
||||||
|
|
||||||
if(hchange < 0) { return; }
|
if(hchange < 0) { return; }
|
||||||
@ -8549,7 +8589,7 @@ void Client::Consume(const EQEmu::ItemData *item, uint8 type, int16 slot, bool a
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int tchange = item->CastTime * cons_mod;
|
int tchange = item->CastTime_ * cons_mod;
|
||||||
tchange = mod_drink_value(item, tchange);
|
tchange = mod_drink_value(item, tchange);
|
||||||
|
|
||||||
if(tchange < 0) { return; }
|
if(tchange < 0) { return; }
|
||||||
|
|||||||
@ -946,6 +946,7 @@ public:
|
|||||||
inline bool HasSpellScribed(int spellid) { return (FindSpellBookSlotBySpellID(spellid) != -1 ? true : false); }
|
inline bool HasSpellScribed(int spellid) { return (FindSpellBookSlotBySpellID(spellid) != -1 ? true : false); }
|
||||||
uint16 GetMaxSkillAfterSpecializationRules(EQEmu::skills::SkillType skillid, uint16 maxSkill);
|
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 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, ...);
|
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;
|
bool PendingTranslocate;
|
||||||
time_t TranslocateTime;
|
time_t TranslocateTime;
|
||||||
|
|||||||
@ -8606,6 +8606,10 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Modern clients don't require pet targeted for item clicks that are 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);
|
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
|
if (m_inv.SupportsClickCasting(slot_id) || ((item->ItemType == EQEmu::item::ItemTypePotion || item->PotionBelt) && m_inv.SupportsPotionBeltCasting(slot_id))) // sanity check
|
||||||
|
|||||||
@ -356,67 +356,15 @@ int32 Client::GetActSpellCost(uint16 spell_id, int32 cost)
|
|||||||
cost -= mana_back;
|
cost -= mana_back;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This formula was derived from the following resource:
|
int spec = GetSpecializeSkillValue(spell_id);
|
||||||
// http://www.eqsummoners.com/eq1/specialization-library.html
|
int PercentManaReduction = 0;
|
||||||
// WildcardX
|
if (spec)
|
||||||
float PercentManaReduction = 0;
|
PercentManaReduction = 1 + spec / 20; // there seems to be some non-obvious rounding here, let's truncate for now.
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int16 focus_redux = GetFocusEffect(focusManaCost, spell_id);
|
int16 focus_redux = GetFocusEffect(focusManaCost, spell_id);
|
||||||
|
PercentManaReduction += focus_redux;
|
||||||
|
|
||||||
if(focus_redux > 0)
|
cost -= cost * PercentManaReduction / 100;
|
||||||
{
|
|
||||||
PercentManaReduction += zone->random.Real(1, (double)focus_redux);
|
|
||||||
}
|
|
||||||
|
|
||||||
cost -= (cost * (PercentManaReduction / 100));
|
|
||||||
|
|
||||||
// Gift of Mana - reduces spell cost to 1 mana
|
// Gift of Mana - reduces spell cost to 1 mana
|
||||||
if(focus_redux >= 100) {
|
if(focus_redux >= 100) {
|
||||||
|
|||||||
@ -6444,6 +6444,47 @@ XS(XS_Client_GetAccountAge) {
|
|||||||
XSRETURN(1);
|
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, 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 Buttons = 0;
|
||||||
|
uint32 Duration = 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) { 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, Buttons, Duration, ButtonName0, ButtonName1, SoundControls);
|
||||||
|
}
|
||||||
|
XSRETURN_EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C"
|
extern "C"
|
||||||
@ -6698,6 +6739,7 @@ XS(boot_Client)
|
|||||||
newXSproto(strcpy(buf, "CalcEXP"), XS_Client_CalcEXP, file, "$");
|
newXSproto(strcpy(buf, "CalcEXP"), XS_Client_CalcEXP, file, "$");
|
||||||
newXSproto(strcpy(buf, "GetMoney"), XS_Client_GetMoney, file, "$$$");
|
newXSproto(strcpy(buf, "GetMoney"), XS_Client_GetMoney, file, "$$$");
|
||||||
newXSproto(strcpy(buf, "GetAccountAge"), XS_Client_GetAccountAge, file, "$");
|
newXSproto(strcpy(buf, "GetAccountAge"), XS_Client_GetAccountAge, file, "$");
|
||||||
|
newXSproto(strcpy(buf, "Popup2"), XS_Client_Popup2, file, "$$$;$$$$$$$");
|
||||||
XSRETURN_YES;
|
XSRETURN_YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -3059,6 +3059,12 @@ int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2,
|
|||||||
if (IsEffectIgnoredInStacking(effect1))
|
if (IsEffectIgnoredInStacking(effect1))
|
||||||
continue;
|
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 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.
|
If Caster1 isn't the same as Caster2 and the effect is a DoT then ignore it.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user