[Quest API] (Performance) Check spell or cast events exist before export and execute (#2897)

* [Quest API] Optionally parse spell/cast events

# Notes
- Optionally parses `EVENT_CAST`, `EVENT_CAST_BEGIN`, `EVENT_CAST_ON`, `EVENT_SPELL_EFFECT_NPC`, `EVENT_SPELL_EFFECT_CLIENT`, `EVENT_SPELL_EFFECT_BOT`, `EVENT_SPELL_EFFECT_BUFF_TIC_CLIENT`, `EVENT_SPELL_EFFECT_BUFF_TIC_NPC`, `EVENT_SPELL_EFFECT_BUFF_TIC_BOT`, `EVENT_SPELL_FADE`, and `EVENT_SPELL_EFFECT_TRANSLOCATE_COMPLETE`.

* Cleanup

* PR comment fixes

---------

Co-authored-by: Akkadius <akkadius1@gmail.com>
This commit is contained in:
Alex King 2023-02-13 00:26:17 -05:00 committed by GitHub
parent 805a9c5f59
commit 9f619859d1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 170 additions and 91 deletions

View File

@ -15228,32 +15228,34 @@ void Client::Handle_OP_Translocate(const EQApplicationPacket *app)
zone->GetInstanceID() == PendingTranslocateData.instance_id zone->GetInstanceID() == PendingTranslocateData.instance_id
); );
if (parse->EventSpell(EVENT_SPELL_EFFECT_TRANSLOCATE_COMPLETE, nullptr, this, spell_id, "", 0) == 0) { if (parse->SpellHasQuestSub(spell_id, EVENT_SPELL_EFFECT_TRANSLOCATE_COMPLETE)) {
// If the spell has a translocate to bind effect, AND we are already in the zone the client if (parse->EventSpell(EVENT_SPELL_EFFECT_TRANSLOCATE_COMPLETE, nullptr, this, spell_id, "", 0) == 0) {
// is bound in, use the GoToBind method. If we send OP_Translocate in this case, the client moves itself // If the spell has a translocate to bind effect, AND we are already in the zone the client
// to the bind coords it has from the PlayerProfile, but with the X and Y reversed. I suspect they are // is bound in, use the GoToBind method. If we send OP_Translocate in this case, the client moves itself
// reversed in the pp, and since spells like Gate are handled serverside, this has not mattered before. // to the bind coords it has from the PlayerProfile, but with the X and Y reversed. I suspect they are
if ( // reversed in the pp, and since spells like Gate are handled serverside, this has not mattered before.
IsTranslocateSpell(spell_id) && if (
in_translocate_zone IsTranslocateSpell(spell_id) &&
) { in_translocate_zone
PendingTranslocate = false; ) {
GoToBind(); PendingTranslocate = false;
return; GoToBind();
} return;
}
////Was sending the packet back to initiate client zone... ////Was sending the packet back to initiate client zone...
////but that could be abusable, so lets go through proper channels ////but that could be abusable, so lets go through proper channels
MovePC( MovePC(
PendingTranslocateData.zone_id, PendingTranslocateData.zone_id,
PendingTranslocateData.instance_id, PendingTranslocateData.instance_id,
PendingTranslocateData.x, PendingTranslocateData.x,
PendingTranslocateData.y, PendingTranslocateData.y,
PendingTranslocateData.z, PendingTranslocateData.z,
PendingTranslocateData.heading, PendingTranslocateData.heading,
0, 0,
ZoneSolicited ZoneSolicited
); );
}
} }
} }

View File

@ -162,28 +162,47 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
} }
} }
std::string export_string = fmt::format(
"{} {} {} {}",
caster ? caster->GetID() : 0,
buffslot >= 0 ? buffs[buffslot].ticsremaining : 0,
caster ? caster->GetLevel() : 0,
buffslot
);
if (IsClient()) { if (IsClient()) {
if (parse->EventSpell(EVENT_SPELL_EFFECT_CLIENT, nullptr, CastToClient(), spell_id, export_string, 0) != 0) { if (parse->SpellHasQuestSub(spell_id, EVENT_SPELL_EFFECT_CLIENT)) {
CalcBonuses(); const auto &export_string = fmt::format(
return true; "{} {} {} {}",
caster ? caster->GetID() : 0,
buffslot >= 0 ? buffs[buffslot].ticsremaining : 0,
caster ? caster->GetLevel() : 0,
buffslot
);
if (parse->EventSpell(EVENT_SPELL_EFFECT_CLIENT, nullptr, CastToClient(), spell_id, export_string, 0) != 0) {
CalcBonuses();
return true;
}
} }
} else if (IsNPC()) { } else if (IsNPC()) {
if (parse->EventSpell(EVENT_SPELL_EFFECT_NPC, this, nullptr, spell_id, export_string, 0) != 0) { if (parse->SpellHasQuestSub(spell_id, EVENT_SPELL_EFFECT_NPC)) {
CalcBonuses(); const auto &export_string = fmt::format(
return true; "{} {} {} {}",
caster ? caster->GetID() : 0,
buffslot >= 0 ? buffs[buffslot].ticsremaining : 0,
caster ? caster->GetLevel() : 0,
buffslot
);
if (parse->EventSpell(EVENT_SPELL_EFFECT_NPC, this, nullptr, spell_id, export_string, 0) != 0) {
CalcBonuses();
return true;
}
} }
} else if (IsBot()) { } else if (IsBot()) {
if (parse->EventSpell(EVENT_SPELL_EFFECT_BOT, this, nullptr, spell_id, export_string, 0) != 0) { if (parse->SpellHasQuestSub(spell_id, EVENT_SPELL_EFFECT_BOT)) {
CalcBonuses(); const auto &export_string = fmt::format(
return true; "{} {} {} {}",
caster ? caster->GetID() : 0,
buffslot >= 0 ? buffs[buffslot].ticsremaining : 0,
caster ? caster->GetLevel() : 0,
buffslot
);
if (parse->EventSpell(EVENT_SPELL_EFFECT_BOT, this, nullptr, spell_id, export_string, 0) != 0) {
CalcBonuses();
return true;
}
} }
} }
@ -3791,7 +3810,7 @@ void Mob::DoBuffTic(const Buffs_Struct &buff, int slot, Mob *caster)
const SPDat_Spell_Struct &spell = spells[buff.spellid]; const SPDat_Spell_Struct &spell = spells[buff.spellid];
std::string export_string = fmt::format( const auto& export_string = fmt::format(
"{} {} {} {}", "{} {} {} {}",
caster ? caster->GetID() : 0, caster ? caster->GetID() : 0,
buffs[slot].ticsremaining, buffs[slot].ticsremaining,
@ -3800,16 +3819,22 @@ void Mob::DoBuffTic(const Buffs_Struct &buff, int slot, Mob *caster)
); );
if (IsClient()) { if (IsClient()) {
if (parse->EventSpell(EVENT_SPELL_EFFECT_BUFF_TIC_CLIENT, nullptr, CastToClient(), buff.spellid, export_string, 0) != 0) { if (parse->SpellHasQuestSub(buff.spellid, EVENT_SPELL_EFFECT_BUFF_TIC_CLIENT)) {
return; if (parse->EventSpell(EVENT_SPELL_EFFECT_BUFF_TIC_CLIENT, nullptr, CastToClient(), buff.spellid, export_string, 0) != 0) {
return;
}
} }
} else if (IsNPC()) { } else if (IsNPC()) {
if (parse->EventSpell(EVENT_SPELL_EFFECT_BUFF_TIC_NPC, this, nullptr, buff.spellid, export_string, 0) != 0) { if (parse->SpellHasQuestSub(buff.spellid, EVENT_SPELL_EFFECT_BUFF_TIC_NPC)) {
return; if (parse->EventSpell(EVENT_SPELL_EFFECT_BUFF_TIC_NPC, this, nullptr, buff.spellid, export_string, 0) != 0) {
return;
}
} }
} else if (IsBot()) { } else if (IsBot()) {
if (parse->EventSpell(EVENT_SPELL_EFFECT_BUFF_TIC_BOT, this, nullptr, buff.spellid, export_string, 0) != 0) { if (parse->SpellHasQuestSub(buff.spellid, EVENT_SPELL_EFFECT_BUFF_TIC_BOT)) {
return; if (parse->EventSpell(EVENT_SPELL_EFFECT_BUFF_TIC_BOT, this, nullptr, buff.spellid, export_string, 0) != 0) {
return;
}
} }
} }
@ -4142,25 +4167,35 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses)
LogSpells("Fading buff [{}] from slot [{}]", buffs[slot].spellid, slot); LogSpells("Fading buff [{}] from slot [{}]", buffs[slot].spellid, slot);
std::string export_string = fmt::format( const auto has_fade_event = parse->SpellHasQuestSub(buffs[slot].spellid, EVENT_SPELL_FADE);
"{} {} {} {}", std::string export_string = "";
buffs[slot].casterid, if (has_fade_event) {
buffs[slot].ticsremaining, export_string = fmt::format(
buffs[slot].casterlevel, "{} {} {} {}",
slot buffs[slot].casterid,
); buffs[slot].ticsremaining,
buffs[slot].casterlevel,
slot
);
}
if (IsClient()) { if (IsClient()) {
if (parse->EventSpell(EVENT_SPELL_FADE, nullptr, CastToClient(), buffs[slot].spellid, export_string, 0) != 0) { if (has_fade_event) {
return; if (parse->EventSpell(EVENT_SPELL_FADE, nullptr, CastToClient(), buffs[slot].spellid, export_string, 0) != 0) {
return;
}
} }
} else if (IsNPC()) { } else if (IsNPC()) {
if (parse->EventSpell(EVENT_SPELL_FADE, this, nullptr, buffs[slot].spellid, export_string, 0) != 0) { if (has_fade_event) {
return; if (parse->EventSpell(EVENT_SPELL_FADE, this, nullptr, buffs[slot].spellid, export_string, 0) != 0) {
return;
}
} }
} else if (IsBot()) { } else if (IsBot()) {
if (parse->EventSpell(EVENT_SPELL_FADE, this, nullptr, buffs[slot].spellid, export_string, 0) != 0) { if (has_fade_event) {
return; if (parse->EventSpell(EVENT_SPELL_FADE, this, nullptr, buffs[slot].spellid, export_string, 0) != 0) {
return;
}
} }
} }

View File

@ -238,25 +238,44 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot,
} }
} }
std::string export_string = fmt::format(
"{} {} {}",
spell_id,
GetID(),
GetCasterLevel(spell_id)
);
if (IsClient()) { if (IsClient()) {
if (parse->EventPlayer(EVENT_CAST_BEGIN, CastToClient(), export_string, 0) != 0) { if (parse->PlayerHasQuestSub(EVENT_CAST_BEGIN)) {
if (IsDiscipline(spell_id)) { const auto& export_string = fmt::format(
CastToClient()->SendDisciplineTimer(spells[spell_id].timer_id, 0); "{} {} {}",
} else { spell_id,
CastToClient()->SendSpellBarEnable(spell_id); GetID(),
GetCasterLevel(spell_id)
);
if (parse->EventPlayer(EVENT_CAST_BEGIN, CastToClient(), export_string, 0) != 0) {
if (IsDiscipline(spell_id)) {
CastToClient()->SendDisciplineTimer(spells[spell_id].timer_id, 0);
}
else {
CastToClient()->SendSpellBarEnable(spell_id);
}
return false;
} }
return false;
} }
} else if (IsNPC()) { } else if (IsNPC()) {
parse->EventNPC(EVENT_CAST_BEGIN, CastToNPC(), nullptr, export_string, 0); if (parse->HasQuestSub(GetNPCTypeID(), EVENT_CAST_BEGIN)) {
const auto& export_string = fmt::format(
"{} {} {}",
spell_id,
GetID(),
GetCasterLevel(spell_id)
);
parse->EventNPC(EVENT_CAST_BEGIN, CastToNPC(), nullptr, export_string, 0);
}
} else if (IsBot()) { } else if (IsBot()) {
parse->EventBot(EVENT_CAST_BEGIN, CastToBot(), nullptr, export_string, 0); if (parse->BotHasQuestSub(EVENT_CAST_BEGIN)) {
const auto& export_string = fmt::format(
"{} {} {}",
spell_id,
GetID(),
GetCasterLevel(spell_id)
);
parse->EventBot(EVENT_CAST_BEGIN, CastToBot(), nullptr, export_string, 0);
}
} }
//To prevent NPC ghosting when spells are cast from scripts //To prevent NPC ghosting when spells are cast from scripts
@ -1635,18 +1654,25 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, CastingSlot slo
// at this point the spell has successfully been cast // at this point the spell has successfully been cast
// //
std::string export_string = fmt::format( const auto& export_string = fmt::format(
"{} {} {}", "{} {} {}",
spell_id, spell_id,
GetID(), GetID(),
GetCasterLevel(spell_id) GetCasterLevel(spell_id)
); );
if (IsClient()) { if (IsClient()) {
parse->EventPlayer(EVENT_CAST, CastToClient(), export_string, 0); if (parse->PlayerHasQuestSub(EVENT_CAST)) {
parse->EventPlayer(EVENT_CAST, CastToClient(), export_string, 0);
}
} else if (IsNPC()) { } else if (IsNPC()) {
parse->EventNPC(EVENT_CAST, CastToNPC(), nullptr, export_string, 0); if (parse->HasQuestSub(GetNPCTypeID(), EVENT_CAST)) {
parse->EventNPC(EVENT_CAST, CastToNPC(), nullptr, export_string, 0);
}
} else if (IsBot()) { } else if (IsBot()) {
parse->EventBot(EVENT_CAST, CastToBot(), nullptr, export_string, 0); if (parse->BotHasQuestSub(EVENT_CAST)) {
parse->EventBot(EVENT_CAST, CastToBot(), nullptr, export_string, 0);
}
} }
if(bard_song_mode) if(bard_song_mode)
@ -3639,20 +3665,36 @@ bool Mob::SpellOnTarget(
(spellOwner->IsClient() ? FilterPCSpells : FilterNPCSpells) /* EQ Filter Type: (8 or 9) */ (spellOwner->IsClient() ? FilterPCSpells : FilterNPCSpells) /* EQ Filter Type: (8 or 9) */
); );
/* Send the EVENT_CAST_ON event */
const auto export_string = fmt::format(
"{} {} {}",
spell_id,
GetID(),
caster_level
);
if (spelltar->IsNPC()) { if (spelltar->IsNPC()) {
parse->EventNPC(EVENT_CAST_ON, spelltar->CastToNPC(), this, export_string, 0); if (parse->HasQuestSub(spelltar->GetNPCTypeID(), EVENT_CAST_ON)) {
const auto& export_string = fmt::format(
"{} {} {}",
spell_id,
GetID(),
caster_level
);
parse->EventNPC(EVENT_CAST_ON, spelltar->CastToNPC(), this, export_string, 0);
}
} else if (spelltar->IsClient()) { } else if (spelltar->IsClient()) {
parse->EventPlayer(EVENT_CAST_ON, spelltar->CastToClient(), export_string, 0); if (parse->PlayerHasQuestSub(EVENT_CAST_ON)) {
const auto& export_string = fmt::format(
"{} {} {}",
spell_id,
GetID(),
caster_level
);
parse->EventPlayer(EVENT_CAST_ON, spelltar->CastToClient(), export_string, 0);
}
} else if (spelltar->IsBot()) { } else if (spelltar->IsBot()) {
parse->EventBot(EVENT_CAST_ON, spelltar->CastToBot(), this, export_string, 0); if (parse->BotHasQuestSub(EVENT_CAST_ON)) {
const auto& export_string = fmt::format(
"{} {} {}",
spell_id,
GetID(),
caster_level
);
parse->EventBot(EVENT_CAST_ON, spelltar->CastToBot(), this, export_string, 0);
}
} }
mod_spell_cast(spell_id, spelltar, reflect_effectiveness, use_resist_adjust, resist_adjust, isproc); mod_spell_cast(spell_id, spelltar, reflect_effectiveness, use_resist_adjust, resist_adjust, isproc);