mirror of
https://github.com/EQEmu/Server.git
synced 2026-03-27 10:32:26 +00:00
[Spells] Support for bards using Disciplines while casting or /melody. (#1936)
* test * complete * Update effects.cpp * Update spells.cpp * Update effects.cpp * [Spells] Support for bards using Disciplines while casting or /melody. Support for spell field 'cast not standing' not allow casting from divine aura * [Spells] Support for bards using Disciplines while casting or /melody. DA bypass logic for spells with field 'cast_not_standing'
This commit is contained in:
parent
804f0681a9
commit
e09a8f8f8f
@ -727,6 +727,9 @@ bool Client::UseDiscipline(uint32 spell_id, uint32 target) {
|
|||||||
// Dont let client waste a reuse timer if they can't use the disc
|
// Dont let client waste a reuse timer if they can't use the disc
|
||||||
if (IsStunned() || IsFeared() || IsMezzed() || IsAmnesiad() || IsPet())
|
if (IsStunned() || IsFeared() || IsMezzed() || IsAmnesiad() || IsPet())
|
||||||
{
|
{
|
||||||
|
if (IsAmnesiad()) {
|
||||||
|
MessageString(Chat::Red, MELEE_SILENCE);
|
||||||
|
}
|
||||||
return(false);
|
return(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -745,6 +748,10 @@ bool Client::UseDiscipline(uint32 spell_id, uint32 target) {
|
|||||||
return(false);
|
return(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (DivineAura() && !spells[spell_id].cast_not_standing) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
//can we use the spell?
|
//can we use the spell?
|
||||||
const SPDat_Spell_Struct &spell = spells[spell_id];
|
const SPDat_Spell_Struct &spell = spells[spell_id];
|
||||||
uint8 level_to_use = spell.classes[GetClass() - 1];
|
uint8 level_to_use = spell.classes[GetClass() - 1];
|
||||||
@ -789,8 +796,9 @@ bool Client::UseDiscipline(uint32 spell_id, uint32 target) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(spell.recast_time > 0)
|
bool instant_recast = true;
|
||||||
{
|
|
||||||
|
if(spell.recast_time > 0) {
|
||||||
uint32 reduced_recast = spell.recast_time / 1000;
|
uint32 reduced_recast = spell.recast_time / 1000;
|
||||||
auto focus = GetFocusEffect(focusReduceRecastTime, spell_id);
|
auto focus = GetFocusEffect(focusReduceRecastTime, spell_id);
|
||||||
// do stupid stuff because custom servers.
|
// do stupid stuff because custom servers.
|
||||||
@ -805,18 +813,31 @@ bool Client::UseDiscipline(uint32 spell_id, uint32 target) {
|
|||||||
reduced_recast -= focus;
|
reduced_recast -= focus;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reduced_recast > 0)
|
if (reduced_recast > 0){
|
||||||
CastSpell(spell_id, target, EQ::spells::CastingSlot::Discipline, -1, -1, 0, -1, (uint32)DiscTimer, reduced_recast);
|
instant_recast = false;
|
||||||
else{
|
|
||||||
CastSpell(spell_id, target, EQ::spells::CastingSlot::Discipline);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
SendDisciplineTimer(spells[spell_id].timer_id, reduced_recast);
|
if (GetClass() == BARD && IsCasting() && spells[spell_id].cast_time == 0) {
|
||||||
|
if (DoCastingChecks(spell_id, target)) {
|
||||||
|
SpellFinished(spell_id, entity_list.GetMob(target), EQ::spells::CastingSlot::Discipline, 0, -1, spells[spell_id].resist_difficulty, false, -1, (uint32)DiscTimer, reduced_recast);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
CastSpell(spell_id, target, EQ::spells::CastingSlot::Discipline, -1, -1, 0, -1, (uint32)DiscTimer, reduced_recast);
|
||||||
|
}
|
||||||
|
|
||||||
|
SendDisciplineTimer(spells[spell_id].timer_id, reduced_recast);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
if (instant_recast) {
|
||||||
CastSpell(spell_id, target, EQ::spells::CastingSlot::Discipline);
|
if (GetClass() == BARD && IsCasting() && spells[spell_id].cast_time == 0) {
|
||||||
|
if (DoCastingChecks(spell_id, target)) {
|
||||||
|
SpellFinished(spell_id, entity_list.GetMob(target), EQ::spells::CastingSlot::Discipline);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
CastSpell(spell_id, target, EQ::spells::CastingSlot::Discipline);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return(true);
|
return(true);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -331,7 +331,7 @@ public:
|
|||||||
void CastedSpellFinished(uint16 spell_id, uint32 target_id, EQ::spells::CastingSlot slot, uint16 mana_used,
|
void CastedSpellFinished(uint16 spell_id, uint32 target_id, EQ::spells::CastingSlot slot, uint16 mana_used,
|
||||||
uint32 inventory_slot = 0xFFFFFFFF, int16 resist_adjust = 0);
|
uint32 inventory_slot = 0xFFFFFFFF, int16 resist_adjust = 0);
|
||||||
bool SpellFinished(uint16 spell_id, Mob *target, EQ::spells::CastingSlot slot = EQ::spells::CastingSlot::Item, uint16 mana_used = 0,
|
bool SpellFinished(uint16 spell_id, Mob *target, EQ::spells::CastingSlot slot = EQ::spells::CastingSlot::Item, uint16 mana_used = 0,
|
||||||
uint32 inventory_slot = 0xFFFFFFFF, int16 resist_adjust = 0, bool isproc = false, int level_override = -1);
|
uint32 inventory_slot = 0xFFFFFFFF, int16 resist_adjust = 0, bool isproc = false, int level_override = -1, uint32 timer = 0xFFFFFFFF, uint32 timer_duration = 0);
|
||||||
void SendBeginCast(uint16 spell_id, uint32 casttime);
|
void SendBeginCast(uint16 spell_id, uint32 casttime);
|
||||||
virtual bool SpellOnTarget(uint16 spell_id, Mob* spelltar, int reflect_effectiveness = 0,
|
virtual bool SpellOnTarget(uint16 spell_id, Mob* spelltar, int reflect_effectiveness = 0,
|
||||||
bool use_resist_adjust = false, int16 resist_adjust = 0, bool isproc = false, int level_override = -1, int32 duration_override = 0);
|
bool use_resist_adjust = false, int16 resist_adjust = 0, bool isproc = false, int level_override = -1, int32 duration_override = 0);
|
||||||
@ -347,7 +347,7 @@ public:
|
|||||||
void StopCasting();
|
void StopCasting();
|
||||||
inline bool IsCasting() const { return((casting_spell_id != 0)); }
|
inline bool IsCasting() const { return((casting_spell_id != 0)); }
|
||||||
uint16 CastingSpellID() const { return casting_spell_id; }
|
uint16 CastingSpellID() const { return casting_spell_id; }
|
||||||
bool DoCastingChecks();
|
bool DoCastingChecks(int32 spell_id = SPELL_UNKNOWN, uint16 target_id = 0);
|
||||||
bool TryDispel(uint8 caster_level, uint8 buff_level, int level_modifier);
|
bool TryDispel(uint8 caster_level, uint8 buff_level, int level_modifier);
|
||||||
bool TrySpellProjectile(Mob* spell_target, uint16 spell_id, float speed = 1.5f);
|
bool TrySpellProjectile(Mob* spell_target, uint16 spell_id, float speed = 1.5f);
|
||||||
void ResourceTap(int32 damage, uint16 spell_id);
|
void ResourceTap(int32 damage, uint16 spell_id);
|
||||||
|
|||||||
@ -159,9 +159,9 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot,
|
|||||||
LogSpells("CastSpell called for spell [{}] ([{}]) on entity [{}], slot [{}], time [{}], mana [{}], from item slot [{}]",
|
LogSpells("CastSpell called for spell [{}] ([{}]) on entity [{}], slot [{}], time [{}], mana [{}], from item slot [{}]",
|
||||||
(IsValidSpell(spell_id))?spells[spell_id].name:"UNKNOWN SPELL", spell_id, target_id, static_cast<int>(slot), cast_time, mana_cost, (item_slot==0xFFFFFFFF)?999:item_slot);
|
(IsValidSpell(spell_id))?spells[spell_id].name:"UNKNOWN SPELL", spell_id, target_id, static_cast<int>(slot), cast_time, mana_cost, (item_slot==0xFFFFFFFF)?999:item_slot);
|
||||||
|
|
||||||
if(casting_spell_id == spell_id)
|
if (casting_spell_id == spell_id) {
|
||||||
ZeroCastingVars();
|
ZeroCastingVars();
|
||||||
|
}
|
||||||
if
|
if
|
||||||
(
|
(
|
||||||
!IsValidSpell(spell_id) ||
|
!IsValidSpell(spell_id) ||
|
||||||
@ -216,8 +216,8 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot,
|
|||||||
return(false);
|
return(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
//cannot cast under divine aura
|
//cannot cast under divine aura, unless spell has 'cast_not_standing' flag.
|
||||||
if(DivineAura()) {
|
if(DivineAura() && !spells[spell_id].cast_not_standing) {
|
||||||
LogSpells("Spell casting canceled: cannot cast while Divine Aura is in effect");
|
LogSpells("Spell casting canceled: cannot cast while Divine Aura is in effect");
|
||||||
InterruptSpell(173, 0x121, false);
|
InterruptSpell(173, 0x121, false);
|
||||||
if(IsClient()) {
|
if(IsClient()) {
|
||||||
@ -240,7 +240,6 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot,
|
|||||||
if ((item_slot != -1 && cast_time == 0) || aa_id) {
|
if ((item_slot != -1 && cast_time == 0) || aa_id) {
|
||||||
can_send_spellbar_enable = false;
|
can_send_spellbar_enable = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (can_send_spellbar_enable) {
|
if (can_send_spellbar_enable) {
|
||||||
SendSpellBarEnable(spell_id);
|
SendSpellBarEnable(spell_id);
|
||||||
}
|
}
|
||||||
@ -620,15 +619,30 @@ void Mob::SendBeginCast(uint16 spell_id, uint32 casttime)
|
|||||||
* it's probably doing something wrong.
|
* it's probably doing something wrong.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool Mob::DoCastingChecks()
|
bool Mob::DoCastingChecks(int32 spell_id, uint16 target_id)
|
||||||
{
|
{
|
||||||
if (!IsClient() || (IsClient() && CastToClient()->GetGM())) {
|
if (!IsClient() || (IsClient() && CastToClient()->GetGM())) {
|
||||||
casting_spell_checks = true;
|
casting_spell_checks = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16 spell_id = casting_spell_id;
|
bool ignore_casting_spell_checks = false;
|
||||||
Mob *spell_target = entity_list.GetMob(casting_spell_targetid);
|
/*
|
||||||
|
If variables are passed into this function it is NOT being called from main spell process
|
||||||
|
thefore we do not want to set the 'casting_spell_checks' state keeping variable.
|
||||||
|
*/
|
||||||
|
if (spell_id != SPELL_UNKNOWN || target_id) {
|
||||||
|
ignore_casting_spell_checks = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (spell_id == SPELL_UNKNOWN) {
|
||||||
|
spell_id = casting_spell_id;
|
||||||
|
}
|
||||||
|
if (!target_id) {
|
||||||
|
target_id = casting_spell_targetid;
|
||||||
|
}
|
||||||
|
|
||||||
|
Mob *spell_target = entity_list.GetMob(target_id);
|
||||||
|
|
||||||
if (RuleB(Spells, BuffLevelRestrictions)) {
|
if (RuleB(Spells, BuffLevelRestrictions)) {
|
||||||
// casting_spell_targetid is guaranteed to be what we went, check for ST_Self for now should work though
|
// casting_spell_targetid is guaranteed to be what we went, check for ST_Self for now should work though
|
||||||
@ -665,7 +679,9 @@ bool Mob::DoCastingChecks()
|
|||||||
if (!CastToClient()->IsLinkedSpellReuseTimerReady(spells[spell_id].timer_id))
|
if (!CastToClient()->IsLinkedSpellReuseTimerReady(spells[spell_id].timer_id))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
casting_spell_checks = true;
|
if (!ignore_casting_spell_checks){
|
||||||
|
casting_spell_checks = true;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2143,7 +2159,8 @@ bool Mob::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_ce
|
|||||||
// we can't interrupt in this, or anything called from this!
|
// we can't interrupt in this, or anything called from this!
|
||||||
// if you need to abort the casting, return false
|
// if you need to abort the casting, return false
|
||||||
bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, CastingSlot slot, uint16 mana_used,
|
bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, CastingSlot slot, uint16 mana_used,
|
||||||
uint32 inventory_slot, int16 resist_adjust, bool isproc, int level_override)
|
uint32 inventory_slot, int16 resist_adjust, bool isproc, int level_override,
|
||||||
|
uint32 timer, uint32 timer_duration)
|
||||||
{
|
{
|
||||||
//EQApplicationPacket *outapp = nullptr;
|
//EQApplicationPacket *outapp = nullptr;
|
||||||
Mob *ae_center = nullptr;
|
Mob *ae_center = nullptr;
|
||||||
@ -2567,6 +2584,12 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, CastingSlot slot, ui
|
|||||||
//set our reuse timer on long ass reuse_time spells...
|
//set our reuse timer on long ass reuse_time spells...
|
||||||
if(IsClient() && !isproc)
|
if(IsClient() && !isproc)
|
||||||
{
|
{
|
||||||
|
//Support for bards to get disc recast timers while singing.
|
||||||
|
if (GetClass() == BARD && spell_id != casting_spell_id && timer != 0xFFFFFFFF) {
|
||||||
|
CastToClient()->GetPTimers().Start(timer, timer_duration);
|
||||||
|
LogSpells("Spell [{}]: Setting bard custom disciple reuse timer [{}] to [{}]", spell_id, timer, timer_duration);
|
||||||
|
}
|
||||||
|
|
||||||
if(casting_spell_aa_id) {
|
if(casting_spell_aa_id) {
|
||||||
AA::Rank *rank = zone->GetAlternateAdvancementRank(casting_spell_aa_id);
|
AA::Rank *rank = zone->GetAlternateAdvancementRank(casting_spell_aa_id);
|
||||||
|
|
||||||
@ -3765,8 +3788,10 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// invuln mobs can't be affected by any spells, good or bad
|
// invuln mobs can't be affected by any spells, good or bad, except if caster is casting a spell with 'cast_not_standing' on self.
|
||||||
if(spelltar->GetInvul() || spelltar->DivineAura()) {
|
if ((spelltar->GetInvul() && !spelltar->DivineAura()) ||
|
||||||
|
(spelltar != this && spelltar->DivineAura()) ||
|
||||||
|
(spelltar == this && spelltar->DivineAura() && !spells[spell_id].cast_not_standing)) {
|
||||||
LogSpells("Casting spell [{}] on [{}] aborted: they are invulnerable", spell_id, spelltar->GetName());
|
LogSpells("Casting spell [{}] on [{}] aborted: they are invulnerable", spell_id, spelltar->GetName());
|
||||||
safe_delete(action_packet);
|
safe_delete(action_packet);
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user