mirror of
https://github.com/EQEmu/Server.git
synced 2026-02-17 18:02:26 +00:00
Merge branch 'master' into luamod
This commit is contained in:
commit
4d8f5df261
@ -1695,6 +1695,7 @@ struct OnLevelMessage_Struct
|
||||
uint32 Duration;
|
||||
uint32 PopupID;
|
||||
uint32 NegativeID;
|
||||
uint32 SoundControls;
|
||||
char ButtonName0[25];
|
||||
char ButtonName1[25];
|
||||
};
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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 <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
|
||||
|
||||
@ -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 <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
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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 <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
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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 <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
|
||||
|
||||
@ -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 || spells[rank->spell].targettype == ST_SummonedPet)
|
||||
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)) {
|
||||
|
||||
@ -3960,6 +3960,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 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, ...) {
|
||||
va_list argptr;
|
||||
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)
|
||||
{
|
||||
int hchange = item->CastTime * cons_mod;
|
||||
int hchange = item->CastTime_ * cons_mod;
|
||||
hchange = mod_food_value(item, hchange);
|
||||
|
||||
if(hchange < 0) { return; }
|
||||
@ -8549,7 +8589,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; }
|
||||
|
||||
@ -946,6 +946,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;
|
||||
|
||||
@ -8599,13 +8599,17 @@ 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 (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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// 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);
|
||||
PercentManaReduction += focus_redux;
|
||||
|
||||
if(focus_redux > 0)
|
||||
{
|
||||
PercentManaReduction += zone->random.Real(1, (double)focus_redux);
|
||||
}
|
||||
|
||||
cost -= (cost * (PercentManaReduction / 100));
|
||||
cost -= cost * PercentManaReduction / 100;
|
||||
|
||||
// Gift of Mana - reduces spell cost to 1 mana
|
||||
if(focus_redux >= 100) {
|
||||
|
||||
@ -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, 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
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@ -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.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user