Merge branch 'master' into luamod

This commit is contained in:
KimLS 2017-06-08 19:55:48 -07:00
commit 4d8f5df261
16 changed files with 116 additions and 65 deletions

View File

@ -1695,6 +1695,7 @@ struct OnLevelMessage_Struct
uint32 Duration;
uint32 PopupID;
uint32 NegativeID;
uint32 SoundControls;
char ButtonName0[25];
char ButtonName1[25];
};

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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)) {

View File

@ -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; }

View File

@ -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;

View File

@ -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

View File

@ -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) {

View File

@ -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;
}

View File

@ -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.